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 
56 inline 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++) {
151  giraffe_slitgeometry_set(clone, i,
152  giraffe_slitgeometry_get(other,i));
153  }
154 
155  }
156 
157  return clone;
158 
159 }
160 
161 
183 giraffe_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 
214  self = giraffe_slitgeometry_new();
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 
349 void
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 
387 cxint
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 
416 void
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 
463 void
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 
509 cpl_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 
540 void
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 
599 GiTable *
600 giraffe_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 
819 cpl_frame *
820 giraffe_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 
843  giraffe_table_delete(slit);
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
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_new(void)
Create a new GiSlitGeometry.
void giraffe_slitgeometry_set(GiSlitGeometry *self, cxint pos, cpl_matrix *nm)
Sets (copies) a cpl_matrix to a specified position 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.
GiSlitGeometry * giraffe_slitgeometry_duplicate(GiSlitGeometry *other)
Creates a (deep) copy 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
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
GiTable * giraffe_table_new(void)
Creates a new, empty Giraffe table.
Definition: gitable.c:85
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
GiTable * giraffe_table_duplicate(const GiTable *src)
Duplicate a Giraffe table.
Definition: gitable.c:176
GiInstrumentMode giraffe_get_mode(cpl_propertylist *properties)
Determines the instrument mode from a property list.
Definition: giutils.c:440
The slit geometry object definition.
cpl_matrix ** subslits

This file is part of the GIRAFFE Pipeline Reference Manual 2.16.10.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Thu Dec 15 2022 21:18:51 by doxygen 1.9.1 written by Dimitri van Heesch, © 1997-2004