Wrapping My Head Around LEISA data

Ben Kamphaus, PhD

FITS data can be a pain to work with, especially when it's data outside of your particular specialty (my background is remote sensing for sensors pointed at earth, not other planets), so this notebook shows some of the head-to-desk, brute force data wrangling involved in figuring out what's going on.


In [1]:
# our routine imports
import pyfits
import numpy as np
from matplotlib import pyplot as plt

In [2]:
!ls data/20070303_003520/


lsb_0035209319_0x53c_sci_1.fit	lsb_0035209319_0x53c_sci_1.lbl

In [7]:
fits_file = 'data/20070303_003520/lsb_0035209319_0x53c_sci_1.fit'
pyfits.info(fits_file)


Filename: data/20070303_003520/lsb_0035209319_0x53c_sci_1.fit
No.    Name         Type      Cards   Dimensions   Format
0    PRIMARY     PrimaryHDU     285   (256, 256, 792)   float32   
1    WAVELENGTHS  ImageHDU         9   (256, 256, 2)   float32   
2    ANGLES      ImageHDU         9   (256, 256, 3)   float32   
3    FLATFIELD   ImageHDU         8   (256, 256)   float32   
4    CALIBRATION  ImageHDU         9   (256, 256, 2)   float32   
5    ERRORMAP    ImageHDU         8   (256, 256)   float32   
6    QUALITY     ImageHDU         8   (256, 256)   int16   
7    QUATERNIONS  ImageHDU        10   (5, 792)     float32   
8    HOUSEKEEPING  BinTableHDU    183   595R x 75C   [J, B, B, B, B, B, B, I, I, I, I, I, I, I, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, I, I, I, B, B, B, B, B, B, B, B, B, B, B, B, I, I, I, I, I, I, I, I, I, J, J, B, I, I, I, I, I, I, I, I, I, J]   

Ok, this time we've got an image cube.


In [10]:
data, hdr = pyfits.getdata(fits_file, 0, header=True)
hdr


Out[10]:
SIMPLE  =                    T / file does conform to FITS standard             
BITPIX  =                  -32 / number of bits per data pixel                  
NAXIS   =                    3 / number of data axes                            
NAXIS1  =                  256 / length of data axis 1                          
NAXIS2  =                  256 / length of data axis 2                          
NAXIS3  =                  792 / length of data axis 3                          
EXTEND  =                    T                                                  
COMMENT   FITS (Flexible Image Transport System) format is defined in 'Astronomy
COMMENT   and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H 
BZERO   =                    0 / no offset                                      
BSCALE  =                    1 / default scaling factor                         
MISSION = 'New Horizons'       / Mission name                                   
HOSTNAME= 'NEW HORIZONS'       / Host name (PDS terminology)                    
HOSTID  = 'NH      '           / Host ID (PDS terminology)                      
INSTRU  = 'lei     '           / Instrument                                     
APID    = '0x53c   '           / Application ID of science data                 
MET     =             35209319 / First packet MET (from instrument or HS bus)   
METEND  =             35209909 / Last packet MET (from instrument or HS bus)    
MET_HK  = 'N/A     '           / MET from housekeeping used in header           
HSCOMPR = 'LOSSLESS'           / High-speed compression mode                    
OBSCOMPL= 'COMPLETE'           / Observation completion status                  
MISSPACK=                    0 / Missing CCSDS packets (-1 = N/A)               
STARTMET=           35209319.0 / Actual start time (in MET seconds)             
STOPMET =           35209909.0 / Actual stop time (in MET seconds)              
DURMET  =                590.0 / Observation duration (in MET seconds)          
METSRC  = 'CCSDS_Header'       / Source of above three times                    
EXPTIME =                0.746 / Exposure time                                  
ARCHDATE= '2007/135'           / Date of MOC archive file                       
GRT     =     18031.9748208354 / Ground receipt time from STP                   
DATE    = '2008-08-22T23:18:14' / Time file was created by SOC                  
SOCVER  =                  1.0 / SOC pipeline software version                  
SOCLOC  = 'TSOC    '           / SOC location where processed (TSOC or CSOC)    
REQID   = 'JELE_JAURORA03'     / Request ID                                     
TARGET  = 'JUPITER '           / Target object                                  
TARGTYPE= 'Not defined'        / Target object type                             
CB1LOAD = 'JUPITER '           / Central Body 1 loaded                          
CB2LOAD = 'IO      '           / Central Body 2 loaded                          
CB3LOAD = 'EUROPA  '           / Central Body 3 loaded                          
REQDESC = 'Lyman alpha/H3+ airglow map' / Sequence description / notes          
REQCOMM = 'LEISA N/S scan; ALICE TTAG' / Sequence Comments                      
SPCSEP  = '***GEOMETRY SECTION*************************************'            
SPCQUAL = 'RECONSTRUCTED'      / QUALITY:  PREDICT (poor); RECONSTRUCTED        
SPCSTAT = 'OK      '           / SPICE status [OK or INCOMPLETE ...]            
SPCINST0= 'NH_RALPH_LEISA'     / Starting SPICE Instrument or FRAME             
SPCINSTR= 'NH_RALPH_LEISA'     / Final SPICE Instrument or FRAME                
SPCMET0 =           35209319.0 / RAW MET timestamp                              
SPCMETDL=                295.0 / [s] delta, (Mid-obs time) - (RAW MET)          
SPCCBTNM= 'JUPITER '           / [text] Target input name                       
SPCCB1NM= 'JUPITER '           / [text] CB1 input name                          
SPCCB2NM= 'IO      '           / [text] CB2 input name                          
SPCCB3NM= 'EUROPA  '           / [text] CB3 input name                          
SPCCBTID=                  599 / [SPICE ID] Target                              
SPCCB1ID=                  599 / [SPICE ID] CB1                                 
SPCCB2ID=                  501 / [SPICE ID] CB2                                 
SPCCB3ID=                  502 / [SPICE ID] CB3                                 
SPCSCLK0= '1/0035209319:00000' / Spacecraft CLocK timestamp                     
SPCINSID=               -98201 / [SPICE ID] Instrument                          
SPCSCID =                  -98 / [SPICE ID] Spacecraft                          
SPCSCNAM= 'NH_SPACECRAFT'      / [SPICE Name] Spacecraft                        
SPCSCET =    226175761.5745186 / [s past J2000] Spacecraft mid-obs time, TDB    
SPCSCLK = '1/0035209614:00000' / Mid-obs Spacecraft CLocK                       
SPCSCDP =      1760480700000.0 / [SCLK milli-ticks] Spacecraft mid-obs time     
SPCUTCID= '2007-062T06:34:56.389' / [ISO DOY] Spacecraft mid-obs time, UTC      
SPCUTCAL= '2007-03-03T06:34:56.389' / [Cal d] Spacecraft mid-obs time, UTC      
SPCUTCJD= 'JD 2454162.7742638' / [Julian d] Spacecraft mid-obs time, UTC        
SPCPSEP = '******INSTRUMENT POINTING*******************************'            
SPCBRRA =    38.32743277750437 / [degrees] Boresight RA, EME J2000              
SPCBRDEC=    15.93090165677164 / [degrees] Boresight DEC, EME J2000             
SPCEMEN =     71.6334584106649 / [degrees] EME J2k North Clk Angle, CW from UP  
SPCPAXIN=               -999.0 / [degrees] Instr +X Pos ang, E from EMEJ2k N    
SPCPAYIN=     71.6334584106649 / [degrees] Instr +Y Pos ang, E from EMEJ2k N    
SPCPAZIN=    161.6334584106649 / [degrees] Instr +Z Pos ang, E from EMEJ2k N    
SPCQA   =  0.07733508435305957 / cos(theta/2)     - Quaternion to transform     
SPCQX   =  -0.3418246738097653 / sin(theta/2) * X -   instrument vectors        
SPCQY   =    0.916220988428968 / sin(theta/2) * Y -   to EME J2000 vectors      
SPCQZ   =   0.1942016412525842 / sin(theta/2) * Z -   ***N.B. SPICE FORMAT      
SPCTSEP0= '******Target:  Target->S/C****************************'              
SPCTCB  = 'JUPITER '           / [SPICE name] Target name                       
SPCTSCX =   -4260028.575086413 / [km] S/C vec wrt Target, X, EMEJ2000           
SPCTSCY =   -3378694.737267694 / [km] S/C vec wrt Target, Y                     
SPCTSCZ =   -1478824.842555082 / [km] S/C vec wrt Target, Z                     
SPCTSCVX=   -7.672086207210675 / [km/s] S/C vel vec wrt Target, X               
SPCTSCVY=   -16.95176037789133 / [km/s] S/C vel vec wrt Target, Y               
SPCTSCVZ=   -6.256937840848359 / [km/s] S/C vel vec wrt Target, Z               
SPCTRANG=    5634744.404420776 / [km] S/C range to Target center                
SPCTTGJD= 'JD 2454162.7740462' / [Julian d] Time at Target, UTC                 
SPCTSEP1= '******Target:  Target->Sun****************************'              
SPCTSOX =     308406733.075757 / [km] Sun vec wrt Target, X, EMEJ2000           
SPCTSOY =    681268249.7704819 / [km] Sun vec wrt Target, Y                     
SPCTSOZ =     284503680.841184 / [km] Sun vec wrt Target, Z                     
SPCTSOVX=   -11.90346801410529 / [km/s] Sun vel vec wrt Target, X               
SPCTSOVY=    3.960535796515569 / [km/s] Sun vel vec wrt Target, Y               
SPCTSOVZ=     1.98741656625856 / [km/s] Sun vel vec wrt Target, Z               
SPCTSORN=    800114670.2591944 / [km] Sun range to Target center                
SPCTSEP2= '******Target:  Target->EarthObserver****************************'    
SPCTEOX =    167129756.8493578 / [km] Earth observer vec wrt Target, X, EMEJ2000
SPCTEOY =    722800632.1470044 / [km] Earth obs vec wrt Target, Y               
SPCTEOZ =    302510968.6394773 / [km] Earth obs vec wrt Target, Z               
SPCTEOVX=   -21.47287574753828 / [km/s] Earth obs vel vec wrt Target, X         
SPCTEOVY=   -22.15995929109344 / [km/s] Earth obs vel vec wrt Target, Y         
SPCTEOVZ=   -9.335527771223759 / [km/s] Earth obs vel vec wrt Target, Z         
SPCTEORN=    801177880.1263983 / [km] Earth observer range to Target center     
SPCTEOJD= 'JD 2454162.8049773' / [Julian d] Time at Earth observer              
SPCTSEPB= '******Target:  Body-fixed info****************************'          
SPCTSCLA=    1.851310528951506 / [degrees] planetocentric Sub-S/C latitude      
SPCTSCLO=    228.8105729487132 / [degrees] planetocentric Sub-S/C EAST longitude
SPCTSOLA=   -2.935956801244215 / [degrees] planetocentric Sub-Solar latitude    
SPCTSOLO=     75.2668866775045 / [degrees] planetocentric Sub-Solar EAST long.  
SPCTNAZ =    90.81892530657854 / [degrees] Target North Azimuth, CW from UP     
SPC1SEP0= '******CB1:  CB1->S/C****************************'                    
SPC1CB  = 'JUPITER '           / [SPICE name] CB1 name                          
SPC1SCX =   -4260028.575086413 / [km] S/C vec wrt CB1, X, EMEJ2000              
SPC1SCY =   -3378694.737267694 / [km] S/C vec wrt CB1, Y                        
SPC1SCZ =   -1478824.842555082 / [km] S/C vec wrt CB1, Z                        
SPC1SCVX=   -7.672086207210675 / [km/s] S/C vel vec wrt CB1, X                  
SPC1SCVY=   -16.95176037789133 / [km/s] S/C vel vec wrt CB1, Y                  
SPC1SCVZ=   -6.256937840848359 / [km/s] S/C vel vec wrt CB1, Z                  
SPC1RANG=    5634744.404420776 / [km] S/C range to CB1 center                   
SPC1TGJD= 'JD 2454162.7740462' / [Julian d] Time at CB1, UTC                    
SPC1SEP1= '******CB1:  CB1->Sun****************************'                    
SPC1SOX =     308406733.075757 / [km] Sun vec wrt CB1, X, EMEJ2000              
SPC1SOY =    681268249.7704819 / [km] Sun vec wrt CB1, Y                        
SPC1SOZ =     284503680.841184 / [km] Sun vec wrt CB1, Z                        
SPC1SOVX=   -11.90346801410529 / [km/s] Sun vel vec wrt CB1, X                  
SPC1SOVY=    3.960535796515569 / [km/s] Sun vel vec wrt CB1, Y                  
SPC1SOVZ=     1.98741656625856 / [km/s] Sun vel vec wrt CB1, Z                  
SPC1SORN=    800114670.2591944 / [km] Sun range to CB1 center                   
SPC1SEP2= '******CB1:  CB1->EarthObserver****************************'          
SPC1EOX =    167129756.8493578 / [km] Earth observer vec wrt CB1, X, EMEJ2000   
SPC1EOY =    722800632.1470044 / [km] Earth obs vec wrt CB1, Y                  
SPC1EOZ =    302510968.6394773 / [km] Earth obs vec wrt CB1, Z                  
SPC1EOVX=   -21.47287574753828 / [km/s] Earth obs vel vec wrt CB1, X            
SPC1EOVY=   -22.15995929109344 / [km/s] Earth obs vel vec wrt CB1, Y            
SPC1EOVZ=   -9.335527771223759 / [km/s] Earth obs vel vec wrt CB1, Z            
SPC1EORN=    801177880.1263983 / [km] Earth observer range to CB1 center        
SPC1EOJD= 'JD 2454162.8049773' / [Julian d] Time at Earth observer              
SPC1SEPB= '******CB1:  Body-fixed info****************************'             
SPC1SCLA=    1.851310528951506 / [degrees] planetocentric Sub-S/C latitude      
SPC1SCLO=    228.8105729487132 / [degrees] planetocentric Sub-S/C EAST longitude
SPC1SOLA=   -2.935956801244215 / [degrees] planetocentric Sub-Solar latitude    
SPC1SOLO=     75.2668866775045 / [degrees] planetocentric Sub-Solar EAST long.  
SPC1NAZ =    90.81892530657854 / [degrees] CB1 North Azimuth, CW from UP        
SPC2SEP0= '******CB2:  CB2->S/C****************************'                    
SPC2CB  = 'IO      '           / [SPICE name] CB2 name                          
SPC2SCX =   -4233783.291900516 / [km] S/C vec wrt CB2, X, EMEJ2000              
SPC2SCY =    -3000461.69775487 / [km] S/C vec wrt CB2, Y                        
SPC2SCZ =   -1298057.350996673 / [km] S/C vec wrt CB2, Z                        
SPC2SCVX=    -25.0459627110942 / [km/s] S/C vel vec wrt CB2, X                  
SPC2SCVY=   -15.86410971839685 / [km/s] S/C vel vec wrt CB2, Y                  
SPC2SCVZ=    -6.02734499645897 / [km/s] S/C vel vec wrt CB2, Z                  
SPC2RANG=    5349078.822465276 / [km] S/C range to CB2 center                   
SPC2TGJD= 'JD 2454162.7740573' / [Julian d] Time at CB2, UTC                    
SPC2SEP1= '******CB2:  CB2->Sun****************************'                    
SPC2SOX =    308473517.3939897 / [km] Sun vec wrt CB2, X, EMEJ2000              
SPC2SOY =    681630641.5299462 / [km] Sun vec wrt CB2, Y                        
SPC2SOZ =    284678430.2178327 / [km] Sun vec wrt CB2, Z                        
SPC2SOVX=   -29.27734457091962 / [km/s] Sun vel vec wrt CB2, X                  
SPC2SOVY=    5.048185693265919 / [km/s] Sun vel vec wrt CB2, Y                  
SPC2SOVZ=    2.217009046119995 / [km/s] Sun vel vec wrt CB2, Z                  
SPC2SORN=    800511118.6218687 / [km] Sun range to CB2 center                   
SPC2SEP2= '******CB2:  CB2->EarthObserver****************************'          
SPC2EOX =    167110911.5816689 / [km] Earth observer vec wrt CB2, X, EMEJ2000   
SPC2EOY =    723187869.4717262 / [km] Earth obs vec wrt CB2, Y                  
SPC2EOZ =    302694899.4829311 / [km] Earth obs vec wrt CB2, Z                  
SPC2EOVX=   -38.84673893727469 / [km/s] Earth obs vel vec wrt CB2, X            
SPC2EOVY=   -21.07231331622518 / [km/s] Earth obs vel vec wrt CB2, Y            
SPC2EOVZ=   -9.105936990236907 / [km/s] Earth obs vel vec wrt CB2, Z            
SPC2EORN=    801592760.3800403 / [km] Earth observer range to CB2 center        
SPC2EOJD= 'JD 2454162.8050043' / [Julian d] Time at Earth observer              
SPC2SEPB= '******CB2:  Body-fixed info****************************'             
SPC2SCLA=    1.965050525508316 / [degrees] planetocentric Sub-S/C latitude      
SPC2SCLO=    130.7841916030378 / [degrees] planetocentric Sub-S/C EAST longitude
SPC2SOLA=   -2.933283849273574 / [degrees] planetocentric Sub-Solar latitude    
SPC2SOLO=    340.4622133403877 / [degrees] planetocentric Sub-Solar EAST long.  
SPC2NAZ =    90.78899114401274 / [degrees] CB2 North Azimuth, CW from UP        
SPC3SEP0= '******CB3:  CB3->S/C****************************'                    
SPC3CB  = 'EUROPA  '           / [SPICE name] CB3 name                          
SPC3SCX =    -4248390.87890847 / [km] S/C vec wrt CB3, X, EMEJ2000              
SPC3SCY =   -2767366.985632797 / [km] S/C vec wrt CB3, Y                        
SPC3SCZ =   -1187894.721440814 / [km] S/C vec wrt CB3, Z                        
SPC3SCVX=   -21.28900364982395 / [km/s] S/C vel vec wrt CB3, X                  
SPC3SCVY=   -16.70153785936566 / [km/s] S/C vel vec wrt CB3, Y                  
SPC3SCVZ=   -6.230195893375756 / [km/s] S/C vel vec wrt CB3, Z                  
SPC3RANG=      5207517.5431668 / [km] S/C range to CB3 center                   
SPC3TGJD= 'JD 2454162.7740627' / [Julian d] Time at CB3, UTC                    
SPC3SEP1= '******CB3:  CB3->Sun****************************'                    
SPC3SOX =     308449569.746989 / [km] Sun vec wrt CB3, X, EMEJ2000              
SPC3SOY =    681867473.3339702 / [km] Sun vec wrt CB3, Y                        
SPC3SOZ =    284789760.1777734 / [km] Sun vec wrt CB3, Z                        
SPC3SOVX=   -25.52038546167947 / [km/s] Sun vel vec wrt CB3, X                  
SPC3SOVY=    4.210758052921167 / [km/s] Sun vel vec wrt CB3, Y                  
SPC3SOVZ=    2.014158388990765 / [km/s] Sun vel vec wrt CB3, Z                  
SPC3SORN=    800743152.1843125 / [km] Sun range to CB3 center                   
SPC3SEP2= '******CB3:  CB3->EarthObserver****************************'          
SPC3EOX =    167106328.4121179 / [km] Earth observer vec wrt CB3, X, EMEJ2000   
SPC3EOY =    723418801.7337338 / [km] Earth obs vec wrt CB3, Y                  
SPC3EOZ =    302804550.7960268 / [km] Earth obs vec wrt CB3, Z                  
SPC3EOVX=   -35.08977237960532 / [km/s] Earth obs vel vec wrt CB3, X            
SPC3EOVY=   -21.90974314194165 / [km/s] Earth obs vel vec wrt CB3, Y            
SPC3EOVZ=   -9.308788594021681 / [km/s] Earth obs vel vec wrt CB3, Z            
SPC3EORN=    801841557.7157582 / [km] Earth observer range to CB3 center        
SPC3EOJD= 'JD 2454162.8050194' / [Julian d] Time at Earth observer              
SPC3SEPB= '******CB3:  Body-fixed info****************************'             
SPC3SCLA=    1.564311714248317 / [degrees] planetocentric Sub-S/C latitude      
SPC3SCLO=    124.8294277065411 / [degrees] planetocentric Sub-S/C EAST longitude
SPC3SOLA=   -2.694122168269053 / [degrees] planetocentric Sub-Solar latitude    
SPC3SOLO=    336.8474867433223 / [degrees] planetocentric Sub-Solar EAST long.  
SPC3NAZ =    91.09790664938915 / [degrees] CB3 North Azimuth, CW from UP        
SPCSEPS = '******S/C->SUN****************************************'              
SPCSSCX =    312635300.9236544 / [km] Sun vec wrt S/C observer, X, EMEJ2000     
SPCSSCY =    684658924.3396858 / [km] Sun vec wrt S/C obs, Y                    
SPCSSCZ =     285988386.139349 / [km] Sun vec wrt S/C obs, Z                    
SPCSSCVX=    -4.23138180706071 / [km/s] Sun obs vel vec wrt S/C obs, X          
SPCSSCVY=    20.91229617420019 / [km/s] Sun vel vec wrt S/C obs, Y              
SPCSSCVZ=    8.244354407021406 / [km/s] Sun vel vec wrt S/C obs, Z              
SPCSSCRN=    805163356.7594771 / [km] S/C observer range to sun center          
SPCSSCJD= 'JD 2454162.7431789' / [Julian d] Time at Sun                         
SPCSEPE = '******EARTH->S/C****************************************'            
SPCESCX =   -171473601.5482978 / [km] S/C observer vec wrt earth, X, EMEJ2000   
SPCESCY =   -726312920.9007869 / [km] S/C obs vec wrt earth, Y                  
SPCESCZ =   -304046899.3279517 / [km] S/C obs vec wrt earth, Z                  
SPCESCVX=    13.83133929712089 / [km/s] S/C obs vel vec wrt earth, X            
SPCESCVY=     5.19921997595215 / [km/s] S/C obs vel vec wrt earth, Y            
SPCESCVZ=    3.074700548637148 / [km/s] S/C obs vel vec wrt earth, Z            
SPCESCRN=    805840041.2528026 / [km] S/C observer range to earth center        
SPCESCJD= 'JD 2454162.7431527' / [Julian d] Time at Earth                       
SPCKSEP = '******SPICE KERNELS*************************************'            
SPCKNUM =                   26 / COUNT OF LOADED SPICE KERNELS:                 
SPCK0001= 'naif0008.tls'       / SPICE kernel 0001                              
SPCK0002= 'new-horizons_371.tsc' / SPICE kernel 0002                            
SPCK0003= 'pck00008.tpc'       / SPICE kernel 0003                              
SPCK0004= 'nh_v200.tf'         / SPICE kernel 0004                              
SPCK0005= 'nh_allinstruments_v001.ti' / SPICE kernel 0005                       
SPCK0006= 'nh_alice_v110.ti'   / SPICE kernel 0006                              
SPCK0007= 'nh_lorri_v100.ti'   / SPICE kernel 0007                              
SPCK0008= 'nh_pepssi_v110.ti'  / SPICE kernel 0008                              
SPCK0009= 'nh_ralph_v100.ti'   / SPICE kernel 0009                              
SPCK0010= 'nh_rex_v100.ti'     / SPICE kernel 0010                              
SPCK0011= 'nh_sdc_v101.ti'     / SPICE kernel 0011                              
SPCK0012= 'nh_swap_v100.ti'    / SPICE kernel 0012                              
SPCK0013= 'nh_soc_misc_v001.tf' / SPICE kernel 0013                             
SPCK0014= 'sb-2002jf56-2.bsp'  / SPICE kernel 0014                              
SPCK0015= 'jup260.bsp'         / SPICE kernel 0015                              
SPCK0016= 'plu013.bsp'         / SPICE kernel 0016                              
SPCK0017= 'nh_nep_ura_000.bsp' / SPICE kernel 0017                              
SPCK0018= 'de413.bsp'          / SPICE kernel 0018                              
SPCK0019= 'nh_recon_e2j_v1.bsp' / SPICE kernel 0019                             
SPCK0020= 'nh_recon_j2sep07_prelimv1.bsp' / SPICE kernel 0020                   
SPCK0021= 'merged_nhpc_2006_v011.bc' / SPICE kernel 0021                        
SPCK0022= 'merged_nhpc_2007_v006.bc' / SPICE kernel 0022                        
SPCK0023= 'merged_nhpc_2008_01_v007.bc' / SPICE kernel 0023                     
SPCK0024= 'merged_nhpc_2008_02_v003.bc' / SPICE kernel 0024                     
SPCK0025= 'merged_nhpc_2008_05_v007.bc' / SPICE kernel 0025                     
SPCK0026= 'merged_nhpc_2008_06_v001.bc' / SPICE kernel 0026                     
PACMMNT0= '*** Position angles (PAs):  XYZ axes, degrees east of EMEJ2k North'  
PACMMNT1= '***   on plane perpendicular to boresight; -999 => Boresight'        
PA_XINST=               -999.0 / [degrees] PA +X, East of EMEJ2k North          
PA_YINST=     71.6334584106649 / [degrees] PA +Y, East of EMEJ2k North          
PA_ZINST=    161.6334584106649 / [degrees] PA +Z, East of EMEJ2k North          
HIGHSSEP= '********************************************************'            
WINDOWX =                    0 / X origin of window                             
WINDOWY =                    0 / Y origin of window                             
WINDOWW =                  256 / Window width                                   
WINDOWH =                  256 / Window height                                  
CPLANE  =                    0 / Color/plane number                             
RALPHSEP= '********************************************************'            
MET510  =             35209319 / MET of 0x510 packet marking acq start          
TRUE510 = 'YES     '           / Is the 0x510 real or assumed from a gap?       
RALPHEXP=                0.746 / RALPH exposure time (s)                        
INSTSSEP= '********************************************************'            
DETECTOR= 'LEISA   '           / CCD detector used                              
FILTER  = 'WEDGE   '           / CCD filter color                               
SCANTYPE= 'LEISA   '           / Type of scan done                              
HK_STATE=                    1                                                  
HK_MODE =                   18                                                  
HK_SIDE =                    1                                                  
TDI_RATE=                    0                                                  
LEI_RATE=                  746                                                  
LEI_TEMP=                -4309                                                  
LEI_OFF1=                 3055                                                  
LEI_OFF2=                 3050                                                  
LEI_OFF3=                 3056                                                  
LEI_OFF4=                 3050                                                  
LEI_MODE= 'SUBTRACTED'         / Instrument mode                                
LEI_SIDE= 'A       '           / Instrument HW side                             

In [11]:
np.shape(data)


Out[11]:
(792, 256, 256)

In [48]:
%matplotlib inline
plt.plot(np.ravel(data[:,100,100]))
plt.ylim((0,2e13))
plt.show()



In [45]:
plt.plot(np.ravel(data[100,:,100]))
plt.show()



In [46]:
plt.plot(np.ravel(data[100,100,:]))


Out[46]:
[<matplotlib.lines.Line2D at 0x121d13ed0>]

The official spec for the LEISA instrument says that pixels are BIL, using (X, Y, Z) as 256,256,N where X, Y, Z are wavelength, at X-offset, in the Nth frame. Since FITS files are created/written w/IDL, Fortran conventions (column major instead of row major) and numpy is (w/o changing args/using keywords) row major, I think the correct interpretation of this is frame, X-offset, wavelength.

This looks consistent with calibrated radiance-ish -- in that it looks biases in a black-body-ish way (except the extra radiance towards the higher wavelengths).


In [49]:
wls, wl_hdr = pyfits.getdata(fits_file, 1, header=True)
np.shape(wls)


Out[49]:
(2, 256, 256)

In [61]:
# the first band of this is supposed to be center wavelengths, though I'm not sure about the ordering
# this does look like this direction (slice of index 1) encompasses a range of wavelengths.
wls[0, :, 0]


Out[61]:
array([ 2.49448347,  2.48605704,  2.47762823,  2.46919775,  2.46076703,
        2.45233655,  2.44390774,  2.43548131,  2.42705822,  2.41863942,
        2.41022563,  2.40181828,  2.3934176 ,  2.38502479,  2.37664056,
        2.36826587,  2.35990143,  2.35154796,  2.34320641,  2.33487725,
        2.32656145,  2.31825972,  2.30997276,  2.30170107,  2.29344535,
        2.28520632,  2.27698469,  2.26878095,  2.2605958 ,  2.25242996,
        2.24428344,  2.23615742,  2.2280519 ,  2.21996784,  2.21190548,
        2.20386529,  2.19584775,  2.18785357,  2.17988276,  2.17193604,
        2.16401362,  2.15611625,  2.14824367,  2.14039683,  2.13257575,
        2.12478089,  2.11701226,  2.10927057,  2.10155582,  2.09386849,
        2.08620858,  2.07857633,  2.07097197,  2.06339598,  2.05584812,
        2.04832911,  2.04083848,  2.03337669,  2.02594399,  2.01854014,
        2.01116562,  2.00382042,  1.99650431,  1.98921776,  1.98196054,
        1.97473288,  1.96753478,  1.96036601,  1.95322692,  1.94611728,
        1.93903708,  1.93198645,  1.92496514,  1.91797316,  1.9110105 ,
        1.90407693,  1.89717257,  1.89029729,  1.88345087,  1.87663329,
        1.86984432,  1.86308396,  1.85635185,  1.84964812,  1.8429724 ,
        1.83632469,  1.82970464,  1.82311213,  1.81654704,  1.81000912,
        1.80349815,  1.797014  ,  1.79055631,  1.78412497,  1.77771962,
        1.77134025,  1.76498652,  1.75865805,  1.75235474,  1.74607635,
        1.73982263,  1.73359323,  1.72738802,  1.72120655,  1.71504879,
        1.70891428,  1.7028029 ,  1.69671428,  1.69064808,  1.68460429,
        1.67858231,  1.67258215,  1.66660345,  1.66064596,  1.65470934,
        1.64879334,  1.64289773,  1.63702226,  1.6311667 ,  1.62533069,
        1.61951399,  1.6137166 ,  1.60793793,  1.60217798,  1.59643638,
        1.59071302,  1.58500767,  1.57932007,  1.57365   ,  1.56799734,
        1.56236184,  1.55674338,  1.55114162,  1.54555666,  1.53998816,
        1.53443599,  1.52890015,  1.52338028,  1.51787663,  1.51238871,
        1.50691676,  1.50146055,  1.49601996,  1.4905951 ,  1.48518586,
        1.47979236,  1.47441435,  1.46905208,  1.46370542,  1.45837462,
        1.45305955,  1.44776046,  1.44247723,  1.43721032,  1.43195951,
        1.42672527,  1.42150772,  1.41630697,  1.41112328,  1.40595686,
        1.40080822,  1.39567733,  1.3905648 ,  1.38547087,  1.38039577,
        1.37534022,  1.37030435,  1.36528873,  1.36029387,  1.35532033,
        1.3503685 ,  1.34543896,  1.34053242,  1.33564949,  1.33079088,
        1.32595718,  1.32114911,  1.31636739,  1.31161296,  1.30688667,
        1.30218911,  1.29752147,  1.29288459,  1.28827941,  1.2837069 ,
        1.27916825,  1.2746644 ,  1.27019644,  1.26576579,  1.2613734 ,
        1.25702071,  1.25270891,  1.24843931,  1.24421322,  1.24003232,
        1.2358979 ,  1.23181152,  1.22777462,  1.22378898,  1.21985614,
        2.26205564,  2.25878906,  2.25552678,  2.25226879,  2.24901485,
        2.24576521,  2.24251986,  2.23927855,  2.23604178,  2.23280907,
        2.22958064,  2.22635627,  2.22313643,  2.21992064,  2.21670914,
        2.21350193,  2.21029878,  2.20710015,  2.20390558,  2.2007153 ,
        2.19752908,  2.19434738,  2.19116974,  2.18799639,  2.18482709,
        2.18166232,  2.17850161,  2.17534518,  2.17219305,  2.16904521,
        2.16590142,  2.16276193,  2.15962672,  2.15649581,  2.15336895,
        2.15024638,  2.14712811,  2.14401412,  2.14090443,  2.13779879,
        2.13469744,  2.13160038,  2.12850761,  2.1254189 ,  2.12233448,
        2.11925435,  2.11617851,  2.11310697,  2.11003947,  2.10697627,
        2.10391736,  2.1008625 ,  2.09781218,  2.0947659 ,  2.09172392,
        2.08868623], dtype=float32)

In [62]:
# and this one looks like slight variation in real wavelength center across pixels that
# should roughly be in the same wavelength range.
wls[0, 0, :]


Out[62]:
array([ 2.49448347,  2.49452114,  2.49454188,  2.49454689,  2.49453759,
        2.49451518,  2.49448109,  2.49443603,  2.49438119,  2.49431753,
        2.49424577,  2.49416685,  2.4940815 ,  2.49399042,  2.4938941 ,
        2.49379349,  2.49368858,  2.49358034,  2.493469  ,  2.49335504,
        2.49323893,  2.49312067,  2.49300098,  2.49288011,  2.49275804,
        2.49263525,  2.49251175,  2.49238777,  2.49226379,  2.49213958,
        2.49201536,  2.49189115,  2.49176717,  2.49164367,  2.4915204 ,
        2.49139738,  2.49127507,  2.491153  ,  2.49103165,  2.49091077,
        2.49079037,  2.49067068,  2.49055147,  2.49043298,  2.49031472,
        2.49019742,  2.49008036,  2.48996401,  2.4898479 ,  2.48973274,
        2.48961782,  2.48950338,  2.48938942,  2.48927617,  2.48916316,
        2.48905063,  2.48893857,  2.48882723,  2.48871613,  2.4886055 ,
        2.48849535,  2.48838568,  2.48827672,  2.488168  ,  2.48806   ,
        2.48795223,  2.48784542,  2.48773885,  2.48763323,  2.48752809,
        2.48742366,  2.48731995,  2.48721695,  2.48711467,  2.48701334,
        2.48691273,  2.48681307,  2.48671436,  2.48661685,  2.48652029,
        2.48642468,  2.48633051,  2.48623729,  2.4861455 ,  2.48605514,
        2.48596597,  2.48587823,  2.48579192,  2.48570728,  2.48562431,
        2.48554301,  2.48546338,  2.48538542,  2.4853096 ,  2.48523545,
        2.48516321,  2.48509312,  2.48502517,  2.48495913,  2.48489547,
        2.48483396,  2.48477459,  2.48471785,  2.48466325,  2.48461103,
        2.48456144,  2.48451447,  2.48446989,  2.48442793,  2.48438859,
        2.48435187,  2.48431802,  2.48428679,  2.48425817,  2.48423266,
        2.48420978,  2.48418951,  2.48417234,  2.48415804,  2.48414636,
        2.48413777,  2.48413205,  2.48412919,  2.48412919,  2.48413205,
        2.48413777,  2.48414636,  2.4841578 ,  2.48417211,  2.48418927,
        2.4842093 ,  2.48423195,  2.48425746,  2.48428559,  2.48431659,
        2.4843502 ,  2.48438621,  2.48442507,  2.48446655,  2.48451042,
        2.48455667,  2.48460555,  2.48465657,  2.48470998,  2.48476577,
        2.48482394,  2.48488402,  2.48494649,  2.48501086,  2.48507714,
        2.48514557,  2.4852159 ,  2.4852879 ,  2.48536205,  2.48543763,
        2.48551488,  2.48559403,  2.48567438,  2.48575664,  2.48584008,
        2.48592496,  2.48601127,  2.48609877,  2.4861877 ,  2.48627758,
        2.48636889,  2.48646092,  2.48655438,  2.4866488 ,  2.48674393,
        2.48684025,  2.48693752,  2.48703551,  2.48713446,  2.48723412,
        2.48733449,  2.48743582,  2.48753786,  2.48764062,  2.48774409,
        2.48784828,  2.48795319,  2.48805904,  2.48816538,  2.48827243,
        2.48838019,  2.48848891,  2.48859835,  2.4887085 ,  2.48881936,
        2.48893118,  2.48904395,  2.48915768,  2.48927212,  2.48938775,
        2.48950434,  2.48962212,  2.48974109,  2.48986101,  2.48998237,
        2.49010515,  2.49022913,  2.49035454,  2.49048138,  2.49060988,
        2.49073982,  2.49087167,  2.49100494,  2.49114013,  2.49127722,
        2.49141598,  2.49155664,  2.49169946,  2.49184394,  2.49199057,
        2.4921391 ,  2.49228978,  2.49244213,  2.49259663,  2.49275303,
        2.49291134,  2.49307132,  2.49323297,  2.49339604,  2.49356079,
        2.49372673,  2.49389386,  2.49406171,  2.49423027,  2.49439907,
        2.49456811,  2.49473667,  2.49490476,  2.49507165,  2.49523687,
        2.49540019,  2.49556088,  2.49571824,  2.49587178,  2.49602056,
        2.49616408,  2.49630117,  2.49643135,  2.49655318,  2.49666572,
        2.496768  ,  2.49685884,  2.49693656,  2.49700022,  2.4970479 ,
        2.49707794,  2.49708915,  2.49707913,  2.49704599,  2.49698782,
        2.49690199], dtype=float32)

In [54]:
wl_hdr


Out[54]:
XTENSION= 'IMAGE   '           / IMAGE extension                                
BITPIX  =                  -32 / number of bits per data pixel                  
NAXIS   =                    3 / number of data axes                            
NAXIS1  =                  256 / length of data axis 1                          
NAXIS2  =                  256 / length of data axis 2                          
NAXIS3  =                    2 / length of data axis 3                          
PCOUNT  =                    0 / required keyword; must = 0                     
GCOUNT  =                    1 / required keyword; must = 1                     
EXTNAME = 'WAVELENGTHS'        / extension name                                 

FITS data can be so strange. You might think "-32" would be a signed 32-bit integer, but this is floating point.


In [78]:
# ok, let's see if we can plot a spectrum. Ordering will probably be sort of strange
# based on what we've seen.
plt.plot(np.ravel(wls[0,:,100]), np.ravel(data[100,0,:]))


Out[78]:
[<matplotlib.lines.Line2D at 0x125cd06d0>]

Ok, this is an ok candidate for a spectrum. There's something of a glitchy looking line of odd (false?) contiguity across wavelengths in the above plot, maybe correctable w/a sort, but this looks reasonable as a spectrum prior to the application of gains and offsets. The spec shows that we have a dataset in the FITS file of gains and offsets as well as a map of bad pixels that can be used as a mask. Lets look at applying these.

Note: I could still be completely wrong at this point.


In [73]:
gain_offset, go_hdr = pyfits.getdata(fits_file, 4, header=True)
(go_hdr, np.shape(gain_offset))


Out[73]:
(XTENSION= 'IMAGE   '           / IMAGE extension                                
 BITPIX  =                  -32 / number of bits per data pixel                  
 NAXIS   =                    3 / number of data axes                            
 NAXIS1  =                  256 / length of data axis 1                          
 NAXIS2  =                  256 / length of data axis 2                          
 NAXIS3  =                    2 / length of data axis 3                          
 PCOUNT  =                    0 / required keyword; must = 0                     
 GCOUNT  =                    1 / required keyword; must = 1                     
 EXTNAME = 'CALIBRATION'        / extension name                                 ,
 (2, 256, 256))

The general strategy to apply gains and offsets is this basic equation:

rad_cal = gain * DN + offset

It's fairly trivial to adapt this to Python


In [79]:
def cal(DN, gain, offset):
    return gain*DN + offset

In [80]:
# with operator overloading for ndarrays in numpy, we can apply this across the arrays.
cal_data = cal(data[0,:,:], gain_offset[0,:,:], gain_offset[1,:,:])

In [92]:
# really, though, we want to apply this to each frame. this is the kind of thing that's trivial
# to express w/a list of frames, harder w/an ND array. 
cal_all_data = np.zeros_like(data)
(np.shape(cal_all_data,), np.shape(data))


Out[92]:
((792, 256, 256), (792, 256, 256))

In [114]:
# Populate cal_all_data image cube. We could probably replace this w/a vectorized operation,
# but this solves it and I don't have a perf requirement to optimize this -- yet.
for i in range(np.shape(cal_all_data)[0]):
    cal_all_data[i] = cal(data[i,:,:], gain_offset[1,:,:], gain_offset[0,:,:])

In [124]:
# ok this result looks really smooth, but doesn't have the features you'd expect
# for a spectrum (fine absorption and emissivity features)
plt.plot(cal_all_data[0,250,:])
plt.show()



In [126]:
plt.plot(wls[0,:,250], cal_all_data[0,250,:])


Out[126]:
[<matplotlib.lines.Line2D at 0x133ad32d0>]

I can't really determine anything from this. I want the wavelengths in order. This is where numpy.argsort comes in - it returns indices we can use to sort multiple arrays.


In [130]:
sort_i = np.argsort(np.ravel(wls[0,:,250]))
plt.plot(wls[0,sort_i,250], cal_all_data[0,250,sort_i])


Out[130]:
[<matplotlib.lines.Line2D at 0x133c09a50>]

In retrospect, the outcome of the sort should have been fairly obvious.


In [135]:
# ok, so my earlier assumption was wrong. Shouldn't draw conclusions from uncalibrated data!
# this matching calibration looks ok, but I'm not really sure what I'm looking at (other than
# that it looks like an inverted sigmoid).
plt.plot(wls[0,sort_i,250], cal_all_data[0,sort_i,5])
plt.show()



In [137]:
plt.plot(wls[0,sort_i,250], cal_all_data[100,sort_i,5])
plt.show()



In [146]:
plt.imshow(cal_all_data[:,50,:], cmap='bone')
plt.title("Image at ~wavelength " + str(np.mean(wls[0,50,:])))
plt.show()


I think this may be the image portion, but I'm pretty out of my depth here and I think I need a new strategy. Let me summarize the outcome of this session:

  • I was apply to apply gains and offsets in a way that looks correct, due to the smoothness of the outcome.
  • I was able to determine where the spectral information was (in retrospect, this matches the BIL description, but not the ordering of the spec - which I'm probably reading incorrectly).
  • I believe I can display images at wavelengths, but as I'm not completely certain what I'm looking at, it's difficult to verify. A roughness of fit w/my Geo vs. Astro background.

This is point where I think it's worth calling it quits and looking to match to a dataset with a published image or something where I can match a specific outcome, then return to more "play" with the data.