MOONS Pipeline Reference Manual 0.13.1
moo_compute_slitoffset.c
1/*
2 * This file is part of the MOONS Pipeline
3 * Copyright (C) 2002-2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20#ifdef HAVE_CONFIG_H
21#include <config.h>
22#endif
23
24/*-----------------------------------------------------------------------------
25 Includes
26 -----------------------------------------------------------------------------*/
27#include <math.h>
28#include <string.h>
29#include <cpl.h>
30
31#include "moo_compute_slitoffset.h"
32#include "moo_fits.h"
33#include "moo_pfits.h"
34#include "moo_badpix.h"
35#include "moo_utils.h"
36/*----------------------------------------------------------------------------*/
41/*----------------------------------------------------------------------------*/
42
45/*-----------------------------------------------------------------------------
46 Function codes
47 -----------------------------------------------------------------------------*/
48static double
49_moo_compute_slitoffset_single(moo_single *det,
50 moo_loc_single *loc,
51 moo_compute_slitoffset_params *params)
52{
53 double res = NAN;
54 cpl_vector *sumfluxv = NULL;
55 cpl_matrix *xpos = NULL;
56 cpl_vector *values = NULL;
57 cpl_polynomial *poly = NULL;
58
59 cpl_ensure(det != NULL, CPL_ERROR_NULL_INPUT, NAN);
60 cpl_ensure(loc != NULL, CPL_ERROR_NULL_INPUT, NAN);
61 cpl_ensure(params != NULL, CPL_ERROR_NULL_INPUT, NAN);
62
63 cpl_errorstate prestate = cpl_errorstate_get();
64
65 cpl_image *fcentroids = moo_loc_single_get_f_centroids(loc);
66 int nb_fibres = cpl_image_get_size_y(fcentroids);
67 int nx = cpl_image_get_size_x(fcentroids);
68
69
70 hdrl_image *himage = moo_single_get_image(det);
71 cpl_image *image = hdrl_image_get_image(himage);
72
73 double min = params->min;
74 double max = params->max;
75 double step = params->step;
76
77 int size = (int)((max - min) / step + 1);
78 moo_try_check(sumfluxv = cpl_vector_new(size), " ");
79
80 double *sumflux = cpl_vector_get_data(sumfluxv);
81 for (int i = 0; i < size; i++) {
82 sumflux[i] = 0;
83 }
84/* The following addresses an issue with the gcc9 compiler series prior to
85 * gcc 9.3. These compiler versions require that the variable '__func__'
86 * appears in the data sharing clause if default(none) is used. However
87 * adding it to the data sharing clause breaks older compiler versions where
88 * these variables are pre-determined as shared.
89 * This was fixed in gcc 9.3 and OpenMP 5.1.
90 */
91#ifdef _OPENMP
92#if (__GNUC__ == 9) && (__GNUC_MINOR__ < 3)
93#pragma omp parallel shared(sumflux, size, min, max, step, nb_fibres, nx, \
94 fcentroids, image)
95#else
96#pragma omp parallel default(none) \
97 shared(sumflux, size, min, max, step, nb_fibres, nx, fcentroids, image)
98#endif
99 {
100#pragma omp for
101#endif
102 for (int s = 0; s < size; s++) {
103 double delta = min + s * step;
104 for (int j = 1; j <= nb_fibres; j++) {
105 for (int i = 1; i <= nx; i++) {
106 int rej;
107 double yc = cpl_image_get(fcentroids, i, j, &rej);
108 if (!isnan(yc)) {
109 int nyc = (int)round(yc + delta);
110 double flux = cpl_image_get(image, i, nyc, &rej);
111 if (rej == 0) {
112 sumflux[s] += flux;
113 }
114 }
115 }
116 }
117 }
118#ifdef _OPENMP
119 }
120#endif
121 double vmax = cpl_vector_get_max(sumfluxv);
122 double lim = vmax * 0.9;
123 int imin = 0;
124
125 for (int i = 0; i < size; i++) {
126 double v = sumflux[i];
127 if (v >= lim) {
128 imin = i;
129 break;
130 }
131 }
132
133 int imax = size - 1;
134 for (int i = size - 1; i >= 0; i--) {
135 double v = sumflux[i];
136 if (v >= lim) {
137 imax = i;
138 break;
139 }
140 }
141
142 int fitsize = imax - imin + 1;
143 xpos = cpl_matrix_new(1, fitsize);
144 values = cpl_vector_new(fitsize);
145
146 for (int i = imin; i <= imax; i++) {
147 double v = sumflux[i];
148 double s = min + i * step;
149 cpl_matrix_set(xpos, 0, i - imin, s);
150 cpl_vector_set(values, i - imin, v);
151 }
152 poly = cpl_polynomial_new(1);
153 const cpl_boolean sampsym = CPL_TRUE;
154 const cpl_size maxdeg1d = 2;
155 cpl_polynomial_fit(poly, xpos, &sampsym, values, NULL, CPL_FALSE, NULL,
156 &maxdeg1d);
157
158 cpl_size power = 2;
159 double a = cpl_polynomial_get_coeff(poly, &power);
160 power = 1;
161 double b = cpl_polynomial_get_coeff(poly, &power);
162 res = b / (2 * a);
163
164moo_try_cleanup:
165 cpl_polynomial_delete(poly);
166 cpl_matrix_delete(xpos);
167 cpl_vector_delete(values);
168 cpl_vector_delete(sumfluxv);
169 // dump error from the state
170 if (!cpl_errorstate_is_equal(prestate)) {
171 cpl_msg_error(__func__, "Error in compute_slitoffset");
172 cpl_errorstate_dump(prestate, CPL_FALSE, cpl_errorstate_dump_one);
173 res = NAN;
174 // Recover from the error(s) (Reset to prestate))
175 cpl_errorstate_set(prestate);
176 }
177 return res;
178}
179/*----------------------------------------------------------------------------*/
195/*----------------------------------------------------------------------------*/
196float *
198 moo_loc *loc,
199 moo_compute_slitoffset_params *params)
200{
201 float *offsets = NULL;
202
203 cpl_ensure(det != NULL, CPL_ERROR_NULL_INPUT, NULL);
204 cpl_ensure(loc != NULL, CPL_ERROR_NULL_INPUT, NULL);
205 cpl_ensure(params != NULL, CPL_ERROR_NULL_INPUT, NULL);
206
207 unsigned int badpix_level = MOO_BADPIX_OUTSIDE_DATA_RANGE |
209
210 offsets = cpl_calloc(6, sizeof(float));
211 cpl_msg_info("compute_slitoffset",
212 "Compute slit offset with [%f,%f] step %f", params->min,
213 params->max, params->step);
214
215 for (int i = 1; i <= 2; i++) {
216 for (int j = 0; j < 3; j++) {
217 int idx = j + (i - 1) * 3;
218 moo_single *det_single =
219 moo_det_load_single(det, j, i, badpix_level);
220 moo_loc_single *loc_single = moo_loc_get_single(loc, j, i);
221 if (det_single != NULL && loc_single != NULL) {
222 offsets[idx] =
223 (float)_moo_compute_slitoffset_single(det_single,
224 loc_single, params);
225 }
226 else {
227 offsets[idx] = NAN;
228 }
229 }
230 }
231
232 return offsets;
233}
#define MOO_BADPIX_OUTSIDE_DATA_RANGE
Definition: moo_badpix.h:62
#define MOO_BADPIX_CALIB_DEFECT
Definition: moo_badpix.h:48
#define MOO_BADPIX_COSMETIC
Definition: moo_badpix.h:57
moo_single * moo_det_load_single(moo_det *self, moo_detector_type type, int num, int level)
Load the type part in DET and return it.
Definition: moo_det.c:197
cpl_image * moo_loc_single_get_f_centroids(moo_loc_single *self)
Get image of fit centroids.
moo_loc_single * moo_loc_get_single(moo_loc *self, moo_detector_type type, int ntas)
Get the type part in LOC and return it.
Definition: moo_loc.c:155
hdrl_image * moo_single_get_image(moo_single *self)
Get the IMAGE part (DATA,ERR) of single DET.
Definition: moo_single.c:330
float * moo_compute_slitoffset(moo_det *det, moo_loc *loc, moo_compute_slitoffset_params *params)
Compute slit offset in LOC.