Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 85 additions & 11 deletions pulse.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ def analyticSignal(self):
def propagate(self, d, indexFct=None):
if indexFct is None:
indexFct = self.bk7
self.indexFct = indexFct

if np.mean(self.fieldEnvelope[0:10]) > 2e-4:
self.S += self.S
Expand All @@ -135,7 +136,7 @@ def setupPlot(self, title=""):
"https://raw.githubusercontent.com/dccote/Enseignement/master/SRC/dccote-errorbars.mplstyle")
plt.title(title)
plt.xlabel("Time [ps]")
plt.ylabel("Field amplitude [arb.u.]")
plt.ylabel("Amplitude [arb.u.]")
plt.ylim(-1, 1)

axis = plt.gca()
Expand All @@ -152,8 +153,23 @@ def setupPlot(self, title=""):
verticalalignment="top",
)

def drawTemporalAndSpectral(self, title=""):
fig, (axTime, axFreq) = plt.subplots(1, 2, figsize=(12, 5))

plt.sca(axTime)
self.setupPlot(title)
self.drawEnvelope(axTime)
self.drawChirpColour(axTime)

self.drawSpectrum(axFreq)
axFreq.set_title("Spectre")

plt.tight_layout()
return fig, axTime, axFreq

def tearDownPlot(self):
plt.clf()
plt.close("all")


def drawEnvelope(self, axis=None):
if axis is None:
Expand All @@ -174,7 +190,7 @@ def drawField(self, axis=None):
) = self.instantRadFrequency()

timeIsPs = instantTime * 1e12
axis.plot(timeIsPs, instantEnvelope * np.cos(instantPhase), "k-")
axis.plot(timeIsPs, instantEnvelope * np.cos(instantPhase), "k-", linewidth=0.5)

def drawChirpColour(self, axis=None):
if axis is None:
Expand Down Expand Up @@ -207,6 +223,54 @@ def drawChirpColour(self, axis=None):
Polygon([(t1, 0), (t1, e1), (t2, e2), (t2, 0)], facecolor=hsv(c))
)

def drawSpectrum(self, axis=None):
if axis is None:
axis = plt.gca()

plt.style.use(
"https://raw.githubusercontent.com/dccote/Enseignement/master/SRC/dccote-errorbars.mplstyle")

frequencies = self.frequencies
spectrum = self.spectrum
amplitudes = abs(spectrum)
amplitudes /= amplitudes.max()

positiveFreqs = np.extract(frequencies > 0, frequencies)
positiveAmps = np.extract(frequencies > 0, amplitudes)
positiveSpectrum = np.extract(frequencies > 0, spectrum)

freqsInTHz = positiveFreqs * 1e-12
axis.plot(freqsInTHz, positiveAmps, "k-")
axis.set_xlabel("Frequency [THz]")
axis.set_ylabel("Amplitude [arb.u.]")

fₒInTHz = self.fₒ * 1e-12
Δf = self.spectralWidth * 1e-12
axis.set_xlim(fₒInTHz - 5 * Δf, fₒInTHz + 5 * Δf)

# Spectral phase via group delay on the raw positive-frequency spectrum.
# angle(S[k+1]*conj(S[k])) gives the wrapped phase step per bin. Unwrapping
# the dPhase array is robust because the GVD variation between consecutive
# bins is tiny (~0.002 rad). Subtracting the mean removes the group delay,
# and cumsum recovers the GVD (quadratic) phase.
mask = positiveAmps > 0.2
maskedSpectrum = positiveSpectrum[mask]
maskedFreqs = freqsInTHz[mask]

dPhase = np.angle(maskedSpectrum[1:] * np.conj(maskedSpectrum[:-1]))
dPhase = np.unwrap(dPhase)
dPhase -= np.mean(dPhase)
envPhase = np.concatenate(([0], np.cumsum(dPhase)))

linearFit = np.polyfit(maskedFreqs, envPhase, 1)
envPhase -= np.polyval(linearFit, maskedFreqs)

axPhase = axis.twinx()
axPhase.plot(maskedFreqs, envPhase, "r-")
axPhase.set_ylabel("Phase [rad]")
axPhase.set_ylim(-2*π, 2*π)
axPhase.tick_params(axis="y")

def silica(self, wavelength):
x = wavelength * 1e6
if x < 0.3:
Expand Down Expand Up @@ -269,23 +333,25 @@ def water(self, wavelength):


# All adjustable parameters below
pulse = Pulse(𝛕=76e-15, 𝜆ₒ=805e-9) # 𝛕 must be the gaissian parameter in electric field
pulse = Pulse(𝛕=5e-15, 𝜆ₒ=805e-9) # 𝛕 must be the gaissian parameter in electric field
# pulse = Pulse(𝛕=1.4142*151e-15, 𝜆ₒ=1045e-9) # 𝛕 must be the gaissian parameter in electric field

# Material propertiues and distances, steps
material = pulse.silica
totalDistance = 0.196
steps = 40
totalDistance = 0.001
steps = 400

# What to display on graph in addition to envelope?
adjustTimeScale = False
showCarrier = False
adjustTimeScale = True
showCarrier = True
showChirpColour = True

# Save graph? (set to None to not save)
filenameTemplate = "fig-{0:02d}.png" # Can use PDF but PNG for making movies with Quicktime Player

# End adjustable parameters


print("#\td[mm]\t∆t[ps]\t∆𝝎[THz]\tProduct")
stepDistance = totalDistance / steps
for j in range(steps):
Expand All @@ -299,12 +365,20 @@ def water(self, wavelength):
)
)

# fig, axTime , _ = pulse.drawTemporalAndSpectral()

# # 𝛕 = pulse.temporalWidth*1e12
# axTime.set_xlim(-1, 1)
axTime = None
pulse.setupPlot("Propagation in {0}".format(material.__func__.__name__))
pulse.drawEnvelope()
pulse.drawChirpColour()
pulse.setupPlot()
pulse.drawEnvelope(axTime)

if showChirpColour:
pulse.drawChirpColour(axTime)

if showCarrier:
pulse.drawField()
pulse.drawField(axTime)

if adjustTimeScale:
𝛕 = pulse.temporalWidth*1e12
Expand Down