<jupyter_start><jupyter_text>Synthesis in programmatic mode  Simple synthesis in a chromosphere For simple calculations, like synthesizing spectral lines in simple models, Hazel v2.0 can be used in programmatic mode. For instance, let us generate a spectral window in the near-infrared and synthesize the He I 10830 A line with some parameters.<jupyter_code>%matplotlib inline
import numpy as np
import matplotlib.pyplot as pl
import hazel
print(hazel.__version__)
label = ['I', 'Q', 'U', 'V']<jupyter_output>1.9.0<jupyter_text>Let's first do a simple experiment in which we synthesize the 10830 A line for a set of parameters. Let's first instantiating a `hazel` model. We set the verbosity to a high level as an example but you should lower it when doing calculations to avoid crowding your terminal:<jupyter_code>mod = hazel.Model(working_mode='synthesis', verbose=3)<jupyter_output><empty_output><jupyter_text>The first thing to do with the model is to add a spectral region for our synthesis.<jupyter_code>mod.add_spectral({'Name': 'spec1', 'Wavelength': [10826, 10833, 150], 'topology': 'ch1',
    'LOS': [0.0,0.0,90.0], 'Boundary condition': [1.0,0.0,0.0,0.0]})<jupyter_output>2018-05-07 12:35:53,388 - Adding spectral region spec1
2018-05-07 12:35:53,391 -   - Using wavelength axis from 10826.0 to 10833.0 with 150 steps
2018-05-07 12:35:53,393 -   - Not mask for pixels
2018-05-07 12:35:53,396 -   - Using LOS [0.0, 0.0, 90.0]
2018-05-07 12:35:53,398 -   - Using boundary condition [0.0, 0.0, 90.0]<jupyter_text>Note that we need to define the angles defining the line-of-sight, the boundary condition, the wavelength range, the name and the topology. We specify in this case that the topology is just a single chromosphere that we label as `ch1`. We need now to define this chromosphere:<jupyter_code>mod.add_chromosphere({'Name': 'ch1', 'Spectral region': 'spec1', 'Height': 3.0, 'Line': '10830', 
                      'Wavelength': [10826, 10833]})<jupyter_output>2018-05-07 12:35:54,348 -     * Adding line : 10830<jupyter_text>Now that we have defined all elements of the synthesis, we finish the setup by invoking the following, which will add all topologies to the spectrum and remove unused atmospheres (if any):<jupyter_code>mod.setup()<jupyter_output>2018-05-07 12:35:55,146 - Adding topologies
2018-05-07 12:35:55,149 -   - ch1
2018-05-07 12:35:55,151 - Removing unused atmospheres
2018-05-07 12:35:55,152 - Number of pixels to read : 1<jupyter_text>It's time now to modify the parameters of the chromosphere and do some plots. You can have access to the wavelength axis and to the synthetic spectrum by accessing the `wavelength_axis`and `stokes` properties of `mod.spectrum[name]`, where `name`is the name given to the spectral region.<jupyter_code>f, ax = pl.subplots(nrows=2, ncols=2, figsize=(10,10))
ax = ax.flatten()
for j in range(10):
    for i in range(4):
        mod.atmospheres['ch1'].set_parameters([50.0*j,0.0,100.0*j,0.2,0.0,8.0,1.0,0.0], 1.0)
        mod.synthesize()
        ax[i].plot(mod.spectrum['spec1'].wavelength_axis - 10830, mod.spectrum['spec1'].stokes[i,:])

for i in range(4):
    ax[i].set_xlabel('Wavelength - 10830[$\AA$]')
    ax[i].set_ylabel('{0}/Ic'.format(label[i]))
    ax[i].set_xlim([-2,2])
    
pl.tight_layout()<jupyter_output>/scratch/miniconda3/envs/py36/lib/python3.6/site-packages/matplotlib/figure.py:2267: UserWarning: This figure includes Axes that are not compatible with tight_layout, so results might be incorrect.
  warnings.warn("This figure includes Axes that are not compatible "<jupyter_text>As another example, let's generate a profile for an off-limb observation. To this end, we just simply select $\theta_\mathrm{obs}=90^\circ$ and set the boundary condition of intensity to zero.<jupyter_code>mod = hazel.Model(working_mode='synthesis', verbose=True)
mod.add_spectral({'Name': 'spec1', 'Wavelength': [10826, 10833, 150], 'topology': 'ch1',
    'LOS': [90.0,0.0,90.0], 'Boundary condition': [0.0,0.0,0.0,0.0]})
mod.add_chromosphere({'Name': 'ch1', 'Spectral region': 'spec1', 'Height': 3.0, 'Line': '10830', 
                      'Wavelength': [10826, 10833]})
mod.setup()

f, ax = pl.subplots(nrows=2, ncols=2, figsize=(10,10))
ax = ax.flatten()
for j in range(10):
    for i in range(4):
        mod.atmospheres['ch1'].set_parameters([50.0*j,0.0,100.0*j,0.2,0.0,8.0,1.0,0.0], 1.0)
        mod.synthesize()
        ax[i].plot(mod.spectrum['spec1'].wavelength_axis - 10830, mod.spectrum['spec1'].stokes[i,:])

for i in range(4):
    ax[i].set_xlabel('Wavelength - 10830[$\AA$]')
    ax[i].set_ylabel('{0}/Ic'.format(label[i]))
    ax[i].set_xlim([-2,2])
    
pl.tight_layout()<jupyter_output>2018-05-07 12:35:08,343 - Adding spectral region spec1
2018-05-07 12:35:08,345 -   - Using wavelength axis from 10826.0 to 10833.0 with 150 steps
2018-05-07 12:35:08,346 -   - Not mask for pixels
2018-05-07 12:35:08,348 -   - Using LOS [90.0, 0.0, 90.0]
2018-05-07 12:35:08,349 -   - Using off-limb normalization (peak intensity)
2018-05-07 12:35:08,351 -   - Using boundary condition [90.0, 0.0, 90.0]
2018-05-07 12:35:08,353 -     * Adding line : 10830
2018-05-07 12:35:08,355 - Adding topologies
2018-05-07 12:35:08,357 -   - ch1
2018-05-07 12:35:08,359 - Removing unused atmospheres
2018-05-07 12:35:08,360 - Number of pixels to read : 1
/scratch/miniconda3/envs/py36/lib/python3.6/site-packages/matplotlib/figure.py:2267: UserWarning: This figure includes Axes that are not compatible with tight_layout, so results might be incorrect.
  warnings.warn("This figure includes Axes that are not compatible "<jupyter_text>Synthesizing with several atmospheres Now that we know how to compute a single atmosphere, let's complicate things a little and add a photosphere below the chromosphere. We define again the spectral region and add a photosphere and a chromosphere. For the photosphere, it's easier to pass a 1D model that will be automatically read and used. If not, then you would need to read the model yourself and change the parameters. The file contents follows:<jupyter_code>%cat photospheres/model_photosphere.1d
mod = hazel.Model(working_mode='synthesis', verbose=True)
mod.add_spectral({'Name': 'spec1', 'Wavelength': [10826, 10833, 150], 'topology': 'ph1->ch1',
    'LOS': [0.0,0.0,90.0], 'Boundary condition': [1.0,0.0,0.0,0.0]})
mod.add_chromosphere({'Name': 'ch1', 'Spectral region': 'spec1', 'Height': 3.0, 'Line': '10830', 
                      'Wavelength': [10826, 10833]})
mod.add_photosphere({'Name': 'ph1', 'Spectral region': 'spec1', 'Spectral lines': [300], 
                      'Wavelength': [10826, 10833], 'Reference atmospheric model': 'model_photosphere.1d'})
mod.setup()<jupyter_output>2018-05-03 12:38:22,043 - Adding spectral region spec1
2018-05-03 12:38:22,045 -   - Using wavelength axis from 10826.0 to 10833.0 with 150 steps
2018-05-03 12:38:22,047 -   - Not mask for pixels
2018-05-03 12:38:22,049 -   - Using LOS [0.0, 0.0, 90.0]
2018-05-03 12:38:22,051 -   - Using boundary condition [0.0, 0.0, 90.0]
2018-05-03 12:38:22,053 -     * Adding line : 10830
2018-05-03 12:38:22,058 -     * Adding line : [300]
2018-05-03 12:38:22,063 -     * Reading 1D model model_photosphere.1d as reference
2018-05-03 12:38:22,073 - Adding topologies
2018-05-03 12:38:22,075 -   - ph1->ch1
2018-05-03 12:38:22,077 - Removing unused atmospheres
2018-05-03 12:38:22,078 - Number of pixels to read : 1<jupyter_text>And then do the plots again by changing the velocity of the chromospheric component.<jupyter_code>f, ax = pl.subplots(nrows=2, ncols=2, figsize=(10,10))
ax = ax.flatten()
for j in range(10):
    for i in range(4):
        mod.atmospheres['ch1'].set_parameters([50.0,0.0,100.0,0.5,-20.0+4*j,8.0,1.0,0.0], 1.0)
        mod.synthesize()
        ax[i].plot(mod.spectrum['spec1'].wavelength_axis, mod.spectrum['spec1'].stokes[i,:])

for i in range(4):
    ax[i].set_xlabel('Wavelength [$\AA$]')
    ax[i].set_ylabel('{0}/Ic'.format(label[i]))
    ax[i].set_xlim([10826,10832])<jupyter_output><empty_output><jupyter_text>Synthesizing with several chromospheres Chromospheres (and atmospheres in general) in Hazel can be combined with filling factors (using `+`) or as stacked atmospheres (using `->`). We provide a few examples of that.  One atmosphere on top of the other Let's stack two chromospheres together with a photosphere below.<jupyter_code>mod = hazel.Model(working_mode='synthesis', verbose=True)
mod.add_spectral({'Name': 'spec1', 'Wavelength': [10826, 10833, 150], 'topology': 'ph1->ch1->ch2',
    'LOS': [0.0,0.0,90.0], 'Boundary condition': [1.0,0.0,0.0,0.0]})
mod.add_chromosphere({'Name': 'ch1', 'Spectral region': 'spec1', 'Height': 3.0, 'Line': '10830', 
                      'Wavelength': [10826, 10833]})
mod.add_chromosphere({'Name': 'ch2', 'Spectral region': 'spec1', 'Height': 3.0, 'Line': '10830', 
                      'Wavelength': [10826, 10833]})
mod.add_photosphere({'Name': 'ph1', 'Spectral region': 'spec1', 'Spectral lines': [300], 
                      'Wavelength': [10826, 10833], 'Reference atmospheric model': 'model_photosphere.1d'})
mod.setup()<jupyter_output>2018-05-03 12:40:40,531 - Adding spectral region spec1
2018-05-03 12:40:40,532 -   - Using wavelength axis from 10826.0 to 10833.0 with 150 steps
2018-05-03 12:40:40,535 -   - Not mask for pixels
2018-05-03 12:40:40,537 -   - Using LOS [0.0, 0.0, 90.0]
2018-05-03 12:40:40,538 -   - Using boundary condition [0.0, 0.0, 90.0]
2018-05-03 12:40:40,540 -     * Adding line : 10830
2018-05-03 12:40:40,542 -     * Adding line : 10830
2018-05-03 12:40:40,544 -     * Adding line : [300]
2018-05-03 12:40:40,547 -     * Reading 1D model model_photosphere.1d as reference
2018-05-03 12:40:40,551 - Adding topologies
2018-05-03 12:40:40,553 -   - ph1->ch1->ch2
2018-05-03 12:40:40,554 - Removing unused atmospheres
2018-05-03 12:40:40,556 - Number of pixels to read : 1<jupyter_text>Now we synthesize the emergent Stokes parameters by changing the velocity of the second component.<jupyter_code>f, ax = pl.subplots(nrows=2, ncols=2, figsize=(10,10))
ax = ax.flatten()
for j in range(9):
#    Bx, By, Bz, tau, v, delta, beta, a
    mod.atmospheres['ch1'].set_parameters([50.0,0.0,100.0,0.3,0.0,8.0,1.0,0.0], 1.0)
    mod.atmospheres['ch2'].set_parameters([50.0,0.0,100.0,0.3,2*j,8.0,1.0,0.0], 1.0)
    mod.synthesize()
    for i in range(4):
        ax[i].plot(mod.spectrum['spec1'].wavelength_axis, mod.spectrum['spec1'].stokes[i,:], color=pl.cm.autumn(25*j))

for i in range(4):
    ax[i].set_xlabel('Wavelength [$\AA$]')
    ax[i].set_ylabel('{0}/Ic'.format(label[i]))
    ax[i].set_xlim([10826,10832])
pl.tight_layout()<jupyter_output><empty_output><jupyter_text>Atmospheres with filling factors And now we combine the atmospheres with a filling factor.<jupyter_code>mod = hazel.Model(working_mode='synthesis', verbose=True)
mod.add_spectral({'Name': 'spec1', 'Wavelength': [10826, 10833, 150], 'topology': 'ph1->ch1+ch2',
    'LOS': [0.0,0.0,90.0], 'Boundary condition': [1.0,0.0,0.0,0.0]})
mod.add_chromosphere({'Name': 'ch1', 'Spectral region': 'spec1', 'Height': 3.0, 'Line': '10830', 
                      'Wavelength': [10826, 10833]})
mod.add_chromosphere({'Name': 'ch2', 'Spectral region': 'spec1', 'Height': 3.0, 'Line': '10830', 
                      'Wavelength': [10826, 10833]})
mod.add_photosphere({'Name': 'ph1', 'Spectral region': 'spec1', 'Spectral lines': [300], 
                      'Wavelength': [10826, 10833], 'Reference atmospheric model': 'model_photosphere.1d'})
mod.setup()<jupyter_output>2018-05-03 12:41:41,841 - Adding spectral region spec1
2018-05-03 12:41:41,844 -   - Using wavelength axis from 10826.0 to 10833.0 with 150 steps
2018-05-03 12:41:41,848 -   - Not mask for pixels
2018-05-03 12:41:41,852 -   - Using LOS [0.0, 0.0, 90.0]
2018-05-03 12:41:41,853 -   - Using boundary condition [0.0, 0.0, 90.0]
2018-05-03 12:41:41,855 -     * Adding line : 10830
2018-05-03 12:41:41,856 -     * Adding line : 10830
2018-05-03 12:41:41,858 -     * Adding line : [300]
2018-05-03 12:41:41,859 -     * Reading 1D model model_photosphere.1d as reference
2018-05-03 12:41:41,863 - Adding topologies
2018-05-03 12:41:41,864 -   - ph1->ch1+ch2
2018-05-03 12:41:41,866 - Removing unused atmospheres
2018-05-03 12:41:41,868 - Number of pixels to read : 1<jupyter_text>Note that filling factors will be combined so that they add up to 1. This way, it is unnecessary to set them by hand to add to 1, it is automatically done by the code. We combine two atmospheres with different velocities and we gradually change the filling factor from 0 to 1.<jupyter_code>f, ax = pl.subplots(nrows=2, ncols=2, figsize=(10,10))
ax = ax.flatten()
for j in range(11):
#    Bx, By, Bz, tau, v, delta, beta, a
    mod.atmospheres['ch1'].set_parameters([50.0,0.0,100.0,1.0,10.0,8.0,1.0,0.0], j/10.0)
    mod.atmospheres['ch2'].set_parameters([50.0,0.0,100.0,1.0,-10.0,8.0,1.0,0.0], 1.0-j/10.0)
    mod.synthesize()
    for i in range(4):
        ax[i].plot(mod.spectrum['spec1'].wavelength_axis, mod.spectrum['spec1'].stokes[i,:], color=pl.cm.autumn(25*j))

for i in range(4):
    ax[i].set_xlabel('Wavelength [$\AA$]')
    ax[i].set_ylabel('{0}/Ic'.format(label[i]))
    ax[i].set_xlim([10826,10832])
pl.tight_layout()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.15776772247360482, 'fraction_numerical': 0.14200603318250377, 'mean_word_length': 4.200392156862745, 'pattern_counts': {'":': 0, '<': 44, '<?xml version=': 0, '>': 53, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '13', 'dir': 'jupyter-structured-clean-dedup', 'id': '487422', 'license': 'MIT', 'n_tokens_mistral': 6141, 'n_tokens_neox': 4904, 'n_words': 1280, 'path': 'docs/notebooks/prog_synthesis.ipynb', 'repo_name': 'fluxtransport/hazel2', 'size': '13260'}