
function rfitsg,filnam,index=fnum,key_struct=hstruc,header=head,error=err, $
               user_struct=ustruc,date_obs=date,time_obs=time,scale=scale


;+
; NAME:
;        RFITSG
; PURPOSE:
;        Reads a standard FITS disk file into an array.
; CATEGORY:
;        Input/Output.
; CALLING SEQUENCE:
;        result = rfitsg(filename)
; INPUTS:
;        filename = string containing the file name.
; OPTIONAL (KEYWORD) INPUT PARAMETERS:
;        index = nonnegative integer. If this parameter is present,
;                a period and the index number are appended to the filename
;                (e.g., '.34').  This option makes handling of data in the
;                MCCD file naming convention easier.
;        user_struct = structure for optional FITS keyword parameters (input).
;                      With this keyword the user can supply a customized
;                      structure definition for the key_struct keyword.
;                      If user_struct is not supplied then the default
;                      structure definition in mkkey_struct() is used.
; OUTPUTS:
;        result = byte, integer, long, float, or double array, containing
;                 the FITS data array.  The dimensionality of result reflects
;                 the structure of the FITS data.
; OPTIONAL (KEYWORD) OUTPUT PARAMETERS:
;        key_struct = structure of optional FITS keyword parameters (output).
;                     The tag names of user_struct are matched with the FITS
;                     header keywords.  Matching header values are placed into
;                     the appropriate structure elements.
;        header = string vector, containing the full FITS header (each element
;                 of the vector contains one FITS keyword parameter).
;        error = I/O error code.  Nonzero if an I/O error occurred.
;        date_obs = date of observation (string).
;        time_obs = time of observation (string).
;                   date_obs and time_obs only for compatibility with older
;                   versions of rfits.  Use key_struct for new applications.
; COMMON BLOCKS:
;        None.
; SIDE EFFECTS:
;        None.
; RESTRICTIONS:
;        Only simple FITS files are read. FITS extensions (e.g., groups and
;        tables) are not supported.
;        The data array is not scaled according to BSCALE and BZERO.
;        Only header keywords written in fixed format (in columns 11 -30) can
;        be interpreted.  Complex type keywords cannot be interpreted.
; MODIFICATION HISTORY:
;        JPW, Nov, 1989.
;        JPW, Nov, 1991.  added floating point data type, header structure,
;                         and modified error handling if file not found.
;-

; open FITS file

if n_elements(fnum) ne 0 then file = filnam+'.'+string(format='(i0)',fnum) $
   else file = filnam
get_lun,unit
openr,unit,file,error=err
if  err ne 0 then begin
    printf,-2,!err_string
    goto,done
endif

; read the header

head = ''
repeat begin
   h = bytarr(80,36)
   readu,unit,h
   h = string(h)
   if n_elements(head) lt 36 then head=h else head=[head,h]
   flag = 0
   for i=0,35 do if strmid(h(i),0,8) eq 'END     ' then flag = i+1
endrep until flag gt 0
nh = n_elements(head)-36+i-1

; get the mandatory keywords

; search BITPIX keyword
i = -1
repeat i=i+1 until (strmid(head(i),0,8) eq 'BITPIX  ' or i eq nh)
if i eq nh then begin
   printf,-2,'error: keyword BITPIX not found '
   err = 10
   goto,done
endif
bitpix = fix(strmid(head(i),10,20))
; search NAXIS keyword
i = -1
repeat i=i+1 until (strmid(head(i),0,8) eq 'NAXIS   ' or i eq nh)
if i eq nh then begin
   printf,-2,'error: keyword NAXIS not found '
   err = 20
   goto,done
endif
naxis = fix(strmid(head(i),10,20))

; search NAXISi keywords
nxi = lonarr(naxis)
for j=1,naxis do begin
   i = -1
   repeat i=i+1 until $
     (strmid(head(i),0,8) eq 'NAXIS'+strtrim(string(j),2)+'  ' or i eq nh)
   if i eq nh then begin
      printf,-2,'error: keyword NAXIS',j,' not found '
      err = 30
      goto,done
   endif
   nxi(j-1) = long(strmid(head(i),10,20))
endfor

; search for optional keywords according to structure tag names.
; use supplied structure ustruc, or create default structure
usiz = size (ustruc)           ; check if ustruc is of type structure
if (usiz(usiz(0)+1) eq 8) then hstruc = ustruc else $
                      hstruc = mkkey_struct()
keynam = tag_names(hstruc)     ; tag names for use as keywords
keynam = strupcase(keynam)     ; convert to upper case
; replace _ by - for FITS header
asctab = bindgen(256)
asctab(byte('_')) = byte('-')
keynam = byte(keynam)
keynam = asctab(keynam)
keynam = string(keynam)

; loop through keywords
for i=0,n_tags(hstruc)-1 do begin
    hdsiz = size(hstruc.(i))
    if hdsiz(0) eq 0 then begin                            ; simple keyword
       key = strmid(keynam(i)+'        ',0,8)
       k = -1
       repeat k=k+1 until (strmid(head(k),0,8) eq key or k eq nh)
       if k lt nh then begin
          on_ioerror,elabel1
          case hdsiz(hdsiz(0)+1) of
             1 : begin                ; it's byte, used for logical keyword
                 aux = strtrim(strmid(head(k),10,20),2)
                 if aux eq 'T' then hstruc.(i) = 1b else hstruc.(i) = 0b
                 end
             7 : begin                ; it's a string
                 spos = 19 > strpos(head(k),"'",19)
                 hstruc.(i) = strmid(head(k),11,spos-11)
                 end
          else : hstruc.(i) = strmid(head(k),10,20)
          endcase
          elabel1: on_ioerror,null
       endif
    endif else begin                   ; indexed keyword, one for each axis
       for j=0,naxis-1 do begin
          key = strmid(keynam(i)+strtrim(string(j+1),2)+'        ',0,8)
          k = -1
          repeat k=k+1 until (strmid(head(k),0,8) eq key or k eq nh)
          if k lt nh then begin
             on_ioerror,elabel2
             case hdsiz(hdsiz(0)+1) of
                1 : begin                ; byte, used for logical keyword
                    aux = strtrim(strmid(head(k),10,20),2)
                    if aux eq 'T' then hstruc.(i)(j) = 1b $
                       else hstruc.(i)(j) = 0b
                    end
                7 : begin                ; it's a string
                    spos = 19 > strpos(head(k),"'",19)
                    hstruc.(i)(j) = strmid(head(k),11,spos-11)
                    end
             else : hstruc.(i)(j) = strmid(head(k),10,20)
             endcase
             elabel2: on_ioerror,null
          endif
       endfor
    endelse
endfor

; get DATE-OBS and TIME-OBS keywords
; date and time only for compatibility with older versions of rfits.
i = -1
repeat i=i+1 until (strmid(head(i),0,8) eq 'DATE-OBS' or i eq nh)
if i eq nh then date = ' 0/ 0/ 0' else begin
   date = strtrim(strmid(head(i),10,20),2)
   j = strlen(date)
   date = strmid(date,1,j-2)
endelse
i = -1
repeat i=i+1 until (strmid(head(i),0,8) eq 'TIME-OBS' or i eq nh)
if i eq nh then time = ' 0: 0: 0' else begin
   time = strtrim(strmid(head(i),10,20),2)
   j = strlen(time)
   time = strmid(time,1,j-2)
endelse


; create data array, and read it

case bitpix of
   8 : data = make_array(/byte,dimension=nxi,/nozero)
  16 : data = make_array(/int,dimension=nxi,/nozero)
  32 : data = make_array(/long,dimension=nxi,/nozero)
 -32 : data = make_array(/float,dimension=nxi,/nozero)
 -64 : data = make_array(/double,dimension=nxi,/nozero)
  else : begin
         printf,-2,'invalid BITPIX keyword '
         err = 40
         goto,done
  endelse
endcase
readu,unit,data
if bitpix eq 16 then byteorder, data
if bitpix eq -32 then begin
  byteorder, data, /ntohl
 endif

done: free_lun,unit

	if keyword_set(scale) then begin

if (where(tag_names(hstruc) eq 'BSCALE'))(0) ge 0 then data=data*hstruc.bscale
if (where(tag_names(hstruc) eq 'BZERO'))(0) ge 0 then data=data+hstruc.bzero

	endif

return,data
end