/usr/share/gnudatalanguage/astrolib/fxbread.pro is in gdl-astrolib 2018.02.16+dfsg-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 | PRO FXBREAD, UNIT, DATA, COL, ROW, NOSCALE=NOSCALE, VIRTUAL=VIR, $
DIMENSIONS=DIMS0, NANVALUE=NANVALUE, ERRMSG=ERRMSG, $
NOIEEE=NOIEEE
;+
; NAME:
; FXBREAD
; Purpose :
; Read a data array from a disk FITS binary table file.
; Explanation :
; Each call to FXBREAD will read the data from one column and one row
; from the FITS data file, which should already have been opened by
; FXBOPEN. One needs to call this routine for every column and every row
; in the binary table. FXBCLOSE will then close the FITS data file.
; Use :
; FXBREAD, UNIT, DATA, COL [, ROW ]
; Inputs :
; UNIT = Logical unit number corresponding to the file containing the
; binary table.
; COL = Column in the binary table to read data from, either as a
; character string containing a column label (TTYPE), or as a
; numerical column index starting from column one.
; Opt. Inputs :
; ROW = Either row number in the binary table to read data from,
; starting from row one, or a two element array containing a
; range of row numbers to read. If not passed, then the entire
; column is read in.
;
; Row must be passed for variable length arrays.
;
; Outputs :
; DATA = IDL data array to be read from the file.
; Opt. Outputs:
; None.
; Keywords :
; NOSCALE = If set, then the output data will not be scaled using the
; optional TSCAL and TZERO keywords in the FITS header.
; Default is to scale.
; NOIEEE = If set, then the output data is not byte-swapped to
; machine order. NOIEEE implies NOSCALE.
; Default is to perform the byte-swap.
; VIRTUAL = If set, and COL is passed as a name rather than a number,
; then if the program can't find a column with that name, it
; will then look for a keyword with that name in the header.
; Such a keyword would then act as a "virtual column", with the
; same value for every row.
; DIMENSIONS = Vector array containing the dimensions to be used to read
; in the data. Bypasses any dimensioning information stored in
; the header. Ignored for bit arrays. If the data type is
; double-precision complex, then an extra dimension of 2 is
; prepended to the dimensions passed by the user.
; NANVALUE= Value signalling data dropout. All points corresponding to
; IEEE NaN (not-a-number) are converted to this number.
; Ignored unless DATA is of type float, double-precision or
; complex.
; ERRMSG = If defined and passed, then any error messages will be
; returned to the user in this parameter rather than
; depending on the MESSAGE routine in IDL. If no errors are
; encountered, then a null string is returned. In order to
; use this feature, ERRMSG must be defined first, e.g.
;
; ERRMSG = ''
; FXBREAD, ERRMSG=ERRMSG, ...
; IF ERRMSG NE '' THEN ...
;
; Calls :
; FXPAR, WHERE_NEGZERO, WHERENAN
; Common :
; Uses common block FXBINTABLE--see "fxbintable.pro" for more
; information.
; Restrictions:
; The binary table file must have been opened with FXBOPEN.
;
; The data must be consistent with the column definition in the binary
; table header.
;
; The row number must be consistent with the number of rows stored in the
; binary table header.
;
; The number of elements implied by the dimensions keyword must not
; exceed the number of elements stored in the file.
;
; Side effects:
; If the DIMENSIONS keyword is used, then the number of data points read
; in may be less than the number of points stored in the table.
;
; If there are no elements to read in (the number of elements is zero),
; then the program sets !ERR to -1, and DATA is unmodified.
;
; Category :
; Data Handling, I/O, FITS, Generic.
; Prev. Hist. :
; W. Thompson, Jan 1992.
; W. Thompson, Feb 1992, modified to support variable length arrays.
; W. Thompson, Jun 1992, modified way that row ranges are read in. No
; longer works reiteratively.
; W. Thompson, Jun 1992, fixed bug where NANVALUE would be modified by
; TSCAL and TZERO keywords.
; W. Thompson, Jun 1992, fixed bug when reading character strings.
; Treats dimensions better when reading multiple
; rows.
; Written :
; William Thompson, GSFC, January 1992.
; Modified :
; Version 1, William Thompson, GSFC, 12 April 1993.
; Incorporated into CDS library.
; Version 2, William Thompson, GSFC, 30 June 1993.
; Added overwrite keyword to REFORM call to speed up.
; Version 3, William Thompson, GSFC, 21 July 1993.
; Fixed bug with variable length arrays.
; Version 4, William Thompson, GSFC, 29 October 1993.
; Added error message for not finding column by name.
; Version 5, William Thompson, GSFC, 31 May 1994
; Added ERRMSG keyword.
; Version 6, William Thompson, GSFC, 23 June 1994
; Modified so that ERRMSG is not touched if not defined.
; Version 7, William Thompson, GSFC, 29 December 1994
; Fixed bug where single element dimensions were lost.
; Version 8, William Thompson, GSFC, 20 March 1995
; Fixed bug introduced in version 7.
; Version 9, Wayne Landsman, GSFC, 3 July 1996
; Fixed bug involving use of virtual keyword.
; Version 10, William Thompson, GSFC, 31-Jan-1997
; Added call to WHERE_NEGZERO.
; Version 11, Wayne Landsman, GSFC, 12 Aug, 1997
; Use IDL dcomplex datatype if needed
; Version 12, Wayne Landmsan, GSFC, 20 Feb, 1998
; Remove call to WHERE_NEGZERO (now part of IEEE_TO_HOST)
; Version 13, 18 Nov 1999, CM, Add NOIEEE keyword
; Version 14, 21 Aug 2000, William Thompson, GSFC
; Catch I/O errors
; Version 15, W. Landsman GSFC 10 Dec 2009
; Fix Dimension keyword, remove IEEE_TO_HOST
; Version 16, William Thompson, 18-May-2016, change POINTER to ULONG
; Version :
; Version 16, 18-May-2016
;-
;
@fxbintable
ON_ERROR, 2
ON_IOERROR, HANDLE_IO_ERROR
;
; Check the number of parameters.
;
IF N_PARAMS() LT 3 THEN BEGIN
MESSAGE = 'Syntax: FXBREAD, UNIT, DATA, COL [, ROW ]'
GOTO, HANDLE_ERROR
ENDIF
;
; Find the logical unit number in the FXBINTABLE common block.
;
ILUN = WHERE(LUN EQ UNIT,NLUN)
ILUN = ILUN[0]
IF NLUN EQ 0 THEN BEGIN
MESSAGE = 'Unit ' + STRTRIM(UNIT,2) + ' not opened properly'
GOTO, HANDLE_ERROR
ENDIF
;
; If COL is of type string, then search for a column with that label.
;
SC = SIZE(COL)
VIRTUAL = 0
IF SC[SC[0]+1] EQ 7 THEN BEGIN
SCOL = STRUPCASE(STRTRIM(COL,2))
ICOL = WHERE(TTYPE[*,ILUN] EQ SCOL, NCOL)
ICOL = ICOL[0]
IF (ICOL LT 0) AND (NOT KEYWORD_SET(VIR)) THEN BEGIN
MESSAGE = 'Column "' + SCOL + '" not found'
GOTO, HANDLE_ERROR
ENDIF
;
; If the column was not found, and VIRTUAL was set, then search for a keyword
; by that name.
;
IF NCOL EQ 0 THEN BEGIN
IF KEYWORD_SET(VIR) THEN BEGIN
HEADER = HEAD[*,ILUN]
VALUE = FXPAR(HEADER,SCOL,COUNT=CC)
IF CC GT 0 THEN BEGIN
DATA = VALUE
VIRTUAL = 1
GOTO, CHECK_ROW
ENDIF
ENDIF
MESSAGE = 'Column "' + SCOL + '" not found'
GOTO, HANDLE_ERROR
ENDIF
;
; Otherwise, a numerical column was passed. Check its value.
;
END ELSE ICOL = LONG(COL) - 1
IF (ICOL LT 0) OR (ICOL GE TFIELDS[ILUN]) THEN BEGIN
MESSAGE = 'COL must be between 1 and ' + $
STRTRIM(TFIELDS[ILUN],2)
GOTO, HANDLE_ERROR
ENDIF
;
; If there are no elements in the array, then set !ERR to -1.
;
IF N_ELEM[ICOL,ILUN] EQ 0 THEN BEGIN
MESSAGE,'Number of elements to read in is zero',/INFORMATIONAL
!ERR = -1
RETURN
ENDIF
;
; If ROW was not passed, then set it equal to the entire range. Otherwise,
; extract the range.
;
CHECK_ROW:
IF N_PARAMS() EQ 3 THEN ROW = [1,NAXIS2[ILUN]]
CASE N_ELEMENTS(ROW) OF
1: ROW2 = LONG(ROW[0])
2: ROW2 = LONG(ROW[1])
ELSE: BEGIN
MESSAGE = 'ROW must have one or two elements'
GOTO, HANDLE_ERROR
END
ENDCASE
ROW1 = LONG(ROW[0])
;
; If ROW represents a range, then make sure that the row range is legal, and
; that reading row ranges is allowed (i.e., the column is not variable length.
;
IF ROW1 NE ROW2 THEN BEGIN
MAXROW = NAXIS2[ILUN]
IF (ROW1 LT 1) OR (ROW1 GT MAXROW) THEN BEGIN
MESSAGE = 'ROW[0] must be between 1 and ' + $
STRTRIM(MAXROW,2)
GOTO, HANDLE_ERROR
END ELSE IF (ROW2 LT ROW1) OR (ROW2 GT MAXROW) THEN BEGIN
MESSAGE = 'ROW[1] must be between ' + $
STRTRIM(ROW1,2) + ' and ' + STRTRIM(MAXROW,2)
GOTO, HANDLE_ERROR
END ELSE IF NOT VIRTUAL THEN IF MAXVAL[ICOL,ILUN] GT 0 THEN $
BEGIN
MESSAGE = 'Row ranges not allowed for ' + $
'variable-length columns'
GOTO, HANDLE_ERROR
ENDIF
;
; Otherwise, if ROW is a single number, then just make sure it's valid.
;
END ELSE BEGIN
IF (ROW1 LT 1) OR (ROW1 GT NAXIS2[ILUN]) THEN BEGIN
MESSAGE = 'ROW must be between 1 and ' + $
STRTRIM(NAXIS2[ILUN],2)
GOTO, HANDLE_ERROR
ENDIF
ENDELSE
;
; If a virtual column, then simply return the value. If necessary, then
; replicate the value the correct number of times.
;
IF VIRTUAL THEN BEGIN
IF ROW1 EQ ROW2 THEN DATA = VALUE ELSE $
DATA = REPLICATE(VALUE,ROW2-ROW1+1)
RETURN
ENDIF
;
; Find the position of the first byte of the data array in the file.
;
OFFSET = NHEADER[ILUN] + NAXIS1[ILUN]*(ROW1-1) + BYTOFF[ICOL,ILUN]
POINT_LUN,UNIT,OFFSET
;
; If a variable length array, then read in the number of elements, and the
; pointer to the variable length array. Change the pointing.
;
IF MAXVAL[ICOL,ILUN] GT 0 THEN BEGIN
POINTER = ULONARR(2)
READU,UNIT,POINTER
BYTEORDER, POINTER, /NTOHL
DIMS = POINTER[0]
POINT_LUN,UNIT,NHEADER[ILUN] + HEAP[ILUN] + POINTER[1]
;
; If there are no elements in the array, then set !ERR to -1.
;
IF DIMS EQ 0 THEN BEGIN
MESSAGE,'Number of elements to read in is zero', $
/INFORMATIONAL
!ERR = -1
RETURN
ENDIF
;
; If the datatype is a bit array, then the array is treated as a byte array
; with 1/8 the number of elements.
;
IF FORMAT[ICOL,ILUN] EQ 'X' THEN DIMS = LONG((DIMS+7)/8)
;
; If fixed length, then get the dimensions of the output array.
;
END ELSE BEGIN
DIMS = N_DIMS[*,ICOL,ILUN]
DIMS = DIMS[1:DIMS[0]]
ENDELSE
;
; If the DIMENSIONS keyword has been passed, then use that instead of the
; dimensions already determined.
;
IF (N_ELEMENTS(DIMS0) GT 0) AND (FORMAT[ICOL,ILUN] NE 'X') $
THEN BEGIN
IF PRODUCT(DIMS0) GT PRODUCT(DIMS) THEN BEGIN
MESSAGE = 'Requested dimensions exceeds the ' + $
'number of elements'
GOTO, HANDLE_ERROR
ENDIF
DIMS = DIMS0
ENDIF
;
; Read in the data. If a character string array, then read in a byte array.
;
DATATYPE = IDLTYPE[ICOL,ILUN]
IF DATATYPE EQ 7 THEN DATATYPE = 1
;
; If only reading in a single row, then the pointer should already be set.
; Otherwise, the pointer needs to be set for each row.
;
IF ROW1 EQ ROW2 THEN BEGIN
DATA = MAKE_ARRAY(TYPE=DATATYPE,DIMENSION=DIMS)
DATA = REFORM(DATA,DIMS,/OVERWRITE)
READU,UNIT,DATA
END ELSE BEGIN
DIMS2 = [DIMS, ROW2-ROW1+1]
DATA = MAKE_ARRAY(TYPE=DATATYPE, DIMENSION=DIMS2)
DATA = REFORM(DATA, DIMS2, /OVERWRITE)
TEMPDATA = MAKE_ARRAY(TYPE=DATATYPE, DIMENSION=DIMS)
TEMPDATA = REFORM(TEMPDATA, DIMS, /OVERWRITE)
NTEMP = N_ELEMENTS(TEMPDATA)
FOR IROW = ROW1,ROW2 DO BEGIN
OFFSET = NHEADER[ILUN] + BYTOFF[ICOL,ILUN]
POINT_LUN,UNIT,OFFSET + NAXIS1[ILUN]*(IROW-1)
READU,UNIT,TEMPDATA
DATA[(IROW-ROW1)*NTEMP] = TEMPDATA[*]
ENDFOR
ENDELSE
;
; If a character string array, then convert to type string.
;
IF IDLTYPE[ICOL,ILUN] EQ 7 THEN BEGIN
DATA = STRING(DATA)
COUNT = 0
;
; Otherwise, if necessary, then convert the data to the native format of the
; host machine. Also, if NANVALUE is passed, then keep track of any IEEE NaN
; values.
;
END ELSE IF IDLTYPE[ICOL,ILUN] NE 1 THEN BEGIN
IF (N_ELEMENTS(NANVALUE) EQ 1) AND (IDLTYPE[ICOL,ILUN] GE 4) $
AND (IDLTYPE[ICOL,ILUN] LE 6) THEN $
W = WHERENAN(DATA,COUNT) ELSE COUNT = 0
IF NOT KEYWORD_SET(NOIEEE) THEN $
SWAP_ENDIAN_INPLACE,DATA,/SWAP_IF_LITTLE
END ELSE COUNT = 0
;
; If DIMS is simply the number 1, then convert DATA either to a scalar or to a
; simple vector, depending on how many rows were read in.
;
IF (N_ELEMENTS(DIMS) EQ 1) AND (DIMS[0] EQ 1) THEN BEGIN
IF N_ELEMENTS(DATA) EQ 1 THEN DATA = DATA[0] ELSE $
DATA = REFORM(DATA,ROW2-ROW1+1,/OVERWRITE)
ENDIF
;
; If the parameters TZERO and TSCAL are non-trivial, then adjust the array by
; these values.
;
IF NOT KEYWORD_SET(NOSCALE) AND NOT KEYWORD_SET(NOIEEE) THEN BEGIN
BZERO = TZERO[ICOL,ILUN]
BSCALE = TSCAL[ICOL,ILUN]
IF (BSCALE NE 0) AND (BSCALE NE 1) THEN DATA *= BSCALE
IF BZERO NE 0 THEN DATA += BZERO
ENDIF
;
; Store NANVALUE everywhere where the data corresponded to IEE NaN.
;
IF COUNT GT 0 THEN DATA[W] = NANVALUE
;
IF N_ELEMENTS(ERRMSG) NE 0 THEN ERRMSG = ''
RETURN
;
; I/O error handling point.
;
HANDLE_IO_ERROR:
MESSAGE = 'I/O error reading file'
;
; Error handling point.
;
HANDLE_ERROR:
IF N_ELEMENTS(ERRMSG) NE 0 THEN ERRMSG = MESSAGE ELSE MESSAGE, MESSAGE
RETURN
END
|