VIRCAM Pipeline 2.3.15
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
37static 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
53static 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
69static const char *testpositive[] = {"channum",
70 "ixmin",
71 "ixmax",
72 "iymin",
73 "iymax",
74 "dcrpix1",
75 "dcrpix2"};
76
77#define NTEST1 4
78static const char *test1[] = {"dcd1_1",
79 "dcd1_2",
80 "dcd2_1",
81 "dcd2_2"};
82
83#define SZCOL 9
84
85static 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);
88static void vircam_chan_close(parquet *p);
89static int vircam_chan_testpos(cpl_table *intab, const char *column);
90static int vircam_chan_test1(cpl_table *intab, const char *column);
91static int vircam_chan_fill_lin(cpl_table *intab, int row, parquet *p);
92
107/*---------------------------------------------------------------------------*/
130/*---------------------------------------------------------------------------*/
131
132extern 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
309extern 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
384extern 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
460extern 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
496extern 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
541extern 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
587extern 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
662static 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
719static 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
753static 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
801static 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
847static 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 $
876Revision 1.12 2007/11/20 09:36:51 jim
877changed column 'qualfit' to 'lin_10000_err'
878
879Revision 1.11 2007/10/25 17:34:00 jim
880Modified to remove lint warnings
881
882Revision 1.10 2007/10/19 09:25:09 jim
883Fixed problems with missing includes
884
885Revision 1.9 2007/03/01 12:42:41 jim
886Modified slightly after code checking
887
888Revision 1.8 2006/11/10 09:26:43 jim
889Modified vircam_channel_new to copy the basic structure of a pre-existing
890template.
891
892Revision 1.7 2006/09/08 09:21:02 jim
893Added routine vircam_chantab_new
894
895Revision 1.6 2006/07/04 09:19:03 jim
896replaced all sprintf statements with snprintf
897
898Revision 1.5 2006/06/09 11:32:59 jim
899A few more minor fixes for lint
900
901Revision 1.4 2006/06/09 11:26:25 jim
902Small changes to keep lint happy
903
904Revision 1.3 2006/03/15 10:43:41 jim
905Fixed a few things
906
907Revision 1.2 2006/03/03 14:29:45 jim
908Modified definition of vir_fits and channel table
909
910Revision 1.1 2006/02/18 11:43:45 jim
911new file
912
913
914*/
cpl_table * vircam_chantab_new(int nord, cpl_table *template)
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)