
FUNCTION cds_getwindata, filename, wvl, second_order=second_order

;+
; NAME
;
;    CDS_GETWINDATA
;
; PROJECT
;
;    SOHO/CDS
;
; EXPLANATION
;
;    This routine takes a CDS file and extracts a wavelength window
;    into 'windata' structure in the same format as that used by the
;    Hinode/EIS software. 
;
;    The uncalibrated CDS file is read and calibrated by standard CDS
;    routines. Intensity errors are determined by first calibrating
;    into photon units from which the photon statistics can be
;    determined. Wavelength corrections are automatically applied with
;    the routine nis_rotate so that the WAVE_CORR tag in the windata structure
;    is not needed (unlike for EIS).
;
;    This routine only has limited functionality at present. In
;    particular the following things need to be implemented/checked:
;
;    1. Sit-and-stare data.
;    2. SOHO roll angles of 180 degrees have not been checked.
;    3. Slot data have not been checked.
;
; INPUTS
;
;    FILENAME  The name of a CDS FITS file.
;
;    WVL    Used to select the wavelength window to be extracted. For
;           full CCD spectra the entire wavelength band will be
;           extracted. (Use the routine eis_trim_windata to reduce the
;           size of the windata structure, if necessary.)
;
; KEYWORDS
;
;    SECOND_ORDER  Applies the 2nd order calibration (through the
;                  nis_calib routine) to the wavelength window.
;
; OUTPUTS
;
;    An IDL structure with the following tags:
;
;    FILENAME        STRING    's765r00.fits'
;    LINE_ID         STRING    'BB_NIS_1'
;    INT             FLOAT     Array[1024, 10, 160]
;    ERR             FLOAT     Array[1024, 10, 160]
;    WVL             FLOAT     Array[1024]
;    TIME            DOUBLE    Array[10]
;    TIME_CCSDS      STRING    Array[10]
;    DATA_QUALITY    BYTE      Array[10]
;    EXPOSURE_TIME   FLOAT     Array[10]
;    SOLAR_X         DOUBLE    Array[10]
;    SOLAR_Y         DOUBLE    Array[160]
;    XCEN            DOUBLE           613.46175
;    YCEN            DOUBLE           7.3008387
;    NL              INT           1024
;    NX              LONG                10
;    NY              LONG               160
;    SCALE           DOUBLE    Array[2]
;    UNITS           STRING    ''
;    MISSING         FLOAT          -100.000
;    IWIN            LONG                 0
;    HDR             STRUCT    -> <Anonymous> Array[1]                   
;    TIME_STAMP      STRING    'Tue Apr 30 13:33:15 2013'
;    WAVE_CORR_SET   INT              1
;    WAVE_CORR       DOUBLE    Array[10, 160]
;    WAVE_CORR_TILT  DOUBLE    Array[160]
;    WAVE_CORR_T     DOUBLE    Array[10]
;
;    If an error occurs then a value of -1 is returned instead.
;
; CALLS
;
;    READCDSFITS, CDS_NEW_SPIKE, VDS_CALIB, NIS_ROTATE, PIX2WAVE,
;    GT_MIRRPOS, NIS_CALIB, GT_NUMWIN
;
; HISTORY
;
;    Beta 1, 5-Apr-2013, Peter Young
;    Beta 2, 30-Apr-2013, Peter Young
;       tidied up code and expanded header.
;-


IF datatype(filename) NE 'STR' THEN BEGIN
  print,'%CDS_GETWINDATA:  The CDS filename must be specified as the first input. Returning...'
  return,-1
ENDIF 

a=readcdsfits(filename)

cds_new_spike,a,/nofill
vds_calib,a

nis_rotate,a

;
; Find wavelength window
;
nwin=GT_numwin(a)
k=where(wvl GE a.detdesc.wavemin AND wvl LE a.detdesc.wavemax,nk)
IF nk EQ 0 THEN BEGIN
  print,'%CDS_GETWINDATA: requested wavelength was not found in this data-set. Returning...'
  return,-1
ENDIF
iwin=k[0]


;
; set up the size of the wavelength, error and intensity arrays
;
exptime=GT_exptime(a)
dim=gt_dimension(a)
winsize=GT_winsize(a)
nl=winsize[iwin]
biny=a.detdesc.biny
dat=GT_windata(a,iwin)
siz=size(dat)
nx=siz[2]
ny=siz[3]
IF dim.ssolar_x EQ 1 THEN nx=siz[4]
pix=fltarr(nl,nx,ny)
err=pix
int=pix

solar_x=findgen(dim.ssolar_x[0])*dim.solar_x_spacing[0]+dim.solar_x_origin[0]
solar_y=findgen(dim.ssolar_y[0])*dim.solar_y_spacing[0]+dim.solar_y_origin[0]

;
; The following checks if data are from the post-loss period, but at
; present this information does not go into the windata structure.
;
postloss=0
tai_0=anytim('30-jun-1998',/tai)
tai=anytim(a.header.date_obs,/tai)
IF tai GT tai_0 THEN BEGIN
  postloss=1
ENDIF



time=a.del_timedata
date_obs_tai=anytim2tai(a.header.date_obs)
time_tai=date_obs_tai+time
time_ccsds=anytim2utc(/ccsds,time_tai)

;
; I need to add in some extra tags to the header as these are used by
; the EIS routines.
;
header=a.header
headnew=add_tag(header,0,'yws')
headnew=add_tag(headnew,0,'rast_id')
headnew=add_tag(headnew,a.header.slit_num,'slit_ind')
headnew=add_tag(headnew,ny,'yw')
headnew=add_tag(headnew,a.header.expcount,'nexp')
headnew=add_tag(headnew,dim.ssolar_x,'nraster')
header=temporary(headnew)

pix=a.detdesc[iwin].detx+findgen(nl)
dety=a.detdesc[iwin].dety+findgen(ny)
band=(max(dety) LT 512) + 1
band_str='NIS'+trim(band)
wvl=pix2wave(band_str,pix,/nolimit)

;
; The format for data was copied exactly from the EIS windata on
; 3-Apr-2013. 
; 
windata={filename: a.header.filename, $
      line_id: GT_wlabel(a,iwin), $
      int: int, $
      err: err, $
      wvl: wvl, $
      time: time, $
      time_ccsds: time_ccsds, $
      data_quality: bytarr(nx), $
      exposure_time: fltarr(nx)+exptime, $
      solar_x: solar_x ,$
      solar_y: solar_y ,$
      xcen: a.header.xcen, $
      ycen: a.header.ycen, $
      nl: nl, $
      nx: nx, $
      ny: ny, $
      scale: [a.detdesc[iwin].spacing[1:2]], $
      units: '', $
      missing: a.detdesc[0].missing, $
      iwin: iwin, $
      hdr: header, $
      time_stamp: '', $
      wave_corr_set: 1, $
      wave_corr: dblarr(nx,ny), $
      wave_corr_tilt: dblarr(ny), $
      wave_corr_t: dblarr(nx) }
      

;************
;   If the raster consists of repeated exposures at the same slit position,
;   then the fourth dimension is classed as the X direction instead of the
;   second dimension.
;
IF dim.ssolar_x EQ 1 THEN BEGIN
  print,'%CDS_GETWINDATA: I have not implemented sit-and-stare yet. Returning...'
  return,-1
;   dat_sub=reform(dat(*,0,*,*))
;    dat=rearrange(dat_sub,[1,3,2])
ENDIF
;************

miss=a.detdesc[iwin].missing
k=where(dat NE miss)
;
; ERR contains the fractional error at this point - it will be multiplied
; by the intensity later
;
windata.err=miss
windata.err[k]=sqrt(2.*abs(dat[k]*exptime)+1.)/dat[k]/exptime



;
; The following keywords put the spectra into the same units as EIS
;
nis_calib,a,/erg,/ster,/ang, second_order=second_order

mirrpos=GT_mirrpos(a)

pix3=fltarr(nl,nx,ny)   ; 3D array for storing pixel positions

ex=fltarr(nx)+1.  ;
ey=fltarr(ny)+1.  ; 1D identity arrays in each dimension
el=fltarr(nl)+1.  ;



dat=GT_windata(a,iwin)
windata.int=dat
windata.err=windata.err*dat
k=where(windata.int EQ windata.missing,nk)
IF nk NE 0 THEN windata.err[k]=windata.missing


windata.time_stamp=systime()

return,windata


END
