Basics of ๐ Objectsยถ
The core of the chromatic
package is the Rainbow
(= ๐) object. Continually saying or typing โspectroscopic light curveโ can get tiring, so we chose "rainbow" as a shorter name that is a little nicer to say/type. Also, every emphemeral ๐ in nature is itself an expression of brightness as a function of wavelength and of time, so it hopefully kind of makes sense as a name?
from chromatic import SimulatedRainbow, version
version()
'0.4.12'
How do we create a ๐?ยถ
We can create Rainbow
objects in a few different ways.
- To load a ๐ in from a file, see Reading/Writing a ๐. We've invested a lot of effort in providing readers/writers in a variety of formats, to allow easy interaction between analyses.
- To create a ๐ from arrays, see Creating a ๐ from Arrays. As long as you provide 1D arrays of
time
andwavelength
and 2D arrays forflux
anduncertainty
(and maybeok
andmodel
), you can make a ๐. - To generate a simulated ๐, see ๐ Actions and use the tools shown there to inject in the compomnents you want into a
SimulatedRainbow()
object.
What variables does a ๐ have?ยถ
To users on the outside, all Rainbow
objects will be guaranteed to have a few key properties. We'll make a simple simulated example to show what those are.
# create a simulated spectroscopic light curve
r = SimulatedRainbow().inject_noise(signal_to_noise=100)
The .wavelength
property is a 1D array containing the wavelengths associated with the flux array. It is a an astropy
Quantity, with units of wavelength associated with it.
r.wavelength
# access the 1D array of wavelengths
print(f"The {r.nwave} wavelengths...")
print(f" have a shape of {r.wavelength.shape},")
print(f" a type of {type(r.wavelength)},")
print(f" units of {r.wavelength.unit}, and")
print(f" a dtype of {r.wavelength.dtype}")
The 231 wavelengths... have a shape of (231,), a type of <class 'astropy.units.quantity.Quantity'>, units of micron, and a dtype of float64
The .time
property is a 1D array containing the time associated with the flux array. It is a an astropy
Quantity, with units of time associated with it. (Watch out! At some point we may switch it over to being an actual astropy Time
object.)
r.time
# access the 1D array of times
print(f"The {r.ntime} times...")
print(f" have a shape of {r.time.shape},")
print(f" a type of {type(r.time)},")
print(f" units of {r.time.unit}, and")
print(f" a dtype of {r.time.dtype}")
The 150 times... have a shape of (150,), a type of <class 'astropy.units.quantity.Quantity'>, units of d, and a dtype of float64
The .flux
property is a 2D array containing the flux associated with each combination of wavelength (row, axis 0) and time (column, axis 1). It can be an astropy
Quantity with a variety of possible units ($\mathrm{photons}$, $\mathrm{W/m^2/nm}$, $\mathrm{MJy/sr}$, ...), or it can be unitless and normalized to be close to 1.
r.flux
array([[0.99467733, 0.99407134, 0.97801359, ..., 0.99181515, 1.01123091, 0.99615536], [1.00248961, 0.99496649, 1.00435501, ..., 0.99173337, 0.99282459, 0.99595508], [1.00258377, 1.00731383, 0.99304558, ..., 0.99999962, 0.99241541, 0.98929456], ..., [0.99352616, 1.0030173 , 0.98842732, ..., 0.98965077, 1.00741202, 1.01430653], [0.99076354, 1.00347768, 0.98618376, ..., 1.0079956 , 0.99430293, 1.00099274], [0.99305504, 1.00361437, 0.99024628, ..., 0.98297773, 1.00365696, 0.98502295]])
# access the 2D array of fluxes
print(f"The {r.nflux} fluxes...")
print(f" have a shape of {r.flux.shape},")
print(f" a type of {type(r.flux)},")
print(f" a dtype of {r.flux.dtype}")
The 34650 fluxes... have a shape of (231, 150), a type of <class 'numpy.ndarray'>, a dtype of float64
The .uncertainty
property is a 2D array containing the uncertainty associated with each flux point. It should have the same units and scale as flux
, whatever those are.
r.uncertainty
array([[0.01, 0.01, 0.01, ..., 0.01, 0.01, 0.01], [0.01, 0.01, 0.01, ..., 0.01, 0.01, 0.01], [0.01, 0.01, 0.01, ..., 0.01, 0.01, 0.01], ..., [0.01, 0.01, 0.01, ..., 0.01, 0.01, 0.01], [0.01, 0.01, 0.01, ..., 0.01, 0.01, 0.01], [0.01, 0.01, 0.01, ..., 0.01, 0.01, 0.01]])
# access the 2D array of times
print(f"The {r.nflux} uncertainties...")
print(f" have a shape of {r.uncertainty.shape},")
print(f" a type of {type(r.uncertainty)},")
print(f" a dtype of {r.uncertainty.dtype}")
The 34650 uncertainties... have a shape of (231, 150), a type of <class 'numpy.ndarray'>, a dtype of float64
The .ok
property is a 2D array indicating whether a particular flux data point is good (True
) or bad (False
). It's a place to keep track of what data should be ignored when fitting or visualizing.
r.ok
array([[ True, True, True, ..., True, True, True], [ True, True, True, ..., True, True, True], [ True, True, True, ..., True, True, True], ..., [ True, True, True, ..., True, True, True], [ True, True, True, ..., True, True, True], [ True, True, True, ..., True, True, True]])
# access the 2D array of times
print(f"The {r.nflux} `ok` mask values...")
print(f" have a shape of {r.ok.shape},")
print(f" a type of {type(r.ok)},")
print(f" a dtype of {r.ok.dtype}")
The 34650 `ok` mask values... have a shape of (231, 150), a type of <class 'numpy.ndarray'>, a dtype of bool
Finally, there is a suggest optional .model
property that contains a 2D array indicating the model values associated with each point. Rainbow
objects should still work fine with no model
defined, but having one present expands options for visualization and calculation. In our simulation, the model is simply 1 everywhere.
r.model
array([[1., 1., 1., ..., 1., 1., 1.], [1., 1., 1., ..., 1., 1., 1.], [1., 1., 1., ..., 1., 1., 1.], ..., [1., 1., 1., ..., 1., 1., 1.], [1., 1., 1., ..., 1., 1., 1.], [1., 1., 1., ..., 1., 1., 1.]])
# access the 2D array of fluxes
print(f"The {r.nflux} model values...")
print(f" have a shape of {r.model.shape},")
print(f" a type of {type(r.model)},")
print(f" a dtype of {r.model.dtype}")
The 34650 model values... have a shape of (231, 150), a type of <class 'numpy.ndarray'>, a dtype of float64
With these 5-6 six basic components (time
, wavelength
, flux
, uncertainty
, ok
, and maybe model
), we can build up some delightfully complicated calculations and visualizations for all ๐ objects.