void TuneFilterDecimate_i::configureTFD(BULKIO::StreamSRI &sri) { LOG_TRACE(TuneFilterDecimate_i, "Configuring SRI: " << "sri.xdelta = " << sri.xdelta << "sri.streamID = " << sri.streamID) Real tmpInputSampleRate = 1 / sri.xdelta; // Calculate sample rate received from SRI bool lastInputComplex = inputComplex; if (sri.mode==1) { inputComplex=true; chan_if =0.0; //center of band is 0 if we are complex } else { inputComplex = false; chan_if = tmpInputSampleRate/4.0; //center of band is fs/4 if we are real //output is always complex even if input is real sri.mode=1; } DecimationFactor = floor(tmpInputSampleRate/DesiredOutputRate); LOG_DEBUG(TuneFilterDecimate_i, "DecimationFactor = " << DecimationFactor); if (DecimationFactor <1) { LOG_WARN(TuneFilterDecimate_i, "Decimation less than 1, setting to minimum") DecimationFactor=1; } bool sampleRateChanged =(InputRate != tmpInputSampleRate); if (sampleRateChanged) { InputRate = tmpInputSampleRate; LOG_DEBUG(TuneFilterDecimate_i, "Sample rate changed: InputRate = " << InputRate); } // Calculate new output sample rate & modify the referenced SRI structure ActualOutputRate = InputRate / DecimationFactor; sri.xdelta = 1.0 / ActualOutputRate; LOG_DEBUG(TuneFilterDecimate_i, "Output xdelta = " << sri.xdelta << " ActualOutputRate " << ActualOutputRate); if (ActualOutputRate < FilterBW) LOG_WARN(TuneFilterDecimate_i, "ActualOutputRate " << ActualOutputRate << " is less than FilterBW " << FilterBW); // Retrieve the front-end collected RF to determine the IF bool validCollectionRF = false; bool validChannelRF = false; double collection_rf = getKeywordByID<CORBA::Double>(sri, "COL_RF", validCollectionRF); double channel_rf = getKeywordByID<CORBA::Double>(sri, "CHAN_RF", validChannelRF); double tmpInputRF; if ((validCollectionRF) && (validChannelRF)) { LOG_WARN(TuneFilterDecimate_i, "Input SRI contains both COL_RF and CHAN_RF, using CHAN_RF"); tmpInputRF = channel_rf; } else if (validCollectionRF) { tmpInputRF = collection_rf; } else if (validChannelRF) { tmpInputRF = channel_rf; } else { if (TuneMode == "RF") { LOG_WARN(TuneFilterDecimate_i, "Input SRI lacks RF keyword. RF tuning cannot be performed."); return; } tmpInputRF = 0; } bool inputComplexChanged = lastInputComplex ^ inputComplex; if (tmpInputRF != InputRF) { LOG_DEBUG(TuneFilterDecimate_i, "Input RF changed " << tmpInputRF); InputRF = tmpInputRF; // If the TuneMode is RF, we actually need to retune if (TuneMode == "RF") { configureTuner("TuningRF"); } else if (TuneMode == "NORM") { configureTuner("TuningNorm"); } TuningRF = InputRF + TuningIF - chan_if; LOG_DEBUG(TuneFilterDecimate_i, "Tuning RF: " << TuningRF); } else if (TuneMode == "RF" && inputComplexChanged) { //the RF didn't change but the IF is changing because we have switched between real and complex data configureTuner("TuningRF"); LOG_DEBUG(TuneFilterDecimate_i, "Tuning RF: " << TuningRF); } // Add the CHAN_RF keyword to the SRI if we know the input RF if (InputRF != 0) { if(!setKeywordByID<CORBA::Double>(sri, "CHAN_RF", (double)TuningRF)) LOG_WARN(TuneFilterDecimate_i, "SRI Keyword CHAN_RF could not be set."); } // Reconfigure the tuner classes only if the sample rate has changed if ((tuner== NULL) || sampleRateChanged) { LOG_DEBUG(TuneFilterDecimate_i, "Remaking tuner"); if (tuner != NULL) { delete tuner; } if (TuneMode == "NORM") { configureTuner("TuningNorm"); } else if (TuneMode == "IF") { configureTuner("TuningIF"); } else if (TuneMode == "RF") { configureTuner("TuningRF"); } tuner = new Tuner(tunerInput, f_complexIn, TuningNorm); } if ((filter==NULL) || sampleRateChanged || RemakeFilter) { LOG_DEBUG(TuneFilterDecimate_i, "Remaking filter"); if((filter != NULL) || (decimate != NULL)) { delete filter; delete decimate; } /* * ASCII ART to explain the filter design * * Lowpass (Real filter) * ---------| * \ * \ * \ * | * ---------------------------------- * 0 FL FL+tw fsOut/2 fsIn/2 * * The basic gist is we tune first, then filter. * Then we filter * Then we decimate * * This means the filter is a LOWPASS filter which must be designed given the INPUT sampling frequency. * The transition frequency happens at 1/2 the requested tune bandwidth. Thus FL = FilterBW / 2.0. * We need the transition region to "finish" by fsOut/2 to avoid aliasing, so we do a check for that too. * */ Real FL = FilterBW / 2.0; //calculate the transition frequency necessary to avoid aliasing Real maxTW = (ActualOutputRate/2.0)-FL; if (maxTW > 0 && maxTW < filterProps.TransitionWidth) { LOG_WARN(TuneFilterDecimate_i, "input transition width "<< filterProps.TransitionWidth<<" too large - replacing with "<< maxTW); filterProps.TransitionWidth = maxTW; } // We generate our FIR filter taps here. The read-only property 'taps' is set. // - We use the transition width and ripple specified by the user to create the filter taps. // - Normalized lowpass cutoff frequency is the only one we need; upper cutoff not used RealVector tmpVec; taps = filterdesigner_.wdfirHz(tmpVec, FIRFilter::lowpass, filterProps.Ripple, filterProps.TransitionWidth, FL, 0, InputRate, MIN_NUM_TAPS, MAX_NUM_TAPS); filterCoeff.clear(); filterCoeff.reserve(tmpVec.size()); for (RealVector::iterator i = tmpVec.begin(); i!=tmpVec.end(); i++) filterCoeff.push_back(*i); // Minimum FFT_size implemented size_t minFftSize = std::max(MIN_FFT_SIZE, pow2ge(2*taps)); if(filterProps.FFT_size < minFftSize) { LOG_DEBUG(TuneFilterDecimate_i, "FFT_size too small, set to " << minFftSize); filterProps.FFT_size = minFftSize; } else if (filterProps.FFT_size > MAX_FFT_SIZE) { LOG_DEBUG(TuneFilterDecimate_i, "FFT_size too large, set to " << MAX_FFT_SIZE); filterProps.FFT_size = MAX_FFT_SIZE; } filter = new firfilter(filterProps.FFT_size, f_realOut, f_complexOut, filterCoeff); decimate = new Decimate(f_complexOut, decimateOutput, DecimationFactor); RemakeFilter = false; } LOG_TRACE(TuneFilterDecimate_i, "Exit configureSRI()"); }
real CompressedDataColumn::sumColumn(int nRows) { RealVector values; fill(values, nRows); return std::accumulate(values.begin(), values.end(), static_cast<real>(0.0)); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// devImprovedPeakAlgorithm //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void DevSuite::devImprovedPeakAlgorithm() { Logger msg( "devImprovedPeakAlgorithm" ); msg << Msg::Info << "Running devImprovedPeakAlgorithm..." << Msg::EndReq; // Take fourier bin size = 4096 // Take sine with phase = 0 // Make center frequency variable // Pick range around center frequency with delta_freq // Compute max rel amp as function of freq delta (envelope) // First sort by amp, remove all non-increasing frequency entries size_t fourierSize = 4096; size_t zeroPadSize = 3*fourierSize; const RealVector& centreFreqs = realVector( 400 ); double deltaRange = 100; size_t numFreqs = 100; const double freqDelta = deltaRange / numFreqs; SamplingInfo samplingInfo; Synthesizer::SineGenerator sineGen( samplingInfo ); RealVector relMaxY; RealVector diffX; for ( size_t iCentreFreq = 0; iCentreFreq < centreFreqs.size(); ++iCentreFreq ) { for ( size_t iFreq = 0; iFreq < numFreqs; ++iFreq ) { double frequency = centreFreqs[ iCentreFreq ] + freqDelta * iFreq; sineGen.setFrequency( frequency ); RawPcmData::Ptr data = sineGen.generate( fourierSize ); WaveAnalysis::SpectralReassignmentTransform transform( samplingInfo, fourierSize, zeroPadSize, 2 ); WaveAnalysis::StftData::Ptr stftData = transform.execute( *data ); const WaveAnalysis::SrSpectrum& spec = stftData->getSrSpectrum( 0 ); const RealVector& x = spec.getFrequencies(); RealVector&& y = spec.getMagnitude(); y /= Utils::getMaxValue( y ); RealVector deltaX = x - frequency; // msg << Msg::Info << deltaX << Msg::EndReq; relMaxY.insert( relMaxY.end(), y.begin(), y.end() ); diffX.insert( diffX.end(), deltaX.begin(), deltaX.end() ); } } SortCache relYSc( diffX ); const RealVector& relMaxYSorted = relYSc.applyTo( relMaxY ); const RealVector& relDiffXSorted = relYSc.applyTo( diffX ); Math::Log10Function log10; gPlotFactory().createPlot( "envelope" ); gPlotFactory().createGraph( relDiffXSorted, relMaxYSorted ); // Create envelope by requiring linear interpolation is always above curve. size_t nEnvelopeSamples = 500; RealVector linearGrid = Utils::createRangeReal( -1000, 1000, nEnvelopeSamples ); RealVector zeros = RealVector( nEnvelopeSamples, 0 ); gPlotFactory().createScatter( linearGrid, zeros, Plotting::MarkerDrawAttr( Qt::red ) ); gPlotFactory().createPlot( "envelopLog" ); gPlotFactory().createGraph( relDiffXSorted, log10.evalMany( relMaxYSorted ) ); // RealVector fCorr = spec.getFrequencyCorrections(); // for ( size_t i = 0; i < spec.getFrequencies().size(); ++i ) // { // fCorr[ i ] /= spec.getFrequency( i ); // } // Math::Log10Function log10Fct; // gPlotFactory().createPlot( "plot1" ); // gPlotFactory().createGraph( x, log10Fct.evalMany( y ), Qt::blue ); // gPlotFactory().createScatter( x, log10Fct.evalMany( y ) ); // gPlotFactory().createGraph( x, log10Fct.evalMany( fCorr ), Qt::green ); // gPlotFactory().createScatter( x, log10Fct.evalMany( fCorr ), Plotting::MarkerDrawAttr( Qt::red ) ); // msg << Msg::Info << "Number of spectra in STFT: " << stftData->getNumSpectra() << Msg::EndReq; // for ( size_t iSpec = 0; iSpec < stftData->getNumSpectra(); ++iSpec ) // { // const WaveAnalysis::WindowLocation* windowLoc = stftData->getSpectrum( iSpec ).getWindowLocation(); // msg << Msg::Info << "WindowLocation: [" << windowLoc->getFirstSample() << ", " << windowLoc->getLastSample() << "]" << Msg::EndReq; // } }