void reload_graphics_state() { #ifdef BOINC_APP_GRAPHICS if (!nographics()) { sah_graphics->si.copy(best_spike, true); sah_graphics->gi.copy(best_gauss, true); sah_graphics->pi.copy(best_pulse, true); sah_graphics->ti.copy(best_triplet, true); } #endif }
int analyze_pot(float *PowerSpectrum, int NumDataPoints, ChirpFftPair_t &cfft, int offset) { // This function analyses Power over Time for the current data block. // The PoT array is created by taking an array of power spectra (a // standard row-major 2D array) and extracting the PoT as column-major // data. We essentialy turn the array on its side. int retval = 0, i, FftLength=cfft.FftLen, // Current FFT length ThisPoT, // index of current PoT along the freq axis PoTLen, // complement of FFT length - determines time res PulsePoTLen, // length of PoT segment passed to pulse finders Overlap, // PoT segment overlap in bins TOffset, // index into ThisPoT of current pulse segment PulsePoTNum = 0, // the oridinal position of a pulse PoT w/in a full PoT NumPulsePoTs = 0, // the number of pulse PoTs w/in a full PoT. This is // constant regardless of FFT or PoT length and is // determined by slew rate. AdvanceBy; // the number of bins to advance for the next pulse PoT float ProgressAddFactor = 0.0, // sum of progress adds for ThisPoT ProgressPerPulsePoT = 0.0; // for local progress display bool SkipGauss = false, SkipPulse = false, SkipTriplet = false, TOffsetOK = true; static float *GaussPoT = NULL, *PulsePoT = NULL; #ifdef DEBUG_POT fprintf(stderr, "========= FftLength = %d =========\n", FftLength); #endif PoTLen = NumDataPoints / FftLength; // in bins GetPulsePoTLen(PoTLen, &PulsePoTLen, &Overlap); // in bins AdvanceBy = PulsePoTLen - Overlap; // in bins // Max limits how *slow* the slewrate can be, while Min limits how // *fast* the slewrate can be. Max is limited only by the client // memory budget. if(PulsePoTLen > PoTInfo.TripletMax || PulsePoTLen < PoTInfo.TripletMin) SkipTriplet = true; SkipGauss = !(cfft.GaussFit); SkipPulse = !(cfft.PulseFind); if(!SkipPulse || !SkipTriplet) { // NumPulsePoTs is the number of PoT segments that we pass to the pulse // detectors per frequency bin. ProgressPerPulsePoT is the inverse of // number of pulse detection segments in the entire data block, taking // into account that we skip the first (DC) frequency bin. An assumption // is made here that minimum pulse/triplet PoT length will always be // greater than 1. Otherwise, AdvanceBy can become zero and a divide by // zero can occur. The assumption is also made that FftLength is always // greater than 1! NumPulsePoTs = 1 + (PoTLen-PulsePoTLen)/AdvanceBy + ((PoTLen-PulsePoTLen)%AdvanceBy ? 1 : 0); ProgressPerPulsePoT = (float)1 / ((FftLength - 1) * NumPulsePoTs); } #ifdef DEBUG_POT fprintf(stderr, "SlewRate = %f\n", PoTInfo.SlewRate); fprintf(stderr, "PoTLen = %d\n", PoTLen); fprintf(stderr, "MaxPoTLen = %d\n", PoTInfo.MaxPoTLen); fprintf(stderr, "PoTDuration = %f\n", PoTInfo.WUDuration); fprintf(stderr, "BeamRate = %f\n", PoTInfo.BeamRate); fprintf(stderr, "PulsePoTLen = %d\n", PulsePoTLen); fprintf(stderr, "Overlap = %d\n", Overlap); fprintf(stderr, "AdvanceBy = %d\n", AdvanceBy); fprintf(stderr, "min_slew = %f\n", PoTInfo.min_slew); fprintf(stderr, "max_slew = %f\n", PoTInfo.max_slew); fprintf(stderr, "PulseOverlapFactor = %f\n", PoTInfo.PulseOverlapFactor); fprintf(stderr, "PulseBeams = %f\n", PoTInfo.PulseBeams); fprintf(stderr, "PulseThresh = %f\n", PoTInfo.PulseThresh); fprintf(stderr, "PulseMax = %d\n", PoTInfo.PulseMax); fprintf(stderr, "PulseMin = %d\n", PoTInfo.PulseMin); fprintf(stderr, "PulseFftMax = %d\n", PoTInfo.PulseFftMax); fprintf(stderr, "TripletThresh = %f\n", PoTInfo.TripletThresh); fprintf(stderr, "TripletMax = %d\n", PoTInfo.TripletMax); fprintf(stderr, "TripletMin = %d\n", PoTInfo.TripletMin); #endif #ifndef USE_PULSE SkipPulse = TRUE; static int doneprintnopulsefind = 0; if(!doneprintnopulsefind) { fprintf(stderr,"SkipPulse is set to TRUE: Not doing Pulsefinds.\n"); doneprintnopulsefind = TRUE; } #endif #ifndef USE_TRIPLET SkipTriplet = TRUE; #endif // Get memory fot the PoT arrays. The PoT array for gausian analysis is // of set size. The PoT array for pulse analysis is sized to cover // PulseBeams beams, regardless of whether this violates either the // triplet or pulse limits on array size. if(!GaussPoT) { GaussPoT = (float *)malloc_a(swi.analysis_cfg.gauss_pot_length * sizeof(float), MEM_ALIGN); if(GaussPoT == NULL) { SETIERROR(MALLOC_FAILED, "GaussPoT == NULL"); } } if(!PulsePoT) { PulsePoT = (float *)calloc_a(PoTInfo.MaxPoTLen+3, sizeof(float), MEM_ALIGN); if(PulsePoT == NULL) { SETIERROR(MALLOC_FAILED, "PulsePoT == NULL"); } } bool b_gaussStarted = false; // Look for gaussians --------------------------------------------------- if(!SkipGauss && (analysis_state.PoT_activity == POT_DOING_GAUSS || analysis_state.PoT_activity == POT_INACTIVE)) { #ifdef BOINC_APP_GRAPHICS if (!nographics()) strcpy(sah_graphics->status, "Searching for Gaussians"); #endif // If we are back from being interrupted in the middle of gaussian PoT // analysis, load state and continue. Otherwise start anew, skipping // the DC (0) bin. if(analysis_state.PoT_activity == POT_DOING_GAUSS) { ThisPoT = analysis_state.PoT_freq_bin; } else { ThisPoT = 1; // skip the DC bin on start of new cfft pair } // Initial display of local Progress / CPU time. Assumes that // we start ThisPoT at 1 each time in! #ifdef BOINC_APP_GRAPHICS if (!nographics()) sah_graphics->local_progress = ((float)ThisPoT-1)/(FftLength-1); #endif #ifdef USE_CUDA //#ifndef CUDAACC_EMULATION if(gSetiUseCudaDevice) { //TODO: remove the autocorr_fftlen test when v6 fully deprecated. bool noscore = false; //swi.analysis_cfg.autocorr_fftlen!=0 && gaussian_count!=0; //cudaAcc_Gaussfit(FftLength, best_gauss->score, noscore); //printf("GaussFitStart\r\n"); b_gaussStarted = true; // started earlier //cudaAcc_GaussfitStart(FftLength, best_gauss->score, noscore); if(PoTLen > swi.analysis_cfg.gauss_pot_length) analysis_state.FLOP_counter+=((double)NumDataPoints+swi.analysis_cfg.gauss_pot_length * (FftLength-1)); // GetFixedPoT // There are FftLength - 1 fixed PoTs for a chirp/fft pair, and for each fixed PoT full analysis would do // (1 + (PoTInfo.GaussTOffsetStop - PoTInfo.GaussTOffsetStart)) GetPeak and GetTrueMean operations. // Use (1 - PoTInfo.GaussSigma*0.09) empirically found to represent fraction of PoTs which don't // take either of the two early out paths. double CorrWt = (1.0 - PoTInfo.GaussSigma*0.09) * (FftLength - 1) * (1 + (PoTInfo.GaussTOffsetStop - PoTInfo.GaussTOffsetStart)); analysis_state.FLOP_counter+=6.0*floor(PoTInfo.GaussSigma+0.5) * CorrWt; // GetPeak analysis_state.FLOP_counter+=(double)(floor(PoTInfo.GaussSigma+0.5) * 3.911+5) * CorrWt; // GetTrueMean // Estimate one in twenty fit positions look good enough to be checked further. analysis_state.FLOP_counter+= 0.05 * (20.0*swi.analysis_cfg.gauss_pot_length+5.0) * CorrWt; // GetChiSq / 20 progress += ProgressUnitSize * GaussianProgressUnits(); progress=std::min(progress,1.0); // prevent display of > 100% fraction_done(progress,remaining); } //#endif CUDAACC_EMULATION else { #endif //USE_CUDA // loop through frequencies /* for(; ThisPoT < FftLength; ThisPoT++) { // Create PowerOfTime array for gaussian fit retval = GetFixedPoT( PowerSpectrum, NumDataPoints, FftLength, GaussPoT, swi.analysis_cfg.gauss_pot_length, ThisPoT ); if (retval) continue; retval = GaussFit(GaussPoT, FftLength, ThisPoT); if (retval) SETIERROR(retval,"from GaussFit"); progress += ProgressUnitSize * GaussianProgressUnits() / (float)(FftLength - 1); progress=std::min(progress,1.0); // prevent display of > 100% fraction_done(progress,remaining); // At the end of each frequency bin we update progress and save state. #ifdef BOINC_APP_GRAPHICS if (!nographics()) { sah_graphics->local_progress = ((float)ThisPoT)/(FftLength-1); } #endif analysis_state.PoT_freq_bin = ThisPoT; analysis_state.PoT_activity = POT_DOING_GAUSS; retval = checkpoint(); if (retval) SETIERROR(retval,"from checkpoint()"); } // end loop through frequencies */ #ifdef USE_CUDA } #endif //USE_CUDA analysis_state.PoT_freq_bin = -1; analysis_state.PoT_activity = POT_INACTIVE; } // end looking for gaussians // Look for pulses ------------------------------------------------------- if(!SkipPulse || !SkipTriplet) { #ifdef BOINC_APP_GRAPHICS if (!nographics()) { strcpy(sah_graphics->status, "Searching for Pulses / Triplets"); // init local progress for pulse search sah_graphics->local_progress = 0; } #endif // If we are back from being interrupted in the middle of pulse PoT // analysis, load state and continue. Otherwise start anew, skipping // the DC (0) bin. if(analysis_state.PoT_activity == POT_DOING_PULSE) { ThisPoT = analysis_state.PoT_freq_bin; } else { ThisPoT = 1; // skip the DC bin on start of new cfft pair } PulsePoTNum = 0; #ifdef BOINC_APP_GRAPHICS // Inital display of Local Progress if(!nographics()) { sah_graphics->local_progress = (((ThisPoT-1) * NumPulsePoTs) + PulsePoTNum) * ProgressPerPulsePoT; } #endif #ifdef USE_CUDA if(gSetiUseCudaDevice) { /* if(!SkipTriplet || !SkipPulse) // do beforehand on fftstreamX { // CUDASYNC; //printf("CalculateMean\r\n"); cudaAcc_calculate_mean(PulsePoTLen, 0, AdvanceBy, FftLength); } if(!SkipPulse) { //printf("FindPulses\r\n"); cudaAcc_find_pulses((float) best_pulse->score, PulsePoTLen, AdvanceBy, FftLength); } if(!SkipTriplet) { //printf("FindTriplets\r\n"); cudaAcc_find_triplets(PulsePoTLen, (float)PoTInfo.TripletThresh, AdvanceBy, FftLength); } */ /* timespec t1, t2; t1.tv_sec = 0; t1.tv_nsec = 5000; while(cudaEventQuery(summaxDoneEvent) != cudaSuccess) nanosleep(&t1, &t2); */ int gflags = 0; if(b_gaussStarted) { //printf("fetchGaussFitFlags\r\n"); b_gaussStarted = false; gflags = cudaAcc_fetchGaussfitFlags(FftLength, best_gauss->score); } //printf("fetchTripletAndPulseFlags\r\n"); int has_dataT = 0, has_dataP = 0; if(!SkipTriplet) has_dataT = cudaAcc_fetchTripletFlags(SkipTriplet, PulsePoTLen, AdvanceBy, FftLength, offset); if(gflags > 0) { //printf("ProcessGaussFit\r\n"); cudaAcc_processGaussFit(FftLength, best_gauss->score); } if(!SkipTriplet) { if((has_dataT & 1) && !(has_dataT & 4)) // has triplet data and no error in triplet { //printf("processTripletResults\r\n"); cudaAcc_processTripletResults(PulsePoTLen, AdvanceBy, FftLength); } analysis_state.FLOP_counter+=(10.0 + PulsePoTLen) * NumPulsePoTs * (FftLength - 1); // ! hard to estimate, so be generous and use 9 analysis_state.FLOP_counter+=810.0; // (10.0*numBinsAboveThreshold*numBinsAboveThreshold); progress += ProgressUnitSize * TripletProgressUnits(); } if(!SkipPulse) has_dataP = cudaAcc_fetchPulseFlags(SkipTriplet, PulsePoTLen, AdvanceBy, FftLength, offset); if(!SkipPulse) { if((has_dataP & 2) && !(has_dataP & 8)) // has pulse data and no error in pulse { //printf("processPulseResults\r\n"); cudaAcc_processPulseResults(PulsePoTLen, AdvanceBy, FftLength); } analysis_state.FLOP_counter+=(PulsePoTLen*0.1818181818182+400.0)*PulsePoTLen * NumPulsePoTs * (FftLength - 1); progress += ProgressUnitSize * PulseProgressUnits(PulsePoTLen, FftLength - 1); } //#ifndef CUDAACC_EMULATION //if(!SkipTriplet) // cudaAcc_fetchTripletAndPulseFlags(SkipTriplet, SkipPulse, PulsePoTLen, AdvanceBy, FftLength); progress=std::min(progress,1.0); // prevent display of > 100% fraction_done(progress,remaining); //if(!SkipTriplet) // cudaAcc_processTripletResults(PulsePoTLen, AdvanceBy, FftLength); //#endif //CUDAACC_EMULATION } // else // { #endif //USE_CUDA // loop through frequencies /* for(; ThisPoT < FftLength; ThisPoT++) { // loop through time for each frequency. PulsePoTNum is // used only for progress calculation. for(TOffset = 0, PulsePoTNum = 1, TOffsetOK = true; TOffsetOK; PulsePoTNum++, TOffset += AdvanceBy) { // Create PowerOfTime array for pulse detection. If there // are not enough points left in this PoT, adjust TOffset // to get the latest possible pulse PoT. if(TOffset + PulsePoTLen >= PoTLen) { TOffsetOK = false; TOffset = PoTLen - PulsePoTLen; } if (use_transposed_pot) { memcpy(PulsePoT, &PowerSpectrum[ThisPoT * PoTLen + TOffset], PulsePoTLen*sizeof(float)); } else { for(i = 0; i < PulsePoTLen; i++) { PulsePoT[i] = PowerSpectrum[ThisPoT + (TOffset+i) * FftLength]; } } if(!SkipTriplet) { retval = find_triplets(PulsePoT, PulsePoTLen, (float)PoTInfo.TripletThresh, TOffset, ThisPoT); if (retval) SETIERROR(retval,"from find_triplets()"); } //#ifndef CUDAACC_EMULATION if(!SkipPulse) { retval = find_pulse(PulsePoT, PulsePoTLen, (float)PoTInfo.PulseThresh, TOffset, ThisPoT ); if (retval) SETIERROR(retval,"from find_pulse()"); } //#endif //CUDAACC_EMULATION // At the end of each pulse PoT we update progress. Progress // will thus get updted several times per frequency bin. #ifdef BOINC_APP_GRAPHICS if (!nographics()) { sah_graphics->local_progress = (((ThisPoT-1) * NumPulsePoTs) + PulsePoTNum) * ProgressPerPulsePoT; } #endif if(!SkipTriplet) { progress += (ProgressUnitSize * TripletProgressUnits()) / (float)(FftLength - 1) / NumPulsePoTs; } if(!SkipPulse) { progress += (ProgressUnitSize * PulseProgressUnits(PulsePoTLen, FftLength - 1)) / (float)(FftLength - 1) / NumPulsePoTs; } progress=std::min(progress,1.0); // prevent display of > 100% fraction_done(progress,remaining); } // end loop through time for each frequency // At the end of each frequency bin we save state. analysis_state.PoT_activity = POT_DOING_PULSE; analysis_state.PoT_freq_bin = ThisPoT; retval = checkpoint(); if (retval) SETIERROR(retval,"from checkpoint()"); } // end loop through frequencies analysis_state.PoT_freq_bin = -1; analysis_state.PoT_activity = POT_INACTIVE; #ifdef USE_CUDA } #endif //USE_CUDA */ } // end looking for pulses if(b_gaussStarted) // process results late { //printf("late GaussBlock\r\n"); int flags = cudaAcc_fetchGaussfitFlags(FftLength, best_gauss->score); if(flags>0) cudaAcc_processGaussFit(FftLength, best_gauss->score); } return (retval); // no error return point }
int FindSpikes( float * fp_PowerSpectrum, int ul_NumDataPoints, int fft_num, SETI_WU_INFO& swi ) { //int i, j, k, m, bin, retval; int i, j, k, m, retval, blksize; float temp, partial; //float total, MeanPower, spike_score; float total, MeanPower; SPIKE_INFO si; i = j = k = m = 0; total = 0.0; blksize = UNSTDMAX(8, UNSTDMIN(pow2((unsigned int) sqrt((float) (ul_NumDataPoints / 32)) * 32), 512)); for(int b = 0; b < ul_NumDataPoints/blksize; b++) { partial = 0.0f; for(i = 0; i < blksize; i++) { partial += fp_PowerSpectrum[b*blksize+i]; } total += partial; } MeanPower = total / ul_NumDataPoints; // for(i = 0; i < ul_NumDataPoints; i++) { // total += fp_PowerSpectrum[i]; // } // MeanPower = total / ul_NumDataPoints; // Here we extract the spikes_to_report highest power events, // outputing them as we go. // Index usage: // i : walk power spectrum us_NumToReport times // j : walks power spectrum for each i // k : marks current high power candidate while j walks on // m : marks the current tail of the high power hit "list" for(i = 0; i < swi.analysis_cfg.spikes_per_spectrum; i++) { temp = 0.0f; // Walk the array, looking for the first/next highest power. // Start j at 1, in order to skip the DC (ie 0) bin. // NOTE: this is a simple scan for high powers. Nice and fast // for a very low i. If i is substantial, this code should be // replaced with an index (q)sort. Do *not* sort the power // spectrum itself in place - it's used elsewhere. float mval = fp_PowerSpectrum[m]; for (j = 1; j < ul_NumDataPoints; j++) { float val = fp_PowerSpectrum[j]; if (val > temp) { if (val < mval || m == 0) { temp = val; k = j; } } } // temp now = first/next highest power and k = it's bin number m = k; // save the "lowest" highest. float score = si.s.peak_power / SPIKE_SCORE_HIGH; bool sidone = false; // if best_spike.s.fft_len == 0, there is not yet a first spike if (si.score > best_spike->score || best_spike->s.fft_len == 0) { // spike info si.s.peak_power = temp/MeanPower; si.s.mean_power = 1.0; si.bin = k; si.fft_ind = fft_num; si.s.chirp_rate = ChirpFftPairs[analysis_state.icfft].ChirpRate; si.s.fft_len = ChirpFftPairs[analysis_state.icfft].FftLen; si.s.freq = cnvt_bin_hz(si.bin, si.s.fft_len); double t_offset=((double)si.fft_ind+0.5)*(double)si.s.fft_len/ swi.subband_sample_rate; si.s.detection_freq=calc_detection_freq(si.s.freq,si.s.chirp_rate,t_offset); si.s.time = swi.time_recorded + t_offset / 86400.0; time_to_ra_dec(si.s.time, &si.s.ra, &si.s.decl); // Score used for "best of" and graphics. si.score = score; si.score = si.score > 0.0f ? (float)log10(si.score) : 0.0f; *best_spike = si; sidone = true; #ifdef BOINC_APP_GRAPHICS if (!nographics()) sah_graphics->si.copy(&si); #endif } // Report a signal if it excceeds threshold. if(si.s.peak_power > (swi.analysis_cfg.spike_thresh)) { if(!sidone) { // spike info si.s.peak_power = temp/MeanPower; si.s.mean_power = 1.0; si.bin = k; si.fft_ind = fft_num; si.s.chirp_rate = ChirpFftPairs[analysis_state.icfft].ChirpRate; si.s.fft_len = ChirpFftPairs[analysis_state.icfft].FftLen; si.s.freq = cnvt_bin_hz(si.bin, si.s.fft_len); double t_offset=((double)si.fft_ind+0.5)*(double)si.s.fft_len/ swi.subband_sample_rate; si.s.detection_freq=calc_detection_freq(si.s.freq,si.s.chirp_rate,t_offset); si.s.time = swi.time_recorded + t_offset / 86400.0; time_to_ra_dec(si.s.time, &si.s.ra, &si.s.decl); // Score used for "best of" and graphics. si.score = score; si.score = si.score > 0.0f ? (float)log10(si.score) : 0.0f; *best_spike = si; } retval = result_spike(si); if (retval) SETIERROR(retval,"from result_spike()"); } } return 0; }
int FindSpikes2( int ul_NumDataPoints, int fft_num, SETI_WU_INFO& swi, float total, float temp, // maximum int pos) { // Here we extract the spikes_to_report highest power events, // outputing them as we go. // Index usage: // i : walk power spectrum us_NumToReport times // j : walks power spectrum for each i // k : marks current high power candidate while j walks on // m : marks the current tail of the high power hit "list" if(swi.analysis_cfg.spikes_per_spectrum > 0) { int i = 0, j = 0, k = 0, m = 0, retval; float fMeanPower = total / ul_NumDataPoints; float fPeakPower = (temp / fMeanPower); //+0.005f; float fScore = fPeakPower / SPIKE_SCORE_HIGH; fScore = (fScore > 0.0f) ? (float)log10( fScore ) : 0.0f; // If we'll need this result, compute pertinent data and place in tmp_spike if ( (fScore > best_spike->score) || (best_spike->s.fft_len == 0) || (fPeakPower > swi.analysis_cfg.spike_thresh) ) { k = pos; m = k; // save the "lowest" highest. tmp_spike->s.peak_power = fPeakPower; tmp_spike->s.mean_power = 1.0; tmp_spike->score = fScore; tmp_spike->bin = k; tmp_spike->fft_ind = fft_num; tmp_spike->s.chirp_rate = ChirpFftPairs[analysis_state.icfft].ChirpRate; tmp_spike->s.fft_len = ChirpFftPairs[analysis_state.icfft].FftLen; tmp_spike->s.freq = cnvt_bin_hz( tmp_spike->bin, tmp_spike->s.fft_len ); double t_offset = ( (double)tmp_spike->fft_ind + 0.5 ) * (double)tmp_spike->s.fft_len / swi.subband_sample_rate; tmp_spike->s.detection_freq = calc_detection_freq( tmp_spike->s.freq, tmp_spike->s.chirp_rate, t_offset ); tmp_spike->s.time = swi.time_recorded + t_offset / 86400.0; time_to_ra_dec( tmp_spike->s.time, &tmp_spike->s.ra, &tmp_spike->s.decl ); } // This is the best spike, so copy to best_spike if ( (fScore > best_spike->score) || (best_spike->s.fft_len == 0) ) { *best_spike = *tmp_spike; #ifdef BOINC_APP_GRAPHICS if( !nographics() ) { sah_graphics->si.copy( tmp_spike, true ); } #endif } // Report a signal if it exceeds threshold if( fPeakPower > swi.analysis_cfg.spike_thresh ) { retval = result_spike( *tmp_spike ); if( retval ) { SETIERROR(retval,"from result_spike()"); } } } return 0; }
int ChooseGaussEvent( int ifft, float PeakPower, float TrueMean, float ChiSq, float null_ChiSq, int bin, float sigma, float PoTMaxPower, float fp_PoT[] ) { #ifdef USE_MANUAL_CALLSTACK call_stack.enter("ChooseGaussEvent"); #endif GAUSS_INFO gi; float scale_factor; bool report, chisqOK=(ChiSq <= swi.analysis_cfg.gauss_chi_sq_thresh); // gaussian info gi.bin = bin; gi.fft_ind = ifft; gi.g.chirp_rate = ChirpFftPairs[analysis_state.icfft].ChirpRate; gi.g.fft_len = ChirpFftPairs[analysis_state.icfft].FftLen; gi.g.sigma = sigma; gi.g.peak_power = PeakPower; gi.g.mean_power = TrueMean; gi.g.chisqr = ChiSq; gi.g.null_chisqr = null_ChiSq; gi.g.freq = cnvt_bin_hz(bin, gi.g.fft_len); double t_offset=(((double)gi.fft_ind+0.5)/swi.analysis_cfg.gauss_pot_length)* PoTInfo.WUDuration; gi.g.detection_freq =calc_detection_freq(gi.g.freq,gi.g.chirp_rate,t_offset); gi.g.time = swi.time_recorded+t_offset/86400.0; gi.g.max_power = PoTMaxPower; gi.score = -13.0; time_to_ra_dec(gi.g.time, &gi.g.ra, &gi.g.decl); // Scale PoT down to 256 16 bit ints. //for (i=0; i<swi.analysis_cfg.gauss_pot_length; i++) gi.pot[i] = fp_PoT[i]; // ??? scale_factor = static_cast<float>(gi.g.max_power) / 255.0f; if (gi.g.pot.size() != static_cast<size_t>(swi.analysis_cfg.gauss_pot_length)) { gi.g.pot.set_size(swi.analysis_cfg.gauss_pot_length); } float_to_uchar(fp_PoT, &(gi.g.pot[0]), swi.analysis_cfg.gauss_pot_length, scale_factor); if (!swi.analysis_cfg.gauss_null_chi_sq_thresh) swi.analysis_cfg.gauss_null_chi_sq_thresh=1.890; // Gauss score used for "best of" and graphics. // This score is now set to be based upon the probability that a signal // would occur due to noise and the probability that it is shaped like // a Gaussian (normalized to 0 at thresholds). Thanks to Tetsuji for // making me think about this. The Gaussian has 62 degrees of freedom and // the null hypothesis has 63 degrees of freedom when gauss_pot_length=64; //JWS: Calculate invariant terms once, ala Alex Kan and Przemyslaw Zych static float gauss_bins = static_cast<float>(swi.analysis_cfg.gauss_pot_length); static float gauss_dof = gauss_bins - 2.0f; static float null_dof = gauss_bins - 1.0f; static double score_offset = ( lcgf(0.5*null_dof, swi.analysis_cfg.gauss_null_chi_sq_thresh*0.5*gauss_bins) -lcgf(0.5*gauss_dof, swi.analysis_cfg.gauss_chi_sq_thresh*0.5*gauss_bins) ); //R: same optimization as for GPU build: if there is reportable Gaussian already - //R: skip score calculation for all except new reportable Gaussians // Final thresholding first. report = chisqOK && (gi.g.peak_power >= gi.g.mean_power * swi.analysis_cfg.gauss_peak_power_thresh) && (gi.g.null_chisqr >= swi.analysis_cfg.gauss_null_chi_sq_thresh); if (gaussian_count==0||report) { gi.score = score_offset +lcgf(0.5*gauss_dof,std::max(gi.g.chisqr*0.5*gauss_bins,0.5*gauss_dof+1)) -lcgf(0.5*null_dof,std::max(gi.g.null_chisqr*0.5*gauss_bins,0.5*null_dof+1)); } // Only include "real" Gaussians (those meeting the chisqr threshold) // in the best Gaussian display. if (gi.score > best_gauss->score && chisqOK) { *best_gauss = gi; } // Update gdata gauss info regardless of whether it is the // best thus far or even passes the final threshold. If // a gaussian has made it this far, display it. #ifdef BOINC_APP_GRAPHICS if (!nographics()) sah_graphics->gi.copy(&gi); #endif analysis_state.FLOP_counter+=24.0; // Final reporting. if (report) { int retval=result_gaussian(gi); #ifdef USE_MANUAL_CALLSTACK call_stack.exit(); #endif return retval; } #ifdef USE_MANUAL_CALLSTACK call_stack.exit(); #endif return 0; }
int ReportPulseEvent(float PulsePower,float MeanPower, float period, int time_bin,int freq_bin, float snr, float thresh, float *folded_pot, int scale, int write_pulse) { PULSE_INFO pi; pulse pulse; int retval=0, i, len_prof=static_cast<int>(floor(period)); float step,norm,index,MinPower=PulsePower*MeanPower*scale; // debug possible heap corruption -- jeffc #ifdef _WIN32 BOINCASSERT(_CrtCheckMemory()); #endif // pulse info pi.score=snr/thresh; pi.p.peak_power=PulsePower-1; pi.p.mean_power=MeanPower; pi.p.fft_len=ChirpFftPairs[analysis_state.icfft].FftLen; pi.p.chirp_rate=ChirpFftPairs[analysis_state.icfft].ChirpRate; pi.p.period=static_cast<float>(period*static_cast<double>(pi.p.fft_len)/swi.subband_sample_rate); pi.p.snr = snr; pi.p.thresh = thresh; pi.p.len_prof = len_prof; pi.freq_bin=freq_bin; pi.time_bin=time_bin; pi.p.freq=cnvt_bin_hz(freq_bin, pi.p.fft_len); double t_offset=(static_cast<double>(time_bin)+0.5) *static_cast<double>(pi.p.fft_len)/ swi.subband_sample_rate; pi.p.detection_freq=calc_detection_freq(pi.p.freq,pi.p.chirp_rate,t_offset); pi.p.time=swi.time_recorded+t_offset/86400.0; time_to_ra_dec(pi.p.time, &pi.p.ra, &pi.p.decl); for (i=0;i<len_prof;i++) { if (folded_pot[i]<MinPower) MinPower=folded_pot[i]; } norm=255.0f/((PulsePower*MeanPower*scale-MinPower)); // Populate the min and max PoT arrays. These are only used // for graphics. #ifdef BOINC_APP_GRAPHICS if (!nographics()) { step=static_cast<float>(len_prof)/swi.analysis_cfg.pulse_pot_length; index=0; for (i=0;i<swi.analysis_cfg.pulse_pot_length;i++) { pi.pot_min[i]=255; pi.pot_max[i]=0; int j; for (j=0; j<step; j++) { unsigned int pot = static_cast<unsigned int>((folded_pot[static_cast<int>(floor(index))+j]-MinPower)*norm); if (pot<pi.pot_min[i]) { pi.pot_min[i]=pot; } if (pi.pot_min[i] >= 256) pi.pot_min[i] = 255; // kludge until we fix the assert failures BOINCASSERT(pi.pot_min[i] < 256); if (pot>pi.pot_max[i]) pi.pot_max[i]=pot; if (pi.pot_max[i] >= 256) pi.pot_max[i] = 255; // kludge until we fix the assert failures BOINCASSERT(pi.pot_max[i] < 256); } index+=step; } } #endif // Populate the result PoT if the folded PoT will fit. if (pi.p.len_prof < swi.analysis_cfg.pulse_pot_length) { pi.p.pot.resize(len_prof); for (i=0;i<len_prof;i++) { pi.p.pot[i] = (unsigned char)((folded_pot[i]-MinPower)*norm); } } else { pi.p.pot.clear(); } // Update gdata pulse info regardless of whether it is the // best thus far. If a pulse has made it this far, display it. #ifdef BOINC_APP_GRAPHICS if (!nographics()) sah_graphics->pi.copy(&pi); #endif // best thus far ? if (pi.score>best_pulse->score) { *best_pulse=pi; } if (write_pulse) { if (signal_count > swi.analysis_cfg.max_signals) { SETIERROR(RESULT_OVERFLOW,"in ReportPulseEvent"); } //for (i=0;i<len_prof;i++) { // sprintf(&pi.p.pot[i], "%02x",(int)((folded_pot[i]-MinPower)*norm)); // } retval = outfile.printf("%s", pi.p.print_xml(0,0,1).c_str()); if (retval >= 0) { outfile.printf("\n"); } if (retval < 0) { SETIERROR(WRITE_FAILED,"in ReportPulseEvent"); } else { signal_count++; pulse_count++; } } // debug possible heap corruption -- jeffc #ifdef _WIN32 BOINCASSERT(_CrtCheckMemory()); #endif return(retval); }
int ReportTripletEvent( float Power, float MeanPower, float period, float mid_time_bin, int start_time_bin, int freq_bin, int pot_len,const float *PoT, int write_triplet ) { TRIPLET_INFO ti; triplet triplet; int retval=0, i, j; double step,norm,index; double max_power=0; static int * inv; // debug possible heap corruption -- jeffc #ifdef _WIN32 BOINCASSERT(_CrtCheckMemory()); #endif if (!inv) inv = (int*)calloc_a(swi.analysis_cfg.triplet_pot_length, sizeof(int), MEM_ALIGN); // triplet info ti.score=Power; ti.t.peak_power=Power; ti.t.mean_power=MeanPower; ti.freq_bin=freq_bin; ti.time_bin=mid_time_bin+start_time_bin+0.5f; ti.t.chirp_rate=ChirpFftPairs[analysis_state.icfft].ChirpRate; ti.t.fft_len=ChirpFftPairs[analysis_state.icfft].FftLen; ti.bperiod=period; ti.t.period=static_cast<float>(period*static_cast<double>(ti.t.fft_len)/swi.subband_sample_rate); ti.t.freq=cnvt_bin_hz(freq_bin, ti.t.fft_len); double t_offset=(static_cast<double>(mid_time_bin)+start_time_bin+0.5) *static_cast<double>(ti.t.fft_len)/ swi.subband_sample_rate; ti.t.detection_freq=calc_detection_freq(ti.t.freq,ti.t.chirp_rate,t_offset); ti.t.time=swi.time_recorded+t_offset/86400.0; time_to_ra_dec(ti.t.time, &ti.t.ra, &ti.t.decl); // Populate the min and max PoT arrays. These are only used // for graphics. memset(ti.pot_min,0xff,swi.analysis_cfg.triplet_pot_length*sizeof(int)); memset(ti.pot_max,0,swi.analysis_cfg.triplet_pot_length*sizeof(int)); step=static_cast<double>(pot_len)/swi.analysis_cfg.triplet_pot_length; ti.scale=static_cast<float>(1.0/step); index=0; for (i=0;i<pot_len;i++) { if (PoT[i]>max_power) max_power=PoT[i]; } norm=255.0/max_power; float mtb = mid_time_bin; if (pot_len > swi.analysis_cfg.triplet_pot_length) { ti.tpotind0_0 = ti.tpotind0_1 = static_cast<int>(((mtb-period)*swi.analysis_cfg.triplet_pot_length)/pot_len); ti.tpotind1_0 = ti.tpotind1_1 = static_cast<int>(((mtb)*swi.analysis_cfg.triplet_pot_length)/pot_len); ti.tpotind2_0 = ti.tpotind2_1 = static_cast<int>(((mtb+period)*swi.analysis_cfg.triplet_pot_length)/pot_len); for (j=0; j<pot_len; j++) { i = (j*swi.analysis_cfg.triplet_pot_length)/pot_len; if ((PoT[j]*norm)<ti.pot_min[i]) { ti.pot_min[i]=static_cast<unsigned int>(floor(PoT[j]*norm)); } if ((PoT[j]*norm)>ti.pot_max[i]) { ti.pot_max[i]=static_cast<unsigned int>(floor(PoT[j]*norm)); } } } else { memset(inv, -1, sizeof(inv)); for (i=0;i<swi.analysis_cfg.triplet_pot_length;i++) { j = (i*pot_len)/swi.analysis_cfg.triplet_pot_length; if (inv[j] < 0) inv[j] = i; if ((PoT[j]*norm)<ti.pot_min[i]) { ti.pot_min[i]=static_cast<unsigned int>(floor(PoT[j]*norm)); } if ((PoT[j]*norm)>ti.pot_max[i]) { ti.pot_max[i]=static_cast<unsigned int>(floor(PoT[j]*norm)); } } ti.tpotind0_0 = inv[static_cast<int>(mtb-period)]; ti.tpotind0_1 = inv[static_cast<int>(mtb-period+1)]; ti.tpotind1_0 = (inv[static_cast<int>(mtb)]+inv[static_cast<int>(mtb+1)])/2; ti.tpotind1_1 = (inv[static_cast<int>(mtb+1)]+inv[static_cast<int>(mtb+2)])/2; ti.tpotind2_0 = inv[static_cast<int>(mtb+period)]; if (mtb+period+1 >= pot_len) ti.tpotind2_1 = swi.analysis_cfg.triplet_pot_length-1; else ti.tpotind2_1 = inv[static_cast<int>(mtb+period+1)]; } // Update sah_graphics triplet info regardless of whether it is the // best thus far. If a triplet has made it this far, display it. #ifdef BOINC_APP_GRAPHICS if (!nographics()) sah_graphics->ti.copy(&ti); #endif // best thus far ? if (ti.score>best_triplet->score) { *best_triplet=ti; } if (write_triplet) { if (signal_count > swi.analysis_cfg.max_signals) { SETIERROR(RESULT_OVERFLOW,"in ReportTripletEvent"); } retval = outfile.printf("%s", ti.t.print_xml(0,0,1).c_str()); if (retval < 0) { SETIERROR(WRITE_FAILED,"in ReportTripletEvent"); } else { signal_count++; triplet_count++; } } // debug possible heap corruption -- jeffc #ifdef _WIN32 BOINCASSERT(_CrtCheckMemory()); #endif return(retval); }