;Main Program Version: idlcr8ascii.pro v3.0, 20080302 ; Written by Ian Boyd, NIWA-ERI for the AVDC - i.boyd@niwa.com ;Sub-versions: ; v3.01, 20081020 - If the HDF4 file is created using the HDF 4.2r3 library, then extra information ; regarding the dimensions of the VAR_DEPEND values is included in the file (which ; show up as extra datasets in the HDF_SD_FILEINFO call). A check for this is ; carried out and, if found, the information is excluded from the output. PRO idlcr8ascii_common ;Procedure to define the data COMMON block WIDGET_WIN_A, containing common variables ;associated with the Graphical User Interface ; ---------- ;Written by Ian Boyd, NIWA-ERI for the AVDC - i.boyd@niwa.com ; ; History: ; 20061004: Introduced to IDLCR8ASCII - Version 2.0 ; 20080302: 'cwidg' variable removed, and 'dux' array added to identify requested ; output options - Version 3.0 ; ; ; Input: Nil ; ; Output: Nil ; ; Called by: N/A ; ; External Subroutines Called: None COMMON WIDGET_WIN_A,wtxt,lineno,base,o3,b3,dux END ; Procedure idlcr8ascii_common PRO intro_a_event, ev ;Procedure to define how Events from the Start-up Introduction Window are handled ; ---------- ;Written by Ian Boyd, NIWA-ERI for the AVDC - i.boyd@niwa.com ; ; History: ; 20061004: Introduced to IDLCR8ASCII - Version 2.0 ; 20080302: Code added to define the Pop-up Window and Log Output events added to ; the Introduction Window - Version 3.0 ; ; Input: ev - Selected widget event structure ; ; Output: o3 - Common string array defining the various options for program output ; ; Called by: XMANAGER in INTRO_A ; ; External Subroutines Called: None COMMON WIDGET_WIN_A ;The uservalue is retrieved from a widget when an event occurs WIDGET_CONTROL,ev.id,GET_UVALUE=uv IF (uv EQ 'C') OR (uv EQ 'P') OR (uv EQ 'idlcr8ascii.log') THEN BEGIN CASE 1 OF uv EQ 'C': uvi=1 uv EQ 'P': uvi=3 ELSE: uvi=4 ENDCASE IF o3[uvi] EQ uv THEN o3[uvi]='0' ELSE o3[uvi]=uv IF uv EQ 'C' THEN BEGIN IF o3[1] EQ '0' THEN WIDGET_CONTROL,ev.id+6,Sensitive=0 $ ELSE IF o3[1] EQ 'C' THEN BEGIN WIDGET_CONTROL,ev.id+6,Sensitive=1 WIDGET_CONTROL,ev.id+1,/Set_Button o3[3]='P' ENDIF ENDIF ENDIF ELSE IF (uv EQ 'A') OR (uv EQ 'D') THEN o3[0]=uv $ ;Assign button event to a variable name ELSE IF uv EQ 'Cont' THEN o3[0]='0' ;changes o3[0] from -1 to 0 IF (uv NE 'C') AND (uv NE 'P') AND (uv NE 'idlcr8ascii.log') THEN WIDGET_CONTROL,ev.top,/DESTROY END ;Intro_Event handler PRO intro_a, InType ;Procedure which creates an Introduction Window at start-up when IDLCR8ASCII is called without parameters, ;or invalid parameters, or is called by IDL Virtual Machine. The user has a choice of continuing with ;the program after selecting input options, or stopping the program. ; ---------- ;Written by Ian Boyd, NIWA-ERI for the AVDC - i.boyd@niwa.com ; ; History: ; 20061004: Introduced to IDLCR8ASCII - Version 2.0 ; 20080302: Swapped the order of the option windows, so that the options indicated by the check ; boxes appear above the option boxes that close the Introduction Window and continue ; with the program; Added options to allow the user to send input/output log information ; to a Pop-Up Window and/or a Log File - Version 3.0 ; ; Input: intype - Integer set to -1 or -2: -1 indicates normal state; -2 indicates that input ; parameters at the IDLCR8ASCII call were invalid. ; ; Output: Nil ; ; Called by: IDLCR8ASCII ; ; External Subroutines Called: INTRO_A_EVENT (via XMANAGER) COMMON WIDGET_WIN_A ;procedure which provides an introduction message before starting the program. nhdr=43 & errtxt=STRARR(nhdr) errtxt[1]='Welcome to IDLcr8ASCII. This program reads AVDC/NDACC/ENVISAT format HDF4 or' errtxt[2]='HDF5 files and saves contents to either session memory, an output window (summary only)' errtxt[3]='or to files (also refer to Readme_IDLcr8ASCII.pdf).' errtxt[5]='Inputs to the program:' errtxt[6]=' HDF FILE(s) - AVDC format HDF4 or compatible HDF5 files. Input can be by DIALOG_BOX' errtxt[7]=' (IDL VM or full version of IDL), or by command line (full version of IDL only).' errtxt[9]='Choice of output is made by checking options in this DIALOG_BOX (IDL VM or full version' errtxt[10]=' of IDL), or by ''Keywords'' at the command line input (full version only), as follows:' errtxt[11]=' /A or /AVDC - generates two output files (with .META and .DATA extensions). The resulting' errtxt[12]=' files can be used as inputs to AVDC HDF write programs (IDLcr8hdf etc), OR' errtxt[13]=' /D or /DUMP - generates two output files (with .META and .DATA extensions). Data values' errtxt[14]=' will be shown as indicated in the array format defined by VAR_SIZE, AND/OR' errtxt[15]=' /C or /CATALOG - sends variable index, variable name, data format, and dimension size' errtxt[16]=' information to an output window, AND/OR' errtxt[17]=' /P or /POPUP - sends log input/output information to a Pop-up Dialog Box, AND/OR' errtxt[18]=' /L or /LOG - sends log input/output information to a file named idlcr8ascii.log errtxt[20]='Example of command line input: idlcr8ascii,HDFSpec[,/A][,/D][,/C][,/P][,/L], where ''HDFSpec''' errtxt[21]=' can either be a string array containing filenames or a scalar string containing a file spec or' errtxt[22]=' single file name.' errtxt[23]='If running the full version of IDL, and input is a single HDF file, output can also be saved' errtxt[24]=' to session memory. This can be done by calling idlcr8ascii with the following command line:' errtxt[25]=' idlcr8ascii,HDFFile,GA,SDS[,/A][,/D][,/C][,/P][,/L].' errtxt[26]='HDFFile can either be the name of an HDF file or '''' (in which case a DIALOG_BOX will open' errtxt[27]=' and prompt for the input filename). ''GA'' is a returned string array containing the Global' errtxt[28]=' Attributes, and ''SDS'' is a returned structure using pointers containing the Variable' errtxt[29]=' Attributes (SDS.VA), and Data (SDS.Data). errtxt[31]='Contacts -' errtxt[32]=' Ian Boyd, NIWA-ERI (i.boyd@niwa.com)' errtxt[33]=' Department of Astronomy, 619 Lederle GRC, University of Massachusetts' errtxt[34]=' 710 North Pleasant St, Amherst, MA 01002, USA' errtxt[36]=' Bojan Bojkov, AVDC Project Manager (Bojan.Bojkov@gsfc.nasa.gov)' errtxt[37]=' NASA Goddard Space Flight Center, Code 613.3' errtxt[38]=' Greenbelt, MD 20771, USA' errtxt[40]='AVDC Website: Tools and documentation available from http://avdc.gsfc.nasa.gov/Overview/index.html' errtxt[42]='To continue, please choose from the options below.' errtxt=' '+errtxt ;Set-up text display widget IF intype EQ -2 THEN xtxt=' - Command Line Input Error' ELSE xtxt='' base=WIDGET_BASE(Title='idlcr8ascii v3.0 March 2008'+xtxt,Tlb_Frame_Attr=1,/Column) ;,Tab_Mode=1) wtxt=WIDGET_TEXT(base,xsize=88,ysize=17,/Scroll) tip='Left Mouse Click or Tab to entry and hit ' base2=WIDGET_BASE(base,/Nonexclusive) cattxt='Catalog - Generate a summary of the contents of the HDF file and send to an output window or file' poptext='Open a Pop-Up Window to display log input/output (default if ''Catalog'' option is chosen)' logtext='Append log input/output to the file ''idlcr8ascii.log'' (will create the file IF it doesn''t exist)' b1=WIDGET_BUTTON(base2,value=cattxt,uvalue='C',frame=3) ;,ToolTip=Tip) b2=WIDGET_BUTTON(base2,value=poptext,uvalue='P',frame=3) b3=WIDGET_BUTTON(base2,value=logtext,uvalue='idlcr8ascii.log',frame=3) base3=WIDGET_BASE(base,/Row) b4=WIDGET_BUTTON(base3,value='AVDC',uvalue='A',frame=3) ;,Tooltip=Tip) b5=WIDGET_BUTTON(base3,value='DUMP',uvalue='D',frame=3) ;,Tooltip=Tip) b6=WIDGET_BUTTON(base3,value='Continue',uvalue='Cont',frame=3,Sensitive=0) ;,Tooltip=Tip) b7=WIDGET_BUTTON(base3,value='Stop',uvalue='S',frame=3) ;,ToolTip=Tip) WIDGET_CONTROL,base,/Realize WIDGET_CONTROL,b1,/Input_Focus FOR i=0,N_ELEMENTS(errtxt)-1 do $ WIDGET_CONTROL,wtxt,set_value=errtxt[i],/Append XMANAGER,'intro_a',base END ;Intro_A PRO idlcr8ascii_event, ev ;Procedure to close the pop-up logging window after user selects 'Finish'. ; ---------- ;Written by Ian Boyd, NIWA-ERI for the AVDC - i.boyd@niwa.com ; ; History: ; 20061004: Introduced to IDLCR8ASCII - Version 2.0 ; ; Input: Selected widget event structure ; ; Output: Nil ; ; Called by: XMANAGER in IDLCR8ASCII and STOP_WITH_ERROR_A ; ; External Subroutines Called: None WIDGET_CONTROL,ev.top,/DESTROY RETALL & HEAP_GC END ;Proc IDLcr8ASCII_Event PRO stop_with_error_a,txt1,txt2,lu ;Procedure called when an error in the program is detected. An error message is displayed ;and the program stopped and reset. If necessary, open files are closed. The error message ;is displayed in one or more of the following: a Pop-up dialog window; the Pop-up logging ;window; the Output Logging window in the IDLDE. ; ---------- ;Written by Ian Boyd, NIWA-ERI for the AVDC - i.boyd@niwa.com ; ; History: ; 20050729: Original IDLCR8ASCII Routine - Version 1.0 ; 20061004: Set-up so that the error output is displayed in the output window dependent on the ; method that IDLCR8ASCII is called. If txt1 is preceeded by 'D_' or is null, the ; error output is to a Pop-up Dialog window. Otherwise output will be to a logging ; window. Renamed from STOP_WITH_ERROR to STOP_WITH_ERROR_A to avoid a name conflict ; with the equivalent procedure in IDLCR8HDF. Common variable definition WIDGET_WIN_A ; added - Version 2.0 ; 20080302: Added code which sends the error message to the IDLDE output window and/or an external ; file (as determined by the dux array values) - Version 3.0 ; ; Inputs: txt1 - the initial text line of the error message. Generally contains the name of the routine ; where the error was detected. ; txt2 - the second text line which generally describes the error state. ; lu - Where applicable, the file unit that needs to be closed at the termination of the program, ; otherwise set to -1. ; ; Output: Nil ; ; Called by: The routine in which the error was detected. The following routines call STOP_WITH_ERROR: ; READ_HDF_SDS; IDLCR8ASCII ; ; External Subroutines Called: IDLCR8ASCII_EVENT (via XMANAGER) COMMON WIDGET_WIN_A IF lu NE -1L THEN FREE_LUN,lu IF txt1 EQ '' THEN BEGIN ; chosen on Intro box res=DIALOG_MESSAGE('IDLcr8ASCII Stopped!',/Information,Title='AVDC IDLcr8ASCII') ENDIF ELSE BEGIN IF STRMID(txt1,0,2) EQ 'D_' THEN txtx=STRMID(txt1,2) ELSE txtx=txt1 FOR i=dux[0],dux[1],dux[2] DO BEGIN PRINTF,i,' ERROR in '+txtx & PRINTF,i,' '+txt2 PRINTF,i,'' & PRINTF,i,'IDLcr8ASCII stopped - Program Ended on '+SYSTIME(0) ENDFOR IF dux[1] GT -1 THEN FREE_LUN,dux[1] IF STRMID(txt1,0,2) EQ 'D_' THEN BEGIN ;write error to DIALOG Box instead of Popup window errtxt2=STRARR(4) errtxt2[0]=STRMID(txt1,2) & errtxt2[1]=txt2 & errtxt2[3]='IDLcr8ASCII Stopped!' res=DIALOG_MESSAGE(errtxt2,/Error,Title='AVDC IDLcr8ASCII Error') ENDIF ELSE BEGIN ;write error to Popup window lineno=lineno+4L WIDGET_CONTROL,wtxt,set_value=' ERROR in '+txt1,/Append WIDGET_CONTROL,wtxt,set_value=' '+txt2,/Append WIDGET_CONTROL,wtxt,set_value='',/Append,Set_text_top_line=lineno WIDGET_CONTROL,wtxt,set_value='HDF file read stopped - hit to close program',/Append WIDGET_CONTROL,b3,Sensitive=1,/Input_Focus XMANAGER,'stop_with_error_a',base,Event_Handler='idlcr8ascii_event' ENDELSE ENDELSE RETALL & HEAP_GC END ;Procedure Stop_With_Error_A PRO read_hdf_sds, ifile, ga, sds, catinfo ;Procedure to read the contents of an AVDC/Envisat/NDACC HDF4 or HDF5 compatible file ;into session memory ; ---------- ;Written by Ian Boyd, NIWA-ERI for the AVDC - i.boyd@niwa.com ; ; History: ; 20050729: Original IDLCR8ASCII Routine - Version 1.0 ; 20050912: Removed Common variable definition CATALOGINFO and made the variable a parameter passed ; to the procedure; Checks that the attribute variable names read by HDF_SD_GETINFO, match ; those recorded in DATA_VARIABLES in the Global Attributes. If not use the variable name ; listed in DATA_VARIABLES - Version 1.1 ; 20061004: Common variable definition WIDGET_WIN_A added for Error calls; Add option to read HDF5 ; files (needs IDL5.6 or newer); Add check that the HDF4 file has valid information on the ; number of global and variable attributes; Checks added in the event that the HDF4 or ; HDF5 file has been created by the NCSA utility programs H5toH4 or H4toH5 from an original ; AVDC/Envisat/NDACC HDF4 or HDF5 file; Ensures variable attributes and data are listed in ; the same order as that given under DATA_VARIABLES - Version 2.0 ; ; Inputs: ifile - a string containing the name of the HDF file to be read in. ; catinfo - a string identifying the type of HDF file ('H4' or 'H5') ; ; Outputs: ga - a string array containing the global attribute labels and values extracted from the HDF ; file. ; sds - a structure using pointers containing the variable attribute labels and values ; (sds[*].va) and the data (sds[*].data) extracted from the HDF file. ; catinfo - a string array of size [n_sds,4] (where n_sds is the number of datasets in the HDF ; file), containing information on the variable name, data type, data dimension, and ; ; ; Called by: IDLCR8ASCII ; ; External Subroutines Called: STOP_WITH_ERROR_A (if error state detected) ; Possible Conditions for STOP_WITH_ERROR call (plus [line number] where called): ; 1. The number of dimensions of a dataset exceeds the maximum allowable [365] ; 2. The data type of a dataset is not INTEGER, LONG, REAL, or DOUBLE [373] ; 3. No datasets present in the root group of an HDF5 file [503] ; 4. The number of datasets or global attributes not able to be determined in an ; HDF4 file [332] COMMON WIDGET_WIN_A ;Possible error messages for this procedure proname='Read_HDF_SDS procedure: ' errtxt=STRARR(4) errtxt[0]='Number of data dimensions exceeds maximum allowable (max. 8): ' errtxt[1]='Data type not one of the four allowable types: ' errtxt[2]='No Datasets present in the Root Group of the HDF5 File.' errtxt[3]=' not determined in call to HDF_SD_FILEINFO (check for corrupted file).' lu=-1 ;If necessary, free up memory by destroying the heap variables pointed at by its pointer arguments ;from previous calls to this program IF N_ELEMENTS(sds) NE 0 THEN PTR_FREE,sds.va,sds.data ;Define the HDF SDS storage structure sds_set={va: PTR_NEW(), $ ;Variable Attributes data: PTR_NEW()} ;SD data array IF catinfo EQ 'H4' THEN BEGIN ;The HDF_OPEN function opens an HDF file for reading (and/or writing). hdf_file_id=HDF_OPEN(ifile,/READ) ;The HDF_SD_START function opens an HDF file and initializes the SD interface. sd_id=HDF_SD_START(ifile) ;Determine the number of SDS (n_sds) and global attributes (n_ga) found ;in the current file. HDF_SD_FILEINFO,sd_id,n_sds,n_ga IF n_sds EQ 0 THEN ntxt='Number of SDS datasets' $ ELSE IF n_ga EQ 0 THEN ntxt='Number of Global Attributes' $ ELSE ntxt='' IF ntxt NE '' THEN STOP_WITH_ERROR_A,o3[3]+proname,ntxt+errtxt[3],lu ga=STRARR(n_ga) ;set the Global Attribute dimensions vn=[''] ;set default for vn array (to hold Dataset names) ;Dimension the structure to the size of the SDS datasets (with dimension n_sds) sds=REPLICATE(sds_set,n_sds) & n_sds_hold=n_sds ;Read the file's Global Attributes FOR i=0,n_ga-1 DO BEGIN ;The HDF_SD_ATTRINFO procedure reads or retrieves info about an SD attribute. HDF_SD_ATTRINFO,sd_id,i,NAME=ga_name,DATA=ga_data ga_name=STRTRIM(ga_name,2) & ga_data=STRTRIM(ga_data,2) ;Assign global attributes to ga ga[i]=ga_name+'='+ga_data ;read list of DATA_VARIABLES into array IF STRMID(STRUPCASE(ga_name),0,13) EQ 'DATA_VARIABLE' THEN BEGIN vn=STRSPLIT(ga_data,' ;',/Extract) ENDIF ENDFOR ;Determine the number of Attributes and the format type of each SDS mx_atts=0 catinfo=STRARR(n_sds,4) ;output info for catalog output FOR i=0,n_sds-1 DO BEGIN ;The HDF_SD_SELECT function returns an SD dataset ID given the current ;SD interface ID, and the zero-based SD dataset index. sds_id=HDF_SD_SELECT(sd_id,i) ;The HDF_SD_GETINFO procedure retrieves information about an SD dataset. HDF_SD_GETINFO,sds_id,NATTS=sds_natts, $ ;no. attributes TYPE=sds_type, $ ;data type DIMS=sds_dim, $ ;dimension information NAME=sds_name ;dataset name IF N_ELEMENTS(sds_dim) gt 8 THEN $ STOP_WITH_ERROR_A,o3[3]+proname+sds_name+': ',errtxt[0]+STRTRIM(N_ELEMENTS(sds_dim),2),lu ;Rename format to be compatible with the Metadata guidelines IF STRTRIM(sds_type,2) EQ 'INT' THEN sds_type='INTEGER' $ ELSE IF STRTRIM(sds_type,2) EQ 'FLOAT' THEN sds_type='REAL' $ ELSE sds_type=STRTRIM(STRUPCASE(sds_type),2) IF (sds_type NE 'INTEGER') AND (sds_type NE 'LONG') AND $ (sds_type NE 'REAL') AND (sds_type NE 'DOUBLE') THEN $ STOP_WITH_ERROR_A,o3[3]+proname+sds_name+': ',errtxt[1]+sds_type,lu IF sds_natts GT mx_atts THEN mx_atts=sds_natts vat=STRARR(sds_natts) ;Extract the variable attributes FOR j=0,sds_natts-1 DO BEGIN ;The HDF_SD_ATTRINFO procedure reads or retrieves information about an SD attribute. HDF_SD_ATTRINFO,sds_id,j,NAME=va_name,DATA=va_value va_name=STRTRIM(va_name,2) & va_value=STRTRIM(va_value,2) IF STRUPCASE(va_name) EQ 'VAR_NAME' THEN BEGIN ;match the order of the dataset to the DATA_VARIABLES list li=WHERE(STRUPCASE(va_value) EQ STRUPCASE(vn),lcnt) IF lcnt EQ 0 THEN li=[i] ;DATASET name does not match any of the DATA_VARIABLES values ENDIF IF STRTRIM(va_name,2) EQ 'valid_range' THEN $ va_value=STRTRIM(va_value[0],2)+' '+STRTRIM(va_value[1],2) ;Assign Data Attributes to meta_arr vat[j]=va_name+'='+va_value ENDFOR ;Extract the data HDF_SD_GETDATA,sds_id,datasize ;Closes the SDS interface. HDF_SD_ENDACCESS,sds_id ;Do check for Dataset Attribute labels added by the H4toH5 utility (start with HDF4_ ;or DIMENSION) and, if present, do not use. test1=STRMID(STRUPCASE(vat),0,5) NE 'HDF4_' test2=STRMID(STRUPCASE(vat),0,9) NE 'DIMENSION' vi=WHERE((test1) AND (test2),vcnt) ;Do check for sds being a Dimension attribute for VAR_DEPEND values (can happen with 4.2r3 library) ri=WHERE(STRUPCASE(sds_name) EQ STRUPCASE(catinfo[*,0]),rcnt) IF (rcnt EQ 0) OR ((rcnt NE 0) AND (sds_natts NE 3)) THEN BEGIN catinfo[li[0],0]=sds_name & catinfo[li[0],1]=sds_type catinfo[li[0],2]=STRTRIM(sds_dim[0],2) & catinfo[li[0],3]=vcnt IF N_ELEMENTS(sds_dim) GT 1 THEN $ FOR j=1,N_ELEMENTS(sds_dim)-1 DO catinfo[li[0],2]=catinfo[li[0],2]+';'+STRTRIM(sds_dim[j],2) ;save data and variable attributes to sds structure IF vcnt NE 0 THEN sds[li[0]].va=PTR_NEW(vat[vi]) sds[li[0]].data=PTR_NEW(datasize) ENDIF ELSE n_sds_hold=n_sds_hold-1 ;Closes the SDS interface. HDF_SD_ENDACCESS,sds_id ENDFOR ;The HDF_SD_END function closes the SD interface to an HDF file. HDF_SD_END,sd_id ;The HDF_CLOSE procedure closes the HDF file associated with the given file handle. HDF_CLOSE, hdf_file_id catinfo=catinfo[0:n_sds_hold-1,*] ENDIF ELSE BEGIN ;HDF5 format file hdf_file_id=H5F_OPEN(ifile) sd_id=H5G_OPEN(hdf_file_id,'/') ;Get number of attributes within the root group (these are the Global Attributes) n_ga=H5A_GET_NUM_ATTRS(sd_id) ga=STRARR(n_ga) ;set the Global Attribute dimensions ;Read in the Global Attribute labels and values FOR i=0,n_ga-1 DO BEGIN ga_id=H5A_OPEN_IDX(sd_id,i) ga_l=H5A_GET_NAME(ga_id) & ga_l=STRUPCASE(STRTRIM(ga_l,2)) ga_v=H5A_READ(ga_id) & ga_v=STRTRIM(ga_v,2) ;Check for _GLOSDS suffix and strip (added for compatibility with H4toH5 utility) IF STRMID(ga_l,STRLEN(ga_l)-7) EQ '_GLOSDS' THEN $ ga_l=STRMID(ga_l,0,STRPOS(ga_l,'_',/Reverse_Search)) while STRMID(ga_l,STRLEN(ga_l)-1) EQ '_' DO ga_l=STRMID(ga_l,0,STRLEN(ga_l)-1) ga[i]=ga_l+'='+ga_v H5A_CLOSE,ga_id ;Extract the list of the DATA_VARIABLES IF ga_l EQ 'DATA_VARIABLES' THEN BEGIN vn=STRSPLIT(ga_v,' ;',/Extract) ENDIF ENDFOR ;Get the number of objects within the root group (including datasets, groups etc) n_obj=H5G_GET_NMEMBERS(sd_id,'/') d_obj=INTARR(n_obj) ;Determine number of datasets. Note: if H5 file created using H4toH5 then an extra ;group will have been created which will not be used. Also datasets may be listed ;alphabetically. FOR i=0,n_obj-1 DO BEGIN obj_name=H5G_GET_MEMBER_NAME(sd_id,'/',i) h5fstat=H5G_GET_OBJINFO(sd_id,Obj_Name) IF h5fstat.type EQ 'DATASET' THEN d_obj[i]=1 ENDFOR di=WHERE(d_obj EQ 1,n_sds) IF n_sds NE 0 THEN BEGIN ;Dimension the structure to the size of the SDS datasets (with dimension n_sds) sds=REPLICATE(sds_set,n_sds) catinfo=STRARR(n_sds,4) ;output info for catalog output ;Read in data and dataset variable attributes FOR i=0,n_sds-1 DO BEGIN obj_name=H5G_GET_MEMBER_NAME(sd_id,'/',di[i]) ds_id=H5D_OPEN(sd_id,obj_name) datasize=H5D_READ(ds_id) ;Determine the number of attributes associated with the dataset n_da=H5A_GET_NUM_ATTRS(ds_id) vat=STRARR(n_da) ci=STRARR(4) ;array containing catalog attributes ;Read in Dataset Attributes FOR j=0,n_da-1 DO BEGIN da_id=H5A_OPEN_IDX(ds_id,j) da_l=H5A_GET_NAME(da_id) & da_l=STRTRIM(da_l,2) da_v=H5A_READ(da_id) & da_v=STRTRIM(da_v,2) CASE 1 OF STRUPCASE(da_l) EQ 'VAR_NAME':BEGIN ;Determine actual list order from DATA_VARIABLE listing (H5 lists datasets alphabetically) li=WHERE(STRUPCASE(da_v) EQ STRUPCASE(vn),lcnt) IF lcnt EQ 0 THEN li=[j] ;DATASET name does not match any of the DATA_VARIABLES values ci[0]=da_v END STRUPCASE(da_l) EQ 'VAR_DATA_TYPE': ci[1]=da_v STRUPCASE(da_l) EQ 'VAR_SIZE': ci[2]=da_v ELSE: ENDCASE vat[j]=da_l+'='+da_v H5A_CLOSE,da_id ENDFOR H5D_CLOSE,ds_id sds[li[0]].data=PTR_NEW(datasize) ;Do check for Dataset Attribute labels added by the H4toH5 utility (start with HDF4_ ;or DIMENSION) and, if present, do not use. test1=STRMID(STRUPCASE(vat),0,5) NE 'HDF4_' test2=STRMID(STRUPCASE(vat),0,9) NE 'DIMENSION' vi=WHERE((test1) AND (test2),vcnt) IF vcnt NE 0 THEN sds[li[0]].va=PTR_NEW(vat[vi]) ci[3]=STRTRIM(vcnt,2) catinfo[li[0],*]=ci[*] ENDFOR ENDIF ELSE STOP_WITH_ERROR_A,o3[3]+proname,errtxt[2],lu H5G_CLOSE,sd_id H5F_CLOSE,hdf_file_id ENDELSE END ;Procedure Read_HDF_SDS PRO output_hdf_data, ifile, ga, sds, catinfo ;Procedure to output the contents of an HDF file in ASCII form, either in a format compatible for ;conversion back to HDF, or in Row and Column format, or as a summary list ; ---------- ;Written by Ian Boyd, NIWA-ERI for the AVDC - i.boyd@niwa.com ; ; History: ; 20050729: Original IDLCR8ASCII Routine - Version 1.0 ; 20050912: Removed Common variable definition CATALOGINFO and made the variable a parameter passed ; to the procedure; Make output filenames lower case; If data type is double and the ; accompanying VIS_FORMAT value starts with an 'F' (e.g. F9.4), then, change the 'F' to a ; 'D' when specifying the format for output - Version 1.1 ; 20061004: Common variable definition WIDGET_WIN_A added for Error calls; Display input/output ; information in a pop-up display window if the program is opened using IDL VM - Version 2.0 ; 20080302: Added code which sends the Catalog and log output to the IDLDE output window and/or an ; external file (as determined by the dux array values); Ensure all data values are ; separated by a space when the Dump output option is chosen - Version 3.0 ; ; Inputs: ifile - a string containing the name of the HDF file to be read in. ; ga - a string array containing the global attribute labels and values extracted from the HDF ; file. ; sds - a structure using pointers containing the variable attribute labels and values ; (sds[*].va) and the data (sds[*].data) extracted from the HDF file. ; catinfo - a string array of size [n_sds,4] (where n_sds is the number of datasets in the HDF ; file), containing information on the variable name, data type, data dimension, and ; ; Outputs: Nil ; ; Called by: IDLCR8ASCII ; ; External Subroutines Called: None COMMON WIDGET_WIN_A ;determine number of datasets and attributes (from sds.va) as=SIZE(catinfo) n_sds=as[1] & mx_atts=MAX(catinfo[*,3]) IF o3[1] EQ 'C' THEN BEGIN IF o3[3] EQ '' THEN BEGIN lineno=lineno+n_sds+1 wintxt='Listing of Var_Name Index; Var_Name; Var_Data_Type; Var_Size' WIDGET_CONTROL,wtxt,set_value=wintxt,/Append,Set_text_top_line=lineno ENDIF FOR i=dux[0],dux[1],dux[2] DO PRINTF,i,'Listing of Var_Name Index; Var_Name; Var_Data_Type; Var_Size' FOR j=0,n_sds-1 DO BEGIN IF o3[3] EQ '' THEN BEGIN wintxt=STRTRIM(j,2)+'; '+catinfo[j,0]+'; '+catinfo[j,1]+'; '+catinfo[j,2] WIDGET_CONTROL,wtxt,set_value=wintxt,/Append ENDIF FOR i=dux[0],dux[1],dux[2] DO $ PRINTF,i,STRTRIM(j,2),'; ',catinfo[j,0],'; ',catinfo[j,1],'; ',catinfo[j,2] ENDFOR ENDIF IF o3[0] NE '0' THEN BEGIN ;create output filenames outf1=STRMID(ifile,0,STRPOS(ifile,'.',/Reverse_Search))+'.meta' outf2=STRMID(ifile,0,STRPOS(ifile,'.',/Reverse_Search))+'.data' OPENW,lu1,outf1,/GET_LUN OPENW,lu2,outf2,/GET_LUN ;NCSA attributes not to be included in the output files ncsa=['long_name','units','format','coordsys','valid_range','_fillvalue'] PRINTF,lu1,'! Output from IDLcr8ASCII application v3.0' PRINTF,lu1,'! '+ifile & PRINTF,lu1,'!' PRINTF,lu1,'! Global Attributes' FOR i=0,N_ELEMENTS(ga)-1 DO PRINTF,lu1,ga[i] FOR j=0,n_sds-1 DO BEGIN vdt='' ;initialize variable holding the VAR_DATA_TYPE PRINTF,lu1,'!' & PRINTF,lu1,'! Variable Attributes' vat=*sds[j].va PRINTF,lu2,catinfo[j,0] FOR i=0,catinfo[j,3]-1 DO BEGIN ;output set of data attributes IF vat[i] NE '' THEN BEGIN res=STRSPLIT(vat[i],'=',/Extract) ;output attribute to Meta File (do not include NCSA attributes) ni=WHERE(STRLOWCASE(res[0]) EQ ncsa,ncnt) IF ncnt EQ 0 THEN PRINTF,lu1,vat[i] IF STRLEN(vat[i]) LT 13 THEN vat[i]=vat[i]+' ' ;check VAR_DATA_TYPE IF STRMID(STRUPCASE(vat[i]),0,13) EQ 'VAR_DATA_TYPE' THEN $ IF N_ELEMENTS(res) EQ 2 THEN vdt=STRTRIM(STRUPCASE(res[1]),2) ELSE vdt='' ;extract format information IF STRMID(STRUPCASE(vat[i]),0,10) EQ 'VIS_FORMAT' THEN BEGIN IF N_ELEMENTS(res) EQ 2 THEN vf=STRTRIM(res[1],2) ELSE vf='' ;change output format if output is in double precision (needed for some OSs) IF (vdt EQ 'DOUBLE') AND (vf NE '') THEN $ IF STRMID(STRUPCASE(vf),0,1) EQ 'F' THEN vf='D'+STRMID(vf,1) ENDIF ENDIF ENDFOR p_f='('+vf+')' IF o3[0] EQ 'A' THEN BEGIN IF vf NE '' THEN PRINTF,lu2,format=p_f,*sds[j].data $ ;formatted output ELSE PRINTF,lu2,format='(a)',STRTRIM(*sds[j].data,2) ;no valid VIS_FORMAT so use default output ENDIF ELSE IF o3[0] EQ 'D' THEN BEGIN ;Ensure there is a single character between all values sdshold=STRTRIM(*sds[j].data,2) maxstr=MAX(STRLEN(sdshold)) & sdssize=SIZE(sdshold,/Dimension) ;use default IDL formatting rules sdshold=STRING(format='(a'+STRTRIM(maxstr,2)+')',sdshold) ;Uncomment line below if format described by VIS_FORMAT is required ;sdshold=STRING(format=p_f,*sds[j].data) sdshold=REFORM(sdshold,sdssize) PRINTF,lu2,sdshold ENDIF ENDFOR PRINTF,lu1,'!' & PRINTF,lu1,'! End of output file created by IDLcr8ASCII' FREE_LUN,lu1 & FREE_LUN,lu2 IF o3[3] EQ '' THEN BEGIN lineno=lineno+2L WIDGET_CONTROL,wtxt,set_value=outf1+' created!',/Append,Set_text_top_line=lineno WIDGET_CONTROL,wtxt,set_value=outf2+' created!',/Append,Set_text_top_line=lineno ENDIF FOR i=dux[0],dux[1],dux[2] DO BEGIN PRINTF,i,' '+outf1+' created!' & PRINTF,i,' '+outf2+' created!' ENDFOR ENDIF END ;Procedure Output_HDF_Data PRO idlcr8ascii, ifile, ga, sds, AVDC=o1, DUMP=o2, CATALOG=o4, POPUP=o5, LOG=o6 ;Main IDL procedure to read HDF4 or HDF5 files formatted for submission to the AVDC, NDACC, ;or NILU (Envisat) databases. ; ;Program documentation, Readme_IDLcr8ASCII.pdf, available on http://avdc.gsfc.nasa.gov. ; ;Program sub-version 3.01 (20081020) ; ---------- ;Written by Ian Boyd, NIWA-ERI for the AVDC - i.boyd@niwa.com ; ; History: ; 20050729: Original Release - Version 1.0 ; 20050912: Removed Common variable definition CATALOGINFO; If the format of the ; DATA_START_DATE and FILE_GENERATION_DATE values is MJD2000, then change to ISO8601, ; unless the output option is /Dump - Version 1.1 ; 20061004: Common variable definition WIDGET_WIN_A added for Error calls; Make the code suitable ; for running on a licensed version of IDL (using the .pro and .sav versions of the code) ; and on IDL Virtual Machine (using the .sav version of the code); Change the command ; line keyword options. Remove the /Help option (window now opened if there are no command ; line parameters), and /Catalog can now be called together with /AVDC or /Dump; The ; program can now handle multiple HDF files as input (either as a string array or as a ; file spec); Display input/output information as well as errors and warnings in a pop-up ; display window if the program is called using IDL VM; Help window becomes an ; Introduction window, and the user has the option of continuing to run the program with ; file inputs; Include option to read HDF5 versions of the ground-based files ; - Version 2.0 ; 20080302: Remove HELP,/TRACEBACK call, which identified how the program was called. This was used ; to stop output to the IDLDE output window in the event that IDL VM was used, but it is ; not required as IDL VM ignores these print calls; Add options to send Catalog and logged ; input/output information to a Pop-up Box (/Popup) and/or to an external file (/Log). Add ; DIALOG_BOX to show completion of the program if program inputs are via the INTRO box, and ; logging window option isn't requested - Version 3.0 ; ; Inputs: ifile - a string array or filespec containing the name of the HDF file(s) to be read in ; ; OPTIONS ; AVDC - Program generates two output files per input file (with .meta and .data extensions). ; The resulting files are compatible with programs that can write HDF files using ; these two files as input. ; DUMP - Program generates two output files per input file (with .meta and .data extensions). ; Data values will be shown as indicated by the array format defined by VAR_SIZE. ; CATALOG - Program sends the variable index, variable name, format, and dimension(s) ; information to a pop-up window or the IDL DE output log window. ; POPUP - to append input/output information as well as warnings and errors to a pop-up ; display window ; LOG - to append input/output/catalog information as well as errors to a log file named ; idlcr8ascii.log ; ; Outputs: ga - If included as a parameter in the command line, a string array containing the global ; attribute labels and values extracted from a single HDF file. ; sds - If included as a parameter in the command line, a structure using pointers containing ; the variable attribute labels and values (sds[*].va) and the data (sds[*].data) ; extracted from a single HDF file. The data is saved in the form defined by the ; variable attributes ; Two ASCII files per input file containing the attributes and datasets extracted from the HDF ; file(s), if the AVDC or DUMP options are chosen. Summary metadata information if the ; CATALOG option is chosen. ; ; Called by: Main Routine ; ; External Subroutines Called: INTRO_A (if program called without command line parameters) ; READ_HDF_SDS ; JDF_2_DATETIME ; OUTPUT_HDF_DATA (if output is not just to session memory only) ; STOP_WITH_ERROR (if error state detected) ; Possible Conditions for STOP_WITH_ERROR call (plus [line number] where called): ; 1. No valid HDF4 or HDF5 file selected [772, 827, 828, 829] ; ; Warning Conditions (when the program is able to make changes): ; 1. If Session Memory option is chosen can only read in one HDF file [801] COMMON WIDGET_WIN_A ;Possible error messages for this procedure proname='IDLCR8ASCII procedure: ' IF FLOAT(!Version.Release) GE 5.6 THEN errtxt='No valid HDF4 or HDF5 file selected.' $ ELSE BEGIN errtxt='No valid HDF4 file selected ' errtxt=errtxt+'(Note: Input file can only be HDF4 for IDL'+!Version.Release+').' ENDELSE lu=-1 ON_IOERROR,TypeConversionError ;used when checking Datetime format IF N_PARAMS() EQ 1 THEN BEGIN ;File input only ;check to see what output keyword options are set - if none then InType=-2 IF (NOT KEYWORD_SET(o1)) AND (NOT KEYWORD_SET(o2)) AND (NOT KEYWORD_SET(o4)) THEN $ intype=-2 ELSE intype=SIZE(ifile,/Type) ENDIF ELSE IF N_PARAMS() GE 1 THEN intype=SIZE(ifile,/Type) $ ;Check that infile is a string ELSE intype=-1 IF (intype NE 7) AND (intype GE 0) THEN intype=-2 ;First Command line parameter not a string dux=[-1,-1,1] ;initialize flags for output log to IDLDE Output Window and/or to file ;dux[0] default allows output to the IDLDE output window (ignored by IDL VM) ;dux[1] is the program assigned file unit for sending log output to file ;dux[2] is the step between dux[0] and dux[1] o3=['-1','0','0','0','0'] IF intype LT 0 THEN BEGIN ;either no input parameters or invalid second parameter INTRO_A,intype ;Open Intro Box and determine output options (AVDC/DUMP, Catalog, Session Memory) IF o3[0] EQ '-1' THEN STOP_WITH_ERROR_A,'','',lu IF o3[3] EQ 'P' THEN o3[3]='' ELSE o3[3]='D_' ENDIF ELSE BEGIN ;Set options (AVDC/DUMP, Catalog, Session Memory, Popup Window, Log Output) IF KEYWORD_SET(o1) THEN o3=['A','0','0','D_','0'] $ ELSE IF KEYWORD_SET(o2) THEN o3=['D','0','0','D_','0'] ELSE o3=['0','0','0','D_','0'] IF N_PARAMS() EQ 3 THEN o3[2]='M' IF KEYWORD_SET(o4) THEN o3[1]='C' IF KEYWORD_SET(o5) THEN o3[3]='' IF KEYWORD_SET(o6) THEN o3[4]='idlcr8ascii.log' ENDELSE IF N_PARAMS() GE 1 THEN BEGIN ;Check that input HDF files exist. If not then prompt the user for the missing files arorfs=SIZE(ifile,/Dimensions) ;Is HDF file input Filespec or String Array? IF (arorfs[0] EQ 0) THEN BEGIN ;input is filespec IF ifile NE '' THEN ifile=FINDFILE(ifile) isize=SIZE(ifile,/Dimensions) IF isize[0] EQ 0 THEN ifile=[''] ;no files found matching filespec ENDIF IF N_ELEMENTS(arorfs) GT 1 THEN ifile=REFORM(ifile,N_ELEMENTS(ifile),/Overwrite) ;Convert to 1-D array file_exist=FILE_TEST(ifile,/Read) gi=WHERE(file_exist EQ 1,gcnt) IF gcnt NE 0 THEN ifile=ifile[gi] ;contains all valid filenames ENDIF ELSE ifile=[''] gi=WHERE(ifile NE '',nfile) IF nfile EQ 0 THEN BEGIN IF o3[2] EQ 'M' THEN $ ;pick one file only ifile=DIALOG_PICKFILE(Filter=['*.hdf','*.h5'],/Must_Exist, $ Title='Select HDFv4 or HDFv5 AVDC Format File') $ ELSE $ ;multiple selection permissable ifile=DIALOG_PICKFILE(Filter=['*.hdf','*.h5'],/Must_Exist, $ /Multiple_Files,Title='Select HDFv4 or HDFv5 AVDC Format File(s)') ENDIF ;now check to see that files were actually selected, if not STOP! gi=WHERE(ifile NE '',nfile) IF nfile EQ 0 THEN STOP_WITH_ERROR_A,'D_'+proname,errtxt,lu $ ELSE BEGIN ifile=ifile[gi] & dsort=SORT(ifile) & ifile=ifile[dsort] ENDELSE ;Set dux values according to output options IF o3[4] NE '0' THEN BEGIN ;open idlcr8ascii.log res=FILE_TEST(o3[4],/Write) IF res EQ 0 THEN openw,du,o3[4],/GET_LUN $ ELSE BEGIN openw,du,o3[4],/Append,/GET_LUN & FOR i=0,1 DO PRINTF,du,'' ENDELSE dux[1]=du & dux[2]=dux[1]-dux[0] ENDIF FOR i=dux[0],dux[1],dux[2] DO PRINTF,i,'HDF File Input/Output Log - Program Started on '+SYSTIME(0) IF o3[3] EQ '' THEN BEGIN ;Set-up output window display widget base=WIDGET_BASE(Title='HDF File Input/Output Log',Units=2,yoffset=3,xoffset=3,Tlb_Frame_Attr=1,/Column) ;,Tab_Mode=1) wtxt=WIDGET_TEXT(base,/Scroll,xsize=100,ysize=12) base2=WIDGET_BASE(base) b3=WIDGET_BUTTON(base2,value='Finish',uvalue='DONE',frame=3,Sensitive=0) ;,Accelerator='Return') WIDGET_CONTROL,wtxt,/Realize WIDGET_CONTROL,base,/Realize lineno=0L ENDIF IF (o3[2] EQ 'M') AND (N_ELEMENTS(ifile) GT 1) THEN BEGIN ifile=[ifile[0]] & nfile=1 warntxt='WARNING: Can read one HDF file into session memory. Only first file in the array will be read.' IF o3[3] EQ '' THEN BEGIN lineno=lineno+1L WIDGET_CONTROL,wtxt,set_value=warntxt,/Append WIDGET_CONTROL,wtxt,set_value='',/Append ENDIF FOR i=dux[0],dux[1],dux[2] DO BEGIN PRINTF,i,warntxt & PRINTF,i,'' ENDFOR ENDIF FOR ndf=0,nfile-1 DO BEGIN IF o3[3] EQ '' THEN BEGIN lineno=lineno+2L IF ndf NE 0 THEN WIDGET_CONTROL,wtxt,set_value='',/Append WIDGET_CONTROL,wtxt,set_value='Reading '+ifile[ndf],/Append,Set_text_top_line=lineno ENDIF FOR i=dux[0],dux[1],dux[2] DO BEGIN IF ndf NE 0 THEN PRINTF,i,'' PRINTF,i,'Reading '+ifile[ndf] ENDFOR IF FILE_TEST(ifile[ndf]) EQ 1 THEN BEGIN IF HDF_ISHDF(ifile[ndf]) EQ 1 THEN catinfo='H4' $ ELSE IF FLOAT(!Version.Release) GE 5.6 THEN BEGIN IF H5F_IS_HDF5(ifile[ndf]) EQ 1 THEN catinfo='H5' $ ELSE STOP_WITH_ERROR_A,o3[3]+proname,errtxt,lu ENDIF ELSE STOP_WITH_ERROR_A,o3[3]+proname,errtxt,lu ENDIF ELSE STOP_WITH_ERROR_A,o3[3]+proname,errtxt,lu ;Open and read the file READ_HDF_SDS,ifile[ndf],ga,sds,catinfo ;Convert format of DATA_START_DATE and FILE_GENERATION_DATE if required ;Note: for /Dump option output will still be original format gaiso=STRARR(2) gi=WHERE((STRPOS(STRUPCASE(ga),'DATA_START_DATE') NE -1) OR $ (STRPOS(STRUPCASE(ga),'FILE_GENERATION_DATE') NE -1),gcnt) IF gcnt NE 0 THEN BEGIN FOR i=0,gcnt-1 DO BEGIN res=STRSPLIT(ga[gi[i]],' =',/Extract) IF N_ELEMENTS(res) EQ 2 THEN BEGIN IF STRPOS(STRUPCASE(res[1]),'Z') EQ -1 THEN BEGIN ;i.e. not ISO8601 valid=0 ;used for Type Conversion Check mjd=DOUBLE(res[1]) ;will jump to TypeConversionError if Res[1] is not a number valid=1 ;got to here so valid conversion (presumably it is MJD2000) TypeConversionError: IF valid EQ 1 THEN BEGIN iso='' & iso=JDF_2_DATETIME(mjd,/MJD2000,/S) gaiso[i]=res[0]+'='+iso IF o3[0] EQ 'A' THEN ga[gi[i]]=gaiso[i] ENDIF ENDIF ENDIF ENDFOR ENDIF IF (o3[0] NE '0') OR (o3[1] NE '0') THEN OUTPUT_HDF_DATA,ifile[ndf],ga,sds,catinfo FOR i=0,1 DO IF gaiso[i] NE '' THEN ga[gi[i]]=gaiso[i] IF o3[2] EQ 'M' THEN BEGIN IF o3[3] EQ '' THEN BEGIN lineno=lineno+1L WIDGET_CONTROL,wtxt,set_value=ifile+' array and heap structure created!',/Append,Set_text_top_line=lineno ENDIF FOR i=dux[0],dux[1],dux[2] DO PRINTF,i,' '+ifile+' array and heap structure created!' ENDIF ENDFOR FOR i=dux[0],dux[1],dux[2] DO BEGIN PRINTF,i,'' & PRINTF,i,'HDF file read completed - Program Ended on '+SYSTIME(0) ENDFOR IF dux[1] GT -1 THEN FREE_LUN,dux[1] IF o3[3] EQ '' THEN BEGIN WIDGET_CONTROL,b3,Sensitive=1,/Input_Focus WIDGET_CONTROL,wtxt,set_value='',/Append,Set_text_top_line=lineno+2L WIDGET_CONTROL,wtxt,set_value='HDF file read completed - hit to close program',/Append XMANAGER,'idlcr8ascii',base ENDIF ELSE IF intype LT 0 THEN BEGIN ;Create Finish Dialog Box res=DIALOG_MESSAGE('HDF file read completed!',/Information,Title='AVDC IDLcr8ASCII') ENDIF END ;procedure IDLcr8ASCII