L0/2D Files: Reading and Examining the Data Products

Import Packages

[1]:
#from astropy.io import fits
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from astropy.time import Time
from astropy.table import Table
from modules.Utils.kpf_parse import get_datecode
from kpfpipe.models.level0 import KPF0
%matplotlib inline

Define Directories and Filenames

One needs to have the L0 file KP.20240422.48942.23.fits and the 2D file KP.20240422.48942.23_2D.fits in the /data/L0/ or /data/2D/ directories, respectively. These files can be downloaded from the Keck Observatory Archive (KOA), or, for those participating in the California Planet Search (CPS), using the Jump portal or shrek.caltech.edu. One can also modify the code below to work with other files or paths.

[2]:
data_dir = '/data/'
#ObsID = 'KP.20230405.46556.38' # on-sky spectrum of HD 127334 (Commissioning data)
ObsID = 'KP.20240422.28832.89' # on-sky spectrum of TOI-1823 (PI: Howard data)
L0_file = data_dir + 'L0/' + get_datecode(ObsID) + '/' + ObsID + '.fits'
D2_file = data_dir + '2D/' + get_datecode(ObsID) + '/' + ObsID + '_2D.fits'
print(f'L0 filename: {L0_file}')
L0 filename: /data/L0/20240422/KP.20240422.28832.89.fits

Open File and Show Information

Note that there are exensions for:

  • Header keywords (PRIMARY)

  • Built-in extensions related to the data reduction pipeline (RECEIPT and CONFIG)

  • Four quadrants of the green CCD (GREEN_AMP1, GREEN_AMP2, GREEN_AMP3, GREEN_AMP4); later L0 files uses two amplifiers had have two halves (REEN_AMP1, GREEN_AMP2)

  • Two halves of the red CCD (RED_AMP1, RED_AMP2)

  • Stitched CCD images (GREEN_CCD and RED_CCD; these extensions are empty in L0, but filled in 2D)

  • Variance of stitched CCD images (GREEN_VAR and RED_VAR; these extensions are empty in L0, but filled in 2D)

  • The CCD image from the Ca H&K Spectrometer (CA_HK)

  • Spectral time series for the Exposure Meter (EXPMETER_SCI, EXPMETER_SKY)

  • The guide camera (GUIDECAM, GUIDE_CUBE_ORIGINS or guide_cube_origins)

  • Telemetry, mostly temperatures during the exposure (TELEMETRY)

  • Solar intensity information for exposures using SoCal (SOLAR_IRRADIANCE)

[3]:
L0 = KPF0.from_fits(L0_file, data_type='KPF')
L0.info()
File name: KP.20240422.28832.89.fits
|Header Name          |# Cards
================================================================================
|PRIMARY              |                 441
|RECEIPT              |                   0
|CONFIG               |                   0
|GREEN_AMP1           |                  11
|GREEN_AMP2           |                  11
|GREEN_CCD            |                   3
|GREEN_VAR            |                   3
|RED_AMP1             |                  13
|RED_AMP2             |                  13
|RED_CCD              |                   0
|RED_VAR              |                   0
|CA_HK                |                  58
|EXPMETER_SCI         |                 849
|EXPMETER_SKY         |                 849
|GUIDECAM             |                   0
|TELEMETRY            |                  26
|SOLAR_IRRADIANCE     |                   0
|GUIDER_CUBE_ORIGINS  |                  87
|GUIDER_AVG           |                   8

|Extension Name       |Data Type            |Data Dimension
================================================================================
|RECEIPT              |table                |1
|CONFIG               |table                |0
|GREEN_AMP1           |image                |(4110, 2094)
|GREEN_AMP2           |image                |(4110, 2094)
|GREEN_CCD            |image                |(0,)
|GREEN_VAR            |image                |(0,)
|RED_AMP1             |image                |(4110, 2094)
|RED_AMP2             |image                |(4110, 2094)
|RED_CCD              |image                |(0,)
|RED_VAR              |image                |(0,)
|CA_HK                |image                |(255, 1024)
|EXPMETER_SCI         |table                |204
|EXPMETER_SKY         |table                |204
|GUIDECAM             |image                |(0,)
|TELEMETRY            |table                |131
|SOLAR_IRRADIANCE     |table                |0
|GUIDER_AVG           |image                |(512, 640)
|GUIDER_CUBE_ORIGINS  |table                |59857

Primary Extension (header keywords)

Here is a list of keywords. Later data products (2D, L1, L2 add keywords to this list)

[4]:
L0.header['PRIMARY']
[4]:
SIMPLE  =                    T / conforms to FITS standard
BITPIX  =                    8 / array data type
NAXIS   =                    0 / number of array dimensions
EXTEND  =                    T
FAVER   = '1.5     '           / Written by FITSAssemble version 1.5
TIMESYS = 'UTC     '
CAMERAS =                    5 / Detectors in assembly request
GREEN   = 'YES     '           / Was this camera found?
RED     = 'YES     '           / Was this camera found?
CA_HK   = 'YES     '           / Was this camera found?
EXPMETER= 'YES     '           / Was this camera found?
GUIDE   = 'YES     '           / Was this camera found?
STARTIME= '2024-04-22T08:00:32.886' / Start of the exposure, passed to assembler
ENDTIME = '2024-04-22T08:10:32.954' / End of the exposure, passed to assembler
DATE-BEG= '2024-04-22T08:00:32.886179' / Start of the exposure, from kpfexpose
DATE-MID= '2024-04-22T08:05:32.920' / Middle of the exposure
DATE-END= '2024-04-22T08:10:32.954200' / End of the exposure, from  kpfexpose
COMMENT ------------------------------------------------------------------------
COMMENT Location: /kroot/rel/default/bin/keyheader
COMMENT Configuration: /kroot/rel/default/data/kpfheaders/keyheader.conf
COMMENT Hostname: kpfserver
COMMENT Header generation start time: 2024-04-22T08:11:21.460067Z
COMMENT ------------------------------------------------------------------------
COMMENT
COMMENT - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
COMMENT keyheader section [ExposureBegin]
COMMENT Snapshot timestamp: 2024-04-22T08:00:32.986180Z
COMMENT - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
COMMENT
UT      = '08:00:32.82'        / DCS Universal Time
DATE-OBS= '2024-04-22'         / Date dcs1.DATE
KPFERA  =                  2.0 / Current era of KPF observations
CURRINST= 'KPF     '           / Selected instrument
TELESCOP= 'Keck I  '           / Telescope
TARGNAME= 'T001823 '           / KPF Target name
DCSNAME = 'T001823 '           / DCS Target name - may not make any sense
TARGRA  = '13:04:52.90'        / [h] DCS Target RA
TARGDEC = '+63:45:14.0'        / [deg] DCS Target Dec
TARGEPOC=               2000.0 / DCS Target epoch
TARGEQUI=               2000.0 / DCS Target equinox
TARGPLAX=                  0.0 / [arcsec] target parallax
TARGPMDC=                  0.0 / [arcsec/yr] target proper motion dec
TARGPMRA=                  0.0 / [s/yr] target proper motion ra
TARGRADV=                  0.0 / [km/s] target radial velocity
TARGWAVE=                 0.65 / target-wavelength
TARGFRAM= 'FK5     '           / target-frame
FULLTARG= 'T001823 '           / Full Target name from kpfconfig
GAIAID  = 'DR3 1676299557803904000' / GAIA Target name from kpfconfig
2MASSID = 'J13045290+6345137'  / 2MASS Target name from kpfconfig
GAIAMAG = '10.3923 '           / GAIA G band magnitude
2MASSMAG= '8.907   '           / 2MASS J band magnitude
TARGTEFF=               4965.0 / Target effective temperature (K)
RA      = '13:04:52.90'        / [h] Right ascension
DEC     = '+63:45:14.0'        / [deg] Declination
EQUINOX =               2000.0 / DCS Equinox
MJD-OBS =         60422.333713 / Modified Julian day
PMFM    =                  0.0 / PMFM value
LFCMODE = 'StandbyHigh'        / LFC Operation Mode
AMPON   =         13615260.535 / LFC: Amount of time amplifier on
LFCFO   =          250000000.0 / LFC filtered Offset Freq RR Comb counted
LFCFREF =          250000000.0 / LFC filtered Offset Freq RR Comb setpoint
LFCFR   =     19999999999.9715 / LFC filtered Offset Freq RR Filter counted
LFCFRREF=        20000000000.0 / LFC filtered Offset Freq RR Filter setpoint
LFCCEOFR=         5220000000.0 / CEO Filtered Setpoint Freq
LFCCWFRF=    288005220000000.0 / CW Freq Reference
LFCCWFRQ=    288005218128500.0 / CW Freq
LFCCWFER=           -1871500.0 / CW Freq Error: Ref-Actual
LFCCWMDN=              1152021 / CW mode number
LFCBIACT=                0.033 / Blue cut amp diode current (A)
LFCBISET=                  0.0 / Blue cut amp diode setting (A)
OCTAGON = 'EtalonFiber'        / selected octagon value
CALMON  = 'Out     '           / Calibration intensity monitor position
HATCH   = 'Open    '           / Status of the hatch on the exterior of the FIU
FIUMODE = 'Observing'          / FIU operating mode
FOLDNAM = 'Out     '           / Named Position of FIU Fold mirror
FOLDVAL =                 24.7 / [mm] Position of FIU Fold mirror
ADCTRACK= 'On      '           / Is the ADC Tracking
HCLSN   = '' / S/N of lamp in use
CAREQ   = 'Yes     '           / Ca HK fibers (6,7) requested
EXPSCREQ= 'Yes     '           / ExpM Science fiber (8ab) requested
FFREQ   = 'No      '           / Flatfield fiber (10ab) requested
SICALREQ= 'Yes     '           / SimCal fiber (3ab) requested
VACSCREQ= 'Yes     '           / Vac Sci fiber (1b) requested
VACSKREQ= 'Yes     '           / Vac Sci fiber (2b) requested
THDAYON = '20240421T15:00:09 HST' / ThAr Daily was last turned on at this time
THDAYTON=               4304.2 / ThAr Daily has been on for this long
THAUON  = '20230503T12:39:28 HST' / ThAr Gold was last turned on at this time
THAUTON =               1465.7 / ThAr Gold has been on for this long
UDAYON  = '20240421T16:12:41 HST' / UNe Daily was last turned on at this time
UDAYTON =               3059.3 / UNe Daily has been on for this long
UAUON   = '19691231T14:00:00 HST' / UNe Gold was last turned on at this time
UAUTON  =                  0.0 / UNe Gold has been on for this long
PTHDAY  =            9.513E-06 / Last ThAr Daily calibration power value (Watts)
PTHDAYT = '20240421T16:06:40 HST' / Time of ThAr Daily last power value
PTHAU   =                  0.0 / Last ThAr Gold calibration power value (Watts)
PTHAUT  = '19691231T14:00:00 HST' / Time of ThAr Gold last power value
PUDAY   =            1.515E-05 / Last UNe Daily calibration power value (Watts)
PUDAYT  = '20240421T16:59:25 HST' / Time of UNe Daily last power value
PUAU    =                  0.0 / Last UNe Gold  calibration power value (Watts)
PUAUT   = '19691231T14:00:00 HST' / Time of UNe Gold last power value
PLFC    =                  0.0 / Last LFC calibration power value (Watts)
PLFCT   = '19691231T14:00:00 HST' / Time of LFC last power value
PETAL   =            1.374E-07 / Last Etalon calibration power value (Watts)
PETALT  = '20240421T16:34:57 HST' / Time of Etalon last power value
PBRB    = 9.57199999999999E-06 / Last Broadband calibration power value (Watts)
PBRBT   = '20240421T12:31:09 HST' / Time of Broadband last power value
PSOL    =                  0.0 / Last SoCal-CalFib cal. power value (Watts)
PSOLT   = '19691231T14:00:00 HST' / Time of SoCal-CalFib last power value
COMMENT
COMMENT - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
COMMENT keyheader section [heartbeats]
COMMENT Snapshot timestamp: 2024-04-22T08:00:32.986180Z
COMMENT - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
COMMENT
COMMENT Data not available for keyword 'heart_12'
COMMENT Data not available for keyword 'heart_34'
COMMENT Data not available for keyword 'heart_35'
COMMENT Data not available for keyword 'heart_36'
COMMENT Data not available for keyword 'heart_37'
COMMENT
COMMENT ------------------------------------------------------------------------
COMMENT End of keyheader output
COMMENT Header generation start time: 2024-04-22T08:11:21.460067Z
COMMENT Header generation end time:   2024-04-22T08:11:21.596902Z
COMMENT ------------------------------------------------------------------------
COMMENT ------------------------------------------------------------------------
COMMENT Location: /kroot/rel/default/bin/keyheader
COMMENT Configuration: /kroot/rel/default/data/kpfheaders/keyheader.conf
COMMENT Hostname: kpfserver
COMMENT Header generation start time: 2024-04-22T08:11:23.016314Z
COMMENT ------------------------------------------------------------------------
COMMENT
COMMENT - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
COMMENT keyheader section [ExposureMiddle]
COMMENT Snapshot timestamp: 2024-04-22T08:05:32.920190Z
COMMENT - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
COMMENT
SRCSHTTR= 'SciSelect,SkySelect' / Source shutters commanded
TIMSHTTR= 'Scrambler,SimulCal,Ca_HK' / Timed shutters commanded
OTIMSHTR= 'Scrambler,SimulCal,Ca_HK' / Timed shutters open exp. midpoint
SCISEL  = 'open    '           / Science Select shutter at exp. midpoint
SKYSEL  = 'open    '           / Sky Select Shutter at exp. midpoint
FFSHTR  = 'closed  '           / Flat field fiber shutter at exp. midpoint
SCRAMSHT= 'open    '           / Scrambler shutter at exp. midpoint
SIMCALSH= 'open    '           / Simult Cal shutter at exp. midpoint
TRIGTARG= 'Green,Red,Ca_HK,ExpMeter,Guide' / Cameras that were sent triggers
IMTYPE  = 'Object  '           / Image Type
CAL-OBJ = 'EtalonFiber'        / Calibration fiber source
SKY-OBJ = 'Sky     '           / Sky fiber source
SCI-OBJ = 'Target  '           / Science fiber source
CAFBS   = 'Yes     '           / Ca HK fibers (6,7) on
EXPSCIFB= 'Yes     '           / ExpM Science fiber (8ab) on
EXPSKYFB= 'Yes     '           / ExpM Science fiber (9) on
FFFB    = 'No      '           / Flatfield fiber (10ab) on
FICALFBS= 'No      '           / FIU Cal fibers (4,5) on
SICALFB = 'Yes     '           / SimCal fiber (3ab) on
VACSCFB = 'Yes     '           / Vac Sci fiber (1b) on
VACSKFB = 'Yes     '           / Vac Sci fiber (2b) on
SCIFB   = 'Yes     '           / Science fiber (1a) on
SKYFB   = 'Yes     '           / Sky fiber (2a) on
CURRBASE= '(335.5, 258.0)'     / [pix] Selected pointing origin
PIXTARG = '(342.081, 264.411)' / [pix] Selected object tip/tilt target
GRACFMD5= '1EF8CF3BA1C2905FE9980C295DCB9953' / Green MD5 sum for the acf file
GRACFFLN= 'regular-read-green.acf' / Green acf file loaded
RDACFMD5= '46B91FD6D29EEBBDED920738326414BA' / Red MD5 sum for the acf file
RDACFFLN= 'regular-read-red.acf' / Red acf file loaded
AGITSTA = 'Running '           / Agitator status kpfmot.AGITATOR
THARGD  = 'Off     '           / Gold ThAr power status
UNEGD   = 'Off     '           / Gold UNe power status
THARDAY = 'Off     '           / Daily ThAr power status
UNEDAY  = 'Off     '           / Daily UNe power status
OCTBB   = 'Off     '           / Octagon broad band power status
FFSOURCE= 'Off     '           / Flat field broad band power status
SCIFBILL= 'Off     '           / Science fiber LED back illuminator power
SKYFBILL= 'Off     '           / Sky fiber LED back illuminator power
HKFBILL = 'Off     '           / Ca H and K fiber LED back illuminator power
EXPFBILL= 'Off     '           / Exposure meter fiber LED back illuminator power
SSCALFW = 'OD 2.0  '           / Sci/Cal FW Position
SIMCALFW= 'OD 0.3  '           / Simual Cal FW Position
FFFW    = 'Blank   '           / Flatfield FW Position
OCTAGON = 'EtalonFiber'        / selected octagon value
PRES    =              622.806 / [hPa] Pressure at Vaisala kpfmet.PRES
RELH    =               10.647 / Relative humidity at Vaisala kpfmet.RELH
PONAME  = 'KPF     '           / DCS Point origin name
PONAME1 = 'Opt Axis'           / DCS Point origin name1
DRA     =                  0.0 / [s/s] DCS Diff RA rate
DDEC    =                  0.0 / [asec/s] DCS Diff Dec rate
RABASE  = '13:04:52.90'        / DCS RA base
RAOFF   =                  0.0 / [asec] DCS RA offset
DECBASE = '+63:45:14.0'        / DCS Dec base
DECOFF  =                  0.0 / [asec] DCS Dec offset
HA      = '+22:42:16.11'       / DCS Hour angle
AIRMASS =                 1.43 / DCS Airmass
PARANG  =               206.31 / [deg] DCS Parallactic angle astrometric
PARANTEL=               206.26 / [deg] DCS Parallactic angle telescope
EL      =                44.25 / [deg] DCS Elevation
AZ      =                12.03 / [deg] DCS Azimuth
LST     = '11:47:09.01'        / DCS Local sidereal time
AXESTAT = 'tracking'           / DCS axes control status
TRACKING= 'yes     '           / DCS Servos tracking status
DTRACK  = 'disabled'           / DCS differential tracking status
GUIDING = 'true    '           / DCS Guiding status
AUTACTIV= 'yes     '           / DCS Guider active
AUTFWHM =             0.499828 / [pix] DCS Guider fwhm
AUTXCENT=                 -0.1 / [asec] DCS Guider x centroid
AUTYCENT=                  0.0 / [asec] DCS Guider y centroid
SECFOCUS=                -1.72 / [mm] Secondary focus
TELFOCUS=               -1.382 / [mm] Telescope focus
TUBEFLEX=                -13.3 / [arcsec] Telescope tube flexure
TUBETEMP=                 1.01 / [degC] Telescope tube temperature
PRIMTEMP=             1.692328 / [degC] Telescope pri temperature
SECMTEMP=   0.5879529999999999 / [degC] Telescope sec temperature
DIFFPTDW=            30.792328 / [decC] Diff between pri mirro temp dewpt
DIFFSTDW=            29.687953 / [decC] Diff between sec mirro temp dewpt
VIGNETTE= 'false   '           / dome vignette (t/f)
STVIGNE = 'false   '           / top shutter vignette (t/f)
SBVIGNE = 'false   '           / bottom shutter vignette (t/f)
SBELEV  =                 3.12 / [deg] bottom shutter elevation
STELEV  =               104.01 / [deg] top shutter elevation
SECSTST = 'INPOS   '           / DCS Secondary status string
SECTHETX=               -340.1 / [asec] DCS Secondary theta x
SECTHETY=                201.1 / [asec] DCS Secondary theta y
TERTSTST= 'INPOS   '           / DCS Tertiary status string
TERTDEST= 'lnas    '           / DCS Tertiary user destination
TERTPOSN= 'lnas    '           / DCS Tertiary user position
DOMEPOSN=                12.26 / DCS Dome user position
DOMESTST= 'TRACK   '           / DCS Dome status string
CALOCAL =                 -7.2 / collimation-azimuth-local
CELOCAL =                 15.9 / collimation-elevation-local
FOCALSTN= 'lnas (left nasmyth)' / focal-station
INSTANGL=                312.0 / porg-to-instrument angle
POXPOS  =                  0.4 / pointing-origin-x-position
POYPOS  =                 -0.8 / pointing-origin-y-position
ROTCALAN=                  0.0 / rotator-calibration-angle
ROTZERO =                  0.0 / rotator-zero-angle
GUIDWAVE=                 0.65 / guidestar-wavelength
TIMEERR = 'ok 2 2 {NTP time correct to within 2 ms}' / resp time serv
ETAV1C1T=            23.982342 / Etalon v1ch1temp
ETAV1C2T=            23.788904 / Etalon v1ch2temp
ETAV1C3T=            23.599926 / Etalon v1ch3temp
ETAV1C4T=            23.900005 / Etalon v1ch4temp
ETAV2C3T=             24.00049 / Etalon v2ch3temp
TSHKEXP = '2024-04-21 22:00:32.875' / Time of signal sent to start HK exposure
WSHKEXP =                0.605 / Window of time start HK exposure active
TSHKSHT = '2024-04-21 22:00:32.889' / Time of signal open to close HK shutter
WSHKSHT =                1.243 / Window of time open HK shutter active
TSTMSHT = '2024-04-21 22:00:32.885' / Time of signal sent to open timed shutter
WSTMSHT =                0.005 / Window of time start timed shutter active
COMMENT
COMMENT ------------------------------------------------------------------------
COMMENT End of keyheader output
COMMENT Header generation start time: 2024-04-22T08:11:23.016314Z
COMMENT Header generation end time:   2024-04-22T08:11:23.154328Z
COMMENT ------------------------------------------------------------------------
COMMENT ------------------------------------------------------------------------
COMMENT Location: /kroot/rel/default/bin/keyheader
COMMENT Configuration: /kroot/rel/default/data/kpfheaders/keyheader.conf
COMMENT Hostname: kpfserver
COMMENT Header generation start time: 2024-04-22T08:11:24.478531Z
COMMENT ------------------------------------------------------------------------
COMMENT
COMMENT - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
COMMENT keyheader section [ExposureEnd]
COMMENT Snapshot timestamp: 2024-04-22T08:10:33.054200Z
COMMENT - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
COMMENT
DATE    = '2024-04-22T08:10:32.954200' / End of exposure from kpfexpose.ENDTIME
DATE-END= '2024-04-22T08:10:32.954200' / End of exposure from kpfexpose.ENDTIME
ELAPSED =              600.068 / Actual exposure time from kpfexpose.ELAPSED
DATE-BEG= '2024-04-22T08:00:32.886179' / Start of exposure from kpfexpose
EXPTIME =                600.0 / Requested exposure time
PROGNAME= 'C050    '           / Program name from kpfexpose
OBJECT  = 'T001823 '           / Object
INSTRUME= 'KPF     '           / Instrument name
DATALVL = '0       '           / Data Product Base Level
OBSERVAT= 'KECK    '           / Observatory name
OBSMODE = 'SPEC    '           / Basic mode of observation
HEADVER = '130006  '           / Header config version
WAVEBNS = '498.12 604.38 710.62 816.88' / Wavelength of EM bins in nm
TOTCNTS = '8.5522e+06 1.6711e+07 1.6836e+07 1.2039e+07' / Total counts kpf_expme
TOTCORR = '1.1777e+07 2.3012e+07 2.3183e+07 1.6585e+07' / Total counts corrected
TEHKEXP = '2024-04-21 22:00:32.875' / Time of signal sent to end HK exposure
WEHKEXP =                0.605 / Window of time end HK exposure active
TEHKSHT = '2024-04-21 22:10:32.952' / Time of signal sent to close HK shutter
WEHKSHT =                1.243 / Window of time close HK shutter active
TETMSHT = '2024-04-21 22:10:32.949' / Time of signal sent to close timed shutter
WETMSHT =                0.004 / Window of time close timed shutter active
USTHRSH = 'No      '           / Was EM thresholding used?
THRSHLD =          211805800.0 / Threshold counts
THRSBIN = '816.875 '           / Threshold bin
OUTDIR  = '/s/sdata1701/kpf1/2024apr21/L0' / Output directory
OFNAME  = 'KP.20240422.28832.89.fits' / Filename of output file
GREENFN = '/s/sdata1701/kpf1/2024apr21/Green/kpf_215921.fits'
REDFN   = '/s/sdata1701/kpf1/2024apr21/Red/kpf_215921.fits'
CA_HKFN = '/s/sdata1701/kpf1/2024apr21/CaHK/kpf_hk_215921.fits'
EXPMETFN= '/s/sdata1701/kpf1/2024apr21/ExpMeter/kpf_em_215921.fits'
GUIDEFN = '/s/sdata1701/kpf1/2024apr21/CRED2/kpfguide_cube_13570.fits'
FRAMENO =               215921
GRCAMD_V= 'Nov  9 2022 09:50:15' / camerad build date Kwd green CAMD_VER
GREXPTI =                    0 / exposure time in msec Kwd green EXPTIME
GRFILENA= 'kpf_215921.fits'    / this filename Kwd green FILENAME
GRFIRMWA= '/kroot/rel/default/data/kpfgreen/ACF/regular-read-green.acf' / contro
GRGAIN02=                    1 / gain for AD chan 2 Kwd green GAIN02
GRGAIN03=                    1 / gain for AD chan 3 Kwd green GAIN03
GRHDRSHI=                    0 / number of HDR right-shift bits Kwd green HDRSHI
GROFFSET=                  100 / offset for AD chan 3 Kwd green OFFSET03
GRSHUTT =                    T / shutter was enabled Kwd green SHUTTEN
GRTM_ZO = 'GMT     '           / time zone Kwd green TM_ZONE
GRCDS0  = '#eval RGsettleT'    /  Kwd green CDS0
GRCDS1  = '#eval CDump - 1'    /  Kwd green CDS1
GRCDS2  = '#eval PixelT'       / 2 + SWsettleT Kwd green CDS2
GRCDS3  =                  950 /  Kwd green CDS3
GRDATAS1= '[4:2044,0:4080]'    / left Kwd green DATASEC1
GRDATAS2= '[50:2090,0:4080]'   / right Kwd green DATASEC2
GRDATE  = '2024-04-22T08:11:19.808910' / FITS file write time Kwd green DATE
GRFRAME =               215921 /  Kwd green FRAMENO
GROBSERV= 'Bossett,Carmichael' / Observer name Kwd green OBSERVER
GRPROGNA= 'C050    '           / Program name Kwd green PROGNAME
GRACF   = 'regular-read-green' / Last user-chosen ACF key Kwd green ACF
GRACFFI = 'regular-read-green.acf' / ACF file from ACF key Kwd green ACFFILE
GRACFMD5= '1EF8CF3BA1C2905FE9980C295DCB9953' / MD5 sum for ACFFILE; unknown if p
GRDATE-B= '2024-04-22T08:00:32.886179' / Shutter-open time Kwd green DATE-BEG
GRDATE-E= '2024-04-22T08:10:32.954200' / Shutter-close time Kwd green DATE-END
GRELAPS =              600.068 / Shutter-elapsed time Kwd green ELAPSED
RDCAMD_V= 'Nov  9 2022 09:50:15' / camerad build date Kwd red CAMD_VER
RDEXPTI =                    0 / exposure time in msec Kwd red EXPTIME
RDFILENA= 'kpf_215921.fits'    / this filename Kwd red FILENAME
RDFIRMWA= '/kroot/rel/default/data/kpfred/ACF/regular-read-red.acf' / controller
RDHDRSHI=                    0 / number of HDR right-shift bits Kwd red HDRSHIFT
RDSHUTT =                    T / shutter was enabled Kwd red SHUTTEN
RDTM_ZO = 'GMT     '           / time zone Kwd red TM_ZONE
RDCDS0  = '#eval RGsettleT'    /  Kwd red CDS0
RDCDS1  = '#eval CDump - 1'    /  Kwd red CDS1
RDCDS2  = '#eval PixelT'       / 2 + SWsettleT Kwd red CDS2
RDCDS3  =                  950 /  Kwd red CDS3
RDTEST  =                  123 / test fitskey from modes file Kwd red TEST
RDDATE  = '2024-04-22T08:11:19.799580' / FITS file write time Kwd red DATE
RDFRAME =               215921 /  Kwd red FRAMENO
RDOBSERV= 'Bossett,Carmichael' / Observer name Kwd red OBSERVER
RDPROGNA= 'C050    '           / Program name Kwd red PROGNAME
RDACF   = 'regular-read-red'   / Last user-chosen ACF key Kwd red ACF
RDACFFI = 'regular-read-red.acf' / ACF file from ACF key Kwd red ACFFILE
RDACFMD5= '46B91FD6D29EEBBDED920738326414BA' / MD5 sum for ACFFILE; unknown if p
RDDATE-B= '2024-04-22T08:00:32.886179' / Shutter-open time Kwd red DATE-BEG
RDDATE-E= '2024-04-22T08:10:32.954200' / Shutter-close time Kwd red DATE-END
RDELAPS =              600.068 / Shutter-elapsed time Kwd red ELAPSED
EMFRAME =               215921 / Frame number Kwd expmeter FRAMENO
EMFILEN = '/s/sdata1701/kpf1/2024apr21/ExpMeter/kpf_em_215921.fits' / Output fil
EMSEQBEG=                    1 / First obs number Kwd expmeter SEQBEG
EMSEQEND=                  204 / Last obs number Kwd expmeter SEQEND
EMDATE-B= '2024-04-22T08:10:31.831' / Date-Beg of 1st obs Kwd expmeter DATE-BEG
EMDATE-E= '2024-04-22T08:10:33.968' / Date-End of last obs Kwd expmeter DATE-END
GCDATE-B= '2024-04-22T08:00:32.345' / sequence begin Kwd guide DATE-BEG
GCDATE-E= '2024-04-22T08:10:33.120' / sequence end Kwd guide DATE-END
GCOUTDIR= '/s/sdata1701/kpf1/2024apr21/CRED2' / original output directory Kwd gu
GCOFNAME= 'kpfguide_cube_13570.fits' / original output filename Kwd guide OFNAME
GCNFRAM =                59857 / quantity of subframes Kwd guide NFRAMES
GCSUBX0 =                  278 / [pix] subframe x0 coordinate Kwd guide SUBX0
GCSUBX1 =                  406 / [pix] subframe x1 coordinate Kwd guide SUBX1
GCSUBY0 =                  200 / [pix] subframe y0 coordinate Kwd guide SUBY0
GCSUBY1 =                  328 / [pix] subframe y1 coordinate Kwd guide SUBY1
GCFPS   =                100.0 / frames per second Kwd guide FPS
GCGAIN  = 'High    '           / detector gain setting Kwd guide GAIN
GCTEMPD =               -40.01 / [deg C] sensor temperature Kwd guide TEMPDET
GCEXPOSI=                    T / continuous exposures active Kwd guide EXPOSING
GCINSTRU= 'KPF     '           / Selected instrument Kwd guide INSTRUME
GCTELESC= 'Keck I  '           / Telescope Kwd guide TELESCOP
GCRA    = '13:04:52.90'        / Right ascension Kwd guide RA
GCDEC   = '+63:45:14.0'        / Declination Kwd guide DEC
GCEL    =                44.25 / [deg] telescope elevation Kwd guide EL
GCAZ    =                12.03 / [deg] telescope azimuth Kwd guide AZ
GCPARANG=               206.31 / [deg] parallactic angle Kwd guide PARANG
GCVA    =                135.8 / [deg] vertical angle Kwd guide VA
GCPA    =                342.1 / [deg] sky position angle Kwd guide PA
GCMJD-O =         60422.337184 / Modified Julian day Kwd guide MJD-OBS
GCPMFM  =                  0.0 / PMFM value Kwd guide PMFM
GCUT    = '08:05:32.70'        / DCS Universal Time Kwd guide UT
GCDATE-O= '2024-04-22'         / Date dcs1.DATE Kwd guide DATE-OBS
GCSECFOC=                -1.72 / [mm] Secondary focus Kwd guide SECFOCUS
GCTELFOC=               -1.382 / [mm] Telescope focus Kwd guide TELFOCUS
GCTUBETE=                 1.01 / [degC] Telescope tube temperature Kwd guide TUB
GCTTCALC= 'Active  '           / Tip/tilt calculation loop Kwd guide TTCALC
GCTTCTRL= 'Active  '           / Tip/tilt control loop Kwd guide TTCTRL
GCTTCTR = 'Mirror  '           / Tip/tilt control Y-axis Kwd guide TTCTRLY
GCTTGAIN=                  0.3 / Tip/tilt command gain Kwd guide TTGAIN
GCOFFGA =                  1.5 / Offload command gain Kwd guide OFFGAIN
GCOBJAR =                  100 / [pix] Object area Kwd guide OBJAREA
GCOBJINT=                   10 / Object intensity Kwd guide OBJINTEN
GCDBCONT=                  7.0 / Deblend contrast ratio Kwd guide DBCONT
GCDBTHRE=                   32 / Deblend thresholds Kwd guide DBTHRESH
GCWCSNA = 'RA/Dec  '           / Descriptive name of this WCS Kwd guide WCSNAME
GCCTYPE1= 'RA---TAN'           / Coordinate type of WCS axis 1 Kwd guide CTYPE1
GCCTYPE2= 'DEC--TAN'           / Coordinate type of WCS axis 2 Kwd guide CTYPE2
GCCNAME1= 'Right Ascension'    / Descriptive name of WCS axis 1 Kwd guide CNAME1
GCCNAME2= 'Declination'        / Descriptive name of WCS axis 2 Kwd guide CNAME2
GCCUNIT1= 'deg     '           / Physical unit of WCS axis 1 Kwd guide CUNIT1
GCCUNIT2= 'deg     '           / Physical unit of WCS axis 2 Kwd guide CUNIT2
GCRADECS= 'ICRS    '           / Celestial coordinate system Kwd guide RADECSYS
GCCD1_1 =         -4.95186E-06 / [deg] RA per pixel in x Kwd guide CD1_1
GCCD1_2 =          1.53312E-05 / [deg] RA per pixel in y Kwd guide CD1_2
GCCD2_1 =          1.53312E-05 / [deg] DEC per pixel in x Kwd guide CD2_1
GCCD2_2 =          4.95186E-06 / [deg] DEC per pixel in y Kwd guide CD2_2
GCCRPIX1=              342.081 / [pix] X coordinate of center pixel Kwd guide CR
GCCRPIX2=              264.411 / [pix] Y coordinate of center pixel Kwd guide CR
GCCRVAL1=           196.220417 / [deg] RA of center pixel Kwd guide CRVAL1
GCCRVAL2=            63.753889 / [deg] DEC of center pixel Kwd guide CRVAL2
GCWCSNAM= 'Az/El   '           / Descriptive name of this WCS Kwd guide WCSNAMEY
GCCTYPE = 'TLAT-TAN'           / Coordinate type of WCS axis 2 Kwd guide CTYPE2Y
GCCNAME = 'Elevation'          / Descriptive name of WCS axis 2 Kwd guide CNAME2
GCCUNIT = 'deg     '           / Physical unit of WCS axis 2 Kwd guide CUNIT2Y
GCRADESY= 'ICRS    '           / Celestial coordinate system Kwd guide RADESYSY
GCCD1_1R=         -4.95186E-06 / [deg] RA per pixel in x Kwd guide CD1_1R
GCCD1_2R=          1.53312E-05 / [deg] RA per pixel in y Kwd guide CD1_2R
GCCD2_1R=          1.53312E-05 / [deg] DEC per pixel in x Kwd guide CD2_1R
GCCD2_2R=          4.95186E-06 / [deg] DEC per pixel in y Kwd guide CD2_2R
GCCRPIX =              264.411 / [pix] Y coordinate of center pixel Kwd guide CR
GCCRVAL =            44.251018 / [deg] El of center pixel Kwd guide CRVAL2Y
GCCD1_1Y=         -1.15502E-05 / [deg] Az per pixel in x Kwd guide CD1_1Y
GCCD1_2Y=         -1.12321E-05 / [deg] Az per pixel in y Kwd guide CD1_2Y
GCCD2_1Y=         -1.12321E-05 / [deg] El per pixel in x Kwd guide CD2_1Y
GCCD2_2Y=          1.15502E-05 / [deg] El per pixel in y Kwd guide CD2_2Y
DRPTAG  = 'v2.7.1  '
DRPHASH = '9f75131b54e92561d83c19b303737362146a360a'
COMMENT
COMMENT ------------------------------------------------------------------------
COMMENT End of keyheader output
COMMENT Header generation start time: 2024-04-22T08:11:24.478531Z
COMMENT Header generation end time:   2024-04-22T08:11:24.534287Z
COMMENT ------------------------------------------------------------------------
COMMENT The keywords that begin with GR come from the green detector system.
COMMENT The keyword and value come from the Primary HDU of the FITS file.
COMMENT The original keyword name follows the Kwd in the comment field
COMMENT The keywords that begin with RD come from the red detector system.
COMMENT The keyword and value come from the Primary HDU of the FITS file.
COMMENT The original keyword name follows the Kwd in the comment field
COMMENT The keywords that begin with EM come from the expmeter detector system.
COMMENT The keyword and value come from the Primary HDU of the FITS file.
COMMENT The original keyword name follows the Kwd in the comment field
COMMENT The keywords that begin with GC come from the guide detector system.
COMMENT The keyword and value come from the Primary HDU of the FITS file.
COMMENT The original keyword name follows the Kwd in the comment field

Extract Keywords

Here we extra the name of the target star and the exposure time and assign them to variables.

[5]:
starname = L0.header['PRIMARY']['TARGNAME']
Texp = L0.header['PRIMARY']['GRELAPS'] # actually, this is the green CCD exposure time
print('Star = ' + starname)
print('Exposure time = ' + str(Texp) + ' sec')
Star = T001823
Exposure time = 600.068 sec

Note that the above code uses KPF0.from_fits() to read KPF fits files. This is the prefered method because the output is a KPF object, which has some built-in properties that are not generated by with from astropy.io import fits and then L0 = fits.open(L0_file).

One difference is that the headers in the object created by the Astropy version of from_fits() are accessed like L0['PRIMARY'].header and L0['PRIMARY'].header['TARGNAME'], not L0.header['PRIMARY'] and L0.header['PRIMARY']['TARGNAME'] as above with the KPF objects.

Green CCD

There are two halves or four quadrants in the green CCD with separate extensions (depending on the read most; KPF has been operating in two-amplifier mode with the Green CCD since mid-2023). Let’s plot one of them.

[6]:
plt.figure(tight_layout=True)
plt.figure(figsize=(6, 6), tight_layout=True)
plt.imshow(L0['GREEN_AMP2'].data, cmap='viridis', origin='lower',
           vmin=np.percentile(L0['GREEN_AMP1'].data,0.1),
           vmax=np.percentile(L0['GREEN_AMP1'].data,99))
plt.xlabel('CCD Quadrant Column Number', fontsize=16)
plt.ylabel('CCD Quadrant Row Number', fontsize=16)
plt.colorbar(shrink=0.7)
plt.grid(False)
plt.show()
<Figure size 432x288 with 0 Axes>
../_images/tutorials_KPF_Data_Tutorial_L0_and_2D_13_1.png

Red CCD

There are two halves for the Red CCD (when read out in 2-amplifier mode). Let’s plot one of them

[7]:
plt.figure(tight_layout=True)
plt.figure(figsize=(6, 12), tight_layout=True)
plt.imshow(L0['RED_AMP1'].data, cmap='viridis', origin='lower',
           vmin=np.percentile(L0['RED_AMP1'].data,0.1),
           vmax=np.percentile(L0['RED_AMP1'].data,99))
plt.xlabel('CCD Quadrant Column Number', fontsize=16)
plt.ylabel('CCD Quadrant Row Number', fontsize=16)
plt.colorbar(shrink=0.66)
plt.grid(False)
plt.show()
<Figure size 432x288 with 0 Axes>
../_images/tutorials_KPF_Data_Tutorial_L0_and_2D_15_1.png

2D File

The 2D file is similar to L0 except that the image segments of the green and red CCDs have been assembled (prescan and overcal removed) and bias has been subtracted. Note that this example uses the from_fits() method from the KPF DRP.

[8]:
D2 = KPF0.from_fits(D2_file, data_type='KPF')
D2.info()
File name: KP.20240422.28832.89_2D.fits
|Header Name          |# Cards
================================================================================
|PRIMARY              |                 519
|RECEIPT              |                  29
|CONFIG               |                  13
|GREEN_AMP1           |                  22
|GREEN_AMP2           |                  22
|GREEN_CCD            |                  11
|GREEN_VAR            |                   9
|RED_AMP1             |                  22
|RED_AMP2             |                  22
|RED_CCD              |                  11
|RED_VAR              |                   9
|CA_HK                |                  56
|EXPMETER_SCI         |                 849
|EXPMETER_SKY         |                 849
|GUIDECAM             |                   7
|TELEMETRY            |                  26
|SOLAR_IRRADIANCE     |                   9
|GUIDER_CUBE_ORIGINS  |                  87
|GUIDER_AVG           |                   8

|Extension Name       |Data Type            |Data Dimension
================================================================================
|RECEIPT              |table                |5
|CONFIG               |table                |0
|GREEN_AMP1           |image                |(0,)
|GREEN_AMP2           |image                |(0,)
|GREEN_CCD            |image                |(4080, 4080)
|GREEN_VAR            |image                |(4080, 4080)
|RED_AMP1             |image                |(0,)
|RED_AMP2             |image                |(0,)
|RED_CCD              |image                |(4080, 4080)
|RED_VAR              |image                |(4080, 4080)
|CA_HK                |image                |(255, 1024)
|EXPMETER_SCI         |table                |204
|EXPMETER_SKY         |table                |204
|GUIDECAM             |image                |(0,)
|TELEMETRY            |table                |131
|SOLAR_IRRADIANCE     |table                |0
|GUIDER_AVG           |image                |(512, 640)
|GUIDER_CUBE_ORIGINS  |table                |59857

[9]:
fig, axs = plt.subplots(1, 2, figsize=(16,10), tight_layout=True)
im1 = axs[0].imshow(D2['GREEN_CCD'].data, cmap='viridis', origin='lower', vmin=0, vmax=np.percentile(D2['GREEN_CCD'].data,99))
axs[0].set_title('Green CCD', fontsize=16)
axs[0].set_xlabel('CCD Column Number', fontsize=16)
axs[0].set_ylabel('CCD Row Number', fontsize=16)
fig.colorbar(im1, ax=axs[0], shrink=0.6)
im2 = axs[1].imshow(D2['RED_CCD'].data, cmap='viridis', origin='lower', vmin=0, vmax=np.percentile(D2['RED_CCD'].data,99))
axs[1].set_title('Red CCD', fontsize=16)
axs[1].set_xlabel('CCD Column Number', fontsize=16)
axs[1].set_ylabel('CCD Row Number', fontsize=16)
fig.colorbar(im2, ax=axs[1], shrink=0.6)
axs[0].grid(False)
axs[1].grid(False)
plt.subplots_adjust(wspace=0.4)
plt.show()
../_images/tutorials_KPF_Data_Tutorial_L0_and_2D_18_0.png

Exposure Meter

Back in the L0 file, there are extensions for the EM SCI and EM SKY fibers. The example below is for EM SCI, but EM SKY is similar. Here we create a Pandas data frame with the spectral time series. Each row is a spectrum for light collected between Date-Beg and Date-End. This example uses the from_fits() method of the KPF DRP to read the L0 file. If one uses the Astropy from_fits() method, then the EM SCI data frame can be created using df_SCI_EM = Table.read(L0_file, format='fits',hdu='EXPMETER_SCI').to_pandas().

[10]:
df_SCI_EM = L0['EXPMETER_SCI']
df_SCI_EM
[10]:
Date-Beg Date-End Date-Beg-Corr Date-End-Corr 872.5 869.1 865.8 862.4 859.2 855.9 ... 447.8 447.4 447.1 446.8 446.4 446.1 445.8 445.4 445.1 444.8
0 2024-04-22T08:00:32.437 2024-04-22T08:00:34.567 2024-04-22T08:00:32.886 2024-04-22T08:00:34.567 1137.109803 1066.929803 1170.369803 1034.909803 1166.109803 1118.889803 ... 136.609803 98.029803 119.609803 -36.930197 83.449803 83.069803 112.289803 85.769803 34.949803 154.969803
1 2024-04-22T08:00:35.386 2024-04-22T08:00:37.524 2024-04-22T08:00:35.386 2024-04-22T08:00:37.524 1513.631970 1477.451970 1373.891970 1453.431970 1357.631970 1429.411970 ... 75.131970 6.551970 24.131970 115.591970 106.971970 141.591970 -24.188030 53.291970 207.471970 103.491970
2 2024-04-22T08:00:38.345 2024-04-22T08:00:40.483 2024-04-22T08:00:38.345 2024-04-22T08:00:40.483 1481.001429 1394.821429 1465.261429 1496.801429 1525.001429 1465.781429 ... 34.501429 125.921429 131.501429 157.961429 79.341429 54.961429 133.181429 72.661429 -14.158571 170.861429
3 2024-04-22T08:00:41.302 2024-04-22T08:00:43.440 2024-04-22T08:00:41.302 2024-04-22T08:00:43.440 1502.395517 1430.215517 1503.655517 1413.195517 1542.395517 1632.175517 ... 80.895517 58.315517 97.895517 -20.644483 136.735517 126.355517 88.575517 56.055517 9.235517 123.255517
4 2024-04-22T08:00:44.260 2024-04-22T08:00:46.395 2024-04-22T08:00:44.260 2024-04-22T08:00:46.395 1472.351182 1414.171182 1482.611182 1552.151182 1376.351182 1465.131182 ... -28.148818 33.271182 72.851182 151.311182 155.691182 65.311182 -11.468818 87.011182 51.191182 123.211182
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
199 2024-04-22T08:10:20.014 2024-04-22T08:10:22.143 2024-04-22T08:10:20.014 2024-04-22T08:10:22.143 1414.764975 1381.584975 1529.024975 1372.564975 1535.764975 1531.544975 ... 69.264975 92.684975 79.264975 54.724975 58.104975 144.724975 21.944975 43.424975 136.604975 37.624975
200 2024-04-22T08:10:22.969 2024-04-22T08:10:25.110 2024-04-22T08:10:22.969 2024-04-22T08:10:25.110 1438.188621 1411.008621 1453.448621 1551.988621 1459.188621 1596.968621 ... 104.688621 27.108621 90.688621 83.148621 -13.471379 74.148621 112.368621 91.848621 145.028621 92.048621
201 2024-04-22T08:10:25.917 2024-04-22T08:10:28.052 2024-04-22T08:10:25.917 2024-04-22T08:10:28.052 1488.040837 1386.860837 1488.300837 1482.840837 1646.040837 1548.820837 ... 152.540837 53.960837 18.540837 90.000837 92.380837 132.000837 12.220837 113.700837 76.880837 79.900837
202 2024-04-22T08:10:28.879 2024-04-22T08:10:31.018 2024-04-22T08:10:28.879 2024-04-22T08:10:31.018 1361.774828 1430.594828 1326.034828 1389.574828 1396.774828 1491.554828 ... -24.725172 13.694828 109.274828 52.734828 101.114828 -19.265172 53.954828 24.434828 112.614828 -12.365172
203 2024-04-22T08:10:31.831 2024-04-22T08:10:33.968 2024-04-22T08:10:31.831 2024-04-22T08:10:32.954 735.484187 728.304187 833.744187 803.284187 896.484187 871.264187 ... 86.984187 123.404187 150.984187 95.444187 39.824187 54.444187 -6.335813 127.144187 134.324187 98.344187

204 rows × 420 columns

Convert Exposure Meter Data into Flux Measurements

[11]:
# Gain of CCD in KPF Exposure Meter
EM_gain = 1.48424 # e-/ADU

# Define wavelength arrays and disperion at each wavelength (nm per pixel)
wav_SCI_str = df_SCI_EM.columns[4:]               # string (center) wavelengths of each pixel
wav_SCI     = df_SCI_EM.columns[4:].astype(float) # float  (center) wavelengths of each pixel
disp_SCI        = wav_SCI*0+np.gradient(wav_SCI,1)*-1
disp_SCI_smooth = np.polyval(np.polyfit(wav_SCI,disp_SCI, deg=6),wav_SCI)

# define normalized flux array (e- / nm / time)
df_SCI_EM_norm = df_SCI_EM[wav_SCI_str] * EM_gain / disp_SCI_smooth

# define time arrays
date_beg = np.array(df_SCI_EM["Date-Beg-Corr"], dtype=np.datetime64)
date_end = np.array(df_SCI_EM["Date-End-Corr"], dtype=np.datetime64)
tdur_sec = (date_end-date_beg).astype(float)/1000. # array exposure durations in sec
time     = (date_beg-date_beg[0])/1000 # array of times since beginning in sec

# define indices for wavelength
ind_550m    = np.where((wav_SCI <  550))
ind_550_650 = np.where((wav_SCI >= 550) & (wav_SCI < 650))
ind_650_750 = np.where((wav_SCI >= 650) & (wav_SCI < 750))
ind_750p    = np.where((wav_SCI >= 750))



# define flux arrays
int_SCI_spec         = df_SCI_EM_norm[1:-1].sum(axis=0) / np.sum(tdur_sec[1:-1]) # flux vs. wavelength per sec (use first five samples)
int_SCI_flux         = df_SCI_EM.sum(axis=1)                                     # flux (ADU) vs. time (per sample)
int_SCI_flux_550m    = df_SCI_EM[wav_SCI_str[np.where((wav_SCI <  550))]].sum(axis=1)
int_SCI_flux_550_650 = df_SCI_EM[wav_SCI_str[np.where((wav_SCI >= 550) & (wav_SCI < 650))]].sum(axis=1)
int_SCI_flux_650_750 = df_SCI_EM[wav_SCI_str[np.where((wav_SCI >= 650) & (wav_SCI < 750))]].sum(axis=1)
int_SCI_flux_750p    = df_SCI_EM[wav_SCI_str[np.where((wav_SCI >= 750))]].sum(axis=1)

Plot EM SCI Spectrum

[12]:
plt.style.use('seaborn-whitegrid')
plt.figure(figsize=(12, 6), tight_layout=True)
plt.axvspan(440, 550, alpha=0.5, color='b')
plt.axvspan(550, 650, alpha=0.5, color='g')
plt.axvspan(650, 750, alpha=0.5, color='orange')
plt.axvspan(750, 880, alpha=0.5, color='red')
plt.plot(wav_SCI, int_SCI_spec, marker='o', color='k')
plt.xlabel("Wavelength (nm)", fontsize=14)
plt.ylabel("Average Exposure Meter Flux (e-/nm/s)", fontsize=14)
plt.xticks(fontsize=14)
plt.yticks(fontsize=14)
plt.xlim(445,870)
plt.legend(["EM SCI"], fontsize=12, loc='best')
plt.show()
#plt.savefig('expmeter_flux_vs_wavelength.png',dpi=144)
../_images/tutorials_KPF_Data_Tutorial_L0_and_2D_24_0.png

Plot EM SCI Time Series

[13]:
plt.style.use('seaborn-whitegrid')
plt.figure(figsize=(12, 6), tight_layout=True)
plt.plot(time, int_SCI_flux_750p    / ((847+4.8/2)-750)           / tdur_sec, marker='o', color='r')
plt.plot(time, int_SCI_flux_650_750 / (750-650)                   / tdur_sec, marker='o', color='orange')
plt.plot(time, int_SCI_flux_550_650 / (650-550)                   / tdur_sec, marker='o', color='g')
plt.plot(time, int_SCI_flux_550m    / (550-(450.1-0.4/2))         / tdur_sec, marker='o', color='b')
plt.plot(time, int_SCI_flux         / ((847+4.8/2)-(450.1-0.4/2)) / tdur_sec, marker='o', color='k')
plt.xlabel("Time (sec)", fontsize=14)
plt.ylabel("Exposure Meter Flux (e-/nm/s)", fontsize=14)
plt.xticks(fontsize=14)
plt.yticks(fontsize=14)
plt.legend(["750-870 nm","650-750 nm","550-650 nm","445-550 nm","445-870 nm",], fontsize=12, loc='best')
plt.show()
../_images/tutorials_KPF_Data_Tutorial_L0_and_2D_26_0.png

Plot Fraction of Flux Time Series in Each Color Bin

This is a measure of the ADC performance.

[14]:
plt.style.use('seaborn-whitegrid')
plt.figure(figsize=(12, 6), tight_layout=True)
plt.plot(time, (int_SCI_flux_550m    / int_SCI_flux ) , marker='o', color='b')
plt.plot(time, (int_SCI_flux_550_650 / int_SCI_flux ) , marker='o', color='g')
plt.plot(time, (int_SCI_flux_650_750 / int_SCI_flux ) , marker='o', color='orange')
plt.plot(time, (int_SCI_flux_750p    / int_SCI_flux ) , marker='o', color='r')
plt.xlabel("Time (sec)", fontsize=14)
plt.ylabel("Exposure Meter Flux Ratio", fontsize=14)
plt.xticks(fontsize=14)
plt.yticks(fontsize=14)
plt.ylim(0,0.45)
plt.legend(["750-870 nm / 445-870 nm",
            "650-750 nm / 445-870 nm",
            "550-650 nm / 445-870 nm",
            "445-550 nm / 445-870 nm"],
           fontsize=12, loc='best')
plt.show()
#plt.savefig('EM_flux_ratio_51peg.png')
../_images/tutorials_KPF_Data_Tutorial_L0_and_2D_28_0.png

Telemetry

Each KPF L0 file contains telemetry on >100 sensors or state values with average, standard deviation, minimum, and maximum values listed.

[15]:
#L0['TELEMETRY']
df_telemetry = L0['TELEMETRY']
df_telemetry.set_index("keyword", inplace=True)
df_telemetry
[15]:
average stddev min max units description
keyword
kpfmet.BENCH_BOTTOM_BETWEEN_CAMERAS 14.3361 0.000524517 14.335 14.337 degC Bench Bottom Between Cameras C2 c- double degC...
kpfmet.BENCH_BOTTOM_COLLIMATOR 14.7717 0.000540249 14.771 14.773 degC Bench Bottom Coll C3 c- double degC {%.3f}
kpfmet.BENCH_BOTTOM_DCUT 14.5422 0.00048175 14.541 14.543 degC Bench Bottom D-cut C4 c- double degC {%.3f}
kpfmet.BENCH_BOTTOM_ECHELLE 14.7104 0.000569869 14.709 14.712 degC Bench Bottom Echelle Cam B c- double degC {%.3f}
kpfmet.BENCH_TOP_BETWEEN_CAMERAS 14.2793 0.000488698 14.278 14.28 degC Bench Top Between Cameras D4 c- double degC {%...
... ... ... ... ... ... ...
kpfmot.AGITAMBI_T 25.8256 0.120058 25.37 26.07 degC Agitator ambient temperature c- double degC {%...
kpfmot.AGITMOT_T 0.448866 0.00922575 0.42 0.48 degC Agitator motor temperature c- double degC {%.2...
kpfpower.OUTLET_A1_Amps 49.4141 1.42826 27 51 milliamps Outlet A1 current amperage c- int milliamps
kpfmon.NTPSTRA_SERVER 2 0 2 2 stratum NTP stratum, from kwd NTPX_SERVER c- int
kpfmon.NTPWMS_SERVER 2.59966 0.490389 2 3 ms NTP within ms, from kwd NTPX_SERVER c- int

131 rows × 6 columns

If one uses the Astropy from_fits() method, then the telemetry data frame can be created as shown below.

df_telemetry = Table.read(L0_file, format='fits', hdu='TELEMETRY').to_pandas()
num_columns = ['average', 'stddev', 'min', 'max']
for column in df_telemetry:
    df_telemetry[column] = df_telemetry[column].str.decode('utf-8')
    df_telemetry = df_telemetry.replace('-nan', 0)# replace nan with 0
    if column in num_columns:
        df_telemetry[column] = pd.to_numeric(df_telemetry[column], downcast="float")
    else:
        df_telemetry[column] = df_telemetry[column].astype(str)
df_telemetry.set_index("keyword", inplace=True)
[16]:
df_telemetry.info()
<class 'pandas.core.frame.DataFrame'>
Index: 131 entries, kpfmet.BENCH_BOTTOM_BETWEEN_CAMERAS to kpfmon.NTPWMS_SERVER
Data columns (total 6 columns):
 #   Column       Non-Null Count  Dtype
---  ------       --------------  -----
 0   average      131 non-null    object
 1   stddev       131 non-null    object
 2   min          131 non-null    object
 3   max          131 non-null    object
 4   units        131 non-null    object
 5   description  131 non-null    object
dtypes: object(6)
memory usage: 7.2+ KB

Print the entire table of telemetry.

[17]:
with pd.option_context('display.max_rows', None, 'display.max_columns', None):
    display(df_telemetry)
average stddev min max units description
keyword
kpfmet.BENCH_BOTTOM_BETWEEN_CAMERAS 14.3361 0.000524517 14.335 14.337 degC Bench Bottom Between Cameras C2 c- double degC...
kpfmet.BENCH_BOTTOM_COLLIMATOR 14.7717 0.000540249 14.771 14.773 degC Bench Bottom Coll C3 c- double degC {%.3f}
kpfmet.BENCH_BOTTOM_DCUT 14.5422 0.00048175 14.541 14.543 degC Bench Bottom D-cut C4 c- double degC {%.3f}
kpfmet.BENCH_BOTTOM_ECHELLE 14.7104 0.000569869 14.709 14.712 degC Bench Bottom Echelle Cam B c- double degC {%.3f}
kpfmet.BENCH_TOP_BETWEEN_CAMERAS 14.2793 0.000488698 14.278 14.28 degC Bench Top Between Cameras D4 c- double degC {%...
kpfmet.BENCH_TOP_COLL 14.8719 0.000536114 14.871 14.873 degC Bench Top Coll D5 c- double degC {%.3f}
kpfmet.BENCH_TOP_DCUT 14.5873 0.000516643 14.586 14.588 degC Bench Top D-cut D3 c- double degC {%.3f}
kpfmet.BENCH_TOP_ECHELLE_CAM 14.6172 0.000505709 14.616 14.618 degC Bench Top Echelle Cam D1 c- double degC {%.3f}
kpfmet.CALEM_SCMBLR_CHMBR_END 15.2488 0.000700176 15.248 15.25 degC Cal EM Scrammbler Chamber End C1 c- double deg...
kpfmet.CALEM_SCMBLR_FIBER_END 15.0862 0.000600753 15.085 15.088 degC Cal EM Scrambler Fiber End D1 c- double degC {...
kpfmet.CAL_BENCH 18.3 6.35278e-08 18.3 18.3 degC CAL_BENCH temperature c- double degC {%.1f}
kpfmet.CAL_BENCH_BB_SRC 18.7137 0.0344625 18.7 18.8 degC CAL_BENCH_BB_SRC temperature c- double degC {%...
kpfmet.CAL_BENCH_BOT 21.3136 0.0342806 21.3 21.4 degC CAL_BENCH_BOT temperature c- double degC {%.1f}
kpfmet.CAL_BENCH_ENCL_AIR 18.2 -nan 18.2 18.2 degC CAL_BENCH_ENCL_AIR temperature c- double degC ...
kpfmet.CAL_BENCH_OCT_MOT 18.1 2.47282e-08 18.1 18.1 degC CAL_BENCH_OCT_MOT temperature c- double degC {...
kpfmet.CAL_BENCH_TRANS_STG_MOT 18.2 -nan 18.2 18.2 degC CAL_BENCH_TRANS_STG_MOT temperature c- double ...
kpfmet.CAL_RACK_TOP 21.1 2.21176e-08 21.1 21.1 degC CAL_RACK_TOP temperature c- double degC {%.1f}
kpfmet.CHAMBER_EXT_BOTTOM 13.4186 0.00076673 13.417 13.42 degC Chamber Exterior Bottom B c- double degC {%.3f}
kpfmet.CHAMBER_EXT_TOP -273.15 4.61404e-07 -273.15 -273.15 degC Chamber Exterior Top C1 c- double degC {%.3f}
kpfmet.CRYOSTAT_G1 -273.15 4.61404e-07 -273.15 -273.15 degC Within cryostat green D2 c- double degC {%.3f}
kpfmet.CRYOSTAT_G2 -273.15 4.61404e-07 -273.15 -273.15 degC Within cryostat green D3 c- double degC {%.3f}
kpfmet.CRYOSTAT_G3 16.8568 0.000724396 16.854 16.858 degC Within cryostat green D4 c- double degC {%.3f}
kpfmet.CRYOSTAT_R1 16.0729 0.000591516 16.072 16.074 degC Within Cryostat red D2 c- double degC {%.3f}
kpfmet.CRYOSTAT_R2 -273.15 4.61404e-07 -273.15 -273.15 degC Within Cryostat red D3 c- double degC {%.3f}
kpfmet.CRYOSTAT_R3 15.5321 0.000807012 15.53 15.534 degC Within Cryostat red D4 c- double degC {%.3f}
kpfmet.ECHELLE_BOTTOM 14.7301 0.000476314 14.729 14.731 degC Echelle Bottom D1 c- double degC {%.3f}
kpfmet.ECHELLE_TOP 14.578 0.000444586 14.577 14.579 degC Echelle Top C1 c- double degC {%.3f}
kpfmet.EXPMETER_1 28.1 1.17244e-07 28.1 28.1 degC EXPMETER_1 temperature c- double degC {%.1f}
kpfmet.EXPMETER_2 25.293 0.0256119 25.2 25.3 degC EXPMETER_2 temperature c- double degC {%.1f}
kpfmet.FF_SRC 17.1 -nan 17.1 17.1 degC FF_SRC temperature c- double degC {%.1f}
kpfmet.GREEN_CAMERA_BOTTOM 15.3159 0.000613804 15.315 15.318 degC Green Camera Bottom C3 c- double degC {%.3f}
kpfmet.GREEN_CAMERA_COLLIMATOR 15.3587 0.000649481 15.357 15.361 degC Green Camera Collimator C4 c- double degC {%.3f}
kpfmet.GREEN_CAMERA_ECHELLE 15.2669 0.000701366 15.265 15.268 degC Green Camera Echelle D5 c- double degC {%.3f}
kpfmet.GREEN_CAMERA_TOP 15.1776 0.000669561 15.176 15.179 degC Green Camera Top C2 c- double degC {%.3f}
kpfmet.GREEN_GRISM_TOP 14.7984 0.000704194 14.797 14.8 degC Green Grism Top C5 c- double degC {%.3f}
kpfmet.GREEN_LN2_FLANGE 6.81303 0.0099326 6.792 6.838 degC Green LN2 Flange A c- double degC {%.3f}
kpfmet.LOWER_AUX_RACK 16.1381 0.0486159 16.1 16.2 degC LOWER_AUX_RACK temperature c- double degC {%.1f}
kpfmet.PRIMARY_COLLIMATOR_TOP 15.1555 0.000563998 15.154 15.157 degC Primary Col Top D2 c- double degC {%.3f}
kpfmet.RED_CAMERA_BOTTOM 14.8146 0.000707443 14.813 14.816 degC Red Camera Bottom D5 c- double degC {%.3f}
kpfmet.RED_CAMERA_COLLIMATOR 15.1483 0.000723759 15.147 15.15 degC Red Camera Coll C3 c- double degC {%.3f}
kpfmet.RED_CAMERA_ECHELLE 15.0947 0.00058406 15.093 15.096 degC Red Camera Ech C4 c- double degC {%.3f}
kpfmet.RED_CAMERA_TOP 15.0565 0.00068429 15.054 15.058 degC Red Camera Top C5 c- double degC {%.3f}
kpfmet.RED_GRISM_TOP 14.7694 0.000588758 14.768 14.771 degC Red Grism Top C2 c- double degC {%.3f}
kpfmet.RED_LN2_FLANGE 3.57325 0.0126173 3.544 3.603 degC Red LN2 Flange D1 c- double degC {%.3f}
kpfmet.REFORMATTER 14.8995 0.000500285 14.899 14.9 degC Reformatter A c- double degC {%.3f}
kpfmet.SCIENCE_CAL_FIBER_STG 18.2122 0.0327559 18.2 18.3 degC SCIENCE_CAL_FIBER_STG temperature c- double de...
kpfmet.SCISKY_SCMBLR_CHMBR_END -273.15 4.61404e-07 -273.15 -273.15 degC SciSky Scrambler Chamber End A c- double degC ...
kpfmet.SCISKY_SCMBLR_FIBER_END 15.2915 0.000549279 15.29 15.292 degC SciSky Scrammbler Fiber End B c- double degC {...
kpfmet.SIMCAL_FIBER_STG 18.2 -nan 18.2 18.2 degC SIMCAL_FIBER_STG temperature c- double degC {%...
kpfmet.SKYCAL_FIBER_STG 18.1 2.47282e-08 18.1 18.1 degC SKYCAL_FIBER_STG temperature c- double degC {%...
kpfmet.TEMP 18.2532 0.0212938 18.218 18.315 degC Vaisala Temperature c- double degC {%.3f}
kpfmet.TH_DAILY 18.2 -nan 18.2 18.2 degC TH_DAILY temperature c- double degC {%.1f}
kpfmet.TH_GOLD 18.2 -nan 18.2 18.2 degC TH_GOLD temperature c- double degC {%.1f}
kpfmet.UPPER_AUX_RACK 15.9 3.8942e-08 15.9 15.9 degC UPPER_AUX_RACK temperature c- double degC {%.1f}
kpfmet.U_DAILY 18.2141 0.0348211 18.2 18.3 degC U_DAILY temperature c- double degC {%.1f}
kpfmet.U_GOLD 18.0557 0.0497202 18 18.1 degC U_GOLD temperature c- double degC {%.1f}
kpfmet.VAC_CART_ABOVE_PUMP 29.6002 0.0373379 29.5 29.7 degC VAC_CART_ABOVE_PUMP temperature c- double degC...
kpfmet.VAC_CART_ELECTRONICS 29.5622 0.0485306 29.5 29.6 degC VAC_CART_ELECTRONICS temperature c- double deg...
kpfgreen.BPLANE_TEMP 34.1536 0.0330547 34.062 34.187 degC Backplane temperature c- double degC {%.3f}
kpfgreen.BRD10_DRVR_T 38.937 0.0280459 38.875 39 degC Board 10 (Driver) temperature c- double degC {...
kpfgreen.BRD11_DRVR_T 37.1135 0.0243359 37.062 37.125 degC Board 11 (Driver) temperature c- double degC {...
kpfgreen.BRD12_LVXBIAS_T 33.1765 0.0233149 33.125 33.187 degC Board 12 (LVxBias) temperature c- double degC ...
kpfgreen.BRD1_HTRX_T 30.0601 0.0300325 30 30.125 degC Board 1 (HeaterX) temperature c- double degC {...
kpfgreen.BRD2_XVBIAS_T 0 0 0 0 degC Board 2 (XV Bias) temperature c- double degC {...
kpfgreen.BRD3_LVDS_T 31.7799 0.0310083 31.75 31.812 degC Board 3 (LVDS) temperature c- double degC {%.3f}
kpfgreen.BRD4_DRVR_T 35.4747 0.0309164 35.437 35.5 degC Board 4 (Driver) temperature c- double degC {%...
kpfgreen.BRD5_AD_T 30.8464 0.0353862 30.75 30.937 degC Board 5 (AD) temperature c- double degC {%.3f}
kpfgreen.BRD7_HTRX_T 35.9881 0.0371853 35.937 36.062 degC Board 7 (HeaterX) temperature c- double degC {...
kpfgreen.BRD9_HVXBIAS_T 34.858 0.0300616 34.812 34.937 degC Board 9 (HVxBias) temperature c- double degC {...
kpfgreen.CF_BASE_2WT -127.167 0.000845305 -127.17 -127.166 degC tip cold finger (2 wire) c- double degC {%.3f}
kpfgreen.CF_BASE_T -273.15 4.61404e-07 -273.15 -273.15 degC base cold finger 2wire temp c- double degC {%.3f}
kpfgreen.CF_BASE_TRG -127.5 0 -127.5 -127.5 degC base cold finger heater 1A, target temp c2 dou...
kpfgreen.CF_TIP_T -127.888 0.000909884 -127.889 -127.886 degC tip cold finger c- double degC {%.3f}
kpfgreen.CF_TIP_TRG -128 0 -128 -128 degC tip cold finger heater 1B, target temp c2 doub...
kpfgreen.COL_PRESS 1e-11 3.13251e-20 1e-11 1e-11 Torr Current ion pump pressure c- double Torr {%.3e}
kpfgreen.CRYOBODY_T 19.0009 0.00212799 18.997 19.005 degC Cryo Body Temperature c- double degC {%.3f}
kpfgreen.CRYOBODY_TRG 19 0 19 19 degC Cryo body heater 7B, target temp c2 double deg...
kpfgreen.CURRTEMP -140 0.000960469 -140.003 -139.998 degC Current cold head temperature c- double degC {...
kpfgreen.ECH_PRESS 1.22027e-07 6.04167e-09 1.2e-07 1.4e-07 Torr Current ion pump pressure c- double Torr {%.3e}
kpfgreen.KPF_CCD_T -101.096 0.000711971 -101.097 -101.094 degC SSL Detector temperature c- double degC {%.3f}
kpfgreen.STA_CCD_T -99.9998 0.000892518 -100.001 -99.997 degC STA Detector temperature c- double degC {%.3f}
kpfgreen.STA_CCD_TRG -100 0 -100 -100 degC Detector heater 7A, target temp c2 double degC...
kpfgreen.TEMPSET -140 0 -140 -140 degC Set point for the cold head temperature c2 dou...
kpfred.BPLANE_TEMP 39.8132 0.0181424 39.75 39.875 degC Backplane temperature c- double degC {%.3f}
kpfred.BRD10_DRVR_T 43.9455 0.0244052 43.875 44 degC Board 10 (Driver) temperature c- double degC {...
kpfred.BRD11_DRVR_T 43.6521 0.0307748 43.625 43.687 degC Board 11 (Driver) temperature c- double degC {...
kpfred.BRD12_LVXBIAS_T 39.7292 0.0296465 39.687 39.75 degC Board 12 (LVxBias) temperature c- double degC ...
kpfred.BRD1_HTRX_T 36.2062 0.0331008 36.125 36.25 degC Board 1 (HeaterX) temperature c- double degC {...
kpfred.BRD2_XVBIAS_T 0 0 0 0 degC Board 2 (XV Bias) temperature c- double degC {...
kpfred.BRD3_LVDS_T 37.3792 0.0191734 37.312 37.437 degC Board 3 (LVDS) temperature c- double degC {%.3f}
kpfred.BRD4_DRVR_T 40.729 0.029724 40.687 40.75 degC Board 4 (Driver) temperature c- double degC {%...
kpfred.BRD5_AD_T 36.94 0.0387569 36.812 37 degC Board 5 (AD) temperature c- double degC {%.3f}
kpfred.BRD7_HTRX_T 41.5504 0.0290442 41.437 41.625 degC Board 7 (HeaterX) temperature c- double degC {...
kpfred.BRD9_HVXBIAS_T 40.8329 0.0356247 40.75 40.875 degC Board 9 (HVxBias) temperature c- double degC {...
kpfred.CF_BASE_2WT -125.689 0.000788791 -125.691 -125.688 degC tip cold finger (2 wire) c- double degC {%.3f}
kpfred.CF_BASE_T -273.15 4.61404e-07 -273.15 -273.15 degC base cold finger 2wire temp c- double degC {%.3f}
kpfred.CF_BASE_TRG -125.75 0 -125.75 -125.75 degC base cold finger heater 1A, target temp c2 dou...
kpfred.CF_TIP_T -127.07 0.000624189 -127.071 -127.068 degC tip cold finger c- double degC {%.3f}
kpfred.CF_TIP_TRG -127.25 0 -127.25 -127.25 degC tip cold finger heater 1B, target temp c2 doub...
kpfred.COL_PRESS 1e-11 3.13251e-20 1e-11 1e-11 Torr Current ion pump pressure c- double Torr {%.3e}
kpfred.CRYOBODY_T 18.9998 0.00217485 18.994 19.005 degC Cryo Body Temperature c- double degC {%.3f}
kpfred.CRYOBODY_TRG 19 0 19 19 degC Cryo body heater 7B, target temp c2 double deg...
kpfred.CURRTEMP -140.5 0.00302428 -140.507 -140.495 degC Current cold head temperature c- double degC {...
kpfred.ECH_PRESS 1.4256e-07 3.26006e-08 1.3e-07 3e-07 Torr Current ion pump pressure c- double Torr {%.3e}
kpfred.KPF_CCD_T -100.814 0.00117526 -100.817 -100.812 degC SSL Detector temperature c- double degC {%.3f}
kpfred.STA_CCD_T -99.9998 0.00199971 -100.005 -99.996 degC STA Detector temperature c- double degC {%.3f}
kpfred.STA_CCD_TRG -100 0 -100 -100 degC Detector heater 7A, target temp c2 double degC...
kpfred.TEMPSET -140.5 0 -140.5 -140.5 degC Set point for the cold head temperature c2 dou...
kpfexpose.BENCH_C 11.46 0.157198 11.1 12.1 degC rtd bench c- double degC {%.1f} { -100.0 .. 10...
kpfexpose.CAMBARREL_C 11.7675 0.167888 11.3 12.4 degC rtd camera barrel c- double degC {%.1f} { -100...
kpfexpose.DET_XTRN_C 14.9424 0.115135 14.7 15.3 degC rtd detector extermal c- double degC {%.1f} { ...
kpfexpose.ECHELLE_C -229.09 0.321566 -229.9 -228.4 degC rtd echelle c- double degC {%.1f} { -100.0 .. ...
kpfexpose.ENCLOSURE_C 14.4569 0.113066 14.1 14.9 degC rtd enclosure c- double degC {%.1f} { -100.0 ....
kpfexpose.RACK_AIR_C 15.068 0.0772323 14.9 15.3 degC rtd rack air c- double degC {%.1f} { -100.0 .....
kpfvac.PUMP_TEMP 43 0 43 43 degC Motor temperature c- double degC {%.2f}
kpf_hk.COOLTARG -60 0 -60 -60 degC temperature target c2 int degC
kpf_hk.CURRTEMP -59.78 1.9733e-07 -59.78 -59.78 degC current temperature c- double degC {%.2f}
kpfgreen.COL_CURR 5.6e-12 1.09025e-20 5.6e-12 5.6e-12 A Current ion pump current c- double A {%.3e}
kpfgreen.ECH_CURR 3.33488e-06 1.37859e-07 3.2e-06 3.7e-06 A Current ion pump current c- double A {%.3e}
kpfred.COL_CURR 5.56627e-12 4.83979e-15 5.56e-12 5.57e-12 A Current ion pump current c- double A {%.3e}
kpfred.ECH_CURR 3.8978e-06 9.52142e-07 3.5e-06 8.29e-06 A Current ion pump current c- double A {%.3e}
kpfcal.IRFLUX 4039.37 6.01266 4015 4057 Counts LFC Fiberlock IR Intensity c- int Counts {%d}
kpfcal.VISFLUX -4.71993 0.482658 -6 -3 Counts LFC Fiberlock Vis Intensity c- int Counts {%d}
kpfcal.BLUECUTIACT 0.0331203 0.0030179 0.023 0.053 A Blue cut amplifier 0 measured current c- doubl...
kpfmot.AGITSPD -3893.11 408.738 -4708 -1791 motor_counts/s agit raw velocity c2 int motor counts/s { -750...
kpfmot.AGITTOR -1.04035 0.692582 -2.618 0.333 V agit motor torque c- double V {%.3f}
kpfmot.AGITAMBI_T 25.8256 0.120058 25.37 26.07 degC Agitator ambient temperature c- double degC {%...
kpfmot.AGITMOT_T 0.448866 0.00922575 0.42 0.48 degC Agitator motor temperature c- double degC {%.2...
kpfpower.OUTLET_A1_Amps 49.4141 1.42826 27 51 milliamps Outlet A1 current amperage c- int milliamps
kpfmon.NTPSTRA_SERVER 2 0 2 2 stratum NTP stratum, from kwd NTPX_SERVER c- int
kpfmon.NTPWMS_SERVER 2.59966 0.490389 2 3 ms NTP within ms, from kwd NTPX_SERVER c- int
[18]:
print('Red CCD Temperature = ', df_telemetry.loc['kpfred.STA_CCD_T', 'average'], '+/-', df_telemetry.loc['kpfred.STA_CCD_T', 'stddev'], df_telemetry.loc['kpfred.STA_CCD_T', 'units'])
Red CCD Temperature =  -99.9998 +/- 0.00199971 degC

Guider Image

The guide camera images are from a CRED-2 camera with 0.056 arcsec pixels in a 950-1200nm passband (approximately z+J band). First, we will fit the image with a Moffat function (assuming a point source).

[19]:
from scipy.optimize import curve_fit

guider_im = D2['GUIDER_AVG'].data - np.median(D2['GUIDER_AVG'].data)
header = D2.header['PRIMARY']
pixel_scale = 0.056 # arcsec per pixel for the CRED-2 imager on the KPF FIU

def moffat_2D(xy, amplitude, x0, y0, alpha, beta):
    x, y = xy
    return amplitude * (1 + ((x - x0) ** 2 + (y - y0) ** 2) / alpha ** 2) ** -beta

x = np.arange(guider_im.shape[1])
y = np.arange(guider_im.shape[0])
X, Y = np.meshgrid(x, y)
x_flat = X.flatten()
y_flat = Y.flatten()
image_data_flat = guider_im.flatten()
p0 = [1, 18.5/0.056, 14.5/0.056, 5.0/0.056, 2.5]  # Initial guess for the parameters
#p0 = [1, header['GCCRPIX1']/2, header['GCCRPIX2']/2, 5.0/0.056, 2.5]  # Initial guess for the parameters
#p0 = [1, guider_im.shape[1] / 2, guider_im.shape[0] / 2, 5/0.056, 2]  # Initial guess for the parameters
popt, pcov = curve_fit(moffat_2D, (x_flat, y_flat), image_data_flat, p0=p0)
amplitude_fit, x0_fit, y0_fit, alpha_fit, beta_fit = popt
print('amplitude = ' + str(amplitude_fit))
print('seeing = ' + str(alpha_fit*0.056) + ' arcsec')
print('beta = ' + str(beta_fit))
print('x0 = ' + str(x0_fit) + ' pixels')
print('y0 = ' + str(y0_fit) + ' pixels')

image_fit = moffat_2D((X, Y), amplitude_fit, x0_fit, y0_fit, alpha_fit, beta_fit)
resid_im = guider_im - image_fit
amplitude = 2722.5908545066213
seeing = 0.45787570559734353 arcsec
beta = 3.1714690594664794
x0 = 342.13993554679377 pixels
y0 = 264.4009311512574 pixels

Plot Guider Image and Model Fit

[20]:
import matplotlib.ticker as ticker

# Plot the original image and residuals
guider_im_zoom = guider_im[255-38:255+38, 320-38:320+38]
resid_im_zoom =   resid_im[255-38:255+38, 320-38:320+38]
#subx0 = D2['GUIDER_AVG'].header['SUBX0']
#subx1 = D2['GUIDER_AVG'].header['SUBX1']
#suby0 = D2['GUIDER_AVG'].header['SUBY0']
#suby1 = D2['GUIDER_AVG'].header['SUBY1']
#guider_im_zoom = guider_im[subx0:subx1, suby0:suby1]
#resid_im_zoom  = guider_im[subx0:subx1, suby0:suby1]

fig, axs = plt.subplots(1, 3, figsize=(15, 5))

# Left panel - full image
im1 = axs[0].imshow(guider_im, cmap='viridis', origin='lower', vmin=0, vmax=np.percentile(guider_im_zoom,99.9))
axs[1].set_aspect(640/512)
image_size_pixels = guider_im.shape
image_size_arcsec = (image_size_pixels[1] * pixel_scale, image_size_pixels[0] * pixel_scale)
x_tick_locator = ticker.MultipleLocator(5/(pixel_scale-0.001))  # Set tick every 5 arcsec
axs[0].xaxis.set_major_locator(x_tick_locator)
y_tick_locator = ticker.MultipleLocator(5/(pixel_scale-0.001))  # Set tick every 5 arcsec
axs[0].yaxis.set_major_locator(y_tick_locator)
xticks = axs[0].get_xticks()
yticks = axs[0].get_yticks()
axs[0].set_xticklabels([f'{int(x * pixel_scale)}' for x in xticks])
axs[0].set_yticklabels([f'{int(y * pixel_scale)}' for y in yticks])
axs[0].set_xlabel('Arcseconds', fontsize=14)
axs[0].set_ylabel('Arcseconds', fontsize=14)
axs[0].set_title('Guider Image - '+str(ObsID)+'\n' +
                 f"{alpha_fit*pixel_scale:.2f}" + '" seeing (z+J-band)\n' +
                 f"{alpha_fit*pixel_scale*(1100/550)**0.2:.2f}" + '" seeing (V-band, scaled)', fontsize=14)
axs[0].grid(True, linestyle='solid', linewidth=0.5, alpha=0.5)
cbar1 = plt.colorbar(im1, ax=axs[0], shrink=0.6)

# Middle panel - zoomed image
im2 = axs[1].imshow(guider_im_zoom, cmap='viridis', origin='lower', vmin=0, vmax=np.percentile(guider_im_zoom,99.9))
axs[1].set_aspect('equal')
image_size_pixels = guider_im_zoom.shape
image_size_arcsec = (image_size_pixels[1] * pixel_scale, image_size_pixels[0] * pixel_scale)
x_tick_locator = ticker.MultipleLocator(0.5/(pixel_scale-0.001))  # Set tick every 0.5 arcsec
axs[1].xaxis.set_major_locator(x_tick_locator)
y_tick_locator = ticker.MultipleLocator(0.5/(pixel_scale-0.001))  # Set tick every 0.5 arcsec
axs[1].yaxis.set_major_locator(y_tick_locator)
xticks = axs[1].get_xticks()
yticks = axs[1].get_yticks()
axs[1].set_xticklabels([f'{int(x * pixel_scale*10)/10}' for x in xticks])
axs[1].set_yticklabels([f'{int(y * pixel_scale*10)/10}' for y in yticks])
axs[1].set_xlabel('Arcseconds', fontsize=14)
axs[1].set_ylabel('Arcseconds', fontsize=14)
axs[1].set_title('Guider Image (zoomed in)', fontsize=14)
axs[1].grid(True, linestyle='solid', linewidth=0.5, alpha=0.5)
cbar2 = plt.colorbar(im2, ax=axs[1], shrink=0.6)

# Right panel - zoomed image of residuals to model
im2 = axs[2].imshow(resid_im_zoom, cmap='viridis', origin='lower', vmin=0, vmax=np.percentile(guider_im_zoom,99.9))
image_size_pixels = guider_im_zoom.shape
image_size_arcsec = (image_size_pixels[1] * pixel_scale, image_size_pixels[0] * pixel_scale)
x_tick_locator = ticker.MultipleLocator(0.5/(pixel_scale-0.001))  # Set tick every 0.5 arcsec
axs[2].xaxis.set_major_locator(x_tick_locator)
y_tick_locator = ticker.MultipleLocator(0.5/(pixel_scale-0.001))  # Set tick every 0.5 arcsec
axs[2].yaxis.set_major_locator(y_tick_locator)
xticks = axs[2].get_xticks()
yticks = axs[2].get_yticks()
axs[2].set_xticklabels([f'{int(x * pixel_scale*10)/10}' for x in xticks])
axs[2].set_yticklabels([f'{int(y * pixel_scale*10)/10}' for y in yticks])
axs[2].set_xlabel('Arcseconds', fontsize=14)
axs[2].set_ylabel('Arcseconds', fontsize=14)
axs[2].set_title('Residuals to Moffat Function Model', fontsize=14)
axs[2].grid(True, linestyle='solid', linewidth=0.5, alpha=0.5)
cbar3 = plt.colorbar(im2, ax=axs[2], shrink=0.6)

plt.tight_layout()
plt.show()
#plt.savefig('guider_image.png',dpi=144)
plt.close()
/usr/local/lib/python3.6/site-packages/ipykernel_launcher.py:26: UserWarning: FixedFormatter should only be used together with FixedLocator
/usr/local/lib/python3.6/site-packages/ipykernel_launcher.py:27: UserWarning: FixedFormatter should only be used together with FixedLocator
/usr/local/lib/python3.6/site-packages/ipykernel_launcher.py:47: UserWarning: FixedFormatter should only be used together with FixedLocator
/usr/local/lib/python3.6/site-packages/ipykernel_launcher.py:48: UserWarning: FixedFormatter should only be used together with FixedLocator
/usr/local/lib/python3.6/site-packages/ipykernel_launcher.py:65: UserWarning: FixedFormatter should only be used together with FixedLocator
/usr/local/lib/python3.6/site-packages/ipykernel_launcher.py:66: UserWarning: FixedFormatter should only be used together with FixedLocator
../_images/tutorials_KPF_Data_Tutorial_L0_and_2D_39_1.png

Examine and Plot Guider Performance Time Series

[21]:
df_GUIDER = Table.read(L0_file, format='fits',hdu='guider_cube_origins').to_pandas()
df_GUIDER
[21]:
subframe_id timestamp target_x target_y command_x command_y object1_flux object1_tnpix object1_npix object1_peak ... object3_tnpix object3_npix object3_peak object3_x object3_y object3_a object3_b object3_theta object3_errxy object3_thresh
0 0 1.713773e+09 342.167 264.438 -0.131590 -0.051213 225389.0 1 0 5389.0 ... 0 0 0.0 -999.0 -999.0 0.0 0.0 0.0 0.0 -999.0
1 1 1.713773e+09 342.167 264.438 -0.076432 -0.073256 226913.0 1 0 6262.0 ... 0 0 0.0 -999.0 -999.0 0.0 0.0 0.0 0.0 -999.0
2 2 1.713773e+09 342.167 264.438 -0.069403 -0.044836 225183.0 1 0 5373.0 ... 0 0 0.0 -999.0 -999.0 0.0 0.0 0.0 0.0 -999.0
3 3 1.713773e+09 342.167 264.438 -0.081925 -0.068397 227190.0 1 0 4778.0 ... 0 0 0.0 -999.0 -999.0 0.0 0.0 0.0 0.0 -999.0
4 4 1.713773e+09 342.167 264.438 -0.154436 -0.041921 226220.0 1 0 4795.0 ... 0 0 0.0 -999.0 -999.0 0.0 0.0 0.0 0.0 -999.0
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
59852 59852 1.713773e+09 341.999 264.385 0.055486 0.077842 227271.0 1 0 4626.0 ... 0 0 0.0 -999.0 -999.0 0.0 0.0 0.0 0.0 -999.0
59853 59853 1.713773e+09 341.999 264.385 0.010104 0.070314 226251.0 1 0 4775.0 ... 0 0 0.0 -999.0 -999.0 0.0 0.0 0.0 0.0 -999.0
59854 59854 1.713773e+09 341.999 264.385 0.026153 0.040634 226465.0 1 0 4687.0 ... 0 0 0.0 -999.0 -999.0 0.0 0.0 0.0 0.0 -999.0
59855 59855 1.713773e+09 341.999 264.385 0.000000 0.000000 0.0 0 0 0.0 ... 0 0 0.0 -999.0 -999.0 0.0 0.0 0.0 0.0 -999.0
59856 59856 1.713773e+09 341.999 264.385 0.000000 0.000000 0.0 0 0 0.0 ... 0 0 0.0 -999.0 -999.0 0.0 0.0 0.0 0.0 -999.0

59857 rows × 39 columns

In the plot below, note that the tip-tilt mirror was only operating correctly in the Y direction, hence larger motion in the X direction.

[22]:
# Trim bad data
df_GUIDER = df_GUIDER[df_GUIDER.timestamp != 0.0]    # remove bogus rows
df_GUIDER = df_GUIDER[df_GUIDER.object1_flux != 0.0] # remove bogus rows

# Create the figure and subplots
fig, axes = plt.subplots(1, 2, figsize=(16, 4), gridspec_kw={'width_ratios': [2, 1]})
plt.style.use('seaborn-whitegrid')

# precompute variables:
time_sec = df_GUIDER.timestamp-min(df_GUIDER.timestamp)
x_mas = (df_GUIDER.target_x - df_GUIDER.object1_x) * pixel_scale * 1000
y_mas = (df_GUIDER.target_y - df_GUIDER.object1_y) * pixel_scale * 1000
r_mas = (x_mas**2+y_mas**2)**0.5
x_rms = (np.nanmean(x_mas**2))**0.5
y_rms = (np.nanmean(y_mas**2))**0.5
r_rms = (np.nanmean(r_mas**2))**0.5

# Plot the data
im1 = axes[1].hist2d(x_mas, y_mas, bins=40, cmap='viridis')
cmap = plt.get_cmap('viridis')
xylim = max(round(np.nanpercentile(abs(x_mas), 99))*1.2, round(np.nanpercentile(abs(y_mas), 99))*1.2)
axes[1].set_xlim(-xylim, xylim) # set symmetric limits for x and y
axes[1].set_ylim(-xylim, xylim)
axes[1].set_aspect('equal')
axes[1].set_facecolor(cmap(0))
axes[1].set_title("Guiding Corrections - RMS-2D = " + f'{int(r_rms*10)/10}'+' mas', fontsize=14)
axes[1].set_xlabel('x (mas)', fontsize=14)
axes[1].set_ylabel('y (mas)', fontsize=14)
axes[1].grid(True, linestyle='solid', linewidth=0.5, alpha=0.5)
cbar = plt.colorbar(im1[3])
cbar.set_label('Samples', fontsize=12)

axes[0].plot(time_sec, x_mas, color='royalblue')
axes[0].plot(time_sec, y_mas, color='orange')
axes[0].set_title("Guiding Correction Time Series", fontsize=14)
axes[0].set_xlabel("Time (sec)", fontsize=14)
axes[0].set_ylabel("Guiding Correction (mas)", fontsize=14)
axes[0].legend(['X - RMS = ' + f'{int(x_rms*10)/10}' + ' mas',
                'Y - RMS = ' + f'{int(y_rms*10)/10}' + ' mas'],
                fontsize=12, loc='best')

# Set the font size of tick mark labels
axes[0].tick_params(axis='both', which='major', labelsize=14)
axes[1].tick_params(axis='both', which='major', labelsize=14)

# Display the plots
plt.show()
#plt.savefig('guider_corrections.png',dpi=144)
../_images/tutorials_KPF_Data_Tutorial_L0_and_2D_43_0.png

Plot Flux Time Series from Guider and Exposure Meter

[23]:
plt.style.use('seaborn-whitegrid')
plt.figure(figsize=(12, 5), tight_layout=True)
plt.plot(df_GUIDER.timestamp-min(df_GUIDER.timestamp), df_GUIDER.object1_flux/np.percentile(df_GUIDER.object1_flux, 95), color='royalblue')
plt.step(time, int_SCI_flux / ((847+4.8/2)-(450.1-0.4/2)) / tdur_sec / max(int_SCI_flux / ((847+4.8/2)-(450.1-0.4/2)) / tdur_sec) * 1.06, color='k')
plt.title("Guider and Exposure Meter Flux Time Series", fontsize=14)
plt.xlabel("Seconds since " + str(header['DATE-BEG']), fontsize=14)
plt.ylabel("Flux (fractional)", fontsize=14)
plt.xticks(fontsize=14)
plt.yticks(fontsize=14)
plt.xlim(min(df_GUIDER.timestamp-min(df_GUIDER.timestamp)), max(df_GUIDER.timestamp-min(df_GUIDER.timestamp)))
plt.legend(['Guider Flux', 'Exposure Meter Flux'], fontsize=12, loc='best')
plt.show()
#plt.savefig('guider_xy_times.png',dpi=144)
../_images/tutorials_KPF_Data_Tutorial_L0_and_2D_45_0.png