Source code for irfpy.swim.swim_mass

''' Module for SWIM mass analysis
'''

import logging
import datetime

import numpy as np

import irfpy.util.utc as utc
from irfpy.util.julday import JdObject

from irfpy.swim.swim_cache import SwimDataCache

class __swimcache:
    instance = None
    @classmethod
    def cache(cls):
        if cls.instance is None:
            cls.instance = SwimDataCache()
        return cls.instance
        


logger = logging.getLogger('swim_mass')
logger.setLevel(logging.DEBUG)


[docs]def getobstime(orbit=None, timerange=None): ''' Return the observation time of SWIM mass data. :keyword orbit: Returns the obseration time for corresponding orbit number :keyword timerange: Time range to be examined. Either ``orbit`` or ``timerange`` should be specified. >>> o939 = getobstime(orbit=939) >>> print(len(o939)) 885 >>> t0 = datetime.datetime(2009, 1, 25, 12, 0, 0) >>> t1 = datetime.datetime(2009, 1, 25, 15, 0, 0) >>> o2 = getobstime(timerange=[t0, t1]) >>> print(len(o2)) 777 ''' return __swimcache.cache().getObstime(orbit=orbit, timerange=timerange)
[docs]def getdata(t, filter=[]): ''' Get the data. :param t: Time. :type t: Type supported by ``irfpy.util.utc.convert``. :keyword filter: Filter to apply. Usually a function defined in :class:`filter` class. >>> t0 = datetime.datetime(2009, 1, 25, 14) >>> data = getdata(t0) >>> mspec = data.getData() # Mass spectra data >>> print(mspec.shape) (16, 16, 32) >>> print(mspec.sum()) # Using v3.2 database. 1538.0 If you use filter to filter out one counts, the value should change. >>> mspec_ocr = getdata(t0, filter=[filter.remove_one_count]).getData() >>> print(mspec_ocr.shape) (16, 16, 32) >>> print(mspec_ocr.sum()) 1409.0 You may remove one count event using :meth:`filter.remove_one_count_event_l1`. >>> mspec_l1 = getdata(t0, filter=[filter.remove_one_count_event_l1]).getData() >>> print(mspec_l1.shape) (16, 16, 32) >>> print(mspec_l1.sum()) 1528.0 ''' t0 = utc.convert(t, datetime.datetime) matx_jdo = __swimcache.cache().getMassMatrix(t0) matx_jd = matx_jdo.getJd() matx = matx_jdo.getData() for f in filter: matx = f(matx) return JdObject(matx_jd, matx)
[docs]def statusCache(): return __swimcache.cache().statusCache()
[docs]def clearCache(): logging.debug('Clearing cache') __swimcache.cache().clearCache()
[docs]class filter: ''' Collection of SWIM mass matrix fileters. SWIM mass matrix filter is a function that get raw E16xD16xM32 matrix (``np.array``) to return the matrix that has the same shape. '''
[docs] @classmethod def remove_one_count(cls, raw): ''' As one count is not statistically siginificant, those counts are removed. # Emulate the raw counts that consists fully with 1. >>> raw = np.ones([16, 16, 32]) >>> print(raw.sum()) 8192.0 # If the filter is applied, everything should be zero. >>> proc = filter.remove_one_count(raw) >>> print(proc.sum()) 0.0 >>> print(raw.sum()) 8192.0 ''' return np.where(raw <= 1, 0, raw)
[docs] @classmethod def remove_one_count_event_l1(cls, raw): ''' Remove one count event with L1 (empirical) suppression. One count event is not same as 1 count in the usual sense. This is an instrumental origin, appears strange count in a specific tof channel. This can also be referred to swimmassspectrum.pro that MW developed originally in IDL. See https://butler.irf.se/sara-trac/file/SARA/swim_mass/swimmassspectrum.pro also. The original procedure contains the comment like: ``define elements where one-count events can happen empiricaly this is probably temperature independent, but takes less events away`` ''' # Copy and paste from MW's implementation. Note: order is M, E, D maskpos= [[1,14,0],[10,9,0],[11,9,0],[11,10,0],[12,10,0],[18,6,0],[19,6,0],[20,6,0],[28,5,0],[24,9,0],[29,9,0], [23,9,1],[24,9,1],[11,10,1],[12,10,1], [10,9,2],[11,9,2],[11,10,2],[12,10,2],[23,9,2],[24,9,2], [27,11,2],[28,11,2],[29,11,2],[28,5,2], [10,9,3],[11,9,3],[11,10,3],[12,10,3],[23,9,3],[30,12,3],[29,12,3],[24,9,3], [25,9,3], [10,9,4],[11,9,4],[11,10,4],[12,10,4],[27,11,4],[28,11,4],[30,12,4],[29,6,4], [27,8,4], [27,11,5], [28,11,5],[24,9,5], [25,9,5], [1,15,6],[12,10,6],[23,9,6],[24,9,6], [10,9,7],[11,9,7],[11,10,7],[12,10,7],[16,3,7],[17,4,7],[18,4,7],[18,6,7],[19,6,7],[20,6,7], [30,6,9], [19,6,9], [15,2,10],[16,2,10],[20,7,10],[21,7,10],[25,10,10],[26,10,10],[30,6,10],[29,12,10],[30,12,10], [25,10,11],[26,10,11],[30,6,11], [25,10,12],[26,10,12], [15,2,13],[16,2,13],[26,4,13],[27,4,13], [25,10,14],[26,10,14],[27,10,14],[11,10,14],[12,10,14], [10,9,15],[11,9,15],[11,10,15],[12,10,15],[24,9,15],[1,14,15]] maskpos = np.array(maskpos) # shape is 92, 3 proc = raw.copy() for m, e, d in maskpos: proc[e, d, m] = 0 return proc
[docs] @classmethod def remove_one_count_event_l2(cls, raw): ''' Remove one count event with L2 (soft) suppression. One count event is not same as 1 count in the usual sense. This is an instrumental origin, appears strange count in a specific tof channel. This can also be referred to swimmassspectrum.pro that MW developed originally in IDL. See https://butler.irf.se/sara-trac/file/SARA/swim_mass/swimmassspectrum.pro also. The original procedure contains the comment like: ``Define elements where one-count events can happen analyticaly: this is temperature independent, but takes sometimes too many counts away`` ''' # SWIM DPU processing table # ETOF for pacc 2 (was always used) etof = np.array([514,527,543,563,586,614,648,687,733,787,850,923,1006,1101,1210,1333]) # Mask for pacc 2 mask = np.array([7,7,7,7,7,7,7,7,7,7,7,7,7,6,6,6]) # I do not yet understand what it means. ### MASK = MASK>7 ; cases where mask is 6 do not seem to generate one-ocunt-events. mask = np.where(mask < 7, 7, mask) proc = raw.copy() for iE in range(16): for iM in range(32): tof = (iM * 2. ** 19) / etof[iE] / (2 ** mask[iE]) if (tof >= 112 and tof <= 127 or tof >= 52 and tof <= 63 or tof >= 176 and tof <= 191): for iD in range(16): proc[iE, iD, iM] = 0 return proc
[docs] @classmethod def remove_one_count_event_l3(cls, raw): ''' Remove one count event with L3 (strong) suppression. One count event is not same as 1 count in the usual sense. This is an instrumental origin, appears strange count in a specific tof channel. This can also be referred to swimmassspectrum.pro that MW developed originally in IDL. See https://butler.irf.se/sara-trac/file/SARA/swim_mass/swimmassspectrum.pro also. The original procedure contains the comment like: ``Define elements where one-count events can happen analyticaly: this is temperature independent, but takes sometimes too many counts away`` ''' # ; SWIM DPU processing tables # ; ETOF for pacc 2 (was always used) # ETOF = [514,527,543,563,586,614,648,687,733,787,850,923,1006,1101,1210,1333] etof = np.array([514,527,543,563,586,614,648,687,733,787,850,923,1006,1101,1210,1333]) # ; MASK for pacc 2 # MASK = [7,7,7,7,7,7,7,7,7,7,7,7,7,6,6,6] # MASK = MASK>7 ; cases where mask is 6 do not seem to generate one-ocunt-events. # Mask for pacc 2 mask = np.array([7,7,7,7,7,7,7,7,7,7,7,7,7,6,6,6]) # I do not yet understand what it means. ### MASK = MASK>7 ; cases where mask is 6 do not seem to generate one-ocunt-events. mask = np.where(mask < 7, 7, mask) #for iD=0,maxe-1 do begin # for iE=0,maxe-1 do begin # for iM=0,maxm-1 do begin # tof = (iM*2.^19)/ETOF[iE]/(2^MASK[iE]) # tofbg[iM,iE,iD] = (tof gt 52) && $ # ( ((floor((tof-3) / 16) mod 2) eq 1) || $ # ((floor((tof-1) / 16) mod 2) eq 1) )? 1 : 0 # endfor # endfor #endfor proc = raw.copy() for ie in range(16): for im in range(32): tof = (im * 2. ** 19) / etof[ie] / (2 ** mask[ie]) ifbg = (tof > 52) and ( ((np.floor((tof-3) / 16) % 2) == 1) or ((np.floor((tof-1) / 16) % 2) == 1) ) if ifbg: for id in range(16): proc[ie, id, im] = 0 return proc
[docs] @classmethod def remove_one_count_event_l4(cls, raw): ''' Remove one count event with L4 (full) suppression. One count event is not same as 1 count in the usual sense. This is an instrumental origin, appears strange count in a specific tof channel. This can also be referred to swimmassspectrum.pro that MW developed originally in IDL. See https://butler.irf.se/sara-trac/file/SARA/swim_mass/swimmassspectrum.pro also. The original procedure contains the comment like: ; Define elements where one-count events can happen analyticaly: ; this is temperature independent, but takes sometimes too many counts away ''' # ; SWIM DPU processing tables # ; ETOF for pacc 2 (was always used) # ETOF = [514,527,543,563,586,614,648,687,733,787,850,923,1006,1101,1210,1333] etof = np.array([514,527,543,563,586,614,648,687,733,787,850,923,1006,1101,1210,1333]) # ; MASK for pacc 2 # MASK = [7,7,7,7,7,7,7,7,7,7,7,7,7,6,6,6] # MASK = MASK>7 ; cases where mask is 6 do not seem to generate one-ocunt-events. # Mask for pacc 2 mask = np.array([7,7,7,7,7,7,7,7,7,7,7,7,7,6,6,6]) # I do not yet understand what it means. ### MASK = MASK>7 ; cases where mask is 6 do not seem to generate one-ocunt-events. mask = np.where(mask < 7, 7, mask) #MASK = MASK>7 ; cases where mask is 6 do not seem to generate one-ocunt-events. #for iD=0,maxe-1 do begin # for iE=0,maxe-1 do begin # for iM=0,maxm-1 do begin # tof = (iM*2.^19)/ETOF[iE]/(2^MASK[iE]) # tofbg[iM,iE,iD] = (tof gt 48) ? 1 : 0 # endfor # endfor #endfor proc = raw.copy() for ie in range(16): for im in range(32): tof = (im * 2. ** 19) / etof[ie] / (2 ** mask[ie]) ifbg = (tof > 48) if ifbg: for id in range(16): proc[ie, id, im] = 0 return proc