;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 <Spacebar>'
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 ;<cancel> 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 <Finish> 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 <Finish> 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