aboutsummaryrefslogtreecommitdiff
path: root/src/libcf/cf_count_rate_y_distort.c
blob: a42a4ac1908e217769aad385be27d057eef7d9ae (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
/*****************************************************************************
 *              Johns Hopkins University
 *              Center For Astrophysical Sciences
 *              FUSE
 *****************************************************************************
 *
 * Synopsis:    cf_count_rate_y_distort(fitsfile *header, long nevents,
 *                                      float *time, float *yfarf,
 *                                      unsigned char *locflags, long nseconds,
 *                                      float *timeline, float *fec_rate)
 *
 * Description: Corrects the Y position of each event based on the
 *              instantaneous count rate.
 *
 * Arguments:   fitsfile  *header       Pointer to FITS file containing the
 *                                      header of the intermediate data file
 *              long      nevents       The number of events
 *              float     *time         An array of event times
 *              float     *yfarf        An array of event Y positions
 *              unsigned char *locflags Location flags for each event
 *              long      nseconds      The number of seconds in the timeline
 *              float     *timeline     The timeline in seconds
 *              float     *fec_rate     Front End Counter rate
 *
 * Calls:
 *
 * Return:      0  on success
 *
 * History:     08/06/02   1.1   peb    Begin work
 *              10/27/02   1.2   peb    Added a time-dependent correction
 *                                      which uses the Front End Counter
 *                                      (FEC) rates.
 *              11/11/02   1.3   peb    Removed non-time-dependent correction.
 *                                      (Code now expects timeline extension
 *                                      data.)
 *              11/11/02   1.4   peb    Fixed compile error - added buffer
 *                                      variable.
 *              11/12/02   1.5   peb    Added check to move only events in
 *                                      active region.
 *		03/11/03   1.6   wvd    Changed locflags to unsigned char
 *              05/20/03   1.7   rdr    Added call to cf_proc_check
 *		07/29/03   1.8   wvd    If cf_proc_check fails, return errflg.
 *		08/04/03   1.9   wvd    Convert fec_rate to type short.
 *		11/26/03   1.10  wvd    Convert fec_rate to type float.
 *		08/18/04   1.11  wvd    Interpolate stretch correction among
 *					tabulated Y values.
 *		10/06/05   1.12  wvd    For HIST data, set each element of
 *					fec_rate to weighted mean of array.
 *		04/07/07   1.13  wvd    Clean up compiler warnings.
 *
 ****************************************************************************/

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

int
cf_count_rate_y_distort(fitsfile *header, long nevents, float *time,
			float *yfarf, unsigned char *locflags, long nseconds,
			float *timeline, float *fec_rate)
{
    char CF_PRGM_ID[] = "cf_count_rate_y_distort";
    char CF_VER_NUM[] = "1.13";
    
    char  instmode[FLEN_VALUE], ystrfile[FLEN_VALUE];
    short xlen, ylen;
    int   errflg=0, hdutype, status=0, anynull=0;
    int   i, ii, i_max, rndx, yndx;
    long  j, k;
    float *ystretch, ystr_1d[NYMAX], flt=0.;
    fitsfile *ystrfits;

    cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
    cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Begin Processing");

    if ((errflg = cf_proc_check(header, CF_PRGM_ID))) return errflg;

    /*
     *  For HIST data, replace fec_rate with weighted mean value.
     */
    FITS_read_key(header, TSTRING, "INSTMODE", instmode, NULL, &status);
    if (!strncmp(instmode, "HIST", 4)) {
	float *mean_rate, ratio, numerator=0, denominator=0;
	mean_rate = (float *) cf_malloc(sizeof(float) * nseconds);
	for (i = 0; i < nseconds; i++) {
	    numerator += fec_rate[i] * fec_rate[i];
	    denominator += fec_rate[i];
	}
	ratio = numerator / denominator;
	for (i = 0; i < nseconds; i++) mean_rate[i] = ratio;
	fec_rate = mean_rate;
	cf_verbose(2, "Weighted mean count rate = %f", ratio);
    }

    /*
     *  Read the rate calibration file.
     */
    FITS_read_key(header, TSTRING, "RATE_CAL", ystrfile, NULL, &status);
    FITS_open_file(&ystrfits, cf_cal_file(ystrfile), READONLY, &status);
    FITS_movabs_hdu(ystrfits, 2, &hdutype, &status);
    FITS_read_key(ystrfits, TSHORT, "NAXIS1", &xlen, 0, &status);
    FITS_read_key(ystrfits, TSHORT, "NAXIS2", &ylen, 0, &status);
    ystretch = (float *) cf_malloc(sizeof(float)*xlen*ylen);
    FITS_read_img(ystrfits, TFLOAT, 1L, xlen*ylen, &flt, ystretch, &anynull,
		  &status);
    FITS_close_file(ystrfits, &status);

    i_max = (xlen-1) * 10;
    for(j=k=0; j<nevents; j++) {	/* Loop through all events. */
	/*
	 *  Move only events in active region.
	 */
	if (!(locflags[j] & LOCATION_SHLD)) {

	    /* If time has changed, compute a new ystretch array. */
	    while(timeline[k]-FRAME_TOLERANCE < time[j] && k < nseconds) {
		k++;

		/* This index reflects the count rate. */
	        rndx = (int)((log10(fec_rate[k])-1.)*10.);
	        if (rndx < 0)
		    rndx = 0;
	        else if (rndx >= ylen)
		    rndx = ylen-1;

		/* 
		 *  This index reflects Y position on the detector.
		 *  Shift information is provided for every 10 Y pixels.
		 *  We interpolate to the nearest Y pixel.  Otherwise,
		 *  counts pile up at the 10-pixel boundaries.
		 */
		for (i = 0; i < i_max; i++) {
		    ii = (i/10) * 10;
		    ystr_1d[i] = ((ii+10-i) * (ystretch+rndx*xlen)[i/10] +
				  (i - ii)  * (ystretch+rndx*xlen)[i/10+1]) / 10.;
		}
		for ( ; i < NYMAX; i++) 
		    ystr_1d[i] = (ystretch+rndx*xlen)[xlen-1];
	    }

	    /* Now apply the shift. */
	    yndx = (int) yfarf[j];
	    if (yndx < 0)
		yndx = 0;
	    else if (yndx >= NYMAX)
		yndx = NYMAX-1;
	    yfarf[j] -= ystr_1d[yndx];
	}
    }
    free(ystretch);
    if (!strncmp(instmode, "HIST", 4)) free(fec_rate);

    cf_proc_update(header, CF_PRGM_ID, "COMPLETE");
    cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Done processing");
    return 0;
}