;----------------------------------------------------------------------------- function cdfx_file_search, pathSpec if !version.release ge '5.5' then $ return, file_search(pathSpec) return, findfile(pathSpec) ; for pre-5.5 end ;----------------------------------------------------------------------------- ; Returns true if either (A) the passed set of two strings are valid time ; specifications for 'read_myCDF', or (B) both strings are empty. function cdfx_valid_time_range, tr syntax = '[0-9]{4}(/[0-9]{2}){2} [0-9]{2}(:[0-9]{2}){2}' return, (tr[0]+tr[1] eq '') or $ (stregex(tr[0], syntax, /boolean) and stregex(tr[1], syntax, /boolean)) end ;----------------------------------------------------------------------------- ; Returns the named attribute of a given variable of a given CDF object. function cdfx_read_attr, cdfid, varname, attname ;attname = strupcase(attname) error_status = 0 ; initialize error flag catch, error_status ; set up exception handler to handle missing name if error_status ne 0 then $ return, '' $ else $ a = read_myattribute(varname, cdf_attnum(cdfid, attname), cdfid) return, a.(0) end ;----------------------------------------------------------------------------- ; Returns the minimum and maximum epoch values of the given CDF data files. function cdfx_time_range_of_files, fpaths, epoch_vartype=epoch_vartype rmin = 6.0e13 ; about 1900 rmax = 7.0e13 ; about 2200 a_rmin=[0] a_rmax=[0] for i = 0, n_elements(fpaths)-1 do begin ;TJK add check for master, don't look for time range in the masters if not stregex(fpaths[i], '.*_00000000_v[0-9]+[.]cdf$', /boolean, /fold) then begin ; print, 'DEBUG, found a non-master -',fpaths[i] cdfid = cdf_open(fpaths[i]) cdf_control, cdfid, set_zmode=2 info = cdf_inquire(cdfid) found = 0L ; initialize flag for varindex = 0, info.nzvars-1 do begin varname = (cdf_varinq(cdfid, varindex, /zvar)).name ;TJK 12/7/2006 - change this to look for range_epoch variable 1st ;since that's the only "good" epoch variable in the THEMIS cdfs ;if not found, then look for a regular epoch variable. ; if stregex(varname, 'epoch.*|range_epoch', /bool, /fold) then begin if stregex(varname, 'range_epoch', /bool, /fold) then begin found = 1L epoch = read_myvariable(varname, cdfid, vary, dtype, recs) cdf_control,CDFid,VAR=varname,GET_VAR_INFO=vinfo2 ; inquire more about the var if (vinfo2.maxrec ne -1) then begin ; ie, epoch var is not empty emin = epoch[0] emax = epoch[n_elements(epoch)-1] endif ; print, emin,emax ;TJK 4/30/2007 - only replace rmin/max w/ different epoch values (from ; the same cdf) if the new min/max are valid ;TJK 5/15/2008 - change to ge instead of gt, since we have cdfs w/ ; just one epoch and we want to show the cdfs time, vs. ; some strange start year like 1901... ; ; if ((i eq 0) and (emax gt emin)) then begin if ((i eq 0) and (emax ge emin)) then begin ;rmin = emin ;rmax = emax a_rmin = emin a_rmax = emax endif else begin ;rmin = min([rmin, emin]) ;rmax = max([rmax, emax]) a_rmin = min([rmin, emin]) a_rmax = max([rmax, emax]) endelse endif endfor if (not found) then begin ;if range_epoch variable not found, look for ;regular epochs for varindex = 0, info.nzvars-1 do begin varinfo = cdf_varinq(cdfid, varindex, /zvar) varname = varinfo.name vartype = varinfo.datatype varys = varinfo.recvar ;TJK 12/15/2006 - determine that the epoch variable we want to use has ; type cdf_epoch AND is record varying (THEMIS has ; several epochs, so you can't just take the 1st one ; that's cdf_epoch ; RCJ 11/01/2012 added cdf_epoch16, cdf_time_tt2000 below: ;if (stregex(vartype, 'cdf_epoch', /bool, /fold) and (varys eq 'VARY')) then begin if ((stregex(vartype, 'cdf_epoch', /bool, /fold)) or $ (stregex(vartype, 'cdf_epoch16', /bool, /fold)) or $ (stregex(vartype, 'cdf_time_tt2000', /bool, /fold)) $ and (varys eq 'VARY')) then begin ;print, 'DEBUG, found epoch, varname = ',varname epoch_vartype=vartype ; to be passed back to calling program epoch = read_myvariable(varname, cdfid, vary, dtype, recs) cdf_control,CDFid,VAR=varname,GET_VAR_INFO=vinfo2 ; inquire more about the var if (vinfo2.maxrec ne -1) then begin ; ie, epoch var is not empty emin = epoch[0] emax = epoch[n_elements(epoch)-1] endif ;TJK 4/30/2007 - only replace rmin/max w/ different epoch values (from ; the same cdf) if the new min/max are valid ;TJK 5/15/2008 - change "gt" to "ge" to handle the case where we have ; one cdf w/ one record - we want the times shown on the ;interface to at least be from the cdf, vs. a year like 1901. if ((i eq 0) and (emax ge emin)) then begin rmin = emin rmax = emax a_rmin = [a_rmin,rmin] a_rmax = [a_rmax,rmax] endif else begin ;TJK 2/15/2008 add code to compare epoch vs. epoch16 values (can't do w/ ;min/max functions). THEMIS has datasets w/ both epoch and epoch16s. if (!version.release ge '6.2') then begin if (size(emin,/tname) eq 'DCOMPLEX')then begin if (cdf_epoch_compare(rmin, emin) ge 0) then rmin = emin if (cdf_epoch_compare(emax, rmax) ge 0) then rmax = emax a_rmin = [a_rmin,rmin] a_rmax = [a_rmax,rmax] endif else begin rmin = min([rmin, emin]) rmax = max([rmax, emax]) a_rmin = [a_rmin, rmin] a_rmax = [a_rmax, rmax] endelse endif else begin rmin = min([rmin, emin]) rmax = max([rmax, emax]) a_rmin = [a_rmin,rmin] a_rmax = [a_rmax,rmax] endelse endelse endif endfor endif found = 0L; reset flag for check in next CDF. cdf_close, cdfid endif endfor if n_elements(a_rmin) gt 1 then rmin=min(a_rmin[1:*]) else rmin=a_rmin if n_elements(a_rmax) gt 1 then rmax=max(a_rmax[1:*]) else rmax=a_rmax return, [rmin, rmax] end ;----------------------------------------------------------------------------- ; Separates a list of CDF file paths into ordinary data files and ; master files. Also supplements the master file set with new ones ; generated from the data file names, looking for masters in both the ; current directory and the user-specified Masters directory. pro cdfx_separate_cdfs, fpaths, cpaths=cpaths, mpaths=mpaths common cdfxcom, CDFxwindows, CDFxprefs ; include cdfx common cpaths = [''] mpaths = [''] for i = 0, n_elements(fpaths)-1 do begin fpath = fpaths[i] if not stregex(fpath, '.*_00000000_v[0-9]+[.]cdf$', /boolean, /fold) then begin ;print,'This does not check for .CDF, only .cdf' ; then got data file, not a master cpaths = [cpaths, fpath] ; add it now ; Now look for data file's master CDF. ;dname = stregex(fpath, '/.*/', /extract) ;fname = stregex(fpath, '[^/]+$', /extract) ; dname = stregex(fpath, '\\.*\\', /extract) ; fname = stregex(fpath, '[^\\]+$', /extract) ;TJK 12/18/2006 - changed above to the following since above didn't ; work for directories containing '_' or various OS's if (strupcase(!version.os_family) eq 'UNIX' or $ strupcase(!version.os_family) eq 'MACOS') then $ delim = strpos(fpath, '/',/reverse_search) else $ delim = strpos(fpath, '\',/reverse_search) dname = strmid(fpath,0,delim+1) fname = strmid(fpath,delim+1, strlen(fpath)) ;TJK 12/18/2006 - change logic since it won't work w/ dataset ; names containing more than the usual fields split = strsplit(fname, '_', /extract) split[n_elements(split)-2] = '00000000' split[n_elements(split)-1] = 'v*.cdf' mname = strjoin(split, '_', /single) ; master CDF file name fpath = cdfx_file_search("{./," + dname + "," + $ CDFxprefs.masters_path + "/}" + mname) ; searches in three places if (size(fpath))[0] ne 0 then $; there is something to add mpaths = [mpaths, fpath[0]] endif endfor if n_elements(cpaths) gt 1 then $ cpaths = cpaths[1:*] if n_elements(mpaths) gt 1 then $ mpaths = cdfx_uniq_sort(mpaths[1:*]) ;print, 'cpaths = ',cpaths ;print, 'masters = ',mpaths ;stop;TJK end ;----------------------------------------------------------------------------- ; Returns whether the given set of CDF data files are structurally ; compatible with each other. Compatibility is defined by the routine ; Compare_mycdfs. function cdfx_files_compatible, cpaths n = n_elements(cpaths) if n lt 2 then return, 1 id0 = cdf_open(cpaths[0]) cdf_control, id0, set_zmode=2 for i = 1, n-1 do begin id = cdf_open(cpaths[i]) cdf_control, id, set_zmode=2 match = compare_mycdfs(id, id0) cdf_close, id if not match then begin cdf_close, id0 return, 0 endif endfor cdf_close, id0 return, 1 end ;----------------------------------------------------------------------------- pro cdfx_refine_open_event, event widget_control, event.top, get_uvalue=info widget_control, (*info).list, get_value=bvals case event.id of (*info).bSelectAll: begin bvals[*] = 1 widget_control, (*info).list, set_value=bvals end (*info).bUnselectAll: begin bvals[*] = 0 widget_control, (*info).list, set_value=bvals end (*info).bCancel: begin widget_control, event.top, /destroy end (*info).bProceed: begin widget_control, (*info).tstart, get_value=tstart widget_control, (*info).tstop, get_value=tstop trange = [tstart[0], tstop[0]] w = where(bvals eq 1, wc) if not cdfx_valid_time_range(trange) then $ resp = dialog_message(/error, "Invalid syntax in time fields!") $ else if wc lt 1 then $ resp = dialog_message(/error, 'No variables selected!') $ else begin (*info).selection = bvals (*info).trange = trange widget_control, event.top, /destroy endelse end else : ; do nothing endcase end ;----------------------------------------------------------------------------- function cdfx_opencdfs,gleader=gleader ; ;Copyright 1996-2013 United States Government as represented by the ;Administrator of the National Aeronautics and Space Administration. ;All Rights Reserved. ; ;------------------------------------------------------------------ common cdfxcom, CDFxwindows, CDFxprefs ; include cdfx common CATCH,error_status ; added this to deal w/ errors coming from cdf_open if (error_status ne 0) then begin print,'Error: ',!error_state.msg endif ; Get a set of CDF files from user. ;paths = dialog_pickfile(title='Choose CDF(s)',/multiple) ;/fix_filter, filter="*.cdf" paths = dialog_pickfile(title='Choose CDF(s)',/multiple, $ path=CDFxprefs.cdf_path,get_path=thispath) CDFxprefs.cdf_path=thispath if paths[0] eq '' then $ return, -1 if !version.release ge '6' then $ if file_test(paths[0], /directory) then $ return, -1 cdfx_separate_cdfs, paths, cpaths=cpaths, mpaths=mpaths if n_elements(cpaths) lt 1 then begin resp = dialog_message(/error, 'No CDF data files selected!') return, -1 endif if not cdfx_files_compatible(cpaths) then begin resp = dialog_message(/error, $ 'The selected data files are not structurally compatible!') return, -1 endif cdfid = cdf_open(cpaths[0]) mcdfid = -1 vnames = get_allvarnames(cdfid=cdfid) ;print, vnames ;!! ;cinfo = cdf_inquire(cdfid) ; inquire about the cdf if mpaths[0] ne '' then begin mcdfid = cdf_open(mpaths[0]) mast_mess = 'Metadata from '+mpaths[0]+' being used. Modify Preferences if this is not correct.' resp = dialog_message(/info, mast_mess) vnames = [vnames, get_allvarnames(cdfid=mcdfid)] ; add master vars endif else $ resp = dialog_message(/info, 'No CDF master files found.') vnames = cdfx_uniq_sort(vnames) new_vnames = [''] ;vlist = [''] tmp_vlist = [''] fname=[''] ;nvars = n_elements(vnames) ;vlist = strarr(nvars) ; Gather display information for the variables. !quiet = 1 for i=0, n_elements(vnames)-1 do begin ; construct the list of variables name vname = vnames[i] ;vtype = cdfx_read_attr(cdfid, vname, 'VAR_TYPE') ;if vtype eq '' and mcdfid ne -1 then vtype = cdfx_read_attr(mcdfid, vname, 'VAR_TYPE') ; RCJ 01/14/2013 I think the call below will ensure what's in the master cdf has priority if mcdfid ne -1 then vtype = cdfx_read_attr(mcdfid, vname, 'VAR_TYPE') else $ vtype = cdfx_read_attr(cdfid, vname, 'VAR_TYPE') ;handle case if vtype eq 'data' then begin if strupcase(vtype) eq 'DATA' then begin tmp_vlist = [tmp_vlist, vname] new_vnames = [new_vnames, vname] ;tmp_fname = cdfx_read_attr(cdfid, vname, 'CATDESC') ;if tmp_fname eq '' and mcdfid ne -1 then tmp_fname = cdfx_read_attr(mcdfid, vname, 'CATDESC') + ' (M)' ; RCJ 01/14/2013 I think the call below will ensure what's in the master cdf has priority if mcdfid ne -1 then tmp_fname = cdfx_read_attr(mcdfid, vname, 'CATDESC') + ' (M)' else tmp_fname = cdfx_read_attr(cdfid, vname, 'CATDESC') ;added this section to guarantee that a proper value is displayed in CDFX on the 'Select Variables and Time Interval' screen if STRCOMPRESS(tmp_fname, /REMOVE_ALL) eq '' then begin if STRTRIM(cdfx_read_attr(cdfid, vname, 'FIELDNAM')) ne '' then begin tmp_fname = (cdfx_read_attr(cdfid, vname, 'FIELDNAM')) endif else if STRTRIM(cdfx_read_attr(cdfid, vname, 'VARNAME')) ne '' then begin tmp_fname = (cdfx_read_attr(cdfid, vname, 'VARNAME')) endif else begin tmp_fname = '...' endelse if STRLEN(tmp_fname) ge 100 then tmp_fname = STRMID(tmp_fname, 0, 97) + '...' endif if STRCOMPRESS(tmp_fname, /REMOVE_ALL) eq '(M)' then begin if STRTRIM(cdfx_read_attr(cdfid, vname, 'FIELDNAM')) ne '' then begin tmp_fname = (cdfx_read_attr(cdfid, vname, 'FIELDNAM')) + ' (M)' endif else if STRTRIM(cdfx_read_attr(cdfid, vname, 'VARNAME')) ne '' then begin tmp_fname = (cdfx_read_attr(cdfid, vname, 'VARNAME')) + ' (M)' endif else begin tmp_fname = '...' endelse if STRLEN(tmp_fname) ge 100 then tmp_fname = STRMID(tmp_fname, 0, 97) + '...' endif ;if STRLEN(tmp_fname) ge 100 then tmp_fname = STRMID(tmp_fname, 0, 97) + '...' fname=[fname,tmp_fname] endif ;fname = cdfx_read_attr(cdfid, vname, 'FIELDNAM') ;if fname eq '' and mcdfid ne -1 then $ ; fname = cdfx_read_attr(mcdfid, vname, 'FIELDNAM') + ' (M)' ;if vtype eq 'data' or vtype eq 'support_data' then begin ; RCJ 12/12/2012 Line below will make interface look more like ; CDAWeb selection page, where only 'data' vars are displayed. ; if vtype eq 'data' then begin ; ;vlist = [vlist, string(format='(a25,a15,a50)', vname, vtype, fname)] ; ;vlist = [vlist, string(format='(a20,2x,a10,2x,a50)', vname, vtype, fname)] ; thisformat='(a'+strtrim(max(strlen(fname)),2) + ',2x,a'+strtrim(max(strlen(vname)),2)+')' ; print,'thisformat = ',thisformat ; vlist = [vlist, string(format=thisformat, fname,vname)] ; new_vnames = [new_vnames, vname] ; endif endfor ;check for the files w/o data variables and get out if (n_elements(new_vnames) eq 1 and (new_vnames[0]eq'')) then begin resp = dialog_message(/info, 'No variables w/ var_type = data found. Select another data file.') return, -1 endif fname=fname[1:*] tmp_vlist=tmp_vlist[1:*] vlist='' thisformat='(a-'+strtrim(max(strlen(fname)),2) + ',3x,a-'+strtrim(max(strlen(tmp_vlist)),2)+')' for i=0,n_elements(tmp_vlist)-1 do begin vlist = [vlist, string(format=thisformat, fname[i],+'('+tmp_vlist[i])+')'] endfor vlist = vlist[1:*] vnames = new_vnames[1:*] !quiet = 0 ;TJK record the number of selectable variables for comparison down below total_vnames = n_elements(new_vnames)-1 ; -1 because the 1st elem. is blank cdf_close, cdfid if mcdfid ne -1 then $ cdf_close, mcdfid if n_elements(vlist) lt 1 then begin ;TJK changed from 2 to 1 on 10/17/2014 resp = dialog_message(/error, $ "No data or support variables were found in the chosen CDF file(s). The files are probably not ISTP-compliant.") return, -1 endif nvars = n_elements(vlist) trange = cdfx_time_range_of_files(cpaths,epoch_vartype=epoch_vartype) tstart = cdfx_time_string_of_epoch(trange[0]) tstop = cdfx_time_string_of_epoch(trange[1]) ;CWG TESTING xyoff= GET_SCREEN_SIZE() ;base = widget_base(/column, title='Select Variables and Time Interval', /frame) base = widget_base(/column, title='Select Variables and Time Interval', /frame,$ group_leader=gleader,/modal,XOFFSET=xyoff[0]/2, YOFFSET=xyoff[1]/2) base1 = widget_base(base, /column, /frame,XOFFSET=xyoff[0]/2, YOFFSET=xyoff[1]/2) base3 = widget_base(base, /row,XOFFSET=xyoff[0]/2, YOFFSET=xyoff[1]/2) base4 = widget_base(base3, /column, /frame,XOFFSET=xyoff[0]/2, YOFFSET=xyoff[1]/2) base2 = widget_base(base3, /column, /frame,XOFFSET=xyoff[0]/2, YOFFSET=xyoff[1]/2) w = widget_label(base4, value='Time Interval') w = widget_label(base4, value='(Format: YYYY/MM/DD hh:mm:ss.mmm)') bstart = widget_base(base4, /row,XOFFSET=xyoff[0]/2, YOFFSET=xyoff[1]/2) lstart = widget_label(bstart, value='Start time:') bstop = widget_base(base4, /row,XOFFSET=xyoff[0]/2, YOFFSET=xyoff[1]/2) lstop = widget_label(bstop, value='Stop time: ') info = ptr_new({$ selection:lonarr(nvars), $ trange:["",""], $ list:cw_bgroup(base1, vlist, /nonexclusive, scroll=(nvars>20), $ set_value = lonarr(nvars), $ label_top = strtrim(string(nvars), 2) + ' Variables', $ y_scroll = (20 * !d.y_ch_size), $ ;x_scroll = (95 * !d.x_ch_size)), $ x_scroll = (max(strlen(vlist)) * !d.x_ch_size)>(95 * !d.x_ch_size)), $ ;tStart: widget_text(bstart, value=tstart, xsize=20, /editable), $ ;tStop: widget_text(bstop , value=tstop , xsize=20, /editable), $ ; Increasing size for miliseconds: tStart: widget_text(bstart, value=tstart, xsize=23, /editable), $ tStop: widget_text(bstop , value=tstop , xsize=23, /editable), $ bProceed: widget_button(base2, value='Proceed'), $ bSelectAll: widget_button(base2, value='Select All'), $ bUnselectAll: widget_button(base2, value='Unselect All'), $ bCancel: widget_button(base2, value='Cancel') }) widget_control, base, /realize, set_uvalue=info xmanager, 'cdfx_refine_open', base;, /modal ;modal is obsolete in xmanager w = where((*info).selection eq 1, wc) a = -1 if wc gt 0 then begin tstart = ((*info).trange)[0] tstop = ((*info).trange)[1] widget_control, /hourglass if mpaths[0] eq '' then $ allpaths = cpaths $ else $ allpaths = [mpaths, cpaths] ;TJK 3/28/2007 - try to improve performance by using the all=2 keyword ; to read_myCDF when we can, otherwise the checking and ; reading of metadata and extra variables is very ; costly, especially in cases like the L1 THEMIS files. ;IF all variables selected, try just reading the data variables and ;those required (depends, etc.) vs. all support/metadata variables ;TJK 7/14/2008 - compare total_vnames w/ vnames(w) not vnames, ; otherwise we get all the variables all the time. if tstart eq "" or tstop eq "" then begin if (total_vnames eq n_elements(vnames[w])) then $ a = read_mycdf(' ', allpaths, /nodatastruct, ALL=2) else $ a = read_mycdf(vnames[w], allpaths, /nodatastruct) endif else begin split=strsplit(tstart,':',/extract) split=strsplit(split[2],'.',/extract) if split[1] ne '' then begin startmsec=strmid(split[1],0,3) startusec=strmid(split[1],3,3) startnsec=strmid(split[1],6,3) startpsec=strmid(split[1],9,3) endif ; split=strsplit(tstop,':',/extract) split=strsplit(split[2],'.',/extract) if split[1] ne '' then begin stopmsec=strmid(split[1],0,3)+1 stopusec=strmid(split[1],3,3) stopnsec=strmid(split[1],6,3) stoppsec=strmid(split[1],9,3) endif ; if (total_vnames eq n_elements(vnames[w]))then $ a = read_mycdf(' ', allpaths, /nodatastruct, ALL=2, $ tstart=tstart, tstop=tstop, start_msec=startmsec,stop_msec=stopmsec, start_usec=startusec,stop_usec=stopusec,$ start_nsec=startnsec,stop_nsec=stopnsec, start_psec=startpsec,stop_psec=stoppsec) else $ a = read_mycdf(vnames[w], allpaths, /nodatastruct, $ tstart=tstart, tstop=tstop, start_msec=startmsec,stop_msec=stopmsec, start_usec=startusec,stop_usec=stopusec,$ start_nsec=startnsec,stop_nsec=stopnsec, start_psec=startpsec,stop_psec=stoppsec) endelse ;if tstart eq "" or tstop eq "" then begin ; if (total_vnames eq n_elements(vnames[w])) then $ ; a = read_mycdf(' ', allpaths, /nodatastruct, ALL=2) else $ ; a = read_mycdf(vnames[w], allpaths, /nodatastruct) ;endif else begin ; if (total_vnames eq n_elements(vnames[w]))then $ ; a = read_mycdf(' ', allpaths, /nodatastruct, ALL=2, $ ; tstart=tstart, tstop=tstop) else $ ; a = read_mycdf(vnames[w], allpaths, /nodatastruct, $ ; tstart=tstart, tstop=tstop) ;endelse endif ptr_free, info return, a end ;-----------------------------------------------------------------------------