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 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 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 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); }