void integratePixAboveThreshold(float *data, uint16_t *mask, long pix_nn, float ADC_threshold, uint16_t pixel_options, long *nat, float *tat) { *nat = 0; *tat = 0.0; for (long i = 0; i < pix_nn; i++) { if (isNoneOfBitOptionsSet(mask[i], pixel_options)) { if (data[i] >= ADC_threshold) { *tat += data[i]; *nat += 1; mask[i] |= PIXEL_IS_PEAK_FOR_HITFINDER; } } } }
int hitfinder4(cGlobal *global, cEventData *eventData, long detIndex) { int hit = 0; long pix_nn = global->detector[detIndex].pix_nn; uint16_t *mask = eventData->detector[detIndex].pixelmask; float *data; long nat = 0; long counter; float total; float mingrad = global->hitfinderMinGradient * 2; mingrad *= mingrad; nat = 0; counter = 0; total = 0.0; if (global->hitfinderOnDetectorCorrectedData) { data = eventData->detector[detIndex].data_detCorr; } else { data = eventData->detector[detIndex].data_detPhotCorr; } /* * Create a buffer for image data so we don't nuke the main image by mistake */ float *temp = (float*) calloc(pix_nn, sizeof(float)); memcpy(temp, data, pix_nn * sizeof(float)); // combine pixelmask bits uint16_t combined_pixel_options = PIXEL_IS_IN_PEAKMASK | PIXEL_IS_OUT_OF_RESOLUTION_LIMITS | PIXEL_IS_HOT | PIXEL_IS_BAD; if (global->hitfinderIgnoreNoisyPixels) { combined_pixel_options |= PIXEL_IS_NOISY; } if (global->detector[detIndex].useStreakFinder) { combined_pixel_options |= PIXEL_IS_IN_JET; } /* * Apply masks * (multiply data by 0 to ignore regions) */ for (long i = 0; i < pix_nn; i++) { temp[i] *= isNoneOfBitOptionsSet(mask[i], combined_pixel_options); } if ((global->hitfinderUseTOF == 1) && (eventData->TOFPresent == 1)) { double total_tof = 0.; for (int i = global->tofDetector[0].hitfinderMinSample; i < global->tofDetector[0].hitfinderMaxSample; i++) { // We'll only look at the first TOF detector total_tof += eventData->tofDetector[0].voltage[i]; } if (total_tof > global->tofDetector[0].hitfinderThreshold) { hit = 1; } } // Use cspad threshold if TOF is not present else { for (long i = 0; i < pix_nn; i++) { if (temp[i] > global->hitfinderADC) { nat++; } } if (nat >= global->hitfinderMinPixCount) hit = 1; } free(temp); return hit; }
/* * Find peaks on the inner 4 2x2 modules * Calculate rest of detector only if needed * Tries to avoid bottleneck in subtractLocalBackground() on the whole detector even for blanks */ long hitfinderFastScan(cEventData *eventData, cGlobal *global) { // Bad detector?? long detIndex = global->hitfinderDetIndex; long pix_nx = global->detector[detIndex].pix_nx; long pix_nn = global->detector[detIndex].pix_nn; long asic_nx = global->detector[detIndex].asic_nx; long asic_ny = global->detector[detIndex].asic_ny; long nasics_x = global->detector[detIndex].nasics_x; long radius = global->detector[detIndex].localBackgroundRadius; float *pix_r = global->detector[detIndex].pix_r; float *data = eventData->detector[detIndex].data_detCorr; float hitfinderADCthresh = global->hitfinderADC; float hitfinderMinSNR = global->hitfinderMinSNR; long hitfinderMinPixCount = global->hitfinderMinPixCount; long hitfinderMaxPixCount = global->hitfinderMaxPixCount; long hitfinderLocalBGRadius = global->hitfinderLocalBGRadius; float hitfinderMinPeakSeparation = global->hitfinderMinPeakSeparation; tPeakList *peaklist = &eventData->peaklist; char *mask = (char*) calloc(pix_nn, sizeof(char)); // Bad region masks (data=0 to ignore regions) uint16_t combined_pixel_options = PIXEL_IS_IN_PEAKMASK | PIXEL_IS_BAD | PIXEL_IS_HOT | PIXEL_IS_BAD | PIXEL_IS_OUT_OF_RESOLUTION_LIMITS; for (long i = 0; i < pix_nn; i++) mask[i] = isNoneOfBitOptionsSet(eventData->detector[detIndex].pixelmask[i], combined_pixel_options); subtractLocalBackground(data, radius, asic_nx, asic_ny, nasics_x, 2); /* * Call the appropriate peak finding algorithm */ long nPeaks; switch (global->hitfinderAlgorithm) { case 3: // Count number of Bragg peaks nPeaks = peakfinder3(peaklist, data, mask, asic_nx, asic_ny, nasics_x, 2, hitfinderADCthresh, hitfinderMinSNR, hitfinderMinPixCount, hitfinderMaxPixCount, hitfinderLocalBGRadius); break; case 6: // Count number of Bragg peaks nPeaks = peakfinder6(peaklist, data, mask, asic_nx, asic_ny, nasics_x, 2, hitfinderADCthresh, hitfinderMinSNR, hitfinderMinPixCount, hitfinderMaxPixCount, hitfinderLocalBGRadius, hitfinderMinPeakSeparation); break; case 8: // Count number of Bragg peaks nPeaks = peakfinder8(peaklist, data, mask, pix_r, asic_nx, asic_ny, nasics_x, 2, hitfinderADCthresh, hitfinderMinSNR, hitfinderMinPixCount, hitfinderMaxPixCount, hitfinderLocalBGRadius); break; default: printf("Unknown peak finding algorithm selected: %i\n", global->hitfinderAlgorithm); printf("Stopping in hitfinderFastScan.\n"); exit(1); break; } /* * Is this a potential hit? */ int hit; eventData->nPeaks = nPeaks; if (nPeaks >= global->hitfinderNpeaks / 2 && nPeaks <= global->hitfinderNpeaksMax / 2) { hit = 1; //printf("%li : Potential hit, npeaks(prescan) = %li\n", eventData->threadNum, nPeaks); // Do the rest of the local background subtraction long offset = (2 * asic_ny) * pix_nx; subtractLocalBackground(data + offset, radius, asic_nx, asic_ny, nasics_x, 6); } free(mask); return hit; }
void addToPowder(cEventData *eventData, cGlobal *global, int powderClass, long detIndex){ // Increment counter of number of powder patterns pthread_mutex_lock(&global->detector[detIndex].powderData_mutex[powderClass]); global->detector[detIndex].nPowderFrames[powderClass] += 1; if(detIndex == 0) global->nPowderFrames[powderClass] += 1; pthread_mutex_unlock(&global->detector[detIndex].powderData_mutex[powderClass]); double *buffer; FOREACH_DATAFORMAT_T(i_f, cDataVersion::DATA_FORMATS) { if (isBitOptionSet(global->detector[detIndex].powderFormat,*i_f)) { cDataVersion dataV(&eventData->detector[detIndex], &global->detector[detIndex], global->detector[detIndex].powderVersion, *i_f); while (dataV.next()) { float * data = dataV.getData(); double * powder = dataV.getPowder(powderClass); double * powder_squared = dataV.getPowderSquared(powderClass); long * powder_counter = dataV.getPowderCounter(powderClass); pthread_mutex_t * mutex = dataV.getPowderMutex(powderClass); // Powder squared buffer = (double*) calloc(dataV.pix_nn, sizeof(double)); if(!global->usePowderThresh) { for(long i=0; i<dataV.pix_nn; i++) // Use double precision throughout the multiplication to reduce rounding errors in powder_squared buffer[i] = ((double) data[i])*data[i]; } else { for(long i=0; i<dataV.pix_nn; i++){ if(data[i] > global->powderthresh) // Use double precision throughout the multiplication to reduce rounding errors in powder_squared buffer[i] = ((double) data[i])*data[i]; else buffer[i] = 0; } } if (global->threadSafetyLevel > 0) { pthread_mutex_lock(mutex); } if(global->detector[detIndex].savePowderMasked == 0 || powder_counter==NULL) { for(long i=0; i<dataV.pix_nn; i++){ // Powder powder[i] += data[i]; // Powder squared powder_squared[i] += buffer[i]; } } else if(global->detector[detIndex].savePowderMasked != 0 && powder_counter!=NULL) { uint16_t *pixelmask = eventData->detector[detIndex].pixelmask; uint16_t combined_pixel_options = PIXEL_IS_HOT|PIXEL_IS_BAD|PIXEL_IS_IN_JET; for(long i=0; i<dataV.pix_nn; i++){ if(isNoneOfBitOptionsSet(pixelmask[i], combined_pixel_options)) { // Powder powder[i] += data[i]; // Powder squared powder_squared[i] += buffer[i]; // Counter powder_counter[i] += 1; } } } if (global->threadSafetyLevel > 0) pthread_mutex_unlock(mutex); free(buffer); } } } /* * Sum of peaks centroids */ if (eventData->nPeaks > 0) { pthread_mutex_lock(&global->detector[detIndex].powderPeaks_mutex[powderClass]); long ci, cx, cy, e; double val; long pix_nn = global->detector[detIndex].pix_nn; long pix_nx = global->detector[detIndex].pix_nx; long pix_ny = global->detector[detIndex].pix_ny; for(long i=0; i<=eventData->peaklist.nPeaks && i<eventData->peaklist.nPeaks_max; i++) { // Peak position and value ci = eventData->peaklist.peak_com_index[i]; cx = lrint(eventData->peaklist.peak_com_x[i]); cy = lrint(eventData->peaklist.peak_com_y[i]); val = eventData->peaklist.peak_totalintensity[i]; // Bounds check if(cx < 0 || cx > (pix_nx-1) ) continue; if(cy < 0 || cy > (pix_ny-1) ) continue; if(ci < 0 || cx > (pix_nn-1) ) continue; // Element in 1D array e = cx + pix_nx*cy; if(e < 0 || e > (pix_nn-1) ) continue; global->detector[detIndex].powderPeaks[powderClass][e] += val; //global->detector[detIndex].powderPeaks[powderClass][ci] += val; } pthread_mutex_unlock(&global->detector[detIndex].powderPeaks_mutex[powderClass]); } // Min nPeaks if(eventData->nPeaks < global->nPeaksMin[powderClass]){ pthread_mutex_lock(&global->nPeaksMin_mutex[powderClass]); global->nPeaksMin[powderClass] = eventData->nPeaks; //memcpy(global->detector[detIndex].correctedMin[powderClass],eventData->detector[detIndex].corrected_data,sizeof(float)*pix_nn); pthread_mutex_unlock(&global->nPeaksMin_mutex[powderClass]); } // Max nPeaks if(eventData->nPeaks > global->nPeaksMax[powderClass]){ pthread_mutex_lock(&global->nPeaksMax_mutex[powderClass]); global->nPeaksMax[powderClass] = eventData->nPeaks; //memcpy(global->detector[detIndex].correctedMax[powderClass],eventData->detector[detIndex].corrected_data,sizeof(float)*pix_nn); pthread_mutex_unlock(&global->nPeaksMax_mutex[powderClass]); } }