Blame view

src/idl_misc/my_create_struct.pro 9.15 KB
427f1205   Jean-Michel Glorian   version 4.2 merged
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
pro my_create_struct, struct, strname, tagnames, tag_descript, DIMEN = dimen, $
              CHATTER = chatter
;+
; NAME:
;	MY_CREATE_STRUCT
; PURPOSE:
;	Create an IDL structure from a list of tag names and
;	dimensions
; EXPLANATION:
;	Dynamically create an IDL structure variable from list of tag
;	names 
;	and data types of arbitrary dimensions.   Useful when the type
;	of
;	structure needed is not known until run time.
; CALLING SEQUENCE:
;	MY_CREATE_STRUCT, STRUCT, strname, tagnames, tag_descript,
;	[DIMEN = ,/CHATTER, /NODELETE]
; INPUTS:
;	STRNAME -   name to be associated with structure (string)
;		Must be unique for each structure created.
;               Set STRNAME = '' to create an anonymous structure
;	TAGNAMES -  tag names for	structure elements
;		(string or string array)
;
;	TAG_DESCRIPT -	String descriptor for the structure
;                       containing the tag type and dimensions.
;                For example, 'A(2),F(3),I', would be the descriptor for
;	         a structure with 3 tags, strarr(2),fltarr(3) and
;	         Integer scalar, respectively.
;		Allowed types are 'A' for strings,
;              'B' or 'L' for unsigned byte integers,
;              'I' for integers, 'J' for longword integers,
;	'F' or 'E' for floating point, 'D' for double precision
;	'C' for complex, and 'M' for double complex
;	Uninterpretable characters in a format field are ignored.
;	For vectors, the tag description can also be specified by
;	a repeat count.  For example, '16E,2J' would specify a
;	structure with two tags, fltarr(16), and lonarr(2)
; OPTIONAL KEYWORD INPUTS:
;   DIMEN - number of dimensions of structure array (default is 1)
;
;   CHATTER -  If /CHATTER is set, then CREATE_STRUCT will display
;	the dimensions of the structure to be created, and prompt
;	the user whether to continue.  Default is no prompt.
; OUTPUTS:
;	STRUCT -   IDL structure, created according to specifications
; EXAMPLES:
;	IDL> my_create_struct, new,
;	'name',['tag1','tag2','tag3'], 'D(2),F,A(1)'
;       will create a structure variable new, with structure name NAME
;	To see the structure of new:
;       IDL> help,new,/struc
;	** Structure NAME, 3 tags, 20 length:
;          TAG1
;	DOUBLE         Array(2)
;          TAG2            FLOAT
;	0.0
;          TAG3            STRING         Array(1)
;
;
; PROCEDURE:
;       At present, can fail if a tag_name cannot be used as a proper
;	structure component definition, e.g., '0.10' will not
;	work, but a typical string like 'RA' or 'DEC' will.
;	A partial workaround checks for characters '\' and '/'
;	and '.' and converts them to '_'. in a tag_name.
;
;       Note that 'L' now specifies a LOGICAL (byte) data type and not
;       a LONG data type for consistency with FITS binary tables
;
; RESTRICTIONS:
;
;       The name of the structure must be unique, for each structure
;       created.
;	Otherwise, the new variable will have the same structure as
;	the 
;	previous definition (because
;          the temporary procedure will not be
;	recompiled).
;          ** No error message will be generated  ***
;
; SUBROUTINES CALLED:
;	GETTOK(), OS_FAMILY(), REPCHR() 
;
;
; MODIFICATION HISTORY:
;    Version 1.0 RAS January 1992
;    Modified 26 Feb 1992 for Rosat IDL Library (GAR)
;    Modified Jun 1992 to accept arrays for tag elements -- KLV,Hughes STX
;    Accept anonymous structures W. Landsman  HSTX Sep. 92
;    Accept 'E' and 'J' format specifications W. Landsman Jan 93
;	    'L' format now stands for logical and not long array
;    Accept repeat format for vectors  W. Landsman Feb 93
;    Accept complex and double complex (for V4.0)   W. Landsman Jul 95
;    Work for long structure definitions  W. Landsman Aug 97
;    Modified 27/12/98 JPhB to use resolve_routine.
;    Modified 04/12/03 JPhB to use execute. No more temporary routine
;    is used
;-
;-------------------------------------------------------------------------------

 npar = N_params()

 if (npar LT 4) then begin
   print,'Syntax - MY_CREATE_STRUCT, STRUCT, strname, tagnames, tag_descript,' 
   print,'                  [ DIMEN = , /CHATTER, /NODELETE ]'
   return
endif

 if not keyword_set( chatter) then chatter = 0 ;default is 0
 if (N_elements(dimen) eq 0) then dimen = 1            ;default is 1

 if (dimen lt 1) then begin
  print,' Number of dimensions must be >= 1. Returning.'
  return
endif

; For anonymous structure, strname = ''
  anonymous = 0b
  if (strlen( strtrim(strname,2)) EQ 0 ) then anonymous = 1b

; --- Determine if a file already exists with same name as temporary
;     file

 tempfile = 'temp_' + strlowcase( strname )

 if !VERSION.OS NE "vms" then begin            ;Don't overwrite file in Unix
EXIST: 
    list = findfile( tempfile + '.pro', COUNT = Nfile)
     if (Nfile GT 0) then begin
       tempfile = tempfile + 'x'
       goto, EXIST
   endif
endif

 good_fmts = [ 'A', 'B', 'I', 'L', 'F', 'E', 'D', 'J','C','M' ]
 fmts = ["' '",'0B','0','0B','0.0','0.0','0.0D0','0L','complex(0)', $
           'dcomplex(0)']
 arrs = [ 'strarr', 'bytarr', 'intarr', 'bytarr', 'fltarr', 'fltarr', $
          'dblarr', 'lonarr','complexarr','dcomplexarr']
 ngoodf = N_elements( good_fmts )

; If tagname is a scalar string separated by commas, convert to a
; string array

 tagname = tagnames
 sz_name = size( tagnames )
 if  ( sz_name(0) Eq 0 ) then begin
         tempname = tagnames
         tagname = gettok(tempname,',')
         while (tempname NE '') do tagname = [ tagname, gettok(tempname,',') ]
 endif else tagname = tagnames

 Ntags = N_elements(tagname)

; Replace any illegal characters in the tag names with an underscore

 bad_chars = [ '\',  '/',  '.']
 for k = 0, N_elements( bad_chars) -1 do $ 
         tagname = repchr( tagname, bad_chars(k), '_' )

;  If user supplied a scalar string descriptor then we want to break
;  it up
;  into individual items.    This is somewhat complicated because the
;  string
;  delimiter is not always a comma, e.g. if 'F,F(2,2),I(2)', so we
;  need
;  to check positions of parenthesis also.

 sz = size(tag_descript)
 if sz(0) EQ 0 then begin
      tagvar = strarr( Ntags)
      temptag = tag_descript
      for i = 0, Ntags - 1 do begin
         comma = strpos( temptag, ',' )
         lparen = strpos( temptag, '(' )
         rparen = strpos( temptag, ')' )
            if ( comma GT lparen ) and (comma LT Rparen) then pos = Rparen+1 $
                                                         else pos = comma 
             if pos EQ -1 then begin
                 if i NE Ntags-1 then message, $
         'WARNING - could only parse ' + strtrim(i+1,2) + ' string descriptors'
                 tagvar(i) = temptag 
                 goto, DONE
             endif else begin
                    tagvar(i) = strmid( temptag, 0, pos )
                    temptag = strmid( temptag, pos+1, 1000)
                endelse
             endfor
             DONE:
            
 endif else tagvar = tag_descript

; create string array for IDL statements, to be written into 
; 'temp_'+strname+'.pro'

pro_string = strarr (ntags + 2) 

 if (dimen EQ 1) then begin

   pro_string(0) = "struct =  { " + strname + " $"
;   pro_string(0) = "struct =  { "+ " $"
   pro_string(ntags+1) = " } "
 endif else begin

   dimen = long(dimen)                ;Changed to LONG from FIX Mar 95
   pro_string(0) = "struct "   + " = replicate ( { " + strname + " $"
   pro_string(ntags+1) = " } , " + string(dimen) + ")"

endelse

 for i = 0, ntags-1 do begin

   goodpos = -1
   try = strupcase( tagvar(i) )
   for j = 0,ngoodf-1 do begin
         fmt_pos = strpos( try, good_fmts(j) )
         if ( fmt_pos GE 0 ) then begin
              goodpos = j
              goto, FOUND_FORMAT
          endif
      endfor

      print,' Format not recognized: ' + tagvar(i)
      print,' Allowed formats are :',good_fmts
      stop,' Redefine tag format (' + string(i) + ' ) or quit now'


FOUND_FORMAT:

    if fmt_pos GT 0 then begin

           repeat_count = strmid( tagvar(i), 0, fmt_pos )
           if strnumber( repeat_count, value ) then begin
                fmt = arrs( goodpos ) + '(' + strtrim(fix(value), 2) + ')'
           endif else begin 
		print,' Format not recognized: ' + tagvar(i)
		stop,' Redefine tag format (' + string(i) + ' ) or quit now'
            endelse

    endif else  begin

 ; Break up the tag descriptor into a format and a dimension
    tagfmts = strmid( tagvar(i), 0, 1)
    tagdim = strtrim( strmid( tagvar(i), 1, 80),2)
    if strmid(tagdim,0,1) NE '(' then tagdim = ''

  if (tagdim EQ '') then fmt = fmts(goodpos) else $
                           fmt = arrs(goodpos) + tagdim 

  endelse
  if anonymous and ( i EQ 0 ) then comma = '' else comma = " , "
  pro_string(i+1) = comma + tagname(i) + ": " + fmt + " $"      

endfor

; Check that this structure definition
; is OK (if chatter set to 1)

if keyword_set ( Chatter )  then begin
   ans = ''
   print,' Structure ',strname,' will be defined according to the following:'
   temp = repchr( pro_string, '$', '')
   print, temp
   read,' OK to continue? (Y or N)  ',ans
   if strmid(strupcase(ans),0,1) eq 'N' then begin
      print,' Returning at user request.'
     return
 endif
 endif 

Nel=(size(pro_string))(1)
sstr=''
FOR i=0L, Nel-1 DO BEGIN
  sstr=sstr+repchr( pro_string(i), '$', '')
ENDFOR

toto=execute(sstr)

return

end         ;pro create_struct