import%20marimo%0A%0A__generated_with%20%3D%20%220.23.16%22%0Aapp%20%3D%20marimo.App(width%3D%22medium%22)%0A%0Aasync%20with%20app.setup(hide_code%3DTrue)%3A%0A%20%20%20%20%23%20Setup%20cell%20for%20marimo%20notebook%2C%20can%20be%20ignored%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20import%20sys%0A%0A%20%20%20%20%23%20Import%20packages%20if%20running%20on%20marimo%20playground%0A%20%20%20%20if%20sys.executable%20%3D%3D%20%22%2Fhome%2Fpyodide%2Fthis.program%22%3A%0A%20%20%20%20%20%20%20%20import%20micropip%0A%0A%20%20%20%20%20%20%20%20await%20micropip.install(%0A%20%20%20%20%20%20%20%20%20%20%20%20%5B%22pint_pandas%3C%3D0.7%22%2C%20%22typing_extensions%3E%3D4.15.0%22%2C%20%22jablonski%3E%3D0.3.1%22%2C%20%22matplotlib%22%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20verbose%3DFalse%2C%0A%20%20%20%20%20%20%20%20)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_()%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%20Getting%20Started%20with%20Jablonski%0A%20%20%20%20Jablonski%20is%20a%20python%20library%20for%20simulating%20photochemical%20systems.%20It%20extends%20%5Bpoincare%5D(https%3A%2F%2Fdyscolab.github.io%2Fpoincare%2F)%2C%20a%20package%20for%20modelling%20dynamical%20systems.%20To%20get%20started%20let's%20implement%20a%20simplified%20version%20of%20the%20ruthenium%20tris(bipyridine)%20model%20described%20in%20https%3A%2F%2Fdoi.org%2F10.1016%2Fj.ccr.2020.213758.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20matplotlib.pyplot%20as%20plt%0A%20%20%20%20import%20numpy%20as%20np%0A%20%20%20%20import%20pint%0A%0A%20%20%20%20from%20jablonski%20import%20(%0A%20%20%20%20%20%20%20%20Simulator%2C%0A%20%20%20%20%20%20%20%20SingletState%2C%0A%20%20%20%20%20%20%20%20SpectroscopicSystem%2C%0A%20%20%20%20%20%20%20%20TripletState%2C%0A%20%20%20%20%20%20%20%20Parameter%2C%0A%20%20%20%20%20%20%20%20initial%2C%0A%20%20%20%20%20%20%20%20assign%2C%0A%20%20%20%20)%0A%20%20%20%20from%20jablonski.simulation%20import%20(%0A%20%20%20%20%20%20%20%20piecewise%2C%0A%20%20%20%20%20%20%20%20pulse_excitation%2C%0A%20%20%20%20%20%20%20%20spectral_time_resolved_emission%2C%0A%20%20%20%20)%0A%20%20%20%20from%20jablonski.transitions%20import%20(%0A%20%20%20%20%20%20%20%20Absorption%2C%0A%20%20%20%20%20%20%20%20InternalConversion%2C%0A%20%20%20%20%20%20%20%20IntersystemCrossing%2C%0A%20%20%20%20%20%20%20%20Phosphorescence%2C%0A%20%20%20%20%20%20%20%20ReverseIntersystemCrossing%2C%0A%20%20%20%20)%0A%0A%20%20%20%20u%20%3D%20pint.get_application_registry()%0A%0A%20%20%20%20%23%20Defiene%20Ruthenium%20tris(bipyridine)%0A%20%20%20%20class%20Ruthenium(SpectroscopicSystem)%3A%0A%20%20%20%20%20%20%20%20ground%3A%20SingletState%20%3D%20initial(%0A%20%20%20%20%20%20%20%20%20%20%20%200%20*%20u.eV%2C%20%22singlet%22%2C%20default%3D10%0A%20%20%20%20%20%20%20%20)%20%20%23%20Define%20ground%20state%0A%20%20%20%20%20%20%20%20MLCT_3%3A%20TripletState%20%3D%20initial(%0A%20%20%20%20%20%20%20%20%20%20%20%202.12%20*%20u.eV%2C%20%22triplet%22%2C%20default%3D0%0A%20%20%20%20%20%20%20%20)%20%20%23%20Triplet%20MLCT%20level%0A%20%20%20%20%20%20%20%20MLCT_1%3A%20SingletState%20%3D%20initial(2.74%2C%20default%3D0)%20%20%23%20Singlet%20MLCT%20level%0A%0A%20%20%20%20%20%20%20%20abs%20%3D%20Absorption(%0A%20%20%20%20%20%20%20%20%20%20%20%20ground%3Dground%2C%20excited%3DMLCT_1%2C%20rate%3D5.6e-17%20*%20u.cm**2%0A%20%20%20%20%20%20%20%20)%20%20%23%20Photon%20absorption%2C%20rate%20is%20cross-section%0A%20%20%20%20%20%20%20%20ph%20%3D%20Phosphorescence(%0A%20%20%20%20%20%20%20%20%20%20%20%20ground%3Dground%2C%20excited%3DMLCT_3%2C%20rate%3D1%20%2F%20(0.6%20*%20u.us)%20*%200.04%0A%20%20%20%20%20%20%20%20)%20%20%23%20Radiative%20decay%20from%20%20MLCT_3%20to%20ground%0A%20%20%20%20%20%20%20%20risc%20%3D%20ReverseIntersystemCrossing(%0A%20%20%20%20%20%20%20%20%20%20%20%20source%3DMLCT_3%2C%20target%3Dground%2C%20rate%3D1%20%2F%20(0.6%20*%20u.us)%20*%200.96%0A%20%20%20%20%20%20%20%20)%20%20%23%20Non%20radiative%20decay%20from%20%20MLCT_3%20to%20ground%0A%20%20%20%20%20%20%20%20isc%20%3D%20IntersystemCrossing(%0A%20%20%20%20%20%20%20%20%20%20%20%20source%3DMLCT_1%2C%20target%3DMLCT_3%2C%20rate%3D1%20%2F%20(1%20*%20u.ps)%20%0A%20%20%20%20%20%20%20%20)%20%20%23%20Non%20radiative%20decay%20from%20%20MLCT_1%20to%20MLCT_3%0A%0A%20%20%20%20return%20(%0A%20%20%20%20%20%20%20%20InternalConversion%2C%0A%20%20%20%20%20%20%20%20Parameter%2C%0A%20%20%20%20%20%20%20%20Phosphorescence%2C%0A%20%20%20%20%20%20%20%20ReverseIntersystemCrossing%2C%0A%20%20%20%20%20%20%20%20Ruthenium%2C%0A%20%20%20%20%20%20%20%20Simulator%2C%0A%20%20%20%20%20%20%20%20SingletState%2C%0A%20%20%20%20%20%20%20%20SpectroscopicSystem%2C%0A%20%20%20%20%20%20%20%20TripletState%2C%0A%20%20%20%20%20%20%20%20assign%2C%0A%20%20%20%20%20%20%20%20initial%2C%0A%20%20%20%20%20%20%20%20np%2C%0A%20%20%20%20%20%20%20%20piecewise%2C%0A%20%20%20%20%20%20%20%20plt%2C%0A%20%20%20%20%20%20%20%20pulse_excitation%2C%0A%20%20%20%20%20%20%20%20spectral_time_resolved_emission%2C%0A%20%20%20%20%20%20%20%20u%2C%0A%20%20%20%20)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_()%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20Let's%20break%20this%20down.%20First%20we%20import%20all%20necessary%20functions%20from%20Jablonski%20as%20well%20as%20%5Bpint%5D(https%3A%2F%2Fpint.readthedocs.io%2Fen%2Fstable%2F)%2C%20which%20will%20allow%20us%20to%20use%20units%20from%20a%20%60UnitResgitry%60.%0A%20%20%20%20Then%20we%20create%20a%20class%20which%20inherits%20from%20%60SpectroscopicSystem%60%20and%20we%20define%20three%20levels%3A%20%60ground%60%2C%20%60MLCT_1%60%2C%20and%20%60MLCT_3%60.%20Each%20has%20an%20%60energy%60%2C%20which%20will%20by%20default%20be%20interpret%20as%20eV%2C%20a%20%60multiplicity%60%20which%20is%20either%20%22singlet%22%20or%20%22triplet%22%2C%20and%20a%20default%20initial%20condition%20representing%20level%20population%20(which%20could%20optionally%20also%20have%20units).%20We%20then%20create%20a%20four%20transitions%3A%20%60Absorption%60%20represents%20photon%20absorption%2C%20which%20we%20give%20a%20ground%20state%2C%20an%20excited%20state%20and%20a%20rate%2C%20which%20represents%20the%20photon%20absorption%20cross%20section%20and%20must%20thus%20be%20in%20units%20of%20distance%20squared.%20There%20are%20three%20emissions%3A%20two%20non-radiative%2C%20%60ReverseIntersystemCrossing%60%20and%20%60IntersystemCrossing%60%2C%20and%20one%20radiative%2C%20%60Phosphorescence%60.%20This%20time%20the%20rate%20is%20the%20inverse%20of%20%24%5Ctext%7Blifetime%7D%20%5Ccdot%20%5Ctext%7Bquantum%20yield%7D%24%2C%20so%20it%20must%20be%20in%20units%20of%20inverse%20time.%20Transitions%20are%20later%20translated%20to%20ODEs%20(although%20stochastic%20simulation%20will%20be%20supported%20in%20the%20future).%20As%20an%20example%20the%20%60Absorption%60%20above%20translates%20to%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cbegin%7Baligned%7D%0A%20%20%20%20%5Cfrac%7Bd%5C%2C%5Ctext%7Bground%7D%7D%7Bdt%7D%20%26%3D%20-%5Ctext%7Brate%7D%20%5Ccdot%20%5Ctext%7Bpump%7D%20%5Ccdot%20%5Ctext%7Bground%7D%20%5C%5C%0A%20%20%20%20%5Cfrac%7Bd%5C%2C%5Ctext%7BMLCT%7D_1%7D%7Bdt%7D%20%26%3D%20%2B%5Ctext%7Brate%7D%20%5Ccdot%20%5Ctext%7Bpump%7D%20%5Ccdot%20%5Ctext%7Bground%7D%0A%20%20%20%20%5Cend%7Baligned%7D%0A%20%20%20%20%24%24%0A%0A%0A%20%20%20%20We%20can%20create%20a%20make%20a%20Jablonski%20diagram%20to%20visualize%20this%20easier.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(Ruthenium%2C%20plt)%3A%0A%20%20%20%20from%20jablonski.plots%20import%20jablonski_diagram%0A%0A%20%20%20%20fig%2C%20ax%20%3D%20jablonski_diagram(Ruthenium%2C%20figsize%3D(7%2C%203)%2C%20fontsize%3D8)%0A%20%20%20%20plt.show()%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_()%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20To%20simulate%20it%20we%20define%20a%20pulse%2C%20which%20we%20%20give%20an%20absorption%20which%20it%20excites%2C%20a%20height%2C%20which%20represents%20photon%20flux%20so%20it%20must%20be%20in%20units%20of%20%241%2F(%5Ctext%7Bdistance%7D%5E2%20%5Ccdot%20%5Ctext%7Btime%7D)%24%2C%20and%20a%20duration%20and%20a%20start%2C%20which%20is%200%20by%20default.%20Then%20we%20pass%20it%20to%20%60piecewise%60%20along%20with%20a%20%60Simulator%60%20for%20a%20system%2C%20and%20a%20series%20of%20times%20to%20save%20at%2C%20which%20are%20interpreted%20in%20seconds.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(Ruthenium%2C%20Simulator%2C%20np%2C%20piecewise%2C%20pulse_excitation%2C%20u)%3A%0A%20%20%20%20sim_1%20%3D%20Simulator(Ruthenium)%0A%20%20%20%20pulse_1%20%3D%20pulse_excitation(%0A%20%20%20%20%20%20%20%20%7BRuthenium.abs%3A%201e23%20%2F%20(u.cm**2%20*%20u.s)%7D%2C%20width%3D5%20*%20u.us%0A%20%20%20%20)%20%20%23%20Pulse%20in%20photon%20flux%0A%20%20%20%20result_1%20%3D%20piecewise(sim_1%2C%20events%3Dpulse_1%2C%20save_at%3Dnp.linspace(0%2C%2010%2C%20100)*%20u.us)%0A%20%20%20%20result_1%0A%20%20%20%20return%20(result_1%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_()%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20The%20result%20is%20an%20%5Bxarray%5D(https%3A%2F%2Fdocs.xarray.dev%2Fen%2Fstable%2F)%20%60DataSet%60%2C%20which%20we%20can%20plot%20by%20converting%20it%20to%20a%20%5Bpandas%5D(https%3A%2F%2Fpandas.pydata.org%2F)%20DataFrame%20and%20using%20the%20inbuilt%20method.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(result_1)%3A%0A%20%20%20%20result_1.pint.dequantify().to_dataframe().plot()%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_()%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20Jablonski%20Systems%20are%20composable%2C%20so%20to%20create%20the%20compound%20with%20Osmium%20defined%20in%20the%20paper%20we%20can%20create%20the%20Osmium%20compound%20separately%20and%20then%20combine%20them.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20Parameter%2C%0A%20%20%20%20Phosphorescence%2C%0A%20%20%20%20ReverseIntersystemCrossing%2C%0A%20%20%20%20SingletState%2C%0A%20%20%20%20SpectroscopicSystem%2C%0A%20%20%20%20TripletState%2C%0A%20%20%20%20assign%2C%0A%20%20%20%20initial%2C%0A%20%20%20%20u%2C%0A)%3A%0A%20%20%20%20%23%20Defiene%20Osmium%20Compound%0A%20%20%20%20class%20Osmium(SpectroscopicSystem)%3A%0A%20%20%20%20%20%20%20%20ground%3A%20SingletState%20%3D%20initial(%0A%20%20%20%20%20%20%20%20%20%20%20%200%20*%20u.eV%2C%20%22singlet%22%2C%20default%3D0%0A%20%20%20%20%20%20%20%20)%20%20%23%20Define%20ground%20state%0A%20%20%20%20%20%20%20%20MLCT_3%3A%20TripletState%20%3D%20initial(1.7%2C%20%22triplet%22%2C%20default%3D0)%20%20%23%20Singlet%20MLCT%20level%0A%20%20%20%20%20%20%20%20ph_rate%3A%20Parameter%20%3D%20assign(default%3D1%20%2F%20(50%20*%20u.ns)%20*%200.004)%0A%20%20%20%20%20%20%20%20ph%20%3D%20Phosphorescence(%0A%20%20%20%20%20%20%20%20%20%20%20%20ground%3Dground%2C%20excited%3DMLCT_3%2C%20rate%3Dph_rate%0A%20%20%20%20%20%20%20%20)%20%20%23%20Radiative%20decay%20from%20%20MLCT_3%20to%20ground%0A%20%20%20%20%20%20%20%20risc%20%3D%20ReverseIntersystemCrossing(%0A%20%20%20%20%20%20%20%20%20%20%20%20source%3DMLCT_3%2C%20target%3Dground%2C%20rate%3D1%20%2F%20(50%20*%20u.ns)%20*%200.996%0A%20%20%20%20%20%20%20%20)%20%20%23%20Non%20radiative%20decay%20from%20%20MLCT_3%20to%20ground%0A%0A%20%20%20%20return%20(Osmium%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_()%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20The%20definition%20is%20similar%2C%20but%20this%20time%20we%20can%20extract%20a%20rate%20into%20a%20separate%20%60Parameter%60.%20We%20then%20create%20instances%20of%20both%20in%20a%20separate%20System.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(InternalConversion%2C%20Osmium%2C%20Ruthenium%2C%20SpectroscopicSystem%2C%20u)%3A%0A%20%20%20%20%23%20Combine%20both%0A%20%20%20%20class%20Ru_Os(SpectroscopicSystem)%3A%0A%20%20%20%20%20%20%20%20ru%20%3D%20Ruthenium()%0A%20%20%20%20%20%20%20%20os%20%3D%20Osmium()%0A%0A%20%20%20%20%20%20%20%20transfer%20%3D%20InternalConversion(%0A%20%20%20%20%20%20%20%20%20%20%20%20high%3Dru.MLCT_3%2C%20low%3Dos.MLCT_3%2C%20rate%3D(2.2e7%20%2B%202e8)%20%2F%20u.s%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20back_transfer%20%3D%20InternalConversion(%0A%20%20%20%20%20%20%20%20%20%20%20%20high%3Dos.ground%2C%20low%3Dru.ground%2C%20rate%3D(9.1e7%20%2B%201.2e8)%20%2F%20u.s%0A%20%20%20%20%20%20%20%20)%0A%0A%20%20%20%20return%20(Ru_Os%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_()%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20To%20combine%20them%20we%20create%20instances%20of%20both%2C%20which%20will%20add%20both%20the%20levels%20and%20equations%20defined%20above.%20We%20can%20add%20more%20equations%20which%20represents%20the%20exchange%20of%20electrons.%20Simulation%20of%20the%20compound%20System%20is%20similar%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(Ru_Os%2C%20Simulator%2C%20np%2C%20piecewise%2C%20pulse_excitation%2C%20u)%3A%0A%20%20%20%20pulse_2%20%3D%20pulse_excitation(%0A%20%20%20%20%20%20%20%20%7BRu_Os.ru.abs%3A%201e25%20%2F%20(u.cm**2%20*%20u.s)%7D%2C%20width%3D5%20*%20u.ns%0A%20%20%20%20)%0A%0A%20%20%20%20sim_2%20%3D%20Simulator(Ru_Os)%0A%20%20%20%20result_2%20%3D%20piecewise(sim_2%2C%20events%3Dpulse_2%2C%20save_at%3Dnp.linspace(0%2C%2030%2C%20100)*u.ns)%0A%20%20%20%20result_2.pint.dequantify().to_dataframe().plot()%0A%20%20%20%20return%20(pulse_2%2C)%0A%0A%0A%40app.cell%0Adef%20_(Ru_Os%2C%20excitation%2C%20u)%3A%0A%20%20%20%20excitation%5BRu_Os.ru.abs%5D.to(1%2F%20(u.cm**2%20*%20u.s))%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_()%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20Apart%20from%20simulation%20Jablonski%20has%20a%20number%20of%20analysis%20tools.%20Instead%20of%20the%20population%20of%20each%20level%20we%20can%20get%20the%20spectral%20time%20resolved%20emission%20with%20the%20same%20pulse.%20We%20get%20the%20result%20by%20each%20line%20and%20%20dictionary%20which%20gives%20us%20each%20line's%20energy.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(Ru_Os%2C%20np%2C%20plt%2C%20pulse_2%2C%20spectral_time_resolved_emission%2C%20u)%3A%0A%20%20%20%20spectral%20%3D%20spectral_time_resolved_emission(%0A%20%20%20%20%20%20%20%20Ru_Os%2C%20excitation%3Dpulse_2%2C%20save_at%3Dnp.linspace(0%2C%2030%2C%20100)%20*%20u.ns%0A%20%20%20%20)%20%20%23%20Time%20resolved%20emission%0A%20%20%20%20spectral.pint.dequantify().to_dataframe().plot()%0A%20%20%20%20plt.yscale(%22log%22)%0A%20%20%20%20plt.show()%0A%20%20%20%20spectral.attrs%20%20%23%20Print%20dict%20with%20energy%20associated%20with%20each%20line%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_()%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20To%20get%20more%20realisic%20excitation%20we%20can%20use%20jablonki's%20helper%20functions.%20%60pump_from_laser%60%20allows%20us%20to%20calculate%20the%20resulting%20excitation%20whith%20the%20molecule%20in%20the%20center%20of%20a%20gaussian%20beam%20of%20a%20certatin%20width%20(as%20standard%20deviation)%2C%20power%2C%20wavelength%20and%20linewidth.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(Ru_Os%2C%20u)%3A%0A%20%20%20%20from%20jablonski.helpers%20import%20pump_from_laser%2C%20h%2C%20c%0A%0A%20%20%20%20wavelngth%20%3D%20(h*c)%2FRu_Os.ru.abs.energy_difference%0A%20%20%20%20excitation%20%3D%20pump_from_laser(Ru_Os%2C%20wavelength%3Dwavelngth%2Clinewidth%3D5*u.nm%2C%20%20power%3D%201*u.W%2C%20width%20%3D%201*u.mm)%0A%20%20%20%20excitation%0A%20%20%20%20return%20excitation%2C%20pump_from_laser%2C%20wavelngth%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_()%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20Since%20jablonski%20doesn't%20support%20line%20profiles%20yet%20the%20linewidth%20is%20taken%20as%20a%20simple%20tolerance%3A%20anything%20within%20it%20is%20pumped%20at%20full%20power%20and%20anything%20outside%20is%20ignored.%0A%0A%20%20%20%20This%20can%20be%20combined%20with%20jablonski's%20sweep%20functions.%20We%20can%20get%20the%20emission%20spectra%20for%20different%20intensities%20by%20using%20the%20%60sweep_emission_spectra%60%20with%20pumps%20for%20different%20laser%20powers.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(Ru_Os%2C%20np%2C%20plt%2C%20pump_from_laser%2C%20u%2C%20wavelngth)%3A%0A%20%20%20%20from%20jablonski.sweeps%20import%20sweep_emission_spectra%0A%0A%20%20%20%20powers%20%3D%20np.logspace(-1%2C2%2C%2020)%20*%20u.W%20%23%20Powers%20to%20sweep%20%0A%20%20%20%20excitations%20%3D%20%5Bpump_from_laser(Ru_Os%2C%20wavelength%3Dwavelngth%2Clinewidth%3D5*u.nm%2C%20%20power%3Dpower%2C%20width%20%3D%201*u.mm)%20for%20power%20in%20powers%5D%0A%20%20%20%20steady%20%3D%20sweep_emission_spectra(%0A%20%20%20%20%20%20%20%20Ru_Os%2C%0A%20%20%20%20%20%20%20%20excitations%3Dexcitations%2C%0A%20%20%20%20%20%20%20%20keys%20%3D%20powers%2C%0A%20%20%20%20)%20%20%23%20Sweep%20steady%20state%20emission%20spectra%0A%20%20%20%20df%20%3D%20steady.pint.dequantify().to_dataframe().T%0A%20%20%20%20df.index%20%3D%20df.index.map(lambda%20x%3A%20x.magnitude)%0A%20%20%20%20df.plot()%0A%20%20%20%20plt.xscale(%22log%22)%3Bplt.yscale(%22log%22)%3B%20plt.xlabel(%22Laser%20power%20%5BW%5D%22)%3B%20plt.ylabel(%22Emission%20%5Bphtons%20%2F%20s%5D%22)%0A%20%20%20%20plt.show()%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_()%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20The%20%60keys%60%20attribute%20gives%20us%20the%20keys%20for%20our%20Dataset.%20If%20the%20excitation%20affects%20only%20one%20transition%20it%20can%20be%20omitted%20and%20defaults%20to%20the%20pump%20intensity%2C%20but%20in%20this%20case%20it%20makes%20more%20sense%20to%20use%20the%20laser%20power.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_()%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Other%20utilities%0A%20%20%20%20Jablonsi%20contains%20a%20number%20of%20other%20built-in%20classes%20to%20represent%20common%20photochemical%20transitions%2C%20found%20in%20%60jablonski.transitions%60%2C%20simulaton%20tools%2C%20found%20in%20%60jablonski.simulation%60%2C%20and%20graphical%20output%20tools%2C%20found%20in%20%60jablonski.plots%60%2C%20all%20of%20which%20are%20listed%20below.%20Since%20Jablonski%20is%20an%20extension%20of%20poincare%20most%20poincare%20utilities%20are%20also%20valid%20with%20jablonski%20and%20systems%20can%20interoperate%20(i.e.%20a%20system%20can%20be%20defined%20partly%20by%20transitions%20and%20partly%20by%20explicit%20ODEs).%20For%20more%20information%20see%20%5Bpoincare's%20documentation%5D(https%3A%2F%2Fdyscolab.github.io%2Fpoincare%2F%23documentation).%0A%0A%20%20%20%20%23%23%23%20Transitions%0A%20%20%20%20-%20%60Absorption(ground%3A%20SingletState%2C%20excited%3A%20SingletState%2C%20rate%3A%20Parameter%2C%20pump%3A%20Parameter)%60%3A%20A%20molecule%20absorbs%20a%20photon%20and%20is%20promoted%20from%20its%20ground%20(or%20any%20lower)%20singlet%20state%20to%20an%20excited%20singlet%20state%2C%20%24S_0%20%5Crightarrow%20S_1%24.%20The%20effective%20rate%20is%20%60rate%20*%20pump%60.%0A%0A%20%20%20%20-%20%60TripletTripletAbsorption(ground%3A%20TripletState%2C%20excited%3A%20TripletState%2C%20rate%3A%20Parameter%2C%20pump%3A%20Parameter)%60%3A%20A%20molecule%20in%20a%20lower%20triplet%20state%20absorbs%20a%20photon%20and%20is%20promoted%20to%20a%20higher%20triplet%20state%2C%20%24T_1%20%5Crightarrow%20T_n%24.%20The%20effective%20rate%20is%20%60rate%20*%20pump%60.%0A%0A%20%20%20%20-%20%60VibrationalRelaxation(high%3A%20SpinState%2C%20low%3A%20SpinState%2C%20rate%3A%20Parameter)%60%3A%20A%20non-radiative%20transition%20to%20a%20lower%20vibrational%20level%20within%20the%20same%20electronic%20state%2C%20%24S_n(v')%20%5Crightarrow%20S_n(v)%24.%0A%0A%20%20%20%20-%20%60InternalConversion(high%3A%20SpinState%2C%20low%3A%20SpinState%2C%20rate%3A%20Parameter)%60%3A%20A%20non-radiative%20transition%20between%20two%20electronic%20states%20of%20the%20same%20spin%20multiplicity%2C%20%24S_2%20%5Crightarrow%20S_1%24.%0A%0A%20%20%20%20-%20%60Fluorescence(excited%3A%20SpinState%2C%20ground%3A%20SpinState%2C%20rate%3A%20Parameter)%60%3A%20A%20radiative%20transition%20between%20two%20electronic%20states%20of%20the%20same%20spin%20multiplicity%2C%20emitting%20a%20photon%2C%20%24S_1%20%5Crightarrow%20S_0%20%2B%20h%5Cnu%24.%0A%0A%20%20%20%20-%20%60IntersystemCrossing(source%3A%20SingletState%2C%20target%3A%20TripletState%2C%20rate%3A%20Parameter)%60%3A%20A%20non-radiative%20transition%20between%20isoenergetic%20vibrational%20levels%20of%20electronic%20states%20with%20different%20spin%20multiplicity%2C%20crossing%20from%20singlet%20to%20triplet%2C%20%24S_1%20%5Crightarrow%20T_1%24.%0A%0A%20%20%20%20-%20%60ReverseIntersystemCrossing(source%3A%20TripletState%2C%20target%3A%20SingletState%2C%20rate%3A%20Parameter)%60%3A%20A%20non-radiative%20transition%20between%20isoenergetic%20vibrational%20levels%20of%20electronic%20states%20with%20different%20spin%20multiplicity%2C%20crossing%20from%20triplet%20back%20to%20singlet%2C%20%24T_1%20%5Crightarrow%20S_1%24.%0A%0A%20%20%20%20-%20%60Phosphorescence(excited%3A%20SpinState%2C%20ground%3A%20SpinState%2C%20rate%3A%20Parameter)%60%3A%20A%20radiative%20transition%20between%20two%20electronic%20states%20of%20different%20spin%20multiplicity%2C%20emitting%20a%20photon%2C%20%24T_1%20%5Crightarrow%20S_0%20%2B%20h%5Cnu%24.%0A%0A%20%20%20%20-%20%60EnergyTransferUpconversion(sensitizer%3A%20SingletState%2C%20activator%3A%20SingletState%2C%20relaxator%3A%20SingletState%2C%20rate%3A%20Parameter)%60%3A%20Two%20sensitizer%20molecules%20in%20an%20excited%20state%20transfer%20their%20combined%20energy%20to%20promote%20an%20activator%20to%20a%20higher%20state%20while%20a%20relaxator%20relaxes%20to%20a%20lower%20one%2C%20%242%20%5Ccdot%20%5Ctext%7BSensitizer%7D%20%5Crightarrow%20%5Ctext%7BActivator%7D%20%2B%20%5Ctext%7BRelaxator%7D%24.%0A%0A%20%20%20%20-%20%60EnergyTransferUpconversion4(sensitizer%3A%20SingletState%2C%20activator%3A%20SingletState%2C%20relaxator%3A%20SingletState%2C%20rate%3A%20Parameter)%60%3A%20Two%20molecules%20in%20an%20excited%20state%20transfer%20their%20combined%20energy%20to%20promote%20an%20activator%20to%20a%20higher%20state%20while%20a%20sensitizer%20relaxes%20to%20a%20lower%20one%2C%20differen%20from%20%60EnergyTransferUpconversion%60%20in%20that%20both%20electrons%20can%20intially%20be%20in%20different%20levels%2C%20%24%5Ctext%7Bsensitizer%5C_high%7D%20%2B%20%5Ctext%7Bactivator%5C_low%7D%20%20%5Crightarrow%20%5Ctext%7Bsensitizer%5C_low%7D%20%2B%20%5Ctext%7Bactivator%5C_high%7D%24.%0A%0A%0A%20%20%20%20All%20transitions%20use%20%60MassAction%60%20kinetics.%20For%20example%2C%20%60Fluorescence(excited%3DS1%2C%20ground%3DS0%2C%20rate%3Dk)%60%20gives%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cbegin%7Baligned%7D%0A%20%20%20%20%5Cfrac%7BdS_1%7D%7Bdt%7D%20%26%3D%20-kS_1%20%5C%5C%0A%20%20%20%20%5Cfrac%7BdS_0%7D%7Bdt%7D%20%26%3D%20%2BkS_1%0A%20%20%20%20%5Cend%7Baligned%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20Jablonski%20contains%20a%20list%20of%20excpected%20ranges%20for%20all%20rates.%20To%20check%20them%20use%20%60transitions.check_all(system%3A%20SpectroscopicSystem)%60%2C%20which%20will%20raise%20warnings%20if%20any%20transitions%20have%20rates%20out%20of%20the%20expected%20range.%0A%0A%20%20%20%20%23%23%23%20Simulation%20tools%0A%20%20%20%20**Time-resolved%20simulation**%20functions%20integrate%20the%20system%20dynamics%20over%20time%3A%0A%0A%20%20%20%20-%20%60piecewise(sim%3A%20Simulator%2C%20events%3A%20dict%5BTime%2C%20Mapping%5D%2C%20save_at%3A%20NDArray)%60%3A%20Low-level%20solver%20that%20integrates%20a%20%60Simulator%60%20across%20a%20sequence%20of%20time%20segments%2C%20applying%20parameter%20changes%20at%20each%20event%20boundary.%20Returns%20an%20xarray%20%60Dataset%60.%0A%0A%20%20%20%20-%20%60time_resolved_emission(system%3A%20SpectroscopicSystem%2C%20excitation%3A%20dict%2C%20save_at%3A%20NDArray%2C%20kind%3A%20SpectraKind%20%3D%20%22emission%22)%60%3A%20Simulates%20total%20emission%20intensity%20over%20time%20for%20all%20radiative%20transitions%20in%20%60system%60%2C%20summed%20across%20all%20emission%20lines.%20Returns%20an%20xarray%20%60Dataset%60%20with%20a%20single%20%60emission%60%20variable.%0A%0A%20%20%20%20-%20%60spectral_time_resolved_emission(system%3A%20SpectroscopicSystem%2C%20excitation%3A%20dict%2C%20save_at%3A%20NDArray%2C%20kind%3A%20SpectraKind%20%3D%20%22emission%22%2C%20join_by_energy%3A%20bool%20%3D%20False)%60%3A%20Like%20%60time_resolved_emission%60%2C%20but%20returns%20each%20emission%20line%20separately.%20If%20%60join_by_energy%3DTrue%60%2C%20lines%20sharing%20the%20same%20energy%20difference%20are%20summed%20together.%20Returns%20an%20xarray%20%60Dataset%60.%0A%0A%0A%20%20%20%20**Excitation%20creators**%20build%20event%20dictionaries%20to%20be%20passed%20to%20simulation%20functions%3A%0A%0A%20%20%20%20-%20%60step_excitation(excitation%3A%20dict%2C%20start%3A%20Time%20%3D%200%20*%20u.s)%60%3A%20Creates%20a%20step%20excitation%20that%20turns%20on%20at%20%60start%60%20and%20remains%20on%2C%20setting%20%60excitation_transition.pump%60%20to%20%60height%60.%0A%0A%20%20%20%20-%20%60pulse_excitation(excitation%3A%20dict%2C%20width%3A%20Time%2C%20start%3A%20Time%20%3D%200%20*%20u.s)%60%3A%20Creates%20a%20finite%20pulse%20excitation%20of%20duration%20%60width%60%20starting%20at%20%60start%60%2C%20setting%20%60excitation_transition.pump%60%20to%20%60height%60%20and%20then%20back%20to%20zero.%0A%0A%20%20%20%20-%20%60delta_excitation(excitation_transition%3A%20Pumper%2C%20area%3A%20Time%2C%20start%3A%20Time%20%3D%200%20*%20u.s)%60%3A%20Creates%20an%20approximation%20of%20a%20%24%5Cdelta%24-function%20excitation%20with%20a%20given%20integrated%20%60area%60%2C%20implemented%20as%20a%20very%20short%20pulse%20of%20proportionally%20large%20height.%0A%0A%20%20%20%20**Steady-state%20simulation**%20functions%20compute%20the%20long-time%20equilibrium%20of%20the%20system%20under%20continuous%20excitation%3A%0A%0A%20%20%20%20-%20%60steady_state_emission(system%3A%20SpectroscopicSystem%2C%20excitation%3A%20dict%2C%20kind%3A%20SpectraKind%20%3D%20%22emission%22)%60%3A%20Computes%20total%20steady-state%20emission%20intensity%2C%20summed%20over%20all%20radiative%20transitions.%20Returns%20an%20xarray%20%60Dataset%60%20with%20a%20single%20%60emission%60%20variable.%0A%0A%20%20%20%20-%20%60spectral_steady_state_emission(system%3A%20SpectroscopicSystem%2C%20excitation%3A%20dict%2C%20kind%3A%20SpectraKind%20%3D%20%22emission%22%2C%20join_by_energy%3A%20bool%20%3D%20False)%60%3A%20Like%20%60steady_state_emission%60%2C%20but%20returns%20each%20emission%20line%20separately%2C%20optionally%20accepting%20multiple%20simultaneous%20excitation%20sources.%20If%20%60join_by_energy%3DTrue%60%2C%20lines%20sharing%20the%20same%20energy%20difference%20are%20summed%20together.%20Returns%20an%20xarray%20%60Dataset%60%20with%20a%20dictionary%20mapping%20the%20line's%20key%20to%20the%20actual%20pint%20quantity%20representing%20the%20enrgy%20in%20%60Dataset.attrs%60.%0A%0A%20%20%20%20**Spectra**%20functions%20compute%20emission%20and%20excitation%20spectra%20as%20a%20function%20of%20wavelength%3A%0A%0A%20%20%20%20-%20%60emission_spectra(system%3A%20SpectroscopicSystem%2C%20excitation%3A%20dict%2C%20unit%3A%20str%20%7C%20Unit%20%3D%20u.nm%2C%20kind%3A%20SpectraKind%20%3D%20%22emission%22)%60%3A%20Computes%20a%20CW%20emission%20spectrum%2C%20converting%20energy%20differences%20to%20wavelengths%20in%20the%20given%20%60unit%60.%20Returns%20an%20xarray%20%60DataArray%60%20indexed%20by%20wavelength.%0A%0A%20%20%20%20-%20%60widened_emission_spectra(system%3A%20SpectroscopicSystemexcitation%3A%20dict%2C%20unit%3A%20str%20%7C%20Unit%20%3D%20u.nm%2C%20kind%3A%20SpectraKind%20%3D%20%22emission%22%2C%20samples%3A%20Iterable%5Bfloat%5D%20%3D%20np.linspace(380%2C%20700%2C%201000)%2C%20width%3A%20float%20%3D%205)%60%3A%20Like%20%60emission_spectra%60%2C%20but%20broadens%20each%20discrete%20emission%20line%20into%20a%20Gaussian%20of%20standard%20deviation%20%60width%60%20and%20evaluates%20the%20result%20over%20%60samples%60%2C%20mostly%20useful%20to%20generate%20plots%20manually%20(altough%20%60plots.graph_spectra%60%20can%20be%20uesd%20for%20that).%20Returns%20an%20xarray%20%60DataArray%60%20indexed%20by%20wavelength.%0A%0A%20%20%20%20-%20%60excitation_emission_matrix(system%3A%20SpectroscopicSystem%2C%20height%3A%20float%20%7C%20Iterable%5Bfloat%5D%2C%20unit%3A%20str%20%7C%20Unit%20%3D%20u.nm)%60%3A%20Computes%20a%20emission%20spectra%20for%20every%20%60Pumper%60%20in%20%60system%60%2C%20returning%20the%20full%20excitation-emission%20matrix%20as%20an%20xarray%20%60Dataset%60%20keyed%20by%20pumper%20excited.%0A%0A%20%20%20%20-%20%60excitation_spectra(system%3A%20SpectroscopicSystem%2C%20emission%3A%20float%20%7C%20int%20%7C%20Quantity%2C%20height%3A%20float%20%7C%20Iterable%5Bfloat%5D%2C%20unit%3A%20str%20%7C%20Unit%20%3D%20u.nm)%60%3A%20Extracts%20a%20slice%20of%20the%20excitation-emission%20matrix%20at%20a%20fixed%20emission%20wavelength%2C%20returning%20intensity%20as%20a%20function%20of%20excitation%20source.%20Returns%20an%20xarray%20%60DataArray%60%20indexed%20by%20pumper.%0A%0A%20%20%20%20%23%23%23%20Graphical%20output%0A%0A%20%20%20%20-%20%60graph_spectra(system%3A%20SpectroscopicSystem%2C%20excitation%3A%20dict%2C%20unit%3A%20str%20%7C%20Unit%20%3D%20u.nm%2C%20kind%3A%20SpectraKind%20%3D%20%22emission%22%2C%20samples%3A%20Iterable%5Bfloat%5D%20%3D%20np.linspace(380%2C%20700%2C%201000)%2C%20width%3A%20float%20%3D%205)%60%3A%20Plots%20a%20widened%20emission%20spectrum%20as%20a%20wavelength-colored%20line%2C%20with%20wavelength%20on%20the%20x-axis%20and%20emission%20intensity%20in%20photons%20on%20the%20y-axis.%20Returns%20a%20%60(fig%2C%20ax)%60%20tuple.%0A%0A%0A%20%20%20%20-%20%60jablonski_diagram(system%3A%20SpectroscopicSystem%2C%20figsize%3A%20tuple%5BNumber%2C%20Number%5D%20%3D%20(6.4%2C%204.8)%2C%20fontsize%3A%20Number%20%3D%2010%2C%20show_energy_axis%3A%20bool%20%3D%20True%2C%20unit%3A%20str%20%7C%20Unit%20%3D%20u.eV)%60%3A%20Renders%20a%20Jablonski%20diagram%20for%20%60system%60%2C%20organizing%20states%20into%20singlet%20and%20triplet%20columns%20with%20energy%20on%20the%20y-axis%20in%20the%20given%20%60unit%60.%20Radiative%20and%20non-radiative%20transitions%20are%20drawn%20distinctly%20by%20a%20straight%20and%20wiggly%20line%20respectively.%20Returns%20a%20%60(fig%2C%20ax)%60%20tuple.%0A%0A%20%20%20%20-%20%60model_report(model%3A%20type%5BSpectroscopicSystem%5D%2C%20path%3A%20str%20%7C%20None%20%3D%20None%2C%20transform%3A%20dict%20%7C%20None%20%3D%20None%2C%20descriptions%3A%20dict%20%7C%20None%20%3D%20None%2C%20standalone%3A%20bool%20%3D%20True%2C%20replace_algebraics%3A%20bool%20%3D%20False)%60%3A%20Generates%20a%20Latex%20report%20for%20%60model%60%2C%20including%20a%20Jablonski%20diagram%20section%20rendered%20as%20a%20PGF%20figure%20alongside%20the%20default%20model%20sections.%20If%20%60path%60%20is%20provided%20the%20report%20is%20written%20to%20disk%3B%20otherwise%20the%20source%20is%20returned%20as%20a%20string.%20%60replace_algebraics%60%20controls%20wheteher%20Parameters%20with%20algebraic%20dependence%20(i.e.%20that%20depend%20on%20ohter%20parameters%20or%20variables)%20are%20included%20as%20defined%20or%20replpaced%20by%20their%20dependence.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
629c6ef023d7eb20f414d378ae54a616