;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; Read in a particular data set and its attributes. ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ function read_sds,sd_id,sds_name,attr,start=start,count=count ;------------------------------------------------------------------------------- ; Read in the sds corresponding to sds_name and all of its attributes. ;------------------------------------------------------------------------------- index = hdf_sd_nametoindex(sd_id,sds_name) ;print,sds_name,sd_id sds_id = hdf_sd_select(sd_id,index) hdf_sd_getinfo,sds_id,natts=natts,dims=dims,ndims=ndims if (n_elements(start) eq ndims) then begin data_start = (start > 0) < (dims - 1) endif else begin data_start = replicate(0L,ndims) endelse if (n_elements(count) eq ndims) then begin data_count = (count > 1) < (dims - start) endif else begin data_count = dims endelse hdf_sd_getdata,sds_id,sds_data,start=data_start,count=data_count if (natts eq 0) then $ attr = create_struct('message','no global attributes were found') for n=0L, natts-1L do begin hdf_sd_attrinfo,sds_id,n,name=name,data=attr_data name = idl_validname(name,/convert_all) if (n eq 0) then $ attr = create_struct(name,attr_data) $ else $ attr = create_struct(attr,name,attr_data) endfor hdf_sd_endaccess,sds_id return,sds_data end ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ function hdf_sds_reader, filename, $ data, $ path=path, $ start=start, $ count=count, $ hdf_struct=hdf_struct, $ sds_index=sds_index, $ attr=attr, $ hdf_names=hdf_names, $ scale_fct=scale_fct, $ print_sds_names=print_sds_names, $ sds_names_only=sds_names_only, $ quiet=quiet, $ help=help ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; NAME: ; HDF_SDS_READER ; ; PURPOSE: ; This is a flexible routine for reading HDF SDS data sets and their ; associated attributes (including global attributes) ; ; CATEGORY: ; File reader ; ; CALLING SEQUENCE: ; status = hdf_sds_reader(filename, $ ; data, $ ; path=path, $ ; start=start, $ ; count=count, $ ; hdf_struct=hdf_struct, $ ; sds_index=sds_index, $ ; attr=attr, $ ; hdf_names=hdf_names, $ ; scale_fct=scale_fct, $ ; print_sds_names=print_sds_names, $ ; sds_names_only, $ ; quiet=quiet, $ ; help=help ; ; INPUTS: ; FILENAME The name of the HDF file to be read ; ; OUTPUTS: ; DATA A structure variable containing all of the SDS's ; read in. The name of each structure member will ; be the same as in the hdf file. For example: ; The SDS "Radiance" is stored as data.radiance. ; Note that if hdf_struct is set, the SDS name tag ; is taken from the alias list, not the actual SDS ; name. See keyword HDF_STRUCT for more details. ; ; RETURNS: ; 0: if successful ; -1: if unsuccessful ; ; KEYWORD PARAMETERS: ; PATH Set this keyword to the name of the directory where ; the hdf file is located. The default is './' ; ; START Set this keyword to a vector containing the start ; position in the array (s) to be read. The default ; is [0,0,....0] ; ; COUNT Set this keyword to a vector containing the number ; of items in the array (s) to be read. The default ; is to read all items. ; ; HDF_STRUCT Set this keyword to a 2 X N_sds string array so that ; hdf_struct = [[actual_sds_name1, alias_sds_name1], $ ; [actual_sds_name2, alias_sds_name2], ...] ; ; SDS_INDEX Set this keyword to a vector of SDS data indices. ; If hdf_struct is not set, then only SDS's with these ; index values in filename will be read. If hdf_struct ; is set, only hdf_struct[*,sds_index] will be read. ; ; ATTR Set this keyword to a named structure variable in ; which all global attributes and attributes associated ; with each SDS read will be returned in structure form. ; The name of each structure member will be the same as ; in the hdf file. For example: the global attribute ; "CREATED" is stored as attr.created. The attrubute ; "units" associated with SDS name "Radiance" is ; stored as attr.radiance.units. Note that if hdf_struct ; is set, the SDS name tag is taken from the alias list. ; ; HDF_NAMES Set this keyword to a named variable in which all of ; the sds names in the file will be returned (or all of ; the names in hdf_struct, if hdf_struct is set). ; ; SCALE_FCT Set this keyword to the name of a function (in string ; form) of type: result = scale_fct_name(scaled_data_array, ; attr) where scaled_data_array is an SDS read from the ; HDF file and attr is the same as ATTR. This function is ; used to unscale scaled data in hdf_sds_reader prior to ; returning to the caller. ; ; PRINT_SDS_NAMES Set this keyword to print all of the sds ; names in the file (or all of the names in ; hdf_struct, if hdf_struct is set). ; ; SDS_NAMES_ONLY Set this keyword to return to the caller prior to ; reading any SDS's. This is useful if you just want to ; get the names of the SDS's (via the hdf_names keyword) ; or read the global attributes into ATTR and return. ; ; QUIET Set this keyword to avoid printing information about ; which SDS's are read. ; ; HELP Set this keyword to display USAGE information. ; ; MODIFICATION HISTORY ; Written by: Mike Pavolonis, NOAA/NESDIS, 1 March 2007 ; ; EXAMPLES ; See hdf_sds_reader_demo.pro ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ if ((n_params() ne 2 and $ keyword_set(print_sds_names) eq 0 and $ keyword_set(sds_names_only) eq 0) or $ (n_elements(filename) eq 0) or $ (keyword_set(help))) then begin print,'USAGE:' print,'result = hdf_sds_reader(filename,' print,' data,' print,' path=path' print,' start=start' print,' count=count' print,' hdf_stuct=hdf_struct' print,' sds_index=sds_index' print,' attr=attr' print,' hdf_names=hdf_names' print,' scale_fct=scale_fct' print,' print_sds_names' print,' sds_names_only' print,' quiet=quiet' print,' help=help' return,-1 endif ;------------------------------------------------------------------------------- ; Set the default file path. ;------------------------------------------------------------------------------- if (keyword_set(path) eq 0) then path = './' ;------------------------------------------------------------------------------- ; Make sure the input file is HDF. ;------------------------------------------------------------------------------- ;print, path ;print, 'Reading '+ filename if not hdf_ishdf(path + filename) then message, 'Input parameter FILENAME is not HDF' ;if not hdf_ishdf(filename) then message, 'Input parameter FILENAME is not HDF' ;------------------------------------------------------------------------------- ; Open the HDF file in SDS read mode. ;------------------------------------------------------------------------------- sd_id = hdf_sd_start(path + filename,/read) ;------------------------------------------------------------------------------- ; Determine how many data sets and global attributes are in the file. ;------------------------------------------------------------------------------- hdf_sd_fileinfo,sd_id,nsds_file,nglobal_attr ;------------------------------------------------------------------------------- ; Read in all of the global attributes and store in attr. ;------------------------------------------------------------------------------- for n=0L, nglobal_attr-1L do begin hdf_sd_attrinfo,sd_id,n,name=name,data=attr_data name = idl_validname(name,/convert_all) if (n eq 0) then $ attr = create_struct(name,attr_data) $ else $ attr = create_struct(attr,name,attr_data) endfor if (nglobal_attr eq 0) then $ attr = create_struct('message','no global attributes were found') ;------------------------------------------------------------------------------- ; If keyword hdf_struct is not set load it up with every sds name in the file, ; otherwise, check to make sure that hdf_struct is of the expected format. ;------------------------------------------------------------------------------- if (n_elements(hdf_struct) eq 0) then begin hdf_struct = strarr(2,nsds_file) hdf_names = strarr(nsds_file) nsds = nsds_file for n=0L, nsds-1L do begin sds_id = hdf_sd_select(sd_id,n) hdf_sd_getinfo,sds_id,name=name hdf_struct[0,n] = name hdf_names[n] = name name = idl_validname(name,/convert_all) hdf_sd_endaccess,sds_id hdf_struct[1,n] = name endfor endif else begin result = size(hdf_struct,/n_dimensions) if (result gt 2) then $ message,'hdf_struct must be a 2 x N string array.' result = size(hdf_struct,/dimen) if (result[0] ne 2) then $ message,'hdf_struct must be a 2 x N string array.' nsds = n_elements(hdf_struct[0,*]) hdf_names = reform(hdf_struct[0,*]) endelse if (keyword_set(sds_names_only)) then begin hdf_sd_end,sd_id return,0 endif ;------------------------------------------------------------------------------- ; If keyword print_sds_names is set, print out the contents of hdf_struct and ; return success. ;------------------------------------------------------------------------------- if (keyword_set(print_sds_names)) then begin print_hdf_list,hdf_struct,nsds hdf_sd_end,sd_id return,0 endif ;------------------------------------------------------------------------------- ; If a subset of the sds's listed in hdf_struct are to be read make sure ; keyword sds_index is set properly. ;------------------------------------------------------------------------------- if (n_elements(sds_index) gt 0) then begin if (min(sds_index) lt 0 or max(sds_index) ge nsds) then begin print,format='("SDS index values must be 0 <= sds_index < ",I0)',nsds return,-1 endif index = sds_index endif else begin index = indgen(nsds) endelse ;------------------------------------------------------------------------------- ; Determine how many sds's are to be read. ;------------------------------------------------------------------------------- nsds_read = n_elements(index) ;------------------------------------------------------------------------------- ; If keyword quiet is not set, print out a list of the sds's that will be read. ;------------------------------------------------------------------------------- if (not keyword_set(quiet)) then begin print,'' print,'Reading the following SDS(s): from ' + filename for n=0L, nsds_read-1L do $ print,format='("SDS index = ",I3,2X,A0)',index[n],hdf_struct[0,index[n]] print,'' endif ;------------------------------------------------------------------------------- ; Loop over each sds that is to be read, read the data and attributes, apply the ; unscale function if keyword scale_fct is set, append the data and attributes ; to the output structures. ;------------------------------------------------------------------------------- for n=0L, nsds_read-1L do begin ;print,sd_id,hdf_struct[0,index[n]] sds_data = read_sds(sd_id,hdf_struct[0,index[n]], $ sds_attr,start=start, $ count=count) if (keyword_set(scale_fct) ne 0) then $ sds_data = call_function(scale_fct,sds_data,sds_attr) attr = create_struct(attr,hdf_struct[1,index[n]],sds_attr) if (n eq 0) then begin data = create_struct(hdf_struct[1,index[n]],sds_data) endif else begin data = create_struct(data,hdf_struct[1,index[n]],sds_data) endelse endfor ;------------------------------------------------------------------------------- ; Close the hdf file. ;------------------------------------------------------------------------------- hdf_sd_end,sd_id ;------------------------------------------------------------------------------- ; Return success. ;------------------------------------------------------------------------------- return,0 end