;+
; :Name: mvn_kp_download_files
;
; :Author: John Martin
;
;
; :Description:
; Download in situ or IUVS kp data files from the Maven SDC web service. Download
; either CDF or ASCII versions of the data files.
;
;
;
; :Keywords:
; filenames: in, optional, type=string or strarr
; Scalar or array of filename strings to download
;
; list_files: in, optional, type=boolean
; Print to standard output a list of files instead of actually downloading
;
; insitu: in, optional, type=boolean
; Search/download in situ KP data files
;
; iuvs: in, optional, type=boolean
; Search/download IUVS KP data files
;
; text_files: in, optional, type=boolean
; Search/download ASCII (.txt) versions of the KP data files
;
; cdf_files: in, optional, type=boolean
; Search/download CDF (.cdf) versions of the KP data files
;
; new_files: in, optional, type=boolean
; Only download files you don't already have saved locally
;
; start_date: in, optional, type=string
; Beginning of time range to search/download files. Format='YYYY-MM-DD'
;
; end_date: in, optional, type=string
; End of time range to search/download files. Format='YYYY-MM-DD'
;
; update_prefs: in, optional, type=boolean
; Before searching or downloading 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,
; search or download of data files 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
; downloading any data.
;
; local_dir: in, optional, type=string
; Specify a directory to download files to - this overrides what's stored in
; kp_preferences.txt
;
; 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.
;
;
; Credit to Doug Lindholm for initial version of this procedure.
;-
function mvn_kp_relative_comp, local, server
server_out = server
for i=0, n_elements(local)-1 do begin
ind = where(server_out NE local[i], count)
;; If no items are found, this means there are no new files on the server
;; to download, so return with an empty string.
if(count eq 0) then return, ''
server_out = server_out(ind)
endfor
return, server_out
end
pro mvn_kp_download_files, filenames=filenames, local_dir=local_dir, insitu=insitu, iuvs=iuvs, new_files=new_files, $
text_files=text_files, cdf_files=cdf_files, start_date=start_date, end_date=end_date, $
update_prefs=update_prefs, list_files=list_files, debug=debug, only_update_prefs=only_update_prefs
;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 & set global variables----------------------- ;;
; 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
if keyword_set(only_update_prefs) then begin
MVN_KP_CONFIG_FILE, /update_prefs
;; Warn user if other parameters supplied
if keyword_set(filenames) or keyword_set(cdf_files) or keyword_set(text_files) then begin
print, "Warning. /ONLY_UPDATE_PREFS option supplied, not querying server."
print, "If you want to update the preferences file & download data, use /UPDATE_PREFS instead"
endif
;; Only update prefs option, return now.
return
endif
;; Get SDC server specs
sdc_server_spec = mvn_kp_config(/data_retrieval)
url_path = sdc_server_spec.url_path_download ; Define the URL path for the download web service.
max_files = sdc_server_spec.max_files ; Define the maximum number of files to allow w/o an extra warning.
;; Default behavior is to download KP data
if keyword_set(insitu) then begin
data_level='l2' ;; FIXME - Currently inconcsistency between insitu/iuvs levels.
endif else if keyword_set(iuvs) then begin
data_level='kp'
endif
;; Set extension keyword based of text_file option or cdf_files
if keyword_set(text_files) then begin
extension = 'txt'
endif else if keyword_set(cdf_files) then begin
extension = 'cdf'
endif else if n_elements(filenames) le 0 then begin
message, "If not specifying filename(s) to download, must specify either /TEXT_FILES or /CDF_FILES."
endif
;; If specific filenames not specified, then user must specify insitu or iuvs
if n_elements(filenames) le 0 then begin
if keyword_set(insitu) and keyword_set(iuvs) then begin
message, "Can't request both INSITU & IUVS data in one query.
endif
if not (keyword_set(insitu) or keyword_set(iuvs)) then begin
message, "If not specifying filename(s) to download, Must specify either /INSITU keyword or /IUVS."
endif
endif
; Build query.
; Start by building an array of arguments based on inputs.
; Many values may be arrays so join with ",".
; Note that a single value will be treated as an array of one by IDL.
query_args = ["hack"] ;IDL doesn't allow empty arrays before version 8.
if keyword_set(insitu) then query_args = [query_args, "instrument=pfp"]
if keyword_set(iuvs) then query_args = [query_args, "instrument=rs"]
if n_elements(filename) gt 0 then query_args = [query_args, "file=" + strjoin(filename, ",")]
if n_elements(data_level) gt 0 then query_args = [query_args, "level=" + strjoin(data_level, ",")]
if n_elements(start_date) gt 0 then query_args = [query_args, "start_date=" + start_date]
if n_elements(end_date) gt 0 then query_args = [query_args, "end_date=" + end_date]
if n_elements(extension) gt 0 then query_args = [query_args, "file_extension=" + extension]
; Join query args with "&", drop the "hack"
if n_elements(query_args) lt 2 then query = '' $
else query = strjoin(query_args[1:*], "&")
; If local_dir not specified, check config file for insitu & iuvs dir.
if (n_elements(local_dir) eq 0) and ( (not keyword_set(list_files)) or keyword_set(new_files) or keyword_set(update_prefs)) then begin
; Check config file for directories to data
mvn_kp_config_file, insitu_data_dir=insitu_data_dir, iuvs_data_dir=iuvs_data_dir, $
update_prefs=update_prefs
if keyword_set(insitu) then begin
local_dir = insitu_data_dir
endif else if keyword_set(iuvs) then begin
local_dir = iuvs_data_dir
endif else begin
message, "If not specifying local_dir option, must specify /insitu or /iuvs"
endelse
endif
;; ------------------------------------------------------------------------------------ ;;
;; ------------------------------ Main logic ------------------------------------------ ;;
; Get the IDLnetURL singleton. May prompt for password.
connection = mvn_kp_get_connection()
; If no input filename(s), then query the server to find available files for download
if not keyword_set (filenames) then begin
; Get the list of files. Names will be full path starting at "mms"? #FIXME - Not MMS
filenames = mvn_kp_get_filenames(query=query)
; Warn if no files. Error code or empty.
if (size(filenames, /type) eq 3 || n_elements(filenames) eq 0) then begin
printf, -2, "WARN: No files found for the query: " + query
return
endif
endif
; If user supplied NEW_FILES option, determine which files they have locally
if keyword_set (new_files) then begin
;; Get filename convetion information from config
insitu_file_spec = mvn_kp_config(/insitu_file_spec)
iuvs_file_spec = mvn_kp_config(/iuvs_file_spec)
insitu_pattern = insitu_file_spec.pattern
iuvs_pattern = iuvs_file_spec.pattern
;; Append appropriate extension
if keyword_set(text_files) then insitu_pattern += '.txt' else insitu_pattern += '.cdf'
if keyword_set(text_files) then iuvs_pattern += '.txt' else iuvs_pattern += '.cdf'
; Get list of all files currently downloaded
if keyword_set(insitu) then begin
local_files = file_basename(file_search(local_dir+path_sep()+insitu_pattern))
endif
if keyword_set(iuvs) then begin
local_files = file_basename(file_search(local_dir+path_sep()+iuvs_pattern))
endif
; Get list of files on server (within a time span if entereted), that are not on local machine
filenames = mvn_kp_relative_comp(local_files, filenames)
endif
;; If LIST_FILES option, then just print out the file list (and save to list_files)
; Don't actually download
if keyword_set(list_files) then begin
list_files=filenames
print, "LIST_FILES option given, printing files instead of downloading"
print, "Files that would be downloaded: "
print, filenames
return
endif
; Get the number of files that would be downloaded.
nfiles = n_elements(filenames)
;; Hanlde the stupid case where IDL has an emptry string and n_elements will return 1.
;; Return from here if no files to download
if (nfiles eq 1) and (strlen(filenames[0]) eq 0) then begin
if keyword_set(insitu) then filetype = 'in situ' else filetype = 'IUVS'
if keyword_set(cdf_files) then extension = 'CDF' else extension = 'text'
print, "No new "+filetype+" "+extension+" files on server to download."
return
endif
; Prompt user to ensure they want to download nfiles amount of files
while(1) do begin
response = ''
print, "Your request will download a total of: " +string(nfiles) +" files."
if (nfiles gt max_files) then print, "NOTE - This is a large number of files and may take a long time to download"
print, "Would you like to proceed with this download:"
read, response, PROMPT='(y/n) >'
if (strlowcase(strmid(response,0,1)) eq 'y') then break
if (strlowcase(strmid(response,0,1)) eq 'n') then begin
print, "Canceled download. Returning..."
return
endif else print, "Invalid input. Please answer with yes or no."
endwhile
print, "Starting download..."
; Download files one at a time.
nerrs = 0 ;count number of errors
for i = 0, nfiles-1 do begin
;TODO: flat or hierarchy? assume flat for now
file = file_basename(filenames[i]) ;just the file name, no path
local_file = local_dir + path_sep() + file ;all in one directory (i.e. flat)
file_query = "file=" + file
result = mvn_kp_execute_neturl_query(connection, url_path, file_query, filename=local_file)
; Updated the download progress bar
MVN_KP_LOOP_PROGRESS,i,0,nfiles-1,message='KP Download Progress'
;count failures so we can report a 'partial' status
;Presumably, mvn_kp_execute_neturl_query will print specific error messages.
if size(result, /type) eq 3 then nerrs = nerrs + 1
endfor
; Print error message if any of the downloads failed.
if nerrs gt 0 then begin
msg = "WARN: " + strtrim(nerrs,2) + " out of " + strtrim(nfiles,2) + " file downloads failed."
printf, -2, msg
return
endif
; UNSET DEBUG ENV VARIABLE
setenv, 'MVNTOOLKIT_DEBUG='
end