// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> bool AmplitudeProcessor_Mjma::deconvolveData(Response *resp, DoubleArray &data, int numberOfIntegrations) { Math::Restitution::FFT::TransferFunctionPtr tf = resp->getTransferFunction(numberOfIntegrations); if ( tf == NULL ) { setStatus(DeconvolutionFailed, 0); return false; } Math::SeismometerResponse::Seismometer5sec paz(Math::Velocity); Math::Restitution::FFT::PolesAndZeros seis5sec(paz); Math::Restitution::FFT::TransferFunctionPtr cascade = *tf / seis5sec; // Remove linear trend double m,n; Math::Statistics::computeLinearTrend(data.size(), data.typedData(), m, n); Math::Statistics::detrend(data.size(), data.typedData(), m, n); return Math::Restitution::transformFFT(data.size(), data.typedData(), _stream.fsamp, cascade.get(), _config.respTaper, _config.respMinFreq, _config.respMaxFreq); }
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> bool AmplitudeProcessor_Md::deconvolveData(Response* resp, DoubleArray& data, int numberOfIntegrations) { if ( numberOfIntegrations < -1 ) return false; SEISCOMP_DEBUG("Inside deconvolve function"); double m, n; Math::Restitution::FFT::TransferFunctionPtr tf = resp->getTransferFunction(numberOfIntegrations < 0 ? 0 : numberOfIntegrations); if ( !tf ) return false; Math::GroundMotion gm; if ( numberOfIntegrations < 0 ) gm = Math::Displacement; else gm = Math::Velocity; Math::Restitution::FFT::TransferFunctionPtr cascade; Math::SeismometerResponse::WoodAnderson woodAndersonResp(gm, _config.woodAndersonResponse); Math::SeismometerResponse::Seismometer5sec seis5sResp(gm); Math::SeismometerResponse::L4C_1Hz l4c1hzResp(gm); Math::Restitution::FFT::PolesAndZeros woodAnderson(woodAndersonResp); Math::Restitution::FFT::PolesAndZeros seis5sec(seis5sResp); Math::Restitution::FFT::PolesAndZeros l4c1hz(l4c1hzResp); SEISCOMP_DEBUG("SEISMO = %d", aFile.SEISMO); switch ( aFile.SEISMO ) { case 1: cascade = *tf / woodAnderson; break; case 2: cascade = *tf / seis5sec; break; case 9: SEISCOMP_INFO("%s Applying filter L4C 1Hz to data", AMPTAG); cascade = *tf / l4c1hz; break; default: cascade = tf; SEISCOMP_INFO("%s No seismometer specified, no signal reconvolution performed", AMPTAG); return false; break; } // Remove linear trend Math::Statistics::computeLinearTrend(data.size(), data.typedData(), m, n); Math::Statistics::detrend(data.size(), data.typedData(), m, n); return Math::Restitution::transformFFT(data.size(), data.typedData(), _stream.fsamp, cascade.get(), _config.respTaper, _config.respMinFreq, _config.respMaxFreq); }
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> void SpectrumWidget::updateData() { _powerSpectrum.clear(); _responseCorrectedPowerSpectrum.clear(); _responsePowerSpectrum.clear(); if ( (_spec.size() < 2) || (_freqNyquist <= 0) ) { _xAxis.setRange(_powerSpectrum.x); return; } // Ignore the first value, this is the offset _powerSpectrum.y.resize(_spec.size()-1); if ( _phaseSpectrum ) { for ( size_t i = 1; i < _spec.size(); ++i ) _powerSpectrum.y[i-1] = rad2deg(arg(_spec[i])); } else { for ( size_t i = 1; i < _spec.size(); ++i ) _powerSpectrum.y[i-1] = abs(_spec[i]); } _powerSpectrum.x.lower = _freqNyquist / _powerSpectrum.count(); _powerSpectrum.x.upper = _freqNyquist; if ( (_powerSpectrum.count() > 1) && _resp ) { Math::Restitution::FFT::TransferFunctionPtr tf = _resp->getTransferFunction(); if ( tf ) { _responseCorrectedPowerSpectrum.y.resize(_spec.size()-1); _responseCorrectedPowerSpectrum.x = _powerSpectrum.x; _responsePowerSpectrum.y.resize(_spec.size()-1); _responsePowerSpectrum.x = _powerSpectrum.x; double dx = _responseCorrectedPowerSpectrum.x.length() / (_spec.size()-1); double px = _responseCorrectedPowerSpectrum.x.lower; if ( _phaseSpectrum ) { for ( size_t i = 1; i < _spec.size(); ++i, px += dx ) { Math::Complex r; tf->evaluate(&r, 1, &px); _responsePowerSpectrum.y[i-1] = rad2deg(arg(r)); _responseCorrectedPowerSpectrum.y[i-1] = rad2deg(arg(_spec[i] / r)); } } else { for ( size_t i = 1; i < _spec.size(); ++i, px += dx ) { Math::Complex r; tf->evaluate(&r, 1, &px); _responsePowerSpectrum.y[i-1] = abs(r); _responseCorrectedPowerSpectrum.y[i-1] = abs(_spec[i] / r); } } } } _xAxis.setRange(_powerSpectrum.x); }
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> void SpectrumWidget::exportSpectra() { if ( (_spec.size() < 1) || (_freqNyquist <= 0) ) { QMessageBox::critical(this, tr("Save spectra"), tr("No data")); return; } QString fn = QFileDialog::getSaveFileName(this, tr("Save spectra"), "spec-" + _exportBasename + ".txt"); if ( fn.isEmpty() ) return; ofstream ofs; ofs.open(fn.toAscii()); if ( !ofs.is_open() ) { QMessageBox::critical(this, tr("Save spectra"), tr("Failed to open/create %1").arg(fn)); return; } ofs << "# This is an ASCII representation of a spectrum. The first column is" << endl << "# the frequency is Hz. The second and third column represent the" << endl << "# complex value (real, imag) at that frequency of the raw spectrum." << endl << "# The amplitude and phase can be found in column four and five." << endl; Math::Restitution::FFT::TransferFunctionPtr tf = _resp ? _resp->getTransferFunction() : NULL; if ( (_spec.size() > 1) && tf ) { ofs << "# The sixth and seventh column represent the complex value of the response" << endl << "# corrected spectrum. Column eight and nine the amplitude and phase" << endl << "# respectively." << endl; } ofs << "#" << endl << "# Note that phases are output in degrees!" << endl; double f = 0; double df = _freqNyquist / (_spec.size()-1); for ( size_t i = 0; i < _spec.size(); ++i, f += df ) { ofs << f << "\t" << _spec[i].real() << "\t" << _spec[i].imag() << "\t" << abs(_spec[i]) << "\t" << deg2rad(arg(_spec[i])); if ( tf ) { ofs << "\t"; if ( i ) { Math::Complex r; tf->evaluate(&r, 1, &f); r = _spec[i] / r; ofs << r.real() << "\t" << r.imag() << "\t" << abs(r) << "\t" << deg2rad(arg(r)); } else ofs << _spec[i].real() << "\t" << _spec[i].imag() << "\t" << abs(_spec[i]) << "\t" << deg2rad(arg(_spec[i])); } ofs << endl; } }