# xrtpy/aiapy Common API Discussion
PyHC Meeting, 5/18/2023
From previous discussion: https://docs.google.com/presentation/d/1WQyYBwFqu4FGfcRTr11sNQj2O5PiYuJJTak45QjiPKk/edit?usp=sharing
Nick's previous pr: https://github.com/sunpy/sunkit-instruments/pull/98/files
## Theory
We want to compute temperature response for an instrument with some wavelength bandpass $c$,
$$
K_c(T) = \int\mathrm{d}\lambda S(\lambda,T)R_c(\lambda),\quad[\mathrm{DN}\,\mathrm{cm}^5\,\mathrm{pix}^{-1}\,\mathrm{s}^{-1}]
$$
where,
- $S(\lambda,T)$ spectra [photon cm$^3$ s$^{-1}$ sr$^{-1}$ Å$^{-1}$]
- $R_c(\lambda)$ wavelength response function for channel $c$ [cm$^2$ DN sr photon$^{-1}$ pixel$^{-1}$]
We need to come up with a common API for computing $S$ and $R_c$.
Both `aiapy` and `xrtpy` already have a conception for $R_c$ but it is slightly different.
Coming up with $S$ is a bit more challenging because there are more possible variations and it is not yet clear how to parameterize it.
## Joe's conception
```python=
class dumb_channel(object):
def __init__(self, waves, ea, time=0.0):
self.waves=waves
self.ea=ea
self.time=time
def just_give_me_the_dumb_ea(self):
return self.waves,self.ea
class dumb_tresp(object):
def __init__(self, waves, temp, iso_spectra):
self.waves=waves
self.temp=temp
self.ispec = iso_spectra
self.n_atoms = iso_spectra.shape[0]
self.nt = iso_spectra.shape[1]
self.nw = iso_spectra.shape[2]
self.dw = waves[1]-waves[0]
def compute(self, channel, abundances=None):
if(abundances is None): abundances = np.ones(self.n_atoms)
tresp = np.zeros(self.nt)
ea_waves, ea = channel.just_give_me_the_dumb_ea()
ea_interp = np.interp(self.waves,ea_waves,ea)
for i in range(0,self.nt):
for j in range(0,self.n_atoms):
tresp[i] += np.sum(ea_interp*self.ispec[j,i]*self.dw*abundances[j])
return self.temp, tresp
```
## More general/abstract interface
```python=
class AbstractChannel:
def ccd_gain_left(self) -> u.electron / u.DN:...
def effective_area(self): # ?????
class AbstractSpectralModel:
def __init__(self, wavelength, flux, temperature): ...
#Different variations of abundance
def
class AbstractTemperatureResponse: # do we need this?
def __init__(self, obs_date, spectral_model: AbstractSpectralModel): ...
# will need to define what spectral_model means
def wavelength(self) -> u.Angstrom: ...
def effective_area(self) -> u.cm ** 2: ...
def temperature_response(self) -> u.DN * u.cm**5 / (u.s * u.pix): ...
# units from xrtpy
def temperature_response(
spectral_model: AbstractSpectralModel,
channel: AbstractChannel,
temperature: Optional[u.Quantity[u.K]] = None,
):
...
```
```pycon=
>>> channel = Channel(...)
>>> spectral_model = SpectralModel(...)
>>> tr = TemperatureResponse(channel, spectral_model)
>>> temperature_response = tr.temperature_response() # or
>>> temperature_response = temperature_response(spectral_model, channel)
```
## Open Questions
- how should the temperature response be calculated
- object? Jon: makes sense to have temperature response separate since it combines the effective area and spectra
- method on channel?
- or separate function?
- how do we deal with time dependence?
- input to Channel object
- or input to the `effective_area` method?
## Notes
- Adding unit annotations will help disambiguate between the different definitions for effective area, etc.
- Aside: Follow up with definitionns for `PhysicalType` objects in `astropy.units` to sort of standardize this?
- `ElementalAbundances` in `plasmapy.particles`? Already in `IonizationStateCollection`.
- Will's thought: could a `temperature_response` function (or object) live upstream? Is there any reason to implement it in each package? If the respective classses expose the right bits of data, it is just a matter of computing the integral above
## Vocabulary
- *effective area*: function of wavelength, must be in units of area; does not include any time-dependent corrections [cm$^2$]
- *gain*: function of wavelength, conversion between DN and photons [DN photon$^{-1}$]
- *plate scale*: steradians per pixel [sr pixel$^{-1}$]
- *wavelength response*: product of effective area, gain, and plate scale that may also include some time-dependent correction; essentially this should include every instrument dependent parameter in the integrand in the above integral [cm$^2$ DN sr photon$^{-1}$ pixel$^{-1}$]
## Conclusions
- It is helpful to have a `Channel` class
- Proposed that `xrtpy` can move `EffectiveAreaFundamental` to a method of `Channel` rather than a standalone object
- Proposed that `xrtpy` can move `TemperatureresponseFundamental` to a standalone function
- It is helpful to have a `SpectralModel` class
- Implement `temperature_response` in `sunkit-instruments` directly? If the interfaces are well-defined, then it could be the same across instruments.
-