{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# TP — Détermination de la distance focale d'une lentille\n", "## Terminale spé Physique — Prépa GEIPI\n", "\n", "**Objectif :** À partir de mesures de la relation de conjugaison, retrouver la focale $f'$ d'une lentille convergente.\n", "\n", "**Durée :** 60 min (simulation + régression + interprétation) \n", "**Outils :** Python (Numpy, Matplotlib, Scipy) \n", "**Données :** Couples $(OA, OA')$ relevés sur le banc optique ou la simulation\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "## 📚 Rappels théoriques\n", "\n", "### Relation de conjugaison\n", "Pour une lentille mince convergente de distance focale $f'$ :\n", "\n", "$$\\frac{1}{OA'} - \\frac{1}{OA} = \\frac{1}{f'}$$\n", "\n", "**Convention de signe :** \n", "- $OA < 0$ (objet réel, à gauche) \n", "- $OA' > 0$ (image réelle, à droite) \n", "- $OA' < 0$ (image virtuelle)\n", "\n", "### Stratégie\n", "Si on pose $Y = \\frac{1}{OA'}$ et $X = \\frac{1}{OA}$, on obtient une relation **linéaire** :\n", "\n", "$$Y = X + \\frac{1}{f'}$$\n", "\n", "Le graphe $Y$ en fonction de $X$ est une droite de **pente 1**, et l'**ordonnée à l'origine** vaut $\\frac{1}{f'}$.\n", "\n", "Donc : $f' = \\frac{1}{b}$ où $b$ est l'ordonnée à l'origine de la régression.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Importer les bibliothèques\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "from scipy.stats import linregress\n", "\n", "# Style graphiques\n", "plt.style.use('seaborn-v0_8-darkgrid')\n", "print(\"✓ Bibliothèques chargées.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "## 1️⃣ SAISIE DE VOS DONNÉES\n", "\n", "Remplissez les listes ci-dessous avec vos mesures du banc optique.\n", "\n", "**Format :** Chaque ligne est un couple (OA en cm, OA' en cm)\n", "\n", "⚠️ **Important :** $OA$ doit être **négatif** (objet à gauche de la lentille)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# ===== À COMPLÉTER AVEC VOS MESURES =====\n", "\n", "# Couples (OA en cm [NÉGATIF], OA' en cm) relevés sur le banc\n", "# Exemple fourni (à remplacer par vos données)\n", "\n", "OA_mesures = np.array([-30.0, -40.0, -50.0, -60.0, -80.0, -100.0, -120.0]) # Négatifs !\n", "OAp_mesures = np.array([60.0, 40.0, 33.3, 30.0, 26.7, 25.0, 24.0]) # Positifs (images réelles)\n", "\n", "UNITE = \"cm\"\n", "N_points = len(OA_mesures)\n", "\n", "print(f\"✓ {N_points} couples de mesures chargés.\\n\")\n", "print(f\"{'OA (' + UNITE + ')':>12} | {'OA\\' (' + UNITE + ')':>12} | {'Grandissement γ':>15}\")\n", "print(\"-\" * 42)\n", "for oa, oap in zip(OA_mesures, OAp_mesures):\n", " gamma = oap / oa\n", " print(f\"{oa:>12.1f} | {oap:>12.1f} | {gamma:>15.2f}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "## 2️⃣ CHANGEMENT DE VARIABLE\n", "\n", "On passe de $(OA, OA')$ à $(1/OA, 1/OA')$ pour linéariser la relation." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Calcul des inverses\n", "X = 1 / OA_mesures # 1/OA en cm⁻¹\n", "Y = 1 / OAp_mesures # 1/OA' en cm⁻¹\n", "\n", "print(\"Changement de variable :\")\n", "print(f\"{'1/OA (' + UNITE + '⁻¹)':>15} | {'1/OA\\' (' + UNITE + '⁻¹)':>15}\")\n", "print(\"-\" * 32)\n", "for x, y in zip(X, Y):\n", " print(f\"{x:>15.5f} | {y:>15.5f}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "## 3️⃣ RÉGRESSION LINÉAIRE\n", "\n", "Appliquer une régression $Y = aX + b$ et calculer le coefficient de corrélation $R^2$." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Régression linéaire\n", "slope, intercept, r_value, p_value, std_err = linregress(X, Y)\n", "\n", "a = slope # Pente (doit être ≈ 1)\n", "b = intercept # Ordonnée à l'origine (= 1/f')\n", "r2 = r_value**2 # R²\n", "\n", "print(\"\\n🔢 RÉSULTATS DE LA RÉGRESSION\")\n", "print(\"=\"*50)\n", "print(f\"Équation de la droite : Y = {a:.4f} × X + {b:.5f}\")\n", "print(f\"Coefficient de corrélation R² = {r2:.5f}\")\n", "print(f\"Erreur type (σ) = {std_err:.5f}\")\n", "print(\"=\"*50)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "## 4️⃣ EXPLOITATION — CALCUL DE LA FOCALE\n", "\n", "Puisque l'ordonnée à l'origine $b = \\frac{1}{f'}$, on en déduit :\n", "\n", "$$f' = \\frac{1}{b}$$" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Calcul de f' à partir de b\n", "if abs(b) < 1e-6:\n", " print(\"⚠️ ERREUR : Ordonnée à l'origine trop proche de zéro. Vérifiez vos mesures.\")\n", " f_prime = None\n", "else:\n", " f_prime = 1 / b\n", "\n", "print(\"\\n📏 DISTANCE FOCALE\")\n", "print(\"=\"*50)\n", "print(f\"Ordonnée à l'origine : b = {b:.5f} {UNITE}⁻¹\")\n", "print(f\"\\n>>> f' = 1/b = {f_prime:.2f} {UNITE}\")\n", "print(\"=\"*50)\n", "\n", "# Vérification : la pente doit être ≈ 1\n", "print(f\"\\n✓ Vérification pente : a = {a:.4f} (attendu ≈ 1)\")\n", "if abs(a - 1) < 0.1:\n", " print(\" → Pente conforme ✓\")\n", "else:\n", " print(\" → Attention : pente s'écarte de 1. Revérifiez vos mesures.\")\n", "\n", "print(f\"\\n✓ Qualité ajustement : R² = {r2:.4f}\")\n", "if r2 > 0.95:\n", " print(\" → Excellente corrélation linéaire ✓\")\n", "elif r2 > 0.90:\n", " print(\" → Bonne corrélation ✓\")\n", "else:\n", " print(\" → Corrélation faible. Points dispersés ?\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "## 5️⃣ VISUALISATION GRAPHIQUE" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Créer la figure\n", "fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5))\n", "\n", "# === GRAPHE 1 : 1/OA' = f(1/OA) ===\n", "ax1.scatter(X, Y, s=80, alpha=0.7, color='#1d3557', edgecolor='black', linewidth=1.5, label='Points expérimentaux')\n", "\n", "# Droite de régression\n", "X_fit = np.linspace(X.min() - 0.01, X.max() + 0.01, 100)\n", "Y_fit = a * X_fit + b\n", "ax1.plot(X_fit, Y_fit, '-', color='#e63946', linewidth=2.5, \n", " label=f'Régression : Y = {a:.3f}X + {b:.4f}\\nR² = {r2:.4f}')\n", "\n", "ax1.axhline(0, color='grey', linestyle='--', linewidth=0.8, alpha=0.5)\n", "ax1.axvline(0, color='grey', linestyle='--', linewidth=0.8, alpha=0.5)\n", "ax1.grid(True, alpha=0.3)\n", "ax1.set_xlabel(f'1/OA ({UNITE}⁻¹)', fontsize=12, fontweight='bold')\n", "ax1.set_ylabel(f'1/OA\\' ({UNITE}⁻¹)', fontsize=12, fontweight='bold')\n", "ax1.set_title('Relation de conjugaison linéarisée', fontsize=13, fontweight='bold')\n", "ax1.legend(fontsize=10, loc='best')\n", "\n", "# === GRAPHE 2 : OA' = f(OA) (comparaison non-linéaire) ===\n", "ax2.scatter(OA_mesures, OAp_mesures, s=80, alpha=0.7, color='#2a9d8f', edgecolor='black', linewidth=1.5,\n", " label='Points expérimentaux')\n", "\n", "# Courbe théorique OA' = OA*f'/(OA+f')\n", "if f_prime is not None:\n", " OA_theo = np.linspace(OA_mesures.min() - 10, -5, 100)\n", " OAp_theo = OA_theo * f_prime / (OA_theo + f_prime)\n", " ax2.plot(OA_theo, OAp_theo, '-', color='#e76f51', linewidth=2.5, \n", " label=f'Théorie : OA\\' = f(OA) avec f\\' = {f_prime:.2f} cm')\n", "\n", "ax2.grid(True, alpha=0.3)\n", "ax2.set_xlabel(f'OA ({UNITE})', fontsize=12, fontweight='bold')\n", "ax2.set_ylabel(f'OA\\' ({UNITE})', fontsize=12, fontweight='bold')\n", "ax2.set_title('Relation complète (non-linéaire)', fontsize=13, fontweight='bold')\n", "ax2.legend(fontsize=10, loc='best')\n", "\n", "plt.tight_layout()\n", "plt.savefig('tp_optique_regression.png', dpi=150, bbox_inches='tight')\n", "plt.show()\n", "\n", "print(\"\\n✓ Graphiques sauvegardés : tp_optique_regression.png\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "## 6️⃣ SYNTHÈSE ET INTERPRÉTATION" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(\"\\n\" + \"=\"*60)\n", "print(\"SYNTHÈSE DE L'EXPÉRIENCE\")\n", "print(\"=\"*60)\n", "\n", "if f_prime is not None:\n", " print(f\"\\n📊 **Distance focale déterminée : f' = {f_prime:.2f} {UNITE}**\")\n", " print(f\"\\nMéthode : Exploitation de la relation de conjugaison linéarisée.\")\n", " print(f\" • Transformation : (OA, OA') → (1/OA, 1/OA')\")\n", " print(f\" • Régression linéaire : Y = {a:.4f}·X + {b:.5f}\")\n", " print(f\" • Calcul : f' = 1/b = 1/{b:.5f} = {f_prime:.2f} cm\")\n", " print(f\"\\n✓ Qualité des données : R² = {r2:.5f}\")\n", " \n", " if r2 > 0.99:\n", " print(\" → Dispersion négligeable, mesures très précises.\")\n", " elif r2 > 0.95:\n", " print(\" → Bon accord avec le modèle.\")\n", " else:\n", " print(\" → Voir section 'Questions'.\")\n", "\n", "print(\"\\n\" + \"=\"*60)\n", "print(\"QUESTIONS DE SYNTHÈSE (à rédiger)\")\n", "print(\"=\"*60)\n", "print(\"\"\"\n", "1. La pente obtenue (a = {:.4f}) correspond-elle à la théorie (a = 1) ?\n", " Interprétez l'écart s'il existe.\n", "\n", "2. Comparez votre résultat f' = {:.2f} cm avec la valeur annoncée du fabricant\n", " (si vous la connaissez). Calculez l'écart relatif.\n", "\n", "3. Quelles sont les trois principales sources d'erreur expérimentale ?\n", "\n", "4. Que se passerait-il si on poussait OA (objet) jusqu'à -f' (au foyer objet) ?\n", " Vérifiez analytiquement avec la relation de conjugaison.\n", "\"\"\".format(a, f_prime))\n", "\n", "print(\"=\"*60)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "## 7️⃣ BONUS : Exporter vos résultats" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Créer un fichier de résultats\n", "resultats = {\n", " \"focale (cm)\": f_prime,\n", " \"pente\": a,\n", " \"ordonnée à l'origine\": b,\n", " \"R²\": r2,\n", " \"unité\": \"cm\"\n", "}\n", "\n", "# Sauvegarder en JSON (optionnel)\n", "import json\n", "with open('resultats_tp_optique.json', 'w') as f:\n", " json.dump(resultats, f, indent=2)\n", "\n", "print(\"✓ Résultats sauvegardés en JSON : resultats_tp_optique.json\")\n", "print(\"\\n📬 Vous pouvez télécharger ce fichier + la figure pour votre compte-rendu.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "\n", "## 📖 Pour aller plus loin\n", "\n", "### Représentation alternative : produit OA·OA' = f(OA − OA')\n", "La relation de conjugaison peut aussi s'écrire :\n", "$$OA \\cdot OA' = f' \\cdot (OA' - OA)$$\n", "\n", "Cette représentation (Newton) donne aussi une droite, utile pour retrouver $f'$. Voir le TP complet pour cette variante.\n", "\n", "### Modèle optique : lunette astronomique\n", "Deux lentilles minces : objectif ($f'_1$) + oculaire ($f'_2$). \n", "Grossissement : $G = f'_1 / f'_2$.\n", "\n", "Consultez le TP interactif sur prof-prive.com pour explorer ce modèle en temps réel.\n", "\n", "---\n", "\n", "**TP réalisé dans le cadre du cursus GEIPI Polytech.** \n", "*Contact : prof-prive.com — Tutoring physique-chimie Terminale spé.*" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python", "version": "3.9.0" } }, "nbformat": 4, "nbformat_minor": 4 }