VIRCAM Pipeline  2.3.10
vircam_channel.c
1 /*
2 
3 $Id: vircam_channel.c,v 1.13 2012-01-15 17:40:09 jim Exp $
4 
5 * This file is part of the VIRCAM Pipeline
6 * Copyright (C) 2015 European Southern Observatory
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 
22 */
23 
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <cpl.h>
28 
29 #include "vircam_channel.h"
30 #include "vircam_utils.h"
31 #include <casu_utils.h>
32 
33 /* Array of character values for all of the expected columns in a
34  channel table. Any other columns will be ignored */
35 
36 #define NCHANTAB_COLS 15
37 static const char *chantab_columns[] = {"channum",
38  "ixmin",
39  "ixmax",
40  "iymin",
41  "iymax",
42  "dcrpix1",
43  "dcrpix2",
44  "dcd1_1",
45  "dcd1_2",
46  "dcd2_1",
47  "dcd2_2",
48  "lin_10000",
49  "lin_10000_err",
50  "norder",
51  "coeff_1"};
52 
53 static const cpl_type chantab_types[] = {CPL_TYPE_INT,
54  CPL_TYPE_INT,
55  CPL_TYPE_INT,
56  CPL_TYPE_INT,
57  CPL_TYPE_INT,
58  CPL_TYPE_INT,
59  CPL_TYPE_INT,
60  CPL_TYPE_INT,
61  CPL_TYPE_INT,
62  CPL_TYPE_INT,
63  CPL_TYPE_INT,
64  CPL_TYPE_DOUBLE,
65  CPL_TYPE_DOUBLE,
66  CPL_TYPE_INT,
67  CPL_TYPE_DOUBLE};
68 #define NTESTPOSITIVE 7
69 static const char *testpositive[] = {"channum",
70  "ixmin",
71  "ixmax",
72  "iymin",
73  "iymax",
74  "dcrpix1",
75  "dcrpix2"};
76 
77 #define NTEST1 4
78 static const char *test1[] = {"dcd1_1",
79  "dcd1_2",
80  "dcd2_1",
81  "dcd2_2"};
82 
83 #define SZCOL 9
84 
85 static int vircam_chan_init(int channum, int ixmin, int ixmax, int iymin,
86  int iymax, int dcrpix1, int dcrpix2, int dcd1_1,
87  int dcd1_2, int dcd2_1, int dcd2_2, parquet *p);
88 static void vircam_chan_close(parquet *p);
89 static int vircam_chan_testpos(cpl_table *intab, const char *column);
90 static int vircam_chan_test1(cpl_table *intab, const char *column);
91 static int vircam_chan_fill_lin(cpl_table *intab, int row, parquet *p);
92 
107 /*---------------------------------------------------------------------------*/
130 /*---------------------------------------------------------------------------*/
131 
132 extern int vircam_chantab_verify(cpl_table *intab) {
133  int i,missing[NCHANTAB_COLS],wrongtype[NCHANTAB_COLS],ierr,norder;
134  int nrows,null,ig;
135  double *c1;
136  const char *fctid = "vircam_chantab_verify";
137  char errmsg[1024],colname[SZCOL],msg[1024];
138  const char *col;
139  cpl_array *cols;
140 
141  /* First check that you've even supplied a channel table...*/
142 
143  errmsg[0] = '\0';
144  if (intab == NULL) {
145  cpl_msg_error(fctid,"Null input channel table");
146  return(CASU_FATAL);
147  }
148 
149  /* Loop through all the expected channel table columns and see if they
150  are there... */
151 
152  ierr = 0;
153  for (i = 0; i < NCHANTAB_COLS; i++) {
154  missing[i] = 0;
155  wrongtype[i] = 0;
156  if (cpl_table_has_column(intab,chantab_columns[i]) != 1) {
157  missing[i] = 1;
158  ierr = 1;
159  } else if (cpl_table_get_column_type(intab,chantab_columns[i]) !=
160  chantab_types[i]) {
161  wrongtype[i] = 1;
162  ierr = 1;
163  }
164  }
165  if (ierr == 1) {
166  (void)strcat(errmsg,"These columns are missing or have incorrect types");
167  for (i = 0; i < NCHANTAB_COLS; i++) {
168  if (missing[i] == 1) {
169  (void)strcat(errmsg,"\n");
170  (void)strcat(errmsg,chantab_columns[i]);
171  (void)strcat(errmsg," Missing");
172  } else if (wrongtype[i] == 1) {
173  (void)strcat(errmsg,"\n");
174  (void)strcat(errmsg,chantab_columns[i]);
175  (void)strcat(errmsg," Wrong type");
176  }
177  }
178  (void)strcat(errmsg,"\n");
179  }
180 
181  /* Do a separate check for any coefficient columns to make sure they
182  are all doubles. This might lead to coeff_1 with 2 error messages,
183  but who cares...*/
184 
185  cols = cpl_table_get_column_names(intab);
186  ig = (int)cpl_array_get_size(cols);
187  for (i = 0; i < ig; i++) {
188  col = cpl_array_get_string(cols,(cpl_size)i);
189  if (! strncmp(col,"coeff_",6)) {
190  if (cpl_table_get_column_type(intab,col) != CPL_TYPE_DOUBLE) {
191  (void)sprintf(msg,"Column %s must be double\n",col);
192  (void)strcat(errmsg,msg);
193  }
194  }
195  }
196  cpl_array_delete(cols);
197 
198  /* Now do a few basic sanity tests. First check that some of the columns
199  have only positive integers */
200 
201  ierr = 0;
202  for (i = 0; i < NTESTPOSITIVE; i++) {
203  missing[i] = 0;
204  if (vircam_chan_testpos(intab,testpositive[i]) == CASU_OK)
205  continue;
206  ierr = 1;
207  missing[i] = 1;
208  }
209  if (ierr == 1) {
210  (void)strcat(errmsg,"These columns should be positive integers only:");
211  for (i = 0; i < NTESTPOSITIVE; i++) {
212  if (missing[i] == 1) {
213  (void)strcat(errmsg,"\n");
214  (void)strcat(errmsg,testpositive[i]);
215  }
216  }
217  (void)strcat(errmsg,"\n");
218  }
219 
220  /* Now check that some of the columns have only -1,0,1 as values */
221 
222  ierr = 0;
223  for (i = 0; i < NTEST1; i++) {
224  missing[i] = 0;
225  if (vircam_chan_test1(intab,test1[i]) == CASU_OK)
226  continue;
227  ierr = 1;
228  missing[i] = 1;
229  }
230  if (ierr == 1) {
231  (void)strcat(errmsg,"These columns should be integers and (-1,0,1) only:");
232  for (i = 0; i < NTEST1; i++) {
233  if (missing[i] == 1) {
234  (void)strcat(errmsg,"\n");
235  (void)strcat(errmsg,test1[i]);
236  }
237  }
238  (void)strcat(errmsg,"\n");
239  }
240 
241  /* Finally check that the order for the fit is matched by the number
242  of coefficients in the table. Also check that the first order
243  coefficient is always 1 */
244 
245  norder = cpl_table_get_int(intab,"norder",0,&null);
246  nrows = (int)cpl_table_get_nrow(intab);
247  c1 = cpl_table_get_data_double(intab,"coeff_1");
248  for (i = 0; i < nrows; i++) {
249  if (c1[i] != 1.0) {
250  (void)strcat(errmsg,"\ncoeff_1 must be all 1s!\n");
251  break;
252  }
253  }
254  for (i = 2; i <= norder; i++) {
255  missing[i] = 0;
256  (void)snprintf(colname,SZCOL,"coeff_%d",i);
257  if (cpl_table_has_column(intab,colname) != 1) {
258  missing[i] = 1;
259  ierr = 1;
260  }
261  }
262  if (ierr == 1) {
263  (void)strcat(errmsg,
264  "\nThese coefficient columns are missing from the channel table:");
265  for (i = 2; i < norder; i++) {
266  if (missing[i] == 1) {
267  (void)snprintf(colname,SZCOL,"coeff_%d",i);
268  (void)strcat(errmsg,"\n");
269  (void)strcat(errmsg,colname);
270  }
271  }
272  (void)strcat(errmsg,"\n");
273  }
274 
275  /* Right, if there are errors to be reported, then do that now */
276 
277  if (errmsg[0] != '\0') {
278  cpl_msg_error(fctid,"Errors in channel table\n%s",errmsg);
279  return(CASU_FATAL);
280  }
281 
282  /* Get out of here */
283 
284  return(CASU_OK);
285 }
286 
287 /*---------------------------------------------------------------------------*/
307 /*---------------------------------------------------------------------------*/
308 
309 extern cpl_table *vircam_chantab_new(int nord, cpl_table *template) {
310  cpl_table *tab;
311  int i,oldnorder,j,nr,null;
312  char colname[SZCOL];
313 
314  /* Create the table */
315 
316  tab = cpl_table_duplicate(template);
317 
318  /* Fix the table so that it's appropriate for the order in the
319  current fit */
320 
321  oldnorder = cpl_table_get_int(tab,"norder",0,&null);
322  if (oldnorder > nord) {
323  for (i = nord+1; i <= oldnorder; i++) {
324  (void)snprintf(colname,SZCOL,"coeff_%d",i);
325  cpl_table_erase_column(tab,colname);
326  }
327  } else if (oldnorder < nord) {
328  for (i = oldnorder+1; i <= nord; i++) {
329  (void)snprintf(colname,SZCOL,"coeff_%d",i);
330  if (cpl_table_has_column(tab,colname))
331  continue;
332  cpl_table_new_column(tab,colname,CPL_TYPE_DOUBLE);
333  }
334  }
335 
336  /* Fill in some reasonable initial values for the linearity info */
337 
338  nr = (int)cpl_table_get_nrow(tab);
339  for (i = 0; i < nr; i++) {
340  cpl_table_set_int(tab,"norder",(cpl_size)i,nord);
341  cpl_table_set_double(tab,"coeff_1",(cpl_size)i,1.0);
342  for (j = 2; j <= nord; j++) {
343  char * colname1 = cpl_sprintf("coeff_%d",j);
344  //(void)snprintf(colname,SZCOL,"coeff_%d",j);
345  cpl_table_set_double(tab,colname1,(cpl_size)i,0.0);
346  cpl_free(colname1);
347  }
348  }
349 
350  /* Get out of here */
351 
352  return(tab);
353 }
354 
355 /*---------------------------------------------------------------------------*/
382 /*---------------------------------------------------------------------------*/
383 
384 extern int vircam_chan_fill(cpl_table *tab, parquet **p, long *np) {
385  parquet *pp;
386  int i,channum,ixmin,ixmax,iymin,iymax,null;
387  int dcrpix1,dcrpix2,dcd1_1,dcd1_2,dcd2_1,dcd2_2,retval;
388 
389  /* Verify the table first */
390 
391  if (vircam_chantab_verify(tab) != CASU_OK)
392  return(CASU_FATAL);
393 
394  /* Get the number of rows in the table. This will tell you how many
395  parquet structures to allocate */
396 
397  *np = (int)cpl_table_get_nrow(tab);
398  *p = cpl_malloc(*np*sizeof(parquet));
399 
400  /* Right, start reading them in... */
401 
402  for (i = 0; i < *np; i++) {
403  pp = *p + i;
404  channum = cpl_table_get_int(tab,"channum",(cpl_size)i,&null);
405  ixmin = cpl_table_get_int(tab,"ixmin",(cpl_size)i,&null);
406  ixmax = cpl_table_get_int(tab,"ixmax",(cpl_size)i,&null);
407  iymin = cpl_table_get_int(tab,"iymin",(cpl_size)i,&null);
408  iymax = cpl_table_get_int(tab,"iymax",(cpl_size)i,&null);
409  dcrpix1 = cpl_table_get_int(tab,"dcrpix1",(cpl_size)i,&null);
410  dcrpix2 = cpl_table_get_int(tab,"dcrpix2",(cpl_size)i,&null);
411  dcd1_1 = cpl_table_get_int(tab,"dcd1_1",(cpl_size)i,&null);
412  dcd1_2 = cpl_table_get_int(tab,"dcd1_2",(cpl_size)i,&null);
413  dcd2_1 = cpl_table_get_int(tab,"dcd2_1",(cpl_size)i,&null);
414  dcd2_2 = cpl_table_get_int(tab,"dcd2_2",(cpl_size)i,&null);
415 
416  /* Right, now fill in the values */
417 
418  retval = vircam_chan_init(channum,ixmin,ixmax,iymin,iymax,dcrpix1,
419  dcrpix2,dcd1_1,dcd1_2,dcd2_1,dcd2_2,pp);
420  if (retval != CASU_OK) {
421  freespace(*p);
422  return(retval);
423  }
424 
425  /* Fill in the linearity coefficient information */
426 
427  retval = vircam_chan_fill_lin(tab,i,pp);
428  if (retval != CASU_OK) {
429  freespace(*p);
430  return(retval);
431  }
432  }
433 
434  /* Get out of here */
435 
436  return(CASU_OK);
437 }
438 
439 /*---------------------------------------------------------------------------*/
458 /*---------------------------------------------------------------------------*/
459 
460 extern void vircam_chan_free(int np, parquet **p) {
461  int i;
462 
463  /* Loop for and close each entry */
464 
465  for (i = 0; i < np; i++)
466  vircam_chan_close(*p+i);
467 
468  /* Now free the array workspace */
469 
470  freespace(*p);
471 }
472 
473 /*---------------------------------------------------------------------------*/
494 /*---------------------------------------------------------------------------*/
495 
496 extern long vircam_chan_d2r(parquet *p, long l) {
497  int lx,ly,kx,ky;
498  long k;
499 
500  /* Convert detector channel index to readout index. First cartesian
501  coords in detector coords */
502 
503  ly = (int)(l/(p->delta_i));
504  lx = l - ly*(p->delta_i);
505 
506  /* Now cartesian in readout coords */
507 
508  kx = (lx - p->Lx)*(p->dcd1_1) + (ly - p->Ly)*(p->dcd1_2);
509  ky = (lx - p->Lx)*(p->dcd2_1) + (ly - p->Ly)*(p->dcd2_2);
510 
511  /* Now the readout index */
512 
513  k = ky*(p->delta_x) + kx;
514  return(k);
515 }
516 
517 /*---------------------------------------------------------------------------*/
539 /*---------------------------------------------------------------------------*/
540 
541 extern long vircam_chan_r2d(parquet *p, long k) {
542  int lx,ly,kx,ky;
543  long l;
544 
545  /* Convert readout index to detector channel index. Do the calculation.
546  First cartesion readout coordinates */
547 
548  ky = (int)(k/(p->delta_x));
549  kx = k - ky*(p->delta_x);
550 
551  /* Now cartesian detector coords */
552 
553  lx = (kx*(p->dcd2_2) - ky*(p->dcd1_2))/(p->det_cd) + p->Lx;
554  ly = (ky*(p->dcd1_1) - kx*(p->dcd2_1))/(p->det_cd) + p->Ly;
555 
556  /* Now the detector index */
557 
558  l = ly*(p->delta_i) + lx;
559  return(l);
560 }
561 
562 /*---------------------------------------------------------------------------*/
585 /*---------------------------------------------------------------------------*/
586 
587 extern long vircam_chan_r2a(parquet *p, long naxis[2], long k) {
588  int lx,ly,kx,ky;
589  long l;
590 
591  /* Convert readout index to detector channel index. Do the calculation.
592  First cartesion readout coordinates */
593 
594  ky = (int)(k/(p->delta_x));
595  kx = k - ky*(p->delta_x);
596 
597  /* Now cartesian detector coords */
598 
599  lx = (kx*(p->dcd2_2) - ky*(p->dcd1_2))/(p->det_cd) + p->Lx + p->ixmin - 1;
600  ly = (ky*(p->dcd1_1) - kx*(p->dcd2_1))/(p->det_cd) + p->Ly + p->iymin - 1;
601 
602  /* Now the detector index */
603 
604  l = ly*naxis[0] + lx;
605  return(l);
606 }
607 
608 
609 /*---------------------------------------------------------------------------*/
659 /*---------------------------------------------------------------------------*/
660 
661 
662 static int vircam_chan_init(int channum, int ixmin, int ixmax, int iymin,
663  int iymax, int dcrpix1, int dcrpix2, int dcd1_1,
664  int dcd1_2, int dcd2_1, int dcd2_2, parquet *p) {
665 
666  /* Fill in the relevant values */
667 
668  p->channum = channum;
669  p->ixmin = ixmin;
670  p->ixmax = ixmax;
671  p->iymin = iymin;
672  p->iymax = iymax;
673  p->fpix[0] = ixmin;
674  p->fpix[1] = iymin;
675  p->lpix[0] = ixmax;
676  p->lpix[1] = iymax;
677  (void)snprintf(p->imsec,SECSIZ,"[%d:%d,%d:%d]",ixmin,ixmax,iymin,iymax);
678  p->delta_i = ixmax - ixmin + 1;
679  p->delta_j = iymax - iymin + 1;
680  if (dcrpix1 < 0 || dcrpix1 > p->delta_i ||
681  dcrpix2 < 0 || dcrpix2 > p->delta_j) {
682  cpl_msg_error("vircam_chan_init",
683  "nonsense values of dcrpix");
684  return(CASU_FATAL);
685  }
686  p->Lx = dcrpix1 - 1;
687  p->Ly = dcrpix2 - 1;
688  p->dcd1_1 = dcd1_1;
689  p->dcd1_2 = dcd1_2;
690  p->dcd2_1 = dcd2_1;
691  p->dcd2_2 = dcd2_2;
692  p->det_cd = dcd1_1*dcd2_2 - dcd1_2*dcd2_1;
693  p->delta_x = abs(dcd1_1*(p->delta_i) + dcd1_2*(p->delta_j));
694  p->delta_y = abs(dcd2_1*(p->delta_i) + dcd2_2*(p->delta_j));
695  p->data = NULL;
696  p->norder = 0;
697  p->bb = NULL;
698  return(CASU_OK);
699 }
700 
701 /*---------------------------------------------------------------------------*/
717 /*---------------------------------------------------------------------------*/
718 
719 static void vircam_chan_close(parquet *p) {
720 
721  /* Check to see if the linearity array has been allocated. If so, then
722  free the workspace. */
723 
724  freespace(p->data);
725  freespace(p->bb);
726 }
727 
728 /*---------------------------------------------------------------------------*/
751 /*---------------------------------------------------------------------------*/
752 
753 static int vircam_chan_testpos(cpl_table *intab, const char *column) {
754  int nrows,i,*idata;
755 
756  /* First check the column type */
757 
758  if (cpl_table_get_column_type(intab,column) != CPL_TYPE_INT)
759  return(CASU_FATAL);
760 
761  /* Now have a look at the actual values and see if they're all
762  positive */
763 
764  nrows = (int)cpl_table_get_nrow(intab);
765  idata = cpl_table_get_data_int(intab,column);
766  for (i = 0; i < nrows; i++)
767  if (idata[i] <= 0)
768  return(CASU_FATAL);
769 
770  /* Otherwise we're OK */
771 
772  return(CASU_OK);
773 }
774 
775 /*---------------------------------------------------------------------------*/
799 /*---------------------------------------------------------------------------*/
800 
801 static int vircam_chan_test1(cpl_table *intab, const char *column) {
802  int nrows,i,*idata;
803 
804  /* First check the column type */
805 
806  if (cpl_table_get_column_type(intab,column) != CPL_TYPE_INT)
807  return(CASU_FATAL);
808 
809  /* Now have a look at the actual values and see if they're all
810  0, 1 or -1 */
811 
812  nrows = (int)cpl_table_get_nrow(intab);
813  idata = cpl_table_get_data_int(intab,column);
814  for (i = 0; i < nrows; i++)
815  if (idata[i] != 0 && idata[i] != -1 && idata[i] != 1)
816  return(CASU_FATAL);
817 
818  /* Otherwise we're OK */
819 
820  return(CASU_OK);
821 }
822 
823 /*---------------------------------------------------------------------------*/
845 /*---------------------------------------------------------------------------*/
846 
847 static int vircam_chan_fill_lin(cpl_table *intab, int row, parquet *p) {
848  int i,null;
849 
850  /* First get the order of the fit */
851 
852  p->norder = cpl_table_get_int(intab,"norder",row,&null);
853 
854  /* Get some workspace for the coefficients */
855 
856  p->bb = cpl_malloc(p->norder*sizeof(double));
857 
858  /* Now loop for the order numbers and read off the coefficents */
859 
860  for (i = 1; i <= p->norder; i++) {
861  char * colname = cpl_sprintf("coeff_%d",i);
862  //(void)snprintf(colname,SZCOL,"coeff_%d",i);
863  p->bb[i-1] = cpl_table_get_double(intab,colname,(cpl_size)row,&null);
864  cpl_free(colname);
865  }
866  return(CASU_OK);
867 }
868 
869 
873 /*
874 
875 $Log: not supported by cvs2svn $
876 Revision 1.12 2007/11/20 09:36:51 jim
877 changed column 'qualfit' to 'lin_10000_err'
878 
879 Revision 1.11 2007/10/25 17:34:00 jim
880 Modified to remove lint warnings
881 
882 Revision 1.10 2007/10/19 09:25:09 jim
883 Fixed problems with missing includes
884 
885 Revision 1.9 2007/03/01 12:42:41 jim
886 Modified slightly after code checking
887 
888 Revision 1.8 2006/11/10 09:26:43 jim
889 Modified vircam_channel_new to copy the basic structure of a pre-existing
890 template.
891 
892 Revision 1.7 2006/09/08 09:21:02 jim
893 Added routine vircam_chantab_new
894 
895 Revision 1.6 2006/07/04 09:19:03 jim
896 replaced all sprintf statements with snprintf
897 
898 Revision 1.5 2006/06/09 11:32:59 jim
899 A few more minor fixes for lint
900 
901 Revision 1.4 2006/06/09 11:26:25 jim
902 Small changes to keep lint happy
903 
904 Revision 1.3 2006/03/15 10:43:41 jim
905 Fixed a few things
906 
907 Revision 1.2 2006/03/03 14:29:45 jim
908 Modified definition of vir_fits and channel table
909 
910 Revision 1.1 2006/02/18 11:43:45 jim
911 new file
912 
913 
914 */
long vircam_chan_d2r(parquet *p, long l)
int vircam_chantab_verify(cpl_table *intab)
long vircam_chan_r2a(parquet *p, long naxis[2], long k)
int vircam_chan_fill(cpl_table *tab, parquet **p, long *np)
void vircam_chan_free(int np, parquet **p)
long vircam_chan_r2d(parquet *p, long k)
cpl_table * vircam_chantab_new(int nord, cpl_table *template)