├── LICENSE.md ├── README.md ├── results ├── numExp01 │ └── main_GNLS_RK4IP.py ├── numExp02 │ ├── main_fmas_SC_basic.py │ └── pp_fig_FIG01 │ │ ├── fig01.png │ │ ├── main_figure_01.py │ │ └── res_spectrum_pyNLO_dz40micron_z14cm.dat ├── numExp03_noise_model_01 │ ├── main_fmas_SC_noise.py │ ├── pp_fig_FIG02 │ │ ├── fig02.png │ │ └── main_figure_02.py │ ├── pp_fig_FIG03 │ │ ├── fig03.png │ │ └── main_figure_03.py │ └── pp_fig_FIG04 │ │ ├── fig04.png │ │ └── main_figure_04.py ├── numExp04_noise_model_02 │ ├── main_fmas_SC_noise.py │ ├── pp_fig_FIG02 │ │ ├── fig02.png │ │ └── main_figure_02.py │ └── pp_fig_FIG03 │ │ ├── fig03.png │ │ └── main_figure_03.py ├── numExp05_noise_model_03 │ ├── main_fmas_SC_noise.py │ ├── pp_fig_FIG02 │ │ ├── fig02.png │ │ └── main_figure_02.py │ └── pp_fig_FIG03 │ │ ├── fig03.png │ │ └── main_figure_03.py └── numExp06_autocorrelation │ ├── fig00.png │ └── main_figure_autocorrelation.py └── src └── GNLStools.py /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright 2022 PhoenixD 2 | Contributor: Oliver Melchert 3 | Affiliation: Theoretical Optics and Computational Photonics Group, Institiute of Quantum Optics, Leibniz Universität Hannover 4 | 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 7 | 8 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 9 | 10 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GNLStools 2 | 3 | `GNLStools.py` is a Python module containing data structures and functions for 4 | simulation and analysis of the propagation dynamics of laserpulses in nonlinear 5 | waveguides, described by the generalized nonlinear Schrödinger equation. 6 | 7 | The provided software implements the effects of linear dispersion, pulse 8 | self-steepening, and the Raman effect. Input pulse shot noise can be included 9 | using commonly adopted quantum noise models considering both, pure spectral 10 | phase noise as well as Gaussian noise, and coherence properties of the 11 | resulting spectra can be calculated. 12 | 13 | We include examples, demonstrating the functionality of the software by 14 | reproducing results for a supercontinuum generation process in a photonic 15 | crystal fiber, documented in the scientific literature. 16 | 17 | ## Prerequisites 18 | 19 | `GNLStools` is developed under python3 (version 3.9.7) and requires the 20 | functionality of 21 | 22 | * numpy (1.21.2) 23 | * scipy (1.7.0) 24 | 25 | Further, the figure generation scripts included with the examples require the 26 | functionality of 27 | 28 | * matplotlib (3.4.3) 29 | 30 | `GNLStools` can be used as an extension module for 31 | [py-fmas](https://github.com/omelchert/py-fmas), allowing a user to take 32 | advantage of variable stepsize z-propagation algorithms. 33 | 34 | ## Availability of the software 35 | 36 | The `GNLStools` presented here are derived from our research software and meant 37 | to work as a (system-)local software tool. There is no need to install it once 38 | you got a local 39 | [clone](https://help.github.com/en/github/creating-cloning-and-archiving-repositories/cloning-a-repository) 40 | of the repository, e.g. via 41 | 42 | ``$ git clone https://github.com/omelchert/GNLStools`` 43 | 44 | 45 | 46 | ## Sample results 47 | 48 | ![alt text](https://github.com/omelchert/GNLStools/blob/main/results/numExp03_noise_model_01/pp_fig_FIG04/fig04.png) 49 | 50 | The figure above shows exemplary results for a supercontinuum generation 51 | process, obtained for input pulses of different duration. The right y-axis shows 52 | the spectrum avereaged over 200 indepenent instances of input pulse noise, and 53 | the left axis shows the standard error of the mean when taking into account a 54 | number of M independed instances of noise. 55 | 56 | ## Further informaion 57 | 58 | The `GNLStools' software package is described in 59 | 60 | > O. Melchert, A. Demircan, "GNLStools.py: A generalized nonlinear Schrödinger Python module implementing different models of input pulse quantum noise," SoftwareX 20 (2022) 101232, DOI: [10.1016/j.softx.2022.101232](https://doi.org/10.1016/j.softx.2022.101232); [arXiv.2206.07526v1](https://doi.org/10.48550/arXiv.2206.07526). 61 | 62 | The presented software has been extensively used in our research work, 63 | including the study of supercontinuum generation and higher-order soliton 64 | compression in diamond waveguides 65 | 66 | > O. Melchert et al., "Soliton compression and supercontinuum spectra in nonlinear diamond photonics," [arXiv.2211.00492v1](https://doi.org/10.48550/arXiv.2211.00492). 67 | 68 | 69 | ## License 70 | 71 | This project is licensed under the MIT License - see the 72 | [LICENSE.md](LICENSE.md) file for details. 73 | 74 | ## Acknowledgments 75 | 76 | This work received funding from the Deutsche Forschungsgemeinschaft (DFG) 77 | under Germany’s Excellence Strategy within the Cluster of Excellence PhoenixD 78 | (Photonics, Optics, and Engineering – Innovation Across Disciplines) (EXC 2122, 79 | projectID 390833453). 80 | -------------------------------------------------------------------------------- /results/numExp01/main_GNLS_RK4IP.py: -------------------------------------------------------------------------------- 1 | '''main_GNLS_RK4IP.py 2 | 3 | Solves generalized nonlinear Schrödinger equation (GNLS) using a fourth-order 4 | Runge Kutta in the interaction picture (RK4IP) method. 5 | 6 | The propagation scenario considered below is discussed on several occations in 7 | the scientific literature. For instance, in Ref. [1], it is used to demonstrate 8 | numerical simulations in terms of the gneralized nonlinear Schrödinger equation 9 | (GNLS) on supercontinuum generation for an instance of a highly nonlinear 10 | photonic crystal fiber (PCF) with an anomalous group-velocity dispersion 11 | regime. In Ref. [2] it is used to introduce a particular z-propagation 12 | algorithm referred to as the "Runge-Kutta in the interacton picture" (RK4IP) 13 | method. 14 | 15 | This script represents supplementary material for Ref. [3], demonstrating how 16 | the GNLS data structure and noise models discussed in [3] can be used with a 17 | z-propagation algorithm. For that purpose, the RK4IP algorithm is implemented 18 | below. 19 | 20 | References: 21 | [1] J. M. Dudley, G. Genty, S. Coen, 22 | Supercontinuum generation in photonic crystal fiber, 23 | Rev. Mod. Phys. 78 (2006) 1135, 24 | http://dx.doi.org/10.1103/RevModPhys.78.1135 25 | 26 | [2] J. Hult, A Fourth-Order Runge–Kutta in the Inter- action Picture 27 | Method for Simulating Supercontin- uum Generation in Optical Fibers, 28 | IEEE J. Light- wave Tech. 25 (2007) 3770, 29 | https://doi.org/10.1109/JLT.2007.909373. 30 | 31 | [3] NN 32 | 33 | Author: 34 | O Melchert, 2022-05-05 35 | ''' 36 | import sys; sys.path.append("../../src/") 37 | import numpy as np 38 | import matplotlib.pyplot as plt 39 | from GNLStools import GNLS, noise_model_01 40 | 41 | # -- SET COMPUTATIONAL GRID 42 | z, dz = np.linspace(0, 0.1e6, 10000, retstep=True) 43 | t = np.linspace(-3500, 3500, 2**13, endpoint=False) 44 | w = np.fft.fftfreq(t.size, d=t[1]-t[0])*2*np.pi 45 | # -- INSTANTIATE GENERALIZED NONLINEAR SCHRÖDINGER EQUATION 46 | gnls = GNLS( 47 | w, # (rad/fs) 48 | beta_n = [ 49 | -1.1830e-2, # (fs^2/micron) beta_2 50 | 8.1038e-2, # (fs^3/micron) beta_3 51 | -0.95205e-1, # (fs^4/micron) beta_4 52 | 2.0737e-1, # (fs^5/micron) beta_5 53 | -5.3943e-1, # (fs^6/micron) beta_6 54 | 1.3486, # (fs^7/micron) beta_7 55 | -2.5495, # (fs^8/micron) beta_8 56 | 3.0524, # (fs^9/micron) beta_9 57 | -1.7140, # (fs^10/micron) beta_10 58 | ], 59 | gamma=0.11e-6, # (1/W/micron) 60 | w0= 2.2559, # (rad/fs) 61 | fR = 0.18, # (-) 62 | tau1 = 12.2, # (fs) 63 | tau2 = 32.0 # (fs) 64 | ) 65 | # -- SPECIFY INITIAL PULSE 66 | ut = np.sqrt(1e4)/np.cosh(t/28.4) 67 | dut = noise_model_01(t, 2.2559, 1) 68 | uw = np.fft.ifft(ut + dut) 69 | 70 | # -- RK4IP PULSE PROPAGATION 71 | P = np.exp(gnls.Lw*dz/2) 72 | for n in range(1,z.size): 73 | uw_I = P*uw 74 | k1 = P*gnls.Nw(uw)*dz 75 | k2 = gnls.Nw(uw_I + k1/2)*dz 76 | k3 = gnls.Nw(uw_I + k2/2)*dz 77 | k4 = gnls.Nw(P*uw_I + k3)*dz 78 | uw = P*(uw_I + k1/6 + k2/3 + k3/3) + k4/6 79 | 80 | # -- PLOT RESULTS 81 | fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 3)) 82 | I = np.abs(np.fft.fft(uw))**2 83 | ax1.plot(t, I*1e-3) 84 | ax1.set_xlim(-200,3200); ax1.set_xlabel(r"Time $t$ (fs)") 85 | ax1.set_ylim(0,6); ax1.set_ylabel(r"Intensity $|u|^2$ (kW)") 86 | Iw = np.abs(uw)**2 87 | ax2.plot(2*np.pi*0.29979/(w+2.2559), 10*np.log10(Iw/np.max(Iw))) 88 | ax2.set_xlim(0.45,1.4); ax2.set_xlabel(r"Wavelength $\lambda$ (micron)") 89 | ax2.set_ylim(-60,0); ax2.set_ylabel(r"Spectrum $|u_\lambda|^2$ (dB)") 90 | fig.tight_layout(); plt.show() 91 | -------------------------------------------------------------------------------- /results/numExp02/main_fmas_SC_basic.py: -------------------------------------------------------------------------------- 1 | import sys; sys.path.append("/Users/omelchert/Programs/Python/py-fmas/"); sys.path.append("../../src/") 2 | import os 3 | import numpy as np 4 | from fmas.config import FTFREQ, FT, IFT, C0 5 | from fmas.grid import Grid 6 | from fmas.tools import plot_evolution 7 | from fmas.solver import CQE 8 | from GNLStools import GNLS 9 | 10 | 11 | def main(del_G): 12 | 13 | # -- INITIALIZATION STAGE ------------------------------------------------- 14 | # ... COMPUTATIONAL DOMAIN 15 | t_max = 7000. # (fs) 16 | t_num = 2**14 # (-) 17 | z_max = 0.15*1e6 # (micron) 18 | z0 = 0.10*1e6 # (micron) 19 | z_num = 700 # (-) 20 | z_skip = 1 # (-) 21 | grid = Grid( t_max = t_max, t_num = t_num) 22 | t, w = grid.t, grid.w 23 | 24 | # ... INITIAL CONDITION 25 | P0 = 1e4 # (W) 26 | t0 = 28.4 # (fs) 27 | w0 = 2.2559 # (rad/fs) 28 | u0_t = np.sqrt(P0)/np.cosh(t/t0) 29 | 30 | # ... GENERALIZED NONLINEAR SCHROEDINGER EQUATION 31 | b2 = -1.1830e-2 # (fs^2/micron) 32 | b3 = 8.1038e-2 # (fs^3/micron) 33 | b4 = -0.95205e-1 # (fs^4/micron) 34 | b5 = 2.0737e-1 # (fs^5/micron) 35 | b6 = -5.3943e-1 # (fs^6/micron) 36 | b7 = 1.3486 # (fs^7/micron) 37 | b8 = -2.5495 # (fs^8/micron) 38 | b9 = 3.0524 # (fs^9/micron) 39 | b10 = -1.7140 # (fs^10/micron) 40 | # ... NONLINEAR PARAMETER 41 | gamma = 0.11e-6 # (1/W/micron) 42 | # ... RAMAN RESPONSE 43 | fR = 0.18 # (-) 44 | tau1 = 12.2 # (fs) 45 | tau2 = 32.0 # (fs) 46 | model = GNLS(w, beta_n = [b2,b3,b4,b5,b6,b7,b8,b9,b10], gamma=gamma, w0=w0, fR=fR, tau1=tau1, tau2=tau2) 47 | 48 | # ... PROPAGATION ALGORITHM 49 | solver = CQE(model.Lw, model.Nw, user_action=model.claw_Ph, del_G=del_G) 50 | solver.set_initial_condition(w, FT(u0_t)) 51 | solver.propagate( z_range = z_max, n_steps = z_num, n_skip = z_skip) 52 | 53 | # -- STORE RESULTS -------------------------------------------------------- 54 | res = { 55 | "P0": P0, 56 | "t0": t0, 57 | "w0": w0, 58 | "del_G": del_G, 59 | "dz_integration": solver.dz_, 60 | "t": grid.t, 61 | "z": solver.z, 62 | "w": solver.w, 63 | "utz": solver.utz, 64 | 'dz_a': np.asarray(solver._dz_a), 65 | 'del_rle' : np.asarray(solver._del_rle), 66 | "Cp": solver.ua_vals 67 | } 68 | 69 | os.makedirs('./data_no_noise', exist_ok=True) 70 | np.savez_compressed('./data_no_noise/res_CQE_SC_delG%g'%(del_G), **res) 71 | 72 | # -- SHOW RESULTS --------------------------------------------------------- 73 | plot_evolution( solver.z, grid.t, solver.utz, 74 | t_lim = (-500,2200), w_lim = (-1.5,2.5), DO_T_LOG = False) 75 | 76 | 77 | if __name__=='__main__': 78 | main(1e-12) 79 | #main(1e-8) 80 | -------------------------------------------------------------------------------- /results/numExp02/pp_fig_FIG01/fig01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omelchert/GNLStools/a9694239f65f3f275fb02083425c8fef5f6b8f42/results/numExp02/pp_fig_FIG01/fig01.png -------------------------------------------------------------------------------- /results/numExp02/pp_fig_FIG01/main_figure_01.py: -------------------------------------------------------------------------------- 1 | """ 2 | Author: O. Melchert 3 | Date: 2020-09-09 4 | """ 5 | import sys 6 | import os 7 | import numpy as np 8 | import numpy.fft as nfft 9 | import matplotlib as mpl 10 | import matplotlib.pyplot as plt 11 | from matplotlib.gridspec import GridSpec, GridSpecFromSubplotSpec 12 | import h5py 13 | 14 | __author__ = 'Oliver Melchert' 15 | __date__ = '2020-09-09' 16 | 17 | 18 | # -- CONVENIENT ABBREVIATIONS 19 | FT = nfft.ifft 20 | IFT = nfft.fft 21 | 22 | def _beta_fun(): 23 | r"""Helper function definig the propagation constant 24 | 25 | Implements group-velocity dispersion with expansion coefficients 26 | listed in Tab. I of Ref. [1]. Expansion coefficients are valid for 27 | :math:`lambda = 835\,\mathrm{nm}`, i.e. for :math:`\omega_0 \approx 28 | 2.56\,\mathrm{rad/fs}`. 29 | 30 | References: 31 | [1] J. M. Dudley, G. Genty, S. Coen, 32 | Supercontinuum generation in photonic crystal fiber, 33 | Rev. Mod. Phys. 78 (2006) 1135, 34 | http://dx.doi.org/10.1103/RevModPhys.78.1135 35 | 36 | Args: 37 | w (:obj:`numpy.ndarray`): Angular frequency grid. 38 | 39 | Returns: 40 | :obj:`numpy.ndarray` Propagation constant as function of 41 | frequency detuning. 42 | """ 43 | # ... EXPANSION COEFFICIENTS DISPERSION 44 | b2 = -1.1830e-2 # (fs^2/micron) 45 | b3 = 8.1038e-2 # (fs^3/micron) 46 | b4 = -0.95205e-1 # (fs^4/micron) 47 | b5 = 2.0737e-1 # (fs^5/micron) 48 | b6 = -5.3943e-1 # (fs^6/micron) 49 | b7 = 1.3486 # (fs^7/micron) 50 | b8 = -2.5495 # (fs^8/micron) 51 | b9 = 3.0524 # (fs^9/micron) 52 | b10 = -1.7140 # (fs^10/micron) 53 | # ... PROPAGATION CONSTANT 54 | beta_w_fun = np.poly1d([b10/3628800, b9/362880, b8/40320, b7/5040, b6/720, 55 | b5/120, b4/24, b3/6, b2/2, 0.0, 0.0]) 56 | return beta_w_fun 57 | 58 | 59 | def set_legend(ax, lines, loc=0, ncol=1): 60 | """set legend 61 | 62 | Function generating a custom legend, see [1] for more options 63 | 64 | Refs: 65 | [1] https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.pyplot.legend.html 66 | 67 | Args: 68 | ax (object): figure part for which the legend is intended 69 | lines (list): list of Line2D objects 70 | """ 71 | # -- extract labels from lines 72 | labels = [x.get_label() for x in lines] 73 | # -- customize legend 74 | ax.legend(lines, # list of Line2D objects 75 | labels, # labels 76 | title = '', # title shown on top of legend 77 | loc = loc, # location of the legend 78 | ncol = ncol, # number of columns 79 | labelspacing = 0.3, # vertical space between handles in font-size units 80 | borderpad = 0.3, # distance to legend border in font-size units 81 | handletextpad = 0.3, # distance between handle and label in font-size units 82 | handlelength = 1.5, # length of handle in font-size units 83 | frameon = False # remove background patch 84 | ) 85 | 86 | 87 | def custom_colormap(): 88 | # -- CREATE CUSTOM COLORMAP 89 | from matplotlib.colors import ListedColormap 90 | cmap_base = mpl.cm.jet(np.arange(256)) 91 | blank = np.ones((12,4)) 92 | for i in range(3): 93 | blank[:,i] = np.linspace(1,cmap_base[0,i], blank.shape[0]) 94 | my_cmap = ListedColormap(np.vstack((blank, cmap_base ))) 95 | return my_cmap 96 | 97 | class Figure(): 98 | 99 | def __init__(self, aspect_ratio = 1.0, fig_format = 'png', fig_basename = 'fig_test'): 100 | self.fig_format = fig_format 101 | self.fig_basename = fig_basename 102 | self.fig = None 103 | self.set_style(aspect_ratio) 104 | 105 | def set_style(self, aspect_ratio = 1.0): 106 | 107 | fig_width = 3.4 # (inch) 108 | fig_height = aspect_ratio*fig_width 109 | 110 | params = { 111 | 'figure.figsize': (fig_width,fig_height), 112 | 'legend.fontsize': 6, 113 | 'legend.frameon': False, 114 | 'axes.labelsize': 6, 115 | 'axes.linewidth': 1., 116 | 'axes.linewidth': 0.8, 117 | 'xtick.labelsize' :6, 118 | 'ytick.labelsize': 6, 119 | 'mathtext.fontset': 'stixsans', 120 | 'mathtext.rm': 'serif', 121 | 'mathtext.bf': 'serif:bold', 122 | 'mathtext.it': 'serif:italic', 123 | 'mathtext.sf': 'sans\\-serif', 124 | 'font.size': 6, 125 | 'font.family': 'serif', 126 | 'font.serif': "Helvetica", 127 | } 128 | mpl.rcParams.update(params) 129 | 130 | 131 | def save(self): 132 | fig_format, fig_name = self.fig_format, self.fig_basename 133 | if fig_format == 'png': 134 | plt.savefig(fig_name+'.png', format='png', dpi=600) 135 | elif fig_format == 'pdf': 136 | plt.savefig(fig_name+'.pdf', format='pdf', dpi=600) 137 | elif fig_format == 'svg': 138 | plt.savefig(fig_name+'.svg', format='svg', dpi=600) 139 | else: 140 | plt.show() 141 | 142 | 143 | def set_subfig_label(self,ax, label, loc=1): 144 | pos = ax.get_position() 145 | 146 | if loc==1: 147 | self.fig.text(pos.x0, pos.y1, label ,color='white', 148 | backgroundcolor='k', bbox=dict(facecolor='k', edgecolor='none', 149 | boxstyle='square,pad=0.1'), verticalalignment='top' ) 150 | 151 | elif loc==2: 152 | self.fig.text(pos.x0, pos.y0, label ,color='white', 153 | backgroundcolor='k', bbox=dict(facecolor='k', edgecolor='none', 154 | boxstyle='square,pad=0.1'), verticalalignment='bottom' ) 155 | 156 | else: 157 | print("check label position") 158 | exit() 159 | 160 | 161 | def set_layout(self): 162 | 163 | fig = plt.figure() 164 | self.fig = fig 165 | 166 | plt.subplots_adjust(left = 0.1, bottom = 0.04, right = 0.89, top = 0.9, wspace = .5, hspace = 3.) 167 | 168 | 169 | 170 | gs00 = GridSpec(nrows = 8, ncols = 1) 171 | gsA = GridSpecFromSubplotSpec(3, 3, subplot_spec=gs00[:5,0], wspace=0.07, hspace=0.1) 172 | axA1 = fig.add_subplot(gsA[1:, 0]) 173 | axA2 = fig.add_subplot(gsA[1:, 1:]) 174 | axB1 = fig.add_subplot(gsA[0, 0]) 175 | axB2 = fig.add_subplot(gsA[0, 1:]) 176 | self.subfig_1 = [axA1, axA2, axB1, axB2] 177 | 178 | gsC = GridSpecFromSubplotSpec(5, 1, subplot_spec=gs00[5:,0], wspace=0.1, hspace=1.) 179 | axC = fig.add_subplot(gsC[0:4,0]) 180 | self.subfig_2 = axC 181 | 182 | 183 | def set_subfig_01(self): 184 | axA1, axA2, axB1, axB2 = self.subfig_1 185 | 186 | #f_name = sys.argv[1] 187 | f_name = '../data_no_noise/res_CQE_SC_delG1e-12.npz' 188 | z, t, w, w0, utz, dz_int, Cp, del_G = fetch_data(f_name) 189 | t = t*1e-3 # fs -> ps 190 | z = z*1e-4 # micron -> cm 191 | w += w0 192 | 193 | t_lim = (-0.5,3.5) 194 | t_ticks = (0,1,2,3) 195 | z_lim = (0,14) 196 | z_ticks = (0,4,8,12) 197 | w_lim = (1,4.2) 198 | w_ticks = (1,2,2.415,3,4) 199 | v_ticks = np.asarray([200, 300, 400, 500, 600]) 200 | 201 | _norm = lambda x: x/x[0].max() 202 | _truncate = lambda x: np.where(x>1.e-20,x,1.e-20) 203 | _dB = lambda x: np.where(x>1e-20,10.*np.log10(x),10*np.log10(1e-20)) 204 | 205 | def set_colorbar_lin(fig, img, ax, ax2, label='text', dw=0.): 206 | # -- EXTRACT POSITION INFORMATION FOR COLORBAR PLACEMENT 207 | refPos = ax.get_position() 208 | x0, y0, w, h = refPos.x0, refPos.y0, refPos.width, refPos.height 209 | h2 = ax2.get_position().height 210 | y2 = ax2.get_position().y0 211 | # -- SET NEW AXES AS REFERENCE FOR COLORBAR 212 | colorbar_axis = fig.add_axes([x0+dw, y2 + h2 + .03*h, w-dw, 0.04*h]) 213 | # -- SET CUSTOM COLORBAR 214 | colorbar = fig.colorbar(img, # image described by colorbar 215 | cax = colorbar_axis, # reference axex 216 | orientation = 'horizontal', # colorbar orientation 217 | extend = 'max' # ends with out-of range values 218 | ) 219 | colorbar.ax.tick_params( 220 | color = 'k', # tick color 221 | labelcolor = 'k', # label color 222 | bottom = False, # no ticks at bottom 223 | labelbottom = False, # no labels at bottom 224 | labeltop = True, # labels on top 225 | top = True, # ticks on top 226 | direction = 'out', # place ticks outside 227 | length = 2, # tick length in pts. 228 | labelsize = 5., # tick font in pts. 229 | pad = 1. # tick-to-label distance in pts. 230 | ) 231 | fig.text(x0, y2+h2+0.03*h, label, horizontalalignment='left', verticalalignment='bottom', size=6) 232 | return colorbar 233 | 234 | def set_colorbar(fig, img, ax, ax2, label='text', dw=0.): 235 | # -- EXTRACT POSITION INFORMATION FOR COLORBAR PLACEMENT 236 | refPos = ax.get_position() 237 | x0, y0, w, h = refPos.x0, refPos.y0, refPos.width, refPos.height 238 | h2 = ax2.get_position().height 239 | y2 = ax2.get_position().y0 240 | # -- SET NEW AXES AS REFERENCE FOR COLORBAR 241 | colorbar_axis = fig.add_axes([x0+dw, y2 + h2 + .03*h, w-dw, 0.04*h]) 242 | # -- SET CUSTOM COLORBAR 243 | colorbar = fig.colorbar(img, # image described by colorbar 244 | cax = colorbar_axis, # reference axex 245 | orientation = 'horizontal', # colorbar orientation 246 | extend = 'both' # ends with out-of range values 247 | ) 248 | colorbar.ax.tick_params( 249 | color = 'k', # tick color 250 | labelcolor = 'k', # label color 251 | bottom = False, # no ticks at bottom 252 | labelbottom = False, # no labels at bottom 253 | labeltop = True, # labels on top 254 | top = True, # ticks on top 255 | direction = 'out', # place ticks outside 256 | length = 2, # tick length in pts. 257 | labelsize = 5., # tick font in pts. 258 | pad = 1. # tick-to-label distance in pts. 259 | ) 260 | fig.text(x0, y2+h2+0.03*h, label, horizontalalignment='left', verticalalignment='bottom', size=6) 261 | return colorbar 262 | 263 | #my_cmap = custom_colormap() 264 | my_cmap = mpl.cm.get_cmap('jet') 265 | 266 | # -- PROPAGATION CHARACERISTICS 267 | # ... BOTTOM PLOT 268 | 269 | Itz = np.abs(utz)**2 270 | #Itz = _truncate(_norm(np.abs(utz)**2)) 271 | 272 | I0 = np.max(Itz[0]) 273 | #for i in range(z.size): 274 | # print(z[i], np.max(Itz[i])/I0) 275 | #exit() 276 | 277 | 278 | # img = axA1.pcolorfast(t, z, _dB(Itz[:-1,:-1]), 279 | # vmin=-40, vmax=0., 280 | # cmap = my_cmap 281 | # ) 282 | # cb = set_colorbar(self.fig, img, axA1, axB1, label='$|\mathcal{u}|^2\,\mathrm{(dB)}$', dw=0.1) 283 | # cb.set_ticks((-40,-20,0)) 284 | 285 | img = axA1.pcolorfast(t, z, Itz[:-1,:-1]/1e3, 286 | vmin=0, vmax=30, 287 | cmap = my_cmap 288 | ) 289 | cb = set_colorbar_lin(self.fig, img, axA1, axB1, label='$|\mathcal{u}|^2\,\mathrm{(kW)}$', dw=0.1) 290 | cb.set_ticks((0,10,20,30,40)) 291 | 292 | axA1.tick_params(axis='x', length=2., pad=2, top=False) 293 | axA1.set_xlim(t_lim) 294 | axA1.set_xticks(t_ticks) 295 | axA1.set_xlabel(r"Time $t~\mathrm{(ps)}$", labelpad=1) 296 | 297 | axA1.tick_params(axis='y', length=2., pad=2, top=False) 298 | axA1.set_ylim(z_lim) 299 | axA1.set_yticks(z_ticks) 300 | axA1.set_ylabel(r"Propagation distance $z~\mathrm{(cm)}$") 301 | 302 | 303 | # ... UPPER PLOT - real field 304 | z_id = np.argmin(np.abs(z-14)) 305 | I = np.abs(utz[z_id])**2 306 | I0 = np.abs(utz[0])**2 307 | axB1.plot(t, I/1e3, color='#1f77b4', linewidth=.75) 308 | #axB1.plot(t, I/1e3, color='k', linewidth=.75) 309 | 310 | axB1.tick_params(axis='x', length=2., pad=2, top=False, labelbottom=False) 311 | axB1.set_xlim(t_lim) 312 | axB1.set_xticks(t_ticks) 313 | 314 | axB1.tick_params(axis='y', length=2., pad=2, top=False, labelleft=True, left=True) 315 | axB1.set_ylim((0,6)) 316 | axB1.set_yticks((0,2,4,6)) 317 | axB1.set_ylabel(r"$|\mathcal{u}|^2\,\mathrm{(kW)}$") 318 | 319 | # -- FREQUENCY DOMAIN 320 | # ... BOTTOM PLOT 321 | uwz = FT(utz,axis=-1) 322 | Iwz_s = nfft.fftshift(_truncate(_norm(np.abs(uwz)**2)),axes=-1) 323 | w_s = nfft.fftshift(w) 324 | 325 | w_s_mask = np.logical_and(w_s>w_lim[0], w_s<6) #w_lim[1]) 326 | Iwz_s_f = Iwz_s[:,w_s_mask] 327 | w_s_f = w_s[w_s_mask] 328 | c0 = 0.29979 329 | _lam = lambda w: 2*np.pi*c0/w 330 | _w = lambda x: 2*np.pi*c0/x 331 | lam = _lam(w_s)*1e3 332 | 333 | l_mask = np.logical_and(lam>400,lam<1500) 334 | img = axA2.pcolorfast(lam[l_mask], z, _dB(Iwz_s[:,l_mask][:-1,:-1]), 335 | vmin=-40, vmax=0., 336 | cmap = my_cmap 337 | ) 338 | cb = set_colorbar(self.fig, img, axA2, axB2, label='$|\mathcal{u}_\Omega|^2\,\mathrm{(dB)}$', dw=0.1) 339 | cb.set_ticks((-40,-30,-20,-10,0)) 340 | 341 | w_ZDW = 2.415 342 | #axA2.axvline( 1e3*2*np.pi*c0/w_ZDW, color='k', dashes=[2,2], linewidth=1) 343 | 344 | axA2.tick_params(axis='x', length=2., pad=2, top=False) 345 | 346 | lam_lim = (450,1350) 347 | lam_ticks = (500,700,900,1100,1300) 348 | axA2.set_xlim(lam_lim) 349 | axA2.set_xticks(lam_ticks) 350 | #axA2.set_xlim(w_lim) 351 | 352 | #v2w = lambda v: v*2*np.pi/1000. 353 | #axA2.set_xticks(v2w(v_ticks)) 354 | #axA2.set_xticklabels( v_ticks ) 355 | #axA2.set_xticklabels( (1,2,r'$\omega_{\rm{Z}}$',3,4) ) 356 | #axA2.set_xlabel(r"Angular frequency $\omega~\mathrm{(rad/fs)}$") 357 | #axA2.set_xlabel(r"Frequency $\nu = (\Omega+\omega_0)/2 \pi~\mathrm{(THz)}$",labelpad=1) 358 | axA2.set_xlabel(r"Wavelength $\lambda = 2 \pi c/(\omega_0+\Omega)~\mathrm{(nm)}$",labelpad=1) 359 | #axA2.set_xlabel(r"Wavelength $\lambda~\mathrm{(nm)}$",labelpad=1) 360 | 361 | axA2.tick_params(axis='y', length=2., pad=2, top=False, labelleft=False) 362 | axA2.set_ylim(z_lim) 363 | axA2.set_yticks(z_ticks) 364 | 365 | #axA1.axhline(0.56, color='magenta', dashes=[2,2], lw=1) 366 | #axA2.axhline(0.56, color='magenta', dashes=[2,2], lw=1) 367 | #axA1.axhline(0.73, color='cyan', dashes=[2,2], lw=1) 368 | #axA2.axhline(0.73, color='cyan', dashes=[2,2], lw=1) 369 | 370 | # -- INSET AXES ---- 371 | axA3 = axA1.inset_axes([0.45,0.025, 0.5,0.5]) 372 | 373 | axA3.pcolorfast(t, z, _norm(Itz[:-1,:-1]), 374 | vmin=0, vmax=3., 375 | cmap = my_cmap 376 | ) 377 | 378 | 379 | x_min, x_max = -0.065, 0.12 380 | y_min, y_max = 0.2, 1.8 381 | axA3.tick_params(axis='x', length=2., pad=1, top=False, bottom=False, labelbottom=False) 382 | axA3.set_xlim(x_min, x_max) 383 | 384 | axA3.tick_params(axis='y', length=2., pad=1, top=False, left=False, labelleft=False) 385 | axA3.set_ylim(y_min, y_max) 386 | 387 | my_col = 'white' 388 | box_x = [x_min, x_min, x_max, x_max, x_min] 389 | box_y = [y_min, y_max, y_max, y_min, y_min] 390 | axA1.plot(box_x, box_y, color=my_col, lw=0.75) 391 | 392 | axA3.spines['top'].set_color(my_col) 393 | axA3.spines['bottom'].set_color(my_col) 394 | axA3.spines['left'].set_color(my_col) 395 | axA3.spines['right'].set_color(my_col) 396 | 397 | f_name = 'res_spectrum_pyNLO_dz40micron_z14cm.dat' 398 | dat = np.loadtxt(f_name) 399 | lam_2 = dat[:,0] 400 | Iw_2 = dat[:,1] 401 | w_2 = 2*np.pi*0.29970/lam_2 402 | l2 = axB2.plot(lam_2, _dB(Iw_2/np.max(Iw_2)), color='lightgray', linewidth=1.5, label=r'B') 403 | 404 | #f_name = 'res_gnlse_Trevors_z14m.dat' 405 | #dat = np.loadtxt(f_name) 406 | #w_3 = dat[:,0] 407 | #Iw_3 = dat[:,1] 408 | #l3 = axB2.plot(w_3/1000, _dB(Iw_3/np.max(Iw_3)), color='lightgray', linewidth=1.5, label=r'B') 409 | 410 | z_id = np.argmin(np.abs(z-14)) 411 | Iw = Iwz_s[z_id] 412 | #l1 = axB2.plot(lam[l_mask] , _dB(Iw[l_mask]/np.max(Iw)), color='k', linewidth=0.75, dashes=[2,2], label=r'A') 413 | l1 = axB2.plot(lam[l_mask] , _dB(Iw[l_mask]/np.max(Iw)), color='#1f77b4', linewidth=0.75, dashes=[2,2], label=r'A') 414 | 415 | set_legend(axB2, l1+l2, loc=(0.4,0.0), ncol=1) 416 | 417 | w_ZDW = 2.415 418 | #axB2.axvline( 1e3*2*np.pi*c0/w_ZDW, color='k', dashes=[2,2], linewidth=1) 419 | 420 | axB2.tick_params(axis='x', length=2., pad=2, top=False, labelbottom=False) 421 | axB2.set_xlim(lam_lim) 422 | #axB2.set_xlim(w_lim) 423 | #axB2.set_xticks(w_ticks) 424 | axB2.set_xticks(lam_ticks) 425 | #axB2.set_xticks(v2w(v_ticks)) 426 | #axA2.set_xticklabels( v_ticks ) 427 | 428 | axB2.tick_params(axis='y', length=2., pad=2, top=False, labelleft=False, left=False, right=True, labelright=True) 429 | axB2.set_ylim((-90,5)) 430 | axB2.set_yticks((-80,-40,0)) 431 | axB2.set_ylabel('$|\mathcal{u}_\Omega|^2~\mathrm{(dB)}$') 432 | axB2.yaxis.set_label_position('right') 433 | 434 | self.set_subfig_label(axA1,'(c)',loc=1) 435 | self.set_subfig_label(axA2,'(d)',loc=1) 436 | self.set_subfig_label(axB1,'(a)',loc=1) 437 | self.set_subfig_label(axB2,'(b)',loc=1) 438 | 439 | 440 | # -- PHOTON NUMBER CONSERVATION --------------------------------------- 441 | ax = self.subfig_2 442 | 443 | l1 = ax.plot(z,(1-Cp/Cp[0])*1e8,lw=.75,color='#1f77b4',label=r"$C_{\rm{Ph}}$") 444 | 445 | ax.tick_params(axis='x', length=2., pad=2, top=False) 446 | ax.set_xlim(0,12) 447 | ax.set_xlabel(r"Propagation distance $z~\mathrm{(cm)}$") 448 | 449 | ax.tick_params(axis='y', length=2., pad=2, top=False) 450 | ax.set_ylim(-1,1) 451 | ax.set_ylabel(r"$1-C_{\rm{Ph}}(z)/C_{\rm{Ph}}(0)~\mathrm{(\times 10^{-8})}$") 452 | 453 | 454 | #ax.add_patch(plt.Rectangle(xy=(0.4,-0.15), width=0.75,height=0.2, fill=False, edgecolor='k', lw=1 )) 455 | 456 | #ax.add_patch(plt.Rectangle(xy=(7.,-0.53), width=0.75,height=0.2, fill=False, edgecolor='k', lw=1 )) 457 | 458 | #pos = ax.get_position() 459 | #self.fig.text(pos.x0+0.027, pos.y0+0.13, r"A" ,color='k', horizontalalignment='left', verticalalignment='top' ) 460 | 461 | 462 | ax2 = ax.twinx() 463 | 464 | E = np.sum(np.abs(uwz)**2,axis=-1) 465 | l2 = ax2.plot(z,1-E/E[0], lw=0.75, dashes = [2,2],color='#1f77b4',label=r"$E$") 466 | 467 | ax2.tick_params(axis='y', length=2., pad=2, top=False) 468 | ax2.set_ylim(0,0.09) 469 | ax2.set_yticks((0,0.02,0.04,0.06,0.08)) 470 | ax2.set_ylabel(r"$1-E(z)/E(0)$") 471 | 472 | set_legend(ax, l1+l2, loc=4, ncol=1) 473 | 474 | self.set_subfig_label(ax,'(e)',loc=1) 475 | 476 | axA1.yaxis.set_label_coords(-0.25,0.5) 477 | axB1.yaxis.set_label_coords(-0.25,0.5) 478 | ax.yaxis.set_label_coords(-0.09,0.5) 479 | 480 | 481 | 482 | def fetch_data(file_path): 483 | dat = np.load(file_path) 484 | utz = dat['utz'] 485 | t = dat['t'] 486 | w = dat['w'] 487 | w0 = dat['w0'] 488 | z = dat['z'] 489 | dz_int = dat['dz_integration'] 490 | dz_a = dat['dz_a'] 491 | Cp = dat['Cp'] 492 | del_G = dat['del_G'] 493 | return z,t,w,w0,utz, dz_a, Cp, del_G 494 | 495 | 496 | def main(): 497 | 498 | myFig = Figure(aspect_ratio=1.1, fig_basename='fig01', fig_format='png') 499 | myFig.set_layout() 500 | myFig.set_subfig_01() 501 | myFig.save() 502 | 503 | if __name__ == '__main__': 504 | main() 505 | -------------------------------------------------------------------------------- /results/numExp03_noise_model_01/main_fmas_SC_noise.py: -------------------------------------------------------------------------------- 1 | import sys; sys.path.append("/Users/omelchert/Programs/Python/py-fmas/"); sys.path.append("../../src/") 2 | import os 3 | import numpy as np 4 | from fmas.config import FTFREQ, FT, IFT, C0 5 | from fmas.grid import Grid 6 | from fmas.tools import plot_claw, plot_evolution 7 | from fmas.solver import CQE 8 | from GNLStools import GNLS, noise_model_01, noise_model_02, noise_model_03 9 | 10 | 11 | def main(del_G, t0_FWHM=50., s0=0): 12 | 13 | # -- INITIALIZATION STAGE ------------------------------------------------- 14 | # ... COMPUTATIONAL DOMAIN 15 | t_max = 3500. # (fs) 16 | t_num = 2**14 # (-) 17 | z_max = 0.12*1e6 # (micron) 18 | z0 = 0.10*1e6 # (micron) 19 | z_num = 200 # (-) 20 | z_skip = 1 # (-) 21 | grid = Grid( t_max = t_max, t_num = t_num) 22 | t, w = grid.t, grid.w 23 | 24 | # ... INITIAL CONDITION 25 | P0 = 1e4 # (W) 26 | t0 = 28.4 # (fs) 27 | t0 = t0_FWHM/1.763 # (fs) 28 | w0 = 2.2559 # (rad/fs) 29 | u0_t = np.sqrt(P0)/np.cosh(t/t0) 30 | 31 | # ... GENERALIZED NONLINEAR SCHROEDINGER EQUATION 32 | b2 = -1.1830e-2 # (fs^2/micron) 33 | b3 = 8.1038e-2 # (fs^3/micron) 34 | b4 = -0.95205e-1 # (fs^4/micron) 35 | b5 = 2.0737e-1 # (fs^5/micron) 36 | b6 = -5.3943e-1 # (fs^6/micron) 37 | b7 = 1.3486 # (fs^7/micron) 38 | b8 = -2.5495 # (fs^8/micron) 39 | b9 = 3.0524 # (fs^9/micron) 40 | b10 = -1.7140 # (fs^10/micron) 41 | # ... NONLINEAR PARAMETER 42 | gamma = 0.11e-6 # (1/W/micron) 43 | # ... RAMAN RESPONSE 44 | fR = 0.18 # (-) 45 | tau1 = 12.2 # (fs) 46 | tau2 = 32.0 # (fs) 47 | model = GNLS(w, beta_n = [b2,b3,b4,b5,b6,b7,b8,b9,b10], gamma=gamma, w0=w0, fR=fR, tau1=tau1, tau2=tau2) 48 | 49 | du0_t = noise_model_01(t,w0,s0) 50 | 51 | # ... PROPAGATION ALGORITHM 52 | solver = CQE(model.Lw, model.Nw, user_action=model.claw_Ph, del_G=del_G) 53 | solver.set_initial_condition(w, FT(u0_t + du0_t)) 54 | solver.propagate( z_range = z_max, n_steps = z_num, n_skip = z_skip) 55 | 56 | # -- STORE RESULTS -------------------------------------------------------- 57 | z_id = np.argmin(np.abs(solver.z-z0)) 58 | results = { 59 | "s0": s0, 60 | "du": du0_t, 61 | "u0": u0_t, 62 | "P0": P0, 63 | "t0": t0, 64 | "w0": w0, 65 | "t": grid.t, 66 | "z": solver.z[z_id], 67 | "w": solver.w, 68 | "utz": solver.utz[z_id], 69 | } 70 | 71 | return results 72 | 73 | 74 | 75 | def wrapper(t0_FWHM=50): 76 | delG = 1e-8 77 | os.makedirs('./data_delG%g_t0FWHM%lf'%(delG,t0_FWHM), exist_ok=True) 78 | 79 | for s0 in range(30): 80 | res = main(delG, t0_FWHM, s0) 81 | np.savez_compressed('./data_delG%g_t0FWHM%lf/res_CQE_SC_delG%g_t0FWHM%lf_s0%d'%(delG, t0_FWHM, delG, t0_FWHM, s0), **res) 82 | 83 | 84 | if __name__=='__main__': 85 | wrapper(50.) 86 | wrapper(100.) 87 | wrapper(150.) 88 | -------------------------------------------------------------------------------- /results/numExp03_noise_model_01/pp_fig_FIG02/fig02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omelchert/GNLStools/a9694239f65f3f275fb02083425c8fef5f6b8f42/results/numExp03_noise_model_01/pp_fig_FIG02/fig02.png -------------------------------------------------------------------------------- /results/numExp03_noise_model_01/pp_fig_FIG02/main_figure_02.py: -------------------------------------------------------------------------------- 1 | """ 2 | Author: O. Melchert 3 | Date: 2020-09-09 4 | """ 5 | import sys 6 | import os 7 | import itertools 8 | import numpy as np 9 | import numpy.fft as nfft 10 | import matplotlib as mpl 11 | import matplotlib.pyplot as plt 12 | from matplotlib.gridspec import GridSpec, GridSpecFromSubplotSpec 13 | 14 | 15 | 16 | # -- CONVENIENT ABBREVIATIONS 17 | FT = nfft.ifft 18 | IFT = nfft.fft 19 | SHIFT = nfft.fftshift 20 | 21 | 22 | def fetch_data(f_list): 23 | """ fetch data from npz-files 24 | 25 | Args: 26 | z0 (float): selected propagation distance 27 | 28 | Returns: (w, Ewz_list) 29 | w (1D array, floats): cropped angular frequency axis 30 | Ewz_list (2D array, floats): cropped frequency doman arrays 31 | """ 32 | 33 | def _helper(iPath): 34 | data = np.load(iPath) 35 | return data['z'], data['t'], data['w'], FT(data['utz']) 36 | 37 | Ewz_list = [] 38 | for fName in f_list: 39 | 40 | # -- FETCH RAW DATA 41 | (z, t, w, Ewz) = _helper(fName) 42 | z = z*1e-6 # rescale to m 43 | w = SHIFT(w) 44 | 45 | Ewz = SHIFT(Ewz,axes=-1) 46 | #Eps_w = SHIFT(Eps_w,axes=-1) 47 | 48 | # -- GET FIELD CORRESPONDING TO SELECTED PROP. DIST. 49 | #Ewz = Eps_w[getClosestPosition(z,z0)] 50 | 51 | # -- KEEP CROPPED FIELD 52 | #wMask = np.logical_and(w>-3.,w<3.) 53 | #Ewz_list += [Ewz[wMask]] 54 | Ewz_list += [Ewz] 55 | 56 | return z, w, np.asarray(Ewz_list) 57 | 58 | 59 | def set_legend(ax, lines, loc=0, ncol=1): 60 | """set legend 61 | 62 | Function generating a custom legend, see [1] for more options 63 | 64 | Refs: 65 | [1] https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.pyplot.legend.html 66 | 67 | Args: 68 | ax (object): figure part for which the legend is intended 69 | lines (list): list of Line2D objects 70 | """ 71 | # -- extract labels from lines 72 | labels = [x.get_label() for x in lines] 73 | # -- customize legend 74 | ax.legend(lines, # list of Line2D objects 75 | labels, # labels 76 | title = '', # title shown on top of legend 77 | loc = loc, # location of the legend 78 | ncol = ncol, # number of columns 79 | labelspacing = 0.3, # vertical space between handles in font-size units 80 | borderpad = 0.3, # distance to legend border in font-size units 81 | handletextpad = 0.3, # distance between handle and label in font-size units 82 | handlelength = 1.5, # length of handle in font-size units 83 | frameon = False # remove background patch 84 | ) 85 | 86 | 87 | def custom_colormap(): 88 | # -- CREATE CUSTOM COLORMAP 89 | from matplotlib.colors import ListedColormap 90 | cmap_base = mpl.cm.jet(np.arange(256)) 91 | blank = np.ones((12,4)) 92 | for i in range(3): 93 | blank[:,i] = np.linspace(1,cmap_base[0,i], blank.shape[0]) 94 | my_cmap = ListedColormap(np.vstack((blank, cmap_base ))) 95 | return my_cmap 96 | 97 | class Figure(): 98 | 99 | def __init__(self, aspect_ratio = 1.0, fig_format = 'png', fig_basename = 'fig_test'): 100 | self.fig_format = fig_format 101 | self.fig_basename = fig_basename 102 | self.fig = None 103 | self.set_style(aspect_ratio) 104 | 105 | def set_style(self, aspect_ratio = 1.0): 106 | 107 | fig_width = 3.2 # (inch) 108 | fig_height = aspect_ratio*fig_width 109 | 110 | params = { 111 | 'figure.figsize': (fig_width,fig_height), 112 | 'legend.fontsize': 6, 113 | 'legend.frameon': False, 114 | 'axes.labelsize': 6, 115 | 'axes.linewidth': 0.8, 116 | 'xtick.labelsize' :6, 117 | 'ytick.labelsize': 6, 118 | 'mathtext.fontset': 'stixsans', 119 | 'mathtext.rm': 'serif', 120 | 'mathtext.bf': 'serif:bold', 121 | 'mathtext.it': 'serif:italic', 122 | 'mathtext.sf': 'sans\\-serif', 123 | 'font.size': 6, 124 | 'font.family': 'serif', 125 | 'font.serif': "Helvetica", 126 | } 127 | mpl.rcParams.update(params) 128 | 129 | 130 | def save(self): 131 | fig_format, fig_name = self.fig_format, self.fig_basename 132 | if fig_format == 'png': 133 | plt.savefig(fig_name+'.png', format='png', dpi=600) 134 | elif fig_format == 'pdf': 135 | plt.savefig(fig_name+'.pdf', format='pdf', dpi=600) 136 | elif fig_format == 'svg': 137 | plt.savefig(fig_name+'.svg', format='svg', dpi=600) 138 | else: 139 | plt.show() 140 | 141 | 142 | def set_subfig_label(self,ax, label1): 143 | pos = ax.get_position() 144 | 145 | self.fig.text(pos.x0, pos.y1+0.01, label1 ,color='white', 146 | backgroundcolor='k', bbox=dict(facecolor='k', edgecolor='none', 147 | boxstyle='square,pad=0.1'), verticalalignment='bottom' ) 148 | 149 | #self.fig.text(pos.x0+0.04, pos.y1+0.01, label2 ,color='k', 150 | # verticalalignment='bottom' ) 151 | 152 | 153 | def set_layout(self): 154 | 155 | fig = plt.figure() 156 | self.fig = fig 157 | 158 | plt.subplots_adjust(left = 0.08, bottom = 0.1, right = 0.89, top = 0.95, wspace = .05, hspace = 0.9) 159 | 160 | gs00 = GridSpec(nrows = 1, ncols = 2) 161 | 162 | gsA = GridSpecFromSubplotSpec(5, 1, subplot_spec=gs00[0,0], wspace=0.07, hspace=0.1) 163 | axA1 = fig.add_subplot(gsA[0, 0]) 164 | axA2 = fig.add_subplot(gsA[1, 0]) 165 | axA3 = fig.add_subplot(gsA[2, 0]) 166 | axA4 = fig.add_subplot(gsA[3, 0]) 167 | axA5 = fig.add_subplot(gsA[4, 0]) 168 | self.subfig_1 = [axA1, axA2, axA3, axA4, axA5] 169 | 170 | gsA = GridSpecFromSubplotSpec(5, 1, subplot_spec=gs00[0,1], wspace=0.07, hspace=0.1) 171 | axA1 = fig.add_subplot(gsA[0, 0]) 172 | axA2 = fig.add_subplot(gsA[1, 0]) 173 | axA3 = fig.add_subplot(gsA[2, 0]) 174 | axA4 = fig.add_subplot(gsA[3, 0]) 175 | axA5 = fig.add_subplot(gsA[4, 0]) 176 | self.subfig_2 = [axA1, axA2, axA3, axA4, axA5] 177 | 178 | 179 | 180 | def set_figs(self, f_list): 181 | sf1 = self.subfig_1 182 | 183 | t_lim = (-0.2,3.2) 184 | t_ticks = (0,1,2,3) 185 | y_lim = (0,10.) 186 | y_ticks = (0,4,8) 187 | 188 | idx_list = np.arange(len(f_list)) 189 | idx_list = np.random.permutation(idx_list) 190 | print(idx_list) 191 | idx_list = [ 9 , 1, 10, 3, 12, 16 , 2 , 6, 7, 11, 5, 13, 19, 14, 18, 15, 8, 17, 0 , 4] 192 | 193 | 194 | for idx, ax in enumerate(sf1): 195 | 196 | dat = np.load(f_list[idx_list[idx]]) 197 | z = dat['z']*1e-6 # (m) 198 | t = dat['t']*1e-3 # (ps) 199 | w = dat['w'] # (rad/fs) 200 | w0 = dat['w0'] # (rad/fs) 201 | P0 = dat['P0'] # (W) 202 | utz = dat['utz'] # (W) 203 | 204 | I = np.abs(utz)**2/1000 205 | 206 | ax.plot(t,I,lw=0.75) 207 | 208 | ax.set_xlim(t_lim) 209 | ax.set_xticks(t_ticks) 210 | ax.set_ylim(y_lim) 211 | ax.set_yticks(y_ticks) 212 | 213 | if idx==2: 214 | ax.set_ylabel(r"Intensity $I(t)~\mathrm{(kW)}$", y=0) 215 | ax.tick_params(axis='y', length=2., pad=2, top=False) 216 | 217 | 218 | if idx==len(sf1)-1: 219 | ax.spines.right.set_color('none') 220 | ax.spines.top.set_color('none') 221 | ax.tick_params(axis='x', length=2., pad=2, top=False) 222 | ax.set_xlabel(r"Time $t~\mathrm{(ps)}$", labelpad=1) 223 | else: 224 | ax.spines.right.set_color('none') 225 | ax.spines.top.set_color('none') 226 | #ax.spines.bottom.set_color('none') 227 | ax.tick_params(axis='x', length=2., pad=2, top=False, bottom=True) 228 | #ax.tick_params(axis='x', length=2., pad=2, top=False, labelbottom=False, bottom=False) 229 | 230 | 231 | sf2 = self.subfig_2 232 | 233 | lam_lim = (400,1500) 234 | lam_ticks = (500,800,1100,1400) 235 | Iw_lim = (0,1.04) 236 | Iw_ticks = (0,0.2,0.4,0.6,0.8,1.0) 237 | 238 | for idx, ax in enumerate(sf2): 239 | 240 | dat = np.load(f_list[idx_list[idx]]) 241 | z = dat['z']*1e-6 # (m) 242 | t = dat['t']*1e-3 # (ps) 243 | w = dat['w'] # (rad/fs) 244 | w0 = dat['w0'] # (rad/fs) 245 | P0 = dat['P0'] # (W) 246 | utz = dat['utz'] # (W) 247 | 248 | w = SHIFT(w) 249 | 250 | c0 = 0.29979 251 | lam = 1e3*2*np.pi*c0/(w0+w) # (nm) 252 | lam_mask = np.logical_and(lam>lam_lim[0],lam1e-20,10.*np.log10(x),10*np.log10(1e-20)) 254 | 255 | Iw = SHIFT(np.abs(FT(utz))**2) 256 | Iw /= Iw.max() 257 | 258 | ax.plot(lam[lam_mask], _dB(Iw[lam_mask]), lw=0.75) 259 | 260 | ax.set_ylim(-85,5) 261 | ax.set_yticks((-70,-40,-10)) 262 | #ax.set_ylabel(r"Intensity $I_\Omega~\mathrm{(dB)}$") 263 | 264 | #axB2.tick_params(axis='y', length=2., pad=2, top=False) 265 | #ax.set_ylim(y_lim) 266 | #ax.set_yticks(y_ticks) 267 | #axB2.set_ylabel(r"Coherence $|g_{12}^{(1)}|$") 268 | 269 | #ax.tick_params(axis='x', length=2., pad=2, top=False) 270 | ax.set_xlim(lam_lim) 271 | ax.set_xticks(lam_ticks) 272 | 273 | if idx==2: 274 | ax.set_ylabel(r"Spectrum $I_\Omega~\mathrm{(dB)}$",y=0) 275 | ax.yaxis.set_label_position('right') 276 | ax.tick_params(axis='y', length=2., pad=2, left=False, right=True, labelleft=False, labelright=True) 277 | 278 | if idx==len(sf1)-1: 279 | ax.spines.left.set_color('none') 280 | ax.spines.top.set_color('none') 281 | ax.tick_params(axis='x', length=2., pad=2, top=False) 282 | ax.set_xlabel(r"Wavelength $\lambda~\mathrm{(nm)}$", labelpad=1) 283 | else: 284 | ax.spines.left.set_color('none') 285 | ax.spines.top.set_color('none') 286 | #ax.spines.bottom.set_color('none') 287 | ax.tick_params(axis='x', length=2., pad=2, top=False, bottom=True) 288 | #ax.tick_params(axis='x', length=2., pad=2, top=False, labelbottom=False, bottom=False) 289 | 290 | self.set_subfig_label(sf1[0],"(a)") 291 | self.set_subfig_label(sf2[0],"(b)") 292 | 293 | 294 | 295 | 296 | def main(): 297 | #path = sys.argv[1] 298 | path = '../data_delG1e-08_t0FWHM150.000000/' 299 | f_list = [path+f for f in os.listdir(path)[:]] 300 | 301 | myFig = Figure(aspect_ratio=0.85, fig_basename="fig02", fig_format='png') 302 | myFig.set_layout() 303 | 304 | myFig.set_figs(f_list) 305 | 306 | myFig.save() 307 | 308 | if __name__ == '__main__': 309 | main() 310 | -------------------------------------------------------------------------------- /results/numExp03_noise_model_01/pp_fig_FIG03/fig03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omelchert/GNLStools/a9694239f65f3f275fb02083425c8fef5f6b8f42/results/numExp03_noise_model_01/pp_fig_FIG03/fig03.png -------------------------------------------------------------------------------- /results/numExp03_noise_model_01/pp_fig_FIG03/main_figure_03.py: -------------------------------------------------------------------------------- 1 | """ 2 | Author: O. Melchert 3 | Date: 2020-09-09 4 | """ 5 | import sys 6 | import os 7 | import itertools 8 | import numpy as np 9 | import numpy.fft as nfft 10 | import matplotlib as mpl 11 | import matplotlib.pyplot as plt 12 | from matplotlib.gridspec import GridSpec, GridSpecFromSubplotSpec 13 | 14 | # -- CONVENIENT ABBREVIATIONS 15 | FT = nfft.ifft 16 | IFT = nfft.fft 17 | SHIFT = nfft.fftshift 18 | 19 | 20 | def fetch_data(f_list): 21 | """ fetch data from npz-files 22 | 23 | Args: 24 | z0 (float): selected propagation distance 25 | 26 | Returns: (w, Ewz_list) 27 | w (1D array, floats): cropped angular frequency axis 28 | Ewz_list (2D array, floats): cropped frequency doman arrays 29 | """ 30 | 31 | def _helper(iPath): 32 | data = np.load(iPath) 33 | return data['z'], data['t'], data['w'], FT(data['utz']) 34 | 35 | Ewz_list = [] 36 | for fName in f_list: 37 | 38 | # -- FETCH RAW DATA 39 | (z, t, w, Ewz) = _helper(fName) 40 | z = z*1e-6 # rescale to m 41 | w = SHIFT(w) 42 | 43 | Ewz = SHIFT(Ewz,axes=-1) 44 | Ewz_list += [Ewz] 45 | 46 | return z, w, np.asarray(Ewz_list) 47 | 48 | 49 | def set_legend(ax, lines, loc=0, ncol=1): 50 | """set legend 51 | 52 | Function generating a custom legend, see [1] for more options 53 | 54 | Refs: 55 | [1] https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.pyplot.legend.html 56 | 57 | Args: 58 | ax (object): figure part for which the legend is intended 59 | lines (list): list of Line2D objects 60 | """ 61 | # -- extract labels from lines 62 | labels = [x.get_label() for x in lines] 63 | # -- customize legend 64 | ax.legend(lines, # list of Line2D objects 65 | labels, # labels 66 | title = '', # title shown on top of legend 67 | loc = loc, # location of the legend 68 | ncol = ncol, # number of columns 69 | labelspacing = 0.3, # vertical space between handles in font-size units 70 | borderpad = 0.3, # distance to legend border in font-size units 71 | handletextpad = 0.3, # distance between handle and label in font-size units 72 | handlelength = 1.5, # length of handle in font-size units 73 | frameon = False # remove background patch 74 | ) 75 | 76 | 77 | def custom_colormap(): 78 | # -- CREATE CUSTOM COLORMAP 79 | from matplotlib.colors import ListedColormap 80 | cmap_base = mpl.cm.jet(np.arange(256)) 81 | blank = np.ones((12,4)) 82 | for i in range(3): 83 | blank[:,i] = np.linspace(1,cmap_base[0,i], blank.shape[0]) 84 | my_cmap = ListedColormap(np.vstack((blank, cmap_base ))) 85 | return my_cmap 86 | 87 | 88 | class Figure(): 89 | 90 | def __init__(self, aspect_ratio = 1.0, fig_format = 'png', fig_basename = 'fig_test'): 91 | self.fig_format = fig_format 92 | self.fig_basename = fig_basename 93 | self.fig = None 94 | self.set_style(aspect_ratio) 95 | 96 | def set_style(self, aspect_ratio = 1.0): 97 | 98 | fig_width = 3.2 # (inch) 99 | fig_height = aspect_ratio*fig_width 100 | 101 | params = { 102 | 'figure.figsize': (fig_width,fig_height), 103 | 'legend.fontsize': 6, 104 | 'legend.frameon': False, 105 | 'axes.labelsize': 6, 106 | 'axes.linewidth': 0.8, 107 | 'xtick.labelsize' :6, 108 | 'ytick.labelsize': 6, 109 | 'mathtext.fontset': 'stixsans', 110 | 'mathtext.rm': 'serif', 111 | 'mathtext.bf': 'serif:bold', 112 | 'mathtext.it': 'serif:italic', 113 | 'mathtext.sf': 'sans\\-serif', 114 | 'font.size': 6, 115 | 'font.family': 'serif', 116 | 'font.serif': "Helvetica", 117 | } 118 | mpl.rcParams.update(params) 119 | 120 | 121 | def save(self): 122 | fig_format, fig_name = self.fig_format, self.fig_basename 123 | if fig_format == 'png': 124 | plt.savefig(fig_name+'.png', format='png', dpi=600) 125 | elif fig_format == 'pdf': 126 | plt.savefig(fig_name+'.pdf', format='pdf', dpi=600) 127 | elif fig_format == 'svg': 128 | plt.savefig(fig_name+'.svg', format='svg', dpi=600) 129 | else: 130 | plt.show() 131 | 132 | 133 | def set_subfig_label(self,ax, label1, label2): 134 | pos = ax.get_position() 135 | 136 | self.fig.text(pos.x0, pos.y1+0.01, label1 ,color='white', 137 | backgroundcolor='k', bbox=dict(facecolor='k', edgecolor='none', 138 | boxstyle='square,pad=0.1'), verticalalignment='bottom' ) 139 | 140 | self.fig.text(pos.x0+0.04, pos.y1+0.01, label2 ,color='k', 141 | verticalalignment='bottom' ) 142 | 143 | 144 | def set_layout(self): 145 | 146 | fig = plt.figure() 147 | self.fig = fig 148 | 149 | plt.subplots_adjust(left = 0.11, bottom = 0.08, right = 0.98, top = 0.95, wspace = .075, hspace = 1.2) 150 | 151 | gs00 = GridSpec(nrows = 7, ncols = 3) 152 | 153 | gsA = GridSpecFromSubplotSpec(1, 1, subplot_spec=gs00[0:2,0], wspace=0.07, hspace=0.1) 154 | axA1 = fig.add_subplot(gsA[0, 0]) 155 | gsB = GridSpecFromSubplotSpec(3, 1, subplot_spec=gs00[2:,0], wspace=0.07, hspace=0.075) 156 | axB1 = fig.add_subplot(gsB[0, 0]) 157 | axB2 = fig.add_subplot(gsB[1, 0]) 158 | axB3 = fig.add_subplot(gsB[2, 0]) 159 | self.subfig_1 = [axA1, axB1, axB2, axB3] 160 | 161 | gsA = GridSpecFromSubplotSpec(1, 1, subplot_spec=gs00[0:2,1], wspace=0.07, hspace=0.1) 162 | axA1 = fig.add_subplot(gsA[0, 0]) 163 | gsB = GridSpecFromSubplotSpec(3, 1, subplot_spec=gs00[2:,1], wspace=0.07, hspace=0.075) 164 | axB1 = fig.add_subplot(gsB[0, 0]) 165 | axB2 = fig.add_subplot(gsB[1, 0]) 166 | axB3 = fig.add_subplot(gsB[2, 0]) 167 | self.subfig_2 = [axA1, axB1, axB2, axB3] 168 | 169 | gsA = GridSpecFromSubplotSpec(1, 1, subplot_spec=gs00[0:2,2], wspace=0.07, hspace=0.1) 170 | axA1 = fig.add_subplot(gsA[0, 0]) 171 | gsB = GridSpecFromSubplotSpec(3, 1, subplot_spec=gs00[2:,2], wspace=0.07, hspace=0.075) 172 | axB1 = fig.add_subplot(gsB[0, 0]) 173 | axB2 = fig.add_subplot(gsB[1, 0]) 174 | axB3 = fig.add_subplot(gsB[2, 0]) 175 | self.subfig_3 = [axA1, axB1, axB2, axB3] 176 | 177 | 178 | def set_subfig_01(self, subfig, f_name, z0): 179 | axA1 = subfig[0] 180 | 181 | t_lim = (-0.2,3.2) 182 | t_ticks = (0,1,2,3) 183 | y_lim = (0,10.) 184 | y_ticks = (0,2,4,6,8,10) 185 | #y_lim = (0,1.) 186 | #y_ticks = (0,0.2,0.4,0.6,0.8,1.0) 187 | 188 | dat = np.load(f_name) 189 | z = dat['z']*1e-6 # (m) 190 | t = dat['t']*1e-3 # (ps) 191 | P0 = dat['P0'] # (W) 192 | utz = dat['utz'] # (W) 193 | 194 | #z_id = np.argmin(np.abs(z-z0)) 195 | #I = np.abs(utz[z_id])**2 196 | I = np.abs(utz)**2/1000 197 | 198 | axA1.plot(t,I,lw=0.75) 199 | #axA1.plot(t,I/P0,lw=0.75) 200 | 201 | axA1.tick_params(axis='x', length=2., pad=2, top=False) 202 | axA1.set_xlim(t_lim) 203 | axA1.set_xticks(t_ticks) 204 | axA1.set_xlabel(r"Time $t~\mathrm{(ps)}$", labelpad=1) 205 | 206 | #axA1.tick_params(axis='y', length=2., pad=2, top=False) 207 | axA1.set_ylim(y_lim) 208 | axA1.set_yticks(y_ticks) 209 | #axA1.set_ylabel(r"Intensity $I(t)/P_0$") 210 | 211 | 212 | def set_subfig_02(self, subfig, f_list, z0): 213 | _, axB1, axB2, axB3 = subfig 214 | 215 | def firstOrderCoherence(w, Ewz_list): 216 | 217 | Iw_av = np.mean(np.abs(Ewz_list)**2, axis=0) 218 | 219 | nPairs = 0 220 | XX = np.zeros(len(Ewz_list[0]),dtype=complex) 221 | for i,j in list(itertools.combinations(range(len(Ewz_list)),2)): 222 | XX += Ewz_list[i]*np.conj(Ewz_list[j]) 223 | nPairs += 1 224 | XX = np.abs(XX)/nPairs 225 | 226 | return np.real(XX/Iw_av), Iw_av 227 | 228 | 229 | def Gamma(w, Ewz_list, w1, w2): 230 | r""" intrapulse coherence function 231 | 232 | Implements variant of intrapulse coherence function, modified 233 | from Eq. (3) of Ref. [1] 234 | 235 | Args: 236 | w (1D array, floats): cropped angular frequency axis 237 | Ewz (2D array, floats): cropped frequency doman arrays 238 | w1 (float): selected frequency for conjugate complexed field 239 | w2 (float): selected frequency for field 240 | 241 | Returns: GammaCEP_val 242 | GammaCEP_val (float): value of coherence function 243 | 244 | NOTE: 245 | - in Ref. [1], intrapulse coherence with focus on f-to-2f setups was 246 | considered. Here the intrapulse coherence of Ref. [1] is modified 247 | by relaxing the f/2f condition. Instead, two general distict 248 | frequencies are considered and the interpulse coherence function is 249 | considered as 250 | 251 | \Gamma(\lambda_1, \lambda_2) = 252 | \frac{ 253 | |\langle A(\lambda_2)A^*(\lambda_1) \rangle| }{ 254 | \langle| A(\lambda_2)A^*(\lambda_1)| \rangle 255 | } 256 | 257 | Refs: 258 | [1] Role of Intrapulse Coherence in Carrier-Envelope Phase Stabilization 259 | N. Raabe, T. Feng, T. Witting, A. Demircan, C. Bree, and G. Steinmeyer, 260 | Phys. Rev. Lett. 119, 123901 (2017) 261 | """ 262 | 263 | def _helper(w,Ewz,w1,w2): 264 | w1Id = np.argmin(np.abs(w-w1)) 265 | w2Id = np.argmin(np.abs(w-w2)) 266 | return Ewz[w2Id]*np.conj(Ewz[w1Id]) 267 | # -- THE LINE BELOW IMPLEMENTS EQ. (3) OF REF. [1] 268 | #return Ewz[w2Id]*Ewz[w2Id]*np.conj(Ewz[w1Id]) 269 | 270 | X_list = list(map(lambda x: _helper(w, x, w1, w2), Ewz_list)) 271 | num = np.abs(np.mean(X_list)) 272 | den = np.mean(np.abs(X_list)) 273 | return num/den 274 | 275 | 276 | dat = np.load(f_list[0]) 277 | w0 = dat['w0'] 278 | 279 | z, w, uwz_list = fetch_data(f_list) 280 | g12, Iw_av = firstOrderCoherence(w, uwz_list) 281 | 282 | 283 | lam_lim = (400,1500) 284 | lam_ticks = (500,800,1100,1400) 285 | y_lim = (0,1.1) 286 | y_ticks = (0,0.2,0.4,0.6,0.8,1.0) 287 | 288 | c0 = 0.29979 289 | lam = 1e3*2*np.pi*c0/(w0+w) # (nm) 290 | lam_mask = np.logical_and(lam>lam_lim[0],lam1e-20,10.*np.log10(x),10*np.log10(1e-20)) 293 | 294 | Iw_av /= Iw_av.max() 295 | axB1.plot(lam[lam_mask], _dB(Iw_av[lam_mask]), lw=0.75) 296 | 297 | axB2.plot(lam[lam_mask], g12[lam_mask], lw=0.75) 298 | 299 | axB1.tick_params(axis='x', length=2., pad=2, top=False, labelbottom=False) 300 | axB1.set_xlim(lam_lim) 301 | axB1.set_xticks(lam_ticks) 302 | 303 | #axB1.tick_params(axis='y', length=2., pad=2, top=False) 304 | axB1.set_ylim(-85,5) 305 | axB1.set_yticks((-80,-60,-40,-20.,0)) 306 | #axB1.set_ylim(-80,2) 307 | #axB1.set_yticks((-70,-50,-30.,-10)) 308 | #axB1.set_ylabel(r"Intensity $I_\Omega~\mathrm{(dB)}$") 309 | 310 | #axB2.tick_params(axis='y', length=2., pad=2, top=False) 311 | axB2.set_ylim(y_lim) 312 | axB2.set_yticks(y_ticks) 313 | #axB2.set_ylabel(r"Coherence $|g_{12}^{(1)}|$") 314 | 315 | axB2.tick_params(axis='x', length=2., pad=2, top=False,labelbottom=False) 316 | axB2.set_xlim(lam_lim) 317 | axB2.set_xticks(lam_ticks) 318 | #axB2.set_xlabel(r"Wavelength $\lambda~\mathrm{(nm)}$", labelpad=1) 319 | 320 | wS = 1.3 321 | w_list = np.linspace(-1,3.,600) 322 | lam_G=1e3*2*np.pi*0.29979/(w_list+w0) 323 | Gam = np.asarray( [Gamma(w, uwz_list, wc, wS) for wc in w_list] ) 324 | #print(Gam) 325 | print(wS, wS-w0, 2*np.pi*0.29979/wS) 326 | #exit() 327 | 328 | lam_G_mask = np.logical_and(lam_G>lam_lim[0],lam_G1e-20,10.*np.log10(x),10*np.log10(1e-20)) 168 | 169 | c0 = 0.29979 170 | w0 = 2.2559 171 | lam_lim = (400,1700) 172 | lam_ticks = (500,800,1100,1400,1600) 173 | y_lim = (0,1.1) 174 | y_ticks = (0,0.2,0.4,0.6,0.8,1.0) 175 | 176 | 177 | 178 | # -- T0 = 100 --------------------------------------------------------- 179 | #path = '../data_delG1e-08_t0FWHM100.000000/' 180 | #f_list = [path+f for f in os.listdir(path)[:]] 181 | 182 | dat = np.load(f_list[0]) 183 | w0 = dat['w0'] 184 | 185 | z, w, uwz_list = fetch_data(f_list) 186 | 187 | lam = 1e3*2*np.pi*c0/(w0+w) # (nm) 188 | lam_mask = np.logical_and(lam>lam_lim[0],lam-3.,w<3.) 53 | #Ewz_list += [Ewz[wMask]] 54 | Ewz_list += [Ewz] 55 | 56 | return z, w, np.asarray(Ewz_list) 57 | 58 | 59 | def set_legend(ax, lines, loc=0, ncol=1): 60 | """set legend 61 | 62 | Function generating a custom legend, see [1] for more options 63 | 64 | Refs: 65 | [1] https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.pyplot.legend.html 66 | 67 | Args: 68 | ax (object): figure part for which the legend is intended 69 | lines (list): list of Line2D objects 70 | """ 71 | # -- extract labels from lines 72 | labels = [x.get_label() for x in lines] 73 | # -- customize legend 74 | ax.legend(lines, # list of Line2D objects 75 | labels, # labels 76 | title = '', # title shown on top of legend 77 | loc = loc, # location of the legend 78 | ncol = ncol, # number of columns 79 | labelspacing = 0.3, # vertical space between handles in font-size units 80 | borderpad = 0.3, # distance to legend border in font-size units 81 | handletextpad = 0.3, # distance between handle and label in font-size units 82 | handlelength = 1.5, # length of handle in font-size units 83 | frameon = False # remove background patch 84 | ) 85 | 86 | 87 | def custom_colormap(): 88 | # -- CREATE CUSTOM COLORMAP 89 | from matplotlib.colors import ListedColormap 90 | cmap_base = mpl.cm.jet(np.arange(256)) 91 | blank = np.ones((12,4)) 92 | for i in range(3): 93 | blank[:,i] = np.linspace(1,cmap_base[0,i], blank.shape[0]) 94 | my_cmap = ListedColormap(np.vstack((blank, cmap_base ))) 95 | return my_cmap 96 | 97 | class Figure(): 98 | 99 | def __init__(self, aspect_ratio = 1.0, fig_format = 'png', fig_basename = 'fig_test'): 100 | self.fig_format = fig_format 101 | self.fig_basename = fig_basename 102 | self.fig = None 103 | self.set_style(aspect_ratio) 104 | 105 | def set_style(self, aspect_ratio = 1.0): 106 | 107 | fig_width = 3.2 # (inch) 108 | fig_height = aspect_ratio*fig_width 109 | 110 | params = { 111 | 'figure.figsize': (fig_width,fig_height), 112 | 'legend.fontsize': 6, 113 | 'legend.frameon': False, 114 | 'axes.labelsize': 6, 115 | 'axes.linewidth': 0.8, 116 | 'xtick.labelsize' :6, 117 | 'ytick.labelsize': 6, 118 | 'mathtext.fontset': 'stixsans', 119 | 'mathtext.rm': 'serif', 120 | 'mathtext.bf': 'serif:bold', 121 | 'mathtext.it': 'serif:italic', 122 | 'mathtext.sf': 'sans\\-serif', 123 | 'font.size': 6, 124 | 'font.family': 'serif', 125 | 'font.serif': "Helvetica", 126 | } 127 | mpl.rcParams.update(params) 128 | 129 | 130 | def save(self): 131 | fig_format, fig_name = self.fig_format, self.fig_basename 132 | if fig_format == 'png': 133 | plt.savefig(fig_name+'.png', format='png', dpi=600) 134 | elif fig_format == 'pdf': 135 | plt.savefig(fig_name+'.pdf', format='pdf', dpi=600) 136 | elif fig_format == 'svg': 137 | plt.savefig(fig_name+'.svg', format='svg', dpi=600) 138 | else: 139 | plt.show() 140 | 141 | 142 | def set_subfig_label(self,ax, label1): 143 | pos = ax.get_position() 144 | 145 | self.fig.text(pos.x0, pos.y1+0.01, label1 ,color='white', 146 | backgroundcolor='k', bbox=dict(facecolor='k', edgecolor='none', 147 | boxstyle='square,pad=0.1'), verticalalignment='bottom' ) 148 | 149 | #self.fig.text(pos.x0+0.04, pos.y1+0.01, label2 ,color='k', 150 | # verticalalignment='bottom' ) 151 | 152 | 153 | def set_layout(self): 154 | 155 | fig = plt.figure() 156 | self.fig = fig 157 | 158 | plt.subplots_adjust(left = 0.08, bottom = 0.1, right = 0.89, top = 0.95, wspace = .05, hspace = 0.9) 159 | 160 | gs00 = GridSpec(nrows = 1, ncols = 2) 161 | 162 | gsA = GridSpecFromSubplotSpec(5, 1, subplot_spec=gs00[0,0], wspace=0.07, hspace=0.1) 163 | axA1 = fig.add_subplot(gsA[0, 0]) 164 | axA2 = fig.add_subplot(gsA[1, 0]) 165 | axA3 = fig.add_subplot(gsA[2, 0]) 166 | axA4 = fig.add_subplot(gsA[3, 0]) 167 | axA5 = fig.add_subplot(gsA[4, 0]) 168 | self.subfig_1 = [axA1, axA2, axA3, axA4, axA5] 169 | 170 | gsA = GridSpecFromSubplotSpec(5, 1, subplot_spec=gs00[0,1], wspace=0.07, hspace=0.1) 171 | axA1 = fig.add_subplot(gsA[0, 0]) 172 | axA2 = fig.add_subplot(gsA[1, 0]) 173 | axA3 = fig.add_subplot(gsA[2, 0]) 174 | axA4 = fig.add_subplot(gsA[3, 0]) 175 | axA5 = fig.add_subplot(gsA[4, 0]) 176 | self.subfig_2 = [axA1, axA2, axA3, axA4, axA5] 177 | 178 | 179 | 180 | def set_figs(self, f_list): 181 | sf1 = self.subfig_1 182 | 183 | t_lim = (-0.2,3.2) 184 | t_ticks = (0,1,2,3) 185 | y_lim = (0,10.) 186 | y_ticks = (0,4,8) 187 | 188 | idx_list = np.arange(len(f_list)) 189 | idx_list = np.random.permutation(idx_list) 190 | print(idx_list) 191 | idx_list = [ 9 , 1, 10, 3, 12, 16 , 2 , 6, 7, 11, 5, 13, 19, 14, 18, 15, 8, 17, 0 , 4] 192 | 193 | 194 | for idx, ax in enumerate(sf1): 195 | 196 | dat = np.load(f_list[idx_list[idx]]) 197 | z = dat['z']*1e-6 # (m) 198 | t = dat['t']*1e-3 # (ps) 199 | w = dat['w'] # (rad/fs) 200 | w0 = dat['w0'] # (rad/fs) 201 | P0 = dat['P0'] # (W) 202 | utz = dat['utz'] # (W) 203 | 204 | I = np.abs(utz)**2/1000 205 | 206 | ax.plot(t,I,lw=0.75) 207 | 208 | ax.set_xlim(t_lim) 209 | ax.set_xticks(t_ticks) 210 | ax.set_ylim(y_lim) 211 | ax.set_yticks(y_ticks) 212 | 213 | if idx==2: 214 | ax.set_ylabel(r"Intensity $I(t)~\mathrm{(kW)}$", y=0) 215 | ax.tick_params(axis='y', length=2., pad=2, top=False) 216 | 217 | 218 | if idx==len(sf1)-1: 219 | ax.spines.right.set_color('none') 220 | ax.spines.top.set_color('none') 221 | ax.tick_params(axis='x', length=2., pad=2, top=False) 222 | ax.set_xlabel(r"Time $t~\mathrm{(ps)}$", labelpad=1) 223 | else: 224 | ax.spines.right.set_color('none') 225 | ax.spines.top.set_color('none') 226 | #ax.spines.bottom.set_color('none') 227 | ax.tick_params(axis='x', length=2., pad=2, top=False, bottom=True) 228 | #ax.tick_params(axis='x', length=2., pad=2, top=False, labelbottom=False, bottom=False) 229 | 230 | 231 | sf2 = self.subfig_2 232 | 233 | lam_lim = (400,1500) 234 | lam_ticks = (500,800,1100,1400) 235 | Iw_lim = (0,1.04) 236 | Iw_ticks = (0,0.2,0.4,0.6,0.8,1.0) 237 | 238 | for idx, ax in enumerate(sf2): 239 | 240 | dat = np.load(f_list[idx_list[idx]]) 241 | z = dat['z']*1e-6 # (m) 242 | t = dat['t']*1e-3 # (ps) 243 | w = dat['w'] # (rad/fs) 244 | w0 = dat['w0'] # (rad/fs) 245 | P0 = dat['P0'] # (W) 246 | utz = dat['utz'] # (W) 247 | 248 | w = SHIFT(w) 249 | 250 | c0 = 0.29979 251 | lam = 1e3*2*np.pi*c0/(w0+w) # (nm) 252 | lam_mask = np.logical_and(lam>lam_lim[0],lam1e-20,10.*np.log10(x),10*np.log10(1e-20)) 254 | 255 | Iw = SHIFT(np.abs(FT(utz))**2) 256 | Iw /= Iw.max() 257 | 258 | ax.plot(lam[lam_mask], _dB(Iw[lam_mask]), lw=0.75) 259 | 260 | ax.set_ylim(-85,5) 261 | ax.set_yticks((-70,-40,-10)) 262 | #ax.set_ylabel(r"Intensity $I_\Omega~\mathrm{(dB)}$") 263 | 264 | #axB2.tick_params(axis='y', length=2., pad=2, top=False) 265 | #ax.set_ylim(y_lim) 266 | #ax.set_yticks(y_ticks) 267 | #axB2.set_ylabel(r"Coherence $|g_{12}^{(1)}|$") 268 | 269 | #ax.tick_params(axis='x', length=2., pad=2, top=False) 270 | ax.set_xlim(lam_lim) 271 | ax.set_xticks(lam_ticks) 272 | 273 | if idx==2: 274 | ax.set_ylabel(r"Spectrum $I_\Omega~\mathrm{(dB)}$",y=0) 275 | ax.yaxis.set_label_position('right') 276 | ax.tick_params(axis='y', length=2., pad=2, left=False, right=True, labelleft=False, labelright=True) 277 | 278 | if idx==len(sf1)-1: 279 | ax.spines.left.set_color('none') 280 | ax.spines.top.set_color('none') 281 | ax.tick_params(axis='x', length=2., pad=2, top=False) 282 | ax.set_xlabel(r"Wavelength $\lambda~\mathrm{(nm)}$", labelpad=1) 283 | else: 284 | ax.spines.left.set_color('none') 285 | ax.spines.top.set_color('none') 286 | #ax.spines.bottom.set_color('none') 287 | ax.tick_params(axis='x', length=2., pad=2, top=False, bottom=True) 288 | #ax.tick_params(axis='x', length=2., pad=2, top=False, labelbottom=False, bottom=False) 289 | 290 | self.set_subfig_label(sf1[0],"(a)") 291 | self.set_subfig_label(sf2[0],"(b)") 292 | 293 | 294 | 295 | 296 | def main(): 297 | #path = sys.argv[1] 298 | path = '../data_delG1e-08_t0FWHM150.000000/' 299 | f_list = [path+f for f in os.listdir(path)[:]] 300 | 301 | myFig = Figure(aspect_ratio=0.85, fig_basename="fig02", fig_format='png') 302 | myFig.set_layout() 303 | 304 | myFig.set_figs(f_list) 305 | 306 | myFig.save() 307 | 308 | if __name__ == '__main__': 309 | main() 310 | -------------------------------------------------------------------------------- /results/numExp04_noise_model_02/pp_fig_FIG03/fig03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omelchert/GNLStools/a9694239f65f3f275fb02083425c8fef5f6b8f42/results/numExp04_noise_model_02/pp_fig_FIG03/fig03.png -------------------------------------------------------------------------------- /results/numExp04_noise_model_02/pp_fig_FIG03/main_figure_03.py: -------------------------------------------------------------------------------- 1 | """ 2 | Author: O. Melchert 3 | Date: 2020-09-09 4 | """ 5 | import sys 6 | import os 7 | import itertools 8 | import numpy as np 9 | import numpy.fft as nfft 10 | import matplotlib as mpl 11 | import matplotlib.pyplot as plt 12 | from matplotlib.gridspec import GridSpec, GridSpecFromSubplotSpec 13 | 14 | # -- CONVENIENT ABBREVIATIONS 15 | FT = nfft.ifft 16 | IFT = nfft.fft 17 | SHIFT = nfft.fftshift 18 | 19 | 20 | def fetch_data(f_list): 21 | """ fetch data from npz-files 22 | 23 | Args: 24 | z0 (float): selected propagation distance 25 | 26 | Returns: (w, Ewz_list) 27 | w (1D array, floats): cropped angular frequency axis 28 | Ewz_list (2D array, floats): cropped frequency doman arrays 29 | """ 30 | 31 | def _helper(iPath): 32 | data = np.load(iPath) 33 | return data['z'], data['t'], data['w'], FT(data['utz']) 34 | 35 | Ewz_list = [] 36 | for fName in f_list: 37 | 38 | # -- FETCH RAW DATA 39 | (z, t, w, Ewz) = _helper(fName) 40 | z = z*1e-6 # rescale to m 41 | w = SHIFT(w) 42 | 43 | Ewz = SHIFT(Ewz,axes=-1) 44 | Ewz_list += [Ewz] 45 | 46 | return z, w, np.asarray(Ewz_list) 47 | 48 | 49 | def set_legend(ax, lines, loc=0, ncol=1): 50 | """set legend 51 | 52 | Function generating a custom legend, see [1] for more options 53 | 54 | Refs: 55 | [1] https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.pyplot.legend.html 56 | 57 | Args: 58 | ax (object): figure part for which the legend is intended 59 | lines (list): list of Line2D objects 60 | """ 61 | # -- extract labels from lines 62 | labels = [x.get_label() for x in lines] 63 | # -- customize legend 64 | ax.legend(lines, # list of Line2D objects 65 | labels, # labels 66 | title = '', # title shown on top of legend 67 | loc = loc, # location of the legend 68 | ncol = ncol, # number of columns 69 | labelspacing = 0.3, # vertical space between handles in font-size units 70 | borderpad = 0.3, # distance to legend border in font-size units 71 | handletextpad = 0.3, # distance between handle and label in font-size units 72 | handlelength = 1.5, # length of handle in font-size units 73 | frameon = False # remove background patch 74 | ) 75 | 76 | 77 | def custom_colormap(): 78 | # -- CREATE CUSTOM COLORMAP 79 | from matplotlib.colors import ListedColormap 80 | cmap_base = mpl.cm.jet(np.arange(256)) 81 | blank = np.ones((12,4)) 82 | for i in range(3): 83 | blank[:,i] = np.linspace(1,cmap_base[0,i], blank.shape[0]) 84 | my_cmap = ListedColormap(np.vstack((blank, cmap_base ))) 85 | return my_cmap 86 | 87 | 88 | class Figure(): 89 | 90 | def __init__(self, aspect_ratio = 1.0, fig_format = 'png', fig_basename = 'fig_test'): 91 | self.fig_format = fig_format 92 | self.fig_basename = fig_basename 93 | self.fig = None 94 | self.set_style(aspect_ratio) 95 | 96 | def set_style(self, aspect_ratio = 1.0): 97 | 98 | fig_width = 3.2 # (inch) 99 | fig_height = aspect_ratio*fig_width 100 | 101 | params = { 102 | 'figure.figsize': (fig_width,fig_height), 103 | 'legend.fontsize': 6, 104 | 'legend.frameon': False, 105 | 'axes.labelsize': 6, 106 | 'axes.linewidth': 0.8, 107 | 'xtick.labelsize' :6, 108 | 'ytick.labelsize': 6, 109 | 'mathtext.fontset': 'stixsans', 110 | 'mathtext.rm': 'serif', 111 | 'mathtext.bf': 'serif:bold', 112 | 'mathtext.it': 'serif:italic', 113 | 'mathtext.sf': 'sans\\-serif', 114 | 'font.size': 6, 115 | 'font.family': 'serif', 116 | 'font.serif': "Helvetica", 117 | } 118 | mpl.rcParams.update(params) 119 | 120 | 121 | def save(self): 122 | fig_format, fig_name = self.fig_format, self.fig_basename 123 | if fig_format == 'png': 124 | plt.savefig(fig_name+'.png', format='png', dpi=600) 125 | elif fig_format == 'pdf': 126 | plt.savefig(fig_name+'.pdf', format='pdf', dpi=600) 127 | elif fig_format == 'svg': 128 | plt.savefig(fig_name+'.svg', format='svg', dpi=600) 129 | else: 130 | plt.show() 131 | 132 | 133 | def set_subfig_label(self,ax, label1, label2): 134 | pos = ax.get_position() 135 | 136 | self.fig.text(pos.x0, pos.y1+0.01, label1 ,color='white', 137 | backgroundcolor='k', bbox=dict(facecolor='k', edgecolor='none', 138 | boxstyle='square,pad=0.1'), verticalalignment='bottom' ) 139 | 140 | self.fig.text(pos.x0+0.04, pos.y1+0.01, label2 ,color='k', 141 | verticalalignment='bottom' ) 142 | 143 | 144 | def set_layout(self): 145 | 146 | fig = plt.figure() 147 | self.fig = fig 148 | 149 | plt.subplots_adjust(left = 0.11, bottom = 0.08, right = 0.98, top = 0.95, wspace = .075, hspace = 1.2) 150 | 151 | gs00 = GridSpec(nrows = 7, ncols = 3) 152 | 153 | gsA = GridSpecFromSubplotSpec(1, 1, subplot_spec=gs00[0:2,0], wspace=0.07, hspace=0.1) 154 | axA1 = fig.add_subplot(gsA[0, 0]) 155 | gsB = GridSpecFromSubplotSpec(3, 1, subplot_spec=gs00[2:,0], wspace=0.07, hspace=0.075) 156 | axB1 = fig.add_subplot(gsB[0, 0]) 157 | axB2 = fig.add_subplot(gsB[1, 0]) 158 | axB3 = fig.add_subplot(gsB[2, 0]) 159 | self.subfig_1 = [axA1, axB1, axB2, axB3] 160 | 161 | gsA = GridSpecFromSubplotSpec(1, 1, subplot_spec=gs00[0:2,1], wspace=0.07, hspace=0.1) 162 | axA1 = fig.add_subplot(gsA[0, 0]) 163 | gsB = GridSpecFromSubplotSpec(3, 1, subplot_spec=gs00[2:,1], wspace=0.07, hspace=0.075) 164 | axB1 = fig.add_subplot(gsB[0, 0]) 165 | axB2 = fig.add_subplot(gsB[1, 0]) 166 | axB3 = fig.add_subplot(gsB[2, 0]) 167 | self.subfig_2 = [axA1, axB1, axB2, axB3] 168 | 169 | gsA = GridSpecFromSubplotSpec(1, 1, subplot_spec=gs00[0:2,2], wspace=0.07, hspace=0.1) 170 | axA1 = fig.add_subplot(gsA[0, 0]) 171 | gsB = GridSpecFromSubplotSpec(3, 1, subplot_spec=gs00[2:,2], wspace=0.07, hspace=0.075) 172 | axB1 = fig.add_subplot(gsB[0, 0]) 173 | axB2 = fig.add_subplot(gsB[1, 0]) 174 | axB3 = fig.add_subplot(gsB[2, 0]) 175 | self.subfig_3 = [axA1, axB1, axB2, axB3] 176 | 177 | 178 | def set_subfig_01(self, subfig, f_name, z0): 179 | axA1 = subfig[0] 180 | 181 | t_lim = (-0.2,3.2) 182 | t_ticks = (0,1,2,3) 183 | y_lim = (0,10.) 184 | y_ticks = (0,2,4,6,8,10) 185 | #y_lim = (0,1.) 186 | #y_ticks = (0,0.2,0.4,0.6,0.8,1.0) 187 | 188 | dat = np.load(f_name) 189 | z = dat['z']*1e-6 # (m) 190 | t = dat['t']*1e-3 # (ps) 191 | P0 = dat['P0'] # (W) 192 | utz = dat['utz'] # (W) 193 | 194 | #z_id = np.argmin(np.abs(z-z0)) 195 | #I = np.abs(utz[z_id])**2 196 | I = np.abs(utz)**2/1000 197 | 198 | axA1.plot(t,I,lw=0.75) 199 | #axA1.plot(t,I/P0,lw=0.75) 200 | 201 | axA1.tick_params(axis='x', length=2., pad=2, top=False) 202 | axA1.set_xlim(t_lim) 203 | axA1.set_xticks(t_ticks) 204 | axA1.set_xlabel(r"Time $t~\mathrm{(ps)}$", labelpad=1) 205 | 206 | #axA1.tick_params(axis='y', length=2., pad=2, top=False) 207 | axA1.set_ylim(y_lim) 208 | axA1.set_yticks(y_ticks) 209 | #axA1.set_ylabel(r"Intensity $I(t)/P_0$") 210 | 211 | 212 | def set_subfig_02(self, subfig, f_list, z0): 213 | _, axB1, axB2, axB3 = subfig 214 | 215 | def firstOrderCoherence(w, Ewz_list): 216 | 217 | Iw_av = np.mean(np.abs(Ewz_list)**2, axis=0) 218 | 219 | nPairs = 0 220 | XX = np.zeros(len(Ewz_list[0]),dtype=complex) 221 | for i,j in list(itertools.combinations(range(len(Ewz_list)),2)): 222 | XX += Ewz_list[i]*np.conj(Ewz_list[j]) 223 | nPairs += 1 224 | XX = np.abs(XX)/nPairs 225 | 226 | return np.real(XX/Iw_av), Iw_av 227 | 228 | 229 | def Gamma(w, Ewz_list, w1, w2): 230 | r""" intrapulse coherence function 231 | 232 | Implements variant of intrapulse coherence function, modified 233 | from Eq. (3) of Ref. [1] 234 | 235 | Args: 236 | w (1D array, floats): cropped angular frequency axis 237 | Ewz (2D array, floats): cropped frequency doman arrays 238 | w1 (float): selected frequency for conjugate complexed field 239 | w2 (float): selected frequency for field 240 | 241 | Returns: GammaCEP_val 242 | GammaCEP_val (float): value of coherence function 243 | 244 | NOTE: 245 | - in Ref. [1], intrapulse coherence with focus on f-to-2f setups was 246 | considered. Here the intrapulse coherence of Ref. [1] is modified 247 | by relaxing the f/2f condition. Instead, two general distict 248 | frequencies are considered and the interpulse coherence function is 249 | considered as 250 | 251 | \Gamma(\lambda_1, \lambda_2) = 252 | \frac{ 253 | |\langle A(\lambda_2)A^*(\lambda_1) \rangle| }{ 254 | \langle| A(\lambda_2)A^*(\lambda_1)| \rangle 255 | } 256 | 257 | Refs: 258 | [1] Role of Intrapulse Coherence in Carrier-Envelope Phase Stabilization 259 | N. Raabe, T. Feng, T. Witting, A. Demircan, C. Bree, and G. Steinmeyer, 260 | Phys. Rev. Lett. 119, 123901 (2017) 261 | """ 262 | 263 | def _helper(w,Ewz,w1,w2): 264 | w1Id = np.argmin(np.abs(w-w1)) 265 | w2Id = np.argmin(np.abs(w-w2)) 266 | return Ewz[w2Id]*np.conj(Ewz[w1Id]) 267 | # -- THE LINE BELOW IMPLEMENTS EQ. (3) OF REF. [1] 268 | #return Ewz[w2Id]*Ewz[w2Id]*np.conj(Ewz[w1Id]) 269 | 270 | X_list = list(map(lambda x: _helper(w, x, w1, w2), Ewz_list)) 271 | num = np.abs(np.mean(X_list)) 272 | den = np.mean(np.abs(X_list)) 273 | return num/den 274 | 275 | 276 | dat = np.load(f_list[0]) 277 | w0 = dat['w0'] 278 | 279 | z, w, uwz_list = fetch_data(f_list) 280 | g12, Iw_av = firstOrderCoherence(w, uwz_list) 281 | 282 | 283 | lam_lim = (400,1500) 284 | lam_ticks = (500,800,1100,1400) 285 | y_lim = (0,1.1) 286 | y_ticks = (0,0.2,0.4,0.6,0.8,1.0) 287 | 288 | c0 = 0.29979 289 | lam = 1e3*2*np.pi*c0/(w0+w) # (nm) 290 | lam_mask = np.logical_and(lam>lam_lim[0],lam1e-20,10.*np.log10(x),10*np.log10(1e-20)) 293 | 294 | Iw_av /= Iw_av.max() 295 | axB1.plot(lam[lam_mask], _dB(Iw_av[lam_mask]), lw=0.75) 296 | 297 | axB2.plot(lam[lam_mask], g12[lam_mask], lw=0.75) 298 | 299 | axB1.tick_params(axis='x', length=2., pad=2, top=False, labelbottom=False) 300 | axB1.set_xlim(lam_lim) 301 | axB1.set_xticks(lam_ticks) 302 | 303 | #axB1.tick_params(axis='y', length=2., pad=2, top=False) 304 | axB1.set_ylim(-85,5) 305 | axB1.set_yticks((-80,-60,-40,-20.,0)) 306 | #axB1.set_ylim(-80,2) 307 | #axB1.set_yticks((-70,-50,-30.,-10)) 308 | #axB1.set_ylabel(r"Intensity $I_\Omega~\mathrm{(dB)}$") 309 | 310 | #axB2.tick_params(axis='y', length=2., pad=2, top=False) 311 | axB2.set_ylim(y_lim) 312 | axB2.set_yticks(y_ticks) 313 | #axB2.set_ylabel(r"Coherence $|g_{12}^{(1)}|$") 314 | 315 | axB2.tick_params(axis='x', length=2., pad=2, top=False,labelbottom=False) 316 | axB2.set_xlim(lam_lim) 317 | axB2.set_xticks(lam_ticks) 318 | #axB2.set_xlabel(r"Wavelength $\lambda~\mathrm{(nm)}$", labelpad=1) 319 | 320 | wS = 1.3 321 | w_list = np.linspace(-1,3.,600) 322 | lam_G=1e3*2*np.pi*0.29979/(w_list+w0) 323 | Gam = np.asarray( [Gamma(w, uwz_list, wc, wS) for wc in w_list] ) 324 | #print(Gam) 325 | print(wS, wS-w0, 2*np.pi*0.29979/wS) 326 | #exit() 327 | 328 | lam_G_mask = np.logical_and(lam_G>lam_lim[0],lam_G-3.,w<3.) 53 | #Ewz_list += [Ewz[wMask]] 54 | Ewz_list += [Ewz] 55 | 56 | return z, w, np.asarray(Ewz_list) 57 | 58 | 59 | def set_legend(ax, lines, loc=0, ncol=1): 60 | """set legend 61 | 62 | Function generating a custom legend, see [1] for more options 63 | 64 | Refs: 65 | [1] https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.pyplot.legend.html 66 | 67 | Args: 68 | ax (object): figure part for which the legend is intended 69 | lines (list): list of Line2D objects 70 | """ 71 | # -- extract labels from lines 72 | labels = [x.get_label() for x in lines] 73 | # -- customize legend 74 | ax.legend(lines, # list of Line2D objects 75 | labels, # labels 76 | title = '', # title shown on top of legend 77 | loc = loc, # location of the legend 78 | ncol = ncol, # number of columns 79 | labelspacing = 0.3, # vertical space between handles in font-size units 80 | borderpad = 0.3, # distance to legend border in font-size units 81 | handletextpad = 0.3, # distance between handle and label in font-size units 82 | handlelength = 1.5, # length of handle in font-size units 83 | frameon = False # remove background patch 84 | ) 85 | 86 | 87 | def custom_colormap(): 88 | # -- CREATE CUSTOM COLORMAP 89 | from matplotlib.colors import ListedColormap 90 | cmap_base = mpl.cm.jet(np.arange(256)) 91 | blank = np.ones((12,4)) 92 | for i in range(3): 93 | blank[:,i] = np.linspace(1,cmap_base[0,i], blank.shape[0]) 94 | my_cmap = ListedColormap(np.vstack((blank, cmap_base ))) 95 | return my_cmap 96 | 97 | class Figure(): 98 | 99 | def __init__(self, aspect_ratio = 1.0, fig_format = 'png', fig_basename = 'fig_test'): 100 | self.fig_format = fig_format 101 | self.fig_basename = fig_basename 102 | self.fig = None 103 | self.set_style(aspect_ratio) 104 | 105 | def set_style(self, aspect_ratio = 1.0): 106 | 107 | fig_width = 3.4 # (inch) 108 | fig_height = aspect_ratio*fig_width 109 | 110 | params = { 111 | 'figure.figsize': (fig_width,fig_height), 112 | 'legend.fontsize': 6, 113 | 'legend.frameon': False, 114 | 'axes.labelsize': 6, 115 | 'axes.linewidth': 0.8, 116 | 'xtick.labelsize' :6, 117 | 'ytick.labelsize': 6, 118 | 'mathtext.fontset': 'stixsans', 119 | 'mathtext.rm': 'serif', 120 | 'mathtext.bf': 'serif:bold', 121 | 'mathtext.it': 'serif:italic', 122 | 'mathtext.sf': 'sans\\-serif', 123 | 'font.size': 6, 124 | 'font.family': 'serif', 125 | 'font.serif': "Helvetica", 126 | } 127 | mpl.rcParams.update(params) 128 | 129 | 130 | def save(self): 131 | fig_format, fig_name = self.fig_format, self.fig_basename 132 | if fig_format == 'png': 133 | plt.savefig(fig_name+'.png', format='png', dpi=600) 134 | elif fig_format == 'pdf': 135 | plt.savefig(fig_name+'.pdf', format='pdf', dpi=600) 136 | elif fig_format == 'svg': 137 | plt.savefig(fig_name+'.svg', format='svg', dpi=600) 138 | else: 139 | plt.show() 140 | 141 | 142 | def set_subfig_label(self,ax, label1): 143 | pos = ax.get_position() 144 | 145 | self.fig.text(pos.x0, pos.y1+0.01, label1 ,color='white', 146 | backgroundcolor='k', bbox=dict(facecolor='k', edgecolor='none', 147 | boxstyle='square,pad=0.1'), verticalalignment='bottom' ) 148 | 149 | #self.fig.text(pos.x0+0.04, pos.y1+0.01, label2 ,color='k', 150 | # verticalalignment='bottom' ) 151 | 152 | 153 | def set_layout(self): 154 | 155 | fig = plt.figure() 156 | self.fig = fig 157 | 158 | plt.subplots_adjust(left = 0.08, bottom = 0.11, right = 0.9, top = 0.93, wspace = .05, hspace = 0.9) 159 | 160 | gs00 = GridSpec(nrows = 1, ncols = 2) 161 | 162 | gsA = GridSpecFromSubplotSpec(6, 1, subplot_spec=gs00[0,0], wspace=0.07, hspace=0.1) 163 | axA1 = fig.add_subplot(gsA[0, 0]) 164 | axA2 = fig.add_subplot(gsA[1, 0]) 165 | axA3 = fig.add_subplot(gsA[2, 0]) 166 | axA4 = fig.add_subplot(gsA[3, 0]) 167 | axA5 = fig.add_subplot(gsA[4, 0]) 168 | axA6 = fig.add_subplot(gsA[5, 0]) 169 | self.subfig_1 = [axA1, axA2, axA3, axA4, axA5, axA6] 170 | 171 | gsA = GridSpecFromSubplotSpec(6, 1, subplot_spec=gs00[0,1], wspace=0.07, hspace=0.1) 172 | axA1 = fig.add_subplot(gsA[0, 0]) 173 | axA2 = fig.add_subplot(gsA[1, 0]) 174 | axA3 = fig.add_subplot(gsA[2, 0]) 175 | axA4 = fig.add_subplot(gsA[3, 0]) 176 | axA5 = fig.add_subplot(gsA[4, 0]) 177 | axA6 = fig.add_subplot(gsA[5, 0]) 178 | self.subfig_2 = [axA1, axA2, axA3, axA4, axA5, axA6] 179 | 180 | 181 | 182 | def set_figs(self, f_list): 183 | sf1 = self.subfig_1 184 | 185 | t_lim = (-0.2,3.2) 186 | t_ticks = (0,1,2,3) 187 | y_lim = (0,10.) 188 | y_ticks = (0,4,8) 189 | 190 | idx_list = np.arange(len(f_list)) 191 | idx_list = np.random.permutation(idx_list) 192 | print(idx_list) 193 | idx_list = [ 9 , 1, 10, 3, 12, 16 , 2 , 6, 7, 11, 5, 13, 19, 14, 18, 15, 8, 17, 0 , 4] 194 | 195 | 196 | for idx, ax in enumerate(sf1): 197 | 198 | dat = np.load(f_list[idx_list[idx]]) 199 | z = dat['z']*1e-6 # (m) 200 | t = dat['t']*1e-3 # (ps) 201 | w = dat['w'] # (rad/fs) 202 | w0 = dat['w0'] # (rad/fs) 203 | P0 = dat['P0'] # (W) 204 | utz = dat['utz'] # (W) 205 | 206 | I = np.abs(utz)**2/1000 207 | 208 | ax.plot(t,I,lw=0.75) 209 | 210 | ax.set_xlim(t_lim) 211 | ax.set_xticks(t_ticks) 212 | ax.set_ylim(y_lim) 213 | ax.set_yticks(y_ticks) 214 | 215 | if idx==2: 216 | ax.set_ylabel(r"Intensity $I(t)~\mathrm{(kW)}$", y=0) 217 | ax.tick_params(axis='y', length=2., pad=2, top=False) 218 | 219 | 220 | if idx==len(sf1)-1: 221 | ax.spines.right.set_color('none') 222 | ax.spines.top.set_color('none') 223 | ax.tick_params(axis='x', length=2., pad=2, top=False) 224 | ax.set_xlabel(r"Time $t~\mathrm{(ps)}$", labelpad=1) 225 | else: 226 | ax.spines.right.set_color('none') 227 | ax.spines.top.set_color('none') 228 | #ax.spines.bottom.set_color('none') 229 | ax.tick_params(axis='x', length=2., pad=2, top=False, bottom=True) 230 | #ax.tick_params(axis='x', length=2., pad=2, top=False, labelbottom=False, bottom=False) 231 | 232 | 233 | sf2 = self.subfig_2 234 | 235 | lam_lim = (400,1500) 236 | lam_ticks = (500,800,1100,1400) 237 | Iw_lim = (0,1.04) 238 | Iw_ticks = (0,0.2,0.4,0.6,0.8,1.0) 239 | 240 | for idx, ax in enumerate(sf2): 241 | 242 | dat = np.load(f_list[idx_list[idx]]) 243 | z = dat['z']*1e-6 # (m) 244 | t = dat['t']*1e-3 # (ps) 245 | w = dat['w'] # (rad/fs) 246 | w0 = dat['w0'] # (rad/fs) 247 | P0 = dat['P0'] # (W) 248 | utz = dat['utz'] # (W) 249 | 250 | w = SHIFT(w) 251 | 252 | c0 = 0.29979 253 | lam = 1e3*2*np.pi*c0/(w0+w) # (nm) 254 | lam_mask = np.logical_and(lam>lam_lim[0],lam1e-20,10.*np.log10(x),10*np.log10(1e-20)) 256 | 257 | Iw = SHIFT(np.abs(FT(utz))**2) 258 | Iw /= Iw.max() 259 | 260 | ax.plot(lam[lam_mask], _dB(Iw[lam_mask]), lw=0.75) 261 | 262 | ax.set_ylim(-85,5) 263 | ax.set_yticks((-70,-40,-10)) 264 | #ax.set_ylabel(r"Intensity $I_\Omega~\mathrm{(dB)}$") 265 | 266 | #axB2.tick_params(axis='y', length=2., pad=2, top=False) 267 | #ax.set_ylim(y_lim) 268 | #ax.set_yticks(y_ticks) 269 | #axB2.set_ylabel(r"Coherence $|g_{12}^{(1)}|$") 270 | 271 | #ax.tick_params(axis='x', length=2., pad=2, top=False) 272 | ax.set_xlim(lam_lim) 273 | ax.set_xticks(lam_ticks) 274 | 275 | if idx==2: 276 | ax.set_ylabel(r"Spectrum $I_\Omega~\mathrm{(dB)}$",y=0) 277 | ax.yaxis.set_label_position('right') 278 | ax.tick_params(axis='y', length=2., pad=2, left=False, right=True, labelleft=False, labelright=True) 279 | 280 | if idx==len(sf1)-1: 281 | ax.spines.left.set_color('none') 282 | ax.spines.top.set_color('none') 283 | ax.tick_params(axis='x', length=2., pad=2, top=False) 284 | ax.set_xlabel(r"Wavelength $\lambda~\mathrm{(nm)}$", labelpad=1) 285 | else: 286 | ax.spines.left.set_color('none') 287 | ax.spines.top.set_color('none') 288 | #ax.spines.bottom.set_color('none') 289 | ax.tick_params(axis='x', length=2., pad=2, top=False, bottom=True) 290 | #ax.tick_params(axis='x', length=2., pad=2, top=False, labelbottom=False, bottom=False) 291 | 292 | self.set_subfig_label(sf1[0],"(a)") 293 | self.set_subfig_label(sf2[0],"(b)") 294 | 295 | 296 | 297 | 298 | def main(): 299 | #path = sys.argv[1] 300 | path = '../data_delG1e-08_t0FWHM150.000000/' 301 | f_list = [path+f for f in os.listdir(path)[:]] 302 | 303 | myFig = Figure(aspect_ratio=.85, fig_basename="fig02", fig_format='png') 304 | myFig.set_layout() 305 | 306 | myFig.set_figs(f_list) 307 | 308 | myFig.save() 309 | 310 | if __name__ == '__main__': 311 | main() 312 | -------------------------------------------------------------------------------- /results/numExp05_noise_model_03/pp_fig_FIG03/fig03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omelchert/GNLStools/a9694239f65f3f275fb02083425c8fef5f6b8f42/results/numExp05_noise_model_03/pp_fig_FIG03/fig03.png -------------------------------------------------------------------------------- /results/numExp05_noise_model_03/pp_fig_FIG03/main_figure_03.py: -------------------------------------------------------------------------------- 1 | """ 2 | Author: O. Melchert 3 | Date: 2020-09-09 4 | """ 5 | import sys 6 | import os 7 | import itertools 8 | import numpy as np 9 | import numpy.fft as nfft 10 | import matplotlib as mpl 11 | import matplotlib.pyplot as plt 12 | from matplotlib.gridspec import GridSpec, GridSpecFromSubplotSpec 13 | 14 | # -- CONVENIENT ABBREVIATIONS 15 | FT = nfft.ifft 16 | IFT = nfft.fft 17 | SHIFT = nfft.fftshift 18 | 19 | 20 | def fetch_data(f_list): 21 | """ fetch data from npz-files 22 | 23 | Args: 24 | z0 (float): selected propagation distance 25 | 26 | Returns: (w, Ewz_list) 27 | w (1D array, floats): cropped angular frequency axis 28 | Ewz_list (2D array, floats): cropped frequency doman arrays 29 | """ 30 | 31 | def _helper(iPath): 32 | data = np.load(iPath) 33 | return data['z'], data['t'], data['w'], FT(data['utz']) 34 | 35 | Ewz_list = [] 36 | for fName in f_list: 37 | 38 | # -- FETCH RAW DATA 39 | (z, t, w, Ewz) = _helper(fName) 40 | z = z*1e-6 # rescale to m 41 | w = SHIFT(w) 42 | 43 | Ewz = SHIFT(Ewz,axes=-1) 44 | Ewz_list += [Ewz] 45 | 46 | return z, w, np.asarray(Ewz_list) 47 | 48 | 49 | def set_legend(ax, lines, loc=0, ncol=1): 50 | """set legend 51 | 52 | Function generating a custom legend, see [1] for more options 53 | 54 | Refs: 55 | [1] https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.pyplot.legend.html 56 | 57 | Args: 58 | ax (object): figure part for which the legend is intended 59 | lines (list): list of Line2D objects 60 | """ 61 | # -- extract labels from lines 62 | labels = [x.get_label() for x in lines] 63 | # -- customize legend 64 | ax.legend(lines, # list of Line2D objects 65 | labels, # labels 66 | title = '', # title shown on top of legend 67 | loc = loc, # location of the legend 68 | ncol = ncol, # number of columns 69 | labelspacing = 0.3, # vertical space between handles in font-size units 70 | borderpad = 0.3, # distance to legend border in font-size units 71 | handletextpad = 0.3, # distance between handle and label in font-size units 72 | handlelength = 1.5, # length of handle in font-size units 73 | frameon = False # remove background patch 74 | ) 75 | 76 | 77 | def custom_colormap(): 78 | # -- CREATE CUSTOM COLORMAP 79 | from matplotlib.colors import ListedColormap 80 | cmap_base = mpl.cm.jet(np.arange(256)) 81 | blank = np.ones((12,4)) 82 | for i in range(3): 83 | blank[:,i] = np.linspace(1,cmap_base[0,i], blank.shape[0]) 84 | my_cmap = ListedColormap(np.vstack((blank, cmap_base ))) 85 | return my_cmap 86 | 87 | 88 | class Figure(): 89 | 90 | def __init__(self, aspect_ratio = 1.0, fig_format = 'png', fig_basename = 'fig_test'): 91 | self.fig_format = fig_format 92 | self.fig_basename = fig_basename 93 | self.fig = None 94 | self.set_style(aspect_ratio) 95 | 96 | def set_style(self, aspect_ratio = 1.0): 97 | 98 | fig_width = 3.2 # (inch) 99 | fig_height = aspect_ratio*fig_width 100 | 101 | params = { 102 | 'figure.figsize': (fig_width,fig_height), 103 | 'legend.fontsize': 6, 104 | 'legend.frameon': False, 105 | 'axes.labelsize': 6, 106 | 'axes.linewidth': 0.8, 107 | 'xtick.labelsize' :6, 108 | 'ytick.labelsize': 6, 109 | 'mathtext.fontset': 'stixsans', 110 | 'mathtext.rm': 'serif', 111 | 'mathtext.bf': 'serif:bold', 112 | 'mathtext.it': 'serif:italic', 113 | 'mathtext.sf': 'sans\\-serif', 114 | 'font.size': 6, 115 | 'font.family': 'serif', 116 | 'font.serif': "Helvetica", 117 | } 118 | mpl.rcParams.update(params) 119 | 120 | 121 | def save(self): 122 | fig_format, fig_name = self.fig_format, self.fig_basename 123 | if fig_format == 'png': 124 | plt.savefig(fig_name+'.png', format='png', dpi=600) 125 | elif fig_format == 'pdf': 126 | plt.savefig(fig_name+'.pdf', format='pdf', dpi=600) 127 | elif fig_format == 'svg': 128 | plt.savefig(fig_name+'.svg', format='svg', dpi=600) 129 | else: 130 | plt.show() 131 | 132 | 133 | def set_subfig_label(self,ax, label1, label2): 134 | pos = ax.get_position() 135 | 136 | self.fig.text(pos.x0, pos.y1+0.01, label1 ,color='white', 137 | backgroundcolor='k', bbox=dict(facecolor='k', edgecolor='none', 138 | boxstyle='square,pad=0.1'), verticalalignment='bottom' ) 139 | 140 | self.fig.text(pos.x0+0.04, pos.y1+0.01, label2 ,color='k', 141 | verticalalignment='bottom' ) 142 | 143 | 144 | def set_layout(self): 145 | 146 | fig = plt.figure() 147 | self.fig = fig 148 | 149 | plt.subplots_adjust(left = 0.11, bottom = 0.08, right = 0.98, top = 0.95, wspace = .075, hspace = 1.2) 150 | 151 | gs00 = GridSpec(nrows = 7, ncols = 3) 152 | 153 | gsA = GridSpecFromSubplotSpec(1, 1, subplot_spec=gs00[0:2,0], wspace=0.07, hspace=0.1) 154 | axA1 = fig.add_subplot(gsA[0, 0]) 155 | gsB = GridSpecFromSubplotSpec(3, 1, subplot_spec=gs00[2:,0], wspace=0.07, hspace=0.075) 156 | axB1 = fig.add_subplot(gsB[0, 0]) 157 | axB2 = fig.add_subplot(gsB[1, 0]) 158 | axB3 = fig.add_subplot(gsB[2, 0]) 159 | self.subfig_1 = [axA1, axB1, axB2, axB3] 160 | 161 | gsA = GridSpecFromSubplotSpec(1, 1, subplot_spec=gs00[0:2,1], wspace=0.07, hspace=0.1) 162 | axA1 = fig.add_subplot(gsA[0, 0]) 163 | gsB = GridSpecFromSubplotSpec(3, 1, subplot_spec=gs00[2:,1], wspace=0.07, hspace=0.075) 164 | axB1 = fig.add_subplot(gsB[0, 0]) 165 | axB2 = fig.add_subplot(gsB[1, 0]) 166 | axB3 = fig.add_subplot(gsB[2, 0]) 167 | self.subfig_2 = [axA1, axB1, axB2, axB3] 168 | 169 | gsA = GridSpecFromSubplotSpec(1, 1, subplot_spec=gs00[0:2,2], wspace=0.07, hspace=0.1) 170 | axA1 = fig.add_subplot(gsA[0, 0]) 171 | gsB = GridSpecFromSubplotSpec(3, 1, subplot_spec=gs00[2:,2], wspace=0.07, hspace=0.075) 172 | axB1 = fig.add_subplot(gsB[0, 0]) 173 | axB2 = fig.add_subplot(gsB[1, 0]) 174 | axB3 = fig.add_subplot(gsB[2, 0]) 175 | self.subfig_3 = [axA1, axB1, axB2, axB3] 176 | 177 | 178 | def set_subfig_01(self, subfig, f_name, z0): 179 | axA1 = subfig[0] 180 | 181 | t_lim = (-0.2,3.2) 182 | t_ticks = (0,1,2,3) 183 | y_lim = (0,10.) 184 | y_ticks = (0,2,4,6,8,10) 185 | #y_lim = (0,1.) 186 | #y_ticks = (0,0.2,0.4,0.6,0.8,1.0) 187 | 188 | dat = np.load(f_name) 189 | z = dat['z']*1e-6 # (m) 190 | t = dat['t']*1e-3 # (ps) 191 | P0 = dat['P0'] # (W) 192 | utz = dat['utz'] # (W) 193 | 194 | #z_id = np.argmin(np.abs(z-z0)) 195 | #I = np.abs(utz[z_id])**2 196 | I = np.abs(utz)**2/1000 197 | 198 | axA1.plot(t,I,lw=0.75) 199 | #axA1.plot(t,I/P0,lw=0.75) 200 | 201 | axA1.tick_params(axis='x', length=2., pad=2, top=False) 202 | axA1.set_xlim(t_lim) 203 | axA1.set_xticks(t_ticks) 204 | axA1.set_xlabel(r"Time $t~\mathrm{(ps)}$", labelpad=1) 205 | 206 | #axA1.tick_params(axis='y', length=2., pad=2, top=False) 207 | axA1.set_ylim(y_lim) 208 | axA1.set_yticks(y_ticks) 209 | #axA1.set_ylabel(r"Intensity $I(t)/P_0$") 210 | 211 | 212 | def set_subfig_02(self, subfig, f_list, z0): 213 | _, axB1, axB2, axB3 = subfig 214 | 215 | def firstOrderCoherence(w, Ewz_list): 216 | 217 | Iw_av = np.mean(np.abs(Ewz_list)**2, axis=0) 218 | 219 | nPairs = 0 220 | XX = np.zeros(len(Ewz_list[0]),dtype=complex) 221 | for i,j in list(itertools.combinations(range(len(Ewz_list)),2)): 222 | XX += Ewz_list[i]*np.conj(Ewz_list[j]) 223 | nPairs += 1 224 | XX = np.abs(XX)/nPairs 225 | 226 | return np.real(XX/Iw_av), Iw_av 227 | 228 | 229 | def Gamma(w, Ewz_list, w1, w2): 230 | r""" intrapulse coherence function 231 | 232 | Implements variant of intrapulse coherence function, modified 233 | from Eq. (3) of Ref. [1] 234 | 235 | Args: 236 | w (1D array, floats): cropped angular frequency axis 237 | Ewz (2D array, floats): cropped frequency doman arrays 238 | w1 (float): selected frequency for conjugate complexed field 239 | w2 (float): selected frequency for field 240 | 241 | Returns: GammaCEP_val 242 | GammaCEP_val (float): value of coherence function 243 | 244 | NOTE: 245 | - in Ref. [1], intrapulse coherence with focus on f-to-2f setups was 246 | considered. Here the intrapulse coherence of Ref. [1] is modified 247 | by relaxing the f/2f condition. Instead, two general distict 248 | frequencies are considered and the interpulse coherence function is 249 | considered as 250 | 251 | \Gamma(\lambda_1, \lambda_2) = 252 | \frac{ 253 | |\langle A(\lambda_2)A^*(\lambda_1) \rangle| }{ 254 | \langle| A(\lambda_2)A^*(\lambda_1)| \rangle 255 | } 256 | 257 | Refs: 258 | [1] Role of Intrapulse Coherence in Carrier-Envelope Phase Stabilization 259 | N. Raabe, T. Feng, T. Witting, A. Demircan, C. Bree, and G. Steinmeyer, 260 | Phys. Rev. Lett. 119, 123901 (2017) 261 | """ 262 | 263 | def _helper(w,Ewz,w1,w2): 264 | w1Id = np.argmin(np.abs(w-w1)) 265 | w2Id = np.argmin(np.abs(w-w2)) 266 | return Ewz[w2Id]*np.conj(Ewz[w1Id]) 267 | # -- THE LINE BELOW IMPLEMENTS EQ. (3) OF REF. [1] 268 | #return Ewz[w2Id]*Ewz[w2Id]*np.conj(Ewz[w1Id]) 269 | 270 | X_list = list(map(lambda x: _helper(w, x, w1, w2), Ewz_list)) 271 | num = np.abs(np.mean(X_list)) 272 | den = np.mean(np.abs(X_list)) 273 | return num/den 274 | 275 | 276 | dat = np.load(f_list[0]) 277 | w0 = dat['w0'] 278 | 279 | z, w, uwz_list = fetch_data(f_list) 280 | g12, Iw_av = firstOrderCoherence(w, uwz_list) 281 | 282 | 283 | lam_lim = (400,1500) 284 | lam_ticks = (500,800,1100,1400) 285 | y_lim = (0,1.1) 286 | y_ticks = (0,0.2,0.4,0.6,0.8,1.0) 287 | 288 | c0 = 0.29979 289 | lam = 1e3*2*np.pi*c0/(w0+w) # (nm) 290 | lam_mask = np.logical_and(lam>lam_lim[0],lam1e-20,10.*np.log10(x),10*np.log10(1e-20)) 293 | 294 | Iw_av /= Iw_av.max() 295 | axB1.plot(lam[lam_mask], _dB(Iw_av[lam_mask]), lw=0.75) 296 | 297 | axB2.plot(lam[lam_mask], g12[lam_mask], lw=0.75) 298 | 299 | axB1.tick_params(axis='x', length=2., pad=2, top=False, labelbottom=False) 300 | axB1.set_xlim(lam_lim) 301 | axB1.set_xticks(lam_ticks) 302 | 303 | #axB1.tick_params(axis='y', length=2., pad=2, top=False) 304 | axB1.set_ylim(-85,5) 305 | axB1.set_yticks((-80,-60,-40,-20.,0)) 306 | #axB1.set_ylim(-80,2) 307 | #axB1.set_yticks((-70,-50,-30.,-10)) 308 | #axB1.set_ylabel(r"Intensity $I_\Omega~\mathrm{(dB)}$") 309 | 310 | #axB2.tick_params(axis='y', length=2., pad=2, top=False) 311 | axB2.set_ylim(y_lim) 312 | axB2.set_yticks(y_ticks) 313 | #axB2.set_ylabel(r"Coherence $|g_{12}^{(1)}|$") 314 | 315 | axB2.tick_params(axis='x', length=2., pad=2, top=False,labelbottom=False) 316 | axB2.set_xlim(lam_lim) 317 | axB2.set_xticks(lam_ticks) 318 | #axB2.set_xlabel(r"Wavelength $\lambda~\mathrm{(nm)}$", labelpad=1) 319 | 320 | wS = 1.3 321 | w_list = np.linspace(-1,3.,600) 322 | lam_G=1e3*2*np.pi*0.29979/(w_list+w0) 323 | Gam = np.asarray( [Gamma(w, uwz_list, wc, wS) for wc in w_list] ) 324 | #print(Gam) 325 | print(wS, wS-w0, 2*np.pi*0.29979/wS) 326 | #exit() 327 | 328 | lam_G_mask = np.logical_and(lam_G>lam_lim[0],lam_G