Skip to content

Commit

Permalink
Time for merging and testing
Browse files Browse the repository at this point in the history
  • Loading branch information
daquintero committed Nov 11, 2024
1 parent ee5db2e commit 7507afb
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 27 deletions.
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ repos:
rev: ad3ff374e97e29ca87c94b5dc7eccdd29adc6296
hooks:
- id: codespell
args: ["-L TE,TE/TM,te,ba,FPR,fpr_spacing,ro,nd,donot,schem,Synopsys,ket,inout,astroid" ]
args: ["-L TE,TE/TM,te,ba,FPR,fpr_spacing,ro,nd,donot,schem,Synopsys,ket,inout,astroid,FOM,Komma" ]
additional_dependencies:
- tomli
43 changes: 24 additions & 19 deletions docs/examples/06a_analytical_mzm_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,23 @@
# - [2] Silicon Photonics Design: From Devices to Systems by Lukas Chrostowski and Michael Hochberg

# +
import piel
import matplotlib.pyplot as plt
from matplotlib import cm

import piel.models.frequency.photonic
import numpy as np
import jax.numpy as jnp
import pandas as pd
import os
# -

# ## Coupler Modelling
#
# A coupler represents a multi-port connection of optical connection towards another subset of optical connection. They can have many physical implementations, such as directional couplers, multi-mode interference couplers (MMIs), permittivity grid couplers such as those inverse designed, etc.
#
# ### 1x2 Coupler
# A 1x2 coupler, also known as a Y-branch, routes two optical connection into one, or viceversa as this is a reversible linear component. Note that we represent the electric fields as $E_{f}$ as phasors equivalent to $E=Ae^{j\omega + \phi}$. The transfer-matrix model for this device without considering propagation loss is:
# A 1x2 coupler, also known as a Y-branch, routes two optical connection into one, or vice-versa as this is a reversible linear component. Note that we represent the electric fields as $E_{f}$ as phasors equivalent to $E=Ae^{j\omega + \phi}$. The transfer-matrix model for this device without considering propagation loss is:
#
# \begin{equation}
# \begin{bmatrix}
Expand Down Expand Up @@ -117,7 +119,7 @@
# \end{bmatrix}
# \end{equation}
#
# Note that the imaginary $j$ term causes a $\pi / 2$ phase shift between teh direct and cross coupled inputs
# Note that the imaginary $j$ term causes a $\pi / 2$ phase shift between the direct and cross coupled inputs

from gdsfactory.components import mmi2x2

Expand Down Expand Up @@ -350,7 +352,7 @@

# ## Phase-Shifter Models

# A phase-shifter can be considered as an "active propagation path" which adds or substracts relative phase in reference to another optical path. If we assume we have two waveguides in parallel in an integrated platform, in order to construct the interferometer, we need to consider the addition of phase $\phi$ onto each of these paths. A more complete model considers the loss $\alpha$ ($\frac{N_p}{m}$) per path length $L$. This can be part of a waveguide model:
# A phase-shifter can be considered as an "active propagation path" which adds or subtracts relative phase in reference to another optical path. If we assume we have two waveguides in parallel in an integrated platform, in order to construct the interferometer, we need to consider the addition of phase $\phi$ onto each of these paths. A more complete model considers the loss $\alpha$ ($\frac{N_p}{m}$) per path length $L$. This can be part of a waveguide model:
#
# ### More Ideal Model
#
Expand Down Expand Up @@ -650,11 +652,11 @@ def waveguide_active_phase(phase):
# * $m_{ch}^*$ Effective mass of holes
# * $[Y]$ Vector of the Y branches (3dB beamsplitters)
# * $w$ angular frequency in which the refractive index is calculated
# * $w'$ integration variable angular frequency for which teh absorption spectrum files is to be integrated
# * $w'$ integration variable angular frequency for which the absorption spectrum files is to be integrated
# * $\mu_e$ electron mobility
# * $\mu_h$ hole mobility

# Propagation in ther ams of the interferometer is modeled by modifying the amplitude and phase of the phasors:
# Propagation in the of the interferometer is modeled by modifying the amplitude and phase of the phasors:
#
# \begin{equation}
# \begin{bmatrix}
Expand Down Expand Up @@ -724,16 +726,16 @@ def waveguide_active_phase(phase):
pi_delta_n_eff = pi_delta_neff_L / L
two_pi_delta_n_eff = two_pi_delta_neff_L / L
fig, ax = plt.subplots()
ax.plot(L, pi_delta_n_eff, "b-", label=r"$\pi$")
ax.plot(L, two_pi_delta_n_eff, "g--", label=r"$2\pi$")
ax.plot(L, pi_delta_n_eff, "-", label=r"$\pi$")
ax.plot(L, two_pi_delta_n_eff, "--", label=r"$2\pi$")
ax.legend()
ax.set_xlabel(r"$L$ (mm)", size=14)
ax.set_xticklabels(plt.xticks()[0] * 1e3)
ax.set_ylabel(r"$\Delta n_{eff}$", size=14)
ax.set_title(
"2um Electro-optic refractive index change per effective modulation length"
)
# fig.savefig("img/refractive_index_change_modulation_length.png")
fig.savefig(os.path.join(os.getenv("TAP"), "refractive_index_change_phase_length.png"))

# +
frey_dn_dT = np.array(
Expand Down Expand Up @@ -802,14 +804,14 @@ def waveguide_active_phase(phase):
dn_dt_dataframe.to_csv()

# +
fig, ax1 = plt.subplots(figsize=(6, 6))
fig, ax1 = plt.subplots(figsize=(12, 4))
ax1.set_xlabel(r"Temperature ($K$)", fontsize=14)
ax1.set_ylabel(r"Silicon Thermo-optic Coefficient $\frac{dn}{dT}$", fontsize=14)
ax1.set_yscale("log")
ax1.plot(
dn_dt_dataframe["temperature"][3:],
dn_dt_dataframe.dn_dT[3:],
"go",
"o",
label=r"$\frac{dn}{dT}$",
)

Expand All @@ -819,14 +821,14 @@ def waveguide_active_phase(phase):
ax2.set_ylabel(
"Silicon Absolute Refractive Index", fontsize=14
) # we already handled the x-label with ax1
ax2.plot(dn_dt_dataframe["temperature"][3:], dn_dt_dataframe.n[3:], "g--", label=r"$n$")
ax2.plot(dn_dt_dataframe["temperature"][3:], dn_dt_dataframe.n[3:], "--", label=r"$n$")
# ax2.tick_params(axis='y', labelcolor=color)
ax1.legend(loc="upper left", fontsize=14)
ax2.legend(loc="lower right", fontsize=14)

ax1.set_title(r"Cryogenic Thermo-optic Parameters", fontweight="bold", fontsize=16)
fig.tight_layout() # otherwise the right y-label is slightly clipped
fig.savefig("thermo_optic_temperature_dependence.png")
fig.savefig(os.path.join(os.getenv("TAP"), "thermo_optic_temperature_dependence.png"))
# -

# We note that the thermo-optic coefficient is variable of temperature
Expand Down Expand Up @@ -916,13 +918,13 @@ def waveguide_active_phase(phase):
# \Delta \alpha (w', E) = \alpha(w', E) - \alpha (w', 0)
# \end{equation}
#
# In teh case of change in absorption due to change in carrier concentration $\Delta N$:
# In the case of change in absorption due to change in carrier concentration $\Delta N$:
#
# \begin{equation}
# \Delta \alpha(w', \Delta N) = \alpha (w', \Delta N) - \alpha (w', 0)
# \end{equation}

# Perturbations in complex refractive index $\bar{n}$ inducted by teh application of electric field (electro-optic effects) or modualting the free carrier concentration.
# Perturbations in complex refractive index $\bar{n}$ inducted by the application of electric field (electro-optic effects) or modualting the free carrier concentration.
#
# Several electro-optic effects:
# * Pockels (refractive index change directly proportional to applied electric field only present in non-centrosymmetric crystals, unstrained silicon is centro-symmetric so does not have Pockel's unless deliberately strained)
Expand Down Expand Up @@ -1166,13 +1168,13 @@ def waveguide_active_phase(phase):
ax1.plot(
delta_N_h_standalone_variation_Ne_1e17_dataframe.delta_N_h,
delta_N_h_standalone_variation_Ne_1e17_dataframe.delta_alpha,
"b-",
"C0-",
label=r"$\Delta \alpha(\Delta N_h$)",
)
ax1.plot(
delta_N_e_standalone_variation_Nh_1e17_dataframe.delta_N_e,
delta_N_e_standalone_variation_Nh_1e17_dataframe.delta_alpha,
"m-.",
"C1-.",
label=r"$\Delta \alpha(\Delta N_e$)",
)
ax1.legend(loc="upper left", fontsize=14)
Expand All @@ -1185,13 +1187,13 @@ def waveguide_active_phase(phase):
ax2.plot(
delta_N_h_standalone_variation_Ne_1e17_dataframe.delta_N_h,
delta_N_h_standalone_variation_Ne_1e17_dataframe.delta_n,
"b--",
"C0--",
label=r"$\Delta n(\Delta N_h$)",
)
ax2.plot(
delta_N_e_standalone_variation_Nh_1e17_dataframe.delta_N_e,
delta_N_e_standalone_variation_Nh_1e17_dataframe.delta_n,
"m:",
"C1:",
label=r"$\Delta n(\Delta N_e$)",
)
ax2.set_ylabel(r"Refractive Index $\Delta n$", fontsize=14)
Expand All @@ -1207,5 +1209,8 @@ def waveguide_active_phase(phase):
fontsize=16,
)
fig.tight_layout() # otherwise the right y-label is slightly clipped
fig.savefig("nedeljkovic_dopant_concentration_variations.png")
# fig.savefig("nedeljkovic_dopant_concentration_variations.png")
fig.savefig(
os.path.join(os.getenv("TAP"), "nedeljkovic_dopant_concentration_variations.png")
)
# -
4 changes: 2 additions & 2 deletions piel/experimental/measurements/data/electro_optic.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def fill_missing_pm_out(

# Create a new PathTransmission instance with filled data
filled_path_transmission = PathTransmission(
ports=path_transmission.output.connection, transmission=filled_transmission
connection=path_transmission.output.connection, transmission=filled_transmission
)

# Compose a new ElectroOpticDCPathTransmission instance
Expand Down Expand Up @@ -163,7 +163,7 @@ def extract_electro_optic_dc_path_transmission_from_csv(

# Create PathTransmission instance with pm_out
path_transmission = PathTransmission(
ports=port_map,
connection=port_map,
transmission=pm_out_values, # `pm_out` may contain np.nan
)

Expand Down
12 changes: 7 additions & 5 deletions piel/visual/plot/signals/time/separate.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ def plot_multi_data_time_signal_different(
ylabel: str | Unit | list[Unit] | list = None,
title: str | Unit | list = None,
time_range_s: Tuple[float, float] = None, # Add time_range parameter
labels: list[str] = None,
**kwargs,
):
"""
Expand Down Expand Up @@ -96,6 +97,11 @@ def plot_multi_data_time_signal_different(
if (len(signal.time_s) == 0) or (signal.time_s is None):
raise ValueError(f"Signal '{signal.data_name}' has an empty time_s array.")

if labels is None:
label_i = signal.data_name
else:
label_i = labels[i]

time = np.array(signal.time_s) / x_correction
data = np.array(signal.data) / y_correction[i]

Expand All @@ -105,11 +111,7 @@ def plot_multi_data_time_signal_different(
time = time[mask]
data = data[mask] / y_correction[i]

axs[i].plot(
time,
data,
label=signal.data_name,
)
axs[i].plot(time, data, label=label_i)

axs[i].set_ylabel(ylabel[i])

Expand Down

0 comments on commit 7507afb

Please sign in to comment.