MOONS Pipeline Reference Manual 0.13.1
moo_psf_single.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 <cpl.h>
29#include "moo_pfits.h"
30#include "moo_psf_single.h"
31#include "moo_fits.h"
32#include "moo_utils.h"
33#ifdef _OPENMP
34#include <omp.h>
35#endif
36/*----------------------------------------------------------------------------*/
52/*----------------------------------------------------------------------------*/
53
56/*-----------------------------------------------------------------------------
57 Function codes
58 -----------------------------------------------------------------------------*/
59
60/*----------------------------------------------------------------------------*/
68/*----------------------------------------------------------------------------*/
69moo_psf_single *
71{
72 moo_psf_single *res = cpl_calloc(1, sizeof(moo_psf_single));
73 return res;
74}
75
76/*----------------------------------------------------------------------------*/
87/*----------------------------------------------------------------------------*/
88moo_psf_single *
89moo_psf_single_create(const char *filename, const char *extname)
90{
91 cpl_ensure(filename != NULL, CPL_ERROR_NULL_INPUT, NULL);
92 cpl_ensure(extname != NULL, CPL_ERROR_NULL_INPUT, NULL);
93
94 moo_psf_single *res = moo_psf_single_new();
95
96 res->extname = extname;
97 res->filename = filename;
98
99 return res;
100}
101
102/*----------------------------------------------------------------------------*/
114/*----------------------------------------------------------------------------*/
115cpl_error_code
116moo_psf_single_set_cube_ref(moo_psf_single *self, double crpix2, double cd2_2)
117{
118 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
119 if (self->header == NULL) {
120 self->header = cpl_propertylist_new();
121 }
122 cpl_propertylist_append_double(self->header, MOO_PFITS_CRPIX1, 1.0);
123 cpl_propertylist_append_string(self->header, MOO_PFITS_CTYPE1, "LINEAR");
124 cpl_propertylist_append_double(self->header, MOO_PFITS_CRPIX2, crpix2);
125 cpl_propertylist_append_string(self->header, MOO_PFITS_CTYPE2, "LINEAR");
126 cpl_propertylist_append_double(self->header, MOO_PFITS_CRVAL1, 1.0);
127 cpl_propertylist_append_double(self->header, MOO_PFITS_CRVAL2, 0.0);
128 cpl_propertylist_append_double(self->header, MOO_PFITS_CD1_1, 1.0);
129 cpl_propertylist_append_double(self->header, MOO_PFITS_CD1_2, 0.0);
130 cpl_propertylist_append_string(self->header, MOO_PFITS_CUNIT1,
131 MOO_PSF_SINGLE_CUNIT1);
132 cpl_propertylist_append_double(self->header, MOO_PFITS_CD2_1, 0.);
133 cpl_propertylist_append_double(self->header, MOO_PFITS_CD2_2, cd2_2);
134
135 return cpl_error_get_code();
136}
137
138/*----------------------------------------------------------------------------*/
150/*----------------------------------------------------------------------------*/
151cpl_error_code
152moo_psf_single_get_cube_ref(moo_psf_single *self, double *crpix2, double *cd2_2)
153{
154 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
155 cpl_ensure_code(crpix2 != NULL, CPL_ERROR_NULL_INPUT);
156 cpl_ensure_code(cd2_2 != NULL, CPL_ERROR_NULL_INPUT);
157
158 if (self->header == NULL) {
159 self->header =
160 moo_fits_load_extension_header(self->filename,
161 MOO_PSF_SINGLE_PREFIX_EXTNAME,
162 self->extname);
163 }
164 *crpix2 = moo_pfits_get_crpix2(self->header);
165 *cd2_2 = moo_pfits_get_cd2_2(self->header);
166
167 return cpl_error_get_code();
168}
169
170static void
171_moo_psf_single_reproject_model_fibre(cpl_image *image,
172 int numfib,
173 cpl_image *centroids,
174 cpl_image *model,
175 double crpix2,
176 double cd2_2,
177 cpl_image *result,
178 cpl_image *contrib)
179{
180 int nx = cpl_image_get_size_x(image);
181 int ny = cpl_image_get_size_y(model);
182
183 double *data = cpl_image_get_data(result);
184 int *contrib_data = cpl_image_get_data(contrib);
185
186 for (int x = 1; x <= nx; x++) {
187 int rej;
188 double centroid = cpl_image_get(centroids, x, numfib, &rej);
189 if (!isnan(centroid)) {
190 for (int y = 1; y <= ny; y++) {
191 double ypos = centroid + (y - crpix2) * cd2_2;
192 double flux = cpl_image_get(model, x, y, &rej);
193 int pix = (int)floor(ypos + 0.5);
194 data[(pix - 1) * nx + x - 1] += flux;
195 contrib_data[(pix - 1) * nx + x - 1] += 1;
196 }
197 }
198 }
199}
200
201cpl_image *
202moo_psf_single_reproject_model(moo_psf_single *self,
203 moo_single *det,
204 moo_loc_single *loc,
205 const int *health,
206 cpl_array *indexes)
207{
208 cpl_image *result = NULL;
209
210 cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, NULL);
211 cpl_ensure(det != NULL, CPL_ERROR_NULL_INPUT, NULL);
212 cpl_ensure(loc != NULL, CPL_ERROR_NULL_INPUT, NULL);
213 cpl_ensure(health != NULL, CPL_ERROR_NULL_INPUT, NULL);
214
215 cpl_image *contrib = NULL;
216
217 cpl_errorstate prestate = cpl_errorstate_get();
218
219 cpl_image *fcentroids = moo_loc_single_get_f_centroids(loc);
220 hdrl_image *himage = moo_single_get_image(det);
221 cpl_image *image = hdrl_image_get_image(himage);
222
223 cpl_ensure(fcentroids != NULL, CPL_ERROR_NULL_INPUT, NULL);
224 cpl_ensure(himage != NULL, CPL_ERROR_NULL_INPUT, NULL);
225
226 int nx = hdrl_image_get_size_x(himage);
227 int ny = hdrl_image_get_size_y(himage);
228 int nb_fibres = cpl_image_get_size_y(fcentroids);
229
230 cpl_imagelist *cube = moo_psf_single_get_cube(self);
231 double crpix2, cd2_2;
232 moo_try_check(moo_psf_single_get_cube_ref(self, &crpix2, &cd2_2), " ");
233 cpl_msg_debug(__func__, "Use nx %d ny %d crpix2 %f cd2_2 %f", nx, ny,
234 crpix2, cd2_2);
235 result = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
236 contrib = cpl_image_new(nx, ny, CPL_TYPE_INT);
237
238/* The following addresses an issue with the gcc9 compiler series prior to
239 * gcc 9.3. These compiler versions require that the variable '__func__'
240 * appears in the data sharing clause if default(none) is used. However
241 * adding it to the data sharing clause breaks older compiler versions
242 * where these variables are pre-determined as shared.
243 * This was fixed in gcc 9.3 and OpenMP 5.1.
244 */
245#ifdef _OPENMP
246#if (__GNUC__ == 9) && (__GNUC_MINOR__ < 3)
247#pragma omp parallel shared(nb_fibres, health, cube, image, fcentroids, \
248 crpix2, cd2_2, result, contrib, indexes)
249#else
250#pragma omp parallel default(none) \
251 shared(nb_fibres, health, cube, image, fcentroids, crpix2, cd2_2, result, \
252 contrib, indexes)
253#endif
254 {
255#pragma omp for
256#endif
257 for (int i = 1; i <= nb_fibres; i++) {
258 int idx = cpl_array_get_cplsize(indexes, i - 1, NULL);
259 int h = health[idx];
260 cpl_msg_debug(__func__, "reproject fibre %d", i);
261
262 if (h != 0) {
263 cpl_image *model = cpl_imagelist_get(cube, i - 1);
264 _moo_psf_single_reproject_model_fibre(image, i, fcentroids,
265 model, crpix2, cd2_2,
266 result, contrib);
267 }
268 }
269#ifdef _OPENMP
270 }
271#endif
272 double *data = cpl_image_get_data(result);
273 int *contrib_data = cpl_image_get_data(contrib);
274
275 for (int i = 0; i < nx * ny; i++) {
276 if (contrib_data[i] != 0) {
277 data[i] /= contrib_data[i];
278 }
279 }
280moo_try_cleanup:
281 cpl_image_delete(contrib);
282 // dump error from the state
283 if (!cpl_errorstate_is_equal(prestate)) {
284 cpl_msg_error(__func__, "Error in PSF file %s ext %s", self->filename,
285 self->extname);
286 cpl_errorstate_dump(prestate, CPL_FALSE, cpl_errorstate_dump_one);
287 cpl_image_delete(result);
288 result = NULL;
289 // Recover from the error(s) (Reset to prestate))
290 cpl_errorstate_set(prestate);
291 }
292 return result;
293}
294
295/*----------------------------------------------------------------------------*/
304/*----------------------------------------------------------------------------*/
305
306cpl_error_code
307moo_psf_single_normalize(moo_psf_single *self)
308{
309 cpl_error_code status = CPL_ERROR_NONE;
310 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
311
312 cpl_imagelist *cube = moo_psf_single_get_cube(self);
313
314 int nb_fibres = cpl_imagelist_get_size(cube);
315 double crpix2, cd2_2;
316 moo_psf_single_get_cube_ref(self, &crpix2, &cd2_2);
317#ifdef _OPENMP
318#pragma omp parallel default(none) shared(nb_fibres, cube, cd2_2)
319 {
320#pragma omp for
321#endif
322 for (int f = 1; f <= nb_fibres; f++) {
323 cpl_image *model = cpl_imagelist_get(cube, f - 1);
324 int nx = cpl_image_get_size_x(model);
325 int ny = cpl_image_get_size_y(model);
326 for (int i = 1; i <= nx; i++) {
327 double sum = 0.0;
328 int rej;
329 for (int j = 1; j <= ny; j++) {
330 sum += cpl_image_get(model, i, j, &rej);
331 }
332 sum *= cd2_2;
333 for (int j = 1; j <= ny; j++) {
334 double val = cpl_image_get(model, i, j, &rej);
335 cpl_image_set(model, i, j, val / sum);
336 }
337 }
338 }
339#ifdef _OPENMP
340 }
341#endif
342 return status;
343}
344/*----------------------------------------------------------------------------*/
353/*----------------------------------------------------------------------------*/
354
355void
356moo_psf_single_delete(moo_psf_single *self)
357{
358 if (self != NULL) {
359 if (self->header != NULL) {
360 cpl_propertylist_delete(self->header);
361 }
362 if (self->cube != NULL) {
363 cpl_imagelist_delete(self->cube);
364 }
365
366 cpl_free(self);
367 }
368}
369/*----------------------------------------------------------------------------*/
379/*----------------------------------------------------------------------------*/
380void
381moo_psf_single_save(const moo_psf_single *self, const char *filename)
382{
383 if (self != NULL) {
384 moo_fits_write_extension_cube(self->cube, filename,
385 MOO_PSF_SINGLE_PREFIX_EXTNAME,
386 self->extname, CPL_TYPE_FLOAT,
387 self->header);
388 }
389}
390
391/*----------------------------------------------------------------------------*/
403/*----------------------------------------------------------------------------*/
404cpl_error_code
405moo_psf_single_dump(const moo_psf_single *self, FILE *stream)
406{
407 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
408 cpl_ensure_code(stream != NULL, CPL_ERROR_NULL_INPUT);
409
410 fprintf(stream, "---MOO_PSF_SINGLE\n");
411 fprintf(stream, "filename %s extname %s\n", self->filename, self->extname);
412
413 return CPL_ERROR_NONE;
414}
415
416/*----------------------------------------------------------------------------*/
427/*----------------------------------------------------------------------------*/
428cpl_imagelist *
429moo_psf_single_get_cube(moo_psf_single *self)
430{
431 cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, NULL);
432 cpl_ensure(self->filename != NULL, CPL_ERROR_NULL_INPUT, NULL);
433 cpl_ensure(self->extname != NULL, CPL_ERROR_NULL_INPUT, NULL);
434
435 if (self->cube == NULL) {
436 self->cube =
437 moo_fits_load_extension_cube(self->filename,
438 MOO_PSF_SINGLE_PREFIX_EXTNAME,
439 self->extname, CPL_TYPE_FLOAT);
440 }
441 return self->cube;
442}
cpl_imagelist * moo_fits_load_extension_cube(const char *filename, const char *name, const char *detectorname, cpl_type type)
Load a cube from FITS file.
Definition: moo_fits.c:455
cpl_error_code moo_fits_write_extension_cube(cpl_imagelist *cube, const char *filename, const char *name, const char *detectorname, cpl_type type, cpl_propertylist *header)
Write a cube as extension in FITS file.
Definition: moo_fits.c:250
cpl_image * moo_loc_single_get_f_centroids(moo_loc_single *self)
Get image of fit centroids.
cpl_error_code moo_psf_single_set_cube_ref(moo_psf_single *self, double crpix2, double cd2_2)
Set cube parameters.
void moo_psf_single_delete(moo_psf_single *self)
Delete a moo_psf_single.
cpl_error_code moo_psf_single_get_cube_ref(moo_psf_single *self, double *crpix2, double *cd2_2)
Set cube parameters.
moo_psf_single * moo_psf_single_new(void)
Create a new moo_psf_single
void moo_psf_single_save(const moo_psf_single *self, const char *filename)
Save a moo_psf_single to a FITS file.
cpl_error_code moo_psf_single_dump(const moo_psf_single *self, FILE *stream)
Dump structural information of PSF_SINGLE.
cpl_error_code moo_psf_single_normalize(moo_psf_single *self)
Normalize cube model profile.
cpl_imagelist * moo_psf_single_get_cube(moo_psf_single *self)
Get cube.
moo_psf_single * moo_psf_single_create(const char *filename, const char *extname)
Create a new moo_psf_single from the given PSF filename.
hdrl_image * moo_single_get_image(moo_single *self)
Get the IMAGE part (DATA,ERR) of single DET.
Definition: moo_single.c:330
double moo_pfits_get_crpix2(const cpl_propertylist *plist)
find out the CRPIX2 value
Definition: moo_pfits.c:1156
double moo_pfits_get_cd2_2(const cpl_propertylist *plist)
find out the CD2_2 value
Definition: moo_pfits.c:1276