; GETTAGS - Helper function: Recursively get the tag names of an IDL struct. ; gettags, struct, vartyp=vartyp, /expand ; ; REFPTRA - Helper function: Dereference an array of pointers. ; refptra, arrptr, arrmin ; ; STRCTXT - Print out an IDL structure as an ASCII table ; strctxt, struct, tagnam, maxwid=40, filnam='output.txt' ;+ ; NAME: ; GETTAGS ; ; PURPOSE: ; Recursively get the tag names of an IDL struct. ; ; CATEGORY: ; General. ; ; CALLING SEQUENCE: ; gettags, struct [, vartyp=vartyp] [, /expand] ; ; REQUIRED INPUTS: ; struct an IDL structure ; ; OPTIONAL INPUTS: ; none ; ; KEYWORDS: ; expand recursively expand nested structures ; ; OUTPUTS: ; result the tag names of the structure ; vartyp type of variable in the respective tag ; ; DESCRIPTION AND EXAMPLE: ; This function determines the tag names and variable types for the ; elements in an IDL structure. If the keyword EXPAND is set, then tag ; names are also determined for nested structures. The program is ; called by: ; result = gettags(struct) ; ; CALLED BY: ; strctxt. ; ; CALLING: ; None. ; ; MODIFICATION HISTORY: ; 2009-06-26 Written by Konrad R. Tristram ; FUNCTION GETTAGS, STRUCT, VARTYP=VARTYP, EXPAND=EXPAND ; GET THE TAG NAMES IN THE STRUCT ;------------------------------------------------------------------------------- tagnam = tag_names(struct) ; DETERMINE THE VARIABLE TYPES ;------------------------------------------------------------------------------- vartyp = make_array(n_elements(tagnam), /byte) for i=0,n_elements(tagnam)-1 do begin didrun = execute('vartyp[i] = size(struct.' + tagnam[i] + ', /type)') ; REFERENCE POINTERS IF PRESENT ;----------------------------------------------------------------------- if (vartyp[i] eq 10) then begin didrun = execute('vartyp[i] = size(*struct[0].' + $ tagnam[i] + ', /type)') endif endfor ; EXPAND NESTED STRUCTURES ;------------------------------------------------------------------------------- idxnum = (where(vartyp eq 8))[0] while keyword_set(expand) and (idxnum ne -1) do begin didrun = execute('tmptag = gettags(struct.' + tagnam[idxnum] + $ ', vartyp=vartmp, expand=expand)') tmptag = tagnam[idxnum] + '.' + tmptag if idxnum eq 0 then begin tagnam = [tmptag, tagnam[idxnum+1:*]] vartyp = [vartmp, vartyp[idxnum+1:*]] endif else if idxnum ge n_elements(tagnam)-1 then begin tagnam = [tagnam[0:idxnum-1], tmptag] vartyp = [vartyp[0:idxnum-1], vartmp] endif else begin tagnam = [tagnam[0:idxnum-1], tmptag, tagnam[idxnum+1:*]] vartyp = [vartyp[0:idxnum-1], vartmp, vartyp[idxnum+1:*]] endelse idxnum = (where(vartyp eq 8))[0] endwhile ; RETURN THE TAG NAMES AS A RESULT ;------------------------------------------------------------------------------- return, tagnam END ;+ ; NAME: ; REFPTRA ; ; PURPOSE: ; Dereference an array of pointers. ; ; CATEGORY: ; General. ; ; CALLING SEQUENCE: ; refptra, arrptr [, arrmin] ; ; REQUIRED INPUTS: ; arrptr an array of pointers ; ; OPTIONAL INPUTS: ; arrmin number of elements to read from each dereferenced variable ; ; KEYWORDS: ; none ; ; OUTPUTS: ; result an array containing the dereferenced variables ; ; DESCRIPTION AND EXAMPLE: ; This function automatically dereferences an array of pointers. For this ; to work the pointers in the array must all point to the same type of ; variable and the pointers must not point to structures. The variable ; type for the result is defined by the variable type of the dereference ; for the first element in ARRPTR. If the dereferenced variables are ; arrays, all arrays are cropped to the shortest one. The program is ; called by: ; result = refptra(arrptr) ; ; CALLED BY: ; strctxt. ; ; CALLING: ; None. ; ; MODIFICATION HISTORY: ; 2009-06-26 Written by Konrad R. Tristram ; FUNCTION REFPTRA, ARRPTR, ARRMIN ; PRINT ERROR MESSAGE AND EXIT IF ARRPTR IS NO ARRAY OF POINTERS ;------------------------------------------------------------------------------- if size(arrptr, /type) ne 10 then begin print, 'Argument must be an array of pointers.' return, -1 endif ; GET NUMBER OF ELEMENTS IN ARRPTR ;------------------------------------------------------------------------------- numele = n_elements(arrptr) ; DETERMINE NUMBER OF ELEMENTS IN THE DEREFERENCED VARIABLES IF NOT PROVIDED ;------------------------------------------------------------------------------- if not keyword_set(arrmin) then begin arrmin = 1d99 for i=0,numele-1 do arrmin = arrmin < n_elements(*arrptr[i]) endif arrmin = arrmin > 1 ; CREATE THE RESULT ARRAY ;------------------------------------------------------------------------------- vartyp = size(*arrptr[0], /type) result = make_array(numele, arrmin, type=vartyp) ; LOOP OVER THE ELEMENTS IN ARRPTR AND COPY THE DATA INTO THE RESULT ARRAY ;------------------------------------------------------------------------------- for i=0,numele-1 do begin tmpvar = *arrptr[i] if n_elements(tmpvar) ge arrmin then begin result[i,*] = tmpvar[0:arrmin-1] endif else begin result[i,0:n_elements(tmpvar)-1] = tmpvar endelse endfor ; RETURN THE RESULT ;------------------------------------------------------------------------------- return, result END ;+ ; NAME: ; STRCTXT ; ; PURPOSE: ; Print out an IDL structure as an ASCII table. ; ; CATEGORY: ; General. ; ; CALLING SEQUENCE: ; strctxt, struct [, tagnam] [, maxwid=maxwid] [, filnam=filnam] ; ; REQUIRED INPUTS: ; struct an IDL structure ; ; OPTIONAL INPUTS: ; tagnam the names of the tags to be printed out as columns ; ; KEYWORDS: ; maxwid maximum with of a (text) column ; filnam file name for output into a text file ; ; OUTPUTS: ; a table on screen ; ; DESCRIPTION AND EXAMPLE: ; This procedure prints out the contents of a struct array in form of a ; table of fixed size, with each column corresponding to one tag in the ; struct. The size of the column is determined from the data type and ; the space needed by the largest element in this column. For strings, ; the width of the column is limited by the keyword MAXWID; its default ; value is 40. The names of the tags and hence columns have to be ; specified by the string array TAGNAM. If TAGNAM is not set then all ; tags of the struct are printed as columns. The program is called by: ; midi_strc2t, struct ; ; CALLED BY: ; midi_strc2t. ; ; CALLING: ; gettags, refptra. ; ; MODIFICATION HISTORY: ; 2009-06-26 Generalised from midi_strc2t by Konrad R. Tristram ; 2011-07-28 K. Tristram: Fixed problem with new lines in header row. ; 2012-08-27 K. Tristram: Added key word FILNAM. ; PRO STRCTXT, STRUCT, TAGNAM, MAXWID=MAXWID, FILNAM=FILNAM ; DO VARIABLE CHECK AND INITIALISE THE STRING VARIABLES FOR THE PRINT COMMAND ;------------------------------------------------------------------------------- if ~ keyword_set(maxwid) then maxwid = 40 if size(filnam, /type) eq 7 then begin openw, unit, filnam, /get_lun endif else unit = -1 format = '(I3, " | "' commnd = 'printf, unit, format=format, i' header = '(A3, " | "' seltag = 0 ; RECURSIVELY GET THE TAG NAMES AND VARIABLE TYPES IN THE STRUCT ;------------------------------------------------------------------------------- if n_elements(tagnam) lt 1 then tagnam = gettags(struct, /expand) ; LOOP OVER ALL TAGNAMES TO BE PRINTED ;------------------------------------------------------------------------------- for i=0,n_elements(tagnam)-1 do begin ; DETERMINE THE VARIABLE TYPE OF THE CURRENT TAG ;----------------------------------------------------------------------- didrun = execute('vartyp = size(struct[0].' + tagnam[i] + ', /type)') if (vartyp eq 10) then begin didrun = execute('vartyp = size(*struct[0].' + tagnam[i] + $ ', /type)') ptrstr = '*' endif else ptrstr = '' ; CHECK IF THE TAG ACTUALLY EXISTS ;----------------------------------------------------------------------- if didrun and (total(vartyp eq [0,8,10,11]) eq 0) then begin ; ADD THE TAG TO THE PRINT COMMAND AND THE LIST OF GOOD TAGS ;--------------------------------------------------------------- commnd += ', (' + ptrstr + 'struct[i].' + tagnam[i] + ')[0]' seltag = [seltag, i] ; ADD A SPECIFIC FORMAT TO THE FORMAT STRING ;--------------------------------------------------------------- if ptrstr eq '*' then begin didrun = execute('length = refptra(struct.' + $ tagnam[i] + ', 1)') endif else begin didrun = execute('length = struct.' + tagnam[i]) endelse ; ADD A SPECIFIC FORMAT TO THE FORMAT STRING ;--------------------------------------------------------------- case vartyp of 1: begin ; BYTE length = '3' format += ', I' + length + ', " | "' end 2: begin ; INTEGER length = alog10(max(abs(length))) length = strtrim(fix(length)+2 > 5, 1) format += ', I' + length + ', " | "' end 3: begin ; LONG length = alog10(max(abs(length))) length = strtrim(fix(length)+2 > 7, 1) format += ', I' + length + ', " | "' end 4: begin ; FLOAT length = max(abs(alog10(abs(length)))) length = strtrim(fix(length)+5 > 8, 1) if fix(length) gt 12 then begin length = strtrim(10, 1) format += ', E' + length + '.4, " | "' endif else begin format += ', F' + length + '.3, " | "' endelse end 5: begin ; DOUBLE length = max(abs(alog10(abs(length)))) length = strtrim(fix(length)+7 > 10, 1) if fix(length) gt 12 then begin length = strtrim(12, 1) format += ', E' + length + '.6, " | "' endif else begin format += ', F' + length + '.5, " | "' endelse end 6: begin ; COMPLEX length = alog10(max(abs(length))) length = strtrim(fix(length)+5 > 8, 1) format += ', F' + length + '.3, "+"' + $ ', F' + length + '.3, "i | "' length = strtrim(2*fix(length)+2, 1) end 7: begin length = max(strlen(length)) < maxwid > 3 length = strtrim(length, 1) format += ', A-' + length + ', " | "' end else: begin length = strtrim(max(abs(length)) > 3, 1) format += ', A' + length + ', " | "' end endcase ; PRINT THE COLUMN HEADER FOR THIS TAG ;--------------------------------------------------------------- header+=', A' + length + ', " | "' endif else message, 'Skipping this tag.', /infor, /noname endfor ; ADD THE END OF THE FORMAT STRING AND START A NEW LINE ;------------------------------------------------------------------------------- printf, unit, ['NUM', tagnam[seltag[1:*]]], format=header+')' ; ADD THE END OF THE FORMAT STRING AND START A NEW LINE ;------------------------------------------------------------------------------- format += ')' printf, unit, '' ; LOOP OVER ALL ELEMENTS IN STRUCT AND EXECUTE THE PRINT COMMAND ;------------------------------------------------------------------------------- for i=0,n_elements(struct)-1 do didrun = execute(commnd) ; CLOSE THE FILE ;------------------------------------------------------------------------------- if size(filnam, /type) eq 7 then free_lun, unit END