|
160 | 160 | "cell_type": "markdown", |
161 | 161 | "metadata": {}, |
162 | 162 | "source": [ |
163 | | - "Now define a model function based on Ohm's law and choose an initial guess for the resistance. The voltage uncertainty is too small to be appear on the `errorbar` plot, so we switch to the conventional `plot` command." |
| 163 | + "Now define a model function based on Ohm's law and choose an initial guess for the resistance. The voltage uncertainty is too small to appear on the `errorbar` plot, so we switch to the conventional `plot` command." |
164 | 164 | ] |
165 | 165 | }, |
166 | 166 | { |
|
170 | 170 | "outputs": [], |
171 | 171 | "source": [ |
172 | 172 | "# Define model\n", |
173 | | - "def vOhm(current, resistance):\n", |
| 173 | + "def v_ohm(current, resistance):\n", |
174 | 174 | " return current*resistance\n", |
175 | 175 | "\n", |
176 | 176 | "# Assign initial guess for resistance and\n", |
177 | 177 | "RInit = 100\n", |
178 | 178 | "Imodel_mA = np.linspace(0,100)\n", |
179 | 179 | "Imodel = 1e-3*Imodel_mA\n", |
180 | | - "Vmodel = vOhm(Imodel, RInit)\n", |
| 180 | + "Vmodel = v_ohm(Imodel, RInit)\n", |
181 | 181 | "plt.plot(I_mA, Vm, 'o')\n", |
182 | 182 | "plt.plot(Imodel_mA, Vmodel, '-')\n", |
183 | 183 | "plt.xlabel(\"Current (mA)\")\n", |
|
197 | 197 | "metadata": {}, |
198 | 198 | "outputs": [], |
199 | 199 | "source": [ |
200 | | - "R_fit, R_fit_cov = curve_fit(vOhm, I_mA*1e-3, Vm, p0=[RInit], \n", |
| 200 | + "R_fit, R_fit_cov = curve_fit(v_ohm, I_mA*1e-3, Vm, p0=[RInit], \n", |
201 | 201 | " sigma=alphaV*np.ones(np.size(Vm)), absolute_sigma=True)\n", |
202 | 202 | "alpha_R = np.sqrt(R_fit_cov[0,0])\n", |
203 | | - "print(\"R = {0:.3f} ± {1:.3f} ohms\".format(R_fit[0], alpha_R))" |
| 203 | + "print(f\"R = {R_fit[0]:.3f} ± {alpha_R:.3f} ohms\")" |
204 | 204 | ] |
205 | 205 | }, |
206 | 206 | { |
|
217 | 217 | "outputs": [], |
218 | 218 | "source": [ |
219 | 219 | "# Compute and display chi-squared\n", |
220 | | - "res = Vm - vOhm(I_mA*1e-3, R_fit)\n", |
| 220 | + "res = Vm - v_ohm(I_mA*1e-3, R_fit)\n", |
221 | 221 | "normres = res/alphaV\n", |
222 | 222 | "chisq = np.sum(normres**2)\n", |
223 | | - "print(\"chisq = {0:.1f}\".format(chisq))" |
| 223 | + "print(f\"chisq = {chisq:.1f}\")" |
224 | 224 | ] |
225 | 225 | }, |
226 | 226 | { |
|
241 | 241 | "# Compute the probability of getting this fit result\n", |
242 | 242 | "dof = 10\n", |
243 | 243 | "cdf = chi2.cdf(chisq, dof)\n", |
244 | | - "print(\"Cumulative probability = {0:.6f}\".format(cdf))\n", |
245 | | - "print(\"Significance: {0:.6f}\".format(1-cdf))" |
| 244 | + "print(f\"Cumulative probability = {cdf:.6f}\")\n", |
| 245 | + "print(f\"Significance: {1-cdf:.6f}\")" |
246 | 246 | ] |
247 | 247 | }, |
248 | 248 | { |
|
279 | 279 | "outputs": [], |
280 | 280 | "source": [ |
281 | 281 | "# Define new model\n", |
282 | | - "def vOhm_offset(current, resistance, offset):\n", |
| 282 | + "def v_ohm_offset(current, resistance, offset):\n", |
283 | 283 | " return current*resistance + offset\n", |
284 | 284 | "\n", |
285 | 285 | "VoffInit = 0\n", |
286 | | - "p_fit, p_fit_cov = curve_fit(vOhm_offset, I_mA*1e-3, Vm, p0=[RInit,VoffInit], \n", |
| 286 | + "p_fit, p_fit_cov = curve_fit(v_ohm_offset, I_mA*1e-3, Vm, p0=[RInit,VoffInit], \n", |
287 | 287 | " sigma=alphaV*np.ones(np.size(Vm)), absolute_sigma=True)\n", |
288 | 288 | "R_fit = p_fit[0]\n", |
289 | 289 | "Voff_fit = p_fit[1]\n", |
290 | 290 | "alpha_R = np.sqrt(p_fit_cov[0,0])\n", |
291 | 291 | "alpha_Voff = np.sqrt(p_fit_cov[1,1])\n", |
292 | | - "print(\"R = {0:.3f} ± {1:.3f} ohms\".format(R_fit, alpha_R))\n", |
293 | | - "print(\"Voff = {0:.3f} ± {1:.3f} V\".format(Voff_fit, alpha_Voff))" |
| 292 | + "print(f\"R = {R_fit:.3f} ± {alpha_R:.3f} ohms\")\n", |
| 293 | + "print(f\"Voff = {Voff_fit:.3f} ± {alpha_Voff:.3f} V\")" |
294 | 294 | ] |
295 | 295 | }, |
296 | 296 | { |
|
307 | 307 | "outputs": [], |
308 | 308 | "source": [ |
309 | 309 | "# Compute and display chi-squared\n", |
310 | | - "res_offset = Vm - vOhm_offset(I_mA*1e-3, R_fit, Voff_fit)\n", |
| 310 | + "res_offset = Vm - v_ohm_offset(I_mA*1e-3, R_fit, Voff_fit)\n", |
311 | 311 | "normres_offset = res_offset/alphaV\n", |
312 | 312 | "chisq_offset = np.sum(normres_offset**2)\n", |
313 | | - "print(\"chisq_offset = {0:.1f}\".format(chisq_offset))\n", |
| 313 | + "print(f\"chisq_offset = {chisq_offset:.1f}\")\n", |
314 | 314 | "\n", |
315 | 315 | "# Compute the probability of getting this fit result\n", |
316 | 316 | "dof_offset = 9\n", |
317 | 317 | "cdf_offset = chi2.cdf(chisq_offset, dof_offset)\n", |
318 | | - "print(\"Cumulative probability = {0:.6f}\".format(cdf_offset))\n", |
319 | | - "print(\"Significance: {0:.6f}\".format(1-cdf_offset))" |
| 318 | + "print(f\"Cumulative probability = {cdf_offset:.6f}\")\n", |
| 319 | + "print(f\"Significance: {1-cdf_offset:.6f}\")" |
320 | 320 | ] |
321 | 321 | }, |
322 | 322 | { |
|
466 | 466 | "g_fit, g_fit_cov = curve_fit(t_fall, d_cm*1e-2, tm, p0=[gInit], \n", |
467 | 467 | " sigma=alpha_t_est*np.ones(np.size(tm)), absolute_sigma=True)\n", |
468 | 468 | "alpha_g = np.sqrt(g_fit_cov[0,0])\n", |
469 | | - "print(\"g = {0:.2f} ± {1:.2f} m/s^2\".format(g_fit[0], alpha_g))" |
| 469 | + "print(f\"g = {g_fit[0]:.2f} ± {alpha_g:.2f} m/s^2\")" |
470 | 470 | ] |
471 | 471 | }, |
472 | 472 | { |
|
486 | 486 | "res = tm - t_fall(d_cm*1e-2, g_fit)\n", |
487 | 487 | "normres = res/alpha_t_est\n", |
488 | 488 | "chisq = np.sum(normres**2)\n", |
489 | | - "print(\"chisq = {0:.1f}\".format(chisq))" |
| 489 | + "print(f\"chisq = {chisq:.1f}\")" |
490 | 490 | ] |
491 | 491 | }, |
492 | 492 | { |
|
508 | 508 | "dof = 9\n", |
509 | 509 | "cdf = chi2.cdf(chisq, dof)\n", |
510 | 510 | "sig = chi2.sf(chisq, dof)\n", |
511 | | - "print(\"Cumulative probability = {0:.6f}\".format(cdf))\n", |
512 | | - "print(\"Significance (1-cdf method): {0:.6f}\".format(1 - cdf))\n", |
513 | | - "print(\"Significance (sf method): {0:.6e}\".format(sig))" |
| 511 | + "print(f\"Cumulative probability = {cdf:.6f}\")\n", |
| 512 | + "print(f\"Significance (1-cdf method): {1 - cdf:.6f}\")\n", |
| 513 | + "print(f\"Significance (sf method): {sig:.6e}\")" |
514 | 514 | ] |
515 | 515 | }, |
516 | 516 | { |
|
543 | 543 | "$$\n", |
544 | 544 | "S = \\sqrt{\\frac{\\chi^2_\\text{min}}{\\nu}} = \\sqrt{\\chi^2_\\nu},\n", |
545 | 545 | "$$\n", |
546 | | - "so that the resulting $\\chi'^2_\\text{min} = S\\chi^2_\\text{min}$ matches the number of degrees of freedom exactly. Of course you forfeit the ability to use $\\chi'^2_\\text{min}$ as evidence of fit quality when you do this, so it is usually preferable to just go back and do a more careful measurement of the noise. This is definitely the case in this example, where $\\chi^2_\\text{min}$ indicates such a poor fit.\n", |
| 546 | + "so that the resulting $\\chi'^2_\\text{min} = S\\chi^2_\\text{min}$ matches the number of degrees of freedom exactly. Of course, you forfeit the ability to use $\\chi'^2_\\text{min}$ as evidence of fit quality when you do this, so it is usually preferable to just go back and do a more careful measurement of the noise. This is definitely the case in this example, where $\\chi^2_\\text{min}$ indicates such a poor fit.\n", |
547 | 547 | "\n", |
548 | 548 | "When $S\\approx 1$, though, it may be advantageous to scale the residuals to improve the accuracy of the *parameter uncertainty,* since the parameter uncertainty estimate given by `curve_fit` depends on $\\chi^2_\\text{min}$. The following code cell computes the scale factor for our example, then uses this to revise $\\alpha_g$. Another way to achieve the same result is to simply set `absolute_sigma=False` in the `curve_fit` algorithm—this will compute the fit by treating the values assigned to `sigma` as *relative uncertainties*, with an overall scale factor given by $S$ above. The defaults are `absolute_sigma=False` and `sigma` set to a vector of ones with the same size as the `y` data, so that when both `sigma` and `absolute_sigma` are omitted, `curve_fit` minimizes\n", |
549 | 549 | "\n", |
|
560 | 560 | "source": [ |
561 | 561 | "# Determine the scaling factor\n", |
562 | 562 | "S = np.sqrt(chisq/dof)\n", |
563 | | - "print(\"Scale factor: {0:.3f}\".format(S))\n", |
| 563 | + "print(f\"Scale factor: {S:.3f}\")\n", |
564 | 564 | "\n", |
565 | 565 | "# Scale measurement uncertainty by S\n", |
566 | | - "print(\"S*alpha_t_est = {0:.2f} ms\".format(1e3*S*alpha_t_est))\n", |
| 566 | + "print(f\"S*alpha_t_est = {1e3*S*alpha_t_est:.2f} ms\")\n", |
567 | 567 | "\n", |
568 | 568 | "# Compare with true measurement uncertainty\n", |
569 | | - "print(\"True alpha_t = {0:.2f}\".format(1e3*alpha_t))\n", |
| 569 | + "print(f\"True alpha_t = {1e3*alpha_t:.2f}\")\n", |
570 | 570 | "\n", |
571 | 571 | "# Scale parameter uncertainty by S\n", |
572 | | - "print(\"g = {0:.2f} ± {1:.2f} m/s^2 (scaled uncertainty)\".format(g_fit[0], S*alpha_g))\n", |
| 572 | + "print(f\"g = ({g_fit[0]:.2f} ± {S*alpha_g:.2f}) m/s^2 (scaled uncertainty)\")\n", |
573 | 573 | "\n", |
574 | 574 | "# Repeat fit with absolute_sigma=False\n", |
575 | 575 | "g_fit_scaled, g_fit_cov_scaled = curve_fit(t_fall, d_cm*1e-2, tm, p0=[gInit], \n", |
576 | 576 | " sigma=alpha_t_est*np.ones(np.size(tm)), absolute_sigma=False)\n", |
577 | 577 | "alpha_g_scaled = np.sqrt(g_fit_cov_scaled[0,0])\n", |
578 | | - "print(\"g = {0:.2f} ± {1:.2f} m/s^2 (absolute_sigma=False)\".format(g_fit_scaled[0], alpha_g_scaled))\n", |
| 578 | + "print(f\"g = ({g_fit_scaled[0]:.2f} ± {alpha_g_scaled:.2f}) m/s^2 (absolute_sigma=False)\")\n", |
579 | 579 | "\n", |
580 | 580 | "# Repeat fit without sigma or absolute_sigma keywords\n", |
581 | 581 | "g_fit_nosig, g_fit_cov_nosig = curve_fit(t_fall, d_cm*1e-2, tm, p0=[gInit])\n", |
582 | 582 | "alpha_g_nosig = np.sqrt(g_fit_cov_nosig[0,0])\n", |
583 | | - "print(\"g = {0:.2f} ± {1:.2f} m/s^2 (no sigma)\".format(g_fit_nosig[0], alpha_g_nosig))" |
| 583 | + "print(f\"g = ({g_fit_nosig[0]:.2f} ± {alpha_g_nosig:.2f}) m/s^2 (no sigma)\")" |
584 | 584 | ] |
585 | 585 | }, |
586 | 586 | { |
|
0 commit comments