;------------------------------------------------------------------------------ ; NAME: ARRCOL_STRUCT ; ; PURPOSE: To construct and IDL structure for a given ARRAY/COLLECTION ; object; intended for use with ARRCOLPDS.PRO ; ; CALLING SEQUENCE: Result = ARRCOL_STRUCT(label, objindex) ; ; INPUTS: ; Label: String array containing ARRAY/COLLECTION header definitions ; Objindex: Integer specifying the index in the label where the ; ARRAY/COLLECTION object starts ; OUTPUTS: ; Result: ARRAY/COLLECTION idl structure constructed from ; designated record ; ; EXAMPLE: ; To construct and IDL structure for VEGA1 PUMA data: ; IDL> label = headpds('mod0bin0.lbl') ; IDL> result = arrcol_struct(label, 20) ; ; IDL> help, /st, result ; ** Structure <820a61c>, 3 tags, length=637248, data length=635454, refs=1: ; FLAG INT 1 ; RECORD_ARRAY STRUCT -> Array[895] ; COUNT INT 23 ; ; PROCEDURES USED: ARRAY_STRUCT, COLL_STRUCT, ELEM_STRUCT, GET_INDEX, OBJPDS, ; PDSPAR, REMOVE_CHARS ; ; MODIFICATION HISTORY: ; Written by: P. Khetarpal [Jan 23, 2005] ; Last modified: never ; ; For a complete list of modifications, see changelog.txt file. ; ;----------------------------------------------------------------------------- ;-- level 3 ------------------------------------------------------------------- ;------------------------------------------------------------------------------ ; precondition: label is a viable PDS label; cur_ind and end_index are ; viable start and end indices for the current object being processed ; postcondition: the name value is extracted from the label for the ; current object and returned. function extract_name, label, objindex, end_index ; initialize variable: flag = 0 ; name keyword found flag (0: not found, 1: found) ; obtain all names keyword values from label: names = pdspar (label, "NAME", count=name_count, index=name_index) if (name_count gt 0) then begin ; obtain index of object just below objindex object: objects = pdspar(label, "OBJECT", count=objcnt, index=objindices) objpos = where(objindices gt objindex, cnt) ; get names within the current object and next object indices: if (cnt gt 0) then begin greatindex = objindices[objpos[0]] pos = where (name_index gt objindex and name_index lt $ greatindex, ncnt) endif else begin pos = where (name_index gt objindex and name_index lt $ end_index, ncnt) endelse ; check if there was a name keyword found: if (ncnt gt 0) then begin name = names[pos[0]] flag = 1 endif endif if (~flag) then begin print, "Error: missing required NAME keyword from ARRAY/COLLECTION" return, "-1" endif ; convert name to a valid idl name: pattern = ['"', '(', ')', ',', '.', "'"] name = remove_chars(name, pattern) name = idl_validname(name, /convert_all) return, name end ;----------------------------------------------------------------------------- ; precondition: label is a viable PDS label; cur_ind and end_index are ; viable start and end indices for the current object being processed ; postcondition: the bytes value is extracted from the label for the ; current object and returned function extract_bytes, label, cur_ind, end_index ; extract all bytes keyword values from the label: bytes_all = pdspar (label, "BYTES", count=byte_count, index=byte_index) if (byte_count eq 0) then begin print, "Error: missing required BYTES keyword from label" return, -1 endif else begin ; obtain index of object just below objindex object: objects = pdspar(label, "OBJECT", count=objcnt, index=objindices) objpos = where (objindices gt cur_ind, cnt) ; get bytes within the current object and next object indices: if (cnt gt 0) then begin greatindex = objindices[objpos[0]] pos = where (byte_index gt cur_ind and byte_index lt $ greatindex, bcnt) endif else begin pos = where (byte_index gt cur_ind and byte_index lt $ end_index, bcnt) endelse ; check if there was a byte keyword found: if (bcnt eq 0) then begin print, "Error: missing required BYTES keyword in ELEMENT/" + $ "COLLECTION object" return, -1 endif else begin bytes = fix(clean(bytes_all[pos[0]],/space),type=3) endelse endelse ; check validity of bytes value: if (bytes le 0) then begin print, "Error: invalid BYTES keyword value specified: " + $ clean(string(bytes), /space) return, -1 endif return, bytes end ;----------------------------------------------------------------------------- ; precondition: label is a viable PDS label; cur_ind and end_index are ; viable start and end indices for the current object being ; processed ; postcondition: the start_byte value is extracted from the label for ; the current object and returned function extract_start_byte, label, cur_ind, end_index ; initialize variable: start_byte = -1 ; obtain all start_byte keyword values from the label: start_all = pdspar(label, "START_BYTE", count=startcount, index=startindex) if (startcount gt 0) then begin ; obtain index of object just below current object: objects = pdspar(label, "OBJECT", count=objcnt, index=objindices) objpos = where(objindices gt cur_ind, cnt) if (cnt gt 0) then begin greatindex = objindices[objpos[0]] startpos = where (startindex gt cur_ind and startindex lt $ greatindex) endif else begin startpos = where(startindex gt cur_ind and startindex lt end_index) endelse ; check if there was a start byte keyword found: if (startpos[0] gt 0) then begin start_byte = fix(clean(start_all[startpos[0]],/space),type=3) endif endif return, start_byte end ;-- level 2 ------------------------------------------------------------------- ;------------------------------------------------------------------------------ ; precondition: object1 and object2 are idl structures containing ; fields of "array", "index", and "count", where the latter former two ; are string and long arrays, respectively. ; postcondition: the object arrays and indices are sorted using ; sequential sort, and returned as a signle idl structure with the ; same fields. function sort_objects, object1, object2 ; initialize variables: array = [object1.array, object2.array] index = [object1.index, object2.index] count = object1.count + object2.count ; go through the indicies and perform sequential sort: for i = 0, count - 1 do begin min = i for j = i + 1, count - 1 do begin if (index[j] lt index[min]) then begin min = j endif endfor temp1 = index[i] temp2 = array[i] index[i] = index[min] array[i] = array[min] index[min] = temp1 array[min] = temp2 endfor ; create structure: objects = create_struct("array", array, "index", index, "count", count) return, objects end ;----------------------------------------------------------------------------- ; precondition: objectname is a scalar string ; postcondition: the objectname is tested for being an element or not, ; return 1 if it is, 0 otherwise. function is_element, objectname ; find whether the object is an ELEMENT flag = 0 ;; A. Cardesin, 2005-03-29; ;; check wether the string "ELEMENT" is at the end of the objectname. pos = strpos(objectname, "ELEMENT") length = strlen(objectname) if (pos NE -1)&&(pos EQ length-7) then flag = 1 return, flag end ;----------------------------------------------------------------------------- ; precondition: objectname is a scalar string ; postcondition: the objectname is tested for being an array or not, ; return 1 if it is, 0 otherwise. function is_array, objectname ; find whether the object is an ARRAY flag = 0 ;; A. Cardesin, 2005-03-29; correction for MEX/SPICAM/UV channel ;; check wether the string "ARRAY" is at the end of the objectname. pos = strpos(objectname, "ARRAY") length = strlen(objectname) if (pos NE -1)&&(pos EQ length-5) then flag = 1 return, flag end ;----------------------------------------------------------------------------- ; precondition: objectname is a scalar string ; postcondition: the objectname is tested for being a collection or ; not, return 1 if it is, 0 otherwise. function is_collection, objectname ; find whether the object is a collection flag = 0 ;; A. Cardesin, 2005-03-29; ;; check wether the string "COLLECTION" is at the end of the objectname. pos = strpos(objectname, "COLLECTION") length = strlen(objectname) if (pos NE -1)&&(pos EQ length-10) then flag = 1 return, flag end ;-- level 1 ------------------------------------------------------------------- ;------------------------------------------------------------------------------ ; precondition: label is a viable PDS label; objindex is a viable ; start index for current array/collection object ; postcondition: all subobjects associated with the current object are ; extracted, sorted by index order, and returned as a structure function get_subobjects, label, objindex ; initialize variables: objstruct = {flag: 1} ; obtain the end object index for the current objindex: eobjindex = get_index(label, objindex) if (eobjindex eq -1) then goto, endfunction ; obtain all objects and element objects from label and combine them: objects = objpds(label, "ALL") if (objects.flag eq -1) then goto, endfunction elementobjects = objpds(label, "ELEMENT") if (elementobjects.flag eq -1) then begin print, "Error: no sub-objects found for current ARRAY or COLLECTION" goto, endfunction endif objects = sort_objects(objects, elementobjects) ; extract all objects from the label between objindex and eobjindex: pos = where(objects.index ge objindex and objects.index lt eobjindex, cnt) if (cnt eq 0) then begin print, "Error: no sub-objects found for current ARRAY or COLLECTION" goto, endfunction endif else begin objstruct = create_struct(objstruct, "array", objects.array[pos], $ "index", objects.index[pos], "count", n_elements(pos)) endelse return, objstruct endfunction: objstruct.flag = -1 return, objstruct end ;----------------------------------------------------------------------------- ; precondition: label is a viable PDS label; objects contains all ; viable objects/subobjects of current array/collection object to be ; read ; postcondition: all the objects and subobjects are processed ; recursively and the structures are populated and returned function process_structs, label, objects ; initialize variables: struct = {flag: 1} count = 0 ; counter for object index flag = 1 ; flag to determine whether all objects have been ; compiled into the structure ; go through each sub object and compile the object structure: while (flag) do begin if (is_element(objects.array[count])) then begin temp_struct = elem_struct(label,objects.index[count]) count = count + 1 endif else if (is_collection(objects.array[count])) then begin temp_struct = coll_struct (label,objects, count) endif else if (is_array(objects.array[count])) then begin temp_struct = arr_struct (label,objects, count) endif else begin print, "Error: invalid PDS object found in label for processing." goto, endfunction endelse ; check for structure flag: if (temp_struct.flag eq -1) then goto, endfunction struct = create_struct(struct, temp_struct.name, temp_struct.element) if (count eq objects.count) then begin flag = 0 endif endwhile struct = create_struct(struct, "count", count) return, struct endfunction: struct.flag = -1 return, struct end ;-- level 0 ------------------------------------------------------------------- ;------------------------------------------------------------------------------ ; precondition: label is a viable PDS label, and objindex is a viable ; start index of the current array/collection object ; postcondition: the idl structure to be read from the label is ; constructed and returned function arrcol_struct, label, objindex ; error protection: on_error, 1 ; check for the number of arguments: if (n_params() lt 2) then begin print, "Syntax: structure = arrcol_struct(label, objindex)" return, -1 endif ; get sub objects for the current objindex: objects = get_subobjects (label, objindex) if (objects.flag eq -1) then return, objects ; compile object structure: struct = process_structs (label, objects) return, struct end