; Revision history:
; 10-Jan-2000, I. Barg - Modified structure names (and tag names) to match 
;             "/iraf/stsdas/lib/hstio.h".
; 13-Jan-2000, I. Barg - Set "data.nx = data.tot_nx" to support CALL_EXTERNAL
;             "C" routines that use "nx,ny" for looping.
; 08-Jan-2001, I. Barg - Modified cna_getNlinData to load up to 3 coeff
;		images and up to 6 error images, to accomodate
;		2nd-order correction scheme (as in STSDAS calnica Version 3.3)
; 10-Jan-2001, I. Barg - Changed all array indexes from () to [].


function getSingleNicmosGroup, fname, ev, x

  ; fname     i: file name of image to read
  ; ev        i: extension number (version)
  ; x    io: NicmosGroup to put image data into.

  ; Check to see if the file exists.
  test = findfile (fname, COUNT = fcount)
  if (fcount eq 0) then begin
    print, 'ERROR, file ',fname,' not found.'
    return, 11
  endif

  ; Open FITS file, read primary header.
  ua_fits_open, fname, infcb
  ua_fits_read,infcb,i_image,PriHdr,EXTEN_NO=0,/HEADER_ONLY,/NO_ABORT
  ; nsamp = sxpar (PriHdr, 'NSAMP')
  

  ; print,'in getSingleNicmosGroup group number = ',ev,' (nsamp = ',nsamp,')'
  ; if (ev lt 1 or ev gt nsamp) then begin
  ;   print, 'Error, bad group number found in getSingleNicmosGroup'
  ;   return, 11
  ; endif

  x.filename = fname
  x.globalhdr = PriHdr

  ; Read the input science image.
  ua_fits_read,infcb,tempdata,tempheader,EXTVER=ev,EXTNAME='SCI',/NO_ABORT
  x.sci.data.data = tempdata
  x.sci.hdr = tempheader

  ; Set tot_nx, tot_ny
  x.sci.data.tot_nx  = sxpar (x.sci.hdr, 'NAXIS1')
  x.sci.data.tot_ny  = sxpar (x.sci.hdr, 'NAXIS2')
  x.sci.data.nx = x.sci.data.tot_nx	;(see hstio.c: allocFloatData)
  x.sci.data.ny = x.sci.data.tot_ny

  ; Set IO descriptor info.
  x.sci.iodesc.filename = fname
  x.sci.iodesc.extname  = sxpar (x.sci.hdr, 'EXTNAME')
  x.sci.iodesc.extver   = sxpar (x.sci.hdr, 'EXTVER')
  x.sci.iodesc.naxis1   = sxpar (x.sci.hdr, 'NAXIS1')
  x.sci.iodesc.naxis2   = sxpar (x.sci.hdr, 'NAXIS2')
  x.sci.iodesc.type     = sxpar (x.sci.hdr, 'BITPIX')

  ua_fits_read,infcb,tempdata,tempheader,EXTVER=ev,EXTNAME='ERR',/NO_ABORT
  x.err.data.data = tempdata
  x.err.hdr = tempheader

  ; Set tot_nx, tot_ny
  x.err.data.tot_nx  = sxpar (x.err.hdr, 'NAXIS1')
  x.err.data.tot_ny  = sxpar (x.err.hdr, 'NAXIS2')
  if x.err.data.tot_nx eq 0 then begin
    x.err.data.tot_nx  = sxpar (x.err.hdr, 'NPIX1')
    x.err.data.tot_ny  = sxpar (x.err.hdr, 'NPIX2')
  endif
  x.err.data.nx = x.err.data.tot_nx	;(see hstio.c: allocFloatData)
  x.err.data.ny = x.err.data.tot_ny

  ; Set IO descriptor info.
  x.err.iodesc.filename = fname
  x.err.iodesc.extname  = sxpar (x.err.hdr, 'EXTNAME')
  x.err.iodesc.extver   = sxpar (x.err.hdr, 'EXTVER')
  x.err.iodesc.naxis1   = sxpar (x.err.hdr, 'NAXIS1')
  x.err.iodesc.naxis2   = sxpar (x.err.hdr, 'NAXIS2')
  x.err.iodesc.type     = sxpar (x.err.hdr, 'BITPIX')

  ua_fits_read,infcb,tempdata,tempheader,EXTVER=ev,EXTNAME='DQ',/NO_ABORT
  x.dq.data.data = tempdata
  x.dq.hdr = tempheader

  ; Set tot_nx, tot_ny
  x.dq.data.tot_nx  = sxpar (x.dq.hdr, 'NAXIS1')
  x.dq.data.tot_ny  = sxpar (x.dq.hdr, 'NAXIS2')
  if x.dq.data.tot_nx eq 0 then begin
    x.dq.data.tot_nx  = sxpar (x.dq.hdr, 'NPIX1')
    x.dq.data.tot_ny  = sxpar (x.dq.hdr, 'NPIX2')
  endif
  x.dq.data.nx = x.dq.data.tot_nx	;(see hstio.c: allocShortData)
  x.dq.data.ny = x.dq.data.tot_ny

  ; Set IO descriptor info.
  x.dq.iodesc.filename = fname
  x.dq.iodesc.extname  = sxpar (x.dq.hdr, 'EXTNAME')
  x.dq.iodesc.extver   = sxpar (x.dq.hdr, 'EXTVER')
  x.dq.iodesc.naxis1   = sxpar (x.dq.hdr, 'NAXIS1')
  x.dq.iodesc.naxis2   = sxpar (x.dq.hdr, 'NAXIS2')
  x.dq.iodesc.type     = sxpar (x.dq.hdr, 'BITPIX')

  ua_fits_read,infcb,tempdata,tempheader,EXTVER=ev,EXTNAME='SAMP',/NO_ABORT
  x.smpl.data.data = tempdata
  x.smpl.hdr = tempheader

  ; Set tot_nx, tot_ny
  x.smpl.data.tot_nx  = sxpar (x.smpl.hdr, 'NAXIS1')
  x.smpl.data.tot_ny  = sxpar (x.smpl.hdr, 'NAXIS2')
  if x.smpl.data.tot_nx eq 0 then begin
    x.smpl.data.tot_nx  = sxpar (x.smpl.hdr, 'NPIX1')
    x.smpl.data.tot_ny  = sxpar (x.smpl.hdr, 'NPIX2')
  endif
  x.smpl.data.nx = x.smpl.data.tot_nx	;(see hstio.c: allocShortData)
  x.smpl.data.ny = x.smpl.data.tot_ny

  ; Set IO descriptor info.
  x.smpl.iodesc.filename = fname
  x.smpl.iodesc.extname  = sxpar (x.smpl.hdr, 'EXTNAME')
  x.smpl.iodesc.extver   = sxpar (x.smpl.hdr, 'EXTVER')
  x.smpl.iodesc.naxis1   = sxpar (x.smpl.hdr, 'NAXIS1')
  x.smpl.iodesc.naxis2   = sxpar (x.smpl.hdr, 'NAXIS2')
  x.smpl.iodesc.type     = sxpar (x.smpl.hdr, 'BITPIX')

  ua_fits_read,infcb,tempdata,tempheader,EXTVER=ev,EXTNAME='TIME',/NO_ABORT
  x.intg.data.data = tempdata
  x.intg.hdr = tempheader

  ; Set tot_nx, tot_ny
  x.intg.data.tot_nx  = sxpar (x.intg.hdr, 'NAXIS1')
  x.intg.data.tot_ny  = sxpar (x.intg.hdr, 'NAXIS2')
  if x.intg.data.tot_nx eq 0 then begin
    x.intg.data.tot_nx  = sxpar (x.intg.hdr, 'NPIX1')
    x.intg.data.tot_ny  = sxpar (x.intg.hdr, 'NPIX2')
  endif
  x.intg.data.nx = x.intg.data.tot_nx	;(see hstio.c: allocFloatData)
  x.intg.data.ny = x.intg.data.tot_ny

  ; Set IO descriptor info.
  x.intg.iodesc.filename = fname
  x.intg.iodesc.extname  = sxpar (x.intg.hdr, 'EXTNAME')
  x.intg.iodesc.extver   = sxpar (x.intg.hdr, 'EXTVER')
  x.intg.iodesc.naxis1   = sxpar (x.intg.hdr, 'NAXIS1')
  x.intg.iodesc.naxis2   = sxpar (x.intg.hdr, 'NAXIS2')
  x.intg.iodesc.type     = sxpar (x.intg.hdr, 'BITPIX')

  ua_fits_close,infcb

  return, 0

end


; CNA_GETPEDIGREE -- Read the PEDIGREE and DESCRIP keywords
;                    from a reference file header.


function cna_getPedigree, refhdr, step

@calnica_common
common reffiles, miss_file, miss_keywd, mismatch, n_missing

  ; Arguments:
  ;  refhdr   i: reference file header structure
  ;  step    io: calibration step info structure

  status = 0

  ; Try to read the PEDIGREE keyword.
  step.ref.pedigree = sxpar (refhdr, 'PEDIGREE')
  if (!ERR eq -1) then begin
    print, 'ERROR: Keyword PEDIGREE not found in ',step.ref.name
    return, 12
  endif

  ; Is this a DUMMY reference file? 
  if (strpos ('DUMMY',step.ref.pedigree) ge 0) then begin
    step.corr = SKIP
    step.ref.dummy = 1
    print, 'PEDIGREE=DUMMY in ',step.ref.name,'; ',step.swname, $
           ' will be skipped.'
  endif else step.ref.dummy = 0

  ; Try to read the DESCRIP keyword.
  step.ref.descrip = sxpar (refhdr, 'DESCRIP')
  if (!ERR eq -1) then begin
    status = 0   ; not an error since it's not a required keyword 
  endif

  ; Successful return.
  return, status

end

 
; CNA_GETREFIMAGE -- Load the data from a reference image. 

function cna_getRefImage, step, extver, image

common reffiles, miss_file, miss_keywd, mismatch, n_missing

  ; Arguments:
  ;  step    io: calibration step info structure
  ;  extver   i: extension version number to load
  ;  image    o: reference image data
  ;  missing  o: missing file counter

  forward_function cna_ckImgSize
  forward_function cna_getPedigree

  ; Read the data 
  if (getSingleNicmosGroup (step.ref.name, extver, image) ne 0) then begin
    miss_file = 1
    return, 0    ; Don't abort yet 
  endif

  ; Check the size of the image 
  if (cna_ckImgSize (image) ne 0) then return, 11

  ; Read the reffile PEDIGREE and DESCRIP keywords 
  if (cna_getPedigree (image.globalhdr, step) ne 0) then return, 11

  ; Successful return 
  return, 0

end



; CNA_GETMASKIMAGE -- Load the bad pixel MASK reference file image and
;                     check to make sure it's the appropriate file for
;                     using with the science data being processed.

function cna_getMaskImage, nic, mask

common reffiles, miss_file, miss_keywd, mismatch, n_missing

  if (cna_getRefImage (nic.MASK, 1, mask) ne 0) then return, 191

  if (miss_file ne 0) then begin
    n_missing = n_missing + 1
    miss_file = 0
    return, 0
  endif

  ; Check the MASK file camera number.
  camera = 0
  camera = sxpar (mask.globalhdr, 'CAMERA')
  if (!ERR eq -1) then begin
    print, 'ERROR: Keyword CAMERA not found in ',nic.MASK.ref.name
    miss_keywd = miss_keywd + 1
  endif else if (camera ne nic.camera) then begin
    print, nic.MASK.ref.name, ' camera number ',camera, $
	   ' does not match science data.'
    mismatch = mismatch + 1
  endif

  return, 0    ; Successful return

end


; CNA_GETNOISIMAGE -- Load the readnoise reference file image and
;                     check to make sure it's the appropriate file for
;                     using with the science data being processed.

function cna_getNoisImage, nic, nois

common reffiles, miss_file, miss_keywd, mismatch, n_missing

  if (cna_getRefImage (nic.NOIS, 1, nois) ne 0) then return, 192

  if (miss_file ne 0) then begin
    n_missing = n_missing + 1
    miss_file = 0
  endif

  ; Check the NOISE file camera number.
  camera = 0
  camera = sxpar (nois.globalhdr, 'CAMERA')
  if (!ERR eq -1) then begin
    print, 'ERROR: Keyword CAMERA not found in ',nic.NOIS.ref.name
    miss_keywd = miss_keywd + 1
  endif else if (camera ne nic.camera) then begin
    print, nic.NOIS.ref.name,' camera number ',camera, $
	   ' does not match science data.'
    mismatch = mismatch + 1
  endif

  ; Check the NOISE file readout speed.
  keyval = ''
  keyval = sxpar (nois.globalhdr, 'READOUT')
  if (!ERR eq -1) then begin
    print, 'ERROR: Keyword READOUT not found in ',nic.NOIS.ref.name
    miss_keywd = miss_keywd + 1
  endif else if (strcompress(keyval,/REMOVE_ALL) ne $
		 strcompress(nic.readout,/REMOVE_ALL)) then begin
    print, nic.NOIS.ref.name,' readout ',keyval, $
	 ' does not match science data.'
    mismatch = mismatch + 1
  endif

  ; Check the NOISE file NREAD value.
  nval = 0
  nval = sxpar (nois.globalhdr, 'NREAD')
  if (!ERR eq -1) then begin
    print, 'WARNING: Keyword NREAD not found in ',nic.NOIS.ref.name
;    miss_keywd = miss_keywd + 1
  endif else if (nval ne nic.nread) then begin
    print, nic.NOIS.ref.name,' NREAD value ',nval, $
	   ' does not match science data.'
  endif

  return, 0

end


; CNA_GETFLATIMAGE -- Load the flat field reference file image and
;                     check to make sure it's the appropriate file for
;                     using with the science data being processed.

function cna_getFlatimage, nic, flat

common reffiles, miss_file, miss_keywd, mismatch, n_missing

  if (cna_getRefImage (nic.FLAT, 1, flat) ne 0) then return, 192

  if (miss_file ne 0) then begin
    n_missing = n_missing + 1
    miss_file = 0
  endif

  ; Check the FLAT file camera number.
  camera = 0
  camera = sxpar (flat.globalhdr, 'CAMERA')
  if (!ERR eq -1) then begin
    print, 'ERROR: Keyword CAMERA not found in ',nic.FLAT.ref.name
    miss_keywd = miss_keywd + 1
  endif else if (camera ne nic.camera) then begin
    print, nic.FLAT.ref.nam,' camera number ',camera, $
	   ' does not match science data.'
    mismatch = mismatch + 1
  endif

  ; Check the FLAT file filter name.
  keyval = ''
  keyval = sxpar (flat.globalhdr, 'FILTER')
  if (!ERR eq -1) then begin
    print, 'ERROR: Keyword FILTER not found in ',nic.FLAT.ref.name
    miss_keywd = miss_keywd + 1
  endif else if (strcompress(keyval,/REMOVE_ALL) ne $
		 strcompress(nic.filter,/REMOVE_ALL)) then begin
    print, nic.FLAT.ref.name,' filter ',keyval, $
	   ' does not match science data.'
    mismatch = mismatch + 1
  endif

  return, 0

end


; CNA_GETZOFFIMAGE -- Load the data for a MULTI-ACCUM zero-read image.
;                     This is simply the last image group in the input file
;                     being processed.  It is not necessary to check for
;                     PEDIGREE and DESCRIP keywords or to tally whether
;                     the file is missing as with normal reference images.


function cna_getZoffImage, nic, zoff

common reffiles, miss_file, miss_keywd, mismatch, n_missing

  ; Arguments:
  ;   nic     i: NICMOS info structure
  ;   zoff    o: zeroth-read image data


  forward_function cna_ckImgSize
  forward_function cna_getPedigree

  ; Read the data 
  if (getSingleNicmosGroup(nic.ZOFF.ref.name,nic.nsamp,zoff) ne 0) then begin
    return, 13
  endif

  ; Get the zeroth read exposure time.
  expt = sxpar (zoff.sci.hdr, 'SAMPTIME')
  if (!ERR eq -1) then begin
    print, 'ERROR: Keyword SAMPTIME not found in ',nic.ZOFF.ref.name
    miss_keywd = miss_keywd + 1
  endif else begin
    nic.exptime[nic.ngroups - 1] = expt
  endelse

  ; Successful return 
  return, 0

end

; CNA_GETNLINDATA -- Read linearity coefficients and their associated
;                    data quality flags and node values from the NLINFILE
;                    reference file.  The coefficient, DQ, and node arrays
;                    are returned in a single NlinData structure.
;
; Initially the correction used was a 1st-order polynomial, involving 2
; coefficient and 3 error images. This routine now accomodates a 2nd-order
; correction, using 3 coefficient and 6 error images. It is designed to be
; backwards-compatible with the 1st-order reference files by checking to
; see how many coeff arrays are present. Unused coeff and error arrays are
; zero-filled.


function cna_getNlinData, nic, nlin

@calnica_common
common reffiles, miss_file, miss_keywd, mismatch, n_missing

  ; Arguments:
  ;  nic       i: nic info structure
  ;  nlin      o: data structure containing linearity coeff's and DQ flags

  ; im = {IOdesc_st}

  ; Check to see if the nonlinearity file exists.
  test = findfile (nic.NLIN.ref.name, COUNT = fcount)
  if (fcount eq 0) then begin
    print, 'ERROR, nonlinearity reference file ',nic.NLIN.ref.name,' not found.'
    miss_file = miss_file + 1
    return, 0
  endif

  ; Open the nonlinearity reference file and read the primary header 
  ua_fits_open, nic.NLIN.ref.name, infcb
  ua_fits_read,infcb,i_image,nlinhdr,EXTEN_NO=0,/HEADER_ONLY

  ; Read the reffile PEDIGREE and DESCRIP keywords 
  if (cna_getPedigree (nlinhdr, nic.NLIN) ne 0) then return, 14
  nlin.globalhdr = nlinhdr

  ; Check for a dummy file.
  if (nic.NLIN.ref.dummy eq 1) then return, 0
  
  ; Determine the number of coefficient and error arrays present:
  ; if nextend <= 10, assume there are 2 coeffs and 3 errors;
  ; else assume there are 3 coeffs and 6 errors. 	
  if infcb.nextend le 10 then begin
      ncoeff = 2
      nerr = 3
  endif else begin
      ncoeff = 3
      nerr = 6
  endelse
  

  ; Get the coefficient images from the NLINFILE.
  for i = 0, ncoeff-1 do begin
    ua_fits_read,infcb,tempdata,tempheader,EXTVER=i+1,EXTNAME='COEF'
    nlin.coeff[i].data.data = tempdata
    nlin.coeff[i].hdr= tempheader
 
    ; Set tot_nx, tot_ny
    nlin.coeff[i].data.tot_nx  = sxpar (nlin.coeff[i].hdr, 'NAXIS1')
    nlin.coeff[i].data.tot_ny  = sxpar (nlin.coeff[i].hdr, 'NAXIS2')
 
    ; Set IO descriptor info.
    nlin.coeff[i].iodesc.filename = nic.NLIN.ref.name
    nlin.coeff[i].iodesc.extname  = sxpar (nlin.coeff[i].hdr, 'EXTNAME')
    nlin.coeff[i].iodesc.extver   = sxpar (nlin.coeff[i].hdr, 'EXTVER')
    nlin.coeff[i].iodesc.naxis1   = sxpar (nlin.coeff[i].hdr, 'NAXIS1')
    nlin.coeff[i].iodesc.naxis2   = sxpar (nlin.coeff[i].hdr, 'NAXIS2')
    nlin.coeff[i].iodesc.type     = sxpar (nlin.coeff[i].hdr, 'BITPIX')
  endfor

  ; Initialize undefined coeffs (up to 3) to zero 
  if (ncoeff eq 2) then begin
    for i = ncoeff, 2 do begin
      init_scihd, nlin.coeff[i]   
    endfor
  endif

  ; Get the error arrays from the NLINFILE.
  for i = 0, nerr-1 do begin
    ua_fits_read,infcb,tempdata,tempheader,EXTVER=i+1,EXTNAME='ERR'
    nlin.error[i].data.data = tempdata
    nlin.error[i].hdr= tempheader
 
    ; Set tot_nx, tot_ny
    nlin.error[i].data.tot_nx  = sxpar (nlin.error[i].hdr, 'NAXIS1')
    nlin.error[i].data.tot_ny  = sxpar (nlin.error[i].hdr, 'NAXIS2')
 
    ; Set IO descriptor info.
    nlin.error[i].iodesc.filename = nic.NLIN.ref.name
    nlin.error[i].iodesc.extname  = sxpar (nlin.error[i].hdr, 'EXTNAME')
    nlin.error[i].iodesc.extver   = sxpar (nlin.error[i].hdr, 'EXTVER')
    nlin.error[i].iodesc.naxis1   = sxpar (nlin.error[i].hdr, 'NAXIS1')
    nlin.error[i].iodesc.naxis2   = sxpar (nlin.error[i].hdr, 'NAXIS2')
    nlin.error[i].iodesc.type     = sxpar (nlin.error[i].hdr, 'BITPIX')
  endfor

  ; Initialize undefined errors (up to 6) to zero
  if (nerr eq 3) then begin
    for i = nerr, 5 do begin
      init_errhd, nlin.error[i]   
    endfor
  endif


  ; Get the DQ array from the NLINFILE.
  ua_fits_read,infcb,tempdata,tempheader,EXTVER=1,EXTNAME='DQ'
  nlin.dqual.data.data = tempdata
  nlin.dqual.hdr= tempheader

  ; Set tot_nx, tot_ny
  nlin.dqual.data.tot_nx  = sxpar (nlin.dqual.hdr, 'NAXIS1')
  nlin.dqual.data.tot_ny  = sxpar (nlin.dqual.hdr, 'NAXIS2')

  ; Set IO descriptor info.
  nlin.dqual.iodesc.filename = nic.NLIN.ref.name
  nlin.dqual.iodesc.extname  = sxpar (nlin.dqual.hdr, 'EXTNAME')
  nlin.dqual.iodesc.extver   = sxpar (nlin.dqual.hdr, 'EXTVER')
  nlin.dqual.iodesc.naxis1   = sxpar (nlin.dqual.hdr, 'NAXIS1')
  nlin.dqual.iodesc.naxis2   = sxpar (nlin.dqual.hdr, 'NAXIS2')
  nlin.dqual.iodesc.type     = sxpar (nlin.dqual.hdr, 'BITPIX')

  ; Get the node arrays from the NLINFILE.
  for i = 0, 1 do begin
    ua_fits_read,infcb,tempdata,tempheader,EXTVER=i+1,EXTNAME='NODE'

    nlin.nodes[i].data.data = tempdata
    nlin.nodes[i].hdr= tempheader
 
    ; Set tot_nx, tot_ny
    nlin.nodes[i].data.tot_nx  = sxpar (nlin.nodes[i].hdr, 'NAXIS1')
    nlin.nodes[i].data.tot_ny  = sxpar (nlin.nodes[i].hdr, 'NAXIS2')
 
    ; Set IO descriptor info.
    nlin.nodes[i].iodesc.filename = nic.NLIN.ref.name
    nlin.nodes[i].iodesc.extname  = sxpar (nlin.nodes[i].hdr, 'EXTNAME')
    nlin.nodes[i].iodesc.extver   = sxpar (nlin.nodes[i].hdr, 'EXTVER')
    nlin.nodes[i].iodesc.naxis1   = sxpar (nlin.nodes[i].hdr, 'NAXIS1')
    nlin.nodes[i].iodesc.naxis2   = sxpar (nlin.nodes[i].hdr, 'NAXIS2')
    nlin.nodes[i].iodesc.type     = sxpar (nlin.nodes[i].hdr, 'BITPIX')
  endfor

  ; Get the super zero-read SCI array from the NLINFILE.
  ua_fits_read,infcb,tempdata,tempheader,EXTVER=1,EXTNAME='ZSCI'
  nlin.zsci.data.data = tempdata
  nlin.zsci.hdr= tempheader

  ; Set tot_nx, tot_ny
  nlin.zsci.data.tot_nx  = sxpar (nlin.zsci.hdr, 'NAXIS1')
  nlin.zsci.data.tot_ny  = sxpar (nlin.zsci.hdr, 'NAXIS2')

  ; Set IO descriptor info.
  nlin.zsci.iodesc.filename = nic.NLIN.ref.name
  nlin.zsci.iodesc.extname  = sxpar (nlin.zsci.hdr, 'EXTNAME')
  nlin.zsci.iodesc.extver   = sxpar (nlin.zsci.hdr, 'EXTVER')
  nlin.zsci.iodesc.naxis1   = sxpar (nlin.zsci.hdr, 'NAXIS1')
  nlin.zsci.iodesc.naxis2   = sxpar (nlin.zsci.hdr, 'NAXIS2')
  nlin.zsci.iodesc.type     = sxpar (nlin.zsci.hdr, 'BITPIX')

  ; Get the super zero-read ERR array from the NLINFILE.
  ua_fits_read,infcb,tempdata,tempheader,EXTVER=1,EXTNAME='ZERR'
  nlin.zerr.data.data = tempdata
  nlin.zerr.hdr= tempheader

  ; Set tot_nx, tot_ny
  nlin.zerr.data.tot_nx  = sxpar (nlin.zerr.hdr, 'NAXIS1')
  nlin.zerr.data.tot_ny  = sxpar (nlin.zerr.hdr, 'NAXIS2')

  ; Set IO descriptor info.
  nlin.zerr.iodesc.filename = nic.NLIN.ref.name
  nlin.zerr.iodesc.extname  = sxpar (nlin.zerr.hdr, 'EXTNAME')
  nlin.zerr.iodesc.extver   = sxpar (nlin.zerr.hdr, 'EXTVER')
  nlin.zerr.iodesc.naxis1   = sxpar (nlin.zerr.hdr, 'NAXIS1')
  nlin.zerr.iodesc.naxis2   = sxpar (nlin.zerr.hdr, 'NAXIS2')
  nlin.zerr.iodesc.type     = sxpar (nlin.zerr.hdr, 'BITPIX')

  ua_fits_close, infcb

  ; Check the NLIN file camera number 
  camera = 0
  camera = sxpar (nlin.globalhdr, 'CAMERA')
  if (!ERR eq -1) then begin
    print, 'ERROR: Keyword CAMERA not found in ',nic.NLIN.ref.name
    miss_keywd = miss_keywd + 1
  endif else if (camera ne nic.camera) then begin
    print, nic.NLIN.ref.name, ' camera number ',camera, $
	   ' does not match science data.'
    mismatch = mismatch + 1
  endif

  return, 0

end


; CNA_GETDARKIMAGE -- Load a dark current image from the DARKFILE reference
;                     file.  A single image is loaded if the exposure time of
;                     the data being calibrated matches the exposure time of
;                     one of the dark images.

function cna_getDarkImage, nic, dark, ngroup

common dark,ndarks,etime
common reffiles, miss_file, miss_keywd, mismatch, n_missing

  ; Arguments:
  ;  nic        i: NICMOS info structure (contains exptime and refname)
  ;  dark       o: dark current image to be used in calibration
  ;  n_missing io: missing reference file counter

  ; When processing group 1, load the list of ref exposure times.
  if (nic.RefDataLoaded eq 0) then begin

    ; Read the first group of the dark reference file 
    if (cna_getRefImage (nic.DARK, 1, dark) ne 0) then return, 15
    if (miss_file eq 1) then begin
      n_missing = n_missing + 1
      miss_file = 0
      return, 0
    endif

    ; Check the DARK file camera number.
    camera = 0
    camera = sxpar (dark.globalhdr, 'CAMERA')
    if (!ERR eq -1) then begin
      print, 'ERROR: Keyword CAMERA not found in ',nic.DARK.ref.name
      miss_keywd = miss_keywd + 1
      status = 0
    endif else if (camera ne nic.camera) then begin
      print, nic.DARK.ref.name,' camera number ',camera, $
	     ' does not match science data.'
      mismatch = mismatch + 1
    endif

    ; Check the DARK file nread number.
    nread = 0
    nread = sxpar (dark.globalhdr, 'NREAD')
    if (!ERR eq -1) then begin
      print, 'WARNING: Keyword NREAD not found in ',nic.DARK.ref.name
      status = 0
    endif else if (nread ne nic.nread) then begin
      print, nic.DARK.ref.name,'  nread number ',nread, $
	     ' does not match science data'
    endif

    ; Check the DARK file SAMP_SEQ number.
    sampseq = 0
    sampseq = sxpar (dark.globalhdr, 'SAMP_SEQ')
    if (!ERR eq -1) then begin
      print, 'ERROR: Keyword SAMP_SEQ not found in ',nic.DARK.ref.name
      miss_keywd = miss_keywd + 1
      status = 0
      phot.mode = strcompress(phot.mode,/REMOVE_ALL)
    endif else if (strcompress(sampseq,/REMOVE_ALL) ne $
		   strcompress(nic.sampseq,/REMOVE_ALL)) then begin
      print, nic.DARK.ref.name,'  sampseq number ',sampseq, $
	     ' does not match science data'
      mismatch = mismatch + 1
    endif


    ; Find out how many dark images are in this file.
    ndarks = 0
    ndarks = sxpar (dark.globalhdr, 'NUMEXPOS')
    if (!ERR eq -1) then begin
      print, 'ERROR: Keyword NUMEXPOS not found in ',nic.DARK.ref.name
      return, 15
    endif

    ; Allocate memory for the list of exposure times.
    etime = dblarr (ndarks)

    ; Read the list of exposure times.
    for i = 0, ndarks-1 do begin
      if (i+1 le 9) then begin
	kword = string(format='("EXPOS_",i1)',i+1)
      endif else if (i+1 le 99) then begin
	kword = string(format='("EXPOS_",i2)',i+1)
      endif else begin
	kword = string(format='("EXPOS_",i3)',i+1)
      endelse
      etime[i] = 0.0
      etime[i] = sxpar (dark.globalhdr, kword)
      if (!ERR eq -1) then begin
        print, 'ERROR: Keyword ',kword,' not found in ',nic.DARK.ref.name
        return, 15
      endif
    endfor
  endif

  ; If the exposure time is zero, don't bother loading data.
  if (nic.exptime[ngroup-1] eq 0) then return, 0

  ; Find an exposure time that matches the science data.
  i = 0
  match = 0
  for i = 0, ndarks-1 do begin
    if (abs(etime[i] - nic.exptime[ngroup-1]) lt .01) then begin
      match = i+1
      nic.darkframe1 = i+1
    endif
  endfor

  ; Reinitialize for loading next dark image.
  dark = {nicdat}
  cna_initnic, dark

  ; If there's a dark image with a matching exposure time, load it. 
  if (match ne 0 ) then begin
    if (cna_getRefImage (nic.DARK, match, dark) ne 0) then return, 15
    if (miss_file eq 1) then return, 15
    print,' DARKCORR will use dark frame ',match,' for group ',ngroup
    print, '          with exptime=', etime[match-1]
  endif else begin
    ; Otherwise, error!
    print,' ERROR, No DARK was found with the correct exposure time for', $
	  ' group ',nic.group
    print, '          with exptime=', nic.exptime[ngroup-1]
    return, 15
  endelse

  ; Successful return.
  return, 0

end


; CNA_GETPHOTDATA -- Read the PHOTTAB reference table and load the
;                    photometry parameters appropriate for the observing mode
;                    of the image being calibrated. The parameters are stored
;                    in the NicInfo data structure and will be recorded as
;                    header keywords in the calibrated output file.


function cna_getPhotData, nic, phot

@calnica_common
common reffiles, miss_file, miss_keywd, mismatch, n_missing

NCOLS        = 8  ; number of columns in PHOTTAB 
N_FLOAT_COLS = 5  ; number of columns with float data type 

  ; Arguments:
  ;  nic     io: NICMOS info structure
  ;  phot    io: photometry parameters data structures

  ; Local variables 
  ; Bool found;                 ; PHOTMODE found in table? 
  ; Bool null[N_FLOAT_COLS];    ; null column entry flags 
  ; int nrows;                  ; number of rows in PHOTTAB 
  ; int col, row;               ; loop indexes 
  ; IRAFPointer tp;             ; PHOTTAB table pointer 
  ; IRAFPointer colptr[NCOLS];  ; PHOTTAB column pointers 
  ; char pmode[17];             ; PHOTTAB photmode entry 

  status = 0

  ; PHOTTAB column names 
  colname = [ 'PHOTMODE', $
              'PHOTFLAM', $
              'PHOTFNU', $
              'PHOTZPT', $
              'PHOTPLAM', $
              'PHOTBW', $
              'PEDIGREE', $
              'DESCRIP']

  ; PHOTMODE -- Observation Mode
  ; PHOTFLAM -- Inverse Sensitivity
  ; PHOTZPT  -- ST magnitude zero point
  ; PHOTFNU
  ; PHOTPLAM -- Pivot Wavelength
  ; PHOTBW   -- RMS Bandwidth of the Filter and Detector

  ; Initialize flag 
  found = 0   ;false

  ; Check to see if photometry file exists.
  test = findfile (nic.PHOT.ref.name, COUNT = fcount)
  if (fcount eq 0) then begin
    print, 'ERROR, photometry reference file ',nic.PHOT.ref.name,' not found.'
    n_missing = n_missing + 1
    return, 0
  endif

  ; Open the PHOTTAB reference table.
  fxbopen,tunit,nic.PHOT.ref.name,1,thdr

  ; Find out how many rows are in PHOTTAB 
  ;nrows = sxpar (thdr,'TBL_NROWS')
  nrows = sxpar (thdr,'NAXIS2')
  if (nrows le 0) then begin
    print, 'Invalid number of rows in ',nic.PHOT.ref.name
    fxbclose, tunit
    return, 16
  endif

  for i=0,7 do begin
    result = fxbcolnum (tunit, colname[i])
    if (result eq 0) then begin
      print, "Couldn't find column ",colname[i],' in ',nic.PHOT.ref.name
      status = 16
    endif
  endfor

  if (status ne 0) then begin
    fxbclose, tunit
    return, status
  endif

  ; Build the PHOTMODE string from camera and filter/grating.
  ;phot.mode = string(format='("NICMOS,",i1,",",a7,",DN")', $
  ;                   nic.camera,nic.filter)
  phot.mode = string(format='("NICMOS,",i1,",")',nic.camera)
  phot.mode = phot.mode+nic.filter+',DN'
  phot.mode = strupcase (phot.mode)
  phot.mode = strcompress(phot.mode,/REMOVE_ALL)

  found = 0
  for i = 0, nrows-1 do begin
    fxbread,tunit,pmode,colname[0],i+1
    if (strpos(pmode,phot.mode) ge 0 ) then begin
      ; Yes! Found the right row
      found = 1
      frow = i+1
    endif
  endfor

  if (found eq 1) then begin
    ; Store photometry parameters from this row.
    fxbread,tunit,temp, colname[1],frow
    phot.flam = temp
    fxbread,tunit,temp, colname[2],frow
    phot.fnu = temp
    fxbread,tunit,temp, colname[3],frow
    phot.zpt = temp
    fxbread,tunit,temp, colname[4],frow
    phot.plam = temp
    fxbread,tunit,temp, colname[5],frow
    phot.bw = temp
    fxbread,tunit,temp2,colname[6],frow
    nic.PHOT.ref.pedigree = temp2
    fxbread,tunit,temp2, colname[7],frow
    nic.PHOT.ref.descrip = temp2

    ; Is this a DUMMY reference file? 
    if (strpos ('DUMMY',nic.PHOT.ref.pedigree) ge 0) then begin
      nic.PHOT.corr = SKIP
      print, 'PEDIGREE=DUMMY in ',nic.PHOT.ref.name,'; ',nic.PHOT.swname, $
	     ' will be skipped'
      fxbclose, tunit
      return, 0
    endif

  endif else begin
    ; Report failure to find a PHOTMODE match.
    print, "Can't find PHOTMODE ',phot.mode,' in ',nic.PHOT.ref.name
    fxbclose, tunit
    return, 16
  endelse

  ; Close the PHOTTAB reference file 
  fxbclose, tunit

  ; Successful return.
  return, 0

end


; CNA_GETREFDATA -- Load all reference data into memory. Check for
;                   missing reference files and reference file data that do
;                   not match the observing mode of the science data being
;                   processed. Return with an error status if any ref files
;                   are missing or incompatibile.  All reference data are
;                   loaded when processing the first group of an input data
;                   file only a new dark image is loaded when processing
;                   subsequent groups of a MULTI-ACCUM file.

function cna_getRefData, nic, zoff, mask, nois, nlin, dark, flat, phot

@calnica_common
common reffiles, miss_file, miss_keywd, mismatch, n_missing

  ; Arguments:
  ;	nic	io: NICMOS info structure
  ;	zoff	 o: M-ACCUM zero-read image
  ;	mask	 o: bad pixel mask
  ;	nois	 o: read-noise image
  ;	nlin	 o: non-linearity image
  ;	dark	 o: dark current image
  ;	flat	 o: flat field image


  ; Local variables 
  ; Bool miss_file;			; missing ref file flag 
  ; Bool miss_keywd;			; missing keyword flag 
  ; Bool mismatch;			; ref data mismatch flat 
  ; int n_missing;			; missing ref file counter 
  ; int camera;				; camera number 
  ; char keyval[20];			; string keyword value 

  status = 0

  ; Initialize the flags 
  miss_file  = 0
  miss_keywd = 0
  mismatch   = 0
  n_missing  = 0

  ; Load the dark image 
  if (nic.DARK.corr eq PERFORM) then begin
    if (cna_getDarkImage (nic, dark, nic.group) ne 0) then return, 10

  endif

  ; If the static ref data have already been loaded, return.  
  if (nic.RefDataLoaded eq 1) then begin
    ; Error check.
    if (n_missing gt 0) then begin
      print, 'Calibration reference file missing'
      return, 2001
    endif else if (mismatch gt 0) then begin
      print, 'Incompatible reference data'
      status = 2001
    endif else if (miss_keywd gt 0) then begin
      status = 2001
    endif else return, 0
  endif

  ; Load the M-ACCUM zero-read image 
  if (nic.ZOFF.corr eq PERFORM) then begin
    if (cna_getZoffImage (nic, zoff) ne 0) then return, 10
  endif

  ; Load the bad pixel MASK image 
  if (nic.MASK.corr eq PERFORM) then begin
    if (cna_getMaskImage (nic, mask) ne 0) then return, 10
  endif

  ; Load the read-NOISE image, if necessary.
  if (nic.NOIS.corr eq PERFORM and nic.obsmode ne RAMP) then begin
    if (cna_getNoisImage (nic, nois) ne 0) then return, 10
  endif

  ; Load the non-linearity coefficients 
  if (nic.NLIN.corr eq PERFORM) then begin
    if (cna_getNlinData (nic, nlin) ne 0) then return, 10
  endif

  ; Load the flat field image 
  if (nic.FLAT.corr eq PERFORM) then begin
    if (cna_getFlatImage (nic, flat) ne 0) then return, 10

  endif

  ; Load the photometry parameters.
  if (nic.PHOT.corr eq PERFORM) then begin
    if (cna_getPhotData (nic, phot) ne 0) then return, 10
  endif

  ; Load the background model parameters 
  if (nic.BACK.corr eq PERFORM) then begin
      ; no routine yet.
  endif

  ; Error check 
  if (n_missing gt 0) then begin
    print, 'Calibration reference file missing.'
    return, 10
  endif else if (mismatch gt 0) then begin
    print, 'Incompatible reference data.'
    status = 1
  endif else if (miss_keywd gt 1) then begin
    status = 1
  endif else begin

    ; Set the flag indicating that the static ref data have been loaded.
    nic.RefDataLoaded = 1
    status = 0

  endelse

  ; Successful return.
  return, status

end

