;$Author: kenb-mac $ ;$Date: 2007-01-24 14:23:38 -0800 (Wed, 24 Jan 2007) $ ;$Header: /home/cdaweb/dev/control/RCS/read_myCDF.pro,v 1.200 2006/12/13 19:07:22 kovalick Exp kovalick $ ;$Locker: kovalick $ ;$Revision: 225 $ ;+------------------------------------------------------------------------ ; This package of IDL functions facilitates reading data and metadata from ; Common Data Format (CDF) files. While CDF provides all the benefits ; of a portable, self-documenting scientific data format, reading them is ; not always a simple matter. To make it simple, I have created this IDL ; package so that all of the data and metadata from multiple variables can ; be read from multiple CDF files ... in one single, simple command. The ; function is called 'READ_MYCDF' and it returns an anonymous structure of ; the form: ; ; structure_name.variable_name.attribute_name.attribute_value ; ; From this structure, all data and metadata for the requested variables ; is easily accessed. ; ; AUTHOR: ; Richard Burley, NASA/GSFC/Code 632.0, Feb 13, 1996 ; burley@nssdca.gsfc.nasa.gov (301)286-2864 ; ; NOTES: ; ; Three additional 'attributes' will be included in the sub-structure for ; each variable. The first is the 'VARNAME' field. Because IDL structure ; tags are always uppercase, and because CDF variable names are case sen- ; sitive, a case sensitive copy of the variable name is created. The second ; 'attribute' to be added is the 'CDFTYPE' field. This field will hold a ; string value holding the cdf data type. The last 'attribute' to be ; artificially added will be either the 'DAT' field or, if the keyword ; NODATASTRUCT is set, the 'HANDLE' field. The 'DAT' field will contain ; the actual data values read from the CDF's for the variable. The 'HANDLE' ; field will hold a handle_id where the data will reside. ; ; This package will look for and utilize certain special attributes required ; by the International Solar Terrestrial Physics Key Parameters Generation ; Software Standards and Guidelines. The existance of these attributes is ; not required for the operation of this software, but will enhance its ; usefullness, primarily by reading variables that will be needed for proper ; utilization of the data, even though you may not have asked for them ; explicitly. ; ; This package was tested under IDL version 4.0.1b. This package was tested ; on CDF's up to version 2.5 and on both r-variables and z-variables. ; ; CDF variables defined as unsigned integers are, unfortunately, currently ; returned by the IDL CDF_VARGET procedure as signed integers. This can ; cause sign flips. This software detects and corrects for this defect for ; data values. However, it cannot detect and correct for this defect for ; attribute values because the IDL procedure CDF_ATTINQ does not return the ; CDF data type of the attribute. These problems have been reported to ; RSI. ; ; ; Modifications: ; As of October 2, 2000, this software can run on all of the following ; IDL versions, 5.1, 5.2 and 5.3 (testing for 5.4 will commence soon). ; Some fairly major changes were necessary in order for read_myCDF ; to work under 5.3. IDL 5.3 enforces the variable naming rules for ; structure tag names. This change affects this s/w because we basically ; had never checked our tag names, e.g. we used the CDF variable names ; and label attribute values directly. So in read_myCDF the general ; concept to fixing this problem was to set up a table (which is shared ; in a common block - not my favorite way to go, but definitely the ; easiest), where there are two tags, equiv and varname. varname ; contains the real CDF variable name, equiv contains the "cleaned up, ; IDL acceptable" variable name that can be used as a structure tag ; name... TJK 04/02/2000 ; ; 1996, NASA/Goddard Space Flight Center ; This software may be used, copied, or redistributed as long as it is not ; sold and this copyright notice is reproduced on each copy made. This ; routine is provided as is without any express or implied warranties ; whatsoever. ;------------------------------------------------------------------------- ; NAME: BREAK_MYSTRING ; PURPOSE: ; Convert a string into a string array given a delimiting character ; CALLING SEQUENCE: ; out = break_mystring(instring) ; INPUTS: ; instring = input text string ; KEYWORD PARAMETERS: ; delimiter = character to parse by. Default = ' ' ; OUTPUTS: ; out = string array ; AUTHOR: ; Jason Mathews, NASA/GSFC/Code 633, June, 1994 ; mathews@nssdc.gsfc.nasa.gov (301)286-6879 ; MODIFICATION HISTORY: ;------------------------------------------------------------------------- FUNCTION break_mySTRING, s, DELIMITER=delimiter ; Validate the input parameters s_size=size(s) & n_size=n_elements(s_size) if (s_size(n_size - 2) ne 7) then begin print,'ERROR>Argument to break_mySTRING must be of type string' return,-1 endif if s eq '' then return, [ '' ] if n_elements(delimiter) eq 0 then delimiter = '' ; dissect the string byte_delim = Byte( delimiter ) ; convert string to byte delimiter result = Where( Byte(s) eq byte_delim(0), count ) ; count occurences result = StrArr( count+1 ) & pos = -1 if (count gt 0) then begin for i=0, count-1 do begin oldpos = pos + 1 pos = StrPos(s, delimiter, oldpos) result(i) = StrMid(s, oldpos, pos-oldpos) endfor endif pos = pos + 1 result(count) = StrMid( s, pos, StrLen(s) - pos ) return, result end ;+----------------------------------------------------------------------- ; Search the tnames array for the instring, returning the index in tnames ; if it is present, or -1 if it is not. ;TJK this function is in a separate file called TAGindex.pro ;since its called from many different routines in this system. ;FUNCTION TAGindex, instring, tnames ;instring = STRUPCASE(instring) ; tagnames are always uppercase ;a = where(tnames eq instring,count) ;if count eq 0 then return, -1 $ ;else return, a(0) ;end ;+------------------------------------------------------------------------ ; NAME: AMI_ISTPPTR ; PURPOSE: ; Return true(1) or false(0) depending on whether or not the ; given attribute name qualifies as an ISTP pointer-class attribute. ; CALLING SEQUENCE: ; out = amI_ISTPptr(attribute_name) ; INPUTS: ; attribute_name = name of a CDF attribute as a string ; KEYWORD PARAMETERS: ; OUTPUTS: ; True(1) or False(0) ; AUTHOR: ; Richard Burley, NASA/GSFC/Code 632.0, Feb 13, 1996 ; burley@nssdca.gsfc.nasa.gov (301)286-2864 ; MODIFICATION HISTORY: ;------------------------------------------------------------------------- FUNCTION amI_ISTPptr, aname if (aname eq 'UNIT_PTR') then return,1 if (aname eq 'FORM_PTR') then return,1 ;if (aname eq 'DELTA_PLUS_VAR') then return,1 ;if (aname eq 'DELTA_MINUS_VAR') then return,1 len = strlen(aname) & pos = strpos(aname,'LABL_PTR_') if ((len gt 9)AND(pos eq 0)) then begin ; label pointer found ON_IOERROR,escape ; return false if non-digit found for j=0,(len-10) do begin ; check one character at a time r = strmid(aname,(9+j),1) & READS,r,v,FORMAT='(I1)' endfor return,1 ; remaining characters in label pointer are valid endif pos = strpos(aname,'OFFSET_') if ((len gt 7)AND(pos eq 0)) then begin ; label pointer found ON_IOERROR,escape ; return false if non-digit found for j=0,(len-8) do begin ; check one character at a time r = strmid(aname,(7+j),1) & READS,r,v,FORMAT='(I1)' endfor return,1 ; remaining characters in offset pointer are valid endif escape: return,0 end ;+------------------------------------------------------------------------ ; NAME: AMI_VAR ; PURPOSE: ; Return true(1) or false(0) depending on whether or not the ; given attribute name's value is assigned to a real CDF variable name. ; CALLING SEQUENCE: ; out = amI_VAR(attribute_name) ; INPUTS: ; attribute_name = name of a CDF attribute as a string ; KEYWORD PARAMETERS: ; OUTPUTS: ; True(1) or False(0) ; AUTHOR: ; Tami Kovalick March 6, 2000 ; ; MODIFICATION HISTORY: ;------------------------------------------------------------------------- FUNCTION amI_VAR, aname if (strpos(aname, 'DEPEND') eq 0) then return,1 if (strpos(aname, 'COMPONENT') eq 0) then return,1 return,0 end ;+------------------------------------------------------------------------ ; NAME: PARSE_DISPLAY_TYPE ; PURPOSE: ; Parse and examine the input string. It should be the value of the ; CDF attribute 'DISPLAY_TYPE'. Return an array of variable names ; that it 'points' to. ; CALLING SEQUENCE: ; out = parse_display_type(instring) ; INPUTS: ; instring = string, value of a CDF attribute called 'DISPLAY_TYPE' ; KEYWORD PARAMETERS: ; OUTPUTS: ; out = string array, names of other variables required for display ; NOTES: This routine expects to find 'DISPLAY_TYPE' values looking like: ; PLOT_TYPE>x=vname,y=vname ... ; PLOT_TYPE>y=vname,z=vname(*,1),z=vname(*,2) ... ; AUTHOR: ; Richard Burley, NASA/GSFC/Code 632.0, Feb 13, 1996 ; burley@nssdca.gsfc.nasa.gov (301)286-2864 ; MODIFICATION HISTORY: ;TJK modified 01/27/98 to not parse orbit display type here - the items ;specified for the orbit plot type aren't additional variables. ;TJK modified 09/25/2001 to not parse the "symsize" keyword because its ;value isn't a variable. ; ;------------------------------------------------------------------------- FUNCTION parse_DISPLAY_TYPE, instring num_vnames = 0L & spos = 0L & i=0L ; initialize a = break_mySTRING(instring,DELIMITER='>') ; break string into components if n_elements(a) le 1 then return,-1 ; no '>' following plot type if a(1) eq '' then return,-1 ; no info past '>' to parse if strlowcase(a(0)) eq 'orbit' then return,-1 ; dont want to parse orbit. lastn=n_elements(a)-1 ; RTB added 3/98 b = break_mystring(a(lastn),delimiter=',') ; Parse the string into substrings for i=0,n_elements(b)-1 do begin ; examine each substring s = strpos(b(i),'=') & p = strpos(b(i),'(') ; find '=' and '(' signs if s ne -1 then begin ; probably a properly formated DISPLAY_TYPE vattr if(strlowcase(strmid(b(i),0,s)) ne 'symsize') then begin s = s + 1 ; point to first character past the '=' sign if p ne -1 then vname = strmid(b(i),s,(p-s)) $ ; extract vname else vname = strmid(b(i),s,(strlen(b(i))-s)) ; extract vname if num_vnames eq 0 then begin variable_names = vname & num_vnames = num_vnames + 1 endif else begin index = where(variable_names eq vname,wc) if wc eq 0 then begin variable_names = [variable_names,vname] ; add to existing list num_vnames = num_vnames + 1 ; keep count of number of names endif endelse endif ;if the left side of the equal sign isn't equal to "symsize" endif endfor if num_vnames eq 0 then return,-1 else return,variable_names end ;Function correct_vnames(vnames) ;This function takes a list of variable names, checks to see if any of them ;are in the structure called "table" which has a mapping of the "real" variable names ;to those who've been "corrected" in order to run under IDL5.3. Function correct_vnames, vnames common global_table, table if (n_elements(table) gt 0) then begin for i = 0, n_elements(table.equiv)-1 do begin c_index = where(vnames eq table.equiv(i), c_count) if (c_count ge 1) then vnames(c_index(0)) = table.varname(i) endfor endif return, vnames end ;+------------------------------------------------------------------------ ; NAME: follow_myDEPENDS ; PURPOSE: ; Search the metadata anonymous structure for ISTP 'DEPEND' attributes. ; If and when found, add the variable name that it points to to the ; vnames array if it is not already present, and increase the size ; of the dhids and mhids arrays. ; CALLING SEQUENCE: ; follow_myDEPENDS, metadata, vnames, dhids, mhids ; INPUTS: ; metadata = anonymous structure holding attribute values ; vnames = string array of the names of variables already processed ; vvarys = string array of the record variance for each variable ; dhids = array of data handle id's ; mhids = array of metadata handle id's ; KEYWORD PARAMETERS: ; OUTPUTS: ; dhids = array of data handle id's ; mhids = array of metadata handle id's ; AUTHOR: ; Richard Burley, NASA/GSFC/Code 632.0, Feb 13, 1996 ; burley@nssdca.gsfc.nasa.gov (301)286-2864 ; MODIFICATION HISTORY: ;------------------------------------------------------------------------- PRO follow_myDEPENDS, metadata, vnames, vvarys, ctypes, dhids, mhids tnames = tag_names(metadata) for i=0,n_elements(tnames)-1 do begin ; Determine if the current tagname is a legal ISTP-style DISPLAY_TYPE vattr if (tnames(i) eq 'DISPLAY_TYPE') then begin dvnames = parse_DISPLAY_TYPE(metadata.(i)) & dvs = size(dvnames) if (dvs(n_elements(dvs)-2) eq 7) then begin ; variable names found for j=0,n_elements(dvnames)-1 do begin dvnames(j) = correct_vnames(dvnames(j)) ;look for variable names that have ;been corrected (no illegal characters) ;replace them w/ their "real" names ;so that their associated data can be ;retrieved from the cdf files. a = where(vnames eq dvnames(j),count) ; search vnames array so no duplicates. if ((dvnames(j) ne '')AND(count eq 0)) then begin ; add the display variable name all array parameters n = n_elements(vnames) newn = strarr(n+1) & newd = lonarr(n+1) & newm = lonarr(n+1) newv = strarr(n+1) & newr = lonarr(n+1) & newc = strarr(n+1) newn(0:(n-1)) = vnames(0:(n-1)) newv(0:(n-1)) = vvarys(0:(n-1)) newc(0:(n-1)) = ctypes(0:(n-1)) newd(0:(n-1)) = dhids(0:(n-1)) newm(0:(n-1)) = mhids(0:(n-1)) newn(n)=dvnames(j) & newv(n)='' & newc(n)='' & newd(n)=0 & newm(n)=0 vnames=newn & vvarys=newv & ctypes=newc & dhids=newd & mhids=newm endif endfor endif endif ; Determine if the current tagname is a legal ISTP-style depend attribute len = strlen(tnames(i)) & pos = strpos(tnames(i),'DEPEND_') if ((len gt 7)AND(pos eq 0)) then begin ; DEPEND found, check remainder ON_IOERROR, escape ; return false if non-digit found for j=0,(len-8) do begin ; check one character at a time r = strmid(tnames(i),(7+j),1) & READS,r,v,FORMAT='(I1)' endfor dvname = metadata.(i) ; depend attribute FOUND dvname = correct_vnames(dvname) ;look for variable names that have ;been corrected (no illegal characters) ;replace them w/ their "real" names ;so that their associated data can be ;retrieved from the cdf files. ; TJK 9/8/03 remove this because we can't touch these attribute values because they ;they need to be the real variables name. ; RCJ 08/11/03 in case we have " " where a "" should be. ; dvname = strtrim(dvname,2) ;debug help, dvname a = where(vnames eq dvname,count) ;search vnames array to make sure ;there are no duplicates if ((dvname ne '')AND(count eq 0)) then begin ; add the depend variable name to all array parameters n = n_elements(vnames) newn = strarr(n+1) & newd = lonarr(n+1) & newm = lonarr(n+1) newv = strarr(n+1) & newr = lonarr(n+1) & newc = strarr(n+1) newn(0:(n-1)) = vnames(0:(n-1)) newv(0:(n-1)) = vvarys(0:(n-1)) newc(0:(n-1)) = ctypes(0:(n-1)) newd(0:(n-1)) = dhids(0:(n-1)) newm(0:(n-1)) = mhids(0:(n-1)) newn(n) = dvname & newv(n)='' & newc(n)='' & newd(n)=0 & newm(n)=0 vnames = newn & vvarys=newv & ctypes=newc & dhids=newd & mhids=newm endif endif escape: ; Current tag name is not a depend attribute endfor end ;------------------------------------------------------------------------- ; NAME: CDFTYPE_T0_MYIDLTYPE ; PURPOSE: ; Convert from CDF type number to IDL type number ; CALLING SEQUENCE: ; out = CDFtype_to_myIDLtype(in) ; INPUTS: ; in = integer, CDF type number ; KEYWORD PARAMETERS: ; OUTPUTS: ; out = integer, IDL type number ; AUTHOR: ; Richard Burley, NASA/GSFC/Code 632.0, Feb 13, 1996 ; burley@nssdca.gsfc.nasa.gov (301)286-2864 ; MODIFICATION HISTORY: ; TJK 6/27/2006 - added CDF_DCOMPLEX (double-precision complex) ; for handling the new (IDL6.3/CDF3.1) Epoch16 values ; The CDFTYPE values come from cdf.inc in the cdf/include directory ;------------------------------------------------------------------------- FUNCTION CDFtype_to_myIDLtype,cdftype case cdftype of 22L : idltype = 5 ; CDF_REAL8 45L : idltype = 5 ; CDF_DOUBLE 31L : idltype = 5 ; CDF_EPOCH 32L : idltype = 9 ; CDF_EPOCH16 21L : idltype = 4 ; CDF_REAL4 44L : idltype = 4 ; CDF_FLOAT 4L : idltype = 3 ; CDF_INT4 14L : idltype = 3 ; CDF_UINT4 2L : idltype = 2 ; CDF_INT2 12L : idltype = 2 ; CDF_UINT2 51L : idltype = 7 ; CDF_CHAR 52L : idltype = 1 ; CDF_UCHAR 1L : idltype = 1 ; CDF_INT1 11L : idltype = 1 ; CDF_UINT1 41L : idltype = 1 ; CDF_BYTE else: idltype = 0 ; undefined endcase return,idltype end ;+------------------------------------------------------------------------ ; NAME: APPEND_MYDATA ; PURPOSE: ; Append the 'new' data to the 'old' data using array concatenation. ; CALLING SEQUENCE: ; out = append_mydata(new,old) ; INPUTS: ; new = data to be appended to the old data ; old = older data that new data is to be appended to ; KEYWORD PARAMETERS: ; OUTPUTS: ; out = product of concatenating the old and new data arrays ; NOTES: ; Special case check: if old data was from either a skeleton CDF or from ; a CDF with only a single record, then the last dimension was dropped ; during the process of saving/retrieving the data from a handle. ; Must compare the dimensionality of the new and old data to determine ; if this drop has occured, and if so, reform the old data to include ; the extra dimension so that the data can be appended. ; AUTHOR: ; Richard Burley, NASA/GSFC/Code 632.0, Feb 13, 1996 ; burley@nssdca.gsfc.nasa.gov (301)286-2864 ; MODIFICATION HISTORY: ;------------------------------------------------------------------------- FUNCTION append_myDATA, new, old ; RCJ (11/21/01) Added this line because of problem w/ dataset wi_k0_sms: ; RCJ (02/01/02) Well, fixed problem for wi_k0_sms but broke for other datasets ; (wi_h1_wav for example) so I'm commenting this out. ;if n_elements(new) ne 1 then new=reform(new) a = size(new) & b = size(old) & data=0L ; RCJ 06/10/2003 Trying to fix dimension problem w/ interball dataset it_k0_wav ; but if it breaks anything I'll remove it. ; ; TJK 12/22/03 - the following if statements breaks the case where each cdf only ; has one record in it, e.g. our new timed guvi files (timed_l1c*). The case this ; was added for was for it_k0_wav and the Mf2 variable (which turns out to be all ; fill, so unless we have other cases that need this, this will be left commented out. ;if (a(0) eq 3) then begin ; if ((a(1) eq 1) or (a(2) eq 1) or (a(3) eq 1)) then begin ; new=reform(new) ; a=size(new) ; endif ;endif if (a(0) gt b(0)) then begin ; dimension mismatch - reform old data print,'WARNING= Dimension mismatch detected, attempting to reform...' ;DEBUG case b(0) of 0 : ; no special actions needed 1 : old = reform(temporary(old),b(1),1) 2 : old = reform(temporary(old),b(1),b(2),1) 3 : old = reform(temporary(old),b(1),b(2),b(3),1) else : print,'ERROR=Cannot reform single-record variable with > 3 dims' endcase b = size(old) ; recompute b after it has been reformed endif if (a(0) lt b(0)) then begin ; dimension mismatch - reform new data ;print,'WARNING= Dimension mismatch detected, attempting to reform...' ;DEBUG case a(0) of 0 : ; no special actions needed 1 : new = reform(temporary(new),a(1),1) 2 : new = reform(temporary(new),a(1),a(2),1) 3 : new = reform(temporary(new),a(1),a(2),a(3),1) else : print,'ERROR=Cannot reform single-record variable with > 3 dims' endcase a = size(new) ; recompute a after it has been reformed endif ;print, size(old) ;print, size(new) ; append the new data to the old data case a(0) of 0:begin data = [old,new] end 1:begin data = [old,new] end 2:begin data = make_array(a(1),a(2)+b(2),type=a(3)) data(*,0:b(2)-1)=old(*,*) & data(*,b(2):*)=new(*,*) end 3:begin data = make_array(a(1),a(2),a(3)+b(3),type=a(4)) data(*,*,0:b(3)-1)=old(*,*,*) & data(*,*,b(3):*)=new(*,*,*) end else: print,'ERROR=Cannot append arrays with > 3 dimensions yet' endcase new = 0L & old = 0L ; free up unneeded memory return,data end ;+------------------------------------------------------------------------ ; NAME: add_myDEPENDS ; PURPOSE: ; Search the metadata anonymous structure for ISTP 'DEPEND' ; attributes and add the variable name that it points to to the ; vnames array if it is not already present. If the DEPEND ; variable is not present in the list, change the data_type so it ; won't be plotted. ; ; CALLING SEQUENCE: ; add_myDEPENDS, metadata, vnames ; ; INPUTS: ; metadata = anonymous structure holding attribute values ; vnames = string array of virtual variables found ; ; OUTPUTS: ; vnames = modified variable name that includes component variable ; names ; ; NOTES - this is similar to follow_myDEPENDS, except it does less. ; ; AUTHOR: ; Tami Kovalick, QSS, 11/29/2006 ;------------------------------------------------------------------------- PRO add_myDEPENDS, metadata, vnames common global_table, table tnames = tag_names(metadata) for k=0,n_elements(tnames)-1 do begin len = strlen(tnames(k)) & pos = strpos(tnames(k),'DEPEND_') if ((len gt 7) AND (pos eq 0)) then begin ; DEPEND found, check remainder ON_IOERROR, escape ; return false if non-digit found for j=0,(len-11) do begin ; check one character at a time r = strmid(tnames(k),(10+j),1) & READS,r,v,FORMAT='(I1)' endfor dvname = metadata.(k) ; depend attribute FOUND dvname = correct_vnames(dvname) ;look for variable names that have a = where(vnames eq dvname,count) ; search vnames array ;TJK 4/23/01 added extra check for the case where the depend_0 variable ; has an alternate name (its original name had invalid characters in it) - so ; check the table prior to including it. v_count = 0 e_index = where(dvname eq table.equiv, e_count) if (e_count gt 0) then begin v_index = where(vnames eq table.varname(e_index), v_count) endif if ((dvname ne '')AND(count eq 0)AND(v_count eq 0)) then begin ;print, 'Adding ',dvname,' to vnames' ; if DEPEND variable not already requested, add it to the vnames ; array, but change data_type so it won't be plotted... vnames = [vnames,dvname] ;put the depend variable in place - TJK endif ; Added all depend variable names endif ; Finished reading all component variable names escape: ;Current tag name is not a depend attribute endfor ; Finished looping through all metadata elements end ;+------------------------------------------------------------------------ ; NAME: add_myCOMPONENTS ; PURPOSE: ; Search the metadata anonymous structure for ISTP 'COMPONENT' ; attributes and add the variable name that it points to to the ; vnames array if it is not already present. If the component ; variable is not present in the list, change the data_type so it ; won't be plotted. ; ; CALLING SEQUENCE: ; add_myCOMPONENTS, metadata, vnames ; ; INPUTS: ; metadata = anonymous structure holding attribute values ; vnames = string array of virtual variables found ; ; OUTPUTS: ; vnames = modified variable name that includes component variable ; names ; ; AUTHOR: ; Carrie Gallap, Raytheon STX, 1/5/98 ;------------------------------------------------------------------------- PRO add_myCOMPONENTS, metadata, vnames common global_table, table tnames = tag_names(metadata) ;TJK changed the i to k since that's what's used below ;for i=0,n_elements(tnames)-1 do begin for k=0,n_elements(tnames)-1 do begin len = strlen(tnames(k)) & pos = strpos(tnames(k),'COMPONENT_') if ((len gt 10) AND (pos eq 0)) then begin ; COMPONENT found, check remainder ON_IOERROR, escape ; return false if non-digit found for j=0,(len-11) do begin ; check one character at a time r = strmid(tnames(k),(10+j),1) & READS,r,v,FORMAT='(I1)' endfor dvname = metadata.(k) ; component attribute FOUND dvname = correct_vnames(dvname) ;look for variable names that have a = where(vnames eq dvname,count) ; search vnames array ;TJK 4/23/01 added extra check for the case where the component_0 variable ; has an alternate name (its original name had invalid characters in it) - so ; check the table prior to including it. v_count = 0 e_index = where(dvname eq table.equiv, e_count) if (e_count gt 0) then begin v_index = where(vnames eq table.varname(e_index), v_count) endif if ((dvname ne '')AND(count eq 0)AND(v_count eq 0)) then begin ;print, 'Adding ',dvname,' to vnames' ; if COMPONENT variable not already requested, add it to the vnames ; array, but change data_type so it won't be plotted... n = n_elements(vnames) newn = strarr(n+1) newn(0:(n-1)) = vnames(0:(n-1)) vnames = newn vnames(n) = dvname ;put the component variable in place - TJK endif ; Added all component variable names endif ; Finished reading all component variable names escape: ;Current tag name is not a Component attribute endfor ; Finished looping through all metadata elements end ;------------------------------------------------------------------------- PRO add_myDELTAS, metadata, vnames common global_table, table tnames = tag_names(metadata) for i=0,n_elements(tnames)-1 do begin len = strlen(tnames(i)) & pos = strpos(tnames(i),'DELTA_') if ((len gt 6)AND(pos eq 0)) then begin ; DELTA found, check remainder dvname = metadata.(i) ; delta attribute FOUND dvname = correct_vnames(dvname) ;look for variable names that have q = where(vnames eq dvname,count) ;search vnames array to make sure ;TJK (from add_mydeltas): added extra check for the case where ; the delta variable ; has an alternate name (its original name had invalid characters in it) - so ; check the table prior to including it. v_count = 0 e_index = where(dvname eq table.equiv, e_count) if (e_count gt 0) then begin v_index = where(vnames eq table.varname(e_index), v_count) endif if ((dvname ne '')AND(count eq 0)AND(v_count eq 0)) then begin ;if ((dvname ne '')AND(q[0] eq -1)) then begin ;print,metadata.var_type ; add the delta variable name to all array parameters vnames=[vnames,dvname] endif endif endfor end ; ; ;+------------------------------------------------------------------------ ; NAME: READ_MYVARIABLE ; PURPOSE: ; Return the data for the requested variable. ; CALLING SEQUENCE: ; out = read_myvariable(vname, CDFid, vary, dtype, recs) ; INPUTS: ; vname = string, name of variable to be read from the CDF ; CDFid = integer, id or already opened CDF file. ; KEYWORD PARAMETERS: ; START_REC = first record to read. ; REC_COUNT = number of records to read. ; OUTPUTS: ; out = all data from the CDF for the variable being read ; vary = True(1) or False(0) is variable record-varying ; dtype= string, CDF data type ; recs = integer, number of data records ; AUTHOR: ; Richard Burley, NASA/GSFC/Code 632.0, Feb 13, 1996 ; burley@nssdca.gsfc.nasa.gov (301)286-2864 ; MODIFICATION HISTORY: ; 96/04/11 : R.Burley :zVar handling when MAXRECS = -1 changed to ; read REC_COUNT of MAXRECS + 2 & return,DAT ; 96/12/20 ; T. Kovalick modified to take START_REC and REC_COUNT ; keywords (see above). If they aren't set you will get all of ; the records in a cdf. ;------------------------------------------------------------------------- FUNCTION read_myVARIABLE, vname, CDFid, vary, $ dtype, recs, START_REC=START_REC, REC_COUNT=REC_COUNT ; ; Get needed information about the cdf and variable cinfo = cdf_inquire(CDFid) ; inquire about the cdf vinfo = cdf_varinq(CDFid,vname) ; inquire about the variable cdf_control,CDFid,VAR=vname,GET_VAR_INFO=vinfo2 ; inquire more about the var zflag = vinfo.is_zvar ; determine if r-variable or z-variable if keyword_set(START_REC) then start_rec = START_REC else start_rec = 0L ;TJK changed this because the maxrec that comes back from cdf_inquire only ;applies to R variables under IDL v5.02, so if you don't have any R ;variables in your CDF, maxrec will come back as -1... ;rcount = cinfo.maxrec+1 & if (vinfo.RECVAR eq 'NOVARY') then rcount=1L rcount = vinfo2.maxrec+1 & if (vinfo.RECVAR eq 'NOVARY') then rcount=1L ;TJK changed this...maxrecs isn't documented by RSI. ;if keyword_set(REC_COUNT) then recs = REC_COUNT else recs = vinfo2.maxrecs+1 ;So if the rec_count keyword is specified use it, else determine the ;the max recs depending on whether the variable is z or r. if keyword_set(REC_COUNT) then recs = REC_COUNT else recs = vinfo2.maxrec+1 ;So if the rec_count keyword is specified use it, else determine the ;the max recs depending on whether the variable is z or r. ;TJK w/ IDL 5.02 they have now defined maxrec and maxrecs, we want to ; use maxrec and this should work the same for both r and z variables. ;if keyword_set(REC_COUNT) then begin ; recs = REC_COUNT ;endif else if(zflag eq 1) then begin ;set the z variable max recs ; recs = vinfo2.maxrec+1 ;endif else recs = vinfo2.maxrecs+1 ;set the r variable max recs vary = vinfo.RECVAR & dtype = vinfo.DATATYPE ; Read the CDF for the data for the requested variable if (zflag eq 1) then begin ; read the z-variable cdf_control,CDFid,VAR=vname,GET_VAR_INFO=zvinfo if zvinfo.MAXREC eq -1 then begin if keyword_set(DEBUG) then print,'WARNING=',vname,' has ZERO records!' ;TJK 11/17/2006 - instead of reading 1 record when maxrec = -1 (which ; indicates that no records for the variable were ; written), return the fill value for this variable ;print, 'WARNING, no records for variable ',vname ;print, 'attempting to get fillval and return that' anum = cdf_attnum(CDFid,'FILLVAL') if ((anum ne -1) and cdf_attexists(CDFid,'FILLVAL',vname))then begin cdf_attget,CDFid,'FILLVAL',vname,wfill if (size(wfill,/tname) eq 'DCOMPLEX') then return,real_part(wfill) else $ return,wfill endif else begin ;if don't have a fill value, go ahead and read 1 rec. cdf_varget,CDFid,vname,dat,REC_COUNT=1 & return,dat endelse endif else begin if keyword_set(DEBUG) then print, 'reading Z at record', start_rec, recs, 'number of records' cdf_varget,CDFid,vname,dat,REC_START=start_rec,REC_COUNT=recs endelse ;TJK - added the next two lines so that extraneous single dimensions ;will be taken out - this was already being done for r variables ;but wasn't for Z variables, so if we were loading a variable from ;both a z and r variable cdf there would be a mismatch and the ;append of the two data arrays would not be successful. ds = size(dat) ; get size info to determine if dat is scalar or not if (ds(0) ne 0) then dat = reform(temporary(dat)) ; eliminate extraneous dims endif else begin ; read the r-variable dims = total(vinfo.dimvar) & dimc = vinfo.dimvar * cinfo.dim dimw = where(dimc eq 0,dcnt) & if (dcnt ne 0) then dimc(dimw)=1 if rcount eq 0 then begin print,'WARNING=',vname,' has ZERO records!' & return,0 ;TJK replaced this line w/ the following to accommodate start_rec and rec_count ; endif else CDF_varget,CDFid,vname,dat,COUNT=dimc,REC_COUNT=rcount endif else CDF_varget,CDFid,vname,dat,COUNT=dimc,REC_START=start_rec,REC_COUNT=recs if keyword_set(DEBUG) then print, 'reading ',vname,' starting at record', start_rec,' ', recs, 'number of records' ds = size(dat) ; get size info to determine if dat is scalar or not if (ds(0) ne 0) then dat = reform(temporary(dat)) ; eliminate extraneous dims endelse ; Correct for fact that IDL retrieves character data as bytes ;if vinfo.DATATYPE eq 'CDF_CHAR' then begin ; IDL retrieves as bytes if ((vinfo.DATATYPE eq 'CDF_CHAR') or (vinfo.DATATYPE eq 'CDF_UCHAR')) then begin ; IDL retrieves as bytes ds = size(dat) ; get dimensions of dat for single char special case if (ds(0) gt 1) then begin dat = string(dat) dat = reform(temporary(dat)); eliminate extraneous dims endif else begin ; process each element of array d2=strarr(ds(1)) for i=0,ds(1)-1 do d2(i)=string(dat(i)) dat = d2 endelse endif ; Check for sign loss for cdf unsigned integer data. IDL (as of v4.0.1b) ; returns unsigned cdf variables as signed IDL variables with the same ; number of bytes. This could cause a sign flip. Detect and Correct. if vinfo.DATATYPE eq 'CDF_UINT2' then begin w = where(dat lt 0,wc) ; search for negative values if (wc gt 0) then begin ; convert to long dat = long(dat) & dat(w) = dat(w)+(2L^16) & dtype='CDF_INT4' print,'WARNING=Converting CDF_UINT2 to CDF_INT4 to avoid sign switch.' endif endif if vinfo.DATATYPE eq 'CDF_UINT4' then begin w = where(dat lt 0,wc) ; search for negative values if (wc gt 0) then begin ; convert to float dat = float(dat) & dat(w) = dat(w)+(2.0d0^32) & dtype='CDF_REAL' print,'WARNING=Converting CDF_UINT4 to CDF_REAL4 to avoid sign switch.' endif endif ; If this variable is a record-varying variable, but this CDF only happens ; to have one record, then we must add the extra dimension onto the end ; for proper appending to take place when other CDF's are read if ((vinfo.RECVAR eq 'VARY')AND(rcount eq 1L)) then begin ; print,'WARNING=Reforming single-record variable' ;DEBUG ds = size(dat) ; get dimensions of dat case ds(0) of 0 : rcount = 1L ; do nothing 1 : dat = reform(temporary(dat),ds(1),1) 2 : dat = reform(temporary(dat),ds(1),ds(2),1) 3 : dat = reform(temporary(dat),ds(1),ds(2),ds(3),1) else : print,'ERROR=Cannot reform single-record variable with > 3 dims' endcase endif ; Return the data read from the CDF return,dat end ;+------------------------------------------------------------------------ ; NAME: READ_MYATTRIBUTE ; PURPOSE: ; Return the value of the requested attribute for the requested variable. ; CALLING SEQUENCE: ; out = read_myattribute(vname,anum,CDFid) ; INPUTS: ; vname = string, name of variable whose attribute is being read ; anum = integer, number of attribute being read ; CDFid = integer, id of already opened CDF file. ; KEYWORD PARAMETERS: ; OUTPUTS: ; out = anonymous structure holding both the name of the attribute ; and the value of the attribute ; AUTHOR: ; Richard Burley, NASA/GSFC/Code 632.0, Feb 13, 1996 ; burley@nssdca.gsfc.nasa.gov (301)286-2864 ; ; MODIFICATION HISTORY: ; RCJ 11/2003 Added keyword isglobal ;------------------------------------------------------------------------- FUNCTION read_myATTRIBUTE, vname, anum, CDFid, isglobal=isglobal common global_table, table cdf_attinq,CDFid,anum,aname,ascope,maxe,maxze ; inquire about the attribute aname = strtrim(aname,2) ; trim any possible leading or trailing blanks ;TJK 2/28/2002 - call replace_bad_chars to replace any "illegal" characters in ;the attribute name w/ a legal one. This was necessary to go to IDL 5.3. aname = replace_bad_chars(aname,repchar="_",found) attval='' & astruct=create_struct(aname,attval) ; initialize anonymous structure ;TJK modified this error catch to re-set the !error value since not finding ;all attributes is not a fatal error - w/o this SSWeb and the IDL server ;were getting stuck. CATCH,error_status & if error_status ne 0 then begin !ERROR=0 & return,astruct & endif if (ascope eq 'GLOBAL_SCOPE')OR(ascope eq 'GLOBAL_SCOPE_ASSUMED') then begin isglobal=1 cdf_attget,CDFid,anum,0,aval & attval = aval ; get the global attribute for entry=1,maxe do begin ; get remaining entrys if any if (entry eq 1) then begin ; create array to hold the data asize = size(aval) & dtype = asize(n_elements(asize)-2) attval = make_array((maxe+1),TYPE=dtype) & attval(0) = aval endif cdf_attget,CDFid,anum,entry,aval attval(entry) = aval endfor asize = size(attval) & nea = n_elements(asize) if (asize(nea-2) eq 7) then begin if asize(0) eq 0 then attval = strtrim(attval,2) $ else for i=0,asize(1)-1 do attval(i) = strtrim(attval(i),2) endif astruct = create_struct(aname,attval) endif else begin ; 'VARIABLE_SCOPE' or 'VARIABLE_SCOPE_ASSUMED' isglobal=0 cdf_attget,CDFid,anum,vname,aval & attval = aval ; read variable attribute if (amI_ISTPptr(aname) eq 1) then begin ; check for pointer-type attribute attval = read_myVARIABLE(attval,CDFid,vary,ctype,recs) endif asize = size(attval) & nea = n_elements(asize) ;TJK, 3/2/2000, restrict the strtrim calls below because some attributes ;values are actually variable names which may need to have any leading/trailing ;blanks in order to be found in the cdf... this is certainly the case for ;depend and component variable attributes... if ((asize(nea-2) eq 7) and NOT(amI_VAR(aname))) then begin if asize(0) eq 0 then attval = strtrim(attval,2) $ else for i=0,asize(1)-1 do attval(i) = strtrim(attval(i),2) endif else begin if (amI_VAR(aname)) then begin ;replace "bad characters" w/ a "$" table_index = where(table.varname eq attval, tcount) ttable_index = where(table.equiv eq attval, ttcount) vcount = -1 ;initialize if (table_index(0) eq -1) and (ttable_index(0) eq -1)then begin ;add this variable to the table if keyword_set(debug) then print, 'found new attribute adding to table, ',attval tfree = where(table.varname eq '',fcount) if (fcount gt 0) then begin table.varname(tfree(0)) = attval endif else begin print, '1, Number of variables exceeds the current size of the table structure, please increase it, current size is ' help, table.varname return, -1 endelse table_index = where(table.varname eq attval, vcount) endif if (vcount ge 0) then begin attval = replace_bad_chars(attval, diff) table.equiv(table_index(0)) = attval ;set equiv to either the ;new changed name or the original ;if it doesn't contain any bad chars.. endif else begin if (vcount eq -1) then begin ;already set in the table, assign attval to what's in equiv. attval = table.equiv(table_index(0)) endif endelse endif endelse astruct = create_struct(aname,attval) endelse return,astruct end ;read_myattribute ;+------------------------------------------------------------------------ ; NAME: READ_MYMETADATA ; PURPOSE: ; To read all of the attribute values for the requested variable, and ; to return this information as an anonymous structure. ; CALLING SEQUENCE: ; metadata = read_mymetadata(vname,CDFid) ; INPUTS: ; vname = string, name of variable whose metadata is being read ; CDFid = integer, id of already opened CDF file ; KEYWORD PARAMETERS: ; OUTPUTS: ; metadata = anonymous structure whose tags are the attribute names ; and whose fields are the corresponding attribute values. ; AUTHOR: ; Richard Burley, NASA/GSFC/Code 632.0, Feb 13, 1996 ; burley@nssdca.gsfc.nasa.gov (301)286-2864 ; MODIFICATION HISTORY: ; ;------------------------------------------------------------------------- FUNCTION read_myMETADATA, vname, CDFid cinfo = cdf_inquire(CDFid) ; inquire about the cdf to get #attributes ; Create initial data structure to hold all of the metadata information METADATA = create_struct('varname',vname) ; Extract all metadata information for the all attributes nglobal=0 for anum=0,cinfo.natts-1 do begin astruct = 0 ; initialize astruct ; Get the name and value of the next attribute for vname astruct = read_myATTRIBUTE(vname,anum,CDFid,isglobal=isglobal) nglobal=[nglobal,isglobal] METADATA = create_struct(temporary(METADATA),astruct) endfor ; for each attribute ; ; CDAWeb's listing and write_mycdf s/w rely on the fact that 'fieldnam' is ; the first of the var attrs. Occasionally (see dataset po_k0_hyd) the data cdf ; is such that 'fieldnam' is not the first of the var attrs. Rewritting the ; structure and moving 'fieldnam' to the top seems to fix that problem. ; RCJ 11/05/03 ; tnames=tag_names(metadata) q0=where(tnames eq 'FIELDNAM') if q0[0] ne -1 then begin n0=where(nglobal eq 0) ; variable scope n1=where(nglobal eq 1) ; global scope if q0[0] ne n0[1] then begin ; if fieldnam is not the second 'variable scope' var. ; we do not compare q0[0] and n0[0] because n0[0] is 'varname's ; position. 'Fieldnam' should be the next one, n0[1] si=strtrim(n1[0],2) comm = "tmpstr=create_struct('varname',vname," ; first global attr for ii=0,n_elements(n1)-1 do begin ;do global attr first si=strtrim(n1[ii],2) ;print,si,' g ',tnames[si] comm = comm + "tnames["+si+"],metadata.("+si+")," endfor si=strtrim(q0[0],2) comm=comm + "'FIELDNAM',metadata.("+si+")," for ii=0,n_elements(n0)-2 do begin ;do variable attr now si=strtrim(n0[ii],2) ;print,si,' v ',tnames[si] if tnames[si] ne 'FIELDNAM' and tnames[si] ne 'VARNAME' then begin comm = comm + "tnames["+si+"],metadata.("+si+")," endif endfor si=strtrim(n0[n_elements(n0)-1],2) ; last variable attr comm = comm + "tnames["+si+"],metadata.("+si+")) s=execute(comm) metadata=tmpstr endif endif ; return,METADATA end ;+------------------------------------------------------------------------ ; NAME: Getvar_attribute_names CDFid ; PURPOSE: ; To return all of the attribute names for the requested variable, as ; an array. ; CALLING SEQUENCE: ; att_array = getvar_attribute_names(vname,CDFid, ALL=ALL) ; INPUTS: ; CDFid = integer, id of already opened CDF file ; KEYWORD PARAMETERS: ; ALL - all attributes are returned ; default is that just variable scoped attributes are returned ; OUTPUTS: ; att_array = string array of attribute names ; AUTHOR: ; Tami Kovalick ; tami.kovalick@gsfc.nasa.gov (301)286-9422 ; MODIFICATION HISTORY: ; ;------------------------------------------------------------------------- FUNCTION getvar_attribute_names, CDFid, ALL=ALL cinfo = cdf_inquire(CDFid) ; inquire about the cdf to get #attributes ; Create initial data structure to hold all of the metadata information ; get the names of the attributes ;TJK 1/28/2003 change size because this won't work when data cdfs don't have ;any global attributes att_array = make_array(cinfo.natts-1,/string, value="") ;TJK 3/21/2003 - added a check for when there are no attributes in the data ;cdfs at all... if (keyword_set(ALL)) then all = 1 else all = 0 ;add a keyword to get all attributes if (cinfo.natts gt 0) then begin att_array = make_array(cinfo.natts,/string, value="") i = 0 for anum=0,cinfo.natts-1 do begin cdf_attinq,CDFid,anum,aname,ascope,maxe,maxze ; inquire about the attribute if (((all eq 0) and (ascope eq 'VARIABLE_SCOPE')OR(ascope eq 'VARIABLE_SCOPE_ASSUMED')) or (all eq 1)) then begin aname = strtrim(aname,2) ; trim any possible leading or trailing blanks ;call replace_bad_chars to replace any "illegal" characters in ;the attribute name w/ a legal one. This was necessary for IDL 5.3. aname = replace_bad_chars(aname,repchar="_",found) att_array(i) = aname i = i +1 endif endfor ; for each attribute endif else att_array = make_array(1, /string, value="-1") return,att_array end ;+------------------------------------------------------------------------ ; NAME: GET_NUMALLVARS ; PURPOSE: ; To return the total number of variables in the cdf. ; ; CALLING SEQUENCE: ; num_vars = get_numallvars(CNAME=CNAME) ; INPUTS: ; KEYWORD PARAMETERS: ; CNAME = string, name of a CDF file to be opened and read ; CDFid = integer, id of an already opened CDF file ; OUTPUTS: ; num_vars = number of variables in the CDF ; AUTHOR: ; Tami Kovalick, RITSS, October 27, 2000 ; MODIFICATION HISTORY: ; ;------------------------------------------------------------------------- FUNCTION get_numallvars, CNAME=CNAME, CDFid=CDFid ; validate keyword combination and open cdf if needed if keyword_set(CNAME) AND keyword_set(CDFid) then return,0 ; invalid if keyword_set(CNAME) then CDFindex = CDF_OPEN(CNAME) ; open the cdf if keyword_set(CDFid) then CDFindex = CDFid ; save the cdf file number ; determine the number of variables cinfo = CDF_INQUIRE(CDFindex) ; inquire about number of variables num_vars = cinfo.nvars + cinfo.nzvars if keyword_set(CNAME) then CDF_close,CDFindex ; close the cdf return, num_vars end ;+------------------------------------------------------------------------ ; NAME: GET_ALLVARNAMES ; PURPOSE: ; To return a string array containing the names of all of the ; variables in the given CDF file. ; CALLING SEQUENCE: ; vnames = get_allvarnames() ; INPUTS: ; KEYWORD PARAMETERS: ; CNAME = string, name of a CDF file to be opened and read ; CDFid = integer, id of an already opened CDF file ; VAR_TYPE = string, only return the names for variables who have an ; attribute called 'VAR_TYPE' and whose value matches the ; value given by this keyword. (ex. VAR_TYPE='data') ; OUTPUTS: ; vnames = string array of variable names ; AUTHOR: ; Richard Burley, NASA/GSFC/Code 632.0, Feb 13, 1996 ; burley@nssdca.gsfc.nasa.gov (301)286-2864 ; MODIFICATION HISTORY: ; 4/9/1998 - TJK modified to include all variable when the "var_type" ; keyword isn't used. The original code only included variables ; that vary by record so some important "support_data" variables ; were being thrown out. ;------------------------------------------------------------------------- FUNCTION get_allvarnames, CNAME=CNAME, CDFid=CDFid, VAR_TYPE=VAR_TYPE ; validate keyword combination and open cdf if needed if keyword_set(CNAME) AND keyword_set(CDFid) then return,0 ; invalid if keyword_set(CNAME) then CDFindex = CDF_OPEN(CNAME) ; open the cdf if keyword_set(CDFid) then CDFindex = CDFid ; save the cdf file number ; determine the number of variables cinfo = CDF_INQUIRE(CDFindex) ; inquire about number of variables numvars = cinfo.nvars + cinfo.nzvars & vnames=strarr(numvars) ; Set up an error handler CATCH, Error_status if Error_status ne 0 then begin if keyword_set(CNAME) then cdf_close,CDFindex print, "STATUS= Error reading CDF. " print,!ERR_STRING, "get_allvarnames.pro" & return,-1 endif ; Get the name of every r variable for i=0,cinfo.nvars-1 do begin vinfo = CDF_VARINQ(CDFindex,i) if keyword_set(VAR_TYPE) then begin ; only get VAR_TYPE='data' metadata = read_myMETADATA(vinfo.name,CDFindex) tags = tag_names(metadata) & temp = where(tags eq 'VAR_TYPE',count) if count ne 0 then begin if metadata.VAR_TYPE eq VAR_TYPE then vnames(i) = vinfo.name endif endif else begin vnames(i) = vinfo.name endelse endfor ; Get the name of every z variable for j=0,cinfo.nzvars-1 do begin vinfo = CDF_VARINQ(CDFindex,j,/ZVARIABLE) if keyword_set(VAR_TYPE) then begin ; only get VAR_TYPE='data' metadata = read_myMETADATA(vinfo.name,CDFindex) ;tags = tag_names(metadata) temp = where(tag_names(metadata) eq 'VAR_TYPE',count) if count ne 0 then begin if metadata.VAR_TYPE eq VAR_TYPE then vnames(j+cinfo.nvars) = vinfo.name endif endif else begin vnames(j+cinfo.nvars) = vinfo.name endelse endfor if keyword_set(CNAME) then CDF_CLOSE,CDFindex ; strip blank vnames from the array v = where(vnames ne "",vc) if vc gt 0 then begin temp = strarr(vc) & temp = vnames(v) & vnames = temp endif return,vnames end function write_fill, vn_sdat, burley, tmp_str ;v_err='ERROR=Instrument off; fillval=dat' v_stat='STATUS=Instrument off for variable '+vn_sdat+'. Re-select variable or time. ' atags=tag_names(burley.(0)) b0 = tagindex('LOGICAL_SOURCE',atags) b1 = tagindex('LOGICAL_FILE_ID',atags) b2 = tagindex('Logical_file_id',atags) if (b0(0) ne -1) then psrce = strupcase(burley.(0).LOGICAL_SOURCE) if (b1(0) ne -1) then $ psrce = strupcase(strmid(burley.(0).LOGICAL_FILE_ID,0,9)) if (b2(0) ne -1) then $ psrce = strupcase(strmid(burley.(0).Logical_file_id,0,9)) v_data='DATASET='+psrce ; Reduce the number of reported errors to the developers RTB 1/97 ;tmp_str=create_struct('DATASET',v_data,'ERROR',v_err,'STATUS',v_stat) tmp_str=create_struct('DATASET',v_data,'STATUS',v_stat) ikill=1 return, ikill end ;This function checks to make sure a given variables 'varname' attribute ;actually matches its structure members name. ; function correct_varname, struct, varnames, index ;TJK 09/29/00 Put in a check to make the varname attribute value match ;its variables structure tag name - if it doesn't list_mystruct won't work... ;This is all necessary for the upgrade to IDL5.3 str_index = strtrim(string(index),2) ;convert to string comm = execute('att_names = tag_names(struct.('+str_index+'))') if (comm eq 1) then begin att_v = where(att_names eq 'VARNAME', att_cnt) if (att_cnt gt 0) then begin ;assign the variable name to the "VARNAME" attribute for this variable... ;assign_string = 'struct.'+varnames(index)+'.('+strtrim(string((att_v(0))),2)+')='''+varnames(index)+''' assign_string = 'struct.('+str_index+').('+strtrim(string((att_v(0))),2)+')='''+varnames(index)+''' ;print, 'assign_string = ',assign_string comm = execute(assign_string) if (comm ne 1) then print, 'execute failed for ',assign_string endif endif ;end TJK mod 09/29/00 return, struct end function find_epochvar, CDFid ;Look in the current data cdf and return the actual correct spelling ;of this epoch variable (called only when one doesn't exist). ;This occurs when the master has depend0 = "Epoch" (which many of the datasets ;data files have, but then for whatever reason, a data file has ;the epoch variable spelled as "EPOCH"... which in CDF land is not a match! cinfo = CDF_INQUIRE(CDFid) ; inquire about number of variables numvars = cinfo.nvars + cinfo.nzvars for j=0,numvars-1 do begin vinfo = CDF_VARINQ(CDFid,j,/ZVARIABLE) caps = strupcase(strtrim(vinfo.name,2)); trim blanks and capitalize match = where(caps eq 'EPOCH',match_cnt) if (match_cnt gt 0) then begin ;print, 'epoch match found = ',vinfo.name, ' returning...' return, vinfo.name endif endfor return, -1 ;no match found end function find_var, CDFid, variable ;Look in the current data cdf and return the actual correct spelling ;of this variable (called only when one doesn't exist). ;This can occur when the master has a variable like "Epoch" (which many ;of the datasets data files have, but then for whatever reason, some of the ;data files have the epoch variable spelled as "EPOCH"... which in CDF ;land is not the same variable (variable names are case sensitive)! cinfo = CDF_INQUIRE(CDFid) ; inquire about number of variables numvars = cinfo.nvars + cinfo.nzvars for j=0,numvars-1 do begin vinfo = CDF_VARINQ(CDFid,j,/ZVARIABLE) caps = strupcase(strtrim(vinfo.name,2)); trim blanks and capitalize in_caps = strupcase(strtrim(variable,2)); trim blanks and capitalize match = where(caps eq in_caps,match_cnt) if (match_cnt gt 0) then begin print, variable,' match found = ',vinfo.name, ' returning...' return, vinfo.name endif endfor return, -1 ;no match found end ;Function merge_metadata ;Merge the master and the 1st data cdf's attributes when some of the ;master's attribute values are intensionally left blank. ;This function was originally conceived to accommodate ACE's concerns ;about including the most appropriate metadata with our listings. ;But will likely be used for other datasets/projects. ; ;Written by Tami Kovalick, QSS, 4/8/2005 ; function merge_metadata, cnames, base_struct ; ;Mods: 12/7/2005 by TJK ;Had to change how I dealt w/ multiple element attributes ;originally I just appended elements together so I didn't have to ;remake the variable structure. But listing didn't like character ;strings that were so long. So this routine basically re-builds the ;data structure for every variable just to include multi-element attributes. ;These changes were prompted by "blanking" out many of the global attributes ;in the cluster masters. ; Set up an error handler CATCH, Error_status if Error_status ne 0 then begin if keyword_set(CNAMES) then cdf_close,data_CDFid print,!ERR_STRING, " in merge_metadata" return, burley ;probably not a critical error, just return the buffer endif status = 0 ;do this merge if we have more than two cdfs specified and the 1st one is a master if ((n_elements(cnames) ge 2) and strpos(cnames(0),'00000000') ne -1) then begin data_CDFid = cdf_open(cnames(1)) data_vnames = get_allvarnames(CDFid=data_CDFid) atmp = read_myMETADATA (data_vnames(0), data_CDFid) dnames=tag_names(atmp) data_attr=where(dnames eq 'FIELDNAM') ; this is the break between global and variable attributes bnames=tag_names(base_struct.(0)) base_attr=where(bnames eq 'FIELDNAM') ; this is the break between global and variable attributes tpnames=tag_names(base_struct) cpy_struct = 0 ; initialize a variable that will contain our new structure filled below ;compare atmp values w/ base_struct if (base_attr(0) gt 0 and data_attr(0) gt 0) then begin ;we have global attributes to look at for vars = 0, n_tags(base_struct) - 1 do begin ; for bnum = 0, base_attr(0)-1 do begin for bnum = 0, n_elements(bnames)-1 do begin ;have to do all attributes now ; ;if attributes are variable_scope if (bnum ge base_attr) then begin ;1st in structure (highly unlikely) if (bnum eq 0) then new_struct = create_struct(bnames(bnum),base_struct.(vars).(bnum)) else $ new_struct = create_struct(temporary(new_struct), bnames(bnum),base_struct.(vars).(bnum)) ;if attributes are global_scope endif else begin if (base_struct.(vars).(bnum)(0) ne '') then begin ;global attribute isn't blank in master... ;if 1st attribute if (bnum eq 0) then new_struct = create_struct(bnames(bnum),base_struct.(vars).(bnum)) else $ new_struct = create_struct(temporary(new_struct), bnames(bnum),base_struct.(vars).(bnum)) endif else begin ;attribute IS blank in master get value for data cdf ;**** have to match up the tag names so get the values in the right places. s = where(dnames eq bnames(bnum), wc) ; print, 'DEBUG1 current master attribute ',bnames(bnum) if (wc gt 0) then begin ; print, 'DEBUG2 found in data ',bnames(bnum) if (atmp.(s(0))(0) ne '') then begin ; print, 'DEBUG Setting missing attribute value ', bnames(bnum), ' = ',atmp.(s(0)), ' from value found in 1st data cdf' if (n_tags(new_struct) eq 0) then begin new_struct = create_struct(bnames(bnum),atmp.(s(0))) endif else begin new_struct = create_struct(temporary(new_struct), bnames(bnum),atmp.(s(0))) endelse endif ;value is good in data cdf endif ; found an attribute match between data and master endelse ;attribute value is blank endelse ;attribute is global scope endfor if (n_tags(cpy_struct) eq 0) then cpy_struct = create_struct(tpnames(vars),new_struct) else $ cpy_struct = create_struct(temporary(cpy_struct),tpnames(vars),new_struct) endfor ; RCJ 12/13/05 wind 3dp data has no global or var attributes ; so data_attr(0) = -1 and we get here. We still want ; to return the structure so make cpy_struct=base_struct : endif else cpy_struct = temporary(base_struct) cdf_close,data_CDFid endif else cpy_struct = temporary(base_struct) return, cpy_struct end ;+------------------------------------------------------------------------ ; NAME: READ_MYCDF ; PURPOSE: ; Read all data and metadata for given variables, from given CDF ; files, and return all information in a single anonymous structure ; of the form: ; structure_name.variable_name.attribute_name.attribute_value ; ; CALLING SEQUENCE: ; out = read_mycdf(vnames,cnames) ; INPUTS: ; vnames = string, array of variable names or a single string of ; names separated by a comma. (ex. 'Epoch,Magfld,Bmax') ; cnames = string, array of CDF filenames or a single string of ; names separated by a comma. ; KEYWORD PARAMETERS: ; ALL = 0: get data and metadata for requested variable(s) only. ; 1: get data and metadata for ALL variables in the CDFs. ; 2: get data and metadata for all var_type='data' variables. ; NODATASTRUCT = If set, instead of returning the data for each variable ; in the 'DAT' attribute field, create a 'HANDLE' field ; and set it to the handle id of a data handle which ; holds the data for each variable. ; NOQUIET = If set, do NOT set the !QUIET system variable before ; reading the cdf file(s). ; DEBUG = If set, print out some progress information during reading. ; TSTART = epoch starting value - YYYYMMDD etc. string. ; TSTOP = epoch ending value - YYYYMMDD etc. string. ; OUTPUTS: ; out = anonymous structure holding all data and metadata for the ; requested variables. If an error occurs, that we know how ; to deal w/, an alternate structure is returned, its structure ; is as follows: ('DATASET',d_set,'ERROR',v_err,'STATUS',v_stat) ; ; AUTHOR: ; Richard Burley, NASA/GSFC/Code 632.0, Feb 13, 1996 ; burley@nssdca.gsfc.nasa.gov (301)286-2864 ; MODIFICATION HISTORY: ; Tami Kovalick, HSTX, 12/16/96 modified to verify whether ; variables requested in vnames array are actually in the "data" cdfs ; prior to requesting the data from these variables. If variables ; aren't valid then they are removed from the vnames array and the ; code continues on to create a valid structure. ; Tami Kovalick, HSTX, 12/20/96 modified to allow the use of ; TSTART and TSTOP keywords (see above). Use of these keywords will ; force the code to only read the necessary records in the CDF, otherwise ; the code will read the entire CDF. Could enhance the code to deal ; w/ one or the other keyword - right now they are only used if both ; are set. ; Tami Kovalick, RSTX, 02/13/98, Carrie Gallap started modifications ; to read_myCDF to accommodate "virtual variables" (VV) . Tami finished ; up the code and made corrections to several sections. One new routine was ; written add_myCOMPONENTS, this routine is called when a valid virtual ; variable is found in order to add any additional variables needed for ; actually generating the data for the VV. The routine looks for variable ; attributes w/ the naming convention COMPONENT_n where n is a digit. The ; basic methodology to the changes is to determine whether any of the ; variables selected are virtual variables, if so then the variable name ; and the source (where the VV was defined - master or data cdfs) are ; stored in a structure called vir_vars, then add the component variables ; to the vnames array. Do the usual checking to see if the variables requested ; in vnames actually exist. Then continue on w/ getting the metadata for all ; variables (including VV), and continue on w/ the getting the data from ; the CDFs for all variables except the VV. Population of the VV's data field ; in the "burley" structure are handled at the very end in a case statement ; which looks for each VV's variable attribute FUNCTION to determine which ; actual "IDL function" to call, ie. conv_pos. ;------------------------------------------------------------------------- FUNCTION read_myCDF, vnames, cnames, ALL=ALL,NODATASTRUCT=NODATASTRUCT, $ NOQUIET=NOQUIET,DEBUG=DEBUG, $ TSTART=TSTART, TSTOP=TSTOP, $ START_MSEC=START_MSEC, STOP_MSEC=STOP_MSEC, START_USEC=START_USEC, $ STOP_USEC=STOP_USEC, START_NSEC=START_NSEC, STOP_NSEC=STOP_NSEC, $ START_PSEC=START_PSEC, STOP_PSEC=STOP_PSEC, NOVIRTUAL=NOVIRTUAL ; establish exception handler to trap errors from all sources. CATCH,error_status if (error_status ne 0) then begin print,!ERR_string ," Trapped in read_myCDF."; output description of error print,'Error Index=',error_status ;also need to check for -123 for IDL 5.02, -98 is for IDL 4.01b - TJK 1/23/98 ;added check for -134 out of memory in IDL5.3 ; added check for the string "unable to allocate memory", since IDL seems ; to change the error number associated w/ this w/ each release if((strpos(!ERR_string, "Unable to allocate memory") gt -1) or error_status eq -98 or error_status eq -123 or error_status eq -124 or error_status eq -134) then begin val_err="ERROR=Memory Exceeded; -98 or -123 or -124 or -134 or -151" val_stat="STATUS=Time range selected generates array which exceeds available system resources. Re-select a smaller time range." ; if(n_elements(mydata) ne 0) then begin atags=tag_names(mydata.(0)) b0 = tagindex('LOGICAL_SOURCE',atags) b1 = tagindex('LOGICAL_FILE_ID',atags) b2 = tagindex('Logical_file_id',atags) if (b0(0) ne -1) then psrce = strupcase(mydata.(0).LOGICAL_SOURCE) if (b1(0) ne -1) then $ psrce = strupcase(strmid(mydata.(0).LOGICAL_FILE_ID,0,9)) if (b2(0) ne -1) then $ psrce = strupcase(strmid(mydata.(0).Logical_file_id,0,9)) v_data='DATASET='+psrce endif else begin parts=str_sep(cnames(cx),'/') piece=strupcase(str_sep(parts(n_elements(parts)-1),'_')) tempnm= piece(0)+'_'+piece(1)+'_'+piece(2) val_data="DATASET="+tempnm endelse tmpstr=create_struct('DATASET',val_data,'ERROR',val_err,'STATUS',val_stat) return, tmpstr endif return,-1 ; return failure flag endif if keyword_set(DEBUG) then debug = 1 else debug=0 need_timeslice = 0L ;initialize ; Validate cnames parameter, remove .cdf extensions if present s = size(cnames) & ns = n_elements(s) if (s(ns-2) eq 7) then begin if (s(0) eq 0) then cnames = break_mySTRING(cnames,DELIMITER=',') for i=0,n_elements(cnames)-1 do begin j=strpos(cnames(i),'.cdf') & if (j eq -1) then j=strpos(cnames(i),'.CDF') if (j ne -1) then cnames(i) = strmid(cnames(i),0,j) endfor endif else begin print,'ERROR=CDF filenames must be given as strings.' & return,-1 endelse if keyword_set(DEBUG) then print,'Number of CDFs to read=',n_elements(cnames) quiet_flag = !quiet ; save current state of quiet flag if not keyword_set(NOQUIET) then !quiet=1 ; turn off annoying cdf messages ;print, 'Announcement of annoying CDF messages = ', !quiet ;TJK setup a structure called table to hold the variable name as they are in ;the cdf and then an 'equivalent' name if the real variable name turned out to ;contain "illegal characters", e.g. "!,@,#" etc.. common global_table, table num_vars = get_numallvars(CNAME=cnames(0)) var_names = strarr(num_vars) ;varname will contain the real cdf variable name(s) ;equiv will contain the "fake" one(s) table = create_struct('varname',var_names,'equiv',var_names) ; If the ALL keyword is set then get names of all data variables ; RCJ 11/21/2003 Added another option for 'all'. Now if all=0: read requested ; var(s); if all=1: read all vars; if all=2: read all 'data' vars if keyword_set(ALL) then begin if all eq 1 then vnames = get_allvarnames(CNAME=cnames(0)) if all eq 2 then vnames = get_allvarnames(CNAME=cnames(0),var_type='data') endif ;make a copy of the vnames in the orig_names array for use w/ ;virtual variables and/or alternate views. TJK 2/4/98 orig_names = vnames ; RCJ 01/10/2005 Commented this part out. Call func ; add_mydeltas instead. ; ;for cx=0,n_elements(cnames)-1 do begin ; ; RCJ 08/25/2003 I was trying to save time with the 'if' below but the error ; ; vars were not being read for cdfs created by write_mycdf since they don't ; ; require a master cdf. ; ;if (strpos(cnames(cx),'00000000') ne -1) then begin ;a master ; CDFid = cdf_open(cnames(cx)) ; ; ; for nreq =0, n_elements(vnames)-1 do begin ; atmp = read_myMETADATA (vnames(nreq), CDFid) ; atags = tag_names (atmp) ; b0 = tagindex ('DELTA_PLUS_VAR', atags) ; if (b0(0) ne -1) then begin ; if (atmp.(b0(0)) ne '') then begin ; ; avoiding duplication: ; q=where(vnames eq atmp.(b0(0))) ; if q(0) eq -1 then vnames=[vnames,atmp.(b0(0))] ; endif ; endif ; b1 = tagindex ('DELTA_MINUS_VAR', atags) ; if (b1(0) ne -1) then begin ; if (atmp.(b1(0)) ne '') then begin ; ; avoiding duplication: ; q=where(vnames eq atmp.(b1(0))) ; if q(0) eq -1 then vnames=[vnames,atmp.(b1(0))] ; endif ; endif ; endfor ; cdf_close,CDFid ; ;endif ;endfor ; ; ; Validate vnames parameter. May be a strarr or single string s = size(vnames) & ns = n_elements(s) if (s(ns-2) eq 7) then begin if (s(0) eq 0) then vnames = break_mySTRING(vnames,DELIMITER=',') endif else begin print,'ERROR=variable names must be given as strings.' & return,-1 endelse ;TJK 10/8/2003 - move this initialization up on the code so that ;inadvertent variables don't get added to the list. ;make a copy of the vnames in the orig_names array for use w/ ;virtual variables and/or alternate views. TJK 2/4/98 ;orig_names = vnames ;TJK - 12/16/96 ; added this section of code to check whether the requested variables ;are actually in the CDFs (other than the master CDFs). If not, take them ;out... and continue building the structure w/ the resultant variables. rcount = n_elements(vnames) num_virs = -1 ; keep counter of number of virtual variables found virs_found = 0L ;TJK 11/28/2006 set a flag, so that if virtual variables are found in the master, ;don't check in the data cdf. ;create a structure to contain the virtual variable name and whether ;the variable was found in the master or in a data CDF, set to ;0 or 1 respectively. ; Added arbitrary # of 10 to structure; need space for vv depends RTB 3/98 ;TJK 11/16/2006 - increase the size of the vir_vars structure because ; we have some datasets (THEMIS all sky imagers) that ; define many virtual variable depends, so set array ; to the total number of variables in the cdf. ;n_tmp = strarr(n_elements(vnames)+10) ; initialize it ;m_tmp = make_array(n_elements(vnames)+10,/integer, value=-1) n_tmp = strarr(num_vars) ; initialize it m_tmp = make_array(num_vars,/integer, value=-1) vir_vars= create_struct('name',n_tmp,'flag',m_tmp) ; RCJ 09/19/05 We are going to use the isis_flag for alouette-2 data too. isis_flag = 0 for cx=0,n_elements(cnames)-1 do begin if (rcount gt 0) then begin ; Open the CDF and inquire about global information about file if (debug) then print,'Verifying variables in ',cnames(cx) CDFid = cdf_open(cnames(cx)) & cinfo = cdf_inquire(CDFid) ; if there is a master, look there for virtual variables that may not ; be defined in the actual cdfs... if (strpos(cnames(cx),'00000000') ne -1) then begin ;a master ; if (debug) then print, 'checking ',cnames(cx), ' for Virtual variables'; ;read the metadata for the variables requested from the master... vdep_cnt=0; ; RCJ 04/18/2003 Going to concatenate the strings instead of limiting ; their number to 20. At the end we take: chkvv_dep=chkvv_dep[1:*] ;chkvv_dep=strarr(20) chkvv_dep='' for nreq =0, n_elements(vnames)-1 do begin atmp = read_myMETADATA (vnames(nreq), CDFid) atags = tag_names (atmp) ;TJK 09/28/2001 add code to flag whether we're looking at an ISIS mission, if so set ; a flag that's used lower down. We need to check here in the master instead of in ; the data cdfs because lots of data cdf's don't have a mission_group global attribute. b0 = tagindex ('MISSION_GROUP', atags) if (b0(0) ne -1) then begin if ((strupcase(atmp.mission_group(0)) eq 'ISIS') or $ (strupcase(atmp.mission_group(0)) eq 'ALOUETTE')) $ then isis_flag = 1 ;if (strupcase(atmp.mission_group(0)) eq 'ISIS') then isis_flag = 1 endif ;TJK 11/23/2005 add logic to look for virtual depend variables related ;to "regular" variables... for some reason we haven't needed this till ;now! b1 = tagindex ('DEPEND_0', atags) if (b1(0) ne -1 ) then begin if (atmp.depend_0 ne '') then begin num = where(chkvv_dep eq atmp.depend_0, cnt) if (cnt eq 0) then begin chkvv_dep=[chkvv_dep,atmp.depend_0] vdep_cnt=vdep_cnt+1 endif endif endif b1 = tagindex ('DEPEND_1', atags) if (b1(0) ne -1 ) then begin if (atmp.depend_1 ne '') then begin num = where(chkvv_dep eq atmp.depend_1, cnt) if (cnt eq 0) then begin chkvv_dep=[chkvv_dep,atmp.depend_1] vdep_cnt=vdep_cnt+1 endif endif endif b1 = tagindex ('DEPEND_2', atags) if (b1(0) ne -1 ) then begin if (atmp.depend_2 ne '') then begin num = where(chkvv_dep eq atmp.depend_2, cnt) if (cnt eq 0) then begin chkvv_dep=[chkvv_dep,atmp.depend_2] vdep_cnt=vdep_cnt+1 endif endif endif ;if (debug) then print, 'At bottom of new section = ',chkvv_dep ;TJK 11/23/2005 - end of new section, back to original section looking ; for virtual variables w/in virtual variables b0 = tagindex ('VIRTUAL', atags) ;look through metadata and look for virtual variables... ; get components of the virtual variables and add them to the vnames ; array... if (b0(0) ne -1 ) then begin if (strlowcase(atmp.VIRTUAL) eq 'true') then begin if (DEBUG) then print, 'Found a VV ',vnames(nreq),' in Master CDF.' num_virs = num_virs + 1 vir_vars.name(num_virs) = vnames(nreq) vir_vars.flag(num_virs) = 0 ;indicate this var found in master print, 'found a VV ', vnames(nreq), ' in Master CDF.' print, 'adding deltas and components next...' add_myDELTAS, atmp, vnames add_myCOMPONENTS, atmp, vnames ; Check VV's depends for other VV's and add to list ;TJK 11/98 added logic to only add the variable if it doesn't ;already exist in the chkvv_dep list. b1 = tagindex ('DEPEND_0', atags) if (b1(0) ne -1 ) then begin if (atmp.depend_0 ne '') then begin num = where(chkvv_dep eq atmp.depend_0, cnt) if (cnt eq 0) then begin ;chkvv_dep(vdep_cnt)=atmp.depend_0 chkvv_dep=[chkvv_dep,atmp.depend_0] vdep_cnt=vdep_cnt+1 endif endif endif b1 = tagindex ('DEPEND_1', atags) if (b1(0) ne -1 ) then begin if (atmp.depend_1 ne '') then begin num = where(chkvv_dep eq atmp.depend_1, cnt) if (cnt eq 0) then begin ;chkvv_dep(vdep_cnt)=atmp.depend_1 chkvv_dep=[chkvv_dep,atmp.depend_1] vdep_cnt=vdep_cnt+1 endif endif endif b1 = tagindex ('DEPEND_2', atags) if (b1(0) ne -1 ) then begin if (atmp.depend_2 ne '') then begin num = where(chkvv_dep eq atmp.depend_2, cnt) if (cnt eq 0) then begin ;chkvv_dep(vdep_cnt)=atmp.depend_2 chkvv_dep=[chkvv_dep,atmp.depend_2] vdep_cnt=vdep_cnt+1 endif endif endif ;TJK - 1/29/2001 add a check to see whether the component ; variables are virtual b1 = tagindex ('COMPONENT_0', atags) if (b1(0) ne -1 ) then begin if (atmp.component_0 ne '') then begin num = where(chkvv_dep eq atmp.component_0, cnt) if (cnt eq 0) then begin ;chkvv_dep(vdep_cnt)=atmp.component_0 chkvv_dep=[chkvv_dep,atmp.component_0] vdep_cnt=vdep_cnt+1 endif endif endif b1 = tagindex ('DELTA_PLUS_VAR', atags) if (b1(0) ne -1 ) then begin if (atmp.delta_plus_var ne '') then begin num = where(chkvv_dep eq atmp.delta_plus_var, cnt) if (cnt eq 0) then begin chkvv_dep=[chkvv_dep,atmp.delta_plus_var] vdep_cnt=vdep_cnt+1 endif endif endif b1 = tagindex ('DELTA_MINUS_VAR', atags) if (b1(0) ne -1 ) then begin if (atmp.delta_minus_var ne '') then begin num = where(chkvv_dep eq atmp.delta_minus_var, cnt) if (cnt eq 0) then begin chkvv_dep=[chkvv_dep,atmp.delta_minus_var] vdep_cnt=vdep_cnt+1 endif endif endif endif ; if atmp.virtual eq true endif ; if b0(0) ne -1 endfor ; Now check the depend var's of the VV for VV if(vdep_cnt gt 0) then begin ;cwc=where(chkvv_dep ne '',cwcn) ;chkvv_dep=chkvv_dep(cwc) chkvv_dep=chkvv_dep[1:*] for nvvq =0, n_elements(chkvv_dep)-1 do begin atmp = read_myMETADATA (chkvv_dep(nvvq), CDFid) atags = tag_names (atmp) b0 = tagindex ('VIRTUAL', atags) if (b0(0) ne -1 ) then begin if (strlowcase(atmp.VIRTUAL) eq 'true') then begin ;TJK 11/28/2006 - need to check to see if this virtual variable is in ; the vnames array, if not add it. This is the case ; for the THEMIS epoch variables since none of them ; are "real" variables". v_index = where(vnames eq chkvv_dep(nvvq) , v_count) if (v_count eq 0) then begin ;need to add to vnames if (DEBUG) then print, 'Found a VV ',chkvv_dep(nvvq),' among Depends; adding to vnames.' vnames = [vnames,chkvv_dep(nvvq)] endif num_virs = num_virs + 1 vir_vars.name(num_virs) = chkvv_dep(nvvq) vir_vars.flag(num_virs) = 0 ;indicate this var found in master add_myDELTAS, atmp, vnames add_myCOMPONENTS, atmp, vnames endif endif endfor endif ; if (vdep_cnt gt 0) endif ;endif a master ;TJK 1/2/2007 - still have to determine how many virtual variables ; there are for use lower down so can't set this for ; keyword_set(ALL) ; if (num_virs ge 0 or keyword_set(ALL)) then virs_found = 1L if (num_virs ge 0) then virs_found = 1L if keyword_set(DEBUG) then print, 'end of master cdf section ',vnames ; Continue to process vnames array... ; Possibly the virtual variable is defined in a data cdf, check for ; that... if (strpos(cnames(cx),'00000000') eq -1) then begin ;not a master ; RCJ 02/02/2005 Added lines below. If we are not using a master cdf ; or if we are using a cdf generated by write_myCDF ; then the deltas and components are added to vnames here: if cx eq 0 then begin ; first cdf only. This could ; represent a problem but I'm trying to avoid cases ; like the one described by TJK 8/27/2002 below. for nreq =0, n_elements(vnames)-1 do begin atmp = read_myMETADATA (vnames(nreq), CDFid) add_mydeltas, atmp, vnames add_mycomponents, atmp, vnames endfor endif ;if this is not a master cdf we want to check to make sure all of the ;variables that were requested (in vnames) actually exist in this cdf. ;If not, do not ask for them... doing so causing problems... ; look for the requested variable in the whole list of vars in this cdf all_cdf_vars = get_allvarnames(CDFid = CDFid) ; Look to see if a virtual variable is defined in the cdf file... ; if (debug) then print, 'checking the data cdf for virtual variables ' att_names = getvar_attribute_names (CDFid, /ALL) ;added all keyword, default ;is the variable attributes ;TJK if no attributes are found, a -1 is returned above - which should ;kick out below. ;TJK 11/28/2006 - add check for virs_found, if ;already found in master, don't check below afound = where(att_names eq 'VIRTUAL', acnt) if (acnt eq 1 and not(virs_found)) then begin ; continue on w/ the checking otherwise get out for nvar = 0, (n_elements(all_cdf_vars)-1) do begin ;TJK 8/27/2002 replaced call to read_myMETADATA since we found at least ; one case w/ c*_pp_whi where doing so severely hampered performance ; because some attributes had many thousands of entries. ; atmp = read_myMETADATA (all_cdf_vars(nvar), CDFid) ; Replaced w/ call to getvar_attribute_names and where statement, then ; only get into this for loop if the VIRTUAL attribute actually exists... ; Now, just get the value for the VIRTUAL attribute, not all ; attributes atmp = read_myATTRIBUTE(all_cdf_vars(nvar),afound(0),CDFid) ;this section finds all virtual variables in the data cdf atags = tag_names (atmp) b0 = tagindex ('VIRTUAL', atags) if (b0(0) ne -1) then begin if (strlowcase(atmp.VIRTUAL) eq 'true') then begin if (debug) then print, 'found a VIRTUAL tag for ',all_cdf_vars(nvar) ;check to see if the vir_var is already in the array, ; if so don't add it to the array. if (num_virs ge 1) then begin c = where(vir_vars.name eq all_cdf_vars(nvar), cnt) ;compare this one with the vir_vars if (cnt eq 0) then begin ;if this one isn't in vir_vars add it. num_virs = num_virs+1 vir_vars.name(num_virs) = all_cdf_vars(nvar) vir_vars.flag(num_virs) = 1 ;indicate this var found in data cdf if (DEBUG) then print, 'Found a VV ',all_cdf_vars(nvar),' in data CDF' endif endif else begin num_virs = num_virs+1 vir_vars.name(num_virs) = all_cdf_vars(nvar) vir_vars.flag(num_virs) = 1 ;indicate this var found in data cdf if (DEBUG) then print, 'Found a VV ',all_cdf_vars(nvar),' in data CDF' endelse endif endif endfor ;TJK 11/30/2006 - moved this endif down below the next section of code, since we ; don't want to add more depends and components if a master was ; present ; endif ;TJK added on 8/27/2002 to match further checking for the VIRTUAL ;attribute. ; If virtual variables were found in the cdf, see if they were requested... dnames='' & cmpnames='' for req_vars=0, (n_elements(vnames)-1) do begin ;TJK 11/29/2006 - add code to get depends and components ;for requested vnames - add to the vnames array a little ;lower down. dtmp = read_myMETADATA (vnames(req_vars), CDFid) add_myDEPENDS, dtmp, dnames for delts = 0, n_elements(dnames)-1 do begin ctmp = read_myMETADATA (dnames(delts), CDFid) add_myCOMPONENTS,ctmp, cmpnames endfor vcdf = where(vir_vars.name eq vnames(req_vars), v_cnt) ;virtual has been requested... if (vcdf(0) ne -1L) then begin ; found in data cdf (vs. Master cdf) so we need to add it if(vir_vars.flag(num_virs)) then begin if (debug) then print, 'Add components for VV, ',vnames(req_vars) atmp = read_myMETADATA (vnames(req_vars), CDFid) add_myDELTAS, atmp, vnames add_myCOMPONENTS, atmp, vnames endif endif endfor ;Concatenate depends and component variables to the vnames array ;Make sure not to add any blanks or variables that are already ;in vnames. x = where(dnames ne '',xcnt) y = where(cmpnames ne '',ycnt) if (xcnt gt 0)then begin vnames = [vnames,dnames(x)] ;append them and then sort out duplicates vnames = vnames[uniq(vnames,sort(vnames))] endif if (ycnt gt 0)then begin vnames = [vnames,cmpnames(y)] vnames = vnames[uniq(vnames,sort(vnames))] endif endif ;TJK added on 8/27/2002 to match further checking for the VIRTUAL ;attribute. ; Now check that all variables requested, and components of virtuals, are ; found in the cdf file... for req_vars=0, (n_elements(vnames)-1) do begin ; if (DEBUG) then print, 'Checking to see if variables are actually in this data cdf.' fcdf = where(all_cdf_vars eq vnames(req_vars), found_cnt) if (fcdf(0) eq -1L) then begin ;didn't find requested variable. ;Make sure you don't blank out a virtual variable that has ;been defined in a master... vcdf = where (vir_vars.name eq vnames(req_vars), v_cnt) ;TJK added code to check whether vnames(req_vars) is a variable that has been altered ;because its original name had "invalid" characters in it - if it was altered, do ;not throw it out... 10/31/2000 table_index = where(table.equiv eq vnames(req_vars), tcount) if (tcount gt 0) then begin ;before adding the table.varname to vnames, make sure it isn't already there... already_there = where(table.varname(table_index(0)) eq vnames, already_cnt) if (already_cnt eq 0) then begin vnames(req_vars) = table.varname(table_index(0)) ;another name needs to be used in order to get ;the data out of the cdf endif ;TJK removed this - this shouldn't be necessary 1/29/2001 ; else vnames(req_vars) = ' ' ; so blank it out endif ;No, this is not a virtual variable ;TJK modified if (vcdf(0) eq -1L) then begin if (vcdf(0) eq -1L and tcount eq 0) then begin if (DEBUG) then print,'Variable ',vnames(req_vars),$ ' not found in this data cdf - throwing out.' vnames(req_vars) = ' ' ; so blank it out endif endif endfor ;for each requested variable if (DEBUG) then print, 'made it through SETUP for DATA cdfs' endif ; if not a master cdf real_vars = where(vnames ne ' ', rcount); if (rcount gt 0) then vnames = vnames(real_vars) cdf_close,CDFid ; close the open cdf endif endfor ; for each cdf if keyword_set(DEBUG) then print, 'end of data cdf section ',vnames ;end TJK modifications dhids = lonarr(n_elements(vnames)) ; create array of handle ids for data mhids = lonarr(n_elements(vnames)) ; create array of handle ids for metadata vvarys = strarr(n_elements(vnames)) ; initialize variable variance array cdftyp = strarr(n_elements(vnames)) ; initialize cdftype array if (rcount gt 0) then begin ; check whether there are any variables to retrieve ; get the data and metadata for all variables from all cdfs mastervary='' for cx=0,n_elements(cnames)-1 do begin ; Open the CDF and inquire about global information about file CDFid = cdf_open(cnames(cx)) & cinfo = cdf_inquire(CDFid) if keyword_set(DEBUG) then print, 'Opening CDF ',cnames(cx) ;TJK had to add the following two calls to cdf_control in order ;to get the proper number of maxrecs down below - this was needed ;for IDL v5.02 cdf_control, CDFid, SET_ZMODE=2 ;set zmode so that i can always know that ;the variables are z variables for next line. cdf_control, CDFid, VAR=0, /Zvariable, GET_VAR_INFO=vinfo2 ; inquire more about the var ; TJK - 12/20/96 - added this section plus some modifications below ; to only get the data for requested time range. This should significantly ; help conserve memory usage in this s/w. start_rec = 0L ;initialize to read the whole cdf. ;TJK changed this since the maxrec coming back from cdf_inquire only ;applies to R variables under IDL v5.02, so if you don't have any R ;variables in your CDF, maxrec will come back as -1... ; rec_count = cinfo.maxrec+1 ; initialize to read all records rec_count = vinfo2.maxrecs+1 ; initialize to read all records ; ;TJK 7/21/2006 initialize some arrays to hold the extra time resolution values msec = make_array(2, /integer, value=0) usec = make_array(2, /integer, value=0) nsec = make_array(2, /integer, value=0) psec = make_array(2, /integer, value=0) if (keyword_set(START_MSEC)) then msec[0] = START_MSEC if (keyword_set(STOP_MSEC)) then msec[1] = STOP_MSEC if (keyword_set(START_USEC)) then usec[0] = START_USEC if (keyword_set(STOP_USEC)) then usec[1] = STOP_USEC if (keyword_set(START_NSEC)) then nsec[0] = START_NSEC if (keyword_set(STOP_NSEC)) then nsec[1] = STOP_NSEC if (keyword_set(START_PSEC)) then psec[0] = START_PSEC if (keyword_set(STOP_PSEC)) then psec[1] = STOP_PSEC if (keyword_set(TSTART) and keyword_set(TSTOP))then begin ;convert the TSTART and TSTOP to double precision numbers. ;Get the epoch variable data first, determine ;which records fall within the TSTART and TSTOP range. start_time = 0.0D0 ; initialize b = size(TSTART) & c = n_elements(b) ;TJK 7/20/2006 - original code. New code gets epoch in original epoch ; and in epoch16 so that either can be used lower down ; in the code... ; if (b(c-2) eq 5) then start_time = TSTART $ ; double float already ; else if (b(c-2) eq 7) then start_time = encode_cdfepoch(TSTART) ; string ; stop_time = 0.0D0 ; initialize ; b = size(TSTOP) & c = n_elements(b) ; if (b(c-2) eq 5) then stop_time = TSTOP $ ; double float already ; else if (b(c-2) eq 7) then stop_time = encode_cdfepoch(TSTOP); string if (b(c-2) eq 5) then start_time = TSTART $ ; double float already else if (b(c-2) eq 7) then begin start_time = encode_cdfepoch(TSTART, MSEC=msec[0]) ; string start_time16 = encode_cdfepoch(TSTART,/EPOCH16, MSEC=msec[0], $ USEC=usec[0], NSEC=nsec[0], $ PSEC=psec[0]) ;string endif stop_time = 0.0D0 ; initialize b = size(TSTOP) & c = n_elements(b) if (b(c-2) eq 5) then stop_time = TSTOP $ ; double float already else if (b(c-2) eq 7) then begin stop_time = encode_cdfepoch(TSTOP, MSEC=msec[1]) ; string stop_time16 = encode_cdfepoch(TSTOP,/EPOCH16, MSEC=msec[1], $ USEC=usec[1], NSEC=nsec[1], $ PSEC=psec[1]) ;string endif endif ;end TJK TSTART and TSTOP modifications. vnn=0 vn_sdat=strarr(n_elements(vnames)+40) all_cdf_vars = get_allvarnames(CDFid = CDFid) ;get the list of vars in the current CDF. ; Read all of the selected variables from the open CDF vx = 0 & REPEAT begin ;TJK check to see if the current variable exists in this CDF. ;if not go to the bottom of the repeat. 5/1/98 found = where(all_cdf_vars eq vnames(vx), found_cnt) ;if the variable isn't found try to find it w/ a different spelling - the ;case that we know exists is w/ geotail orbit files, most data files and the ; master cdf have the variable Epoch, some data cdfs have it spelled EPOCH... if (found_cnt eq 0L) then begin new_name = find_var(CDFid, vnames(vx)) ; return the actual ;correct spelling of the variable if (strtrim(string(new_name),2) ne '-1') then begin print, 'replacing vnames ',vnames(vx), ' w/ ',new_name vnames(vx) = new_name found_cnt = 1L endif endif if (found_cnt gt 0L) then begin ;did find requested variable. ;TJK added this next section so that the vvarys array is ;actually set for all of the variables. 4/98 ;TJK 10/5/2006 only initialize the vvarys and cdftyp to novary and ' ' ;if this cdf is a master. Otherwise vvs info were being wiped out. if (strpos(cnames(cx),'00000000') ne -1) then begin ;a master vvarys(vx) = 'NOVARY' cdftyp(vx) = ' ' endif if (num_virs gt -1) then begin vv = where(vnames(vx) eq vir_vars.name, vv_cnt) ;if this var is not virtual or looking in a master CDF if ((vv_cnt le 0) or (cx eq 0)) then begin vinfo = cdf_varinq(CDFid,vnames(vx)) ; inquire about the variable vvarys(vx) = vinfo.RECVAR cdftyp(vx) = vinfo.DATATYPE endif endif else begin vinfo = cdf_varinq(CDFid,vnames(vx)) ; inquire about the variable vvarys(vx) = vinfo.RECVAR cdftyp(vx) = vinfo.DATATYPE endelse ;end of TJK mods. 4/98 ; Read the data for the variable unless it is known to be non varying if (vvarys(vx) ne 'NOVARY') then begin ; Determine rec_count from depend_0 of current variable; check start & stop times RTB 9/30/97 if (keyword_set(TSTART) and keyword_set(TSTOP))then begin ; Need to find depend_0 for the current variable ;TJK - 12/20/96 added the use of the start_rec and rec_count keywords. if (cx eq 0) then begin ;TJK only get the metadata from the 1st cdf. ;read this metadata from a master CDF only atmp=read_myMETADATA(vnames(vx), CDFid) endif else begin ;get the already retrieved data out of the handle handle_value, mhids(vx), atmp endelse mnames=tag_names(atmp) ; If a depend0 is not defined for a variable, read ;entire cdf (no time limits applied. RTB nck=where(mnames eq 'DEPEND_0',dum) if(nck(0) ne -1L) then depend0=atmp.depend_0 $ else begin if keyword_set(DEBUG) then print, "No depend_0 attribute, read entire cdf" start_rec = 0L goto, NO_VAR_ATT endelse nck=where(mnames eq 'VAR_TYPE',dum) if(nck(0) ne -1L) then vartype=atmp.var_type $ else begin if keyword_set(DEBUG) then print, "No variable attribute, read entire cdf" start_rec = 0L goto, NO_VAR_ATT endelse ;RTB - 10/03/97 added code to distinguish b/w epoch and other data ;read all epoch data then apply start and stop times ;TJK Jan.17, 2003 - had to remove this section - found a case w/ equator s ;data that contain variable names including "%", that the following code won't work w/. ;TJK - determine if there is a variable in this data cdf that matches the ;depend0 - we have cases were this isn't the case, e.g. depend0 = Epoch, ;the real data variable is named EPOCH... if not, this catch should detect this, and ;then find the correct spelled epoch variable in this data cdf... ; tami = 0 ;TJK debugging... ; CATCH,error_status ; if ((error_status ne 0) and (depend0 ne '')) then begin ; ;found case where depend0 variable doesn't really exist in the data cdf ; ;send depend0 to blank so we'll read the entire cdf ; print, 'variable ',depend0,' not found in this cdf, trying to correct spelling' ; depend0 = find_epochvar(CDFid) ; return the actual ; ;correct spelling of the depend0 variable ; ; if (strtrim(string(depend0),2) eq '-1') then begin ; v_err='ERROR=Depend0 variable for variable '+vnames(vx)+' not found in data cdf' ; v_stat='STATUS=Depend0 variable for variable '+vnames(vx)+$ ; ' not found. CDAWeb support staff has been notified. ' ; atags=tag_names(atmp) ; b0 = tagindex('LOGICAL_SOURCE',atags) ; b1 = tagindex('LOGICAL_FILE_ID',atags) ; b2 = tagindex('Logical_file_id',atags) ; if (b0(0) ne -1) then psrce = strupcase(atmp.LOGICAL_SOURCE) ; if (b1(0) ne -1) then psrce = strupcase(strmid(atmp.LOGICAL_FILE_ID,0,9)) ; if (b2(0) ne -1) then psrce = strupcase(strmid(atmp.Logical_file_id,0,9)) ; v_data='DATASET='+psrce ; ; Reduce the number of reported errors to the developers RTB 1/97 ; tmp_str=create_struct('DATASET',v_data,'ERROR',v_err,'STATUS',v_stat) ; return, tmp_str ; endif ; print, '****depend0 successfully reset to ',depend0 ; endif ; if(depend0 ne '') then vinfo = cdf_varinq(CDFid,depend0) ; inquire about the variable if(depend0 ne '') then begin table_index = where(table.equiv eq depend0, tcount) if (tcount gt 0) then begin depend0 = table.varname(table_index(0)) ;another name needs to be used ;in order to get the data out of the cdf endif epoch = read_myVARIABLE(depend0,CDFid,vary,dtype,recs) endif else begin ;assumes this is the epoch variable if(vartype ne 'metadata') then begin table_index = where(table.equiv eq vnames(vx), tcount) if (tcount gt 0) then begin depend0 = table.varname(table_index(0)) ;another name needs to be used ;in order to get the data out of the cdf epoch = read_myVARIABLE(depend0,CDFid,vary,dtype,recs) endif else begin epoch = read_myVARIABLE(vnames(vx),CDFid,vary,dtype,recs) endelse endif endelse ; RCJ 11/21/2003 Added this test when tests using all=1 lead ; to error because recs was undefined. ;TJK 9/15/2006 would like to check for whether epoch variable is a virtual ;(which is the case for the THEMIS epochs), but don't have that info ;here. So if THEMIS and no recs, read the whole cdf... ;print, 'THEMIS TEST and setting rec_count to 0 so all recs will read' ;stop;TJK if ((n_elements(recs) gt 0) and strcmp('THEMIS',strupcase(atmp.project[0]),6)) then begin rec_count = 0L if (keyword_set(TSTART) and keyword_set(TSTOP)) then need_timeslice = 1L goto, NO_VAR_ATT endif if (n_elements(recs) gt 0) then begin ; if recs is defined if (recs gt 0) then begin ; we're looking at a cdf w/ data in it! ;valid_recs = where(((epoch lt stop_time) and (epoch gt start_time)),$ ; RCJ 06/24/2003 Changed line above to line below. ; Is there any reason to be exclusive instead of inclusive? ;TJK 6/26/2006 - because of CDF_epoch16, if we're running ; w/ IDL6.3,use the new cdf_epoch_compare function to compare ;epoch values (epoch16's are dcomplex - 2 double ;values), so the usual comparison w/ ;the "where" function fails. if (!version.release ge '6.2') then begin if (size(epoch,/tname) eq 'DCOMPLEX')then begin ;TJK can't do this, have to compare value by value... ; valid_recs = where(((epoch le stop_time16) and (epoch ge start_time16)),$ ; rec_count) valid_recs = lonarr(n_elements(epoch)) for i = 0L, n_elements(epoch)-1 do begin temp_epoch = epoch(i) valid_recs(i) = ((cdf_epoch_compare(stop_time16, temp_epoch) ge 0) and $ (cdf_epoch_compare(temp_epoch, start_time16) ge 0)) ;cdf_epoch_compare returns 0 for equal ;value and 1 for greater than endfor v_recs = where(valid_recs eq 1, rec_count) valid_recs = v_recs endif else $ valid_recs = where(((epoch le stop_time) and (epoch ge start_time)),$ rec_count) endif else begin ;original code for regular epoch value valid_recs = where(((epoch le stop_time) and (epoch ge start_time)),$ rec_count) endelse if (rec_count gt 0) then begin start_rec = valid_recs(0) endif else begin ;read one, only because if I set rec_count to zero start_rec = 0L ;we'll get ALL of the records instead of none! rec_count = 1L endelse endif else start_rec = 0L ;read the whole cdf. endif endif else begin ; if keyword set start and stop start_rec = 0L ; else, get all records for this variable rec_count = 0L endelse endif else begin ;variables don't vary start_rec = 0L & rec_count = 1L endelse NO_VAR_ATT: ; RTB end 9/30/97 if keyword_set(DEBUG) then begin print,'Reading data for ',vnames(vx) print, 'Starting at record ',start_rec,' and reading ',$ rec_count, ' records.' endif ;TJK - 02/17/98 added check for virtual variables, if a ;virtual variable has been requested then there isn't any ;data to read from the CDF so set the data array to zero. ;The data will be filled in at the very bottom of this routine. read_flag = 1 ; set flag to true if (num_virs gt -1) then begin vv = where(vnames(vx) eq vir_vars.name, vv_cnt) if (vv_cnt ge 1) then begin ;one exception to above ; Check var_type for current variable RTB 5/98 ; if (tami eq 1) then begin ; print, 'going to try to get attributes for ',vnames(vx) ; stop ;TJK debuggin ; endif cdf_attget,CDFid,'VAR_TYPE',vnames(vx),vartype if ((vartype eq 'metadata') and(vvarys(vx) eq 'NOVARY') and $ (cx eq 0)) then begin ;vv,novary,metadata read from master read_flag = 1 if (debug) then print, 'reading vv, novary,non-metadata from master, ',vnames(vx) endif else begin read_flag = 0 ;set read flag to false data = 0 ;set the data array to nothing as a place holder. endelse endif endif if (read_flag) then $ data = read_myVARIABLE(vnames(vx),CDFid,$ vary,dtype,recs,start_rec=start_rec, $ rec_count=rec_count) ; read the data ; RCJ 10/22/2003 This is for cases when the variable is 'novary' in the master cdf ; but 'vary' in the data cdfs. The type is then changed to 'novary'. ; It doesn't seem to be a problem for plotting or listing in CDAWeb ; but it is a problem for cdfs created by write_mycdf. ; This was found for dataset im_k0_lena (spinsector and polarzone) if cx[0] eq 0 then begin mastervary=[mastervary,vary] endif else begin ; RCJ vx+1 is because mastervary already has a first element: '' if vary eq 'VARY' and mastervary(vx+1) eq 'NOVARY' then $ vary=mastervary(vx+1) endelse ; Flag arrays of length 1; will check later to see if these have fillval's ; which indicates instrument is off RTB 9/96 sz=size(data) ;print,vnames(vx) ;print, sz ; Check if data is of 0, 1 or multi-dimension and set flag ; if(sz(0) ge 1) then szck=sz(1)/(sz(sz(0)+2)) else szck=sz(sz(0)+2) ; RTB 10/29/97 if(sz(0) gt 1) then szck=sz(1)/(sz(sz(0)+2)) else szck=sz(sz(0)+2) if(sz(0) eq 3) then szck=sz(sz(0)) ;TJK 3/17/98, added check for read_flag, if its set then this is ;NOT a virtual variable, so go ahead w/ the check for a single ;record containing fill (indicates instrument is off). ;TJK 10/25/99 added further check to see if this CDF is a master, if ;it is then don't check for "instrument off" since most masters ;don't contain any data. if(szck eq 1) and (vnames(vx) ne '') and (read_flag eq 1) and $ (strpos(cnames(cx),'00000000') eq -1) then begin vn_sdat(vnn)=vnames(vx) vnn=vnn+1 ;print, "Add to instrument off list:", vn_sdat endif ; vvarys(vx) = vary ; save the record variance flag ; ; RCJ 07/31/2003 commented out line below. If only 1 var is requested ; and it's a vv it's cdftype is cdf_epoch! ;cdftyp(vx) = dtype ; save the cdf data type ; ;TJK moved this up above No_VAR_ATT 4/16/98 endif ; Process the metadata of the current variable if (cx eq 0) then begin ; for only the first cdf on the list vvarys(vx) = vary ; set value in variable variance array if keyword_set(DEBUG) then print,'Reading metadata for ',vnames(vx), ' and CDF #',cx metadata = read_myMETADATA(vnames(vx),CDFid) ; read variable metadata mhids(vx) = HANDLE_CREATE() & HANDLE_VALUE, mhids(vx), metadata, /SET ; Check metadata for ISTP depend attr's, modify other arrays accordingly follow_myDEPENDS, metadata, vnames, vvarys, cdftyp, dhids, mhids endif ; Process the data of the current variable ;if(strpos(cnames(cx),'00000000') eq -1) OR (vvarys(vx) eq 'NOVARY') then begin ; RCJ 09/01 Read the variable geo_coord (from satellite ISIS) even though it is ; a 'novary' variable. ;TJK modified this check for mission_group (moved that check up to where we're ;reading the master) and just check the flag here since its quite possible a ;data cdf wouldn't have a mission_group global attribute. 9/28/2001 ; RCJ 11/01 Same for ISIS variable FH ; RCJ 04/23/2003 Had to change the logic associated w/ isis variables. ; We were getting arrays starting w/ a '0' because we had to force ; these 'novary' variables to be read. Further down this first element ; '0' is removed from the array. if (strpos(cnames(cx),'00000000') eq -1) OR (vvarys(vx) eq 'NOVARY') $ then begin ; not a master skeleton or NRV data values from a master, ; (RCJ 09/01) but make an exception for variable geo_coord from ISIS satellite if (dhids(vx) eq 0) then begin ; create handle to hold data dhids(vx) = HANDLE_CREATE() if (isis_flag) then begin if (vnames(vx) eq 'FH') or $ (vnames(vx) eq 'geo_coord') then begin ; RCJ 09/04/2003 Problem when the user only asked for ;'FH': at this point in the program valid_recs was undefined. ; If, for example, 'freq' and 'FH' were requested, then there was ; no problem because valid_recs would have been calculated for ; 'freq'. My solution was to (re)calculate valid_recs here: ; ; RCJ 10/21/2005 This if statement seems to be causing ; problems now and I'm not getting all of the FH/geo_coord ; points I need. I'm commenting it out so valid_recs will ; *always* be recalculated. I did the same a few lines below, ; same case. ;if n_elements(valid_recs) eq 0 then begin epoch = read_myVARIABLE('Epoch',CDFid,vary,dtype,recs) ; Above, we know that for FH or geo_coord data time is 'Epoch' valid_recs = where((epoch le stop_time) and $ (epoch ge start_time)) print, 'Recalculated. Reading ', n_elements(valid_recs), ' records.' ;endif tmpdata=0 for i=0,(n_elements(valid_recs))-1 do tmpdata=[tmpdata,data] data=tmpdata[1:*] endif endif HANDLE_VALUE, dhids(vx), data, /SET endif else begin ; only append record varying data ;if (vvarys(vx) eq 'VARY') then begin ; append data to previous data ; RCJ 09/01 Again, read the varible geo_coord even though it is a 'novary' variable. ; RCJ 11/01 Same for ISIS variable FH if (vvarys(vx) eq 'VARY') or $ (isis_flag and (vnames(vx) eq 'geo_coord')) or $ (isis_flag and (vnames(vx) eq 'FH')) then begin ; append data to previous data HANDLE_VALUE, dhids(vx), olddata ; get data from previous cdf's ; Append only data when the instrument is on. RTB 10/29/97 ;print, "vnn=", vnn ;print, vnames ;print, "vn_sdat ",vn_sdat ;if(vnn eq 0) then begin ;if(vn_sdat(vnn-1) ne vnames(vx)) then $ ;data = append_myDATA(data,olddata) ; append new data to old data ;endif else begin ; print, vnames(vx),vnn ; ; RCJ 09/01 If satellite is ISIS and variable is the 3-element array geo_coord ; (one 3-element array per cdf) we have to replicate the array ; based on the number of valid_recs (or time elements) in this cdf, so we can ; have enough points to plot a graph. ; RCJ 11/01 Same for variable FH, but this is just a scalar. if (isis_flag) then begin if (vnames(vx) eq 'FH') or $ (vnames(vx) eq 'geo_coord') then begin ; RCJ 09/04/2003 Problem when the user only asked for ;'FH': at this point in the program valid_recs was undefined. ; If, for example, 'freq' and 'FH' were requested, then there was ; no problem because valid_recs would have been calculated for ; 'freq'. My solution was to (re)calculate valid_recs here: ; ; RCJ 10/21/2005 Commented out this if statement. ; Reason is stated a few lines above, for the same case. ;if n_elements(valid_recs) eq 0 then begin epoch = read_myVARIABLE('Epoch',CDFid,vary,dtype,recs) ; Above, we know that for FH or geo_coord data time is 'Epoch' valid_recs = where((epoch le stop_time) and $ (epoch ge start_time)) print, 'Recalculated. Reading ', n_elements(valid_recs), ' records.' ;endif tmpdata=0 for i=0,(n_elements(valid_recs))-1 do tmpdata=[tmpdata,data] data=tmpdata[1:*] endif endif data = append_myDATA(data,olddata) ; append new data to old data HANDLE_VALUE, dhids(vx), data ,/SET ; save back into handle endif endelse endif endif else print, 'variable ',vnames(vx), ' not found in ',cnames(cx) vx = vx + 1 ; increment variable name index ENDREP UNTIL (vx eq n_elements(vnames)) cdf_close,CDFid ; close the open cdf endfor ; loop thru all cdfs if keyword_set(DEBUG) then print,'Assembling Anonymous Structure' ; It is possible that some of the variable names may be padded with blanks ; This will likely cause problems later, so trim any blanks around vnames. ;TJK took out on 3/12/01 - because the replace_bad_chars function now ;replaces any non-acceptable characters w/ dollars signs instead of just ;removing them. ;for i=0,n_elements(vnames)-1 do vnames(i) = strtrim(vnames(i),2) ; Retrieve the data and metadata from first handle, and append them ; together to create a data structure to be output from this function. HANDLE_VALUE, mhids(0), metadata, /NO_COPY & HANDLE_FREE,mhids(0) if dhids(0) ne 0 then HANDLE_VALUE,dhids(0),data else data = '' ds = size(data) & if (ds(0) ne 0) then data = reform(temporary(data)) ; special case ;IDL 5.3 doesn't allow structure tag names that are not valid variable names, ;thus we need to check the vnames array for any CDF variable names that contain ;special characters, e.g. badChars=['\','/','.','%','!','@','#','^','&', ; '*','(',')','-','+','=', '`','~','|','?','<','>'] and replace them w/ a "$" ; character instead... not sure what other ramifications this will have ; throughout the rest of the system. TJK 4/5/2000 for t=0, n_elements(vnames)-1 do begin ; if keyword_set(DEBUG) then print, 'Processing table variable, ',vnames(t) table_index = where(table.varname eq vnames(t), tcount) ttable_index = where(table.equiv eq vnames(t), ttcount) vcount = -1 ;initialize if (table_index(0) eq -1) and (ttable_index(0) eq -1) then begin ;add this variable to the table ; if keyword_set(DEBUG) then print, 'found new variable, adding to table, ',vnames(t) tfree = where(table.varname eq '' or table.varname eq ' ',fcount) if (fcount gt 0) then begin table.varname(tfree(0)) = vnames(t) endif else begin print, '2, Number of variables exceeds the current size ' + $ 'of the table structure, please increase it, current size is ' ; help, table.varname return, -1 endelse table_index = where(table.varname eq vnames(t), vcount) endif if (vcount ge 0) then begin vnames(t) = replace_bad_chars(vnames(t), diff) table.equiv(table_index(0)) = vnames(t) ;set equiv to either the new changed name or the original ;if it doesn't contain any bad chars.. endif else begin if (vcount eq -1) then begin ;already set in the table, assign to what's in equiv. if table_index(0) ge 0 then idx = table_index(0) if ttable_index(0) ge 0 then idx = ttable_index(0) vnames(t) = table.equiv(idx) endif endelse endfor if keyword_set(NODATASTRUCT) then begin ; Rather than place the actual data into the megastructure, create ; a data handle structure field and put the data handle id in it. mytype = create_struct('cdftype',cdftyp(0)) ; create .cdftype structure myvary = create_struct('cdfrecvary',vvarys(0)) ; create .cdfrecvary structure - TJK added 8/1/2001 mydata = create_struct('handle',dhids(0)) ; create .handle structure mysize = create_struct('idlsize',size(data)) ; create .idlsize structure mytype = create_struct(mytype,myvary) ; append the structures - TJK added 8/1/2001 mytype = create_struct(mytype,mysize) ; append the structures mydata = create_struct(mytype,mydata) ; append the structures mydata = create_struct(metadata,mydata) ; append the metadata burley = create_struct(vnames(0),mydata) ; create initial structure endif else begin ; Place the actual data into the large data structure. This requires ; moving data and can take a long time with large image data arrays. if dhids(0) ne 0 then HANDLE_FREE,dhids(0) ds = size(data) & if (ds(0) ne 0) then data = reform(data) ; special case mytype = create_struct('cdftype',cdftyp(0)) ; create .cdftype structure myvary = create_struct('cdfrecvary',vvarys(0)) ; create .cdfrecvary structure - TJK added 8/1/2001 mydata = create_struct('dat',data) ; create .dat structure mytype = create_struct(mytype,myvary) ; append the structures - TJK added 8/1/2001 mydata = create_struct(mytype,mydata) ; append the structures mydata = create_struct(metadata,mydata) ; append the metadata burley = create_struct(vnames(0),mydata) ; create initial structure endelse burley = correct_varname(burley, vnames, 0) ; If more than one variable is being processed, then retrieve the data ; and metadata from the handles, and append them into an anonymous struct ; and append these structures into a single anonymous struct for output. for vx = 1,n_elements(vnames)-1 do begin ; retrieve and append HANDLE_VALUE, mhids(vx), metadata, /NO_COPY & HANDLE_FREE,mhids(vx) if dhids(vx) ne 0 then HANDLE_VALUE,dhids(vx),data else data = '' ds = size(data) & if (ds(0) ne 0) then data = reform(temporary(data)) ; special case if keyword_set(NODATASTRUCT) then begin ; Rather than place the actual data into the megastructure, create ; a data handle structure field and put the data handle id in it. mytype = create_struct('cdftype',cdftyp(vx)) ; create .cdftype structure myvary = create_struct('cdfrecvary',vvarys(vx)) ; create .cdfrecvary structure - TJK added 8/1/2001 mysize = create_struct('idlsize',size(data)) ; create .idlsize structure mydata = create_struct('handle',dhids(vx)) ; create .handle structure mytype = create_struct(mytype,myvary) ; append the structures - TJK added 8/1/2001 mytype = create_struct(mytype,mysize) ; append the structures mydata = create_struct(mytype,mydata) ; append the structures mydata = create_struct(metadata,mydata) ; append the metadata rick = create_struct(vnames(vx),mydata) ; create new structure burley = create_struct(burley,rick) ; create initial structure endif else begin if (dhids(vx) ne 0) then HANDLE_FREE,dhids(vx) mytype = create_struct('cdftype',cdftyp(vx)) ; create .cdftype structure myvary = create_struct('cdfrecvary',vvarys(vx)) ; create .cdfrecvary structure - TJK added 8/1/2001 mydata = create_struct('dat',data) ; create .dat structure mytype = create_struct(mytype,myvary) ; append the structures - TJK added 8/1/2001 mydata = create_struct(mytype,mydata) ; append the structures mydata = create_struct(metadata,mydata) ; append the metadata rick = create_struct(vnames(vx),mydata) ; create new structure burley = create_struct(burley,rick) ; append the structures endelse burley = correct_varname(burley, vnames, vx) endfor ; Check for conditions where ISTP instrument may be off; data array length of ; 1 and equal to the fill value. If true set structure to -1 and return ; error and status messages ;TJK changed to ne 4/29/98 wvn=where(vn_sdat eq '',wcvn) ikill=0 wvn=where(vn_sdat ne '',wcvn) if(wcvn ne 0) then begin for vi=0, wcvn-1 do begin if(vn_sdat(vi) ne '') then begin ;TJK - get the tag index in the burley structure for this variable name - ;can't use the variable names since they sometimes contain wierd ;characters like "%" in equator-s ttags = tag_names(burley) ; RCJ 11/28/00 added line below. vn_sdat still had bad characters in ; the variable names and the search for var_type was failing. vn_sdat(vi) = replace_bad_chars(vn_sdat(vi), diff) tindex = strtrim(string(tagindex(vn_sdat(vi),ttags)),2) ;convert to string comm=execute('var_type=burley.('+tindex+').var_type') if(var_type eq 'data') then begin comm=execute('vfill=burley.('+tindex+').fillval') if(keyword_set(NODATASTRUCT)) then begin comm=execute('temp=burley.('+tindex+').handle') handle_value,temp,vdat endif else comm=execute('vdat=burley.('+tindex+').dat') if(not comm) then print, 'ERROR=execute failed ' ;TJK 4/17/98, added check for the datatype before doing ;the abs function test. If the data_type is byte, then the ;abs function cannot be applied, ie. under IDL 5.02 abs(255) is 1. data_size = size(vdat) data_type = data_size(n_elements(data_size)-2) ;TJK added logic to check if the data array size is still equal to ;just one value. If so,then check the fill value, else get out. if(data_size(0) gt 1) then $ szck=data_size(1)/(data_size(data_size(0)+2)) else $ szck=data_size(data_size(0)+2) if(data_size(0) eq 3) then szck=data_size(data_size(0)) if(szck eq 1) then begin ;data array has single value in it. if (data_type eq 1) then begin ;print, 'detected a byte value' if (vfill eq vdat(0)) then $ ikill = write_fill(vn_sdat(vi), burley, tmp_str) endif else begin if (data_type gt 1) then begin ; RCJ 06/06/01 Commented this part out. Maybe we have to rethink ; the way we handle these situations. ;;print, 'detected a non byte value' ;if (abs(vfill) eq abs(vdat(0))) then $ ; ikill = write_fill(vn_sdat(vi), burley, tmp_str) endif ;datatype isn't byte (is gt 1) endelse endif else begin ; RCJ 05/01 commented this part out. We don't want to set ikill=1 if at least ; one of the variables has good data. ;if (data_size(0) eq 1) then begin ; fidx = where(vfill eq vdat, fcnt) ; if (fcnt eq n_elements(vdat)) then begin ; ;print, 'Found single record vector w/ all fill values' ; ;print, 'Setting fill message for variable',vn_sdat(vi) ; ikill = write_fill(vn_sdat(vi), burley, tmp_str) ; endif ;endif endelse endif endif endfor endif endif else begin ;TJK added check for no varibles to retrieve ;get some metadata out of the 1st CDF or Master CDF v_err = 'ERROR=Variable(s) not available for specified time range.' v_stat='STATUS=Variable(s) not available for specified time range. Re-select a different time range.' slash = rstrpos(cnames(0),'/') d_set = strmid(cnames(0), slash+1, 9) d_set = 'DATASET='+strupcase(d_set) tmp_str=create_struct('DATASET',d_set,'ERROR',v_err,'STATUS',v_stat) ikill=1 endelse if(ikill) then return, tmp_str !quiet = quiet_flag ; restore ; Return successfull if (keyword_set(DEBUG)) then begin print, 'num_virs',num_virs+1 endif ;TJK add check in orig_names array for any variable name that might have ;bad characters in it. Compare w/ what's been stored in the table structure. ;if (debug) then print, 'orig_names before checking ',orig_names for i = 0, n_elements(orig_names)-1 do begin found = where(orig_names(i) eq table.varname, found_cnt) if (found_cnt eq 1) then orig_names(i) = table.equiv(found(0)) endfor ;if (debug) then print, 'orig_names after checking ',orig_names ;TJK add system time check to determine how long our virtual variables ;take to generate. if not keyword_set(NOVIRTUAL) then begin ttime = systime(1) for i = 0, num_virs do begin vtags = tag_names(burley) ;vindex = tagindex(vir_vars.name(i), vtags) ; find the VV index number vindex = tagindex(replace_bad_chars(vir_vars.name(i),diff), vtags) ; find the VV index number if (vindex(0) ge 0) then begin vartags = tag_names(burley.(vindex)) ; findex = tagindex('FUNCTION', vartags) ; find the FUNCTION index number findex = tagindex('FUNCT', vartags) ; find the FUNCT index number if (findex(0) ne -1) then begin ;found a virtual value w/ a function definition if keyword_set(DEBUG) then print,'VV function being called ',$ strlowcase(burley.(vindex).(findex)), ' for variable ',vir_vars.name(i) case (strlowcase(burley.(vindex).(findex))) of 'crop_image': begin burley=crop_image(temporary(burley),orig_names,index=vindex) end 'alternate_view': begin burley = alternate_view(temporary(burley),orig_names) end 'conv_pos': begin ; RCJ 11/21/2003 Added 'index=vindex'. It is necessary if all=1 burley = conv_pos(temporary(burley),orig_names,$ tstart=start_time, tstop=stop_time,index=vindex) end 'conv_pos1': begin burley = conv_pos(temporary(burley),orig_names,$ tstart=start_time, tstop=stop_time, $ COORD="ANG-GSE",INDEX=vindex) end 'conv_pos2': begin burley = conv_pos(temporary(burley),orig_names,$ tstart=start_time, tstop=stop_time, $ COORD="SYN-GEO",INDEX=vindex) end 'conv_map_image': begin burley = conv_map_image(temporary(burley),orig_names) end 'calc_p': begin burley = calc_p(temporary(burley),orig_names,INDEX=vindex) end 'create_vis': begin burley = create_vis(temporary(burley),orig_names) end 'create_plain_vis': begin burley = create_plain_vis(temporary(burley),orig_names) end 'create_plmap_vis': begin burley = create_plmap_vis(temporary(burley),orig_names) end 'apply_qflag': begin burley = apply_qflag(temporary(burley),orig_names,index=vindex) end 'region_filt': begin burley = region_filt(temporary(burley),orig_names,index=vindex) end 'convert_log10': begin burley = convert_log10(temporary(burley),orig_names) end 'add_51s': begin ;for po_h2_uvi burley = Add_seconds(temporary(burley),orig_names,index=vindex,seconds=51) end 'add_1800': begin ;for omni burley = Add_seconds(temporary(burley),orig_names,index=vindex,seconds=1800) end 'comp_themis_epoch': begin ;for computing THEMIS epoch burley = comp_themis_epoch(temporary(burley),orig_names,index=vindex) end 'comp_themis_epoch16': begin ;for computing THEMIS epoch burley = comp_themis_epoch(temporary(burley),orig_names,index=vindex,/sixteen) end 'compute_magnitude': begin burley = compute_magnitude(temporary(burley),orig_names,index=vindex) end 'height_isis': begin burley = height_isis(temporary(burley),orig_names,index=vindex) end 'flip_image': begin burley = flip_image(temporary(burley),orig_names,index=vindex) end 'wind_plot': begin burley = wind_plot(temporary(burley),orig_names,index=vindex) end else : print, 'WARNING= No function for:', vtags(vindex) endcase endif ;if function defined for this virtual variable endif ;found the tag index for this virtual variable endfor ; for number of virtual variables print, 'read_myCDF took ',systime(1)-ttime, ' seconds to generate VVs.' endif ;no virtual variable population ;Add a check for variables that have var_type of data, but that the user didn't request. ;This has just recently become an issue because we want to allow plotting of variables ;that are defined as depends for other variables, e.g. ge_k0_epi. TJK 11/22/2000 var_stat = 0 ;TJK 1/26/01 - add if statement because if one of the virtual variable ;functions has trouble running (doesn't find any data), burley will be ; equal to -1, then check_myvartype fails... so basically check to see ;if burley is a structure, by asking how many tags it has, if its not a ;structure, n_tags returns 0 if (n_tags(burley) ne 0) then begin var_stat = check_myvartype(burley, orig_names) if (var_stat ne 0) then print, 'READ_MYCDF, no data to plot/list.' burley = merge_metadata(cnames, burley) endif ;TJK 10/25/2006 - if THEMIS data then epoch values had to be computed ; (all virtual), thus time subsetting wasn't possible ; above, do it here by calling timeslice_mystruct if (need_timeslice) then begin burley = timeslice_mystruct(temporary(burley), start_time16, stop_time16) endif Return, burley end