PWIZ_API_DECL void ChromatogramList_Thermo::createIndex() const { for (int controllerType = Controller_MS; controllerType <= Controller_UV; ++controllerType) { long numControllers = rawfile_->getNumberOfControllersOfType((ControllerType) controllerType); for (long n=1; n <= numControllers; ++n) { rawfile_->setCurrentController((ControllerType) controllerType, n); // skip this controller if it has no spectra if (rawfile_->value(NumSpectra) == 0) continue; switch ((ControllerType) controllerType) { case Controller_MS: { // support file-level TIC for all file types index_.push_back(IndexEntry()); IndexEntry& ci = index_.back(); ci.controllerType = (ControllerType) controllerType; ci.controllerNumber = n; ci.filter = ""; ci.index = index_.size()-1; ci.id = "TIC"; ci.chromatogramType = MS_TIC_chromatogram; idMap_[ci.id] = ci.index; // for certain filter types, support additional chromatograms auto_ptr<StringArray> filterArray = rawfile_->getFilters(); ScanFilter filterParser; for (size_t i=0, ic=filterArray->size(); i < ic; ++i) { string filterString = filterArray->item(i); filterParser.initialize(); filterParser.parse(filterString); switch (filterParser.scanType_) { case ScanType_SRM: { // produce spectra rather than a chromatogram if (config_.srmAsSpectra) break; string precursorMZ = (format("%.10g") % filterParser.precursorMZs_[0]).str(); /*index_.push_back(IndexEntry()); IndexEntry& ci = index_.back(); ci.controllerType = (ControllerType) controllerType; ci.controllerNumber = n; ci.filter = filterString; ci.index = index_.size()-1; ci.id = "SRM TIC " + precursorMZ; ci.q1 = filterParser.precursorMZs_[0]; idMap_[ci.id] = ci.index;*/ for (size_t j=0, jc=filterParser.scanRangeMin_.size(); j < jc; ++j) { index_.push_back(IndexEntry()); IndexEntry& ci = index_.back(); ci.chromatogramType = MS_SRM_chromatogram; ci.controllerType = (ControllerType) controllerType; ci.controllerNumber = n; ci.filter = filterString; ci.index = index_.size()-1; ci.q1 = filterParser.precursorMZs_[0]; ci.q3 = (filterParser.scanRangeMin_[j] + filterParser.scanRangeMax_[j]) / 2.0; ci.id = (format("SRM SIC %s,%.10g") % precursorMZ % ci.q3 ).str(); ci.q3Offset = (filterParser.scanRangeMax_[j] - filterParser.scanRangeMin_[j]) / 2.0; idMap_[ci.id] = ci.index; } } break; // case ScanType_SRM case ScanType_SIM: { // produce spectra rather than a chromatogram if (config_.simAsSpectra) break; for (size_t j=0, jc=filterParser.scanRangeMin_.size(); j < jc; ++j) { index_.push_back(IndexEntry()); IndexEntry& ci = index_.back(); ci.chromatogramType = MS_SIM_chromatogram; ci.controllerType = (ControllerType) controllerType; ci.controllerNumber = n; ci.filter = filterString; ci.index = index_.size()-1; ci.q1 = (filterParser.scanRangeMin_[j] + filterParser.scanRangeMax_[j]) / 2.0; ci.id = (format("SIM SIC %.10g") % ci.q1 ).str(); // this should be q1Offset ci.q3Offset = (filterParser.scanRangeMax_[j] - filterParser.scanRangeMin_[j]) / 2.0; idMap_[ci.id] = ci.index; } } break; // case ScanType_SIM default: case ScanType_Full: /*{ string precursorMZ = lexical_cast<string>(filterParser.precursorMZs_[0]); index_.push_back(make_pair(ChromatogramIdentity(), filterString)); ChromatogramIdentity& ci = index_.back().first; ci.index = index_.size()-1; ci.id = "SIC " + precursorMZ; idMap_[ci.id] = ci.index; }*/ break; } } } break; // case Controller_MS case Controller_PDA: { // "Total Scan" appears to be the equivalent of the TIC index_.push_back(IndexEntry()); IndexEntry& ci = index_.back(); ci.controllerType = (ControllerType) controllerType; ci.controllerNumber = n; ci.index = index_.size()-1; ci.id = "Total Scan"; ci.chromatogramType = MS_absorption_chromatogram; idMap_[ci.id] = ci.index; } break; // case Controller_PDA case Controller_Analog: { // "ECD" appears to be the equivalent of the TIC index_.push_back(IndexEntry()); IndexEntry& ci = index_.back(); ci.controllerType = (ControllerType) controllerType; ci.controllerNumber = n; ci.index = index_.size()-1; ci.id = "ECD"; ci.chromatogramType = MS_emission_chromatogram; idMap_[ci.id] = ci.index; } default: // TODO: are there sensible default chromatograms for other controller types? break; } } } /*ostringstream imStream; std::auto_ptr<LabelValueArray> imArray = rawfile_->getInstrumentMethods(); for(size_t i=0, end=imArray->size(); i < end; ++i) imStream << imArray->label(i) << imArray->value(i) << endl; string im = imStream.str(); // Parent Center Width Time CE Q1PW Q3PW TubeLens boost::regex scanEventRegex("^\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+$");*/ }
PWIZ_API_DECL ChromatogramPtr ChromatogramList_Thermo::chromatogram(size_t index, bool getBinaryData) const { boost::call_once(indexInitialized_.flag, boost::bind(&ChromatogramList_Thermo::createIndex, this)); if (index>size()) throw runtime_error(("[ChromatogramList_Thermo::chromatogram()] Bad index: " + lexical_cast<string>(index)).c_str()); const IndexEntry& ci = index_[index]; ChromatogramPtr result(new Chromatogram); result->index = ci.index; result->id = ci.id; result->set(ci.chromatogramType); rawfile_->setCurrentController(ci.controllerType, ci.controllerNumber); switch (ci.chromatogramType) { default: break; case MS_TIC_chromatogram: { ChromatogramDataPtr cd = rawfile_->getChromatogramData( Type_TIC, Operator_None, Type_MassRange, "", "", "", 0, 0, rawfile_->rt(rawfile_->value(NumSpectra)), Smoothing_None, 0); pwiz::msdata::TimeIntensityPair* data = reinterpret_cast<pwiz::msdata::TimeIntensityPair*>(cd->data()); if (getBinaryData) result->setTimeIntensityPairs(data, cd->size(), UO_minute, MS_number_of_counts); else result->defaultArrayLength = cd->size(); } break; case MS_SIC_chromatogram: // generate SIC for <precursor> { ChromatogramDataPtr cd = rawfile_->getChromatogramData( Type_BasePeak, Operator_None, Type_MassRange, index_[index].filter, "", "", 0, 0, rawfile_->rt(rawfile_->value(NumSpectra)), Smoothing_None, 0); pwiz::msdata::TimeIntensityPair* data = reinterpret_cast<pwiz::msdata::TimeIntensityPair*>(cd->data()); if (getBinaryData) result->setTimeIntensityPairs(data, cd->size(), UO_minute, MS_number_of_counts); else result->defaultArrayLength = cd->size(); } break; /*case 3: // generate SRM TIC for <precursor> { vector<string> tokens; bal::split(tokens, ci.id, bal::is_any_of(" ")); ChromatogramDataPtr cd = rawfile_->getChromatogramData( Type_TIC, Operator_None, Type_MassRange, "ms2 " + tokens[2], "", "", 0, 0, rawfile_->rt(rawfile_->value(NumSpectra)), Smoothing_None, 0); pwiz::msdata::TimeIntensityPair* data = reinterpret_cast<pwiz::msdata::TimeIntensityPair*>(cd->data()); if (getBinaryData) result->setTimeIntensityPairs(data, cd->size(), UO_minute, MS_number_of_counts); else result->defaultArrayLength = cd->size(); } break;*/ case MS_SRM_chromatogram: { result->precursor.isolationWindow.set(MS_isolation_window_target_m_z, ci.q1, MS_m_z); ScanFilter filterParser; filterParser.parse(ci.filter); ActivationType activationType = filterParser.activationType_; if (activationType == ActivationType_Unknown) activationType = ActivationType_CID; // assume CID SetActivationType(activationType, result->precursor.activation); if (filterParser.activationType_ == ActivationType_CID) result->precursor.activation.set(MS_collision_energy, filterParser.precursorEnergies_[0]); result->product.isolationWindow.set(MS_isolation_window_target_m_z, ci.q3, MS_m_z); result->product.isolationWindow.set(MS_isolation_window_lower_offset, ci.q3Offset, MS_m_z); result->product.isolationWindow.set(MS_isolation_window_upper_offset, ci.q3Offset, MS_m_z); string q1 = (format("%.10g") % ci.q1).str(); string q3Range = (format("%.10g-%.10g") % (ci.q3 - ci.q3Offset) % (ci.q3 + ci.q3Offset) ).str(); ChromatogramDataPtr cd = rawfile_->getChromatogramData( Type_MassRange, Operator_None, Type_MassRange, "SRM ms2 " + q1, q3Range, "", 0, 0, rawfile_->rt(rawfile_->value(NumSpectra)), Smoothing_None, 0); pwiz::msdata::TimeIntensityPair* data = reinterpret_cast<pwiz::msdata::TimeIntensityPair*>(cd->data()); if (getBinaryData) result->setTimeIntensityPairs(data, cd->size(), UO_minute, MS_number_of_counts); else result->defaultArrayLength = cd->size(); } break; case MS_SIM_chromatogram: { result->precursor.isolationWindow.set(MS_isolation_window_target_m_z, ci.q1, MS_m_z); result->precursor.isolationWindow.set(MS_isolation_window_lower_offset, ci.q3Offset, MS_m_z); result->precursor.isolationWindow.set(MS_isolation_window_upper_offset, ci.q3Offset, MS_m_z); string q1Range = (format("%.10g-%.10g") % (ci.q1 - ci.q3Offset) % (ci.q1 + ci.q3Offset) ).str(); ChromatogramDataPtr cd = rawfile_->getChromatogramData( Type_MassRange, Operator_None, Type_MassRange, "SIM ms [" + q1Range + "]", q1Range, "", 0, 0, rawfile_->rt(rawfile_->value(NumSpectra)), Smoothing_None, 0); pwiz::msdata::TimeIntensityPair* data = reinterpret_cast<pwiz::msdata::TimeIntensityPair*>(cd->data()); if (getBinaryData) result->setTimeIntensityPairs(data, cd->size(), UO_minute, MS_number_of_counts); else result->defaultArrayLength = cd->size(); } break; case MS_absorption_chromatogram: // generate "Total Scan" chromatogram for entire run { ChromatogramDataPtr cd = rawfile_->getChromatogramData( Type_TotalScan, Operator_None, Type_MassRange, "", "", "", 0, 0, rawfile_->rt(rawfile_->value(NumSpectra)), Smoothing_None, 0); pwiz::msdata::TimeIntensityPair* data = reinterpret_cast<pwiz::msdata::TimeIntensityPair*>(cd->data()); if (getBinaryData) result->setTimeIntensityPairs(data, cd->size(), UO_minute, MS_number_of_counts); else result->defaultArrayLength = cd->size(); } break; case MS_mass_chromatogram: // generate "ECD" chromatogram for entire run { ChromatogramDataPtr cd = rawfile_->getChromatogramData( Type_ECD, Operator_None, Type_MassRange, "", "", "", 0, 0, std::numeric_limits<double>::max(), Smoothing_None, 0); pwiz::msdata::TimeIntensityPair* data = reinterpret_cast<pwiz::msdata::TimeIntensityPair*>(cd->data()); if (getBinaryData) result->setTimeIntensityPairs(data, cd->size(), UO_minute, MS_number_of_counts); else result->defaultArrayLength = cd->size(); } break; } return result; }
int main(int argc, char* argv[]) { try { if (argc > 2) throw runtime_error("Usage: ScanFilterTest [Thermo RAW filename]"); else if (argc == 1) { // unit test static strings for (size_t i=0; i < testScanFiltersSize; ++i) { const TestScanFilter& f = testScanFilters[i]; try { vector<double> cidParentMass = parseDoubleArray(f.cidParentMassArray); vector<double> cidParentEnergy = parseDoubleArray(f.cidEnergyArray); vector<double> scanRangeMin = parseDoubleArray(f.scanRangeMinArray); vector<double> scanRangeMax = parseDoubleArray(f.scanRangeMaxArray); double compensationVoltage = 0.0; if (string(f.compensationVoltage) != "") compensationVoltage = lexical_cast<double> (f.compensationVoltage); ScanFilter scanFilter; scanFilter.parse(f.filter); testFilter(scanFilter, f.scanSegment, f.scanEvent, f.accurateMassType, f.coronaOn, f.detectorSet, f.photoIonizationOn, f.sourceCIDOn, f.turboScanOn, f.supplementalCIDOn, f.widebandOn, f.enhancedOn, f.dependentActive, f.lockMassOn, f.faimsOn, compensationVoltage, f.massAnalyzerType, f.polarityType, f.dataPointType, f.ionizationType, f.scanType, f.msLevel, cidParentMass, cidParentEnergy, scanRangeMin, scanRangeMax); } catch (exception& e) { cout << "Unit test on filter \"" << f.filter << "\" failed:\n" << e.what() << endl; } } } return 0; } catch (exception& e) { cout << "Caught exception: " << e.what() << endl; } catch (...) { cout << "Caught unknown exception.\n"; } return 1; }