import numpy as np
import math
import matplotlib.pyplot as plt
import scipy.constants as sc
import sympy as sp
sp.init_printing()
%matplotlib inline
x,y,z,t = sp.symbols('x,y,z,t')
omega,phi,A = sp.symbols('omega,phi,A')
k, m, n = sp.symbols('k m n', integer=True)
f = sp.Function('f')
numpy og math kan lidt det samme. np.pi er det samme som math.pi.
scipy.constants importerer alle konstanter man kunne tænke sig sc.c sc.m_n for hhv lystets hastighed og neutronmassen se alle konstanter her .
sympy sympy kan lave CAS og solve.
Jeg kan bedst lige at bruge scipy til at differentiere og integrere. Men sympy kan også.
import math
BT = 2
def roundBT(x, BT):
if x == 0:
return '0'
else:
# Antallet af decimaler, der skal rundes til
decimal_places = BT - int(math.floor(math.log10(abs(x)))) - 1
# Rund tallet
rounded_value = round(x, decimal_places)
# Konverter til videnskabelig notation, hvis tallet er stort
if abs(rounded_value) >= 10**BT:
formatted_value = f"{rounded_value:.{BT-1}e}"
else:
# Ellers formater tallet uden unødvendige decimaler
formatted_value = f"{rounded_value:.{BT}g}"
return formatted_value
Koden til venstre bruges til at rundet et tal til antal betydende cifre variablen BT.
Med BT = 2 får man derfor følgende resultater:
BT = 2
print(roundBT(45359, BT)) # Forventet output: "4.5e4"
print(roundBT(0.45567, BT)) # Forventet output: "0.46"
print(roundBT(12345, BT)) # Forventet output: "1.2e4"
print(roundBT(math.pi, BT)) # Forventet output: "3.1"
Læg mærke til at koden formaterer 0.45567 til 0.46 og ikke 4.6e-1
Det synes jeg gør det lidt smukt kun at bruge scientific notation når det er nødvendigt.
Integration af en funktion med scipy
import numpy as np
import scipy.integrate as integrate
def f(x): return np.sin(x)
a = 0 #Nedre grænse
b = np.pi # Øvre grænse
result, error = integrate.quad(f, a, b)
print(f"Resultat: {result}")
print(f"Fejl: {error}")
Jeg kan bedre lide den numeriske metode da man har væredier i x_values og y_values klar i dejlige numpy arrays som man kan plotte og regne videre på.
Nedenstående kode bruger trapz med grænser
Numerisk integration med np.trapz
import numpy as np
x_values = np.linspace(0, np.pi, 100)
y_values = np.sin(x_values)
integral_value = np.trapz(y_values,x_values)
print(f"Resultat med trapz:{integral_value}")
Numpy trapz med grænser a til b
import numpy as np
x_values = np.linspace(0, np.pi, 100)
y_values = np.sin(x_values)
a = 0.4
b = 0.6
indices = np.where((x_values >= a) & (x_values <= b))
x_ny = x_values[indices]
y_ny = y_values[indices]
int_res = np.trapz(y_ny, x_ny)
print(f"Resultat {a} til {b}: {int_res}")
import numpy as np
import scipy.constants as sc
myt = np.linspace(-2,2,1000)
s_0 = 10#m
v_0 = 10#m/s
a_0 = sc.g
s_t = .5*a_0*myt**2 + v_0*myt + s_0
diffs_t = np.gradient(s_t, myt) #diff af s_t funktion
plt.plot(myt,s_t)
plt.plot(myt,diffs_t)
plt.grid()
import numpy as np
import scipy.constants as sc
import matplotlib.pyplot as plt
from scipy.signal import find_peaks
myt = np.linspace(-2, 2, 1000)
s_0 = 10 # m
v_0 = 10 # m/s
a_0 = sc.g
#s_t = -0.5*a_0*myt**2 + v_0 * myt + s_0
s_t = 0.5*a_0*myt**2 + v_0 * myt + s_0
diffs_t = np.gradient(s_t, myt)
peak, _ = find_peaks(s_t) #finder maxima
dal, _ = find_peaks(-s_t) #finder minimna
maxima = [(myt[p], s_t[p]) for p in peak]
minima = [(myt[t], s_t[t]) for t in dal]
print("Maxima:", maxima)
print("Minima:", minima)
# Plot s_t og dens afledte
plt.plot(myt, s_t, label='s(t)')
plt.plot(myt, diffs_t, label="s'(t)")
# Plot maxima og minima
plt.plot(myt[peak], s_t[peak], 'rx', label='Maxima')
plt.plot(myt[dal], s_t[dal], 'bo', label='Minima')
# Plot
plt.legend()
plt.grid()
plt.xlabel('Tid (s)')
plt.ylabel('Position (m)')
plt.title('s(t) og dens afledte med maxima og minima')
plt.show()
Igen her synes jeg det er en fordel at holde sig væk fra sympy, som selvfølgelig også kan beregne disse ting.
Ovenstående kode giver tre dejlig arrays
myt, s_t og diffs_t som jo er hastighedsfunktionen. Numpy arrays er supernem at manipulere med python. Sympy spytter sine egne formater ud og det kan være svært at få resultater over til python lister og arrays.
Et kast af en bold opad ville beskreves af følgende funktion
s_t = -0.5*a_0*myt**2 + v_0 * myt + s_0
hvor accelerationen er negativ. Her har funktionen et maximum med bevægelsesretningen opad.
Maxima: [(1.019019019019019, 15.098578681484288)]
Minima: []
Boldkast har et maksiumum ved (x,y) = (1.019,15.099) dvs at med en starthastighed på 10m/s flyver bolden 5.1m længere op i luften. Husk at s_0 = 10m :-)
Funktionen
s_t = 0.5*a_0*myt**2 + v_0 * myt + s_0
vil have et minimum ved (x,y) = (-1.019,4.901)
Maxima: []
Minima: [(-1.019019019019019, 4.901421318515712)]
Som man også kan se i grafen nedenunder.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# Læs CSV filen
file_path = 'datafil.csv'
df = pd.read_csv(file_path, sep=';', encoding='utf-8')
# Spring antal række over
df = df.iloc[1:]
# Replace commas with dots in the specified columns
df['Tid'] = df['Tid'].str.replace(',', '.').astype(float)
df['Lodret fart'] = df['Lodret fart'].str.replace(',', '.').astype(float)
# Extract x and y values
x_values = df['Tid'].values
y_values = df['Lodret fart'].values
# Ekstraher x- og y-værdier fra de relevante rækker og kolonner
x_values = df.iloc[start_row:, x_col].values
y_values = df.iloc[start_row:, y_col].values
Her er CSV filens struktur:
Ovenstående kode danner x_values og y_values klar til at bliver benyttet af python.
Koden til venstre importerer en CSV fil som skal ligge i samme mappe som pythonkoden.
file_path = 'datafil.csv'
Hvis man har en sti så kan den angives som fx
file_path = 'c:\mikkel\Skrivebord\datafil.csv'
Det kan være lidt vanskeligt at gøre det. Hvis du ikke ved hvilken mappe din python fil ligger i så søg på filnavnet. Jupyterfiler har efternavnet ipynb som fx "FysikA-opgaver.ipynb"
Åben excel fil og "gem som CSV" fil med semikolon ; som separator. Gem den i samme mappe som din ipynb fil så kan du nøjes med
file_path = 'datafil.csv'
Den blå del læser datafilen og kræver at separatoren er et semikolon ;
Den grønne del springer 1 linje over da data i denne fil starter i linje 3. Se filen til venstre.
Læg mærke at A1 og B1 er OVERSKRIFTER som altid er med i datafilen, det ved panda importen godt.
Den linje der skal springes over er linje 2.
# Spring antal række over
df = df.iloc[1:]
Den røde tekst erstatter komma , med punktum . så numpy / python kan arbejde med det.
Læg mærke til at i næste afsnit bruges teksten i A1 df['Tid'] og B2 'Lodret fart' til at definere hvilken række der skal læses. Disse ord skal selvfølgelig erstattes. Husk at store og små bogstaver betyder noget.
Find integralet fra 0.4 til max for et datasæt.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# Læs CSV filen
file_path = 'datafil.csv'
df = pd.read_csv(file_path, sep=';', encoding='utf-8')
# Spring antal række over
df = df.iloc[1:]
# Replace commas with dots in the specified columns
df['Tid'] = df['Tid'].str.replace(',', '.').astype(float)
df['Lodret fart'] = df['Lodret fart'].str.replace(',', '.').astype(float)
# Extract x and y values
x_values = df['Tid'].values
y_values = df['Lodret fart'].values
# Ekstraher x- og y-værdier fra de relevante rækker og kolonner
x_values = df.iloc[start_row:, x_col].values
y_values = df.iloc[start_row:, y_col].values
intfraA = 0.4 # starten på integralberegning
inttilB = 5.25 # slut på integrationen
indices = np.where((x_values >= intfraA) & (x_values <= inttilB))
x_fill = x_values[indices]
y_fill = y_values[indices]
integral_value = np.trapz(y_fill, x_fill)#trapz beregner integral
print("Integral value:", integral_value)
plt.fill_between(x_fill, y_fill, alpha=0.3)
plt.plot(x_values, y_values)
plt.plot(x_fill, y_fill)
plt.grid()
plt.legend(loc='upper left', title=f'Integral fra ({intfraA} til {inttilB}) = {integral_value:.4f}')
plt.show()
De mørkegule rækker definerer over hvad der skal integreres. her fra 0.4 til 5.25.
np.trapz udfører selve integrationen og spytter integralværdien ud.
plt.fill_between er en matplotlib feature der viser integralværdien grafisk i figuren.
Den lila kode plt.legend plotter integralværdien ind i figuren.