CR2RE Pipeline Reference Manual 1.6.7
hdrl_cat_extend.c
1/*
2 * This file is part of the HDRL
3 * Copyright (C) 2017 European Southern Observatory
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#include <string.h>
21
22#include "hdrl_cat_extend.h"
23
24#include "hdrl_cat_statistics.h"
25#include "hdrl_cat_polynm.h"
26
27
28/*** Defines ***/
29
30#define NACC 10 /* */
31#define NCOEF 4 /* Number of coeficients using in the call to the polynm */
32
33
34/*---------------------------------------------------------------------------*/
42/*----------------------------------------------------------------------------*/
43
46/* ---------------------------------------------------------------------------*/
66/* ---------------------------------------------------------------------------*/
67cpl_error_code hdrl_extend(
68 ap_t *ap, double xniso, double xbar, double ybar,
69 double sxx, double sxy, double syy, double areal0, double tmax, double *ttotal)
70{
71 /* Initialise a few things */
72 double *map = ap->indata;
73 cpl_size nx = ap->lsiz;
74 cpl_size ny = ap->csiz;
75 double skysig = ap->sigma;
76 double thresh = ap->thresh;
77 unsigned char *mflag = ap->mflag;
78
79 /* Calculate the eccentricity and position angle of the object
80 * CONSTANTS: 0.5, 4, 16, 0.9, 5, 3, 2 */
81 double srr = CPL_MAX(0.5, sxx + syy);
82 double ecc = CPL_MIN(0.9, sqrt((syy - sxx) * (syy - sxx) + 4. * sxy * sxy) / srr);
83 double xx = 0.5 * (1. + ecc) * srr - sxx;
84
85 double theta;
86 if (sxy == 0) {
87 theta = 0.;
88 } else if (xx == 0.) {
89 theta = CPL_MATH_PI_2;
90 } else {
91 theta = atan(sxy / xx);
92 }
93
94 double ctheta = cos(theta);
95 double stheta = sin(theta);
96
97 /* Eccentricity modified by noise effect. NB: 50 == 16*pi */
98 ecc = CPL_MIN(0.9, sqrt( CPL_MAX( (syy - sxx) * (syy - sxx)
99 - 16. * CPL_MATH_PI * skysig * srr * srr * srr / (xniso * xniso)
100 + 4. * sxy * sxy,
101 0.) ) / srr);
102
103 /* Set initial aperture to be isophotal area */
104 double a = sqrt(srr * (1. + ecc));
105 double b = sqrt(srr * (1. - ecc));
106 double stretch = sqrt(areal0 / (CPL_MATH_PI * a * b));
107
108 /* Number of isophotal radii to extend */
109 double rad = CPL_MAX(1.1, (tmax - skysig) / thresh);
110 double sfac = CPL_MIN(5., CPL_MAX(2., 3. / sqrt(log(rad))));
111
112 a *= sfac * stretch;
113 b *= sfac * stretch;
114
115 /* Clear accumulator */
116 double accum[NACC];
117 memset(accum, 0, NACC * sizeof(double));
118
119 /* Generate image boundaries. First for y */
120 double climsq = CPL_MAX(1., (a * ctheta) * (a * ctheta) + (b * stheta) * (b * stheta));
121 double clim = sqrt(climsq);
122
123 double pt1 = sin(2. * theta) * (b * b - a * a);
124 double pt2 = (b * ctheta) * (b * ctheta) + (a * stheta) * (a * stheta);
125 double pt3 = (a * b) * (a * b);
126
127 cpl_size jmin = CPL_MAX( 1, (cpl_size)(ybar - clim));
128 cpl_size jmax = CPL_MIN(ny, (cpl_size)(ybar + clim + 1.));
129 for (cpl_size jj = jmin; jj <= jmax; jj++) {
130
131 /* Now for x */
132 cpl_size kk = (jj-1)*nx;
133
134 double c = (double)jj - ybar;
135
136 double pa = climsq;
137 double pb = pt1 * c;
138 double pc = pt2 * c * c - pt3;
139
140 double arg1 = sqrt(CPL_MAX(0., pb * pb - 4. * pa * pc));
141
142 double xliml = (-pb - arg1) / (2. * pa);
143 double xlimu = (-pb + arg1) / (2. * pa);
144
145 cpl_size imin = CPL_MAX( 1, (cpl_size)(xbar + xliml ));
146 cpl_size imax = CPL_MIN(nx, (cpl_size)(xbar + xlimu + 1.));
147
148 double y = c;
149
150 for (cpl_size ii = imin; ii <= imax; ii++) {
151
152 if ( mflag[kk + ii - 1] == MF_CLEANPIX
153 || mflag[kk + ii - 1] == MF_OBJPIX
154 || mflag[kk + ii - 1] == MF_SATURATED)
155 {
156 double t = map[kk + ii - 1];
157 double x = (double)ii - xbar;
158
159 /* Accumulate elliptical isophotal areas */
160 double xnew = x * ctheta - y * stheta;
161 double ynew = x * stheta + y * ctheta;
162
163 double ellrad = 2. * sqrt( (ynew / a) * (ynew / a)
164 + (xnew / b) * (xnew / b));
165
166 cpl_size iupd = CPL_MIN(NACC, CPL_MAX(1, (cpl_size)((2. - ellrad) * (double)NACC) + 1));
167
168 for (cpl_size idx = 1; idx <= iupd; idx++) {
169 accum[NACC - idx] += t;
170 }
171 }
172 }
173 }
174
175 /* Now find limiting intensity */
176 if (xniso < 0.) {
177 for (cpl_size i = 0; i < NACC; i++) {
178 accum[i] = -accum[i];
179 }
180 }
181
182 hdrl_median(accum, NACC, 3);
183
184 double xmax = 0.;
185 double xlim1 = -1.;
186 double xlim2 = -1.;
187
188 double xcord[NACC];
189 double xdat[NACC];
190 for (cpl_size i = 0; i < NACC; i++) {
191 xcord[i] = i + 1;
192 xmax = CPL_MAX(xmax, accum[i]);
193 xdat[i] = accum[i];
194 }
195
196 double polycf[NCOEF];
197 hdrl_polynm(xdat, xcord, NACC, polycf, NCOEF, 0);
198
199 double pa = polycf[1];
200 double pb = polycf[2] * 2.;
201 double pc = polycf[3] * 3.;
202
203 double arg1 = sqrt(CPL_MAX(0., pb * pb - 4. * pa * pc));
204
205 if (pc != 0.) {
206
207 double rt1 = (-pb + arg1) / (2. * pc);
208 double rt2 = (-pb - arg1) / (2. * pc);
209
210 if (rt1 < (double)NACC && rt1 > 1.) {
211
212 cpl_size ir = (cpl_size)rt1;
213 double t1 = rt1 - (double)ir;
214
215 xlim1 = (1. - t1) * accum[ir - 1] + t1 * accum[ir];
216 }
217
218 if (rt2 < (double)NACC && rt2 > 1.) {
219
220 cpl_size ir = (cpl_size)rt2;
221 double t1 = rt2 - ir;
222
223 xlim2 = (1. - t1) * accum[ir - 1] + t1 * accum[ir];
224 }
225 }
226
227 double xlimit = CPL_MAX(xlim1, xlim2);
228 if (xlimit < 0.) {
229 xlimit = xmax;
230 }
231
232 /* Update total intensity */
233 if (xniso < 0.) {
234 xlimit = -xlimit;
235 }
236 *ttotal = xlimit;
237
238 return CPL_ERROR_NONE;
239}
240
cpl_error_code hdrl_extend(ap_t *ap, double xniso, double xbar, double ybar, double sxx, double sxy, double syy, double areal0, double tmax, double *ttotal)
Do aperture integration.
cpl_error_code hdrl_polynm(double xdat[], double xcor[], cpl_size n, double polycf[], cpl_size m, cpl_size ilim)
Work out the median seeing.
cpl_error_code hdrl_median(double xbuf[], cpl_size npt, cpl_size nfilt)
compute median