# include # include # include # include # include "../acs.h" # include "../acsinfo.h" # include "../acserr.h" # define NUMCOLS 23 /* Defined locally to be specific to CCDTAB */ typedef struct { IRAFPointer tp; /* pointer to table descriptor */ IRAFPointer cp_amp; /* column descriptors */ IRAFPointer cp_ccdchip; IRAFPointer cp_ccdgain; IRAFPointer cp_ccdoffset[NAMPS]; IRAFPointer cp_bin1; IRAFPointer cp_bin2; IRAFPointer cp_bias; IRAFPointer cp_atodgain[NAMPS]; IRAFPointer cp_readnoise[NAMPS]; IRAFPointer cp_ampx; IRAFPointer cp_ampy; IRAFPointer cp_saturate; IRAFPointer cp_pedigree; IRAFPointer cp_descrip; int nrows; /* number of rows in table */ } TblInfo; typedef struct { char ccdamp[ACS_CBUF]; int ccdgain; int ccdchip; int bin[2]; int ccdoffset[NAMPS]; float ccdbias; float atodgain[NAMPS]; float readnoise[NAMPS]; int ampx; int ampy; float saturate; } TblRow; static int OpenCCDTab (char *, TblInfo *); static int ReadCCDTab (TblInfo *, int, TblRow *); static int CloseCCDTab (TblInfo *); /* This routine gets the gain, bias and readnoise for the CCD from the CCD parameters table (keyword name CCDTAB). The CCD parameters table should contain the following: header parameters: none needed columns: CCDAMP: identifies which amp was used (string A-D) CCDCHIP: identifies which chip corresponds to the extension CCDGAIN: commanded gain of the CCD (int) CCDOFSTA: commanded bias for amp 1 of CCD (int) CCDOFSTB: commanded bias for amp 2 of CCD (int) CCDOFSTC: commanded bias for amp 3 of CCD (int) CCDOFSTD: commanded bias for amp 4 of CCD (int) BINAXIS1, BINAXIS2: commanded bin sizes (int) ATODGN[A,B,C,D]: actual gain of amps 1-4 used for readouts(double) CCDBIAS: typical value of bias (double) READNSE[A,B,C,D]: typical value of readout noise for each amp(double) SATURATE: CCD saturation threshold AMPX: first column affected by second amp on multiamp readout (int) AMPY: first line affected by second set of amps on multiamp readout (int) The table is read to find the row for which the CCDAMP matches the expected amplifier string (from the image header) and for which the commanded CCD gain, commanded CCD bias, CCDCHIP, and bin sizes match the values read from the image header. The CCDAMP value from the image header must match exactly the value read from the row, including the order of the AMPs listed in CCDAMP. The AMPs should be listed in increasing value, from A to D, for whichever AMPs are used. The matching row is then read to get the actual gain, bias, readnoise, and saturation level. ** This was only modified to read ACS specific columns from CCDTAB. May ** still need to be modified to support multiple AMP readout from a single ** chip by adding AMPX (and AMPY) column(s), which specify the column (and row) ** boundaries for each AMP configuration for that chip. ** AMPX will be set to 0 (zero) for 1 AMP readout of the chip. ** In addition, AMPY gets set to 0 (zero) for 1 AMP readout. 19 Feb 1999 WJH: Revised to handle more columns correctly, increased NUMCOLS to 23 and added CCDOFST[C,D] to the list of columns in used for printing missing columns. */ int GetCCDTab (ACSInfo *acs, int dimx, int dimy) { /* arguments: ACSInfo *acs io: calibration switches, etc int dimx i: number of columns in exposure int dimy i: number of lines in exposure */ extern int status; TblInfo tabinfo; /* pointer to table descriptor, etc */ TblRow tabrow; /* values read from a table row */ int row; /* loop index */ int i; char amp[5] = "ABCD"; int foundit; /* has the correct row been found? */ int RowPedigree (RefTab *, int, IRAFPointer, IRAFPointer, IRAFPointer); int SameInt (int, int); int SameString (char *, char *); /* Open the CCD parameters table and find columns. */ if (OpenCCDTab (acs->ccdpar.name, &tabinfo)) return (status); /* Check each row for a match with ccdamp, ccdgain, ccdoffst, binaxis1, and binaxis2, and get info from the matching row. */ foundit = 0; for (row = 1; row <= tabinfo.nrows; row++) { /* Read the current row into tabrow. */ if (ReadCCDTab (&tabinfo, row, &tabrow)) return (status); if (SameString (tabrow.ccdamp, acs->ccdamp) && SameInt (tabrow.ccdgain, acs->ccdgain) && SameInt (tabrow.ccdchip, acs->chip) && SameInt (tabrow.ccdoffset[0], acs->ccdoffset[0]) && SameInt (tabrow.ccdoffset[1], acs->ccdoffset[1]) && SameInt (tabrow.ccdoffset[2], acs->ccdoffset[2]) && SameInt (tabrow.ccdoffset[3], acs->ccdoffset[3])) { foundit = 1; if (RowPedigree (&acs->ccdpar, row, tabinfo.tp, tabinfo.cp_pedigree, tabinfo.cp_descrip)) return (status); if (acs->ccdpar.goodPedigree == DUMMY_PEDIGREE) { sprintf (MsgText, "Row %d of CCDTAB is DUMMY.", row); trlwarn (MsgText); } acs->ccdbias = tabrow.ccdbias; for (i = 0; i < NAMPS; i++){ /* If the amp is used, keep the value, otherwise set to zero*/ if (strchr(acs->ccdamp, amp[i]) != NULL) { acs->atodgain[i] = tabrow.atodgain[i]; acs->readnoise[i] = tabrow.readnoise[i]; } else { acs->atodgain[i] = 0.; acs->readnoise[i] = 0.; } } /* Correct ampx/ampy to match the actual size of the exposure This will allow more seamless processing of subarrays. */ acs->ampx = (tabrow.ampx > dimx) ? dimx : tabrow.ampx; acs->ampy = tabrow.ampy; acs->saturate = tabrow.saturate; break; } } if (!foundit) { sprintf (MsgText, "Matching row not found in CCDTAB `%s'.", acs->ccdpar.name); trlerror (MsgText); sprintf (MsgText, "CCDAMP %s, CCDGAIN %d, CCDOFFST %d,%d,%d,%d.", acs->ccdamp, acs->ccdgain, acs->ccdoffset[0], acs->ccdoffset[1], acs->ccdoffset[2], acs->ccdoffset[3]); trlerror (MsgText); CloseCCDTab (&tabinfo); return (status = TABLE_ERROR); } if (CloseCCDTab (&tabinfo)) /* close the table */ return (status); return (status); } /* This routine opens the CCD parameters table, finds the columns that we need, and gets the total number of rows in the table. The columns are CCDAMP, CCDGAIN, CCDBIAS, and READNSE. */ static int OpenCCDTab (char *tname, TblInfo *tabinfo) { extern int status; int nocol[NUMCOLS]; int i, j, missing; char *colnames[NUMCOLS] ={"CCDAMP", "CCDCHIP", "CCDGAIN", "BINAXIS1", "BINAXIS2", "CCDOFSTA", "CCDOFSTB", "CCDOFSTC", "CCDOFSTD","CCDBIAS", "ATODGNA", "ATODGNB", "ATODGNC", "ATODGND", "READNSEA", "READNSEB", "READNSEC", "READNSED", "AMPX", "AMPY", "SATURATE"}; int PrintMissingCols (int, int, int *, char **, char *, IRAFPointer); for (j = 0; j < NUMCOLS; j++) nocol[j] = NO; tabinfo->tp = c_tbtopn (tname, IRAF_READ_ONLY, 0); if (c_iraferr()) { sprintf (MsgText, "CCDTAB `%s' not found.", tname); trlerror (MsgText); return (status = OPEN_FAILED); } tabinfo->nrows = c_tbpsta (tabinfo->tp, TBL_NROWS); /* Find the columns. */ c_tbcfnd1 (tabinfo->tp, "CCDAMP", &tabinfo->cp_amp); c_tbcfnd1 (tabinfo->tp, "CCDCHIP", &tabinfo->cp_ccdchip); c_tbcfnd1 (tabinfo->tp, "CCDGAIN", &tabinfo->cp_ccdgain); c_tbcfnd1 (tabinfo->tp, "BINAXIS1", &tabinfo->cp_bin1); c_tbcfnd1 (tabinfo->tp, "BINAXIS2", &tabinfo->cp_bin2); c_tbcfnd1 (tabinfo->tp, "CCDOFSTA", &tabinfo->cp_ccdoffset[0]); c_tbcfnd1 (tabinfo->tp, "CCDOFSTB", &tabinfo->cp_ccdoffset[1]); c_tbcfnd1 (tabinfo->tp, "CCDOFSTC", &tabinfo->cp_ccdoffset[2]); c_tbcfnd1 (tabinfo->tp, "CCDOFSTD", &tabinfo->cp_ccdoffset[3]); c_tbcfnd1 (tabinfo->tp, "CCDBIAS", &tabinfo->cp_bias); c_tbcfnd1 (tabinfo->tp, "ATODGNA", &tabinfo->cp_atodgain[0]); c_tbcfnd1 (tabinfo->tp, "ATODGNB", &tabinfo->cp_atodgain[1]); c_tbcfnd1 (tabinfo->tp, "ATODGNC", &tabinfo->cp_atodgain[2]); c_tbcfnd1 (tabinfo->tp, "ATODGND", &tabinfo->cp_atodgain[3]); c_tbcfnd1 (tabinfo->tp, "READNSEA", &tabinfo->cp_readnoise[0]); c_tbcfnd1 (tabinfo->tp, "READNSEB", &tabinfo->cp_readnoise[1]); c_tbcfnd1 (tabinfo->tp, "READNSEC", &tabinfo->cp_readnoise[2]); c_tbcfnd1 (tabinfo->tp, "READNSED", &tabinfo->cp_readnoise[3]); c_tbcfnd1 (tabinfo->tp, "AMPX", &tabinfo->cp_ampx); c_tbcfnd1 (tabinfo->tp, "AMPY", &tabinfo->cp_ampy); c_tbcfnd1 (tabinfo->tp, "SATURATE", &tabinfo->cp_saturate); /* Initialize counters here... */ missing = 0; i=0; /* Increment i for every column, mark only missing columns in nocol as YES. WJH 27 July 1999 */ if (tabinfo->cp_amp == 0 ) { missing++; nocol[i] = YES;} i++; if (tabinfo->cp_ccdchip == 0 ) { missing++; nocol[i] = YES;} i++; if (tabinfo->cp_ccdgain == 0 ) { missing++; nocol[i] = YES;} i++; if (tabinfo->cp_bin1 == 0 ) { missing++; nocol[i] = YES;} i++; if (tabinfo->cp_bin2 == 0 ) { missing++; nocol[i] = YES;} i++; if (tabinfo->cp_ccdoffset[0] == 0 ) { missing++; nocol[i] = YES;} i++; if (tabinfo->cp_ccdoffset[1] == 0 ) { missing++; nocol[i] = YES;} i++; if (tabinfo->cp_ccdoffset[2] == 0 ) { missing++; nocol[i] = YES;} i++; if (tabinfo->cp_ccdoffset[3] == 0 ) { missing++; nocol[i] = YES;} i++; if (tabinfo->cp_bias == 0 ) { missing++; nocol[i] = YES;} i++; if (tabinfo->cp_atodgain[0] == 0 ) { missing++; nocol[i] = YES;} i++; if (tabinfo->cp_atodgain[1] == 0 ) { missing++; nocol[i] = YES;} i++; if (tabinfo->cp_atodgain[2] == 0 ) { missing++; nocol[i] = YES;} i++; if (tabinfo->cp_atodgain[3] == 0 ) { missing++; nocol[i] = YES;} i++; if (tabinfo->cp_readnoise[0] == 0 ) { missing++; nocol[i] = YES;} i++; if (tabinfo->cp_readnoise[1] == 0 ) { missing++; nocol[i] = YES;} i++; if (tabinfo->cp_readnoise[2] == 0 ) { missing++; nocol[i] = YES;} i++; if (tabinfo->cp_readnoise[3] == 0 ) { missing++; nocol[i] = YES;} i++; if (tabinfo->cp_ampx == 0 ) { missing++; nocol[i] = YES;} i++; if (tabinfo->cp_ampy == 0 ) { missing++; nocol[i] = YES;} i++; if (tabinfo->cp_saturate == 0) { missing++; nocol[i] = YES;} i++; if (PrintMissingCols (missing, NUMCOLS, nocol, colnames, "CCDTAB", tabinfo->tp) ) return(status); /* Pedigree and descrip are optional columns. */ c_tbcfnd1 (tabinfo->tp, "PEDIGREE", &tabinfo->cp_pedigree); c_tbcfnd1 (tabinfo->tp, "DESCRIP", &tabinfo->cp_descrip); return (status); } int PrintMissingCols (int missing, int numcols, int *nocol, char *colnames[], char *tabname, IRAFPointer tp) { /* Parameters: int missing i: number of missing columns int numcols i: number of columns expected in table int *nocol i: array of YES/NO for each column, YES means missing char **colnames i: array of colnames char *tabname i: name of table columns were read from IRAFPointer tp i: pointer to table, close it if necessary */ extern int status; int j; /* If any columns are missing... */ if (missing) { sprintf (MsgText,"%d columns not found in %s.", missing, tabname); trlerror (MsgText); for (j=0; j< numcols; j++) { /* Recall which ones were marked missing... */ if (nocol[j]) { /*... and print out that column's name */ sprintf (MsgText,"Column %s not found in %s.", colnames[j], tabname); trlerror (MsgText); } } c_tbtclo (tp); return (status = COLUMN_NOT_FOUND); } return(status); } /* This routine reads the relevant data from one row. The amplifier number, CCD gain, bias, and readnoise are gotten. */ static int ReadCCDTab (TblInfo *tabinfo, int row, TblRow *tabrow) { extern int status; c_tbegtt (tabinfo->tp, tabinfo->cp_amp, row, tabrow->ccdamp, ACS_CBUF-1); if (c_iraferr()) return (status = TABLE_ERROR); c_tbegti (tabinfo->tp, tabinfo->cp_ccdchip, row, &tabrow->ccdchip); if (c_iraferr()) return (status = TABLE_ERROR); c_tbegti (tabinfo->tp, tabinfo->cp_ccdgain, row, &tabrow->ccdgain); if (c_iraferr()) return (status = TABLE_ERROR); c_tbegti (tabinfo->tp, tabinfo->cp_ccdoffset[0], row, &tabrow->ccdoffset[0]); if (c_iraferr()) return (status = TABLE_ERROR); c_tbegti (tabinfo->tp, tabinfo->cp_ccdoffset[1], row, &tabrow->ccdoffset[1]); if (c_iraferr()) return (status = TABLE_ERROR); c_tbegti (tabinfo->tp, tabinfo->cp_ccdoffset[2], row, &tabrow->ccdoffset[2]); if (c_iraferr()) return (status = TABLE_ERROR); c_tbegti (tabinfo->tp, tabinfo->cp_ccdoffset[3], row, &tabrow->ccdoffset[3]); if (c_iraferr()) return (status = TABLE_ERROR); c_tbegti (tabinfo->tp, tabinfo->cp_bin1, row, &tabrow->bin[0]); if (c_iraferr()) return (status = TABLE_ERROR); c_tbegti (tabinfo->tp, tabinfo->cp_bin2, row, &tabrow->bin[1]); if (c_iraferr()) return (status = TABLE_ERROR); c_tbegtr (tabinfo->tp, tabinfo->cp_bias, row, &tabrow->ccdbias); if (c_iraferr()) return (status = TABLE_ERROR); c_tbegtr (tabinfo->tp, tabinfo->cp_atodgain[0], row, &tabrow->atodgain[0]); if (c_iraferr()) return (status = TABLE_ERROR); c_tbegtr (tabinfo->tp, tabinfo->cp_atodgain[1], row, &tabrow->atodgain[1]); if (c_iraferr()) return (status = TABLE_ERROR); c_tbegtr (tabinfo->tp, tabinfo->cp_atodgain[2], row, &tabrow->atodgain[2]); if (c_iraferr()) return (status = TABLE_ERROR); c_tbegtr (tabinfo->tp, tabinfo->cp_atodgain[3], row, &tabrow->atodgain[3]); if (c_iraferr()) return (status = TABLE_ERROR); c_tbegtr (tabinfo->tp, tabinfo->cp_readnoise[0], row, &tabrow->readnoise[0]); if (c_iraferr()) return (status = TABLE_ERROR); c_tbegtr (tabinfo->tp, tabinfo->cp_readnoise[1], row, &tabrow->readnoise[1]); if (c_iraferr()) return (status = TABLE_ERROR); c_tbegtr (tabinfo->tp, tabinfo->cp_readnoise[2], row, &tabrow->readnoise[2]); if (c_iraferr()) return (status = TABLE_ERROR); c_tbegtr (tabinfo->tp, tabinfo->cp_readnoise[3], row, &tabrow->readnoise[3]); if (c_iraferr()) return (status = TABLE_ERROR); c_tbegti (tabinfo->tp, tabinfo->cp_ampx, row, &tabrow->ampx); if (c_iraferr()) return (status = TABLE_ERROR); c_tbegti (tabinfo->tp, tabinfo->cp_ampy, row, &tabrow->ampy); if (c_iraferr()) return (status = TABLE_ERROR); c_tbegtr (tabinfo->tp, tabinfo->cp_saturate, row, &tabrow->saturate); if (c_iraferr()) return (status = TABLE_ERROR); return (status); } /* This routine closes the ccdtab table. */ static int CloseCCDTab (TblInfo *tabinfo) { extern int status; c_tbtclo (tabinfo->tp); if (c_iraferr()) return (status = TABLE_ERROR); return (status); }