bool waveform::fft::lowpass_filter( adcontrols::MassSpectrum& ms, double freq ) { if ( ms.isCentroid() ) return false; size_t totalSize = ms.size(); (void)totalSize; size_t N = 32; while ( N < ms.size() ) N *= 2; const size_t NN = ms.size(); double sampInterval = ms.getMSProperty().getSamplingInfo().fSampInterval(); // seconds if ( sampInterval == 0 ) sampInterval = ( ms.getTime( ms.size() - 1 ) - ms.getTime( 0 ) ) / ms.size(); const double T = N * sampInterval; // time full scale in seconds. Freq = n/T (Hz) // power spectrum has N/2 points and is n/T Hz horizontal axis := data[N/2] = (N/2)/T Hz size_t cutoff = size_t( T * freq ); adportable::array_wrapper<const double> pIntens( ms.getIntensityArray(), N ); std::vector< std::complex<double> > spc( N ); std::vector< std::complex<double> > fft( N ); size_t n; for ( n = 0; n < N && n < NN; ++n ) spc[ n ] = std::complex<double>( pIntens[ n ] ); while ( n < N ) spc[ n++ ] = pIntens[ NN - 1 ]; adportable::fft::fourier_transform( fft, spc, false ); // appodization for ( size_t i = cutoff; i < N - cutoff; ++i ) fft[ i ] = 0; //adportable::fft::apodization( N/2 - N/16, N / 16, fft ); adportable::fft::fourier_transform( spc, fft, true ); std::vector<double> data( N ); for ( size_t i = 0; i < NN; ++i ) data[ i ] = spc[i].real(); ms.setIntensityArray( &data[0] ); return true; }
void MSPropertyForm::render( std::ostream& o, const adcontrols::MassSpectrum& ms ) { using adportable::utf; using namespace adcontrols::metric; static const char * const polarities [] = { "Indeterminant", "Positive", "Negative", "Mixed" }; adcontrols::segment_wrapper< const adcontrols::MassSpectrum > segments( ms ); std::vector< std::pair< std::string, std::string > > temp; temp.push_back( std::make_pair( "Spectrum", ( ms.isCentroid() ? "Centroid" : "Profile" ) ) ); temp.push_back( std::make_pair( "Polarity", polarities[ ms.polarity() ] ) ); o << "<hr>"; o << "<table border=\"1\" cellpadding=\"1\">"; o << "<caption>Descriptions</caption>"; o << "<tr>"; o << "<th>key</th>" << "<th>description</th>" << "</tr>"; for ( auto it: temp ) { o << "<tr>" << "<td>" << it.first << "</td>" << "<td>" << it.second << "</td>" << "</tr>"; } for ( size_t i = 0; i < ms.getDescriptions().size(); ++i ) { auto desc = ms.getDescriptions()[ i ]; o << "<tr>" << "<td>" << utf::to_utf8( desc.key() ) << "</td>" << "<td>" << utf::to_utf8( desc.text() ) << "</td>" << "</tr>"; } o << "</table>"; std::pair< double, double > massrange = ms.getAcquisitionMassRange(); o << "Acquisition mass range: " << boost::format( "%.3lf -- %.3lf" ) % massrange.first % massrange.second; o << "<table border=\"1\" cellpadding=\"4\">"; o << "<caption>Acquisition and calibration parameter(s)</caption>"; o << "<tr>"; o << "<th>#seg</th>" << "<th>samp. interval(ps)</th>" << "<th>sampling start (μs)</th>" << "<th>sampling end (μs)</th>" << "<th>num. samples</th>" << "<th>num. average</th>" << "<th>mode</th>" << "<th>classid</th>" << "</tr>"; int n = 0; for ( auto& m: segments ) { const adcontrols::MSCalibration& calib = m.calibration(); size_t nrowspan = calib.coeffs().empty() ? 1 : 2; const adcontrols::MSProperty& prop = m.getMSProperty(); const adcontrols::MSProperty::SamplingInfo& info = prop.getSamplingInfo(); double start_delay = scale_to<double, micro>( info.sampInterval * info.nSamplingDelay, pico ); double time_end = scale_to<double, micro>( info.sampInterval * ( info.nSamplingDelay + info.nSamples ), pico ); o << "<tr>" << boost::format( "<td rowspan=\"%1%\">" ) % nrowspan << n++ << "</td>" << "<td>" << info.sampInterval << "</td>" << "<td>" << boost::format( "%.4lfμs" ) % start_delay << "</td>" << "<td>" << boost::format( "%.4lfμs" ) % time_end << "</td>" << "<td>" << info.nSamples << "</td>" << "<td>" << info.nAverage << "</td>" << "<td>" << info.mode << "</td>" << "<td>" << prop.dataInterpreterClsid() << "</td>" << "</tr>"; if ( ! calib.coeffs().empty() ) { //----------------------------- o << "<tr>"; o << "<td colspan=7><b>Calibration ID:</b><i>" << utf::to_utf8( calib.calibId() ) << "</i>" << " " << calib.date(); o << "<hr>"; o << "√<span style=\"text-decoration: overline\"> <i>m/z</i></span> = " << boost::format( "%.14lf" ) % calib.coeffs()[0] << " + "; for ( size_t i = 1; i < calib.coeffs().size(); ++i ) o << boost::format( "\t%.14lf × t<sup>%d</sup>" ) % calib.coeffs()[i] % i; if ( ! calib.t0_coeffs().empty() ) { o << "<br>" << "T<sub>0</sub> = " << calib.t0_coeffs()[0]; for ( size_t i = 1; i < calib.t0_coeffs().size(); ++i ) o << boost::format( "\t%.14lf × √<span style=\"text-decoration: overline\"> <i>m/z</i></span><sup>%d</sup>" ) % calib.coeffs()[i] % i; if ( calib.algorithm() == adcontrols::MSCalibration::MULTITURN_NORMALIZED ) o << "\t(MULTITURN_NORMAILZED algorithm)"; } o << "</tr>"; //----------------------------- } } o << "</table>"; o << "<hr>"; try { // device (averager) dependent data (require data interpreter) std::vector < std::pair< std::string, std::string > > textv; auto& prop = ms.getMSProperty(); const char * ipClsid = prop.dataInterpreterClsid(); if ( ipClsid && (std::strlen( ipClsid )) > 0 ) { auto& interpreter = prop.spectrometer().getDataInterpreter(); if ( interpreter.make_device_text( textv, ms.getMSProperty() ) ) { o << "<table border=\"1\" cellpadding=\"4\">"; o << "<caption>Averager/digitizer dependent information</caption>"; o << "<tr>"; o << "<th>#seg</th>"; std::for_each( textv.begin(), textv.end(), [&] ( const std::pair< std::string, std::string>& text ) { o << "<th>" << text.first << "</th>"; } ); o << "</tr>"; int seg = 0; for ( auto& m : segments ) { if ( interpreter.make_device_text( textv, m.getMSProperty() ) ) { o << "<tr>"; o << "<td>" << seg++ << "</td>"; std::for_each( textv.begin(), textv.end(), [&] ( const std::pair< std::string, std::string>& text ) { o << "<td>" << text.second << "</td>"; } ); o << "</tr>"; } } o << "</table>"; o << "<hr>"; } } else { o << "<hr>No dataInterpreterClsid specifid.</hr>"; ADERROR() << "no dataInterpreterClisidSpecified."; } } catch ( boost::exception& ex ) { o << "<hr>data exception: " << boost::diagnostic_information( ex ) << "</hr>"; ADERROR() << boost::diagnostic_information( ex ); } catch ( ... ) { o << "<hr>data exception: " << boost::current_exception_diagnostic_information() << "</hr>"; ADERROR() << boost::current_exception_diagnostic_information(); } }