;$Author: nikos $
;$Date: 2014-09-03 15:05:59 -0700 (Wed, 03 Sep 2014) $
;$Header: /home/cdaweb/dev/control/RCS/read_myCDF.pro,v 1.303 2014/03/21 15:18:07 kovalick Exp johnson $
;$Locker: johnson $
;$Revision: 15739 $
;+------------------------------------------------------------------------
; 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, dict_key=dict_key, vector=vector
; 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)
; RCJ 10/04/2012 Created this 'observe me' variable. This will be
; the 'size' of whatever array was *not* reformed.
; Default is the size of the new array.
obsme=(a = size(new)) & b = size(old) & data=0L
if not keyword_set(dict_key) then dict_key=''
; 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
; TJK 8/23/2007 dimensions match, but in the
; case of a single record of some size like a vector of 3 -
; need to reform old data. If new happens to also be a single
; record of 3, will get reformed below.
;if ((a(0) eq b(0)) and (a(1) eq b(1))) then begin
; if (b(0) eq 1) then begin
; print,'WARNING= First two dimensions are the same, attempting to reform...' ;DEBUG
; old = reform(temporary(old),b(1),1)
; b = size(old) ; recompute b after it has been reformed
; endif
;endif
;TJK 9/29/2010 add code to remove the extra dimension on a 2-d "new"
;array - this was added specifically for the new isis_av_all dataset
; which has a bunch of data variables that use the cdf "sparse
; records" setting - which takes one value and fills it into
; all records.
; RCJ 05/23/2013 Cover also cases when a[1] eq 1 :
if (b[0] eq 1 and (a[0] eq 2 and ((a[2] eq 1) or (a[1] eq 1)))) then begin
;if (b[0] eq 1 and (a[0] eq 2 and a[2] eq 1)) then begin
print,'WARNING= Single dimension found, attempting to reform...0' ;DEBUG
new = reform(temporary(new))
obsme=(a = size(new))
endif
if (a[0] gt b[0]) then begin ; dimension mismatch - reform old data
print,'WARNING= Dimension mismatch detected, attempting to reform...1' ;DEBUG
case b[0] of
0 : ; no special actions needed
1 : begin
;old = reform(temporary(old),b[1],1)
if keyword_set(vector) then old = reform(temporary(old),b[1],1) $
else old = reform(temporary(old),1,b[1])
; RCJ 04/19/2013 Making value=old[0] makes all values of a vector
; equal to that value.
;old = make_array(a[1],1,type=size(old,/type),value=old[0])
end
2 : begin
;old = reform(temporary(old),b[1],b[2],1)
old = reform(temporary(old),a[1],b[2],1)
end
3 : begin
;old = reform(temporary(old),b[1],b[2],b[3],1)
old = reform(temporary(old),a[1],b[2],b[3],1)
end
else : print,'ERROR=Cannot reform single-record variable with > 3 dims'
endcase
b = size(old) ; recompute b after it has been reformed
obsme = size(new)
endif
if (a[0] lt b[0]) then begin ; dimension mismatch - reform new data
print,'WARNING= Dimension mismatch detected, attempting to reform...2' ;DEBUG
case a[0] of
0 : ; no special actions needed
1 : begin
;new = reform(temporary(new),a[1],1)
if keyword_set(vector) then new = reform(temporary(new),a[1],1) $
else new = reform(temporary(new),1,a[1])
; RCJ 04/19/2013 Making value=new[0] makes all values of a vector
; equal to that value.
;new = make_array(b[1],1,type=size(new,/type),value=new[0])
end
2 : begin
;new = reform(temporary(new),a[1],a[2],1)
new = reform(temporary(new),b[1],a[2],1)
end
3 : begin
;new = reform(temporary(new),a[1],a[2],a[3],1)
new = reform(temporary(new),b[1],a[2],a[3],1)
end
else : print,'ERROR=Cannot reform single-record variable with > 3 dims'
endcase
a = size(new) ; recompute a after it has been reformed
obsme= size(old)
endif
; append the new data to the old data
;case a[0] of
case obsme[0] of
0:begin
; RCJ 02/09/2007 Problem reading po_k0_uvi_20020318 and 19.
; Day 18 generates an image array: [228,200,21]. Day 19 is a
; small cdf containing one (fill)value: -1.0000e+31 for the image.
; New data cannot concatenate w/ old. Shouldn't test above fix this?
data = [old,new]
end
1:begin
;data = [old,new]
; RCJ 09/20/2007 This is to resolve cases when the
; var is a vector but the first cdf read contains an array[3]
; Best would be array[3,1], but that info is lost when we get
; to this point, so when we finally get array[3,*] the
; concatenation can be done properly.
; TJK 11/19/2007 Extend this to also look for spectrogram types
;TJK 6/25/2008 add this catch because sometimes the "vector"
;setting isn't correct. So reset "vector" and try again.
CATCH,error_status
if (error_status ne 0) then begin
if (vector) then begin
vector= 0 ;try again w/ vector set to off
!ERROR=0 ;and reset the error
if (keyword_set(DEBUG)) then print, 'try no vector append'
endif
endif
if ((strpos(strlowcase(dict_key),'vector') ne -1) or keyword_set(vector)) $
then data = [[old],[new]] else data = [old,new]
end
2:begin
data = [[old],[new]]
end
3:begin
;TJK 2/23/2009 add this check for vector set (it_k0_wav) and three dimensional
;array (which they are because the third dim. is added above - which
;is what you'd want to do if these were images, but they aren't
;so remove the last dimension from each array, and append the arrays.
if (keyword_set(vector) and a[3] eq 1) then begin
new = reform(temporary(new))
old = reform(temporary(old))
data = [[old],[new]]
endif else begin
data = [[[old]],[[new]]]
endelse
end
4:begin
;can't do: IDL doesn't support more than 3 dimensions:
; data = [[[[old]]],[[[new]]]] so do this the old fashioned way
a = size(new)
b = size(old)
data = make_array(a[1],a[2],a[3],a[4]+b[4],type=a(5))
data[*,*,*,0:b[4]-1]=old[*,*,*,*]
data[*,*,*,b[4]:*]=new[*,*,*,*]
end
else: print,'ERROR=Cannot append arrays with > 4 dimensions yet'
endcase
; TJK 10/21/2009 remove this line from here. Plot_spectrogram uses
; append_mydata to add fill values to the data array. The following line wipes
; out the fill values. Let the calling routine take care of releasing memory.
;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
pos1 = strpos(tnames[i],'DELTA_PLUS_VAR') $
& pos2 = strpos(tnames[i],'DELTA_MINUS_VAR')
if ((pos1[0] ne -1) or (pos2[0] ne -1)) then begin ; DELTA found,
dvname = metadata.(i)
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,DEBUG=DEBUG
;
; Get needed information about the cdf and variable
;stop;
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 ; this means NO records have been written
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 $
;TJK 5/4/2007 - change from "return,wfill" to check if size should be
; an array, if so the make the appropriate size array
; and fill w/ the variables fill value.
; dim is array of longs. The value of each element corresponds to the dimension of the variable.
; This field is only included in the structure if the variable is a zVariable. (source: cdf_varinq in idl help)
; So this 'case' refers to the number of elements of dim.
case (size(vinfo.dim, /n_elements)) of
0: return, wfill
1: begin
;if (vinfo.dim le 0) then return, wfill $
;else return, make_array(vinfo.dim,value=wfill)
if (vinfo.dim le 0) then begin
return, wfill
endif else begin
; RCJ 02/07/2012
; if var and its depend_0 have no records (vinfo2.maxrecs=0) OR
; if var has no records but its depend_0 does, then we need
; to fill in the var array w/ as many records as depend_0 has.
; Ran into this problem w/ thb_l2_mom_20090929_v01.cdf
;if vinfo2.maxrecs eq 0 then begin
; RCJ 03/23/2012 maxrecs could be -1 too, so changed to 'le'
;TJK 4/11/2012, use maxrecs+1 instead of maxrecs
if (vinfo2.maxrecs le 0) then begin
return, make_array(vinfo.dim,value=wfill)
endif else begin
;1/30/2014 TJK check the depend0 variable to see if its virtual, if so
;it will have a component_1 (THEMIS case) so the epoch values don't
;exist yet... so need to get the depend_0's, component_1's data size
;and compare w/ the current variables size - stored below in cinfo.maxrec
;3/18/2014 - call cdf_attexists for depend_0 and component_0 instead
;of cdf_attnum (attnum fails if the attribute doesn't exist)
dnum = cdf_attexists(CDFid,'DEPEND_0') ;returns true or false
if ((dnum) and cdf_attexists(CDFid,'DEPEND_0',vname))then begin
cdf_attget,CDFid,'DEPEND_0',vname, depend0 ;depend_0 of the data variable
if (depend0 ne ' ') then begin ;if depend_0 isn't blank get its component_0
cnum = cdf_attexists(CDFid,'COMPONENT_1') ;returns true or false
if ((cnum) and cdf_attexists(CDFid,'COMPONENT_1',depend0))then begin
cdf_attget,CDFid,'COMPONENT_1',depend0,component1 ;component_1 of the data variable
if (component1 ne ' ') then begin ; now get the data array sizes for the component_1 variable
cdf_control,CDFid,VAR=component1,GET_VAR_INFO=cinfo
if (cinfo.maxrec+1 gt 0) then make_records = cinfo.maxrec+1 else make_records = 1
if keyword_set(DEBUG) then print,'WARNING, ',vname,' has no records but its component_1 ',component1,' does. Filling in array with ',make_records,' elements.'
return, make_array(vinfo.dim,make_records,value=wfill)
; help, /struct, cinfo
endif
endif else begin ; if component_1 isn't found, then use the maxrec for this variable
if (vinfo2.maxrec+1 gt 0) then make_records = vinfo2.maxrec+1 else make_records = 1
if keyword_set(DEBUG) then print,'WARNING, ',vname,' has no records but its depend_0 ',depend0,' does. Filling in array with ',make_records,' elements.'
return, make_array(vinfo.dim,make_records,value=wfill)
endelse
endif
endif else begin ; if depend_0 isn't found, then use the maxrec for this variable
if (vinfo2.maxrec+1 gt 0) then make_records = vinfo2.maxrec+1 else make_records = 1
if keyword_set(DEBUG) then print,'WARNING, ',vname,' has no records and no depend_0. Filling in array with ',make_records,' elements.'
return, make_array(vinfo.dim,make_records,value=wfill)
endelse
;1/30/2014 TJK vinfo2.maxrecs is the maximum record for all variables
;in this cdf. So we don't want
;to use that, see above for new logic
; if keyword_set(DEBUG) then print,'WARNING, ',vname,' has no records but its depend_0 does. Filling in array with ',vinfo2.maxrecs+1,' elements.'
; return, make_array(vinfo.dim,vinfo2.maxrecs+1,value=wfill)
endelse
endelse
end
2: begin
tmp_a = make_array(dimension=vinfo.dim, value=wfill)
tmp_a = reform(temporary(tmp_a),vinfo.dim[0],vinfo.dim[1],1)
return, tmp_a
end
3: begin
tmp_a = make_array(dimension=vinfo.dim, value=wfill)
tmp_a = reform(temporary(tmp_a),vinfo.dim[0],vinfo.dim[1],vinfo.dim[2],1)
return, tmp_a
end
else: print, "STATUS = array size too large"
endcase
endif else begin ;if don't have a fill value, go ahead and read 1 rec.
; if keyword_set(DEBUG) then vtime = systime(1)
cdf_varget,CDFid,vname,dat,REC_COUNT=1 & return,dat
; if keyword_set(DEBUG) then print, '1 Took ',systime(1)-vtime, ' seconds to do cdf_varget for ',vname
endelse
endif else begin
; if keyword_set(DEBUG) then vtime = systime(1)
cdf_varget,CDFid,vname,dat,REC_START=start_rec,REC_COUNT=recs
; if keyword_set(DEBUG) then print, '2 Took ',systime(1)-vtime, ' seconds to do cdf_varget for ',vname
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 begin
; if keyword_set(DEBUG) then vtime = systime(1)
CDF_varget,CDFid,vname,dat,COUNT=dimc,REC_START=start_rec,REC_COUNT=recs
; if keyword_set(DEBUG) then print, '3 Took ',systime(1)-vtime, ' seconds to do cdf_varget for ',vname
endelse
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
if ((ds[0] eq 1) and vinfo.dim eq 1) then begin
; print, 'converting one record of bytes '
dat = string(dat)
endif else begin ; process each element of array
; print, 'converting more than one record of bytes '
d2=strarr(ds[1])
for i=0,ds[1]-1 do d2[i]=string(dat[i])
dat = d2
endelse
endelse
if keyword_set(DEBUG) then print, 'Converted cdf_char BYTE to STRING ', dat
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
;11/20/2007 TJK after all attributes are read and put in metadata
;structure, add one more attribute that's needed for appending the
;data arrays from file to file (for THEMIS especially). Add a
;dim_sizes element.
status = cdf_varnum(CDFid,vname) ;check to see if this named variable exists
; RCJ 01/31/2008 Need to check for the existence of dim_sizes
; In cdfs generated by cdaweb, for example, they already exist in the structure
q=where(tag_names(metadata) eq 'DIM_SIZES')
if (status ne -1) and (q[0] eq -1) then begin
cdf_control, CDFid, SET_ZMODE=2 ;set zmode so that we'll always get a .dim (default for R variables
;is a value for .dimvar (which is different than .dim)...
vinfo = cdf_varinq(CDFid,vname) ; get the dim_size info. on this var.
METADATA = create_struct(temporary(METADATA),'DIM_SIZES',vinfo.dim)
nglobal=[nglobal,0] ;add this as a variable attribute [0]
endif
;
; 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, var_cnt) ; variable scope
n1=where(nglobal eq 1, global_cnt) ; global scope
;print, 'number of global attrs ', global_cnt
;print, 'number of variable attrs ', var_cnt
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
if (global_cnt gt 0) then begin ;TJK 11/27 check if there are global attributes
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
endif
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)
vnames=''
; 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
;TJK 5/9/2008 add code to determine the zmode, the call below
;to read_myetadata changes the mode to 2, and you can't call
;cdf_varinq in zmode=2 w/o the /zvariable keyword set...
;This is only a problem w/ cdfs that have R variables, e.g. po_k0_uvi
cdf_control, CDFindex, GET_ZMODE=mode ;get zmode
if (mode gt 0) then vinfo = CDF_VARINQ(CDFindex,i,/ZVARIABLE) else $
vinfo = CDF_VARINQ(CDFindex,i)
if keyword_set(VAR_TYPE) then begin ; only get VAR_TYPE='data', for example
; RCJ 01/14/2013 Mabye this approach works better? My experience is that,
; because mode changes when read_mymetadata is called, I did not get all
; requested vars back when all=2 (all 'data' types) in the call to read_myCDF.
cdf_attget,CDFindex,'VAR_TYPE',vinfo.name,attgot
if ((attgot eq VAR_TYPE) and (vinfo.recvar eq 'VARY')) then vnames=[vnames,vinfo.name]
;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
vnames=[vnames,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'
; RCJ 01/14/2013 Same argument as above (see RCJ 01/14/2013)
cdf_attget,CDFindex,'VAR_TYPE',vinfo.name,attgot
if ((attgot eq VAR_TYPE) and (vinfo.recvar eq 'VARY')) then vnames=[vnames,vinfo.name]
;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
vnames=[vnames,vinfo.name]
endelse
endfor
if keyword_set(CNAME) then CDF_CLOSE,CDFindex
; RCJ 01/14/2013 Not needed since we are appending values to the array.
; 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
; RCJ 01/14/2013 Changed this because we are appending values to the array.
return,vnames[1:*]
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_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 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
print, 'in find_epochvar'
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 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, all=all
;
;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])
; RCJ 01/14/2013 get_allvarnames needs to know the value of 'all'.
;data_vnames = get_allvarnames(CDFid=data_CDFid)
if keyword_set(ALL) then begin
if all eq 1 then data_vnames = get_allvarnames(CDFid=data_CDFid)
if all eq 2 then data_vnames = get_allvarnames(CDFid=data_CDFid,var_type='data')
endif else 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
;uniq_array takes two string arrays (like lists of variable names)
;and doesn't modify the 1st, but adds the second to the 1st w/o adding
;any duplicates.
function unique_array, first, second
x = where(second ne '',xcnt)
if (xcnt gt 0) then begin
second = second[x]
u_s_index = uniq(second, sort(second))
for s=0,n_elements(u_s_index)-1 do begin
for u=0,n_elements(first)-1 do begin
if (first[u] eq second[u_s_index[s]]) then begin
print, first[u], second[u_s_index[s]]
second[u_s_index[s]] = ' '
endif
endfor
endfor
t = where(second ne ' ',tcnt)
if (tcnt gt 0) then first = [first,second[t]] ;append sorted/uniqed
endif
return, first
end
;+------------------------------------------------------------------------
; RCJ 03/30/2012 Commented out this function. It was called once and that
; call is commented out too.
;;check the variables_comp array for existence of the variable name, for
;;the current cdf.
;function check_varcompare, variables_comp, cdf_index, variable_name
;;print,'**** ' & help,variables_comp
;;print, variable_name, cdf_index, variables_comp
;;stop;
;x = where(variable_name eq variables_comp(cdf_index,*), xcnt)
;if (xcnt gt 0)then print, variable_name, ' found 1' else print, variable_name, ' not found 0'
;if (xcnt gt 0)then return, 1 else return, 0
;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
compile_opt idl2
if (!version.release ge '8.0') then CDF_SET_VALIDATE, /no ;turn off CDF validation
; 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
;TJK 03/15/2010 - check for the max number of variables between the
; master and a datacdf (if there is a
; master)... sometimes the master has fewer (like w/
; sta_l1_mag_rtn) which then causes a problem.
if (n_elements(cnames) gt 1) then num_vars = max([get_numallvars(CNAME=cnames[0]), get_numallvars(CNAME=cnames[1])]) else $
num_vars = get_numallvars(CNAME=cnames[0])
var_names = strarr(num_vars)
total_storage_time = 0L
;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
variables_read = make_array(n_elements(cnames),num_vars,/string, value="")
;variables_comp = make_array(n_elements(cnames),num_vars,/string, value="")
;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)
add_mydeltas,atmp,vnames
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
atmp_dep1=atmp.depend_1
; RCJ 05/16/2013 ok, but if alt_cdaweb_depend_1 exists, use it instead:
q=tagindex ('ALT_CDAWEB_DEPEND_1', atags)
if q[0] ne -1 then if (atmp.alt_cdaweb_depend_1 ne '') then atmp_dep1=atmp.alt_cdaweb_depend_1
;if (atmp.depend_1 ne '') then begin
if (atmp_dep1 ne '') then begin
if q[0] ne -1 then num = where(chkvv_dep eq atmp.alt_cdaweb_depend_1, cnt) else num = where(chkvv_dep eq atmp.depend_1, cnt)
if (cnt eq 0) then begin
if q[0] ne -1 then chkvv_dep=[chkvv_dep,atmp.alt_cdaweb_depend_1] else 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
atmp_dep2=atmp.depend_2
; RCJ 05/16/2013 ok, but if alt_cdaweb_depend_1 exists, use it instead:
q=tagindex ('ALT_CDAWEB_DEPEND_2', atags)
if q[0] ne -1 then if (atmp.alt_cdaweb_depend_2 ne '') then atmp_dep2=atmp.alt_cdaweb_depend_2
;if (atmp.depend_2 ne '') then begin
if (atmp_dep2 ne '') then begin
if q[0] ne -1 then num = where(chkvv_dep eq atmp.alt_cdaweb_depend_2, cnt) else num = where(chkvv_dep eq atmp.depend_2, cnt)
if (cnt eq 0) then begin
if q[0] ne -1 then chkvv_dep=[chkvv_dep,atmp.alt_cdaweb_depend_2] else chkvv_dep=[chkvv_dep,atmp.depend_2]
vdep_cnt=vdep_cnt+1
endif
endif
endif
;TJK 4/17/2008 adding check for deltas here otherwise those vars
;get thrown out below (needed this for voyager coho datasets
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
;end of 4/17/2008 added check for deltas
;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)
c0 = tagindex ('COMPONENT_0', atags) ;add check for component_0 value as well
;look through metadata and look for virtual variables...
; get components of the virtual variables and add them to the vnames
; array...
;TJK 11/6/2009 add check for component_0 in order to determine if virtual
;variable definition is for real or not.
; if (b0[0] ne -1 ) then begin
; if (strlowcase(atmp.VIRTUAL) eq 'true') then begin
if ((b0[0] ne -1) and (c0[0] ne -1)) then begin
if ((strlowcase(atmp.VIRTUAL) eq 'true') and (atmp.COMPONENT_0 ne '')) 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
if (DEBUG) then begin
print, 'found a VV ', vnames[nreq], ' in Master CDF.'
print, 'adding deltas and components next...'
endif
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
atmp_dep1=atmp.depend_1
; RCJ 05/16/2013 ok, but if alt_cdaweb_depend_1 exists, use it instead:
q=tagindex ('ALT_CDAWEB_DEPEND_1', atags)
if (q[0] ne -1) then if (atmp.alt_cdaweb_depend_1 ne '') then atmp_dep1=atmp.alt_cdaweb_depend_1
;if (atmp.depend_1 ne '') then begin
if (atmp_dep1 ne '') then begin
if (q[0] ne -1) then num = where(chkvv_dep eq atmp.alt_cdaweb_depend_1, cnt) else num = where(chkvv_dep eq atmp.depend_1, cnt)
if (cnt eq 0) then begin
;chkvv_dep(vdep_cnt)=atmp.depend_1
if q[0] ne -1 then chkvv_dep=[chkvv_dep,atmp.alt_cdaweb_depend_1] else 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
atmp_dep2=atmp.depend_2
; RCJ 05/16/2013 ok, but if alt_cdaweb_depend_2 exists, use it instead:
q=tagindex ('ALT_CDAWEB_DEPEND_2', atags)
if (q[0] ne -1) then if (atmp.alt_cdaweb_depend_2 ne '') then atmp_dep2=atmp.alt_cdaweb_depend_2
;if (atmp.depend_2 ne '') then begin
if (atmp_dep2 ne '') then begin
if (q[0] ne -1) then num = where(chkvv_dep eq atmp.alt_cdaweb_depend_2, cnt) else num = where(chkvv_dep eq atmp.depend_2, cnt)
if (cnt eq 0) then begin
;chkvv_dep(vdep_cnt)=atmp.depend_2
if q[0] ne -1 then chkvv_dep=[chkvv_dep,atmp.alt_cdaweb_depend_2] else 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
;TJK - 1/27/2009 add a check to see whether the component_1
; variables are virtual
b1 = tagindex ('COMPONENT_1', atags)
if (b1[0] ne -1 ) then begin
if (atmp.component_1 ne '') then begin
num = where(chkvv_dep eq atmp.component_1, cnt)
if (cnt eq 0) then begin
;chkvv_dep(vdep_cnt)=atmp.component_1
chkvv_dep=[chkvv_dep,atmp.component_1]
vdep_cnt=vdep_cnt+1
endif
endif
endif
;TJK - 1/27/2009 add a check to see whether the component_2
; variables are virtual
b1 = tagindex ('COMPONENT_2', atags)
if (b1[0] ne -1 ) then begin
if (atmp.component_2 ne '') then begin
num = where(chkvv_dep eq atmp.component_2, cnt)
if (cnt eq 0) then begin
;chkvv_dep(vdep_cnt)=atmp.component_2
chkvv_dep=[chkvv_dep,atmp.component_2]
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)
add_myDELTAS, atmp, vnames ;TJK add this here because we have regular variables w/ delta
;not only virtual variables (3/20/2014)
b0 = tagindex ('VIRTUAL', atags)
;TJK 11/6/2009 add check for component_0 in order to determine if virtual
;variable definition is for real or not.
; if (b0[0] ne -1 ) then begin
; if (strlowcase(atmp.VIRTUAL) eq 'true') then begin
c0 = tagindex ('COMPONENT_0', atags) ;add check for component_0 value as well
if ((b0[0] ne -1) and (c0[0] ne -1)) then begin
if ((strlowcase(atmp.VIRTUAL) eq 'true') and (atmp.COMPONENT_0 ne '')) 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
;TJK 3/26/2009 add check for whether the variable name is in the
;vir_vars array
v_index = where(vir_vars.name eq chkvv_dep[nvvq] , v_count)
if (v_count eq 0) then begin ;need to add to vir_vars...
if (DEBUG) then print, 'Found a VV ',chkvv_dep[nvvq],' among Depends; adding to vir_vars.'
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
endif
endfor
endif ; if (vdep_cnt gt 0)
if keyword_set(DEBUG) then print, 'end of master cdf section ',vnames
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
; 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)
;TJK 3/12/2010 - add code to get component_0 info so it can be checked
; below - otherwise we can't read themis cdfs (w/o
; masters) because they depend so heavily on
; virtual variables.
bfound = where(att_names eq 'COMPONENT_0', bcnt)
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)
;TJK 3/12/2010 added the following because it was wrong before... atags only has
;the virtual tag in it not all tags for the given variable (unlike way
;above)... so get the component_0 info. and store in btmp, btags and use t0 below
btmp = read_myATTRIBUTE(all_cdf_vars[nvar],bfound[0],CDFid)
btags = tag_names (btmp)
t0 = tagindex ('COMPONENT_0', btags);add check for component_0 value as well
;TJK 11/6/2009 add check for component_0 in order to determine if virtual
;variable definition is for real or not.
; if (b0[0] ne -1) then begin
; if (strlowcase(atmp.VIRTUAL) eq 'true') then begin
;TJK 3/12/2010 - this check was wrong since atags only had "virtual"
; in it - instead use t0 and btmp defined above
; c0 = tagindex ('COMPONENT_0', atags) ;add check for component_0 value as well
; if ((b0[0] ne -1) and (c0[0] ne -1)) then begin
; if ((strlowcase(atmp.VIRTUAL) eq 'true') and (atmp.COMPONENT_0 ne '')) then begin
;print, 'DEBUG 3rd check for VIRTUAL and COMPONENT '
;print, ' tag indexes for virtual ',b0, 'for component ', t0
;
;TJK 3/12/2010 change to only check for virtuals in data cdfs if there
;isn't a master cdf. So if the data cdf has some virtuals defined
;they will be found... so they better be correct! If the data cdfs
;virtual's aren't correct like in sta/b_l1_mag/b_rtn/sc, then use a
;master cdf w/ the virtuals turned off (set to false) and you'll be set.
if (strpos(cnames[0],'00000000') eq -1) then begin
;print, 'DEBUG 1st cdf is not a master ', cnames[0]
if ((b0[0] ne -1) and (t0[0] ne -1)) then begin
if ((strlowcase(atmp.VIRTUAL) eq 'true') and (btmp.COMPONENT_0 ne '')) 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
endif ; check for whether a master cdf has been defined
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, 'Reading metadata for VV, ',vnames[req_vars]
atmp = read_myMETADATA (vnames[req_vars], CDFid)
if (debug) then print, 'Add DELTAs for VV, ',vnames[req_vars]
add_myDELTAS, atmp, vnames
if (debug) then print, 'Add components for VV, ',vnames[req_vars]
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.
;TJK 6/23/2008 add code to add theunique list of depends and
;components, but don't want to use sort and uniq on the requested vnames
;array, because that messes up the ordering of the variables (we want to
;plot them in the same order they're listed in the master cdf.
vnames = unique_array(vnames, dnames)
cmpnames = unique_array(vnames, cmpnames)
;old code below:
; 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 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
start_timett = encode_cdfepoch(TSTART, /TT2000, 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
stop_timett = encode_cdfepoch(TSTOP, /TT2000, 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 reallyexist 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)
epoch_varname = depend0
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)
epoch_varname = depend0
; print, 'DEBUG looking for valid epoch recs'
; print, 'DEBUG ',stop_timett, start_timett, epoch[0]
endif else begin
epoch = read_myVARIABLE(vnames[vx],CDFid,vary,dtype,recs)
epoch_varname = vnames[vx]
endelse
endif
endelse
; fix for isis cdfs that have first element epoch = last time element epoch. RCJ 02/25/2009.
; Who knows the isis data says this shouldn't have happened. Don't know if the data providers
; can fix it the data. For now, this is the s/w fix.
if isis_flag then begin
if n_elements(epoch) gt 1 then begin
if epoch[0] eq epoch[n_elements(epoch)-1] then begin
if keyword_set(DEBUG) then print,'ISIS or ALOUETTE data. First and last elements of epoch are the same, deleting last....'
epoch=epoch[0:n_elements(epoch)-2]
recs=recs-1
endif
endif
endif
; 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
;4/27/2010 - also only look at this epoch variable if we haven't
; before - for this cdf - use check_varcompare function and the
; variables_comp array to keep track.
; RCJ 03/30/2012 check_varcompare didn't work on waltz. We tried to save_valid_recs
; but the vars may not be in order w/ their Epochs when there are 2 or more Epochs in the requested data.
;if (not(check_varcompare(variables_comp, cx, epoch_varname)))then begin
if keyword_set(DEBUG) then etime = systime(1)
case size(epoch,/tname) of
'LONG64': begin ;TT2000 case
valid_recs=where(cdf_epoch_compare(epoch, start_timett, stop_timett), rec_count)
;print, '1st rec = ',valid_recs[0], 'last rec = ',valid_recs(n_elements(valid_recs)-1)
if keyword_set(DEBUG) then print, 'Took ',systime(1)-etime, ' seconds to do cdf_epoch_compare'
end
'DCOMPLEX': begin ;Epoch16 case
valid_recs=where(cdf_epoch_compare(epoch, start_time16, stop_time16), rec_count)
;print, '1st rec = ',valid_recs[0], 'last rec = ',valid_recs(n_elements(valid_recs)-1)
if keyword_set(DEBUG) then print, 'Took ',systime(1)-etime, ' seconds to do cdf_epoch_compare'
end
else: begin
valid_recs = where(((epoch le stop_time) and (epoch ge start_time)), rec_count)
end
endcase
;if (size(epoch,/tname) eq 'LONG64')then begin ;TT2000 case
; valid_recs=where(cdf_epoch_compare(epoch, start_timett, stop_timett), rec_count)
; ;print, '1st rec = ',valid_recs[0], 'last rec = ',valid_recs(n_elements(valid_recs)-1)
;endif else if (size(epoch,/tname) eq 'DCOMPLEX')then begin ;Epoch16 case
; valid_recs=where(cdf_epoch_compare(epoch, start_time16, stop_time16), rec_count)
; ;print, '1st rec = ',valid_recs[0], 'last rec = ',valid_recs(n_elements(valid_recs)-1)
;endif else $
; valid_recs = where(((epoch le stop_time) and (epoch ge start_time)), rec_count)
;variables_comp(cx,vx) = epoch_varname
;save_valid_recs = valid_recs ;save off the valid_recs for use below
;save_rec_count = rec_count ; save off the rec_count for use below
;endif else begin
; valid_recs = save_valid_recs
; rec_count = save_rec_count
; ;valid_recs = where(((epoch le stop_time) and (epoch ge start_time)), rec_count)
; ;rec_count = rec_count
;endelse
endif else begin ;original code for regular epoch value and old versions of IDL
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]
; print, 'DEBUG Setting start_rec to valid_recs[0] ', start_rec
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
;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 begin
;double check to see if we've read this variable already in this cdf,
;but if its the depend_0, read it again... (because the above reads of
;depend_0 aren't saved into the dhids structure below)
data = read_myVARIABLE(vnames[vx],CDFid,$
vary,dtype,recs,start_rec=start_rec, $
rec_count=rec_count, debug=debug) ; read the data
if keyword_set(DEBUG) then begin
print,'Read data for ',vnames[vx],'. Started at record ',start_rec,' and read ', rec_count, ' records.'
endif
;TJK 5/28/2013 for the case where no valid time values are found, put
;the valid fill into the data variables array so that nothing will be
;listed/plotted - instead of using the first records data, which is
;definitely not correct.
if (n_elements(valid_recs) gt 0) then begin ;see if valid_recs is defined
if (valid_recs[0] eq -1 and (recs gt 0)) then begin ; if recs is defined but no epoch data was found w/i the requested time range
if (cdf_attexists(CDFid,'FILLVAL',vnames[vx])) then begin
anum = cdf_attnum(CDFid,'FILLVAL') ; find the fill value for this variable and load the data array w/ it
cdf_attget,CDFid,'FILLVAL',vnames[vx],vfill
if keyword_set(DEBUG) then print, 'For ',cnames[cx],' setting ',vnames[vx],' values to fill ',vfill, ' because no data w/in start/stop range'
data_size = size(data, /struc) ; use the size of the data returned in the 1st record to set up the new array
if (data_size.n_dimensions eq 0 and data_size.n_elements eq 1) then begin
data = vfill
endif else begin
dsize_x = where(data_size.dimensions ne 0)
data = make_array(dimension=data_size.dimensions[dsize_x], type=data_size.type, value=vfill)
endelse
endif
endif
endif
endif ;if read_flag
; 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_isis = where((epoch le stop_time) and $
(epoch ge start_time), rec_count)
if keyword_set(DEBUG) then print, 'Recalculated - Reading ', rec_count, ' records.'
;endif
tmpdata=0
;for i=0,(n_elements(valid_recs))-1 do tmpdata=[tmpdata,data]
if rec_count gt 0 then begin
for i=0,rec_count-1 do tmpdata=[tmpdata,data]
data=tmpdata[1:*]
endif else data=tmpdata
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_isis = where((epoch le stop_time) and $
(epoch ge start_time), rec_count)
if keyword_set(DEBUG) then print, 'Recalculated - Reading ', rec_count, ' records.'
;endif
tmpdata=0
;for i=0,(n_elements(valid_recs))-1 do tmpdata=[tmpdata,data]
if rec_count gt 0 then begin
for i=0,rec_count-1 do tmpdata=[tmpdata,data]
data=tmpdata[1:*]
endif else data=tmpdata
endif
endif
;RCJ look for dict_key to help identify vector arrays
q = where(strlowcase(tag_names(atmp)) eq 'dict_key')
if q[0] eq -1 then dk='' else dk=atmp.dict_key
;TJK more generic approach to this appending of single records problem
;because we have it for 3 elements vectors as well as spectrogram
;data, e.g. THEMIS L2 ESA
n_dims = size(data, /dimensions)
handle_value, mhids[vx], cur_var
vector=0L
;This was setting an array of just one value to vector, which was not intended.
; if (n_elements(cur_var.dim_sizes) eq 1) then begin
if (n_elements(cur_var.dim_sizes) eq 1 and cur_var.dim_sizes[0] gt 1) then begin
if (cur_var.dim_sizes[0] eq n_dims[0]) then begin
vector = 1L ;as in a 1-d array that is just one record
; like 32 element record, all fill,
; that needs to be appended as another
; record, not appended as 32 records
endif
endif
if (keyword_set(DEBUG)) then begin
if (vector) then print, 'append_mydata vector flag set' else print, 'append_mydata vector flag not set'
endif
data = append_myDATA(data,olddata,dict_key=dk,vector=vector) ; append new data to old data
;if (keyword_set(DEBUG)) then begin
; print, 'after append_mydata'
; help, data
;endif
HANDLE_VALUE, dhids[vx], data ,/SET ; save back into handle
endif
endelse
endif
endif else begin
if (keyword_set(DEBUG)) then print, 'variable ',vnames[vx], ' not found in ',cnames[cx]
endelse
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
mymajor= create_struct('cdfmajor',cinfo.majority)
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,mymajor) ; append the structures
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
mymajor= create_struct('cdfmajor',cinfo.majority)
mydata = create_struct('dat',data) ; create .dat structure
mytype = create_struct(mytype,myvary) ; append the structures - TJK added 8/1/2001
mytype = create_struct(mytype,mymajor) ; 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
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
mymajor= create_struct('cdfmajor',cinfo.majority)
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,mymajor) ; append the structures
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
mymajor= create_struct('cdfmajor',cinfo.majority)
mydata = create_struct('dat',data) ; create .dat structure
mytype = create_struct(mytype,myvary) ; append the structures - TJK added 8/1/2001
mytype = create_struct(mytype,mymajor) ; 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) ; 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
;TJK - 3/9/2007 - comment this out, we
; really don't want to kick out
; entirely.
;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.
; RCJ 02/09/2007 Found case where images from po_k0_uvi were
; requested but cdf was small (po_k0_uvi_20070130),
; had *one* (fill)value in place of image array.
; Ended up here w/ a data_type of 4 (float) and
; one (fill)value: -1.0000e+31
;;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
if not keyword_set(NOVIRTUAL) then begin
;TJK 3/26/2009 add this code to removed the un-used spots in the vir_vars
;structure arrays because I need to reverse the order of the variables
;so that in case there are virtual variables that depend on other v.v.s
;they'll likely be populated (this was specifically needed for
;wi_h4/m2_swe)
tids = where(vir_vars.flag ge 0, tcount)
if (tcount gt 0) then begin
if keyword_set(debug) then print, 'Before ', vir_vars.name
vir_vars2= create_struct('name',vir_vars.name[tids],'flag',vir_vars.flag[tids])
vir_vars.name = vir_vars2.name
vir_vars.flag = vir_vars2.flag
if keyword_set(debug) then print, 'Remove extra virtual variables from list ', vir_vars.name
endif
;TJK add system time check to determine how long our virtual variables
;take to generate.
ttime = systime(1)
q='' ; RCJ 03/04/2010 This test was triggered by a case where the only 'data' var
; in the structure was 'thrown out' somewhere in the code above.
; var was thg_ask_nrsq, date was Nov/2007, for which we don't have data.
for i=0,n_tags(burley)-1 do q=[q,burley.(i).var_type]
;reuse q :
q=where(strlowcase(q) eq 'data')
if q[0] eq -1 then begin
d_set='DATASET='+strupcase(atmp.logical_source)
v_err="ERROR=No var type 'data' in structure"
v_stat='STATUS= Data not available'
tmp_str=create_struct('DATASET',d_set,'ERROR',v_err,'STATUS',v_stat)
return, tmp_str
endif
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_pos_hungarian': begin
burley = conv_pos_hungarian(temporary(burley),orig_names,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
'apply_rtn_qflag': begin
burley = apply_rtn_qflag(temporary(burley),orig_names,index=vindex)
end
'apply_rtn_cadence': begin
burley = apply_rtn_cadence(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
'apply_esa_qflag': begin
burley = apply_esa_qflag(temporary(burley),orig_names,index=vindex)
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
'error_bar_array': begin
burley=error_bar_array(temporary(burley), $
index=vindex,value=0.02)
end
'convert_toev': begin
burley=convert_toev(temporary(burley), orig_names, index=vindex)
end
'convert_ni': begin
burley=convert_Ni(temporary(burley), orig_names, index=vindex)
end
'correct_fast_by': begin
burley = correct_FAST_By(temporary(burley),orig_names,index=vindex)
end
'compute_cadence': begin
burley = compute_cadence(temporary(burley),orig_names,index=vindex)
end
'extract_array': begin
burley = extract_array(temporary(burley),orig_names,index=vindex)
end
'expand_wave_data': begin
burley = expand_wave_data(temporary(burley),orig_names,index=vindex)
end
'make_stack_array': begin
burley = make_stack_array(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
if keyword_set(DEBUG) then 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.'
; RCJ 01/14/2013 Add keyword 'all' to call to merge_metadata:
;burley = merge_metadata(cnames, burley)
burley = merge_metadata(cnames, burley, all=all)
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,$
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)
endif
Return, burley
end