;+ ;NAME: ; fa_esa_cmn_l2gen.pro ;PURPOSE: ; turn a FAST ESA common block into a L2 CDF. ;CALLING SEQUENCE: ; fa_esa_cmn_l2gen, cmn_dat ;INPUT: ; cmn_dat = a structrue with the data: ; PROJECT_NAME STRING 'FAST' ; DATA_NAME STRING 'Iesa Burst' ; DATA_LEVEL STRING 'Level 1' ; UNITS_NAME STRING 'Compressed' ; UNITS_PROCEDURE STRING 'fa_convert_esa_units' ; VALID INT Array[59832] ; DATA_QUALITY BYTE Array[59832] ; TIME DOUBLE Array[59832] ; END_TIME DOUBLE Array[59832] ; INTEG_T DOUBLE Array[59832] ; DELTA_T DOUBLE Array[59832] ; NBINS BYTE Array[59832] ; NENERGY BYTE Array[59832] ; GEOM_FACTOR FLOAT Array[59832] ; DATA_IND LONG Array[59832] ; GF_IND INT Array[59832] ; BINS_IND INT Array[59832] ; MODE_IND BYTE Array[59832] ; THETA_SHIFT FLOAT Array[59832] ; THETA_MAX FLOAT Array[59832] ; THETA_MIN FLOAT Array[59832] ; BKG FLOAT Array[59832] ; DATA0 BYTE Array[48, 32, 59832] ; DATA1 FLOAT NaN (48, 64, ntimes) (here single NaN means no data) ; DATA2 FLOAT NaN (96, 32, ntimes) ; ENERGY FLOAT Array[96, 32, 2] ; BINS BYTE Array[96, 32] ; THETA FLOAT Array[96, 32, 2] ; GF FLOAT Array[96, 64] ; DENERGY FLOAT Array[96, 32, 2] ; DTHETA FLOAT Array[96, 32, 2] ; EFF FLOAT Array[96, 32, 2] ; DEAD FLOAT 1.10000e-07 ; MASS FLOAT 0.0104389 ; CHARGE INT 1 ; SC_POT FLOAT Array[59832] ; BKG_ARR FLOAT Array[96, 64] ; HEADER_BYTES BYTE Array[44, 59832] ; DATA BYTE Array[59832, 96, 64] ; EFLUX FLOAT Array[59832, 96, 64] ; ENERGY_FULL FLOAT Array[59832, 96, 64] ; DENERGY_FULL FLOAT Array[59832, 96, 64] ; PITCH_ANGLE FLOAT Array[59832, 96, 64] ; DOMEGA FLOAT Array[59832, 96, 64] ;KEYWORDS: ; otp_struct = this is the structure that is passed into ; cdf_save_vars to create the file ; directory = Set this keyword to direct the output into this ; directory; the default is './' ; fullfile_out = the output filename ;HISTORY: ; Hacked from mvn_sta_cmn_l2gen.pro, 22-jul-2015 ; SOme chages for version 2, jmm, 2021-09-28 ; $LastChangedBy: jimm $ ; $LastChangedDate: 2021-10-11 13:27:22 -0700 (Mon, 11 Oct 2021) $ ; $LastChangedRevision: 30348 $ ; $URL: svn+ssh://thmsvn@ambrosia.ssl.berkeley.edu/repos/spdsoft/tags/spedas_5_0/general/missions/fast/fa_esa/l2util/fa_esa_cmn_l2gen.pro $ ;- Pro fa_esa_cmn_l2gen, cmn_dat, esa_type=esa_type, $ otp_struct = otp_struct, $ directory = directory, $ fullfile_out = fullfile0, $ no_compression = no_compression, $ _extra = _extra ;Keep track of software versioning here sw_vsn = fa_esa_current_sw_version() sw_vsn_str = 'v'+string(sw_vsn, format='(i2.2)') If(~is_struct(cmn_dat)) Then Begin message,/info,'No Input Structure' Return Endif If(cmn_dat.orbit_start Ne cmn_dat.orbit_end) Then Begin message,/info,'No multiple orbit files plaese' Return Endif ;Get the start time for this orbit: ; tt = fa_orbit_to_time(cmn_dat.orbit_start) ; date = time_string(tt[1], format=6) ;First, global attributes gen_date = time_string(systime(/sec), precision=-3) global_att = {Acknowledgment:'None', $ Data_type:'CAL>Calibrated', $ Data_version:'0', $ Descriptor:'FA_ESA>Fast Auroral SnapshoT Explorer, Electrostatic Analyzer', $ Discipline:'Space Physics>Planetary Physics>Particles', $ File_naming_convention: 'descriptor_datatype_yyyyMMddHHmmss', $ Generated_by:'FAST SOC' , $ ; Generation_date:'2015-07-28' , $ Generation_date:gen_date , $ HTTP_LINK:'http://sprg.ssl.berkeley.edu/fast/', $ Instrument_type:'Particles (space)' , $ LINK_TEXT:'General Information about the FAST mission' , $ LINK_TITLE:'FAST home page' , $ Logical_file_id:'fa_esa_l2_XXX_00000000000000_00000_v00.cdf' , $ Logical_source:'fa_esa_l2_XXX' , $ Logical_source_description:'FAST Ion and Electron Particle Distributions', $ Mission_group:'FAST' , $ MODS:'Rev-2 2021-09-28' , $ PI_name:'J. P. McFadden', $ PI_affiliation:'U.C. Berkeley Space Sciences Laboratory', $ Planet:'Earth', $ Project:'FAST', $ Rules_of_use:'Open Data for Scientific Use' , $ Source_name:'FAST>Fast Auroral SnapshoT Explorer', $ TEXT:'ESA>Electrostatic Analyzer', $ Time_resolution:'1 sec', $ Title:'FAST ESA Electron and Ion Distributions'} ;Now variables and attributes cvars = strlowcase(tag_names(cmn_dat)) ;What type of data? ext is for filenames ext1, 2 for labels If(keyword_set(esa_type)) Then Begin ext = strlowcase(strcompress(/remove_all, esa_type[0])) Endif Else Begin type_test = strlowcase(strcompress(/remove_all, cmn_dat.data_name)) Case type_test Of 'iesasurvey': ext = 'ies' 'iesaburst': ext = 'ieb' 'eesasurvey': ext = 'ees' 'eesaburst': ext = 'eeb' Else: ext = 'oops' Endcase Endelse Case ext Of 'ies': Begin ext1 = 'Survey Ion ' ext2 = 'Differential survey-mode ion ' End 'ieb': Begin ext1 = 'Burst Ion ' ext2 = 'Differential burst-mode ion ' End 'ees': Begin ext1 = 'Survey Electron ' ext2 = 'Differential survey-mode electron ' End 'eeb': Begin ext1 = 'Burst Electron ' ext2 = 'Differential burst-mode electron ' End Else: Begin ext1 = ext ext2 = ext End Endcase ; Here are variable names, type, catdesc, and lablaxis rv_vt = [['epoch', 'CDF_EPOCH', 'CDF EPOCH time, one element per ion distribution (NUM_DISTS elements)', 'CDF_EPOCH'], $ ['time_unix', 'DOUBLE', 'Unix time (elapsed seconds since 1970-01-01/00:00 without leap seconds) for each data record, one element per distribution. This time is the center time of data collection. (NUM_DISTS elements)', 'Unix Time'], $ ['time_start', 'DOUBLE', 'Unix time at the start of data collection. (NUM_DISTS elements)', 'Interval start time (unix)'], $ ['time_end', 'DOUBLE', 'Unix time at the end of data collection. (NUM_DISTS elements)', 'Interval end time (unix)'], $ ['time_delta', 'DOUBLE', 'Averaging time. (TIME_END - TIME_START). (NUM_DISTS elements).', 'Averaging time'], $ ['time_integ', 'DOUBLE', 'Integration time. (TIME_DELTA/N_ENERGY). (NUM_DISTS elements).', 'Integration time'], $ ['header_bytes', 'BYTE', 'The packet header bytes. (44XNUM_DISTS elements)', 'Header'], $ ['valid', 'INTEGER', 'Validity flag codes valid data from CDF, 0 for invalid data, 1 for good data', ' Valid flag'], $ ['data_quality', 'INTEGER', 'Quality flag (NUM_DISTS elements)', 'Quality flag, 0 for good quality, add 2 for counter overflow overflow, add 4 for excess dead_time above 0.90'], $ ['nbins', 'INTEGER', 'Number of angluar bins (NUM_DISTS elements)', 'Number of bins'], $ ['nenergy', 'INTEGER', 'Number of energies (NUM_DISTS elements)', 'Number of energies'], $ ['geom_factor', 'DOUBLE', 'GEOM_FACTOR, Geometrical factor used in calibration (NUM_DISTS elements)', 'Geometric Factor'], $ ['gf_ind', 'INTEGER', 'Index for the value of the Geometrical factor for data (NUM_DISTS elements)', 'GF index'], $ ['bins_ind', 'INTEGER', 'Index for the number of angular bins for data (NUM_DISTS elements)', 'Bins index'], $ ['mode_ind', 'INTEGER', 'Index for the data mode (0-2 for survey data, 0-1 for burst data) (NUM_DISTS elements)', 'Mode index'], $ ['theta_shift', 'DOUBLE', 'Angular shift (NUM_DISTS elements)', 'Angular shift, converts theta bin values to pitch angles'], $ ['theta_max', 'DOUBLE', 'Angular maximum (NUM_DISTS elements)', 'Angular max'], $ ['theta_min', 'DOUBLE', 'Angular minimum (NUM_DISTS elements)', 'Angular min'], $ ['bkg', 'FLOAT', 'Background counts array with dimensions (NUM_DISTS)', 'Background counts'], $ ['sc_pot', 'FLOAT', 'Spacecraft potential (NUM_DISTS elements)', 'Spacecraft potential'], $ ['data', 'BYTE', ext1+'Raw Counts data with dimensions (96, 64, NUM_DISTS)', ext1+'Raw Counts'], $ ['eflux', 'FLOAT', ext2+'Differential energy flux array with dimensions (96, 64, NUM_DISTS) (as plasmagrams)', ext1+'Energy flux'], $ ['eflux_movie', 'FLOAT', ext1+'Plasmagram movie', ext1+'Energy Flux'],$ ['eflux_byE_atA', 'FLOAT', ext1+'Spectrograms by energy at sample pitch angles', ext1+'Energy Flux'],$ ['eflux_byA_atE', 'FLOAT', ext1+'Spectrograms by pitch_angle at sample energies', ext1+'Energy Flux'],$ ['pitch_angle_median', 'FLOAT', '---> Median Pitch Angle', 'Median Pitch Angle'],$ ['energy_median', 'FLOAT', '---> Median Energy', 'Median Energy'],$ ['pitch_angle', 'FLOAT', 'Pitch Angle values for each distribution (96, 64, NUM_DISTS)', 'Pitch Angle'], $ ['domega', 'FLOAT', 'Solid angle for each distribution (96, 64, NUM_DISTS)', 'DOmega'], $ ['energy_full', 'FLOAT', 'Angular values for each distribution (96, 64, NUM_DISTS)', 'Energy'], $ ['denergy_full', 'FLOAT', 'Energy bin size for each distribution (96, 64, NUM_DISTS)', 'DEnergy'], $ ['orbit_number', 'FLOAT', 'Orbit number for this file, does not change, so only 2 entries per file', 'Orbit_number'], $ ['orbit_number_time', 'DOUBLE', 'Time array, unix time for orbit number', 'Orbit Number Time'], $ ['orbit_number_epoch', 'CDF_EPOCH', 'CDF Epoch array for orbit number', 'Orbit Number Epoch']] ;Use Lower case for variable names; try to relax this assumption ; rv_vt[0, *] = strlowcase(rv_vt[0, *]) ;No need for lablaxis values here, just use the name nv_vt = [['project_name', 'STRING', 'FAST'], $ ['data_name', 'STRING', cmn_dat.data_name], $ ['data_level', 'STRING', 'Level 2'], $ ['units_name', 'STRING', 'eflux'], $ ['units_procedure', 'STRING', 'fa_esa_convert_esa_units, name of IDL routine used for units conversion '], $ ['num_dists', 'INTEGER', 'Number of measurements or times in the file'], $ ['bins', 'INTEGER', 'Array with dimension NBINS containing 1 OR 0 used to flag bad angle bins'], $ ['energy', 'FLOAT', 'Energy array with dimension (96,64 or 32,nmode)'], $ ['denergy', 'FLOAT', 'Delta Energy array with dimension (96, 64 or 32, 2 or 3)'], $ ['theta', 'FLOAT', 'Angle array with with dimension (96, 64 or 32, 2 or 3)'], $ ['dtheta', 'FLOAT', 'Delta Angle array with with dimension (96, 64 or 32, 2 or 3)'], $ ['gf', 'FLOAT', 'Geometric Factor array with dimension (96, 64)'], $ ['eff', 'FLOAT', 'Efficiency array with dimension (96, 64 or 32, 2 or 3)'], $ ['dead', 'FLOAT', 'Dead time in seconds for 1 processed count'], $ ['mass', 'FLOAT', 'Proton or Electron mass in units of MeV/c2'], $ ['charge', 'FLOAT', 'Proton or Electron charge (1 or -1)'], $ ['bkg_arr', 'FLOAT', 'Background counts array with dimension (96, 64)'], $ ['orbit_start', 'LONG', 'Start Orbit of file'], $ ['orbit_end', 'LONG', 'End Orbit of file'], $ ;added channel and bin for depend variables, so that depend values are not ;messed up, jmm, 2020-01-12 ['energy_channel', 'LONG', 'Energy Channel'], $ ['pitch_angle_bin', 'LONG', 'Pitch Angle Bin']] ;Create variables for epoch cdf_leap_second_init date_range = time_double(['1996-08-21/00:00:00','2009-05-01/00:00:00']) epoch_range = time_epoch(date_range) ;Use center time for time variables center_time = 0.5*(cmn_dat.time+cmn_dat.end_time) num_dists = n_elements(center_time) ;Initialize otp_struct = -1 count = 0L ;First handle RV variables lrv = n_elements(rv_vt[0, *]) For j = 0L, lrv-1 Do Begin ;Either the name is in the common block or not, names not in the ;common block have to be dealt with as special cases. Vectors will ;need label and component variables is_virtual = 0b is_tvar = 0b vj = rv_vt[0, j] Have_tag = where(cvars Eq vj, nhave_tag) If(nhave_tag Gt 0) Then Begin dvar = cmn_dat.(have_tag) If(vj Eq 'header_bytes') Then dvar = transpose(dvar) Endif Else Begin ;Case by case basis Case vj of 'epoch': Begin dvar = time_epoch(center_time) is_tvar = 1b End 'time_unix': Begin dvar = center_time is_tvar = 1b End 'time_start': Begin dvar = cmn_dat.time is_tvar = 1b End 'time_end': Begin dvar = cmn_dat.end_time is_tvar = 1b End 'time_delta': dvar = cmn_dat.delta_t 'time_integ': dvar = cmn_dat.integ_t 'orbit_number': dvar = [cmn_dat.orbit_start, cmn_dat.orbit_end] 'orbit_number_time': Begin dvar = minmax(center_time) is_tvar = 1b End 'orbit_number_epoch': Begin dvar = time_epoch(minmax(center_time)) is_tvar = 1b End 'eflux_movie':Begin dvar = 1.0 ;do this for data typing is_virtual = 1b End 'eflux_byE_atA':Begin dvar = 1.0 is_virtual = 1b End 'eflux_byA_atE':Begin dvar = 1.0 is_virtual = 1b End 'energy_median':Begin is_virtual = 1b dvar = 1.0 End 'pitch_angle_median':Begin dvar = 1.0 is_virtual = 1b End Else: Begin message, /info, 'Variable '+vj+' Unaccounted for.' End Endcase Endelse ;variable attributes here, but only the string attributes, the others ;depend on the data type vatt = {catdesc:'NA', display_type:'NA', fieldnam:'NA', $ units:'None', depend_time:'NA', $ depend_0:'NA', depend_1:'NA', depend_2:'NA', $ depend_3:'NA', var_type:'NA', $ coordinate_system:'sensor', $ scaletyp:'NA', lablaxis:'NA',$ labl_ptr_1:'NA',labl_ptr_2:'NA',labl_ptr_3:'NA', $ form_ptr:'NA', monoton:'FALSE',var_notes:'None'} cdf_type = idl2cdftype(dvar, format_out = fmt, fillval_out = fll, validmin_out = vmn, validmax_out = vmx) ;Change types for CDF time variables If(vj eq 'epoch' Or vj Eq 'orbit_number_epoch') Then cdf_type = 'CDF_EPOCH' dtype = size(dvar, /type) ;probably the same for all vars vatt.catdesc = rv_vt[2, j] vatt.lablaxis = rv_vt[3, j] vatt.fieldnam = rv_vt[3, j] ;shorter name vatt.depend_0 = 'epoch' vatt.depend_time = 'time_unix' vatt.var_type='data' str_element, vatt, 'fillval', fll, /add str_element, vatt, 'format', fmt, /add ;Handle virtual variables separately If(vj Eq 'eflux_movie') Then Begin vatt.units='eV/(cm^2-s-sr-eV)' vatt.scaletyp='log' vatt.display_type = 'plasmagram>THUMBSIZE>166>xsz=4,ysz=7>xx=pitch_angle_median,y=energy_median,z=data' str_element, vatt, 'validmin', 0.0, /add str_element, vatt, 'validmax', 1.0e10, /add vatt.depend_2 = 'energy_median' vatt.depend_1 = 'pitch_angle_median' str_element, vatt, 'virtual', 'true', /add str_element, vatt, 'funct', 'alternate_view', /add str_element, vatt, 'component_0', 'eflux', /add Endif Else If(vj Eq 'eflux_byE_atA') Then Begin vatt.units='eV/(cm^2-s-sr-eV)' vatt.scaletyp='log' vatt.display_type = 'spectrogram>y=energy_median,z=eflux_byE_atA(2,*),z=eflux_byE_atA(8,*),z=eflux_byE_atA(14,*),z=eflux_byE_atA(20,*),z=eflux_byE_atA(26,*),z=eflux_byE_atA(32,*),z=eflux_byE_atA(50,*)' str_element, vatt, 'validmin', 0.0, /add str_element, vatt, 'validmax', 1.0e10, /add vatt.depend_2 = 'energy_median' vatt.depend_1 = 'pitch_angle_median' str_element, vatt, 'virtual', 'true', /add str_element, vatt, 'funct', 'alternate_view', /add str_element, vatt, 'component_0', 'eflux', /add vatt.labl_ptr_1 = 'eflux_bypitch_labl' vatt.labl_ptr_2 = 'eflux_byenergy_labl' Endif Else If(vj Eq 'eflux_byA_atE') Then Begin vatt.units='eV/(cm^2-s-sr-eV)' vatt.scaletyp='log' vatt.display_type = 'spectrogram>y=compno_64,z=eflux_byA_atE(*,2),z=eflux_byA_atE(*,8),z=eflux_byA_atE(*,14),z=eflux_byA_atE(*,20),z=eflux_byA_atE(*,26),z=eflux_byA_atE(*,32),z=eflux_byA_atE(*,38),z=eflux_byA_atE(*,44),z=eflux_byA_atE(*,76)' str_element, vatt, 'validmin', 0.0, /add str_element, vatt, 'validmax', 1.0e10, /add vatt.depend_2 = 'energy_median' vatt.depend_1 = 'pitch_angle_median' str_element, vatt, 'virtual', 'true', /add str_element, vatt, 'funct', 'alternate_view', /add str_element, vatt, 'component_0', 'eflux', /add vatt.labl_ptr_1 = 'eflux_bypitch_labl' vatt.labl_ptr_2 = 'eflux_byenergy_labl' Endif Else If(vj Eq 'energy_median') Then Begin vatt.units = 'eV' vatt.scaletyp = 'log' vatt.display_type = 'stack_plot' str_element, vatt, 'validmin', 0.0, /add str_element, vatt, 'validmax', 200000.0, /add str_element, vatt, 'scalemin', 1.0, /add str_element, vatt, 'scalemax', 100000.0, /add vatt.depend_1 = 'compno_64' vatt.labl_ptr_1 = 'angle_labl_64' str_element, vatt, 'virtual', 'true', /add str_element, vatt, 'funct', 'arr_slice', /add str_element, vatt, 'component_0', 'energy_full', /add str_element, vatt, 'arr_index', 16, /add str_element, vatt, 'arr_dim', 0, /add Endif Else If(vj Eq 'pitch_angle_median') Then Begin vatt.units = 'degrees' vatt.scaletyp = 'linear' vatt.display_type = 'stack_plot' str_element, vatt, 'validmin',-360.0, /add str_element, vatt, 'validmax', 360.0, /add str_element, vatt, 'scalemin', -20.0, /add str_element, vatt, 'scalemax', 380.0, /add vatt.depend_1 = 'compno_64' vatt.labl_ptr_1 = 'angle_labl_64' str_element, vatt, 'virtual', 'true', /add str_element, vatt, 'funct', 'arr_slice', /add str_element, vatt, 'component_0', 'pitch_angle', /add str_element, vatt, 'arr_index', 24, /add str_element, vatt, 'arr_dim', 1, /add Endif Else Begin ;fix valid mins and valid max's here If(vj Eq 'eflux') Then Begin str_element, vatt, 'validmin', 0.0, /add str_element, vatt, 'validmax', 1.0e10, /add Endif Else If(vj Eq 'epoch' Or vj Eq 'orbit_number_epoch') Then Begin str_element, vatt, 'fillval', -1.0d+31, /add_replace ;istp str_element, vatt, 'validmin', epoch_range[0], /add str_element, vatt, 'validmax', epoch_range[1], /add Endif Else If(vj Eq 'time_unix' Or vj Eq 'time_start' Or vj Eq 'time_end' $ Or vj Eq 'orbit_number_time') Then Begin str_element, vatt, 'validmin', date_range[0], /add str_element, vatt, 'validmax', date_range[1], /add Endif Else If(vj Eq 'theta_shift' Or vj Eq 'pitch_angle' Or vj Eq 'dpitch_angle' Or $ vj Eq 'theta_min' Or vj Eq 'theta_max') Then Begin str_element, vatt, 'validmin', -400.0, /add str_element, vatt, 'validmax', 400.0, /add Endif Else Begin str_element, vatt, 'validmin', vmn, /add str_element, vatt, 'validmax', vmx, /add Endelse ;data is log scaled, everything else is linear, set data, support data ;display type here IF(vj Eq 'data' Or vj Eq 'eflux') Then Begin vatt.scaletyp = 'log' vatt.display_type = 'plasmagram>THUMBSIZE>166>xsz=4,ysz=7>xx=pitch_angle_median,y=energy_median,z=data' Endif Else Begin vatt.scaletyp = 'linear' vatt.display_type = 'time_series' If(vj eq 'bkg' Or vj Eq 'theta_shift' Or vj Eq 'pitch_angle' Or $ vj Eq 'dpitch_angle' Or vj Eq 'theta_min' Or vj Eq 'theta_max' Or $ vj Eq 'sc_pot') Then Begin dummy = 1 ;var type is already 'data' Endif Else vatt.var_type = 'support_data' Endelse ;Units If(is_tvar) Then Begin ;Time variables vatt.units = 'sec' Endif Else Begin If(strpos(vj, 'time') Ne -1) Then vatt.units = 'sec' $ ;time interval sizes Else If(strpos(vj, 'theta') Ne -1 Or strpos(vj, 'pitch') Ne -1) Then vatt.units = 'degrees' $ Else If(strpos(vj, 'energy') Ne -1) Then vatt.units = 'eV' $ Else If(strpos(vj, 'omega') Ne -1) Then vatt.units = 'ster' $ Else If(vj Eq 'sc_pot') Then vatt.units = 'volts' $ Else If(vj Eq 'data') Then vatt.units = 'Counts' $ Else If(vj Eq 'eflux') Then vatt.units = 'eV/(cm^2-s-sr-eV)' ;check this, checked 2016-10-24, jmm Endelse ;Depends and labels If(strpos(vj, 'orbit_number') Ne -1) Then Begin vatt.depend_time = 'orbit_number_time' vatt.depend_0 = 'orbit_number_epoch' Endif Else Begin vatt.depend_time = 'time_unix' vatt.depend_0 = 'epoch' Endelse If(vj Eq 'theta_shift') Then vatt.lablaxis = 'Angular shift' ;jmm, 2016-06-17 ;Assign labels and components for vectors If(vj Eq 'data' Or vj Eq 'eflux' Or $ vj Eq 'pitch_angle' Or vj Eq 'energy_full' Or $ vj Eq 'denergy_full' Or vj Eq 'domega') Then Begin ;For ISTP compliance, it looks as if the depend's are switched, ;probably because we transpose it all in the file ;??? Check this ??? Cannot have depends for non-virtual data to be ;virtual, 2020-01-11, jmm vatt.depend_1 = 'energy_channel' vatt.depend_2 = 'pitch_angle_bin' Endif ;Time variables are monotonically increasing: If(is_tvar) Then vatt.monoton = 'INCREASE' Else vatt.monoton = 'FALSE' Endelse ;delete all 'NA' tags vatt_tags = tag_names(vatt) nvatt_tags = n_elements(vatt_tags) rm_tag = bytarr(nvatt_tags) For k = 0, nvatt_tags-1 Do Begin If(is_string(vatt.(k)) && vatt.(k) Eq 'NA') Then rm_tag[k] = 1b Endfor xtag = where(rm_tag Eq 1, nxtag) If(nxtag Gt 0) Then Begin tags_to_remove = vatt_tags[xtag] For k = 0, nxtag-1 Do str_element, vatt, tags_to_remove[k], /delete Endif ;Create and fill the variable structure vsj = {name:'', num:0, is_zvar:1, datatype:'', $ type:0, numattr: -1, numelem: 1, recvary: 1b, $ numrec:0L, ndimen: 0, d:lonarr(6), dataptr:ptr_new(), $ attrptr:ptr_new()} vsj.name = vj vsj.datatype = cdf_type vsj.type = dtype vsj.numrec = num_dists ;It looks as if you do not include the time variation? ;No data if it's a virtual variable If(~is_virtual) Then Begin ndim = size(dvar, /n_dimen) dims = size(dvar, /dimen) vsj.ndimen = ndim-1 If(ndim Gt 1) Then vsj.d[0:ndim-2] = dims[1:*] vsj.dataptr = ptr_new(dvar) Endif vsj.attrptr = ptr_new(vatt) ;Append the variables structure If(count Eq 0) Then vstr = vsj Else vstr = [vstr, vsj] count = count+1 Endfor ;Now the non-record variables nrv = n_elements(nv_vt[0, *]) For j = 0L, nrv-1 Do Begin vj = nv_vt[0, j] Have_tag = where(cvars Eq vj, nhave_tag) If(nhave_tag Gt 0) Then Begin dvar = cmn_dat.(have_tag) ;Set any 1d array value to a scalar, for ISTP If(n_elements(dvar) Eq 1) Then dvar = dvar[0] Endif Else Begin ;Case by case basis Case vj of 'num_dists': Begin dvar = num_dists End 'energy_channel': Begin dvar = lindgen(96) End 'pitch_angle_bin': Begin dvar = lindgen(64) End Else: Begin message, /info, 'Variable '+vj+' Unaccounted for.' End Endcase Endelse cdf_type = idl2cdftype(dvar, format_out = fmt, fillval_out = fll, validmin_out = vmn, validmax_out = vmx) dtype = size(dvar, /type) ;variable attributes here, but only the string attributes, the others ;depend on the data type, note that these are metadata, not support_data vatt = {catdesc:'NA', fieldnam:'NA', $ units:'NA', var_type:'metadata', $ coordinate_system:'sensor'} str_element, vatt, 'format', fmt, /add ;Don't need mins and maxes for string variables If(~is_string(dvar)) Then Begin ;angles from 0.0 t0 360.0 If(vj Eq 'theta' Or vj Eq 'dtheta') Then Begin str_element, vatt, 'validmin', 0.0, /add str_element, vatt, 'validmax', 360.0, /add Endif Else If(vj Eq 'energy_channel' Or vj Eq 'pitch_angle_bin') Then Begin str_element, vatt, 'validmin', min(dvar), /add str_element, vatt, 'validmax', max(dvar), /add Endif Else Begin str_element, vatt, 'validmin', vmn, /add str_element, vatt, 'validmax', vmx, /add Endelse str_element, vatt, 'fillval', fll, /add str_element, vatt, 'scalemin', vmn, /add str_element, vatt, 'scalemax', vmx, /add Endif vatt.catdesc = nv_vt[2, j] vatt.fieldnam = nv_vt[0, j] If(vj Eq 'energy' Or vj Eq 'denergy') Then vatt.units = 'eV' $ Else If(vj Eq 'theta' Or vj Eq 'dtheta') Then vatt.units = 'Degrees' ;Create and fill the variable structure vsj = {name:'', num:0, is_zvar:1, datatype:'', $ type:0, numattr: -1, numelem: 1, recvary: 0b, $ numrec:-1L, ndimen: 0, d:lonarr(6), dataptr:ptr_new(), $ attrptr:ptr_new()} vsj.name = vj vsj.datatype = cdf_type vsj.type = dtype ;Include all dimensions ndim = size(dvar, /n_dimen) dims = size(dvar, /dimen) vsj.ndimen = ndim If(ndim Gt 0) Then vsj.d[0:ndim-1] = dims vsj.dataptr = ptr_new(dvar) vsj.attrptr = ptr_new(vatt) ;Append the variables structure If(count Eq 0) Then vstr = vsj Else vstr = [vstr, vsj] count = count+1 Endfor ;Now compnos, need 96, 64 ext_compno = [96, 64] vcompno = 'compno_'+strcompress(/remove_all, string(ext_compno)) For j = 0, n_elements(vcompno)-1 Do Begin vj = vcompno[j] xj = strsplit(vj, '_', /extract) nj = Fix(xj[1]) ;Component attributes vatt = {catdesc:vj, fieldnam:vj, $ fillval:0, format:'I3', $ validmin:0, dict_key:'number', $ validmax:255, var_type:'metadata'} ;Also a data array dvar = 1+indgen(nj) ;Create and fill the variable structure vsj = {name:'', num:0, is_zvar:1, datatype:'', $ type:0, numattr: -1, numelem: 1, recvary: 0b, $ numrec:-1L, ndimen: 0, d:lonarr(6), dataptr:ptr_new(), $ attrptr:ptr_new()} vsj.name = vj vsj.datatype = 'CDF_INT2' vsj.type = 2 ;Include all dimensions ndim = size(dvar, /n_dimen) dims = size(dvar, /dimen) vsj.ndimen = ndim If(ndim Gt 0) Then vsj.d[0:ndim-1] = dims vsj.dataptr = ptr_new(dvar) vsj.attrptr = ptr_new(vatt) ;Append the variables structure If(count Eq 0) Then vstr = vsj Else vstr = [vstr, vsj] count = count+1 Endfor ;Labels now lablvars = ['energy_labl_96', 'angle_labl_64'] For j = 0, n_elements(lablvars)-1 Do Begin vj = lablvars[j] xj = strsplit(vj, '_', /extract) nj = Fix(xj[2]) aj = xj[0]+'@'+strupcase(xj[1]) dvar = aj+strcompress(/remove_all, string(indgen(nj))) ndv = n_elements(dvar) numelem = strlen(dvar[ndv-1]) ;needed for numrec fmt = 'A'+strcompress(/remove_all, string(numelem)) ;Label attributes vatt = {catdesc:vj, fieldnam:vj, $ format:fmt, dict_key:'label', $ var_type:'metadata'} ;Create and fill the variable structure vsj = {name:'', num:0, is_zvar:1, datatype:'', $ type:0, numattr: -1, numelem: 1, recvary: 0b, $ numrec:-1L, ndimen: 0, d:lonarr(6), dataptr:ptr_new(), $ attrptr:ptr_new()} vsj.name = vj vsj.datatype = 'CDF_CHAR' vsj.type = 1 vsj.numelem = numelem ;Include all dimensions ndim = size(dvar, /n_dimen) dims = size(dvar, /dimen) vsj.ndimen = ndim If(ndim Gt 0) Then vsj.d[0:ndim-1] = dims vsj.dataptr = ptr_new(dvar) vsj.attrptr = ptr_new(vatt) ;Append the variables structure If(count Eq 0) Then vstr = vsj Else vstr = [vstr, vsj] count = count+1 Endfor ;more labels vj = 'eflux_bypitch_labl' nj = 64 dvar = ext1+'eflux @ PA '+strcompress(string(indgen(nj)+1), /remove_all) vatt = {catdesc:'Energy Flux by Pitch Angle labels', $ fieldnam:'Energy Flux by Pitch Angle labels', $ format:'A29', dict_key:'label>angle', $ var_type:'metadata'} vsj = {name:'', num:0, is_zvar:1, datatype:'', $ type:0, numattr: -1, numelem: 1, recvary: 0b, $ numrec:-1L, ndimen: 0, d:lonarr(6), dataptr:ptr_new(), $ attrptr:ptr_new()} vsj.name = vj vsj.datatype = 'CDF_CHAR' vsj.type = 1 vsj.numelem = nj ndim = size(dvar, /n_dimen) dims = size(dvar, /dimen) vsj.ndimen = ndim If(ndim Gt 0) Then vsj.d[0:ndim-1] = dims vsj.dataptr = ptr_new(dvar) vsj.attrptr = ptr_new(vatt) If(count Eq 0) Then vstr = vsj Else vstr = [vstr, vsj] count = count+1 vj = 'eflux_byenergy_labl' nj = 96 dvar = ext1+'eflux @ Energy '+strcompress(string(indgen(nj)+1), /remove_all) vatt = {catdesc:'Energy Flux by Energy labels', $ fieldnam:'Energy Flux by Energy labels', $ format:'A33', dict_key:'label>energy', $ var_type:'metadata'} vsj = {name:'', num:0, is_zvar:1, datatype:'', $ type:0, numattr: -1, numelem: 1, recvary: 0b, $ numrec:-1L, ndimen: 0, d:lonarr(6), dataptr:ptr_new(), $ attrptr:ptr_new()} vsj.name = vj vsj.datatype = 'CDF_CHAR' vsj.type = 1 vsj.numelem = nj ndim = size(dvar, /n_dimen) dims = size(dvar, /dimen) vsj.ndimen = ndim If(ndim Gt 0) Then vsj.d[0:ndim-1] = dims vsj.dataptr = ptr_new(dvar) vsj.attrptr = ptr_new(vatt) If(count Eq 0) Then vstr = vsj Else vstr = [vstr, vsj] count = count+1 nvars = n_elements(vstr) natts = n_tags(global_att)+n_tags(vstr[0]) inq = {ndims:0l, decoding:'HOST_DECODING', $ encoding:'IBMPC_ENCODING', $ majority:'COLUMN_MAJOR', maxrec:-1,$ nvars:0, nzvars:nvars, natts:natts, dim:lonarr(1)} ;time resolution and UTC start and end If(num_dists Gt 0) Then Begin tres = 86400.0/num_dists tres = strcompress(string(tres, format = '(f8.1)'))+' sec' Endif Else tres = ' 0.0 sec' global_att.time_resolution = tres otp_struct = {filename:'', g_attributes:global_att, inq:inq, nv:nvars, vars:vstr} ;Create filename and call cdf_save_vars. If(keyword_set(directory)) Then Begin dir = directory If(~is_string(file_search(dir))) Then file_mkdir, dir temp_string = strtrim(dir, 2) ll = strmid(temp_string, strlen(temp_string)-1, 1) If(ll Ne '/' And ll Ne '\') Then temp_string = temp_string+'/' dir = temporary(temp_string) Endif Else dir = './' ;SPDF requests full start time in the filename date = time_string(min(center_time), format=6) orb_string = string(long(cmn_dat.orbit_start), format = '(i5.5)') file0 = 'fa_esa_l2_'+ext+'_'+date+'_'+orb_string+'_'+sw_vsn_str+'.cdf' fullfile0 = dir+file0 otp_struct.g_attributes.data_type = 'l2_'+ext+'>Level 2 data: '+cmn_dat.data_name otp_struct.g_attributes.logical_file_id = file0 otp_struct.g_attributes.logical_source = 'fa_esa_l2_'+ext ;save the file -- full database management dummy = cdf_save_vars2(otp_struct, fullfile0, /no_file_id_update) If(~keyword_set(no_compression)) Then Begin spawn, '/usr/local/pkg/cdf-3.6.2_CentOS-6.7/bin/cdfconvert '+fullfile0+' '+fullfile0+' -blockingfactor optimal -compressnonepoch -compression cdf:none -delete' Endif Return End