<jupyter_start><jupyter_text>SCEE and Simphony SiPANN includes a module that wraps all of the models produced by SCEE for easy use in [simphony](https://simphonyphotonics.readthedocs.io/en/latest/), allowing for cascading devices to make complex structures. This gives the user multiple options (Interconnect or Simphony) to cascade devices.The SCEE wrapper can be found in `SiPANN.scee_int`.<jupyter_code>from SiPANN import scee
from SiPANN.scee_int import SimphonyWrapper

from simphony.library import ebeam
from simphony.netlist import Subcircuit
from simphony.simulation import SweepSimulation, MonteCarloSweepSimulation

import matplotlib.pyplot as plt
import numpy as np

def pltAttr(x, y, title=None, legend='upper right', save=None):
    if legend is not None:
        plt.legend(loc=legend)
    plt.xlabel(x)
    plt.ylabel(y)
    if title is not None:
        plt.title(title)
    if save is not None:
        plt.savefig(save)<jupyter_output><empty_output><jupyter_text>Standard Simulation First we'll make our device like we always have using `SiPANN.scee`.<jupyter_code>r = 10000
w = 500
t = 220
wavelength = np.linspace(1500, 1600)
gap = 100

hr = scee.HalfRing(w, t, r, gap)<jupyter_output><empty_output><jupyter_text>Simply put our device into the simphony wrapper.<jupyter_code>s_hr = SimphonyWrapper(hr)<jupyter_output><empty_output><jupyter_text>Then use in simphony like you would any other device. Here we'll make a ring resonator as an example.<jupyter_code>def make_ring(half_ring):
    term = ebeam.ebeam_terminator_te1550()

    circuit = Subcircuit()
    circuit.add([
        (half_ring, 'input'),
        (half_ring, 'output'),
        (term, 'terminator')
    ])

    circuit.elements['input'].pins = ('pass', 'midb', 'in', 'midt')
    circuit.elements['output'].pins = ('out', 'midt', 'term', 'midb')

    circuit.connect_many([
        ('input', 'midb', 'output', 'midb'),
        ('input', 'midt', 'output', 'midt'),
        ('terminator', 'n1', 'output', 'term')
    ])
    
    return circuit
# Simphony takes in wavelength values in meters
circuit = make_ring(s_hr)
sim1 = SweepSimulation(circuit, 1500e-9, 1600e-9)
res1 = sim1.simulate()

f1, s = res1.data(res1.pinlist['in'], res1.pinlist['pass'])
plt.figure(figsize=(10,6))
plt.plot(f1, s)
pltAttr('Frequency (Hz)', 'Magnitude', "10-micron Ring Resonator")
plt.tight_layout()
plt.show()<jupyter_output>No handles with labels found to put in legend.<jupyter_text>Monte-Carlo Simulations `SimphonyWrapper` also functions with monte_carlo simulations. It allows ANY of the parameters set in SiPANN to be used. To use it you must include a dictionary mapping the parameter you wish to perturb to a standard deviation in nm.<jupyter_code>sigmas = {"width": 2, "thickness": 1}
s_hr = SimphonyWrapper(hr, sigmas)<jupyter_output><empty_output><jupyter_text>And then simply make our circuit as before, and run through monte-carlo simulations<jupyter_code>circuit = make_ring(s_hr)
#run monte carlo simulation
simulation = MonteCarloSweepSimulation(circuit, 1500e-9, 1600e-9)
runs = 5
result = simulation.simulate(runs=runs)

#plot
plt.figure(figsize=(10,6))
for i in range(1, runs + 1):
    f, s = result.data('in', 'pass', i)
    plt.plot(f, s)

# The data located at the 0 position is the ideal values.
f, s = result.data('in', 'pass', 0)
plt.plot(f, s, 'k')
pltAttr('Frequency (Hz)', 'Magnitude', "10-micron RR Monte-Carlo (width and thickness)", legend=None)
plt.tight_layout()
plt.show()<jupyter_output><empty_output><jupyter_text>As an example, we'll do another simulation, but this time varying radius of the ring only. Note we could vary both sides of the ring independently as well (ie the gap distance on each side isn't necessarily going to be equal), but for simplicity using our `make_ring` function we have identical halves.<jupyter_code>sigmas = {"radius": 20}
s_hr = SimphonyWrapper(hr, sigmas)

circuit = make_ring(s_hr)
#run monte carlo simulation
simulation = MonteCarloSweepSimulation(circuit, 1500e-9, 1600e-9)
runs = 5
result = simulation.simulate(runs=runs)

#plot
plt.figure(figsize=(10,6))
for i in range(1, runs + 1):
    f, s = result.data('in', 'pass', i)
    plt.plot(f, s)

# The data located at the 0 position is the ideal values.
f, s = result.data('in', 'pass', 0)
plt.plot(f, s, 'k')
pltAttr('Frequency (Hz)', 'Magnitude', "10-micron RR Monte-Carlo (radius)", legend=None)
plt.tight_layout()
plt.show()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.12215973003374578, 'fraction_numerical': 0.021147356580427448, 'mean_word_length': 4.983849259757739, 'pattern_counts': {'":': 3, '<': 28, '<?xml version=': 0, '>': 28, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '557218', 'license': 'MIT', 'n_tokens_mistral': 1632, 'n_tokens_neox': 1493, 'n_words': 463, 'path': 'examples/Tutorials/Simphony.ipynb', 'repo_name': 'joamatab/SiPANN', 'size': '4445'}