Inizio importando le librerie rilevanti
import numpy as np
from matplotlib import pyplot as plt
from scipy.optimize import curve_fit
import sys, os, re, glob
I dati sono in formato csv
(Comma Separated Value), ovvero moralmente una matrice, le cui righe sono le righe del file, e le colonne sono separate da una virgola. I dati sono preceduti da un header che contiene una serie di informazioni utili, ma irrilevanti per caricare i dati.
I dati hanno il seguente aspetto
raw
#Digilent WaveForms Oscilloscope Acquisition
#Device Name: Discovery2
#Serial Number: SN:210321A80946
#Date Time: 2023-10-12 11:53:11.112
#Sample rate: 1e+08Hz
#Samples: 8192
#Trigger: Source: Channel 1 Type: Edge Condition: Rising Level: 0 V Hyst.: Auto HoldOff: 0 s
#Average: 50
#Channel 1: Range: 2 V/div Offset: 0 V Attenuation: 1 X Sample Mode: Average
#Channel 2: Range: 100 mV/div Offset: 0 V Attenuation: 1 X Sample Mode: Average
#Wavegen Channel 1: Running
#Mode: Simple
#Type: Square
#Frequency: 100 kHz
#Period: 10 us
#Amplitude: 5 V
#Offset: 0 V
#Symmetry: 50 %
#Phase: 0 �
Time (s),Channel 1 (V),Channel 2 (V)
-3.846e-05,5.085902338391357,0.06376411006974371
-3.845e-05,5.094266532267553,0.02677705734965165
-3.844e-05,5.110457597217541,-0.0434228710443975
-3.843e-05,5.110366054322634,-0.04297428551065288
-3.842e-05,5.109892687551182,-0.0422770834362886
-3.841e-05,5.109265147325687,-0.04156873124351793
...
Carico con loadtxt
, specificando il delimitatore, il numero di righe da salvare e unpack = True
per poter ottenere ciascuna colonna in un vettore differente
t, Vin, Vout = np.loadtxt('integratore_quadro_fit.csv', delimiter=',', unpack = True, skiprows = 21)
Verifico la dimensione dei files caricati
print(t.shape, Vin.shape)
(8192,) (8192,)
Definisco la funzione con cui intendo fittare, in questo caso banalmente una retta
def myLine(x, m, q):
return m*x+q
Plotto usando la notazione ad oggetti, in particolare
fig, ax = plt.subplots()
per creare la figuraax.plot(...)
per plottare i vettori di datilogico = (t > startFit) & (t < endFit)
creo un vettore logico di veri o falsi in base a dove la condizione è soddisfatta o meno vado ad effettuare il masking ovvero ottengo solo gli elementi in corrispondenza di dove la condizione vale 1. Questo semplifica anche la realizzazione di operazioni booleane (and, or...)%matplotlib inline
# %matplotlib widget
fig, ax = plt.subplots()
fig.set_size_inches(12, 5)
# Plotto i dati (*10 solo per visualizzare meglio)
ax.plot(t, Vin, marker = ".", ls = "", label = "Vin")
ax.plot(t, Vout * 10, marker = ".", ls = "", label = "Vout")
# Definisco gli estremi di fit
startFit = 0.1e-5
endFit = 0.4e-5
# Disegno le righe della regione di fit
ax.axvline(x = startFit, ls = "--", c = "grey")
ax.axvline(x = endFit, ls = "--", c = "grey")
# Creo la maschera booleana per i punti da fittare
logico = (t > startFit) & (t < endFit)
# ax.plot(t[logico], Vout[logico] * 10, marker = ".", ls = "", label = "Vout")
# Fit
popt, pcov = curve_fit(myLine, t[logico], Vout[logico])
# Plotto la curva fittata. L'operatore * effettua l'unpacking, ovvero è
# come se valesse tutti i suoi elementi, in ordine, separati da virgola
ax.plot(t[logico], 10 * myLine(t[logico], *popt ), lw = 3, c = "k")
ax.legend()
ax.set_xlabel("Time")
ax.set_ylabel("Amplitude")
ax.grid()
plt.show()