Module stixdcpy.energylut

This script provides APIs to retrieve energy calibration data from STIX data center ,and some tools to display the data Author: Hualin Xiao (hualin.xiao@fhnw.ch) Date: Sep. 1, 2021

Expand source code
#!/usr/bin/python
"""
    This script provides APIs to retrieve energy  calibration data from STIX data center  ,and some tools to display the data
    Author: Hualin Xiao (hualin.xiao@fhnw.ch)
    Date: Sep. 1, 2021

"""
from pprint import pprint

import numpy as np
from stixdcpy.logger import logger
from stixdcpy import io as sio
from stixdcpy.net import JSONRequest as jreq
from stixdcpy.transmission import Transmission


class EnergyLUT(sio.IO):
    def __init__(self, data):
        self.data = data
        self.tran = Transmission()

    @classmethod
    def request(cls, utc):
        data = jreq.fetch_elut(utc)
        '''
        data structure
        {'data':{
                    'onboard':self.onboard_elut, 
                    'calibration':self.calibration_run_elut,
                    'true_energy_bin_edges':self.true_energy_bin_edges,
                    'energy_bin_edges':NOMINAL_EBIN_EDGES,
                },
                'info': self.info(),
                }
                '''
        return cls(data)

    @classmethod
    def from_npy(cls, filename):
        with np.load(filename, allow_picke=True) as data:
            elut_data = data.item()['elut']
            cls(elut_data)

    def save_npy(self, filename):
        np.save(filename, {'elut': self.data})

    def info(self):
        try:
            pprint(self.data['info'])
            # pprint('Pixel 0 true energy bin  edges: ')
            # pprint(self.get_pixel_true_ebins(0))
            # pprint('...')

        except KeyError as e:
            logger.error(e)

    def __getattr__(self, name):
        if name == 'data':
            return self.data['data']

    def get_data(self):
        return self.data['data']

    def get_calibration_data(self):
        """Get calibration data

        Returns:
            result: dict, or None
                Calibration data python dictionary if success or None if failed 
        """
        try:
            return self.data['data']['calibration']
        except Exception as e:
            print(e)
            return None

    def get_onboard_elut(self):
        try:
            return self.data['data']['onboard']
        except (KeyError, TypeError):
            logger.error('Failed to retrieve onboard elut!')
            return None

    def get_pixel_true_ebins(self, pixel):
        """Get the real energy bin ranges for the given pixel

        Args:
            pixel (int): pixel ID ranging from 0...383

        Returns:
            ebins: numpy.array
                Lower and upper bounds of 32 energy bins
        """        
        true_ebins = np.array(self.data['data']['true_energy_bin_edges'])
        pixel_ebins = true_ebins[:, pixel]  # 33 x 384 retrieve the column
        ebins = np.column_stack((pixel_ebins[:-1], pixel_ebins[1:]))
        return ebins

    def get_pixel_ebins_transmissions(self):
        """
        Get transmission for pixels at a given time
        Args: 
            None
        Returns:
            A numpy array with a shape of 32 x12 x 32.  The three dimensions indicate detector, pixel, and transmission for 32 energy channels.
            The transmission for the last energy bin set to 0
            """
        true_ebins = np.array(
            self.data['data']
            ['true_energy_bin_edges'])  # an 2d array: 33 x 384
        trans = np.zeros((32, 12, 32))
        for i in range(32):
            for j in range(12):
                ipix = i * 12 + j
                pixel_ebins = true_ebins[:, ipix]  # retrieve the column
                ebins = np.column_stack((pixel_ebins[:-1], pixel_ebins[1:]))
                ebins[0][0] = np.finfo(float).eps
                ebins[31][1] = 300

                trans[i][j] = self.tran.get_detector_transmission(
                    i, ebins, attenuator=False)
        trans[:, :,
              31] = 0  # set the transmission for the last energy bin to 0
        trans[:, :,
              0] = 0  # set the transmission for the first energy bin to 0
        return trans

Classes

class EnergyLUT (data)

Base object

Expand source code
class EnergyLUT(sio.IO):
    def __init__(self, data):
        self.data = data
        self.tran = Transmission()

    @classmethod
    def request(cls, utc):
        data = jreq.fetch_elut(utc)
        '''
        data structure
        {'data':{
                    'onboard':self.onboard_elut, 
                    'calibration':self.calibration_run_elut,
                    'true_energy_bin_edges':self.true_energy_bin_edges,
                    'energy_bin_edges':NOMINAL_EBIN_EDGES,
                },
                'info': self.info(),
                }
                '''
        return cls(data)

    @classmethod
    def from_npy(cls, filename):
        with np.load(filename, allow_picke=True) as data:
            elut_data = data.item()['elut']
            cls(elut_data)

    def save_npy(self, filename):
        np.save(filename, {'elut': self.data})

    def info(self):
        try:
            pprint(self.data['info'])
            # pprint('Pixel 0 true energy bin  edges: ')
            # pprint(self.get_pixel_true_ebins(0))
            # pprint('...')

        except KeyError as e:
            logger.error(e)

    def __getattr__(self, name):
        if name == 'data':
            return self.data['data']

    def get_data(self):
        return self.data['data']

    def get_calibration_data(self):
        """Get calibration data

        Returns:
            result: dict, or None
                Calibration data python dictionary if success or None if failed 
        """
        try:
            return self.data['data']['calibration']
        except Exception as e:
            print(e)
            return None

    def get_onboard_elut(self):
        try:
            return self.data['data']['onboard']
        except (KeyError, TypeError):
            logger.error('Failed to retrieve onboard elut!')
            return None

    def get_pixel_true_ebins(self, pixel):
        """Get the real energy bin ranges for the given pixel

        Args:
            pixel (int): pixel ID ranging from 0...383

        Returns:
            ebins: numpy.array
                Lower and upper bounds of 32 energy bins
        """        
        true_ebins = np.array(self.data['data']['true_energy_bin_edges'])
        pixel_ebins = true_ebins[:, pixel]  # 33 x 384 retrieve the column
        ebins = np.column_stack((pixel_ebins[:-1], pixel_ebins[1:]))
        return ebins

    def get_pixel_ebins_transmissions(self):
        """
        Get transmission for pixels at a given time
        Args: 
            None
        Returns:
            A numpy array with a shape of 32 x12 x 32.  The three dimensions indicate detector, pixel, and transmission for 32 energy channels.
            The transmission for the last energy bin set to 0
            """
        true_ebins = np.array(
            self.data['data']
            ['true_energy_bin_edges'])  # an 2d array: 33 x 384
        trans = np.zeros((32, 12, 32))
        for i in range(32):
            for j in range(12):
                ipix = i * 12 + j
                pixel_ebins = true_ebins[:, ipix]  # retrieve the column
                ebins = np.column_stack((pixel_ebins[:-1], pixel_ebins[1:]))
                ebins[0][0] = np.finfo(float).eps
                ebins[31][1] = 300

                trans[i][j] = self.tran.get_detector_transmission(
                    i, ebins, attenuator=False)
        trans[:, :,
              31] = 0  # set the transmission for the last energy bin to 0
        trans[:, :,
              0] = 0  # set the transmission for the first energy bin to 0
        return trans

Ancestors

Static methods

def from_npy(filename)
Expand source code
@classmethod
def from_npy(cls, filename):
    with np.load(filename, allow_picke=True) as data:
        elut_data = data.item()['elut']
        cls(elut_data)
def request(utc)
Expand source code
@classmethod
def request(cls, utc):
    data = jreq.fetch_elut(utc)
    '''
    data structure
    {'data':{
                'onboard':self.onboard_elut, 
                'calibration':self.calibration_run_elut,
                'true_energy_bin_edges':self.true_energy_bin_edges,
                'energy_bin_edges':NOMINAL_EBIN_EDGES,
            },
            'info': self.info(),
            }
            '''
    return cls(data)

Methods

def get_calibration_data(self)

Get calibration data

Returns

result
dict, or None Calibration data python dictionary if success or None if failed
Expand source code
def get_calibration_data(self):
    """Get calibration data

    Returns:
        result: dict, or None
            Calibration data python dictionary if success or None if failed 
    """
    try:
        return self.data['data']['calibration']
    except Exception as e:
        print(e)
        return None
def get_data(self)
Expand source code
def get_data(self):
    return self.data['data']
def get_onboard_elut(self)
Expand source code
def get_onboard_elut(self):
    try:
        return self.data['data']['onboard']
    except (KeyError, TypeError):
        logger.error('Failed to retrieve onboard elut!')
        return None
def get_pixel_ebins_transmissions(self)

Get transmission for pixels at a given time Args: None

Returns

A numpy array with a shape of 32 x12 x 32. The three dimensions indicate detector, pixel, and transmission for 32 energy channels. The transmission for the last energy bin set to 0

Expand source code
def get_pixel_ebins_transmissions(self):
    """
    Get transmission for pixels at a given time
    Args: 
        None
    Returns:
        A numpy array with a shape of 32 x12 x 32.  The three dimensions indicate detector, pixel, and transmission for 32 energy channels.
        The transmission for the last energy bin set to 0
        """
    true_ebins = np.array(
        self.data['data']
        ['true_energy_bin_edges'])  # an 2d array: 33 x 384
    trans = np.zeros((32, 12, 32))
    for i in range(32):
        for j in range(12):
            ipix = i * 12 + j
            pixel_ebins = true_ebins[:, ipix]  # retrieve the column
            ebins = np.column_stack((pixel_ebins[:-1], pixel_ebins[1:]))
            ebins[0][0] = np.finfo(float).eps
            ebins[31][1] = 300

            trans[i][j] = self.tran.get_detector_transmission(
                i, ebins, attenuator=False)
    trans[:, :,
          31] = 0  # set the transmission for the last energy bin to 0
    trans[:, :,
          0] = 0  # set the transmission for the first energy bin to 0
    return trans
def get_pixel_true_ebins(self, pixel)

Get the real energy bin ranges for the given pixel

Args

pixel : int
pixel ID ranging from 0…383

Returns

ebins
numpy.array Lower and upper bounds of 32 energy bins
Expand source code
def get_pixel_true_ebins(self, pixel):
    """Get the real energy bin ranges for the given pixel

    Args:
        pixel (int): pixel ID ranging from 0...383

    Returns:
        ebins: numpy.array
            Lower and upper bounds of 32 energy bins
    """        
    true_ebins = np.array(self.data['data']['true_energy_bin_edges'])
    pixel_ebins = true_ebins[:, pixel]  # 33 x 384 retrieve the column
    ebins = np.column_stack((pixel_ebins[:-1], pixel_ebins[1:]))
    return ebins
def info(self)
Expand source code
def info(self):
    try:
        pprint(self.data['info'])
        # pprint('Pixel 0 true energy bin  edges: ')
        # pprint(self.get_pixel_true_ebins(0))
        # pprint('...')

    except KeyError as e:
        logger.error(e)
def save_npy(self, filename)
Expand source code
def save_npy(self, filename):
    np.save(filename, {'elut': self.data})

Inherited members