Comparison of data and model — species 0.1.2 documentation

# Comparison of data and model

In this tutorial, the photometric fluxes of the brown dwarf companion PZ Tel B is compared with a spectrum from the AMES-Cond atmospheric model.

## Initiating species

    [1]:

    import species

    [2]:

    species.SpeciesInit()

    Initiating species v0.1.0... [DONE]
    Creating species_config.ini... [DONE]
    Database: /Users/tomasstolker/applications/species/docs/tutorials/species_database.hdf5
    Data folder: /Users/tomasstolker/applications/species/docs/tutorials/data
    Working folder: /Users/tomasstolker/applications/species/docs/tutorials
    Creating species_database.hdf5... [DONE]
    Creating data folder... [DONE]

    [2]:

    <species.core.setup.SpeciesInit at 0x12556b5f8>

## Adding model spectra

A `Database` object is now created which can be used for importing of data into the database.

    [3]:

    database = species.Database()

The spectra of the AMES-Cond model are downloaded and added to the database. This requires sufficient disk storage in the data_folder that is set in the configuration file.

While the full AMES-Cond grid is downloaded, a restiction on the wavelength and Teff range can be used when the data is imported. Also the spectral resolution can be set to downsample the high-resolution of the original spectra spectra.

    [4]:

    database.add_model(model='ames-cond',
                       wavel_range=(0.1, 6.),
                       spec_res=1000.
                       teff_range=(2800., 3000.))

    Downloading AMES-Cond model spectra (823 MB)... [DONE]
    Unpacking AMES-Cond model spectra (823 MB)... [DONE]
    Adding AMES-Cond model spectra... [DONE]

## Adding companion data

The distance and magnitudes of PZ Tel B are added to the database. This will automatically download the filter transmission profiles and a flux calibrated spectrum of Vega, which are used for the flux calibration.

    [5]:

    database.add_companion(name='PZ Tel B')

    Adding filter: Paranal/SPHERE.ZIMPOL_R_PRIM... [DONE]
    Downloading Vega spectrum (270 kB)... [DONE]
    Adding Vega spectrum... [DONE]
    Adding filter: Paranal/SPHERE.ZIMPOL_I_PRIM... [DONE]
    Adding filter: Paranal/SPHERE.IRDIS_D_H23_2... [DONE]
    Adding filter: Paranal/SPHERE.IRDIS_D_H23_3... [DONE]
    Adding filter: Paranal/SPHERE.IRDIS_D_K12_1... [DONE]
    Adding filter: Paranal/SPHERE.IRDIS_D_K12_2... [DONE]
    Adding filter: Paranal/NACO.J... [DONE]
    Adding filter: Paranal/NACO.H... [DONE]
    Adding filter: Paranal/NACO.Ks... [DONE]
    Adding filter: Paranal/NACO.Lp... [DONE]
    Adding filter: Paranal/NACO.NB405... [DONE]
    Adding filter: Paranal/NACO.Mp... [DONE]
    Adding filter: Gemini/NICI.ED286... [DONE]
    Adding filter: Gemini/NIRI.H2S1v2-1-G0220... [DONE]
    Adding object: PZ Tel B... [DONE]

Alternatively, the `add_object` method of `Database` can be used for manually adding magnitudes and spectra of an individual object. Before coninuing, let’s check the content of the database.

    [6]:

    database.list_content()

    Database content:
    - filters: <HDF5 group "/filters" (2 members)>
            - Gemini: <HDF5 group "/filters/Gemini" (2 members)>
                    - NICI.ED286: <HDF5 dataset "NICI.ED286": shape (2, 387), type "<f4">
                    - NIRI.H2S1v2-1-G0220: <HDF5 dataset "NIRI.H2S1v2-1-G0220": shape (2, 129), type "<f4">
            - Paranal: <HDF5 group "/filters/Paranal" (12 members)>
                    - NACO.H: <HDF5 dataset "NACO.H": shape (2, 23), type "<f4">
                    - NACO.J: <HDF5 dataset "NACO.J": shape (2, 20), type "<f4">
                    - NACO.Ks: <HDF5 dataset "NACO.Ks": shape (2, 27), type "<f4">
                    - NACO.Lp: <HDF5 dataset "NACO.Lp": shape (2, 31), type "<f4">
                    - NACO.Mp: <HDF5 dataset "NACO.Mp": shape (2, 18), type "<f4">
                    - NACO.NB405: <HDF5 dataset "NACO.NB405": shape (2, 67), type "<f4">
                    - SPHERE.IRDIS_D_H23_2: <HDF5 dataset "SPHERE.IRDIS_D_H23_2": shape (2, 113), type "<f4">
                    - SPHERE.IRDIS_D_H23_3: <HDF5 dataset "SPHERE.IRDIS_D_H23_3": shape (2, 180), type "<f4">
                    - SPHERE.IRDIS_D_K12_1: <HDF5 dataset "SPHERE.IRDIS_D_K12_1": shape (2, 175), type "<f4">
                    - SPHERE.IRDIS_D_K12_2: <HDF5 dataset "SPHERE.IRDIS_D_K12_2": shape (2, 191), type "<f4">
                    - SPHERE.ZIMPOL_I_PRIM: <HDF5 dataset "SPHERE.ZIMPOL_I_PRIM": shape (2, 189), type "<f4">
                    - SPHERE.ZIMPOL_R_PRIM: <HDF5 dataset "SPHERE.ZIMPOL_R_PRIM": shape (2, 169), type "<f4">
    - models: <HDF5 group "/models" (1 members)>
            - ames-cond: <HDF5 group "/models/ames-cond" (4 members)>
                    - flux: <HDF5 dataset "flux": shape (3, 13, 4097), type "<f4">
                    - logg: <HDF5 dataset "logg": shape (13,), type "<f4">
                    - teff: <HDF5 dataset "teff": shape (3,), type "<f4">
                    - wavelength: <HDF5 dataset "wavelength": shape (4097,), type "<f4">
    - objects: <HDF5 group "/objects" (1 members)>
            - PZ Tel B: <HDF5 group "/objects/PZ Tel B" (3 members)>
                    - Gemini: <HDF5 group "/objects/PZ Tel B/Gemini" (2 members)>
                            - NICI.ED286: <HDF5 dataset "NICI.ED286": shape (4,), type "<f4">
                            - NIRI.H2S1v2-1-G0220: <HDF5 dataset "NIRI.H2S1v2-1-G0220": shape (4,), type "<f4">
                    - Paranal: <HDF5 group "/objects/PZ Tel B/Paranal" (12 members)>
                            - NACO.H: <HDF5 dataset "NACO.H": shape (4,), type "<f4">
                            - NACO.J: <HDF5 dataset "NACO.J": shape (4,), type "<f4">
                            - NACO.Ks: <HDF5 dataset "NACO.Ks": shape (4,), type "<f4">
                            - NACO.Lp: <HDF5 dataset "NACO.Lp": shape (4,), type "<f4">
                            - NACO.Mp: <HDF5 dataset "NACO.Mp": shape (4,), type "<f4">
                            - NACO.NB405: <HDF5 dataset "NACO.NB405": shape (4,), type "<f4">
                            - SPHERE.IRDIS_D_H23_2: <HDF5 dataset "SPHERE.IRDIS_D_H23_2": shape (4,), type "<f4">
                            - SPHERE.IRDIS_D_H23_3: <HDF5 dataset "SPHERE.IRDIS_D_H23_3": shape (4,), type "<f4">
                            - SPHERE.IRDIS_D_K12_1: <HDF5 dataset "SPHERE.IRDIS_D_K12_1": shape (4,), type "<f4">
                            - SPHERE.IRDIS_D_K12_2: <HDF5 dataset "SPHERE.IRDIS_D_K12_2": shape (4,), type "<f4">
                            - SPHERE.ZIMPOL_I_PRIM: <HDF5 dataset "SPHERE.ZIMPOL_I_PRIM": shape (4,), type "<f4">
                            - SPHERE.ZIMPOL_R_PRIM: <HDF5 dataset "SPHERE.ZIMPOL_R_PRIM": shape (4,), type "<f4">
                    - distance: <HDF5 dataset "distance": shape (2,), type "<f4">
    - spectra: <HDF5 group "/spectra" (1 members)>
            - calibration: <HDF5 group "/spectra/calibration" (1 members)>
                    - vega: <HDF5 dataset "vega": shape (3, 8827), type "<f4">

## Reading model spectra

Model spectra are read from the database by creating an object of `ReadModel`. The model name and optionally a wavelength range should be provided. The wavelength range should fit within the range that was specified in `add_model`.

    [7]:

    readmodel = species.ReadModel(model='ames-cond',
                                  wavel_range=(0.1, 6.))

Before extracting a spectrum, let’s check which parameters are required for the AMES-Cond models.

    [8]:

    readmodel.get_parameters()

    [8]:

    ['teff', 'logg']

And also the grid boundaries that are stored in the database.

    [9]:

    readmodel.get_bounds()

    [9]:

    {'teff': (2800.0, 3000.0), 'logg': (0.0, 6.0)}

The parameters are provided in a dictionary. Make sure to chose values within the grid boundaries. The radius (RJup) and distance (pc) will scale the emitted spectrum to the observer. Without these values, the spectrum is provided at the outermost layer of the atmosphere.

    [10]:

    model_param = {'teff': 2900., 'logg': 4.5, 'radius': 2.2, 'distance': 47.13}

The grid of spectra is linearly interpolated at a spectral resolution of 100 and stored in a `ModelBox`.

    [11]:

    modelbox = readmodel.get_model(model_param=model_param,
                                   spec_res=100.)

## Reading companion data

The photometry data of PZ Tel B are also read from the database and stored in an `ObjectBox`.

    [12]:

    objectbox = database.get_object(object_name='PZ Tel B')

    Getting object: PZ Tel B... [DONE]

## Synthetic photometry for all filters

For comparison, we create synthetic photometry from the model spectrum for all filters of PZ Tel B, which are stored in a `SynphotBox`.

    [13]:

    synphotbox = species.multi_photometry(datatype='model',
                                          spectrum='ames-cond',
                                          filters=objectbox.filters,
                                          parameters=model_param)

    Calculating synthetic photometry... [DONE]

## Creating flux residuals

The `get_residuals` function is used to calculate the difference between the observed fluxes and the synthetic photometry of the model spectrum. The residuals are stored in a `ResidualsBox`.

    [14]:

    residualsbox = species.get_residuals(datatype='model',
                                         spectrum='ames-cond',
                                         parameters=model_param,
                                         filters=objectbox.filters,
                                         objectbox=objectbox,
                                         inc_phot=True,
                                         inc_spec=False)

    Calculating synthetic photometry... [DONE]
    Calculating residuals... [DONE]

## Opening Box objects

The `open_box` function can be used to view the content of a `Box` object. For example, the `ModelBox` contains several attributes, including the wavelength points and flux densities.

    [15]:

    modelbox.open_box()

    Opening ModelBox...

    model = ames-cond
    type = None
    wavelength = [0.1       0.1001    0.1002001 ... 5.739604  5.7453437 5.751089 ]
    flux = [7.69244319e-10 6.23827156e-09 1.04784443e-05 ... 3.85241479e-16
     3.84432439e-16 3.83581166e-16]
    parameters = {'teff': 2900.0, 'logg': 4.5, 'radius': 2.2, 'distance': 47.13, 'mass': 61.7508434070773}
    quantity = flux

Similarly, an `ObjectBox` contains a dictionary with the apparent magnitudes and a dictionary with the flux densities.

    [16]:

    objectbox.open_box()

    Opening ObjectBox...

    name = PZ Tel B
    filters = ['Gemini/NICI.ED286', 'Gemini/NIRI.H2S1v2-1-G0220', 'Paranal/NACO.H', 'Paranal/NACO.J', 'Paranal/NACO.Ks', 'Paranal/NACO.Lp', 'Paranal/NACO.Mp', 'Paranal/NACO.NB405', 'Paranal/SPHERE.IRDIS_D_H23_2', 'Paranal/SPHERE.IRDIS_D_H23_3', 'Paranal/SPHERE.IRDIS_D_K12_1', 'Paranal/SPHERE.IRDIS_D_K12_2', 'Paranal/SPHERE.ZIMPOL_I_PRIM', 'Paranal/SPHERE.ZIMPOL_R_PRIM']
    magnitude = {'Gemini/NICI.ED286': array([11.68,  0.14], dtype=float32), 'Gemini/NIRI.H2S1v2-1-G0220': array([11.39,  0.14], dtype=float32), 'Paranal/NACO.H': array([11.93,  0.14], dtype=float32), 'Paranal/NACO.J': array([12.47,  0.2 ], dtype=float32), 'Paranal/NACO.Ks': array([11.53,  0.07], dtype=float32), 'Paranal/NACO.Lp': array([11.04,  0.22], dtype=float32), 'Paranal/NACO.Mp': array([10.93,  0.03], dtype=float32), 'Paranal/NACO.NB405': array([10.94,  0.07], dtype=float32), 'Paranal/SPHERE.IRDIS_D_H23_2': array([11.78,  0.19], dtype=float32), 'Paranal/SPHERE.IRDIS_D_H23_3': array([11.65,  0.19], dtype=float32), 'Paranal/SPHERE.IRDIS_D_K12_1': array([11.56,  0.09], dtype=float32), 'Paranal/SPHERE.IRDIS_D_K12_2': array([11.29,  0.1 ], dtype=float32), 'Paranal/SPHERE.ZIMPOL_I_PRIM': array([15.16,  0.12], dtype=float32), 'Paranal/SPHERE.ZIMPOL_R_PRIM': array([17.84,  0.31], dtype=float32)}
    flux = {'Gemini/NICI.ED286': array([2.7825625e-14, 3.5979198e-15], dtype=float32), 'Gemini/NIRI.H2S1v2-1-G0220': array([1.0590437e-14, 1.3693687e-15], dtype=float32), 'Paranal/NACO.H': array([1.9687588e-14, 2.5456521e-15], dtype=float32), 'Paranal/NACO.J': array([3.1106848e-14, 5.7625536e-15], dtype=float32), 'Paranal/NACO.Ks': array([1.1241627e-14, 7.2527667e-16], dtype=float32), 'Paranal/NACO.Lp': array([2.0200626e-15, 4.1212692e-16], dtype=float32), 'Paranal/NACO.Mp': array([9.1877844e-16, 2.5390018e-17], dtype=float32), 'Paranal/NACO.NB405': array([1.6704631e-15, 1.0777336e-16], dtype=float32), 'Paranal/SPHERE.IRDIS_D_H23_2': array([2.5412999e-14, 4.4699182e-15], dtype=float32), 'Paranal/SPHERE.IRDIS_D_H23_3': array([2.4269955e-14, 4.2688669e-15], dtype=float32), 'Paranal/SPHERE.IRDIS_D_K12_1': array([1.1547812e-14, 9.5833011e-16], dtype=float32), 'Paranal/SPHERE.IRDIS_D_K12_2': array([1.1428121e-14, 1.0540576e-15], dtype=float32), 'Paranal/SPHERE.ZIMPOL_I_PRIM': array([1.0862880e-14, 1.2030557e-15], dtype=float32), 'Paranal/SPHERE.ZIMPOL_R_PRIM': array([1.8263311e-15, 5.2856905e-16], dtype=float32)}
    distance = 47.130001068115234
    spectrum = None

The attributes in the `Box` objects can be extracted for further analyis or manual plots, for example:

    [17]:

    modelbox.wavelength

    [17]:

    array([0.1      , 0.1001   , 0.1002001, ..., 5.739604 , 5.7453437,
           5.751089 ], dtype=float32)

## Plotting spectra, fluxes and filters

The `Box` objects can provided as list to `plot_spectrum`, which will be interpreted accordingly. Optionally, the filter names can be included for plotting the transmission profiles and the `ResidualsBox` can be included for showing the residuals. The `ObjectBox` requires a color for the photometry data and a spectrum with the latter set to `None` in this case.

    [18]:

    species.plot_spectrum(boxes=[modelbox, objectbox, synphotbox],
                          filters=objectbox.filters,
                          residuals=residualsbox,
                          colors=('darkblue', ('black', None), 'black'),
                          offset=(-0.08, -0.06),
                          xlim=(0.2, 5.5),
                          ylim=(-3e-15, 4.8e-14),
                          legend='upper right',
                          output='spectrum.png')

    Plotting spectrum: spectrum.png... [DONE]

Let’s have a look at the result. The plot is stored in the working folder. The black squares are the photometry data of PZ Tel B and the open squares are the synthetic photometry computed from the model spectrum. The residuals are shown relative to the uncertainties on the fluxes.

    [19]:

    from IPython.display import Image
    Image('spectrum.png')

    [19]: