;+ ; :Description: ; Read a Cassini UVIS data Cube. ; ; :Params: ; filename [in, required, String] : File path to the fits file. ; ; :Keywords: ; HEADER [out, optional, String[]] : String array containing the primary header information. ; NAME [in, optional, String] : Structure name. If omitted, the structure name default to 'SINGLE'. ; ; :Returns: ; Data structure of the following form: ; hdus = {datastruct:... ; datastruct_initial:... ; datastruct_final:... ; } ; where each datastruct* is a structure containing the appropriate data. ; ; :Requires: ; Written with IDL 8.6.1, but should run with anything > 8.3 ; IDLAstro : https://github.com/wlandsman/IDLAstro ; ; :Author: ; Josh Elliott : joshua.elliott@lasp.colorado.edu ; ; :History: ; Created 21 November 2017 ;- function uvis_read_fits_cube, filename, HEADER=header, NAME=name compile_opt idl2 if ~keyword_set(name) then name = 'SINGLE' ; Get the number of hdus fits_info, filename, N_EXT=n_hdus, /SILENT ; Get the header !null = mrdfits(filename, 0, header, /SILENT) hdus = hash() for i=1, n_hdus do begin ; start from 1, 0 is the "primary" which is just the header in our case. hdu = mrdfits(filename, i, /SILENT) hdu = orderedhash(hdu) dataset_name = hdu.Remove('DATASET_NAME') if (dataset_name.contains('CALIBRATION', /fold)) then begin hdus[dataset_name] = hdu['DATA'] endif else begin ; Check the "readouts" dimension to see how many structs we need to put into the array. dims = (hdu['UVIS']).dim if (dims.length eq 2) then begin ; Only one readout is present hdus[dataset_name] = hdu.tostruct() endif else begin ; For multiple readouts, each data element will have an extra "readout" dimension. For example ; the raw counts might have [64,1024,n_readouts] dimensions. ; Rather than return a struct field with this extra dimension, we'll want to unpack it ; into a struct array with n_readouts elements, each of which will have a raw counts field with [64,1024] ; elements, etc. n_readouts = dims[2] ; Create a new struct-array whith n_readounts elements, with each tag in the struct ; having one less dimension that the original (i.e. remove the readouts dimension) new_hdu = orderedhash() foreach item, hdu, key do begin dims = item.dim if (dims.length eq 1) then begin new_hdu[key] = fix(0, TYPE=size(item, /TYPE)) endif else begin new_hdu[key] = make_array(DIMENSION=dims[0:-2], TYPE=size(item, /TYPE)) endelse endforeach new_hdu = replicate(new_hdu.tostruct(), n_readouts) ; Convert to struct hdu = hdu.tostruct() ; Now use IDL's snazzy array indexing magic to write the struct.field[dims, n_readouts] ; variables into the struct[n_readouts].field[dims] variables. for j=0, n_tags(hdu)-1 do new_hdu.(j) = hdu.(j) hdus[dataset_name] = new_hdu endelse endelse endfor ; Return the struct return, hdus.tostruct() end