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

This file is part of the GIRAFFE Pipeline Reference Manual 2.18.0.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Wed Jun 11 2025 18:04:57 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2004