/**************************************************************** * * j_src_spectra/lc.c * * Name of source file: j_src_lc/spectra.c * Version of source file: 5.1.0 * Date: 2005/10/13 * Function name j_src_params * Parent component: j_src_spectra/lc_main * Children: none * Programmer: Stefan Larsson * Affiliation: Stockholm Observatory * Contact address: Stockholm Observatory * SCFAB, SE-106 91 Stockholm, Sweden * Phone: +46 8-5537 8543 FAX: +46 8-5537 8510 * stefan@astro.su.se * Purpose: Get the input parameters and open files for the * j_src_spectra executable * * * * Type of element: Function * Part of package: j_src_lc/spectra-5.1.0.tar.gz * Name: j_src_params * Children: None * Returns: Zero - executable completed with no errors * Negative values - incomplete execution due to * error condition * Error codes: See j_src_spectra.txt * * Parameters: * * inSWGptr dal_element ** Output Pointer to consolidated data SWG * Should positive * fullPtr dal_element ** Output Pointer to FULL event data structure * with events (if any) * Should be positive * restPtr dal_element ** Output Pointer to REST event data structure * with events (if any) * Should be positive * jemxStr char * Output String prefixes for this jemx unit's * data structures `JMX1' or `JMX2' * timeStart double * Output Time at beginning of (first) spectrum * in IJD. * timeStop double * Output End time for data extraction in IJD. * timeStep double * Output If nPhaseBins=0: Store one spectrum * per source integrated over timeStep * (seconds). * If nPhaseBins != 0: timeStep is the * period by which all data is folded * into phase bins. * nPhaseBins int * Output Number of bin size values to * read from "phaseBins". * If < 0: Equal sizes. "phaseBins" * ignored. * phaseBins double * Output Length of the phase bins. * (timeStepSet values in phase units.) * evtType int * Output Data types to use * 0=FULL,1=REST,-1=BOTH * precisionLevel int * Output Speed/precision level * (1-100, 0=Default) * diagnosticMode int * Output Diagnostic Mode * (0=Normal, * 1=Diagnostic spectra * 2=Resolution leakage * 3=Position mapping * 4=Randomized event positions * 5=Tilted collimator * tAccuracy int * Output Time Corr. accuracy * 0: Accuracy = TCOR_ACCURATE * 1: Accuracy = TCOR_INACCURATE * 3: Accuracy = TCOR_ANY * (see DAL3AUX manual) * * bgrMethod int * Output Background subtraction method * chatty int * Output Log message control parameter * status int Input Usual program status flag * 0 or negative *****************************************************************/ #include int j_src_params( dal_element **inSWGptr, /* Pointer to SWG */ dal_element **instrGrpPtr, /* Pointer to Group with MOD data */ dal_element **responsePtr, /* Pointer to response Group */ dal_element **bkgSpecCatPtr, /* Pointer to instr. bkg spec cat.*/ dal_element **dbgSpecCatPtr, /* Pointer to diff. bkg spec cat.*/ char *responseFile, /* Response file name. */ char *rowSelect, /* CFITSIO selection string. */ char *jemxStr, /* JEM-X number file name string */ char *gtiNames, /* GTI names */ char *instMod, double *timeStep, /* Integration time for bins */ double *timeStart, /* Start time in IJD */ double *timeStop, /* Stop time in IJD */ int *evtType, /* Data types to use */ int *precisionLevel, /* Speed/precision level */ int *diagnosticMode, /* Diagnostic Mode */ double *diagnosticParam, /* Diagnostic parameter */ double *overrideCollTilt, /* Collimator tilt parameter */ int *tAccuracy, /* Time correlation accuracy */ int *nPhaseBins, /* Number of phase bins */ double **phaseBins, /* Phase folding bin sizes */ int *bgrMethod, /* Background subtraction method */ int *vignCorr, /* Vignetting correction */ int *useRaDec, /* Src coord: RA,DEC or instr. */ int *nChanBins, /* Number of channel bins */ int *chanLow, /* Lower channel boundary */ int *chanHigh, /* Higher channel boundary */ double *radiusLimit, int *fluxScaling, /* Flux scaling option */ int doLC, int doSpec, int *doPif, int *skipNearDeadAnode, /* Skip near dead anodes */ int *skipHotSpot, /* Skip hotspot area */ int *chatty, /* Level of debugging output */ int status ) /* Status flag */ { char *inputGroup = "inSWG"; /* char *inputDOLs = ""; */ char *inputDOLs = "fullCor,fullPrp,instStat,deadTime,goodTime"; char *outputGroup = "outSWG"; /* char *outputDOLs = "outBkgSpec,outSrcSpec,outSrcArf,outSrcLc"; */ char outputDOLs[DAL_MAX_STRING]; char responsePath[DAL_FILE_NAME_STRING]; char bkgSpecCat[DAL_FILE_NAME_STRING]; char dbgSpecCat[DAL_FILE_NAME_STRING]; char structName[DAL_MAX_NAME_SIZE]; dal_element *fullPtr=NULL; /* Pointer to FULL data, if any */ dal_element *restPtr=NULL; /* Pointer to REST data, if any */ double sumPhase=0.0; /* Sum of phase bin lengths, for sanity check */ int jemxNum = 0; int makeUnique = 1; int clobber = 0; long numRows=0; long i=0; /* loop index */ /*Specific for lc version*************/ int bins, aux, diff; /* Immediate return if called while executable is in error condition */ if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : Non-zero status value passed to j_src_params", status); return status ; } if(doLC == 1 && doSpec == 1) { strcpy(outputDOLs,"outBkgSpec,outSrcSpec,outSrcArf,outSrcLc"); } if(doLC == 1 && doSpec == 0) { strcpy(outputDOLs,"outSrcLc"); } if(doLC == 0 && doSpec == 1) { strcpy(outputDOLs,"outBkgSpec,outSrcSpec,outSrcArf"); } /************* Get chatty parameter*************************************/ status = PILGetInt("chatter", chatty); if( status != ISDC_OK ){ RILlogMessage(NULL, Warning_2, "%d : Could not get chatter parameter from *.par: so let chatter=5", status); *chatty = 5; status=ISDC_OK; } if( *chatty > J_CHATTY_QUIET ){ RILlogMessage( NULL, Log_0, "Value of chatter: %d", *chatty); } /************* Get jemx unit number parameter****************************/ status = PILGetInt("jemxNum", &jemxNum); if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : Could not read jemx unit number from *.par file", status); return status; } switch (jemxNum){ case 1: strcpy(jemxStr,"JMX1"); break; case 2: strcpy(jemxStr,"JMX2"); break; default: status = J_SRC_WRONG_JEMX_NUM; RILlogMessage(NULL, Error_2, "%d: No valid instrument number given in parameter file", status); break; } if( *chatty > J_CHATTY_QUIET ){ RILlogMessage(NULL, Log_3,"Making data for instrument %s", jemxStr); } /************* Get GTI Names parameter ************************************/ status = PILGetString("gtiNames", gtiNames); if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : Could not read gtiNames from *.par file", status); return status; } if (strlen(gtiNames) > 0) { if (*chatty >= J_CHATTY_VERBOSE) { RILlogMessage(NULL,Log_1,"%s %s", "Using the following GTIs:", gtiNames); } } if (strlen(gtiNames)>=DAL_FILE_NAME_STRING) { status = J_SRC_STRING_TOO_LONG; RILlogMessage(NULL,Error_2,"%s %s %d", "Parameter 'gtiNames' is longer than ", "the maximum allowed length of ", DAL_FILE_NAME_STRING); } if (strlen(gtiNames) <= 0) { if (*chatty >= J_CHATTY_VERBOSE) { RILlogMessage(NULL,Warning_2, "No GTI to be used defined at all!"); } gtiNames=NULL; } /************* Read event type parameter****************************/ status = PILGetInt("evtType", evtType); if( status != ISDC_OK ){ RILlogMessage(NULL, Warning_2, "%d : Could not get evtType parameter from *.par: Using FULL only", status); *evtType = 0; status=ISDC_OK; } if( *chatty > J_CHATTY_QUIET ){ if(*evtType == 0){ status = RILlogMessage( NULL, Log_0, "working on Full Imaging events"); } else if(*evtType == -1){ status = RILlogMessage( NULL, Log_0, "working on Full Imaging events"); RILlogMessage( NULL, Log_0, "Restricted mode data not yet supported"); /* Force FULL Imaging mode. (Remove when REST mode used) */ *evtType = 0; } else if(*evtType == 1) { status = ISDC_OK; RILlogMessage(NULL, Warning_2, "Event parameter (evtType: %d )", *evtType); RILlogMessage( NULL, Warning_2, "Restricted mode data not yet supported"); return status ; } else { status = J_SRC_INVALID_PAR; RILlogMessage(NULL, Error_2, "%d : Invalid event parameter (evtType: %d ", status, *evtType); return status ; } } /************* Read event selection parameter*****************************/ status = PILGetString("rowSelect",rowSelect); if (status != ISDC_OK) { if (*chatty >= J_CHATTY_NORMAL) { RILlogMessage(NULL,Error_0,"%s %s %d", "Could not read parameter 'rowSelect'.", "Error status = ",status); } return status; } if (strlen(rowSelect) > 0) { if (*chatty >= J_CHATTY_VERBOSE) { RILlogMessage(NULL,Log_1,"%s %s\n %s", "Selecting input events according to", "the user defined string:", rowSelect); } } else { if (*chatty >= J_CHATTY_VERBOSE) { RILlogMessage(NULL,Log_1, "No special selection on input events."); } rowSelect=NULL; } /************* Read channel bins and set boundaries***********************/ /* * One-step do-loop for error control */ if(doLC == 1) { do { /* * Get number of channel bins * >0 = read nChanBins values from chanLow and chanHigh parameters * 0 = bin all together into single band * -1 = make one lightcurve per possible energy band * -N = bin abs(N) channels together * Only do this if we have events with energy information */ if((status = PILGetInt("nChanBins", nChanBins)) != ISDC_OK){ RILlogMessage(NULL,Log_1, "Could not read parameter 'nChanBins'."); continue; } if(*nChanBins > J_NUM_SCI_BINS){ RILlogMessage(NULL,Log_1, "Bad number of channel bins: %d (must be <= %d)", *nChanBins,J_NUM_SCI_BINS); status = J_SRC_BAD_NUM_VALUES; continue; } if(*nChanBins >= 1){ /* Read 'chanLow' string of boundary values*/ if((status = PILGetIntVector("chanLow", *nChanBins, chanLow)) != ISDC_OK){ RILlogMessage(NULL,Log_1, "Could not read parameter 'chanLow'."); continue; } /* Read 'chanHigh' string of boundary values*/ if((status = PILGetIntVector("chanHigh", *nChanBins, chanHigh)) != ISDC_OK){ RILlogMessage(NULL,Log_1, "Could not read parameter 'chanHigh'."); continue; } }else if(*nChanBins == 0){ /* 0 = bin all */ *nChanBins = 1; chanLow[0] = 0; chanHigh[0] = J_NUM_SCI_BINS-1; }else if(*nChanBins == -1){ /* full resolution */ *nChanBins = J_NUM_SCI_BINS; for(i=0; i<*nChanBins; i++){ chanLow[i] = i; chanHigh[i] = i; } }else if(*nChanBins <= -2){ /* ..,-4,-3,-2 */ /* Allocate numerical array counterparts for chanLow & chanHigh strings */ bins = (int)ceil( (-1.0 * J_NUM_SCI_BINS) / *nChanBins); /* Fill chanLow & chanHigh with boundary values Examples: nChanBins = -2: nChanBins = -3: etc. ChanLow: 0, 2, 4, 6,... ChanLow: 0, 3, 6, 9,... ChanHigh: 1, 3, 5, 7,... ChanHigh: 2, 5, 8, 11,.. */ aux = 0; diff = -*nChanBins - 1; for(i=0; i J_NUM_SCI_BINS-1 || chanHigh[i] < 0 || chanHigh[i] > J_NUM_SCI_BINS-1) { RILlogMessage(NULL,Error_2, "Impossible channel number given - " "they must be between 0 and 255! "); return(J_SRC_BAD_NUM_VALUES); } if (chanLow[i] > chanHigh[i]) { RILlogMessage(NULL,Error_2, "Bad boundary definition: 'low' %d > 'high' %d!", chanLow[i],chanHigh[i]); return(J_SRC_BAD_NUM_VALUES); } } } while (0); /* end of one-time do loop */ } /************* Read diagnostic Mode parameter****************************/ status = PILGetInt("diagnosticMode", diagnosticMode); if( status != ISDC_OK ){ RILlogMessage(NULL, Warning_2, "%d : Could not get diagnosticMode parameter from *.par", status); RILlogMessage(NULL, Log_0, "Using non-Diagnostic Mode"); *diagnosticMode = 0; status=ISDC_OK; } if( *chatty > J_CHATTY_NORMAL ){ if(*diagnosticMode == 0){ status = RILlogMessage( NULL, Log_0, "Running in non-Diagnostic Mode"); } else if(*diagnosticMode == 1){ RILlogMessage(NULL,Log_0 , "Running in diagnostic Mode = 1"); RILlogMessage(NULL,Log_0 , "Store counts in illuminated and shadowed instead of net source"); RILlogMessage(NULL,Log_0 , "and background rates."); } else if(*diagnosticMode == 2){ RILlogMessage(NULL,Log_0 , "Running in resolution diagnostic Mode"); RILlogMessage(NULL,Log_0 , "Will compute and print the leakage from illuminated to"); RILlogMessage(NULL,Log_0 , "shadowed regions on the detector."); } else if(*diagnosticMode == 3){ RILlogMessage(NULL,Log_0 , "Running in position mapping diagnostic Mode"); } else if(*diagnosticMode == 4){ RILlogMessage(NULL,Log_0 , "Running in diagnostic Mode 4. Randomized event positions."); } else if(*diagnosticMode == 5){ RILlogMessage(NULL,Log_0 , "Running in diagnostic Mode 5. Tilted collimator."); } else { RILlogMessage(NULL,Log_0 , "Non-valid diagnostic Mode number "); RILlogMessage(NULL,Log_0 , "Will run in Non-diagnostic Mode! "); } } /************* Read diagnostic Parameter *******************************/ if(*diagnosticMode > 0) { status = PILGetReal("diagnosticParam", diagnosticParam); if( status != ISDC_OK ){ RILlogMessage(NULL, Warning_2, "%d : Could not get diagnostic parameter from *.par", status); RILlogMessage(NULL, Warning_2, "Will use default"); } else { if (*diagnosticMode == 3) { RILlogMessage( NULL, Log_0, "Distance between positions (mm) = %lf ", *diagnosticParam); } if (*diagnosticMode == 4) { RILlogMessage( NULL, Log_0, "Seed for random number generator = %d", (int) *diagnosticParam); } if (*diagnosticMode == 5) { RILlogMessage( NULL, Log_0, "Collimator tilt parameter = %lf", *diagnosticParam); } } } /************* Read collimator tilt parameter **************************/ status = PILGetReal("overrideCollTilt",overrideCollTilt ); if( status != ISDC_OK ){ RILlogMessage(NULL, Warning_2, "%d : Could not get overrideCollTilt parameter from *.par", status); *overrideCollTilt = -1.0; status=ISDC_OK; RILlogMessage( NULL, Log_0, "Will use collimator tilt from IMOD"); } /************* Read Time Corr Accuracy parameter ***********************/ status = PILGetInt("tAccuracy", tAccuracy); if( status != ISDC_OK ){ RILlogMessage(NULL, Warning_2, "%d : Could not get tAccuracy parameter from *.par: Using Low", status); *tAccuracy = 0; status=ISDC_OK; } if(*tAccuracy == 0){ if( *chatty > J_CHATTY_QUIET ){ RILlogMessage( NULL, Log_0, "Using Time Corr Accuracy: TCOR_ACCURATE"); } } else if (*tAccuracy == 1){ if( *chatty > J_CHATTY_QUIET ){ RILlogMessage( NULL, Log_0, "Using Time Corr Accuracy: TCOR_INACCURATE"); } } else if (*tAccuracy == 3){ if( *chatty > J_CHATTY_QUIET ){ RILlogMessage( NULL, Log_0, "Using Time Corr Accuracy: TCOR_ANY"); } } else { status = J_SRC_INVALID_PAR; RILlogMessage(NULL, Error_2, "%d : Invalid time corr accuray value = %d ", *tAccuracy ); return status ; } /************* Read background Method parameter****************************/ status = PILGetInt("bgrMethod", bgrMethod); if( status != ISDC_OK ){ RILlogMessage(NULL, Warning_2, "%d : Could not get bgrMethod parameter from *.par: Using FLAT bgr", status); *bgrMethod = 0; status=ISDC_OK; } if(*bgrMethod == 0){ if( *chatty > J_CHATTY_QUIET ){ RILlogMessage( NULL, Log_0, "Using flat background model"); } } else if (*bgrMethod == 1){ if( *chatty > J_CHATTY_QUIET ){ RILlogMessage( NULL, Log_0, "Using precalculated background model"); } } else { status = J_SRC_INVALID_PAR; RILlogMessage(NULL, Error_2, "%d : Invalid background option, bgrMethod = %d ", *bgrMethod ); return status ; } /************* Read precision level parameter****************************/ status = PILGetInt("precisionLevel", precisionLevel); if( status != ISDC_OK ){ RILlogMessage(NULL, Warning_2, "%d : Could not get precisionLevel parameter from *.par: Using DEFAULT", status); *precisionLevel = 20; status=ISDC_OK; } /* Temporarily for this delivery we will only allow pL=20 if(*precisionLevel != 20){ RILlogMessage(NULL, Warning_2, "The selected precisionLevel value is not supported. Using default."); *precisionLevel = 20; } */ /* if(*precisionLevel != 0 && *precisionLevel != 20 && *precisionLevel != 30){ RILlogMessage(NULL, Warning_2, "The selected precisionLevel value is not supported. Using default."); *precisionLevel = 20; } */ status = RILlogMessage( NULL, Log_0, "Value of precisionLevel: %d", *precisionLevel); /************* Read integration time ****************************/ status = PILGetReal("timeStep", timeStep); if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : Could not get timeStep parameter from *.par", status); return status; } /************* Read radiusLimit ****************************/ status = PILGetReal("radiusLimit", radiusLimit); if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : Could not get radiusLimit parameter from *.par", status); return status; } RILlogMessage( NULL, Log_0, "Value of radiusLimit: %lf mm", *radiusLimit); /************* Read number of phase bins parameter****************************/ status = PILGetInt("nPhaseBins", nPhaseBins); if( status != ISDC_OK ){ RILlogMessage(NULL, Warning_2, "%d : Could not get nPhaseBins parameter from *.par: Using 1.", status); *nPhaseBins = -1; status=ISDC_OK; } status = RILlogMessage( NULL, Log_0, "Value of nPhaseBins: %d", *nPhaseBins); if(*nPhaseBins == 0) { if(doLC > 0){ if(*timeStep > 0) { status = RILlogMessage( NULL, Log_0, "Length of time bins: %lf seconds", *timeStep); } else { status = RILlogMessage( NULL, Log_0, "Will use all selected data for one time bin per source"); } } if(doSpec > 0){ if(*timeStep > 0) { status = RILlogMessage( NULL, Log_0, "Will store one spectrum per source per %lf seconds", *timeStep); } else { status = RILlogMessage( NULL, Log_0, "Will use all selected data for one single spectrum per source"); } } } else if(*nPhaseBins < 0) { status = RILlogMessage( NULL, Log_0, "Events will be phase folded into %d equally long bins", -*nPhaseBins); } else if(*nPhaseBins > 0) { status = RILlogMessage( NULL, Log_0, "Events will be phase folded into %d phase bins.", *nPhaseBins); } /* if(*nPhaseBins != 0) { status = J_SRC_INVALID_PAR; RILlogMessage(NULL, Warning_2, "%d : Phase folding not supported!", status); return status; } */ /************* Read phase bin specification ****************************/ if(*nPhaseBins > 0) { if (*chatty >= J_CHATTY_VERBOSE) { RILlogMessage(NULL,Log_1, "Dividing period interval of %lf seconds " "in %d user-defined phase bins", *timeStep,abs(*nPhaseBins)); } *phaseBins = malloc(*nPhaseBins * sizeof(double)); if (NULL==*phaseBins) { RILlogMessage(NULL,Error_2, "Could not allocate buffer for phase bins!"); status = J_SRC_OUT_OF_MEMORY; return status; } status = PILGetRealVector("phaseBins",*nPhaseBins,*phaseBins); if (status != ISDC_OK) { RILlogMessage(NULL,Error_0,"%s %s %d", "Could not read parameter 'phaseBins'.", "Error status = ",status); return status; } status = RILlogMessage( NULL, Log_0, "%d phase bin specifications read", *nPhaseBins); if( *chatty >= J_CHATTY_VERBOSE ){ for( i=0L; i < *nPhaseBins; i++){ RILlogMessage(NULL,Log_0, "Phase length of bin %d = %lf",i+1,phaseBins[i]); } } /* Do a sanity check on phase bin definition */ sumPhase = 0.0; for (i=0; i<*nPhaseBins; i++) { sumPhase += (*phaseBins)[i]; } /* Note: comparison of difference to avoid rounding errors */ if ( fabs(sumPhase-1.0) > J_SRC_ACCURACY ) { RILlogMessage(NULL,Error_2, "Defined phase bin intervals do not " "sum up to 1.0, but to %4.2f!", sumPhase); RILlogMessage(NULL,Error_2, "This would lead to strange results " "in the processing of events => exit!"); status = J_SRC_BAD_NUM_VALUES; return status; } } /* A negative number is interpreted to mean abs(nPhaseBins) * equally spaced phase bins */ if (*nPhaseBins<0) { if (*chatty >= J_CHATTY_VERBOSE) { RILlogMessage(NULL,Log_1, "Dividing period interval of %lf seconds " "in %d equally spaced phase bins", *timeStep,abs(*nPhaseBins)); } *nPhaseBins=abs(*nPhaseBins); status = DALallocateDataBuffer((void **)phaseBins, *nPhaseBins * sizeof(double), status ); if (status != ISDC_OK) { if (DAL_MALLOC_ERROR==status) { status = J_SRC_OUT_OF_MEMORY; } RILlogMessage(NULL,Error_2, "Could not allocate buffer for phase bins!"); return status; } for (i=0; i<*nPhaseBins; i++) { (*phaseBins)[i] = (1.0 / (*nPhaseBins)); } } /************* Read integration start time ****************************/ status = PILGetReal("timeStart", timeStart); if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : Could not get timeStart parameter from *.par", status); return status; } if( *chatty >= J_CHATTY_NORMAL ){ if( *timeStart > 0.0) { RILlogMessage( NULL, Log_0, "input value of timeStart: IJD %lf", *timeStart); } else { RILlogMessage( NULL, Log_0, "Option to use beginning of SWG as time start."); } } /************* Read integration stop time****************************/ status = PILGetReal("timeStop", timeStop); if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : Could not get timeStop parameter from *.par", status); return status; } if( *chatty >= J_CHATTY_NORMAL ){ if( *timeStop > 0.0) { RILlogMessage( NULL, Log_0, "Input value of timeStop: IJD %lf", *timeStop); } else { RILlogMessage( NULL, Log_0, "Option to use end of SWG as time stop."); } } /************* Read vignetting option ********************************/ status = PILGetBool("vignCorr", vignCorr); if( status != ISDC_OK ){ RILlogMessage(NULL, Warning_2, "%d : Could not get vignCorr from parameter file", status); *vignCorr = 0; status = ISDC_OK; } if( *chatty >= J_CHATTY_NORMAL ){ if( *vignCorr == 0) { RILlogMessage( NULL, Log_0, "No vignetting correction of source fluxes"); } else { if(*precisionLevel > 0){ RILlogMessage(NULL,Warning_2, "vignCorr has no effect for precisionLevel > 0 !"); } RILlogMessage( NULL, Log_0, "Source fluxes will be corrected for vignetting."); } } /************* Read Flux scaling option ******************************/ status = PILGetInt("fluxScaling", fluxScaling); if( status != ISDC_OK ){ RILlogMessage(NULL, Warning_2, "%d : Could not get fluxScaling parameter from *.par: Using 1", status); *fluxScaling = 1; status=ISDC_OK; } if(*fluxScaling < 1 || *fluxScaling > 3) { RILlogMessage( NULL, Log_0, "fluxScaling value in par-file out of range. Ignored."); *fluxScaling = 1; } if( *chatty >= J_CHATTY_NORMAL ){ if( *fluxScaling == 1) { RILlogMessage( NULL, Log_0, "Source/Backgr fluxes scaled to open area"); } else if( *fluxScaling == 2) { RILlogMessage( NULL, Log_0, "Source/Backgr fluxes scaled to nominal detector area (100 cm2"); } else if( *fluxScaling == 3) { RILlogMessage( NULL, Log_0, "Source/Backgr fluxes scaled to per cm2"); } } /************* Read coordinate option ********************************/ status = PILGetBool("useRaDec", useRaDec); if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : Could not get useRaDec from parameter file", status); return status; } if( *chatty >= J_CHATTY_NORMAL ){ if( *useRaDec == 0) { RILlogMessage( NULL, Log_0, "Will use instrument coordinates for sources"); } else { RILlogMessage( NULL, Log_0, "Will use sky coordinates (RA,DEC) for sources"); } } /************* Read Flux PIF saving option *************************/ status = PILGetInt("storePif", doPif); if( status != ISDC_OK ){ RILlogMessage(NULL, Warning_2, "%d : Could not get Pif save parameter from *.par: Using 0", status); *doPif = 1; status=ISDC_OK; } if(*doPif < 0 || *doPif > 2) { RILlogMessage( NULL, Log_0, "doPif value in par-file out of range. Ignored."); *doPif = 1; } if( *chatty >= J_CHATTY_NORMAL ){ if( *doPif == 0) { RILlogMessage( NULL, Log_0, "No PIFs stored"); } else if( *doPif == 1) { RILlogMessage( NULL, Log_0, "Event PIFs will be stored."); } else if( *doPif == 2) { RILlogMessage( NULL, Log_0, "Storage of detector PIFs not implemented"); RILlogMessage( NULL, Log_0, "Only event PIFs will be stored."); *doPif = 1; /* RILlogMessage( NULL, Log_0, "Event and detector map PIFs will be stored"); */ } } if(*doPif == 1) { strcat(outputDOLs,",outSrcPif"); } /************* Read anode option **************************************/ status = PILGetBool("skipNearDeadAnode",skipNearDeadAnode ); if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : Could not get skipNearDeadAnode from parameter file", status); return status; } if( *chatty >= J_CHATTY_NORMAL ){ if( *skipNearDeadAnode == 0) { RILlogMessage( NULL, Log_0, "Will use pixels near (but not at) dead anodes"); } else { RILlogMessage( NULL, Log_0, "Will ignore also pixels at and near dead anodes"); } } /************* Read anode option **************************************/ status = PILGetBool("skipHotSpot",skipHotSpot ); if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : Could not get skipHotSpot from parameter file", status); return status; } if( *chatty >= J_CHATTY_NORMAL ){ if( *skipHotSpot == 0) { RILlogMessage( NULL, Log_0, "Will use pixels also in hotspot area"); } else { RILlogMessage( NULL, Log_0, "Will ignore pixels in hotspot area."); } } /************* Now make consolidated I/O SWG ****************************/ *inSWGptr = NULL; status = CommonPreparePARsStrings(inputGroup, inputDOLs, outputGroup, outputDOLs, makeUnique, inSWGptr, &clobber, status); if (status != ISDC_OK) { RILlogMessage(NULL, Error_2, "%d : CommonPreparePARsStrings failed for %s", status, COMPONENT_NAME); return status; } /************ Get DOL to Instrument Model group and obtain pointer *******/ status = PILGetString("instMod", instMod); if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : could not read Instrument Model DOL", status); return status; } status = DALobjectOpen(instMod,instrGrpPtr,status); if( ISDC_OK != status ){ RILlogMessage(NULL, Error_2, "%d : Could not open Instrument Model Group", status); return status; } else { if ( *chatty > J_CHATTY_NORMAL ){ RILlogMessage( NULL, Log_0, "Instrument model group: %s", instMod); } } /************ Get response file name *********** ********/ if(doSpec == 1){ status = PILGetString("response", responseFile); if( status != ISDC_OK ){ RILlogMessage(NULL, Error_0, "%d : could not read response File name", status); return status; } if ((strlen(responseFile) > 0) && (strlen(responseFile)>=DAL_FILE_NAME_STRING)) { if (*chatty >= J_CHATTY_VERBOSE) { RILlogMessage(NULL,Log_1,"%s\n %s", "Spectra will have response keywords set to", responseFile); } } if (strlen(responseFile)+12>=DAL_FILE_NAME_STRING) { status = J_SRC_STRING_TOO_LONG; RILlogMessage(NULL,Error_2,"%s %s %d", "Parameter 'response' is longer than ", "the maximum allowed length of ", DAL_FILE_NAME_STRING); } strcpy(responsePath,responseFile); strcat(responsePath,"[GROUPING,1]"); status = DALobjectOpen(responsePath,responsePtr,status); if( ISDC_OK != status ){ RILlogMessage(NULL,Warning_2, "%d : Could not open response Group", status); status = ISDC_OK; } else { if ( *chatty > J_CHATTY_NORMAL ){ RILlogMessage( NULL, Log_0, "Response file: %s", responseFile); } } } /*** Get DOL to inst. backgr. spectra catalog and obtain pointer ************/ if(*bgrMethod != 0){ status = PILGetString("bkgSpecCat", bkgSpecCat); if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : could not read Instr. Bkg spectra catalog DOL", status); return status; } status = DALobjectOpen(bkgSpecCat,bkgSpecCatPtr,status); if( ISDC_OK != status ){ RILlogMessage(NULL, Error_2, "%d : Could not open Instr. Bkg spectra catalog", status); } } /***** Get DOL to diff. backgr. spectra catalog and obtain pointer *********/ if(*bgrMethod != 0){ status = PILGetString("dbgSpecCat", dbgSpecCat); if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : could not read Diffuse Bkg spectra catalog DOL", status); return status; } status = DALobjectOpen(dbgSpecCat,dbgSpecCatPtr,status); if( ISDC_OK != status ){ RILlogMessage(NULL, Error_2, "%d : Could not open Diffuse Bkg spectra catalog", status); } } /************* Check if cor. full im. events are available *************/ strcpy( structName, jemxStr); strcat( structName, J_FULLCOR_DS); numRows = 0; status = DALobjectFindElement(*inSWGptr, structName, &fullPtr, status); if ( status==DAL_ELEMENT_NOT_FOUND){ status = ISDC_OK; strcpy( structName, jemxStr); strcat( structName, J_FULLALL_DS); status = DALobjectFindElement(*inSWGptr, structName, &fullPtr, status); } if ( status==DAL_ELEMENT_NOT_FOUND){ /* Even on second try! */ status = ISDC_OK; if ( *chatty > J_CHATTY_NORMAL ){ RILlogMessage(NULL, Log_1, "No FULL imaging data (%s or %s) found in SWG", J_FULLCOR_DS,J_FULLALL_DS); } } else { /****** Check if there's any data events in the extension ********/ status = DALtableGetNumRows(fullPtr, &numRows, status); if (status != ISDC_OK){ numRows = 0; } if ( numRows==0 ){ RILlogMessage(NULL, Log_2, "No FULL imaging events in existing data structure"); fullPtr = NULL; } else if ( *chatty > J_CHATTY_QUIET ) { RILlogMessage(NULL, Log_1, "Number of FULL imaging events in SWG: %ld",numRows); } } if (ISDC_OK!=status) { return(status); } /************* Check if cor. restr im. events are available *************/ strcpy( structName, jemxStr); strcat( structName, J_RESTCOR_DS); numRows = 0; status = DALobjectFindElement(*inSWGptr, structName, &restPtr, status); if ( status==DAL_ELEMENT_NOT_FOUND){ status = ISDC_OK; strcpy( structName, jemxStr); strcat( structName, J_RESTALL_DS); status = DALobjectFindElement(*inSWGptr, structName, &restPtr, status); } if ( status==DAL_ELEMENT_NOT_FOUND){ /* Even on second try! */ status = ISDC_OK; if ( *chatty > J_CHATTY_NORMAL ){ RILlogMessage(NULL, Log_1, "No REST imaging data (%s or %s) found in SWG", J_RESTCOR_DS,J_RESTALL_DS); } } else { /****** Check if there's any data events in the extension ********/ status = DALtableGetNumRows(restPtr, &numRows, status); if (status != ISDC_OK){ numRows = 0; } if ( numRows==0 ){ RILlogMessage(NULL, Log_2, "No REST imaging events in existing data structure"); restPtr = NULL; } else if ( *chatty > J_CHATTY_QUIET ) { RILlogMessage(NULL, Log_1, "Number of REST imaging events in SWG: %ld",numRows); } } if (ISDC_OK!=status) { return(status); } if ( (fullPtr==NULL)&&(restPtr==NULL) ){ status = J_SRC_NO_INPUT_DATA; } return status; } /****************************************************************** * * Version of source file: 1.1 * Function name: j_src_array_all.c * File name: j_src_spectra.c * Parent component: j_src_work * Programmer: Carol Anne Oxborrow * Affiliation: Danish Space Research Institute * Contact address: Juliane Maries Vej 30 * DK-2100 Copenhagen, Denmark * oxborrow@dsri.dk * Purpose: Retrieve any JEMX array * from the I/O SWG file in FITS format * Origin date: 2000/09/22 * Update history: * 1999/12/14 0.00 NJW Copied from JSIMGLgetJEMXArrShort.c * 2000/09/07 1.00 CAO Broadened to a general array-fetching routine * for use in j_src_lc and j_src_spectra. * Now handles all data types,not just short * integers. * 2000/09/22 1.1 CAO No change from 1.0 * * Type of element: Function * Part of package: j_src_lc/spectra * Returns: Zero (ISDC_OK): function completed without error * Negative: function could not completed due to * an error condition * Required components: DAL, PIL, RIL * *****************************************************************/ #include int j_src_array_all( dal_element *theSWG, /* The consolidated I/O group */ char *elementName, /* DS name of data element to get */ void *array, /* pointer to array, returned */ int nAxes, /* Number of axes in array to get */ long *dimAxes, /* Dimension of axes of array */ dal_element **elementPtr, /* Pointer to the data array extension */ int status) /* flag for status when called */ { void *arrayBuffer = NULL; int numAxes=0; int i = 0; long axes[DAL_MAX_ARRAY_DIMENSION]; long startValues[DAL_MAX_ARRAY_DIMENSION]; long bufferSize = 0; long numValues; long numPixels = 0; long j = 0; dal_dataType arrayType; /* No action if fault condition has been reported at time of call */ if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "Non-zero status flag passed to j_src_array"); return( status ); } /* Find the correct element */ status = DALobjectFindElement( theSWG, elementName, elementPtr, status ); if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : Could not find array %s", status, elementName); return( status ); } /* Get the structure of the data array */ status = DALarrayGetStruct( *elementPtr, &arrayType, &numAxes, axes, status); if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : Could not read in array %s structure", status, elementName); return( status ); } if ( numAxes != nAxes){ status = J_SRC_WRONG_DIMS ; RILlogMessage(NULL, Error_2, "%d : Array %s has wrong number of axes: expected: %ld found: %ld", status, elementName, nAxes, numAxes); return status ; } for ( i=0 ; i IJD time conversions added. * - time range options implemented. * (using GTI, timeStart, timeStop and timeStep) * 2001/11/08 2.4 SL Using new templates for -ARF, -SPE, -BSP. * based on ARF II and PHA II and more XSPEC * friendly. * 2002/01/15 2.5 SL Updates: * - Grey Filter correction is now applied. * - Collimator vignetting, detector QEFF and * area is now included in the ARF. * - All -ARF columns are now filled with * relevant data. * 2002/05/09 2.6 SL Updates: SPRs resolved * SPR-780 * - The case of zero events falling * in GTI is now catched. (SPR-1198) * - Time correlation accuracy can now be * set through parameter tAccuracy (SPR-1199) * - Flawed logic in checking ScW boundaries * is now corrected (SPR-1203) * - BACKFILE (background file name) is no * longer written to JMXi-SRCL-SPE since * this caused a double background * subtraction in XSPEC (SPR-1274) * SCREW-506 * Type of element: Function * Part of package: j_src_lc/spectra.tar.gz * Name: j_src_work * Children: * Returns: Zero - executable completed with no errors * Negative values - incomplete execution due to * error condition * * Notes: * 010626: All event arrays (Pi, DetX,Y OBT changed * from fixed length to pointers with * memory allocation according to number of * events. * 010706: Changed rate and bRate arrays from 3 dim * to pointers. Same content but now accessed * as a 1 dim array. This is to allow * dynamic memory allocation. * * 010817: rowFilter for event selection is now * (STATUS==123 || STATUS==0) * The first is for simulated events and the * second is for good real events. * * 010907: Finished new functions and _work update to * use IJD instead of OBT in data selection etc. * j_src_nspec: Calculates number of time ranges * for which to calculate spectra. * j_src_nspec_times: Returns start, stop and * integration times for the time ranges. * * *-------------------------------------------------------------------------- * * VARIABLES * * * a11[] = Array of resolution correction factors. * a12[] 4 transformation values per energy channel. * a21[] * a22[] * * *aLC11 = Pointers to resolution correction factors. * *aLC12 4 transformation values per ligh curve * *aLC21 channel. * *aLC22 * * ancrFileDOL = DOL of -ARF data structure. Used to find * ancrFileName. * * ancrFileName = Character string containing the (path +) * file name where the ancilliary file (ARF) * associated with a source spectrum can be found. * * ancrFileNameI = ancrFileName + row specification in file. * * arfQuantumEff[i] = Average quantum efficiency over the ARF * energy bins. * * axisArf[i] = On-axis ARF read from column SPECRESP in * the JMXi-AXIS-ARF data structure in the * response file. * * bkgResCorr[] = Contain leakage correction factors for * each energy channel. The corrections are * applied to ???? * * bkgID = Text string used to write source background ID * in JMXi-SRCL-BSP. * * bRateVarianceMin[] = If background count rate is zero dont assume * variance = bRate*bRate = 0 but * variance = 1*1 = 1 (but scaled to the * bRate scaling). * * closedArea[] = Closed detector area as seen in precisionLevel * > 1. One value per source.This is the area * used for background calculation, so it is * the shadowed detector area subject to the same * restrictions as openArea (e.g. radiusLimit, * screened bad areas etc.). * * closedArea1 = Closed detector area as seen by the projected * mask and computed in precisionLevel = 1. * * deadCorr = Present Dead Time correction factor. * = 1/(1-deadtime). * For full event data this is applyed to each * event. * * *deadTimes = Dead time values. Actually dead time fraction! * * * detCorX[][] = 2dim array with one element per detector pixel. * Each element contains the detector X correction * value which is applied to RAWY values when they * are transformed to DETX. * In this program the correction values are * needed when the instrumen response for a * source (pif) is computed. * Read from JMXi-CORX-MOD. * * detCorY[][] = 2dim array with one element per detector pixel. * Each element contains the detector Y correction * value which is applied to RAWY values when they * are transformed to DETY. * In this program the correction values are * needed when the instrumen response for a * source (pif) is computed. * Read from JMXi-CORY-MOD. * * detDepthMax = Depth of the active detection region (mm) * (= HDRIFT, Hight of drift layer in JMXi-DETE-MOD) * * detectorArea = Geometric detector area. * * detectorRadius = Geometric radius of the detector (mm). * (= RAD_DET in JMXi-DETE-MOD) * * diagn3Scale = Distance (mm) between points in thr position * mapping (diagnosticMode 3). * * diagnosticMode = * 0=Normal, * 1=Open area counts in src-lc/spe and * closed area counts in src-lc/spe backgr * 2=Resolution leakage * 3=Position mapping * 4=Randomized event positions * 5=Collimator tilt * * diagnosticParam = Parameter for diagnostic Modes * Mode 0: Not used * 1: dP=0 Counts corrected for Deadt & Greyf. * dP=1 Counts uncorrected * 2: Not used * 3: Position scale (mm) * 4: Seed for random generator * dP<0 Also random source positions * * doColl = 0 No ray tracing through collimator. * 1 Do ray tracing through collimator. * * doLC = Switch to compute lightcurve. * Compute lightcurve if doLC = 1. * * doSpec = Switch to compute spectra. * Compute spectra if doSpec = 1. * * fluxAreaNorm = Index which indicates to which detector area * resulting flux estimates are normalized. * 0 for per cm**2 * 1 for per source illuminated area. * 2 for per total detector area. * * fullChannel[] = Energy channel number. For channel - energy * conversion table. * * fullEMin[] = Lower energy (keV) for energy channel with * corresponding index. (E_MIN) * * fullEMax[] = Upper energy (keV) for energy channel with * corresponding index. (E_MAX) * * gaussPDFSize = Number of points per axis in the gaussian * distribution function representing the * detector resolution. * * gaussPDFWidth = Width of the 2-dimensional gaussian * distribution function representing the * detector resolution. * * gaussPDFStep = Distance [mm] between points in the * gaussian distribution function. * * greyCorr = Present Grey filter correction factor. * = 32/(greyfilter+1). * * *gtiStart = Pointer to GTI start times in IJD. * * *gtiEnd = Pointer to GTI end times in IJD. * * holeEffRadius = The effective radius of a mask element * [Defined from Area = Pi*(radius)^2] * * ijdStartSWG = Time in IJD at beginning of SWG * * ijdStopSWG = Time in IJD at end of SWG * * lc = Parameter to set lightcurve output. * = 1: Write lightcurve * Else no lightcurve output. * * leakage[i] = leakFraction in energy channel i. * Calculated from polynomial fit (coefficients * in j_src_lc.h). * Polynomial obtained off-line after running * j_src_lc/spectra with diagnosticMode=2 and * fitting total leakage as a function of * intrinsic detector resolution. * * leakFraction = Fraction of flux falling onto a mask hole * which leaks outside of the projected hole * area on the detector. * * leakageFrOpen = When using PIFs and selecting pixels with * illumination > openCut, this is the fraction * of flux lost from the illuminated pixels. * * nBkgCounts = Long int used to sum up the total number of source * background counts accumulated. Only used for log * output. * * *nBRate = Pointer to an array with the same numer of * elements as bRate. It is used to count the number * of events added to each background spectrum * time energy bin. * * nDeadTimes = Number of Dead time values. * * nextDead = Index of next Dead time value, which is * valid from deadTimeIJD[nextDead] (=deadTimeIJDNext). * * nextGrey = Index of next Grey filter value, which is * valid from statusIJD[nextGrey] (=timeIJDGreyNext). * * nGreyChanges = number of Grey filter changes. * (Number of values for statusOBT and *statusIJD). * * noIJDStartSWG = 1 if no ijdStartSWG found (0 otherwise). * * noIJDStopSWG = 1 if no ijdStopSWG found (0 otherwise). * * *nRate = Pointer to an array with the same numer of * elements as rate. It is used to count the number * of events added to each spectrum time energy bin. * * nSrcCounts = Long int used to sum up the total number of source * counts accumulated. Only used for log output. * * openArea[] = Open detector area as seen in precisionLevel * > 1. One value per source. This is the source * illuminated detector area subject to the slected * restrictions (e.g. radiusLimit, screened bad * areas etc.). * * openArea1 = Open detector area as seen through the projected * mask as computed in precisionLevel = 1. * * of[] = openFraction as seen from each of the source sky * positions. [Under development] * * openFraction = (# open mask elements) / (total # mask elements) * as seen from a specific sky direction. * * openFractionAve = (# open mask elements) / (total # mask elements) * for the whole mask. * * overrideCollTilt = Parameter used to specify collimator tilt. * Same functionalaty as diagnosticMode=5. * Parameter is real, e.g. 3.85 means that * the absolut tilt of the collimator is * 3 arcmin in angular direction 0.85. * Angle is circular fraction, from X-axis * counter clockwise. (So 0.85 is * 0.85*360 degrees.) * * pifjIniOpen[i][j] = Sum of all pixel illumination factors * (pif) from source j in the open elements * used to extract source i. * * pifjIniClosed[i][j] = Sum of all pixel illumination factors * (pif) from source j in the closed elements * used to extract source i. * * pixFluxDistr[] = Distribution of pixel fluxes as function of pixel * sizes. * * pixFluxDistrErr[] = Estimated errors for pixFluxDistr. * * posRes[] = Positional resolution on the detector. * * *phaseBinEnd = Pointer to double array with nPhaseBins elements. * Contains the phase at the end of each phase * folding bin. * * *phaseBinStart = Pointer to double array with nPhaseBins elements. * Contains the phase at the beginning of each * phase folding bin. * * phaseSum = Temporary used when computing folding phase * values. * * posResEnergy[] = Energy (keV) for positional resolution values. * * posResChannel[] = Channel (number) for positional resolution values. * Contains the number of the energy channel closest * to the corresponding posResEnergy-value. * (This is a decent approximation). * * poissonErr = Poisson error estimates. Saved as STAT_ERR. * * PSFStep = Point Spread Function step length (mm). * Used when computing the detector response * distribution for a photon. * * ratePoissonErr = The Poisson error estimates scaled from * counts to countrate. * (poissonErr/(integration time).) * * rateVarianceMin[] = If count rate is zero dont assume * variance = rate*rate = 0 but * variance = 1*1 = 1 (but scaled to the * rate scaling). * * sampleDF = Input parameter to j_src_leakage. * Used to estimate the average effect of * detector binning of events. * If > 0, sample the hole distribution * function this number of times (with * different shift of the bins). * * *statusIJD = Pointer to the IJD times at which the Grey filter * value changed (# values = nGreyChanges). * * srcCosX[] = Source coordinates (in radians) in the * srcCosY[] telescope system. X along optical axis and * srcCosZ[] the Y,Z plane parallel to the detector. * * srcID[] = Array of text strings used to read source IDs. * IDs are written to JMXi-SRCL-SPE. * * srcY[] = Source Y and Z coordinates (in mm) as * srcZ[] projected onto the mask. * * subPif = Pixel redistribution map. For each sub pixel * subPif contains an array which describes how * a photon hitting the subpixel has a * probability distribution to procuce events in * the nearby pixels. * * *timeStartSpec = Pointer to end time in IJD for each spectrum. * One value for each time interval where spectra * are calculated. * * timeIJDGreyNext = Time of next Grey filter change. Used in loop * over events where spectra are summed up. * * *timeIntSpec = Pointer to integration time values. * One value per spectrum (time interval). * * *timeStartSpec = Pointer to start time in IJD for each spectrum. * One value for each time interval where spectra * are calculated. * * useRaDec = Decides which type of source coordiantes in * JMXi-SRCL-RES are used. * = 0: Use instrument coordinates. * else: Use sky (Ra,Dec) coordinates. * * vignArray[][] = Vigneting array. Read from JMXi-VIGN-MOD. * 256*256 elements. Gives the transmission through * the collimator as a function of viewing angle. * * vignArrayCRPixY = Central pixal in the Y-direction in array * vignArray[][]. * * vignArrayCRPixZ = Central pixal in the Z-direction in array * vignArray[][]. * * vignArrayDeltaY = The size of a vignArray[][] pixel in Y-direction * (in radians). * * vignArrayDeltaZ = The size of a vignArray[][] pixel in Z-direction * (in radians). * * vignCorr = Boolean value indicating if source count rates * should (y or: vignCorr != 0) be corrected for * vignetting or if they * should not (n or: vignCorr = 0). * * vignetting = Vignetting given as transmission for a particular * source direction. * * vignPtr = Pointer to JMXi-VIGN-MOD data structure. * *****************************************************************************/ #include int j_src_work(dal_element *theSWGptr, /* Pointer to input SWG */ dal_element *instrGrpPtr, /* Pointer to MOD group */ dal_element *responsePtr, /* Pointer to RSP group */ dal_element *bkgSpecCatPtr, /* Pointer to -SCAT-BKG */ dal_element *dbgSpecCatPtr, /* Pointer to -SCAT-DBG */ char *responseFile, /* Response file name */ char *jemxStr, /* Number string of JEMX unit */ char *gtiNames, /* GTI names */ char *instModDOL, double timeStep, /* Integration period (sec) */ double timeStart, /* Start time in IJD */ double timeStop, /* Stop time in IJD */ int evtType, /* Data types to use */ int precisionLevel, /* Speed/precision level */ int diagnosticMode, /* Diagnostic Mode */ double diagnosticParam, /* Diagnostic parameter */ double overrideCollTilt, /* Collimator tilt param. */ int tAccuracy, /* Time Corr. Accuracy */ int nPhaseBins, /* Number of phase bins */ double *phaseBins, /* Phase folding bin sizes */ int bgrMethod, /* Background subtr. method */ int vignCorr, /* Vignetting correction */ int useRaDec, /* Src coord: RA,DEC or instr.*/ char *rowSelect, /* CFITSIO selection string */ int nChanBinsLC, /* Number of channel bins */ int *chanLow, /* Lower channel boundary */ int *chanHigh, /* Higher channel boundary */ double radiusLimit, /* Radius limit for detector */ int fluxScaling, /* Flux scaling option */ int doLC, /* Switch to compute lc */ int doSpec, /* Switch to compute spectra */ int doPif, /* Store PIF Data structure */ int skipNearDeadAnode, /* Skip near dead anodes */ int skipHotSpot, /* Skip hotspot area */ int chatty, /* Level of debugging output */ int status) /* Status flag */ { static short maskArray[J_DIM_MASK][J_DIM_MASK]; static short mask[J_DIM_MASK][J_DIM_MASK]; static short iSpecBkg[J_NUM_X_PIXELS][J_NUM_Y_PIXELS]; static short dSpecBkg[J_NUM_X_PIXELS][J_NUM_Y_PIXELS]; static unsigned short detMap[J_NUM_X_PIXELS][J_NUM_Y_PIXELS]; unsigned short bitValue = 0; unsigned char *byteBuffer=NULL; int *greyValues = NULL; int *modeValues = NULL; static unsigned char balk[J_DIM_BALK][J_DIM_BALK]; unsigned long *ulongBuffer = NULL; unsigned long diffRadMin[J_SSP_MAX_SPEC_MODS]; unsigned long diffRadMax[J_SSP_MAX_SPEC_MODS]; char appFlag[2] = "F"; char templateName[DAL_MAX_NAME_SIZE]; char structName[DAL_MAX_NAME_SIZE]; char bStructName[DAL_MAX_NAME_SIZE]; char bkgID[DAL_MED_STRING]; static char srcID[J_SRC_MAXSRC][DAL_MED_STRING]; char **stringBuffer = NULL; char rowFilter[DAL_BIG_STRING]; char ancrFileDOL[DAL_FILE_NAME_STRING]; char ancrFileName[DAL_FILE_NAME_STRING]; char ancrFileNameI[DAL_FILE_NAME_STRING]; char fileRow[10]; char colName[10]; /* Name of current PIF column */ char attname[30]; static char levelSpe[3] = "SPE"; long dimAxes[DAL_MAX_ARRAY_DIMENSION]; long startIndices[2]; long stopIndices[2]; long iSpec = 0; long nSpec = 0; long nOpen = 0; long nClosed = 0; long nGreyChanges = 0; long nValuesRead = 0; long nValuesWrite = 0; long bufferSize = 0; long bufferSize2 = 0; long nGTIs = 0; long nOBTs = 0; long nBytes = 0; long nFloats = 0; long nDoubles = 0; long nInts = 0; long nInts2 = 0; long nULongs = 0; long nChars = 0 ; long nDeadTimes = 0; long nPosRes = 0; long nAtXe = 0; long nQeff = 0; long nIscal = 0; long nDscal = 0; long nSpecModels = 0; long nDiffModels = 0; long stringLen = 0; long nFullEvents = 0; long nRestEvents = 0; long nEvents = 0; long nRows = 0; long binSize = 0; long nAdd = 0; long ii = 0; long jj = 0; long ix = 0; long jy = 0; long i=0; long j=0; long iEvent = 0; long iGTI = 0; long iSource = 0; long nSources = 0; long nStrings = 0; long nLineEnergies = 0; long *nRate = NULL; long *nBRate = NULL; long *nRateLC = NULL; long *nBRateLC = NULL; long nSrcCounts = 0; long nBkgCounts = 0; long nRateSum = 0; long nextGrey = 0; long nextDead = 0; long nFullChannels = 0; long nPosResInterpol = 0; long nPifEnergies = 0; long nColl = 0; long randSeed = 18; long midEventDistr = 50; long nSum = 0; long nBSum = 0; int skipGrey = 0; int skipGTI = 0; int skipDEAD = 0; int noIJDStartSWG = 0; int noIJDStopSWG = 0; int nChanBins = J_NUM_SCI_BINS; int specModelIdx[J_SSP_MAX_SPEC_MODS]; int diffModelIdx[J_SSP_MAX_SPEC_MODS]; int *fullEventPi = NULL; int *restEventPi = NULL; int Pi = 0; int *intBuffer = NULL; int *intBuffer2 = NULL; int eBand = 0; int iBin = 0; int icount1 = 0; int icount2 = 0; int icount3 = 0; int icount4 = 0; int icount5 = 0; int icount6 = 0; int icountOutside = 0; int nGTI = 0; /* Used for j_read_GTI */ int stringlength = 0; int fluxAreaNorm = 2; int fullChannel[J_NUM_SCI_BINS]; int *posResChannel = NULL; int gaussPDFSize = 100; int holeCenter = 0; int sampleDF = 0; static int collimator[J_SRC_COLL_SIZE][J_SRC_COLL_SIZE]; int doColl = 1; int nstep = 4; int iPixX = 0; int iPixY = 0; int midSubPifPix = 0; int subPifOffset = 0; int iPifEnergy = 0; int pifOffset = 0; int pifChannel[J_SRC_PIF_MAX_ENERGIES]; int offset = 0; int maskRimCut = 1; /* 1 will cut at mask rim */ int iros=0; /* test iros parameter */ int isCrab = -1; /* Set to src# if source is Crab (extended). */ int nSubPifPix = 9; int iPixFlux = 0; float gaussPDFWidth = 0.3; float gaussPDFStep = 0.02; float ffullEMin[J_NUM_SCI_BINS]; float ffullEMax[J_NUM_SCI_BINS]; float maskRatio = 0.0; float openFraction = 0.0; float openFractionAve = 0.0; float of[J_SRC_MAXSRC]; float srcOffAxisAngle[J_SRC_MAXSRC]; float *floatBuffer = NULL; float *pifBuffer = NULL; static float vignArray[J_VIGN_DIM][J_VIGN_DIM]; static float pifWork[J_NUM_X_PIXELS][J_NUM_Y_PIXELS]; float *pif = NULL; float *subPif = NULL; float pifInterpol = 0.0; static float pifEnergy[J_SRC_PIF_MAX_ENERGIES]; static float detCorX[J_NUM_X_PIXELS][J_NUM_Y_PIXELS]; static float detCorY[J_NUM_X_PIXELS][J_NUM_Y_PIXELS]; static float detPixArea[J_NUM_X_PIXELS][J_NUM_Y_PIXELS]; static float detPixLLX[J_NUM_X_PIXELS][J_NUM_Y_PIXELS]; static float detPixLLY[J_NUM_X_PIXELS][J_NUM_Y_PIXELS]; static float gaussPDF[J_SRC_PSF_SIZE][J_SRC_PSF_SIZE]; float distrEnergy = 0.0; float distrScale = 0.0; static float eventDistr[J_NUM_EVENT_PIXELS][J_NUM_EVENT_PIXELS]; static float iSpatBkg[J_NUM_X_PIXELS][J_NUM_Y_PIXELS]; static float dSpatBkg[J_NUM_X_PIXELS][J_NUM_Y_PIXELS]; static float sourceARF[J_SRC_MAXSRC][J_NUM_ARF_BINS]; float eventWeights[J_SRC_MAXSRC]; float weight = 0.0; float *holeDF = NULL; float RA_SCX = 0.0; float DEC_SCX = 0.0; float RA_SCZ = 0.0; float DEC_SCZ = 0.0; float srcRa[J_SRC_MAXSRC]; float srcDec[J_SRC_MAXSRC]; float cosXjmx = 0.0; float cosYjmx = 0.0; float cosZjmx = 0.0; float xRSTI = 0.0; float yRSTI = 0.0; float xCoord = 0.0; float yCoord = 0.0; float rightX[J_SRC_MAX_NUM_X_SUBPIXELS]; float rightY[J_SRC_MAX_NUM_Y_SUBPIXELS]; float leftX[J_SRC_MAX_NUM_X_SUBPIXELS]; float leftY[J_SRC_MAX_NUM_Y_SUBPIXELS]; float anstep = 4.0; float PSFStep = 0.1; float openCut = 0.0; float closedCut = 0.0; float openSrcCut[J_SRC_MAXSRC]; float closedSrcCut[J_SRC_MAXSRC]; static float openSrcCutEnergy[J_SRC_MAXSRC][J_SRC_PIF_MAX_ENERGIES]; static float closedSrcCutEnergy[J_SRC_MAXSRC][J_SRC_PIF_MAX_ENERGIES]; float pifInterpolEnergy = 0.0; float *eventPifs = NULL; float *eventEnergy = NULL; float *eventDeadc = NULL; double *rate = NULL; double *bRate = NULL; double *fracExp = NULL; double a = 0.0; double aaa = 0.0; double sumRate = 0.0; double sumBRate = 0.0; double sumError = 0.0; double angleZ = 0.0; double timeStepIJD = 0.0; double timeIJDGreyNext = 0.0; double poissonErr = 0.0; double poissonErrBkg = 0.0; double poissonErrSrc = 0.0; double ratePoissonErr = 0.0; double bRatePoissonErr = 0.0; double srcRate = 0.0; double bkgRate = 0.0; double *dblBuffer = NULL; double detectorRadius = 0.0; double detectorArea = 0.0; double detDepthMax = 0.0; double radMask = 0.00; double detMaskDist = 0.00; double detDepth = 0.0; double detDepthX[J_SRC_MAXSRC]; double detDepthY[J_SRC_MAXSRC]; double detDepthZ[J_SRC_MAXSRC]; double rhoCell = 0.00; double vignArrayCRPixY = 0.0; double vignArrayCRPixZ = 0.0; double vignArrayDeltaY = 0.0; double vignArrayDeltaZ = 0.0; double vignetting[J_SRC_MAXSRC]; double ijdStartSWG = -1.0; double ijdStopSWG = -1.0; double timeStartStop[2]; double *deadTimes = NULL; double *rateCor = NULL; double *deadEff = NULL; double quantumEff[J_SSP_MAX_QEFF_NUM]; double quantEnergy[J_SSP_MAX_QEFF_NUM]; double defEnergyLo[J_SSP_MAX_ARF_LENRG_NUM]; double defEnergyHi[J_SSP_MAX_ARF_LENRG_NUM]; double axisArf[J_SSP_MAX_ARF_LENRG_NUM]; double arfQuantumEff[J_SSP_MAX_ARF_LENRG_NUM]; double posResEnergy[J_SSP_MAX_POSRES_NUM]; double posRes[J_SSP_MAX_POSRES_NUM]; double atXeEnergy[J_SRC_MAX_ATXE_NUM]; double atXe[J_SRC_MAX_ATXE_NUM]; double fullEMin[J_NUM_SCI_BINS]; double fullEMax[J_NUM_SCI_BINS]; double posResInterpol[J_NUM_SCI_BINS]; double iScalFactors[J_SSP_MAX_ISCAL_NUM]; double dScalFactors[J_SSP_MAX_DSCAL_NUM]; static double bkgSpecModel[J_SSP_MAX_SPEC_MODS][J_NUM_SCI_BINS]; double specRAscX[J_SSP_MAX_SPEC_MODS]; double specDECscX[J_SSP_MAX_SPEC_MODS]; double specRAscZ[J_SSP_MAX_SPEC_MODS]; double specDECscZ[J_SSP_MAX_SPEC_MODS]; double specSunAspt[J_SSP_MAX_SPEC_MODS]; static double specXYZpos[J_SSP_MAX_SPEC_MODS][3]; static double diffSpecModel[J_SSP_MAX_SPEC_MODS][J_NUM_SCI_BINS]; double diffRAscX[J_SSP_MAX_SPEC_MODS]; double diffDECscX[J_SSP_MAX_SPEC_MODS]; double diffRAscZ[J_SSP_MAX_SPEC_MODS]; double diffDECscZ[J_SSP_MAX_SPEC_MODS]; double srcCosX[J_SRC_MAXSRC]; double srcCosY[J_SRC_MAXSRC]; double srcCosZ[J_SRC_MAXSRC]; double srcY[J_SRC_MAXSRC]; double srcZ[J_SRC_MAXSRC]; double *fullDetX = NULL; double *fullDetY = NULL; double *restDetX = NULL; double *restDetY = NULL; double *timeIJD = NULL; double *statusIJD = NULL; double *deadTimeIJD = NULL; double *gtiStart = NULL; double *gtiEnd = NULL; double *timeStartSpec = NULL; double *timeEndSpec = NULL; double *timeIntSpec = NULL; double greyCorr = 1.0; double deadCorr = 1.0; double deadTimeIJDNext = 0.0; double leakFraction = 0.0; double leakage[J_NUM_SCI_BINS]; double polynom = 0.0; double polFactor = 0.0; double aa[6]; double a11[J_NUM_SCI_BINS]; double a12[J_NUM_SCI_BINS]; double a21[J_NUM_SCI_BINS]; double a22[J_NUM_SCI_BINS]; double *aLC11 = NULL; double *aLC12 = NULL; double *aLC21 = NULL; double *aLC22 = NULL; double channelEnergy = 0.0; double relativeRateErr = 0.0; double rateErr = 0.0; double rateVariance = 0.0; double bRateVariance = 0.0; double rateVarianceMin[J_SRC_MAXSRC]; double bRateVarianceMin[J_SRC_MAXSRC]; double oF2 = 0.0; double cF2 = 0.0; double radius = 0.0; double diagn3Scale = 0.0; double holeEffRadius = 1.74; double openArea1 = 0.0; double closedArea1 = 0.0; double effOpenArea1 = 0.0; double leakageFrOpen1 = 0.0; double leakageToClosed1 = 0.0; double sourceX = 0.0; double sourceY = 0.0; double phaseSum = 0.0; double *phaseBinStart = NULL; double *phaseBinEnd = NULL; double foldPhase = 0.0; static double collimatorXBot[J_SRC_COLL_SIZE][J_SRC_COLL_SIZE]; static double collimatorYBot[J_SRC_COLL_SIZE][J_SRC_COLL_SIZE]; static double collimatorXTop[J_SRC_COLL_SIZE][J_SRC_COLL_SIZE]; static double collimatorYTop[J_SRC_COLL_SIZE][J_SRC_COLL_SIZE]; double collXCrossBot[J_SRC_COLL_NUM]; double collYCrossBot[J_SRC_COLL_NUM]; double collXCrossTop[J_SRC_COLL_NUM]; double collYCrossTop[J_SRC_COLL_NUM]; double collHeight = 0.0; double effCollHeight = 0.0; double collDirectionAngle = 0.0; double collTiltAngle = 0.0; double collTiltX = 0.0; double collTiltY = 0.0; double step = 0.1; double xstep = 0.0; double ystep = 0.0; double openArea[J_SRC_MAXSRC]; double closedArea[J_SRC_MAXSRC]; double effOpenArea[J_SRC_MAXSRC]; double leakageFrOpen[J_SRC_MAXSRC]; double leakageToClosed[J_SRC_MAXSRC]; static double openAreaEnergy[J_SRC_MAXSRC][J_SRC_PIF_MAX_ENERGIES]; static double closedAreaEnergy[J_SRC_MAXSRC][J_SRC_PIF_MAX_ENERGIES]; static double effOpenAreaEnergy[J_SRC_MAXSRC][J_SRC_PIF_MAX_ENERGIES]; static double leakageFrOpenEnergy[J_SRC_MAXSRC][J_SRC_PIF_MAX_ENERGIES]; static double leakageToClosedEnergy[J_SRC_MAXSRC][J_SRC_PIF_MAX_ENERGIES]; double subPixelX = 0.0; double subPixelY = 0.0; double subPixArea = 0.0; double errDr = 0.0; double errDbR = 0.0; double srcVariance = 0.0; double bkgVariance = 0.0; static double pifjIniOpen[J_SRC_MAXSRC][J_SRC_MAXSRC]; static double pifjIniClosed[J_SRC_MAXSRC][J_SRC_MAXSRC]; static double openAreaChan[J_NUM_SCI_BINS]; double closedAreaChan[J_NUM_SCI_BINS]; double effOpenAreaChan[J_NUM_SCI_BINS]; double leakageFrOpenChan[J_NUM_SCI_BINS]; double leakageToClosedChan[J_NUM_SCI_BINS]; double srcToBkgArea = 0.0; double longsph = 0.0; double shortsph = 0.0; double pixFluxDistr[20]; double pixFluxDistrErr[20]; double pixAreaDistr[20]; dal_dataType dalType = DAL_DT_UNKNOWN; dal_dataType DALtype; dal_dataType diskType; dal_dataType diskTypeOut = 0; dal_accessType accessType; dal_baseType baseType; dal_element *maskPtr=NULL; dal_element *vignPtr=NULL; dal_element *corXPtr=NULL; dal_element *corYPtr=NULL; dal_element *detPtr=NULL; dal_element *fbdsPtr=NULL; dal_element *deadPtr=NULL; dal_element *statusPtr=NULL; dal_element *moPtr=NULL; dal_element *collPtr=NULL; dal_element *qeffPtr=NULL; dal_element *posResPtr=NULL; dal_element *atXePtr=NULL; dal_element *lenergyPtr=NULL; dal_element *iscalPtr=NULL; dal_element *dscalPtr=NULL; dal_element *iSpatPtr=NULL; dal_element *dSpatPtr=NULL; dal_element *iSpecBkgPtr = NULL; dal_element *dSpecBkgPtr = NULL; dal_element *srcListPtr = NULL; dal_element *arfPtr = NULL; dal_element *pifPtr = NULL; dal_element *bspecPtr = NULL; dal_element *specPtr = NULL; OBTime *obtBuffer=NULL; OBTime *statusOBT = NULL; OBTime *gtiStartOBT=NULL; OBTime *gtiEndOBT=NULL; OBTime timeStartStopOBT[2]; /* timeStart, timeStop in OBT. */ OBTime *deadTimeOBT = NULL; OBTime iScalDobt[J_SSP_MAX_ISCAL_NUM]; OBTime dScalDobt[J_SSP_MAX_ISCAL_NUM]; OBTime swapOBT = 0; OBTime *fullEventOBT = NULL; OBTime *restEventOBT = NULL; OBTime *eventOBT = NULL; OBTime obtStart = 0; OBTime obtEnd = 0; OBTime obtStartBin = 0; OBTime obtEndBin = 0; OBTime obtStartSWG = 0; OBTime obtStopSWG = 0; Instrument JEMX_num; TCOR_flag Accuracy; /* --- variables related to the output lightcurves -------------------- */ char nameLC[14]; /* name of output LC JMXi-xxxx-DLC */ double *rateLC=NULL; /* buffer for count rate spectrum */ double *bRateLC=NULL; /* buffer for bkg count rate spectrum */ double *errLC=NULL; /* buffer for count rate error spectrum */ double *bErrLC=NULL; /* buffer for count rate error spectrum */ double *timeLC=NULL; /* buffer for IJD times of LC bins */ double *timeDel=NULL; /* buffer for LC bin duration */ double sumPhase=0.0; /* holds sum of preceding phase bins */ double *avgRate=NULL; /* average count rate per channel bin */ double *avgRateErr=NULL; /* average count rate error per channel */ long nOutLCBins=0; /* number of output time or phase bins */ long iLCBin=0; /* index variable for output lc bins */ long nLCBins=0; /* counter for processed bins */ int iChan=0; /* index variable for lightcurve channels*/ int iPhase=0; /* index variable for phase boundaries */ double elapsedTime=0.0; /* Total integration time covered */ double totalOnTime=0.0; /* Sum over all used GTI intervals */ double meanDeadCorr=1.0; /* average dead time correction factor */ float outLCBins = 0.0; int chanPi[J_NUM_SCI_BINS]; int skipARF = 0; /* --- variables related to event weight data output ------------------- */ int totDet = 0; /* Hidden test parameter. If set to 1 a detector lightcurve will be computed instead of the usual src extraction data. */ /* Immediate return if called while executable is in error condition */ if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "Non-zero status flag passed to j_src_work: %d", status); return status ; } if(tAccuracy == 0){ Accuracy = TCOR_ACCURATE; } else if(tAccuracy == 1){ Accuracy = TCOR_INACCURATE; } else if(tAccuracy == 3){ Accuracy = TCOR_ANY; } else{ status = J_SRC_INVALID_PAR; RILlogMessage(NULL, Error_2, "%d : Invalid time corr accuray value = %d ", Accuracy ); return status ; } /* Which JEMX? Select enumeration. */ if ( strcmp( jemxStr, "JMX1") == 0 ){ JEMX_num = JMX1; } else if ( strcmp( jemxStr, "JMX2") == 0){ JEMX_num = JMX2; } else{ status = J_SRC_WRONG_VALUE; RILlogMessage(NULL, Error_2, "Incorrect JEMX instrument number in j_src_work: %d", status); return status ; } if( chatty > J_CHATTY_VERBOSE ){ RILlogMessage(NULL,Log_0, "Instrument enumeration selected: %d",JEMX_num); } /* If timeStep < 0 use one time bin. */ if ( timeStep <= J_SRC_ACCURACY ) { timeStep = (timeStop - timeStart) * DAL3GEN_SECONDS_IN_DAY; } /* Time step in IJD, timeStep -> timeStepIJD */ timeStepIJD = timeStep/DAL3GEN_SECONDS_IN_DAY; /* If no spectral extraction: Skip all ARF stuff. */ if(doSpec == 0){ skipARF = 1; } if(diagnosticMode == 101) { doColl = 0; } if( diagnosticMode == 4){ if(diagnosticParam < 0) { srand48((long) -diagnosticParam); } else { srand48( (long) diagnosticParam); } } /* Read in energies at which PIF-maps are to be computed. */ if(precisionLevel == 20){ nPifEnergies = J_SRC_PIF_N20_ENERGIES; pifEnergy[0] = J_SRC_PIF_0_ENERGY; pifEnergy[1] = J_SRC_PIF_1_ENERGY; pifEnergy[2] = J_SRC_PIF_2_ENERGY; pifEnergy[3] = J_SRC_PIF_3_ENERGY; pifEnergy[4] = J_SRC_PIF_4_ENERGY; pifEnergy[5] = J_SRC_PIF_5_ENERGY; pifEnergy[6] = J_SRC_PIF_6_ENERGY; pifEnergy[7] = J_SRC_PIF_7_ENERGY; pifEnergy[8] = J_SRC_PIF_8_ENERGY; pifEnergy[9] = J_SRC_PIF_9_ENERGY; } if(precisionLevel == 25){ nPifEnergies = J_SRC_PIF_N25_ENERGIES; pifEnergy[0] = J_SRC_PIF25_0_ENERGY; pifEnergy[1] = J_SRC_PIF25_1_ENERGY; pifEnergy[2] = J_SRC_PIF25_2_ENERGY; pifEnergy[3] = J_SRC_PIF25_3_ENERGY; pifEnergy[4] = J_SRC_PIF25_4_ENERGY; pifEnergy[5] = J_SRC_PIF25_5_ENERGY; pifEnergy[6] = J_SRC_PIF25_6_ENERGY; pifEnergy[7] = J_SRC_PIF25_7_ENERGY; pifEnergy[8] = J_SRC_PIF25_8_ENERGY; pifEnergy[9] = J_SRC_PIF25_9_ENERGY; pifEnergy[10] = J_SRC_PIF25_10_ENERGY; pifEnergy[11] = J_SRC_PIF25_11_ENERGY; pifEnergy[12] = J_SRC_PIF25_12_ENERGY; pifEnergy[13] = J_SRC_PIF25_13_ENERGY; pifEnergy[14] = J_SRC_PIF25_14_ENERGY; pifEnergy[15] = J_SRC_PIF25_15_ENERGY; pifEnergy[16] = J_SRC_PIF25_16_ENERGY; pifEnergy[17] = J_SRC_PIF25_17_ENERGY; } for ( i=0 ; i<20 ; i++){ pixFluxDistr[i] = 0.0; pixFluxDistrErr[i] = 0.0; pixAreaDistr[i] = 0.0; } /* Read in all the non-event data needed for the processing */ /************************************************************************* READING ScW START AND STOP TIMES **************************************************************************/ strcpy( structName, "GNRL-SCWG-GRP" ); if( chatty > J_CHATTY_VERBOSE){ RILlogMessage(NULL, Log_0, "Reading SWG time from %s", structName); } statusPtr = NULL; status = DALobjectFindElement(theSWGptr, structName, &statusPtr, status); if ( status!=ISDC_OK ){ RILlogMessage(NULL, Warning_2, "%d : Could not find extension %s", status, structName); status = ISDC_OK; } else { /********************* READING ScW OBTSTART ********** ******************/ status = DAL3GENattributeGetOBT(statusPtr,"OBTSTART", (void *)&obtStartSWG, NULL, status); if (status != ISDC_OK){ RILlogMessage(NULL, Warning_2, "%d : Could not read time OBT at start of SWG.", status); status = ISDC_OK; } else { if( chatty >= J_CHATTY_NORMAL ){ RILlogMessage(NULL,Log_0, "Time OBT at start of SWG read from %s ", structName ); } } /********************* READING ScW OBTEND ******************************/ status = DAL3GENattributeGetOBT(statusPtr,"OBTEND", (void *)&obtStopSWG, NULL, status); if (status != ISDC_OK){ RILlogMessage(NULL, Warning_2, "%d : Could not read time OBT at end of SWG.", status); status = ISDC_OK; } else { if( chatty > J_CHATTY_NORMAL ){ RILlogMessage(NULL,Log_0, "Time OBT at end of SWG read from %s ", structName ); } } /********************* READING ScW TSTART (IJD) **********************/ status = DALattributeGet(statusPtr,"TSTART", DAL_DOUBLE, (void *)&ijdStartSWG,NULL, NULL, status); if (status != ISDC_OK){ RILlogMessage(NULL, Warning_2, "%d : Could not get time IJD at start of SWG.", status); status = ISDC_OK; noIJDStartSWG = 1; } else { if( chatty > J_CHATTY_NORMAL ){ RILlogMessage(NULL,Log_0, "Time IJD at start of SWG = %f",ijdStartSWG); } } /********************* READING ScW TSTOP (IJD) ***************************/ status = DALattributeGet(statusPtr,"TSTOP", DAL_DOUBLE, (void *)&ijdStopSWG,NULL, NULL, status); if (status != ISDC_OK){ RILlogMessage(NULL, Warning_2, "%d : Could not get time IJD at end of SWG.", status); status = ISDC_OK; noIJDStopSWG = 1; } else { if( chatty > J_CHATTY_NORMAL ){ RILlogMessage(NULL,Log_0, "Time IJD at end of SWG = %f",ijdStopSWG); } } } /********************* DEFAULT timeStart,timeStop? **************************/ if( timeStart < 0.0) { if( noIJDStartSWG == 0) { timeStart = ijdStartSWG; if( chatty > J_CHATTY_NORMAL ){ RILlogMessage(NULL,Log_0, "Start time set to beginning of SWG: %f",timeStart); } } else { RILlogMessage(NULL, Log_0, "No start time found. Will use time at first data point."); } } if( timeStop < 0.0) { if( noIJDStopSWG == 0) { timeStop = ijdStopSWG; if( chatty > J_CHATTY_NORMAL ){ RILlogMessage(NULL, Log_0, "Stop time set to end of SWG: %f",timeStop); } } else { RILlogMessage(NULL, Log_0, "No stop time found. Will use time at last data point."); } } /************************************************************************* CK: 031210 Initializing balk structure definitions **************************************************************************/ if(J_SRC_IGNORE_BALK == 0){ for ( i=0 ; i J_CHATTY_VERBOSE){ RILlogMessage(NULL, Log_0,"Reading data structure: %s", structName,status); } dimAxes[0] = (long) J_DIM_MASK ; dimAxes[1] = (long) J_DIM_MASK ; /* Read mask pattern array */ status = j_src_array_all(instrGrpPtr, structName, (void*) mask[0], 2, dimAxes, &maskPtr, status); if( status != ISDC_OK ){ RILlogMessage( NULL, Log_0, "Error getting jemx mask pattern array in DS: %s",structName); return status; } if( chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_0, "Mask pattern read"); } for ( i=0 ; i J_CHATTY_VERY_VERBOSE ){ RILlogMessage(NULL, Log_0,"Mask pattern open fraction: %f", openFraction); } /* Find other inputs from mask pattern data structure */ status = DALattributeGet(maskPtr, "RAD_MASK", DAL_DOUBLE, (void *)&radMask, NULL, NULL, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not get mask radius value from %s", status, structName); return status; } if( chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_0, "Mask radius = %f", radMask); } status = DALattributeGet(maskPtr, "RHO", DAL_DOUBLE, (void *)&rhoCell, NULL, NULL, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not get mask rho value from %s", status, structName); return status; } if( chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_0, "Mask cell rho-parameter = %f", rhoCell); } status = DALattributeGet(maskPtr,"DM_DIST", DAL_DOUBLE,(void *)&detMaskDist, NULL, NULL, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Couldn't get detector-mask distance from %s", status, structName); return status; } if( chatty > J_CHATTY_VERY_VERBOSE ){ RILlogMessage(NULL,Log_0, "Detector mask distance = %f",detMaskDist); } /***************** Transform "maskArray" into "mask". The use of two mask arrays is for simplicity when merging with older code. Might change... **************/ status = j_src_mask(mask, maskArray, chatty, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : mask transformation error in j_src_mask", status); return status; } if( chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_0, "Mask transformation completed"); } /************************************************************************* Compute the distribution function for an evenly illuminated mask hole. -------- NOT USED PRESENTLY --- "j_src_maskhole" changed to be used for resolution estimate. *************************************************************************/ /* Allocate memory for holeDF array. */ /* bufferSize = J_SRC_HOLE_SIZE*J_SRC_HOLE_SIZE*sizeof(float); status = DALallocateDataBuffer( (void **)&holeDF, bufferSize, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not allocate memory for holeDF", status ); return status; } holeCenter = (int) (0.5*(double)J_SRC_HOLE_SIZE+0.1); gaussPDFSize = 100; gaussPDFWidth = 0.3; gaussPDFStep = 0.05; status = j_src_maskhole(holeDF, holeCenter, gaussPDFSize, gaussPDFWidth, gaussPDFStep, holeInOut, normDF, &leakFraction, chatty, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Error at exit from j_src_maskhole", status); return status; } if( chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_0, "Mask hole profile computed"); } */ /************************************************************************* READING DATA STRUCTURE JMXi-VIGN-MOD **************************************************************************/ /* Create structure name of JEMX instr. data : */ strcpy( structName, jemxStr ); strcat( structName, J_VIGN_DS); if( chatty > J_CHATTY_VERBOSE){ RILlogMessage(NULL, Log_0,"Reading data structure: %s", structName,status); } dimAxes[0] = (long) J_VIGN_DIM ; dimAxes[1] = (long) J_VIGN_DIM ; /* Read vignetting array */ status = j_src_array_all(instrGrpPtr, structName, (void*) vignArray[0], 2, dimAxes, &vignPtr, status); if( status != ISDC_OK ){ RILlogMessage( NULL, Log_0, "Error getting jemx vignetting table in DS: %s",structName); return status; } if( chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_0, "Vignetting table read"); } /* Read attributes. */ status = DALattributeGet(vignPtr, "CRPIX1", DAL_DOUBLE, (void *)&vignArrayCRPixY, NULL, NULL, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not read zero point definition for vigneting from %s", status, structName); return status; } if( chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_0, "Vignetting array Central pixel (in Y) = %f", vignArrayCRPixY); } status = DALattributeGet(vignPtr, "CRPIX2", DAL_DOUBLE, (void *)&vignArrayCRPixZ, NULL, NULL, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not read zero point definition for vigneting from %s", status, structName); return status; } if( chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_0, "Vignetting array Central pixel (in Z) = %f", vignArrayCRPixZ); } status = DALattributeGet(vignPtr, "CDELT1", DAL_DOUBLE, (void *)&vignArrayDeltaY, NULL, NULL, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not read Y pixel size for vigneting array from %s", status, structName); return status; } if( chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_0, "Vignetting array pixel size (in Y) = %12.9lf", vignArrayDeltaY); } status = DALattributeGet(vignPtr, "CDELT2", DAL_DOUBLE, (void *)&vignArrayDeltaZ, NULL, NULL, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not read Z pixel size for vigneting array from %s", status, structName); return status; } if( chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_0, "Vignetting array pixel size (in Z) = %12.9lf", vignArrayDeltaZ); } /************************************************************************* READING DATA STRUCTURE JMXi-DETE-MOD **************************************************************************/ /* Now move on to the detector model data extension - to get detector radius and the detector map. */ strcpy( structName, jemxStr ); strcat( structName, J_DETECTOR_DS); if( chatty > J_CHATTY_VERY_VERBOSE ){ RILlogMessage(NULL, Log_0,"Reading data structure: %s", structName, status); } dimAxes[0] = (long) J_NUM_X_PIXELS ; dimAxes[1] = (long) J_NUM_Y_PIXELS ; /* Read DETE-MOD array. Using "detPixArea" for temporary storage while swapping axes. */ status = j_src_array_all(instrGrpPtr, structName, (void*) iSpecBkg[0], 2, dimAxes, &detPtr, status); if( status != ISDC_OK ){ RILlogMessage( NULL, Log_0, "Error getting jemx detector model table in DS: %s", structName); return status; } for ( i=0 ; i cm^2 */ status = DALattributeGet(detPtr, "HDRIFT", DAL_DOUBLE, (void *)&detDepthMax, NULL, NULL, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not get detector depth value from %s", status, structName); return status; } if( chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_0, "Active detector Depth = %f mm",detDepthMax); } /************************************************************************* READING DATA STRUCTURE JMXi-CORX-MOD **************************************************************************/ if(precisionLevel > 9) { /* Create structure name of JEMX instr. data : */ strcpy( structName, jemxStr ); strcat( structName, J_CORX_DS); if( chatty > J_CHATTY_VERBOSE){ RILlogMessage(NULL, Log_0,"Reading data structure: %s", structName,status); } dimAxes[0] = (long) J_NUM_X_PIXELS ; dimAxes[1] = (long) J_NUM_Y_PIXELS ; /* Read CORX-MOD array. Using "detPixArea" for temporary storage while swapping axes. */ status = j_src_array_all(instrGrpPtr, structName, (void*) detPixArea[0], 2, dimAxes, &corXPtr, status); if( status != ISDC_OK ){ RILlogMessage( NULL, Log_0, "Error getting jemx position correction X table in DS: %s", structName); return status; } for ( i=0 ; i 9) { /* Create structure name of JEMX instr. data : */ strcpy( structName, jemxStr ); strcat( structName, J_CORY_DS); if( chatty > J_CHATTY_VERBOSE){ RILlogMessage(NULL, Log_0,"Reading data structure: %s", structName,status); } dimAxes[0] = (long) J_NUM_X_PIXELS ; dimAxes[1] = (long) J_NUM_Y_PIXELS ; /* Read CORY-MOD array. Using "detPixArea" for temporary storage while swapping axes. */ status = j_src_array_all(instrGrpPtr, structName, (void*) detPixArea[0], 2, dimAxes, &corYPtr, status); if( status != ISDC_OK ){ RILlogMessage( NULL, Log_0, "Error getting jemx position correction Y table in DS: %s", structName); return status; } for ( i=0 ; i 248){ detCorY[i][j] = 125.0; }else { detCorY[i][j] = detPixArea[j][i]; } } } if( chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_0, "Position correction Y table read"); } } /************************************************************************* READING DATA STRUCTURE JMXi-FBDS-MOD **************************************************************************/ /* Read Channel energy conversion table (if we have full imaging data). The table is needed to convert detector resolution as function of energy to a function of channel later on. */ strcpy( structName, jemxStr ); strcat( structName, J_PIBINS_DS); if( chatty > J_CHATTY_VERY_VERBOSE ){ RILlogMessage(NULL, Log_0,"Reading data structure: %s", structName, status); } fbdsPtr = NULL; status = DALobjectFindElement(instrGrpPtr, structName, &fbdsPtr, status); if (status!=ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not find extension %s", status, structName); return status; } status = DALtableGetNumRows(fbdsPtr,&nFullChannels,status); if (status != ISDC_OK) { RILlogMessage(NULL,Error_2,"%s %s - status = %d", "Error in determining number of", "channel-energy table entries", status); return status; } if( chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_0, "Number of energy channels found = %d",nFullChannels); } /* Now get an int data buffer for CHANNEL */ if (nInts2 < J_NUM_SCI_BINS){ if ( intBuffer2!=NULL){ status = DALfreeDataBuffer( (void *) intBuffer2, status); if (status!= ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : could not free integer data buffer", status); return status; } } nInts2 = J_NUM_SCI_BINS; bufferSize2 = (long) J_NUM_SCI_BINS*sizeof(int); intBuffer2 = NULL; status = DALallocateDataBuffer( (void **)&intBuffer2, bufferSize2, status); if (status!= ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : could not allocate new integer data buffer", status); return status; } } diskType= DAL_INT; /* Now get CHANNEL */ status = DALtableGetCol(fbdsPtr, "CHANNEL",0, &diskType, &nValuesRead, (void *)intBuffer2, status); if (status!= ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : could not read CHANNEL from %s", status, structName); return status; } if ( nValuesRead !=J_NUM_SCI_BINS ){ status = J_SRC_BAD_NUM_VALUES; RILlogMessage(NULL, Error_2, "%d : Wrong no. CHANNEL values read for Energy-channel table", status); return status; } for ( i=0 ; i J_CHATTY_VERY_VERBOSE ){ RILlogMessage(NULL, Log_0, "Reading data structure: %s",structName, status); } statusPtr = NULL; status = DALobjectFindElement(theSWGptr, structName, &statusPtr, status); if ( status!=ISDC_OK ){ RILlogMessage(NULL, Warning_2, "%d : Could not find extension %s", status, structName); status = ISDC_OK; skipGrey = 1; } if (skipGrey == 1){ nGreyChanges = 0; } else{ status = DALtableGetNumRows(statusPtr,&nGreyChanges,status ); RILlogMessage(NULL, Log_2, "Number of instrument status entries for this SWG: %ld",nGreyChanges); if( status != ISDC_OK ){ RILlogMessage( NULL,Error_2, "%d :Error reading number of grey filter/mode changes", status ); return status ; } if( nGreyChanges == 0 ){ RILlogMessage(NULL,Error_2, "No instrument status entries found in %s", structName ); status = J_SRC_NO_INPUT_VALUES; return status ; } /* Allocate memory buffer for MODE, GREY_FILTER and OB_TIME */ bufferSize = (long) nGreyChanges*sizeof(unsigned char); byteBuffer=NULL; nBytes = nGreyChanges; status = DALallocateDataBuffer((void **) &byteBuffer, bufferSize,status ); if( status != ISDC_OK ){ RILlogMessage( NULL, Error_2, "%d : could not allocate byte buffer for instrument status", status ); return status; } bufferSize = (long) nGreyChanges*sizeof(OBTime); nOBTs = nGreyChanges; obtBuffer=NULL; status = DALallocateDataBuffer((void **)&obtBuffer, bufferSize,status ); if( status != ISDC_OK ){ RILlogMessage( NULL,Error_3, "%d :Problem allocating memory for grey filter OBTime buffer", status ); return status ; } if( chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_0, "Grey filter OBT buffer allocated to size: %d", bufferSize); } /* Read status and grey filter changes */ DALtype = DAL_BYTE; status = DALtableGetCol( statusPtr, "MODE", 0, &DALtype, &nValuesRead, byteBuffer, status ); if( status != ISDC_OK ){ RILlogMessage( NULL,Error_3, "%d :Could not read in instrument mode values from %s", status, structName ); return status ; } if ( nValuesRead!= nGreyChanges ){ status = J_SRC_BAD_NUM_VALUES ; RILlogMessage( NULL,Error_3, "%d : Wrong number of instrument mode values read in from %s", status, structName ); return status; } /* Allocate memory for modeValues*/ bufferSize = (long) nGreyChanges*sizeof(int); status = DALallocateDataBuffer( (void **)&modeValues, bufferSize, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not allocate memory for modeValues", status ); return status; } for ( i=0 ; i 0) { bufferSize = nGreyChanges*sizeof(double); status = DALallocateDataBuffer( (void **)&statusIJD, bufferSize, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not allocate memory for statusIJD", status ); return status; } status = DAL3AUXconvertOBT2IJD(theSWGptr,Accuracy, nGreyChanges, statusOBT, statusIJD, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Error when converting Grey filter times from OBT to IJD", status ); return status; } if( chatty > J_CHATTY_NORMAL ){ RILlogMessage(NULL,Log_0, "Number of Grey filter times converted to IJD: %d ", nGreyChanges ); } if( nGreyChanges > 0 && chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_0, "Greyfilter time(IJD), Filter value, mode "); i = 0; while (i < 10 && i < nGreyChanges){ RILlogMessage(NULL,Log_0," %lf %d %d", statusIJD[i], greyValues[i], modeValues[i]); i = i + 1; } } } /*--------------------------------------------------------------------- * Set initial values for Grey filter correction. *--------------------------------------------------------------------*/ if( nGreyChanges > 0) { greyCorr = 32.0/((float) (greyValues[0] + 1)); /* greyCorr = 1.0; DESTEST */ nextGrey = 1; if(nextGrey < nGreyChanges) { timeIJDGreyNext = statusIJD[nextGrey]; } else { timeIJDGreyNext = statusIJD[0]; } } /************* Grey filter OBT -> IJD conversion completed **************/ /************************************************************************* READ GOOD TIME INTERVALS (GTI) **************************************************************************/ /* Obtain Good-Time Interval (GTI) information. If skipGTI = 1, No GTI data will be read. If no GTI data is found skipGTI is set to 1 and all data within the time range is used. In present code skipGTI is always = 0! /SL020501 */ if(skipGTI != 1){ status = j_read_GTI(theSWGptr,JEMX_num,gtiNames, &nGTI,>iStartOBT,>iEndOBT, >iStart,>iEnd, chatty,status); if (J_SRC_NO_GTI == status) { RILlogMessage(NULL,Warning_2, "No Good Time in selected GTI tables => exiting!"); return status; } if (ISDC_OK != status) { RILlogMessage(NULL,Error_2, "Error in reading GTI information! status = %d", status); } else if (nGTI > 0 && chatty >= J_CHATTY_VERBOSE) { RILlogMessage(NULL,Log_1, "Succesfully read %d Good Time Intervals",nGTI); } nGTIs = nGTI; } if( nGTIs == 0){ RILlogMessage(NULL, Log_0, "No GTIs found. Using all data within time range."); } else{ RILlogMessage(NULL, Log_0,"%d GTIs found",nGTIs); } /* If timeStart and timeStop parameters are given, restrict the GTIs (if found) with these values. The else-values of timeStartStop are set just so the conversion routine will not be upset (dont know if this is necessary). */ if( nGTIs > 0 && (timeStart > 0 || timeStop > 0) ){ if (timeStart > 0) { timeStartStop[0] = timeStart; } else{ timeStartStop[0] = timeStop; } if (timeStop > 0) { timeStartStop[1] = timeStop; } else{ timeStartStop[1] = timeStart; } status = DAL3AUXconvertIJD2OBT(theSWGptr,Accuracy,2, timeStartStop,timeStartStopOBT,status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Error in IJD -> OBT conversion of timeStart, timeStop",status ); return status; } /* Count the number of GTIs before timeStart (in OBT) and delete those GTIs. */ if( timeStart > 0) { iGTI = 0; /* Count number of GTIs to delete. */ for ( i=0 ; i< nGTIs ; i++){ if (timeStartStopOBT[0] > gtiEndOBT[i]) { iGTI = iGTI + 1; } } if (iGTI > 0){ /* Delete first iGTI GTI ranges. */ for ( i=0 ; i< nGTIs-iGTI ; i++){ gtiStartOBT[i] = gtiStartOBT[i+iGTI]; gtiEndOBT[i] = gtiEndOBT[i+iGTI]; } nGTIs = nGTIs - iGTI; } /* Any GTIs left? There should be! */ if(nGTIs <= 0) { status = J_SRC_WRONG_VALUE; RILlogMessage(NULL, Error_2, "%d : Inconsistent GTI and time range parameters",status ); return status; } /* Now check if the first GTI starts before timeStart. If so, modify the GTI-value. */ if(timeStartStopOBT[0] > gtiStartOBT[0]) { gtiStartOBT[0] = timeStartStopOBT[0]; } } /* Now the GTIs are corrected for timeStart. Lets continue with timeStop. */ if( timeStop > 0) { iGTI = 0; /* Count number of GTIs to delete. */ for ( i=0 ; i< nGTIs ; i++){ if (timeStartStopOBT[1] < gtiStartOBT[i]) { iGTI = iGTI + 1; } } nGTIs = nGTIs - iGTI; /* Any GTIs left? There should be! */ if(nGTIs <= 0) { status = J_SRC_WRONG_VALUE; RILlogMessage(NULL, Error_2, "%d : Inconsistent GTI and time range parameters",status ); return status; } if (timeStartStopOBT[1] < gtiEndOBT[nGTIs-1]) { gtiEndOBT[nGTIs-1] = timeStartStopOBT[1]; } } } /* If timeStart and timeStop parameters are given, but no GTIs, then set one GTI with these limits. NOTE: We do not check if there are any data in this range! */ if( nGTIs == 0){ if (timeStart > -0.000001) { timeStartStop[0] = timeStart; } else { /* Use SWG time!! */ RILlogMessage(NULL, Log_0,"Using SWG Start time"); } if (timeStop > 0.0) { timeStartStop[1] = timeStop; } else { /* Use SWG time!! */ RILlogMessage(NULL, Log_0,"Using SWG Stop time"); } RILlogMessage(NULL, Log_0, "Using all data within time range. NO CHECKING FOR DATA GAPS!"); status = DAL3AUXconvertIJD2OBT(theSWGptr,Accuracy,2, timeStartStop,timeStartStopOBT,status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Error in IJD -> OBT conversion of timeStart, timeStop",status ); return status; } gtiStartOBT[0] = timeStartStopOBT[0]; gtiEndOBT[0] = timeStartStopOBT[1]; nGTIs = 1; } /************************************************************************* READING DATA STRUCTURE JMXi-DEAD-SCP **************************************************************************/ /* The follow section does: * - If skipDEAD = 1 or if the Dead Time data structure is not found * the number of Dead times is set to zero and no Dead time corrections * are applyed. * Otherwise * - The dead time values and time the time for which they are valid are * read from the DS. * - Memory for storage is allocated. * - The OBT times are transformed to IJD. * - The initial value of the Dead time correction (deadCorr) is * calculated and the time in IJD when it will change is stored in * deadTimeIJDNext -------------------------------------------------------------------------*/ /* Obtain Dead Time table information. */ if(skipDEAD != 1) { strcpy( structName, jemxStr ); strcat( structName, J_DEAD_DS); RILlogMessage(NULL, Log_0,"Reading data structure: %s", structName,status); deadPtr = NULL; status = DALobjectFindElement(theSWGptr, structName, &deadPtr, status); if ( status!=ISDC_OK ){ RILlogMessage(NULL, Warning_2, "%d : Could not find extension %s", status, structName); status = ISDC_OK; /* Reset status to OK and go on. */ skipDEAD = 1; } } if (skipDEAD == 1) { nDeadTimes = 0; } else { /* Find how many Dead time values there are to read in */ status = DALtableGetColStruct( deadPtr, 0, &nDeadTimes, "DEADTIME", &diskType, NULL, NULL, status); if (status!=ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Couldn't find number of dead times in %s",status,structName); return status; } /* If there are dead times, get the OBT values in the extension First however, check that the current OBT buffer has enough room, and allocate space for the OBT_START and OBT_END values */ if ( nDeadTimes == 0){ status = J_SRC_NO_INPUT_VALUES; RILlogMessage(NULL, Error_2, "%d : No dead time values available in SWG", status); return status; } if ( nDeadTimes > nOBTs ){ status = DALfreeDataBuffer( (void *) obtBuffer,status ); if(status!=ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not free up obt data buffer", status); return status; } nOBTs = nDeadTimes; bufferSize = nDeadTimes * sizeof(OBTime); obtBuffer=NULL; status = DALallocateDataBuffer((void **)&obtBuffer, bufferSize, status ); if( status != ISDC_OK ){ RILlogMessage( NULL,Error_3, "%d :Problem allocating memory for deadtime OBTime buffer", status ); return status ; } } /* Now read in the dead time OBTs */ status = DAL3GENtableGetOBT( deadPtr,"OB_TIME",0,&nValuesRead, obtBuffer,status ); if( status != ISDC_OK ){ RILlogMessage( NULL,Error_3, "%d :Could not read in dead time OBT values from %s", status, structName ); return status ; } if ( nDeadTimes!= nValuesRead ){ status = J_SRC_BAD_NUM_VALUES ; RILlogMessage( NULL,Error_3, "%d : Wrong number of dead time OBTs read in from %s", status, structName ); return status; } bufferSize = nDeadTimes* 4 * sizeof(OBTime); status = DALallocateDataBuffer( (void **)&deadTimeOBT, bufferSize, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not allocate memory for deadTimeOBT", status ); return status; } for ( i=0 ; i IJD. * ---------------------------------------------------------------------*/ if( nDeadTimes > 0) { bufferSize = nDeadTimes*sizeof(double); status = DALallocateDataBuffer( (void **)&deadTimeIJD, bufferSize, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not allocate memory for deadTimeIJD", status ); return status; } status = DAL3AUXconvertOBT2IJD(theSWGptr,Accuracy, nDeadTimes, deadTimeOBT, deadTimeIJD, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Error when converting Dead times from OBT to IJD", status ); return status; } if( chatty > J_CHATTY_NORMAL ){ RILlogMessage(NULL,Log_0, "Number of Dead times converted to IJD: %d ", nDeadTimes ); } if( nDeadTimes > 0 && chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_0, "Time(IJD), Dead time, rateCor, deadEff. (first 4)"); i = 0; while (i < 4 && i < nDeadTimes){ RILlogMessage(NULL,Log_0," %lf %lf %lf %lf", deadTimeIJD[i], deadTimes[i], rateCor[i], deadEff[i]); i = i + 1; } } } /*--------------------------------------------------------------------- * Set initial values for dead time correction. *--------------------------------------------------------------------*/ if(nDeadTimes > 0) { /* if(deadTimes[0] != 1.0) { */ /* deadCorr = 1.0/(1.0-deadTimes[0]); */ /* } */ deadCorr = rateCor[0]; nextDead = 1; if(nextDead < nDeadTimes) { deadTimeIJDNext = deadTimeIJD[nextDead]; } else { deadTimeIJDNext = deadTimeIJD[0]; } } /************************************************************************* READING MATERIAL PROPERIES DATA STRUCTURES *************************************************************************/ /***************READING JEMX-COLL-MOD****************************************/ /* Obtain Collimator information. */ strcpy( structName, jemxStr ); strcat( structName, J_COLL_DS); if( chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL, Log_0,"Reading data structure: %s", structName,status); } /* dimAxes[0] = (long) 2 ; dimAxes[1] = (long) 1153 ; */ collPtr = NULL; status = DALobjectFindElement(instrGrpPtr, structName, &collPtr, status); if (status!=ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not find extension %s", status, structName); return status; } if( chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_0, "Data structure found"); } /* Read keywords, e.g. collimator height. */ status = DALattributeGet(collPtr, "CLHEIGHT", DAL_DOUBLE, (void *)&collHeight, NULL, NULL, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not read collemator height from %s", status, structName); return status; } if( chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_0, "Collimator height = %f", collHeight); } /* Collimator tilt test collTiltAngle (radians) = Tilt angle relative to optical axis. (Unit: arcmin transformed to radians) collDirectionAngle = Azimuthal tilt direction angle (Unit: cercular fraction transformed to radians) collTiltX & Y = Collimator tilt (displacement) of upper plane in the instrument X and Y directions resp. (Unit: mm) */ if( diagnosticMode == 5){ overrideCollTilt = diagnosticParam; } if( overrideCollTilt > -0.0001){ collDirectionAngle = overrideCollTilt - (double)((int)overrideCollTilt); /* collTiltAngle = Azimuthal tilt direction angle */ collTiltAngle = (3.14159/180.0)* (overrideCollTilt - collDirectionAngle)/60.0; RILlogMessage(NULL,Log_0, "collTiltAngle: %f", collTiltAngle ); collDirectionAngle = collDirectionAngle*3.14159*2.0; RILlogMessage(NULL,Log_0, "collDirectionAngle: %f", collDirectionAngle ); collTiltX = collHeight*tan(collTiltAngle)* cos(collDirectionAngle); collTiltY = collHeight*tan(collTiltAngle)* sin(collDirectionAngle); RILlogMessage(NULL,Log_0, "COLLIMATOR TILT"); RILlogMessage(NULL,Log_0, "Top level displacement in X: %f mm.", collTiltX ); RILlogMessage(NULL,Log_0, "Top level displacement in Y: %f mm.", collTiltY ); } /* Find how many collimator cross point values there are to read in */ status = DALtableGetColStruct( collPtr, 0, &nColl, "XSECTBOT",&diskType, NULL, NULL, status); if (status!=ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Couldn't find number of collimator array values in %s", status, structName); return status; } /* If there are collimator values, get the values in the extension First however, check that the current float buffer has enough room */ if ( nColl == 0){ status = J_SRC_NO_INPUT_VALUES; RILlogMessage(NULL, Error_2, "%d : No collimator values available ", status); return status; } if ( nColl > nFloats ){ status = DALfreeDataBuffer( (void *) floatBuffer,status ); if(status!=ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not free up float data buffer", status); return status; } nFloats = nColl; bufferSize = nColl * sizeof(float); floatBuffer=NULL; status = DALallocateDataBuffer((void **)&floatBuffer, bufferSize, status ); if( status != ISDC_OK ){ RILlogMessage( NULL,Error_3, "%d :Problem allocating memory for float buffer", status ); return status ; } } status = DALtableGetCol( collPtr, "XSECTBOT", 0, &diskType, &nValuesRead, (void *)floatBuffer, status); if( status != ISDC_OK ){ RILlogMessage( NULL, Error_2, "%d :Could not get XSECTBOT values from %s", status, structName ); return status; } if( chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_0, "Read %d XSECTBOT values",nValuesRead ); } if ( nColl!= nValuesRead ){ status = J_SRC_BAD_NUM_VALUES ; RILlogMessage( NULL,Error_3, "%d : Wrong number of collimator points read in from %s", status, structName ); return status; } for ( i=0 ; i -0.0001){ collimatorXTop[ix][jy] = collXCrossBot[i] + collTiltX; collimatorYTop[ix][jy] = collYCrossBot[i] + collTiltY; }else{ collimatorXTop[ix][jy] = collXCrossTop[i]; collimatorYTop[ix][jy] = collYCrossTop[i]; } /* The diameter of the collimator is 250 mm, just so you remember */ } /************************************************************************* READING DATA STRUCTURE JMXi-DPOS-MOD **************************************************************************/ /* Obtain detector position resolution as function of energy. */ strcpy( structName, jemxStr ); strcat( structName, J_DPOS_DS); if( chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL, Log_0,"Reading data structure: %s", structName,status); } posResPtr = NULL; status = DALobjectFindElement(instrGrpPtr, structName, &posResPtr, status); if (status!=ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not find extension %s", status, structName); return status; } if( chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_0, "Data structure found"); } /* Find how many detector resolution values there are to read in */ status = DALtableGetColStruct( posResPtr, 0, &nPosRes, "ENERGY",&diskType, NULL, NULL, status); if (status!=ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Couldn't find number of detector resolution values in %s", status, structName); return status; } /* If there are detector resolution values, get the values in the extension First however, check that the current float buffer has enough room */ if ( nPosRes == 0){ status = J_SRC_NO_INPUT_VALUES; RILlogMessage(NULL, Error_2, "%d : No detector resolution values available ", status); return status; } if ( nPosRes > nFloats ){ status = DALfreeDataBuffer( (void *) floatBuffer,status ); if(status!=ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not free up float data buffer", status); return status; } nFloats = nPosRes; bufferSize = nPosRes * sizeof(float); floatBuffer=NULL; status = DALallocateDataBuffer((void **)&floatBuffer, bufferSize, status ); if( status != ISDC_OK ){ RILlogMessage( NULL,Error_3, "%d :Problem allocating memory for float buffer", status ); return status ; } } status = DALtableGetCol( posResPtr, "ENERGY", 0, &diskType, &nValuesRead, (void *)floatBuffer, status); if( status != ISDC_OK ){ RILlogMessage( NULL, Error_2, "%d :Could not get ENERGY values from %s", status, structName ); return status; } if( chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_0, "Read %d Energy values",nValuesRead ); } if ( nPosRes!= nValuesRead ){ status = J_SRC_BAD_NUM_VALUES ; RILlogMessage( NULL,Error_3, "%d : Wrong number detector resolution energies read in from %s", status, structName ); return status; } for ( i=0 ; i 0) { status = DALallocateDataBuffer( (void **) &posResChannel, nPosRes*sizeof(int), status ); if (status != ISDC_OK) { if (DAL_MALLOC_ERROR==status) { status = J_SRC_OUT_OF_MEMORY; } RILlogMessage(NULL,Error_3, "Could not allocate memory for POSRES channel values"); return status; } /*-------------------------------------------------------------------- Using the detector resolution we can compute the leakFactor, which is how much of the flux onto an open mask hole will be detected outside the projection of the hole on the detector. Of the flux leaking out some (= mask open fraction) will on average leak into another open hole. The leakFraction is corrected for that effect. In normal mode the leakage computation is based on a parametrization, with parameters from the .h-file. in diagnosticMode=2 the parmeters are computed by a ray- tracing procedure. ------------------------------------------------------------------ */ if(diagnosticMode == 2) { status = j_src_leakage(posRes, posResEnergy, nPosRes, openFraction, chatty, status); } } /************************************************************************* WITH CHANNEL/ENERGY TABLE AND POSRES AVAILABLE WE CAN COMPUTE THE LEAKAGE CORRECTION COEFFICIENTS. **************************************************************************/ for ( i=0 ; i closed. To take out open -> open we multiply with (1-openFraction). This is not really true when the collimator is considered. */ leakage[i] = polynom*(1.0-openFractionAve); } /************************************************************************* READING DATA STRUCTURE JMXi-ATXE-MOD **************************************************************************/ /* Xenon attenuation length as function of energy. */ strcpy( structName, jemxStr ); strcat( structName, J_XENON_DS); if( chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL, Log_0,"Reading data structure: %s", structName,status); } atXePtr = NULL; status = DALobjectFindElement(instrGrpPtr, structName, &atXePtr, status); if (status!=ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not find extension %s", status, structName); return status; } if( chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_0, "Data structure found"); } /* Find how many values there are to read in */ status = DALtableGetColStruct( atXePtr, 0, &nAtXe, "ENERGY",&diskType, NULL, NULL, status); if (status!=ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Couldn't find number of detector resolution values in %s", status, structName); return status; } /* If there are detector resolution values, get the values in the extension First however, check that the current float buffer has enough room */ if ( nPosRes == 0){ status = J_SRC_NO_INPUT_VALUES; RILlogMessage(NULL, Error_2, "%d : No detector resolution values available ", status); return status; } if ( nAtXe > nFloats ){ status = DALfreeDataBuffer( (void *) floatBuffer,status ); if(status!=ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not free up float data buffer", status); return status; } nFloats = nAtXe; bufferSize = nAtXe * sizeof(float); floatBuffer=NULL; status = DALallocateDataBuffer((void **)&floatBuffer, bufferSize, status ); if( status != ISDC_OK ){ RILlogMessage( NULL,Error_3, "%d :Problem allocating memory for float buffer", status ); return status ; } } status = DALtableGetCol( atXePtr, "ENERGY", 0, &diskType, &nValuesRead, (void *)floatBuffer, status); if( status != ISDC_OK ){ RILlogMessage( NULL, Error_2, "%d :Could not get ENERGY values from %s", status, structName ); return status; } if( chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_0, "Read %d Energy values",nValuesRead ); } if ( nAtXe!= nValuesRead ){ status = J_SRC_BAD_NUM_VALUES ; RILlogMessage( NULL,Error_3, "%d : Wrong number detector resolution energies read in from %s", status, structName ); return status; } for ( i=0 ; i nFloats ){ status = DALfreeDataBuffer( (void *) floatBuffer,status ); if(status!=ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not free up float data buffer", status); return status; } nFloats = nQeff; bufferSize = nQeff * sizeof(float); floatBuffer=NULL; status = DALallocateDataBuffer((void **)&floatBuffer, bufferSize, status ); if( status != ISDC_OK ){ RILlogMessage( NULL,Error_3, "%d :Problem allocating memory for float buffer", status ); return status ; } } status = DALtableGetCol( qeffPtr, "ENERGY", 0, &diskType, &nValuesRead, (void *)floatBuffer, status); if( status != ISDC_OK ){ RILlogMessage( NULL, Error_2, "%d :Could not get ENERGY values from %s", status, structName ); return status; } if( chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_0, "Read %d QEFF Energy values",nValuesRead ); } if ( nQeff!= nValuesRead ){ status = J_SRC_BAD_NUM_VALUES ; RILlogMessage( NULL,Error_3, "%d : Wrong number quantum efficiency energies read in from %s", status, structName ); return status; } for ( i=0 ; i nFloats ){ status = DALfreeDataBuffer( (void *) floatBuffer,status ); if(status!=ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not free up float data buffer", status); return status; } nFloats = nLineEnergies; bufferSize = nLineEnergies * sizeof(float); floatBuffer=NULL; status = DALallocateDataBuffer((void **)&floatBuffer, bufferSize, status ); if( status != ISDC_OK ){ RILlogMessage( NULL,Error_3, "%d :Problem allocating memory for float buffer", status ); return status ; } } /* ------------------------------------------------------------------------ Read ENERG_LO ---------------------------------------------------------------------- */ status = DALtableGetCol( lenergyPtr, "ENERG_LO", 0, &diskType, &nValuesRead, (void *)floatBuffer, status); if( status != ISDC_OK ){ RILlogMessage( NULL, Error_2, "%d :Could not get ENERG_LO values from %s", status, structName ); return status; } if( chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_0, "Read %d ARF ENERG_LO values",nValuesRead ); } if (nLineEnergies != nValuesRead ){ status = J_SRC_BAD_NUM_VALUES ; RILlogMessage( NULL,Error_3, "%d : Wrong number of ENERG_LO values read in from %s", status, structName ); return status; } for ( i=0 ; i nFloats ){ status = DALfreeDataBuffer( (void *) floatBuffer,status ); if(status!=ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not free up float data buffer", status); return status; } nFloats = nIscal; bufferSize = nIscal * sizeof(float); floatBuffer=NULL; status = DALallocateDataBuffer((void **)&floatBuffer, bufferSize, status ); if( status != ISDC_OK ){ RILlogMessage( NULL,Error_3, "%d :Problem allocating memory for float buffer", status ); return status ; } } status = DALtableGetCol( iscalPtr, "SCALFACT", 0, &diskType, &nValuesRead, (void *)floatBuffer, status); if( status != ISDC_OK ){ RILlogMessage( NULL, Error_2, "%d :Could not get SCALFACT values from %s", status, structName ); return status; } if ( nIscal!= nValuesRead ){ status = J_SRC_BAD_NUM_VALUES ; RILlogMessage( NULL,Error_3, "%d : Wrong number bkg scaling factors read in from %s", status, structName ); return status; } for ( i=0 ; i nOBTs ){ status = DALfreeDataBuffer( (void *) obtBuffer,status ); if(status!=ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not free up obt data buffer", status); return status; } nOBTs = nIscal; bufferSize = nIscal * sizeof(OBTime); obtBuffer=NULL; status = DALallocateDataBuffer((void **)&obtBuffer, bufferSize, status ); if( status != ISDC_OK ){ RILlogMessage( NULL,Error_3, "%d :Problem allocating memory for bkg scaling OBTime buffer", status ); return status ; } } status = DAL3GENtableGetOBTBins( iscalPtr, "DELTAOBT", 0, 1, nIscal, &nValuesRead, obtBuffer, status); if( status != ISDC_OK ){ RILlogMessage( NULL, Error_2, "%d :Couldn't get DELTAOBT values from %s", status,structName); return status; } if ( nIscal != nValuesRead ){ status = J_SRC_BAD_NUM_VALUES ; RILlogMessage( NULL,Error_3, "%d : Wrong number instrument bkg scaling values read from %s", status, structName ); return status; } for ( i=0 ; i nFloats ){ status = DALfreeDataBuffer( (void *) floatBuffer,status ); if(status!=ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not free up float data buffer", status); return status; } nFloats = nDscal; bufferSize = nDscal * sizeof(float); floatBuffer=NULL; status = DALallocateDataBuffer((void **)&floatBuffer, bufferSize, status ); if( status != ISDC_OK ){ RILlogMessage( NULL,Error_3, "%d :Problem allocating memory for float buffer", status ); return status ; } } status = DALtableGetCol( dscalPtr, "SCALFACT", 0, &diskType, &nValuesRead, (void *)floatBuffer, status); if( status != ISDC_OK ){ RILlogMessage( NULL, Error_2, "%d :Could not get SCALFACT values from %s", status, structName ); return status; } if ( nDscal!= nValuesRead ){ status = J_SRC_BAD_NUM_VALUES ; RILlogMessage( NULL,Error_3, "%d : Wrong number diffuse bkg scaling factors read in from %s", status, structName ); return status; } for ( i=0 ; i nOBTs ){ status = DALfreeDataBuffer( (void *) obtBuffer,status ); if(status!=ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not free up obt data buffer", status); return status; } nOBTs = nDscal; bufferSize = nDscal * sizeof(OBTime); obtBuffer=NULL; status = DALallocateDataBuffer((void **)&obtBuffer, bufferSize, status ); if( status != ISDC_OK ){ RILlogMessage( NULL,Error_3, "%d :Problem allocating memory for bkg scaling OBTime buffer", status ); return status ; } } status = DAL3GENtableGetOBTBins( dscalPtr, "DELTAOBT", 0, 1, nDscal, &nValuesRead, obtBuffer, status); if( status != ISDC_OK ){ RILlogMessage( NULL, Error_2, "%d :Couldn't get DELTAOBT values from %s", status,structName); return status; } if ( nDscal != nValuesRead ){ status = J_SRC_BAD_NUM_VALUES ; RILlogMessage( NULL,Error_3, "%d : Wrong number diffuse bkg scaling values read from %s", status, structName ); return status; } for ( i=0 ; i J_CHATTY_NORMAL ) { RILlogMessage(NULL, Log_0, "Satellite pointing direction"); RILlogMessage(NULL, Log_0, "RA_SCX = %f DEC_SCX = %f", RA_SCX, DEC_SCX); RILlogMessage(NULL, Log_0, "RA_SCZ = %f DEC_SCZ = %f", RA_SCZ, DEC_SCZ); } } /************************************************************************* READING DATA STRUCTURE JMXi-SRCL-RES **************************************************************************/ /* Find and find out about JMXi-SRCL-RES */ strcpy( structName, jemxStr); strcat( structName, J_SRC_LIST_DS); srcListPtr = NULL; status = DALobjectFindElement(theSWGptr, structName, &srcListPtr, status); if (status!=ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not find extension %s", status, structName); return J_SRC_NO_SOURCES; } status = DALtableGetColStruct( srcListPtr, 0, &nSources, "SOURCE_ID", &diskType, &stringLen, NULL, status); if (status!=ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not find structure of column SOURCE_ID in %s", status, structName); return status; } if (nSources == 0){ RILlogMessage(NULL, Warning_2, "Number of sources is ZERO!. Let's quit."); /* The following does not delete the -SPE data structure as intended. */ if(doSpec == 1) { strcpy( structName, jemxStr); strcat( structName, J_SRC_SPEC_DS); specPtr = NULL; status = DALobjectFindElement ( theSWGptr, structName, &specPtr, status); /* Detach child status = DALelementDetach(specPtr,theSWGptr,status); if (ISDC_OK!=status) { RILlogMessage(NULL,Error_1, " Could not detach -SPE"); return(status); } */ /* And remove it by closing */ status = DALobjectClose(specPtr,DAL_DELETE,status); if (ISDC_OK!=status) { RILlogMessage(NULL,Error_1, " Could not remove -SPE"); return(status); } else if (J_CHATTY_VERBOSE<=chatty) { RILlogMessage(NULL,Log_1, "%s data structure has been closed " "and deleted!",structName); } } return status; } /* make string buffer for source ID string */ if (nChars < nSources*(stringLen+1) ){ if ( ( stringBuffer!=NULL)||(nStrings>0) ){ status = DALfreeStringBuffer(stringBuffer, (int) nStrings, status); if (status!=ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not free string buffer", status); return status; } } nStrings = nSources; status = DALallocateStringBuffer(&stringBuffer, (int) nStrings, (int)stringLen, status); if (status!=ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not allocate string data buffer", status); return status; } nChars = nSources*(stringLen+1); } /* Get the source ID strings */ status = DALtableGetColStrings( srcListPtr, "SOURCE_ID", 0, 1, nSources, &nValuesRead, stringBuffer, status); if (status!=ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : could not read column strings SOURCE_ID in %s", status, structName); return status; } for ( i=0 ; i nDoubles ){ status = DALfreeDataBuffer( (void *) dblBuffer,status ); if(status!=ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not free up double data buffer", status); return status; } nDoubles = nSources; bufferSize = nDoubles * sizeof(double); dblBuffer=NULL; status = DALallocateDataBuffer((void **)&dblBuffer, bufferSize, status ); if( status != ISDC_OK ){ RILlogMessage( NULL,Error_3, "%d :Problem allocating memory for double buffer", status ); return status ; } } diskType = DAL_DOUBLE; if(useRaDec != 1) { /* First get all values of COSX */ status = DALtableGetCol( srcListPtr, "COSX_JMX", 0, &diskType, &nValuesRead, (void *)dblBuffer, status); if( status != ISDC_OK ){ RILlogMessage( NULL, Error_2, "%d :Could not get COSX_JMX values from %s", status,structName); return status; } if ( nSources!= nValuesRead ){ status = J_SRC_BAD_NUM_VALUES ; RILlogMessage( NULL,Error_3, "%d : Wrong number of COSX_JMX values read in from %s", status, structName ); return status; } for ( i=0 ; i 0.0){ if( JEMX_num == JMX1 ) { /* 180 deg rotation */ srcY[i] = detMaskDist*srcCosY[i]/srcCosX[i]; srcZ[i] = detMaskDist*srcCosZ[i]/srcCosX[i]; } if( JEMX_num == JMX2 ) { /* 180 deg rotation */ srcY[i] = -detMaskDist*srcCosY[i]/srcCosX[i]; srcZ[i] = -detMaskDist*srcCosZ[i]/srcCosX[i]; } if( diagnosticMode == 4) { if(diagnosticParam < 0.0) { xCoord = srcY[i]; yCoord = srcZ[i]; status = j_src_randXY(&xCoord, &yCoord, radiusLimit, chatty, status); srcY[i] = xCoord; srcZ[i] = yCoord; } } detDepthX[i] = 7.33; /* PI dependent maybe */ detDepthY[i] = srcY[i]*detDepthX[i]/detMaskDist; detDepthZ[i] = srcZ[i]*detDepthX[i]/detMaskDist; } else { status = J_SRC_WRONG_VALUE; RILlogMessage(NULL, Error_2, "%d : Negative source position X-coordinate not allowed", status); return status; } } /* Negative diagnosticParam for this mode means to randomize source position, done above. So now set it positiv. */ if( diagnosticMode == 4) { if(diagnosticParam < 0.0) { diagnosticParam = - diagnosticParam; } } /* If diagnosticMode is for position mapping Ignore all but the first source. Then add sources at array of source positions. */ if( diagnosticMode == 3) { if(diagnosticParam > J_SRC_ACCURACY) { diagn3Scale = diagnosticParam; } else { diagn3Scale = J_SRC_DIAGN3_SCALE; /* Default */ } srcY[J_SRC_MAXSRC-1] = srcY[0]; srcZ[J_SRC_MAXSRC-1] = srcZ[0]; nSources = 25; for ( i=0 ; i<5 ; i++){ for ( j=0 ; j<5 ; j++){ srcY[i*5+j] = srcY[J_SRC_MAXSRC-1] + diagn3Scale*( (double) (i-2)); srcZ[i*5+j] = srcZ[J_SRC_MAXSRC-1] + diagn3Scale*( (double) (j-2)); } } /* In diagnostic Mode 3 (position mapping) we use the same vignetting correction factor for all positions. Maybe I'll fix this later.... */ if(vignCorr == 0){ RILlogMessage(NULL,Log_0, "In position mapping mode we use the SAME vignetting correction" "for all 25 positions!"); for ( i=0 ; i<25 ; i++){ srcCosX[i] = srcCosX[0]; srcCosY[i] = srcCosX[0]; srcCosZ[i] = srcCosY[0]; } } if( useRaDec != 0) { useRaDec = 0; RILlogMessage(NULL,Log_0, "In position mapping mode we ignore the USE RA,DEC parameter"); } for ( i=1 ; i= J_CHATTY_NORMAL ){ RILlogMessage(NULL,Log_0, "Number of sources = %d", (int)nSources); if( useRaDec == 1) { RILlogMessage(NULL,Log_0, "Src no. SrcID RA(degrees) DEC(degrees)"); for ( i=0 ; i -1.0 && a < 1.0){ srcOffAxisAngle[i] = (float) (asin(a)*180.0/J_COR_PI); if( chatty >= J_CHATTY_NORMAL ){ RILlogMessage(NULL,Log_0, "Off-axis angle for source %d: %f degrees", ((int)i)+1,srcOffAxisAngle[i]); } }else{ srcOffAxisAngle[i] = 90.0; if( chatty >= J_CHATTY_NORMAL ){ RILlogMessage(NULL, Warning_2, "Source %d off-axis angle (OFFANGLE) is out of range.", ((int)i)+1); } } } /************************************************************************* COMPUTE OPEN AND CLOSED AREA AS WELL AS MASK OPENFRACTION AS SEEN BY EACH INDIVIDUAL SOURCE. j_src_through_coll: Neglects detector penetration so these are taken into account by increasing the collimator height. **************************************************************************/ if(precisionLevel == 0) { doColl = 0; } if(precisionLevel > 9) { bufferSize = nSources*J_SRC_PIF_MAX_ENERGIES*J_NUM_X_PIXELS* J_NUM_Y_PIXELS*sizeof(float); status = DALallocateDataBuffer( (void **)&pif, bufferSize, status); if( status != ISDC_OK ){ RILlogMessage( NULL, Error_2, "%d :Could not allocate float values PIF array", status); return status; } for ( i=0 ; i 19) { /* Estimate the area of each individual pixel and also keep the lower left pixel coordinates in detPixLLX & detPixLLY. */ status = j_src_pixel_area( detPixArea, detPixLLX, detPixLLY, detCorX, detCorY, radiusLimit, chatty, status); /* Statistics of pixel area distribution. */ if(chatty > J_CHATTY_VERBOSE){ for ( ix=0 ; ix 0 && iPixFlux<20) { pixAreaDistr[iPixFlux] = pixAreaDistr[iPixFlux] + 1.0; }else if(iPixFlux > 19){ pixAreaDistr[19] = pixAreaDistr[19] + 1.0; } } } } } /* For each source: Loop over the detector pixels For each pixel: Define N*N subpixels. For each subpixel: Add detector response to the pif. Comments: - pifOffset is the offset for a particular source in the allocated memmory for pif. - subPifOffset is the corresponding offset in subPif for a particular sub pixel. */ /* Find which channels the PIF energies correspond to. */ for ( iPifEnergy=0 ; iPifEnergy=fullEMin[i] && pifEnergy[iPifEnergy]<=fullEMax[i]){ pifChannel[iPifEnergy] = i; } } if( chatty > J_CHATTY_NORMAL ){ RILlogMessage(NULL,Log_0, "PIF CHANNEL, ENERGY %d %f", pifChannel[iPifEnergy], pifEnergy[iPifEnergy]); } } bufferSize = nstep*nstep*J_SRC_SUBPIF_SIZE* J_SRC_SUBPIF_SIZE*sizeof(float); status = DALallocateDataBuffer( (void **)&subPif, bufferSize, status); if( status != ISDC_OK ){ RILlogMessage( NULL, Error_2, "%d :Could not allocate float values subPif array", status); return status; } for ( iPifEnergy=0 ; iPifEnergy J_CHATTY_NORMAL ){ RILlogMessage(NULL,Log_0," "); } if(precisionLevel > 19 && precisionLevel < 30 ) { status = j_src_pif_create20(iSource, nSources, srcY[iSource], srcZ[iSource], isCrab, mask, detMaskDist, longsph, shortsph, balk, collimatorXBot, collimatorYBot, collimatorXTop, collimatorYTop, collimator, collHeight, detMap, detCorX, detCorY, posResInterpol, detDepth, detDepthMax, skipHotSpot, skipNearDeadAnode, maskRimCut, radiusLimit, iChan, subPif, pifWork, nSubPifPix, pifInterpolEnergy, pifEnergy, &pifInterpol, radMask, chatty, status); } if(precisionLevel == 30) { status = j_src_pif_create30(iSource, nSources, srcY[iSource], srcZ[iSource], isCrab, mask, detMaskDist, longsph, shortsph, balk, collimatorXBot, collimatorYBot, collimatorXTop, collimatorYTop, collimator, collHeight, detMap, detCorX, detCorY, posResInterpol, detDepth, detDepthMax, detPixArea, detPixLLX, detPixLLY, skipHotSpot, skipNearDeadAnode, maskRimCut, radiusLimit, iChan, subPif, pifWork, nSubPifPix, pifInterpolEnergy, pifEnergy, &pifInterpol, radMask, chatty, status); } /* For this source, sort the pif values and compute the number of elements treated as open and closed. leakage values are used to correct for the fact that flux is leaking away from the illuminated area into the shadowed area. */ if( chatty >= J_CHATTY_NORMAL ){ RILlogMessage(NULL, Log_0, "Sum up open and closed areas (mm2) for source %d " "at %f keV", (int)iSource+1, pifEnergy[iPifEnergy]); } status = j_src_pif_sort( pifWork, detCorX, detCorY, &openCut, &closedCut, radMask, &openArea1, &closedArea1, &effOpenArea1, &leakageFrOpen1, &leakageToClosed1, radiusLimit, chatty, status); /* status = j_src_pif_sort25( pifWork, detCorX, detCorY, detPixArea, &openCut, &closedCut, radMask, &openArea1, &closedArea1, &effOpenArea1, &leakageFrOpen1, &leakageToClosed1, radiusLimit, chatty, status); */ /* Copy pifWork into pif */ offset = nSources*iPifEnergy*J_NUM_X_PIXELS*J_NUM_Y_PIXELS+ iSource*J_NUM_X_PIXELS*J_NUM_Y_PIXELS; a = 0.0; for (ii=0 ; ii 0.0){ pifjIniOpen[ii][jj] = pifjIniOpen[ii][jj]/effOpenArea[jj]; pifjIniClosed[ii][jj] = pifjIniClosed[ii][jj]/effOpenArea[jj]; }else{ pifjIniOpen[ii][jj] = 0.0; pifjIniClosed[ii][jj] = 0.0; } } } if( chatty > J_CHATTY_VERBOSE){ RILlogMessage(NULL, Log_0, " Done pif at energy no. %d", iPifEnergy); } } /* End of loop over PIF energies */ } if(precisionLevel > 1 && precisionLevel < 20) { step = 0.1; for ( iSource=0 ; iSource 0.001 && weight < 1.5){ effCollHeight = collHeight + detDepthX[iSource]; status = j_src_through_coll(xstep, ystep, srcY[iSource], srcZ[iSource], collimatorXBot, collimatorYBot, collimatorXTop, collimatorYTop, collimator, detMaskDist, effCollHeight, &weight, chatty, status); } if(weight >-1.5 && weight < -0.5){ nClosed = nClosed + 1; } if(weight >0.5 && weight < 1.5){ nOpen = nOpen + 1; } } } } openArea[iSource] = step*step*((float) nOpen); closedArea[iSource] = step*step*((float) nClosed); of[iSource] = (float) nOpen / (float) (nOpen+nClosed); if( chatty > J_CHATTY_QUIET ){ RILlogMessage(NULL, Log_0, "Source %d open fraction (mask+collimator): %f", ((int)iSource)+1, of[iSource]); RILlogMessage(NULL, Log_0, "Source %d open area (mask+collimator): %f", ((int) iSource)+1, openArea[iSource]); RILlogMessage(NULL, Log_0, "Source %d closed area (mask+collimator): %f", ((int) iSource)+1, closedArea[iSource]); } } openFraction = of[0]; } if(precisionLevel == 1) { for ( i=0 ; i J_SRC_ACCURACY) { of[i] = (float) (openArea1/(openArea1+closedArea1)); } else { of[i] = 0.0; } if( chatty > J_CHATTY_NORMAL ){ RILlogMessage(NULL,Log_0, "Open Fraction for source %d = %f", (int) i, of[i]); } } openFraction = of[0]; } if(precisionLevel == 0) { for ( iSource=0 ; iSource0) { strcpy(rowFilter , rowSelect); } else { /* strcpy(rowFilter, "(STATUS==0)" ); */ strcpy(rowFilter, "(STATUS==123 || STATUS==0 )" ); /* For sim data!!*/ } if( chatty > J_CHATTY_VERBOSE ){ RILlogMessage(NULL,Log_0, "Event selection rowFilter string: %s",rowFilter); } /* Select the FULL events */ status = DAL3JEMXselectEvents(theSWGptr, JEMX_num, FULL, COR, (int)nGTIs, gtiStartOBT, gtiEndOBT, rowFilter, status ); if(status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not select full imaging events", status); return status; } /* Get number of events */ status = DAL3JEMXgetNumEvents( &nFullEvents, status ); if( status != ISDC_OK ) { RILlogMessage( NULL, Error_2, "%d : Could not get number of selected full imaging events", status); return status; } RILlogMessage(NULL, Log_2, "Number of full events selected: %d", (int) nFullEvents ); if ( nFullEvents>0){ /* Check we have a big enough float buffer for this number of events */ if ( nFloats < nFullEvents ){ status = DALfreeDataBuffer( (void *)floatBuffer, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not free floatBuffer", status ); return status; } bufferSize = nFullEvents* sizeof(float); nFloats = nFullEvents; floatBuffer = NULL; status = DALallocateDataBuffer( (void **)&floatBuffer, bufferSize, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not allocate floatBuffer", status ); return status; } if( chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_0, "Full event float buffer allocated."); } } /* get DETX */ diskType = DAL_FLOAT; status = DAL3JEMXgetEvents(DETX, &diskType, (void *)floatBuffer, status); if ( status!=ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not get DETX for the selected FULL events", status); return status; } if( chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_0, "Full event DETX values read."); } /* Memory allocation when changing from fixed array size. /SL/010626 */ bufferSize = nFullEvents*sizeof(double); status = DALallocateDataBuffer( (void **)&fullDetX, bufferSize, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not allocate memory for fullDetX", status ); return status; } for ( i=0 ; i fullEventOBT[i] ){ obtStart = fullEventOBT[i]; } if ( obtEnd < fullEventOBT[i] ){ obtEnd = fullEventOBT[i]; } } if( chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_0, "All full event data read."); } } /* End if ( nFullEvents>0) */ /****************READING REST EVENT DATA*************************************/ if(evtType == 1 || evtType ==-1){ /* Compose selection string */ strcpy(rowFilter,"(STATUS==0)" ); if( chatty > J_CHATTY_VERBOSE ){ RILlogMessage(NULL,Log_0, "Event selection rowFilter string: %s",rowFilter); } /* Select the REST events */ status = DAL3JEMXselectEvents(theSWGptr, JEMX_num, REST, COR, (int)nGTIs, gtiStartOBT, gtiEndOBT, rowFilter, status ); if(status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not select restricted imaging events", status); return status; } /* Get number of selected REST events */ status = DAL3JEMXgetNumEvents( &nRestEvents, status ); if( status != ISDC_OK ) { RILlogMessage( NULL, Error_2, "%d : Could not get number of selected rest imaging events", status); return status; } if( chatty > J_CHATTY_NORMAL ){ RILlogMessage(NULL,Log_0, "Number of selected restricted events: %d", (int) nRestEvents); } if ( nRestEvents>0){ /* Check we have a big enough float buffer for this number of events */ if ( nFloats < nRestEvents ){ status = DALfreeDataBuffer( (void *)floatBuffer, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not free floatBuffer", status ); return status; } bufferSize = nRestEvents* sizeof(float); nFloats = nRestEvents; status = DALallocateDataBuffer( (void **)&floatBuffer, bufferSize, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not allocate floatBuffer", status ); return status; } } /* get DETX */ diskType = DAL_FLOAT; status = DAL3JEMXgetEvents(DETX, &diskType, (void *)floatBuffer, status); if ( status!=ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not get DETX for the selected REST events", status); return status; } /* Memory allocation when changing from fixed array size. /SL/010626 */ bufferSize = nRestEvents*sizeof(double); status = DALallocateDataBuffer( (void **)&restDetX, bufferSize, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not allocate memory for restDetX", status ); return status; } for ( i=0 ; i 0 ){ RILlogMessage(NULL,Log_0, "Restricted DetX positions read. DetX[1] = %e", restDetX[1]); } /* get DETY */ diskType = DAL_FLOAT; status = DAL3JEMXgetEvents(DETY, &diskType, (void *)floatBuffer, status); if ( status!=ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not get DETY for the selected REST events", status); return status; } /* Memory allocation when changing from fixed array size. /SL/010626 */ bufferSize = nRestEvents*sizeof(double); status = DALallocateDataBuffer( (void **)&restDetY, bufferSize, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not allocate memory for restDetY", status ); return status; } for ( i=0 ; i restEventOBT[i] ){ obtStart = restEventOBT[i]; } if ( obtEnd < restEventOBT[i] ){ obtEnd = restEventOBT[i]; } } } /* End if ( nRestEvents>0) */ } /*********************** If no events found: Exit***************************/ if ((nFullEvents == 0) && (nRestEvents == 0)) { RILlogMessage(NULL, Warning_2, " No events found within GTI range. Data extraction stoped."); return status; } /*********************** De-allocate buffer memory***************************/ if( chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_0, "Deallocate memory for all buffers"); } if( byteBuffer!= NULL ){ status = DALfreeDataBuffer( (void *) byteBuffer,status ); if ( status!=ISDC_OK ){ RILlogMessage(NULL, Warning_2, "%d : could not free memory for the byte buffer", status); status = ISDC_OK; } } if( obtBuffer!= NULL ){ status = DALfreeDataBuffer( (void *) obtBuffer,status ); if ( status!=ISDC_OK ){ RILlogMessage(NULL, Warning_2, "%d : could not free memory for the obt buffer", status); status = ISDC_OK; } } if ( ulongBuffer!= NULL){ status = DALfreeDataBuffer( (void *) ulongBuffer,status ); if ( status!=ISDC_OK ){ RILlogMessage(NULL, Warning_2, "%d : could not free memory for unsigned long buffer", status); status = ISDC_OK; } } if ( dblBuffer!= NULL){ status = DALfreeDataBuffer( (void *) dblBuffer,status ); if ( status!=ISDC_OK ){ RILlogMessage(NULL, Warning_2, "%d : could not free memory for double buffer", status); status = ISDC_OK; } } if ( intBuffer!= NULL){ status = DALfreeDataBuffer( (void *) intBuffer,status ); if ( status!=ISDC_OK ){ RILlogMessage(NULL, Warning_2, "%d : could not free memory for integer buffer", status); status = ISDC_OK; } } if ( intBuffer2!= NULL){ status = DALfreeDataBuffer( (void *) intBuffer2,status ); if ( status!=ISDC_OK ){ RILlogMessage(NULL, Warning_2, "%d : could not free memory for integer buffer2", status); status = ISDC_OK; } } if ( stringBuffer!= NULL){ status = DALfreeStringBuffer( stringBuffer, (int) nStrings, status ); if ( status!=ISDC_OK ){ RILlogMessage(NULL, Warning_2, "%d : could not free memory for string buffer", status); status = ISDC_OK; } } if( chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_0, "Deallocate completed."); } /***************** END DEALLOCATE*********************************/ /****************************************************************** * * Allocate memory for gtiStart and gtiEnd arrays (IJD unit GTIs) * and then convert OBT GTIs to IJD. * (SL/010827) * ******************************************************************/ /* gtiStart: */ bufferSize = nGTIs*sizeof(double); status = DALallocateDataBuffer( (void **)>iStart, bufferSize, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not allocate memory for gtiStart", status ); return status; } if( chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_0, "Memory allocated to gtiStart, Size: %d", (int) bufferSize); } status = DAL3AUXconvertOBT2IJD(theSWGptr,Accuracy,nGTIs, gtiStartOBT,gtiStart,status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Error in GTI Start conversion from OBT to IJD ", status ); return status; } if( chatty > J_CHATTY_NORMAL ){ RILlogMessage(NULL,Log_0, "Number of GTIs to convert to IJD: %d ", (int) nGTIs); if( chatty == J_CHATTY_MAXIMAL && nGTIs > 0){ RILlogMessage(NULL,Log_0, "GTI OBT converted to IJD. (gtiStart[0] = %e ", gtiStart[0]); } } /* gtiEnd: */ status = DALallocateDataBuffer( (void **)>iEnd, bufferSize, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not allocate memory for gtiEnd", status ); return status; } if( chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_0, "Memory allocated to gtiEnd, Size: %d", (int) bufferSize); } status = DAL3AUXconvertOBT2IJD(theSWGptr,Accuracy,nGTIs, gtiEndOBT,gtiEnd,status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Error in GTI End conversion from OBT to IJD ", status ); return status; } if( chatty == J_CHATTY_MAXIMAL && nGTIs > 0){ RILlogMessage(NULL,Log_0, "GTI OBT converted to IJD. (gtiEnd[0] = %e ", gtiEnd[0]); } /***************** GTI OBT -> IJD conversion completed **************/ /********************************************************************* * * Calculate time ranges and integration times for each spectrum. * 1. Call "j_src_nspec" to get the number of time ranges for * spectra. * 2. Allocate memory for timeStartSpec, timeEndSpec and timeIntSpec * to hold this number of elements. * 3. Call "j_src_nspec_times" to get the actual time values. * * * Parameter = -1.0 (timeStart) means that time ranges will * not start before the beginning of GTIs. * Parameter = 0 means: Use all segments containing any data. * Parameter = 2 means: Use only segments fully within GTIs. * * timeIntSpec is in seconds timeDel is in days ********************************************************************/ if(doSpec == 1) { status = j_src_nspec( gtiStart, gtiEnd, nGTIs, timeStepIJD, -1.0, &nSpec, 0, chatty, status); } else { status = j_src_nspec( gtiStart, gtiEnd, nGTIs, timeStepIJD, -1.0, &nSpec, 2, chatty, status); } if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : When calculating number of spectra", status ); return status; } /********** Memory allocation *********/ /* timeStartSpec: */ bufferSize = nSpec*sizeof(double); status = DALallocateDataBuffer( (void **)&timeStartSpec, bufferSize, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not allocate memory for timeStartSpec", status ); return status; } /* timeEndSpec: */ bufferSize = nSpec*sizeof(double); status = DALallocateDataBuffer( (void **)&timeEndSpec, bufferSize, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not allocate memory for timeEndSpec", status ); return status; } /* timeIntSpec: */ bufferSize = nSpec*sizeof(double); status = DALallocateDataBuffer( (void **)&timeIntSpec, bufferSize, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not allocate memory for timeIntSpec", status ); return status; } status = j_src_nspec_times( gtiStart, gtiEnd, nGTIs, timeStepIJD, -1.0, timeStartSpec, timeEndSpec, timeIntSpec, &nSpec, 0, chatty, status); if (status == J_SRC_NO_SPEC_DATA){ RILlogMessage(NULL, Warning_2, "No time bins within the GTIs. Exiting" ); status = ISDC_OK; return status; } if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : When calculating spectral time ranges", status ); return status; } /******************************************************************** * * Memory allocation: rate, bRate and nRate, nBRate * ********************************************************************/ if(doSpec == 1) { bufferSize = nSpec*nSources*J_NUM_SCI_BINS*sizeof(double); status = DALallocateDataBuffer( (void **)&rate, bufferSize, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not allocate memory for rate", status ); return status; } status = DALallocateDataBuffer( (void **)&bRate, bufferSize, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not allocate memory for bRate", status ); return status; } bufferSize = nSpec*nSources*J_NUM_SCI_BINS*sizeof(long); status = DALallocateDataBuffer( (void **)&nRate, bufferSize, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not allocate memory for nRate", status ); return status; } status = DALallocateDataBuffer( (void **)&nBRate, bufferSize, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not allocate memory for nBRate", status ); return status; } } /****************************************************************** * * Allocate memory for timeIJD array and convert times from * OBT -> IJD. (SL/010706) * ******************************************************************/ bufferSize = nFullEvents*sizeof(double); status = DALallocateDataBuffer( (void **)&timeIJD, bufferSize, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not allocate memory for timeIJD", status ); return status; } status = DAL3AUXconvertOBT2IJD(theSWGptr,Accuracy,nFullEvents, fullEventOBT,timeIJD,status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Error in OBT -> timeIJD", status ); return status; } if( chatty > J_CHATTY_NORMAL){ RILlogMessage(NULL,Log_0, "Event OBT converted to IJD. First and last events are:"); RILlogMessage(NULL,Log_0,"timeIJD[0] = %e ", timeIJD[0]); RILlogMessage(NULL,Log_0,"timeIJD[N-1] = %e ", timeIJD[nFullEvents-1]); } if(totDet == 1){ icount1 = 0; icount2 = 1; for( iEvent = 1L; iEvent < nFullEvents; iEvent++ ) { if(timeIJD[iEvent]-timeIJD[0] < ((float) icount2)*timeStepIJD){ radius = sqrt(fullDetX[iEvent]*fullDetX[iEvent]+ fullDetY[iEvent]*fullDetY[iEvent]); if ( radius < radiusLimit){ icount1 = icount1 + 1; } } else { RILlogMessage(NULL,Log_0," %e %d ", timeIJD[0]+((float) icount2*timeStepIJD*DAL3GEN_SECONDS_IN_DAY), icount1); icount1 = 0; icount2 = icount2 + 1; } } } /***************************************************************** * * If timeStartSpec[0] < 0: We want to use all data so set * time range using first and last event (assuming them to be * sorted!). * *******************************************************************/ if(nSpec == 0) { status = J_SRC_NO_SPEC_DATA; RILlogMessage(NULL, Error_2, "%d : Data and selected parameters resulted in ZERO spectra.", status ); return status; } if(nSpec == 1) { if(timeStartSpec[0] < 0) { timeStartSpec[0] = timeIJD[0]; timeEndSpec[0] = timeIJD[nFullEvents-1]; timeIntSpec[0] = timeEndSpec[0] - timeStartSpec[0]; RILlogMessage(NULL, Warning_2, "Integration time assumes NO data gaps!"); } } /***************************************************************** * * Lightcurve setup * * *******************************************************************/ if (doLC == 1) { /* ================================================================= * Set length of interval used in time binning below and the * number of time bins to be produced. * If we have normal time binning, the bin length is just "timeStep" * and we need enough time bins to cover the total time length with * intervals of this length. * If we have pulse phase binning, each processing bin is one pulse * period ("timeStep") divided by the number of phase bins. The * number of time bins is just given by "nPhaseBins". * If timeStep was set to zero all data is binned to a single value. * ================================================================= */ elapsedTime = (timeStop - timeStart) * DAL3GEN_SECONDS_IN_DAY; if (chatty >= J_CHATTY_VERBOSE) { RILlogMessage(NULL,Log_1, "Events from IJD %12f to %12f will be binned", timeStart,timeStop); RILlogMessage(NULL,Log_1, "This corresponds to a total integration time " "of %f sec",elapsedTime); } if (nPhaseBins == 0) { nOutLCBins = nSpec; } else { nOutLCBins = nPhaseBins; } if(nOutLCBins < nSpec) { nSpec = nOutLCBins; } if (chatty >= J_CHATTY_NORMAL) { if (nPhaseBins == 0) { RILlogMessage(NULL,Log_2, "There will be %d energy resolved lightcurves " "produced with %d time bins each", nChanBinsLC, (int) nOutLCBins); } else { RILlogMessage(NULL,Log_2, "There will be %d energy resolved folded " "lightcurves produced with %d phase bins each", nChanBinsLC,nPhaseBins); } } /* Set look up table to relate Pi channels with lightcurve bands. A Pi channel can only belong to ONE LC band! */ for (i=0; i=chanLow[ii] && i<=chanHigh[ii]){ chanPi[i] = ii; } } } /* =========================================================== * Allocate buffers for lightcurve data. * All buffers are allocated as _linear_ buffers * For the actual rates and errors we need arrays sized for * number of time bins * number of energy bands. * The memory order in these linear buffers is first vary over * energy, then over time, i.e. if we have 3 energy bands, * then the first 3 values of these buffers will correspond to * the first time bin in each band, the next 3 to the next * time bin, etc. * Other buffers are identical for each energy band and thus * are only addressed by the time bin * ============================================================ */ status = DALallocateDataBuffer((void**)&rateLC, nSources*nOutLCBins*nChanBinsLC*sizeof(double), status); status = DALallocateDataBuffer((void**)&nRateLC, nSources*nOutLCBins*nChanBinsLC*sizeof(long), status); status = DALallocateDataBuffer((void**)&errLC, nSources*nOutLCBins*nChanBinsLC*sizeof(double), status); status = DALallocateDataBuffer((void**)&bRateLC, nSources*nOutLCBins*nChanBinsLC*sizeof(double), status); status = DALallocateDataBuffer((void**)&nBRateLC, nSources*nOutLCBins*nChanBinsLC*sizeof(long), status); status = DALallocateDataBuffer((void**)&bErrLC, nSources*nOutLCBins*nChanBinsLC*sizeof(double), status); status = DALallocateDataBuffer((void**)&timeLC, nOutLCBins*sizeof(double), status); status = DALallocateDataBuffer((void**)&fracExp, nOutLCBins*sizeof(double), status); status = DALallocateDataBuffer((void**)&timeDel, nOutLCBins*sizeof(double), status); status = DALallocateDataBuffer((void**)&avgRate, nSources*nChanBinsLC*sizeof(double), status); status = DALallocateDataBuffer((void**)&avgRateErr, nSources*nChanBinsLC*sizeof(double), status); status = DALallocateDataBuffer((void**)&phaseBinStart, nPhaseBins*sizeof(double), status); status = DALallocateDataBuffer((void**)&phaseBinEnd, nPhaseBins*sizeof(double), status); if (ISDC_OK != status) { RILlogMessage(NULL,Error_2, "Could not allocate buffers for %d time bins " "and %d energy bands!", (int) nOutLCBins,nChanBinsLC); return status; } else if (chatty >= J_CHATTY_VERY_VERBOSE) { RILlogMessage(NULL,Log_0, "Allocated buffers for %d timebins " "and %d energy bands", (int) nOutLCBins, nChanBinsLC); } /* Inserted 021011/SL */ if (nPhaseBins == 0) { totalOnTime = 0.0; for (i=0; i< nOutLCBins ; i++){ timeLC[i] = 0.5*(timeStartSpec[i]+timeEndSpec[i]); timeDel[i] = timeIntSpec[i]/DAL3GEN_SECONDS_IN_DAY; totalOnTime = totalOnTime + timeIntSpec[i]; } status = j_src_fracexp(timeStep, timeStartSpec, timeEndSpec, timeIntSpec, fracExp, nSpec, deadTimeIJD, deadEff, nDeadTimes, chatty, status); } else { phaseSum = 0.0; for (i=0; i< nOutLCBins ; i++){ phaseBinStart[i] = phaseSum; timeLC[i] = phaseSum + 0.5*phaseBins[i]; phaseSum = phaseSum + phaseBins[i]; timeDel[i] = phaseBins[i]; phaseBinEnd[i] = phaseSum; } } /* make sure output buffers are empty and some counters reset */ for (i=0; i= J_CHATTY_NORMAL){ RILlogMessage(NULL,Log_0, "Source %d Vignetting factor (approx): %f", ((int)i)+1, vignetting[i] ); } } srcCosY[0] = 0.0; srcCosZ[0] = 0.0; /***************************************************************** * * Ancilliary Response Function. * From version 3.3.0 the ARF is computed from the * on-axis arf and QE is not used any longer. * (Option J_SRC_SPECTRA_USE_QEFF == 1 is kept for a * while to allow testing.) * * If vignetting correction is selected (vignCorr=1) * the vignetting correction is applied to the spectrum * otherwise (vignCorr=0) it is applied to the ARF. * * For XSPEC this should be equivalent but vignetting * corrected spectra can more easily be added together. * * The else-case (DEFAULT): Division by openFraction to * scale to full detector area. * * 030818: * (openArea is in mm^2 and detectorRadius is in mm.) * Since the effect of the mask is in both openArea * and in axisArf we have to devide out the one in * the axisArf by dividing with openFractionAve. * * Options for normalisation: * Flux is scaled to * * fluxScaling = 1 Illuminated area. * fluxScaling = 2 100 cm2 * fluxScaling = 3 1 cm2 * * For fluxScaling 2 and 3 vignetting correction is always * applied. * * /040615: Added J_COLL_OPEN_FRAC (collimator open fraction * in the scaling of on-axis ARF). * It is included in the onaxis ARF! * *******************************************************************/ if(doSpec == 1) { if(J_SRC_SPECTRA_USE_QEFF == 1) { status = j_src_qeff( quantumEff, quantEnergy, nQeff, defEnergyLo, defEnergyHi, arfQuantumEff, nLineEnergies, chatty, status); for ( i=0 ; i 1){ if(fluxScaling == 1) { sourceARF[i][j] = (float) (openArea[i]*axisArf[j]/ (openFractionAve*J_COLL_OPEN_FRAC*J_COR_PI* detectorRadius*detectorRadius)); } if(fluxScaling == 2) { sourceARF[i][j] = (float) (10000.0*axisArf[j]/ (openFractionAve*J_COLL_OPEN_FRAC*J_COR_PI* detectorRadius*detectorRadius)); /* if(vignCorr > 0) { } */ } if(fluxScaling == 3) { sourceARF[i][j] = (float) (100.0*axisArf[j]/ (openFractionAve*J_COLL_OPEN_FRAC*J_COR_PI* detectorRadius*detectorRadius)); } }else{ if(fluxScaling == 1) { if(vignCorr == 0) { sourceARF[i][j] = (radiusLimit*radiusLimit/ (detectorRadius*detectorRadius))* (float) (axisArf[j]*vignetting[i]); } else { sourceARF[i][j] = (radiusLimit*radiusLimit/ (detectorRadius*detectorRadius))* (float) (axisArf[j]); } } if(fluxScaling == 2) { if(vignCorr == 0) { sourceARF[i][j] = (float) (10000.0*axisArf[j]/ (openFractionAve*J_COLL_OPEN_FRAC*J_COR_PI* detectorRadius*detectorRadius)); }else{ sourceARF[i][j] = (float) (10000.0*axisArf[j]*vignetting[i]/ (openFractionAve*J_COLL_OPEN_FRAC*J_COR_PI* detectorRadius*detectorRadius)); } /* sourceARF[i][j] = (radiusLimit*radiusLimit/ (detectorRadius*detectorRadius))* sourceARF[i][j]/( (float) of[i]); */ } if(fluxScaling == 3) { if(vignCorr == 0) { sourceARF[i][j] = (float) (100.0*axisArf[j]/ (openFractionAve*J_COLL_OPEN_FRAC*J_COR_PI* detectorRadius*detectorRadius)); }else{ sourceARF[i][j] = (float) (100.0*axisArf[j]*vignetting[i]/ (openFractionAve*J_COLL_OPEN_FRAC*J_COR_PI* detectorRadius*detectorRadius)); } } } } } } } /***************************************************************** * * First initialize etc. then loop over all events * and bin spectra. * *******************************************************************/ if( chatty > J_CHATTY_NORMAL ){ RILlogMessage(NULL,Log_0, "Entering data processing section"); } /* Set parameters according to Full or Restricted mode */ /* TO BE DONE, Then run twice, once per mode */ nEvents = nFullEvents; eventOBT = fullEventOBT; /* Point to fullEventOBT SL/010626 */ /* Reset spectrum binning variables */ for( iSource=0L; iSource < nSources; iSource++ ) { eventWeights[iSource] = 0.0; if(doSpec == 1){ for( eBand=0L; eBand < nChanBins; eBand++ ) { for( iSpec=0L; iSpec < nSpec; iSpec++ ) { ii = eBand + J_NUM_SCI_BINS*(iSource + nSources*iSpec); rate[ii] = 0.0; bRate[ii] = 0.0; nRate[ii] = 0; nBRate[ii] = 0; } } } } /****** Open PIF DS if selected.**********************************/ if(doPif > 0){ strcpy( structName,"GNRL-EVTS-LST"); pifPtr = NULL; status = DALobjectFindElement ( theSWGptr, structName, &pifPtr, status); if ( status == DAL_ELEMENT_NOT_FOUND ){ status = ISDC_OK; strcpy( templateName, "GNRL-EVTS-LST"); strcat( templateName, ".tpl"); status = DAL3GENobjectAppend( theSWGptr, DAL_DISK,structName, templateName,&pifPtr, status); if ( status == DAL_ELEMENT_NOT_FOUND ){ RILlogMessage(NULL, Error_2, "%d : could not append output data structure %s", status, structName); return status; } } bufferSize = nSources*nEvents*sizeof(float); status = DALallocateDataBuffer( (void **)&eventPifs, bufferSize, status); if( status != ISDC_OK ){ RILlogMessage( NULL, Error_2, "%d :Could not allocate event PIF array", status); return status; } for ( i=0 ; i J_CHATTY_NORMAL ){ RILlogMessage(NULL,Log_0, "Beginning of main loop over all events"); } icount1 = 0; for( iEvent = 0L; iEvent < nEvents; iEvent++ ) { /******* Calculate within which time or phase bin we are and set iSpec (the spectrum in which to store the event).****/ if(nPhaseBins == 0) { iSpec = -1L; /* While -1, dont use this event */ ii = 0L; do { if (timeIJD[iEvent] >= timeStartSpec[ii] && timeIJD[iEvent] <= timeEndSpec[ii]) { iSpec = ii; } ii = ii + 1L; }while( iSpec < 0L && ii < nSpec); } else if(nPhaseBins != 0) { /* PERIOD FOLDING. CALCULATE WITHIN WHICH PHASE BIN WE ARE AND SET iSpec SO THE EVENT IS ADDED TO THAT SPECTRUM. */ foldPhase = (timeIJD[iEvent]-timeStart)/timeStepIJD; foldPhase = foldPhase - (double) ((int) foldPhase); iSpec = -1L; /* While -1, dont use this event */ ii = 0L; do { if (foldPhase >= phaseBinStart[ii] && foldPhase <= phaseBinEnd[ii]) { iSpec = ii; } ii = ii + 1L; }while( iSpec < 0L && ii < nSpec); } /****** End of iSpec calculattion ****/ if( iSpec >= 0L) { icount1 = icount1 + 1; /* For testing /SL */ /*----------------------------------------------------*/ /* Check if Grey filter has changed. If so update correction factor. */ if( nGreyChanges > 0) { do{ if(timeIJD[iEvent] > timeIJDGreyNext) { if(nextGrey < nGreyChanges-1) { greyCorr = 32.0/((float) (greyValues[nextGrey]+1)); /* if( chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_0, "Grey filter correction factor at IJD %lf is %f.", statusIJD[nextGrey] , greyCorr); } */ nextGrey = nextGrey + 1; timeIJDGreyNext = statusIJD[nextGrey]; } else if(nextGrey == nGreyChanges-1){ greyCorr = 32.0/((float) (greyValues[nextGrey]+1)); timeIJDGreyNext = timeIJD[iEvent] + 1.0; } else if(nextGrey > nGreyChanges-1){ if(nGreyChanges == 1){ greyCorr = 32.0/((float) (greyValues[0]+1)); timeIJDGreyNext = timeIJD[iEvent] + 1.0; } else{ RILlogMessage(NULL,Warning_2, "Inconsistent number of Grey filters"); RILlogMessage(NULL,Warning_2, "nGreyChanges = %d, nextGrey = %d", (int) nGreyChanges , (int) nextGrey); } } } else { continue; } } while (timeIJD[iEvent] > timeIJDGreyNext); } /*-------End of Grey filter update. ------------------*/ /*----------------------------------------------------*/ /* Check if Dead time has changed. If so update correction factor. */ if( nDeadTimes > 0) { do{ if(timeIJD[iEvent] > deadTimeIJDNext) { if(nextDead < nDeadTimes-1) { deadCorr = rateCor[nextDead]; nextDead = nextDead + 1; deadTimeIJDNext = deadTimeIJD[nextDead]; } else if(nextDead == nDeadTimes-1){ deadCorr = rateCor[nextDead]; deadTimeIJDNext = timeIJD[iEvent] + 1.0; } else if(nextDead > nDeadTimes-1){ if(nDeadTimes == 1){ deadCorr = rateCor[0]; deadTimeIJDNext = timeIJD[iEvent] + 1.0; } else{ RILlogMessage(NULL,Warning_2, "Inconsistent number of dead times"); RILlogMessage(NULL,Warning_2, "nDeadTimes = %d, nextDead = %d", (int) nDeadTimes , (int) nextDead); } } } else { continue; } } while (timeIJD[iEvent] > deadTimeIJDNext); } /*-------End of Dead time update. ----------------*/ if(doPif > 0){ eventDeadc[iEvent] = greyCorr*deadCorr; } radius = sqrt(fullDetX[iEvent]*fullDetX[iEvent]+ fullDetY[iEvent]*fullDetY[iEvent]); /*-------If diagnosticmode = 4 --------------------*/ /* NOTE: READING PIF IS FROM OLD VERSION UPDATE!!!!!!!!!!!!!!! */ if ( radius < radiusLimit && diagnosticMode == 4){ if(precisionLevel > 19){ do { ix = (long int) (drand48()*detectorRadius*2.0); jy = (long int) (drand48()*detectorRadius*2.0); if(ix >= 0 && ix < J_NUM_X_PIXELS && jy >= 0 && jy < J_NUM_X_PIXELS){ a = (double) *(pif+(ix*J_NUM_X_PIXELS+jy)); if(a < -0.001){ radius = radiusLimit + 1.0; }else{ xCoord = detCorX[ix][jy]; yCoord = detCorY[ix][jy]; radius = sqrt(xCoord*xCoord + yCoord*yCoord); } }else{ radius = radiusLimit + 1.0; /* To continue loop*/ icount4 = icount4 + 1; /* For testing /SL */ } } while(radius > radiusLimit); }else{ xCoord = fullDetX[iEvent]; yCoord = fullDetY[iEvent]; status = j_src_randXY(&xCoord, &yCoord, radiusLimit, chatty, status); } fullDetX[iEvent] = xCoord; fullDetY[iEvent] = yCoord; } /*-------End diagnosticmode = 4 -------------------*/ Pi = fullEventPi[iEvent]; /* NOTE: Also Restr!! /SL */ for( iSource=0L; iSource < nSources; iSource++ ) { radius = sqrt(fullDetX[iEvent]*fullDetX[iEvent]+ fullDetY[iEvent]*fullDetY[iEvent]); if(precisionLevel > 19 && precisionLevel < 31){ /* Move this call to above iSource loop. */ if ( radius < radiusLimit){ status = j_src_dete_index(fullDetX[iEvent], fullDetY[iEvent], detPixLLX, detPixLLY, detCorX, detCorY, &ix, &jy, chatty, status); /* For high chatty we collect statistics of the correlation between pixel sizes and number of events */ if(iSource == 0 && chatty > J_CHATTY_VERBOSE){ iPixFlux = (int) (10.0*detPixArea[ix][jy]); if(iPixFlux > 0 && iPixFlux<20) { pixFluxDistr[iPixFlux] = pixFluxDistr[iPixFlux] + 1.0; }else if(iPixFlux > 19){ pixFluxDistr[19] = pixFluxDistr[19] + 1.0; } } pifInterpolEnergy = (float) (0.5*(fullEMin[Pi]+fullEMax[Pi])); if(doPif > 0){ eventEnergy[iEvent] = pifInterpolEnergy; } status = j_src_pif_interpol(iSource, nSources, pifInterpolEnergy, ix, jy, pifEnergy, nPifEnergies, pif, &pifInterpol, chatty, status); /* SL 20040427: Cut level now depend on source and energy so we have to interpolate. We use the same cut level for open and closed area but that can be changed by adding a second interpolation (closedSrcCutEnergy). */ status = j_src_pifcut_interpol( iSource, Pi, pifChannel, openSrcCutEnergy, nPifEnergies, &openCut, chatty, status); openSrcCut[iSource] = openCut; closedSrcCut[iSource] = openCut; eventWeights[iSource] = pifInterpol; /* if(ix>=118&&ix<125 && jy>=110 && jy<128){ RILlogMessage(NULL,Log_0, " %f %f %d %d %f", fullDetX[iEvent],fullDetY[iEvent],ix,jy, pifInterpol); } */ if(eventWeights[iSource] < -0.5){ icount3 = icount3 + 1; /* For testing /SL */ }else{ icount6 = icount6 + 1; /* For testing /SL */ if( (Pi >= 0) && (Pi <= 255) ) { if(doLC == 1){ for (iChan=0; iChan=chanLow[iChan] && Pi<=chanHigh[iChan]){ iLCBin = iSource*nChanBinsLC*nOutLCBins + iSpec*nChanBinsLC + iChan; if(eventWeights[iSource]>openSrcCut[iSource]){ rateLC[iLCBin] = rateLC[iLCBin] + deadCorr*greyCorr; nRateLC[iLCBin] = nRateLC[iLCBin] + 1; } if(eventWeights[iSource]>-0.0001 && eventWeights[iSource]openSrcCut[iSource]){ rate[ii] = rate[ii] + deadCorr*greyCorr; nRate[ii] = nRate[ii] + 1; } if(eventWeights[iSource] radiusLimit){ weight = 0.0; } eventWeights[iSource] = weight; /* If the mask is transparent we also check the line of sight through collimator (unless excluded by option). fullDetX & Y used but depth effect is included by increasing the effective height of the collimator (030903). */ if(weight > 0.001 && weight < 1.5){ if(doColl == 1){ effCollHeight = collHeight + detDepthX[iSource]; status = j_src_through_coll(fullDetX[iEvent], fullDetY[iEvent], srcY[iSource], srcZ[iSource], collimatorXBot, collimatorYBot, collimatorXTop, collimatorYTop, collimator, detMaskDist, effCollHeight, &weight, chatty, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d :j_src_through_coll exit error ", status ); return status; } if(weight < 0.0) { eventWeights[iSource] = weight; } } } icount6 = icount6 + 1; /* For testing /SL */ if( (Pi >= 0) && (Pi <= 255) ) { if(doLC == 1){ for (iChan=0; iChan=chanLow[iChan] && Pi<=chanHigh[iChan]){ iLCBin = iSource*nChanBinsLC*nOutLCBins + iSpec*nChanBinsLC + iChan; if((eventWeights[iSource]>0.5) && (eventWeights[iSource]<1.5)){ rateLC[iLCBin] = rateLC[iLCBin] + deadCorr*greyCorr*1.0/openFraction; nRateLC[iLCBin] = nRateLC[iLCBin] + 1; } else if((eventWeights[iSource]>-1.5) && (eventWeights[iSource]<-0.5)) { bRateLC[iLCBin] = bRateLC[iLCBin] + deadCorr*greyCorr*1.0/(1.0-openFraction); nBRateLC[iLCBin] = nBRateLC[iLCBin] + 1; } } } } if(doSpec == 1) { ii = (long)Pi + J_NUM_SCI_BINS*(iSource + nSources*iSpec); if((eventWeights[iSource]>0.5) && (eventWeights[iSource]<1.5)){ rate[ii] = rate[ii] + deadCorr*greyCorr*1.0/openFraction; nRate[ii] = nRate[ii] + 1; } else if((eventWeights[iSource]>-1.5) && (eventWeights[iSource]<-0.5)) { bRate[ii]=bRate[ii] + deadCorr*greyCorr*1.0/(1.0-openFraction); nBRate[ii] = nBRate[ii] + 1; } } } } if(doPif > 0){ i = (int)iSource*nEvents+iEvent; *(eventPifs + i) = eventWeights[iSource]; } } } } if( chatty >= J_CHATTY_NORMAL ){ if(nSources > 1){ icount3 = icount3/nSources; icountOutside = icountOutside/nSources; } /* RILlogMessage(NULL,Log_0, "Ignored %d of the selected events inside radiusLimit", icount3); RILlogMessage(NULL,Log_0,"Ignored %d events outside radiusLimit", icountOutside); */ RILlogMessage(NULL,Log_0,"Binning completed. Using %d events", icount1-icount3); if(icount4 > 0){ RILlogMessage(NULL,Warning_2, "Random generated events were %d times outside of index range", icount4); RILlogMessage(NULL,Warning_2, "No harm done by it self but it should not happen!"); } } if(precisionLevel > 19 && chatty > J_CHATTY_VERBOSE){ RILlogMessage(NULL,Log_0, " Events per mm2 as function of pixel size "); RILlogMessage(NULL,Log_0, " 20 sizebins, from 0.0-0.1 to 1.9-2.0 mm2 "); RILlogMessage(NULL,Log_0, " Area per pixel, Pixels, Events, Events/pixel, Events/mm2,"); for ( i=0 ; i<20 ; i++){ if(pixAreaDistr[i] > 0.001){ a = pixFluxDistr[i]/pixAreaDistr[i]; }else{ a = 0.0; } aaa = a/(0.05+0.1*(double)i); RILlogMessage(NULL,Log_0," %f %f %f %f %f", 0.05+0.1*(float)i, pixAreaDistr[i], pixFluxDistr[i], a, aaa); } } if(doSpec == 1){ /* If illuminated area flux is = 0 the error should not be zero. Right now we assume a minimum error variance = 1. This we have to scale from nRate=1 to rate. The scaling factor in rate is (rate/nRate), which is also the scaling factor for the error, sqrt(Variance). Variance therefore scale as (rate/nRate)**2, i.e. variance = nRate * (rate/nRate)**2. In this case we evaluate (rate/nRate) for the total counts and multiply by nRate=1 to get the variance scaled to one count. Note that this is not the true variance since the gaussian approximation is not really valid here. */ for( iSource=0L; iSource < nSources; iSource++ ) { nSrcCounts = 0; nBkgCounts = 0; sumRate = 0.0; sumBRate = 0.0; for( eBand=0L; eBand < nChanBins; eBand++ ) { for( iSpec=0L; iSpec < nSpec; iSpec++ ) { ii = eBand + J_NUM_SCI_BINS*(iSource + nSources*iSpec); nSrcCounts = nSrcCounts + nRate[ii]; nBkgCounts = nBkgCounts + nBRate[ii]; sumRate = sumRate + rate[ii]; sumBRate = sumBRate + bRate[ii]; } } if( chatty >= J_CHATTY_NORMAL){ RILlogMessage(NULL,Log_0, "Source %d illum. area: %d events (total). " "Shadow area: %d events.", ((int)iSource) +1, (int) nSrcCounts, (int) nBkgCounts); } if(nSrcCounts != 0){ sumRate = sumRate/((double) nSrcCounts); rateVarianceMin[iSource] = sumRate*sumRate; } if(nBkgCounts != 0){ sumBRate = sumBRate/((double) nBkgCounts); bRateVarianceMin[iSource] = sumBRate*sumBRate; } } } /*********** PIF data structure: Add rows ********************************/ if(doPif > 0){ if ( nEvents>0 ){ status = DALtableAddRows( pifPtr, 0, nEvents, status); if ( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : could not add %ld rows to the PIF data structure", status, nEvents ); return status; } diskType= DAL_DOUBLE; status = DALtablePutCol(pifPtr, "TIME", 0, diskType, (long) nEvents, (void *) timeIJD, status); diskType= DAL_FLOAT; status = DALtablePutCol(pifPtr, "ENERGY", 0, diskType, (long) nEvents, (void *) eventEnergy, status); bufferSize = nEvents*sizeof(float); status = DALallocateDataBuffer( (void **)&pifBuffer, bufferSize, status); for( iSource=0L; iSource < nSources; iSource++ ) { sprintf(attname,"SRC_%ld",iSource+1); status = DALattributePut(pifPtr,attname,DAL_CHAR, (void*)srcID[iSource],NULL,NULL,status); sprintf(colName,"PIF_%ld",iSource+1); status=DALtableAddCol(pifPtr,colName,DAL_FLOAT,1,status); if (status!=ISDC_OK){ RILlogMessage(NULL,Error_2, "Error %d adding column %s to event table!", status,colName); break; } for ( i=0 ; i 0){ status = CommonStampObject(pifPtr, "Event list and PIFs written", status); if ( status!=ISDC_OK ){ RILlogMessage(NULL, Warning_2, "%d : Could not stamp PIF data structure %s%s ", status, jemxStr); status = ISDC_OK; } } /************* free allocated memory **************************************/ if ( fullEventPi!= NULL){ status = DALfreeDataBuffer( (void *) fullEventPi, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not free fullEventPi allocated memory", status ); return status; } } if ( fullDetX!= NULL){ status = DALfreeDataBuffer( (void *) fullDetX, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not free fullDetX allocated memory", status ); return status; } } if ( fullDetY!= NULL){ status = DALfreeDataBuffer( (void *) fullDetY, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not free fullDetY allocated memory", status ); return status; } } if ( eventOBT!= NULL){ eventOBT = NULL; } if ( fullEventOBT!= NULL){ status = DALfreeDataBuffer( (void *) fullEventOBT, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not free fullEventOBT allocated memory", status ); return status; } } if ( restEventPi!= NULL){ status = DALfreeDataBuffer( (void *) restEventPi, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not free restEventPi allocated memory", status ); return status; } } if ( restDetX!= NULL){ status = DALfreeDataBuffer( (void *) restDetX, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not free restDetX allocated memory", status ); return status; } } if ( restDetY!= NULL){ status = DALfreeDataBuffer( (void *) restDetY, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not free restDetY allocated memory", status ); return status; } } if ( restEventOBT!= NULL){ status = DALfreeDataBuffer( (void *) restEventOBT, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not free restEventOBT allocated memory", status ); return status; } } if(doPif > 0){ if ( eventPifs!= NULL){ status = DALfreeDataBuffer( (void *) eventPifs, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not free eventPifs allocated memory", status ); return status; } } if ( eventEnergy!= NULL){ status = DALfreeDataBuffer( (void *) eventEnergy, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not free eventEnergy allocated memory", status ); return status; } } if ( pifBuffer!= NULL){ status = DALfreeDataBuffer( (void *) pifBuffer, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not free pifBuffer allocated memory", status ); return status; } } if ( eventDeadc!= NULL){ status = DALfreeDataBuffer( (void *) eventDeadc, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not free eventDeadc allocated memory", status ); return status; } } } if(doLC == 1) { if( chatty >= J_CHATTY_NORMAL){ RILlogMessage(NULL,Log_1, "Total number of counts in the source illuminated area:"); for (iSource=0; iSource0) { strcat(nameLC,"FLC"); } else { strcat(nameLC,"LCR"); } /* ============================================================== * Allocate memory for resolution corr. factors. (LC channels) * Then average the spectral resolution corr. factors over the * light curve channels. NOTE: No weights with respect to source * spectrum (TODO?) * ============================================================== */ status = DALallocateDataBuffer( (void **)&aLC11, nChanBinsLC * sizeof(double), status ); status = DALallocateDataBuffer( (void **)&aLC12, nChanBinsLC * sizeof(double), status ); status = DALallocateDataBuffer( (void **)&aLC21, nChanBinsLC * sizeof(double), status ); status = DALallocateDataBuffer( (void **)&aLC22, nChanBinsLC * sizeof(double), status ); if (ISDC_OK!=status) { RILlogMessage(NULL,Error_2, " Error allocating resolution corr. array!"); return(status); } for (ii=0; ii 0){ aLC11[ii] = aLC11[ii]/( (double) icount1); aLC12[ii] = aLC12[ii]/( (double) icount1); aLC21[ii] = aLC21[ii]/( (double) icount1); aLC22[ii] = aLC22[ii]/( (double) icount1); } } /* ======================================================= * Write everything to the output data structure(s). * A single function is used for both normal and folded * lightcurves - nPhaseBins is used as flag to distinguish * the two cases. * ======================================================= */ /* if we have folded lightcurves we must make sure to write * only nPhaseBin entries */ nLCBins = nOutLCBins; if (0= J_CHATTY_NORMAL) { for (i=0; i J_CHATTY_VERBOSE ){ RILlogMessage(NULL,Log_0, "Will now put spectral responses in JXMi-SRCL-ARF"); } strcpy( structName, jemxStr); strcat( structName, J_SRCL_ARF_DS); arfPtr = NULL; status = DALobjectFindElement ( theSWGptr, structName, &arfPtr, status); if ( status == DAL_ELEMENT_NOT_FOUND ){ status = ISDC_OK; strcpy( templateName, structName); strcat( templateName, ".tpl"); status = DAL3GENobjectAppend( theSWGptr, DAL_DISK,structName, templateName,&arfPtr, status); if ( status == DAL_ELEMENT_NOT_FOUND ){ RILlogMessage(NULL, Error_2, "%d : could not append output data structure %s", status, structName); return status; } } /* ------------------------------------------------------------------- Find the DOL and filename for JMXi-SRCL-ARF. This will be written in JMXi-SRCL-SPE so that XSPEC can relate individual source spectra with their ARFs. -------------------------------------------------------------------- */ status = DALelementGetLocation(arfPtr,ancrFileDOL,status); status = j_ssp_GetFileName(ancrFileDOL,ancrFileName,status); /* -------------Copy attributes from SWG to JMXi-SRCL-ARF --------------- */ status = DAL3GENattributeCopy( theSWGptr, arfPtr, "REVOL,SWID,SW_TYPE,SWBOUND,OBTSTART,OBTEND", status); if ( status != ISDC_OK ){ RILlogMessage(NULL, Warning_2, "%d : could not copy all attributes to %s", status, structName); status = ISDC_OK; } /* ------------------------------------------------------------------ Add rows to this output extension if they're needed -------------------------------------------------------------------- */ status = DALtableGetColStruct( arfPtr, 0, &nRows, "SPECRESP", &diskTypeOut, &binSize, NULL, status); if ( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : could not get column structure of data structure %s", status, structName); return status; } nAdd = nSources - nRows; if ( nAdd>0 ){ status = DALtableAddRows( arfPtr, nRows, nAdd, status); if ( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : could not add %ld rows to data structure %s", status, nAdd, structName); return status; } } /* Make the float buffer */ /* Deallocate added 010521 /SL */ status = DALfreeDataBuffer( (void *)floatBuffer, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not free floatBuffer", status ); return status; } floatBuffer = NULL; nFloats = nSources * J_NUM_ARF_BINS; bufferSize = sizeof(float) * nFloats; status = DALallocateDataBuffer( (void **)&floatBuffer, bufferSize, status); if ( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : could not allocate float buffer", status); return status; } /* Fill the float buffer */ for ( ii=0 ; ii J_CHATTY_NORMAL ){ RILlogMessage(NULL,Log_0, "Spectral response values have been stored in JXMi-SRCL-ARF"); } /* ------------------------------------------------------------------- Store ENERG_LO column. -------------------------------------------------------------------- */ /* Fill the float buffer */ /* for ( ii=0 ; ii J_CHATTY_VERBOSE ){ RILlogMessage(NULL,Log_0, "ARF reference numbers have been stored in %s ", structName); } /* Add keywords to the data structure */ status = DAL3GENattributeCopy( theSWGptr, arfPtr, "REVOL,SWID,SW_TYPE,SWBOUND,OBTSTART,OBTEND,TSTART,TSTOP", status); if ( status != ISDC_OK ){ RILlogMessage(NULL, Warning_2, "%d : could not copy all attributes to %s", status, structName); status = ISDC_OK; } status = DALattributePut(arfPtr,"EXPOSURE",DAL_DOUBLE, (void*)&timeIntSpec[0],NULL,NULL,status); status = DALattributePut(arfPtr,"TELAPSE",DAL_DOUBLE, (void*)&elapsedTime,NULL,NULL,status); status = DALattributePut(arfPtr,"ONTIME",DAL_DOUBLE, (void*)&totalOnTime,NULL,NULL,status); status = DALattributePut(arfPtr,"DEADC",DAL_DOUBLE, (void*)&meanDeadCorr,NULL,NULL,status); if ( status != ISDC_OK ){ RILlogMessage(NULL, Warning_2, "%d : could not set attributes TELAPSE, ONTIME, DEADC in %s", status, structName); status = ISDC_OK; } status = CommonStampObject(arfPtr, "Effective area written", status); if ( status!=ISDC_OK ){ RILlogMessage(NULL, Warning_2, "%d : Could not stamp data structure %s%s ", status, jemxStr,J_SRCL_ARF_DS); status = ISDC_OK; } /* Deallocate added 010522 /SL */ status = DALfreeDataBuffer( (void *)floatBuffer, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not free floatBuffer", status ); return status; } /****************************************************************** Putting output data in JXMi-SRCL-BSP ******************************************************************/ strcpy( structName, jemxStr); strcat( structName, J_SRC_BSP_DS); strcpy( bStructName, structName); /* To reuse later.*/ if( chatty > J_CHATTY_NORMAL ){ RILlogMessage( NULL, Log_0, "Write background spectra to data structure: %s", structName); } bspecPtr = NULL; status = DALobjectFindElement(theSWGptr,structName,&bspecPtr,status); if ( status == DAL_ELEMENT_NOT_FOUND ){ status = ISDC_OK; strcpy( templateName, structName); strcat( templateName, ".tpl"); status = DAL3GENobjectAppend( theSWGptr, DAL_DISK,structName, templateName, &bspecPtr, status); if ( status == DAL_ELEMENT_NOT_FOUND ){ RILlogMessage(NULL, Error_2, "%d : could not append output data structure %s", status, structName); return status; } } /* ------------------------------------------------------------------- Copy attributes from SWG to JMXi-SRCL-BSP -------------------------------------------------------------------- */ status = DAL3GENattributeCopy( theSWGptr, bspecPtr, "REVOL,SWID,SW_TYPE,SWBOUND,OBTSTART,OBTEND,TSTART,TSTOP", status); if ( status != ISDC_OK ){ RILlogMessage(NULL, Warning_2, "%d : could not copy all attributes to %s", status, structName); status = ISDC_OK; } /* ------------------------------------------------------------------- Add rows to this output extension if needed -------------------------------------------------------------------- */ status = DALtableGetColStruct( bspecPtr, 0, &nRows, "RATE", &diskType, &binSize, NULL, status); if ( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : could not get column structure of data structure %s", status, structName); return status; } /* Number of rows to add (one per spectrum). */ nAdd = nSources*nSpec - nRows; if( chatty > J_CHATTY_VERBOSE ){ RILlogMessage( NULL, Log_0, "Add %d rows to background datastructure",(int) nAdd); } if ( nAdd>0 ){ status = DALtableAddRows( bspecPtr, nRows, nAdd, status); if ( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : could not add %ld rows to data structure %s", status, nAdd, structName); return status; } } /* Make the float buffer */ floatBuffer = NULL; nFloats = nSources*nSpec*J_NUM_SCI_BINS; bufferSize = sizeof(float) * nFloats; status = DALallocateDataBuffer( (void **)&floatBuffer, bufferSize, status); if ( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : could not allocate float buffer", status); return status; } /* Fill the float buffer */ sumRate = 0.0; if( chatty >= J_CHATTY_NORMAL ){ if(vignCorr == 1 && fluxScaling == 1){ RILlogMessage( NULL, Log_0, "Sum of backgr. spectrum countrates corrected"); RILlogMessage( NULL, Log_0, "for vignetting and scaled to open area."); } if(vignCorr == 1 && fluxScaling == 2){ RILlogMessage( NULL, Log_0, "Sum of backgr. spectrum countrates corrected"); RILlogMessage( NULL, Log_0, "for vignetting and scaled to"); RILlogMessage( NULL, Log_0, " nominal detector area (100 cm2)."); } if(vignCorr == 1 && fluxScaling == 3){ RILlogMessage( NULL, Log_0, "Sum of backgr. spectrum countrates corrected"); RILlogMessage( NULL, Log_0, "for vignetting and scaled to 1 cm^2."); } if(vignCorr == 0 && fluxScaling == 1){ RILlogMessage( NULL, Log_0, "Sum of backgr. spectrum countrates (NO vignetting corr.)."); RILlogMessage( NULL, Log_0, "Scaled to open area."); } if(vignCorr == 0 && fluxScaling == 2){ RILlogMessage( NULL, Log_0, "Sum of backgr. spectrum countrates (NO vignetting corr.)."); RILlogMessage( NULL, Log_0, " Scaled to nominal detector area (100 cm2)."); } if(vignCorr == 0 && fluxScaling == 3){ RILlogMessage( NULL, Log_0, "Sum of backgr. spectrum countrates (NO vignetting corr.)."); RILlogMessage( NULL, Log_0, " Scaled to 1 cm^2."); } } for ( iSpec=0 ; iSpec 19 && precisionLevel < 31){ /* For this source interpolate areas and correction factors from pifChannel to channel ii */ status = j_src_factors_interpol( iSource, pifChannel, openAreaEnergy, closedAreaEnergy, effOpenAreaEnergy, leakageFrOpenEnergy, leakageToClosedEnergy, nPifEnergies, openAreaChan, closedAreaChan, effOpenAreaChan, leakageFrOpenChan, leakageToClosedChan, chatty, status); nSum = 0; for ( ii=0 ; ii= J_CHATTY_NORMAL ){ if(nSum > 0){ sumError = sumRate/sqrt((double)nSum); } RILlogMessage( NULL, Log_0, "Source %d backgr. countrate = %f +/- %f", ((int)iSource)+1, sumRate, sumError); } sumRate = 0.0; } } /* Now put the source countrate into the data structure */ status = DALtablePutCol(bspecPtr, "RATE", 0, diskType, nFloats, (void *) floatBuffer, status); if ( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : fill data column RATE in %s", status, structName); return status; } /* ------------------------------------------------------------------- Estimate statistical errors and store in STAT_ERR column. -------------------------------------------------------------------- */ /* bRate is scaled back to counts and squared to get poisson error then scaled again to detector total area and to per second. [Remember bRate is already scaled to total detector area and SQRT(bRate*((1-f)/1)) * 1/(1-f) is simplified to SQRT(bRate*(1/(1-f))) ] -------------------------------------------------------------------- */ iBin = 0; /* This is also a loop? */ for (iSpec=0 ; iSpec 19 && precisionLevel < 31){ /* For this source interpolate areas and correction factors from pifChannel to channel ii */ status = j_src_factors_interpol( iSource, pifChannel, openAreaEnergy, closedAreaEnergy, effOpenAreaEnergy, leakageFrOpenEnergy, leakageToClosedEnergy, nPifEnergies, openAreaChan, closedAreaChan, effOpenAreaChan, leakageFrOpenChan, leakageToClosedChan, chatty, status); sumRate = 0.0; for ( ii=0 ; ii J_CHATTY_VERBOSE ){ RILlogMessage(NULL,Log_0, "Spectrum numbers have been stored in %s ", bStructName); } /* ------------------------------------------------------------------- Write source identification in column ROWID. -------------------------------------------------------------------- */ nStrings = nSources*nSpec; stringBuffer = NULL; status = DALallocateStringBuffer(&stringBuffer, (int) nStrings, DAL_MED_STRING, status); if (status!=ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : could not allocate string buffer for source IDs", status); return status; } /* Fill the string buffer with source IDs Must add check of string lengths!!! /TODO/SL/011103 */ for (iSpec=0 ; iSpec0 ){ status = DALtableAddRows( specPtr, nRows, nAdd, status); if ( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : could not add %ld rows to data structure %s", status, nAdd, structName); return status; } } /* ------------------------------------------------------------------- Write RATE column. -------------------------------------------------------------------- */ /* Make the float buffer */ floatBuffer = NULL; nFloats = nSources * nSpec * J_NUM_SCI_BINS; bufferSize = sizeof(float) * nFloats; status = DALallocateDataBuffer( (void **)&floatBuffer, bufferSize, status); if ( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : could not allocate float buffer", status); return status; } /* Fill the float buffer */ sumRate = 0.0; if( chatty >= J_CHATTY_NORMAL ){ if(vignCorr == 1 && fluxScaling == 1){ RILlogMessage( NULL, Log_0, "Sum of net source spectrum countrates corrected "); RILlogMessage( NULL, Log_0, "for vignetting and scaled to open area."); } if(vignCorr == 1 && fluxScaling == 2){ RILlogMessage( NULL, Log_0, "Sum of net source spectrum countrates corrected "); RILlogMessage( NULL, Log_0, "for vignetting and scaled to nominal detector area (100 cm2)."); } if(vignCorr == 1 && fluxScaling == 3){ RILlogMessage( NULL, Log_0, "Sum of net source spectrum countrates corrected "); RILlogMessage( NULL, Log_0, "for vignetting and scaled to 1 cm**2."); } if(vignCorr == 0 && fluxScaling == 1){ RILlogMessage( NULL, Log_0, "Sum of net source spectrum countrates (NO vignetting corr.)"); RILlogMessage( NULL, Log_0, " Scaled to open area."); } if(vignCorr == 0 && fluxScaling == 2){ RILlogMessage( NULL, Log_0, "Sum of net source spectrum countrates (NO vignetting corr.)."); RILlogMessage( NULL, Log_0, " Scaled to nominal detector area (100 cm2)."); } if(vignCorr == 0 && fluxScaling == 3){ RILlogMessage( NULL, Log_0, "Sum of net source spectrum countrates (NO vignetting corr.)."); RILlogMessage( NULL, Log_0, " Scaled to 1 cm2."); } } for (iSpec=0 ; iSpec 19 && precisionLevel < 31){ /* For this source interpolate areas and correction factors from pifChannel to channel ii */ status = j_src_factors_interpol( iSource, pifChannel, openAreaEnergy, closedAreaEnergy, effOpenAreaEnergy, leakageFrOpenEnergy, leakageToClosedEnergy, nPifEnergies, openAreaChan, closedAreaChan, effOpenAreaChan, leakageFrOpenChan, leakageToClosedChan, chatty, status); nSum = 0; nBSum = 0; sumRate = 0.0; for ( ii=0 ; ii 0.0){ srcToBkgArea = openArea1/closedArea1; } status = j_src_solve_rate(openArea1, closedArea1, effOpenArea1, leakageFrOpen1, leakageToClosed1, rate[i], bRate[i], &srcRate, &bkgRate, nRate[i], nBRate[i], &ratePoissonErr, &bRatePoissonErr, chatty, status); nSum = nSum + nRate[i]; /* To log error value. */ nBSum = nBSum + nBRate[i]; /* To log error value. */ if(fluxScaling == 1) { a = srcRate*openArea1/timeIntSpec[iSpec]; *(floatBuffer + (nSources*iSpec+iSource)*nChanBins +ii) = a; } else if(fluxScaling == 2) { a = (srcRate*10000.0)/timeIntSpec[iSpec]; *(floatBuffer + (nSources*iSpec+iSource)*nChanBins +ii) = a; } else if(fluxScaling == 3) { a = (srcRate*100.0)/timeIntSpec[iSpec]; *(floatBuffer + (nSources*iSpec+iSource)*nChanBins +ii) = a; } sumRate = sumRate + a; if(diagnosticMode == 1) { /* DIAGNOSTIC MODE */ *(floatBuffer + (nSources*iSpec+iSource)*nChanBins +ii) = (float) nRate[i]; } } }else{ openFraction = of[iSource]; /* Leakage coefficients are now computed for each source since open fractions now includes the collimator. */ status = j_src_leak_coefficients(leakage, a11, a12, a21, a22, openFraction, chatty, status); RILlogMessage( NULL, Log_0, "Source %d, openFraction = %f", ((int)iSource+1), openFraction); for ( ii=0 ; ii= J_CHATTY_NORMAL ){ if(nSum > 0){ aaa = sqrt((double)nSum+(double)(nBSum)*srcToBkgArea); a = ((double)nSum-(double)(nBSum)*srcToBkgArea); if(a != 0.0){ aaa = aaa/a; }else{ aaa = 10.0; } }else{ aaa = sumRate*10.0; } sumError = sumRate*aaa; if(sumError < 0.0){ sumError = -sumError; } RILlogMessage( NULL, Log_0, "Source %d, spectrum %d, net countrate = %f +/- %f", ((int)iSource+1), ((int)iSpec)+1, sumRate, sumError); } sumRate = 0.0; } } /* Now put the source countrates into the data structure Change to DALtablePutColBins to support time resolved option. 001127/SL */ status = DALtablePutCol(specPtr, "RATE", 0, diskType, nFloats, (void *) floatBuffer, status); if ( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : fill data column RATE in %s", status, structName); return status; } /* ------------------------------------------------------------------- Estimate statistical errors and store in STAT_ERR column. -------------------------------------------------------------------- */ /* Error estimate is: Signal S = R, which is scaled to detector area as R*f. Signal-to-noise is still R/sqrt(R) so scaling gives S/N = R*f/(sqrt(R)*f) = R*f/(sqrt(R*f)*f). Also Variance is additive (rate & bRate) Finaly the Poisson error is scaled to countrate. **************************************************************************/ for (iSpec=0 ; iSpec 19 && precisionLevel < 31){ /* For this source interpolate areas and correction factors from pifChannel to channel ii */ status = j_src_factors_interpol( iSource, pifChannel, openAreaEnergy, closedAreaEnergy, effOpenAreaEnergy, leakageFrOpenEnergy, leakageToClosedEnergy, nPifEnergies, openAreaChan, closedAreaChan, effOpenAreaChan, leakageFrOpenChan, leakageToClosedChan, chatty, status); for ( ii=0 ; ii J_CHATTY_VERBOSE ){ RILlogMessage(NULL,Log_0, "Spectrum number have been stored in %s ", structName); } /* ------------------------------------------------------------------- Write EVT_TYPE column. -------------------------------------------------------------------- */ /* Fill the int buffer (same size as for SPEC_NUM). */ for ( iSpec=0 ; iSpec J_CHATTY_VERBOSE ){ RILlogMessage(NULL,Log_0, "EVT_TYPE values have been stored in %s", structName ); } /* ------------------------------------------------------------------- Write CHANNEL column. -------------------------------------------------------------------- */ /* Now get an int data buffer for CHANNEL numbers. */ if (nInts < nChanBins*nSources*nSpec ){ if ( intBuffer != NULL){ status = DALfreeDataBuffer( (void *) intBuffer, status); if (status!= ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : could not free integer data buffer", status); return status; } } nInts = nChanBins*nSources*nSpec; bufferSize = nInts*sizeof(int); intBuffer = NULL; status = DALallocateDataBuffer( (void **)&intBuffer, bufferSize, status); if (status!= ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : could not allocate new integer data buffer", status); return status; } } diskType= DAL_INT; /* Fill the int buffer */ for ( iSpec=0 ; iSpec J_CHATTY_VERBOSE ){ RILlogMessage(NULL,Log_0, "Spectral channel numbers have been stored in %s ", structName); } /* Now put the CHANNEL numbers into JXMi-SRCL-BSP. */ status = DALtablePutCol(bspecPtr, "CHANNEL", 0, diskType, nValuesWrite, (void *) intBuffer, status); if ( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : fill data column CHANNEL in %s", status, bStructName); return status; } if( chatty > J_CHATTY_VERBOSE ){ RILlogMessage(NULL,Log_0, "Spectral channel numbers have been stored in %s ", bStructName); } /* ------------------------------------------------------------------- Write source identification in column ROWID. -------------------------------------------------------------------- */ if ( stringBuffer != NULL){ status = DALfreeDataBuffer( (void *) stringBuffer, status); if (status!= ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : could not free string data buffer", status); return status; } } nStrings = nSources*nSpec; stringBuffer = NULL; status = DALallocateStringBuffer(&stringBuffer, (int) nStrings, DAL_MED_STRING, status); if (status!=ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : could not allocate string buffer for source IDs", status); return status; } /* Fill the string buffer with source IDs */ for (iSpec=0 ; iSpec J_CHATTY_VERBOSE ){ RILlogMessage(NULL,Log_0, "Source IDs have been stored in %s ", structName); } /* ------------------------------------------------------------------- Fill the RA, DEC columns. -------------------------------------------------------------------- */ /* Make the float buffer */ status = DALfreeDataBuffer( (void *)floatBuffer, status); if (status!=ISDC_OK){ RILlogMessage(NULL, Warning_2, " %d : Could not free the float buffer", status); status = ISDC_OK; } floatBuffer = NULL; nFloats = nSources * nSpec; bufferSize = sizeof(float) * nFloats; status = DALallocateDataBuffer( (void **)&floatBuffer, bufferSize, status); if ( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : could not allocate float buffer", status); return status; } /* Put the source coordinates into JMXi-SRCL-SPE: */ for (iSpec=0 ; iSpec J_CHATTY_VERBOSE ){ RILlogMessage(NULL,Log_0, "R.A. and Dec have been stored in %s ", structName); } /* ------------------------------------------------------------------- Write filename containing ARF into column ANCRFILE. -------------------------------------------------------------------- */ if ( stringBuffer != NULL){ status = DALfreeDataBuffer( (void *) stringBuffer, status); if (status!= ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : could not free string data buffer", status); return status; } } nStrings = nSources*nSpec; stringBuffer = NULL; status = DALallocateStringBuffer(&stringBuffer, (int) nStrings, DAL_FILE_NAME_STRING, status); if (status!=ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : could not allocate string buffer for ARF-file name", status); return status; } /* Fill the string buffer. */ stringlength = strlen(ancrFileName); if(stringlength <= DAL_FILE_NAME_STRING - 5) { for (iSpec=0 ; iSpec J_CHATTY_VERBOSE ){ RILlogMessage(NULL,Log_0, "ANCRFILE (ARF file names) have been stored in %s ", structName); } } /* ------------------------------------------------------------------- Write filename containing RMF into keyword RESPFILE. -------------------------------------------------------------------- */ /* Write to JMXi-SRCL-SPE: */ /* Set response information */ if (0 J_CHATTY_VERBOSE ){ RILlogMessage(NULL,Log_0, "EXPOSURE values have been stored in %s ", structName); } status = DALtablePutCol(bspecPtr, "EXPOSURE", 0, diskType, (long) nDoubles, (void *) dblBuffer, status); if ( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : fill data column EXPOSURE in %s", status, bStructName ); return status; } if( chatty > J_CHATTY_VERBOSE ){ RILlogMessage(NULL,Log_0, "EXPOSURE values have been stored in %s ", bStructName); } /* ------------------------------------------------------------------- Write BACKSCAL column. -------------------------------------------------------------------- */ for (iSpec=0 ; iSpec J_CHATTY_VERBOSE ){ RILlogMessage(NULL,Log_0, "BACKSCAL values have been stored in %s ", structName); } /* ------------------------------------------------------------------- Write TFIRST column. -------------------------------------------------------------------- */ /* Fill the double buffer with TFIRST values. */ for (iSpec=0 ; iSpec J_CHATTY_VERBOSE ){ RILlogMessage(NULL,Log_0, "TFIRST values have been stored in %s ", structName); } /* Put the start times into JMXi-SRCL-BSP */ status = DALtablePutCol(bspecPtr, "TFIRST", 0, diskType, (long) nDoubles, (void *) dblBuffer, status); if ( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : fill data column TFIRST in %s", status, bStructName); return status; } if( chatty > J_CHATTY_VERBOSE ){ RILlogMessage(NULL,Log_0, "TFIRST values have been stored in %s ", bStructName); } /* ------------------------------------------------------------------- Write TLAST column. -------------------------------------------------------------------- */ /* Fill the double buffer with TLAST values. */ for (iSpec=0 ; iSpec J_CHATTY_VERBOSE ){ RILlogMessage(NULL,Log_0, "TLAST values have been stored in %s ", structName); } /* Put the end times into JMXi-SRCL-BSP */ status = DALtablePutCol(bspecPtr, "TLAST", 0, diskType, (long) nDoubles, (void *) dblBuffer, status); if ( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : fill data column TLAST in %s", status, bStructName); return status; } if( chatty > J_CHATTY_VERBOSE ){ RILlogMessage(NULL,Log_0, "TLAST values have been stored in %s ", bStructName); } /************************************************************************** Add keywords. ***************************************************************************/ status = CommonStampObject(specPtr, "Source spectra written", status); if ( status!=ISDC_OK ){ RILlogMessage(NULL, Warning_2, "%d : Could not stamp data structure %s%s ", status, jemxStr,J_SRC_SPEC_DS); status = ISDC_OK; } /* Put in the flags to show which corrections have been performed */ strcpy(appFlag, "T"); status = DALattributePut(specPtr, "BACKAPP", DAL_BOOL, (void *) appFlag, NULL, "Spectra not corrected for background", status); if ( status!=ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not put BACKAPP keyword in %s", status, structName); return status; } strcpy(appFlag, "F"); status = DALattributePut(specPtr, "DEADAPP", DAL_BOOL, (void *) appFlag, NULL, "Spectra not corrected for deadtime", status); if ( status!=ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not put DEADAPP keyword in %s", status, structName); return status; } strcpy(appFlag, "F"); status = DALattributePut(specPtr, "VIGNAPP", DAL_BOOL, (void *) appFlag, NULL, "Spectra not corrected for vignetting", status); if ( status!=ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not put VIGNAPP keyword in %s", status, structName); return status; } /************************* Free up the data buffers *************************/ if ( intBuffer != NULL){ status = DALfreeDataBuffer( (void *) intBuffer, status); if (status!= ISDC_OK ){ RILlogMessage(NULL, Warning_2, "%d : could not free integer data buffer", status); return status; } } if ( floatBuffer != NULL){ status = DALfreeDataBuffer( (void *)floatBuffer, status); if (status!=ISDC_OK){ RILlogMessage(NULL, Warning_2, " %d : Could not free the float buffer", status); status = ISDC_OK; } } if ( stringBuffer != NULL){ status = DALfreeStringBuffer( stringBuffer, (int) nStrings, status); if (status!=ISDC_OK){ RILlogMessage(NULL, Warning_2, " %d : Could not free the string buffer", status); status = ISDC_OK; } } if ( aLC11 != NULL){ status = DALfreeDataBuffer( (void *) aLC11, status); if (status!= ISDC_OK ){ RILlogMessage(NULL, Warning_2, "%d : could not free aLC11 allocation", status); return status; } } return status ; } /************************************************************************ * * j_src_mask v1.0 13/09/2001 * * * Source file: j_src_lc/spectra.c * File version : 2.5 * Date: 2001/09/13 * Function name j_src_mask * Function version : 1.0 * Parent component: j_src_work * Children: j_src_mask_find_element * j_mask_findxy * Developer: Stefan Larsson * Contact Address: Stockholm Observatory * SCFAB * SE-106 91 Stockholm * Phone: +46 8-5537 8543 FAX: +46 8-5537 8510 * stefan@astro.su.se * Purpose: To set up an array containing a description * of the mask pattern. * The array ("mask") will code the mask transparancy * at each element as: * 1 = open * 0 = closed * 7 = uncoded (outside of the mask) * Mask transparancy at any point can then be found * by first calling j_src_mask_find_element to get * the corresponding mask element and read the * transparancy code from "mask[][]". * * Comment: Since the routine will only be used for positive * values the handling of negative values could be * taken out. * Some cleaning of old parameters and test output * would be in order.......... * * Modification history: v0.02 1999/09/29 * Introduced -1 in mask-values to indicate * uncoded point. * 2001/06/19 2.2 SL Error in mask geomery definition corrected. * Using same transparancy definitions (0,1,7) * as imaging software. * HOWEVER: Mask coordinates are NOT the same. * We use linear coordintes. * *------------------------------------------------------------------------- * * PARAMETERS: * * yin, xin = Mask coordinates for hole as read from * input file. * iny, inx = Index to indicate when values are stored * in yin, xin. * * *************************************************************************/ #include int j_src_mask( short mask[J_DIM_MASK][J_DIM_MASK], short maskArray[J_DIM_MASK][J_DIM_MASK], int chatty, /* Level of debugging output */ int status) /* Status flag */ { double yin, xin, rho; double posX, posY; double relX = 0.0; double relY = 0.0; int ix, iy; int i, j; int elements, open, closed, outside, wrong; int open0 = 0; int closed0 = 0; int outside0 = 0; int wrong0 = 0; double openfraction = 0.0; double ratio = 1000.0; rho = 1.65; elements = 0; open = 0; closed = 0; outside = 0; wrong = 0; yin = 0.0; xin = 0.0; if( chatty > J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_0,"In routine j_src_mask"); } /* *Immediate return if called while executable is in error condition */ if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : Non-zero status value passed to j_src_mask",\ status); return status ; } /* * Initialize the the mask-array with index = 7 (outside pattern) */ for (i=0;i<=J_DIM_MASK-1;i=i+1){ for (j=0;j<=J_DIM_MASK-1;j=j+1){ mask[i][j] = 7; /* Initialize to outside of the mask */ } } /* * Transform hole indexes from maskPatternArray -> mask * and store mask element values in array mask. */ for (i=-J_DIM_MASK/2;i<=J_DIM_MASK/2;i=i+1){ for (j=-J_DIM_MASK/2;j<=J_DIM_MASK/2;j=j+1){ /* xin = -rho*(double)(2*i + j); */ xin = rho*(double)(2*i + j); yin = rho*sqrt(3.0) * (double)j; status = j_src_mask_find_element( xin, yin, &relX, &relY, &ix, &iy, chatty, /* Level of output */ status); /* Status flag */ status = j_mask_findxy(ix,iy,&posX,&posY,chatty,status); if( ((ix>=0)&&(ix=0)&&(i+100=0)&&(iy=0)&&(j+100 0) { RILlogMessage(NULL,Warning_2, "Number of wrong values in mask calculation: %d", wrong); } elements = closed + open; if (elements != 0) { openfraction = (double)open / (double)elements; } if( chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_0, "After mask transf.: Mask open fraction: %f", openfraction); } return status; } /************************************************************************ * * j_src_mask_find_element v1.0 13/09/2001 * * Source file: j_src_lc/spectra.c * File version : 2.5 * Date: 2001/09/13 * Function name j_src_mask_find_element * Function version : 1.0 * Parent component: j_src_mask * Children: j_src_oddeven * Developer: Stefan Larsson * Contact Address: Stockholm Observatory * SCFAB * SE-106 91 Stockholm * Phone: +46 8-5537 8543 FAX: +46 8-5537 8510 * stefan@astro.su.se * Purpose: Given a point (x,y) on the mask find the * corresponding matrix element in "mask[][]" (nearest * hole, closed or open.) * * Comment: *****************************************************************************/ #include int j_src_mask_find_element(double posX, double posY, double *relX, double *relY, int *ix, int *iy, int chatty, /* Level of debugging output */ int status) /* Status flag */ { double aix, aiy; double holeX = 0.0; double holeY = 0.0; int iny = 0; int iyodd = 0; int in = 0; int in2 = 0; /* Immediate return if called while executable is in error condition */ if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : Non-zero status value passed to j_src_mask_find_element",\ status); return status ; } aiy = posY/J_MASK_ELEM_RS; aiy = aiy + 1100.0; /* Center of mask is at mask[100][100] */ iny = (int) (aiy+0.5); iny = iny - 1000; iyodd = (iny % 2); *iy = iny; /* Below we do +1100 and -1000 since 1) The (int) statement to round off assumes positive values. 2) The center of mask is at mask[100][100] */ if (iyodd == 0) { aix = posX/J_MASK_ELEM_RD; aix = aix + 1100.0; *ix = (int) (aix+0.5); *ix = *ix - 1000; } else { aix = posX/J_MASK_ELEM_RD+0.5; aix = aix + 1100.0; *ix = (int) (aix+0.5); *ix = *ix - 1000; } /* The identification of mask element above was based on a rectangular approximation of mask elements. Lets now correct for the actual hexagonal shape. */ status = j_mask_findxy(*ix,*iy,&holeX,&holeY,chatty,status); *relX = posX - holeX; *relY = posY - holeY; status = j_src_in_hole (*relX, *relY, &in, chatty, status); if(in == 0) { if(*relY > 0 && *relX > 0) { *iy = *iy+1; if (iyodd == 0) { *ix = *ix+1; } } if(*relY < 0 && *relX > 0) { *iy = *iy-1; if (iyodd == 0) { *ix = *ix+1; } } if(*relY < 0 && *relX < 0) { *iy = *iy-1; if (iyodd != 0) { *ix = *ix-1; } } if(*relY > 0 && *relX < 0) { *iy = *iy+1; if (iyodd != 0) { *ix = *ix-1; } } status = j_mask_findxy(*ix,*iy,&holeX,&holeY, chatty,status); *relX = posX - holeX; *relY = posY - holeY; status = j_src_in_hole (*relX, *relY, &in2, chatty, status); } return status; } /************************************************************************ * * j_mask_findxy v1.0 13/09/2001 * * Source file: j_src_lc/spectra.c * File version : 2.5 * Date: 2001/09/13 * Function name j_src_findxy * Function version : 1.0 * Parent component: j_src_mask * j_src_through_mask * Children: * Developer: Stefan Larsson * Contact Address: Stockholm Observatory * SCFAB * SE-106 91 Stockholm * Phone: +46 8-5537 8543 FAX: +46 8-5537 8510 * stefan@astro.su.se * Purpose: Given a matrix element in "mask[][]" find the * corresponding (x,y) coordinates for the center * of that element. * * Input: ix, iy Mask element indices * Output: posX, posY (x.y) position in mm of the mask element. * * Comment: Adapted from JMaskFindXY ***************************************************************************/ int j_mask_findxy(int ix, int iy, double *posX, double *posY, int chatty, int status) { int iyodd; status = 0; iyodd = (iy % 2); *posY = J_MASK_ELEM_RS*(iy-100); if (iyodd == 0) { *posX = J_MASK_ELEM_RD*(ix-100); } else { *posX = J_MASK_ELEM_RD*((ix-100)-0.5); } return status; } /************************************************************************ * * j_eventweight v1.0 13/09/2001 * * Source file: j_src_lc/spectra.c * File version : 2.5 * Date: 2001/09/13 * Function name j_eventweight * Function version : 1.0 * Parent component: j_src_work * Children: j_src_through_mask * j_src_through_balk (new 031208) * Developer: Stefan Larsson * Contact Address: Stockholm Observatory * SCFAB * SE-106 91 Stockholm * Phone: +46 8-5537 8543 FAX: +46 8-5537 8510 * stefan@astro.su.se * Purpose: Calculate an event weight. * Done by calling ray tracing routines that * calculates the source visibility from the * event position. * * The weight of an event is its net contribution * to the flux of a source at a given position * (sourceX,sourceY). * The coordinates of the source is given as its * projected mask position when viewed from the * center of the detector. * * * Input: * Output: * * Comment: eventPi, the energy of the event, is not yet * used in the visibility calculation. * * This version use integer weights (-1,0 or 1). * Fractional weights will be implemented later. * * Update history: * 2003/12/10 CK Included longsph, shortsph, balk[][] in the * function definition. * Included call to j_src_through_balk. * ***************************************************************************/ int j_eventweight(double eventX, double eventY, double sourceX, double sourceY,double detMaskDist, short mask[J_DIM_MASK][J_DIM_MASK], double longsph, double shortsph, unsigned char balk[J_DIM_BALK][J_DIM_BALK], int eventPi, float *eventweight, int chatty, int status) { int ix=0; int iy=0; short weightInt; short maskweight; short balkweight; /* *Immediate return if called while executable is in error condition */ if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : Non-zero status value passed to j_eventweight", status); return status ; } status = j_src_through_mask( eventX, eventY, sourceX, sourceY, &weightInt, mask, chatty, status); maskweight=weightInt; /***********************************************************/ /* Balktest */ /* Test 1 (0.0) sourceX = 0.0; sourceY = 0.0 ; */ /* Test 2 (125.0) sourceX = 125.0; sourceY = 0.0 ; */ /* Test 3 (m125.0) sourceX = -125.0; sourceY = 0.0 ; */ /* Test 4 (0.125) sourceX = 0.0; sourceY = 125.0 ; */ /* Test 5 (0.m125) sourceX = 0.0; sourceY = -125.0 ; */ /* Test 6 (125.125) sourceX = 125.0; sourceY = 125.0 ; */ /* Test 7 (m125.m125) sourceX = -125.0; sourceY = -125.0 ; */ /* Test 8 (250.0) sourceX = 250.0; sourceY = 0.0 ; */ /* Test 9 (125.m125) sourceX = 125.0; sourceY = -125.0 ; */ /* Test 10 (m125.125) sourceX = -125.0; sourceY = 125.0 ; */ /* for (ix = 1; ix < 1200 ; ix++){ eventX = -300.0 + ix*0.5; for (iy = 1; iy <1200 ; iy++){ eventY = -300.0 + iy*0.5; status = j_src_through_balk(eventX, eventY, sourceX, sourceY, detMaskDist, longsph, shortsph, balk, &weightInt, chatty, status); if (weightInt == -1) { RILlogMessage( NULL, Log_0, "Balk: %f %f", eventX,eventY); } } } exit(0); */ /***********************************************************/ /* status = j_src_through_balk(eventX, eventY, sourceX, sourceY, detMaskDist,longsph,shortsph, balk, &weightInt, chatty, status); */ if(J_SRC_IGNORE_BALK == 1){ balkweight=1; }else{ balkweight=weightInt; } if ((maskweight == 1) && (balkweight == 1)){ /* Mask and balk open. I.e. ray reaches detector */ *eventweight = 1; } else if ((maskweight == 7) || (balkweight == 7)){ /* ray outside of balk and mask array. CK question */ *eventweight = 7; } else if ((maskweight == -1) || (balkweight == -1)){ /* Either mask or balk closed. I.e. ray does not reach detector */ *eventweight = -1; } else{ RILlogMessage(NULL, Error_2, "%d %d: Unknown weights in j_eventweight", maskweight,balkweight); status = J_SRC_WRONG_VALUE; } return(status); } /***************************************************************** * * j_src_through_coll v1.0 27/07/2003 * * Source file: j_src_lc/spectra.c * File version : 3.5 * Date: 2003/07/27 * Function name j_src_through_coll * Function version : 1.0 * Parent component: * Children: * Developer: Stefan Larsson * Contact Address: Stockholm Observatory * SCFAB * SE-106 91 Stockholm * Phone: +46 8-5537 8543 FAX: +46 8-5537 8510 * stefan@astro.su.se * Purpose: Given source coordinates and event position * find collimator transparancy. In other words: * Is there a free path from the event * position towards the source? * If the line of sight goes through the * perifery (radius 125mm) of the collimator * the event is neglected (weight = 7). * * Origin date: 030727 * Update history: * * Error codes: See j_src_lc/spectra.txt * * collimator[ix][jy] = 1 At collimator cross * 0 if no collimator cross at this point * 2 if outside of collimator but coordinates * added for computation ease. * * ***********************************************************************/ #include int j_src_through_coll( double eventX, /* Event detector position in X */ double eventY, /* Event detector position in Y */ double sourceX, /* Source X-pos as projected on mask */ double sourceY, /* Source Y-pos as projected on mask */ double collimatorXBot[J_SRC_COLL_SIZE][J_SRC_COLL_SIZE], double collimatorYBot[J_SRC_COLL_SIZE][J_SRC_COLL_SIZE], double collimatorXTop[J_SRC_COLL_SIZE][J_SRC_COLL_SIZE], double collimatorYTop[J_SRC_COLL_SIZE][J_SRC_COLL_SIZE], int collimator[J_SRC_COLL_SIZE][J_SRC_COLL_SIZE], double detMaskDist, double collHeight, /* Collimator height */ float *weight, /* Integer event weight */ int chatty, /* Level of debugging output */ int status) /* Status flag */ { /* Ordinary variables */ long ix = 0; long jy = 0; int xOK = 0; int yOK = 0; double posX = 0.0; double posY = 0.0; /* 1. Ignore events outside of collimator radius (125 mm). */ if(sqrt(eventX*eventX+eventY*eventY) > 125.0){ *weight = 7.0; return status; } /* 2. In which collimator cell is the event? */ /* First estimate (lower corner in both x & y). */ ix = (long int) (21.0 + eventX/7.05); jy = (long int) (21.0 + eventY/7.05); /* 3. Verify index. */ if(ix < 0 || ix > J_SRC_COLL_SIZE){ status = J_SRC_INDEX_ERR; RILlogMessage(NULL, Error_2, "%d : Array index out of range in j_src_through_col", status); return status; } if(jy < 0 || jy > J_SRC_COLL_SIZE){ status = J_SRC_INDEX_ERR; RILlogMessage(NULL, Error_2, "%d : Array index out of range in j_src_through_coll", status); return status; } /* 4. Make sure we are in the correct cell. Keep stepping until we are. (This will be neccessary if the instrument model, cross positions, are modified. */ do { if(collimator[ix][jy]==0 && collimator[ix+1][jy+1]>=1){ collimatorXBot[ix][jy] = collimatorXBot[ix+1][jy+1]-7.05; collimatorYBot[ix][jy] = collimatorYBot[ix+1][jy+1]-7.05; collimatorXTop[ix][jy] = collimatorXTop[ix+1][jy+1]-7.05; collimatorYTop[ix][jy] = collimatorYTop[ix+1][jy+1]-7.05; collimator[ix][jy] = 2; } if(collimator[ix][jy]>=1 && collimator[ix+1][jy+1]==0){ collimatorXBot[ix][jy] = collimatorXBot[ix+1][jy+1]+7.05; collimatorYBot[ix][jy] = collimatorYBot[ix+1][jy+1]+7.05; collimatorXTop[ix][jy] = collimatorXTop[ix+1][jy+1]+7.05; collimatorYTop[ix][jy] = collimatorYTop[ix+1][jy+1]+7.05; collimator[ix+1][jy+1] = 2; } if(collimator[ix][jy]==0 && collimator[ix+1][jy+1]==0){ *weight = 7.0; RILlogMessage(NULL, Warning_2, "%d : Event outside of collimator. Ignored."); return status; } if(collimatorXBot[ix][jy]<=eventX && collimatorXBot[ix+1][jy+1]>=eventX) { xOK = 1; }else{ if(eventX < collimatorXBot[ix][jy]){ ix = ix-1; } if(eventX > collimatorXBot[ix+1][jy+1]){ ix = ix+1; } xOK = 0; } if(collimatorYBot[ix][jy]<=eventY && collimatorYBot[ix+1][jy+1]>=eventY) { yOK = 1; }else{ if(eventY < collimatorYBot[ix][jy]){ jy = jy-1; } if(eventY > collimatorYBot[ix+1][jy+1]){ jy = jy+1; } yOK = 0; } /* if(xOK+yOK<2){ RILlogMessage(NULL, Error_2, "xOK, yOK, ix, jy = %d %d %d %d", xOK, yOK, ix, jy); RILlogMessage(NULL, Log_2, "colX, eventX = %f %f", collimatorXBot[ix][jy], eventX); RILlogMessage(NULL, Log_2, "colY, eventY = %f %f", collimatorYBot[ix][jy], eventY); } */ }while(xOK+yOK<2); /* 5. Compute the projection point, at the top of the collimator, of the line of sight from the event towards the source. Compare with the edge of the collimator wall (0.225 mm half thickness). */ posX = eventX + sourceX*collHeight/detMaskDist; posY = eventY + sourceY*collHeight/detMaskDist; *weight = 1.0; if(posX > collimatorXTop[ix+1][jy+1]-0.225) { *weight = -1.0; } if(posX < collimatorXTop[ix][jy]+0.225) { *weight = -1.0; } if(posY > collimatorYTop[ix+1][jy+1]-0.225) { *weight = -1.0; } if(posY < collimatorYTop[ix][jy]+0.225) { *weight = -1.0; } if(sqrt(posX*posX+posY*posY) > 125.0){ *weight = 7.0; } return status; } /***************************************************************** * * j_src_event_add v1.0 18/09/2003 * * Source file: j_src_lc/spectra.c * File version : 3.5 * Date: 2003/09/18 * Function name j_src_event_add * Function version : 1.0 * Parent component: j_src_work * Children: * Developer: Stefan Larsson * Contact Address: Stockholm Observatory * SCFAB * SE-106 91 Stockholm * Phone: +46 8-5537 8543 FAX: +46 8-5537 8510 * stefan@astro.su.se * Purpose: Given a detector position hit by a photon * add the response distribution function * (eventDistr) to the pif for this source * (pifWork). * * Loop over all points in the distribution function * and put them in the proper pixel. * This is done by first approximating each * pixel with a rectangle at the outer limits of * the pixel. If a point is inside the rectangle * Origin date: 030918 * Update history: * * Error codes: See j_src_lc/spectra.txt * * ipx,ipy = Indexes running over the 2D distribution array. * * PSFStep = Step (mm) betwen the points in array eventDistr. * * subPifX,subPifY = (X,Y) detector position (mm) for a point in the * event distribution function, eventDistr. * xmin,xmax * ymin,ymax = 2d arrays containing the coordinates of a * rectangle at the outer limits of the pixel. * (The pixels themselfs have an irregular shape) * * STATUS: Works, BUT accepts all intermediate cases (inbetween * the inner and outer rectangle) and does not stop * loop over surrounding pixels at a hit. "used" makes * sure that a distribution point is only used once. * (Take away "used" when intermediate case is handled better). * ***********************************************************************/ #include int j_src_event_add(long ix, long jy, double subPixelX, double subPixelY, float detPixArea[J_NUM_X_PIXELS][J_NUM_Y_PIXELS], float detPixLLX[J_NUM_X_PIXELS][J_NUM_Y_PIXELS], float detPixLLY[J_NUM_X_PIXELS][J_NUM_Y_PIXELS], float pifWork[J_NUM_X_PIXELS][J_NUM_Y_PIXELS], float eventDistr[J_NUM_EVENT_PIXELS][J_NUM_EVENT_PIXELS], float PSFStep, long midPSF, int chatty, int status) { /* Ordinary variables */ long i = 0; long j = 0; long ipx = 0; long jpy = 0; long jj = 0; long ii = 0; long istart = 0; long jstart = 0; long ilast = 0; long jlast = 0; int used = 0; float subPifX = 0.0; float subPifY = 0.0; float xmin[7][7]; float xmax[7][7]; float ymin[7][7]; float ymax[7][7]; float xminIn[7][7]; float xmaxIn[7][7]; float yminIn[7][7]; float ymaxIn[7][7]; istart = ix - 3; jstart = jy - 3; ilast = ix + 3; jlast = jy + 3; if(istart < 0) istart = 0; if(jstart < 0) jstart = 0; if(ilast > J_NUM_X_PIXELS-1) ilast = J_NUM_X_PIXELS-1; if(jlast > J_NUM_X_PIXELS-1) jlast = J_NUM_X_PIXELS-1; /* RILlogMessage(NULL,Log_0, "ix,jy,istart,ilast,jstart,jlast: %d %d %d %d %d %d", ix,jy,istart,ilast,jstart,jlast); */ /* Compute the limits of an outer and an inner rectangle for each of the pixels concidered. This is used for a fast check if a point can be or has to be inside a particular pixel. If it is in the intermediate region a more detailed check has to be done. */ for ( i=istart ; i detPixLLX[i][j+1]){ xmin[i-ix+3][j-jy+3] = detPixLLX[i][j+1]; } xmax[i-ix+3][j-jy+3] = detPixLLX[i+1][j]; if(xmax[i-ix+3][j-jy+3] < detPixLLX[i+1][j+1]){ xmax[i-ix+3][j-jy+3] = detPixLLX[i+1][j+1]; } ymin[i-ix+3][j-jy+3] = detPixLLY[i][j]; if(ymin[i-ix+3][j-jy+3] > detPixLLY[i+1][j]){ ymin[i-ix+3][j-jy+3] = detPixLLY[i+1][j]; } ymax[i-ix+3][j-jy+3] = detPixLLY[i][j+1]; if(ymax[i-ix+3][j-jy+3] < detPixLLY[i+1][j+1]){ ymax[i-ix+3][j-jy+3] = detPixLLY[i+1][j+1]; } xminIn[i-ix+3][j-jy+3] = detPixLLX[i][j]; if(xminIn[i-ix+3][j-jy+3] > detPixLLX[i][j+1]){ xminIn[i-ix+3][j-jy+3] = detPixLLX[i][j+1]; } xmaxIn[i-ix+3][j-jy+3] = detPixLLX[i+1][j]; if(xmaxIn[i-ix+3][j-jy+3] < detPixLLX[i+1][j+1]){ xmaxIn[i-ix+3][j-jy+3] = detPixLLX[i+1][j+1]; } yminIn[i-ix+3][j-jy+3] = detPixLLY[i][j]; if(yminIn[i-ix+3][j-jy+3] > detPixLLY[i+1][j]){ yminIn[i-ix+3][j-jy+3] = detPixLLY[i+1][j]; } ymaxIn[i-ix+3][j-jy+3] = detPixLLY[i][j+1]; if(ymaxIn[i-ix+3][j-jy+3] < detPixLLY[i+1][j+1]){ ymaxIn[i-ix+3][j-jy+3] = detPixLLY[i+1][j+1]; } } } for ( ipx=0 ; ipx xmin[ii][jj] && subPifX < xmax[ii][jj]){ if(subPifY > ymin[ii][jj] && subPifY < ymax[ii][jj]){ /* So, the point is inside the outer rectangle. */ if((subPifX > xminIn[ii][jj]) && (subPifX < xmaxIn[ii][jj]) && (subPifY > yminIn[ii][jj]) && (subPifY < ymaxIn[ii][jj]) ){ /* OK inside inner rectangle. Add to this pixel.*/ pifWork[i][j] = pifWork[i][j] + eventDistr[ipx][jpy]; used = 1; }else{ /* In between rectangles require more work..... */ if(used == 1){ pifWork[i][j] = pifWork[i][j] + eventDistr[ipx][jpy]; } } } } } } } } return status; } /***************************************************************** * * j_src_event_add_0 v1.0 18/09/2003 * * Source file: j_src_lc/spectra.c * File version : 3.5 * Date: 2003/09/18 * Function name j_src_event_add * Function version : 1.0 * Parent component: j_src_work * Children: * Developer: Stefan Larsson * Contact Address: Stockholm Observatory * SCFAB * SE-106 91 Stockholm * Phone: +46 8-5537 8543 FAX: +46 8-5537 8510 * stefan@astro.su.se * Purpose: Given a detector position hit by a photon * add the response distribution function * (eventDistr) to the pif for this source * (pifWork). * * Loop over all points in the distribution function * and put them in the proper pixel. * This is done by first approximating each * pixel with a rectangle at the outer limits of * the pixel. If a point is inside the rectangle * * Origin date: 030918 * Update history: * * Error codes: See j_src_lc/spectra.txt * * ipx,ipy = Indexes running over the 2D distribution array. * * PSFStep = Step (mm) betwen the points in array eventDistr. * * subPifX,subPifY = (X,Y) detector position (mm) for a point in the * event distribution function, eventDistr. * xmin,xmax * ymin,ymax = 2d arrays containing the coordinates of a * rectangle at the outer limits of the pixel. * (The pixels themselfs have an irregular shape) * * subPif contains one (nSubPifPix*nSubPifPix) array per subpixel * (There are nstep*nstep subpixels). * nSubPifPix SHOULD be odd! * * STATUS: Works, BUT accepts all intermediate cases (inbetween * the inner and outer rectangle) and does not stop * loop over surrounding pixels at a hit. "used" makes * sure that a distribution point is only used once. * (Take away "used" when intermediate case is handled better). * ***********************************************************************/ #include int j_src_event_add_0( float *subPif, int nSubPifPix, int nstep, float eventDistr[J_NUM_EVENT_PIXELS][J_NUM_EVENT_PIXELS], float PSFStep, long midPSF, int chatty, int status) { /* Ordinary variables */ long i = 0; long j = 0; long ipx = 0; long jpy = 0; int nShiftX = 0; int nShiftY = 0; int midSubPifPix = 0; int iadd = 0; int jadd = 0; int offset = 0; float subPifX = 0.0; float subPifY = 0.0; float subPixelX = 0.0; float subPixelY = 0.0; float anstep = 0.0; float anorm = 0.0; float xstep = 0.0; float ystep = 0.0; /* Subpixel coordinates are relative to pixel center. */ midSubPifPix = nSubPifPix/2; anstep = (float) nstep; xstep = 1.0/anstep; ystep = 1.0/anstep; for ( i=0 ; i= 0 && iadd < nSubPifPix){ if(jadd >= 0 && jadd < nSubPifPix){ offset = (nSubPifPix*nSubPifPix)*(i*nstep+j)+ iadd*nSubPifPix+jadd; *(subPif+(offset)) = *(subPif+(offset)) + eventDistr[ipx][jpy]; } } } } } } /* Normalize pif to one event per full pixel */ anorm = 1.0/(anstep*anstep); for ( i=0 ; i int j_src_pif_sort( float pifWork[J_NUM_X_PIXELS][J_NUM_Y_PIXELS], float detCorX[J_NUM_X_PIXELS][J_NUM_Y_PIXELS], float detCorY[J_NUM_X_PIXELS][J_NUM_Y_PIXELS], float *openCut, float *closedCut, double radMask, double *openArea1, double *closedArea1, double *effOpenArea, double *leakageFrOpen, double *leakageToClosed, double radiusLimit, int chatty, int status) { /* Ordinary variables */ long i = 0; long j = 0; long bufferSize = 0; long npoints = -1; long count = 0; double sumOpenPif = 0.0; double sumClosedPif = 0.0; double srcSum = 0.0; double bkgrSum = 0.0; double openSumTmp = 0.0; double signalToNoiseMax = 0.0; double srcRatePerPixel = 1.0; double bkgRatePerPixel = 1.0; double sumPif = 0.0; float xCoord = 0.0; float yCoord = 0.0; float radius = 0.0; float *sortedPif = NULL; double openCut1 = 0.0 ; /* float *areaPif = NULL; */ float pcount = 0.0; *openCut = J_SRC_PIF_OPEN_CUT; *closedCut = J_SRC_PIF_CLOSED_CUT; bufferSize = J_NUM_X_PIXELS*J_NUM_X_PIXELS*sizeof(float); status = DALallocateDataBuffer( (void **)&sortedPif, bufferSize, status); /* if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not allocate memory for sortedPif ", status ); status = DALallocateDataBuffer( (void **)&areaPif, bufferSize, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not allocate memory for areaPif ", status ); return status; } */ /* */ for ( i=0 ; i= -0.001){ npoints = npoints + 1; sortedPif[npoints] = pifWork[i][j]; } } } if(npoints > 1){ status = j_src_sort( sortedPif, (unsigned long) npoints, chatty, status); if( chatty > J_CHATTY_VERBOSE ){ RILlogMessage(NULL, Log_0," %d pifs sorted", (int) npoints); } }else{ if( chatty > J_CHATTY_VERBOSE ){ RILlogMessage(NULL, Log_0," No positive PIF values"); } } *effOpenArea = 0.0; *openArea1 = 0.0; *closedArea1 = 0.0; *leakageFrOpen = 0.0; *leakageToClosed = 0.0; sumOpenPif = 0.0; sumClosedPif = 0.0; count = 0; pcount = 0.0; sumPif = 0.0; /* First try to set cutlevel. Select level for which leakage is about 0.25 */ for ( i=0 ; i *openCut){ *openArea1 = *openArea1 + 1.0; sumOpenPif = sumOpenPif + (double)sortedPif[i]; } if(sortedPif[i] < *closedCut){ *closedArea1 = *closedArea1 + 1.0; sumClosedPif = sumClosedPif + (double)sortedPif[i]; } } if(*effOpenArea > 0.0){ if(*openArea1 > 0.0){ *leakageFrOpen = (*effOpenArea - sumOpenPif)/(*effOpenArea); }else{ *leakageFrOpen = 0.0; } if(*closedArea1 > 0.0){ *leakageToClosed = sumClosedPif/(*effOpenArea); }else{ *leakageToClosed = 0.0; } }else{ *leakageFrOpen = 0.0; *leakageToClosed = 0.0; } openSumTmp = 0.0; for ( i=0 ; i J_CHATTY_NORMAL ){ RILlogMessage(NULL, Log_0, " Effective illuminated Area: %f", *effOpenArea ); RILlogMessage(NULL, Log_0," Open area (from PIF > %f ): %f", *openCut, *openArea1 ); RILlogMessage(NULL, Log_0," Closed area (from PIF < %f ): %f", *closedCut, *closedArea1 ); RILlogMessage(NULL, Log_0, " Leakage (fraction of ill. flux) from open area (PIF > %f ): %f", *openCut, *leakageFrOpen ); RILlogMessage(NULL, Log_0, " Leakage (fraction of ill. flux) to closed area (PIF < %f ): %f", *closedCut, *leakageToClosed ); } return status; } /***************************************************************** * * j_src_pif_sort25 v1.0 19/03/2004 * * Source file: j_src_lc/spectra.c * File version : 3.5 * Date: 2004/03/19 * Function name j_src_pif_sort * Function version : 1.0 * Parent component: j_src_work * Children: * Developer: Stefan Larsson * Contact Address: Stockholm Observatory * SCFAB * SE-106 91 Stockholm * Phone: +46 8-5537 8543 FAX: +46 8-5537 8510 * stefan@astro.su.se * Purpose: Sort the pif values in pifWork[][] from * min to max (0 to 1). Apply cut criteria for * the classification as source illuminated and * shadowed areas. * At present the sorted values are not used to * optimize the cut value. This will be * implemented after more testing. * * Origin date: 040319 * Update history: * * Error codes: See j_src_lc/spectra.txt * * Note: pif values < 0 are not used since these are * "bad pixels" (e.g. dead anode areas). * * ***********************************************************************/ #include int j_src_pif_sort25( float pifWork[J_NUM_X_PIXELS][J_NUM_Y_PIXELS], float detCorX[J_NUM_X_PIXELS][J_NUM_Y_PIXELS], float detCorY[J_NUM_X_PIXELS][J_NUM_Y_PIXELS], float detPixArea[J_NUM_X_PIXELS][J_NUM_Y_PIXELS], float *openCut, float *closedCut, double radMask, double *openArea1, double *closedArea1, double *effOpenArea, double *leakageFrOpen, double *leakageToClosed, double radiusLimit, int chatty, int status) { /* Ordinary variables */ long i = 0; long j = 0; long bufferSize = 0; long npoints = -1; long count = 0; double sumOpenPif = 0.0; double sumClosedPif = 0.0; double srcSum = 0.0; double bkgrSum = 0.0; double openSumTmp = 0.0; double pixelArea = 1.0; float xCoord = 0.0; float yCoord = 0.0; float radius = 0.0; float *sortedPif = NULL; float pcount = 0.0; float sortedPifArea[J_NUM_X_PIXELS*J_NUM_X_PIXELS]; *openCut = J_SRC_PIF_OPEN_CUT; *closedCut = J_SRC_PIF_CLOSED_CUT; bufferSize = J_NUM_X_PIXELS*J_NUM_X_PIXELS*sizeof(float); status = DALallocateDataBuffer( (void **)&sortedPif, bufferSize, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not allocate memory forsortedPif ", status ); return status; } /* */ for ( i=0 ; i= -0.001){ npoints = npoints + 1; sortedPif[npoints] = pifWork[i][j]; sortedPifArea[npoints] = detPixArea[i][j]; } } } if(npoints > 1){ status = j_src_sort25( sortedPif, sortedPifArea, (unsigned long) npoints, chatty, status); /* if( chatty > 1 ){ for ( j=0 ; j<7 ; j++){ RILlogMessage(NULL, Log_0," %d %f %f ",j,sortedPif[j], sortedPifArea[j]); } } */ } if( chatty > J_CHATTY_VERBOSE ){ RILlogMessage(NULL, Log_0," %d pifs sorted", (int) npoints); } *effOpenArea = 0.0; *openArea1 = 0.0; *closedArea1 = 0.0; *leakageFrOpen = 0.0; *leakageToClosed = 0.0; sumOpenPif = 0.0; sumClosedPif = 0.0; count = 0; pcount = 0.0; for ( i=0 ; i *openCut){ *openArea1 = *openArea1 + pixelArea; sumOpenPif = sumOpenPif + (double)sortedPif[i]*pixelArea; } if(sortedPif[i] < *closedCut){ *closedArea1 = *closedArea1 + pixelArea; sumClosedPif = sumClosedPif + (double)sortedPif[i]*pixelArea; } } if(*effOpenArea > 0.0){ if(*openArea1 > 0.0){ *leakageFrOpen = (*effOpenArea - sumOpenPif)/(*effOpenArea); }else{ *leakageFrOpen = 0.0; } if(*closedArea1 > 0.0){ *leakageToClosed = sumClosedPif/(*effOpenArea); }else{ *leakageToClosed = 0.0; } }else{ *leakageFrOpen = 0.0; *leakageToClosed = 0.0; } openSumTmp = 0.0; for ( i=0 ; i J_CHATTY_NORMAL ){ RILlogMessage(NULL, Log_0, " Effective illuminated Area: %f", *effOpenArea ); RILlogMessage(NULL, Log_0," Open area (from PIF > %f ): %f", *openCut, *openArea1 ); RILlogMessage(NULL, Log_0," Closed area (from PIF < %f ): %f", *closedCut, *closedArea1 ); RILlogMessage(NULL, Log_0, " Leakage (fraction of ill. flux) from open area (PIF > %f ): %f", *openCut, *leakageFrOpen ); RILlogMessage(NULL, Log_0, " Leakage (fraction of ill. flux) to closed area (PIF < %f ): %f", *closedCut, *leakageToClosed ); } return status; } /***************************************************************** * * j_src_sort v1.0 27/09/2003 * * Source file: j_src_lc/spectra.c * File version : 3.5 * Date: 2003/09/27 * Function name j_src_sort * Function version : 1.0 * Parent component: j_src_pif_sort * Children: * Developer: Stefan Larsson * Contact Address: Stockholm Observatory * SCFAB * SE-106 91 Stockholm * Phone: +46 8-5537 8543 FAX: +46 8-5537 8510 * stefan@astro.su.se * Purpose: Sort the pif values in sortedPif[] * * * Origin date: 030927 * Update history: * * Error codes: See j_src_lc/spectra.txt * * ***********************************************************************/ #include int j_src_sort( float sortedPif[J_NUM_X_PIXELS*J_NUM_X_PIXELS], unsigned long n, int chatty, int status) { /* Ordinary variables */ unsigned long i; unsigned long ir; unsigned long j; unsigned long l; float rra; l=(n >> 1)+1; ir=n; for (;;) { if (l > 1) { rra=sortedPif[(--l)-1]; } else { rra=sortedPif[ir-1]; sortedPif[ir-1]=sortedPif[1-1]; if (--ir == 1) { sortedPif[0]=rra; break; } } i=l; j=l+l; while (j <= ir) { if (j < ir && sortedPif[j-1] < sortedPif[j]) j++; if (rra < sortedPif[j-1]) { sortedPif[i-1]=sortedPif[j-1]; i=j; j <<= 1; } else j=ir+1; } sortedPif[i-1]=rra; } return status; } /***************************************************************** * * j_src_sort25 v1.0 27/09/2003 * * Source file: j_src_lc/spectra.c * File version : 3.5 * Date: 2003/09/27 * Function name j_src_sort * Function version : 1.0 * Parent component: j_src_pif_sort * Children: * Developer: Stefan Larsson * Contact Address: Stockholm Observatory * SCFAB * SE-106 91 Stockholm * Phone: +46 8-5537 8543 FAX: +46 8-5537 8510 * stefan@astro.su.se * Purpose: Sort the pif values in sortedPif[] * * * Origin date: 030927 * Update history: * * Error codes: See j_src_lc/spectra.txt * * ***********************************************************************/ #include int j_src_sort25( float sortedPif[J_NUM_X_PIXELS*J_NUM_X_PIXELS], float sortedPifArea[J_NUM_X_PIXELS*J_NUM_Y_PIXELS], unsigned long n, int chatty, int status) { /* Ordinary variables */ unsigned long i = 0; unsigned long ir = 0; unsigned long j = 0; unsigned long l = 0; float rra = 0.0; float area = 0.0; l=(n >> 1)+1; ir=n; for (;;) { if (l > 1) { rra=sortedPif[(--l)-1]; area=sortedPifArea[l-1]; } else { rra=sortedPif[ir-1]; area=sortedPifArea[ir-1]; sortedPif[ir-1]=sortedPif[0]; sortedPifArea[ir-1]=sortedPifArea[0]; if (--ir == 1) { sortedPif[0]=rra; sortedPifArea[0]=area; break; } } i=l; j=l+l; while (j <= ir) { if (j < ir && sortedPif[j-1] < sortedPif[j]) j++; if (rra < sortedPif[j-1]) { sortedPif[i-1]=sortedPif[j-1]; sortedPifArea[i-1]=sortedPifArea[j-1]; i=j; j <<= 1; } else j=ir+1; } sortedPif[i-1]=rra; sortedPifArea[i-1]=area; } return status; } /***************************************************************** * * j_src_event v1.0 28/08/2003 * * Source file: j_src_lc/spectra.c * File version : 3.5 * Date: 2003/08/28 * Function name j_src_event * Function version : 1.0 * Parent component: j_src_work * Children: * Developer: Stefan Larsson * Contact Address: Stockholm Observatory * SCFAB * SE-106 91 Stockholm * Phone: +46 8-5537 8543 FAX: +46 8-5537 8510 * stefan@astro.su.se * Purpose: Given a source (sky) direction and photon * energy compute the distribution function * on the detector and store in a 2 dim. array. * * Origin date: 030828 * Update history: * * Error codes: See j_src_lc/spectra.txt * * depthX = Position shift in the X direction due to the * the photon penetration depth into the detector. * * depthY = As depthX but in Y-direction. * * iChan = Use this energy channel for the computation. * Affects the resolution and penetration depth. * * newmid = index # for center point in array. * * posResInterpol = Detector spatial resolution as function of * channel (0-255). * * * 031128 by CK * * - replaced 100 with PSFSize in calculating bufferSize, and as upper * limits for ix,iy in double for-loop calculating eventDistr * * - energy dependent gaussPSFWidth * * - Calculated the evenDistr at different depths along the photon path. * * nDepthBin = Number of bins in depth, for which contributions * to the eventDistr is calculated. * * depthXMax = Maximum position shift in the X direction due to the * the photon penetration depth into the detector. * * depthYMax = As depthXMax but in Y-direction. * * factDepthMax = depthXMax/depthX (same for Y,Z) * Depends on energy. * As a first assumption a constant value (2) is used. * * dlm1 = The length along the ray (in the xy-plane) at which the * intensity has decreased by a factor exp(-1). * That length is assumed to be given by depthX and * depthY. * * depProb = The deposition probability along the ray at * different depths. ***********************************************************************/ #include int j_src_event( double depth, double depthX, double depthY, double detDepthMax, double posResInterpol[J_NUM_SCI_BINS], int iChan, float PSFStep, float eventDistr[J_NUM_EVENT_PIXELS][J_NUM_EVENT_PIXELS], long newmid, int chatty, int status) { /* Ordinary variables */ long ix = 0; long iy = 0; long imx = 0; long imy = 0; long midx = 0; long midy = 0; long i = 0; long bufferSize = 0; float *resPSF = NULL; float gaussPSFWidth = 1.0; /* Set to energy dependent value below */ float factDepthMax = 2.0; /* Preliminary guess, depends on energy */ int PSFSize = 100; int mid = 50; int idx = 0; int idy = 0; int nDepthBin = 8; double sum = 0.0; double depthXMax = 0.0 ; double depthYMax = 0.0 ; double depthScale = 0.0 ; double dxBin = 0.0; double dyBin = 0.0; double dlBin = 0.0; double dlm1 = 0.0 ; double depProb[nDepthBin] ; gaussPSFWidth = 0.5*posResInterpol[iChan]; if(chatty > J_CHATTY_VERBOSE){ status = RILlogMessage( NULL, Log_0, "Detector resolution gaussian PSF half Width = %f", gaussPSFWidth); } for ( ix=0 ; ix detDepthMax){ depthXMax = depthXMax*(detDepthMax/depthScale); depthYMax = depthYMax*(detDepthMax/depthScale); } /* Calculate the deposition probability at different heights */ dlm1 = sqrt(depthX*depthX + depthY*depthY) ; dxBin = depthXMax/((double)nDepthBin) ; dyBin = depthYMax/((double)nDepthBin) ; dlBin = sqrt(dxBin*dxBin + dyBin*dyBin) ; if (dlm1 > 0.) { sum = 0.0 ; for ( i=0 ; i= 0 && imx < J_NUM_EVENT_PIXELS) { if(imy >= 0 && imy < J_NUM_EVENT_PIXELS) { eventDistr[imx][imy] = eventDistr[imx][imy] + *(resPSF + PSFSize*iy + ix)*depProb[i]; } } } } } sum = 0.0; for ( ix=0 ; ix J_SRC_ACCURACY){ for ( ix=0 ; ix J_CHATTY_VERBOSE){ sum = 0.0; for ( ix=0 ; ix int j_src_pixel_area( float detPixArea[J_NUM_X_PIXELS][J_NUM_Y_PIXELS], float detPixLLX[J_NUM_X_PIXELS][J_NUM_Y_PIXELS], float detPixLLY[J_NUM_X_PIXELS][J_NUM_Y_PIXELS], float detCorX[J_NUM_X_PIXELS][J_NUM_Y_PIXELS], float detCorY[J_NUM_X_PIXELS][J_NUM_Y_PIXELS], double radiusLimit, int chatty, int status) { /* Ordinary variables */ long ix = 0; long iy = 0; long nneg = 0; long nsmall = 0; long nlarge = 0; long npixels = 0; float height = 0.0; float width = 0.0; float radius = 0.0; float area = 0.0; float a00x = 0.0; float a00y = 0.0; float a01x = 0.0; float a01y = 0.0; float a10x = 0.0; float a10y = 0.0; float a11x = 0.0; float a11y = 0.0; float detPixAreaRect = 0.0; float areamin = 1.0; area = 0.0; /* Main loop over all detector pixels. */ for ( ix=1 ; ix areamin){ areamin = detPixArea[ix][iy]; /* RILlogMessage(NULL, Log_0," ix,iy,area %d %d %f %f %f", ix,iy,areamin,height,width); */ } if( chatty > J_CHATTY_VERBOSE ){ radius = sqrt(detCorX[ix][iy]*detCorX[ix][iy] + detCorY[ix][iy]*detCorY[ix][iy]); if(radius < radiusLimit){ if( detPixArea[ix][iy] < 0.1 ) { nsmall = nsmall + 1; } if( detPixArea[ix][iy] < 0.0) { nneg = nneg + 1; } if( detPixArea[ix][iy] > 5.0) { nlarge = nlarge + 1; } area = area + detPixArea[ix][iy]; npixels = npixels + 1; } } } else{ detPixArea[ix][iy] = 1.0; } } } if( chatty > J_CHATTY_VERBOSE ){ RILlogMessage(NULL, Log_0," Sum of pixel areas = %f ", area); RILlogMessage(NULL, Log_0," Used detector area = %f ", 3.14159*radiusLimit*radiusLimit); RILlogMessage(NULL, Log_0," No. of pixels = %d ", (int) npixels); } return status; } /***************************************************************** * * j_src_through_mask v1.0 13/09/2001 * * Source file: j_src_lc/spectra.c * File version : 2.3 * Date: 2001/09/13 * Function name j_src_through_mask * Function version : 1.0 * Parent component: j_eventweight * Children: j_mask_findxy * Developer: Stefan Larsson * Contact Address: Stockholm Observatory * SCFAB * SE-106 91 Stockholm * Phone: +46 8-5537 8543 FAX: +46 8-5537 8510 * stefan@astro.su.se * Purpose: Given source coordinates and event position * find mask transparancy. In other words: * Is there a free path from the detector * position towards the source? * Origin date: 000706 * Update history: 0.01 000511 Adaption from test code jextr5.c * 2.2 010609 Reflecting mask x-values * to fix mask bug. * Mask pattern is coded such that 0 = closed * 6 = open * 7 = outside mask pattern * * * Error codes: See j_src_lc/spectra.txt * * * * ***********************************************************************/ #include int j_src_through_mask( double eventX, /* Event detector position in X */ double eventY, /* Event detector position in Y */ double sourceX, /* Source X-pos as projected on mask */ double sourceY, /* Source Y-pos as projected on mask */ short *weightInt, /* Integer event weight */ short mask[J_DIM_MASK][J_DIM_MASK], int chatty, /* Level of debugging output */ int status) /* Status flag */ { /* Ordinary variables */ int ix = 0; int iy = 0; int in = 0; int ix0 = 0; double posX = 0.0; double posY = 0.0; double dX = 0.0; double dY = 0.0; double relX = 0.0; double relY = 0.0; /* * Immediate return if called while executable is in error condition */ if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : Non-zero status value passed to j_src_through_mask",\ status); return status ; } /* * Project event position onto the mask in the direction of the source. */ eventX = eventX + sourceX; eventY = eventY + sourceY; status = j_src_mask_find_element( eventX, eventY, &relX, &relY, &ix, &iy, chatty, status); /* During testing (May-June 2001) an error in the mask geometry was discovered. A plot revealed that the mask geometry is a mirror image with respect to the Y-axis. Reflecting the x-values around ix = 100 recover the correct geometry. The error should be tracked down so that its cause is understood but for now I am happy to have a working solution. /Stefan Larsson 010609 This error is now corrected directly when creating the mask array. SL/020724 */ ix0 = ix; /* ix = 200 - ix; See comment above*/ if ((ix>=0&&ix<200) && (iy>=0&&iy<200)) { status = j_mask_findxy(ix,iy,&posX,&posY,chatty,status); dX = eventX - posX; dY = eventY - posY; status = j_src_in_hole (dX, dY, &in, chatty, status); if(mask[ix][iy] == 6){ *weightInt = 1; } else if(mask[ix][iy] == 0){ *weightInt = -1; /* RILlogMessage(NULL, Log_0," %f %f", dX, dY); */ } else if(mask[ix][iy] == 7){ *weightInt = 7; } } else { *weightInt = 7; /* Outside of the mask! NOTE: From 0-> -1 990930/SL*/ } return status; } /***************************************************************** * * j_src_nspec v1.0 13/09/2001 * * Source file: j_src_lc/spectra.c * File version : 2.3 * Date: 2001/09/13 * Function name j_src_nspec * Function version : 1.0 * Parent component: j_src_work * Children: None * Developer: Stefan Larsson * Contact Address: Stockholm Observatory * SCFAB * SE-106 91 Stockholm * Phone: +46 8-5537 8543 FAX: +46 8-5537 8510 * stefan@astro.su.se * Purpose: Calculate the number of time ranges for * which spectra should be calculated. * Parameters startTime and restrictiveness * determines startpoints and data * completness requirement (see Note below) * Origin date: 010827 * Update history: 2.3 New routine * * Note: If timeStart < 0 the time ranges will * start at beginning of GTIs. * If timeStart > 0 the time ranges will * start at timeStart + i*timeStep. * * Parameter restrictiveness: * Specify how much data should be in * in a data segment for a spectrum * to be calculated. * * 0 = Use all data segments. * 1 = Use if at least half contains * data. * 2 = Only use if the full data * segment contains data. * * Error codes: See j_src_lc/spectra.txt * * * Bugs: If timeStart > 0!! * If GTIs are close make sure nSpec gets right! ***********************************************************************/ #include int j_src_nspec( double *gtiStart, /* Beginning of GTIs in IJD */ double *gtiEnd, /* End of GTIs in IJD */ int nGTIs, /* Number of GTIs */ double timeStep, /* Integration time */ double timeStart, /* Start time */ long *nSpec, /* Number of time ranges. */ int restrictiveness, /* Data coverage */ int chatty, /* Level of debugging output */ int status) /* Status flag */ { /* Ordinary variables */ int i = 0; int ii = 0; /* * Immediate return if called while executable is in error condition */ if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : Non-zero status value passed to j_src_nfilled_spec",\ status); return status ; } if( timeStep <= 0.0 ){ *nSpec = 1; if( chatty > J_CHATTY_VERY_VERBOSE ){ RILlogMessage(NULL, Log_0, "Non-positive timeStep: One spectrum for all data."); } return status ; } if(timeStart < 0.0){ for ( i=0 ; i< (nGTIs) ; i++){ if(restrictiveness == 0) { ii = (int) (1.0 + (gtiEnd[i]-gtiStart[i])/timeStep); *nSpec = *nSpec + ii; } else if(restrictiveness == 1) { ii = (int) (0.5 + (gtiEnd[i]-gtiStart[i])/timeStep); *nSpec = *nSpec + ii; } else if(restrictiveness == 2) { ii = (int) ((gtiEnd[i]-gtiStart[i])/timeStep); *nSpec = *nSpec + ii; } } } RILlogMessage(NULL, Log_2, "Number of time ranges for spectra/lc in j_src_nspec: %d",\ (int) *nSpec); return status; } /***************************************************************** * * j_src_nspec_times v1.0 13/09/2001 * * Source file: j_src_lc/spectra.c * File version : 2.3 * Date: 2001/09/13 * Function name j_src_nspec_times * Function version : 1.0 * Parent component: j_src_work * Children: None * Developer: Stefan Larsson * Contact Address: Stockholm Observatory * SCFAB * SE-106 91 Stockholm * Phone: +46 8-5537 8543 FAX: +46 8-5537 8510 * stefan@astro.su.se * Purpose: Calculate the start and stop times * for the time ranges where * spectra should be calculated. * The number of spectra (nSpec) should * first be calculated and used to * allocate memory for * Parameters startTime and restrictiveness * determines startpoints and data * Origin date: 010831 * Update history: 2.3 New routine * * Note: If timeStart < 0 the time ranges will * start at beginning of GTIs. * If timeStart > 0 the time ranges will * start at timeStart + i*timeStep. * * Parameter restrictiveness: * Specify how much data should be in * in a data segment for a spectrum * to be calculated. * * 0 = Use all data segments. * 1 = Use if at least half contains * data. * 2 = Only use if the full data * segment contains data. * * If too few (< nSpec) time ranges * are found, a warning of lost data * will be issued and the value of * nSpec will be reduced. * * Error codes: See j_src_lc/spectra.txt * * * * VARIABLES * * doiSpecStep = Indicates that in the next run through * the do-loop, iSpec will be incremented * by one. * * frac = Fraction of a data segment in which there * is data (determined by GTI overlap). * * timeBegin,timeEnd = Time range over which the present * spectrum time range and GTI overlap. * * timeEndSpec[] = Time in IJD at the end of each * time range selected for spectra. * * timeIntSpec[] = Integration time in seconds for the * time ranges selected for spectra. * * timeStartSpec[] = Start time in IJD at the beginning of each * time range selected for spectra. * * ***********************************************************************/ #include int j_src_nspec_times( double *gtiStart, /* Beginning of GTIs in IJD */ double *gtiEnd, /* End of GTIs in IJD */ int nGTIs, /* Number of GTIs */ double timeStep, /* Integration time */ double timeStart, /* Start time */ double *timeStartSpec, /* Beginning of time ranges */ double *timeEndSpec, /* End of time ranges */ double *timeIntSpec, /* Integration times. */ long *nSpec, /* Number of time ranges. */ int restrictiveness, /* Data coverage */ int chatty, /* Level of debugging output */ int status) /* Status flag */ { /* Ordinary variables */ int i = 0; int iSpec = 0; int nInt = 0; int lost = 0; int nPrint = 0; int doiSpecStep = 0; /* Indicate if iSpec will be incremented. */ double epsilon = 1.0e-8; /* In case of numerical error in frac. */ double frac = 0.0; double timeBegin = 0.0; double timeEnd = 0.0; double timeStartSpecLast = 0.0; /* * Immediate return if called while executable is in error condition */ if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : Non-zero status value passed to j_src_nspec_times",\ status); return status ; } if( timeStep <= 0.0 ){ if(nGTIs > 0) { timeStartSpec[0] = gtiStart[0]; timeEndSpec[0] = gtiEnd[nGTIs-1]; if( chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL, Log_0, "Calculating integration time using GTIs"); } /* Calculate integration time. */ timeIntSpec[0] = 0.0; nInt = 0; for ( i=0 ; i< nGTIs ; i++){ timeIntSpec[0] = timeIntSpec[0] + (gtiEnd[i] - gtiStart[i]); nInt = nInt + 1; } timeIntSpec[0] = timeIntSpec[0]*DAL3GEN_SECONDS_IN_DAY; } else { timeStartSpec[0] = -1.0; timeEndSpec[0] = -1.0; if( chatty > J_CHATTY_MAXIMAL ){ RILlogMessage(NULL, Log_0, "No GTIs available. Integration time set = observation time"); } timeIntSpec[0] = -1.0; } return status ; } if( chatty == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_0, "Calculating time ranges for spectra/lc."); if(restrictiveness == 2) { RILlogMessage(NULL,Log_0, "Ignoring time ranges not filled with data."); } else if(restrictiveness == 1){ RILlogMessage(NULL,Log_0, "Using all time ranges >50%% filled with data."); } else if(restrictiveness == 0){ RILlogMessage(NULL,Log_0, "Using all time ranges containing any data."); } } /***************************************************************** * * The two main options (timeStart < 0, time start at GTI-start) * and (timeStart > 0, time start at timestart+i*timeStep) are * handled differently. So according to the value of timeStart * choose where to go... * *****************************************************************/ if(timeStart < 0) { timeStartSpec[0] = gtiStart[0]; timeEndSpec[0] = timeStartSpec[0] + timeStep; } else if(timeStart >= 0) { /***************************************************************** * Increment time range until we reach the first GTI. *****************************************************************/ timeStartSpec[0] = timeStart; do { timeStartSpec[0] = timeStartSpec[0] + timeStep; }while(timeStartSpec[0]+timeStep < gtiStart[0]); timeEndSpec[0] = timeStartSpec[0] + timeStep; } if( chatty > J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_0, "Starting time for first spectrum = %f", timeStartSpec[0]); } timeStartSpecLast = timeStartSpec[0]; /***************************************************************** * ******************************************************************/ do{ if(doiSpecStep == 1){ timeStartSpec[iSpec] = timeStartSpecLast + timeStep; timeStartSpecLast = timeStartSpec[iSpec]; timeEndSpec[iSpec] = timeStartSpec[iSpec] + timeStep; /* if(timeStart < 0.0){ If timeStartSpec[iSpec] is not within a GTI I might like to shift it to the beginning of the next GTI. I should then also make a similar change in j_src_nspec since it may affect nSpec. } */ } /* For this iSpec time range: Loop over GTIs and calculate time overlap. Store as integration time. */ timeIntSpec[iSpec] = 0.0; nInt = 0; for ( i=0 ; i< nGTIs ; i++){ if((timeEndSpec[iSpec] > gtiStart[i]) && timeStartSpec[iSpec] < gtiEnd[i]) { if(timeStartSpec[iSpec] < gtiStart[i]){ timeBegin = gtiStart[i]; } else{ timeBegin = timeStartSpec[iSpec]; } if(timeEndSpec[iSpec] < gtiEnd[i]){ timeEnd = timeEndSpec[iSpec]; } else{ timeEnd = gtiEnd[i]; } timeIntSpec[iSpec] = timeIntSpec[iSpec] + (timeEnd - timeBegin); nInt = nInt + 1; } } doiSpecStep = 1; if(nInt > 0) { frac = timeIntSpec[iSpec]/timeStep; /* Check if integration time is acceptable according to the restrictiveness-parameter. */ if(restrictiveness == 2) { if(frac > 1.0-epsilon) { iSpec = iSpec + 1; } } else if(restrictiveness == 1){ if(frac > 0.5) { iSpec = iSpec + 1; } } else if(restrictiveness == 0){ /* Maybe add a minimum fraction?: */ iSpec = iSpec + 1; } } if(timeStartSpecLast + timeStep > gtiEnd[nGTIs-1]){ /* No more GTI data so lets quit. But first check if we have got all expected time segments. iSpec at this point should be equal to the number of time ramges stored. (lost should be = 0).*/ lost = *nSpec - iSpec; *nSpec = iSpec; /* The actual number read. Will force exit as well. */ if(lost > 0) { RILlogMessage(NULL, Warning_2, "Lost %d data segments in j_src_nspec_times." \ "No error but some data will be missing. (report bug)", lost); } } }while(iSpec < *nSpec); if(*nSpec == 0) { status = J_SRC_NO_SPEC_DATA; } /*********************************************************** Convert integration time from days -> seconds ************************************************************/ for ( i=0 ; i< *nSpec ; i++){ timeIntSpec[i] = timeIntSpec[i]*DAL3GEN_SECONDS_IN_DAY; } /*********************************************************** Print result if you are very chatty ************************************************************/ if( (chatty == J_CHATTY_MAXIMAL) && (*nSpec > 0) ){ RILlogMessage(NULL,Log_0, "Selected time ranges for spectra/lc:"); RILlogMessage(NULL,Log_0, " No., Start, Stop, Integr.time "); if (*nSpec > 10){ nPrint = 10; RILlogMessage(NULL,Log_0, "(Listing first 10 only) "); } else { nPrint = *nSpec; } for ( i=0 ; i< nPrint ; i++){ RILlogMessage(NULL,Log_0, " %d %f %f %f ", i, timeStartSpec[i], timeEndSpec[i], timeIntSpec[i]); } } return status; } /***************************************************************** * * j_src_fracexp v1.0 04/04/2005 * * Source file: j_src_spectra.c * File version : 5.0 * Date: 2005/04/01 * Function name j_src_fracexp * Function version : 1.0 * Parent component: j_src_work * Children: None * Developer: Stefan Larsson * Contact Address: Stockholm Observatory * SCFAB * SE-106 91 Stockholm * Phone: +46 8-5537 8543 FAX: +46 8-5537 8510 * stefan@astro.su.se * Purpose: Return grey filter correction factor averaged * over the specified time range. * In j_src_spectra_work we apply an average * correction factor for the full integration * interval of a spectrum. * Since the grey filter means that we loose * individual events we gain nothing by applying * corrections to the actual grey filter intervals. * Actually we loose because thoose subspectra * are noisier! * * Origin date: 010915 * Update history: 2.3 New routine * * Note: The grey filter applied on-board Integral is * defined as follows: * There are 32 possible filter values * N, from 0 to 31. * They define the filter transmission fraction, * * TF = (N+1)/32 * * The filter correction factor is therfore, * * CorrFac = 1/TF * * For each spectral time range we calculate the * weighted mean of the correction factor, as * * W. mean = SUM(CorrFac[i]*t[i]) / SUM(t[i]) * * [The weight is the length of time a filter * level is applied.] * * Error codes: * * Basic offset: * J_ERROR_CODE_START + J_SRCEEXTRACT_ERROR_START + J_EXTR_ERROR_START * * * * VARIABLES * * greyCorrSpec[] = Grey filter correction factors. * * greyExtrapolation = Flag to indicate the grey values had to * be extrapolated to preceeding time points. * = 0 For no extrapolation. * = 1 For extrapolation needed. * * *greyValues = Pointer to grey filter values. * The values are 0 - 31, each stored * as one byte (equivalent to a char). * * HigherLimit = * * LowerLimit = * * timeBegin,timeEnd = Time range over which the present * spectrum time range and GTI overlap. * * timeEndSpec[] = Time in IJD at the end of each * time range selected for spectra. * * timeIntSpec[] = Integration time in seconds for the * time ranges selected for spectra. * * timeStartSpec[] = Start time in IJD at the beginning of each * time range selected for spectra. * * ***********************************************************************/ #include int j_src_fracexp( double timeStep, /* Integration time */ double *timeStartSpec, /* Beginning of time ranges */ double *timeEndSpec, /* End of time ranges */ double *timeIntSpec, /* Integration times (sec).*/ double *fracExp, /* FRACEXP values returned */ long nSpec, /* Number of time ranges. */ double *deadTimeIJD, /* Time at Grey change */ double *deadEff, /* Eff. deadtime (grey&dead) */ long nDeadTimes, /* No. of deadtime values. */ int chatty, /* Level of output */ int status) /* Status flag */ { /* Ordinary variables */ long iDead = 0; long iSpec = 0; long nInt = 0; long i = 0; long iDeadPrevious = 0; double fracSum = 0.0; double LowerLimit = 0.0; double HigherLimit = 0.0; double deadTimePrevious = 0.0; double overlapsum = 0.0; double fracWeights = 0.0; double weights = 0.0; double weight = 0.0; double deadEffNow = 0.0; /* * Immediate return if called while executable is in error condition */ if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : Non-zero status value passed to j_src_fracexp",\ status); return status ; } /* * Immediate return if nSpec <= 0. */ if( nSpec <= 0 ){ RILlogMessage(NULL, Warning_2, "No data time bins, no FRACEXP values computed!"); return status ; } /***************************************************************** * Calculate FRACEXP values for each time bin. *****************************************************************/ for ( iSpec=0 ; iSpec< nSpec ; iSpec++){ iDeadPrevious = 0; weight = 0.0; weights = 0.0; fracSum = 0.0; deadTimePrevious = timeStartSpec[iSpec]; deadEffNow = deadEff[0]; for ( iDead=0 ; iDead< nDeadTimes ; iDead++){ if( deadTimeIJD[iDead] > timeStartSpec[iSpec] && deadTimePrevious < timeEndSpec[iSpec]) { status = j_min_range(timeStartSpec[iSpec], timeEndSpec[iSpec], deadTimePrevious, deadTimeIJD[iDead], &LowerLimit, &HigherLimit, chatty, status); /* LowerLimit = max(deadTimePrevious,timeStartSpec[iSpec]); HigherLimit = min(deadTimeIJD[iDead],timeEndSpec[iSpec]); */ if(iDead == nDeadTimes-1 && deadTimeIJD[iDead] 0.0) { fracExp[iSpec] = 1.0 - fracSum/weights; if(timeIntSpec[iSpec] > 0.0) { fracWeights = DAL3GEN_SECONDS_IN_DAY*weights/timeIntSpec[iSpec]; if(fracWeights < 0.95 && chatty > J_CHATTY_NORMAL) { RILlogMessage(NULL,Log_0, "(j_src_fracexp): fracWeight, weights, dt %f %f %f", fracWeights,weights, timeIntSpec[iSpec]); } } } } /*********************************************************** Print result if you are very chatty ************************************************************/ if( (chatty == J_CHATTY_MAXIMAL) && (nSpec > 0) ){ RILlogMessage(NULL,Log_0, "Spec no., Start, Stop, FRACEXP"); for ( i=0 ; i< nSpec ; i++){ RILlogMessage(NULL,Log_0, " %d %f %f %f ", i, timeStartSpec[i], timeEndSpec[i], fracExp[i]); } } return status; } /***************************************************************** * * j_min_range v1.0 17/09/2001 * * Source file: j_src_lc/spectra.c * File version : 2.3 * Date: 2001/09/17 * Function name j_min_range * Function version : 1.0 * Parent component: j_src_grey_correction * Children: None * Developer: Stefan Larsson * Contact Address: Stockholm Observatory * SCFAB * SE-106 91 Stockholm * Phone: +46 8-5537 8543 FAX: +46 8-5537 8510 * stefan@astro.su.se * Purpose: Given two continous time ranges (a1,a2) and * (b1,b2) calculate the overlaping range * (max[a1,b1], min[a2,b2]). * Result returned as (res1,res2). * * Origin date: 010917 * Update history: 2.3 New routine * * Note: * * Error codes: See j_src_lc/spectra.txt * * * * VARIABLES * * ***********************************************************************/ #include int j_min_range ( double a1, /* Beginning of range a */ double a2, /* End of range a */ double b1, /* Beginning of range b */ double b2, /* End of range b */ double *res1, /* Beginning of overlap */ double *res2, /* End of overlap */ int chatty, /* Level of debugging output */ int status) /* Status flag */ { /* * Immediate return if called while executable is in error condition */ if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : Non-zero status value passed to j_min_range",\ status); return status ; } if( a1 > b1) { *res1 = a1; } else { *res1 = b1; } if( a2 > b2) { *res2 = b2; } else { *res2 = a2; } if( *res2 < *res1 ){ status = J_SRC_WRONG_VALUE; RILlogMessage(NULL, Error_2, "%d : Negative time range in j_min_range",\ status); return status ; } return status; } /***************************************************************** * * j_gti_overlap v1.0 17/09/2001 * * Source file: j_src_lc/spectra.c * File version : 2.3 * Date: 2001/09/17 * Function name j_gti_overlap * Function version : 1.0 * Parent component: j_src_grey_correction * Children: None * Developer: Stefan Larsson * Contact Address: Stockholm Observatory * SCFAB * SE-106 91 Stockholm * Phone: +46 8-5537 8543 FAX: +46 8-5537 8510 * stefan@astro.su.se * Purpose: Calculate the overlap of a continous * time range (a1,a2) and a set og GTIs. * * * Origin date: 010918 * Update history: 2.3 New routine * * Note: * * Error codes: See j_src_lc/spectra.txt * * * * VARIABLES * * ***********************************************************************/ #include int j_gti_overlap ( double a1, /* Beginning of range a */ double a2, /* End of range a */ double *gtiStart, /* Beginning of GTIs in IJD */ double *gtiEnd, /* End of GTIs in IJD */ int nGTIs, /* Number of GTIs */ double *overlap, /* Calculated overlap */ int chatty, /* Level of debugging output */ int status) /* Status flag */ { /* Ordinary variables */ long i = 0; long nInt = 0; double timeBegin = 0.0; double timeEnd = 0.0; /* * Immediate return if called while executable is in error condition */ if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : Non-zero status value passed to j_gti_overlap",\ status); return status ; } /* For the given time range: Loop over GTIs and calculate time overlap. Store as integration time. */ *overlap = 0.0; nInt = 0; for ( i=0 ; i< nGTIs ; i++){ if((a2 > gtiStart[i]) && a1 < gtiEnd[i]) { status = j_min_range(a1, a2, gtiStart[i], gtiEnd[i], &timeBegin, &timeEnd, chatty, status); nInt = nInt + 1; /* if(a1 < gtiStart[i]){ timeBegin = gtiStart[i]; } else{ timeBegin = a1; } if(a2 < gtiEnd[i]){ timeEnd = a2; } else{ timeEnd = gtiEnd[i]; } */ *overlap = *overlap + (timeEnd - timeBegin); } } if( (chatty == J_CHATTY_MAXIMAL) && (nInt == 0) ){ RILlogMessage(NULL,Warning_2, "No GTI overlap for given time range: %f, %f", a1, a2); } return status; } /***************************************************************************** Function: j_read_GTI Description: Reads Good Time Interval boundaries, allocating the corresponding buffers as required. Error codes (constants defined in header files): 0 == ISDC_OK ==> function executed with no errors < 0 (various) ==> ISDC system function error code, passed on J_SRC_OUT_OF_MEMORY ==> not enough memory for some buffers Parameter arguments: name range I/O description theSWG !=NULL input handle to SWG jemxInstr JMX1 or JMX2 input instrument number gtiNames (string) input Names of GTIs to be used nGTI >=0 output Number of Good Time Intervals found gtiStartOBT (array) output Start OBTimes of GTIs gtiEndOBT (array) output End OBTimes of GTIs gtiStartIJD (array) output Start IJDs of GTIs gtiEndIJD (array) output End IJDs of GTIs chatty 0 to 5 input Verbosity control variable callingStatus any input Error status on input *****************************************************************************/ int j_read_GTI(dal_element *theSWG, Instrument jemxInstr, char *gtiNames, int *nGTI, OBTime **gtiStartOBT, OBTime **gtiEndOBT, double **gtiStartIJD, double **gtiEndIJD, int chatty, int callingStatus) { char **foundNames=NULL; /* GTI names (used by DAL3HKcheckGTI) */ char **notFoundNames=NULL; /* GTI names (used by DAL3HKcheckGTI) */ int gtiNumFoundNames=0; /* Number of GTI names found in SWG */ int iGTI=0; /* Index to loop over GTI names */ int setupDefaultGTI=0; /* Boolean: should we set up a default GTI */ int status=ISDC_OK; /* * exit function immediately if callingStatus is not OK on entry */ if(callingStatus != ISDC_OK) return(callingStatus); /* * Single-pass do loop, only used to allow clean exits (via continue) * if errors are encountered */ do { foundNames = malloc(J_SSP_MAX_GTI_NAMES*sizeof(char *)); notFoundNames = malloc(J_SSP_MAX_GTI_NAMES*sizeof(char *)); if (NULL==foundNames || NULL==notFoundNames) { RILlogMessage(NULL,Error_3, "Not enough memory for GTI names."); status=J_SRC_OUT_OF_MEMORY; continue; } for (iGTI=0; iGTI= J_CHATTY_VERBOSE ){ if ( gtiNumFoundNames > 0) { for (iGTI=0; iGTI0) { /* Determine upper limit of possible GTIs */ status = DAL3HKgetNumGTI(theSWG,jemxInstr,>iNames,1, nGTI,status); if (status != ISDC_OK) { RILlogMessage(NULL,Error_1,"%s status = %d", "DAL3HKgetNumGTI failed.", status); continue; } if (0 < *nGTI) { /* Allocate memory for GTI buffer */ if (chatty >= J_CHATTY_VERBOSE) { RILlogMessage(NULL,Log_1, "%d Good Time Intervals found.", *nGTI); } *gtiStartOBT=malloc(*nGTI * sizeof(OBTime)); *gtiEndOBT =malloc(*nGTI * sizeof(OBTime)); *gtiStartIJD=malloc(*nGTI * sizeof(double)); *gtiEndIJD =malloc(*nGTI * sizeof(double)); if (NULL==*gtiStartOBT || NULL==*gtiEndOBT || NULL==*gtiStartIJD || NULL==*gtiEndIJD ) { RILlogMessage(NULL,Error_3, "Not enough memory for GTI intervals."); status=J_SRC_OUT_OF_MEMORY; continue; } /* Read actual good time intervals */ status = DAL3HKgetGTI(theSWG,jemxInstr, >iNames,1, DAL3_NO_OBTIME, /* No further OBT */ DAL3_NO_OBTIME, /* selection */ nGTI, *gtiStartOBT,*gtiEndOBT, status); if (status != ISDC_OK) { RILlogMessage(NULL,Error_1,"%s status = %d", "DAL3HKgetGTI failed.", status); continue; } /* Convert GTI OBTimes to IJD */ status = DAL3AUXconvertOBT2IJD(theSWG,TCOR_ANY,*nGTI, *gtiStartOBT,*gtiStartIJD, status); status = DAL3AUXconvertOBT2IJD(theSWG,TCOR_ANY,*nGTI, *gtiEndOBT,*gtiEndIJD, status); if (ISDC_OK != status) { RILlogMessage(NULL,Error_2, "Error converting GTI OBT bounds to IJD! " "status = %d",status); continue; } else if (chatty >= J_CHATTY_VERY_VERBOSE) { RILlogMessage(NULL,Log_0, "Converted GTI OBTs to IJD"); } } else { /* i.e. the upper limit of intervals is <1 */ setupDefaultGTI = 0; if (chatty >= J_CHATTY_NORMAL) { RILlogMessage(NULL,Warning_2, "Apparently all the time in this dataset " "is to be considered bad!"); } status = J_SRC_NO_GTI; continue; } } else { /* i.e. we have no to work with */ setupDefaultGTI = 1; if (chatty >= J_CHATTY_NORMAL) { RILlogMessage(NULL,Warning_2,"No GTI information found!"); } } /* Set up default GTI if no GTI information is available */ if (setupDefaultGTI) { if (chatty >= J_CHATTY_VERBOSE) { RILlogMessage(NULL,Log_2, "Setting up default GTI spanning SWG"); } *gtiStartOBT=malloc(sizeof(OBTime)); *gtiEndOBT =malloc(sizeof(OBTime)); *gtiStartIJD=malloc(sizeof(double)); *gtiEndIJD =malloc(sizeof(double)); if (NULL==*gtiStartOBT || NULL==*gtiEndOBT || NULL==*gtiStartIJD || NULL==*gtiEndIJD) { RILlogMessage(NULL,Error_3, "Not enough memory for GTI interval."); status=J_SRC_OUT_OF_MEMORY; continue; } status = DAL3GENattributeGetOBT(theSWG,"OBTSTART",*gtiStartOBT, NULL,status); status = DAL3GENattributeGetOBT(theSWG,"OBTEND",*gtiEndOBT, NULL,status); if (ISDC_OK!=status) { RILlogMessage(NULL,Log_0, "Missing OBTSTART, OBTEND. "); status = ISDC_OK; } status = DALattributeGet(theSWG,"TSTART",DAL_DOUBLE, (void*)*gtiStartIJD,NULL,NULL,status); status = DALattributeGet(theSWG,"TSTOP",DAL_DOUBLE, (void*)*gtiEndIJD,NULL,NULL,status); if (ISDC_OK!=status) { RILlogMessage(NULL,Log_0, "Missing TSTART, TSTOP. "); *nGTI = 0; status = ISDC_OK; return(status); } if(**gtiEndIJD > **gtiStartIJD){ RILlogMessage(NULL,Log_0, "Read GTI start and end times from " "SWG attributes"); RILlogMessage(NULL,Log_0, "gtiStartIJD: %f",*gtiStartIJD[0]); RILlogMessage(NULL,Log_0, "gtiEndIJD: %f",*gtiEndIJD[0]); *nGTI = 1; } else { if (chatty >= J_CHATTY_VERBOSE) { RILlogMessage(NULL,Log_0, "Inconsistent TSTART, TSTOP values."); } *nGTI = 0; } } /* end of default setup */ } while(0); return(status); } /***************************************************************************** Function: j_ssp_GetFileName Copy of j_bbs_GetFileName in j_bin_bkg_spectra. Description: Extract path to structure from a DOL Error codes (constants defined in header files): 0 == ISDC_OK ==> function executed with no errors < 0 (various) ==> ISDC system function error code, passed on Parameter arguments: name range I/O description DOL --- input Full DOL to a data structure fileName --- output Filename contained in DOL extStatus any input Error status on input *****************************************************************************/ int j_ssp_GetFileName(char *DOL, char *fileName, int extStatus) { int status=ISDC_OK; char location[DAL_FILE_NAME_STRING]; char *lastslash=NULL; if (ISDC_OK!=extStatus) { return(extStatus);} status=FITSparseDOL(DOL,location,NULL,NULL,NULL,NULL,status); if (ISDC_OK!=status) { return(status); } /* Get position of last slash in DOL */ lastslash=strrchr(location,'/'); if (lastslash==NULL) { strcpy(fileName,location); } else { strcpy(fileName,lastslash+1); } return(status); } /***************************************************************** * * j_src_vignetting v1.0 3/12/2001 * * Source file: j_src_lc/spectra.c * File version : 2.5 * Date: 2001/12/03 * Function name j_src_vignetting * Function version : 1.0 * Parent component: j_src_lc/spectra * Children: * Developer: Stefan Larsson * Contact Address: Stockholm Observatory * SCFAB * SE-106 91 Stockholm * Phone: +46 8-5537 8543 FAX: +46 8-5537 8510 * stefan@astro.su.se * Purpose: Calculate vignetting values for a source direction * using an interpolation of the vignetting * table array vignArray[][]. * * * Origin date: 011203 * Update history: * * * * Error codes: See j_src_lc/spectra.txt * * * srcCosY = Source coordinates (in radians) in the * srcCosZ telescope system. The Y,Z plane is parallel to * the detector plane. * * vignArrayCRPixY = Central pixal in the Y-direction in array * vignArray[][]. * * vignArrayCRPixZ = Central pixal in the Z-direction in array * vignArray[][]. * * vignArrayDeltaY = The size of a vignArray[][] pixel in Y-direction * (in radians). * * vignArrayDeltaZ = The size of a vignArray[][] pixel in Z-direction * (in radians). * ***********************************************************************/ #include int j_src_vignetting( double srcCosY, double srcCosZ, float vignArray[J_VIGN_DIM][J_VIGN_DIM], double vignArrayCRPixY, double vignArrayCRPixZ, double vignArrayDeltaY, double vignArrayDeltaZ, double *vignetting, int chatty, int status) { /* Ordinary variables */ double srcCosYPix = 0.0; double srcCosZPix = 0.0; double t = 0.0; double u = 0.0; long iY1 = 0; long iY2 = 0; long iZ1 = 0; long iZ2 = 0; /* * Immediate return if called while executable is in error condition */ if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : Non-zero status value passed to j_src_vignetting",\ status); return status ; } if(vignArrayDeltaY <= 0 || vignArrayDeltaZ <= 0) { status = J_SRC_WRONG_VALUE; RILlogMessage(NULL, Error_2, "%d : Non-positive vignetting pixel sizes in j_src_vignetting", status); return status; } /**************** Transform srcCosY and Z to pixel coordinates *********/ srcCosYPix = vignArrayCRPixY + srcCosY/vignArrayDeltaY; srcCosZPix = vignArrayCRPixZ + srcCosZ/vignArrayDeltaZ; /************ If we are outside of the array transmission is zero *****/ if((srcCosYPix < 0.0) || (srcCosYPix > J_VIGN_DIM - 1)) { *vignetting = 0.0; return status; } /************************************************************************* * OK, you are inside the array so we have to interpolate. * In this case we go for bilinear interpolation * (as "Press and friends" says it's "close enough for government work". *************************************************************************/ iY1 = (long) srcCosYPix; iY2 = iY1 + 1; iZ1 = (long) srcCosZPix; iZ2 = iZ1 + 1; t = srcCosYPix - (double) iY1; u = srcCosZPix - (double) iZ1; *vignetting = (1.0-t)*(1.0-u)*vignArray[iY1][iZ1] + t*(1.0-u)*vignArray[iY2][iZ1] + t*u*vignArray[iY2][iZ2] + (1.0-t)*u*vignArray[iY1][iZ2]; return status; } /***************************************************************** * * j_src_qeff v1.0 05/12/2001 * * Source file: j_src_lc/spectra.c * File version : 2.5 * Date: 2001/12/05 * Function name j_src_qeff * Function version : 1.0 * Parent component: j_src_lc/spectra * Children: * Developer: Stefan Larsson * Contact Address: Stockholm Observatory * SCFAB * SE-106 91 Stockholm * Phone: +46 8-5537 8543 FAX: +46 8-5537 8510 * stefan@astro.su.se * Purpose: Calculate the average quantum efficiency * for each arf energy bin. The computation is * based on the quantum efficiency values at * specific energies read from datastructure * JMXi-QEFF-MOD. * The average is the weighted mean of the QEFF * (as obtained by linear interpolation) over * each arf bin. * * * Origin date: 011205 * Update history: * * * * Error codes: * * * ii0 = Start index for loop to find line energies * for integration. Updated to skip unnecessary * loops. * ***********************************************************************/ #include int j_src_qeff( double quantumEff[J_SSP_MAX_QEFF_NUM], double quantEnergy[J_SSP_MAX_QEFF_NUM], int nQEff, double arfEnergyLo[J_SSP_MAX_ARF_LENRG_NUM], double arfEnergyHi[J_SSP_MAX_ARF_LENRG_NUM], double arfQuantumEff[J_SSP_MAX_ARF_LENRG_NUM], int nLineEnergies, int chatty, int status) { /* Ordinary variables */ long i = 0; long ii = 0; long ii0 = 0; long iiLo = 0; long iiHi = 0; long iiNumb = 0; double deltaEnergy = 0.0; double dEsub = 0.0; double dEsum = 0.0; double qEff1 = 0.0; double averageQEff = 0.0; double subQEff = 0.0; double weight = 0.0; /* * Immediate return if called while executable is in error condition */ if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : Non-zero status value passed to j_src_qeff",\ status); return status ; } if( chatty == J_CHATTY_MAXIMAL){ RILlogMessage(NULL,Log_0, "Calculating Quantum efficiencies for the ARF channels" ); } /************************************************************************* * LINEAR INTERPOLATION OF QEFF VALUES AT NEW *************************************************************************/ ii0 = 0; for ( i=0 ; i= J_SSP_MAX_ARF_LENRG_NUM) { status = J_SRC_INDEX_ERR; RILlogMessage(NULL, Error_2, "%d : Index out of limits in j_src_qeff", status); return status ; } if(iiLo < 0 || iiHi < 0) { status = J_SRC_INTERPOL_ERR; RILlogMessage(NULL, Error_2, "%d : Not enough data for interpolation in j_src_qeff", status); return status ; } iiNumb = iiHi - iiLo; /********* If no QEFF point in the interval it is simple to take ave. *****/ if(iiNumb == 0){ status = j_src_interval_ave( quantEnergy[iiLo], quantumEff[iiLo], quantEnergy[iiHi+1], quantumEff[iiHi+1], arfEnergyLo[i], arfEnergyHi[i], &averageQEff, chatty, status); } /****** If at least one point in the interval we take the first and * last intarvals. */ else { averageQEff = 0.0; subQEff = 0.0; dEsub = 0.0; dEsum = 0.0; /* Average for first sub interval. */ status = j_src_interval_ave( quantEnergy[iiLo], quantumEff[iiLo], quantEnergy[iiLo+1], quantumEff[iiLo+1], arfEnergyLo[i], quantEnergy[iiLo+1], &subQEff, chatty, status); dEsub = quantEnergy[iiLo+1] - arfEnergyLo[i]; dEsum = dEsub; weight = dEsub/deltaEnergy; averageQEff = averageQEff + subQEff*weight; /* Average for last sub interval. */ status = j_src_interval_ave( quantEnergy[iiHi], quantumEff[iiHi], quantEnergy[iiHi+1], quantumEff[iiHi+1], quantEnergy[iiHi], arfEnergyHi[i], &subQEff, chatty, status); dEsub = arfEnergyHi[i] - quantEnergy[iiHi]; dEsum = dEsum + dEsub; weight = dEsub/deltaEnergy; averageQEff = averageQEff + subQEff*weight; /**** Finaly we take those subintervals that fall completely * inside the arf energy bin. */ if(iiNumb > 1) { for (ii=iiLo+1 ; ii 0.001) { status = J_SRC_WRONG_VALUE; RILlogMessage(NULL, Error_2, "%d : Inconsistent calculation in j_src_qeff (bug?)", status); return status ; } } arfQuantumEff[i] = averageQEff; } return status; } /***************************************************************** * * j_src_interpol v1.0 06/22/2002 * * Source file: j_src_lc/spectra.c * File version : 2.9.0 * Date: 2002/06/22 * Function name j_src_interpol * Function version : 1.0 * Parent component: j_src_lc/spectra * Children: * Developer: Stefan Larsson * Contact Address: Stockholm Observatory * SCFAB * SE-106 91 Stockholm * Phone: +46 8-5537 8543 FAX: +46 8-5537 8510 * stefan@astro.su.se * Purpose: Given an array of values (x,y) and a binned * data set (x1,x2) [x1,x2 is a bin along x.] * for each (x1,x2) bin calculate an average of * y over this bin, using linear interpolation. * Bins with x2 < x[0] are set = x[0]. * Bins with x2 > x[ny-1] are set = x[ny-1]. * * * Origin date: 020622 * Update history: * * * * Error codes: * * * ii0 = Start index for loop to find line energies * for integration. Updated to skip unnecessary * loops. * * TODO: Change variable name subQEff -> subAve * dE... ***********************************************************************/ #include int j_src_interpol( double y[J_SSP_MAX_INTERPOL_NUM], double x[J_SSP_MAX_INTERPOL_NUM], long ny, double x1[J_SSP_MAX_INTERPOL_NUM], double x2[J_SSP_MAX_INTERPOL_NUM], double yave[J_SSP_MAX_INTERPOL_NUM], long nyave, int chatty, int status) { /* Ordinary variables */ long i = 0; long ii = 0; long ii0 = 0; long iiLo = 0; long iiHi = 0; long iiNumb = 0; double delta = 0.0; double dEsub = 0.0; double dEsum = 0.0; double qEff1 = 0.0; double average = 0.0; double subQEff = 0.0; double weight = 0.0; /* * Immediate return if called while executable is in error condition */ if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : Non-zero status value passed to j_src_interpol",\ status); return status ; } /* * Immediate return if number of data points too large. */ if( ny > J_SSP_MAX_INTERPOL_NUM ){ status = J_SRC_INDEX_ERR; RILlogMessage(NULL, Error_2, "%d : Too many points for arrays in j_src_interpol",\ status); RILlogMessage(NULL,Log_0, "ny = %d", (int) ny ); RILlogMessage(NULL,Log_0, "Array maximum is %d", J_SSP_MAX_INTERPOL_NUM ); return status ; } if( nyave > J_SSP_MAX_INTERPOL_NUM ){ status = J_SRC_INDEX_ERR; RILlogMessage(NULL, Error_2, "%d : Too many points for arrays in j_src_interpol",\ status); RILlogMessage(NULL,Log_0, "nyave = %d", (int) nyave ); RILlogMessage(NULL,Log_0, "Array maximum is %d", J_SSP_MAX_INTERPOL_NUM ); return status ; } if( chatty == J_CHATTY_MAXIMAL){ RILlogMessage(NULL,Log_0, " In j_src_interpol" ); } /************************************************************************* * LINEAR INTERPOLATION *************************************************************************/ ii0 = 0; for ( i=0 ; i= J_SSP_MAX_INTERPOL_NUM) { status = J_SRC_INDEX_ERR; RILlogMessage(NULL, Error_2, "%d : Index out of limits in j_src_interpol", status); return status ; } /* If bin start and stop (x1,x2) are below all reference points (x[ii], ii=0,1,2...) we have to EXTRAPOLATE. We do so by setting yave[i] = y[0] */ if(iiLo < 0 && iiHi < 0) { average = y[0]; } /* If only the start of the bin is below all the reference points we simply take the first point. A little crude but good enough for me (at least now). */ else if(iiLo < 0 && iiHi >= 0) { average = y[0]; } /* If bin start and stop (x1,x2) are above all reference points (x[ii], ii=0,1,2...) we have to EXTRAPOLATE. We do so by setting yave[i] = y[ny-1] */ else if(iiLo == ny-1 && iiHi == ny-1) { average = y[ny-1]; } /* If only the end of the bin is above all the reference points we simply take the last point. A little crude but good enough for me (at least for now). */ else if(iiLo < ny-1 && iiHi == ny-1) { average = y[ny-1]; } else { iiNumb = iiHi - iiLo; /***** If no input point in the interval it is simple to take ave. *****/ if(iiNumb == 0){ status = j_src_interval_ave( x[iiLo], y[iiLo], x[iiHi+1], y[iiHi+1], x1[i], x2[i], &average, chatty, status); } /****** If at least one point in the interval we take the first and * last intarvals. */ else { average = 0.0; subQEff = 0.0; dEsub = 0.0; dEsum = 0.0; /* Average for first sub interval. */ status = j_src_interval_ave( x[iiLo], y[iiLo], x[iiLo+1], y[iiLo+1], x1[i], x[iiLo+1], &subQEff, chatty, status); dEsub = x[iiLo+1] - x1[i]; dEsum = dEsub; weight = dEsub/delta; average = average + subQEff*weight; /* Average for last sub interval. */ status = j_src_interval_ave( x[iiHi], y[iiHi], x[iiHi+1], y[iiHi+1], x[iiHi], x2[i], &subQEff, chatty, status); dEsub = x2[i] - x[iiHi]; dEsum = dEsum + dEsub; weight = dEsub/delta; average = average + subQEff*weight; /**** Finaly we take those subintervals that fall completely * inside the arf energy bin. */ if(iiNumb > 1) { for (ii=iiLo+1 ; ii 0.001) { status = J_SRC_WRONG_VALUE; RILlogMessage(NULL, Error_2, "%d : Inconsistent calculation in j_src_interpol (bug?)", status); return status ; } } } yave[i] = average; } if( chatty == J_CHATTY_MAXIMAL){ RILlogMessage(NULL,Log_0, "%d points interpolated in j_src_interpol", (int) nyave ); RILlogMessage(NULL,Log_0, "%d input points used for the interpolation.", (int) ny ); } return status; } /***************************************************************** * * j_src_interval_ave v1.0 05/12/2001 * * Source file: j_src_lc/spectra.c * File version : 2.5 * Date: 2001/12/06 * Function name j_src_interval_ave * Function version : 1.0 * Parent component: j_src_qeff * Children: * Developer: Stefan Larsson * Contact Address: Stockholm Observatory * SCFAB * SE-106 91 Stockholm * Phone: +46 8-5537 8543 FAX: +46 8-5537 8510 * stefan@astro.su.se * Purpose: Given two data points calculate the average * of the linear interpolation/extrapolation * over a specified interval. * * * Origin date: 011206 * Update history: * * * * * ***********************************************************************/ #include int j_src_interval_ave( double x1, double y1, double x2, double y2, double xLo, double xHi, double *average, int chatty, int status) { /* Ordinary variables */ double yLo = 0.0; double yHi = 0.0; double slope = 0.0; double m = 0.0; /* * Immediate return if called while executable is in error condition */ if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : Non-zero status value passed to j_src_interval_ave",\ status); return status ; } /************************************************************************* * CHECK FOR STUPID CASES *************************************************************************/ /* Stupid and maybe wrong but we don't like division with zero. */ if(x2 == x1) { *average = y2; return status; } if(y2 == y1) { *average = y2; return status; } /************************************************************************* * GET EQUATION OF THE LINE AND CALCULATE AVERAGE *************************************************************************/ slope = (y2 - y1)/(x2 - x1); m = y2 - slope*x2; yLo = slope*xLo + m; yHi = slope*xHi + m; *average = 0.5*(yLo+yHi); return status; } /***************************************************************** * * j_src_maskhole * * Source file: j_src_lc/spectra.c * File version : 2.8 * Date: 2002/07/30 * Function name j_src_maskhole * Function version : 1.0 * Parent component: * Children: * Developer: Stefan Larsson * Contact Address: Stockholm Observatory * SCFAB * SE-106 91 Stockholm * Phone: +46 8-5537 8543 FAX: +46 8-5537 8510 * stefan@astro.su.se * Purpose: Using the resolution point spread function * compute the distribution function for an * evenly illuminated hole by convolution of * the resolution PSF with the hole geometry. * Compute the leakage factor (fraction of * flux ending up outside of the projected hole. * * Origin date: 020724 * Update history: * * * * * ***********************************************************************/ #include int j_src_maskhole(float *holeDF, int holeCenter, int PSFSize, float gaussPDFWidth, float PDFStep, float *resPSF, int *holeInOut, int normDF, double *leakFraction, int chatty, int status) { int mid = 0; int ix = 0; int jy = 0; int in = 0; /* float *gaussPDF = NULL; */ float dX = 0.0; float dY = 0.0; float maxDF = 0.0; float valueDF = 0.0; double sumIllum = 0.0; double sumTotal = 0.0; double sumOutside = 0.0; /* * Immediate return if called while executable is in error condition */ if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : Non-zero status value passed to j_src_maskhole",\ status); return status ; } /* Fill the Point spread function array, resPSF, with a 2-dim gaussian distribution. */ status = j_src_fill_gauss(resPSF, PSFSize, gaussPDFWidth, PDFStep, &mid, chatty, status); /* Now step across the array, holeDF, covering the hole and at each point, if open, add the resolution PDF. */ for(ix=0;ix maxDF) { maxDF = valueDF; } dX = (float) (ix-holeCenter) * PDFStep; dY = (float) (jy-holeCenter) * PDFStep; /* replace call with in = *(holeInOut + J_SRC_HOLE_SIZE*jy + ix); */ status = j_src_in_hole (dX, dY, &in, chatty, status); if(in == 1) { sumIllum = sumIllum + (double)valueDF; } else { sumOutside = sumOutside + (double)valueDF; } } } sumTotal = sumIllum + sumOutside; if(sumTotal == 0.0){ status = J_SRC_WRONG_VALUE; RILlogMessage(NULL, Error_2, "%d : Sum of distrib. function = 0 in j_src_maskhole",\ status); return status ; } *leakFraction = sumOutside/sumTotal; /* ------------------------------------------------------------ Normalize the DF, either 1) to peak = 1 or 2) Integral of DF = 1. ------------------------------------------------------------- */ if(normDF == 1) { for(ix=0;ix int j_src_fill_gauss(float *gaussPDF, int gaussPDFSize, float gaussPDFWidth, float gaussPDFStep, int *mid, int chatty, int status) { int i = 0; int j = 0; float amid = 0.0; float power = 0.0; float dx = 0.0; float dy = 0.0; float gaussValue = 0.0; /* * Immediate return if called while executable is in error condition */ if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : Non-zero status value passed to j_src_fill_gauss",\ status); return status; } amid = 0.5*(double)gaussPDFSize; *mid = (int) (amid+0.1); /*Even, if odd (size+1)/2 */ for(i=0;i int j_src_add_array(float *fromArray, int fromArrayNumb, int mid, float *holeDF, int holeDFNumb, int iAddPoint, int jAddPoint, int chatty, int status) { int i = 0; int j = 0; int iStart = 0; int jStart = 0; int ifr = 0; int jfr = 0; /* * Immediate return if called while executable is in error condition */ if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : Non-zero status value passed to j_src_add_array",\ status); return status ; } iStart = iAddPoint - mid; jStart = jAddPoint - mid; for(i=iStart;i=0 && i < holeDFNumb) && (j>=0 && j < holeDFNumb)) { if((ifr >=0 && ifr < fromArrayNumb) && (jfr >=0 && jfr < fromArrayNumb)) { *(holeDF + holeDFNumb*j + i) = *(holeDF + holeDFNumb*j + i) + *(fromArray + fromArrayNumb*(jfr) + (ifr)); } } } } return status; } /************************************************************************ * * j_src_in_hole * * * Purpose: Check if a given point (x,y) is within or * outside of a mask hole. Coordinates with * respect to hole center. * * Parameters: * * maskHoleA = Half of one side of hexagone. * maskHoleR = Smallest distance from element center to * hexagone edge. * maskHoleH = Longest distance from element center to * hexagone edge ("corner"). int iy = 0; * * Output: in = 0: Point outside of polygone. * in = 1: Point within polygone. * *************************************************************************/ int j_src_in_hole (double x, double y, int *in, int chatty, int status) { double pi = 3.14159265358979; double normal = 0.0; double maskHoleA = 0.0; double maskHoleH = 0.0; double maskHoleR = 0.0; /* * Immediate return if called while executable is in error condition */ if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : Non-zero status value passed to j_src_in_hole",\ status); return status ; } *in = 0; maskHoleR = 0.5*J_MASK_ELEM_RD; maskHoleH = maskHoleR/cos(pi/6.0); maskHoleA = maskHoleH*sin(pi/6.0); /* Due to symetry we just reflect the point to the first quadrant */ x = fabs(x); y = fabs(y); /* First check if the point is within a rectangle surrounding the outer limits of the hexagone. */ if( x maskHoleA) { normal = y*cos(pi/6.0) + x*sin(pi/6.0); if( normal > maskHoleR) { *in = 0; /* In rectangle but outside hexagone */ } } return status; } /***************************************************************** * * j_src_leakage * * Source file: j_src_lc/spectra.c * File version : 2.8 * Date: 2002/07/31 * Function name j_src_leakage * Function version : 1.0 * Parent component: * Children: * Developer: Stefan Larsson * Contact Address: Stockholm Observatory * SCFAB * SE-106 91 Stockholm * Phone: +46 8-5537 8543 FAX: +46 8-5537 8510 * stefan@astro.su.se * Purpose: Compute the amount of leakage from the * illuminated detector area to surrounding * area. * * Origin date: 020731 * Update history: * * * * * ***********************************************************************/ #include int j_src_leakage(double posRes[J_SSP_MAX_POSRES_NUM], double posResEnergy[J_SSP_MAX_POSRES_NUM], int nPosRes, float openFraction, int chatty, int status) { long bufferSize = 0; long i = 0; long ii = 0; long jj = 0; int psfSize = 0; int holeCenter = 0; int *holeInOut = 0; int normDF = 2; float *resPSF = NULL; float *holeDF = NULL; float *holeDFbin = NULL; float psfWidth = 0.0; float psfStep = 0.0; double leakFraction = 0.0; double leakage[J_SSP_MAX_POSRES_NUM]; double leakageBin[J_SSP_MAX_POSRES_NUM]; double posResCorr[J_SSP_MAX_POSRES_NUM]; float detBin = 1.0; double average = 0.0; double polynom = 0.0; double polFactor = 0.0; double aa[6]; double netLeakFraction = 0.0; /* * Immediate return if called while executable is in error condition */ if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : Non-zero status value passed to j_src_leakage",\ status); return status ; } /***************** Compute the distribution function for an evenly illuminated mask hole. ******************/ /* Allocate memory for holeDF array. */ bufferSize = J_SRC_HOLE_SIZE*J_SRC_HOLE_SIZE*sizeof(float); status = DALallocateDataBuffer( (void **)&holeDF, bufferSize, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not allocate memory for holeDF", status ); return status; } holeCenter = (int) (0.5*(double)J_SRC_HOLE_SIZE+0.1); /* Allocate memory for holeDFbin array. */ bufferSize = J_SRC_HOLE_SIZE*J_SRC_HOLE_SIZE*sizeof(float); status = DALallocateDataBuffer( (void **)&holeDFbin, bufferSize,status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not allocate memory for holeDFbin", status ); return status; } /* Allocate memory for holeInOut array. */ bufferSize = J_SRC_HOLE_SIZE*J_SRC_HOLE_SIZE*sizeof(int); status = DALallocateDataBuffer( (void **)&holeInOut, bufferSize, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not allocate memory for holeInOut", status ); return status; } /*-------------------------------------------------------------------- Using the detector resolution we can now compute the leakFactor, which is how much of the flux onto an open mask hole will be detected outside the projection of the hole on the detector. Of the flux leaking out some (= mask open fraction) will on average leak into another open hole. The leakFraction is corrected for that effect. ------------------------------------------------------------------ */ /* Allocate memory for PSF array. */ bufferSize = J_SRC_PSF_SIZE*J_SRC_PSF_SIZE*sizeof(float); status = DALallocateDataBuffer( (void **)&resPSF, bufferSize, status); if (status != ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : Could not allocate memory for resolution PSF", status ); return status; } if(normDF == 1) { if( chatty >= J_CHATTY_VERY_VERBOSE ){ RILlogMessage(NULL,Log_0, "Detector response function normalized so that "); RILlogMessage(NULL,Log_0, "max peak = 1."); } } else if(normDF == 2) { if( chatty >= J_CHATTY_VERY_VERBOSE ){ RILlogMessage(NULL,Log_0, "Detector response function normalized so integral = 1 "); } } /* Work in progress...... else if(normDF == 3) { if( chatty >= J_CHATTY_VERY_VERBOSE ){ } } */ for ( i=0 ; i int j_src_maskhole_sample (float *holeDF, int holeCenter, float *holeDFbin, float psfStep, float detBin, int *holeInOut, int chatty, int status) { int ix = 0; int jy = 0; int iixd = 0; int iix = 0; int jjyd = 0; int jjy = 0; int ij0 = 0; int stepPerBin = 0; float areaFloat =0.0; float areaInt = 0.0; float areaCorr = 0.0; double sum = 0.0; /* * Immediate return if called while executable is in error condition */ if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : Non-zero status value passed to j_src_maskhole_sampled",\ status); return status ; } /* Given a detector bin size compute the number of corresponding integer steps in the DF array. Also compute a factor to correct for the error caused by using finite size psfStep. */ stepPerBin = (int) (detBin/psfStep + 0.5); areaFloat = detBin*detBin; areaInt = ((float)stepPerBin*psfStep)*((float)stepPerBin*psfStep); areaCorr = areaFloat/areaInt; ij0 = (int) ((detBin/psfStep)*0.5 + 0.5); iixd = stepPerBin-ij0; jjyd = stepPerBin-ij0; /* Initialize array values to 0. This is mainly to set points at the outer rim since these are not set below. */ for(ix=0;ix_SRC_HOLE_SIZE) ( jjy<0 || jjy>_SRC_HOLE_SIZE) */ sum = sum + (double) *(holeDF + J_SRC_HOLE_SIZE*jjy + iix); } } sum = areaCorr*sum; *(holeDFbin + J_SRC_HOLE_SIZE*jy + ix) = (float) sum; } } return status; } /***************************************************************** * * j_src_maskhole_average * * Source file: j_src_lc/spectra.c * File version : 2.8 * Date: 2002/08/01 * Function name j_src_maskhole_average * Function version : 1.0 * Parent component: * Children: * Developer: Stefan Larsson * Contact Address: Stockholm Observatory * SCFAB * SE-106 91 Stockholm * Phone: +46 8-5537 8543 FAX: +46 8-5537 8510 * stefan@astro.su.se * Purpose: Given a detector distribution function for * an illuminated mask hole, compute the average * leakage. Leakage is the fraction of the * flux through the hole which is detected * outside its projection onto the detector. * * Origin date: 020801 * Update history: 020821: The phasing of the dector pixels * relative to the mask hole is now taken * from a random distribution. * An average of 4000 random pixel phases * are computed. * This gives un uncertainty in * the correction factor of < 0.1%. * * * ***********************************************************************/ #include int j_src_maskhole_average (float *holeDFbin, float psfStep, float detBin, int *holeInOut, double *average, int chatty, int status) { long i = 0; int ix = 0; int jy = 0; int ij0 = 0; int ix0 = 0; int iy0 = 0; int stepPerBin = 0; int counter = 0; double start = 13.0; double sum = 0.0; double sumIn = 0.0; double sumOut = 0.0; /* * Immediate return if called while executable is in error condition */ if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : Non-zero status value passed to j_src_maskhole_average",\ status); return status ; } /* */ stepPerBin = (int) (detBin/psfStep + 0.5); ij0 = (int) ((detBin/psfStep)*0.5 + 0.5); /* Now step across the array, holeDF, convolving at each point with the detector bin size. Start point for the detector bins is random. Take 40000 averages. This is an order of magnitude more than the total number of mask holes. So the averaging is accurate enough. */ srand48((long) start); for( i = 0; i <400000 ; i++) { start = drand48(); ix0 = (int) (start*stepPerBin); start = drand48(); iy0 = (int) (start*stepPerBin); sumOut = 0.0; sumIn = 0.0; for(ix=ij0+ix0;ix 0.0) { sum = sum + sumOut/(sumOut+sumIn); counter = counter + 1; } } if(counter > 0){ *average = sum/((double)counter); } return status; } /***************************************************************** * * j_src_leak_coefficients * * Source file: j_src_lc/spectra.c * File version : 2.8 * Date: 2002/09/04 * Function name j_src_leak_coefficients * Function version : 1.0 * Parent component: * Children: * Developer: Stefan Larsson * Contact Address: Stockholm Observatory * SCFAB * SE-106 91 Stockholm * Phone: +46 8-5537 8543 FAX: +46 8-5537 8510 * stefan@astro.su.se * Purpose: Calculate transformation coefficients to * convert the observed rates in illuminated * and shadowed areas to source and background * rates corrected for leakage. * * The coefficients should be applied as: * * Rate_src = a11*rate_ill + a12*rate_shad * Rate_bkg = a21*rate_ill + a22*rate_shad * * Note: * Rate_src is net (background subtracted) rate. * Rate_src & _bkg are rates per full detector area. * * Origin date: 020904 * Update history: * * Variables: * * b2 = f*leakage*(1-f) * * * COMMENTS: a12 is independent of leakFraction and so does * not really need to be an array. I'll keep it like * this for the time being. * ***********************************************************************/ #include int j_src_leak_coefficients(double leakage[J_NUM_SCI_BINS], double a11[J_NUM_SCI_BINS], double a12[J_NUM_SCI_BINS], double a21[J_NUM_SCI_BINS], double a22[J_NUM_SCI_BINS], double openFraction, int chatty, int status) { long i = 0; double a11a = 0.0; double b1 = 0.0; double OneMinusF = 0.0; /* * Immediate return if called while executable is in error condition */ if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : Non-zero status value passed to j_src_leak_coefficients",\ status); return status ; } OneMinusF = 1.0-openFraction; b1 = 1.0 - leakage[i] - openFraction; for(i=0;i function executed with no errors < 0 (various) ==> ISDC system function error code, passed on J_BEL_ILLEGAL_INPUT_DATA ==> event type not recognized Parameter arguments: name range I/O description theSWG !=NULL input handle to SWG evtType FULL/(REST) input JEM-X event type nameLC JMXi-SRC.-LCR input name of LC data structure srcID string array input source identification srcRa 0.0 to 360.0 input source right ascension srcDec -90.0 to +90.0 input source declination nOutLCBins >=0 input number of lightcurve bins rateLC (array) input lightcurve rates errLC (array) input lightcurve rate errors timeLC (array) input central time/phase of lightcurve bins timeDel (array) input width of lightcurve bins nPhaseBins >=0 input number of phase bins, used as flag timeStep >0.0 input period used in lightcurve folding timeStart any input time of phase zero for folding nChanbins 1 to 256 input number of channel bins (LC energy bands) chanLow (array) input lower channel boundaries chanHigh (array) input upper channel boundaries instModDOL (string) input DOL of JMXi-IMOD-GRP tElapse >=0.0 input total elapsed time onTime >=0.0 input sum of good times avgRate (array) input average count rate per channel avgRateErr (array) input error of average count rate chatter 0 to 5 input verbosity control variable callingStatus any input error status on input Updates: 040126 SL Introduced energy dependent PIFs. Parameter arrays openAreaEnergy, closedAreaEnergy, effOpenAreaEnergy, leakageFrOpenEnergy, leakageToClosedEnergy are expanded to two dimensions to hold the energy dependence (and "Energy" added to their names). The energy dependence is taken into account by interpolating (j_src_factors_interpol) to all (256) energy channels and and then selecting the value at the center of the band. *****************************************************************************/ int j_src_WriteLC(dal_element *theSWG, Instrument jemxInstr, JEMX_type evtType, char *nameLC, char srcID[J_SRC_MAXSRC][DAL_MED_STRING], float srcRa[J_SRC_MAXSRC], float srcDec[J_SRC_MAXSRC], long nSources, long *nRateLC, long nOutLCBins, double *rateLC, double *errLC, double *timeLC, double *timeDel, double *fracExp, long *nBRateLC, double *bRateLC, double *bErrLC, int nChanBins, int *chanLow, int *chanHigh, long nPhaseBins, double timeStep, double timeStart, double tElapse, double onTime, double meanDead, double *avgSrcRate, double *avgSrcRateErr, char *instModDOL, double *aLC11, double *aLC12, double *aLC21, double *aLC22, float openFraction, float of[J_SRC_MAXSRC], int vignCorr, double vignetting[J_SRC_MAXSRC], float srcOffAxisAngle[J_SRC_MAXSRC], double openAreaEnergy[J_SRC_MAXSRC][J_SRC_PIF_MAX_ENERGIES], double closedAreaEnergy[J_SRC_MAXSRC][J_SRC_PIF_MAX_ENERGIES], double effOpenAreaEnergy[J_SRC_MAXSRC][J_SRC_PIF_MAX_ENERGIES], double leakageFrOpenEnergy[J_SRC_MAXSRC][J_SRC_PIF_MAX_ENERGIES], double leakageToClosedEnergy[J_SRC_MAXSRC][J_SRC_PIF_MAX_ENERGIES], long nPifEnergies, double radiusLimit, double detectorRadius, float openFractionAve, double pifjIniOpen[J_SRC_MAXSRC][J_SRC_MAXSRC], double pifjIniClosed[J_SRC_MAXSRC][J_SRC_MAXSRC], int pifChannel[J_SRC_PIF_MAX_ENERGIES], int diagnosticMode, double diagnosticParam, int precisionLevel, int fluxScaling, int iros, int chatter, int callingStatus) { dal_element *dalPtr=NULL; /* generic DAL pointer */ dal_element *ebdsPtr=NULL; /* DAL pointer to energy bounds table */ dal_dataType dType=DAL_DT_UNKNOWN; /* needed for DAL calls */ char nameEbds[14]; /* name of energy boundaries table */ char typeName[FLEN_CARD]; /* FULL or REST */ char appFlag[2] = "F"; double a = 0.0; double *rateBuff=NULL; /* local buffer for rate per energy */ double *errBuff=NULL; /* local buffer for error per energy */ double *bRateBuff=NULL; /* local buffer for bRate per energy */ double *bErrBuff=NULL; /* local buffer for bError per energy */ double *irosBuff=NULL; /* iros work buffer */ double timeErr=1.0/8192.0; /* JEM-X time uncertainty */ double timeErrRel=0.0; /* JEM-X time relative uncertainty */ double rate=0.0; /* Keep rate value during calc */ double bRate=0.0; /* Keep bRate value during calc */ double srcRate=0.0; /* Net source rate */ double bkgRate=0.0; /* Background rate */ double time=0.0; /* Live time for a bin */ double sumtime=0.0; /* Sum of time for bins */ double sumRate=0.0; /* Sum of net rate for all timebins */ double sumBRate=0.0; /* Sum of bkg. rates for all time bins*/ double sumNRate=0.0; /* Sum of nRate for all timebins */ double sumNBRate=0.0; /* Sum of nBRate for all time bins */ double oF2=0.0; /* openFraction square */ double cF2=0.0; /* closedFraction square */ double rateVariance=0.0; /* Variance of illum. rate */ double bRateVariance=0.0; /* Variance of shadow. rate */ double poissonErr=0.0; /* Source count statistical error */ double bPoissonErr=0.0; /* Backgr. count statistical error */ double ratePoissonErr=0.0; /* Source rate statistical error */ double bRatePoissonErr=0.0; /* Backgr. rate statistical error */ double sumSrcVariance=0.0; /* Sum of source error variances */ double sumBkgVariance=0.0; /* Sum of backgr. error variances */ double rateVarianceMin[J_SRC_MAXSRC]; double bRateVarianceMin[J_SRC_MAXSRC]; double avgNRate = 0.0; /* Average open rate per live time */ double avgNBRate = 0.0; /* Average closed rate per live time */ double avgRate=0.0; double avgRateErr=0.0; double avgBRate=0.0; double avgBRateErr=0.0; double areaScaling=0.0; double errDr = 0.0; double errDbR = 0.0; double srcVariance = 0.0; double bkgVariance = 0.0; double openAreaChan[J_NUM_SCI_BINS]; double closedAreaChan[J_NUM_SCI_BINS]; double effOpenAreaChan[J_NUM_SCI_BINS]; double leakageFrOpenChan[J_NUM_SCI_BINS]; double leakageToClosedChan[J_NUM_SCI_BINS]; double openArea = 0.0; double closedArea = 0.0; double effOpenArea = 0.0; double leakageFrOpen = 0.0; double leakageToClosed = 0.0; float eMin[J_NUM_SCI_BINS]; /* buffer for lower energy bounds */ float eMax[J_NUM_SCI_BINS]; /* buffer for upper energy bounds */ float deltaT=0.0; /* TIMEDEL */ float vignFloat=0.0; float detSig = 0.0; /* Detection significance */ long iLC=0; /* loop over time bins */ long numRead=0; /* counter of read values */ long iSource=0; /* loop over sources */ long iLCBin=0; /* rate array index */ long nRate=0; /* Number of events (illum. area) */ long nBRate=0; /* Number of events (shad. area) */ int iChan=0; /* loop over channels */ int midChan[J_NUM_SCI_BINS]; /* Mid point of LC band/channel */ int offset=0; /* loop over channels */ int giveEbounds=0; /* boolean: do we have energy bounds? */ int status=ISDC_OK; /* local status */ /* * exit function immediately if callingStatus is not OK on entry */ if(callingStatus != ISDC_OK) return(callingStatus); areaScaling = (detectorRadius/radiusLimit)* (detectorRadius/radiusLimit); /* * First get energy bounds corresponding to our channels */ status = DALobjectOpen(instModDOL,&dalPtr,status); if (ISDC_OK==status) { giveEbounds = 1; } else { RILlogMessage(NULL,Warning_2, "(WriteLC) Can not open IMOD group %s!", instModDOL); RILlogMessage(NULL,Log_2, "(WriteLC) Lacking IMOD group: " "E_MIN and E_MAX will not be written"); status = ISDC_OK; giveEbounds = 0; } if (giveEbounds) { switch (jemxInstr) { case JMX1: strcpy(nameEbds,"JMX1-"); break; case JMX2: strcpy(nameEbds,"JMX2-"); break; default: status = J_SRC_WRONG_JEMX_NUM; RILlogMessage(NULL,Error_1, "Can not handle JEM-X code %i",jemxInstr); break; } if (ISDC_OK!=status) { return(status); } strcat(nameEbds,"FBDS-MOD"); status = DALobjectFindElement(dalPtr,nameEbds,&ebdsPtr,status); if (ISDC_OK!=status) { RILlogMessage(NULL,Error_2, "(WriteLC) Can not find %s in IMOD group in %s!", nameEbds,instModDOL); return(status); } dType=DAL_FLOAT; status = DALtableGetCol(ebdsPtr,"E_MIN",0,&dType,&numRead, (void*)eMin,status); if (ISDC_OK!=status) { RILlogMessage(NULL,Error_2, "(WriteLC) Error reading E_MIN from %s!", nameEbds); return(status); } dType=DAL_FLOAT; status = DALtableGetCol(ebdsPtr,"E_MAX",0,&dType,&numRead, (void*)eMax,status); if (ISDC_OK!=status) { RILlogMessage(NULL,Error_2, "(WriteLC) Error reading E_MAX from %s!", nameEbds); return(status); } status = DALobjectClose(dalPtr,DAL_SAVE,status); if (ISDC_OK!=status) { RILlogMessage(NULL,Error_2, "(WriteLC) Error closing IMOD group in %s!", instModDOL); return(status); } if (J_CHATTY_VERY_VERBOSE>=chatter) { RILlogMessage(NULL,Log_1, "(WriteLC) read energy bounds from %s in " "Instrument Model Group", nameEbds); } } /* end if giveEbounds */ /* Allocate local buffers */ status = DALallocateDataBuffer( (void **)&rateBuff, nOutLCBins * sizeof(double), status ); status = DALallocateDataBuffer( (void **)&errBuff, nOutLCBins * sizeof(double), status ); status = DALallocateDataBuffer( (void **)&bRateBuff, nOutLCBins * sizeof(double), status ); status = DALallocateDataBuffer( (void **)&bErrBuff, nOutLCBins * sizeof(double), status ); if(iros > 0){ status = DALallocateDataBuffer( (void **)&irosBuff, nChanBins * nOutLCBins * sizeof(double), status ); } if (ISDC_OK!=status) { RILlogMessage(NULL,Error_2, "(WriteLC) Error allocating buffers!"); return(status); } /* Compute energy channel number (0-255) at the center of the energy band. An average leakage correction for this light curve energy band/channel is done for that energy. */ for (iChan=0;iChan 19 && precisionLevel <= 30){ /* For this source interpolate areas and correction factors from pifChannel to channel ii */ status = j_src_factors_interpol( iSource, pifChannel, openAreaEnergy, closedAreaEnergy, effOpenAreaEnergy, leakageFrOpenEnergy, leakageToClosedEnergy, nPifEnergies, openAreaChan, closedAreaChan, effOpenAreaChan, leakageFrOpenChan, leakageToClosedChan, chatter, status); } for (iChan=0;iChan 19 && precisionLevel <= 30){ openArea = openAreaChan[midChan[iChan]]; closedArea = closedAreaChan[midChan[iChan]]; effOpenArea = effOpenAreaChan[midChan[iChan]]; leakageFrOpen = leakageFrOpenChan[midChan[iChan]]; leakageToClosed = leakageToClosedChan[midChan[iChan]]; if( chatter == J_CHATTY_MAXIMAL ){ RILlogMessage(NULL,Log_1, "Interpolation for source %d band %d ", iSource+1, iChan+1); RILlogMessage(NULL,Log_1," Open area = %f ", openArea); RILlogMessage(NULL,Log_1," Closed area = %f ", closedArea); RILlogMessage(NULL,Log_1," Effectve open area = %f ", effOpenArea); RILlogMessage(NULL,Log_1, " Leakage fraction from open area = %f ", leakageFrOpen); RILlogMessage(NULL,Log_1, " Leakage fraction into closed area = %f ", leakageToClosed); } } /* Create new child of detector lightcurve Index */ status = DAL3GENindexCreateMember(theSWG,nameLC,NULL, &dalPtr,status); if (ISDC_OK!=status) { RILlogMessage(NULL,Error_1, "(WriteLC) Can not correctly create output " "LC number %d!", iChan+1); return(status); } /* At this point we compute a mean rate for open and closed area where the data is weighted after bin live time. (the live time information is in the difference beween rate and nRate since the first is corrected for deadtime and grey filter). This information is exact except when the grey/dead changes where the time of change is not known and taken into account. It also requires at least one event in the bin to extract the live time. */ sumtime = 0.0; sumRate = 0.0; sumBRate = 0.0; sumNRate = 0.0; sumNBRate = 0.0; for (iLC=0; iLC 0){ time = (rate+bRate)/((double)(nRate+nBRate)); }else{ time = 0.0; } sumtime = sumtime + time; sumNRate = sumNRate + (double) nRate; sumNBRate = sumNBRate + (double) nBRate; sumRate = sumRate + rate; sumBRate = sumBRate + bRate; } /* If illuminated area flux is = 0 the error should not be zero. Right now we assume a minimum error variance = 1. This we have to scale from nRate=1 to rate. The scaling factor in rate is (rate/nRate), which is also the scaling factor for the error, sqrt(Variance). Variance therefore scale as (rate/nRate)**2, i.e. variance = nRate * (rate/nRate)**2. In this case we evaluate (rate/nRate) for the total counts and multiply by nRate=1 to get the variance scaled to one count. Note that this is not the true variance since the gaussian approximation is not really valid here. */ if(sumNRate > J_SRC_ACCURACY){ sumRate = sumRate/sumNRate; rateVarianceMin[iSource] = sumRate*sumRate; } if(sumNBRate > J_SRC_ACCURACY){ sumBRate = sumBRate/sumNBRate; bRateVarianceMin[iSource] = sumBRate*sumBRate; } /* Does not yet handle precisionLevel=0 */ if(sumtime > J_SRC_ACCURACY && precisionLevel > 19){ avgNRate = sumNRate/sumtime; avgNBRate = sumNBRate/sumtime; /* openArea can be zero but closed should not. Anyway */ if(openArea > 0 && closedArea > 0){ a = (avgNRate/openArea) - (avgNBRate/closedArea); }else{ a = 0.0; } srcRate = a/(1.0 - leakageFrOpen - (openArea/closedArea)* leakageToClosed); bkgRate = (avgNBRate/closedArea) - srcRate*(openArea/closedArea)* leakageToClosed; if(fluxScaling == 1) { srcRate = srcRate*openArea; bkgRate = bkgRate*openArea; } else if(fluxScaling == 2) { srcRate = srcRate*10000.0; bkgRate = bkgRate*10000.0; } else if(fluxScaling == 3) { srcRate = srcRate*100.0; bkgRate = bkgRate*100.0; } avgNRate = srcRate; avgNBRate = bkgRate; } /* End of live time based calculation of mean rate. */ sumRate = 0.0; sumBRate = 0.0; sumSrcVariance = 0.0; sumBkgVariance = 0.0; /* Extract values for all time bins in the current energy band */ for (iLC=0; iLC 0){ if(iSource > 0){ offset = iChan*nOutLCBins + iLC; a = *(irosBuff + offset); rate = rate - a*pifjIniOpen[iSource][0]; bRate = bRate - a*pifjIniClosed[iSource][0]; } } status = j_src_solve_rate(openArea, closedArea, effOpenArea, leakageFrOpen, leakageToClosed, rate, bRate, &srcRate, &bkgRate, nRate, nBRate, &ratePoissonErr, &bRatePoissonErr, chatter, status); if(fluxScaling == 1) { srcRate = srcRate*openArea; bkgRate = bkgRate*openArea; } else if(fluxScaling == 2) { srcRate = srcRate*10000.0; bkgRate = bkgRate*10000.0; } else if(fluxScaling == 3) { srcRate = srcRate*100.0; bkgRate = bkgRate*100.0; } if ( timeDel[iLC] > 0.0){ srcRate = srcRate/(timeDel[iLC]*DAL3GEN_SECONDS_IN_DAY); bkgRate = bkgRate/(timeDel[iLC]*DAL3GEN_SECONDS_IN_DAY); } else{ srcRate = 0.0; bkgRate = 0.0; } if(diagnosticMode == 1){ if(diagnosticParam < 0.5){ srcRate = rate; bkgRate = bRate; }else{ srcRate = (float) (*(nRateLC + iLCBin)); bkgRate = (float) (*(nBRateLC + iLCBin)); } } sumRate = sumRate + srcRate; sumBRate = sumBRate + bkgRate; *(rateBuff+iLC) = srcRate; *(bRateBuff+iLC) = bkgRate; /* Error estimate. */ nRate = *(nRateLC + iLCBin); nBRate = *(nBRateLC + iLCBin); bRatePoissonErr = bRatePoissonErr/ (timeDel[iLC]*DAL3GEN_SECONDS_IN_DAY); ratePoissonErr = ratePoissonErr/ (timeDel[iLC]*DAL3GEN_SECONDS_IN_DAY); if(fluxScaling == 1) { bRatePoissonErr = bRatePoissonErr*openArea; ratePoissonErr = ratePoissonErr*openArea; } else if(fluxScaling == 2) { bRatePoissonErr = bRatePoissonErr*10000.0; ratePoissonErr = ratePoissonErr*10000.0; } else if(fluxScaling == 3) { bRatePoissonErr = bRatePoissonErr*100.0; ratePoissonErr = ratePoissonErr*100.0; } *(bErrBuff+iLC) = bRatePoissonErr; *(errBuff+iLC) = ratePoissonErr; if(diagnosticMode == 1){ ratePoissonErr = sqrt( (float) nRate); bRatePoissonErr = sqrt((float) nBRate); if(diagnosticParam < 0.5){ if(nRate > 0){ ratePoissonErr = ratePoissonErr*(srcRate/(float) nRate); }else{ ratePoissonErr = 1.0; } if(nBRate > 0){ bRatePoissonErr = bRatePoissonErr*(bkgRate/(float) nBRate); }else{ bRatePoissonErr = 1.0; } } *(errBuff+iLC) = ratePoissonErr; *(bErrBuff+iLC) = bRatePoissonErr; } sumSrcVariance = sumSrcVariance + ratePoissonErr*ratePoissonErr; sumBkgVariance = sumBkgVariance + bRatePoissonErr*bRatePoissonErr; } /* Write the source IDs. */ status = DALattributePut(dalPtr,"SOURCEID",DAL_CHAR, (void*)&srcID[iSource],NULL,NULL,status); if (ISDC_OK!=status) { RILlogMessage(NULL,Error_1, "(WriteLC) Error writing SOURCEID keyword!"); return(status); } /* Write angle offset from the center of the field of view. */ status = DALattributePut(dalPtr,"OFFANGLE",DAL_FLOAT, (void*)&srcOffAxisAngle[iSource],NULL, NULL,status); if (ISDC_OK!=status) { RILlogMessage(NULL,Error_1, "(WriteLC) Error writing OFFANGLE keyword!"); return(status); } /* Write the source coordinates. */ status = DALattributePut(dalPtr,"RA_OBJ",DAL_FLOAT, (void*)&srcRa[iSource],NULL,NULL,status); if (ISDC_OK!=status) { RILlogMessage(NULL,Error_1, "(WriteLC) Error writing RA_OBJ keyword!"); return(status); } /* Write the source coordinates. */ status = DALattributePut(dalPtr,"DEC_OBJ",DAL_FLOAT, (void*)&srcDec[iSource],NULL,NULL,status); if (ISDC_OK!=status) { RILlogMessage(NULL,Error_1, "(WriteLC) Error writing DEC_OBJ keyword!"); return(status); } /* Compute averages */ avgRate = sumRate/((double) nOutLCBins); avgRateErr = sqrt(sumSrcVariance)/((double) nOutLCBins); avgBRate = sumBRate/((double) nOutLCBins); avgBRateErr = sqrt(sumBkgVariance)/((double) nOutLCBins); *(avgSrcRate+iSource+nSources*iChan) = avgRate; *(avgSrcRateErr+iSource+nSources*iChan) = avgRateErr; /* Not yet used RILlogMessage(NULL,Log_1, "Source no. %d Energy band %d, Live time based Rate = %f ", ((int) iSource)+1, ((int) iChan)+1, avgNRate); */ /* This is a first attempt of an iros-like correction. This first source the lightcurves for the first source. MUST DEVELOP A BETTER WAY TO HANDLE SIGNIFICENS CRITERION. */ if(iros > 0){ if(iSource == 0){ if(precisionLevel > 19 && precisionLevel < 31){ if(avgRate/avgRateErr > 1.0){ for (iLC=0; iLC 0.0 && avgRateErr > 0.0){ detSig = avgRate/avgRateErr; }else { detSig = 0.0; } status = DALattributePut(dalPtr,"DETSIG",DAL_FLOAT, (void*)&detSig,NULL,NULL, status); /* set further keywords: elapsed time and on time */ status = DALattributePut(dalPtr,"TELAPSE",DAL_DOUBLE, (void*)&tElapse,NULL,NULL,status); if (ISDC_OK!=status) { RILlogMessage(NULL,Error_1, "(WriteLC) Error writing TELAPSE keyword!"); return(status); } status = DALattributePut(dalPtr,"ONTIME",DAL_DOUBLE, (void*)&onTime,NULL,NULL,status); if (ISDC_OK!=status) { RILlogMessage(NULL,Error_1, "(WriteLC) Error writing ONTIME keyword!"); return(status); } /* mean dead time correction factor */ status = DALattributePut(dalPtr,"DEADC",DAL_DOUBLE, (void*)&meanDead,NULL,NULL,status); if (ISDC_OK!=status) { RILlogMessage(NULL,Error_1, "(WriteLC) Error writing DEADC keyword!"); return(status); } /* average countrate and error */ status = DALattributePut(dalPtr,"SRCCNT",DAL_DOUBLE, (void*)(&avgRate),NULL,NULL,status); /* (void*)(avgRate+iChan),NULL,NULL,status); */ if (ISDC_OK!=status) { RILlogMessage(NULL,Error_1, "(WriteLC) Error writing SRCCNT keyword!"); return(status); } status = DALattributePut(dalPtr,"SRCCNTE",DAL_DOUBLE, (void*)(&avgRateErr), NULL,NULL,status); if (ISDC_OK!=status) { RILlogMessage(NULL,Error_1, "(WriteLC) Error writing SRCCNTE keyword!"); return(status); } /* for folded lightcurves record also period and phase zero */ if (0 J_SRC_ACCURACY) { strcpy(appFlag, "T"); status = DALattributePut(dalPtr, "VIGNAPP", DAL_BOOL, (void *) appFlag, NULL, "Light curve corrected for vignetting", status); vignFloat = (float) vignetting[iSource]; status = DALattributePut(dalPtr, "VIGNET", DAL_FLOAT, (void *) &vignFloat, NULL, "Vignetting factor", status); } else { strcpy(appFlag, "F"); status = DALattributePut(dalPtr, "VIGNAPP", DAL_BOOL, (void *) appFlag, NULL, "Light curve not corrected for vignetting", status); } if ( status!=ISDC_OK){ RILlogMessage(NULL, Error_2, "%d : (WriteLC) Error writing VIGNAPP keyword", status); return status; } if(vignCorr == 0 && vignetting[iSource] < J_SRC_ACCURACY) { RILlogMessage(NULL, Warning_2, "(WriteLC): No vignetting correction for source %d ", (int) iSource); RILlogMessage(NULL, Warning_2, "(WriteLC): Vignetting factor below limit (%f) ", J_SRC_ACCURACY); } /* Copy standard keywords from SWG */ status = DAL3GENattributeCopy(theSWG,dalPtr, "REVOL,SWID,SW_TYPE,SWBOUND," "OBTSTART,OBTEND,TSTART,TSTOP",status); if (ISDC_OK!=status) { RILlogMessage(NULL,Warning_2, "(WriteLC) Problems copying standard keywords " "from the SWG! status=%d",status); RILlogMessage(NULL,Log_2, "(WriteLC) Resetting status to ISDC_OK."); status = ISDC_OK; } if(chatter > J_CHATTY_VERBOSE){ status = CommonStampObject(dalPtr,"Wrote lightcurve data",status); } if (status != ISDC_OK) { RILlogMessage(NULL,Error_2, "Problem stamping lightcurve! status=%d", status); } status = DAL3GENindexUpdate(dalPtr,theSWG,status); if (status != ISDC_OK) { RILlogMessage(NULL,Error_2, "Error updating lightcurve index! status=%d", status); } } /* end of loop over channels */ } /* end of loop over sources */ if (rateBuff != NULL) { DALfreeDataBuffer(rateBuff,ISDC_OK); } if (errBuff != NULL) { DALfreeDataBuffer(errBuff, ISDC_OK); } return(status); } /***************************************************************** docbegin: * Name of source file: j_src_wcs_rsti.c * Copy of j_isf_wcs_rsti.c SL/021029 * Version of source file: 1.5.0 * Parent component: j_src_work * Programmer: Niels J. Westergaard * Affiliation: Danish Space Research Institute * Contact address: Juliane Maries Vej 30 * DK-2100 Copenhagen, Denmark * Phone: +45 35325705 FAX: +45 35362475 * njw@dsri.dk * Purpose: Transform source position from WCS, i.e. RA and DEC * coordinates to position in RSTI * Origin date: 020813 * Update history: 0.0.0 020813 * 1.4.2 020813 * 1.5.0 020829 Fluxes now derived in all energy bands * Type of element: Function * Part of package: j_src_spec/lc * Name: j_src_wcs_rsti * Calls: * Returns: * Required components: DAL, PIL, RIL, DAL3GEN docend: Various remarks: Flow of program: Error codes: Basic offset: J_ERROR_CODE_START + J_SRC_SPEC_ERR First RIL code : ##100## *****************************************************************/ int j_src_wcs_rsti( Instrument jemxNum, /* JEMX unit number */ float RA_SCX, /* RA of spacecraft X */ float DEC_SCX, /* DEC of spacecraft X */ float RA_SCZ, /* RA of spacecraft Z */ float DEC_SCZ, /* DEC of spacecraft Z */ float RA_SRC, /* RA of source */ float DEC_SRC, /* DEC of source */ float *cosXjmx, /* Direction cosine of X */ float *cosYjmx, /* Direction cosine of Y */ float *cosZjmx, /* Direction cosine of Z */ float *xRSTI, /* (return) X position in RSTI */ float *yRSTI, /* (return) Y position in RSTI */ int chatter, /* Monitoring output level */ int status ) /* Fault condition flag */ { int j; float yPos; float zPos; float yPosMm; float zPosMm; double Omega[3][3]; double s_sc[3]; /* Source vector in satellite coordinates */ double s_eq[3]; /* Source vector in WCS (Equatorial) */ /* * Get the source vector in WCS */ s_eq[0] = cos(RA_SRC*DEGRAD) * cos(DEC_SRC*DEGRAD); s_eq[1] = sin(RA_SRC*DEGRAD) * cos(DEC_SRC*DEGRAD); s_eq[2] = sin(DEC_SRC*DEGRAD); /* * Construct transposed coordinate transformation matrix */ Omega[0][0] = cos(RA_SCX*DEGRAD) * cos(DEC_SCX*DEGRAD); Omega[0][1] = sin(RA_SCX*DEGRAD) * cos(DEC_SCX*DEGRAD); Omega[0][2] = sin(DEC_SCX*DEGRAD); Omega[2][0] = cos(RA_SCZ*DEGRAD) * cos(DEC_SCZ*DEGRAD); Omega[2][1] = sin(RA_SCZ*DEGRAD) * cos(DEC_SCZ*DEGRAD); Omega[2][2] = sin(DEC_SCZ*DEGRAD); /* * Get Y-column as a cross product to Z-col and X-col: */ j_src_crossprod( Omega[2], Omega[0], Omega[1] ); if( chatter > 3 ) { for( j = 0; j < 3; j++ ) { RILlogMessage( NULL, Log_0, "j_src_wcs_rsti: Omega %d %f %f %f", j, Omega[j][0], Omega[j][1], Omega[j][2]); } } /* * Get source vector in S/C coordinates */ matvMult( Omega, s_eq, s_sc ); *cosXjmx = s_sc[0]; *cosYjmx = s_sc[1]; *cosZjmx = s_sc[2]; yPosMm = s_sc[1] * 3401. / fabs(s_sc[0]); zPosMm = s_sc[2] * 3401. / fabs(s_sc[0]); if( jemxNum == JMX2 ) { /* 180 deg rotation */ yPosMm = -yPosMm; zPosMm = -zPosMm; } zPos = zPosMm / (sqrt(3.0) * 1.65) + 153; yPos = 0.5*(yPosMm - zPosMm / sqrt(3.0)) / 1.65 + 153; *xRSTI = yPos; *yRSTI = zPos; return( status ); } /***************************************************************** docbegin: * Name of source file: /home/njw/jsim/src/matvMult.c * Version of source file: 1.5.0 * Parent component: * Programmer: Niels J. Westergaard * Affiliation: Danish Space Research Institute * Contact address: Juliane Maries Vej 30 * DK-2100 Copenhagen, Denmark * Phone: +45 35325705 FAX: +45 35362475 * njw@dsri.dk * Purpose: Multiply 3x3 matrix with 3 vector * Origin date: 990113 * Update history: * 1.00 001004 New component * 1.1.0 001108 Now flux determination * 1.1.1 001110 Small bug fix * 1.2.0 010601 Update for consolidation * 1.2.1 010717 Parameter "findRes" included * 1.3.0 011227 New unit test implemented * 1.3.2 020322 Y/ZPOS columns removed. Ghost peaks elim. * 1.3.3 020503 Stamp comments removed * 1.4.0 020507 Greyfilter correction implemented * 1.4.1 020610 Changed chatty to chatter. Removed unused var.s * 1.4.2 020627 Initialize all variables in *main.c and *work.c * 1.5.0 020829 Fluxes now derived in all energy bands * Type of element: General function * Part of package: * Name: * Calls: * Returns: * Required components: None docend: *****************************************************************/ void matvMult(double a[3][3], double b[3], double c[3]) { int i, j; double sum; for(i=0;i<3;i++){ sum = 0.0; for(j=0;j<3;j++) sum += a[i][j] * b[j]; c[i] = sum; } } /***************************************************************** docbegin: * Name of source file: j_src_crossprod.c * ( Copy of j_isf_crossprod.c SL/021028) * Version of source file: 1.5.0 * Parent component: * Programmer (j_isf_crossprod.c): Niels J. Westergaard * Affiliation: Danish Space Research Institute * Contact address: Juliane Maries Vej 30 * DK-2100 Copenhagen, Denmark * Phone: +45 35325705 FAX: +45 35362475 * njw@dsri.dk * Purpose: Find vectorial cross product of two * 3 element (double) vectors * Origin date: 990531 * Update history: 1.0 021028 Copy of j_isf_crossprod * * Type of element: Lowest level routine * Calls: double pointer - vector A * double pointer - vector B * Returns: double pointer - vector C = A X B * Required components: None docend: *****************************************************************/ void j_src_crossprod( double *a, double *b, double *c ) { c[0] = a[1] * b[2] - a[2] * b[1]; c[1] = a[2] * b[0] - a[0] * b[2]; c[2] = a[0] * b[1] - a[1] * b[0]; return; } /***************************************************************** docbegin: * Name of source file: j_src_get_pointing.c * Copy of j_isf_get_pointing.c SL/021029 * Version of source file: 1.5.0 * Parent component: None * Programmer: Niels J. Westergaard * Affiliation: Danish Space Research Institute * Contact address: Juliane Maries Vej 30 * DK-2100 Copenhagen, Denmark * Phone: +45 35325705 FAX: +45 35362475 * njw@dsri.dk * Purpose: Get INTEGRAL attitude either from OSIM-PDEF * or from DAL3AUXgetPointing * Origin date: 001025 * Update history: 021029: Copied from j_isf_get_pointing * Type of element: Function * Part of package: j_src * Name: j_src_get_pointing * Calls: * Returns: * Required components: DAL, PIL, RIL, DAL3GEN docend: Various remarks: Flow of program: *****************************************************************/ #include int j_src_get_pointing( dal_element *inSWGptr, /* pointer to SWG */ Instrument jemxNum, /* JEMX identifier */ float *RA_INST_X, /* RA of Instr. X-axis [deg] */ float *DEC_INST_X, /* DEC of Instr. X-axis [deg] */ float *RA_INST_Z, /* RA of Instr. Z-axis [deg] */ float *DEC_INST_Z, /* DEC of Instr. Z-axis [deg] */ int chatter, /* Level of debugging output */ int status) { char unit[30]; char comment[80]; int *SWGpointing = 0; int PointingMode = 0; int NumPoint = 0; int *NumIntervals = 0; double Xtol = 0.0; double Ztol = 0.0; double (*time_start)[DAL3AUX_ATT_GTI_SIZE]; double (*time_stop )[DAL3AUX_ATT_GTI_SIZE]; double tstart = 0.0; double tstop = 0.0; double IJDtime = 0.0; /* Time for which conversion is requested */ double RAX_ATTR = 0.0; double DECX_ATTR = 0.0; double RAZ_ATTR = 0.0; double DECZ_ATTR = 0.0; double RA_SCX_INST = 0.0; double DEC_SCX_INST = 0.0; double RA_SCZ_INST = 0.0; double DEC_SCZ_INST = 0.0; double RA_SCX = 0.0; double DEC_SCX = 0.0; double RA_SCZ = 0.0; double DEC_SCZ = 0.0; double *RA; double *DEC; double *ZRA; double *ZDEC; double *ExpTime; AUXDATA_type AuxType; PointingMode = DAL3AUX_POINTING_MODE; AuxType = DAL3AUX_ANY; Xtol = 0.5; Ztol = 0.9; status = DAL3AUXgetPointing( inSWGptr, AuxType, PointingMode, Xtol, Ztol, &NumPoint, (void **) (&SWGpointing), &RA, &DEC, &ZRA, &ZDEC, &ExpTime, &NumIntervals, &time_start, &time_stop, status); if( status == ISDC_OK && NumPoint > 0 ) { /* If good values, use them */ if ( NumIntervals[0] > 1) { RILlogMessage( NULL, Warning_3, "j_src_get_pointing: We have a problem: " "%d intervals within the pointing! " "Using first value.", *NumIntervals); } RA_SCX = RA[0]; DEC_SCX = DEC[0]; RA_SCZ = ZRA[0]; DEC_SCZ = ZDEC[0]; IJDtime = 0.5*(time_start[0][0] + time_stop[0][0]); } else { /* If not, then use the SWG values */ if( chatter > J_CHATTY_NORMAL ) RILlogMessage( NULL, Log_0, "j_src_get_pointing: Get pointing from SWG header"); status = ISDC_OK; /* Required to make functions work */ status = DALattributeGetReal( inSWGptr, "RA_SCX", &RAX_ATTR, unit, comment, status); status = DALattributeGetReal( inSWGptr, "DEC_SCX", &DECX_ATTR, unit, comment, status); status = DALattributeGetReal( inSWGptr, "RA_SCZ", &RAZ_ATTR, unit, comment, status); status = DALattributeGetReal( inSWGptr, "DEC_SCZ", &DECZ_ATTR, unit, comment, status); status = DALattributeGetReal( inSWGptr, "TSTART", &tstart, unit, comment, status); status = DALattributeGetReal( inSWGptr, "TSTOP", &tstop, unit, comment, status); if( status != ISDC_OK ) return( status ); RA_SCX = RAX_ATTR; DEC_SCX = DECX_ATTR; RA_SCZ = RAZ_ATTR; DEC_SCZ = DECZ_ATTR; IJDtime = 0.5*(tstart + tstop); } /* * Apply the instrument mis-alignment matrix */ status = DAL3AUXcalcInstrumentAttitude( RA_SCX, DEC_SCX, RA_SCZ, DEC_SCZ, IJDtime, jemxNum, &RA_SCX_INST, &DEC_SCX_INST, &RA_SCZ_INST, &DEC_SCZ_INST, status ); if( status != ISDC_OK ) return( status ); *RA_INST_X = (float) RA_SCX_INST; *DEC_INST_X = (float) DEC_SCX_INST; *RA_INST_Z = (float) RA_SCZ_INST; *DEC_INST_Z = (float) DEC_SCZ_INST; return( status ); } /************************************************************************ * * j_src_randXY v1.0 23/11/2002 * * * Source file: j_src_lc/spectra.c * File version : 3.2 * Function name j_src_randXY * Function version : 1.0 * Parent component: j_src_work * Developer: Stefan Larsson * Contact Address: Stockholm Observatory * SCFAB * SE-106 91 Stockholm * Phone: +46 8-5537 8543 FAX: +46 8-5537 8510 * stefan@astro.su.se * Purpose: * * Comment: * * Modification history: *------------------------------------------------------------------------- * * PARAMETERS: * * * *************************************************************************/ int j_src_randXY( float *x, float *y, double radiusLimit, int chatter, int status) { double radius = 0.0; *x = (drand48()-0.5)*radiusLimit*2.0; *x = floor(*x + 0.5); *y = (drand48()-0.5)*radiusLimit*2.0; *y = floor(*y + 0.5); radius = sqrt((*x) * (*x) + (*y) * (*y)); do { *x = (drand48()-0.5)*radiusLimit*2.0; *x = floor(*x + 0.5); *y = (drand48()-0.5)*radiusLimit*2.0; *y = floor(*y + 0.5); radius = sqrt((*x) * (*x) + (*y) * (*y)); } while(radius > radiusLimit); /* RILlogMessage( NULL, Log_0, "j_src_randXY: %f %f", *x, *y); */ return status; } /************************************************************************ * * j_src_openfraction v1.0 29/11/2002 * * * Source file: j_src_lc/spectra.c * File version : 3.2 * Function name j_src_openfraction * Function version : 1.0 * Parent component: j_src_work * Children: * Developer: Stefan Larsson * Contact Address: Stockholm Observatory * SCFAB * SE-106 91 Stockholm * Phone: +46 8-5537 8543 FAX: +46 8-5537 8510 * stefan@astro.su.se * Purpose: Compute a precise value of the mask open fraction * as seen from a particular sky direction. * Direction is given by the projected coordinates * sourceX, sourceY (mm). * * Comment: * * Modification history: *------------------------------------------------------------------------- * * PARAMETERS: * * (maskX,maskY) = Coordinates as projected onto the mask. * * (detX,detY) = Coordinates on the detector. * * *************************************************************************/ #include int j_src_openfraction( short mask[J_DIM_MASK][J_DIM_MASK], double sourceX, double sourceY, double *openArea, double *closedArea, double holeEffRadius, double radiusLimit, int precisionLevel, int chatty, /* Level of debugging output */ int status) /* Status flag */ { int ix = 0; int iy = 0; double holeEffArea = 0.0; double usedArea = 0.0; double detArea = 0.0; double areaRatio = 0.0; double holeFraction = 0.0; double radiusInner = 0.0; double radius = 0.0; double maskX = 0.0; double maskY = 0.0; double detX = 0.0; double detY = 0.0; /*********************************************************************** Loop over mask elements. If the element is fully inside the detector area add its contribution to openArea, if it outside ignore it. For elements on the edge the part inside the edge is estimated and added. ***********************************************************************/ *openArea = 0.0; *closedArea = 0.0; holeEffArea = J_COR_PI*holeEffRadius*holeEffRadius; radiusInner = radiusLimit - holeEffRadius; for ( ix=0 ; ix< 199 ; ix++){ for ( iy=0 ; iy< 199 ; iy++){ status = j_mask_findxy(ix,iy,&maskX,&maskY,chatty,status); detX = maskX - sourceX; detY = maskY - sourceY; radius = sqrt(detX*detX + detY*detY); if( mask[ix][iy] == 6) { if(radius < radiusInner) { *openArea = *openArea + holeEffArea; } else if( radius >= radiusInner && (radius <= radiusLimit+holeEffRadius)) { holeFraction = (radius-radiusInner)/(2.0*holeEffRadius); *openArea = *openArea + holeEffArea*holeFraction; } } else if( mask[ix][iy] == 0) { if(radius < radiusInner) { *closedArea = *closedArea + holeEffArea; } else if( radius >= radiusInner && (radius <= radiusLimit+holeEffRadius)) { holeFraction = (radius-radiusInner)/(2.0*holeEffRadius); *closedArea = *closedArea + holeEffArea*holeFraction; } } } } detArea = J_COR_PI*radiusLimit*radiusLimit; usedArea = *openArea + *closedArea; if( chatty >= J_CHATTY_VERBOSE ){ RILlogMessage(NULL,Log_0, "j_src_openfraction: openArea = %f", *openArea); RILlogMessage(NULL,Log_0, "j_src_openfraction: closedArea = %f", *closedArea); if(detArea > J_SRC_ACCURACY) { areaRatio = usedArea/detArea; RILlogMessage(NULL,Log_0, "j_src_openfraction: (open+closed area)/(Detector area) = %f", areaRatio); } } return status; } /********************************************************************* * * j_src_dete_index v1.0 28/09/2003 * * * Source file: j_src_lc/spectra.c * File version : 3.2 * Function name j_src_dete_index * Function version : 1.0 * Parent component: j_src_work * Developer: Stefan Larsson * Contact Address: Stockholm Observatory * SCFAB * SE-106 91 Stockholm * Phone: +46 8-5537 8543 FAX: +46 8-5537 8510 * stefan@astro.su.se * Purpose: From detector coordinate (X,Y) find the * corresponding index number (=uncorrected coord.). * * Comment: * * Modification history: *------------------------------------------------------------------------- * * PARAMETERS: * * * *************************************************************************/ int j_src_dete_index(double posX0, double posY0, float detPixLLX[J_NUM_X_PIXELS][J_NUM_Y_PIXELS], float detPixLLY[J_NUM_X_PIXELS][J_NUM_Y_PIXELS], float detCorX[J_NUM_X_PIXELS][J_NUM_Y_PIXELS], float detCorY[J_NUM_X_PIXELS][J_NUM_Y_PIXELS], long *ix, long *jy, int chatty, int status) { int ixt = 0; int iyt = 0; int i = 0; float x = 0.0; float y = 0.0; float dx = 0.0; float dy = 0.0; float posX = 0.0; float posY = 0.0; ixt = (int)(127.5 + posX0); iyt = (int)(127.5 + posY0); posX = (float) posX0; posY = (float) posY0; /* if(posX < 0) { ixt = -(int)(-posX+0.5); }else{ ixt = (int)(posX+0.5); } if(posY < 0) { iyt = -(int)(-posY+0.5); }else{ iyt = (int)(posY+0.5); } */ if(ixt < 0 || ixt >= J_NUM_X_PIXELS){ return(status); } if(iyt < 0 || iyt >= J_NUM_Y_PIXELS){ return(status); } x = detCorX[ixt][iyt]; y = detCorY[ixt][iyt]; dx = posX - x; dy = posY - y; for( i=0; i < 12; i++ ) { if( fabs(dx) < 0.4 && fabs(dy) < 0.4){ *ix = (long) ixt; *jy = (long) iyt; return(status); } if(fabs(dx) > fabs(dy)){ if(dx>0){ ixt = ixt + 1; }else{ ixt = ixt - 1; } }else{ if(dy>0){ iyt = iyt + 1; }else{ iyt = iyt - 1; } } if(ixt < 0 || ixt >= J_NUM_X_PIXELS){ return(status); } if(iyt < 0 || iyt >= J_NUM_Y_PIXELS){ return(status); } x = detCorX[ixt][iyt]; y = detCorY[ixt][iyt]; dx = posX - x; dy = posY - y; } if( chatty >= J_CHATTY_VERBOSE ){ RILlogMessage(NULL,Log_0, "j_src_dete_index: eventX,eventY: %f %f ix,iy: %d %d x,y: %f %f", posX,posY,ixt,iyt,x,y); } return(status); } /************************************************************************ * * j_src_get_bit v1.0 2/10/2003 * * * Source file: j_src_lc/spectra.c * File version : 3.5 * Function name j_src_get_bit * Function version : 1.0 * Parent component: j_src_work * Developer: Stefan Larsson * Contact Address: Stockholm Observatory * SCFAB * SE-106 91 Stockholm * Phone: +46 8-5537 8543 FAX: +46 8-5537 8510 * stefan@astro.su.se * Purpose: Return the value of a specific bit in an * unsigned short integer, x. * ibit = The position of the bit to read * Counting from lowest bit (no. 1). * *n is set to 1 or 0 according to the bit value. * * Comment: * * Modification history: *------------------------------------------------------------------------- * * PARAMETERS: * * * *************************************************************************/ int j_src_get_bit(unsigned short x, int ibit, unsigned short *n, int status) { *n = (x >> (ibit)) & ~(~0 << 1); return status; } /************************************************************************ * * j_src_status_bit v1.0 31/10/2004 * * * Source file: j_src_lc/spectra.c * File version : 4.1.1 * Function name j_src_status_bit * Function version : 1.0 * Parent component: j_src_pif_create20 * Developer: Stefan Larsson * Contact Address: Stockholm Observatory * SCFAB * SE-106 91 Stockholm * Phone: +46 8-5537 8543 FAX: +46 8-5537 8510 * stefan@astro.su.se * Purpose: Given a detector STATUS definition value, * statusByte, (always a power of 2) compute how * many steps are needed to shift the corresponding * bit to the first bit position. * This is used when reading off this * particular bit from the status values * in the detector pixel map. * * Comment: * * Modification history: *------------------------------------------------------------------------- * * PARAMETERS: * * * *************************************************************************/ int j_src_status_bit(int statusByte, int *ibit, int status) { int stepByte = 0; *ibit = 0; stepByte = statusByte; do { stepByte = stepByte/2; *ibit = *ibit + 1; } while(stepByte > 1); return status; } /************************************************************************ * * j_src_correlation v1.0 08/11/2003 * * File name: j_src_lc/spectra.c * Version: 1.0 * Parent Component: * Developer: Stefan Larsson * Contact Address: Stockholm Observatory, Sweden * Purpose: Calculate the amount of overlap of the source * pixel illumination factors (pifs). * These overlaps can be used to correct fluxes for * the effect of these correlations in an iros like * procedure. * * * Variables: * * pifjIniOpen[i][j] = Sum of all pixel illumination factors * (pif) from source j in the open elements * used to extract source i. * * pifjIniClosed[i][j] = Sum of all pixel illumination factors * (pif) from source j in the closed elements * used to extract source i. *****************************************************************************/ int j_src_correlation(long nSources, float *pif, int iPifEnergy, float openSrcCut[J_SRC_MAXSRC], float closedSrcCut[J_SRC_MAXSRC], double pifjIniOpen[J_SRC_MAXSRC][J_SRC_MAXSRC], double pifjIniClosed[J_SRC_MAXSRC][J_SRC_MAXSRC], int chatty, /* Level of debugging output */ int status) /* Status flag */ { long iPifOffset = 0L; long jPifOffset = 0L; long i = 0L; long iSource = 0L; long jSource = 0L; long nPixels = 0L; float pifi = 0.0; float pifj = 0.0; /* Initialize arrays to zero */ for ( iSource=0L ; iSource0.0){ if(pifi>openSrcCut[iSource]){ pifjIniOpen[iSource][jSource] = pifjIniOpen[iSource][jSource] + (double) pifj; } if(pifi=0.0){ pifjIniClosed[iSource][jSource] = pifjIniClosed[iSource][jSource] + (double) pifj; } } } } } } if( chatty > J_CHATTY_NORMAL){ RILlogMessage(NULL, Log_0," Done pif overlap calculation"); } return status; } /************************************************************************ * * j_src_mean v1.0 2003-11-10 * * File name: j_src_lc/spectra.c * Version: 1.0 * Parent Component: * Developer: Stefan Larsson * Contact Address: Stockholm Observatory, Sweden * Purpose: Compute the weighted mean of a set of values * with errors. * * * Variables: * *****************************************************************************/ int j_src_mean(long nPoints, double *dataValue, double *error, double *mean, double *meanError, int chatty, /* Level of debugging output */ int status) /* Status flag */ { long i = 0L; long zeroError = 0L; double *weights = NULL; double sumOfWeights = 0.0; *mean = 0.0; *meanError = 0.0; /* Allocate memmory for the weight data */ status = DALallocateDataBuffer( (void **)&weights, nPoints * sizeof(double), status ); /* Compute weights and sum of weights */ for ( i=0L ; i 0.0){ weights[i] = 1.0/(error[i]*error[i]); sumOfWeights = sumOfWeights + weights[i]; }else{ zeroError = zeroError + 1; } } /* Normalize the weights */ for ( i=0L ; i 0.0){ *meanError = 1.0/sqrt(sumOfWeights); }else{ *meanError = -1.0; status = J_SRC_WRONG_VALUE; } if (weights != NULL) { DALfreeDataBuffer(weights,ISDC_OK); } return status; } /************************************************************************ * * j_src_pifcut v1.0 2003-11-10 * * File name: j_src_lc/spectra.c * Version: 1.0 * Parent Component: * Developer: Stefan Larsson * Contact Address: Stockholm Observatory, Sweden * Purpose: Compute PIF cut value (lower limit of PIF used to * select open area pixels). * * * Variables: * *****************************************************************************/ int j_src_pifcut(float sortedPif[J_NUM_X_PIXELS*J_NUM_X_PIXELS], long nPoints, double srcRatePerPixel, double bkgRatePerPixel, double *pifCut, double *signalToNoiseMax, int chatty, /* Level of debugging output */ int status) /* Status flag */ { long i = 0L; long imax = 0L; long zeroError = 0L; long in = 99L; double cumulativeBkg[100]; double cumulativeSrc[100]; double signalToNoise = 0.0; double pifBin = 0.99; double noise = 0.0; for ( i=0 ; i<99 ; i++){ cumulativeBkg[i] = 0.0; cumulativeSrc[i] = 0.0; } for ( i=0 ; i0 ; i--){ noise = sqrt(cumulativeSrc[i] * cumulativeSrc[i] + cumulativeBkg[i] * cumulativeBkg[i]); if(noise > 0.0){ signalToNoise = cumulativeSrc[i]/noise; }else{ signalToNoise = 0.0; } if(signalToNoise > *signalToNoiseMax){ *signalToNoiseMax = signalToNoise; imax = i; RILlogMessage(NULL, Log_0," pifcut: imax %d", imax); } } *pifCut = (double)imax / ((double) 100); return status; } /************************************************************************ * * j_src_pif_interpol v1.0 2003-11-27 * * File name: j_src_lc/spectra.c * Version: 1.0 * Parent Component: * Developer: Stefan Larsson * Contact Address: Stockholm Observatory, Sweden * Purpose: Interpolate the PIF values as function of energy * to energy pifInterpolEnergy. * Result returned in "*pifInterpol". * * * Variables: * iSource = Source index number (starting from 0) * * nSources = Number of soueces for which PIFs are stored in *pif. * * pifInterpolEnergy = Event energy (keV). Interpolate the PIFs to this * energy. * * ix,iy = Detector pixel index in X,Y directions. * * pifEnergy[i] = Energy (keV) at which PIF no. i is computed. * * *pif = Pointer to the PIFs. * * *pifInterpol = Interpolated pif-value at energy "pifEnergy". * *****************************************************************************/ int j_src_pif_interpol(long iSource, long nSources, float pifInterpolEnergy, long ix, long jy, float pifEnergy[J_SRC_PIF_MAX_ENERGIES], long nPifEnergies, float *pif, float *pifInterpol, int chatty, /* Level of debugging output */ int status) /* Status flag */ { long i = 0; long lowIndex = 0; long highIndex = 0; long offset = 0; float pifAtE[J_SRC_PIF_MAX_ENERGIES]; float deltaE = 0.0; for (i = 0L ; i= pifEnergy[nPifEnergies-1]){ *pifInterpol = pifAtE[nPifEnergies-1]; return status; } /* If we reach this point the event energy is inside the range of energies for which we have PIF maps. Then interpolate the PIFs to the event energy. */ /* Between which two PIFs is the event energy? */ lowIndex = 0; highIndex = nPifEnergies-1; for (i = 0L ; i pifEnergy[i]){ lowIndex = i; } if(pifInterpolEnergy < pifEnergy[nPifEnergies-1-i]){ highIndex = nPifEnergies-1-i; } } /* Interpolate */ deltaE = pifEnergy[highIndex] - pifEnergy[lowIndex]; if(deltaE > 0.0){ *pifInterpol = pifAtE[lowIndex] + (pifAtE[highIndex]-pifAtE[lowIndex])* (pifInterpolEnergy-pifEnergy[lowIndex])/deltaE; } else{ *pifInterpol = pifAtE[lowIndex]; } return status; } /************************************************************************ * * j_src_factors_interpol v1.0 2003-11-27 * * File name: j_src_lc/spectra.c * Version: 1.0 * Parent Component: * Developer: Cecilia Kozma * Contact Address: Stockholm Observatory, Sweden * * Purpose: To interpolate, for all bins: * openAreaChan * closedAreaChan * effOpenAreaChan * leakageFrOpenChan * leakageToClosedChan * * from the channels given in pifChannel and * the values (for a given source, iSource) at * those channels as given in * openAreaEnergy * closedAreaEnergy * effOpenAreaEnergy * leakageFrOpenEnergy * leakageToClosedEnergy * * Variables: * iSource = Source index number (starting from 0) * * pifChannel = Channel numbers for which the data in * openAreaEnergy, closedAreaEnergy,effOpenAreaEnergy * leakageFrOpenEnergy,leakageToClosedEnergy * are given * * Modified * * 031207 (SL): Integer devision changed to double. (i-pC1))/(pC2-pC1) * ipc loop increased by one. *****************************************************************************/ int j_src_factors_interpol( long iSource, int pifChannel[J_SRC_PIF_MAX_ENERGIES], double openAreaEnergy[J_SRC_MAXSRC][J_SRC_PIF_MAX_ENERGIES], double closedAreaEnergy[J_SRC_MAXSRC][J_SRC_PIF_MAX_ENERGIES], double effOpenAreaEnergy[J_SRC_MAXSRC][J_SRC_PIF_MAX_ENERGIES], double leakageFrOpenEnergy[J_SRC_MAXSRC][J_SRC_PIF_MAX_ENERGIES], double leakageToClosedEnergy[J_SRC_MAXSRC][J_SRC_PIF_MAX_ENERGIES], long nPifEnergies, double openAreaChan[J_NUM_SCI_BINS], double closedAreaChan[J_NUM_SCI_BINS], double effOpenAreaChan[J_NUM_SCI_BINS], double leakageFrOpenChan[J_NUM_SCI_BINS], double leakageToClosedChan[J_NUM_SCI_BINS], int chatty, /* Level of debugging output */ int status) /* Status flag */ { long i = 0; int pC1 = 0; int pC2 = 0; int ipc = 0; double doAE = 0.0; double dcAE = 0.0; double deOAC = 0.0; double dlFOE = 0.0; double dlTCE = 0.0; double pCFrac = 0.0; /* For all channels below the lowest pifChannel (i.e. pifChannel[0]), assume constant values equal to the value at pifChannel[0]. */ for (i=0; i< pifChannel[0]; i++){ openAreaChan[i] = openAreaEnergy[iSource][0]; closedAreaChan[i] = closedAreaEnergy[iSource][0]; effOpenAreaChan[i] = effOpenAreaEnergy[iSource][0]; leakageFrOpenChan[i] = leakageFrOpenEnergy[iSource][0]; leakageToClosedChan[i] = leakageToClosedEnergy[iSource][0]; } /* For all channels above the highest pifChannel (i.e. pifChannel[nPifEnergies-1]), assume constant values equal to the value at pifChannel[nPifEnergies-1]. */ for (i=pifChannel[nPifEnergies-1]; i< J_NUM_SCI_BINS; i++){ openAreaChan[i] = openAreaEnergy[iSource][nPifEnergies-1]; closedAreaChan[i] = closedAreaEnergy[iSource][nPifEnergies-1]; effOpenAreaChan[i] = effOpenAreaEnergy[iSource][nPifEnergies-1]; leakageFrOpenChan[i] = leakageFrOpenEnergy[iSource][nPifEnergies-1]; leakageToClosedChan[i] = leakageToClosedEnergy[iSource][nPifEnergies-1]; } /* For all the remaining channels between pifChannel[0] and pifChannel[nPifEnergies-1], interpolate. */ for (ipc=1 ; ipc < nPifEnergies; ipc++){ pC1=pifChannel[ipc-1]; pC2=pifChannel[ipc]; doAE = openAreaEnergy[iSource][ipc] - openAreaEnergy[iSource][ipc-1]; dcAE = closedAreaEnergy[iSource][ipc] - closedAreaEnergy[iSource][ipc-1]; deOAC = effOpenAreaEnergy[iSource][ipc] - effOpenAreaEnergy[iSource][ipc-1]; dlFOE = leakageFrOpenEnergy[iSource][ipc] - leakageFrOpenEnergy[iSource][ipc-1]; dlTCE = leakageToClosedEnergy[iSource][ipc] - leakageToClosedEnergy[iSource][ipc-1]; for (i=pC1 ; i= pifChannel[nPifEnergies-1]){ *pifCut = srcCutEnergy[iSource][nPifEnergies-1]; return status; } for (i=0; i< nPifEnergies; i++){ if(Pi == pifChannel[i]){ *pifCut = srcCutEnergy[iSource][i]; return status; } if(Pi <= pifChannel[i]){ pC1 = pifChannel[i-1]; pC2 = pifChannel[i]; pCFrac=((float)(Pi-pC1))/((float)(pC2-pC1)); doAE = srcCutEnergy[iSource][i] - srcCutEnergy[iSource][i-1]; *pifCut = pCFrac*doAE + srcCutEnergy[iSource][i-1]; return status; } } /* For all channels below the lowest pifChannel (i.e. pifChannel[0]), assume constant values equal to the value at pifChannel[0]. */ return status; } /************************************************************************ * * j_src_pif_create20 v1.0 2004-02-21 * * File name: j_src_lc/spectra.c * Version: 1.0 * Parent Component: * Developer: Stefan Larsson * Contact Address: Stockholm Observatory, Sweden * Purpose: Given a source position in the field od view * create a PIF map. * PIF = Pixel Illumination Fraction, is the * fractional of a pixel which is illuminated * by the source. * In this version (precisionLevel 20) * the area of individul pixels are taken into * account when the illumination is calculated * but NOT when the redistribution due to * detector resolution is computrd. * Variables: * iSource = Source index number (starting from 0) * * nSources = Number of soueces for which PIFs are stored in *pif. * * pifInterpolEnergy = Event energy (keV). Interpolate the PIFs to this * energy. * * ix,iy = Detector pixel index in X,Y directions. * * pifEnergy[i] = Energy (keV) at which PIF no. i is computed. * * *pif = Pointer to the PIFs. * * *pifInterpol = Interpolated pif-value at energy "pifEnergy". * *****************************************************************************/ int j_src_pif_create20(long iSource, long nSources, double srcY, double srcZ, int isCrab, short mask[J_DIM_MASK][J_DIM_MASK], double detMaskDist, double longsph, double shortsph, unsigned char balk[J_DIM_BALK][J_DIM_BALK], double collimatorXBot[J_SRC_COLL_SIZE][J_SRC_COLL_SIZE], double collimatorYBot[J_SRC_COLL_SIZE][J_SRC_COLL_SIZE], double collimatorXTop[J_SRC_COLL_SIZE][J_SRC_COLL_SIZE], double collimatorYTop[J_SRC_COLL_SIZE][J_SRC_COLL_SIZE], int collimator[J_SRC_COLL_SIZE][J_SRC_COLL_SIZE], double collHeight, unsigned short detMap[J_NUM_X_PIXELS][J_NUM_Y_PIXELS], float detCorX[J_NUM_X_PIXELS][J_NUM_Y_PIXELS], float detCorY[J_NUM_X_PIXELS][J_NUM_Y_PIXELS], double posResInterpol[J_NUM_SCI_BINS], double detDepth, double detDepthMax, int skipHotSpot, int skipNearDeadAnode, int maskRimCut, double radiusLimit, int iChan, float *subPif, float pifWork[J_NUM_X_PIXELS][J_NUM_Y_PIXELS], int nSubPifPix, float pifInterpolEnergy, float pifEnergy[J_SRC_PIF_MAX_ENERGIES], float *pifInterpol, double radMask, int chatty, int status) { int nstep = 4; int i = 0; int j = 0; int offset = 0; long midEventDistr = 50; float anstep = 4.0; double detDepthX; double detDepthY; double detDepthZ; double radius = 0.0; double xstep = 0.0; double ystep = 0.0; double effCollHeight = 0.0; double a = 0.0; float eventDistr[J_NUM_EVENT_PIXELS][J_NUM_EVENT_PIXELS]; float PSFStep = 0.1; long ix = 0; long jy = 0; long ii = 0; long jj = 0; int eventPi = 0; int iPixX = 0; int iPixY = 0; int midSubPifPix = 0; float weight = 0.0; unsigned short bitValue = 0; int bitStepBadAnode = 0; int statusBadAnode = 0; int bitStepBadNeighbour = 0; int statusBadNeighbour = 0; int bitStepHotspot = 0; int statusHotspot = 0; int bitStepCalSource = 0; int statusCalSource = 0; int icount = 0; /* SL Test */ nstep = J_SRC_SUBPIF_NSTEP; anstep = (double) nstep; midSubPifPix = J_SRC_SUBPIF_SIZE/2; for ( i=0 ; i 0.0001 && weight < 1.5){ effCollHeight = collHeight; status = j_src_through_coll(xstep, ystep, srcY, srcZ, collimatorXBot, collimatorYBot, collimatorXTop, collimatorYTop, collimator, detMaskDist, effCollHeight, &weight, chatty, status); } /* If weight is positive the line of sight is open and we can go on to add the the distribution function centered on the present pixel (ix,jy). iPixX,iPixY runs over the surrounding pixels. */ if(weight > 0.0001 && weight < 1.5){ a = a + weight; for ( iPixX=-midSubPifPix ; iPixX 0 && ii < J_NUM_X_PIXELS){ if(jj > 0 && jj < J_NUM_Y_PIXELS){ pifWork[ii][jj] = pifWork[ii][jj] + *(subPif+(offset)); } } } } } } } } } } /* We now exclude those regions of the pif map which we dont want to use by setting pifWork = -1. First bad anodes etc. and then also regions that are outside of the projected mask rim. We dont want to use them for background either. */ /* First find out the number of bits to step for each status flag used */ statusBadAnode = J_COR_BAD_ANODE; status = j_src_status_bit( statusBadAnode, &bitStepBadAnode, status); statusBadNeighbour = J_COR_BAD_NEIGHBOUR; status = j_src_status_bit( statusBadNeighbour, &bitStepBadNeighbour, status); statusHotspot = J_COR_HOTSPOT; status = j_src_status_bit( statusHotspot, &bitStepHotspot, status); statusCalSource = J_COR_BAD_CAL_SOURCE; status = j_src_status_bit( statusCalSource, &bitStepCalSource, status); icount = 0; for ( ii=0 ; ii 0){ pifWork[ii][jj] = -1.0; }else{ /* Calibration source position */ status = j_src_get_bit(detMap[ii][jj], bitStepCalSource, &bitValue, status); if(bitValue > 0){ pifWork[ii][jj] = -1.0; } } /* Ignore pixels near dead anodes. */ if(skipNearDeadAnode > 0){ status = j_src_get_bit(detMap[ii][jj], bitStepBadNeighbour, &bitValue, status); if(bitValue > 0){ pifWork[ii][jj] = -1.0; } } /* Ignore Hot spot areas */ if(skipHotSpot > 0){ status = j_src_get_bit(detMap[ii][jj], bitStepHotspot, &bitValue, status); if(bitValue > 0){ pifWork[ii][jj] = -1.0; } } /* Ignore regions outside of the projected mask rim. */ if(maskRimCut > 0){ xstep = detCorX[ii][jj] + srcY; ystep = detCorY[ii][jj] + srcZ; radius = sqrt(xstep*xstep+ystep*ystep); if(radius > radMask) { icount = icount + 1; /* SL Test */ pifWork[ii][jj] = -1.0; } } } } if(chatty > J_CHATTY_VERBOSE){ RILlogMessage(NULL, Log_0, " No. pixels outside projected mask rim: %d", icount); } return status; } /************************************************************************ * * j_src_pif_create30 v1.0 2004-04-02 * * File name: j_src_lc/spectra.c * Version: 1.0 * Parent Component: * Developer: Stefan Larsson * Contact Address: Stockholm Observatory, Sweden * Purpose: Given a source position in the field od view * create a PIF map. * PIF = Pixel Illumination Fraction, is the * fractional of a pixel which is illuminated * by the source. * In this version (precisionLevel 20) * the area of individul pixels are taken into * account when the illumination is calculated * but NOT when the redistribution due to * detector resolution is computrd. * Variables: * iSource = Source index number (starting from 0) * * nSources = Number of soueces for which PIFs are stored in *pif. * * pifInterpolEnergy = Event energy (keV). Interpolate the PIFs to this * energy. * * ix,iy = Detector pixel index in X,Y directions. * * pifEnergy[i] = Energy (keV) at which PIF no. i is computed. * * *pif = Pointer to the PIFs. * * *pifInterpol = Interpolated pif-value at energy "pifEnergy". * *****************************************************************************/ int j_src_pif_create30(long iSource, long nSources, double srcY, double srcZ, int isCrab, short mask[J_DIM_MASK][J_DIM_MASK], double detMaskDist, double longsph, double shortsph, unsigned char balk[J_DIM_BALK][J_DIM_BALK], double collimatorXBot[J_SRC_COLL_SIZE][J_SRC_COLL_SIZE], double collimatorYBot[J_SRC_COLL_SIZE][J_SRC_COLL_SIZE], double collimatorXTop[J_SRC_COLL_SIZE][J_SRC_COLL_SIZE], double collimatorYTop[J_SRC_COLL_SIZE][J_SRC_COLL_SIZE], int collimator[J_SRC_COLL_SIZE][J_SRC_COLL_SIZE], double collHeight, unsigned short detMap[J_NUM_X_PIXELS][J_NUM_Y_PIXELS], float detCorX[J_NUM_X_PIXELS][J_NUM_Y_PIXELS], float detCorY[J_NUM_X_PIXELS][J_NUM_Y_PIXELS], double posResInterpol[J_NUM_SCI_BINS], double detDepth, double detDepthMax, float detPixArea[J_NUM_X_PIXELS][J_NUM_Y_PIXELS], float detPixLLX[J_NUM_X_PIXELS][J_NUM_Y_PIXELS], float detPixLLY[J_NUM_X_PIXELS][J_NUM_Y_PIXELS], int skipHotSpot, int skipNearDeadAnode, int maskRimCut, double radiusLimit, int iChan, float *subPif, float pifWork[J_NUM_X_PIXELS][J_NUM_Y_PIXELS], int nSubPifPix, float pifInterpolEnergy, float pifEnergy[J_SRC_PIF_MAX_ENERGIES], float *pifInterpol, double radMask, int chatty, int status) { int nstep = 4; int i = 0; int j = 0; int offset = 0; long midEventDistr = 50; float anstep = 4.0; double detDepthX; double detDepthY; double detDepthZ; double radius = 0.0; double xstep = 0.0; double ystep = 0.0; double effCollHeight = 0.0; double a = 0.0; double subPixArea = 0.0; double subPixelX = 0.0; double subPixelY = 0.0; float leftX[J_SRC_MAX_NUM_X_SUBPIXELS]; float leftY[J_SRC_MAX_NUM_X_SUBPIXELS]; float rightX[J_SRC_MAX_NUM_X_SUBPIXELS]; float rightY[J_SRC_MAX_NUM_X_SUBPIXELS]; float eventDistr[J_NUM_EVENT_PIXELS][J_NUM_EVENT_PIXELS]; float PSFStep = 0.1; long ix = 0; long jy = 0; long ii = 0; long jj = 0; int eventPi = 0; int iPixX = 0; int iPixY = 0; int midSubPifPix = 0; float weight = 0.0; unsigned short bitValue = 0; int bitStepBadAnode = 0; int statusBadAnode = 0; int bitStepBadNeighbour = 0; int statusBadNeighbour = 0; int bitStepHotspot = 0; int statusHotspot = 0; int bitStepCalSource = 0; int statusCalSource = 0; nstep = J_SRC_SUBPIF_NSTEP; anstep = (double) nstep; midSubPifPix = J_SRC_SUBPIF_SIZE/2; for ( i=0 ; i 0){ pifWork[ii][jj] = -1.0; }else{ /* Calibration source position */ status = j_src_get_bit(detMap[ii][jj], bitStepCalSource, &bitValue, status); if(bitValue > 0){ pifWork[ii][jj] = -1.0; } } /* Ignore pixels near dead anodes. */ if(skipNearDeadAnode > 0){ status = j_src_get_bit(detMap[ii][jj], bitStepBadNeighbour, &bitValue, status); if(bitValue > 0){ pifWork[ii][jj] = -1.0; } } /* Ignore Hot spot areas */ if(skipHotSpot > 0){ status = j_src_get_bit(detMap[ii][jj], bitStepHotspot, &bitValue, status); if(bitValue > 0){ pifWork[ii][jj] = -1.0; } } /* Ignore regions outside of the projected mask rim. */ if(maskRimCut > 0){ xstep = detCorX[ii][jj] + srcY; ystep = detCorY[ii][jj] + srcZ; radius = sqrt(xstep*xstep+ystep*ystep); if(radius > radMask) { pifWork[ii][jj] = -1.0; } } } } return status; } /***************************************************************** * * j_src_ext_crab v1.0 1/12/2003 * * Source file: j_src_lc/spectra.c * File version : 3.5.2 * Date: 2003/12/02 * Function name j_src_ext_crab * Function version : 1.0 * Parent component: j_src_work * Children: * Developer: Cecilia Kozma * Contact Address: Stockholm Observatory * SCFAB * SE-106 91 Stockholm * Phone: +46 8-5537 8536 FAX: +46 8-5537 8510 * cecilia@astro.su.se * Purpose: Given the response distribution function on * the detector (as stored in eventDistr) * for the Crab as a point source, calculate the * eventDistr for the Crab as an extended source. * * Origin date: 031201 * Update history: * * Error codes: See j_src_lc/spectra.txt (?) * * Introduced the following macros in j_src_lc.h : * * J_SRC_CRAB_SIZE = X and Y dim for extCrabSrc[][] * J_SRC_CRAB_STEP = Bin size, in mm, for extCrabSrc[][] * * * Variables : * * extCrabSrc = An array describing the probability of * emitting a photon from different positions * in the extended Crab source. * The values in this array is preliminary. * Each pixel should be proportional to the * intensity at that position * * midCrab = The coordinates in extCrabSrc[][] for which * the point source has been calculated giving * rise to eventDistr. * Now assumed to be the middle point. * ***********************************************************************/ #include int j_src_ext_crab( float PSFStep, float eventDistr[J_NUM_EVENT_PIXELS][J_NUM_EVENT_PIXELS], int chatty, int status) { long ix = 0; long iy = 0; long icx = 0; long icy = 0; long imx = 0; long imy = 0; long idx = 0; long idy = 0; int midCrab = J_SRC_CRAB_SIZE/2 ; /* First approximation, based on Chandra picture. Intensity variations have not been taken into account. Orientation on the sky ? */ float extCrabSrc[J_SRC_CRAB_SIZE][J_SRC_CRAB_SIZE] = { {0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.}, /* icx=0, icy=0-10 */ {0.,0.,0.,0.,0.,0.,1.,1.,1.,0.,0.}, /* icx=1, icy=0-10 */ {0.,0.,1.,1.,1.,1.,1.,1.,1.,0.,0.}, /* icx=2, icy=0-10 */ {0.,0.,1.,1.,1.,1.,1.,1.,1.,0.,0.}, /* icx=3, icy=0-10 */ {0.,1.,1.,1.,1.,1.,1.,1.,1.,1.,0.}, /* icx=4, icy=0-10 */ {0.,0.,1.,1.,1.,1.,1.,1.,1.,1.,0.}, /* icx=5, icy=0-10 */ {0.,0.,1.,1.,1.,1.,1.,1.,1.,1.,0.}, /* icx=6, icy=0-10 */ {0.,0.,1.,1.,1.,1.,1.,1.,1.,1.,0.}, /* icx=7, icy=0-10 */ {0.,0.,1.,0.,0.,1.,1.,1.,1.,0.,0.}, /* icx=8, icy=0-10 */ {0.,0.,0.,0.,0.,0.,1.,1.,1.,0.,0.}, /* icx=9, icy=0-10 */ {0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.} /* icx=10,icy=0-10 */ }; float eventDistrExt[J_NUM_EVENT_PIXELS][J_NUM_EVENT_PIXELS]; double sum = 0.0; /* Normalization of extCrabSrc */ sum = 0.0; for ( icx=0 ; icx= 0 && imx < J_NUM_EVENT_PIXELS) { if (imy >= 0 && imy < J_NUM_EVENT_PIXELS) { eventDistrExt[imx][imy]=eventDistrExt[imx][imy]+ eventDistr[ix][iy]*extCrabSrc[icx][icy]; } } } } } } sum = 0.0; for ( ix=0 ; ix J_SRC_ACCURACY){ for ( ix=0 ; ix int j_src_through_balk( double eventX, /* Event detector position in X */ double eventY, /* Event detector position in Y */ double sourceX, /* Source X-pos as projected on mask */ double sourceY, /* Source Y-pos as projected on mask */ double detMaskDist, /* Detector-mask distance */ double longsph, double shortsph, unsigned char balk[J_DIM_BALK][J_DIM_BALK], short *weightInt, /* Integer event weight */ int chatty, /* Level of debugging output */ int status) /* Status flag */ { int balkweight = 7; int last = 0; double xm = 0.0; double ym = 0.0; /* * Immediate return if called while executable is in error condition */ if( status != ISDC_OK ){ RILlogMessage(NULL, Error_2, "%d : Non-zero status value passed to j_src_through_balk",\ status); return status ; } xm = eventX + sourceX; /* CK question : Check if + or - */ ym = eventY + sourceY; /* CK question : Check if + or - */ /* balkweight = struchk(xm, ym, eventX, eventY, longsph, shortsph, balk, last);*/ status = struchk(xm, ym, eventX, eventY, detMaskDist, longsph, shortsph, balk, &balkweight, last, status); if (balkweight == 1){ /* The ray intersects the balk; closed */ *weightInt=-1; } else if (balkweight == 0) { /* The ray does not intersect the balk; open */ *weightInt=1; } else if (balkweight == 7) { /* The ray is outside the balk array */ *weightInt=7; } else { status = J_SRC_WRONG_VALUE; RILlogMessage(NULL, Error_2, "%d : Unknown value on balkweight", status); } return(status); } /*********************************************************** Routines from Niels Lund below Originally identical to m_strkdef.c from Niels Lund. Updated by CK 031210 ************************************************************/ /***************************************************************** * * struktu * * Source file: j_src_lc/spectra.c * File version : 3.5 * Date: 2003/12/11 * Function name struktu * Function version : 1.0 * Parent component: strukdef * Children: ring * bolt * bar * * Developer: Niels Lund * Contact Address: * Purpose: This routine sets up the array * balk[][], which describes the * mask support structure. * * Origin date: * Update history: * 2003/12/11 CK Changed the function definition. * Removed global parameters, and * included them in function call. * A status is returned. * Changed the name of the structure * array (struk[][]) to balk[][]. * * Error codes: See j_src_lc/spectra.txt * * RETURNING ONAX?? NOT USED ANYWARE!!! *****************************************************************/ /* void struktu(void) */ int struktu( double longspx[6][2], double longspy[6][2], double longspw, double longspw2, double shortspx[6][2], double shortspy[6][2], double shortspw, double shortspw2, double ringri[3], double ringro[3], double ringri2[3], double ringro2[3], double bolt1x[6], double bolt2x[6], double bolt3x[6], double bolt1y[6], double bolt2y[6], double bolt3y[6], double bolt1r, double bolt1s, double bolt2r, double bolt2s, double bolt3r, double bolt3s, double joint1x[6], double joint1y[6], double joint1r, double joint1r2, double joint2x[6], double joint2y[6], double joint2r, double joint2r2, double rx[4], double r_twist, unsigned char balk[J_DIM_BALK][J_DIM_BALK], int status) { int i = 0; int j = 0; int k = 0; int mark = 0; double endx[12][2], endy[12][2], w[12]; double rir[3], ror[3], onax; double xc[30], yc[30], r[30]; mark = 1; /* mark for wide shadow border */ ring(ringri2[0],ringro2[0],rx,r_twist,mark, balk); /* ring 1 shadow region (check at 21 mm) */ mark = 0; /* mark for narrow shadow border */ ring(ringri2[1],ringro2[1],rx,r_twist,mark,balk); /* ring 2 shadow region (check at 10 mm) */ ring(ringri2[2],ringro2[2],rx,r_twist,mark,balk); /* ring 3 shadow region (check at 10 mm) */ for (i=0; i<6; i++) { mark = 1; /* mark for wide shadow border */ bar(longspx[i], longspy[i], longspw2, rx, r_twist, mark, balk); bolt(bolt1x[i], bolt1y[i], bolt1s, rx, r_twist, mark,balk); bolt(bolt2x[i], bolt2y[i], bolt2s, rx, r_twist, mark,balk); mark = 0; /* mark for narrow shadow border */ bolt(bolt3x[i], bolt3y[i], bolt3s, rx, r_twist, mark,balk); bar(shortspx[i], shortspy[i], shortspw2, rx, r_twist, mark, balk); bolt(joint1x[i], joint1y[i], joint1r2, rx, r_twist, mark,balk); bolt(joint2x[i], joint2y[i], joint2r2, rx, r_twist,mark,balk); } mark = 64; /* mark for exclusion */ ring(ringri[0], ringro[0],rx,r_twist, mark, balk); /* mark ring 1 in balk array (excluded) */ mark = 32; /* mark for exclusion at 10 mm */ ring(ringri[1],ringro[1],rx,r_twist,mark,balk); /* mark ring 2 (exclude at 10 mm) */ ring(ringri[2],ringro[2],rx,r_twist,mark,balk); /* mark ring 3 (exclude at 10 mm) */ for (i=0; i<6; i++) { mark = 64; /* mark for exclusion */ bar(longspx[i], longspy[i], longspw, rx, r_twist, mark, balk); bolt(bolt1x[i], bolt1y[i], bolt1r, rx, r_twist, mark,balk); bolt(bolt2x[i], bolt2y[i], bolt2r, rx, r_twist, mark,balk); mark = 32; /* mark solid regions for exclusion at 10 mm) */ bar(shortspx[i], shortspy[i], shortspw, rx, r_twist, mark, balk); bolt(joint1x[i], joint1y[i], joint1r, rx, r_twist, mark, balk); bolt(joint2x[i], joint2y[i], joint2r, rx, r_twist, mark, balk); bolt(bolt3x[i], bolt3y[i], bolt3r, rx, r_twist, mark, balk); } k = 0; for (i=-250; i<250; i++) { for (j=-250; j<250; j++) { if ((i*i+j*j) > 62500) continue; if (balk[550+i][550+j] >= 32) k++; } } onax = (double)(k) / (3.14159 * 250.0 * 250.0); return (status); } /***************************************************************** * * bar * * Source file: j_src_lc/spectra.c * File version : 3.5 * Date: 2003/12/11 * Function name bar * Function version : 1.0 * Parent component: struktu * Children: bolt * * Developer: Niels Lund * Contact Address: * Purpose: This routine sets up parts the * array balk[][], which describes the * mask support structure. * * Origin date: * Update history: * 2003/12/11 CK Changed the function definition. * Removed global parameters, and * included them in function call. * Changed the name of the structure * array (struk[][]) to balk[][]. * * Error codes: See j_src_lc/spectra.txt * *****************************************************************/ /* void bar(double endx[2], double endy[2], double w, int mark) */ void bar(double endx[2], double endy[2], double w, double rx[4], double r_twist, int mark, unsigned char balk[J_DIM_BALK][J_DIM_BALK]) { int i = 0; int j = 0; double length = 0.0; double xv = 0.0; double yv = 0.0; double dx = 0.0; double dy = 0.0; double r = 0.0; double rin = 0.0; double rout = 0.0; length = sqrt((endx[0]-endx[1])*(endx[0]-endx[1]) + (endy[0]-endy[1])*(endy[0]-endy[1])); rin = sqrt(endx[0]*endx[0] + endy[0]*endy[0]); rout = sqrt(endx[1]*endx[1] + endy[1]*endy[1]); /* printf("Bar length: %7.2lf, rin: %7.2lf, rout: %7.2lf, endxy: %7.2lf/%7.2lf\n", length, rin, rout, endx[0], endy[0]); */ r = w / 2.0; j = length / 0.5 + 1; dx = (endx[0]-endx[1]) / j; dy = (endy[0]-endy[1]) / j; for (i=0; i<=j; i++) { xv = endx[1] + i * dx; yv = endy[1] + i * dy; bolt(xv, yv, r, rx, r_twist, mark, balk); } return; } /***************************************************************** * * ring * * Source file: j_src_lc/spectra.c * File version : 3.5 * Date: 2003/12/11 * Function name ring * Function version : 1.0 * Parent component: struktu * Children: circle * strukupdate * * Developer: Niels Lund * Contact Address: * Purpose: This routine sets up parts the * array balk[][], which describes the * mask support structure. * * Origin date: * Update history: * 2003/12/11 CK Changed the function definition. * Removed global parameters, and * included them in function call. * Changed the name of the structure * array (struk[][]) to balk[][]. * * Error codes: See j_src_lc/spectra.txt * *****************************************************************/ /* void ring(double ri,double ro,int mark) */ void ring(double ri, double ro, double rx[4], double r_twist, int mark, unsigned char balk[J_DIM_BALK][J_DIM_BALK] ) { int ix = 0; int iy = 0; int xlow = 0; int xhigh = 0; int ylow = 0; int yhigh = 0; int n = 0; double xv = 0.0; double yv = 0.0; double dn = 0.0; double rc = 0.0; double rv = 0.0; xlow = 550 - ro * 2.0; xhigh = 550 + ro * 2.0; ylow = 550 - ro * 2.0; yhigh = 550 + ro * 2.0; rc = (ri + ro) / 2.0; if (xlow < 0) xlow = 0; if (xhigh > 1099) xhigh = 1099; if (ylow < 0) ylow = 0; if (yhigh > 1099) yhigh = 1099; n = 0; for (ix=xlow; ix<=xhigh; ix++) { for (iy=ylow; iy<=yhigh; iy++) { xv = (double)(ix - 550) / 2.0; yv = (double)(iy - 550) / 2.0; if (circle(dn, dn, ro, xv, yv, &rv) == 1) { if (rv > ri) { if (mark <= 1) balk[ix][iy] = strukupdate(xv,yv,rv,rx,r_twist) + mark; if (mark > 1) balk[ix][iy] = mark; n++; } } } } return; } /***************************************************************** * * bolt * * Source file: j_src_lc/spectra.c * File version : 3.5 * Date: 2003/12/11 * Function name bolt * Function version : 1.0 * Parent component: struktu * bar * Children: circle * strukupdate * * Developer: Niels Lund * Contact Address: * Purpose: This routine sets up parts the * array balk[][], which describes the * mask support structure. * * Origin date: * Update history: * 2003/12/11 CK Changed the function definition. * Removed global parameters, and * included them in function call. * Changed the name of the structure * array (struk[][]) to balk[][]. * Removed parameter prin, which * controlled output, for testing. * * Error codes: See j_src_lc/spectra.txt * *****************************************************************/ /*void bolt(double xc, double yc, double r, int mark, int prin) */ void bolt( double xc, double yc, double r, double rx[4], double r_twist, int mark, unsigned char balk[J_DIM_BALK][J_DIM_BALK] ) { int ix, iy, ixlow, ixhigh, iylow, iyhigh, mrk; double xv, yv, c_angle, angle, rv, rb; ixlow = (xc - r) * 2.0 + 550.0; ixhigh = (xc + r) * 2.0 + 550.0; iylow = (yc - r) * 2.0 + 550.0; iyhigh = (yc + r) * 2.0 + 550.0; if (ixlow < 0) ixlow = 0; if (ixhigh > 1099) ixhigh = 1099; if (iylow < 0) iylow = 0; if (iyhigh > 1099) iyhigh = 1099; for (ix=ixlow; ix<=ixhigh; ix++) { for (iy=iylow; iy<=iyhigh; iy++) { xv = (double)(ix - 550) / 2.0; yv = (double)(iy - 550) / 2.0; if (circle(xc, yc, r, xv, yv, &rb) == 1) { if (mark > 1) balk[ix][iy] = mark; if (mark <= 1) { rv = sqrt(xv*xv + yv*yv); balk[ix][iy] = strukupdate(xv,yv,rv,rx,r_twist) + mark; } } } } return; } /***************************************************************** * * circle * * Source file: j_src_lc/spectra.c * File version : 3.5 * Date: 2003/12/11 * Function name circle * Function version : 1.0 * Parent component: ring * bolt * Children: * * Developer: Niels Lund * Contact Address: * Purpose: This routine checks if the coordinates * (xc,yc) are inside a circle of radius r. * If inside 1 is returned, else 0. * * * Origin date: * * Update history: * 2003/12/11 CK Removed printf-statements * * Error codes: See j_src_lc/spectra.txt * *****************************************************************/ int circle(double xc, double yc, double r, double x, double y, double *rv) { int inside; static int m=0; inside = 0; if ((*rv = sqrt((x-xc)*(x-xc) + (y-yc)*(y-yc))) <= r) inside = 1; m++; /* if (m < 1000) { printf("Circle: m: %3d, xc/yc: %5.1lf/%5.1lf, r: %5.1lf, x/y: %6.1lf/%6.1lf, inside: %1d\n", m, xc, yc, r, x, y, inside); } */ return(inside); } /***************************************************************** * * j_src_balk_strukdef * * Source file: j_src_lc/spectra.c * File version : 3.5 * Date: 2003/12/11 * Function name j_src_balk_strukdef * Function version : 1.0 * Parent component: j_src_work * Children: struktu * s_turn * * Developer: Niels Lund * Contact Address: * Purpose: This routine initializes the mask * support structure, balk[][] * * Origin date: * * Update history: * 2003/12/11 CK Changed name of the function from * strukdef to j_src_balk_strukdef. * Changed the function definition. * Removed global parameters, and * included them in function call. * Changed the name of the structure * array (struk[][]) to balk[][]. * A status is returned. * * Error codes: See j_src_lc/spectra.txt * *****************************************************************/ /* void strukdef(void) */ int j_src_balk_strukdef(double *longsph, double *shortsph, unsigned char balk[J_DIM_BALK][J_DIM_BALK], int status) /* Status flag */ { int i, j, s_offi, s_offj; double ta, len; double longspx[6][2],longspy[6][2],longspw,longspw2,offs_lsp; double shortspx[6][2],shortspy[6][2],shortspw,shortspw2,offs_ssp; double ringri[3],ringro[3]; double ringri2[3],ringro2[3]; double bolt1x[6],bolt1y[6],bolt1r,bolt1s,offs_b1; double bolt2x[6],bolt2y[6],bolt2r,bolt2s,offs_b2; double bolt3x[6],bolt3y[6],bolt3r,bolt3s,offs_b3; double joint1x[6],joint1y[6],joint1r,joint1r2,offs_j1; double joint2x[6],joint2y[6],joint2r,joint2r2,offs_j2; double rx[4],twist,r_twist; /* INITIALIZE ARRAYS. ADDED BY SL 040416 */ for (i=0; i<3; i++) { ringri[i] = 0.0; ringri2[i] = 0.0; ringro[i] = 0.0; ringro2[i] = 0.0; rx[i] = 0.0; } rx[4] = 0.0; for (i=0; i<6; i++) { bolt1x[i] = 0.0; bolt2x[i] = 0.0; bolt3x[i] = 0.0; bolt1y[i] = 0.0; bolt2y[i] = 0.0; bolt3y[i] = 0.0; joint1x[i] = 0.0; joint2x[i] = 0.0; joint1y[i] = 0.0; joint2y[i] = 0.0; for (j=0; j<2; j++) { longspx[i][j] = 0.0; longspy[i][j] = 0.0; shortspx[i][j] = 0.0; shortspy[i][j] = 0.0; } } twist = -4.286; /* twist angle for entire support structure */ r_twist = twist * DEGRAD; ringri[0] = 45.0; /* inner radius of ring 1 */ ringro[0] = 48.0; /* outer radius of ring 1 */ ringri2[0] = 45.0 - 3.5; /* inner radius of shadow region */ ringro2[0] = 48.0 + 3.5; /* outer radius of shadow region */ ringri[1] = 114.9; /* inner radius of ring 2 */ ringro[1] = 117.1; /* outer radius of ring 2 */ ringri2[1] = 114.9 - 1.7; /* inner radius of shadow region */ ringro2[1] = 117.1 + 1.7; /* outer radius of shadow region */ ringri[2] = 210.0; /* inner radius of ring 3 */ ringro[2] = 212.2; /* outer radius of ring 3 */ ringri2[2] = 210.0 - 1.7; /* inner radius of shadow region */ ringro2[2] = 212.2 + 1.7; /* outer radius of shadow region */ rx[0] = (ringri[0] + ringro[0]) / 2.0; rx[1] = (ringri[1] + ringro[1]) / 2.0; rx[2] = (ringri[2] + ringro[2]) / 2.0; rx[3] = 267.5; /* NOTE: the initial coordinates are not yet twisted by -4.286 degrees ! */ longspx[0][0] = 46.5; /* inner end of long spoke */ longspx[0][1] = 268.0; /* outer end of long spoke */ longspy[0][0] = 0.0; /* inner end of long spoke */ longspy[0][1] = 0.0; /* outer end of long spoke */ longspw = 2.2; /* width of long spoke */ longspw2 = 2.2 + 7.0; /* width of long spoke shadow */ *longsph = 21.25; /* height of long spoke */ offs_lsp = 30.0 + twist; /* angular offset of first long spoke */ shortspx[0][0] = 116.0; /* inner end of short spoke */ shortspx[0][1] = 211.0; /* outer end of short spoke */ shortspy[0][0] = 0.0; /* inner end of short spoke */ shortspy[0][1] = 0.0; /* outer end of short spoke */ shortspw = 2.2; /* width of short spoke */ shortspw2 = 2.2 + 3.4; /* width of shadow region */ *shortsph = 10.25; /* height of short spoke */ offs_ssp = 0.0 + twist; /* angular offset of first short spoke */ bolt1x[0] = 49.5; /* x coordinate of bolt1 */ bolt1y[0] = 0.0; /* y coordinate of bolt1 */ bolt1r = 4.5; /* radius of bolt1 */ bolt1s = 4.5 + 3.5; /* radius of bolt1 shadow */ offs_b1 = 30.0 + twist; /* angular offset of first bolt in 1. bolt set */ bolt2x[0] = 116.0; /* x coordinate of bolt2 */ bolt2y[0] = 0.0; /* y coordinate of bolt2 */ bolt2r = 4.5; /* radius of bolt */ bolt2s = 4.5 + 3.5; /* radius of bolt2 shadow */ offs_b2 = 30.0 + twist; /* angular offset of first bolt in 2. bolt set */ bolt3x[0] = 211.4; /* x coordinate of bolt3 */ bolt3y[0] = 0.0; /* y coordinate of bolt3 */ bolt3r = 3.5; /* radius of bolt */ bolt3s = 3.5 + 3.5; /* radius of bolt3 shadow */ offs_b3 = 0.0 + twist; /* angular offset of first bolt in 3. bolt set */ joint1x[0] = 211.4; /* x coordinate of joint1 */ joint1y[0] = 0.0; /* y coordinate of joint1 */ joint1r = 3.34; /* radius of joint1 */ joint1r2 = 3.34 + 1.7; /* outer radius of shadow region */ offs_j1 = 30.0 + twist; /* angular offset of first joint in 1. joint set */ joint2x[0] = 117.1; /* x coordinate of joint2 */ joint2y[0] = 0.0; /* y coordinate of joint2 */ joint2r = 2.5; /* radius of joint2 */ joint2r2 = 2.5 + 1.7; /* radius of shadow region */ offs_j2 = 0.0 + twist; /* angular offset of first joint in 2. joint set */ for (j=1; j<7; j++) { i = j % 6; ta = 60.0 * i; s_turn(longspx[0][0], longspy[0][0], ta+offs_lsp, &longspx[i][0], &longspy[i][0]); s_turn(longspx[0][1], longspy[0][1], ta+offs_lsp, &longspx[i][1], &longspy[i][1]); /* len = sqrt((longspx[i][0]-longspx[i][1]) * (longspx[i][0]-longspx[i][1]) + (longspy[i][0]-longspy[i][1]) * (longspy[i][0]-longspy[i][1])); printf("long %1d: x1/y1: %7.2lf/%7.2lf, x2/y2: %7.2lf/%7.2lf, length: %7.2lf\n", i, longspx[i][0], longspy[i][0], longspx[i][1], longspy[i][1], len); */ s_turn(shortspx[0][0], shortspy[0][0], ta+offs_ssp, &shortspx[i][0], &shortspy[i][0]); s_turn(shortspx[0][1], shortspy[0][1], ta+offs_ssp, &shortspx[i][1], &shortspy[i][1]); /* len = sqrt((shortspx[i][0]-shortspx[i][1]) * (shortspx[i][0]-shortspx[i][1]) + (shortspy[i][0]-shortspy[i][1]) * (shortspy[i][0]-shortspy[i][1])); printf("short %1d: x1/y1: %7.2lf/%7.2lf, x2/y2: %7.2lf/%7.2lf, length: %7.2lf\n", i, shortspx[i][0], shortspy[i][0], shortspx[i][1], shortspy[i][1], len); */ s_turn(bolt1x[0], bolt1y[0], ta+offs_b1, &bolt1x[i], &bolt1y[i]); s_turn(bolt2x[0], bolt2y[0], ta+offs_b2, &bolt2x[i], &bolt2y[i]); s_turn(bolt3x[0], bolt3y[0], ta+offs_b3, &bolt3x[i], &bolt3y[i]); s_turn(joint1x[0], joint1y[0], ta+offs_j1, &joint1x[i], &joint1y[i]); s_turn(joint2x[0], joint2y[0], ta+offs_j2, &joint2x[i], &joint2y[i]); } status = struktu(longspx, longspy, longspw, longspw2, shortspx, shortspy, shortspw, shortspw2, ringri, ringro, ringri2, ringro2, bolt1x, bolt2x, bolt3x, bolt1y, bolt2y, bolt3y, bolt1r, bolt1s, bolt2r, bolt2s, bolt3r, bolt3s, joint1x, joint1y, joint1r, joint1r2, joint2x, joint2y, joint2r, joint2r2, rx, r_twist, balk, status); /* build structure image array */ return(status); } /***************************************************************** * * s_turn * * Source file: j_src_lc/spectra.c * File version : 3.5 * Date: 2003/12/11 * Function name s_turn * Function version : 1.0 * Parent component: j_src_balk_strukdef * Children: * * Developer: Niels Lund * Contact Address: * Purpose: * * Origin date: * * Update history: * 2003/12/11 CK Removed parameter prin, which * controlled output, for testing. * The parameter gtorad was replaced * by macro DEGRAD. * * Error codes: See j_src_lc/spectra.txt * *****************************************************************/ void s_turn(double xin, double yin, double angle, double *xout, double *yout) { double sin_a, cos_a; sin_a = sin(angle*DEGRAD); cos_a = cos(angle*DEGRAD); *xout = cos_a * xin - sin_a * yin; *yout = cos_a * yin + sin_a * xin; /* printf("angle: %6.2lf, sin %6.4lf, cos %6.4lf, x/y in: %6.2lf/%6.2lf, x/y out: %6.2lf/%6.2lf\n", angle, sin_a, cos_a, xin, yin, *xout, *yout); */ return; } /***************************************************************** * * strukupdate * * Source file: j_src_lc/spectra.c * File version : 3.5 * Date: 2003/12/11 * Function name strukupdate * Function version : 1.0 * Parent component: ring * bolt * Children: * * Developer: Niels Lund * Contact Address: * Purpose: * * Origin date: * * Update history: * 2003/12/11 CK Changed the function definition. * Removed global parameters, and * included them in function call. * The parameter twopi was replaced * by macro J_TWOPI. * Set pi6 in the routine. * * Error codes: See j_src_lc/spectra.txt * *****************************************************************/ /* int strukupdate(double xv, double yv, double rv) */ int strukupdate( double xv, double yv, double rv, double rx[4], double r_twist ) { int m6, m12; double pi6 = J_COR_PI / 6.0; if (rv < rx[0]) return(0); m12 = (atan2(yv, xv) + J_TWOPI - r_twist) / pi6; m12 %= 2; m6 = (atan2(yv, xv) + J_TWOPI - r_twist - pi6) / (pi6 * 2.0); m6 %= 2; /* if (rv < rx[1]) return(8 + m6); if (rv < rx[2]) return(16 + m12); if (rv < rx[3]) return(32 + m6); */ if (rv < rx[1]) return(2+2*m6); if (rv < rx[2]) return(8+8*m12); if (rv < rx[3]) return(2+2*m6); return(0); } /***************************************************************** * * struchk * * Source file: j_src_lc/spectra.c * File version : 3.5 * Date: 2003/12/11 * Function name struchk * Function version : 1.0 * Parent component: j_src_through_balk * * Children: * * Developer: Niels Lund * Contact Address: * Purpose: * * Origin date: * * Update history: * 2003/12/11 CK Changed the function definition. * Removed global parameters, and * included them in function call. * The initialization of the mask * support structure (balk[][]) was * removed and is now done separately * in the beginning of j_src_work. * Replaced printf-statements with * Warning_2 messages. * The parameter first was removed. * The mask_height is set to .... * Changed the name of the structure * array (struk[][]) to balk[][]. * A status is returned. * * Included detMaskDist in function call. * * Error codes: See j_src_lc/spectra.txt * *****************************************************************/ /*int struchk(double xm, double ym, double dxl, double dyl, double dxh, double dyh, int last)*/ /*int struchk(double xm, double ym, double x_det, double y_det, int last) */ int struchk(double xm, double ym, double x_det, double y_det, double detMaskDist, double longsph, double shortsph, unsigned char balk[J_DIM_BALK][J_DIM_BALK], int *balkweight, int last, int status ) /* The "balk" array contains information about the mask support structure and its shadowing of the mask. The array covers a 550x550 mm2 area with pixels of 0.5x0.5 mm2. The access tests should be done in the following order: 1) calculate intersection of ray with the mask plane. Find corresponding pixel in the "balk" array. 2) If the pixel value is 0 access is allowed along this path (in open areas between structural members) 3) If the pixel value is >= 32 access is forbidden along this path (hit solid structure or mask elim. hole) 4) If the pixel value is >0 and <32: (in potential shadow area close to a structural member) 4a) If the pixel value is odd, (close to a structural member of 21 mm height) Calculate intersection points of this photon with two leves at +/- 21.25 mm 4b) If the pixel value is even, (close to a structural member of 10 mm height) Calculate intersection points of this photon with two leves at +/- 10.25 mm 5) If the pixel value in any of the two new points is 64 access is forbidden. (hit solid structure) 6) If the pixel value in any of the two new points is 32 and the first pixel value was even, access is forbidden. (hit solid structure) 7) If the pixel value in both of the two new points is >= 0 and the two values are different, access is forbidden. (traverse solid structure) 8) Otherwise access is allowed. The following symbols are used in the pixels of balk: 0: free access, no further tests are required. 32: access blocked by solid material in mask support structure of 10.25 mm height. 64: access blocked by solid material in mask support structure of 21.25 mm height. 1, 3, 5, 7, 9: 17: Photon close to high structure. Test required at plus/minus 21.25 mm from the mask plane. 2, 4, 6, 8, 16: Photon close to low structure. Test required at plus/minus 10.25 mm from the mask plane. */ { int i, j, ix, iy, ixb, iyb, ixu, iyu, sbval, suval; double xb, yb, xu, yu, dxl, dyl, dxh, dyh, xdif, ydif, mask_height; static int p_count[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; *balkweight = 0; /* height of mask above detector window */ mask_height = detMaskDist; /* check that the mask_height has been defined (external variable) */ if ((mask_height < 3397.0) || (mask_height > 3403.0)) { status = J_SRC_INVALID_PAR; RILlogMessage(NULL, Error_2, "%d : mask_height value outside acceptable range", status); return(status); } xb = xu = xm * 2.0 + 550.5; yb = yu = ym * 2.0 + 550.5; xdif = xm - x_det; ydif = ym - y_det; dxl = xdif * 2.0 * shortsph / mask_height; dyl = ydif * 2.0 * shortsph / mask_height; dxh = xdif * 2.0 * longsph / mask_height; dyh = ydif * 2.0 * longsph / mask_height; ix = xb; iy = yb; if ((ix < 0) || (ix > 1099) || (iy < 0) || (iy > 1099)) { /* CK question : if ix=iy=0 => i=0 <=> The ray does not intersect balk, open Instead set *balkweight = 7 to indicate that ray outside balk-array. */ /* RILlogMessage(NULL, Warning_2, "ix/iy outside limits: %4d/%4d, x/y_mask: %6.2f/%6.2f, x/y_det: %6.2f/%6.2f", ix, iy, xm, ym, x_det, y_det); */ *balkweight = 7; ix = iy = 0; } i = 0; if (balk[ix][iy] == 0) { if (last) p_count[7]++; goto retu; /* in open areas between structural members */ } i = 1; if (balk[ix][iy] >= 32) { if (last) p_count[0]++; goto retu; /* hit solid structure */ } if ((balk[ix][iy]%2) == 0) { /* balk value is even - close to a structural member of 10 mm height */ xb -= dxl; yb -= dyl; ixb = xb; iyb = yb; if ((ixb < 0) || (ixb > 1099) || (iyb < 0) || (iyb > 1099)) { RILlogMessage(NULL, Warning_2, "ixb/iyb outside limits: %4d/%4d, x/y_mask: %6.2f/%6.2f, x/y_det: %6.2f/%6.2f", ixb, iyb, xm, ym, x_det, y_det); ixb = iyb = 0; } sbval = balk[ixb][iyb]; if (sbval >= 32) { if (last) p_count[1]++; goto retu; /* hit solid structure */ } xu += dxl; yu += dyl; ixu = xu; iyu = yu; if ((ixu < 0) || (ixu > 1099) || (iyu < 0) || (iyu > 1099)) { RILlogMessage(NULL, Warning_2, "ixu/iyu outside limits: %4d/%4d, x/y_mask: %6.2f/%6.2f, x/y_det: %6.2f/%6.2f", ixu, iyu, xm, ym, x_det, y_det); ixu = iyu = 0; } suval = balk[ixu][iyu]; if (suval >= 32) { if (last) p_count[2]++; goto retu; /* hit solid structure */ } if ((sbval > 0) && (suval > 0) && ((sbval&0xffe) != (suval&0xffe))) { if (last) p_count[3]++; goto retu; /* traverse structure */ } } else { /* balk value is odd - close to a structural member of 21 mm height */ xb = xu = xm * 2.0 + 550.5; yb = yu = ym * 2.0 + 550.5; xb -= dxh; yb -= dyh; ixb = xb; iyb = yb; if ((ixb < 0) || (ixb > 1099) || (iyb < 0) || (iyb > 1099)) { RILlogMessage(NULL, Warning_2, "ixb/iyb2 outside limits: %4d/%4d, x/y_mask: %6.2f/%6.2f, x/y_det: %6.2f/%6.2f", ixb, iyb, xm, ym, x_det, y_det); ixb = iyb = 0; } sbval = balk[ixb][iyb]; if (sbval >= 64) { if (last) p_count[4]++; goto retu; /* hit solid structure */ } xu += dxh; yu += dyh; ixu = xu; iyu = yu; if ((ixu < 0) || (ixu > 1099) || (iyu < 0) || (iyu > 1099)) { RILlogMessage(NULL, Warning_2, "ixu/iyu2 outside limits: %4d/%4d, x/y_mask: %6.2f/%6.2f, x/y_det: %6.2f/%6.2f", ixu, iyu, xm, ym, x_det, y_det); ixu = iyu = 0; } suval = balk[ixu][iyu]; if (suval >= 64) { if (last) p_count[5]++; goto retu; /* hit solid structure */ } if ((sbval > 0) && (suval > 0) && ((sbval&0xffe) != (suval&0xffe))) { if (last) p_count[6]++; goto retu; /* traverse structure */ } } if (last) p_count[8]++; i = 0; retu: if (*balkweight != 7) { if (i > 0) *balkweight = 1 ; else *balkweight = 0; } return(status); } /************************************************************************ * * j_src_solve_rate v1.0 2004-04-24 * * File name: j_src_lc/spectra.c * Version: 1.0 * Parent Component: * Developer: Stefan Larsson * Contact Address: Stockholm Observatory, Sweden * Purpose: Give observed open and closed area rates etc * solve for source and background rates per mm2 * * Note: Since we use scaled count rates (obsOpenRate and * obsClosedRate) we also have to scale Poisson errors * from the unscaled event rates (nObsOpenRate and * nObsClosedRate). * Variance scales as follows: * If y = c*n * * Var(y) = c*c*Var(n) = y*y/n * * since c=y/n and Var(n) = n * * Variables: * *****************************************************************************/ int j_src_solve_rate(double openArea1, double closedArea1, double effOpenArea1, double leakageFrOpen1, double leakageToClosed1, double obsOpenRate, double obsClosedRate, double *srcRate, double *bkgRate, long nObsOpenRate, long nObsClosedRate, double *srcRateErr, double *bkgRateErr, int chatty, int status) { double a = 0.0; double aaa = 0.0; double varObsOpenRate = 0.0; double varObsClosedRate = 0.0; double varSrcRate = 0.0; double varBkgRate = 0.0; if(openArea1 > 0.0 && closedArea1 > 0.0){ a = obsOpenRate - openArea1*obsClosedRate/closedArea1; }else{ a = 0.0; } if(closedArea1 > 0.0){ aaa = effOpenArea1*(1.0-leakageFrOpen1-leakageToClosed1); }else{ aaa = 1.0; } if(aaa > 0.0){ *srcRate = a/aaa; }else{ *srcRate = a; } if(closedArea1 > 0.0){ *bkgRate = (obsClosedRate - (*srcRate)*effOpenArea1*leakageToClosed1)/ closedArea1; }else{ *bkgRate = 0.0; } /* Error estimate assuming poisson statistics. */ /* Transform Poisson variance (Minimum counts = 1) */ if(nObsOpenRate > 0){ varObsOpenRate = obsOpenRate*obsOpenRate/((double) nObsOpenRate); }else{ varObsOpenRate = 1.0; } if(nObsClosedRate > 0){ varObsClosedRate = obsClosedRate*obsClosedRate/((double) nObsClosedRate); }else{ varObsClosedRate = 1.0; } if(closedArea1 > 0.0 && aaa > 0.0){ varSrcRate = varObsOpenRate + varObsClosedRate*(openArea1/closedArea1)*(openArea1/closedArea1); varSrcRate = varSrcRate/(aaa*aaa); *srcRateErr = sqrt(varSrcRate); }else{ *srcRateErr = varObsOpenRate + varObsClosedRate; } if(closedArea1 > 0.0 ){ varBkgRate = varObsClosedRate + varSrcRate*(effOpenArea1*leakageToClosed1)*(effOpenArea1*leakageToClosed1); varBkgRate = varBkgRate/(closedArea1*closedArea1); *bkgRateErr = sqrt(varBkgRate); }else{ *bkgRateErr = varObsOpenRate + varObsClosedRate; } return(status); }