VIRCAM Pipeline  1.3.3
vircam_channel.c
1 /*
2 
3 $Id: vircam_channel.c,v 1.13 2012-01-15 17:40:09 jim Exp $
4 
5 */
6 
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <cpl.h>
11 
12 #include "vircam_channel.h"
13 #include "vircam_utils.h"
14 
15 /* Array of character values for all of the expected columns in a
16  channel table. Any other columns will be ignored */
17 
18 #define NCHANTAB_COLS 15
19 static const char *chantab_columns[] = {"channum",
20  "ixmin",
21  "ixmax",
22  "iymin",
23  "iymax",
24  "dcrpix1",
25  "dcrpix2",
26  "dcd1_1",
27  "dcd1_2",
28  "dcd2_1",
29  "dcd2_2",
30  "lin_10000",
31  "lin_10000_err",
32  "norder",
33  "coeff_1"};
34 
35 static const cpl_type chantab_types[] = {CPL_TYPE_INT,
36  CPL_TYPE_INT,
37  CPL_TYPE_INT,
38  CPL_TYPE_INT,
39  CPL_TYPE_INT,
40  CPL_TYPE_INT,
41  CPL_TYPE_INT,
42  CPL_TYPE_INT,
43  CPL_TYPE_INT,
44  CPL_TYPE_INT,
45  CPL_TYPE_INT,
46  CPL_TYPE_DOUBLE,
47  CPL_TYPE_DOUBLE,
48  CPL_TYPE_INT,
49  CPL_TYPE_DOUBLE};
50 #define NTESTPOSITIVE 7
51 static const char *testpositive[] = {"channum",
52  "ixmin",
53  "ixmax",
54  "iymin",
55  "iymax",
56  "dcrpix1",
57  "dcrpix2"};
58 
59 #define NTEST1 4
60 static const char *test1[] = {"dcd1_1",
61  "dcd1_2",
62  "dcd2_1",
63  "dcd2_2"};
64 
65 #define SZCOL 9
66 
67 static int vircam_chan_init(int channum, int ixmin, int ixmax, int iymin,
68  int iymax, int dcrpix1, int dcrpix2, int dcd1_1,
69  int dcd1_2, int dcd2_1, int dcd2_2, parquet *p);
70 static void vircam_chan_close(parquet *p);
71 static int vircam_chan_testpos(cpl_table *intab, const char *column);
72 static int vircam_chan_test1(cpl_table *intab, const char *column);
73 static int vircam_chan_fill_lin(cpl_table *intab, int row, parquet *p);
74 
89 /*---------------------------------------------------------------------------*/
112 /*---------------------------------------------------------------------------*/
113 
114 extern int vircam_chantab_verify(cpl_table *intab) {
115  int i,missing[NCHANTAB_COLS],wrongtype[NCHANTAB_COLS],ierr,norder;
116  int nrows,null;
117  double *c1;
118  const char *fctid = "vircam_chantab_verify";
119  char errmsg[1024],colname[SZCOL],msg[1024];
120  const char *col;
121 
122  /* First check that you've even supplied a channel table...*/
123 
124  errmsg[0] = '\0';
125  if (intab == NULL) {
126  cpl_msg_error(fctid,"Null input channel table");
127  return(VIR_FATAL);
128  }
129 
130  /* Loop through all the expected channel table columns and see if they
131  are there... */
132 
133  ierr = 0;
134  for (i = 0; i < NCHANTAB_COLS; i++) {
135  missing[i] = 0;
136  wrongtype[i] = 0;
137  if (cpl_table_has_column(intab,chantab_columns[i]) != 1) {
138  missing[i] = 1;
139  ierr = 1;
140  } else if (cpl_table_get_column_type(intab,chantab_columns[i]) !=
141  chantab_types[i]) {
142  wrongtype[i] = 1;
143  ierr = 1;
144  }
145  }
146  if (ierr == 1) {
147  (void)strcat(errmsg,"These columns are missing or have incorrect types");
148  for (i = 0; i < NCHANTAB_COLS; i++) {
149  if (missing[i] == 1) {
150  (void)strcat(errmsg,"\n");
151  (void)strcat(errmsg,chantab_columns[i]);
152  (void)strcat(errmsg," Missing");
153  } else if (wrongtype[i] == 1) {
154  (void)strcat(errmsg,"\n");
155  (void)strcat(errmsg,chantab_columns[i]);
156  (void)strcat(errmsg," Wrong type");
157  }
158  }
159  (void)strcat(errmsg,"\n");
160  }
161 
162  /* Do a separate check for any coefficient columns to make sure they
163  are all doubles. This might lead to coeff_1 with 2 error messages,
164  but who cares...*/
165 
166  col = cpl_table_get_column_name(intab);
167  while (col != NULL) {
168  if (! strncmp(col,"coeff_",6)) {
169  if (cpl_table_get_column_type(intab,col) != CPL_TYPE_DOUBLE) {
170  (void)sprintf(msg,"Column %s must be double\n",col);
171  (void)strcat(errmsg,msg);
172  }
173  }
174  col = cpl_table_get_column_name(NULL);
175  }
176 
177  /* Now do a few basic sanity tests. First check that some of the columns
178  have only positive integers */
179 
180  ierr = 0;
181  for (i = 0; i < NTESTPOSITIVE; i++) {
182  missing[i] = 0;
183  if (vircam_chan_testpos(intab,testpositive[i]) == VIR_OK)
184  continue;
185  ierr = 1;
186  missing[i] = 1;
187  }
188  if (ierr == 1) {
189  (void)strcat(errmsg,"These columns should be positive integers only:");
190  for (i = 0; i < NTESTPOSITIVE; i++) {
191  if (missing[i] == 1) {
192  (void)strcat(errmsg,"\n");
193  (void)strcat(errmsg,testpositive[i]);
194  }
195  }
196  (void)strcat(errmsg,"\n");
197  }
198 
199  /* Now check that some of the columns have only -1,0,1 as values */
200 
201  ierr = 0;
202  for (i = 0; i < NTEST1; i++) {
203  missing[i] = 0;
204  if (vircam_chan_test1(intab,test1[i]) == VIR_OK)
205  continue;
206  ierr = 1;
207  missing[i] = 1;
208  }
209  if (ierr == 1) {
210  (void)strcat(errmsg,"These columns should be integers and (-1,0,1) only:");
211  for (i = 0; i < NTEST1; i++) {
212  if (missing[i] == 1) {
213  (void)strcat(errmsg,"\n");
214  (void)strcat(errmsg,test1[i]);
215  }
216  }
217  (void)strcat(errmsg,"\n");
218  }
219 
220  /* Finally check that the order for the fit is matched by the number
221  of coefficients in the table. Also check that the first order
222  coefficient is always 1 */
223 
224  norder = cpl_table_get_int(intab,"norder",0,&null);
225  nrows = (int)cpl_table_get_nrow(intab);
226  c1 = cpl_table_get_data_double(intab,"coeff_1");
227  for (i = 0; i < nrows; i++) {
228  if (c1[i] != 1.0) {
229  (void)strcat(errmsg,"\ncoeff_1 must be all 1s!\n");
230  break;
231  }
232  }
233  for (i = 2; i <= norder; i++) {
234  missing[i] = 0;
235  (void)snprintf(colname,SZCOL,"coeff_%d",i);
236  if (cpl_table_has_column(intab,colname) != 1) {
237  missing[i] = 1;
238  ierr = 1;
239  }
240  }
241  if (ierr == 1) {
242  (void)strcat(errmsg,
243  "\nThese coefficient columns are missing from the channel table:");
244  for (i = 2; i < norder; i++) {
245  if (missing[i] == 1) {
246  (void)snprintf(colname,SZCOL,"coeff_%d",i);
247  (void)strcat(errmsg,"\n");
248  (void)strcat(errmsg,colname);
249  }
250  }
251  (void)strcat(errmsg,"\n");
252  }
253 
254  /* Right, if there are errors to be reported, then do that now */
255 
256  if (errmsg[0] != '\0') {
257  cpl_msg_error(fctid,"Errors in channel table\n%s",errmsg);
258  return(VIR_FATAL);
259  }
260 
261  /* Get out of here */
262 
263  return(VIR_OK);
264 }
265 
266 /*---------------------------------------------------------------------------*/
286 /*---------------------------------------------------------------------------*/
287 
288 extern cpl_table *vircam_chantab_new(int nord, cpl_table *template) {
289  cpl_table *tab;
290  int i,oldnorder,j,nr,null;
291  char colname[SZCOL];
292 
293  /* Create the table */
294 
295  tab = cpl_table_duplicate(template);
296 
297  /* Fix the table so that it's appropriate for the order in the
298  current fit */
299 
300  oldnorder = cpl_table_get_int(tab,"norder",0,&null);
301  if (oldnorder > nord) {
302  for (i = nord+1; i <= oldnorder; i++) {
303  (void)snprintf(colname,SZCOL,"coeff_%d",i);
304  cpl_table_erase_column(tab,colname);
305  }
306  } else if (oldnorder < nord) {
307  for (i = oldnorder+1; i <= nord; i++) {
308  (void)snprintf(colname,SZCOL,"coeff_%d",i);
309  if (cpl_table_has_column(tab,colname))
310  continue;
311  cpl_table_new_column(tab,colname,CPL_TYPE_DOUBLE);
312  }
313  }
314 
315  /* Fill in some reasonable initial values for the linearity info */
316 
317  nr = (int)cpl_table_get_nrow(tab);
318  for (i = 0; i < nr; i++) {
319  cpl_table_set_int(tab,"norder",(cpl_size)i,nord);
320  cpl_table_set_double(tab,"coeff_1",(cpl_size)i,1.0);
321  for (j = 2; j <= nord; j++) {
322  (void)snprintf(colname,SZCOL,"coeff_%d",j);
323  cpl_table_set_double(tab,colname,(cpl_size)i,0.0);
324  }
325  }
326 
327  /* Get out of here */
328 
329  return(tab);
330 }
331 
332 /*---------------------------------------------------------------------------*/
359 /*---------------------------------------------------------------------------*/
360 
361 extern int vircam_chan_fill(cpl_table *tab, parquet **p, long *np) {
362  parquet *pp;
363  int i,channum,ixmin,ixmax,iymin,iymax,null;
364  int dcrpix1,dcrpix2,dcd1_1,dcd1_2,dcd2_1,dcd2_2,retval;
365 
366  /* Verify the table first */
367 
368  if (vircam_chantab_verify(tab) != VIR_OK)
369  return(VIR_FATAL);
370 
371  /* Get the number of rows in the table. This will tell you how many
372  parquet structures to allocate */
373 
374  *np = (int)cpl_table_get_nrow(tab);
375  *p = cpl_malloc(*np*sizeof(parquet));
376 
377  /* Right, start reading them in... */
378 
379  for (i = 0; i < *np; i++) {
380  pp = *p + i;
381  channum = cpl_table_get_int(tab,"channum",(cpl_size)i,&null);
382  ixmin = cpl_table_get_int(tab,"ixmin",(cpl_size)i,&null);
383  ixmax = cpl_table_get_int(tab,"ixmax",(cpl_size)i,&null);
384  iymin = cpl_table_get_int(tab,"iymin",(cpl_size)i,&null);
385  iymax = cpl_table_get_int(tab,"iymax",(cpl_size)i,&null);
386  dcrpix1 = cpl_table_get_int(tab,"dcrpix1",(cpl_size)i,&null);
387  dcrpix2 = cpl_table_get_int(tab,"dcrpix2",(cpl_size)i,&null);
388  dcd1_1 = cpl_table_get_int(tab,"dcd1_1",(cpl_size)i,&null);
389  dcd1_2 = cpl_table_get_int(tab,"dcd1_2",(cpl_size)i,&null);
390  dcd2_1 = cpl_table_get_int(tab,"dcd2_1",(cpl_size)i,&null);
391  dcd2_2 = cpl_table_get_int(tab,"dcd2_2",(cpl_size)i,&null);
392 
393  /* Right, now fill in the values */
394 
395  retval = vircam_chan_init(channum,ixmin,ixmax,iymin,iymax,dcrpix1,
396  dcrpix2,dcd1_1,dcd1_2,dcd2_1,dcd2_2,pp);
397  if (retval != VIR_OK) {
398  freespace(*p);
399  return(retval);
400  }
401 
402  /* Fill in the linearity coefficient information */
403 
404  retval = vircam_chan_fill_lin(tab,i,pp);
405  if (retval != VIR_OK) {
406  freespace(*p);
407  return(retval);
408  }
409  }
410 
411  /* Get out of here */
412 
413  return(VIR_OK);
414 }
415 
416 /*---------------------------------------------------------------------------*/
435 /*---------------------------------------------------------------------------*/
436 
437 extern void vircam_chan_free(int np, parquet **p) {
438  int i;
439 
440  /* Loop for and close each entry */
441 
442  for (i = 0; i < np; i++)
443  vircam_chan_close(*p+i);
444 
445  /* Now free the array workspace */
446 
447  freespace(*p);
448 }
449 
450 /*---------------------------------------------------------------------------*/
471 /*---------------------------------------------------------------------------*/
472 
473 extern long vircam_chan_d2r(parquet *p, long l) {
474  int lx,ly,kx,ky;
475  long k;
476 
477  /* Convert detector channel index to readout index. First cartesian
478  coords in detector coords */
479 
480  ly = (int)(l/(p->delta_i));
481  lx = l - ly*(p->delta_i);
482 
483  /* Now cartesian in readout coords */
484 
485  kx = (lx - p->Lx)*(p->dcd1_1) + (ly - p->Ly)*(p->dcd1_2);
486  ky = (lx - p->Lx)*(p->dcd2_1) + (ly - p->Ly)*(p->dcd2_2);
487 
488  /* Now the readout index */
489 
490  k = ky*(p->delta_x) + kx;
491  return(k);
492 }
493 
494 /*---------------------------------------------------------------------------*/
516 /*---------------------------------------------------------------------------*/
517 
518 extern long vircam_chan_r2d(parquet *p, long k) {
519  int lx,ly,kx,ky;
520  long l;
521 
522  /* Convert readout index to detector channel index. Do the calculation.
523  First cartesion readout coordinates */
524 
525  ky = (int)(k/(p->delta_x));
526  kx = k - ky*(p->delta_x);
527 
528  /* Now cartesian detector coords */
529 
530  lx = (kx*(p->dcd2_2) - ky*(p->dcd1_2))/(p->det_cd) + p->Lx;
531  ly = (ky*(p->dcd1_1) - kx*(p->dcd2_1))/(p->det_cd) + p->Ly;
532 
533  /* Now the detector index */
534 
535  l = ly*(p->delta_i) + lx;
536  return(l);
537 }
538 
539 /*---------------------------------------------------------------------------*/
562 /*---------------------------------------------------------------------------*/
563 
564 extern long vircam_chan_r2a(parquet *p, long naxis[2], long k) {
565  int lx,ly,kx,ky;
566  long l;
567 
568  /* Convert readout index to detector channel index. Do the calculation.
569  First cartesion readout coordinates */
570 
571  ky = (int)(k/(p->delta_x));
572  kx = k - ky*(p->delta_x);
573 
574  /* Now cartesian detector coords */
575 
576  lx = (kx*(p->dcd2_2) - ky*(p->dcd1_2))/(p->det_cd) + p->Lx + p->ixmin - 1;
577  ly = (ky*(p->dcd1_1) - kx*(p->dcd2_1))/(p->det_cd) + p->Ly + p->iymin - 1;
578 
579  /* Now the detector index */
580 
581  l = ly*naxis[0] + lx;
582  return(l);
583 }
584 
585 
586 /*---------------------------------------------------------------------------*/
636 /*---------------------------------------------------------------------------*/
637 
638 
639 static int vircam_chan_init(int channum, int ixmin, int ixmax, int iymin,
640  int iymax, int dcrpix1, int dcrpix2, int dcd1_1,
641  int dcd1_2, int dcd2_1, int dcd2_2, parquet *p) {
642 
643  /* Fill in the relevant values */
644 
645  p->channum = channum;
646  p->ixmin = ixmin;
647  p->ixmax = ixmax;
648  p->iymin = iymin;
649  p->iymax = iymax;
650  p->fpix[0] = ixmin;
651  p->fpix[1] = iymin;
652  p->lpix[0] = ixmax;
653  p->lpix[1] = iymax;
654  (void)snprintf(p->imsec,SECSIZ,"[%d:%d,%d:%d]",ixmin,ixmax,iymin,iymax);
655  p->delta_i = ixmax - ixmin + 1;
656  p->delta_j = iymax - iymin + 1;
657  if (dcrpix1 < 0 || dcrpix1 > p->delta_i ||
658  dcrpix2 < 0 || dcrpix2 > p->delta_j) {
659  cpl_msg_error("vircam_chan_init",
660  "nonsense values of dcrpix");
661  return(VIR_FATAL);
662  }
663  p->Lx = dcrpix1 - 1;
664  p->Ly = dcrpix2 - 1;
665  p->dcd1_1 = dcd1_1;
666  p->dcd1_2 = dcd1_2;
667  p->dcd2_1 = dcd2_1;
668  p->dcd2_2 = dcd2_2;
669  p->det_cd = dcd1_1*dcd2_2 - dcd1_2*dcd2_1;
670  p->delta_x = abs(dcd1_1*(p->delta_i) + dcd1_2*(p->delta_j));
671  p->delta_y = abs(dcd2_1*(p->delta_i) + dcd2_2*(p->delta_j));
672  p->data = NULL;
673  p->norder = 0;
674  p->bb = NULL;
675  return(VIR_OK);
676 }
677 
678 /*---------------------------------------------------------------------------*/
694 /*---------------------------------------------------------------------------*/
695 
696 static void vircam_chan_close(parquet *p) {
697 
698  /* Check to see if the linearity array has been allocated. If so, then
699  free the workspace. */
700 
701  freespace(p->data);
702  freespace(p->bb);
703 }
704 
705 /*---------------------------------------------------------------------------*/
728 /*---------------------------------------------------------------------------*/
729 
730 static int vircam_chan_testpos(cpl_table *intab, const char *column) {
731  int nrows,i,*idata;
732 
733  /* First check the column type */
734 
735  if (cpl_table_get_column_type(intab,column) != CPL_TYPE_INT)
736  return(VIR_FATAL);
737 
738  /* Now have a look at the actual values and see if they're all
739  positive */
740 
741  nrows = (int)cpl_table_get_nrow(intab);
742  idata = cpl_table_get_data_int(intab,column);
743  for (i = 0; i < nrows; i++)
744  if (idata[i] <= 0)
745  return(VIR_FATAL);
746 
747  /* Otherwise we're OK */
748 
749  return(VIR_OK);
750 }
751 
752 /*---------------------------------------------------------------------------*/
776 /*---------------------------------------------------------------------------*/
777 
778 static int vircam_chan_test1(cpl_table *intab, const char *column) {
779  int nrows,i,*idata;
780 
781  /* First check the column type */
782 
783  if (cpl_table_get_column_type(intab,column) != CPL_TYPE_INT)
784  return(VIR_FATAL);
785 
786  /* Now have a look at the actual values and see if they're all
787  0, 1 or -1 */
788 
789  nrows = (int)cpl_table_get_nrow(intab);
790  idata = cpl_table_get_data_int(intab,column);
791  for (i = 0; i < nrows; i++)
792  if (idata[i] != 0 && idata[i] != -1 && idata[i] != 1)
793  return(VIR_FATAL);
794 
795  /* Otherwise we're OK */
796 
797  return(VIR_OK);
798 }
799 
800 /*---------------------------------------------------------------------------*/
822 /*---------------------------------------------------------------------------*/
823 
824 static int vircam_chan_fill_lin(cpl_table *intab, int row, parquet *p) {
825  int i,null;
826  char colname[SZCOL];
827 
828  /* First get the order of the fit */
829 
830  p->norder = cpl_table_get_int(intab,"norder",row,&null);
831 
832  /* Get some workspace for the coefficients */
833 
834  p->bb = cpl_malloc(p->norder*sizeof(double));
835 
836  /* Now loop for the order numbers and read off the coefficents */
837 
838  for (i = 1; i <= p->norder; i++) {
839  (void)snprintf(colname,SZCOL,"coeff_%d",i);
840  p->bb[i-1] = cpl_table_get_double(intab,colname,(cpl_size)row,&null);
841  }
842  return(VIR_OK);
843 }
844 
845 
849 /*
850 
851 $Log: not supported by cvs2svn $
852 Revision 1.12 2007/11/20 09:36:51 jim
853 changed column 'qualfit' to 'lin_10000_err'
854 
855 Revision 1.11 2007/10/25 17:34:00 jim
856 Modified to remove lint warnings
857 
858 Revision 1.10 2007/10/19 09:25:09 jim
859 Fixed problems with missing includes
860 
861 Revision 1.9 2007/03/01 12:42:41 jim
862 Modified slightly after code checking
863 
864 Revision 1.8 2006/11/10 09:26:43 jim
865 Modified vircam_channel_new to copy the basic structure of a pre-existing
866 template.
867 
868 Revision 1.7 2006/09/08 09:21:02 jim
869 Added routine vircam_chantab_new
870 
871 Revision 1.6 2006/07/04 09:19:03 jim
872 replaced all sprintf statements with snprintf
873 
874 Revision 1.5 2006/06/09 11:32:59 jim
875 A few more minor fixes for lint
876 
877 Revision 1.4 2006/06/09 11:26:25 jim
878 Small changes to keep lint happy
879 
880 Revision 1.3 2006/03/15 10:43:41 jim
881 Fixed a few things
882 
883 Revision 1.2 2006/03/03 14:29:45 jim
884 Modified definition of vir_fits and channel table
885 
886 Revision 1.1 2006/02/18 11:43:45 jim
887 new file
888 
889 
890 */