;
; NOSA HEADER START
;
; The contents of this file are subject to the terms of the NASA Open
; Source Agreement (NOSA), Version 1.3 only (the "Agreement"). You may
; not use this file except in compliance with the Agreement.
;
; You can obtain a copy of the agreement at
; docs/NASA_Open_Source_Agreement_1.3.txt
; or
; https://cdaweb.gsfc.nasa.gov/WebServices/NASA_Open_Source_Agreement_1.3.txt.
;
; See the Agreement for the specific language governing permissions
; and limitations under the Agreement.
;
; When distributing Covered Code, include this NOSA HEADER in each
; file and include the Agreement file at
; docs/NASA_Open_Source_Agreement_1.3.txt. If applicable, add the
; following below this NOSA HEADER, with the fields enclosed by
; brackets "[]" replaced with your own identifying information:
; Portions Copyright [yyyy] [name of copyright owner]
;
; NOSA HEADER END
;
; Copyright (c) 2010-2017 United States Government as represented by the
; National Aeronautics and Space Administration. No copyright is claimed
; in the United States under Title 17, U.S.Code. All Other Rights
; Reserved.
;
;
;+
; This program provides a GUI for choosing datasets from
; CDAWeb.
;
; @copyright Copyright (c) 2010-2017 United States Government as
; represented by the National Aeronautics and Space Administration.
; No copyright is claimed in the United States under Title 17,
; U.S.Code. All Other Rights Reserved.
;
; @author B. Harris
;-
pro twinscolorbar
end
;+
; Selects a dataview.
;
; @param tlb {in} {type=int}
; widget id of top level base.
; @param dvList {in} {type=int}
; widget id of dataview list widget.
; @param dvIndex {in} {type=int}
; index of dataview to select
;-
pro spdfSelectDataview, $
tlb, dvList, dvIndex
compile_opt idl2
widget_control, dvList, set_combobox_select=dvIndex
widget_control, dvList, $
send_event={id:dvList, top:tlb, handler:dvList, index:dvIndex}
end
;+
; Responds to a "dataview selected" event.
;
; @param event {in} {type=widget event}
; widget_list event.
;-
pro spdfDataviewSelected, $
event
compile_opt idl2
widget_control, event.top, get_uvalue=state
*state.selectedDataview = state.dataviews[event.index]->getId()
if *state.selectedDataview eq 'cnofs' then begin
reply = dialog_message( $
['The required authentication for this dataview is not yet implemented.', 'Please choose a different dataview.'], $
title='Dataview Selection', /center, /information)
spdfSelectDataview, event.top, state.dataviewList, 0
return
endif
widget_control, /hourglass
observatoryGroups = state.cdas->getObservatoryGroups($
dataview = *state.selectedDataview, $
authenticator=state.authenticator, $
httpErrorReporter=state.errorDialog)
*state.observatoryGroups = strarr(n_elements(observatoryGroups))
for i = 0, n_elements(observatoryGroups) - 1 do begin
(*state.observatoryGroups)[i] = observatoryGroups[i]->getName()
endfor
obj_destroy, observatoryGroups
widget_control, state.observatoryGroupList, $
set_value=*state.observatoryGroups
instrumentTypes = state.cdas->getInstrumentTypes($
dataview = *state.selectedDataview, $
authenticator=state.authenticator, $
httpErrorReporter=state.errorDialog)
*state.instrumentTypes = strarr(n_elements(instrumentTypes))
for i = 0, n_elements(instrumentTypes) - 1 do begin
(*state.instrumentTypes)[i] = instrumentTypes[i]->getName()
endfor
obj_destroy, instrumentTypes
widget_control, state.instrumentTypeList, $
set_value=*state.instrumentTypes
end
;+
; Finds the specified dataset description within the given array of
; descriptions.
;
; @private
;
; @param descriptions {in} {type=SpdfDatasetDescription}
; Array of descriptions to search (for example,
; state.datasets).
; @param id {in} {type=string}
; Dataset identifier.
; @returns Dataset description from descriptions with the specified id
; or a NULL object reference if the description was not
; found.
;-
function spdfGetDatasetDescription, $
descriptions, id
compile_opt idl2
for i = 0, n_elements(descriptions) - 1 do begin
if descriptions[i]->getId() eq id then return, descriptions[i]
endfor
return, obj_new()
end
;+
; Responds to a dataset tree event.
;
; @param event {in} {type=widget event}
; event triggering the execution of this procedure
;-
pro spdfDatasetTreeEvent, $
event
compile_opt idl2
;
; Note: In general, the selected item's tree index cannot be used
; to locate the corresponding SpdfDatasetDescription in
; state.datasets because "pointer datasets" are not in the tree but
; are in state.datasets and the tree may be sorted differently.
;
widget_control, event.top, get_uvalue=state
selectedItem = widget_info(state.datasetTree, /tree_select)
if selectedItem[0] eq -1 then return
widget_control, selectedItem[0], get_uvalue=selectedValue
; Only dataset tree values are of type 7 (string) so ignore
; all others
if size(selectedValue, /type) ne 7 then return
*state.selectedDataset = $
spdfGetDatasetDescription(*state.datasets, selectedValue)
if tag_names(event, /structure_name) eq 'WIDGET_CONTEXT' then begin
widget_displaycontextmenu, event.ID, event.X, event.Y, $
state.datasetContextMenu
end
end
;+
; Responds to a request to view a dataset's notes.
;
; @param event {in} {type=widget event}
; event triggering the execution of this procedure
;-
pro spdfViewNotes, $
event
compile_opt idl2
widget_control, event.top, get_uvalue=state
selectedDataset = *state.selectedDataset
fullNotesUrl = selectedDataset->getNotes()
urlComponents = $
strsplit(fullNotesUrl, '#', count=componentCount, /extract)
notesUrl = urlComponents[0]
if componentCount eq 2 then begin
notesAnchor = urlComponents[1]
endif
pathComponents = $
strsplit(notesUrl, '/', count=componentCount, /extract)
filename = pathComponents[componentCount - 1]
proxy_authentication = 0
proxy_hostname = ''
proxy_password = ''
proxy_port = ''
proxy_username = ''
http_proxy = getenv('HTTP_PROXY')
if strlen(http_proxy) gt 0 then begin
proxyComponents = parse_url(http_proxy)
proxy_hostname = proxyComponents.hostname
proxy_password = proxyComponents.password
proxy_port = proxyComponents.port
proxy_username = proxyComponents.username
if strlen(proxy_username) gt 0 then begin
proxy_authentication = 3
endif
endif
notes = obj_new('IDLnetURL', $
proxy_authentication = proxy_authentication, $
proxy_hostname = proxy_hostname, $
proxy_port = proxy_port, $
proxy_username = proxy_username, $
proxy_password = proxy_password, $
ssl_verify_host=0, ssl_verify_peer=0)
localNotes = notes->get(filename=filename, url=notesUrl)
; save filename so it can be deleted when this program Exits
if n_elements(notesAnchor) ne 0 then begin
online_help, notesAnchor, book=localNotes, /full_path
endif else begin
online_help, book=localNotes, /full_path
endelse
end
;+
; Responds to an inventory window close event.
;
; @param event {in} {type=widget_button}
; event triggering the execution of this procedure.
;-
pro spdfCloseInventory, $
event
compile_opt idl2
widget_control, event.top, /destroy
end
;+
; Responds to a request to view a dataset's inventory.
;
; @param event {in} {type=widget event}
; event triggering the execution of this procedure
;-
pro spdfViewInventory, $
event
widget_control, event.top, get_uvalue=state
selectedDataset = *state.selectedDataset
inventory = state.cdas->getInventory( $
dataview = *state.selectedDataview, $
selectedDataset->getId(), $
authenticator=state.authenticator, $
httpErrorReporter=state.errorDialog)
intervals = inventory->getTimeIntervals()
intervalStrings = strarr(2, n_elements(intervals))
for i = 0, n_elements(intervals) - 1 do begin
intervalStrings[0, i] = intervals[i]->getCdawebStart()
intervalStrings[1, i] = intervals[i]->getCdawebStop()
endfor
title = inventory->getId() + ' Data Inventory'
inventoryWin = $
widget_base(title=title, /column, group_leader=event.top)
label = widget_label(inventoryWin, value=title);
table = widget_table(inventoryWin, $
column_labels = ['Start Time', 'Stop Time'], $
/no_row_headers, value=intervalStrings)
closeButton = widget_button(inventoryWin, /align_left, $
event_pro='spdfCloseInventory', $
value='Close', tooltip='Close inventory window')
widget_control, inventoryWin, /realize
xmanager, 'SpdfViewInventory', inventoryWin, /no_block
obj_destroy, intervals
obj_destroy, inventory
end
;+
; Responds to a request to set a default time value.
;
; @param event {in} {type=widget event}
; event triggering the execution of this procedure
;-
pro spdfDefaultTime, $
event
compile_opt idl2
widget_control, event.top, get_uvalue=state
selectedItem = widget_info(state.datasetTree, /tree_select)
if selectedItem[0] eq -1 then begin
reply = dialog_message( $
'Please choose a Dataset/Variable', $
title='Missing Dataset Selection', /center, /error)
return
endif
if ~widget_info(selectedItem[0], /tree_folder) then begin
datasetWidget = widget_info(selectedItem[0], /parent)
endif else begin
datasetWidget = selectedItem[0]
endelse
widget_control, datasetWidget, get_uvalue=datasetId
selectedDataset = $
spdfGetDatasetDescription(*state.datasets, datasetId)
timeInterval = selectedDataset->getTimeInterval()
timeInterval->setStart, timeInterval->getStop() - 1
widget_control, state.startTime, $
set_value = timeInterval->getCdawebStart()
widget_control, state.stopTime, $
set_value = timeInterval->getCdawebStop()
end
;+
; Responds to an event by doing nothing (ignoring it).
;
; @param event {in} {type=widget event}
; event triggering the execution of this procedure.
;-
pro spdfIgnoreSelected, $
event
compile_opt idl2
end
;+
; Responds to a "save data" button event.
;
; @param event {in} {type=widget event}
; event triggering the execution of this function.
; @returns 0
;-
function spdfSaveDataButton, $
event
compile_opt idl2
widget_control, event.top, get_uvalue=state
*state.saveData = event.select
return, 0
end
;+
; Responds to an event that initiates a search for datasets that
; satisfies the users previous selections.
;
; @param event {in} {type=widget_button}
; event triggering the execution of this procedure.
;-
pro spdfFindDatasets, $
event
compile_opt idl2
widget_control, event.top, get_uvalue=state
selectedObservatoryGroups = $
widget_info(state.observatoryGroupList, /list_select)
if selectedObservatoryGroups[0] eq -1 then begin
reply = dialog_message( $
'Please choose one or more Mission Groups', $
title='Mission Selection', /center, /error)
return
endif
observatoryGroups = ptr_new()
if selectedObservatoryGroups[0] ne -1 then begin
observatoryGroups = strarr(n_elements(selectedObservatoryGroups))
for i = 0, n_elements(observatoryGroups) - 1 do begin
observatoryGroups[i] = $
(*state.observatoryGroups)[selectedObservatoryGroups[i]]
endfor
endif
selectedInstrumentTypes = $
widget_info(state.instrumentTypeList, /list_select)
if selectedInstrumentTypes[0] eq -1 then begin
reply = dialog_message( $
'Please choose one or more Instrument Types', $
title='Mission Selection', /center, /error)
return
endif
instrumentTypes = ptr_new()
if selectedInstrumentTypes[0] ne -1 then begin
instrumentTypes = strarr(n_elements(selectedInstrumentTypes))
for i = 0, n_elements(instrumentTypes) - 1 do begin
instrumentTypes[i] = $
(*state.instrumentTypes)[selectedInstrumentTypes[i]]
endfor
endif
oldRootNode = widget_info(state.datasetTree, /child)
if oldRootNode ne 0 then widget_control, oldRootNode, /destroy
if n_elements(*state.datasets) then begin
*state.selectedDataset = obj_new()
obj_destroy, *state.datasets
endif
rootNode = widget_tree(state.datasetTree, value='Datasets', $
event_pro='spdfIgnoreSelected', $
/folder, /expanded)
widget_control, /hourglass
datasets = state.cdas->getDatasets( $
dataview = *state.selectedDataview, $
observatoryGroups = observatoryGroups, $
instrumentTypes = instrumentTypes, $
authenticator=state.authenticator, $
httpErrorReporter=state.errorDialog)
if ~obj_valid(datasets[0]) then begin
reply = dialog_message( $
['No datasets were found matching the selection criteria.',$
'Please change the selection criteria.'], $
title='Datasets Not Found', /center, /information)
obj_destroy, datasets
return
endif
*state.datasets = datasets
datasetIds = strarr(n_elements(datasets))
for i = 0, n_elements(datasets) - 1 do begin
datasetIds[i] = datasets[i]->getId()
endfor
sortedDatasetIndexes = sort(datasetIds)
for i = 0, n_elements(datasets) - 1 do begin
datasetId = datasets[sortedDatasetIndexes[i]]->getId()
datasetLabel = datasets[sortedDatasetIndexes[i]]->getLabel()
datasetTimeRange = datasets[sortedDatasetIndexes[i]]->getTimeInterval()
datasetTitle = datasetId + ': ' + $
datasetTimeRange->getCdawebStart() + ' - ' + $
datasetTimeRange->getCdawebStop() + ': ' + datasetLabel
variables = state.cdas->getVariables( $
datasetId, $
dataview = *state.selectedDataview, $
authenticator=state.authenticator, $
httpErrorReporter=state.errorDialog)
if obj_valid(variables[0]) then begin
; Not merely a pointer dataset (we do not show pointer
; datasets in the tree).
;
; Putting a uvalue of datasets[i] in the tree widget
; makes destroying the widget more difficult
;
datasetNode = widget_tree(rootNode, value=datasetTitle, $
; /folder, /expanded, uvalue=datasetId, $
/folder, uvalue=datasetId, $
event_pro='spdfDatasetTreeEvent')
for j = 0, n_elements(variables) - 1 do begin
varName = variables[j]->getName()
varDescription = variables[j]->getLongDescription()
if varDescription eq '' then begin
varDescription = variables[j]->getShortDescription()
endif
varTitle = varName + ': ' + varDescription
varNode = widget_tree(datasetNode, value=varTitle, $
event_pro='spdfIgnoreSelected', $
uvalue={datasetId:datasetId, varName:varName})
endfor
endif
obj_destroy, variables
endfor
end
;+
; Determines if the given string is a valid date/time value.
;
; @param value {in} {type=string}
; value to be tested.
; @returns true if the given string is a valid date/time value.
; Otherwise false.
;-
function spdfIsValidDate, $
value
compile_opt idl2
return, stregex(value, $
'[12][0-9]{3}[-/][01][0-9][-/][0-3][0-9]([ T][0-2][0-9]:[0-5][0-9]:[0-5][0-9])?', $
/boolean)
end
;+
; Gets the dataset and variable selection values.
;
; @param datasetTree {in} {type=int}
; id of dataset tree widget.
; @param selectedDatasetId {out} {type=string}
; id of selected dataset.
; @param selectedVarNames {out} {type=strarr}
; names of selected variables.
; @returns 1 if a valid selections was made. 0 if the selection
; was invalid.
;-
function spdfGetDatasetSelection, $
datasetTree, selectedDatasetId, selectedVarNames
compile_opt idl2
selectedItems = widget_info(datasetTree, /tree_select)
if selectedItems[0] eq -1 then begin
reply = dialog_message( $
'Please choose one or more Variables within a single Dataset', $
title='Dataset Variable Selection', /center, /error)
return, 0
endif
datasetsSelected = 0
varsSelected = 0
selectedDatasetId = ''
; first count the number of selected datasets and variables
for i = 0, n_elements(selectedItems) - 1 do begin
if ~widget_info(selectedItems[i], /tree_folder) then begin
widget_control, selectedItems[i], $
get_uvalue=selectedDataset
if selectedDataset.datasetId ne selectedDatasetId then begin
datasetsSelected++
selectedDatasetId = selectedDataset.datasetId
varsSelected = 0
endif
varsSelected++
endif
endfor
if datasetsSelected eq 1 then begin
selectedVarNames = strarr(varsSelected)
selectedVarIndex = 0
; now go back and get the selected variable names
for i = 0, n_elements(selectedItems) - 1 do begin
if ~widget_info(selectedItems[i], /tree_folder) then begin
widget_control, selectedItems[i], $
get_uvalue=selectedDataset
selectedVarNames[selectedVarIndex] = $
selectedDataset.varName
selectedVarIndex++
endif
endfor
endif else begin
reply = dialog_message( $
'Please choose one or more Variables within a single Dataset', $
title='Dataset Variable Selection', /center, /error)
return, 0
endelse
return, 1
end
;+
; Gets the specified time interval.
;
; @param startTimeWidget {in} {type=int}
; id of start time widget.
; @param stopTimeWidget {in} {type=int}
; id of stop time widget.
; @returns specifed time interval or null object reference if an
; invalid value was specified.
;-
function spdfGetSpecifiedTime, $
startTimeWidget, stopTimeWidget
compile_opt idl2
widget_control, startTimeWidget, get_value=startTime
if ~spdfIsValidDate(startTime) then begin
reply = dialog_message( $
['The Start Time must be set to a valid value', $
'YYYY/MM/DD[ HH:MM:SS]'], $
title='Invalid Date', /center, /error)
return, obj_new()
endif
widget_control, stopTimeWidget, get_value=stopTime
if ~spdfIsValidDate(stopTime) then begin
reply = dialog_message( $
['The Stop Time must be set to a valid value', $
'YYYY/MM/DD[ HH:MM:SS]'], $
title='Invalid Date', /center, /error)
return, obj_new()
endif
timeInterval = obj_new('SpdfTimeInterval', startTime, stopTime)
if ~timeInterval->isStartLessThanStop() then begin
reply = dialog_message( $
'Start Time must be less than Stop Time value', $
title='Invalid Time Interval', /center, /error)
obj_destroy, timeInterval
return, obj_new()
endif
return, timeInterval
end
;+
; Creates IDL statements to read the specified data into an IDL
; environment.
;
; @param state {in} {type=struct}
; widget program's state.
; @param timeInterval {in} {type=SpdfTimeInterval}
; time range of data to get. If this is not a valid
; object reference, then the generated IDL statement
; contains the variable names t_init and t_final instead
; of actual time values.
; @param datasetId {in} {type=string}
; dataset identifier.
; @param varNames {in} {type=strarr}
; names of variables containing the desired data.
;-
pro spdfGetCdawebDataCmd, $
state, timeInterval, datasetId, varNames
compile_opt idl2
widget_control, state.dataVarName, get_value=dataVarName
datasetCmdTxt = "'" + datasetId + "'"
varCmdTxt = "['" + varNames[0] + "'"
for i = 1, n_elements(varNames) - 1 do begin
varCmdTxt = varCmdTxt + ", '" + varNames[i] + "'"
endfor
varCmdTxt = varCmdTxt + "]"
if obj_valid(timeInterval) then begin
timeCmdTxt = "['" + timeInterval->getIso8601Start() + $
"', '" + timeInterval->getIso8601Stop() + "']"
endif else begin
timeCmdTxt = "[t_init, t_final]"
endelse
print, dataVarName, ' = spdfgetdata(', datasetCmdTxt, ', ', $
varCmdTxt, ', ', timeCmdTxt, ')'
reply = dialog_message( $
['The specified data can be read into the IDL environment by', $
'executing the IDL statements that were printed on the ', $
'IDL console.'], $
title='Get Data Operation', /center, /information)
end
; Eliminated the following when everyone is using CDF 3.5's better version.
;
function spdfCdfEpoch2Julday, $
epoch
compile_opt idl2
julday = dblarr(n_elements(epoch), /nozero)
for i = 0, n_elements(epoch) - 1 do begin
cdf_epoch, epoch[i], /breakdown_epoch, $
year, month, day, hour, minute, second, millisecond
secondMillisecond = float(second) + float(millisecond) / 1000.0
julday[i] = julday (month, day, year, hour, minute, secondMillisecond)
endfor
return, julday
end
;+
; Executes the the operation to retrieve the specified data into this
; IDL environment.
;
; @param state {in} {type=struct}
; widget program's state.
; @param timeInterval {in} {type=SpdfTimeInterval}
; time range of data to get.
; @param datasetId {in} {type=string}
; dataset identifier.
; @param varNames {in} {type=strarr}
; names of variables containing the desired data.
;-
pro spdfGetCdawebDataExec, $
state, timeInterval, datasetId, varNames
compile_opt idl2
widget_control, state.dataVarName, get_value=dataVarName
if dataVarName eq '' then begin
reply = dialog_message( $
'A name for the result variable must be set.', $
title='Missing Variable Name', /center, /error)
return
endif
widget_control, /hourglass
dataResults = $
state.cdas->getCdfData($
timeInterval, datasetId, varNames, $
dataview=*state.selectedDataview, $
authenticator=state.authenticator, $
httpErrorReporter=state.errorDialog)
fileDescriptions = dataResults->getFileDescriptions()
if obj_valid(fileDescriptions) and $
n_elements(fileDescriptions) gt 0 then begin
localCdfNames = strarr(n_elements(fileDescriptions))
for i = 0, n_elements(fileDescriptions) - 1 do begin
localCdfNames[i] = fileDescriptions[i]->getFile()
endfor
; make a copy of localCdfNames that read_mycdf can alter
localCdfNames2 = localCdfNames
cdfData = read_mycdf(varNames, localCdfNames2)
(scope_varFetch(dataVarName, /enter, level=1)) = $
hsave_struct(cdfData, /nosave)
resultMsgLines = n_elements(varNames) + 1
if *state.saveData then begin
resultMsgLines += n_elements(localCdfNames) + 1
endif
resultMsg = strarr(resultMsgLines)
resultMsg[0] = $
'The selected data is now available in'
for i = 0, n_elements(varNames) - 1 do begin
resultMsg[1 + i] = $
' ' + dataVarName + '.' + varNames[i] + '.dat'
endfor
if *state.saveData then begin
resultMsgIndex = n_elements(varNames)
resultMsg[resultMsgIndex++] = $
'Also, the downloaded data has been saved in'
for i = 0, n_elements(localCdfNames) - 1 do begin
resultMsg[resultMsgIndex + i] = $
' ' + localCdfNames[i]
endfor
endif else begin
file_delete, localCdfNames
endelse
endif else begin
resultMsg = 'No data found with the specified parameters.'
endelse
obj_destroy, fileDescriptions
obj_destroy, dataResults
reply = dialog_message(resultMsg, $
title='Get Data Operation', /center, /information)
end
;+
; Responds to an event requesting the retrieval of the data
; specified by the users previous selections.
;
; @param event {in} {type=widget_button}
; event triggering the execution of this procedure.
;-
pro spdfGetCdawebData, $
event
compile_opt idl2
widget_control, event.top, get_uvalue=state
if spdfGetDatasetSelection(state.datasetTree, $
selectedDatasetId, selectedVarNames) ne 1 then return
timeInterval = spdfGetSpecifiedTime(state.startTime, state.stopTime)
if ~obj_valid(timeInterval) then return
spdfGetCdawebDataExec, $
state, timeInterval, selectedDatasetId, selectedVarNames
obj_destroy, timeInterval
end
;+
; Responds to an event requesting the IDL code to retrieve the data
; specified by the users previous selections.
;
; @param event {in} {type=widget_button}
; event triggering the execution of this procedure.
;-
pro spdfGetCdawebDataIdl, $
event
compile_opt idl2
widget_control, event.top, get_uvalue=state
if spdfGetDatasetSelection(state.datasetTree, $
selectedDatasetId, selectedVarNames) ne 1 then return
widget_control, state.startTime, get_value=startTime
widget_control, state.stopTime, get_value=stopTime
if startTime eq '' and stopTime eq '' then begin
timeInterval = obj_new()
endif else begin
timeInterval = $
spdfGetSpecifiedTime(state.startTime, state.stopTime)
if ~obj_valid(timeInterval) then return
endelse
spdfGetCdawebDataCmd, $
state, timeInterval, selectedDatasetId, selectedVarNames
obj_destroy, timeInterval
end
;+
; Responds to an event requesting that data be read from a local
; file.
;
; @param event {in} {type=widget_button}
; event triggering the execution of this procedure.
;-
pro spdfReadLocalData, $
event
compile_opt idl2
widget_control, event.top, get_uvalue=state
widget_control, state.dataVarName, get_value=dataVarName
files = dialog_pickfile(default_extension='cdf', $
filter=['*.cdf'], /fix_filter, $
/multiple_files, /must_exist, /read)
widget_control, /hourglass
if files ne '' then begin
cdfData = read_mycdf(varNames, files, all=1)
(scope_varFetch(dataVarName, /enter, level=1)) = $
hsave_struct(cdfData, /nosave)
reply = dialog_message($
'Data from the selected file(s) is now available in ' $
+ dataVarName + '.dat', $
title='Read Data Operation', /center, /information)
endif
end
;+
; Responds to an event requesting the CDAWlib's plot of the retrieved
; data specified by the users previous selections.
;
; @param event {in} {type=widget_button}
; event triggering the execution of this procedure.
;-
pro spdfGetCdawebPlot, $
event
compile_opt idl2
widget_control, event.top, get_uvalue=state
widget_control, state.dataVarName, get_value=dataVarName
if n_elements((scope_varFetch(dataVarName, /enter, level=1))) then begin
; make a copy of the data for plotmaster to destroy
copyOfData = scope_varFetch(dataVarName, level=1)
s = plotmaster(copyOfData, xsize=600, /AUTO, /CDAWEB, /SMOOTH, /SLOW)
endif else begin
reply = dialog_message( $
'Data must be retrieved before plotting it', $
title='Get Plot Operation', /center, /error)
endelse
end
;+
; Responds to an event requesting the CDAWlib's listing of the retrieved
; data specified by the users previous selections.
;
; @param event {in} {type=widget_button}
; event triggering the execution of this procedure.
;-
pro spdfCreateCdawebListing, $
event
compile_opt idl2
widget_control, event.top, get_uvalue=state
widget_control, state.dataVarName, get_value=dataVarName
if n_elements((scope_varFetch(dataVarName, /enter, level=1))) then begin
filename = dialog_pickfile(default_extension='txt', $
filter=['*.txt', '*.asci'], $
/overwrite_prompt, /write)
if filename ne '' then begin
; make a copy of the data for list_mystruct to destroy
copyOfData = scope_varFetch(dataVarName, level=1)
listing = list_mystruct(copyOfData, filename=filename[0])
xdisplayfile, filename[0], group=event.top
endif
endif else begin
reply = dialog_message( $
'Data must be read before listing it', $
title='Get Plot Operation', /center, /error)
endelse
end
;+
; Responds to an event that initiates a termination of this program.
;
; @param event {in} {type=widget_button}
; event triggering the execution of this procedure.
;-
pro spdfExit, $
event
compile_opt idl2
widget_control, event.top, get_uvalue=state
obj_destroy, state.errorDialog
obj_destroy, state.authenticator
obj_destroy, state.cdas
obj_destroy, state.dataviews
ptr_free, state.selectedDataview
ptr_free, state.observatoryGroups
ptr_free, state.instrumentTypes
if n_elements(*state.datasets) then obj_destroy, *state.datasets
ptr_free, state.datasets
ptr_free, state.selectedDataset
ptr_free, state.saveData
; file_delete Notes?.html files
heap_gc
widget_control, event.top, /destroy
end
;+
; Display information about this software.
;
; @param event {in} {type=widget_button}
; event triggering the execution of this procedure.
;-
pro spdfAbout, $
event
compile_opt idl2
widget_control, event.top, get_uvalue=state
reply = dialog_message([ $
'NASA/Goddard Space Flight Center (GSFC)',$
'Space Physics Data Facility (SPDF)', $
'https://spdf.gsfc.nasa.gov/', $
'', $
'Current CDAWlib version: ' + version(), $
'Current SpdfCdas version: ' + state.cdas->getVersion()], $
title='About', /center, /information)
end
;+
; Gets all dataview descriptions.
;
; @private
;
; @param cdas {in} {required} {type=SpdfCdas}
; the Coordinated Data Analysis System.
; @returns objarr containing SpdfDataviewDescription objects for all
; cdaweb dataviews.
;-
function spdfGetDataviews, $
cdas
compile_opt idl2
if ~(cdas->isUpToDate()) then begin
reply = dialog_message([ $
'Current CDAWlib version: ' + version(), $
'Current SpdfCdas version: ' + cdas->getVersion(), $
'Available SpdfCdas version: ' + cdas->getCurrentVersion(), $
'There is a newer version of the SpdfCdas library available.'], $
title='Version Warning', /center, /information)
endif
dataviews = cdas->getDataviews()
extraDataviewIds = getenv('SPDF_EXTRA_DATAVIEWS')
if strlen(extraDataviewIds) eq 0 then begin
return, dataviews
endif
extraDataviewIds = strsplit(extraDataviewIds, ':', /extract)
numExtraDataviews = 0
for i = 0, n_elements(extraDataviewIds) - 1 do begin
datasets = cdas->getDatasets(dataview = extraDataviewIds[i])
if n_elements(datasets) eq 1 && $
~obj_valid(datasets[0]) then begin
print, extraDataviewIds[i], $
' does not appear to be a valid dataview.', $
' It will be ignored.'
extraDataviewIds[i] = ''
endif else begin
numExtraDataviews = numExtraDataviews + 1
endelse
endfor
if numExtraDataviews gt 0 then begin
expandedDataviews = $
objarr(n_elements(dataviews) + numExtraDataviews, /nozero)
for i = 0, n_elements(dataviews) - 1 do begin
expandedDataviews[i] = dataviews[i]
endfor
endpointAddress = dataviews[0]->getEndpointAddress()
endpointAddress = $
strsplit(endpointAddress, dataviews[0]->getId(), $
/regex, /extract)
j = 0
for i = n_elements(dataviews), $
n_elements(expandedDataviews) - 1 do begin
while extraDataviewIds[j] eq '' do j = j + 1
expandedDataviews[i] = $
obj_new('SpdfDataviewDescription', $
extraDataviewIds[j], endpointAddress, $
extraDataviewIds[j], '', '', 1b, '', 0b)
j = j + 1
endfor
return, expandedDataviews
endif
return, dataviews
end
;+
; Provides a GUI for choosing and retrieving data from
; CDAWeb.
;
; If access to the Internet is through an HTTP proxy, the caller
; should ensure that the HTTP_PROXY environment is correctly set
; before this procedure is called. The HTTP_PROXY value should be of
; the form
; http://username:password@hostname:port/.
;
; @keyword endpoint {in} {optional} {type=string}
; {default=SpdfCdas->getDefaultEndpoint()}
; URL of CDAS web service.
; @keyword GROUP_LEADER {in} {optional} {type=int}
; The widget ID of the group leader for this window. If
; no value is provided, the resulting window will not
; belong to a group and will be non-blocking.
;-
pro spdfCdawebChooser, $
endpoint = endpoint, $
GROUP_LEADER = groupLeaderWidgetId
compile_opt idl2
cd, current=cwd
if ~file_test(cwd, /write) then begin
print, 'Error: The current working directory (', $
cwd, ') is not writable.'
print, 'Downloaded files are saved in the current working directory.'
print, 'Use the IDL CD procedure to change the current working'
print, 'directory to one that is writable and then re-run'
print, 'SpdfCdawebChooser.'
return
endif
; This is suppose to help with getting windows placed better in a
; multi-monitor environment but it doesn't seem to for an
; "extended desktop".
; monitorInfo = obj_new('IDLsysMonitorInfo')
if keyword_set(groupLeaderWidgetId) then begin
tlb = widget_base(title='CDAWeb Data Chooser', /column, $
GROUP_LEADER=groupLeaderWidgetId)
defaultSaveCdfOption = 1
endif else begin
tlb = widget_base(title='CDAWeb Data Chooser', /column)
defaultSaveCdfOption = 0
endelse
cdas = $
obj_new('SpdfCdas', $
endpoint=endpoint, $
userAgent='CdawebChooser')
dataviews = spdfGetDataviews(cdas)
if ~obj_valid(dataviews[0]) then begin
reply = dialog_message( $
['Could not connect to CDAWeb.', $
'Please check Internet connectivity to ', $
'https://cdaweb.gsfc.nasa.gov/.'], $
title='Network Error', /center, /error)
return
endif
initialDvSelection = 0
dvTitles = strarr(n_elements(dataviews))
for i = 0, n_elements(dataviews) - 1 do begin
dvTitles[i] = dataviews[i]->getTitle()
if dataviews[i]->getId() eq 'sp_phys' then begin
initialDvSelection = i
endif
endfor
;
; Dataview selection panel
;
dvBase = widget_base(tlb, frame=3, /column)
dvLabel = widget_label(dvBase, /align_left, $
value='Dataview Selection: ')
dvList = widget_combobox(dvBase, event_pro='spdfDataviewSelected', $
value=dvTitles)
;
; Dataset selection panel
;
datasetSelectionPanel = widget_base(tlb, frame=3, /column)
datasetSelectionLabel = $
widget_label(datasetSelectionPanel, /align_left, $
value='Dataset Selection:')
miPanel = widget_base(datasetSelectionPanel, /row)
missionGroups = ['']
missionGroupsPanel = widget_base(miPanel, /column)
mLabel = widget_label(missionGroupsPanel, value='Mission Groups')
mList = widget_list(missionGroupsPanel, $
event_pro='spdfIgnoreSelected', $
value=missionGroups, xsize=50, ysize=7, /multiple)
instrumentTypes = ['']
instrumentTypesPanel = widget_base(miPanel, /column)
iLabel = widget_label(instrumentTypesPanel, $
value='Instrument Types')
iList = widget_list(instrumentTypesPanel, $
event_pro='spdfIgnoreSelected', $
value=instrumentTypes, xsize=50, ysize=7, /multiple)
dsButton = widget_button(datasetSelectionPanel, $
/align_left, $
event_pro='spdfFindDatasets', $
value='Find Datasets', $
tooltip='Find datasets for the specified mission groups and instrument types')
;
; Data selection panel
;
dataSelectionPanel = widget_base(tlb, frame=3, /column)
dataSelectionLabel = $
widget_label(dataSelectionPanel, /align_left, $
value='Data Selection:')
dsLabel = widget_label(dataSelectionPanel, $
value='Datasets/Variables')
dsTree = widget_tree(dataSelectionPanel, /multiple, $
/context_events, event_pro='spdfDatasetTreeEvent', $
xsize=600, ysize=240)
dsContextMenu = widget_base(tlb, /context_menu)
viewNotesButton = widget_button(dsContextMenu, $
event_pro='spdfViewNotes', $
value="View Notes")
viewInventoryButton = widget_button(dsContextMenu, $
event_pro='spdfViewInventory', $
value="View Inventory")
timePanel = widget_base(dataSelectionPanel, /row)
defaultTimeButton = widget_button(timePanel, $
event_pro='spdfDefaultTime', $
value="Set Default Time")
startTime = cw_field(timePanel, title='Start Time')
stopTime = cw_field(timePanel, title='Stop Time')
timeFormatLabel = widget_label(timePanel, $
value='Format YYYY/MM/DD[ HH:MM:SS]')
;
; Data operation panel
;
dataOperationPanel = widget_base(tlb, frame=3, /column)
dataOperationLabel = $
widget_label(dataOperationPanel, /align_left, $
value='Data Operation:')
optionPanel = widget_base(dataOperationPanel, /row)
dataVarName = cw_field(optionPanel, title='Variable Name', $
value='data')
saveCdfOption = cw_bgroup(optionPanel, $
['Save local CDF files'], $
/nonexclusive, /frame, $
label_left='File Option', $
event_funct='spdfSaveDataButton', $
set_value=[defaultSaveCdfOption])
actionPanel = widget_base(dataOperationPanel, /row)
dataButton = widget_button(actionPanel, $
event_pro='spdfGetCdawebData', $
value='Get CDAWeb Data', $
tooltip='Read CDAWeb data into IDL environment')
idlButton = widget_button(actionPanel, $
event_pro='spdfGetCdawebDataIdl', $
value='Show Get Data IDL', $
tooltip='Display IDL code to get data')
fileButton = widget_button(actionPanel, $
event_pro='spdfReadLocalData', $
value='Read Local CDF', $
tooltip='Read data from local file into IDL environment')
plotButton = widget_button(actionPanel, $
event_pro='spdfGetCdawebPlot', $
value='Show CDAWlib Plot', $
tooltip="Display CDAWlib's plot of the data")
listButton = widget_button(actionPanel, $
event_pro='spdfCreateCdawebListing', $
value='Create CDAWlib Listing', $
tooltip="Create CDAWlib's listing of the data")
bottomPanel = widget_base(tlb, frame=3, row=1)
;
; Program control panel
;
programControlPanel = widget_base(bottomPanel, /column)
programControlLabel = $
widget_label(programControlPanel, /align_left, $
value='Window Control:')
exitButton = widget_button(programControlPanel, /align_left, $
event_pro='spdfExit', $
value='Close', tooltip='Close this window')
; this button needs to be positioned better
; aboutButton = widget_button(bottomPanel, /align_right, $
; event_pro='spdfAbout', $
; value='About', tooltip='About this software')
state = { $
errorDialog:obj_new('SpdfHttpErrorDialog'), $
authenticator:obj_new('SpdfCdawebChooserAuthenticator', tlb), $
cdas:cdas, $
selectedDataview:ptr_new(/allocate_heap), $
dataviews:dataviews, $
dataviewList:dvList, $
observatoryGroups:ptr_new(/allocate_heap), $
observatoryGroupList:mList, $
instrumentTypes:ptr_new(/allocate_heap), $
instrumentTypeList:iList, $
datasets:ptr_new(/allocate_heap), $
datasetTree:dsTree, $
selectedDataset:ptr_new(/allocate_heap), $
datasetContextMenu:dsContextMenu, $
startTime:startTime, $
stopTime:stopTime, $
dataVarName:dataVarName, $
saveData:ptr_new(defaultSaveCdfOption) $
}
widget_control, tlb, set_uvalue=state, /realize
if keyword_set(groupLeaderWidgetId) then begin
xmanager, 'SpdfCdawebChooser', tlb, $
group_leader=groupLeaderWidgetId
endif else begin
xmanager, 'SpdfCdawebChooser', tlb, /no_block
endelse
spdfSelectDataview, tlb, dvList, initialDvSelection
end