Skip to content

Commit 63cbd7d

Browse files
committed
Updated routines to accommdate support subarray processing using the new bias level processing which previously only applied to full frame data.
1 parent d741b49 commit 63cbd7d

File tree

6 files changed

+740
-818
lines changed

6 files changed

+740
-818
lines changed

pkg/acs/calacs/acsccd/blev_funcs_postsm4.c

Lines changed: 176 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22
#include <stdlib.h>
33
#include <string.h>
44
#include <stdio.h>
5+
#include <stdarg.h> /* Supports the variable number of parameters for bias_shift_corr() */
6+
#include <ctype.h>
57

8+
#include "hstcal_memory.h"
69
#include "hstcal.h"
710
#include "hstio.h"
811

@@ -36,152 +39,218 @@ static int make_amp_array(const int arr_rows, const int arr_cols, SingleGroup *
3639
static int unmake_amp_array(const int arr_rows, const int arr_cols, SingleGroup * im,
3740
int amp, double * array);
3841

42+
/* Remove the signal dependent bias shift from post-SM4 full frame WFC data
43+
* (based on ISR http://www.stsci.edu/hst/acs/documents/isrs/isr1202.pdf),
44+
* as well as from supported subarray data (~post-mid-2016) as identified by
45+
* specific aperture names
46+
* (based on ISR http://www.stsci.edu/hst/acs/documents/isrs/isr1703.pdf).
47+
*
48+
* chip2 consists of amps C & D, chip1 consists of amps A & B.
49+
*
50+
* Because full frame data uses both chips, but supported subarray data
51+
* is only from a single amp (therefore, a portion of a single chip), this
52+
* routine has a variable number of input SingleGroups.
53+
*
54+
* 16-May-2018 M.D. De La Pena: Generalized bias_shift_corr() to handle subarray data.
55+
*/
56+
int bias_shift_corr(ACSInfo *acs, int nGroups, ...) {
57+
58+
/* Code to handle variable number of input parameters. The number of SingleGroup is 2 when
59+
processing a full frame (2 chips - all 4 amps) and only 1 when processing a supported subarray
60+
(1 chip from a single amp).
61+
*/
62+
SingleGroup *sg[nGroups];
63+
va_list arguments;
64+
65+
/* Initializing arguments to store all the values being passed to this routine via "..." */
66+
va_start (arguments, nGroups);
67+
{
68+
/* sg[0] is chip2 and sg[1] is chip 1 for a full frame image */
69+
{unsigned int i;
70+
for (i = 0; i < nGroups; i++) {
71+
sg[i]= va_arg (arguments, SingleGroup *);
72+
}}
73+
}
74+
va_end (arguments);
3975

40-
/* remove signal dependent bias shift from post-SM4 full frame WFC data.
41-
* based on ISR http://www.stsci.edu/hst/acs/documents/isrs/isr1202.pdf
42-
* chip2 is amps C & D, chip1 is amps A & B. */
43-
int bias_shift_corr(ACSInfo *acs, SingleGroup *chip2, SingleGroup *chip1) {
4476
extern int status;
45-
46-
int i, j, k; /* iteration variables */
47-
48-
/* array for amp data and amp data + gap pixels */
49-
double * ampdata, * ampdata_gap;
50-
77+
5178
const double serial_freq = 1000./22.; /* serial pixel frequency */
5279
const double parallel_shift = 3.212; /* parallel shift time */
5380

5481
/* number of virtual pixels at end of each row */
5582
const int ngap_pix = (int) (serial_freq * parallel_shift + 0.5);
5683

57-
const int arr_rows = chip2->sci.data.ny;
58-
const int arr_cols = chip2->sci.data.nx/2;
84+
/* There is always at least one SingleGroup - use sg[0] to get the image size of a single amp.
85+
* If this is a full frame image, then "nx" represents all the columns across both amps plus
86+
* the physical overscan and must be divided by 2. If this is a subarray, then "nx" represents
87+
* just the columns for a single amp plus physical overscan.
88+
*/
89+
const int arr_rows = sg[0]->sci.data.ny;
90+
const int arr_cols = (acs->subarray == NO) ? sg[0]->sci.data.nx/2 : sg[0]->sci.data.nx;
5991

6092
/* total number of real and gap pixels per quadrant */
6193
const int nquad_pix = (arr_cols + ngap_pix) * arr_rows;
6294

63-
/* array of true DC bias levels */
64-
double * dc_bias_levels;
65-
6695
/* arrays below are in order of amp A, B, C, D */
6796

68-
/* time constant of AC high pass filter in external pre-amp. */
97+
/* time constant of AC high pass filter in external pre-amp in microseconds */
6998
const double time_const[NAMPS] = {37.290251, 36.180001, 37.867770, 42.461249};
7099

71100
/* ratio of DC offset shift and pixel signal */
72101
const double dc_ratio[NAMPS] = {0.3, 0.3, 0.3, 0.3};
73102

74103
/* DSI sensitivity */
75104
const double dsi_sens[NAMPS] = {2.9188919e-3, 10.805754e-3, 12.432145e-3, 3.8596253e-3};
76-
77-
/* factor combining time constant and clocking frequency */
78-
double factor;
79-
80-
/* summation variables */
81-
double sum;
82-
int num;
83-
double magic_square_mean;
84-
85-
/* allocate space for data arrays */
86-
ampdata = malloc(arr_rows * arr_cols * sizeof(double));
87-
ampdata_gap = malloc(nquad_pix * sizeof(double));
88-
89-
/* allocate space for true DC bias levels array */
105+
106+
PtrRegister ptrReg;
107+
initPtrRegister(&ptrReg);
108+
109+
/* array of true DC bias levels */
110+
double * dc_bias_levels = NULL;
90111
dc_bias_levels = malloc((nquad_pix + 1) * sizeof(double));
91-
92-
for (i = 0; i < NAMPS; i++) {
93-
/* put a single amp's data into ampdata */
94-
if (i < 2) {
95-
make_amp_array(arr_rows, arr_cols, chip1, i, ampdata);
96-
} else {
97-
make_amp_array(arr_rows, arr_cols, chip2, i, ampdata);
98-
}
99-
100-
/* calculate "magic square mean" */
101-
sum = 0.0;
102-
num = 0;
112+
addPtr(&ptrReg, dc_bias_levels, &free);
103113

104-
for (j = 2057; j <= 2066; j++) {
105-
for (k = 13; k <= 22; k++) {
106-
sum += ampdata[arr_cols*j + k];
107-
num++;
114+
/* array for amp data and amp data + gap pixels */
115+
double *ampdata = malloc(arr_rows * arr_cols * sizeof(double));
116+
addPtr(&ptrReg, ampdata, &free);
117+
double *ampdata_gap = malloc(nquad_pix * sizeof(double));
118+
addPtr(&ptrReg, ampdata_gap, &free);
119+
120+
/* For full frame data, there are four amps in use. For supported subarray
121+
* data, there is only one amp in use. The actual amp in use must be determined.
122+
*/
123+
int numAmpsInUse = (acs->subarray == YES) ? 1 : NAMPS;
124+
125+
/* Loop over all the amps for full frame data (total of 4 amps, 0 to 3) or just use
126+
* the single amp value corresponding to the supported subarray (1 amp, value defined in acs.h).
127+
*/
128+
int ampInUse = 0;
129+
{unsigned int i;
130+
for (i = 0; i < numAmpsInUse; i++) {
131+
ampInUse = i;
132+
if ((i == 0) && (acs->subarray == YES)) {
133+
if (strcmp (acs->ccdamp, "A") == 0)
134+
ampInUse = AMP_A;
135+
else if (strcmp (acs->ccdamp, "B") == 0)
136+
ampInUse = AMP_B;
137+
else if (strcmp (acs->ccdamp, "C") == 0)
138+
ampInUse = AMP_C;
139+
else if (strcmp (acs->ccdamp, "D") == 0)
140+
ampInUse = AMP_D;
141+
}
142+
143+
/* put a single amp's data into ampdata */
144+
if (acs->subarray == YES) {
145+
make_amp_array(arr_rows, arr_cols, sg[0], ampInUse, ampdata);
146+
} else {
147+
if (i < 2) {
148+
make_amp_array(arr_rows, arr_cols, sg[1], ampInUse, ampdata);
149+
} else {
150+
make_amp_array(arr_rows, arr_cols, sg[0], ampInUse, ampdata);
151+
}
108152
}
109-
}
153+
154+
/* calculate "magic square mean" - this works for any single amp */
155+
double sum = 0.0;
156+
int num = 0;
157+
double magic_square_mean = 0.0;
110158

111-
magic_square_mean = sum / (double) num;
159+
{unsigned int j, k;
160+
for (j = 2057; j <= 2066; j++) {
161+
for (k = 13; k <= 22; k++) {
162+
sum += ampdata[arr_cols*j + k];
163+
num++;
164+
}
165+
}}
112166

113-
/* make amp + gap array */
114-
for (j = 0; j < arr_rows; j++) {
115-
for (k = 0; k < (arr_cols + ngap_pix); k++) {
116-
if (k < arr_cols) {
117-
ampdata_gap[(arr_cols + ngap_pix)*j + k] = ampdata[arr_cols*j + k];
118-
} else {
119-
ampdata_gap[(arr_cols + ngap_pix)*j + k] = magic_square_mean;
167+
magic_square_mean = sum / (double) num;
168+
169+
/* make amp + gap array */
170+
{unsigned int j, k;
171+
for (j = 0; j < arr_rows; j++) {
172+
for (k = 0; k < (arr_cols + ngap_pix); k++) {
173+
if (k < arr_cols) {
174+
ampdata_gap[(arr_cols + ngap_pix)*j + k] = ampdata[arr_cols*j + k];
175+
} else {
176+
ampdata_gap[(arr_cols + ngap_pix)*j + k] = magic_square_mean;
177+
}
120178
}
121-
}
122-
}
179+
}}
123180

124-
/* calculate true DC bias levels */
125-
factor = 1.0 - exp(-1.0 / (time_const[i] * serial_freq));
181+
/* factor combining time constant and clocking frequency */
182+
double factor = 1.0 - exp(-1.0 / (time_const[ampInUse] * serial_freq));
126183

127-
dc_bias_levels[0] = magic_square_mean * dc_ratio[i];
184+
/* calculate true DC bias levels */
185+
dc_bias_levels[0] = magic_square_mean * dc_ratio[ampInUse];
128186

129-
for (j = 1; j < nquad_pix + 1; j++) {
130-
dc_bias_levels[j] = ampdata_gap[j-1] * factor * dc_ratio[i] +
187+
{unsigned int j;
188+
for (j = 1; j < nquad_pix + 1; j++) {
189+
dc_bias_levels[j] = ampdata_gap[j-1] * factor * dc_ratio[ampInUse] +
131190
(1.0 - factor) * dc_bias_levels[j-1];
132-
}
191+
}}
133192

134-
/* calculate correction to data */
135-
for (j = 0; j < nquad_pix; j++) {
136-
ampdata_gap[j] = (ampdata_gap[j] - dsi_sens[i] * dc_bias_levels[j+1]) -
193+
/* calculate correction to data */
194+
{unsigned int j;
195+
for (j = 0; j < nquad_pix; j++) {
196+
ampdata_gap[j] = (ampdata_gap[j] - dsi_sens[ampInUse] * dc_bias_levels[j+1]) -
137197
(10./22.) * (dc_bias_levels[j+1] - dc_bias_levels[j]);
138-
}
198+
}}
139199

140-
/* copy corrected data back to ampdata */
141-
for (j = 0; j < arr_rows; j++) {
142-
for (k = 0; k < arr_cols; k++) {
143-
ampdata[arr_cols*j + k] = ampdata_gap[(arr_cols + ngap_pix)*j + k];
144-
}
145-
}
200+
/* copy corrected data back to ampdata */
201+
{unsigned int j, k;
202+
for (j = 0; j < arr_rows; j++) {
203+
for (k = 0; k < arr_cols; k++) {
204+
ampdata[arr_cols*j + k] = ampdata_gap[(arr_cols + ngap_pix)*j + k];
205+
}
206+
}}
146207

147-
/* re-calculate "magic square mean" */
148-
sum = 0.0;
149-
num = 0;
208+
/* re-calculate "magic square mean" */
209+
sum = 0.0;
210+
num = 0;
211+
magic_square_mean = 0.0;
150212

151-
for (j = 2057; j <= 2066; j++) {
152-
for (k = 13; k <= 22; k++) {
153-
sum += ampdata[arr_cols*j + k];
154-
num++;
155-
}
156-
}
213+
{unsigned int j, k;
214+
for (j = 2057; j <= 2066; j++) {
215+
for (k = 13; k <= 22; k++) {
216+
sum += ampdata[arr_cols*j + k];
217+
num++;
218+
}
219+
}}
157220

158-
magic_square_mean = sum / (double) num;
159-
/* Keep track of the total bias correction applied to each AMP region */
160-
acs->blev[i] += magic_square_mean;
161-
/* Report to the user the contribution to the bias level correction
162-
made by this processing step.
163-
*/
164-
sprintf(MsgText, "Bias shift correcting for bias level in Amp %c of %0.4f electrons.",AMPSORDER[i], magic_square_mean);
165-
trlmessage(MsgText);
221+
magic_square_mean = sum / (double) num;
222+
223+
/* Keep track of the total bias correction applied to each AMP region */
224+
acs->blev[ampInUse] += magic_square_mean;
225+
226+
/* Report to the user the contribution to the bias level correction
227+
made by this processing step.
228+
*/
229+
sprintf(MsgText, "Bias shift correcting for bias level in Amp %c of %0.4f electrons.",AMPSORDER[ampInUse], magic_square_mean);
230+
trlmessage(MsgText);
166231

167-
/* subtract "magic square mean" from data*/
168-
for (j = 0; j < arr_rows; j++) {
169-
for (k = 0; k < arr_cols; k++) {
170-
ampdata[arr_cols*j + k] -= magic_square_mean;
171-
}
172-
}
232+
/* subtract "magic square mean" from data*/
233+
{unsigned int j, k;
234+
for (j = 0; j < arr_rows; j++) {
235+
for (k = 0; k < arr_cols; k++) {
236+
ampdata[arr_cols*j + k] -= magic_square_mean;
237+
}
238+
}}
173239

174-
/* copy modified data back to SingleGroup structs */
175-
if (i < 2) {
176-
unmake_amp_array(arr_rows, arr_cols, chip1, i, ampdata);
177-
} else {
178-
unmake_amp_array(arr_rows, arr_cols, chip2, i, ampdata);
179-
}
180-
}
240+
/* copy modified data back to SingleGroup structs */
241+
242+
if (acs->subarray == YES) {
243+
unmake_amp_array(arr_rows, arr_cols, sg[0], ampInUse, ampdata);
244+
} else {
245+
if (i < 2) {
246+
unmake_amp_array(arr_rows, arr_cols, sg[1], ampInUse, ampdata);
247+
} else {
248+
unmake_amp_array(arr_rows, arr_cols, sg[0], ampInUse, ampdata);
249+
}
250+
}
251+
}}
181252

182-
free(ampdata);
183-
free(ampdata_gap);
184-
free(dc_bias_levels);
253+
freeOnExit(&ptrReg);
185254

186255
return status;
187256
}
@@ -894,6 +963,7 @@ static int make_amp_array(const int arr_rows, const int arr_cols, SingleGroup *i
894963
array[i*arr_cols + j] = Pix(im->sci.data, c, r);
895964
}
896965
}
966+
trlmessage (MsgText);
897967

898968
return status;
899969
}

0 commit comments

Comments
 (0)