Skip to content

Commit

Permalink
Set qcTraceName on ChromatogramGroupId (#982)
Browse files Browse the repository at this point in the history
* Set qcTraceName on ChromatogramGroupId.

* Fix error importing Skyline documents with Spectrum Filters (#921)

"Spectrum Filter" gets parsed from the Skyline document
light:heavy ratios are not calculated for precursors that have a spectrum filter
The spectrum filter is used when deciding which chromatogram to read from the .skyd file for a particular precursor.
# Conflicts:
#	src/org/labkey/targetedms/parser/ChromatogramGroupId.java

* Added constructor for ChromatogramGroupId that takes both qcTraceName and spectrumFilter.

---------

Co-authored-by: nickshulman <[email protected]>
  • Loading branch information
vagisha and nickshulman authored Nov 19, 2024
1 parent d886075 commit e4c1920
Show file tree
Hide file tree
Showing 13 changed files with 394 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ALTER TABLE targetedms.GeneralPrecursor
ADD COLUMN SpectrumFilter BYTEA;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE targetedms.GeneralPrecursor ADD SpectrumFilter VARBINARY(MAX);
1 change: 1 addition & 0 deletions resources/schemas/targetedms.xml
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,7 @@
<column columnName="Modified">
<formatString>DateTime</formatString>
</column>
<column columnName="SpectrumFilter" />
</columns>
</table>
<table tableDbType="TABLE" tableName="MoleculePrecursor">
Expand Down
2 changes: 2 additions & 0 deletions src/org/labkey/targetedms/SkylineDocImporter.java
Original file line number Diff line number Diff line change
Expand Up @@ -1521,6 +1521,8 @@ else if (generalMolecule instanceof Molecule molecule)
{
if (precursor.getIsotopeLabelId() != numLabelId)
continue;
if (precursor.getSpectrumFilter() != null)
continue;

PrecursorAreaRatio pRatio = areaRatioCalculator.getPrecursorAreaRatio(sampleFile.getId(),
precursor,
Expand Down
6 changes: 4 additions & 2 deletions src/org/labkey/targetedms/TargetedMSModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
import org.labkey.targetedms.folderImport.QCFolderWriterFactory;
import org.labkey.targetedms.parser.Protein;
import org.labkey.targetedms.parser.SampleFile;
import org.labkey.targetedms.parser.SpectrumFilter;
import org.labkey.targetedms.parser.skyaudit.SkylineAuditLogParser;
import org.labkey.targetedms.passport.PassportController;
import org.labkey.targetedms.pipeline.TargetedMSPipelineProvider;
Expand Down Expand Up @@ -222,7 +223,7 @@ public String getName()
@Override
public Double getSchemaVersion()
{
return 24.004;
return 24.005;
}

@Override
Expand Down Expand Up @@ -668,7 +669,8 @@ public Set<Class> getUnitTests()
TargetedMSController.TestCase.class,
PrecursorManager.TestCase.class,
CrossLinkedPeptideInfo.TestCase.class,
Protein.TestCase.class
Protein.TestCase.class,
SpectrumFilter.TestCase.class
);
}

Expand Down
29 changes: 27 additions & 2 deletions src/org/labkey/targetedms/parser/ChromatogramGroupId.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,32 @@
*/
package org.labkey.targetedms.parser;

import org.apache.commons.lang3.StringUtils;
import org.labkey.targetedms.parser.proto.ChromatogramGroupDataOuterClass;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class ChromatogramGroupId
{
private Target _target;
private String _qcTraceName;
private SpectrumFilter _spectrumFilter;

private ChromatogramGroupId()
{
}
public ChromatogramGroupId(Target target)
public ChromatogramGroupId(Target target, String qcTraceName, SpectrumFilter spectrumFilter)
{
_target = target;
_qcTraceName = StringUtils.isEmpty(qcTraceName) ? null : qcTraceName;
_spectrumFilter = spectrumFilter;
}

public ChromatogramGroupId(Target target, SpectrumFilter spectrumFilter)
{
this(target, null, spectrumFilter);
}

public Target getTarget()
Expand All @@ -43,6 +53,11 @@ public String getQcTraceName()
return _qcTraceName;
}

public SpectrumFilter getSpectrumFilter()
{
return _spectrumFilter;
}

public static ChromatogramGroupId forQcTraceName(String qcTraceName)
{
ChromatogramGroupId chromatogramGroupId = new ChromatogramGroupId();
Expand All @@ -55,14 +70,24 @@ public static List<ChromatogramGroupId> fromProtos(ChromatogramGroupDataOuterCla
List<Target> targets = new ArrayList<>();
// Make one-based lookups easy
targets.add(null);

List<SpectrumFilter.FilterClause> filterClauses = new ArrayList<>();

for (ChromatogramGroupDataOuterClass.ChromatogramGroupIdsProto.Target target : proto.getTargetsList())
{
targets.add(new Target(target));
}
for (ChromatogramGroupDataOuterClass.ChromatogramGroupIdsProto.SpectrumFilter spectrumFilter : proto.getFiltersList())
{
filterClauses.add(SpectrumFilter.FilterClause.fromProtocolMessage(spectrumFilter));
}
List<ChromatogramGroupId> list = new ArrayList<>();
for (ChromatogramGroupDataOuterClass.ChromatogramGroupIdsProto.ChromatogramGroupId chromatogramGroupId : proto.getChromatogramGroupIdsList())
{
list.add(new ChromatogramGroupId(targets.get(chromatogramGroupId.getTargetIndex())));
SpectrumFilter spectrumFilter = SpectrumFilter.fromFilterClauses(
chromatogramGroupId.getFilterIndexesList().stream()
.map(filterClauses::get).collect(Collectors.toList())).orElse(null);
list.add(new ChromatogramGroupId(targets.get(chromatogramGroupId.getTargetIndex()), chromatogramGroupId.getQcTraceName(), spectrumFilter));
}
return list;
}
Expand Down
11 changes: 11 additions & 0 deletions src/org/labkey/targetedms/parser/GeneralPrecursor.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public class GeneralPrecursor<TransitionType extends GeneralTransition> extends
private Double _explicitCcsSqa;
private Double _explicitCompensationVoltage;
private Double _precursorConcentration;
private byte[] _spectrumFilter;

public long getGeneralMoleculeId()
{
Expand Down Expand Up @@ -213,4 +214,14 @@ public void setPrecursorConcentration(Double precursorConcentration)
{
_precursorConcentration = precursorConcentration;
}

public byte[] getSpectrumFilter()
{
return _spectrumFilter;
}

public void setSpectrumFilter(byte[] spectrumFilter)
{
_spectrumFilter = spectrumFilter;
}
}
7 changes: 7 additions & 0 deletions src/org/labkey/targetedms/parser/PeakAreaRatioCalculator.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ public void init(Map<SkylineDocImporter.SampleFileKey, SampleFile> skylineIdSamp

for(Precursor precursor: _peptide.getPrecursorList())
{
if (precursor.getSpectrumFilter() != null)
{
// Ideally, ratios would be calculated separately between Precursors with the same Spectrum Filter.
// However, we only store one ratio in the database for each Peptide, so we just skip precursors
// which have a Spectrum Filter.
continue;
}
for(PrecursorChromInfo precursorChromInfo : precursor.getChromInfoList())
{
if(precursorChromInfo.isOptimizationPeak())
Expand Down
2 changes: 1 addition & 1 deletion src/org/labkey/targetedms/parser/SkylineBinaryParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ public ChromatogramGroupId getTextId(ChromGroupHeaderInfo chromGroupHeaderInfo)
{
return null;
}
return new ChromatogramGroupId(target);
return new ChromatogramGroupId(target, null);
}

public String getFilePath(ChromGroupHeaderInfo chromGroupHeaderInfo) {
Expand Down
49 changes: 35 additions & 14 deletions src/org/labkey/targetedms/parser/SkylineDocumentParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.labkey.targetedms.parser;

import com.google.common.collect.Iterables;
import com.google.protobuf.InvalidProtocolBufferException;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.Logger;
Expand Down Expand Up @@ -63,6 +64,7 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.regex.Pattern;
Expand Down Expand Up @@ -157,6 +159,7 @@ public class SkylineDocumentParser implements AutoCloseable
private static final String CHARGE = "charge" ;
public static final String TRANSITION_DATA = "transition_data";
private static final String LINKED_FRAGMENT_ION = "linked_fragment_ion";
private static final String SPECTRUM_FILTER = "spectrum_filter";

private static final double MIN_SUPPORTED_VERSION = 1.2;
public static final double MAX_SUPPORTED_VERSION = 23.1;
Expand Down Expand Up @@ -1860,7 +1863,7 @@ private MoleculePrecursor readMoleculePrecursor(XMLStreamReader reader, Molecule
String charge = reader.getAttributeValue(null, CHARGE);
if(null != charge)
moleculePrecursor.setCharge(Integer.parseInt(charge));

List<SpectrumFilter.FilterClause> spectrumFilterClauses = new ArrayList<>();
while(reader.hasNext())
{
int evtType = reader.next();
Expand All @@ -1879,8 +1882,11 @@ else if (XmlUtil.isStartElement(reader, evtType, ANNOTATION))
annotations.add(readAnnotation(reader, new PrecursorAnnotation()));
else if (XmlUtil.isStartElement(reader, evtType, NOTE))
moleculePrecursor.setNote(readNote(reader));
else if (XmlUtil.isStartElement(reader, evtType, SPECTRUM_FILTER))
spectrumFilterClauses.add(SpectrumFilter.FilterClause.parse(reader));
}

moleculePrecursor.setSpectrumFilter(SpectrumFilter.fromFilterClauses(spectrumFilterClauses)
.map(SpectrumFilter::toByteArray).orElse(null));
List<ChromGroupHeaderInfo> chromatograms = tryLoadChromatogram(moleculeTransitionList, molecule, moleculePrecursor, _matchTolerance);
populateChromInfoChromatograms(moleculePrecursor, chromatograms);

Expand Down Expand Up @@ -2035,7 +2041,7 @@ private Precursor readPrecursor(XMLStreamReader reader, Peptide peptide, boolean
precursor.setExplicitCcsSqa(XmlUtil.readDoubleAttribute(reader, "explicit_ccs_sqa"));
precursor.setExplicitCompensationVoltage(XmlUtil.readDoubleAttribute(reader, "explicit_compensation_voltage"));
precursor.setPrecursorConcentration(XmlUtil.readDoubleAttribute(reader, "precursor_concentration"));

List<SpectrumFilter.FilterClause> spectrumFilterClauses = new ArrayList<>();
while (reader.hasNext()) {

int evtType = reader.next();
Expand Down Expand Up @@ -2083,8 +2089,15 @@ else if (XmlUtil.isStartElement(reader, evtType, NOTE))
{
precursor.setNote(readNote(reader));
}
else if (XmlUtil.isStartElement(reader, evtType, SPECTRUM_FILTER))
{
spectrumFilterClauses.add(SpectrumFilter.FilterClause.parse(reader));
}
}

precursor.setSpectrumFilter(SpectrumFilter.fromFilterClauses(spectrumFilterClauses)
.map(SpectrumFilter::toByteArray).orElse(null));

// Boolean type annotations are not listed in the .sky file if their value was false.
// We would still like to store them in the database.
List<String> missingBooleanAnnotations = _dataSettings.getMissingBooleanAnnotations(annotations,
Expand Down Expand Up @@ -3113,7 +3126,6 @@ public List<SampleFileChromInfo> getSampleFileChromInfos(Map<String, SampleFile>
{
return Collections.emptyList();
}
int traceMetricIndex = 1;
for (ChromGroupHeaderInfo chromatogram : _binaryParser.getChromatograms())
{
// Sample-scoped chromatograms have a magic precursor MZ value
Expand Down Expand Up @@ -3145,14 +3157,7 @@ public List<SampleFileChromInfo> getSampleFileChromInfos(Map<String, SampleFile>
ChromatogramGroupId chromatogramGroupId = _binaryParser.getTextId(chromatogram);
if (chromatogramGroupId != null)
{
if (chromatogramGroupId.getQcTraceName() == null && chromatogram.getFlagValues().contains(ChromGroupHeaderInfo.FlagValues.extracted_qc_trace))
{
info.setTextId("QC Trace " + traceMetricIndex++);
}
else
{
info.setTextId(chromatogramGroupId.getQcTraceName());
}
info.setTextId(chromatogramGroupId.getQcTraceName());
}
info.setChromatogramFormat(chromatogram.getChromatogramBinaryFormat().ordinal());
info.setChromatogramOffset(chromatogram.getLocationPoints());
Expand Down Expand Up @@ -3204,8 +3209,24 @@ private List<ChromGroupHeaderInfo> tryLoadChromatogram(
ChromGroupHeaderInfo chrom = _binaryParser.getChromatograms()[i++];
// Sequence matching for extracted chromatogram data added in v1.5
ChromatogramGroupId chromTextId = _binaryParser.getTextId(chrom);
if (chromTextId != null && !molecule.targetMatches(chromTextId.getTarget()))
continue;
if (chromTextId != null)
{
if (!molecule.targetMatches(chromTextId.getTarget()))
continue;
try
{
SpectrumFilter spectrumFilter = SpectrumFilter.fromByteArray(precursor.getSpectrumFilter());
if (!Objects.equals(spectrumFilter, chromTextId.getSpectrumFilter()))
{
continue;
}
}
catch (InvalidProtocolBufferException e)
{
_log.warn("Error parsing spectrum filter {}", e);
return Collections.emptyList();
}
}

// If explicit retention time info is available, use that to discard obvious mismatches
if (explicitRT == null || !chrom.excludesTime(explicitRT))
Expand Down
Loading

0 comments on commit e4c1920

Please sign in to comment.