int allocAsnInfo (AsnInfo *asn, int numsp, int *spmems) { extern int status; /* Local variables */ int i; /* loop index */ int prodid = 0; /* product ID: for looping over products later */ int j; /* loop index for EXPs */ int numexp; /* Function definitions */ void initAsnProduct (ProdInfo *, int); void initAsnSubProd (SubProdInfo *, int); void initAsnExp (ExpInfo *); void freeAsnInfo (AsnInfo *); void initAsnExp (ExpInfo *); /* Free the structure if necessary */ if (asn->product != NULL) freeAsnInfo(asn); /* Allocate the member structures */ asn->spmems = (int *)calloc(numsp+1,sizeof(int)); asn->product = (ProdInfo *)calloc(1,sizeof(ProdInfo )); /* Initialize each member structure */ for (i=0; i < asn->numprod; i++) { initAsnProduct (&(asn->product[i]), numsp+1); } asn->product[prodid].subprod = (SubProdInfo *)calloc(numsp+1, sizeof(SubProdInfo)); for (i=0; i <= numsp; i++) { if (spmems[i] > 0) numexp = spmems[i]; else numexp = 1; initAsnSubProd(&(asn->product[prodid].subprod[i]), numexp); } for (i=0; i <= numsp; i++) { asn->product[0].subprod[i].exp = (ExpInfo *)calloc(spmems[i]+1, sizeof(ExpInfo)); for (j=0; j <= spmems[i]; j++) initAsnExp (&(asn->product[prodid].subprod[i].exp[j])); } /* Check for error during allocation */ if (asn->product == NULL) { asn->numprod = 0; asn->numasn = 0; trlerror ("Insufficient memory to allocate ASN structure"); return (status = 1); } /* Succesful return */ return (status); }
int GetAsnTable (AsnInfo *asn) { /* Arguments: ** asn o: Association info structure */ extern int status; /* Local variables */ int i; /* loop index */ int nrows; /* number of rows in ASNTAB */ int col, row; /* loop indexes */ IRAFPointer tp; /* ASNTAB table pointer */ IRAFPointer colptr[NCOLS]; /* ASNTAB column pointers */ int numsp; /* number of sub-products in asn */ int posid; /* id of sub-product */ RowInfo *exp; /* Internal structure for table information */ int *spmems, *expmem; /* number of EXP for each sub-product */ int poslen; /* Length of memtype string minus POSID */ int prodid; /* id of product */ int expid; int defid; /* default position id for exposures */ int procprod; int maxspmems; /* max number of sub-product members */ char *word; Bool proddth; char spname_ext[SZ_CBUF+1]; /* Extension for sub-product */ char spname_ext_cte[SZ_CBUF+1]; /* Extension for sub-product */ char memtype[SZ_COLNAME+1]; char memsubtype[SZ_COLNAME+1]; /* ASNTAB column names */ char colname[NCOLS][SZ_COLNAME+1] = { "MEMNAME", "MEMTYPE", "MEMPRSNT" }; /* Function definitions */ void freeAsnInfo (AsnInfo *); int allocAsnInfo (AsnInfo *, int, int *); void trlopenerr (char *); void trlwarn (char *); char *lowcase (char *, char *); int MkName (char *, char *, char *, char *, char *, int); void initRowInfo (RowInfo *); int streq_ic (char *, char *); /* strings equal? (case insensitive) */ if (asn->debug) { sprintf (MsgText, "GetAsnTable: ASN_TABLE is %s",asn->asn_table); trlmessage (MsgText); } /* Open the ASN table */ tp = c_tbtopn (asn->asn_table, IRAF_READ_ONLY, 0); if (c_iraferr()) { trlopenerr (asn->asn_table); return (status = TABLE_ERROR); } /* Get pointers to columns in ASNTAB */ for (col=0; col < NCOLS; col++) { c_tbcfnd1 (tp, colname[col], &(colptr[col])); if (c_iraferr() || colptr[col] == 0) { sprintf (MsgText, "Can't find column %s in %s", colname[col], asn->asn_table); trlerror (MsgText); c_tbtclo (tp); return (status = COLUMN_NOT_FOUND); } } /* Find out how many rows are in ASNTAB */ nrows = 0; nrows = c_tbpsta (tp, TBL_NROWS); if (nrows <= 0) { sprintf (MsgText, "Invalid number of rows in %s", asn->asn_table); trlerror (MsgText); c_tbtclo (tp); return (status = TABLE_ERROR); } /* Initialize total number of members based on number of ** rows in table */ asn->numasn = nrows; poslen = 0; /* Allocate space for internal variables */ exp = NULL; exp = (RowInfo *)calloc(nrows, sizeof(RowInfo)); for (row = 0; row < nrows; row++) initRowInfo (&(exp[row])); /* Read each row of ASNTAB into a local structure */ for (row = 0; row < nrows; row++) { /* Get the MEMBER NAME in this row */ c_tbegtt (tp, colptr[0], row+1, exp[row].memname, SZ_CBUF); if (c_iraferr()) { sprintf (MsgText, "Can't read %s in row %d in %s", colname[0], row+1, asn->asn_table); trlerror (MsgText); c_tbtclo (tp); free (exp); return (status = ELEMENT_NOT_FOUND); } /* Convert to lowercase for use as a file name */ for (i = 0; i < strlen(exp[row].memname); i++) exp[row].memname[i] = tolower(exp[row].memname[i]); /* Get the TYPE in this row */ c_tbegtt (tp, colptr[1], row+1, exp[row].mtype, SZ_CBUF); if (c_iraferr()) { sprintf (MsgText, "Can't read %s in row %d in %s", colname[1], row+1, asn->asn_table); trlerror (MsgText); c_tbtclo (tp); free (exp); return (status = ELEMENT_NOT_FOUND); } /* Convert to lowercase for use later in routine. ** Also, if a value of MEMTYPE contains a UNDERLINE, then ** record conversion to DASH in trailer file and warn ** user to correct the value. */ lowcase (exp[row].type, exp[row].mtype); for (i = 0; i < strlen(exp[row].type); i++) { if (exp[row].type[i] == UNDERLINE_CHAR) { exp[row].type[i] = DASH_CHAR; sprintf(MsgText, "MEMTYPE %s in row %d was INVALID and needs to be corrected.", exp[row].mtype, row+1); trlwarn(MsgText); } } /* Get the STATUS in this row */ c_tbegtb (tp, colptr[2], row+1, &(exp[row].prsnt)); if (c_iraferr()) { sprintf (MsgText, "Can't read %s in row %d in %s", colname[2], row+1, asn->asn_table); trlerror (MsgText); c_tbtclo (tp); free (exp); return (status = ELEMENT_NOT_FOUND); } if (asn->debug) { sprintf (MsgText, "GetAsnTable: Read in row %d from ASN table", row); trlmessage (MsgText); } } /* ** Determine whether CRCORR or RPTOBS processing will be required ** by searching for MEMTYPE of EXP_CR* or EXP_RPT*, respectively. ** Once it is determined, go on to next step... */ for (row = 0; row < nrows; row++) { /* Check to see if we need to do CR-SPLIT combination ... */ if (strstr (exp[row].type, "-cr") != NULL) { asn->crcorr = PERFORM; asn->rptcorr = OMIT; poslen = CRLEN; break; /* ... or REPEAT-OBS combination ... */ } else if (strstr (exp[row].type, "-rp") != NULL) { asn->rptcorr = PERFORM; asn->crcorr = OMIT; poslen = RPTLEN; break; /* ... or neither at all */ } else { asn->rptcorr = OMIT; asn->crcorr = OMIT; poslen = DTHLEN; } } /* Default to always perform DRIZCORR step */ asn->dthcorr = PERFORM; if (asn->debug) { sprintf (MsgText, "GetAsnTable: CRCORR = %d, RPTCORR = %d", asn->crcorr,asn->rptcorr); trlmessage (MsgText); } /* Sort through the list figuring out which are input vs. output ** files, and see if any input files are missing. */ /* Initialize local variables */ numsp = 0; posid = 0; prodid = 0; proddth = False; defid = 1; /* Find out how many products/sub-products are in the association ** and determine the posid for each member. */ for (row = 0; row < nrows; row++) { memtype[0] = '\0'; memsubtype[0] = '\0'; /* As long as this is not the final product, ** count number of members in each product/sub-product...*/ if (strstr(exp[row].type,"prod-dth") != NULL) { exp[row].posid = 0; posid = 0; /* If we have a dither product listed, we want to eventually ** perform dither combining step... */ prodid++; proddth = True; /* We always want to produce a product, but if ** not set to PERFORM, then create an empty product... */ if (asn->dthcorr == OMIT) asn->dthcorr = DUMMY; } else { strcpy(memtype,exp[row].type); /* Let's start by breaking up the MEMTYPE string */ word = strtok(memtype,"-"); strcpy(memsubtype,word); /* The end of this second part of MEMTYPE has the POSID */ word = strtok(NULL,"\n"); /* If the last character of the memtype is a number or letter, ** convert to an integer value... */ if (streq_ic(word,"crj") || streq_ic(word,"rpt") || streq_ic(word,"crc") ) { posid = 1; } else { if (exp[row].prsnt || streq_ic(memsubtype,"prod")) { if (isalnum(word[poslen])) { /* Interpret the POSID from the second part ** of MEMTYPE */ posid=(int)strtol(&word[poslen],(char **)NULL,10); } else { /* Otherwise, assume it is a different pointing ** and assign an incremented position ID. After ** all, it is NOT a CR-SPLIT or RPT-OBS exposure.*/ posid = defid; defid++; } } } /* Keep track of how many sub-products there are based on ** POSID from MEMTYPE values */ if (posid > numsp) { if ((exp[row].prsnt && (strstr(memtype,"exp") != NULL)) || strstr(memtype,"prod") != NULL) { numsp++; } } exp[row].posid = posid; } if (asn->debug) { sprintf (MsgText, "GetAsnTable: Posid = %d for row %d",posid, row); trlmessage (MsgText); } /* If the member is missing, give a warning */ /* This implies that MEMPRSNT must be set to YES for EXP_* ** This is not fatal for WF3. Simply decrement tmembers. */ if (!exp[row].prsnt && strncmp(exp[row].type, "prod-",5) != 0) { sprintf (MsgText, "Member \"%s\" is not present", exp[row].memname); trlwarn (MsgText); asn->numasn--; /* Now flag row as being absent so it doesn't get passed ** along for further processing... */ exp[row].posid = MEMABSENT; } } if (asn->debug) { sprintf (MsgText, "GetAsnTable: NUMSP = %d, PRODID = %d",numsp, prodid); trlmessage (MsgText); } /* Check for existence of enough data to process */ if (asn->numasn < 1) { trlerror ("No data available for given assoc. table"); freeAsnInfo (asn); return (status = ERROR_RETURN); } /* Record the number of products found in association */ if (proddth) { asn->numprod = prodid; } else { /* If there are no PROD-DTH entries in ASN table, set ** numprod to 1 */ asn->numprod = prodid + 1; } /* Determine what elements should be processed based on ** initial input, either FULL or PARTIAL processing. */ procprod = 0; if (asn->process != FULL) { for (row=0; row < nrows; row++){ /* Look for entry with same name as input */ if (streq_ic(exp[row].memname, asn->rootname)) { /* We only want to process this product */ procprod = exp[row].posid; numsp = 1; } } } /* Allocate space to count number of exposures per sub-product ** with spmems[0] being reserved for final output product ** since POSID starts indexing at 1. */ spmems = (int *)calloc(numsp+1,sizeof(int)); expmem = (int *)calloc(numsp+1,sizeof(int)); /* Initialize arrays */ for (i=0; i <= numsp; i++) { spmems[i] = 0; expmem[i] = 0; } /* For each sub-product, ** identify each EXP that belongs to that posid and ** is present to be processed. */ for (row=0; row < nrows; row++) { if (strstr(exp[row].type, "exp-") && exp[row].posid > MEMABSENT) { if ((asn->process != FULL && exp[row].posid == procprod) || asn->process == FULL) { spmems[exp[row].posid]++; /* Exposure IDs will start at 1 to be consistent ** with POSID numbering. Initialize here, count later. */ expmem[exp[row].posid] = 1; } } } /* Allocate slots for all members in ASN info structure */ if (allocAsnInfo (asn, numsp, spmems)) { return (status = TABLE_ERROR); } asn->product[prodid].prodid = prodid; /* Reset prodid for filling ASN table */ prodid = 0; /* Copy summary information about ASN relationships to ASN structure. */ maxspmems = 0; asn->numsp = numsp; for (i=0; i <= numsp; i++) { asn->spmems[i] = spmems[i]; if (spmems[i] > maxspmems) maxspmems = spmems[i]; } /* If there aren't any sub-products with more than 1 member, then ** omit crcorr/rptcorr processing */ if ((maxspmems < 2) && asn->crcorr == PERFORM) { sprintf (MsgText, "No sub-product with more than 1 member; CRCORR will be skipped"); trlwarn (MsgText); asn->crcorr = DUMMY; } else if ((maxspmems < 2) && asn->rptcorr == PERFORM) { sprintf (MsgText, "No sub-product with more than 1 member; RPTCORR will be skipped"); trlwarn (MsgText); asn->rptcorr = DUMMY; } /* Copy information read-in into ASN structure now... */ for (row = 0; row < nrows; row++) { if (exp[row].posid != MEMABSENT) { if ((asn->process != FULL && exp[row].posid == procprod) || asn->process == FULL) { posid = exp[row].posid; /* Is this row the final product entry? */ if (strstr(exp[row].type, "prod-dth") != NULL) { strcpy (asn->product[prodid].name, exp[row].memname); strcpy (asn->product[prodid].mtype, exp[row].type); asn->product[prodid].prsnt = exp[row].prsnt; asn->product[prodid].numsp = numsp; asn->product[prodid].asnrow = row+1; /* Create full file name for this image */ if (MkName (exp[row].memname, "_raw", "_drz", "", asn->product[prodid].prodname, SZ_LINE)){ strcpy(asn->product[prodid].prodname, exp[row].memname); strcat (asn->product[prodid].prodname, "_drz.fits"); } /* Create full file name for this CTE image */ if (MkName (exp[row].memname, "_rac_tmp", "_drc", "", asn->product[prodid].prodname_cte, SZ_LINE)){ strcpy(asn->product[prodid].prodname_cte, exp[row].memname); strcat (asn->product[prodid].prodname_cte, "_drc.fits"); } /* Or, is this row an input exposure? */ } else if (strstr(exp[row].type, "exp-") != NULL) { if (exp[row].posid > MEMABSENT) { /* Internal counter for which exposure we want for ** a position */ expid = expmem[posid]; strcpy(asn->product[prodid].subprod[posid].exp[expid].name, exp[row].memname); strcpy(asn->product[prodid].subprod[posid].exp[expid].mtype, exp[row].type); asn->product[prodid].subprod[posid].exp[expid].prsnt = exp[row].prsnt; asn->product[prodid].subprod[posid].exp[expid].asnrow= row+1; /* Create full file name for this image */ if (MkName (exp[row].memname, "_raw", "_raw", "", asn->product[prodid].subprod[posid].exp[expid].expname, SZ_LINE)) { strcpy(asn->product[prodid].subprod[posid].exp[expid].expname, exp[row].memname); strcat(asn->product[prodid].subprod[posid].exp[expid].expname, "_raw.fits"); } /* Fill-in sub-product information for EXP-DTH ** exposures which don't create sub-products */ if (strstr(exp[row].type, "exp-dth") != NULL) { if (!MkName (exp[row].memname, "_raw", "_flt", "", asn->product[prodid].subprod[posid].spname, SZ_LINE) ) { strcpy(asn->product[prodid].subprod[posid].name, exp[row].memname); strcpy(asn->product[prodid].subprod[posid].mtype, exp[row].type); asn->product[prodid].subprod[posid].posid = exp[row].posid; } } /* Increment that counter for next exposure's id ** for this posid */ expmem[posid]++; } /* If neither, it must be a sub-product */ } else { if (spmems[posid] > 0) { strcpy(asn->product[prodid].subprod[posid].name, exp[row].memname); strcpy(asn->product[prodid].subprod[posid].mtype, exp[row].type); asn->product[prodid].subprod[posid].prsnt = exp[row].prsnt; asn->product[prodid].subprod[posid].asnrow = row+1; /* Create full file name for this image for ** DTHCORR input */ spname_ext[0] = '\0'; spname_ext_cte[0] = '\0'; if (asn->crcorr || asn->rptcorr) { strcpy (spname_ext, "_crj"); strcpy (spname_ext_cte,"_crc"); } else { strcpy (spname_ext, "_sfl"); strcpy (spname_ext_cte, "_sfl"); } if (MkName (exp[row].memname, "_raw", spname_ext, "", asn->product[prodid].subprod[posid].spname, SZ_LINE)) { strcpy(asn->product[prodid].subprod[posid].spname, exp[row].memname); strcat(asn->product[prodid].subprod[posid].spname, spname_ext); strcat(asn->product[prodid].subprod[posid].spname, ".fits"); } if (MkName (exp[row].memname, "_raw", spname_ext_cte, "", asn->product[prodid].subprod[posid].spname_cte, SZ_LINE)) { strcpy(asn->product[prodid].subprod[posid].spname_cte, exp[row].memname); strcat(asn->product[prodid].subprod[posid].spname_cte, spname_ext_cte); strcat(asn->product[prodid].subprod[posid].spname_cte, ".fits"); } asn->product[prodid].subprod[posid].numexp = spmems[posid]; asn->product[prodid].subprod[posid].posid = posid; } } } } /* Process only those exposures where MEMPRSNT == YES */ } /* Close the ASN table. We are done reading it in. */ c_tbtclo (tp); /* Clean up memory usage as well. */ free (spmems); free (expmem); free (exp); if (asn->debug) { trlmessage ("GetAsnTable: Info from ASN read into memory."); } /* Successful return */ return (status); }
int CalAcsRun (char *input, int printtime, int save_tmp, int verbose, int debug, const unsigned nThreads, const unsigned cteAlgorithmGen, const char * pcteTabNameFromCmd) { /* arguments: char *input i: name of the FITS file/table to be processed int printtime i: true --> print time stamps at intermediate steps int *save_tmp i: true --> save temporary files int verbose i: true --> print info during processing int debug i: true --> print debugging info during processing int onecpu i: true --> turn off use of OpenMP during processing */ extern int status; ACSInfo acshdr; /* calibration switches, etc */ AsnInfo asn; /* association table data */ char *acsdth_input; /* Input list for ACSDTH */ int prod; void PrBegin (char *); void PrEnd (char *); void PrFileName (char *, char *); void TimeStamp (char *, char *); /* Association table routines */ void initAsnInfo (AsnInfo *); void freeAsnInfo (AsnInfo *); int LoadAsn (AsnInfo *); int ProcessACSCCD (AsnInfo *, ACSInfo *, int *, int, const unsigned nThreads, const unsigned cteAlgorithmGen, const char * pcteTabNameFromCmd); int ProcessMAMA (AsnInfo *, ACSInfo *, int); int AcsDth (char *, char *, int, int, int); char *BuildDthInput (AsnInfo *, int); void InitDthTrl (char *, char *); /* Post error handler */ push_hstioerr (errchk); PrBegin ("CALACS"); /* *** CALACS -- Version ... *** */ if (printtime) TimeStamp ("CALACS started", ""); /* Determine if input is a single file or an association table, then populate ASN structure with appropriate information to control processing. */ initAsnInfo(&asn); if (debug) { trlmessage ("Initialized Association data ... "); } /* Copy Input filename to ASN structure */ strcpy (asn.input, input); /* Print image name. */ trlmessage ("\n"); PrFileName ("input", asn.input); /* Set verbose flag... */ asn.verbose = verbose; asn.debug = debug; /* LoadAsn will determine whether input is a single file or an Association table. If a single image, it will look in that images association table to see what products are associated with it, and process them accordingly. If it is just a single image as its own output, it will proceed as a 1 element table. Based on routines from n_getAsnTable() and n_setup() in CALNICB */ if(LoadAsn(&asn)) { freeAsnInfo (&asn); return (status); } /* Check to see that detector is known, as it could come through with a value of 0 or UNKNOWN_DETECTOR. WJH 2Mar99 */ if (asn.detector == UNKNOWN_DETECTOR || asn.detector == 0) { trlwarn ("Unknown detector type for observations."); freeAsnInfo(&asn); return (status = NOTHING_TO_DO); } if (asn.verbose) { sprintf (MsgText,"CALACS: Detector %s, type %d ",asn.instr, asn.detector); trlmessage (MsgText); } /* Determine what detector we are working with... */ if (asn.detector != MAMA_DETECTOR ) { /* Process CCD data ... */ if (asn.verbose) { trlmessage ("CALACS: processing a CCD product"); } if (ProcessACSCCD(&asn, &acshdr, &save_tmp, printtime, nThreads, cteAlgorithmGen, pcteTabNameFromCmd)) { if (status == NOTHING_TO_DO) { trlwarn ("No processing desired for CCD data."); } else { trlerror ("Couldn't process CCD data"); } freeAsnInfo(&asn); return (status); } trlmessage("Finished CCD processing..."); } else { /* Process MAMA observations here */ trlmessage("Starting to process MAMA data now..."); if (ProcessMAMA(&asn, &acshdr, printtime)) { if (status == NOTHING_TO_DO){ trlwarn ("No processing desired for MAMA data."); } else{ trlerror ("Couldn't process MAMA data"); } freeAsnInfo(&asn); return (status); } trlmessage("Finished MAMA processing..."); } /* Add DTH processing here... */ /* For each DTH product... */ if (asn.process == FULL){ if (asn.verbose) { trlmessage ("CALACS: Building DTH products"); } acsdth_input = NULL; for (prod = 0; prod < asn.numprod; prod++) { /* Create empty DTH product, header only */ /* This uses only one sub-product for the header template, but later versions should use a function similar to BuildSumInput to create list of subproducts as inputs... */ acsdth_input = BuildDthInput (&asn, prod); /* We always want to create a final concatenated trailer file for the entire association whether there is a product or not. So, we set up the trailer file based on the association file name itself. */ /* If desired, we could optionally use the full _drz.tra filename as the trailer filename, based on the output dither product name. if (strcmp(asn.product[prod].prodname,"") != 0) { InitDthTrl (acsdth_input, asn.product[prod].prodname); } else { */ InitDthTrl(acsdth_input, asn.rootname); /* End brace for optional dither product name assignment... } */ /* Check if we have a PROD-DTH specified...*/ if (strcmp(asn.product[prod].prodname, "") != 0) { if ((asn.dthcorr == PERFORM || asn.dthcorr == DUMMY)) { if (AcsDth (acsdth_input, asn.product[prod].prodname, asn.dthcorr, printtime, asn.verbose) ) return (status); /* Pass posid of 0 to indicate a PRODUCT is to be updated */ updateAsnTable(&asn, prod, NOPOSID); } } else { trlwarn ("No DTH product name specified. No product created."); /*status = ACS_OK; */ } } free (acsdth_input); } if (asn.verbose) { trlmessage ("CALACS: Finished processing product "); } freeAsnInfo(&asn); trlmessage ("\n"); PrEnd ("CALACS"); /* *** CALACS complete *** */ if (printtime) TimeStamp ("CALACS completed", acshdr.rootname); /* Return the final value of status, which should be ACS_OK if all went well or some error condition otherwise. */ return (status); }