;+
; Project     : STEREO - PLASTIC
;
; Name        : plastic_parse_packet
;
; Purpose     : Parse Beacon PTP packet, and put in daily CDF file.
;
; Category    : Quicklook, Telemetry, Data-extraction
;
; Explanation : Takes a PLASTIC Beacon data PTP packet structure
;               as created by READ_STEREO_PKT, parese it, and
;               puts the raw data into cdf files. There is one cdf
;               file created for each 24 hour day. Data is
;               uncompressed. There are variables for raw data
;               as well as converted data.
;
; Syntax      : IDL> plastic_parse_packet, packet
;
; Examples    : IDL> packet = 0
;               IDL> WHILE n_elements(packet) NE 0 DO BEGIN
;                        read_stereo_pkt, in_lun, packet
;                        IF n_elements(packet) NE 0 THEN plastic_parse_packet, packet
;                    ENDWHILE
;
; Inputs      : packet     a structure as returned from READ_STEREO_PKT
;
; Opt. Inputs : none
;
; Outputs     : none
;
; Opt. Outputs: none
;
; Keywords    : filepath   Path to write file to.  Defaults to current
;                          directory.
;
; Common      : none
;
; Restrictions: requires environmental variable SKELETONCDF be set
;               requires skeleton file PLA_LB_00000000_V01.skt in data/skeleton/
;               directory
;               requires plastic_conversions.txt in data/conversions/ directory
;
; Side effects: creates cdf file in filepath directory
;
; History     : version 1, 11/15/05, LB Ellis, written
;               version 2, 12/01/05, W. Thompson, added filepath keyword
;               version 3, 12/01/05, LB Ellis, changed alpha dist to 5x5x5
;               version 4, 10/23/06, LB Ellis, added moment
;               calibration files
;               version 5, 01/09/07, LB Ellis put moments in
;               ccordinates
;               version 6, 01/29/07, LBE fixed bytes for old DPU
;               (version 3.1.7)
;                          01/30/07, LBE added unscale factor
;                          02/01/07, LBE fixed bug in density
;               version 7, 05/17/07, LBE changed moment decompression
;                                        fixed reading of temperature_s, heat_flux_s
;                                        changed _inst to _spcrft
;                                        added option for new DPU
;                          07/05/07, LBE changed time for new DPU for B
;               version 8, 09/14/07, LBE significant rewrite for moment calibrations
;                          09/21/07, LBE added vel_box to take average
;                          09/24/07, LBE added plastic_check_doy, check for valid ratio data
;                          09/25/07, LBE fixed bug in temperature
;                          10/08/07, LBE new format for ratio files, have to look for zeros
;                          09/18/08, LBE fixed typo (valid should be valid_i)
;               version 9, 06/12/09, LBE updated moment algorithm to match RA
;                          07/20/09, LBE added temporal offsets for density and Temp_x
;                          08/14/09, LBE removed unwanted variables.
;                          11/12/09, LBE check if vel_box has elements before assigning to vel_box_a/b
;                          01/06/10, LBE updated E/W temporal offset.
;                          03/16/10, LBE updated E/W temporal offset.
;                          03/18/10, LBE check for negative utc.time
;                          04/14/10, LBE updated E/W temporal offset.
;                          05/19/10, LBE updated E/W temporal offset.
;                          07/09/10, LBE updated E/W temporal offset.
;                          10/20/10, LBE updated E/W temporal offset.
;              version 10, 06/14/11, LBE changed for DPU V32A.
;                                        updated E/W temporal offset.
;                          07/06/11, LBE change filenames.
;
; Contact     : Lorna Ellis (Lorna.Ellis@unh.edu)
;-

; For the data array, byte 0 is correct, odd bytes +1, even bytes -1

PRO uncompress8, input, output

output = input

msb = ishft(input, -4) AND '0F'x
lsb = input AND '0F'x

temp = where(input LT '20'x, count)
IF count GT 0 THEN output[temp] = input[temp]
temp = where(input GE '20'x, count)
IF count GT 0 THEN output[temp] = (lsb[temp] OR '10'x) * (2 ^ (msb[temp]-1))

END 

PRO uncompress_moment, input, output

output = double(input)
s = ishft(input, -15) AND '1'x  ; sign bit
e = ishft(input,  -9) AND '3F'x ; exponent
m = input AND '1FF'x            ; mantissa

output = ((-1) ^ s) * (512 + m) * (double(2) ^ (e-10))

END 

PRO plastic_parse_packet, packet, filepath=filepath
COMMON com_moment, cal_read_a, cal_read_b, step_var_a, step_var_b, table_norm_a, table_norm_b, geom_a, geom_b, ra_trig_eff_a, ra_trig_eff_b, vel_groups_a, vel_groups_b, mom_cal_start_a, mom_cal_start_b, mom_cal_stop_a, mom_cal_stop_b, ratio_read_a, ratio_read_b, vel_box_a, vel_box_b
; step_var_a/b [one element for each relevant calibration file]
; table_norm_a/b [file][D,V,P,H]
; geom_a/b [file][M,S channel]
; ra_trig_eff_a/b [file][128][esa step num, K vel, table vel, eff]
; vel_groups_a/b [file] [32 average of our vel in ra_trig_eff]
; mom_cal_start/stop_a/b [file] -- for each file, start time and stop
;                                  time (as double) -- -1=no limit
; vel_box_a/b -- used to find average velocity to lookup

version = "V10"

apid = parse_stereo_pkt(packet, /APID)

IF apid EQ '370'x THEN BEGIN 
    new_file = 0   ; will be set if create a new file
    error = 0      ; will be set if we get a value out of bounds

    ; check checksum
    check = 0L
    temp = ishft(packet.pkt.hdr, -8) AND 'FF'x
    IF temp GE '80'x THEN check = check - (NOT(byte(temp)) + 1) ELSE check = check + temp
    temp = packet.pkt.hdr AND 'FF'x
    IF temp GE '80'x THEN check = check - (NOT(byte(temp)) + 1) ELSE check = check + temp
    temp = ishft(packet.pkt.grp, -8) AND 'FF'x
    IF temp GE '80'x THEN check = check - (NOT(byte(temp)) + 1) ELSE check = check + temp
    temp = packet.pkt.grp AND 'FF'x
    IF temp GE '80'x THEN check = check - (NOT(byte(temp)) + 1) ELSE check = check + temp
    temp = ishft(packet.pkt.size, -8) AND 'FF'x
    IF temp GE '80'x THEN check = check - (NOT(byte(temp)) + 1) ELSE check = check + temp
    temp = packet.pkt.size AND 'FF'x
    IF temp GE '80'x THEN check = check - (NOT(byte(temp)) + 1) ELSE check = check + temp
    temp = ishft(packet.pkt.seconds, -24) AND 'FF'x
    IF temp GE '80'x THEN check = check - (NOT(byte(temp)) + 1) ELSE check = check + temp
    temp = ishft(packet.pkt.seconds, -16) AND 'FF'x
    IF temp GE '80'x THEN check = check - (NOT(byte(temp)) + 1) ELSE check = check + temp
    temp = ishft(packet.pkt.seconds, -8) AND 'FF'x
    IF temp GE '80'x THEN check = check - (NOT(byte(temp)) + 1) ELSE check = check + temp
    temp = packet.pkt.seconds AND 'FF'x
    IF temp GE '80'x THEN check = check - (NOT(byte(temp)) + 1) ELSE check = check + temp
    temp = packet.pkt.subsec AND 'FF'x 
    IF temp GE '80'x THEN check = check - (NOT(byte(temp)) + 1) ELSE check = check + temp
    FOR i = 0, 260 DO BEGIN
        temp = packet.dat[i]
        IF temp GE '80'x THEN check = check - (NOT(byte(temp)) + 1) ELSE check = check + temp
    ENDFOR 
    check = check MOD 256

    spacecraft = packet.grh.spacecraft_id
    ; read calibration files
    timestamp = parse_stereo_pkt(packet, /PKT_DATE, /CCSDS) ; /ccsds is for anytim2utc
    utc = anytim2utc(timestamp)
    utc.time = utc.time - 90000 ; go back 90 seconds
    IF utc.time LT 0 THEN BEGIN ; goes over date boundary
        utc.mjd = utc.mjd - 1
        utc.time = utc.time + 86400000
    ENDIF 
    timestamp = utc2str(utc)
    year = fix(strmid(timestamp, 0, 4))
    ;utc = anytim2utc(timestamp)
    doy = utc2doy(utc)
    ratio_doy = doy-2
    ratio_year = year
    plastic_check_doy, ratio_year, ratio_doy
    CASE spacecraft OF
        'EA'x: BEGIN 
            sat = 'A'
            IF n_elements(cal_read_a) EQ 0 THEN cal_read_a = 0
            IF cal_read_a EQ 1 THEN BEGIN
                IF timestamp LT mom_cal_start_a OR timestamp GT mom_cal_stop_a THEN cal_read_a = 0
            ENDIF 
            IF cal_read_a EQ 0 THEN plastic_beacon_mom_conv, sat, timestamp
            step_var = step_var_a
            table_norm = table_norm_a
            geom = geom_a
            vel_groups = vel_groups_a
            ra_trig_eff = ra_trig_eff_a
            mom_cal_start = mom_cal_start_a
            mom_cal_stop = mom_cal_stop_a
            ; WARNING: This next line doesn't catch if year changes and doy stays the same
            IF n_elements(ratio_doy_a) EQ 0 THEN plastic_read_ratios, sat, ratio_year, ratio_doy, svalid_ratrig_ratio, pri0_ratio $
              ELSE IF ratio_doy_a NE ratio_doy THEN plastic_read_ratios, sat, ratio_year, ratio_doy, svalid_ratrig_ratio, pri0_ratio 
            temp = where(pri0_ratio NE 0, count)
            WHILE count EQ 0 DO BEGIN 
                ratio_doy = ratio_doy - 1
                plastic_check_doy, ratio_year, ratio_doy
                plastic_read_ratios, sat, ratio_year, ratio_doy, svalid_ratrig_ratio, pri0_ratio 
                temp = where(pri0_ratio NE 0, count)
            ENDWHILE
            ratio_doy_a = ratio_doy
            IF n_elements(vel_box_a) GT 0 THEN vel_box = vel_box_a
        END 
        'EB'x: BEGIN
            sat = 'B'
            IF n_elements(cal_read_b) EQ 0 THEN cal_read_b = 0
            IF cal_read_b EQ 1 THEN BEGIN
                IF timestamp LT mom_cal_start_b OR timestamp GT mom_cal_stop_b THEN cal_read_b = 0
            ENDIF 
            IF cal_read_b EQ 0 THEN plastic_beacon_mom_conv, sat, timestamp
            step_var = step_var_b
            table_norm = table_norm_b
            geom = geom_b
            vel_groups = vel_groups_b
            ra_trig_eff = ra_trig_eff_b
            mom_cal_start = mom_cal_start_b
            mom_cal_stop = mom_cal_stop_b
            ; WARNING: This next line doesn't catch if year changes and doy stays the same
            IF n_elements(ratio_doy_b) EQ 0 THEN plastic_read_ratios, sat, ratio_year, ratio_doy, svalid_ratrig_ratio, pri0_ratio $
              ELSE IF ratio_doy_b NE ratio_doy THEN plastic_read_ratios, sat, ratio_year, ratio_doy, svalid_ratrig_ratio, pri0_ratio 
            temp = where(pri0_ratio NE 0, count)
            WHILE count EQ 0 DO BEGIN 
                ratio_doy = ratio_doy - 1
                plastic_check_doy, ratio_year, ratio_doy
                plastic_read_ratios, sat, ratio_year, ratio_doy, svalid_ratrig_ratio, pri0_ratio 
                temp = where(pri0_ratio NE 0, count)
            ENDWHILE
            ratio_doy_b = ratio_doy
            IF n_elements(vel_box_b) GT 0 THEN vel_box = vel_box_b
        END 
        ELSE: print, "invalid spacecraft", spacecraft
    ENDCASE
    filename     = 'ST'+sat+'_LB_PLASTIC_'
    pub_filename = 'ST'+sat+'_LB_PLA_'

    ; create cdf
    year =  strmid(timestamp,  0, 4)
    month = strmid(timestamp,  5, 2)
    day =   strmid(timestamp,  8, 2)
    hour =  strmid(timestamp, 11, 2)
    min =   strmid(timestamp, 14, 2)
    sec =   strmid(timestamp, 17, 2)
    milli = strmid(timestamp, 20, 3)
    fileprefix     =     filename          +year+month+day+'_'+version
    pub_fileprefix = pub_filename+'BROWSE_'+year+month+day+'_'+version
    IF n_elements(filepath) EQ 1 THEN BEGIN
        fileprefix     = concat_dir(filepath, fileprefix)
        pub_fileprefix = concat_dir(filepath, pub_fileprefix)
    ENDIF 
    filename          =     fileprefix+".cdf"
    pub_filename      = pub_fileprefix+".cdf"
    skeleton_name     = '$SSW_PLASTIC/data/skeleton/PLA_LB_00000000_'+version
    ;skeleton_name     = 'PLA_LB_00000000_'+version
    pub_skeleton_name = '$SSW_PLASTIC/data/skeleton/ST'+sat+'_LB_PLA_BROWSE_00000000_'+version
    ;pub_skeleton_name = 'ST'+sat+'_LB_PLA_BROWSE_'+version
    command     = '$SKELETONCDF -cdf '+    fileprefix+' -nodelete -fillval '+    skeleton_name
    pub_command = '$SKELETONCDF -cdf '+pub_fileprefix+' -nodelete -fillval '+pub_skeleton_name
    IF file_test(filename) EQ 0 THEN BEGIN 
        spawn, command
        new_file = 1
    ENDIF 
    IF file_test(pub_filename) EQ 0 then spawn, pub_command

    ; get info from conversion file
    openr, conv_lun, '$SSW_PLASTIC/data/conversions/plastic_conversions.txt', /get_lun
    line = ' '
    readf, conv_lun, line
    parts = strsplit(line, /extract)
    WHILE parts[0] NE 'version' DO BEGIN 
        readf, conv_lun, line
        parts = strsplit(line, /extract)
    ENDWHILE 
    conv_version = fix(parts[2])
    IF spacecraft EQ 'EA'x THEN BEGIN 
        WHILE strmid(parts[0], 0, 8) NE 'MCP_VM.1' DO BEGIN 
            readf, conv_lun, line
            parts = strsplit(line, /extract)
        ENDWHILE 
    ENDIF ELSE BEGIN 
        WHILE strmid(parts[0], 0, 8) NE 'MCP_VM.2' DO BEGIN 
            readf, conv_lun, line
            parts = strsplit(line, /extract)
        ENDWHILE 
    ENDELSE 
    conv_mcp_vm = parts
    IF spacecraft EQ 'EA'x THEN BEGIN 
        WHILE strmid(parts[0], 0, 8) NE 'PAC_VM.1' DO BEGIN 
            readf, conv_lun, line
            parts = strsplit(line, /extract)
        ENDWHILE 
    ENDIF ELSE BEGIN 
        WHILE strmid(parts[0], 0, 8) NE 'PAC_VM.2' DO BEGIN 
            readf, conv_lun, line
            parts = strsplit(line, /extract)
        ENDWHILE 
    ENDELSE 
    conv_pac_vm = parts
    close, conv_lun
    free_lun, conv_lun

    ; check if new DPU
    IF sat EQ 'A' THEN BEGIN 
        IF timestamp GE '2011-06-17T20:10:00.000' THEN dpu_version = '32A'x ELSE $
          IF timestamp GE '2007-06-26T16:00:00.000' THEN dpu_version = 324 $
          ELSE dpu_version = 317
    ENDIF ELSE BEGIN ; B
        ;IF timestamp GE '2011-07-01T00:00:00.000' THEN dpu_version = '32A'x ELSE $
          IF timestamp GE '2007-07-02T20:00:00.000' THEN dpu_version = 324 $
          ELSE dpu_version = 317
    ENDELSE 

    cdf_id = cdf_open(filename)
    pub_id = cdf_open(pub_filename)
    IF new_file EQ 1 THEN cdf_varput, cdf_id, 'Conversion_version', conv_version
    ; epoch
    cdf_epoch, epoch, year, month, day, hour, min, sec, milli, /compute_epoch
    cdf_control, cdf_id, get_var_info = info, variable = 'Epoch1'
    cdf_varput, cdf_id, 'Epoch1', epoch, rec_start = (info.maxrec+1)
    cdf_varput, pub_id, 'Epoch1', epoch, rec_start = (info.maxrec+1)
    ; General
    IF check EQ 0 THEN BEGIN 
        cdf_varput, cdf_id, 'Checksum', 0B, rec_start = (info.maxrec+1) 
        cdf_varput, pub_id, 'Checksum', 0B, rec_start = (info.maxrec+1) 
    ENDIF ELSE BEGIN 
        cdf_varput, cdf_id, 'Checksum', 1B, rec_start = (info.maxrec+1)
        cdf_varput, pub_id, 'Checksum', 1B, rec_start = (info.maxrec+1)
    ENDELSE 
    schan = packet.dat[16-11+1] AND '7F'x
    cdf_varput, cdf_id, 'SChannel_switch', schan, rec_start = (info.maxrec+1)
    cdf_varput, pub_id, 'SChannel_switch', schan, rec_start = (info.maxrec+1)
    IF dpu_version GE 324 THEN BEGIN
        cycle = packet.dat[79-11-1]
        cdf_varput, cdf_id, 'Cycle', cycle, rec_start = (info.maxrec+1)
    ENDIF 
    ; HK
    hk_flag = packet.dat[13-11-1]
    IF hk_flag NE 1 THEN error = 1 ; 1=valid
    IF dpu_version LE 317 THEN BEGIN 
        pac_vm = ishft(fix(packet.dat[18-11+1]), 8) OR packet.dat[17-11-1]
        mcp_vm = ishft(fix(packet.dat[20-11+1]), 8) OR packet.dat[19-11-1]
    ENDIF ELSE BEGIN 
        pac_vm = ishft(fix(packet.dat[19-11-1]), 8) OR packet.dat[18-11+1]
        mcp_vm = ishft(fix(packet.dat[21-11-1]), 8) OR packet.dat[20-11+1]
    ENDELSE 
    pac_vm_conv = ((float(conv_pac_vm[3])*pac_vm) + float(conv_pac_vm[4])) * float(conv_pac_vm[5])
    mcp_vm_conv = ((float(conv_mcp_vm[3])*mcp_vm) + float(conv_mcp_vm[4])) * float(conv_mcp_vm[5])
    cdf_varput, cdf_id, 'HK_flag', hk_flag, rec_start = (info.maxrec+1)
    cdf_varput, cdf_id, 'PAC_VM_Raw', pac_vm, rec_start = (info.maxrec+1)
    cdf_varput, cdf_id, 'PAC_VM_Conv', pac_vm_conv, rec_start = (info.maxrec+1)
    cdf_varput, cdf_id, 'MCP_VM_Raw', mcp_vm, rec_start = (info.maxrec+1)
    cdf_varput, cdf_id, 'MCP_VM_Conv', mcp_vm_conv, rec_start = (info.maxrec+1)
    ; Moments
    IF dpu_version GE 324 THEN BEGIN
        mom_array = packet.dat[17-11-1]
        cdf_varput, cdf_id, 'Moment_Array', mom_array, rec_start = (info.maxrec+1)
        cdf_varput, pub_id, 'Moment_Array', mom_array, rec_start = (info.maxrec+1)
    ENDIF 
    unscale = (double(2)^16)/'3FFB001'x ; 0x3FFB001 = 4095 * 16383
                                ; Math.pow(2,16) for bit shifting by 16 bits
                                ; 4095 for theta normalization to 12 bits
                                ; 16383 for phi normalization to 14 bits
    velocity_m = intarr(3)
    temperature_m = intarr(6)
    heat_flux_m = intarr(3)
    velocity_s = intarr(3)
    temperature_s = intarr(6)
    heat_flux_s = intarr(3)
    IF dpu_version LE 317 THEN BEGIN 
        density_m = ishft(fix(packet.dat[22-11+1]), 8) OR packet.dat[21-11-1]
        FOR i = 0, 2 DO BEGIN 
            velocity_m[i] = ishft(fix(packet.dat[24-11+(i*2)+1]), 8) OR packet.dat[23-11+(i*2)-1]
        ENDFOR 
        FOR i = 0, 5 DO BEGIN 
            temperature_m[i] = ishft(fix(packet.dat[30-11+(i*2)+1]), 8) OR packet.dat[29-11+(i*2)-1]
        ENDFOR 
        FOR i = 0, 2 DO BEGIN 
            heat_flux_m[i] = ishft(fix(packet.dat[42-11+(i*2)+1]), 8) OR packet.dat[41-11+(i*2)-1]
        ENDFOR 
        density_s = ishft(fix(packet.dat[48-11+1]), 8) OR packet.dat[47-11-1]
        FOR i = 0, 2 DO BEGIN 
            velocity_s[i] = ishft(fix(packet.dat[50-11+(i*2)+1]), 8) OR packet.dat[49-11+(i*2)-1]
        ENDFOR 
        FOR i = 0, 5 DO BEGIN  
            temperature_s[i] = ishft(fix(packet.dat[56-11+(i*2)+1]), 8) OR packet.dat[55-11+(i*2)-1]
        ENDFOR 
        FOR i = 0, 2 DO BEGIN 
            heat_flux_s[i] = ishft(fix(packet.dat[68-11+(i*2)+1]), 8) OR packet.dat[67-11+(i*2)-1]
        ENDFOR 
    ENDIF ELSE BEGIN 
        density_m = ishft(fix(packet.dat[23-11-1]), 8) OR packet.dat[22-11+1]
        FOR i = 0, 2 DO BEGIN 
            velocity_m[i] = ishft(fix(packet.dat[25-11+(i*2)-1]), 8) OR packet.dat[24-11+(i*2)+1]
        ENDFOR 
        FOR i = 0, 5 DO BEGIN 
            temperature_m[i] = ishft(fix(packet.dat[31-11+(i*2)-1]), 8) OR packet.dat[30-11+(i*2)+1]
        ENDFOR 
        FOR i = 0, 2 DO BEGIN 
            heat_flux_m[i] = ishft(fix(packet.dat[43-11+(i*2)-1]), 8) OR packet.dat[42-11+(i*2)+1]
        ENDFOR 
        density_s = ishft(fix(packet.dat[49-11-1]), 8) OR packet.dat[48-11+1]
        FOR i = 0, 2 DO BEGIN 
            velocity_s[i] = ishft(fix(packet.dat[51-11+(i*2)-1]), 8) OR packet.dat[50-11+(i*2)+1]
        ENDFOR 
        FOR i = 0, 5 DO BEGIN  
            temperature_s[i] = ishft(fix(packet.dat[57-11+(i*2)-1]), 8) OR packet.dat[56-11+(i*2)+1]
        ENDFOR 
        FOR i = 0, 2 DO BEGIN 
            heat_flux_s[i] = ishft(fix(packet.dat[69-11+(i*2)-1]), 8) OR packet.dat[68-11+(i*2)+1]
        ENDFOR 
    ENDELSE 
    uncompress_moment, density_m, density_m_uncomp
    density_m_uncomp = double(long(unscale * density_m_uncomp))
    uncompress_moment, velocity_m, velocity_m_uncomp
    velocity_m_uncomp = double(long(unscale * velocity_m_uncomp))
    uncompress_moment, temperature_m, temperature_m_uncomp
    temperature_m_uncomp = double(long(unscale * temperature_m_uncomp))
    uncompress_moment, heat_flux_m, heat_flux_m_uncomp
    heat_flux_m_uncomp = double(long(unscale * heat_flux_m_uncomp))
    uncompress_moment, density_s, density_s_uncomp
    density_s_uncomp = double(long(unscale * density_s_uncomp))
    uncompress_moment, velocity_s, velocity_s_uncomp
    velocity_s_uncomp = double(long(unscale * velocity_s_uncomp))
    uncompress_moment, temperature_s, temperature_s_uncomp
    temperature_s_uncomp = double(long(unscale * temperature_s_uncomp))
    uncompress_moment, heat_flux_s, heat_flux_s_uncomp
    heat_flux_s_uncomp = double(long(unscale * heat_flux_s_uncomp))

    ; Moments -- combine Main and S and put in units
    ; find right calibration file
    ii = 0
    found = 0
    WHILE found NE 1 DO BEGIN
        IF timestamp GE mom_cal_start[ii] AND (timestamp LT mom_cal_stop[ii] OR mom_cal_stop[ii] LT 0) THEN BEGIN
            i_cal = ii
            found = 1
        ENDIF ELSE IF ii EQ n_elements(mom_cal_start) THEN BEGIN
            printf, 'ERROR: No valid calibration file found'
            found = 1
        ENDIF ELSE ii = ii+1
    ENDWHILE 

    ; velocity
    velocity_eng = dblarr(4)
    prefix = table_norm[1]/table_norm[0] ; Bv/Bd in Lynn's document
    denom = (density_s_uncomp/geom[1]) + (density_m_uncomp/geom[0]) ; Ds/Gs + Dm/Gm
    FOR jj = 0, 2 DO BEGIN      ; x,y,z
        numer = (velocity_s_uncomp[jj]/geom[1]) + (velocity_m_uncomp[jj]/geom[0]) ; Vx,y,zs/Gs + Vx,y,zm/Gm
        velocity_eng[jj] = prefix * numer / denom
    ENDFOR
    velocity_total = sqrt((velocity_eng[0]^2)+(velocity_eng[1]^2)+(velocity_eng[2]^2)) 
    velocity_bulk_reformed = interpol(reform(ra_trig_eff[i_cal, *, 1]), reform(ra_trig_eff[i_cal, *, 2]), velocity_total)
    vx_inst_d = reform(velocity_eng[0])
    vy_inst_d = reform(velocity_eng[1])
    vz_inst_d = reform(velocity_eng[2])

    ; ns
    ns_inst_d = 180 / !PI * ATAN(vz_inst_d / SQRT((vx_inst_d ^ 2)+(vy_inst_d ^ 2)))
    ; Kristin's algorithm for N/S
    IF sat EQ 'A' THEN BEGIN  ; NOTE: OB needs an offset because of deflection wobble (3/17/2009)
        scaled_ns = 3.0*(ns_inst_d + 3.5) ; 3.5 shifts center of dist., 3.0 spreads out dist.
        ns_inst_d = scaled_ns + (-2.0854E-7)*(velocity_bulk_reformed^3)+(3.0371E-4)*(velocity_bulk_reformed^2) + $
                  (-1.2454E-1)*velocity_bulk_reformed+1.0983E1 ; modified 27 August, 2008
                                ; above line comes from velocity dependence of leakage (compared to other spacecraft)
    ENDIF ELSE BEGIN 
        ns_inst_d = -1.0 * ns_inst_d
        scaled_ns = 1.75*(ns_inst_d - 4.62) ; modified 14 August, 2008
        ns_inst_d = scaled_ns + (-2.6404E-7)*(velocity_bulk_reformed^3) + (4.3726E-4)*(velocity_bulk_reformed^2) + $
                     (-2.3922E-1)*velocity_bulk_reformed+4.2639E1
    ENDELSE 
    bad_i = where(ns_inst_d GT 20.0, bad_count)
    IF bad_count GT 0 THEN ns_inst_d[bad_i] = !values.f_nan ; added 02 September, 2008

    ; ew
    amp_toni = 11.25
    fullscale_toni = 19.6875
    ew_inst_d = 180 / !PI * ATAN(vy_inst_d / vx_inst_d)
    IF sat EQ 'B' THEN ew_inst_d = -1.0 * ew_inst_d
    ew_inst_d = (amp_toni*(sinh((ew_inst_d/fullscale_toni))))

    ; add temporal offset for E/W and N/S
    CASE fix(year) OF 
        2007: temp_doy = doy
        2008: temp_doy = doy+365
        2009: temp_doy = doy+365+366
        2010: temp_doy = doy+365+366+365
        2011: temp_doy = doy+365+366+365+365
        2012: temp_doy = doy+365+366+365+365+365
        2013: temp_doy = doy+365+366+365+365+365+366
        2014: temp_doy = doy+365+366+365+365+365+366+365
        2015: temp_doy = doy+365+366+365+365+365+366+365+365
        2016: temp_doy = doy+365+366+365+365+365+366+365+365+365
        2017: temp_doy = doy+365+366+365+365+365+366+365+365+365+366
        2018: temp_doy = doy+365+366+365+365+365+366+365+365+365+366+365
        2019: temp_doy = doy+365+366+365+365+365+366+365+365+365+366+365+365
        2020: temp_doy = doy+365+366+365+365+365+366+365+365+365+366+365+365+365
    ENDCASE 
    temp_doy = double(temp_doy)
    IF sat EQ 'A' THEN BEGIN 
        ; E/W
        IF temp_doy LT 164 THEN BEGIN ; until 6/24/2007
            ew_temporal_offset = (2.045E-05*(temp_doy^2))       $
                                 + (8.914E-03*temp_doy) +  6.209E-01
            ew_inst_d = ew_inst_d + ew_temporal_offset
        ENDIF ELSE IF temp_doy GE 164 AND temp_doy LT 610 THEN BEGIN ; 6/24/2007-8/31/2008 
            ew_temporal_offset = (-1.5447E-12*(temp_doy^5))    $
                                 + (3.8175E-09*(temp_doy^4))                         $
                                 - (3.5857E-06*(temp_doy^3))                         $
                                 + (1.5666E-03*(temp_doy^2))                         $
                                 - (3.0460E-01*(temp_doy)) + 2.3513E+01
            ew_inst_d = ew_inst_d + ew_temporal_offset
        ENDIF ELSE IF temp_doy GE 610 AND temp_doy LT 822 THEN BEGIN ; 9/01/2008-3/31/2009 
            ew_temporal_offset = (2.7020E-09*(temp_doy^4))                         $
                                 - (7.4886E-06*(temp_doy^3))                         $
                                 + (7.7275E-03*(temp_doy^2))                         $
                                 - (3.5128E-00*(temp_doy)) + 5.9799E+02
            ew_inst_d = ew_inst_d + ew_temporal_offset
        ENDIF ELSE IF temp_doy GE 822 AND temp_doy LT 1005 THEN BEGIN ; 4/01/2008-10/01/2009 
            ew_temporal_offset = (-0.0000128*(temp_doy^2))                         $
                                 + (0.0263893*(temp_doy)) - 7.5820845
            ew_inst_d = ew_inst_d + ew_temporal_offset
        ENDIF ELSE IF temp_doy GE 1005 AND temp_doy LT 1096 THEN BEGIN ; 10/01/2009-01/01/2010 
            ew_temporal_offset = (0.0000110*(temp_doy^2))                         $
                                 - (0.0171306*(temp_doy)) + 12.1293050
            ew_inst_d = ew_inst_d + ew_temporal_offset
        ENDIF ELSE IF temp_doy GE 1096 AND temp_doy LT 1143 THEN BEGIN ; 01/01/2010-02/15/2010
            ew_temporal_offset = 0.0029*temp_doy + 3.2291
            ew_inst_d = ew_inst_d + ew_temporal_offset
        ENDIF ELSE IF temp_doy GE 1143 AND temp_doy LT 1169 THEN BEGIN ; 02/16/2010-03/13/2010
            ew_temporal_offset = 6.01468
            ew_inst_d = ew_inst_d + ew_temporal_offset
        ENDIF ELSE IF temp_doy GE 1169 AND temp_doy LT 1172 THEN BEGIN ; 03/14/2010-03/16/2010
            ew_temporal_offset = 6.5
            ew_inst_d = ew_inst_d + ew_temporal_offset
        ENDIF ELSE IF temp_doy GE 1171 AND temp_doy LT 1201 THEN BEGIN ; 03/17/2010-04/14/2010
            ew_temporal_offset = (-2.29988E-05*(temp_doy^2))                         $
                                 + (5.80601E-02*(temp_doy)) - 2.99325E01
            ew_inst_d = ew_inst_d + ew_temporal_offset
        ENDIF ELSE IF temp_doy GE 1201 AND temp_doy LT 1217 THEN BEGIN  ; 04/15/2010-05/01/2010
            ew_temporal_offset = -1.3459E-06*(temp_doy^3) + $
                                 5.2070E-03*(temp_doy^2) - $
                                 6.6988E+00*(temp_doy) + 2.8728E+03
            ew_inst_d = ew_inst_d + ew_temporal_offset
        ENDIF ELSE IF temp_doy GE 1217 and temp_doy lt 1492 THEN BEGIN ; 05/01/2010-12/01/2010
            ew_temporal_offset = (2.2880E-09*(temp_doy^4)) - $
                                 (1.2698E-05*(temp_doy^3)) + $
                                 (2.6333E-02*(temp_doy^2)) - $
                                 (2.4176E+01*(temp_doy)) + 8.2959E+03
            ew_inst_d = ew_inst_d + ew_temporal_offset
        ENDIF ELSE IF temp_doy GE 1492 AND temp_doy LT 1554 THEN BEGIN ; 12/01/2010-2/1/2011
            ew_temporal_offset = (-2.96635E-07*(temp_doy^3)) + $
                                 ( 1.29937E-03*(temp_doy^2)) - $
                                 ( 1.88899E+00*(temp_doy)) + 9.20112E+02
            ew_inst_d = ew_inst_d + ew_temporal_offset
        ENDIF ELSE IF temp_doy GE 1554 AND temp_doy LT 1582 THEN BEGIN ; 2/01/2011-3/01/2011
            ew_temporal_offset = (-1.47581E-07*(temp_doy^3)) + $
                                 ( 6.42584E-04*(temp_doy^2)) - $
                                 ( 9.26037E-01*(temp_doy)) + 450.301
            ew_inst_d = ew_inst_d + ew_temporal_offset
        ;ENDIF ELSE IF temp_doy GE 1582 THEN BEGIN ; 3/01/2011-
        ENDIF ELSE BEGIN ; 03/01/2011 - 
            ew_temporal_offset = (-2.20016E-05*(temp_doy^2)) + $
                                 ( 6.94598E-02*(temp_doy)) - 4.57606E+01
            ew_inst_d = ew_inst_d + ew_temporal_offset
        ENDELSE 
        ; N/S 
        IF temp_doy LT 135 THEN BEGIN  ; until 5/15/2007
            ns_temporal_offset = -2.4
            ns_inst_d = ns_inst_d + ns_temporal_offset
        ENDIF ELSE IF temp_doy GE 135 AND temp_doy LT 470 THEN BEGIN ; 5/15/2007 - 4/15/2008
            ns_temporal_offset = (0.0014*temp_doy) -  2.543
            ns_inst_d = ns_inst_d + ns_temporal_offset
        ENDIF ELSE BEGIN  ; 4/15/2008 -
            ns_temporal_offset = -2.0
            ns_inst_d = ns_inst_d + ns_temporal_offset
        ENDELSE 
    ENDIF ELSE BEGIN ; B
        ; N/S 
        ns_temporal_offset = 1.0
        ns_inst_d = ns_inst_d + ns_temporal_offset
    ENDELSE 

    ; Adjust OB Vx and find Vt

    vx_inst_d = vx_inst_d * cos(ew_inst_d * !pi / 180) / cos(20 * !pi / 180)
    bulk_speed_inst_sav_d = sqrt(vx_inst_d^2 + vy_inst_d^2 + vz_inst_d^2) ; used for finding density
    bulk_speed_inst_d = interpol(reform(ra_trig_eff[i_cal, *, 1]), reform(ra_trig_eff[i_cal, *, 2]), bulk_speed_inst_sav_d)

    ; Turn angles into coordinates
    vx_inst_d         = bulk_speed_inst_d * cos(ns_inst_d*!PI/180) * cos(ew_inst_d*!PI/180) 
    vy_inst_d         = bulk_speed_inst_d * cos(ns_inst_d*!PI/180) * sin(ew_inst_d*!PI/180)
    vz_inst_d         = bulk_speed_inst_d * sin(ns_inst_d*!PI/180) 

    ; spacecraft coordinates  
    vel_spcrft_d = dblarr(3)  ; spacecraft coord
    vx_spcrft_d         = -1 * vx_inst_d ; multiplying by Lynn's matrix
    vy_spcrft_d         = vz_inst_d
    vz_spcrft_d         = -1 * vy_inst_d
    ns_spcrft_d         = atan(vz_spcrft_d / sqrt((vx_spcrft_d^2)+(vy_spcrft_d^2)))
    ew_spcrft_d         = atan(vy_spcrft_d / vx_spcrft_d)
    bulk_speed_spcrft_d = sqrt((vx_spcrft_d^2)+(vy_spcrft_d^2)+(vz_spcrft_d^2))
    vel_spcrft_d[0] = vx_spcrft_d
    vel_spcrft_d[1] = vy_spcrft_d
    vel_spcrft_d[2] = vz_spcrft_d

; Put in HERTN
    timestamp = strmid(timestamp, 0, 19) ; for checking against level 1
    cmat_hertn  = get_stereo_cmat(timestamp, sat, system = 'hertn')
    vel_hertn_d = cmat_hertn # vel_spcrft_d

    ; Add Aberration
    state = get_stereo_coord(timestamp, sat, system = 'hci')
    spcrft_vel = state[3:5, *]
    convert_stereo_coord, timestamp, spcrft_vel, 'hci', 'hertn', spacecraft = sat
    vel_hertn_d = vel_hertn_d + spcrft_vel

    ; recompute angles and bulk speed
    vr_hertn_d         = vel_hertn_d[0, *]
    vt_hertn_d         = vel_hertn_d[1, *]
    vn_hertn_d         = vel_hertn_d[2, *]
    ns_hertn_d         = atan(vn_hertn_d / sqrt((vr_hertn_d^2)+(vt_hertn_d^2))) * 180 / !pi
    ew_hertn_d         = atan(vt_hertn_d / vr_hertn_d) * 180 / !pi
    bulk_speed_hertn_d = sqrt((vr_hertn_d^2)+(vt_hertn_d^2)+(vn_hertn_d^2))

; Put in RTN
    cmat_rtn  = get_stereo_cmat(timestamp, sat, system = 'rtn')
    vel_rtn_d = cmat_rtn # vel_spcrft_d

    ; Add Aberration
    state = get_stereo_coord(timestamp, sat, system = 'hci')
    spcrft_vel = state[3:5, *]
    convert_stereo_coord, timestamp, spcrft_vel, 'hci', 'rtn', spacecraft = sat, /ignore_origin
    vel_rtn_d = vel_rtn_d + spcrft_vel

    ; recompute angles and bulk speed
    vr_rtn_d         = vel_rtn_d[0, *]
    vt_rtn_d         = vel_rtn_d[1, *]
    vn_rtn_d         = vel_rtn_d[2, *]
    ns_rtn_d         = atan(vn_rtn_d / sqrt((vr_rtn_d^2)+(vt_rtn_d^2))) * 180 / !pi
    ew_rtn_d         = atan(vt_rtn_d / vr_rtn_d) * 180 / !pi
    bulk_speed_rtn_d = sqrt((vr_rtn_d^2)+(vt_rtn_d^2)+(vn_rtn_d^2))

    vel_hertn_d  = [vel_hertn_d,  bulk_speed_hertn_d]
    vel_rtn_d    = [vel_rtn_d,    bulk_speed_rtn_d]
    IF sat EQ 'B' THEN BEGIN ; don't include components and e/w
        vel_hertn_d[0:2] = -1e31 
        vel_rtn_d  [0:2] = -1e31 
        ew_hertn_d       = -1e31
        ew_rtn_d         = -1e31
    ENDIF 
    IF finite(bulk_speed_rtn_d) EQ 0 THEN BEGIN
        vel_hertn_d[0:3] = -1e31 
        vel_rtn_d  [0:3] = -1e31 
        ew_hertn_d       = -1e31
        ew_rtn_d         = -1e31
        bad_vel          = 1
    ENDIF ELSE bad_vel = 0
    cdf_varput, cdf_id, 'Velocity_HERTN',       vel_hertn_d,  rec_start = (info.maxrec+1)
    cdf_varput, cdf_id, 'N_S_flow_angle_HERTN', ns_hertn_d,   rec_start = (info.maxrec+1)
    cdf_varput, cdf_id, 'E_W_flow_angle_HERTN', ew_hertn_d,   rec_start = (info.maxrec+1)
    cdf_varput, cdf_id, 'Velocity_RTN',         vel_rtn_d,    rec_start = (info.maxrec+1)
    cdf_varput, cdf_id, 'N_S_flow_angle_RTN',   ns_rtn_d,     rec_start = (info.maxrec+1)
    cdf_varput, cdf_id, 'E_W_flow_angle_RTN',   ew_rtn_d,     rec_start = (info.maxrec+1)
    cdf_varput, pub_id, 'Bulk_Speed', reform(vel_hertn_d[3]), rec_start = (info.maxrec+1)
    cdf_varput, pub_id, 'Vr_HERTN',   reform(vel_hertn_d[0]), rec_start = (info.maxrec+1)
    cdf_varput, pub_id, 'Vt_HERTN',   reform(vel_hertn_d[1]), rec_start = (info.maxrec+1)
    cdf_varput, pub_id, 'Vn_HERTN',   reform(vel_hertn_d[2]), rec_start = (info.maxrec+1)
    cdf_varput, pub_id, 'Vr_RTN',     reform(vel_hertn_d[0]), rec_start = (info.maxrec+1)
    cdf_varput, pub_id, 'Vt_RTN',     reform(vel_hertn_d[1]), rec_start = (info.maxrec+1)
    cdf_varput, pub_id, 'Vn_RTN',     reform(vel_hertn_d[2]), rec_start = (info.maxrec+1)
    cdf_varput, pub_id, 'N_S_flow_angle_HERTN', ns_hertn_d,   rec_start = (info.maxrec+1)
    cdf_varput, pub_id, 'E_W_flow_angle_HERTN', ew_hertn_d,   rec_start = (info.maxrec+1)
    cdf_varput, pub_id, 'N_S_flow_angle_RTN',   ns_rtn_d,     rec_start = (info.maxrec+1)
    cdf_varput, pub_id, 'E_W_flow_angle_RTN',   ew_rtn_d,     rec_start = (info.maxrec+1)

    ; the rest
    pi = dblarr(6)
    pressure_6 = dblarr(6)
    pressure_inst = dblarr(3)
    pressure_spcrft = dblarr(3)
    temperature_inst = dblarr(3)
    temperature_spcrft = dblarr(3)
    energy_flux = dblarr(3)

    ; fill in efficiencies
    found = 0
    jj = 0
    IF bulk_speed_inst_sav_d GT ra_trig_eff[i_cal, 127, 2] THEN BEGIN ; take into average
        IF n_elements(vel_box) EQ 0 THEN BEGIN
            vel_box = [bulk_speed_inst_sav_d] 
        ENDIF ELSE IF n_elements(vel_box) GT 9 THEN BEGIN ; go up to 9 elements in box
            vel_box = vel_box[1:n_elements(vel_box)-1]
            vel_box = [vel_box, bulk_speed_inst_sav_d]
        ENDIF ELSE vel_box = [vel_box, bulk_speed_inst_sav_d] 
    ENDIF 
    IF n_elements(vel_box) EQ 0 THEN temp_velocity = bulk_speed_inst_sav_d ELSE temp_velocity = total(vel_box)/n_elements(vel_box)
    ; check for 0 values in ratio arrays
    valid_i = where(svalid_ratrig_ratio NE 0, count)
    IF count GT 0 THEN BEGIN
        IF valid_i[0] GT 0 THEN svalid_ratrig_ratio[0:valid_i[0]-1] = svalid_ratrig_ratio[valid_i[0]]
        FOR jj = 0, count-2 DO BEGIN ; fill in between valid indices
            IF valid_i[jj] LT valid_i[jj+1]-1 THEN BEGIN ; have gap
                svalid_ratrig_ratio[valid_i[jj]+1:valid_i[jj+1]-1] = svalid_ratrig_ratio[valid_i[jj+1]] ; take one to the right
            ENDIF
        ENDFOR 
        IF valid_i[count-1] LT 31 THEN svalid_ratrig_ratio[valid_i[count-1]+1:31] = svalid_ratrig_ratio[valid_i[count-1]]
    ENDIF 
    valid_i = where(pri0_ratio NE 0, count)
    IF count GT 0 THEN BEGIN
        IF valid_i[0] GT 0 THEN pri0_ratio[0:valid_i[0]-1] = pri0_ratio[valid_i[0]]
        FOR jj = 0, count-2 DO BEGIN ; fill in between valid indices
            IF valid_i[jj] LT valid_i[jj+1]-1 THEN BEGIN ; have gap
                pri0_ratio[valid_i[jj]+1:valid_i[jj+1]-1] = pri0_ratio[valid_i[jj+1]] ; take one to the right
            ENDIF
        ENDFOR 
        IF valid_i[count-1] LT 127 THEN pri0_ratio[valid_i[count-1]+1:127] = pri0_ratio[valid_i[count-1]]
    ENDIF 
    ; search for closest efficiency
    WHILE jj LT 127 AND found EQ 0 DO BEGIN ; this takes the lower value
        IF temp_velocity GT ra_trig_eff[i_cal, jj, 2] THEN BEGIN
            ratio_interp = interpol(svalid_ratrig_ratio, reform(vel_groups[i_cal, *]), temp_velocity)
            efficiency = ra_trig_eff[i_cal, jj, 3] * ratio_interp
            pri_efficiency = pri0_ratio[jj]
            found = 1
        ENDIF ELSE jj = jj + 1
    ENDWHILE 
    IF found EQ 0 THEN BEGIN
        efficiency = double(ra_trig_eff[i_cal, 127, 3])
        pri_efficiency = pri0_ratio[127]
    ENDIF
    IF dpu_version LE 317 AND sat EQ 'B' THEN pri_efficiency = 1 ; don't use for SW-all
    IF dpu_version GT 317 AND mom_array EQ 0 THEN pri_efficiency = 1

    ; density

    density_m_uncomp = density_m_uncomp * step_var[i_cal] * table_norm[i_cal, 0] / (geom[i_cal, 0] * efficiency)
    density_s_uncomp = density_s_uncomp * step_var[i_cal] * table_norm[i_cal, 0] / (geom[i_cal, 1] * efficiency)
    density = (density_m_uncomp + density_s_uncomp) / pri_efficiency

    ; add temporal offset ratio to density
    saved_density = density ; used for calculating temperature
    IF sat EQ 'A' THEN BEGIN 
        den_temporal_offset_ratio = 1.5
        density = density * den_temporal_offset_ratio
    ENDIF ELSE BEGIN ; B
        IF temp_doy LT 288 THEN BEGIN  ; until 10/15/2007
            den_temporal_offset_ratio = 1.5
            density = density * den_temporal_offset_ratio
        ENDIF ELSE IF temp_doy GE 288 AND temp_doy LT 411 THEN BEGIN  ; 10/15/2007 - 2/14/2008
            den_temporal_offset_ratio = (0.0054*temp_doy) -  0.1663
            density = density * den_temporal_offset_ratio
        ENDIF ELSE BEGIN ; 2/14/2008 - 
            den_temporal_offset_ratio = 2.0
            density = density * den_temporal_offset_ratio
        ENDELSE 
    ENDELSE         
    IF bad_vel EQ 1 THEN density = -1e+31
    cdf_varput, cdf_id, 'Density', density, rec_start = (info.maxrec+1)
    cdf_varput, pub_id, 'Density', density, rec_start = (info.maxrec+1)

    ; pressure & temperature
    k = 1.38E-23 ; Boltzmann constant J/deg
    a_bp_e = step_var[i_cal] * table_norm[2] / efficiency
    IF mom_array EQ 1 THEN a_bp_e = a_bp_e / pri_efficiency
    mn = 1.67E-27 * saved_density * (10 ^ 6D)  ; added 10^6 9/25/07
    FOR jj = 0, 5 DO BEGIN      ; xx,xy,xz,yy,yz,zz
        IF jj LT 3 THEN vel1 = velocity_eng[0] ELSE IF jj LT 5 THEN $
          vel1 = velocity_eng[1] ELSE vel1 = velocity_eng[2]
        IF jj EQ 0 THEN vel2 = velocity_eng[0] ELSE IF (jj EQ 1 OR jj EQ 3) THEN $
          vel2 = velocity_eng[1] ELSE vel2 = velocity_eng[2]
        vel1 = vel1 * 1000 ; added 9/25/07
        vel2 = vel2 * 1000 ; added 9/25/07
        sum = (temperature_s_uncomp[jj] / geom[1]) + $
              (temperature_m_uncomp[jj] / geom[0]) 
        pi[jj] = a_bp_e * sum
        pressure_6[jj] = pi[jj] - (mn * vel1 * vel2)
    ENDFOR
    pressure_inst[0] = pressure_6[0] ; xx
    pressure_inst[1] = pressure_6[3] ; yy
    pressure_inst[2] = pressure_6[5] ; zz
    pressure_spcrft[0] = pressure_inst[0]
    pressure_spcrft[1] = pressure_inst[2]
    pressure_spcrft[2] = pressure_inst[1]
    IF bad_vel EQ 1 THEN pressure_inst[*] = -1e+31
    cdf_varput, cdf_id, 'Pressure_Inst', pressure_inst[0], rec_start = (info.maxrec+1)
    cdf_varput, pub_id, 'Pressure_Inst', pressure_inst[0], rec_start = (info.maxrec+1)
    temperature_inst = pressure_inst/(saved_density * (10 ^ 6D) * k) ; 10^6 to convert to 1/m3 for density
    ; add temporal offset ratio to temperature_xx
    IF sat EQ 'A' THEN BEGIN 
        temp_xx_temporal_offset_ratio = 0.0001 * temp_doy + 0.2867
        temperature_inst[0] = temperature_inst[0] * temp_xx_temporal_offset_ratio
    ENDIF ELSE BEGIN ; B
        temp_xx_temporal_offset_ratio = 0.25
        temperature_inst[0] = temperature_inst[0] * temp_xx_temporal_offset_ratio
    ENDELSE         
    temperature_spcrft[0] = temperature_inst[0]
    temperature_spcrft[1] = temperature_inst[2]
    temperature_spcrft[2] = temperature_inst[1]
    IF bad_vel EQ 1 THEN temperature_inst[*] = -1e+31
    cdf_varput, cdf_id, 'Temperature_Inst', temperature_inst[0], rec_start = (info.maxrec+1) 
    cdf_varput, pub_id, 'Temperature_Inst', temperature_inst[0], rec_start = (info.maxrec+1) 
    ; energy flux density 
    a_bh_e = step_var[i_cal] * table_norm[3] / efficiency
    a_bh_e = a_bh_e / pri_efficiency
    sum = (heat_flux_m_uncomp/geom[0]) + (heat_flux_s_uncomp/geom[1])
    energy_flux[*] = a_bh_e * sum
    cmat_gse = get_stereo_cmat(timestamp, sat, system = gse) ; get conversion matrix 
    cmat_hgrtn = get_stereo_cmat(timestamp, sat, system = hgrtn)
    energy_flux_gse = reform(cmat_gse ## energy_flux)
    energy_flux_hgrtn = reform(cmat_hgrtn ## energy_flux)
    ; Alpha
    peak_array = packet.dat[14-11+1]
    IF peak_array NE 0 AND peak_array NE 1 THEN error = 1
    IF peak_array EQ 0 THEN cdf_varput, cdf_id, 'AlphaPeakArray', 'Doubles', rec_start = (info.maxrec+1) ELSE $
      IF peak_array EQ 1 THEN cdf_varput, cdf_id, 'AlphaPeakArray', 'Triples', rec_start = (info.maxrec+1) ELSE $
      cdf_varput, cdf_id, 'AlphaPeakArray', 'Invalid', rec_start = (info.maxrec+1) 
    alpha_array = packet.dat[15-11-1]
    IF alpha_array NE 0 AND alpha_array NE 1 THEN error = 1
    IF alpha_array EQ 0 THEN cdf_varput, cdf_id, 'AlphaArray', 'Doubles', rec_start = (info.maxrec+1) ELSE $
      IF alpha_array EQ 1 THEN cdf_varput, cdf_id, 'AlphaArray', 'Triples', rec_start = (info.maxrec+1) ELSE $
      cdf_varput, cdf_id, 'AlphaArray', 'Invalid', rec_start = (info.maxrec+1) 
    IF dpu_version LE 317 THEN BEGIN 
        pp = packet.dat[73-11-1]
        dp = packet.dat[74-11+1]
        ep = packet.dat[75-11-1] AND '7F'x
        index = 79-11
    ENDIF ELSE BEGIN 
        pp = packet.dat[74-11+1]
        dp = packet.dat[75-11-1]
        ep = packet.dat[76-11+1] AND '7F'x
        index = 79-11
    ENDELSE 
    IF pp LT 0 OR pp GT 31 THEN error = 1
    cdf_varput, cdf_id, 'AlphaPeakPos', pp, rec_start = (info.maxrec+1)
    IF dp LT 0 OR dp GT 31 THEN error = 1
    cdf_varput, cdf_id, 'AlphaPeakDefl', dp, rec_start = (info.maxrec+1)
    cdf_varput, cdf_id, 'AlphaPeakEnergy', ep, rec_start = (info.maxrec+1)
    alpha = lonarr(5, 5, 5)
    FOR i = 0, 4 DO BEGIN ; esa
        FOR j = 0, 4 DO BEGIN ; pos
            FOR k = 0, 4 DO BEGIN ; defl
                temp_index = index + (i*25) + (j*5) + k
                IF temp_index MOD 2 EQ 0 THEN alpha[i, j, k] = packet.dat[temp_index-1] $
                  ELSE alpha[i, j, k] = packet.dat[temp_index+1]
            ENDFOR
        ENDFOR
    ENDFOR
    uncompress8, alpha, alpha_uncomp
    cdf_varput, cdf_id, 'AlphaDist', alpha_uncomp, rec_start = (info.maxrec+1)
    ; Heavies
    start_esa = bytarr(2)
    swz = lonarr(10, 2)
    wap_ssd_tcr = lonarr(5, 3)
    wap_ssd_dcr = lonarr(5, 3)
    num_cycles  = lonarr(5, 2)
    IF dpu_version LE 317 THEN BEGIN 
        start_esa[0] = packet.dat[76-11+1]
        start_esa[1] = packet.dat[77-11-1]
        index_swz2 = 204-11
        index_wap_ssd_tcr = 224-11
        index_wap_ssd_dcr = 239-11
    ENDIF ELSE BEGIN 
        start_esa[0] = packet.dat[77-11-1]
        start_esa[1] = packet.dat[78-11+1]
        index_swz2 = 206-11
        index_wap_ssd_tcr = 226-11
        index_wap_ssd_dcr = 241-11
        index_num_cycles  = 256-11
    ENDELSE 
    ; SWZ>2
    FOR j = 0, 1 DO BEGIN       ; data/flag
        FOR i = 0, 9 DO BEGIN   ; Class
            temp_index = index_swz2 + (j*10) + i
            IF temp_index MOD 2 EQ 0 THEN swz[i, j] = packet.dat[temp_index-1] ELSE swz[i, j] = packet.dat[temp_index+1]
        ENDFOR
    ENDFOR
    uncompress8, swz, swz_uncomp
    cdf_varput, cdf_id, 'SW_Z>2', swz_uncomp, rec_start = (info.maxrec+1)
    ; WAP_SSD_TCR
    IF start_esa[0] LT 0 OR start_esa[0] GT 127 THEN error = 1
    IF start_esa[1] LT 0 OR start_esa[1] GT 127 THEN error = 1
    cdf_varput, cdf_id, 'SW_Z>2_startESA', start_esa, rec_start = (info.maxrec+1)
    cdf_varput, cdf_id, 'Error_Flag', error, rec_start = (info.maxrec+1)
    FOR j = 0, 2 DO BEGIN       ; Energy bin
        FOR i = 0, 4 DO BEGIN   ; Class
            temp_index = index_wap_ssd_tcr + (j*5) + i
            IF temp_index MOD 2 EQ 0 THEN wap_ssd_tcr[i, j] = packet.dat[temp_index-1] ELSE $
              wap_ssd_tcr[i, j] = packet.dat[temp_index+1]
        ENDFOR
    ENDFOR
    uncompress8, wap_ssd_tcr, wap_ssd_tcr_uncomp
    cdf_varput, cdf_id, 'WAP_SSD_TCR', wap_ssd_tcr_uncomp, rec_start = (info.maxrec+1)
    ; WAP_SSD_DCR
    FOR j = 0, 2 DO BEGIN       ; Energy bin
        FOR i = 0, 4 DO BEGIN   ; Class
            temp_index = index_wap_ssd_dcr + (j*5) + i
            IF temp_index MOD 2 EQ 0 THEN wap_ssd_dcr[i, j] = packet.dat[temp_index-1] ELSE $
              wap_ssd_dcr[i, j] = packet.dat[temp_index+1]
        ENDFOR
    ENDFOR
    uncompress8, wap_ssd_dcr, wap_ssd_dcr_uncomp
    cdf_varput, cdf_id, 'WAP_SSD_DCR', wap_ssd_dcr_uncomp, rec_start = (info.maxrec+1)
    ; num_cycles
    IF dpu_version EQ '32A'x THEN BEGIN 
        FOR j = 0, 4 DO BEGIN ; Apid (31A, 31B, 31C, 31E, 31F)
            FOR i = 0, 1 DO BEGIN ; Num cycles (found, expected)
                temp_index = index_num_cycles + (j*2) + i
                IF temp_index MOD 2 EQ 0 THEN num_cycles[j, i] = packet.dat[temp_index-1] ELSE $
                  num_cycles[j, i] = packet.dat[temp_index+1]
            ENDFOR
        ENDFOR
        cdf_varput, cdf_id, 'Num_Cycles_Heavies', num_cycles, rec_start = (info.maxrec+1)
    ENDIF 
                
    cdf_close, cdf_id
    cdf_close, pub_id

    CASE spacecraft OF
        'EA'x: BEGIN 
            IF n_elements(vel_box) GT 0 THEN vel_box_a = vel_box
        END
        'EB'x: BEGIN 
            IF n_elements(vel_box) GT 0 THEN vel_box_b = vel_box
        END
    ENDCASE 
ENDIF 

END 
