GIRAFFE Pipeline Reference Manual

gislitgeometry.c
1/*
2 * This file is part of the GIRAFFE Pipeline
3 * Copyright (C) 2002-2019 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 St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifdef HAVE_CONFIG_H
21# include <config.h>
22#endif
23
24#include <cxmemory.h>
25
26#include <cpl_msg.h>
27
28#include "gierror.h"
29#include "gimessages.h"
30#include "giframe.h"
31#include "gifiberutils.h"
32#include "gimatrix.h"
33#include "gislitgeometry.h"
34
35
44/*
45 * @brief
46 * Create a cpl_matrix at a specified position of the GiSlitGeometry
47 *
48 * @param self GiSlitGeometry in which to create the cpl_matrix
49 * @param pos Position at which to create the matrix
50 * @param nrow Number of rows of the matrix
51 * @param ncol Number of columns of the matrix
52 *
53 * Creates a cpl_matrix at position @em pos inside the GiSlitGeometry
54 * @em self of @em nrow rows and @em ncol columns. If a cpl_matrix is
55 * already present at position @em pos, it is properly deallocated first.
56 */
57
58inline static void
59_giraffe_slitgeometry_insert(GiSlitGeometry *self, cxint pos, cxint nrow,
60 cxint ncol)
61{
62
63 if (self == NULL) {
64 return;
65 }
66
67 if (self->subslits == NULL) {
68 return;
69 }
70
71 if ((pos < 0) || (pos > self->nsubslits)) {
72 return;
73 }
74
75 if (self->subslits[pos] != NULL) {
76 cpl_matrix_delete(self->subslits[pos]);
77 }
78
79 self->subslits[pos] = cpl_matrix_new(nrow, ncol);
80
81 return;
82
83}
84
85
99{
100
101 GiSlitGeometry *self = cx_malloc(sizeof *self);
102
103 self->xf = NULL;
104 self->yf = NULL;
105
106 self->nsubslits = 0;
107 self->subslits = NULL;
108
109 return self;
110
111}
112
113
128{
129
130 GiSlitGeometry *clone = NULL;
131
132
133 if (other) {
134
135 cxint i;
136
137
138 clone = (GiSlitGeometry *)cx_malloc(sizeof *clone);
139
140 if ((other->subslits == NULL) || (other->nsubslits == 0)) {
141
142 clone->nsubslits = other->nsubslits;
143 clone->subslits = other->subslits;
144
145 return clone;
146
147 }
148
149 clone->nsubslits = other->nsubslits;
150 clone->subslits = cx_calloc(clone->nsubslits, sizeof(cpl_matrix *));
151
152 for (i = 0; i < other->nsubslits; i++) {
154 giraffe_slitgeometry_get(other,i));
155 }
156
157 }
158
159 return clone;
160
161}
162
163
185giraffe_slitgeometry_create(GiTable *slitgeometry, cxbool subslits)
186{
187
188 const cxchar *fctid = "giraffe_slitgeometry_create";
189
190
191 const cxchar *c_xf = "XF";
192 const cxchar *c_yf = "YF";
193 const cxchar *c_fps = "FPS";
194 const cxchar *c_ssn = "SSN";
195 const cxchar *c_rindex = NULL;
196
197 /*cxint status;*/
198 cxint nfibers = 0;
199 cxint max_nsubslits = 0;
200 cxint i = 0;
201 cxint j = 0;
202 cxint count = 0;
203 cxint column_index = 0;
204
205 cpl_matrix *nsubslits = NULL;
206
207 cpl_table *_slitgeometry = NULL;
208
209 GiSlitGeometry *self = NULL;
210
211
212 if (slitgeometry == NULL) {
213 return NULL;
214 }
215
217
218 if (self == NULL) {
219 return NULL;
220 }
221
222 _slitgeometry = giraffe_table_get(slitgeometry);
223 nfibers = cpl_table_get_nrow(_slitgeometry);
224
225 self->xf = cpl_matrix_new(nfibers, 1);
226 self->yf = cpl_matrix_new(nfibers, 1);
227 self->fps = cpl_matrix_new(nfibers, 1);
228 self->rindex = cpl_matrix_new(nfibers, 1);
229
230 nsubslits = cpl_matrix_new(nfibers, 1);
231
232
233 c_rindex = giraffe_fiberlist_query_index(_slitgeometry);
234
235 /*
236 * Copy relevant data to matrices
237 */
238
239 max_nsubslits = 0;
240
241 for (i = 0; i < nfibers; i++) {
242
243 cxint _nsubslits = cpl_table_get_int(_slitgeometry, c_ssn, i, NULL);
244 cxint _fps = cpl_table_get_int(_slitgeometry, c_fps, i, NULL) - 1;
245 cxint _index = cpl_table_get_int(_slitgeometry, c_rindex,
246 i, NULL) - 1;
247
248 cxdouble _xf = cpl_table_get(_slitgeometry, c_xf, i, NULL);;
249 cxdouble _yf = cpl_table_get(_slitgeometry, c_yf, i, NULL);
250
251
252 if (_nsubslits > max_nsubslits) {
253 max_nsubslits = _nsubslits;
254 }
255
256 /*status =*/ cpl_matrix_set(self->xf, i, 0, _xf);
257 /*status =*/ cpl_matrix_set(self->yf, i, 0, _yf);
258 /*status =*/ cpl_matrix_set(self->fps, i, 0, (cxdouble)_fps);
259 /*status =*/ cpl_matrix_set(self->rindex, i, 0, (cxdouble)_index);
260
261 /*status =*/ cpl_matrix_set(nsubslits, i, 0, (cxdouble)_nsubslits);
262
263 }
264
265
266 /*
267 * Create Slit Geometry
268 */
269
270 if (subslits) {
271
272 /* create multiple subslits */
273
274 giraffe_slitgeometry_resize(self, max_nsubslits);
275
276 for (i = 1; i <= max_nsubslits; i++) {
277
278 cxint curr_ssn;
279
280 cpl_matrix *ref_matrix = NULL;
281
282 count = 0;
283 for (j = 0; j < nfibers; j++) {
284 curr_ssn = (cxint) cpl_matrix_get(nsubslits, j, 0);
285
286 if (i == curr_ssn) {
287 ++count;
288 }
289 }
290
291 _giraffe_slitgeometry_insert(self, i - 1, count, 1);
292
293 ref_matrix = giraffe_slitgeometry_get(self, i - 1);
294
295 column_index = 0;
296 for (j = 0; j < nfibers; j++) {
297
298 curr_ssn = (cxint) cpl_matrix_get(nsubslits, j, 0);
299
300 if (i == curr_ssn) {
301
302 /*status =*/ cpl_matrix_set(ref_matrix, column_index, 0,
303 (cxdouble)j);
304 ++column_index;
305 }
306 }
307 }
308
309 cpl_msg_debug(fctid, "Using multiple slits for Slit Geometry");
310
311 }
312 else {
313
314 /* create one subslit containing all fibers */
315
316 cpl_matrix *ref_matrix = NULL;
317
319 _giraffe_slitgeometry_insert(self, 0, nfibers, 1);
320
321 ref_matrix = giraffe_slitgeometry_get(self, 0);
322
323 for (j = 0; j < nfibers; j++) {
324
325 /*status =*/ cpl_matrix_set(ref_matrix, j, 0, (cxdouble)j);
326
327 }
328
329 cpl_msg_debug(fctid, "Using single slit for Slit Geometry");
330
331 }
332
333 cpl_matrix_delete(nsubslits);
334
335 return self;
336
337}
338
339
351void
353{
354
355 if (self == NULL) {
356 return;
357 }
358
359 if (self->subslits != NULL) {
360
361 cxint i;
362
363 for (i = 0; i < self->nsubslits; i++) {
364 cpl_matrix_delete(self->subslits[i]);
365 }
366
367 cx_free(self->subslits);
368
369 }
370
371 return;
372
373}
374
375
389cxint
391{
392
393 if (self == NULL) {
394 return -1;
395 }
396
397 if (self->subslits != NULL) {
398 return self->nsubslits;
399 }
400
401 return 0;
402
403}
404
405
418void
420{
421
422 if (self == NULL) {
423 return;
424 }
425
426 if (size == self->nsubslits) {
427 return;
428 }
429
430 if (self->subslits != NULL) {
431
432 cxint i;
433
434 for (i = 0; i < self->nsubslits; i++) {
435 cpl_matrix_delete(self->subslits[i]);
436 }
437
438 }
439
440 cx_free(self->subslits);
441
442 self->nsubslits = size;
443 self->subslits = cx_calloc(self->nsubslits, sizeof(cpl_matrix *));
444
445 return;
446
447}
448
449
465void
467 cpl_matrix *nm)
468{
469
470 if (self == NULL) {
471 return;
472 }
473
474 if (self->subslits == NULL) {
475 return;
476 }
477
478 if ((pos < 0) || (pos > self->nsubslits)) {
479 return;
480 }
481
482 if (self->subslits[pos] != NULL) {
483 cpl_matrix_delete(self->subslits[pos]);
484 }
485
486 if (nm) {
487 self->subslits[pos] = cpl_matrix_duplicate(nm);
488 }
489 else {
490 self->subslits[pos] = NULL;
491 }
492
493 return;
494
495}
496
497
511cpl_matrix *
513{
514
515 if (self == NULL) {
516 return NULL;
517 }
518
519 if (self->subslits == NULL) {
520 return NULL;
521 }
522
523 if ((pos < 0) || (pos > self->nsubslits)) {
524 return NULL;
525 }
526
527 return self->subslits[pos];
528
529}
530
531
542void
544{
545
546 const cxchar *fctid = "giraffe_slitgeometry_print";
547
548 cxint i;
549
550 gi_message("Current slit geometry setup");
551
552 if (self == NULL) {
553 gi_message("Empty slit geometry!");
554 return;
555 }
556
557 if (self->subslits == NULL) {
558 gi_message(fctid, "Invalid slit geometry, no slit matrices "
559 "present!");
560 return;
561 }
562
563
564 for (i = 0; i < self->nsubslits; i++) {
565
566 cxint nrow = 0;
567
568 cpl_matrix *ref = NULL;
569
570 ref = giraffe_slitgeometry_get(self, i);
571 nrow = cpl_matrix_get_nrow(ref);
572
573 giraffe_matrix_dump(ref, nrow);
574 }
575
576 return;
577
578}
579
580
601GiTable *
602giraffe_slitgeometry_load(const GiTable *fibers, const cxchar *filename,
603 cxint pos, const cxchar *tag)
604{
605
606 const cxchar *fctid = "giraffe_slitgeometry_load";
607
608
609 const cxchar *fps_name = "FPS";
610 const cxchar *ridx = NULL;
611
612 cxint i;
613 cxint nfibers = 0;
614
615 cpl_propertylist *properties = NULL;
616
617 cpl_table *_fibers = NULL;
618 cpl_table *_slit_geometry = NULL;
619
620 GiTable *slit_geometry = NULL;
621
622 GiInstrumentMode mode;
623
624
625
626 if (fibers == NULL) {
627 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
628 return NULL;
629 }
630
631 _fibers = giraffe_table_get(fibers);
632
633 if (_fibers == NULL) {
634 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
635 return NULL;
636 }
637
638 /*
639 * Get the instrument setup corresponding to the slit geometry in
640 * the file.
641 */
642
643 properties = cpl_propertylist_load(filename, 0);
644
645 if (properties == NULL) {
646 cpl_msg_error(fctid, "Cannot load properies of data set 0 "
647 "from `%s'!", filename);
648 cpl_propertylist_delete(properties);
649 return NULL;
650 }
651 else {
652
653 mode = giraffe_get_mode(properties);
654
655 if (mode == GIMODE_NONE) {
656 cpl_msg_error(fctid, "Invalid instrument mode!");
657
658 cpl_propertylist_delete(properties);
659 return NULL;
660 }
661
662 }
663
664 cpl_propertylist_delete(properties);
665
666
667 /*
668 * Load the slit geometry information
669 */
670
671 slit_geometry = giraffe_table_new();
672
673 giraffe_error_push();
674
675 if (giraffe_table_load(slit_geometry, filename, pos, tag)) {
676 if (cpl_error_get_code() == CPL_ERROR_BAD_FILE_FORMAT) {
677 cpl_msg_error(fctid, "Data set %d in `%s' is not a slit "
678 "geometry table!", pos, filename);
679 giraffe_table_delete(slit_geometry);
680 return NULL;
681 }
682 else {
683 cpl_msg_error(fctid, "Cannot load data set %d (slit geometry) "
684 "from `%s!", pos, filename);
685 giraffe_table_delete(slit_geometry);
686 return NULL;
687 }
688 }
689
690 giraffe_error_pop();
691
692 _slit_geometry = giraffe_table_get(slit_geometry);
693
694 if (!cpl_table_has_column(_slit_geometry, fps_name)) {
695 if (cpl_table_has_column(_slit_geometry, "NSPEC")) {
696 cpl_msg_warning(fctid, "Slit geometry loaded from `%s' uses "
697 "deprecated OGL column names.", filename);
698
699 // FIXME: This should not be done here. The data should
700 // be correct!
701 // The following code assumes that all possible fibers
702 // are listed in the order they appear on an image.
703 // Only fibers which do not appear on the CCD on the
704 // right side (high FPS numbers for Medusa and IFU, low
705 // FPS numbers for Argus) may be missing. For all other
706 // cases the code below would just generate garbage.
707
708 cpl_table_duplicate_column(_slit_geometry, fps_name,
709 _slit_geometry, "NSPEC");
710
711 cpl_table_name_column(_slit_geometry, "NSPEC", "INDEX");
712
713 if (mode == GIMODE_ARGUS) {
714
715 cxint nrow = cpl_table_get_nrow(_slit_geometry);
716
717 for (i = 0; i < nrow; i++) {
718
719 cxint idx = cpl_table_get_int(_slit_geometry, "INDEX",
720 nrow - i - 1, NULL);
721
722 cpl_table_set_int(_slit_geometry, fps_name, i, idx);
723
724 }
725
726 }
727
728 }
729 else {
730 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
731 giraffe_table_delete(slit_geometry);
732 return NULL;
733 }
734 }
735
736
737 /*
738 * Extract the slit geometry information corresponding to the
739 * given fiber setup
740 */
741
742 nfibers = cpl_table_get_nrow(_fibers);
743
744 cpl_table_unselect_all(_slit_geometry);
745
746 for (i = 0; i < cpl_table_get_nrow(_slit_geometry); i++) {
747
748 cxint fps = cpl_table_get_int(_slit_geometry, fps_name, i, NULL);
749 cxint j;
750
751 for (j = 0; j < nfibers; j++) {
752
753 cxint _fps = cpl_table_get_int(_fibers, "FPS", j, NULL);
754
755 if (_fps == fps) {
756 cpl_table_select_row(_slit_geometry, i);
757 break;
758 }
759
760 }
761
762 }
763
764 _slit_geometry = cpl_table_extract_selected(_slit_geometry);
765
766
767 ridx = giraffe_fiberlist_query_index(_fibers);
768 cpl_table_new_column(_slit_geometry, "RINDEX", CPL_TYPE_INT);
769
770 for (i = 0; i < cpl_table_get_nrow(_slit_geometry); i++) {
771
772 cxint fps = cpl_table_get_int(_slit_geometry, fps_name, i, NULL);
773 cxint j;
774
775 for (j = 0; j < nfibers; j++) {
776
777 cxint _fps = cpl_table_get_int(_fibers, "FPS", j, NULL);
778
779 if (_fps == fps) {
780
781 cxint _ridx = cpl_table_get_int(_fibers, ridx, j , NULL);
782
783 cpl_table_set_int(_slit_geometry, "RINDEX", i, _ridx);
784 break;
785
786 }
787
788 }
789
790 }
791
792
793 /*
794 * If the loaded table had the OGL label for the fiber position within
795 * the slit (FPS) change it.
796 */
797
798 if (strcmp(fps_name, "FPS") != 0) {
799 cpl_table_name_column(_slit_geometry, fps_name, "FPS");
800 }
801
802
803 /*
804 * Reset the index column
805 */
806
807 for (i = 0; i < cpl_table_get_nrow(_slit_geometry); i++) {
808 cpl_table_set_int(_slit_geometry, "INDEX", i, i + 1);
809 }
810
811 giraffe_table_set(slit_geometry, _slit_geometry);
812
813 cpl_table_delete(_slit_geometry);
814 _slit_geometry = NULL;
815
816 return slit_geometry;
817
818}
819
820
821cpl_frame *
822giraffe_slitgeometry_save(const GiTable *slitgeometry)
823{
824
825 cpl_frame *frame = NULL;
826
827
828 if (slitgeometry) {
829
830 GiTable *slit = giraffe_table_duplicate(slitgeometry);
831
832
833 if (slit == NULL) {
834 return NULL;
835 }
836
837 if (cpl_table_has_column(giraffe_table_get(slit), "RINDEX")) {
838 cpl_table_erase_column(giraffe_table_get(slit), "RINDEX");
839 }
840
841 frame = giraffe_frame_create_table(slit, GIFRAME_SLITSETUP,
842 CPL_FRAME_LEVEL_FINAL,
843 TRUE, TRUE);
844
846
847 }
848
849 return frame;
850
851}
const cxchar * giraffe_fiberlist_query_index(const cpl_table *fibers)
Query a fiber list for the name of the fiber reference index column.
cpl_frame * giraffe_frame_create_table(GiTable *table, const cxchar *tag, cpl_frame_level level, cxbool save, cxbool update)
Create a table product frame.
Definition: giframe.c:543
void giraffe_matrix_dump(const cpl_matrix *matrix, cxint max_rows)
Output a maximum number of rows of the input matrix.
Definition: gimatrix.c:836
void gi_message(const cxchar *format,...)
Log a normal message.
Definition: gimessages.c:146
GiSlitGeometry * giraffe_slitgeometry_new(void)
Create a new GiSlitGeometry.
void giraffe_slitgeometry_resize(GiSlitGeometry *self, cxint size)
Destructive resize of a GiSlitGeometry.
void giraffe_slitgeometry_print(GiSlitGeometry *self)
Dump the the information contained in a GiSlitGeometry to output.
cxint giraffe_slitgeometry_size(GiSlitGeometry *self)
Returns current size of a GiSlitGeometry.
cpl_matrix * giraffe_slitgeometry_get(GiSlitGeometry *self, cxint pos)
Gets a reference to the matrix at a specified position.
GiSlitGeometry * giraffe_slitgeometry_duplicate(GiSlitGeometry *other)
Creates a (deep) copy of the GiSlitGeometry.
GiTable * giraffe_slitgeometry_load(const GiTable *fibers, const cxchar *filename, cxint pos, const cxchar *tag)
Load the slit geometry information for a given fiber setup.
void giraffe_slitgeometry_set(GiSlitGeometry *self, cxint pos, cpl_matrix *nm)
Sets (copies) a cpl_matrix to a specified position of the GiSlitGeometry.
GiSlitGeometry * giraffe_slitgeometry_create(GiTable *slitgeometry, cxbool subslits)
Create a slit geometry object from a slit geometry table.
void giraffe_slitgeometry_delete(GiSlitGeometry *self)
Destroy an GiSlitGeometry.
cxint giraffe_table_set(GiTable *self, cpl_table *table)
Sets the table data.
Definition: gitable.c:456
GiTable * giraffe_table_new(void)
Creates a new, empty Giraffe table.
Definition: gitable.c:85
GiTable * giraffe_table_duplicate(const GiTable *src)
Duplicate a Giraffe table.
Definition: gitable.c:176
cxint giraffe_table_load(GiTable *self, const cxchar *filename, cxint position, const cxchar *id)
Reads a data set from a file into a Giraffe table.
Definition: gitable.c:562
void giraffe_table_delete(GiTable *self)
Destroys a Giraffe table.
Definition: gitable.c:154
cpl_table * giraffe_table_get(const GiTable *self)
Get the table data from a Giraffe table.
Definition: gitable.c:433
GiInstrumentMode giraffe_get_mode(cpl_propertylist *properties)
Determines the instrument mode from a property list.
Definition: giutils.c:444
The slit geometry object definition.
cpl_matrix ** subslits

This file is part of the GIRAFFE Pipeline Reference Manual 2.19.4.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Fri Feb 6 2026 11:30:08 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2004