aboutsummaryrefslogtreecommitdiff
path: root/src/libcf/cf_rebin_background.c
blob: 23e15f3ae14aa364998c1a649517dec9c5188531 (plain) (blame)
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
/*****************************************************************************
 *              Johns Hopkins University
 *              Center For Astrophysical Sciences 
 *              FUSE
 *****************************************************************************
 *
 * Synopsis:   cf_rebin_background(infits, aperture, nout, wave_out,
 *		  binx, biny, bnx, bny, bimage, barray) 
 *
 * Arguments:   *fitsfile  infits     :  Input IDF file
 *              int       aperture    :  Aperture ID for the analysis
 *              long      nout        :  Length of wave_out array
 *              float     wave_out    :  Wavelength vector
 *              int       binx, biny  :  Binning factors of the background array
 *              int       bnx, bny    :  X and Y dimension of the background array
 *              float     bimage      :  2-D background image (original) 
 *              float     barray      :  (OUTPUT) Binned background image.
 *
 * Description:
 *
 *	The input background image is binned in X.
 *	We need an image binned in wavelength.   
 *	To get it, we use the WAVE_CAL file (shifted to account
 *	for the FPA position) to derive a wavelength array for the
 *	background image.  For each row in the background image (bimage),
 *	we build a second image (barray) scaled to the size of the output 
 *	wavelength bins.
 *
 *  History     02/21/03   v1.1   rdr   Started work
 *              04/01/03   v1.2   rdr   Made aeff arrays double precision in 
 *                                      the cf_read_fluxcal routine to be 
 *                                      compatible with data in calfiles
 *		05/07/03   v1.4   wvd	Don't divide by EXPTIME.
 *					Read WPC from file header.
 *					Use cf_verbose.
 *              06/02/03   v1.5   rdr   Correct bug in filling output arrays
 *              06/11/03   v1.7   wvd	Pass datatype to cf_read_col.
 *					Change calfusettag.h to calfuse.h
 *              08/22/03   v1.8   bjg	Move get_extraction_limits to external
 *					subroutine.  Free orphan arrays.
 *					Change coltype from char to int in
 *					cf_read_col.
 *              08/28/03   v1.9   wvd	Debug
 *              09/29/03   v1.10  wvd	Shift background model to match
 *					position of FPA.
 *              03/16/04   v1.11  wvd	Correct error in calculation of dw_ave
 *					and dweff.
 *              04/05/04   v1.12  wvd	Modify i/o.
 *              04/26/04   v1.13  wvd	Do not flux-calibrate 2-D background
 *					model.  Do not extract 1-D background
 *					spectrum.
 *              05/13/04   v1.14  wvd	Correct value of CF_PRGM_ID.
 *              07/21/04   v1.16  wvd	Delete unused variables.
 *
 *****************************************************************************/

#include <math.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "calfuse.h"


int cf_rebin_background(fitsfile *infits, int aperture, long nout,
	float *wave_out, int binx, int biny, int bnx, int bny,
	float *bimage, float **barray) {

    char CF_PRGM_ID[] = "cf_rebin_background";
    char CF_VER_NUM[] = "1.16";

    fitsfile  *wavefits ;
    int       status=0;
    int       dndx, dpix, nyout;
    long      npix, npix_out, nwave, ndx, ndx1, ndx2;
    long      i, j, k;
    float     dwb, dw_out, mf, ctot, dw_ave;
    float     dpix_fpa;
    float     *wave, *wavet, *outarr;
    char      wavefile[FLEN_VALUE], det[FLEN_VALUE] ;

    /* Initialize error checking */
    cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
    cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Started execution.");

    /* Read wavelength spacing of the output array */
    FITS_read_key(infits, TFLOAT, "WPC", &dw_out, NULL, &status) ;
    cf_verbose(3, "Bin size of the output wavelength array = %5.3f A",
	dw_out) ;
    FITS_read_key(infits, TSTRING, "DETECTOR", det, NULL, &status) ;
    cf_verbose(3,"Detector = %s, aperture = %d", det, aperture) ;

    /* Read wavelength-calibration file */
    FITS_read_key(infits, TSTRING, "WAVE_CAL", wavefile, NULL, &status) ;
    cf_verbose(3, "Wavelength calibration file = %s",wavefile) ;
    FITS_open_file(&wavefits, cf_cal_file(wavefile), READONLY, &status) ;
    cf_verbose(3, "HDU to read = %d",aperture+1) ;
    FITS_movabs_hdu(wavefits, aperture +1, NULL, &status) ;
    nwave=cf_read_col(wavefits,TFLOAT,"WAVELENGTH",(void **) &wave);
    cf_verbose(3, "Points read = %d, min & max: %4.2f, %4.2f",
	nwave, wave[0], wave[nwave-1]);

    /* Read pixel shifts due to FPA positions */
    if (aperture < 5) 
	FITS_read_key(infits, TFLOAT, "FPADXLIF", &dpix_fpa, NULL, &status);
    else 
	FITS_read_key(infits, TFLOAT, "FPADXSIC", &dpix_fpa, NULL, &status);
    dpix = cf_nint(dpix_fpa);

    /* To correct for the position of the FPA, each photon has been shifted
	in X by dpix pixels.  Rather than shifting the background to match,
	we modify the wavelength array that maps the background onto the
	output spectrum. */
    cf_verbose(2, "Shifting aperture %d background by %d X pixels "
	"to match the FPA shift.", aperture, cf_nint(dpix_fpa));

    /*  Generate a new wavelength array binned to match the background array */
    cf_verbose(3, "X and Y binning factors for background array = %d, %d",
	binx, biny) ;

        wavet = (float *) cf_calloc(bnx, sizeof(float));
	for (i = 0; i < bnx; i++) {
          ndx=i * binx + (binx/2) + dpix;
	  if (ndx > nwave-1) ndx = nwave-1 ;
	  if (ndx < 0) ndx = 0;
	  wavet[i] = wave[ndx];
	 }

      /* Error check: average wavelength spacing */
      dw_ave = fabs(wavet[bnx-1]-wavet[0])/(bnx-1);
      cf_verbose(3,"Average wavelength spacing of background array = %f", dw_ave) ;

      if ((aperture < 4 && strncmp(det,"1",1) == 0) ||
	  (aperture > 4 && strncmp(det,"2",1) == 0)) {
           cf_verbose(3, "Maximum tabulated wavelength = %.2f", wavet[bnx-1]);
           cf_verbose(3, "Maximum of wave_out = %.2f", wave_out[nout-1] );
      }
      else {
           cf_verbose(3, "Maximum tabulated wavelength = %.2f", wave_out[nout-1] );
           cf_verbose(3, "Maximum of wave_out = %.2f", wave_out[nout-1] );
      }

  /* Define some sizes and allocate space for the output arrays */
  nyout = bny * biny ;		/* Y dimension of output 2-D bkgd array */
  npix_out = nout * nyout ;	/* Size of output 2-D bkgd array */
  npix = bnx * bny ;		/* Size of input 2-D bkgd array */
  outarr = (float *) cf_calloc(npix_out, sizeof(float) ); /* 2-D output array */

    /* Error check: total counts in the background image */
    ctot=0.;
    for (i=0; i<npix; i++) ctot+=bimage[i] ;
    cf_verbose(3, "Number of counts in the input bkgd image = %f",ctot) ;

  /* For each wavelength in the output array, find the nearest point
     in the input background array.  Scale its value by the relative
     sizes of the background and output wavelength bins.

     Remember: wavelengths for the Lif channels and the SiC channels run
               in opposite directions.  For side one, wavelengths increase 
               with index for Lif but decrease for SiC. The opposite is true
	       for side two. */
  ndx=0 ;
  dndx = 1 ; 
  if ((aperture < 4 && strncmp(det,"2",1) == 0)  ||
      (aperture > 4 && strncmp(det,"1",1) == 0 ) ) {
    ndx = bnx - 1 ;
    dndx = -1 ;
  }

  cf_verbose(3,"Filling output: starting ndx=%d, increment =%d ", ndx, dndx) ;

  dwb = dw_ave;
  for (i=0; i<nout; i++) {
    /* Locate the element of the bkgd array corresponding to this wavelength */
        while (wavet[ndx] < wave_out[i] && ndx < bnx && ndx >= 0) ndx += dndx ;

	/* compute the relative
           wavelength coverage of the background and output arrays */
        if (ndx < bnx-2) dwb = fabs((double) (wavet[ndx+1]-wavet[ndx])) ;
	   mf = dw_out/dwb ;
	/* correct the scale factor for binning in y */
           mf /= biny ;
	/* populate the column of the array */
	for (j=0; j< nyout ; j++) {
          k = j/biny ;
          ndx1 = j*nout + i ;
	  if (ndx1 > npix_out-1) ndx1 = npix_out-1 ;
	  ndx2 = k*bnx + ndx ;
	    if (ndx2 > npix-1) ndx2=npix-1 ;
	  outarr[ndx1] = mf * bimage[ndx2] ; 
	}
  }


    /* Error checking: total counts in the background image */
    ctot=0.;
    for (i=0; i<npix_out; i++) ctot+=outarr[i] ;
    cf_verbose(3, "Number of counts in the output bkgd image = %f", ctot) ;


 /* Return output arrays */
    *barray = outarr ;
     
 /* Close wavelength calibration file */
      FITS_close_file(wavefits, &status) ;

   free(wave);
   free(wavet);

   cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Finished execution.");
   return status;
}