""" IMA extra processing module.
**Differential flux**
IMA extra data (:class:`irfpy.mima.imaextra.ImaExtra`) is in counts.
Here the IMA extra data is converted to the differential flux.
- Simple conversion (:func:`simple_jH`, :func:`simple_jO`, or :class:`SimpleConvCJ`)
Simple conversion follows the standard definition of the G-factor,
and no quality control is implemented.
"""
import numpy as _np
from irfpy.mima import gfactor0 as _gfactor
[docs]class SimpleConvCJ:
""" Claculating conversion between counts, differential flux, and moment for IMA extra
Users can also use high-level functions: :func:`simple_jH` or :func:`simple_jO`
>>> from irfpy.mima import imaextra
>>> import datetime
>>> t0 = datetime.datetime(2011, 3, 3, 14)
>>> t1 = datetime.datetime(2011, 3, 3, 15)
>>> imaextradata = imaextra.getImaExtra(t0, t1)
>>> print(imaextradata.ndat)
18
>>> converter = SimpleConvCJ(imaextradata)
>>> print(converter.energytable().shape)
(96, 18)
>>> jHr = converter.jHreal()
>>> print(jHr.shape)
(16, 96, 16, 18)
>>> import numpy as np
>>> print('{:.2f}'.format(np.nanmax(jHr)))
173704.77
>>> jG = converter.jGhost()
>>> print('{:.2f}'.format(np.nanmax(jG)))
32947337.26
>>> jO = converter.jO()
>>> print('{:.2f}'.format(np.nanmax(jO)))
42098.34
"""
__etblcache = {} # Cache of energy table.
__eeprom = {0: 0, 1: 1, 2: 15} # Conversion from EXTRA ETableN to EEPROM
dPhi = _np.deg2rad(22.5)
dt = 0.1209
def __init__(self, imaextraobj, lowest_ene_P=300, lowest_ene_G=300, lowest_ene_O=30):
""" Initialize the simple conversion class.
:param imaextraobj: IMAEXTRA object
:keyword lowest_ene_P: Lowest energy of proton to be considered
:keyword lowest_ene_G: Lowest energy of ghost ot be considered
:keyword lowest_ene_O: Lowest energy of oxygen to be considered
:type imaextraobj: :class:`irfpy.mima.imaextra.ImaExtra`
"""
self.imaex = imaextraobj # IMAEXTRA data
self.e0h = lowest_ene_P
self.e0g = lowest_ene_G
self.e0o = lowest_ene_O
def _energy_table(self, etablen):
from irfpy.mima import energy as _energy
try:
return SimpleConvCJ.__etblcache[etablen]
except KeyError:
etbl = _np.ma.masked_less(_energy.get_default_table_extra(etablen, keep_negative=True), 0)
SimpleConvCJ.__etblcache[etablen] = etbl
return etbl
[docs] def energytable(self, lowest_energy=0):
""" Return the time series of energy table
:return: (96, N) array of energy table in eV.
"""
etbl = self.imaex.data['ETableN']
e = _np.ma.masked_less([self._energy_table(_) for _ in etbl], lowest_energy)
e = _np.transpose(e, (1, 0))
return e
def _create_glfactor_table(self, species):
""" Return the time series of GL factor table.
:return: (96, N) array of GL factor in cm2 rad eV/eV
"""
gLlist = []
for _ti in range(self.imaex.ndat):
etablen = self.imaex.data['ETableN'][_ti]
eeprom = SimpleConvCJ.__eeprom[etablen]
pacc = self.imaex.data['Pacc'][_ti]
gL = _gfactor.GL_extra.get(species, eeprom, pacc)
gLlist.append(gL)
gLlist = _np.ma.masked_less(gLlist, 0)
gLlist = _np.transpose(gLlist, (1, 0))
return gLlist
[docs] def j(self, species, lowest_energy=0):
""" Calculate the differential flux for a specific species.
:param species: Species. Either of ("Proton", "ProtonGhost", or "Oxygen").
:return: An array of differential flux in [AEPT] order. Unit is in ``/cm2 s sr eV``
"""
if species in ("Proton"):
proton_counts = self.imaex.getHpSpec() # [AEPT] order
elif species in ("ProtonGhost"):
proton_counts = self.imaex.getHGspec()
elif species in ("Oxygen", "Heavy"):
proton_counts = self.imaex.getHeavySpec()
else:
raise ValueError("Species {} unknown".format(species))
glfactor_time = self._create_glfactor_table(species) # (E96, T) order
energytable_time = self.energytable(lowest_energy=lowest_energy) # (E96, T) order
gfactor_time = _np.ma.masked_less(glfactor_time * self.dPhi, 0) # (E96, T) order
j_proton = proton_counts / (gfactor_time * energytable_time * self.dt)[_np.newaxis, :, _np.newaxis, :]
return j_proton.filled(_np.nan)
[docs] def jHreal(self):
""" Calculate the proton differential flux (real signal).
:return: An array of differential flux in [AEPT] order. Unit is in ``/cm2 s sr eV``
"""
return self.j("Proton", lowest_energy=self.e0h)
[docs] def jGhost(self):
""" Calcuate the proton differential flux from ghost signal.
:return: An array of differential flux in [AEPT] order.
"""
return self.j("ProtonGhost", lowest_energy=self.e0g)
[docs] def jO(self):
return self.j("Oxygen", lowest_energy=self.e0o)
[docs]def simple_jH(imaextraobj, lowest_energy=300):
""" Calculate the differential flux of proton.
:param imaextraobj: IMAEXTRA object.
:type imaextraobj: :class:`irfpy.imaextra.ImaExtra`
:param lowest_energy: Lowest energy to be used.
:return: An array of differential flux. [AEPT] order.
"""
return SimpleConvCJ(imaextraobj).jH(lowest_energy=lowest_energy)
[docs]def simple_jG(imaextraobj, lowest_energy=300):
""" Calculate the differential flux of proton ghost.
:param imaextraobj: IMAEXTRA object.
:type imaextraobj: :class:`irfpy.imaextra.ImaExtra`
:param lowest_energy: Lowest energy to be used.
:return: An array of differential flux. [AEPT] order.
"""
return SimpleConvCJ(imaextraobj).jG(lowest_energy=lowest_energy)
[docs]def simple_jO(imaextraobj, lowest_energy=30):
""" Calculate the differential flux of proton.
:param imaextraobj: IMAEXTRA object.
:type imaextraobj: :class:`irfpy.imaextra.ImaExtra`
:param lowest_energy: Lowest energy to be used.
:return: An array of differential flux. [AEPT] order.
"""
return SimpleConvCJ(imaextraobj).jO(lowest_energy=lowest_energy)