# Notebook from biosustain/p-thermo
Path: notebooks/23. Fixing reversability & cycles I.ipynb

# Introduction
We've seen that in optimizing the model, there is always a lot pyruvate formed, more than should be possible.
So in this notebook, I will investigate the pyruvate node to try to find out where this discrepancy is coming from.

Also, I've seen before that we get a cycle formed from F1P, which should be fixed. I will try to do that here aswell._____no_output_____

import cameo
import pandas as pd
import cobra.io
import escher
from escher import Builder_____no_output_____model = cobra.io.read_sbml_model('../model/p-thermo.xml')_____no_output_____model_e_coli = cameo.load_model ('iML1515')_____no_output_____model_b_sub = cameo.load_model('iYO844')_____no_output_____

__Duplicate metabolite alac__S_c__
Randomly, i spotted the duplicate metabolite alac__S_b_c and alac__S_c. These should be merged and then the faulty one removed._____no_output_____

#found two duplicate reactions
model.remove_reactions(model.reactions.PYRACT)_____no_output_____model.remove_reactions(model.reactions.PYRACTT)_____no_output_____#APLh is the same as ALACPH, so this one should be removed
model.remove_reactions(model.reactions.ALACPH)_____no_output_____model.reactions.DMORh.id = 'KARA1'_____no_output_____model.reactions.DHMBISO.add_metabolites({model.metabolites.alac__S_c:-1, model.metabolites.alac__S_b_c:1})_____no_output_____model.remove_metabolites(model.metabolites.alac__S_b_c)_____no_output_____#save&commit
cobra.io.write_sbml_model(model,'../model/p-thermo.xml')_____no_output_____

__PFL__
In our model PFL is still reversible, which it should not be._____no_output_____

model.reactions.PFL.bounds=(-1000,0)_____no_output_____

__SERD-L__ Should also be irreversible._____no_output_____

model.reactions.SERD_L.bounds = (0,1000)_____no_output_____#save&commit
cobra.io.write_sbml_model(model,'../model/p-thermo.xml')_____no_output_____

## Pyruvate
Here I will check which reactions are irreversible and associated with pyruvate. I will go through the list by hand to modify them to be sure they reflect correct thermodynamic boundaries._____no_output_____

rev_id = []
rev_reaction = []
for rct in model.metabolites.pyr_c.reactions:
    if rct.upper_bound > 0 and rct.lower_bound < 0:
        rev_id.append(rct.id)
        rev_reaction.append(rct.reaction)
    else:
        continue_____no_output_____rev = pd.DataFrame({'ID':rev_id, 'Reaction':rev_reaction})
rev_____no_output_____#this reaction produces CO2. As geobacillus doesn't assimilate CO2, i expect it to be irreversible.
model.reactions.PYRLLOR.bounds = (0,1000)_____no_output_____#this reaction should also be irreversible, as CO2 is produced.
model.reactions.ME1.bounds = (-1000,0)_____no_output_____

the __DAPOP__ reaction is prettry much the same as PYK, but with dATP instead of ATP. The PYK enzyme is known to be promiscuous, and can convert dNTPs as well, but really favors ATP/ADP. The efficiency of conversion is around 5x slower with dATP. (see doi:10.1016/j.enzmictec.2008.06.004) So for that reason, this enzyme will be removed, to prevent flux passing through this node instead of the main PYK activity which is to be expected. _____no_output_____

model.remove_reactions(model.reactions.DAPOP)_____no_output_____#CYSDS should be irreversible, as our strain doesnt assimilate hydrogen
model.reactions.CYSDS.bounds = (0,1000)_____no_output_____model.reactions.APLh.id = 'APL'_____no_output_____model.metabolites.thmpp_c.name = 'Thiamine diphosphate'_____no_output_____model.metabolites.get_by_id('2ahethmpp_c').name = '2-Hydroxyethyl-ThPP'_____no_output_____#in this reaction CO2 is formed, so it is to be expected that this is irreversible
model.reactions.PDHam1hi.bounds = (0,1000)_____no_output_____#save& commit
cobra.io.write_sbml_model(model,'../model/p-thermo.xml')_____no_output_____

## Reversability of CO2 and O2 reactions
The previous work got me thinking, that reactions production CO2 and consuming O2 should be irreversible too. So here I will look into that too._____no_output_____

model = cobra.io.read_sbml_model('../model/p-thermo.xml')_____no_output_____rev_co2_id = []
rev_co2_reaction = []
for rct in model.metabolites.co2_c.reactions:
    if rct.upper_bound > 0 and rct.lower_bound < 0:
        rev_co2_id.append(rct.id)
        rev_co2_reaction.append(rct.reaction)
    else:
        continue_____no_output_____rev_co2 = pd.DataFrame({'ID':rev_co2_id, 'Reaction':rev_co2_reaction})
rev_co2_____no_output_____model.reactions.PPNDH.bounds = (-1000,0)_____no_output_____

3OAR40_1 seems to be a wrong reaction. If you search the KEGG ID and information fit to it, you get another reaction. So I will fix the kegg annotations here, and change the name to prevent further confusion.
Again, as here CO2 is produced, I will restrict this reaction to make it irreversible._____no_output_____

model.reactions.get_by_id('3OAR40_1').notes ={}_____no_output_____model.reactions.get_by_id('3OAR40_1').name = 'R10707'_____no_output_____model.reactions.get_by_id('3OAR40_1').id = 'AMACT'_____no_output_____model.reactions.AMACT.notes['ENZYME'] = 'E.C.2.3.1.180'
model.reactions.AMACT.notes['KEGG'] = '10707'
model.reactions.AMACT.notes['NAME'] = '3-ketoacyl-acyl carrier protein synthase III'
model.reactions.AMACT.notes['DEFINITION'] = 'Acetyl-CoA + Malonyl-[acyl-carrier protein] <=> Acetoacetyl-[acp] + CoA + CO2'_____no_output_____model.reactions.AMACT.bounds = (0,1000)_____no_output_____#KAS14
model.reactions.KAS14.bounds = (0,1000)_____no_output_____model.reactions.MMSAD3.bounds = (0,1000)_____no_output_____model.metabolites.get_by_id('3opalmACP_c').id = '3oxhdacp'_____no_output_____#again here we produce CO2, so should be irreversible. Also is seems to be a condensation so would make sense to expel CO2.
model.reactions.MMACPAT.bounds = (0,1000)_____no_output_____model.metabolites.sucsal_c.name = 'Succinate semialdehyde'_____no_output_____#likely irreversible
model.reactions.OXGDC.bounds = (0,1000)_____no_output_____model.reactions.PPND.bounds = (0,1000)_____no_output_____model.reactions.MALACPAT.bounds = (0,1000)_____no_output_____model.reactions.OOR3r.bounds = (0,1000)_____no_output_____model.reactions.DECACPAT.bountds = (0,1000)_____no_output_____model.reactions.OCTACPAT.bounds = (0,1000)_____no_output_____model.reactions.MMSAD1.bounds = (0,1000)_____no_output_____model.reactions.HEXACPAT.bounds = (0,1000)_____no_output_____model.reactions.CPPPGO2.bounds = (-1000,0)_____no_output_____model.reactions.IGPS.bounds = (0,1000)_____no_output_____model.reactions.UPPDC1.bounds = (-1000,0)_____no_output_____model.reactions.BUTACPAT.bounds = (0,1000)_____no_output_____model.reactions.MAHMPDC.bounds = (0,1000)_____no_output_____#based on thermodynamics
model.reactions.OAACOLY.bounds = (0,1000)_____no_output_____#based on thermodynamics
model.reactions.AKGDEHY.bounds = (0,1000)_____no_output_____model.reactions.HDEACPT.bounds = (0,1000)_____no_output_____#save& commit
cobra.io.write_sbml_model(model,'../model/p-thermo.xml')Error encountered trying to <Setting notes on sbase: <Reaction R_AMACT "R10707">>.
LibSBML error code -3: The requested action could not be performed. This can occur in a variety of contexts, such as passing a null object as a parameter in a situation where it does not make sense to permit a null object.

### Reactions involving oxygen
Similar to the motivation about CO2, here I will investigate which reactions use oxygen and which can produce oxygen, as the latter is unrealistic to expect in many cases._____no_output_____

rev_o2_id = []
rev_o2_reaction = []
for rct in model.metabolites.o2_c.reactions:
    if rct.upper_bound > 0 and rct.lower_bound < 0:
        rev_o2_id.append(rct.id)
        rev_o2_reaction.append(rct.reaction)
    else:
        continue_____no_output_____rev_o2 = pd.DataFrame({'ID':rev_o2_id, 'Reaction':rev_o2_reaction})
rev_o2_____no_output_____model.metabolites.o2_c.summary()_____no_output_____#should be reversible, but kills all biomass.
#model.reactions.GLYO1.bounds = (0,1000)_____no_output_____

Seems the DHORDfum reaction is wrong. It should contain fumarate instead of oxygen. I will change this and make it irreversible as it should be.
Further inspection: the original EC1.3.3.1 reaction no longer exisists in databases, it has  been elucidated to be coupled to succinate and fumarate instead. I.e. EC1.3.98.1_____no_output_____

model.reactions.DHORDfum.add_metabolites({model.metabolites.o2_c:1, model.metabolites.h2o2_c:-1, model.metabolites.fum_c: -1, model.metabolites.succ_c:1})_____no_output_____#this reaction should be irreversible but kills biomass
#model.reactions.DHORDfum.bounds = (0,1000)_____no_output_____model.reactions.MOX.bounds = (0,1000)_____no_output_____model.metabolites.no_c.name = 'Nitric oxide'_____no_output_____model.reactions.NODOy.bounds = (0,1000)_____no_output_____model.reactions.PPPGO_1.bounds = (0,1000)_____no_output_____model.reactions.AMACT.annotation = {}_____no_output_____model.reactions.AMACT.annotation['kegg.reaction'] = 'R10707'
model.reactions.AMACT.annotation ['sbo'] = 'SBO:0000176'_____no_output_____model.reactions.AMACT.notes ={}_____no_output_____model.reactions.AMACT.notes['ENZYME'] = 'E.C.2.3.1.180'
model.reactions.AMACT.notes['KEGG ID'] = 'R10707'
model.reactions.AMACT.notes['NAME'] = '3-ketoacyl-acyl carrier protein synthase III'
model.reactions.AMACT.notes['DEFINITION'] = 'Acetyl-CoA + Malonyl-[acyl-carrier protein] <=> Acetoacetyl-[acp] + CoA + CO2'_____no_output_____#save & commit
cobra.io.write_sbml_model(model,'../model/p-thermo.xml')Error encountered trying to <Setting notes on sbase: <Reaction R_AMACT "R10707">>.
LibSBML error code -3: The requested action could not be performed. This can occur in a variety of contexts, such as passing a null object as a parameter in a situation where it does not make sense to permit a null object.
model.optimize()_____no_output_____

### Propanoate cycle
When looking into the amp biosynthesis, I ran into a cycle that just dissipates ATP and produced amp. This ivolves propanoate and looks as follows: prpnte_c --> ppcoa_c --> ppap_c --> prpnte.
Here I need to find a way to fix that.

After looking into this issue, it seems to come from the reaction PRPNTELIG	, converting propanoate into propanoyl-coa, using ATP to do so. It was added into the model due to the automatic annotation of the gene to E.C. 6.2.1.13. I think this is a wrong annotation. Looking into the genome I cannot find this enzyme (which forms adp) but i can find the EC 6.2.2.1 reaction, which is amp forming and reflects the PRPNTELIG reaction.

The prefered substrate of this reaction is acetate, not propanoate. In some distant organisms it has been shown to be able to function on propanoate, but this has not bee shown for B. subtilis, and so I think it makes sense to exclude this reaction from the model. This strain is not known to grow on or produce large amounts of propanoate, so even if this may be present it will ikely carry very little flux, not as is happening in the model now.

This is a knowledge gap, and so we have to make the best decision we can with available information. _____no_output_____

model = cobra.io.read_sbml_model('../model/p-thermo.xml')_____no_output_____#saw incorrectly named reaction that should also be irreversible.
model.reactions.PCPPTh.id = 'PTA2'_____no_output_____model.reactions.PTA2.bounds = (0,1000)_____no_output_____model.metabolites.ppap_c.name = 'Propanoyl phosphate'_____no_output_____#should this reaction be in the model? I will remove it
model.remove_reactions(model.reactions.PRPNTELIG)C:\Users\vivmol\AppData\Local\Continuum\anaconda3\envs\g-thermo\lib\site-packages\cobra\core\model.py:716: UserWarning:

need to pass in a list

C:\Users\vivmol\AppData\Local\Continuum\anaconda3\envs\g-thermo\lib\site-packages\cobra\core\group.py:110: UserWarning:

need to pass in a list

#check the EC.6.2.2.1 is there for acetate conversion: it is.
# model.reactions.ACS_____no_output_____#save& commit
cobra.io.write_sbml_model(model,'../model/p-thermo.xml')_____no_output_____

### Acetyl adenylate
acetyl adenylate (aad_c) is an intermediate in the formation of acetyl-coa. It seems there is also a cycle going on here.
- accoa + amp <--> aad + coa (rct AADCOAT)
- aad + ppi <--> ac + atp (rct ATPACAT)
so net reaction is accoa + amp + ppi <--> ac + atp + coa.

At the same time the model also has the ACS rection (also E.C. 6.2.1.1):
ac_c + atp_c + coa_c --> accoa_c + amp_c + ppi_c
which we know should be irreversible. So with this combination you can see a cycle starts to arise.

To solve that, we need to define the reversability of the first two reactions, or even remove them completely. acetyl adenylate  is a metabolite not often included, and doesn't connect anywhere else into the model. So for simplicities sake (and keep it more bigg compliant), i will remove the two reactions and the aad_c metabolite.

You can observe that doing this really decreases the biomass accumulation to 12/h, which is a good sign._____no_output_____

model.remove_reactions(model.reactions.AADCOAT)C:\Users\vivmol\AppData\Local\Continuum\anaconda3\envs\g-thermo\lib\site-packages\cobra\core\model.py:716: UserWarning:

need to pass in a list

C:\Users\vivmol\AppData\Local\Continuum\anaconda3\envs\g-thermo\lib\site-packages\cobra\core\group.py:110: UserWarning:

need to pass in a list

model.remove_reactions(model.reactions.ATPACAT)C:\Users\vivmol\AppData\Local\Continuum\anaconda3\envs\g-thermo\lib\site-packages\cobra\core\model.py:716: UserWarning:

need to pass in a list

C:\Users\vivmol\AppData\Local\Continuum\anaconda3\envs\g-thermo\lib\site-packages\cobra\core\group.py:110: UserWarning:

need to pass in a list

model.remove_metabolites(model.metabolites.aad_c)_____no_output_____#save & commit
cobra.io.write_sbml_model(model,'../model/p-thermo.xml')_____no_output_____

### F1P cylce (issue #34)

It seems that this may come from the ridiculous amounts of G3P that are somehow made in the PPP.
It seems we have a lot of r5p_c, coming from r1p_c. the r1p_c comes from two reactions: adn_c and gsn_c. These in turn are made from amp and gmp respectively. So the problem is that we have so many of these in the model that influences PPP and glycolysis.
__So there is some fundamental problem with the nucleotides that causes these fluxes. This maybe ties into the RNA/DNA node problem too..__

Also, this has highlighted to me the problem with thiamin: this is imported and converted into thmpp_c and then the majority further into thmtp_c and exported... This just consumes some atp and ends up forming huge amounts of amp. why does the model do this??
A little bit of the thmpp_c is used for converting adhlam to alac__S_b_c, but also at higher levels than it should._____no_output_____

model.metabolites.get_by_id('2ahethmpp_c').summary()_____no_output_____model.metabolites.thmpp_c.summary()_____no_output_____model.optimize()_____no_output_____


# Notebook from longgangfan/underworld2
Path: docs/user_guide/01_GettingStarted.ipynb

# Getting Started

## Welcome to using Underworld!

[Underworld](http://www.underworldcode.org) is a Python library for the development of long time scale earth process models. The Underworld Python interface is designed to facilitate interactive and intuitive model development. To this end, we embrace Jupyter Notebooks as the preferred development environment, although the standard Python interpreter is the only requirement. Underworld utilises MPI parallelisation to allow large simulation across HPC facilities. The Python interface was partly funded by the NeCTAR [eResearch_tools](http://www.nectar.org.au/eresearch-tools) program.

Underworld includes the `visualisation` submodule for interactive visualisation within the Jupter Notebook environment, and for seamless visualisation capabilities across parallel simulations. The [LavaVu](https://github.com/OKaluza/LavaVu) Python package is leveraged for rendering capabilities.

## Resources

There are numerous resources that you might find useful for learning and using Underworld:

1. [underworld2.readthedocs.io](http://underworld2.readthedocs.io): The page where most of our primary documentation is published, including this user guide, and the API documentation. It also links out to most other resources.
1. [github.com/underworldcode/underworld2](https://github.com/underworldcode/underworld2): Our code repository. You can keep track of changes to the codes base here, and you can also browse most of our documention directly within the Github interface. Don't forget to `Star` and `Watch` our project if you find it useful!
1. [github.com/underworldcode/underworld2/issues](https://github.com/underworldcode/underworld2/issues): Please use our issue tracker to report any bugs or difficulties you encounter. This includes any general usage questions as well as technial issues. If you wish to submit a suspected bug, please include a **minimal** example which allows us to reproduce the issue. It is also the place to post any feature requests you may have!
1. **The User Guide**: A more focused look at the various aspects of Underworld modelling. Note that each section is a self container Jupyter Notebook document, available in the Underworld repository (`docs/user_guide`). It is also published at the Underworld ReadTheDocs page.
1. **Examples**: These notebooks go through the entire Underworld workflow for constructing and solving geophysics models. These models demonstrate Underworld current best usage practises, and are guaranteed to operate correctly for each Underworld release. They are available in the repository at `docs/examples`.
1. **API Documentation**: The Underworld API documentation is published at our ReadTheDocs page. Note that the API documentation is embedded in the Python implementation as *docstrings*, and is therefore also available directy via the Python `help()` *built-in*. More usefully, this information is accessible within Jupyter Notebooks via the *tooltips* shortcut `Shift`-`Tab` (when in edit mode).
1. [Underworld Models Library](https://github.com/underworldcode/model_library): A repository of Underworld models. The library includes models which reproduce publication results, tutorials, examples and usage tidbits. Note that these models are not explicitly maintained, and so may not operate against the latest version of Underworld. If you scroll to the end of each model, it should state which version of Underworld the repository model was successfully ran against.

## Required Python Skills

To use Underworld successfully, you will need to have an understanding of the following Python constructs:

1. Basic Python, such as importing modules, and syntax structure (indenting, functions, etc).
1. Containers such as dictionaries, lists and tuples.
1. Flow control (loops, if-else conditionals, etc).
1. Python objects, object methods, object attributes, object lifecycles.

Most beginner (or intermediate) Python tutorials should cover these concepts. Also useful, though not strictly necessary, is some familiarity with the following:

1. Exception handling (for dealing with errors that might occur).
1. Context managers (for mesh and swarm deformations).
1. Operator overloading.

Note that Underworld heavily leverages the `numpy` Python numerical library for all heavy data access and manipulation. All Underworld objects that record heavy data will expose their data via the `data` attribute, which is actually a handle to a `numpy` array. As such, familiary with numpy usage paradigms is a must, and more advanced usage patterns (array slicing, advanced indexing, etc) will become important as your models increase in complexity.

Similarly, Underworld uses `h5py` for all heavy data disk IO. H5py is a Python library which provides a Python interface to writing/reading `HDF5` format files. While not strictly required, more advanced users will certainly find having some familiarity with the `h5py` libary useful, both for directly querying files Underworld has generated, and also for writing their own files (in preference to CSV for example).

## Jupyter Notebooks

Jupyter Notebooks is the recommended environment for most model development. In Underworld we utilise notebooks to provide inline visualisation of your model configurations, allowing you to quickly see your results, modify as required, and then regenerate and repeat. Equally important is the *tooltips* and *autocomplete* functionality provided within the notebooks. To access tooltips, use `shift`-`tab` while you have the text editing cursor located within an Underworld object (or you can write a question mark after the object, and execute the cell). For autocomplete, after you type a few letters you can press `tab` to be provided with all possible completion options. Using these tools is essential to rapid and frustration free model development, especially for new users.

If you are new to Jupyter Notebooks, you should familiarise yourself with the notebook environment first. Also, remember the **Help** menu bar option provides useful references and keyboard shortcuts.

### Jupyter Authentication

Jupyter is, by design, a web service providing mechanisms for the execution of arbitrary code, such as your Underworld models (or other Python scripts). However, as a web service, security measures are required to preclude external parties from accessing your Jupyter instances (and thereby potentially executing malicious code). Jupyter therefore requires you to provide an authentication Token upon first accessing the service via your web browser. This token is generated when you first start Jupyter from the command line:

![](Figures/jupyter_token.png)

Simply copy/paste the generated token and enter it manually within your browser (once you have browsed to the Jupyter instance url, often http://127.0.0.1:8888).

For those using the Kitematic GUI to launch our Docker image, Jupyter will be launched automatically, and the token may be found within the **CONTAINER LOGS** dialog:

![](Figures/kitematic_token.png)

## How to get help

If you encounter issues or suspect a bug, please create a ticket using the [issue tracker on github](https://github.com/underworldcode/underworld2/issues).

_____no_output_____A quick demo
-----

Let's do a quick run through of setting up some basic Underworld objects._____no_output_____

<code>
# Import underworld
import underworld as uw
# Create a mesh:
mesh = uw.mesh.FeMesh_Cartesian( elementRes  = (8, 8),
                                 minCoord    = (0., 0.),
                                 maxCoord    = (2., 1.))

# Next we create a mesh variable:
temperatureField = mesh.add_variable( nodeDofCount=1 )

# Let's initialise the variable with some data:
for index, coord in enumerate(mesh.data):
    temperatureField.data[index] = coord[1]  # set the temperature to be the vertical (y) coordinate

# Finally we will render the temperature field.
import underworld.visualisation as vis
fig = vis.Figure(figsize=(800,400))
fig.append( vis.objects.Surface(mesh, temperatureField, colours="blue white red") )
fig.append( vis.objects.Mesh(mesh) )
fig.show()_____no_output_____
</code>

Typically we might then setup boundary conditions, particle swarms, rheology and systems to be solved.

All of these topics are discussed in the following sections of the user guide._____no_output_____


# Notebook from maxwellmb/pynrc
Path: notebooks/GTO/NRC_GTO_YSO_Imaging(old).ipynb

# Makes print and division act like Python 3
from __future__ import print_function, division

# Import the usual libraries
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.patches as patches

# Enable inline plotting at lower left
%matplotlib inline

from IPython.display import display, Latex, clear_output
from matplotlib.backends.backend_pdf import PdfPages_____no_output_____import pynrc
from pynrc import nrc_utils
from pynrc.nrc_utils import S
from pynrc.obs_nircam import model_to_hdulist, obs_coronagraphy
from pynrc.obs_nircam import plot_contrasts, planet_mags, plot_planet_patches

from pynrc.speckle_noise import offset_bar
pynrc.setup_logging('WARNING', verbose=False)

from astropy.io import (fits, ascii)_____no_output_____

# Observation Definitions

Functions to create at optimize a series of observation objects stored as a dictionary._____no_output_____

def make_key(filter, pupil=None, mask=None):
    """Create identification key (string) based on filter, pupil, and mask"""
    mask_key = 'none' if mask is None else mask
    pupil_key = 'none' if pupil is None else pupil
    key = '{}_{}_{}'.format(filter,mask_key,pupil_key)
    return key_____no_output_____def obs_wfe(wfe_ref_drift, filt_list, dist, sp_ref=None, args_disk=None, fov_pix=None, verbose=False):
    """
    For a given WFE drift and series of filters, create a list of
    NIRCam observations.
    """

    if sp_ref is None:
        sp_ref = sp_sci

    fov_pix_orig = fov_pix

    obs_dict = {}
    for filt, mask, pupil in filt_list:
        if verbose: print(filt, mask, pupil)

        # Disk Model
        if args_disk is not None:
            # Convert to photons/sec in specified filter
            hdu_disk = model_to_hdulist(args_disk, sp_sci, filt, pupil=pupil, mask=mask)
        else:
            hdu_disk = None

        # Create identification keys
        key = make_key(filt, mask=mask, pupil=pupil)

        # Define the subarray readout size
        # Set the PSF size and oversampling amount
        if mask is None:
            subsize = 400
        elif ('MASK210R' in mask) or ('MASKSWB' in mask):
            subsize = 640
        else:
            subsize = 320
        fov_pix = subsize if fov_pix is None else fov_pix

        # Offset for bar mask
        if (mask is not None) and ('WB' in mask):
            offset_r, offset_theta = offset_bar(filt, mask)
        else:
            offset_r, offset_theta = (None, None)

        # Other coronagraph vs direct imaging settings
        if mask is None:
            module = 'B'
            oversample = 4
        else:
            module = 'A'
            oversample = 2

        # Initialize and store the observation
        # A reference obseration is stored inside each parent obs_coronagraphy class.
        obs_dict[key] = obs_coronagraphy(sp_sci, sp_ref, dist, module=module, disk_hdu=hdu_disk,
                                         wfe_ref_drift=wfe_ref_drift, filter=filt, mask=mask, pupil=pupil,
                                         wind_mode='WINDOW', xpix=subsize, ypix=subsize,
                                         offset_r=offset_r, offset_theta=offset_theta,
                                         oversample=oversample, fov_pix=fov_pix, verbose=verbose)
        fov_pix = fov_pix_orig
    return obs_dict_____no_output_____

## Functions to init, optimize, and plot_____no_output_____

# Generate initial observations for each filter(no WFE drift)
def do_init(args_disk=None, fov_pix=None, verbose=True):
    wfe_ref_drift = 0
    obs_dict = obs_wfe(wfe_ref_drift, args_list, dist_sci, sp_ref=sp_ref,
                       args_disk=args_disk, fov_pix=fov_pix, verbose=verbose)
    return obs_dict_____no_output_____# For each filter setting, generate a series of contrast curves at different WFE values
def do_contrast(wfe_list, filt_keys, nsig=5, roll_angle=None, **kwargs):
    """
    kwargs to pass to calc_contrast() and their defaults:

    exclude_disk = True
    exclude_planets = True
    exclude_noise = False
    opt_diff = True
    """
    contrast_all = {}
    for i, key in enumerate(filt_keys):
        print(key)
        obs = obs_dict[key]

        filt, mask, pupil = args_list[i]
        if roll_angle is None:
            roll_angle = 0 if mask is None else 10

        # Stores tuple of (Radial Distances, Contrast, and Sensitivity) for each WFE drift
        curves = []
        for wfe_ref_drift in wfe_list:
            obs.wfe_ref_drift = wfe_ref_drift
            result = obs.calc_contrast(roll_angle=roll_angle, nsig=nsig, **kwargs)
            curves.append(result)

        contrast_all[key] = curves
    return contrast_all_____no_output_____def do_plot_contrast(obs, curves, wfe_list, nsig, age, xlim=[0,10], ylim=[24,8], save_fig=False):

    fig, axes = plt.subplots(1,2, figsize=(13,4.5))
    entropy_vals = [13,8]

    for j, ax in enumerate(axes.flatten()):
        ax.set_xlim(xlim)
        ax.set_ylim(ylim)
        plot_contrasts(curves, wfe_list, ax=ax)
        plot_planet_patches(ax, obs, age=age, entropy=entropy_vals[j])

    for ax in axes.flatten():
        ax.set_xlabel('Distance (arcsec)')
        ax.set_ylabel('{}-sigma Sensitivities (mag)'.format(nsig))
        ax.set_xlim(xlim)
        ax.set_ylim(ylim)
        ax.legend(ncol=2)

    fig.tight_layout()

    dist = obs.distance
    age_str = 'Age = {:.0f} Myr'.format(age)
    dist_str = 'Distance = {:.1f} pc'.format(dist) if dist is not None else ''

    fig.suptitle('{} ({}, {})'.format(name_sci,age_str,dist_str), fontsize=16);
    #fig.subplots_adjust(top=0.85)
    fig.subplots_adjust(wspace=0.1, hspace=0.1, top=0.85, bottom=0.1 , left=0.05, right=0.97)

    fname = "{}_contrast.pdf".format(name_sci.replace(" ", ""))
    if save_fig:
        fig.savefig(outdir+fname)_____no_output_____def do_gen_hdus(obs_dict, wfe_ref_drift, verbose=False, **kwargs):

    """
    kwargs to pass to gen_roll_image() and their defaults:

    PA1 = 0
    PA2 = 10
    zfact         = None
    oversample    = None
    exclude_disk  = False
    exclude_noise = False
    opt_diff      = True
    """

    hdulist_dict = {}
    for key in filt_keys:
        if verbose: print(key)
        obs = obs_dict[key]
        obs.wfe_ref_drift = wfe_ref_drift
        hdulist = obs.gen_roll_image(**kwargs)

        hdulist_dict[key] = hdulist

    return hdulist_dict_____no_output_____

## Science spectral model_____no_output_____

# Final science spectrum is the stellar spectrum tagged at V-Band
# with a modified blackbody added on top
def bb_jy(wave, T):
    """
    For a given set of wavelengths and a Temperature, return
    the blackbody function in units of Jy.
    """

    # Physical Constants
    H  = 6.62620000E-27  # Planck's constant in cgs units
    HS = 6.62620000E-34  # Planck's constant in standard units
    C  = 2.99792458E+08  # speed of light in standard units
    K  = 1.38064852E-23  # Boltzmann constant in standard units

    # Blackbody coefficients (SI units)
    C1 = 2.0 * HS * C    # Power * unit area / steradian
    C2 = HS * C / K

    w_m = wave * 1e-6

    exponent = C2 / (w_m * T)
    expfactor = np.exp(exponent)

    return 1.0E+26 * C1 * (w_m**-3.0) / (expfactor - 1.0)

def func_model(x, sp):
    bb_flux = x[0] * bb_jy(sp.wave/1e4, x[1]) * (sp.wave/1e4)**x[2] / 1e17
    sp_bb = S.ArraySpectrum(sp.wave, bb_flux, fluxunits='Jy')
    sp_bb.convert('Flam')

    f1 = sp.flux
    f2 = sp_bb.flux

    ftot = f1 + f2

    sp_res = S.ArraySpectrum(sp.wave, ftot, fluxunits='Flam')

    return sp_res

def func_resid(x, sp_phot, sp_star):
    sp_model = func_model(x,sp_star)

    wvals = sp_phot.wave
    ind = (wvals < 30e4)

    wvals = wvals[ind]
    yvals = sp_phot.flux[ind]

    mod_interp = np.interp(wvals, sp_star.wave, sp_model.flux)
    return 1e15*(mod_interp - yvals)

_____no_output_____from scipy.optimize import least_squares
def gen_sp_sci(i, robust=False, return_ax=False, plot=True):
    name_sci, dist_sci, age_sci, spt_sci, vmag_sci, kmag_sci, w1_sci, w2_sci, vot = args_sources[i]

    # Import source SED from VOTable
    from astropy.io.votable import parse, parse_single_table
    table = parse_single_table(vot)
    freq = table.array["sed_freq"] * 1e9 # Hz
    isort = np.argsort(1/freq)

    # Sort flux monotomically with wavelength
    freq = freq[isort]
    flux = table.array["sed_flux"][isort]
    eflux = table.array["sed_eflux"][isort]

    # Average duplicate data points
    ufreq, ucnt = np.unique(freq, return_counts=True)
    ufreq = ufreq[::-1]
    ucnt = ucnt[::-1]

    uflux = []
    for i, f in enumerate(ufreq):
        ind = (freq==f)
        flx = np.median(flux[ind]) if ucnt[i]>1 else flux[ind]
        uflux.append(flx)
    uflux = np.array(uflux)

    # Photometric data points
    sp_phot = S.ArraySpectrum(ufreq, uflux, waveunits='Hz', fluxunits='Jy')
    sp_phot.convert('Angstrom')
    sp_phot.convert('Flam')

    # Stellar spectrum normalized at V-Band
    sp_star = pynrc.stellar_spectrum(spt_sci, vmag_sci, 'vegamag', bp_v)

    x0 = [1, 2000, 0]
    loss = 'soft_l1' if robust else 'linear'
    res = least_squares(func_resid, x0, args=(sp_phot, sp_star), bounds=(0,np.inf),
                        loss=loss)
    out = res.x
    print(out)

    sp_sci = func_model(out, sp_star)
    sp_sci.name = name_sci

    if plot:
        fig, ax = plt.subplots(1,1, figsize=(8,5))
        ax.loglog(sp_star.wave/1e4, sp_star.flux, lw=1, label='Photosphere')
        ax.loglog(sp_sci.wave/1e4, sp_sci.flux, lw=2, label='Model Fit')
        ax.loglog(sp_phot.wave/1e4, sp_phot.flux, marker='o', ls='none', label='Photometry')
        ax.set_xlabel('Wavelength (microns)')
        ax.set_ylabel('Flux ({})'.format(sp_sci.fluxunits))
        ax.set_title(name_sci)
        fig.tight_layout()

        if return_ax:
            return (sp_sci, (fig,ax))
        else:
            return sp_sci
    else:
        return sp_sci
_____no_output_____

## Define Source and their Reference Counterparts_____no_output_____

#                source,      dist, age, sptype, vmag kmag  W1   W2
args_sources = [('SAO 206462', 140,  10, 'F8V',  8.7, 5.8, 5.0, 4.0, 'YSOs/SAO206462.vot'),
                ('TW Hya',      54,  10, 'M0V', 11.0, 7.3, 7.0, 6.9, 'YSOs/TWHya.vot'),
                ('MWC 758',    150,   5, 'A5V',  8.3, 5.7, 4.6, 3.5, 'YSOs/MWC758.vot'), # Lazareff et al. (2016)
                ('HL Tau',     140,   1, 'K5V', 15.1, 7.4, 5.2, 3.3, 'YSOs/HLTau.vot')]

# Corresponding reference stars
#ref_sources =  [('GJ 588', 'M2V', 4.6),
#                ('GJ 588', 'M2V', 4.6),
#                ('HR 1889',  'F5III', 5.4),
#                ('HR 1889',  'F5III', 5.4)]

ref_sources =  [('HD 94771', 'G4V', 5.6),
                ('HD 94771', 'G4V', 5.6),
                ('HR 1889',  'F5III', 5.4),
                ('HR 1889',  'F5III', 5.4)]

outdir = 'YSOs/'_____no_output_____# Various Bandpasses
bp_v = S.ObsBandpass('v')
bp_k = pynrc.bp_2mass('k')
bp_w1 = pynrc.bp_wise('w1')
bp_w2 = pynrc.bp_wise('w2')

# List of filters
args_list =  [('F187N', None, None),
              ('F200W', None, None),
              ('F356W', None, None),
              ('F444W', None, None)]

#args_list =  [('F300M', None, None),
#              ('F356W', None, None),
#              ('F356W', 'MASK430R', 'CIRCLYOT'),
#              ('F430M', None, None),
#              ('F444W', None, None),
#              ('F444W', 'MASK430R', 'CIRCLYOT')]

filt_keys = []
for (filt,mask,pupil) in args_list:
    filt_keys.append(make_key(filt, mask=mask, pupil=pupil)) _____no_output_____

## 1. SAO 206462_____no_output_____

i = 0

name_sci, dist_sci, age_sci, spt_sci, vmag_sci, kmag_sci, w1_sci, w2_sci, vot = args_sources[i]
name_ref, spt_ref, kmag_ref = ref_sources[i]

# Science target and reference star spectra
sp_ref = pynrc.stellar_spectrum(spt_ref, kmag_ref, 'vegamag', bp_k)
sp_ref.name = name_ref

robust = True if i>=2 else False
sp_sci, (fig,ax) = gen_sp_sci(i, robust=robust, return_ax=True)

ax.plot(sp_ref.wave/1e4, sp_ref.flux, lw=1, label='PSF Reference')
ax.legend()
ax.set_xlim([0.4,10])
ax.set_ylim([5e-15,1e-11])

fname = "{}_spectra.pdf".format(name_sci.replace(" ", ""))
fig.savefig('YSOs/'+fname)

# Disk model information
# File name, arcsec/pix, dist (pc), wavelength (um), flux units
args_disk = ('example_disk.fits', 0.007, 140.0, 1.6, 'mJy/arcsec^2')[  1.20751698e+00   1.91598941e+03   5.34940819e-01]
obs_dict = do_init(args_disk=args_disk, fov_pix=401, verbose=False)_____no_output_____# Update detector readout
for key in filt_keys:
    obs = obs_dict[key]

    if 'none' in key:
        pattern, ng, nint_sci, nint_ref = ('RAPID',5,160,160)
    elif ('MASK210R' in key) or ('MASKSWB' in key):
        pattern, ng, nint_sci, nint_ref = ('BRIGHT2',10,20,20)
    else:
        pattern, ng, nint_sci, nint_ref = ('MEDIUM8',10,15,15)

    obs.update_detectors(read_mode=pattern, ngroup=ng, nint=nint_sci)
    obs.nrc_ref.update_detectors(read_mode=pattern, ngroup=ng, nint=nint_ref)

    #print(key)
    #print(obs.multiaccum_times)
    #_ = obs.sensitivity(nsig=5, units='vegamag', verbose=True)
    #print('')_____no_output_____

### Saturation Regions_____no_output_____

dmax = []
for k in filt_keys:
    print(k)
    obs = obs_dict[k]
    im_sat = obs.saturation_levels(ngroup=0)

    dist = nrc_utils.dist_image(im_sat, pixscale=obs.pix_scale)
    dmax.append(dist[im_sat>0.8].max())F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none

### Photon Limit Curves_____no_output_____

nsig = 5

for k in filt_keys:
    obs_dict[k].sp_ref = sp_sci

wfe_list = [0]

curves_photon = do_contrast(wfe_list, filt_keys, nsig=nsig, opt_diff=True)
F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none

### Reference Reconstruction Curves_____no_output_____

nsig = 5

for k in filt_keys:
    obs_dict[k].sp_ref = sp_sci

wfe_list = [10]
curves_recon10 = do_contrast(wfe_list, filt_keys, nsig=nsig, opt_diff=True)

wfe_list = [5]
curves_recon5 = do_contrast(wfe_list, filt_keys, nsig=nsig, opt_diff=True)

wfe_list = [2]
curves_recon2 = do_contrast(wfe_list, filt_keys, nsig=nsig, opt_diff=True)F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none
F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none
F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none

### Basic PSF Subtraction Curves_____no_output_____

nsig = 5

for k in filt_keys:
    obs_dict[k].sp_ref = sp_ref

wfe_list = [5]

curves_basic = do_contrast(wfe_list, filt_keys, nsig=nsig, opt_diff=True)F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none

### Roll Subtraction_____no_output_____

# Update detector readout
for key in filt_keys:
    obs = obs_dict[key]

    if 'none' in key:
        pattern, ng, nint_sci, nint_ref = ('RAPID',5,135,135)
    elif ('MASK210R' in key) or ('MASKSWB' in key):
        pattern, ng, nint_sci, nint_ref = ('BRIGHT2',10,20,20)
    else:
        pattern, ng, nint_sci, nint_ref = ('MEDIUM8',10,15,15)

    obs.update_detectors(read_mode=pattern, ngroup=ng, nint=nint_sci)
    obs.nrc_ref.update_detectors(read_mode=pattern, ngroup=ng, nint=nint_ref)

    #print(key)
    #print(obs.multiaccum_times)
    #_ = obs.sensitivity(nsig=5, units='vegamag', verbose=True)
    #print('')_____no_output_____nsig = 5

for k in filt_keys:
    obs_dict[k].sp_ref = sp_sci

wfe_list = [0]

curves_photon2 = do_contrast(wfe_list, filt_keys, nsig=nsig, no_ref=True, roll_angle=10)F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none
nsig = 5

for k in filt_keys:
    obs_dict[k].sp_ref = sp_sci

wfe_list = [10]
curves_noref10 = do_contrast(wfe_list, filt_keys, nsig=nsig, no_ref=True, roll_angle=10)

wfe_list = [5]
curves_noref5 = do_contrast(wfe_list, filt_keys, nsig=nsig, no_ref=True, roll_angle=10)

wfe_list = [2]
curves_noref2 = do_contrast(wfe_list, filt_keys, nsig=nsig, no_ref=True, roll_angle=10)F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none
F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none
F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none
import matplotlib.patches as patches

fig, axes = plt.subplots(2,2, figsize=(13,8))
xlim1 = [0,5]
xlim2 = [0,10]
ylim  = [25,8]

curves_all = [curves_basic, curves_recon10, curves_recon5, curves_recon2, curves_photon]
labels = ['Basic Ref Sub', 'Opt Sub (10 nm)', 'Opt Sub (5 nm)',
          'Opt Sub (2 nm)', 'Opt Sub (0 nm)']

lin_vals = np.linspace(0.2,0.7,len(curves_all))
cb = plt.cm.Blues_r(lin_vals)[::-1]

curves_all2 = [curves_noref10, curves_noref5, curves_noref2, curves_photon2]
labels2 = ['Roll Sub (10 nm)', 'Roll Sub (5 nm)',
           'Roll Sub (2 nm)', 'Roll Sub (0 nm)']
lin_vals2 = np.linspace(0.2,0.7,len(curves_all2))
cr = plt.cm.Reds_r(lin_vals2)[::-1]

axes = axes.flatten()

for j, k in enumerate(filt_keys):
    for jj, cv in enumerate(curves_all):
        curves = cv[k]
        rr, contrast, mag_sens = curves[0]
        axes[j].plot(rr, mag_sens, color=cb[jj], zorder=1, lw=2, label=labels[jj])
    for jj, cv in enumerate(curves_all2):
        curves = cv[k]
        rr, contrast, mag_sens = curves[0]
        axes[j].plot(rr, mag_sens, color=cr[jj], zorder=1, lw=2, label=labels2[jj])

for j, ax in enumerate(axes):
    ax.set_xlabel('Distance (arcsec)')
    ax.set_ylabel('{}-sigma Sensitivities (mag)'.format(nsig))

    if j<2: ax.set_xlim(xlim1)
    else: ax.set_xlim(xlim2)
    ax.set_ylim(ylim)

    obs = obs_dict[filt_keys[j]]
    plot_planet_patches(ax, obs, age=age_sci)

    ax.legend(ncol=3)

# Saturation levels
for j, ax in enumerate(axes):
    dy = ylim[1] - ylim[0]

    rect = patches.Rectangle((0, ylim[0]), dmax[j], dy, alpha=0.2,
                             color='k', zorder=2)
    ax.add_patch(rect)

fig.tight_layout()

dist = obs.distance
age_str = 'Age = {:.0f} Myr'.format(age_sci)
dist_str = 'Distance = {:.1f} pc'.format(dist) if dist is not None else ''

fig.suptitle('{} ({}, {})'.format(name_sci,age_str,dist_str), fontsize=16);
#fig.subplots_adjust(top=0.85)
fig.subplots_adjust(top=0.9)

fname = "{}_contrast2.pdf".format(name_sci.replace(" ", ""))
fig.savefig(outdir+fname)_____no_output_____

## 2. TW Hya_____no_output_____

i = 1

name_sci, dist_sci, age_sci, spt_sci, vmag_sci, kmag_sci, w1_sci, w2_sci, vot = args_sources[i]
name_ref, spt_ref, kmag_ref = ref_sources[i]

# Science target and reference star spectra
sp_ref = pynrc.stellar_spectrum(spt_ref, kmag_ref, 'vegamag', bp_k)
sp_ref.name = name_ref

robust = True if i>=2 else False
sp_sci, (fig,ax) = gen_sp_sci(i, robust=robust, return_ax=True)

ax.plot(sp_ref.wave/1e4, sp_ref.flux, lw=1, label='PSF Reference')
ax.legend()
ax.set_xlim([0.4,10])
ax.set_ylim([5e-16,1e-11])

fname = "{}_spectra.pdf".format(name_sci.replace(" ", ""))
fig.savefig('YSOs/'+fname)

# Disk model information
# File name, arcsec/pix, dist (pc), wavelength (um), flux units
args_disk = None #('example_disk.fits', 0.007, 140.0, 1.6, 'mJy/arcsec^2')[  8.27857683e-02   4.38870542e+02   2.49196394e+00]
obs_dict = do_init(args_disk=args_disk, fov_pix=401, verbose=False)_____no_output_____# Update detector readout
for key in filt_keys:
    obs = obs_dict[key]

    if 'none' in key:
        pattern, ng, nint_sci, nint_ref = ('RAPID',5,160,160)
    elif ('MASK210R' in key) or ('MASKSWB' in key):
        pattern, ng, nint_sci, nint_ref = ('BRIGHT2',10,20,20)
    else:
        pattern, ng, nint_sci, nint_ref = ('MEDIUM8',10,15,15)

    obs.update_detectors(read_mode=pattern, ngroup=ng, nint=nint_sci)
    obs.nrc_ref.update_detectors(read_mode=pattern, ngroup=ng, nint=nint_ref)

    #print(key)
    #print(obs.multiaccum_times)
    #_ = obs.sensitivity(nsig=5, units='vegamag', verbose=True)
    #print('')_____no_output_____

### Saturation Regions_____no_output_____

dmax = []
for k in filt_keys:
    print(k)
    obs = obs_dict[k]
    im_sat = obs.nrc_ref.saturation_levels(sp_ref,ngroup=0)

    dist = nrc_utils.dist_image(im_sat, pixscale=obs.pix_scale)
    dmax.append(dist[im_sat>0.8].max())F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none

### Photon Limit Curves_____no_output_____

nsig = 5

for k in filt_keys:
    obs_dict[k].sp_ref = sp_sci

wfe_list = [0]

curves_photon = do_contrast(wfe_list, filt_keys, nsig=nsig, opt_diff=True)F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none

### Reference Reconstruction Curves_____no_output_____

nsig = 5

for k in filt_keys:
    obs_dict[k].sp_ref = sp_sci

wfe_list = [10]
curves_recon10 = do_contrast(wfe_list, filt_keys, nsig=nsig, opt_diff=True)

wfe_list = [5]
curves_recon5 = do_contrast(wfe_list, filt_keys, nsig=nsig, opt_diff=True)

wfe_list = [2]
curves_recon2 = do_contrast(wfe_list, filt_keys, nsig=nsig, opt_diff=True)F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none
F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none
F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none

### Basic PSF Subtraction Curves_____no_output_____

nsig = 5

for k in filt_keys:
    obs_dict[k].sp_ref = sp_ref

wfe_list = [5]

curves_basic = do_contrast(wfe_list, filt_keys, nsig=nsig, opt_diff=True)F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none

### Roll Subtraction_____no_output_____

# Update detector readout
for key in filt_keys:
    obs = obs_dict[key]

    if 'none' in key:
        pattern, ng, nint_sci, nint_ref = ('RAPID',5,150,150)
    elif ('MASK210R' in key) or ('MASKSWB' in key):
        pattern, ng, nint_sci, nint_ref = ('BRIGHT2',10,20,20)
    else:
        pattern, ng, nint_sci, nint_ref = ('MEDIUM8',10,15,15)

    obs.update_detectors(read_mode=pattern, ngroup=ng, nint=nint_sci)
    obs.nrc_ref.update_detectors(read_mode=pattern, ngroup=ng, nint=nint_ref)

    #print(key)
    #print(obs.multiaccum_times)
    #_ = obs.sensitivity(nsig=5, units='vegamag', verbose=True)
    #print('')_____no_output_____nsig = 5

for k in filt_keys:
    obs_dict[k].sp_ref = sp_sci

wfe_list = [0]

curves_photon2 = do_contrast(wfe_list, filt_keys, nsig=nsig, no_ref=True, roll_angle=10)F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none
nsig = 5

for k in filt_keys:
    obs_dict[k].sp_ref = sp_sci

wfe_list = [10]
curves_noref10 = do_contrast(wfe_list, filt_keys, nsig=nsig, no_ref=True, roll_angle=10)

wfe_list = [5]
curves_noref5 = do_contrast(wfe_list, filt_keys, nsig=nsig, no_ref=True, roll_angle=10)

wfe_list = [2]
curves_noref2 = do_contrast(wfe_list, filt_keys, nsig=nsig, no_ref=True, roll_angle=10)F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none
F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none
F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none
import matplotlib.patches as patches

fig, axes = plt.subplots(2,2, figsize=(13,8))
xlim1 = [0,5]
xlim2 = [0,10]
ylim  = [25,8]

curves_all = [curves_basic, curves_recon10, curves_recon5, curves_recon2, curves_photon]
labels = ['Basic Ref Sub', 'Opt Sub (10 nm)', 'Opt Sub (5 nm)',
          'Opt Sub (2 nm)', 'Opt Sub (0 nm)']

lin_vals = np.linspace(0.2,0.7,len(curves_all))
cb = plt.cm.Blues_r(lin_vals)[::-1]

curves_all2 = [curves_noref10, curves_noref5, curves_noref2, curves_photon2]
labels2 = ['Roll Sub (10 nm)', 'Roll Sub (5 nm)',
           'Roll Sub (2 nm)', 'Roll Sub (0 nm)']
lin_vals2 = np.linspace(0.2,0.7,len(curves_all2))
cr = plt.cm.Reds_r(lin_vals2)[::-1]

axes = axes.flatten()

for j, k in enumerate(filt_keys):
    for jj, cv in enumerate(curves_all):
        curves = cv[k]
        rr, contrast, mag_sens = curves[0]
        axes[j].plot(rr, mag_sens, color=cb[jj], zorder=1, lw=2, label=labels[jj])
    for jj, cv in enumerate(curves_all2):
        curves = cv[k]
        rr, contrast, mag_sens = curves[0]
        axes[j].plot(rr, mag_sens, color=cr[jj], zorder=1, lw=2, label=labels2[jj])

for j, ax in enumerate(axes):
    ax.set_xlabel('Distance (arcsec)')
    ax.set_ylabel('{}-sigma Sensitivities (mag)'.format(nsig))

    if j<2: ax.set_xlim(xlim1)
    else: ax.set_xlim(xlim2)
    ax.set_ylim(ylim)

    obs = obs_dict[filt_keys[j]]
    plot_planet_patches(ax, obs, age=age_sci)

    ax.legend(ncol=3)

# Saturation levels
for j, ax in enumerate(axes):
    dy = ylim[1] - ylim[0]

    rect = patches.Rectangle((0, ylim[0]), dmax[j], dy, alpha=0.2,
                             color='k', zorder=2)
    ax.add_patch(rect)

fig.tight_layout()

dist = obs.distance
age_str = 'Age = {:.0f} Myr'.format(age_sci)
dist_str = 'Distance = {:.1f} pc'.format(dist) if dist is not None else ''

fig.suptitle('{} ({}, {})'.format(name_sci,age_str,dist_str), fontsize=16);
#fig.subplots_adjust(top=0.85)
fig.subplots_adjust(top=0.9)

fname = "{}_contrast2.pdf".format(name_sci.replace(" ", ""))
fig.savefig(outdir+fname)_____no_output_____

## 3. MWC 758_____no_output_____

i = 2

name_sci, dist_sci, age_sci, spt_sci, vmag_sci, kmag_sci, w1_sci, w2_sci, vot = args_sources[i]
name_ref, spt_ref, kmag_ref = ref_sources[i]

# Science target and reference star spectra
sp_ref = pynrc.stellar_spectrum(spt_ref, kmag_ref, 'vegamag', bp_k)
sp_ref.name = name_ref

robust = True if i>=2 else False
sp_sci, (fig,ax) = gen_sp_sci(i, robust=robust, return_ax=True)

ax.plot(sp_ref.wave/1e4, sp_ref.flux, lw=1, label='PSF Reference')
ax.legend()
ax.set_xlim([0.4,10])
ax.set_ylim([5e-15,1e-11])

fname = "{}_spectra.pdf".format(name_sci.replace(" ", ""))
fig.savefig('YSOs/'+fname)

# Disk model information
# File name, arcsec/pix, dist (pc), wavelength (um), flux units
args_disk = ('example_disk.fits', 0.007, 140.0, 1.6, 'mJy/arcsec^2')[  1.64168384e-01   2.98052913e+03   1.64704399e+00]
obs_dict = do_init(args_disk=args_disk, fov_pix=401, verbose=False)_____no_output_____# Update detector readout
for key in filt_keys:
    obs = obs_dict[key]

    if 'none' in key:
        pattern, ng, nint_sci, nint_ref = ('RAPID',5,160,160)
    elif ('MASK210R' in key) or ('MASKSWB' in key):
        pattern, ng, nint_sci, nint_ref = ('BRIGHT2',10,20,20)
    else:
        pattern, ng, nint_sci, nint_ref = ('MEDIUM8',10,15,15)

    obs.update_detectors(read_mode=pattern, ngroup=ng, nint=nint_sci)
    obs.nrc_ref.update_detectors(read_mode=pattern, ngroup=ng, nint=nint_ref)

    #print(key)
    #print(obs.multiaccum_times)
    #_ = obs.sensitivity(nsig=5, units='vegamag', verbose=True)
    #print('')_____no_output_____

### Saturation Regions_____no_output_____

dmax = []
for k in filt_keys:
    print(k)
    obs = obs_dict[k]
    im_sat = obs.nrc_ref.saturation_levels(sp_ref,ngroup=0)

    dist = nrc_utils.dist_image(im_sat, pixscale=obs.pix_scale)
    dmax.append(dist[im_sat>0.8].max())F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none

### Photon Limit Curves_____no_output_____

nsig = 5

for k in filt_keys:
    obs_dict[k].sp_ref = sp_sci

wfe_list = [0]

curves_photon = do_contrast(wfe_list, filt_keys, nsig=nsig, opt_diff=True)F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none

### Reference Reconstruction Curves_____no_output_____

nsig = 5

for k in filt_keys:
    obs_dict[k].sp_ref = sp_sci

wfe_list = [10]
curves_recon10 = do_contrast(wfe_list, filt_keys, nsig=nsig, opt_diff=True)

wfe_list = [5]
curves_recon5 = do_contrast(wfe_list, filt_keys, nsig=nsig, opt_diff=True)

wfe_list = [2]
curves_recon2 = do_contrast(wfe_list, filt_keys, nsig=nsig, opt_diff=True)F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none
F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none
F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none

### Basic PSF Subtraction Curves_____no_output_____

nsig = 5

for k in filt_keys:
    obs_dict[k].sp_ref = sp_ref

wfe_list = [5]

curves_basic = do_contrast(wfe_list, filt_keys, nsig=nsig, opt_diff=True)F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none

### Roll Subtraction_____no_output_____

# Update detector readout
for key in filt_keys:
    obs = obs_dict[key]

    if 'none' in key:
        pattern, ng, nint_sci, nint_ref = ('RAPID',5,135,135)
    elif ('MASK210R' in key) or ('MASKSWB' in key):
        pattern, ng, nint_sci, nint_ref = ('BRIGHT2',10,20,20)
    else:
        pattern, ng, nint_sci, nint_ref = ('MEDIUM8',10,15,15)

    obs.update_detectors(read_mode=pattern, ngroup=ng, nint=nint_sci)
    obs.nrc_ref.update_detectors(read_mode=pattern, ngroup=ng, nint=nint_ref)

    #print(key)
    #print(obs.multiaccum_times)
    #_ = obs.sensitivity(nsig=5, units='vegamag', verbose=True)
    #print('')_____no_output_____nsig = 5

for k in filt_keys:
    obs_dict[k].sp_ref = sp_sci

wfe_list = [0]

curves_photon2 = do_contrast(wfe_list, filt_keys, nsig=nsig, no_ref=True, roll_angle=10)F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none
nsig = 5

for k in filt_keys:
    obs_dict[k].sp_ref = sp_sci

wfe_list = [10]
curves_noref10 = do_contrast(wfe_list, filt_keys, nsig=nsig, no_ref=True, roll_angle=10)

wfe_list = [5]
curves_noref5 = do_contrast(wfe_list, filt_keys, nsig=nsig, no_ref=True, roll_angle=10)

wfe_list = [2]
curves_noref2 = do_contrast(wfe_list, filt_keys, nsig=nsig, no_ref=True, roll_angle=10)F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none
F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none
F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none
import matplotlib.patches as patches

fig, axes = plt.subplots(2,2, figsize=(13,8))
xlim1 = [0,5]
xlim2 = [0,10]
ylim  = [25,8]

curves_all = [curves_basic, curves_recon10, curves_recon5, curves_recon2, curves_photon]
labels = ['Basic Ref Sub', 'Opt Sub (10 nm)', 'Opt Sub (5 nm)',
          'Opt Sub (2 nm)', 'Opt Sub (0 nm)']

lin_vals = np.linspace(0.2,0.7,len(curves_all))
cb = plt.cm.Blues_r(lin_vals)[::-1]

curves_all2 = [curves_noref10, curves_noref5, curves_noref2, curves_photon2]
labels2 = ['Roll Sub (10 nm)', 'Roll Sub (5 nm)',
           'Roll Sub (2 nm)', 'Roll Sub (0 nm)']
lin_vals2 = np.linspace(0.2,0.7,len(curves_all2))
cr = plt.cm.Reds_r(lin_vals2)[::-1]

axes = axes.flatten()

for j, k in enumerate(filt_keys):
    for jj, cv in enumerate(curves_all):
        curves = cv[k]
        rr, contrast, mag_sens = curves[0]
        axes[j].plot(rr, mag_sens, color=cb[jj], zorder=1, lw=2, label=labels[jj])
    for jj, cv in enumerate(curves_all2):
        curves = cv[k]
        rr, contrast, mag_sens = curves[0]
        axes[j].plot(rr, mag_sens, color=cr[jj], zorder=1, lw=2, label=labels2[jj])

for j, ax in enumerate(axes):
    ax.set_xlabel('Distance (arcsec)')
    ax.set_ylabel('{}-sigma Sensitivities (mag)'.format(nsig))

    if j<2: ax.set_xlim(xlim1)
    else: ax.set_xlim(xlim2)
    ax.set_ylim(ylim)

    obs = obs_dict[filt_keys[j]]
    plot_planet_patches(ax, obs, age=age_sci)

    ax.legend(ncol=3)

# Saturation levels
for j, ax in enumerate(axes):
    dy = ylim[1] - ylim[0]

    rect = patches.Rectangle((0, ylim[0]), dmax[j], dy, alpha=0.2,
                             color='k', zorder=2)
    ax.add_patch(rect)

fig.tight_layout()

dist = obs.distance
age_str = 'Age = {:.0f} Myr'.format(age_sci)
dist_str = 'Distance = {:.1f} pc'.format(dist) if dist is not None else ''

fig.suptitle('{} ({}, {})'.format(name_sci,age_str,dist_str), fontsize=16);
#fig.subplots_adjust(top=0.85)
fig.subplots_adjust(top=0.9)

fname = "{}_contrast2.pdf".format(name_sci.replace(" ", ""))
fig.savefig(outdir+fname)_____no_output_____

## 4. HL Tau_____no_output_____

i = 3

name_sci, dist_sci, age_sci, spt_sci, vmag_sci, kmag_sci, w1_sci, w2_sci, vot = args_sources[i]
name_ref, spt_ref, kmag_ref = ref_sources[i]

# Science target and reference star spectra
sp_ref = pynrc.stellar_spectrum(spt_ref, kmag_ref, 'vegamag', bp_k)
sp_ref.name = name_ref

robust = True if i>=2 else False
sp_sci, (fig,ax) = gen_sp_sci(i, robust=robust, return_ax=True)

ax.plot(sp_ref.wave/1e4, sp_ref.flux, lw=1, label='PSF Reference')
ax.legend()
ax.set_xlim([0.4,10])
ax.set_ylim([5e-16,1e-11])

fname = "{}_spectra.pdf".format(name_sci.replace(" ", ""))
fig.savefig('YSOs/'+fname)

# Disk model information
# File name, arcsec/pix, dist (pc), wavelength (um), flux units
args_disk = None #('example_disk.fits', 0.007, 140.0, 1.6, 'mJy/arcsec^2')[  2.37592190e-02   2.47428825e+03   2.84970482e+00]
obs_dict = do_init(args_disk=args_disk, fov_pix=401, verbose=False)_____no_output_____# Update detector readout
for key in filt_keys:
    obs = obs_dict[key]

    if 'none' in key:
        pattern, ng, nint_sci, nint_ref = ('RAPID',5,160,160)
    elif ('MASK210R' in key) or ('MASKSWB' in key):
        pattern, ng, nint_sci, nint_ref = ('BRIGHT2',10,20,20)
    else:
        pattern, ng, nint_sci, nint_ref = ('MEDIUM8',10,15,15)

    obs.update_detectors(read_mode=pattern, ngroup=ng, nint=nint_sci)
    obs.nrc_ref.update_detectors(read_mode=pattern, ngroup=ng, nint=nint_ref)

    #print(key)
    #print(obs.multiaccum_times)
    #_ = obs.sensitivity(nsig=5, units='vegamag', verbose=True)
    #print('')_____no_output_____

### Saturation Regions_____no_output_____

dmax = []
for k in filt_keys:
    print(k)
    obs = obs_dict[k]
    im_sat = obs.saturation_levels(ngroup=0)

    dist = nrc_utils.dist_image(im_sat, pixscale=obs.pix_scale)
    dmax.append(dist[im_sat>0.8].max())F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none

### Photon Limit Curves_____no_output_____

nsig = 5

for k in filt_keys:
    obs_dict[k].sp_ref = sp_sci

wfe_list = [0]

curves_photon = do_contrast(wfe_list, filt_keys, nsig=nsig, opt_diff=True)
F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none

### Reference Reconstruction Curves_____no_output_____

nsig = 5

for k in filt_keys:
    obs_dict[k].sp_ref = sp_sci

wfe_list = [10]
curves_recon10 = do_contrast(wfe_list, filt_keys, nsig=nsig, opt_diff=True)

wfe_list = [5]
curves_recon5 = do_contrast(wfe_list, filt_keys, nsig=nsig, opt_diff=True)

wfe_list = [2]
curves_recon2 = do_contrast(wfe_list, filt_keys, nsig=nsig, opt_diff=True)F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none
F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none
F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none

### Basic PSF Subtraction Curves_____no_output_____

nsig = 5

for k in filt_keys:
    obs_dict[k].sp_ref = sp_ref

wfe_list = [5]

curves_basic = do_contrast(wfe_list, filt_keys, nsig=nsig, opt_diff=True)F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none

### Roll Subtraction_____no_output_____

# Update detector readout
for key in filt_keys:
    obs = obs_dict[key]

    if 'none' in key:
        pattern, ng, nint_sci, nint_ref = ('RAPID',5,150,150)
    elif ('MASK210R' in key) or ('MASKSWB' in key):
        pattern, ng, nint_sci, nint_ref = ('BRIGHT2',10,20,20)
    else:
        pattern, ng, nint_sci, nint_ref = ('MEDIUM8',10,15,15)

    obs.update_detectors(read_mode=pattern, ngroup=ng, nint=nint_sci)
    obs.nrc_ref.update_detectors(read_mode=pattern, ngroup=ng, nint=nint_ref)

    #print(key)
    #print(obs.multiaccum_times)
    #_ = obs.sensitivity(nsig=5, units='vegamag', verbose=True)
    #print('')_____no_output_____nsig = 5

for k in filt_keys:
    obs_dict[k].sp_ref = sp_sci

wfe_list = [0]

curves_photon2 = do_contrast(wfe_list, filt_keys, nsig=nsig, no_ref=True, roll_angle=10)F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none
nsig = 5

for k in filt_keys:
    obs_dict[k].sp_ref = sp_sci

wfe_list = [10]
curves_noref10 = do_contrast(wfe_list, filt_keys, nsig=nsig, no_ref=True, roll_angle=10)

wfe_list = [5]
curves_noref5 = do_contrast(wfe_list, filt_keys, nsig=nsig, no_ref=True, roll_angle=10)

wfe_list = [2]
curves_noref2 = do_contrast(wfe_list, filt_keys, nsig=nsig, no_ref=True, roll_angle=10)F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none
F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none
F187N_none_none
F200W_none_none
F356W_none_none
F444W_none_none
import matplotlib.patches as patches

fig, axes = plt.subplots(2,2, figsize=(13,8))
xlim1 = [0,5]
xlim2 = [0,10]
ylim  = [25,8]

curves_all = [curves_basic, curves_recon10, curves_recon5, curves_recon2, curves_photon]
labels = ['Basic Ref Sub', 'Opt Sub (10 nm)', 'Opt Sub (5 nm)',
          'Opt Sub (2 nm)', 'Opt Sub (0 nm)']

lin_vals = np.linspace(0.2,0.7,len(curves_all))
cb = plt.cm.Blues_r(lin_vals)[::-1]

curves_all2 = [curves_noref10, curves_noref5, curves_noref2, curves_photon2]
labels2 = ['Roll Sub (10 nm)', 'Roll Sub (5 nm)',
           'Roll Sub (2 nm)', 'Roll Sub (0 nm)']
lin_vals2 = np.linspace(0.2,0.7,len(curves_all2))
cr = plt.cm.Reds_r(lin_vals2)[::-1]

axes = axes.flatten()

for j, k in enumerate(filt_keys):
    for jj, cv in enumerate(curves_all):
        curves = cv[k]
        rr, contrast, mag_sens = curves[0]
        axes[j].plot(rr, mag_sens, color=cb[jj], zorder=1, lw=2, label=labels[jj])
    for jj, cv in enumerate(curves_all2):
        curves = cv[k]
        rr, contrast, mag_sens = curves[0]
        axes[j].plot(rr, mag_sens, color=cr[jj], zorder=1, lw=2, label=labels2[jj])

for j, ax in enumerate(axes):
    ax.set_xlabel('Distance (arcsec)')
    ax.set_ylabel('{}-sigma Sensitivities (mag)'.format(nsig))

    if j<2: ax.set_xlim(xlim1)
    else: ax.set_xlim(xlim2)
    ax.set_ylim(ylim)

    obs = obs_dict[filt_keys[j]]
    plot_planet_patches(ax, obs, age=age_sci)

    ax.legend(ncol=3)

# Saturation levels
for j, ax in enumerate(axes):
    dy = ylim[1] - ylim[0]

    rect = patches.Rectangle((0, ylim[0]), dmax[j], dy, alpha=0.2,
                             color='k', zorder=2)
    ax.add_patch(rect)

fig.tight_layout()

dist = obs.distance
age_str = 'Age = {:.0f} Myr'.format(age_sci)
dist_str = 'Distance = {:.1f} pc'.format(dist) if dist is not None else ''

fig.suptitle('{} ({}, {})'.format(name_sci,age_str,dist_str), fontsize=16);
#fig.subplots_adjust(top=0.85)
fig.subplots_adjust(top=0.9)

fname = "{}_contrast2.pdf".format(name_sci.replace(" ", ""))
fig.savefig(outdir+fname)_____no_output_____