FUNCTION ieeeopen, filename IF N_PARAMS() NE 1 THEN BEGIN print, 'open_ieee: Need filename' RETURN, 0 ; undefined ENDIF openr, unit, filename, /GET_LUN print,unit finfo = fstat(unit) loninfo = assoc(unit, lonarr(1)) bytinfo = assoc(unit, bytarr(1)) IF 16909060 THEN BEGIN ; thats the magic number print, 'open_ieee: This is not an IEEEIO file; ', filename RETURN, 0 ENDIF ; we'll switch to handles later for the ; following data structure; descriptor = {IEEEINFO, NDATASETS:0, UNIT:0, DATASETS:LONARR(5000), ATTRIBUTES:LONARR(5000, 12)} descriptor.unit = unit descriptor.ndatasets = (loninfo(2))(0) PRINT, 'scanning file for records' ; now scan the file for records FINDEX = LONG(16) FOR I=0, descriptor.ndatasets-1 DO BEGIN PTR = assoc(unit, LONARR(1), FINDEX) ; 0=type<1 is data> 1=len 2=seq IF (PTR(0))(0) EQ 1 THEN BEGIN descriptor.DATASETS(I) = FINDEX ; store this data offset ;print, 'Data RecordI=', i ;print, 'RecordType=', PTR(0) ;print, 'RecordLength=', PTR(1) ;print, 'RecordSeq=', PTR(2) FINDEX = FINDEX + 12 + (PTR(1))(0) ; NOW Seek to the next record FOR J=0, 11 DO BEGIN PTR = assoc(unit, LONARR(1), FINDEX) ; 0=type<1 is data> 1=len 2=seq ;print, 'I=', i, ' J=', j ;print, 'RecordType=', PTR(0) ;print, 'RecordLength=', PTR(1) ;print, 'RecordSeq=', PTR(2) IF (PTR(0))(0) EQ 3 THEN descriptor.ATTRIBUTES(I,J) = FINDEX ; store annotation offset IF (PTR(0))(0) EQ 1 THEN J = 11 ELSE FINDEX = FINDEX + 12 + (PTR(1))(0) IF FINDEX GE finfo.size THEN J = 11 END ENDIF END print, 'was successful' RETURN, descriptor END PRO ieeeclose, descriptor IF descriptor.unit GE 0 THEN close, descriptor.unit ELSE print, 'closeieee: Already closed' descriptor.unit = -1 print, 'closeieee: done' RETURN END FUNCTION ieeendatasets, descriptor IF N_PARAMS() LE 0 THEN BEGIN print, 'PRO ieeendatasts: Requires an ieeeio file descriptor' RETURN, -1 ENDIF IF descriptor.unit LT 0 THEN BEGIN print, 'PRO ieeendatasts: error, descriptor is closed or invalid' RETURN, -1 ENDIF RETURN, descriptor.ndatasets END FUNCTION ieeenattribs, descriptor, datasetnumber IF N_PARAMS() LT 2 THEN BEGIN print, 'PRO ieeendatasts: Requires an ieeeio file descriptor and the dataset number.' RETURN, -1 ENDIF IF descriptor.unit LT 0 THEN BEGIN print, 'PRO ieeendatasts: error, descriptor is closed or invalid' RETURN, -1 ENDIF IF datasetnumber GE descriptor.ndatasets THEN BEGIN print, 'PRO ieeenattribs: There are only ', descriptor.ndatasets, ' datasets in this file ' print, ' You were requesting info from dataset number ', datasetnumber RETURN, -1 ENDIF nattribs = 12 ; default FOR I=0, 11 DO BEGIN IF descriptor.attributes(datasetnumber, I) EQ 0 THEN BEGIN nattribs = I I = 11 ; exit the loop ENDIF END RETURN, nattribs END PRO ieeereadattr, descriptor, datasetnumber, NAME=name, NUMBER=attribnumber, LENGTH=len, TYPE=datatype, DATA=data, ASSOC_ELEMENTS=assoc_e, ASSOC_1D=assoc_1d, COPY=cpy, ALLOCATE=alloc, INFO=nodat, BYNAME=byname IF N_ELEMENTS(descriptor) LT 1 THEN BEGIN print, 'PRO ieeeread: You need to provide at least a IEEE file descriptor to call this routine' RETURN ENDIF IF descriptor.unit LT 0 THEN BEGIN print, 'PRO ieeeread: The IEEE file descriptor you specified is either closed or invalid' RETURN ENDIF IF N_ELEMENTS(datasetnumber) LT 1 THEN datasetnumber = 0 ; eg. default datasetnumber=0 IF datasetnumber GT (1+descriptor.ndatasets) THEN BEGIN print, 'PRO ieeeread: There are only ', descriptor.ndatasets, ' datasets in this file' print, 'You attempted to read dataset number ', datasetnumber RETURN ENDIF ; should check for indexing past max ; annotation index IF (N_ELEMENTS(attribnumber) EQ 0) OR (KEYWORD_SET(BYNAME) NE 0) THEN BEGIN ; no index provided, so we are probably searching by name ; print, 'Byname flag is set or NUMBER is not set' IF (KEYWORD_SET(NAME) NE 0) THEN BEGIN ; find attribute by name (ICK!) ; lets call ourself recursively to ; scan for attrib names ; print, 'We are searching by name ; because the number is undefined' nattribs = ieeenattribs(descriptor, datasetnumber) FOR i=0, nattribs-1 DO BEGIN ; for each annotation ; use recursive call to get the name ; of the parameter IF descriptor.attributes(datasetnumber, i) NE 0 THEN ieeereadattr, descriptor, datasetnumber, NUMBER=i, NAME=nm, /INFO IF nm EQ name THEN BEGIN attribnumber = i i = nattribs-1 ; end the search ENDIF END IF nm NE name THEN BEGIN ; that name was not found attribnumber = -1 len = -1 datatype = -1 RETURN ; would be easier if could return scalars from a PRO ENDIF ENDIF ENDIF IF KEYWORD_SET(assoc_e) THEN assoc_e = 1 ELSE assoc_e = 0 ; this is just for convenience (you'll see) IF KEYWORD_SET(assoc_1d) THEN assoc_1d = 1 ELSE assoc_1d = 0 IF KEYWORD_SET(cpy) THEN cpy = 1 ELSE cpy = 0 IF KEYWORD_SET(alloc) THEN alloc = 1 ELSE alloc = 0 IF KEYWORD_SET(nodat) THEN nodat = 1 ELSE nodat = 0 IF KEYWORD_SET(byname) THEN byname = 1 ELSE byname = 0 ;print, 'lets read some info' ; Now lets read the info attribhdr = assoc(descriptor.unit, lonarr(1), descriptor.attributes(datasetnumber, attribnumber) + 12) len = (attribhdr(0))(0) datatype = (attribhdr(1))(0) namelen = (attribhdr(2))(0) namehdr = assoc(descriptor.unit, bytarr(namelen-1), descriptor.attributes(datasetnumber, attribnumber) + 24) ; offset to stored name offset = descriptor.attributes(datasetnumber, attribnumber) + 24 + namelen ; used for data reading later on IF datatype EQ 1 THEN len = len / 2 ELSE $ ; the length is in bytes, must divide by sizeof type IF (datatype EQ 2) OR (datatype EQ 4) THEN len = len / 4 ELSE $ IF (datatype EQ 3) OR (datatype EQ 5) THEN len = len / 8 ; default is BYTE ;print, 'len=', len, ' type=', datatype, ' namelen=', namelen ; note: the bytarr is of length ; namelen-1 to strip it of the ; null terminator bname = namehdr(0) ; print, 'bname=' ;help, bname name = STRING(bname) ; convert from bytarr to String type ; print, 'name=', name IF nodat NE 0 THEN RETURN ; we've copied all of the info and they don't want the data so... print, 'now well read some data' CASE datatype OF 0:BEGIN IF assoc_e THEN data = assoc(descriptor.unit,bytarr(1), offset) ELSE $ IF assoc_1d THEN data = assoc(descriptor.unit,bytarr(len), offset) ELSE BEGIN ; Associate with file descriptor since ; this is the only simple way to lseek() in IDL; rawdata = assoc(descriptor.unit, bytarr(len), offset) ; Here's where we actually assign or ; copy the data IF (N_ELEMENTS(data) NE len) OR (alloc NE 0) THEN data = rawdata(0) ELSE data(*) = rawdata(0) ; copy 1D ENDELSE END 1:BEGIN IF assoc_e THEN data = assoc(descriptor.unit,intarr(1), offset) ELSE $ IF assoc_1d THEN data = assoc(descriptor.unit,intarr(len), offset) ELSE BEGIN ; Associate with file descriptor since ; this is the only simple way to lseek() in IDL; rawdata = assoc(descriptor.unit, intarr(len), offset) ; Here's where we actually assign or ; copy the data IF (N_ELEMENTS(data) NE len) OR (alloc NE 0) THEN data = rawdata(0) ELSE data(*) = rawdata(0) ; copy 1D ENDELSE END 2:BEGIN IF assoc_e THEN data = assoc(descriptor.unit,lonarr(1), offset) ELSE $ IF assoc_1d THEN data = assoc(descriptor.unit,lonarr(len), offset) ELSE BEGIN ; Associate with file descriptor since ; this is the only simple way to lseek() in IDL; rawdata = assoc(descriptor.unit, lonarr(len), offset) ; Here's where we actually assign or ; copy the data IF (N_ELEMENTS(data) NE len) OR (alloc NE 0) THEN data = rawdata(0) ELSE data(*) = rawdata(0) ; copy 1D ENDELSE END 3:BEGIN print, 'PRO ieeeread: Error... This data is Int64 and IDL has no 64-bit integer datatype.' END 4:BEGIN IF assoc_e THEN data = assoc(descriptor.unit,fltarr(1), offset) ELSE $ IF assoc_1d THEN data = assoc(descriptor.unit,fltarr(len), offset) ELSE BEGIN ; Associate with file descriptor since ; this is the only simple way to lseek() in IDL; rawdata = assoc(descriptor.unit, fltarr(len), offset) ; Here's where we actually assign or ; copy the data IF (N_ELEMENTS(data) NE len) OR (alloc NE 0) THEN data = rawdata(0) ELSE data(*) = rawdata(0) ; copy 1D ENDELSE END 5:BEGIN IF assoc_e THEN data = assoc(descriptor.unit,dblarr(1), offset) ELSE $ IF assoc_1d THEN data = assoc(descriptor.unit,dblarr(len), offset) ELSE BEGIN ; Associate with file descriptor since ; this is the only simple way to lseek() in IDL; rawdata = assoc(descriptor.unit, dblarr(len), offset) ; Here's where we actually assign or ; copy the data IF (N_ELEMENTS(data) NE len) OR (alloc NE 0) THEN data = rawdata(0) ELSE data(*) = rawdata(0) ; copy 1D ENDELSE END ENDCASE RETURN END PRO ieeeread, descriptor, datasetnumber, RANK=rank, DIMENSIONS=dims, TYPE=datatype, DATA=data, ASSOC_ELEMENTS=assoc_e, ASSOC_1D=assoc_1d, COPY=cpy, ALLOCATE=alloc, INFO=nodat IF N_ELEMENTS(descriptor) LT 1 THEN BEGIN print, 'PRO ieeeread: You need to provide at least a IEEE file descriptor to call this routine' RETURN ENDIF IF descriptor.unit LT 0 THEN BEGIN print, 'PRO ieeeread: The IEEE file descriptor you specified is either closed or invalid' RETURN ENDIF IF N_ELEMENTS(datasetnumber) LT 1 THEN datasetnumber = 0 ; eg. default datasetnumber=0 IF datasetnumber GT (1+descriptor.ndatasets) THEN BEGIN print, 'PRO ieeeread: There are only ', descriptor.ndatasets, ' datasets in this file' print, 'You attempted to read dataset number ', datasetnumber RETURN ENDIF IF KEYWORD_SET(assoc_e) THEN assoc_e = 1 ELSE assoc_e = 0 ; this is just for convenience (you'll see) IF KEYWORD_SET(assoc_1d) THEN assoc_1d = 1 ELSE assoc_1d = 0 IF KEYWORD_SET(assoc_2d) THEN assoc_2d = 1 ELSE assoc_2d = 0 IF KEYWORD_SET(assoc_3d) THEN assoc_3d = 1 ELSE assoc_3d = 0 IF KEYWORD_SET(cpy) THEN cpy = 1 ELSE cpy = 0 IF KEYWORD_SET(alloc) THEN alloc = 1 ELSE alloc = 0 IF KEYWORD_SET(nodat) THEN nodat = 1 ELSE nodat = 0 datahdr = assoc(descriptor.unit, lonarr(1), descriptor.datasets(datasetnumber) + 12) ; datasize,numbertype,rank,dims(ndims) datatype = (datahdr(1))(0) rank = (datahdr(2))(0) IF n_elements(dims) LT rank THEN dims = intarr(rank) FOR I=0, rank-1 DO dims(I) = (datahdr(3+I))(0) ; copy the dims print, 'dims=', dims offset = descriptor.datasets(datasetnumber) + 24 + rank*4 unit = descriptor.unit ; In this section we do sanity checks ; on the calling parameters aflags = assoc_e + assoc_1d + assoc_2d + assoc_3d print, 'aflags=', aflags IF aflags GT 1 THEN print, 'PRO ieeeread: you can only use one association type... not ALL of them' dflags = cpy + alloc + nodat print, 'dflags=', dflags IF dflags GT 1 THEN print, 'PRO ieeeread: Choose one of /COPY, /ALLOCATE, or /INFO.' IF (dflags GT 1) AND (aflags GT 1) THEN print, 'PRO ieeeread: the /ASSOC flags are mutually exclusive of all of the others. Dont mix them' IF (nodat) THEN BEGIN ; IF (nodat) OR (KEYWORD_SET(DATA) EQ 0) THEN BEGIN ; GRRRR.... if data is empty, then ; keyword_set(DATA) gives 0. There is ; way to see if someone said "DATA=d" ; at the call. So, must force people ; to use /INFO switch to tell if they ; don't intend to read any data. ;print, 'DATA Keyword val=', KEYWORD_SET(DATA) RETURN ; no data or (eg. the /INFO flag) ENDIF nelements = LONG(1) FOR I=0,rank-1 DO nelements = nelements*dims(I) print, 'nelements=', nelements IF (cpy) THEN BEGIN IF (N_ELEMENTS(DATA) LT nelements) THEN BEGIN print, 'PRO ieeereader: The dataset requires ', nelements, ' you have only provided ', N_ELEMENTS(DATA) print, ' If you want this routine to do the allocation, then use /ALLOCATE or dont use the /COPY flag' print, ' Otherwise you should allocate data of the proper type and size for reading' print, ' Dimensions are not important as long as you have enough elements' RETURN ENDIF ; will have additional checks for ; datatype sanity here ENDIF print, 'now we read data' CASE datatype OF 0:BEGIN IF assoc_e THEN data = assoc(descriptor.unit,bytarr(1), offset) ELSE $ IF assoc_1d THEN data = assoc(descriptor.unit,bytarr(dims(0)), offset) ELSE $ IF assoc_2d THEN data = assoc(descriptor.unit, bytarr(dims(0), dims(1)), offset) ELSE $ IF assoc_3d THEN data = assoc(descriptor.unit, bytarr(dims(0), dims(1), dims(2)), offset) ELSE BEGIN ; Associate with file descriptor since ; this is the only simple way to lseek() in IDL; IF rank EQ 1 THEN rawdata = assoc(descriptor.unit, bytarr(dims(0)), offset) ELSE $ IF rank EQ 2 THEN rawdata = assoc(descriptor.unit, bytarr(dims(0), dims(1)), offset) ELSE $ IF rank EQ 3 THEN rawdata = assoc(descriptor.unit, bytarr(dims(0), dims(1), dims(2)), offset) ; Here's where we actually assign or ; copy the data IF (N_ELEMENTS(data) EQ 0) OR (alloc) THEN data = rawdata(0) ELSE BEGIN ; copy and allocate ; OK, here's where we copy data. if no ; data is allocated then the statement ; above will automatically do that for us IF rank EQ 1 THEN data(*) = rawdata(0) ELSE $ ; copy 1D IF rank EQ 2 THEN data(*, *) = rawdata(0) ELSE $ ; copy 2D IF rank EQ 3 THEN data(*, *, *) = rawdata(0) ; copy 3D ENDELSE ENDELSE END 1:BEGIN IF assoc_e THEN data = assoc(descriptor.unit,intarr(1), offset) ELSE $ IF assoc_1d THEN data = assoc(descriptor.unit,intarr(dims(0)), offset) ELSE $ IF assoc_2d THEN data = assoc(descriptor.unit, intarr(dims(0), dims(1)), offset) ELSE $ IF assoc_3d THEN data = assoc(descriptor.unit, intarr(dims(0), dims(1), dims(2)), offset) ELSE BEGIN ; Associate with file descriptor since ; this is the only simple way to lseek() in IDL; IF rank EQ 1 THEN rawdata = assoc(descriptor.unit, intarr(dims(0)), offset) ELSE $ IF rank EQ 2 THEN rawdata = assoc(descriptor.unit, intarr(dims(0), dims(1)), offset) ELSE $ IF rank EQ 3 THEN rawdata = assoc(descriptor.unit, intarr(dims(0), dims(1), dims(2)), offset) ; Here's where we actually assign or ; copy the data IF (N_ELEMENTS(data) EQ 0) OR (alloc) THEN data = rawdata(0) ELSE BEGIN ; copy and allocate ; OK, here's where we copy data. if no ; data is allocated then the statement ; above will automatically do that for us IF rank EQ 1 THEN data(*) = rawdata(0) ELSE $ ; copy 1D IF rank EQ 2 THEN data(*, *) = rawdata(0) ELSE $ ; copy 2D IF rank EQ 3 THEN data(*, *, *) = rawdata(0) ; copy 3D ENDELSE ENDELSE END 2:BEGIN IF assoc_e THEN data = assoc(descriptor.unit,lonarr(1), offset) ELSE $ IF assoc_1d THEN data = assoc(descriptor.unit,lonarr(dims(0)), offset) ELSE $ IF assoc_2d THEN data = assoc(descriptor.unit, lonarr(dims(0), dims(1)), offset) ELSE $ IF assoc_3d THEN data = assoc(descriptor.unit, lonarr(dims(0), dims(1), dims(2)), offset) ELSE BEGIN ; Associate with file descriptor since ; this is the only simple way to lseek() in IDL; IF rank EQ 1 THEN rawdata = assoc(descriptor.unit, lonarr(dims(0)), offset) ELSE $ IF rank EQ 2 THEN rawdata = assoc(descriptor.unit, lonarr(dims(0), dims(1)), offset) ELSE $ IF rank EQ 3 THEN rawdata = assoc(descriptor.unit, lonarr(dims(0), dims(1), dims(2)), offset) ; Here's where we actually assign or ; copy the data IF (N_ELEMENTS(data) EQ 0) OR (alloc) THEN data = rawdata(0) ELSE BEGIN ; copy and allocate ; OK, here's where we copy data. if no ; data is allocated then the statement ; above will automatically do that for us IF rank EQ 1 THEN data(*) = rawdata(0) ELSE $ ; copy 1D IF rank EQ 2 THEN data(*, *) = rawdata(0) ELSE $ ; copy 2D IF rank EQ 3 THEN data(*, *, *) = rawdata(0) ; copy 3D ENDELSE ENDELSE END 3:BEGIN print, 'PRO ieeeread: Error... This data is Int64 and IDL has no 64-bit integer datatype.' END 4:BEGIN IF assoc_e THEN data = assoc(descriptor.unit,fltarr(1), offset) ELSE $ IF assoc_1d THEN data = assoc(descriptor.unit,fltarr(dims(0)), offset) ELSE $ IF assoc_2d THEN data = assoc(descriptor.unit, fltarr(dims(0), dims(1)), offset) ELSE $ IF assoc_3d THEN data = assoc(descriptor.unit, fltarr(dims(0), dims(1), dims(2)), offset) ELSE BEGIN ; Associate with file descriptor since ; this is the only simple way to lseek() in IDL; IF rank EQ 1 THEN rawdata = assoc(descriptor.unit, fltarr(dims(0)), offset) ELSE $ IF rank EQ 2 THEN rawdata = assoc(descriptor.unit, fltarr(dims(0), dims(1)), offset) ELSE $ IF rank EQ 3 THEN rawdata = assoc(descriptor.unit, fltarr(dims(0), dims(1), dims(2)), offset) ; Here's where we actually assign or ; copy the data IF (N_ELEMENTS(data) EQ 0) OR (alloc) THEN data = rawdata(0) ELSE BEGIN ; copy and allocate ; OK, here's where we copy data. if no ; data is allocated then the statement ; above will automatically do that for us IF rank EQ 1 THEN data(*) = rawdata(0) ELSE $ ; copy 1D IF rank EQ 2 THEN data(*, *) = rawdata(0) ELSE $ ; copy 2D IF rank EQ 3 THEN data(*, *, *) = rawdata(0) ; copy 3D ENDELSE ENDELSE END 5:BEGIN IF assoc_e THEN data = assoc(descriptor.unit,dblarr(1), offset) ELSE $ IF assoc_1d THEN data = assoc(descriptor.unit,dblarr(dims(0)), offset) ELSE $ IF assoc_2d THEN data = assoc(descriptor.unit, dblarr(dims(0), dims(1)), offset) ELSE $ IF assoc_3d THEN data = assoc(descriptor.unit, dblarr(dims(0), dims(1), dims(2)), offset) ELSE BEGIN ; Associate with file descriptor since ; this is the only simple way to lseek() in IDL; IF rank EQ 1 THEN rawdata = assoc(descriptor.unit, dblarr(dims(0)), offset) ELSE $ IF rank EQ 2 THEN rawdata = assoc(descriptor.unit, dblarr(dims(0), dims(1)), offset) ELSE $ IF rank EQ 3 THEN rawdata = assoc(descriptor.unit, dblarr(dims(0), dims(1), dims(2)), offset) ; Here's where we actually assign or ; copy the data IF (N_ELEMENTS(data) EQ 0) OR (alloc) THEN data = rawdata(0) ELSE BEGIN ; copy and allocate ; OK, here's where we copy data. if no ; data is allocated then the statement ; above will automatically do that for us IF rank EQ 1 THEN data(*) = rawdata(0) ELSE $ ; copy 1D IF rank EQ 2 THEN data(*, *) = rawdata(0) ELSE $ ; copy 2D IF rank EQ 3 THEN data(*, *, *) = rawdata(0) ; copy 3D ENDELSE ENDELSE END ENDCASE RETURN END