;;---------------------------------------------------------------------------- ;; Name: QUBEPDS ;; ;; Purpose: To read a three dimensional PDS QUBE object. ;; ;; Calling Sequence: ;; result = qubepds (filename, label, index [, /SILENT, /NOSCALE]) ;; ;; Input: ;; filename - scalar string containing the name of the PDS file to ;; read ;; label - string array containing the qube header information ;; index - an integer giving the index of label array where the ;; start of the QUBE object ;; ;; Output: ;; result - a qube array constructed from designated record ;; ;; Optional input: ;; SILENT - suppresses any messages from the procedure ;; NOSCALE - does not perform scaling and offset of values, ;; default is to scale and offset. ;; ;; External routines: Verify_label, Get_index, Pointpds, Clean, Get_idl_type, ;; Extract_keyword, Break_string ;; ;; Modification history: ;; Written by Puneet Khetarpal, August 2002 ;; ;; For a complete list of modifications, see changelog.txt file ;; ;;---------------------------------------------------------------------------- ;- level 1 ------------------------------------------------------------------- ; precondition: the label has been verified and index is a viable index ; for QUBE object ; postcondition: the required keywords are extracted and returned as a struct function obtain_qube_required, label, index, endindex ; extract axes keyword axes = extract_keyword(label, 'AXES', index, endindex, 1) ; extract axis name keyword axis_name = extract_keyword(label, 'AXIS_NAME', index, endindex, 1) axis_name = break_string('AXIS_NAME', axis_name, long(axes)) ; extract core items keyword core_items = extract_keyword(label, 'CORE_ITEMS', index, endindex, 1) core_items = break_string('CORE_ITEMS', core_items, long(axes)) ; extract core item bytes keyword core_item_bytes = extract_keyword(label,'CORE_ITEM_BYTES',index,endindex,1) ; extract core item type keyword core_item_type = extract_keyword(label,'CORE_ITEM_TYPE',index, endindex, 1) ; extract core base keyword core_base = extract_keyword(label, 'CORE_BASE', index, endindex, 1) ; extract core multiplier keyword core_mult = extract_keyword(label, 'CORE_MULTIPLIER', index, endindex, 1) ; extract suffix bytes keyword suffix_bytes = extract_keyword(label,'SUFFIX_BYTES', index, endindex, 1) ; extract suffix items keyword suffix_items = extract_keyword(label, 'SUFFIX_ITEMS', index, endindex, 1) suffix_items = break_string('SUFFIX_ITEMS', suffix_items, long(axes)) ; store in a structure struct = {axes:long(axes),axis_name:axis_name,core_items:long(core_items),$ core_item_bytes:long(core_item_bytes), core_item_type:core_item_type,$ core_base:float(core_base), core_multiplier:float(core_mult), $ suffix_bytes:long(suffix_bytes), suffix_items:long(suffix_items)} return, struct end ; precondition: the required keywords have been obtained from label ; postcondition: the qube structure is constructed and returned function obtain_qube_structure, required ; local variables item_bytes = required.core_item_bytes type = required.core_item_type ; get the idl type of the vector to be created idl_type = get_idl_type(type, item_bytes, 'BINARY') ; determine which element contains the SAMPLE axis pos = where (required.axis_name eq "SAMPLE") vector = make_array(required.core_items[pos[0]], type = idl_type) ; construct the structure with sample suffix bytes if any if (required.suffix_items[pos[0]] gt 0) then begin bytes = required.suffix_items[pos[0]] * 4 sample_struct = {sample:vector, sideplane:bytarr(bytes)} endif else begin sample_struct = {sample:vector} endelse ; replicate the above structure LINES items times: pos = where (required.axis_name eq "LINE") lines_struct = replicate(sample_struct, required.core_items[pos[0]]) ; construct the structure with line suffix bytes if any: if (required.suffix_items[pos[0]] gt 0) then begin bytes = required.suffix_items[pos[0]] * 4 band_struct = {line:lines_struct, bottomplane:bytarr(bytes)} endif else begin band_struct = {line:lines_struct} endelse ; replicate the above structure BAND items times: pos = where (required.axis_name eq "BAND") struct = replicate(band_struct, required.core_items[pos[0]]) return, struct end ; precondition: the pointer information is obtained, structure has ; been compiled to be read, the architecture of the data is known ; postcondition: pointer information is used to read the data, the data ; architecture is converted to the appropriate type for reading function read_qube_data, pointer, struct, arch ; error checking on_ioerror, signal ; initialize variable and declare flag data_read = {flag:1} ; 0: error, 1: no error ; open the file to be read and apply swap endian if needed if (arch eq 'MSB') then begin openr, unit, pointer.datafile, /get_lun, /swap_if_little_endian endif else begin openr, unit, pointer.datafile, /get_lun, /swap_if_big_endian endelse ; set the file pointer to current object to be read point_lun, unit, pointer.skip ; read the image object into the structure readu, unit, struct ; close the unit and free it close, unit free_lun, unit ; add to structure data_read = create_struct(data_read, 'struct', struct) ; return return, data_read signal: on_ioerror, null print, "Error: file either corrupted or invalid parameters specified" data_read.flag = 0 return, data_read end ; precondition: current contains the raw qube data structure for ; current cube as read from datafile; keywords contains all ; current qube object keyword values ; postcondition: extracts the qube array from the current structure, ; converts the array values to signed integers if necessary, and ; performs scaling and offset if noscale keyword is not supplied function convert_qube_data, current, keywds, noscale ; extract qube from the read data element = current[*].line[*].sample ; convert data elements for signed bytarr objects ; (IDL only supports byt values of 0-255) if ((keywds.core_item_bytes eq 1) && (~ stregex(keywds.core_item_type, $ 'UNSIGNED', /boolean))) then begin element = fix(element) ; set to integer fixitlist = where (element gt 127, count) ; check where gt 127 if (count gt 0) then begin ; if > 127 found, then element[fixitlist] -= 256 ; subtract 256 endif endif ; process scaling factor and offset if (~ noscale) then begin element *= keywds.core_multiplier ; apply core multiplier element += keywds.core_base ; apply core base endif return, element end ;- level 0 ------------------------------------------------------------------- function qubepds, filename, label, index, SILENT = silent, NOSCALE = noscale ; error check on_error, 1 ; check for number of parameters in function call if (n_params() lt 3) then begin message, "Syntax Error: cube = QUBEPDS(filename, label [,/SILENT, "+$ "/NOSCALE])" endif silent = keyword_set(silent) noscale = keyword_set(noscale) ; verify label res = verify_label(label, filename) ; check current qube object index if (~ stregex(label[index], 'QUBE', /boolean)) then begin print, "Error: Invalid index specified for QUBE object "+string(index) return, 0 endif ; get endindex value for current qube object endindex = get_index(label, index) ; obtain all required qube keywords required = obtain_qube_required(label, index, endindex) ; obtain qube architecture arch = (stregex(required.core_item_type, '(LSB)|(VAX)|(PC)', /boolean)) ? $ 'LSB' : 'MSB' ; obtain qube structure to be read from file struct = obtain_qube_structure(required) ; obtain object name from current index name = stregex(label[index], '= +([0-9A-Z_]+)', /extract, /subexpr) ; obtain pointer information pointer = pointpds(label, filename, name[1]) ; if not silent then inform user if (~ silent) then begin text = "Now reading " for k = 0, required.axes - 2 do begin text += clean(string(required.core_items[k]), /space) + " by " endfor text += clean(string(required.core_items[required.axes - 1]), /space)+$ " qube array" print, text endif ; read data from file data_read = read_qube_data(pointer, struct, arch) ; perform data conversion if necessary data = convert_qube_data(data_read.struct, required, noscale) return, data end