Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/org/labkey/targetedms/TargetedMSController.java
Original file line number Diff line number Diff line change
Expand Up @@ -874,6 +874,7 @@ public static class LeveyJenningsPlotOptions
private Integer _trailingRuns;
private Integer _calendarMonthsToShow;
private String _heatmapDataSource;
private String _hiddenSeries;

public Map<String, String> getAsMapOfStrings()
{
Expand Down Expand Up @@ -906,6 +907,8 @@ public Map<String, String> getAsMapOfStrings()
valueMap.put("calendarMonthsToShow", Integer.toString(_calendarMonthsToShow));
if (_heatmapDataSource != null)
valueMap.put("heatMapDataSource", _heatmapDataSource);
if (_hiddenSeries != null)
valueMap.put("hiddenSeries", _hiddenSeries);
// note: start and end date handled separately since they can be null and we want to persist that
return valueMap;
}
Expand Down Expand Up @@ -1034,6 +1037,16 @@ public void setHeatmapDataSource(String heatmapDataSource)
{
_heatmapDataSource = heatmapDataSource;
}

public String getHiddenSeries()
{
return _hiddenSeries;
}

public void setHiddenSeries(String hiddenSeries)
{
_hiddenSeries = hiddenSeries;
}
}

@RequiresPermission(ReadPermission.class)
Expand Down
44 changes: 44 additions & 0 deletions src/org/labkey/targetedms/model/QCPlotFragment.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ public class QCPlotFragment
private List<GuideSetStats> guideSetStats;
@Nullable
private Color _seriesColor;
@Nullable
private Long precursorRowId;
@Nullable
private Long peptideGroupId;
@Nullable
private String peptideGroupLabel;

public String getSeriesLabel()
{
Expand Down Expand Up @@ -77,6 +83,11 @@ public JSONObject toJSON(boolean includeLJ, boolean includeMR, boolean includeMe
JSONObject jsonObject = new JSONObject();
jsonObject.put("DataType", getDataType());
jsonObject.put("SeriesLabel", getSeriesLabel());
if (peptideGroupId != null)
{
jsonObject.put("PeptideGroupId", peptideGroupId);
jsonObject.put("PeptideGroupLabel", peptideGroupLabel != null ? peptideGroupLabel : "");
}
if (_seriesColor != null)
{
jsonObject.put("SeriesColor", "#" + Integer.toHexString(_seriesColor.getRGB()).substring(2).toUpperCase());
Expand Down Expand Up @@ -205,4 +216,37 @@ public Color getSeriesColor()
{
return _seriesColor;
}

@Nullable
public Long getPrecursorRowId()
{
return precursorRowId;
}

public void setPrecursorRowId(Long precursorRowId)
{
this.precursorRowId = precursorRowId;
}

@Nullable
public Long getPeptideGroupId()
{
return peptideGroupId;
}

public void setPeptideGroupId(Long peptideGroupId)
{
this.peptideGroupId = peptideGroupId;
}

@Nullable
public String getPeptideGroupLabel()
{
return peptideGroupLabel;
}

public void setPeptideGroupLabel(String peptideGroupLabel)
{
this.peptideGroupLabel = peptideGroupLabel;
}
}
22 changes: 20 additions & 2 deletions src/org/labkey/targetedms/outliers/OutlierGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,11 @@
import org.labkey.targetedms.model.SampleFileQCMetadata;
import org.labkey.targetedms.parser.GeneralMolecule;
import org.labkey.targetedms.parser.GeneralPrecursor;
import org.labkey.targetedms.parser.PeptideGroup;
import org.labkey.targetedms.parser.SampleFile;
import org.labkey.targetedms.query.MoleculeManager;
import org.labkey.targetedms.query.MoleculePrecursorManager;
import org.labkey.targetedms.query.PeptideGroupManager;
import org.labkey.targetedms.query.PeptideManager;
import org.labkey.targetedms.query.PrecursorManager;

Expand Down Expand Up @@ -539,7 +541,11 @@ public List<QCPlotFragment> getQCPlotFragment(List<RawMetricDataSet> rawMetricDa
Optional<RawMetricDataSet> bestPrecursorIdRow = entry.getValue().stream().filter(x -> x.getPrecursorId() != null).min(Comparator.comparing(RawMetricDataSet::getPrecursorId));

// Remember the precursor ID so that we can assign a series color based on Skyline's algorithm
bestPrecursorIdRow.ifPresent(rawMetricDataSet -> fragmentsByPrecursorId.put(rawMetricDataSet.getPrecursorId(), qcPlotFragment));
// and to sort by Skyline document order (row ID) instead of alphabetically
bestPrecursorIdRow.ifPresent(rawMetricDataSet -> {
fragmentsByPrecursorId.put(rawMetricDataSet.getPrecursorId(), qcPlotFragment);
qcPlotFragment.setPrecursorRowId(rawMetricDataSet.getPrecursorId());
});

qcPlotFragment.setSeriesLabel(entry.getKey());
qcPlotFragment.setQcPlotData(entry.getValue());
Expand All @@ -559,6 +565,7 @@ public List<QCPlotFragment> getQCPlotFragment(List<RawMetricDataSet> rawMetricDa
// Now that we have all the precursor IDs, in order (important so that we de-dupe the colors in a stable order),
// run through them and choose a color
Set<Color> seriesColors = new HashSet<>();
Map<Long, PeptideGroup> peptideGroupCache = new HashMap<>();
for (Map.Entry<Long, QCPlotFragment> entry : fragmentsByPrecursorId.entrySet())
{
long precursorId = entry.getKey();
Expand Down Expand Up @@ -588,10 +595,21 @@ public List<QCPlotFragment> getQCPlotFragment(List<RawMetricDataSet> rawMetricDa
Color color = ColorGenerator.getColor(molecule.getTextId(), seriesColors);
entry.getValue().setSeriesColor(color);
seriesColors.add(color);

// set the peptide group (protein / molecule list) for the combined plot tree legend
PeptideGroup peptideGroup = peptideGroupCache.computeIfAbsent(molecule.getPeptideGroupId(), id -> PeptideGroupManager.getPeptideGroup(c, id));
if (peptideGroup != null)
{
entry.getValue().setPeptideGroupId(peptideGroup.getId());
entry.getValue().setPeptideGroupLabel(peptideGroup.getLabel());
}
}
}

qcPlotFragments.sort(Comparator.comparing(QCPlotFragment::getSeriesLabel));
// Sort by precursor row ID to preserve Skyline document order. Fragments with no precursor ID
// (e.g. trace metrics) fall back to alphabetical order after all precursor-scoped series.
qcPlotFragments.sort(Comparator.comparing(QCPlotFragment::getPrecursorRowId, Comparator.nullsLast(Comparator.naturalOrder()))
.thenComparing(QCPlotFragment::getSeriesLabel));
return qcPlotFragments;
}

Expand Down
15 changes: 15 additions & 0 deletions test/src/org/labkey/test/components/targetedms/QCPlotsWebPart.java
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,20 @@ public Locator getLegendItemLocator(String text, boolean exactMatch)
return elementCache().legendItem.containing(text);
}

public Locator getTreeLegendItemLocator(String text, boolean exactMatch)
{
if (exactMatch)
return elementCache().combinedTreeLegendItem.withText(text);
else
return elementCache().combinedTreeLegendItem.containing(text);
}

public Locator getTreeLegendPrecursorLocator(String text)
{
// Match data-fragment attribute to avoid relying on potentially overflow-hidden span text
return Locator.css(".qc-tree-precursor").withAttributeContaining("data-fragment", text);
}

public Locator getLegendItemLocatorByTitle(String text)
{
// Use containing instead of withText() to ignore the +2 or other suffices
Expand Down Expand Up @@ -933,6 +947,7 @@ public class Elements extends BodyWebPart<?>.ElementCache
Locator.CssLocator legendItem = Locator.css("svg g.legend-item");
Locator.CssLocator legendItemTitle = Locator.css("svg g.legend-item title");
Locator.CssLocator legendItemPopup = Locator.css(".headerlegendpopup svg g.legend-item");
Locator.CssLocator combinedTreeLegendItem = Locator.css(".qc-combined-tree-legend > div");
Locator.CssLocator paginationPrevBtn = Locator.css(".qc-paging-prev");
Locator.CssLocator paginationNextBtn = Locator.css(".qc-paging-next");
Locator.CssLocator svgBackgrounds = Locator.css("svg g.brush rect.background");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@

import java.util.Arrays;

/**
* Tests the ability to hide/show specific peptides and molecules in QC folders across multiple folder structure
* configurations.
*/
@Category({})
@BaseWebDriverTest.ClassTimeout(minutes = 6)
public class TargetedMSHidePeptidesAndMolecules extends TargetedMSTest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@

import static org.junit.Assert.assertTrue;

/**
* Validates isotopologue metric display and calculation in the Panorama Dashboard QC metrics panel.
*/
@Category({})
@BaseWebDriverTest.ClassTimeout(minutes = 3)
public class TargetedMSIsotopologueTest extends TargetedMSPremiumTest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
import java.util.LinkedHashMap;
import java.util.Map;

/**
* Tests import/export of QC folder configurations and data as a round-trip operation.
*/
@Category({})
@BaseWebDriverTest.ClassTimeout(minutes = 6)
public class TargetedMSQCFolderImportExport extends TargetedMSPremiumTest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@
import static org.labkey.test.components.targetedms.QCPlotsWebPart.QCPlotType.CUSUMm;
import static org.labkey.test.util.PermissionsHelper.READER_ROLE;

/**
* Tests premium-tier QC functionality: guide sets, advanced QC metrics, CUSUM plots, and premium-specific permission
* checks.
*/
@Category({})
@BaseWebDriverTest.ClassTimeout(minutes = 6)
public class TargetedMSQCPremiumTest extends TargetedMSPremiumTest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
import java.util.List;
import java.util.Map;

/**
* Tests integration between TargetedMS and the Sample Manager module, including linked sample type data flowing into
* Skyline documents.
*/
@Category({})
@BaseWebDriverTest.ClassTimeout(minutes = 3)
public class TargetedMSSampleManagerIntegrationTest extends TargetedMSPremiumTest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* Tests iRT metrics calculations and their visualization specifically within the QC dashboard context.
*/
@Category({})
@BaseWebDriverTest.ClassTimeout(minutes = 5)
public class TargetedMSiRTMetricsTest extends TargetedMSPremiumTest
Expand Down Expand Up @@ -223,17 +226,31 @@ private String getChromatogramPlotColor(String peptide)

private void verifyQCPlotColors(String peptide, String color)
{
List<WebElement> treeItems = Locator.css(".qc-tree-precursor").findElements(getDriver());
for (WebElement e : treeItems)
{
String fragment = e.getAttribute("data-fragment");
if (fragment != null && fragment.contains(peptide))
{
checker().verifyEquals("Incorrect color for QC plot for " + peptide, color,
e.getAttribute("data-color"));
return;
}
}

// Fallback for files without peptide groups (SVG-based legend)
List<WebElement> legendList = Locator.tagWithClass("g", "legend-item").findElements(getDriver());
for (WebElement e : legendList)
{
if (e.getAttribute("title").startsWith(peptide + " "))
String title = e.getAttribute("title");
if (title != null && title.startsWith(peptide + " "))
{
checker().verifyEquals("Incorrect color for QC plot for " + peptide, color,
Locator.tag("path").findElement(e).getAttribute("fill"));
return;
}

}

throw new RuntimeException("Did not find the peptide " + peptide);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@

import java.util.Arrays;

/**
* Tests the Clustergrammer heatmap visualization integration for peptide data.
*/
@Category({})
@BaseWebDriverTest.ClassTimeout(minutes = 5)
public class ClustergrammerTest extends TargetedMSTest
Expand Down
3 changes: 3 additions & 0 deletions test/src/org/labkey/test/tests/targetedms/GetDataAPITest.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertThat;

/**
* Tests the GetData API with query transformations, filtering, and pivot operations on TargetedMS data.
*/
@Category({})
@BaseWebDriverTest.ClassTimeout(minutes = 5)
public class GetDataAPITest extends TargetedMSTest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

/**
* Tests instrument scheduling workflows including date/time handling and permissions across QC folders.
*/
@Category({})
@FixMethodOrder(MethodSorters.NAME_ASCENDING) // Don't insert additional projects until after testSchedule() has run
public class InstrumentSchedulingTest extends TargetedMSTest implements PostgresOnlyTest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@

import static org.junit.Assert.assertEquals;

/**
* Verifies that audit log entries from Skyline documents are correctly imported and displayed as an audit trail.
*/
@Category({})
@BaseWebDriverTest.ClassTimeout(minutes = 5)
public class TargetedMSAuditLogTest extends TargetedMSTest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
import java.util.LinkedList;
import java.util.List;

/**
* Tests chromatogram optimization workflows and library file generation from imported Skyline documents.
*/
@Category({})
@BaseWebDriverTest.ClassTimeout(minutes = 3)
public class TargetedMSChromatogramOptimizationTest extends TargetedMSTest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
import java.util.Collections;
import java.util.List;

/**
* Tests backward compatibility by importing Skyline documents across multiple historical format versions.
*/
@Category({})
public class TargetedMSDocumentFormatsTest extends TargetedMSTest
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@

import static org.junit.Assert.assertEquals;

/**
* Tests the PTM (post-translational modification) peptide report feature, including data pre-pivoting for
* early-stage PTM analysis.
*/
@Category({})
public class TargetedMSEarlyStagePTMReportTest extends TargetedMSTest
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@

import static org.junit.Assert.assertEquals;

/**
* Tests iRT (indexed Retention Time) scale import in experiment folders, validating the standard peptide set.
*/
@Category({})
@BaseWebDriverTest.ClassTimeout(minutes = 5)
public class TargetedMSExperimentIrtTest extends TargetedMSIrtTest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@
import static org.labkey.test.util.DataRegionTable.DataRegion;
import static org.labkey.test.util.PermissionsHelper.READER_ROLE;

/**
* Broad coverage of experiment folder behavior: file uploads, shared file access, and folder-level permissions.
*/
@Category({})
@BaseWebDriverTest.ClassTimeout(minutes = 8)
public class TargetedMSExperimentTest extends TargetedMSTest
Expand Down
Loading
Loading