;+
; :Name: mvn_kp_read
;
; :Author: Kris Larsen & John Martin
;
;
; :Description:
; Read local Maven KP data files into memory. Capable of reading both in situ KP data files
; and IUVS KP data files. Capable of reading in either CDF or ASCII formated data files.
; By default, CDF files are read. There are also hooks in place, using /download_new keyword,
; to query the SDC web server and download missing or updated KP data files.
;
; :Params:
; time: in, required, can be a scalar or a two item array of type:
; long(s) orbit number
; string(s) format: YYYY-MM-DD/hh:mm:ss
; A start or start & stop time (or orbit #) range for reading kp data.
;
; insitu_output: output, required, type=array of structures
; This paramater will contain the in situ KP data that is read into memory. It will
; be structured as an array of structures. Each array entry corresponds to each time.
;
; iuvs_output: output, optional, type=array of structures
; This parameter will contain the IUVS KP data that is read into memory. It will be
; structured as an array of structures. Each array entry corresponds to one orbit of data.
;
; :Keywords:
; download_new: in, optional, type=boolean
; optional keyword to instruct IDL to query the SDC server to look for any new or missing
; files to download over the input timerange.
; update_prefs: in, optional, type=boolean
; Before reading in data, allow user to update kp_preferences.txt - which contains paths
; to the in situ data and IUVS data. After selecting new paths to data folders, read will
; continue.
; only_update_prefs: in, optional, type=boolean
; Allow user to update kp_preferences.txt - which contains paths to the in situ data and
; IUVS data. After selecting new paths to data folders, procedure will return - not reading
; in any data.
; debug: in, optional, type=boolean
; On error, - "Stop immediately at the statement that caused the error and print
; the current program stack." If not specified, error message will be printed and
; IDL with return to main program level and stop.
; duration: in, optional, type=integer
; Length of time range for data read, only used if input time parameter is a single value.
; If input time is a string, duration is interpreted as seconds. If input time is an integer
; (orbit), duration is interpreted as orbits.
; text_files: in optional, type=boolean
; Read in ASCII files instead of the default of reading CDF files.
; save_files: in optional, type=boolean
; Read in .sav files instead of the default of reading CDF files. This option exists primarily
; for the developers and debugging.
; insitu_only: in optional, type=boolean
; Read in only in situ data. If this is supplied, the iuvs_output paramater will be ignored if
; input. Because insitu spacecraft time series ephemeris data is necessary for the visulization
; procedures to work, there is no iuvs_only option.
; lpw: in, optional, type=boolean
; return all of the LPW data
; static: in, optional, type=boolean
; return all of the STATIC data
; swia: in, optional, type=boolean
; return all of the SWIA data
; swea: in, optional, type=boolean
; return all of the SWEA data
; mag: in, optional, type=boolean
; return all of the MAG data
; sep: in, optional, type=boolean
; return all of the SEP data
; ngims: in, optional, type=boolean
; return all of the NGIMS data
; inbound: in, optional, type=boolean
; return only the data from the inbound leg of an orbit
; outbound: in, optional, type=boolean
; return only the data from the outbound leg of an orbit
; insitu_all: in, optional, type=boolean
; return all in situ data. This keyword is necessary if an IUVS observation mode keyword
; is specified and you want to still read in all in situ data. If no in situ instrument
; or IUVS observation keyword specified, default behavior is to read in all in situ data.
;
; iuvs_periapse: in, optional, type=boolean
; return all of the IUVS PERIAPSE limb scan data
; iuvs_apoapse: in, optional, type=boolean
; return all of the IUVS APOAPSE data
; iuvs_coronaEchellehigh: in, optional, type=boolean
; return all of the IUVS Corona Echelle high altitude data
; iuvs_coronaEchelleDisk: in, optional, type=boolean
; return all of the IUVS Corona Echelle disk data
; iuvs_coronaEchelleLimb: in, optional, type=boolean
; return all of the IUVS Corona Echelle limb data
; iuvs_coronaLoresDisk: in, optional, type=boolean
; return all of the IUVS Corona LoRes disk data
; iuvs_coronaLoreshigh: in, optional, type=boolean
; return all of the IUVS Corona LoRes high altitude data
; iuvs_coronaLoreslimb: in, optional, type=boolean
; return all of the iuvs corona LoREs on limb data
; iuvs_stellarocc: in, optional, type=boolean
; return all of the IUVS Stellar Occulatation data
; iuvs_all: in, optional, type=boolean
; return all IUVS observation modes. This keyword is necessary if an in situ instrument
; keyword is specified and you want to still read in all IUVS data. If no in situ instrument
; or IUVS observation keyword specified, default behavior is to read in all IUVS data.
;
;-
@mvn_kp_file_search
@mvn_kp_time_bounds
@mvn_kp_loop_progress
@mvn_kp_config_file
@mvn_kp_config
@mvn_kp_insitu_struct_init
@mvn_kp_iuvs_struct_init
@mvn_kp_insitu_assign
@mvn_kp_iuvs_binary_assign
@mvn_kp_read_insitu_file
@mvn_kp_read_iuvs_file
@mvn_kp_iuvs_cdf_read
@mvn_kp_insitu_cdf_read
pro MVN_KP_READ, time, insitu_output, iuvs_output, download_new=download_new, update_prefs=update_prefs, $
debug=debug, duration=duration, text_files=text_files, save_files=save_files, $
insitu_only=insitu_only, insitu_all=insitu_all, inbound=inbound, outbound=outbound, $
lpw=lpw, static=static, swia=swia, swea=swea, mag=mag, sep=sep, ngims=ngims, $
iuvs_all=iuvs_all, iuvs_periapse=iuvs_periapse, iuvs_apoapse=iuvs_apoapse, $
iuvs_coronaEchellehigh=iuvs_coronaEchellehigh,iuvs_coronaEchelleDisk=iuvs_coronaEchelleDisk,$
iuvs_coronaEchelleLimb=iuvs_coronaEchelleLimb, iuvs_coronaLoresDisk=iuvs_coronaLoresDisk, $
iuvs_coronaLoreshigh=iuvs_coronaLoreshigh, iuvs_coronaLoreslimb=iuvs_coronaLoreslimb, $
iuvs_stellarocc=iuvs_stellarocc, only_update_prefs=only_update_prefs
overall_start_time = systime(1)
;IF NOT IN DEBUG, SETUP ERROR HANDLER
if not keyword_set(debug) then begin
;ESTABLISH ERROR HANDLER. WHEN ERRORS OCCUR, THE INDEX OF THE
;ERROR IS RETURNED IN THE VARIABLE ERROR_STATUS:
catch, Error_status
;THIS STATEMENT BEGINS THE ERROR HANDLER:
if Error_status ne 0 then begin
;HANDLE ERRORS BY RETURNING TO MAIN:
print, '**ERROR HANDLING - ', !ERROR_STATE.MSG
print, '**ERROR HANDLING - Cannot proceed. Returning to main'
Error_status = 0
catch, /CANCEL
return
endif
endif
;; ------------------------------------------------------------------------------------ ;;
;; ---------------------------- Check input options ----------------------------------- ;;
; IF DEBUG SET, CREATE ENVIRONMENT VARIABLE SO ALL PROCEDURES/FUNCTIONS CALLED CAN CHECK FOR IT
if keyword_set(debug) then begin
setenv, 'MVNTOOLKIT_DEBUG=TRUE'
endif
;; Read from and/or update preferences file
if keyword_set(only_update_prefs) then begin
MVN_KP_CONFIG_FILE, /update_prefs, insitu_only=insitu_only
;; Warn user if other parameters supplied
if keyword_set(time) or keyword_set(insitu) or keyword_set(iuvs) then begin
print, "Warning. /ONLY_UPDATE_PREFS option supplied, not reading any data."
print, "If you want to update the preferences file & read data, use /UPDATE_PREFS instead"
endif
;; Only update prefs option, return now.
return
endif else begin
;; Read or create preferences file
MVN_KP_CONFIG_FILE, insitu_data_dir=kp_insitu_data_directory, iuvs_data_dir=kp_iuvs_data_directory, $
update_prefs=update_prefs, insitu_only=insitu_only
endelse
;SET UP instruments struct WHICH IS USED FOR CREATING DATA STRUCTURE & CONTROLLING WHICH INSTRUMENTS DATA TO READ
if keyword_set(lpw) or keyword_set(static) or keyword_set(swia) or keyword_set(swea) or keyword_set(mag) or keyword_set(sep) or $
keyword_set(ngims) or keyword_set(iuvs_all) or keyword_set(iuvs_periapse) or keyword_set(iuvs_apoapse) or $
keyword_set(iuvs_coronaEchelleDisk) or keyword_set(iuvs_coronaEchelleLimb) or keyword_set(iuvs_coronaEchelleHigh) or keyword_set(iuvs_coronaLoresHigh) or $
keyword_set(iuvs_coronaloreslimb) or keyword_set(iuvs_coronaloresdisk) or keyword_set(iuvs_stellarocc) or keyword_set(insitu_all) then begin
;; Setup instrument struct which is used for creating data structure & controlling which instruments to read
instruments = CREATE_STRUCT('lpw', 0, 'static', 0, 'swia', 0, $
'swea', 0, 'mag', 0, 'sep', 0, $
'ngims', 0, 'periapse', 0, 'c_e_disk', 0, $
'c_e_limb', 0, 'c_e_high', 0, 'c_l_disk', 0, $
'c_l_limb', 0, 'c_l_high', 0, 'apoapse' , 0, 'stellarocc', 0)
if keyword_set(lpw) then begin
instruments.lpw = 1 & print,'Returning All LPW Instrument KP Data.'
endif
if keyword_set(static) then begin
instruments.static = 1 & print,'Returning All STATIC Instrument KP Data.'
endif
if keyword_set(swia) then begin
instruments.swia = 1 & print,'Returning All SWIA Instrument KP Data.'
endif
if keyword_set(swea) then begin
instruments.swea = 1 & print,'Returning All SWEA Instrument KP Data.'
endif
if keyword_set(mag) then begin
instruments.mag = 1 & print,'Returning All MAG Instrument KP Data.'
endif
if keyword_set(sep) then begin
instruments.sep = 1 & print,'Returning All SEP Instrument KP Data.'
endif
if keyword_set(ngims) then begin
instruments.ngims = 1 & print,'Returning All NGIMS Instrument KP Data.'
endif
if keyword_set(inbound) then begin
print,'Returning only inbound in situ data'
endif
if keyword_set(outbound) then begin
print,'Returning only outbound in situ data'
endif
if keyword_set(iuvs_periapse) then begin
instruments.periapse = 1 & print,'Returning All IUVS Instrument Periapse KP Data.'
endif
if keyword_set(iuvs_apoapse) then begin
instruments.apoapse = 1 & print,'Returning All IUVS Instrument Apoapse KP Data.'
endif
if keyword_set(iuvs_coronaEchellehigh) then begin
instruments.c_e_high = 1 & print,'Returning All IUVS Instrument Corona Echelle High Altitude KP Data.'
endif
if keyword_set(iuvs_coronaEchellelimb) then begin
instruments.c_e_limb = 1 & print,'Returning All IUVS Instrument Corona Echelle Limb KP Data.'
endif
if keyword_set(iuvs_stellarocc) then begin
instruments.stellarocc = 1 & print,'Returning All IUVS Instrument Stellar Occultation KP Data.'
endif
if keyword_set(iuvs_coronaLoreshigh) then begin
instruments.c_l_high = 1 & print,'Returning All IUVS Instrument Corona Lores High Altitude KP Data.'
endif
if keyword_set(iuvs_coronaLoreslimb) then begin
instruments.c_l_limb = 1 & print,'Returning All IUVS Instrument Corona Lores Limb KP Data.'
endif
if keyword_set(iuvs_coronaLoresdisk) then begin
instruments.c_l_disk = 1 & print,'Returning All IUVS Instrument Corona Lores Disk KP Data.'
endif
if keyword_set(iuvs_coronaechelledisk) then begin
instruments.c_e_disk = 1 & print,'Returning All IUVS Instrument Corona Echelle Disk KP Data.'
endif
if keyword_set(insitu_all) then begin
instruments.lpw = 1
instruments.static = 1
instruments.swia = 1
instruments.swea = 1
instruments.mag = 1
instruments.sep = 1
instruments.ngims = 1
print, 'Returning all INSITU Instrument KP Data.'
endif
if keyword_set(iuvs_all) then begin
instruments.periapse = 1
instruments.c_e_disk = 1
instruments.c_e_limb = 1
instruments.c_e_high = 1
instruments.c_l_disk = 1
instruments.c_l_limb = 1
instruments.c_l_high = 1
instruments.apoapse = 1
instruments.stellarocc = 1
print,'Returning All IUVS Instrument KP Data.'
endif
endif else begin
;SET ALL INSTRUMENT FLAGS TO 1 TO CREATE FULL STRUCTURE FOR ALL INSTRUMENT DATA
instruments = CREATE_STRUCT('lpw', 1, 'static', 1, 'swia', 1, $
'swea', 1, 'mag', 1, 'sep', 1, $
'ngims', 1, 'periapse', 1, 'c_e_disk', 1, $
'c_e_limb', 1, 'c_e_high', 1, 'c_l_disk', 1, $
'c_l_limb', 1, 'c_l_high', 1, 'apoapse' , 1, 'stellarocc', 1)
endelse
;SET INBOUND/OUTBOUND KEYWORDS IF NEEDED
io_flag = intarr(2)
if keyword_set(inbound) eq 1 then begin
io_flag[0] = 1
io_flag[1] = 0
endif
if keyword_set(outbound) eq 1 then begin
io_flag[0] = 0
io_flag[1] = 1
endif
if (keyword_set(inbound) eq 0) and (keyword_set(outbound) eq 0) then begin
io_flag[0] = 1
io_flag[1] = 1
endif
;; ------------------------------------------------------------------------------------ ;;
;; ----------------------- Process input time/orbit range ---------------------------- ;;
; DEFAULT RETRIEVAL PERIOD TO 1 DAY OR 1 ORBIT
if keyword_set(duration) eq 0 then begin
if size(time,/type) eq 7 then duration = 86400
if size(time,/type) eq 2 then duration = 1
endif
;IF ORBIT(s) SUPPLIED
;;============================
if size(time, /type) eq 2 then begin
;; If only one orbit supplied, add duration to first orbit to created end_orbit
if n_elements(time) eq 1 then begin
print,'Retrieving KP data for ',strtrim(string(duration),2),' orbits beginning at orbit #',strtrim(string(time),2)
begin_orbit = time[0]
end_orbit = time[0] + duration
endif else begin
begin_orbit = time[0]
end_orbit = time[1]
endelse
;; Use orbit file look up to get time strings for each orbit -- FIXME check output of this to ensure we found orbits.
MVN_KP_ORBIT_TIME, begin_orbit, end_orbit, begin_time_string, end_time_string
;; Create Jul day versions
mvn_kp_time_split_string, begin_time_string, year=yr, month=mo, day=dy, hour=hr, min=min, sec=sec, /FIX
begin_time_jul = julday(mo, dy, yr, hr, min, sec)
mvn_kp_time_split_string, end_time_string, year=yr, month=mo, day=dy, hour=hr, min=min, sec=sec, /FIX
end_time_jul = julday(mo, dy, yr, hr, min, sec)
endif
;IF TIME STRING(s) SUPPLIED
;;============================
if size(time, /type) eq 7 then begin
if n_elements(time) eq 1 then begin
; IF ONE TIME SUPPLIED USE IT AS START. DETERMINE END TIME BASED ON duration (DEFAULT 1 DAY OR USER SUPPLIED)
begin_time_string = time[0]
mvn_kp_time_split_string, begin_time_string, year=yr, month=mo, day=dy, hour=hr, min=min, sec=sec, /FIX
begin_time_jul = julday(mo, dy, yr, hr, min, sec)
;; Add seconds onto begin jul date to get end jul date
end_time_jul = begin_time_jul + (duration/86400.0D)
end_time_string = MVN_KP_TIME_CREATE_STRING(end_time_jul)
endif else begin
;IF THE USER SUPPLIES A 2-VALUE ARRAY OF TIMES, USE THESE AS TIME STRINGS - FIXME VALIDATE TIMES HERE?
begin_time_string = time[0]
end_time_string = time[1]
;; Create Jul day versions
mvn_kp_time_split_string, begin_time_string, year=yr, month=mo, day=dy, hour=hr, min=min, sec=sec, /FIX
begin_time_jul = julday(mo, dy, yr, hr, min, sec)
mvn_kp_time_split_string, end_time_string, year=yr, month=mo, day=dy, hour=hr, min=min, sec=sec, /FIX
end_time_jul = julday(mo, dy, yr, hr, min, sec)
endelse
endif
;IF LONG INTEGER TIME SUPPLIED CONVERT FROM UNIX TIME TO TIME STRING (FIXME: SECONDS?)
;;============================
if size(time,/type) eq 3 then begin
if n_elements(time) eq 1 then begin
begin_time_string = time_string(time, format=0)
end_time_string = time_string((time+duration), format=0)
endif else begin
begin_time_string = time_string(time[0],format=0)
end_time_string = time_string(time[1],format=0)
endelse
;; Create Jul day versions
mvn_kp_time_split_string, begin_time_string, year=yr, month=mo, day=dy, hour=hr, min=min, sec=sec, /FIX
begin_time_jul = julday(mo, dy, yr, hr, min, sec)
mvn_kp_time_split_string, end_time_string, year=yr, month=mo, day=dy, hour=hr, min=min, sec=sec, /FIX
end_time_jul = julday(mo, dy, yr, hr, min, sec)
endif
;; Create structs for both begin/end times containing string versions and jul days
begin_time_struct = create_struct('string', begin_time_string, 'jul', begin_time_jul)
end_time_struct = create_struct('string', end_time_string, 'jul', end_time_jul)
;; ------------------------------------------------------------------------------------ ;;
;; -------------- Find files which contain data in input time range ------------------- ;;
;; -------------- and initialize data structures for holding data --------------------- ;;
;; FIXME variable names
MVN_KP_FILE_SEARCH, begin_time_struct, end_time_struct, target_KP_filenames, kp_insitu_data_directory, iuvs_filenames, $
kp_iuvs_data_directory, save_files=save_files, text_files=text_files, insitu_only=insitu_only, download_new=download_new
;CREATE OUTPUT STRUCTURES BASED ON SEARCH PARAMETERS & INITIALIZE ARRAY OF DATA STRUTURES
MVN_KP_INSITU_STRUCT_INIT, insitu_record, instruments=instruments
kp_data_temp = replicate(insitu_record,21600L*n_elements(target_KP_filenames))
if not keyword_set(insitu_only) then begin
MVN_KP_IUVS_STRUCT_INIT, iuvs_record, instruments=instruments
iuvs_data_temp = replicate(iuvs_record, n_elements(iuvs_filenames))
endif
;; ------------------------------------------------------------------------------------ ;;
;; ----------------------- Main read loop: In situ data ---------------------------- ;;
; FIXME: These variables aren't being used?
;VARIABLES TO HOLD THE COUNT OF VARIOUS OBSERVATION TYPES (IE. HIGH VS. LOW ALTITUDE)
; high_count = 0
; low_count = 0
if target_kp_filenames[0] ne 'None' then begin
totalEntries=0L
start_index=0L
for file=0,n_elements(target_KP_filenames)-1 do begin
;UPDATE THE READ STATUS BAR
MVN_KP_LOOP_PROGRESS,file,0,n_elements(target_KP_filenames)-1,message='In-situ KP File Read Progress'
fileAndPath = kp_insitu_data_directory+target_kp_filenames[file]
MVN_KP_READ_INSITU_FILE, fileAndPath, kp_data, begin_time=begin_time_struct, end_time=end_time_struct, io_flag=io_flag, $
instruments=instruments, save_files=save_files, text_files=text_files
;; Ensure what was returned is a structure, (and not int 0 indicating no matches)
if size(kp_data, /TYPE) eq 8 then begin
kp_data_temp[start_index:(start_index+n_elements(kp_data)-1)] = kp_data
start_index += n_elements(kp_data)
totalEntries += n_elements(kp_data)
endif
endfor
;OUTPUT INSITU DATA STRUCTURE
insitu_output = kp_data_temp[0:totalEntries-1]
print,'A total of ',strtrim(n_elements(insitu_output),2),' INSITU KP data records were found that met the search criteria.'
endif else begin
printf,-2, "Warning: No Insitu files found for input timerange."
endelse
;; ------------------------------------------------------------------------------------ ;;
;; ----------------------- Main read loop: IUVS data ------------------------------- ;;
;IF ANY IUVS DATA IS REQUESTED & NOT IN INSITU ONLY MODE
if not keyword_set(insitu_only) and (instruments.periapse or instruments.c_e_disk or instruments.c_e_limb or instruments.c_e_high or $
instruments.apoapse or instruments.c_l_disk or instruments.c_l_limb or instruments.c_l_high or $
instruments.stellarocc) then begin
iuvs_index=0
if iuvs_filenames[0] ne 'None' then begin
;; Loop through each file
for file=0,n_elements(iuvs_filenames)-1 do begin
MVN_KP_LOOP_PROGRESS,file,0,n_elements(iuvs_filenames)-1,message='IUVS KP File Read Progress'
fileAndPath = kp_iuvs_data_directory+iuvs_filenames[file]
MVN_KP_READ_IUVS_FILE, fileAndPath, iuvs_record, begin_time=begin_time_struct, end_time=end_time_struct, $
instruments=instruments, save_files=save_files, text_files=text_files
;; If iuvs_record not eq -1 (Indicating some observation within time range) add to temp array
if size(iuvs_record, /type) eq 8 then begin
;; Add single iuvs_record to array of iuvs records
iuvs_data_temp[iuvs_index] = iuvs_record
iuvs_index++
endif
endfor
;OUTPUT IUVS DATA STRUCTURE IF ANY IUVS DATA IS REQUESTED
iuvs_output = iuvs_data_temp[0:iuvs_index-1]
print,'including ',strtrim(string(iuvs_index),2),' IUVS data records'
endif else begin
printf, -2, "Warning: No IUVS files found for input timerange"
endelse
endif
;TIME TO RUN ROUTINE
overall_end_time = systime(1)
print,'Your query took ', overall_end_time - overall_start_time,' seconds to complete.'
; UNSET DEBUG ENV VARIABLE
setenv, 'MVNTOOLKIT_DEBUG='
end