vircam_channel.c

00001 /*
00002 
00003 $Id: vircam_channel.c,v 1.12 2007/11/20 09:36:51 jim Exp $
00004 
00005 */
00006 
00007 #include <stdlib.h>
00008 #include <stdio.h>
00009 #include <string.h>
00010 #include <cpl.h>
00011 
00012 #include "vircam_channel.h"
00013 #include "vircam_utils.h"
00014 
00015 /* Array of character values for all of the expected columns in a 
00016    channel table. Any other columns will be ignored */
00017 
00018 #define NCHANTAB_COLS 15
00019 static const char *chantab_columns[] = {"channum",
00020                                         "ixmin",
00021                                         "ixmax",
00022                                         "iymin",
00023                                         "iymax",
00024                                         "dcrpix1",
00025                                         "dcrpix2",
00026                                         "dcd1_1",
00027                                         "dcd1_2",
00028                                         "dcd2_1",
00029                                         "dcd2_2",
00030                                         "lin_10000",
00031                                         "lin_10000_err",
00032                                         "norder",
00033                                         "coeff_1"};
00034 
00035 static const cpl_type chantab_types[] = {CPL_TYPE_INT,
00036                                          CPL_TYPE_INT,
00037                                          CPL_TYPE_INT,
00038                                          CPL_TYPE_INT,
00039                                          CPL_TYPE_INT,
00040                                          CPL_TYPE_INT,
00041                                          CPL_TYPE_INT,
00042                                          CPL_TYPE_INT,
00043                                          CPL_TYPE_INT,
00044                                          CPL_TYPE_INT,
00045                                          CPL_TYPE_INT,
00046                                          CPL_TYPE_DOUBLE,
00047                                          CPL_TYPE_DOUBLE,
00048                                          CPL_TYPE_INT,
00049                                          CPL_TYPE_DOUBLE};
00050 #define NTESTPOSITIVE 7
00051 static const char *testpositive[] = {"channum",
00052                                      "ixmin",
00053                                      "ixmax",
00054                                      "iymin",
00055                                      "iymax",
00056                                      "dcrpix1",
00057                                      "dcrpix2"};
00058 
00059 #define NTEST1 4
00060 static const char *test1[] = {"dcd1_1",
00061                               "dcd1_2",
00062                               "dcd2_1",
00063                               "dcd2_2"};
00064 
00065 #define SZCOL 9
00066 
00067 static int vircam_chan_init(int channum, int ixmin, int ixmax, int iymin,
00068                             int iymax, int dcrpix1, int dcrpix2, int dcd1_1,
00069                             int dcd1_2, int dcd2_1, int dcd2_2, parquet *p);
00070 static void vircam_chan_close(parquet *p);
00071 static int vircam_chan_testpos(cpl_table *intab, const char *column);
00072 static int vircam_chan_test1(cpl_table *intab, const char *column);
00073 static int vircam_chan_fill_lin(cpl_table *intab, int row, parquet *p);
00074 
00089 /*---------------------------------------------------------------------------*/
00112 /*---------------------------------------------------------------------------*/
00113 
00114 extern int vircam_chantab_verify(cpl_table *intab) {
00115     int i,missing[NCHANTAB_COLS],wrongtype[NCHANTAB_COLS],ierr,norder;
00116     int nrows,null;
00117     double *c1;
00118     const char *fctid = "vircam_chantab_verify";
00119     char errmsg[1024],colname[SZCOL],msg[1024];
00120     const char *col;
00121 
00122     /* First check that you've even supplied a channel table...*/
00123 
00124     errmsg[0] = '\0';
00125     if (intab == NULL) {
00126         cpl_msg_error(fctid,"Null input channel table");
00127         return(VIR_FATAL);
00128     }
00129 
00130     /* Loop through all the expected channel table columns and see if they
00131        are there... */
00132 
00133     ierr = 0;
00134     for (i = 0; i < NCHANTAB_COLS; i++) {
00135         missing[i] = 0;
00136         wrongtype[i] = 0;
00137         if (cpl_table_has_column(intab,chantab_columns[i]) != 1) {
00138             missing[i] = 1;
00139             ierr = 1;
00140         } else if (cpl_table_get_column_type(intab,chantab_columns[i]) !=
00141                    chantab_types[i]) {
00142             wrongtype[i] = 1;
00143             ierr = 1;
00144         }
00145     }
00146     if (ierr == 1) {
00147         (void)strcat(errmsg,"These columns are missing or have incorrect types");
00148         for (i = 0; i < NCHANTAB_COLS; i++) {
00149             if (missing[i] == 1) {
00150                 (void)strcat(errmsg,"\n");
00151                 (void)strcat(errmsg,chantab_columns[i]);
00152                 (void)strcat(errmsg," Missing");
00153             } else if (wrongtype[i] == 1) {
00154                 (void)strcat(errmsg,"\n");
00155                 (void)strcat(errmsg,chantab_columns[i]);
00156                 (void)strcat(errmsg," Wrong type");
00157             }
00158         }
00159         (void)strcat(errmsg,"\n");
00160     }
00161 
00162     /* Do a separate check for any coefficient columns to make sure they
00163        are all doubles. This might lead to coeff_1 with 2 error messages,
00164        but who cares...*/
00165 
00166     col = cpl_table_get_column_name(intab);
00167     while (col != NULL) {
00168         if (! strncmp(col,"coeff_",6)) {
00169             if (cpl_table_get_column_type(intab,col) != CPL_TYPE_DOUBLE) {
00170                 (void)sprintf(msg,"Column %s must be double\n",col);
00171                 (void)strcat(errmsg,msg);
00172             }
00173         }
00174         col = cpl_table_get_column_name(NULL);
00175     }
00176 
00177     /* Now do a few basic sanity tests. First check that some of the columns
00178        have only positive integers */
00179 
00180     ierr = 0;
00181     for (i = 0; i < NTESTPOSITIVE; i++) {
00182         missing[i] = 0;
00183         if (vircam_chan_testpos(intab,testpositive[i]) == VIR_OK)
00184             continue;
00185         ierr = 1;
00186         missing[i] = 1;
00187     }
00188     if (ierr == 1) {
00189         (void)strcat(errmsg,"These columns should be positive integers only:");
00190         for (i = 0; i < NTESTPOSITIVE; i++) {
00191             if (missing[i] == 1) {
00192                 (void)strcat(errmsg,"\n");
00193                 (void)strcat(errmsg,testpositive[i]);
00194             }
00195         }
00196         (void)strcat(errmsg,"\n");
00197     }
00198 
00199     /* Now check that some of the columns have only -1,0,1 as values */
00200 
00201     ierr = 0;
00202     for (i = 0; i < NTEST1; i++) {
00203         missing[i] = 0;
00204         if (vircam_chan_test1(intab,test1[i]) == VIR_OK)
00205             continue;
00206         ierr = 1;
00207         missing[i] = 1;
00208     }
00209     if (ierr == 1) {
00210         (void)strcat(errmsg,"These columns should be integers and (-1,0,1) only:");
00211         for (i = 0; i < NTEST1; i++) {
00212             if (missing[i] == 1) {
00213                 (void)strcat(errmsg,"\n");
00214                 (void)strcat(errmsg,test1[i]);
00215             }
00216         }
00217         (void)strcat(errmsg,"\n");
00218     }
00219 
00220     /* Finally check that the order for the fit is matched by the number
00221        of coefficients in the table. Also check that the first order 
00222        coefficient is always 1 */
00223 
00224     norder = cpl_table_get_int(intab,"norder",0,&null);
00225     nrows = cpl_table_get_nrow(intab);
00226     c1 = cpl_table_get_data_double(intab,"coeff_1");
00227     for (i = 0; i < nrows; i++) {
00228         if (c1[i] != 1.0) {
00229             (void)strcat(errmsg,"\ncoeff_1 must be all 1s!\n");
00230             break;
00231         }
00232     }
00233     for (i = 2; i <= norder; i++) {
00234         missing[i] = 0;
00235         (void)snprintf(colname,SZCOL,"coeff_%d",i);
00236         if (cpl_table_has_column(intab,colname) != 1) {
00237             missing[i] = 1;
00238             ierr = 1;
00239         }
00240     }
00241     if (ierr == 1) {
00242         (void)strcat(errmsg,
00243                "\nThese coefficient columns are missing from the channel table:");
00244         for (i = 2; i < norder; i++) {
00245             if (missing[i] == 1) {
00246                 (void)snprintf(colname,SZCOL,"coeff_%d",i);
00247                 (void)strcat(errmsg,"\n");
00248                 (void)strcat(errmsg,colname);
00249             }
00250         }
00251         (void)strcat(errmsg,"\n");
00252     }
00253 
00254     /* Right, if there are errors to be reported, then do that now */
00255 
00256     if (errmsg[0] != '\0') {
00257         cpl_msg_error(fctid,"Errors in channel table\n%s",errmsg);
00258         return(VIR_FATAL);
00259     }
00260 
00261     /* Get out of here */
00262 
00263     return(VIR_OK);
00264 }
00265 
00266 /*---------------------------------------------------------------------------*/
00286 /*---------------------------------------------------------------------------*/
00287 
00288 extern cpl_table *vircam_chantab_new(int nord, cpl_table *template) {
00289     cpl_table *tab;
00290     int i,oldnorder,null,j,nr;
00291     char colname[SZCOL];
00292 
00293     /* Create the table */
00294 
00295     tab = cpl_table_duplicate(template);
00296 
00297     /* Fix the table so that it's appropriate for the order in the 
00298        current fit */
00299 
00300     oldnorder = cpl_table_get_int(tab,"norder",0,&null);
00301     if (oldnorder > nord) {
00302         for (i = nord+1; i <= oldnorder; i++) {
00303             (void)snprintf(colname,SZCOL,"coeff_%d",i);
00304             cpl_table_erase_column(tab,colname);
00305         }
00306     } else if (oldnorder < nord) {
00307         for (i = oldnorder+1; i <= nord; i++) {
00308             (void)snprintf(colname,SZCOL,"coeff_%d",i);
00309             if (cpl_table_has_column(tab,colname)) 
00310                 continue;
00311             cpl_table_new_column(tab,colname,CPL_TYPE_DOUBLE);
00312         }
00313     }
00314     
00315     /* Fill in some reasonable initial values for the linearity info */
00316 
00317     nr = cpl_table_get_nrow(tab);
00318     for (i = 0; i < nr; i++) {
00319         cpl_table_set_int(tab,"norder",i,nord);
00320         cpl_table_set_double(tab,"coeff_1",i,1.0);
00321         for (j = 2; j <= nord; j++) {
00322             (void)snprintf(colname,SZCOL,"coeff_%d",j);
00323             cpl_table_set_double(tab,colname,i,0.0);
00324         }
00325     }
00326 
00327     /* Get out of here */
00328 
00329     return(tab);
00330 }
00331 
00332 /*---------------------------------------------------------------------------*/
00359 /*---------------------------------------------------------------------------*/
00360 
00361 extern int vircam_chan_fill(cpl_table *tab, parquet **p, long *np) {
00362     parquet *pp;
00363     int i,channum,ixmin,ixmax,iymin,iymax;
00364     int dcrpix1,dcrpix2,dcd1_1,dcd1_2,dcd2_1,dcd2_2,retval,null;
00365 
00366     /* Verify the table first */
00367 
00368     if (vircam_chantab_verify(tab) != VIR_OK)
00369         return(VIR_FATAL);
00370 
00371     /* Get the number of rows in the table. This will tell you how many 
00372        parquet structures to allocate */
00373 
00374     *np = cpl_table_get_nrow(tab);
00375     *p = cpl_malloc(*np*sizeof(parquet));
00376 
00377     /* Right, start reading them in... */
00378 
00379     for (i = 0; i < *np; i++) {
00380         pp = *p + i;
00381         channum = cpl_table_get_int(tab,"channum",i,&null);
00382         ixmin = cpl_table_get_int(tab,"ixmin",i,&null);
00383         ixmax = cpl_table_get_int(tab,"ixmax",i,&null);
00384         iymin = cpl_table_get_int(tab,"iymin",i,&null);
00385         iymax = cpl_table_get_int(tab,"iymax",i,&null);
00386         dcrpix1 = cpl_table_get_int(tab,"dcrpix1",i,&null);
00387         dcrpix2 = cpl_table_get_int(tab,"dcrpix2",i,&null);
00388         dcd1_1 = cpl_table_get_int(tab,"dcd1_1",i,&null);
00389         dcd1_2 = cpl_table_get_int(tab,"dcd1_2",i,&null);
00390         dcd2_1 = cpl_table_get_int(tab,"dcd2_1",i,&null);
00391         dcd2_2 = cpl_table_get_int(tab,"dcd2_2",i,&null);
00392             
00393         /* Right, now fill in the values */
00394 
00395         retval = vircam_chan_init(channum,ixmin,ixmax,iymin,iymax,dcrpix1,
00396                                   dcrpix2,dcd1_1,dcd1_2,dcd2_1,dcd2_2,pp);
00397         if (retval != VIR_OK) {
00398             freespace(*p);
00399             return(retval);
00400         }
00401 
00402         /* Fill in the linearity coefficient information */
00403 
00404         retval = vircam_chan_fill_lin(tab,i,pp);
00405         if (retval != VIR_OK) {
00406             freespace(*p);
00407             return(retval);
00408         }
00409     }
00410 
00411     /* Get out of here */
00412 
00413     return(VIR_OK);
00414 }
00415 
00416 /*---------------------------------------------------------------------------*/
00435 /*---------------------------------------------------------------------------*/
00436 
00437 extern void vircam_chan_free(int np, parquet **p) {
00438     int i;
00439 
00440     /* Loop for and close each entry */
00441 
00442     for (i = 0; i < np; i++)
00443         vircam_chan_close(*p+i);
00444 
00445     /* Now free the array workspace */
00446 
00447     freespace(*p);
00448 }
00449 
00450 /*---------------------------------------------------------------------------*/
00471 /*---------------------------------------------------------------------------*/
00472 
00473 extern long vircam_chan_d2r(parquet *p, long l) {
00474     int lx,ly,kx,ky;
00475     long k;
00476 
00477     /* Convert detector channel index to readout index. First cartesian 
00478        coords in detector coords */
00479 
00480     ly = (int)(l/(p->delta_i));
00481     lx = l - ly*(p->delta_i);
00482 
00483     /* Now cartesian in readout coords */
00484 
00485     kx = (lx - p->Lx)*(p->dcd1_1) + (ly - p->Ly)*(p->dcd1_2);
00486     ky = (lx - p->Lx)*(p->dcd2_1) + (ly - p->Ly)*(p->dcd2_2);
00487 
00488     /* Now the readout index */
00489 
00490     k = ky*(p->delta_x) + kx;
00491     return(k);
00492 }
00493 
00494 /*---------------------------------------------------------------------------*/
00516 /*---------------------------------------------------------------------------*/
00517 
00518 extern long vircam_chan_r2d(parquet *p, long k) {
00519     int lx,ly,kx,ky;
00520     long l;
00521 
00522     /* Convert readout index to detector channel index. Do the calculation. 
00523        First cartesion readout coordinates */
00524 
00525     ky = (int)(k/(p->delta_x));
00526     kx = k - ky*(p->delta_x);
00527 
00528     /* Now cartesian detector coords */
00529 
00530     lx = (kx*(p->dcd2_2) - ky*(p->dcd1_2))/(p->det_cd) + p->Lx;
00531     ly = (ky*(p->dcd1_1) - kx*(p->dcd2_1))/(p->det_cd) + p->Ly;
00532 
00533     /* Now the detector index */
00534     
00535     l = ly*(p->delta_i) + lx;
00536     return(l);
00537 }
00538 
00539 /*---------------------------------------------------------------------------*/
00562 /*---------------------------------------------------------------------------*/
00563 
00564 extern long vircam_chan_r2a(parquet *p, long naxis[2], long k) {
00565     int lx,ly,kx,ky;
00566     long l;
00567 
00568     /* Convert readout index to detector channel index. Do the calculation. 
00569        First cartesion readout coordinates */
00570 
00571     ky = (int)(k/(p->delta_x));
00572     kx = k - ky*(p->delta_x);
00573 
00574     /* Now cartesian detector coords */
00575 
00576     lx = (kx*(p->dcd2_2) - ky*(p->dcd1_2))/(p->det_cd) + p->Lx + p->ixmin - 1;
00577     ly = (ky*(p->dcd1_1) - kx*(p->dcd2_1))/(p->det_cd) + p->Ly + p->iymin - 1;
00578 
00579     /* Now the detector index */
00580     
00581     l = ly*naxis[0] + lx;
00582     return(l);
00583 }
00584 
00585 
00586 /*---------------------------------------------------------------------------*/
00636 /*---------------------------------------------------------------------------*/
00637 
00638 
00639 static int vircam_chan_init(int channum, int ixmin, int ixmax, int iymin, 
00640                             int iymax, int dcrpix1, int dcrpix2, int dcd1_1, 
00641                             int dcd1_2, int dcd2_1, int dcd2_2, parquet *p) {
00642 
00643     /* Fill in the relevant values */
00644 
00645     p->channum = channum;
00646     p->ixmin = ixmin;
00647     p->ixmax = ixmax;
00648     p->iymin = iymin;
00649     p->iymax = iymax;
00650     p->fpix[0] = ixmin;
00651     p->fpix[1] = iymin;
00652     p->lpix[0] = ixmax;
00653     p->lpix[1] = iymax;
00654     (void)snprintf(p->imsec,SECSIZ,"[%d:%d,%d:%d]",ixmin,ixmax,iymin,iymax);
00655     p->delta_i = ixmax - ixmin + 1;
00656     p->delta_j = iymax - iymin + 1;
00657     if (dcrpix1 < 0 || dcrpix1 > p->delta_i || 
00658         dcrpix2 < 0 || dcrpix2 > p->delta_j) {
00659         cpl_msg_error("vircam_chan_init",
00660                       "nonsense values of dcrpix");
00661         return(VIR_FATAL);
00662     }
00663     p->Lx = dcrpix1 - 1;
00664     p->Ly = dcrpix2 - 1;
00665     p->dcd1_1 = dcd1_1;
00666     p->dcd1_2 = dcd1_2;
00667     p->dcd2_1 = dcd2_1;
00668     p->dcd2_2 = dcd2_2;
00669     p->det_cd = dcd1_1*dcd2_2 - dcd1_2*dcd2_1;
00670     p->delta_x = abs(dcd1_1*(p->delta_i) + dcd1_2*(p->delta_j));
00671     p->delta_y = abs(dcd2_1*(p->delta_i) + dcd2_2*(p->delta_j));
00672     p->data = NULL;
00673     p->norder = 0;
00674     p->bb = NULL;
00675     return(VIR_OK);
00676 }
00677 
00678 /*---------------------------------------------------------------------------*/
00694 /*---------------------------------------------------------------------------*/
00695 
00696 static void vircam_chan_close(parquet *p) {
00697     
00698     /* Check to see if the linearity array has been allocated. If so, then
00699        free the workspace. */
00700 
00701     freespace(p->data);
00702     freespace(p->bb);
00703 }
00704 
00705 /*---------------------------------------------------------------------------*/
00728 /*---------------------------------------------------------------------------*/
00729 
00730 static int vircam_chan_testpos(cpl_table *intab, const char *column) {
00731     int nrows,i,*idata;
00732 
00733     /* First check the column type */
00734 
00735     if (cpl_table_get_column_type(intab,column) != CPL_TYPE_INT)
00736         return(VIR_FATAL);
00737 
00738     /* Now have a look at the actual values and see if they're all 
00739        positive */
00740 
00741     nrows = cpl_table_get_nrow(intab);
00742     idata = cpl_table_get_data_int(intab,column);
00743     for (i = 0; i < nrows; i++)
00744         if (idata[i] <= 0)
00745             return(VIR_FATAL);
00746 
00747     /* Otherwise we're OK */
00748 
00749     return(VIR_OK);
00750 }
00751 
00752 /*---------------------------------------------------------------------------*/
00776 /*---------------------------------------------------------------------------*/
00777 
00778 static int vircam_chan_test1(cpl_table *intab, const char *column) {
00779     int nrows,i,*idata;
00780 
00781     /* First check the column type */
00782 
00783     if (cpl_table_get_column_type(intab,column) != CPL_TYPE_INT)
00784         return(VIR_FATAL);
00785 
00786     /* Now have a look at the actual values and see if they're all 
00787        0, 1 or -1 */
00788 
00789     nrows = cpl_table_get_nrow(intab);
00790     idata = cpl_table_get_data_int(intab,column);
00791     for (i = 0; i < nrows; i++)
00792         if (idata[i] != 0 && idata[i] != -1 && idata[i] != 1)
00793             return(VIR_FATAL);
00794 
00795     /* Otherwise we're OK */
00796 
00797     return(VIR_OK);
00798 }
00799 
00800 /*---------------------------------------------------------------------------*/
00822 /*---------------------------------------------------------------------------*/
00823 
00824 static int vircam_chan_fill_lin(cpl_table *intab, int row, parquet *p) {
00825     int i,null;
00826     char colname[SZCOL];
00827     
00828     /* First get the order of the fit */
00829 
00830     p->norder = cpl_table_get_int(intab,"norder",row,&null);
00831 
00832     /* Get some workspace for the coefficients */
00833 
00834     p->bb = cpl_malloc(p->norder*sizeof(double));
00835 
00836     /* Now loop for the order numbers and read off the coefficents */
00837 
00838     for (i = 1; i <= p->norder; i++) {
00839         (void)snprintf(colname,SZCOL,"coeff_%d",i);
00840         p->bb[i-1] = cpl_table_get_double(intab,colname,row,&null);
00841     }
00842     return(VIR_OK);
00843 }
00844         
00845 
00849 /*
00850 
00851 $Log: vircam_channel.c,v $
00852 Revision 1.12  2007/11/20 09:36:51  jim
00853 changed column 'qualfit' to 'lin_10000_err'
00854 
00855 Revision 1.11  2007/10/25 17:34:00  jim
00856 Modified to remove lint warnings
00857 
00858 Revision 1.10  2007/10/19 09:25:09  jim
00859 Fixed problems with missing includes
00860 
00861 Revision 1.9  2007/03/01 12:42:41  jim
00862 Modified slightly after code checking
00863 
00864 Revision 1.8  2006/11/10 09:26:43  jim
00865 Modified vircam_channel_new to copy the basic structure of a pre-existing
00866 template.
00867 
00868 Revision 1.7  2006/09/08 09:21:02  jim
00869 Added routine vircam_chantab_new
00870 
00871 Revision 1.6  2006/07/04 09:19:03  jim
00872 replaced all sprintf statements with snprintf
00873 
00874 Revision 1.5  2006/06/09 11:32:59  jim
00875 A few more minor fixes for lint
00876 
00877 Revision 1.4  2006/06/09 11:26:25  jim
00878 Small changes to keep lint happy
00879 
00880 Revision 1.3  2006/03/15 10:43:41  jim
00881 Fixed a few things
00882 
00883 Revision 1.2  2006/03/03 14:29:45  jim
00884 Modified definition of vir_fits and channel table
00885 
00886 Revision 1.1  2006/02/18 11:43:45  jim
00887 new file
00888 
00889 
00890 */

Generated on Wed Apr 10 04:01:55 2013 for VIRCAM Pipeline by  doxygen 1.5.1