From 34843a96d3c64a9a57fb4cf1964753fba4d3fff8 Mon Sep 17 00:00:00 2001 From: labkey-jeckels Date: Fri, 15 Sep 2023 16:50:07 -0700 Subject: [PATCH] Reduce DB queries queries by reusing study visits, NAb runs and sample properties --- nab/src/org/labkey/nab/NabAssayRun.java | 2 +- .../labkey/nab/SinglePlateNabAssayRun.java | 28 +++++++++---------- .../labkey/nab/SinglePlateNabDataHandler.java | 12 ++++---- .../CrossPlateDilutionNabAssayRun.java | 15 ++++------ .../CrossPlateDilutionNabDataHandler.java | 4 +-- .../HighThroughputNabDataHandler.java | 10 ++++--- .../SinglePlateDilutionNabAssayRun.java | 26 ++++++----------- .../SinglePlateDilutionNabDataHandler.java | 27 ++---------------- 8 files changed, 45 insertions(+), 79 deletions(-) diff --git a/nab/src/org/labkey/nab/NabAssayRun.java b/nab/src/org/labkey/nab/NabAssayRun.java index ef4520094..de05334cd 100644 --- a/nab/src/org/labkey/nab/NabAssayRun.java +++ b/nab/src/org/labkey/nab/NabAssayRun.java @@ -50,7 +50,7 @@ public abstract class NabAssayRun extends DilutionAssayRun { - public NabAssayRun(DilutionAssayProvider provider, ExpRun run, + public NabAssayRun(DilutionAssayProvider provider, ExpRun run, User user, List cutoffs, StatsService.CurveFitType renderCurveFitType) { super(provider, run, user, cutoffs, renderCurveFitType); diff --git a/nab/src/org/labkey/nab/SinglePlateNabAssayRun.java b/nab/src/org/labkey/nab/SinglePlateNabAssayRun.java index c4cf70595..2b65260b3 100644 --- a/nab/src/org/labkey/nab/SinglePlateNabAssayRun.java +++ b/nab/src/org/labkey/nab/SinglePlateNabAssayRun.java @@ -24,6 +24,7 @@ import org.labkey.api.assay.plate.WellGroup; import org.labkey.api.collections.CaseInsensitiveHashMap; import org.labkey.api.data.ColumnInfo; +import org.labkey.api.data.Container; import org.labkey.api.data.SimpleFilter; import org.labkey.api.data.TableInfo; import org.labkey.api.data.TableSelector; @@ -52,20 +53,20 @@ */ public class SinglePlateNabAssayRun extends NabAssayRun { - protected Plate _plate; - private DilutionSummary[] _dilutionSummaries; + protected final Plate _plate; + private final DilutionSummary[] _dilutionSummaries; public static final String SAMPLE_WELL_GROUP_NAME = "SampleWellGroupName"; - private Map _positionToVirusMap = new HashMap<>(); - private Map> _virusGroupToControlMap = new HashMap<>(); + private final Map _positionToVirusMap = new HashMap<>(); + private final Map> _virusGroupToControlMap = new HashMap<>(); - public SinglePlateNabAssayRun(DilutionAssayProvider provider, ExpRun run, Plate plate, + public SinglePlateNabAssayRun(DilutionAssayProvider provider, ExpRun run, Plate plate, User user, List cutoffs, StatsService.CurveFitType renderCurveFitType) { super(provider, run, user, cutoffs, renderCurveFitType); _plate = plate; List specimenGroups = _plate.getWellGroups(WellGroup.Type.SPECIMEN); - _dilutionSummaries = getDilutionSumariesForWellGroups(specimenGroups); + _dilutionSummaries = getDilutionSummariesForWellGroups(specimenGroups, run.getContainer()); } @Override @@ -81,7 +82,7 @@ public List getPlates() } @Override - protected DilutionSummary[] getDilutionSumariesForWellGroups(List specimenGroups) + protected DilutionSummary[] getDilutionSummariesForWellGroups(List specimenGroups, Container container) { List specimenVirusGroups = new ArrayList<>(); for (WellGroup specimenGroup : specimenGroups) @@ -116,7 +117,7 @@ protected DilutionSummary[] getDilutionSumariesForWellGroups(List data /** * Returns the virus well group that contains the specified positions. - * @param plate - * @param positions - * @return */ @Nullable private WellGroup getVirusGroupForPositions(Plate plate, List positions) @@ -267,7 +265,7 @@ private WellGroup getControlWellsForVirus(Plate plate, WellGroup virusGroup, Str if (virus.contains(pos)) { if (!virusToControlPositions.containsKey(virus)) - virusToControlPositions.put(virus, new ArrayList()); + virusToControlPositions.put(virus, new ArrayList<>()); virusToControlPositions.get(virus).add(pos); break; @@ -322,7 +320,7 @@ public Map getVirusNames() protected String getVirusName(String virusWellGroupName) { List outputDatas = _run.getOutputDatas(null); - if (outputDatas.size() > 0) + if (!outputDatas.isEmpty()) { Lsid virusLsid = DilutionDataHandler.createVirusWellGroupLsid(outputDatas.get(0), virusWellGroupName); AssayProtocolSchema schema = _provider.createProtocolSchema(_user, _run.getContainer(), _protocol, null); @@ -356,8 +354,8 @@ private WellGroup getControlWellGroupForVirus(Plate plate, String virusWellGroup return plate.getWellGroup(WellGroup.Type.CONTROL, controlGroupName); } - private CaseInsensitiveHashMap _cellControls = new CaseInsensitiveHashMap<>(); - private CaseInsensitiveHashMap _virusControls = new CaseInsensitiveHashMap<>(); + private final CaseInsensitiveHashMap _cellControls = new CaseInsensitiveHashMap<>(); + private final CaseInsensitiveHashMap _virusControls = new CaseInsensitiveHashMap<>(); private boolean ensureCellControl(Plate plate, String virusWellGroupName) { diff --git a/nab/src/org/labkey/nab/SinglePlateNabDataHandler.java b/nab/src/org/labkey/nab/SinglePlateNabDataHandler.java index 022f9ddab..7a17d3892 100644 --- a/nab/src/org/labkey/nab/SinglePlateNabDataHandler.java +++ b/nab/src/org/labkey/nab/SinglePlateNabDataHandler.java @@ -94,7 +94,7 @@ public DataType getDataType() } @Override - protected DilutionAssayRun createDilutionAssayRun(DilutionAssayProvider provider, ExpRun run, List plates, User user, + protected DilutionAssayRun createDilutionAssayRun(DilutionAssayProvider provider, ExpRun run, List plates, User user, List sortedCutoffs, StatsService.CurveFitType fit) { return new SinglePlateNabAssayRun(provider, run, plates.get(0), user, sortedCutoffs, fit); @@ -175,7 +175,7 @@ DataLoader createGrid() throws IOException, ExperimentException // Excel can only handle single sheets so this helper class abstracts away creating the loader for a specific sheet. // In addition we need to configure the loaders differently for parsing a list of data versus a grid of data without headers. - protected abstract class Load + protected abstract static class Load { abstract DataLoader createList() throws IOException, ExperimentException; abstract DataLoader createGrid() throws IOException, ExperimentException; @@ -313,11 +313,11 @@ protected void prepareWellGroups(List groups, ExpMaterial sampleInput virusData.add(well); } } - applyDilution(virusData, sampleInput, properties, reverseDirection); + applyDilution(virusData, sampleInput, properties, reverseDirection, sampleProperties); } } else - applyDilution(wells, sampleInput, properties, reverseDirection); + applyDilution(wells, sampleInput, properties, reverseDirection, sampleProperties); } @Override @@ -363,11 +363,11 @@ public void beforeDeleteData(List datas, User user) throws ExperimentEx AssayProvider provider = AssayService.get().getProvider(protocol); AssayProtocolSchema protocolSchema = provider.createProtocolSchema(null, protocol.getContainer(), protocol, null); TableInfo virusTable = protocolSchema.createTable(DilutionManager.VIRUS_TABLE_NAME, null); - if (virusTable instanceof FilteredTable) + if (virusTable instanceof FilteredTable ft) { if (virusTable.getColumn(FieldKey.fromParts(NabVirusDomainKind.DATLSID_COLUMN_NAME)) != null) { - TableInfo table = ((FilteredTable) virusTable).getRealTable(); + TableInfo table = ft.getRealTable(); SimpleFilter dataLsidFilter = new SimpleFilter(FieldKey.fromString(NabVirusDomainKind.DATLSID_COLUMN_NAME), data.getLSID()); // delete the rows in the virus table associated with this run diff --git a/nab/src/org/labkey/nab/multiplate/CrossPlateDilutionNabAssayRun.java b/nab/src/org/labkey/nab/multiplate/CrossPlateDilutionNabAssayRun.java index 7e454c0c6..07b233e08 100644 --- a/nab/src/org/labkey/nab/multiplate/CrossPlateDilutionNabAssayRun.java +++ b/nab/src/org/labkey/nab/multiplate/CrossPlateDilutionNabAssayRun.java @@ -36,10 +36,10 @@ */ public class CrossPlateDilutionNabAssayRun extends NabAssayRun { - protected List _plates; - private DilutionSummary[] _dilutionSummaries; + protected final List _plates; + private final DilutionSummary[] _dilutionSummaries; - public CrossPlateDilutionNabAssayRun(DilutionAssayProvider provider, ExpRun run, List plates, + public CrossPlateDilutionNabAssayRun(DilutionAssayProvider provider, ExpRun run, List plates, User user, List cutoffs, StatsService.CurveFitType renderCurveFitType) { super(provider, run, user, cutoffs, renderCurveFitType); @@ -52,18 +52,13 @@ public CrossPlateDilutionNabAssayRun(DilutionAssayProvider provider, ExpRun run, { for (WellGroup sample : plate.getWellGroups(WellGroup.Type.SPECIMEN)) { - List groups = sampleGroups.get(sample.getName()); - if (groups == null) - { - groups = new ArrayList<>(); - sampleGroups.put(sample.getName(), groups); - } + List groups = sampleGroups.computeIfAbsent(sample.getName(), k -> new ArrayList<>()); groups.add(sample); } } int index = 0; for (Map.Entry> sample : sampleGroups.entrySet()) - _dilutionSummaries[index++] = new DilutionSummary(this, sample.getValue(), null, _renderedCurveFitType); + _dilutionSummaries[index++] = new DilutionSummary(this, sample.getValue(), null, _renderedCurveFitType, run.getContainer()); } @Override diff --git a/nab/src/org/labkey/nab/multiplate/CrossPlateDilutionNabDataHandler.java b/nab/src/org/labkey/nab/multiplate/CrossPlateDilutionNabDataHandler.java index c3d25560a..cd0425241 100644 --- a/nab/src/org/labkey/nab/multiplate/CrossPlateDilutionNabDataHandler.java +++ b/nab/src/org/labkey/nab/multiplate/CrossPlateDilutionNabDataHandler.java @@ -49,7 +49,7 @@ public DataType getDataType() } @Override - protected Map> getMaterialWellGroupMapping(DilutionAssayProvider provider, List plates, Map sampleInputs) throws ExperimentException + protected Map> getMaterialWellGroupMapping(DilutionAssayProvider provider, List plates, Map sampleInputs) throws ExperimentException { Map nameToMaterial = new HashMap<>(); for (Map.Entry e : sampleInputs.entrySet()) @@ -81,7 +81,7 @@ protected Map> getMaterialWellGroupMapping(Dilution } @Override - protected DilutionAssayRun createDilutionAssayRun(DilutionAssayProvider provider, ExpRun run, List plates, User user, List sortedCutoffs, StatsService.CurveFitType fit) + protected DilutionAssayRun createDilutionAssayRun(DilutionAssayProvider provider, ExpRun run, List plates, User user, List sortedCutoffs, StatsService.CurveFitType fit) { return new CrossPlateDilutionNabAssayRun(provider, run, plates, user, sortedCutoffs, fit); } diff --git a/nab/src/org/labkey/nab/multiplate/HighThroughputNabDataHandler.java b/nab/src/org/labkey/nab/multiplate/HighThroughputNabDataHandler.java index f82bad4f0..cfd071e93 100644 --- a/nab/src/org/labkey/nab/multiplate/HighThroughputNabDataHandler.java +++ b/nab/src/org/labkey/nab/multiplate/HighThroughputNabDataHandler.java @@ -85,7 +85,7 @@ protected List createPlates(File dataFile, Plate template) throws Experim final int expectedCols = template.getColumns(); List matrices = parse(dataFile, loader.getColumns(), loader.load(), expectedRows, expectedCols); - if (matrices == null || matrices.size() == 0) + if (matrices == null || matrices.isEmpty()) throw createParseError(dataFile, "No plate data found"); int plateNumber = 1; @@ -184,11 +184,13 @@ protected void prepareWellGroups(List groups, ExpMaterial sampleInput List wells = new ArrayList<>(); // All well groups use the same plate template, so it's okay to just check the dilution direction of the first group: boolean reverseDirection = Boolean.parseBoolean((String) groups.get(0).getProperty(SampleProperty.ReverseDilutionDirection.name())); + + Map sampleProperties = sampleInput.getPropertyValues(); + for (WellGroup group : groups) { - Map map = sampleInput.getPropertyValues(); for (DomainProperty property : properties.values()) - group.setProperty(property.getName(), map.get(property.getPropertyDescriptor())); + group.setProperty(property.getName(), sampleProperties.get(property.getPropertyDescriptor())); boolean hasExplicitOrder = true; List wellData = group.getWellData(true); @@ -230,7 +232,7 @@ protected void prepareWellGroups(List groups, ExpMaterial sampleInput wells.addAll(wellData); } - applyDilution(wells, sampleInput, properties, reverseDirection); + applyDilution(wells, sampleInput, properties, reverseDirection, sampleProperties); } @Override diff --git a/nab/src/org/labkey/nab/multiplate/SinglePlateDilutionNabAssayRun.java b/nab/src/org/labkey/nab/multiplate/SinglePlateDilutionNabAssayRun.java index c590ff97e..48a7978d5 100644 --- a/nab/src/org/labkey/nab/multiplate/SinglePlateDilutionNabAssayRun.java +++ b/nab/src/org/labkey/nab/multiplate/SinglePlateDilutionNabAssayRun.java @@ -19,6 +19,7 @@ import org.labkey.api.assay.dilution.DilutionSummary; import org.labkey.api.assay.nab.Luc5Assay; import org.labkey.api.assay.plate.WellGroup; +import org.labkey.api.data.Container; import org.labkey.api.data.statistics.StatsService; import org.labkey.api.exp.PropertyDescriptor; import org.labkey.api.exp.api.ExpMaterial; @@ -40,10 +41,10 @@ */ public class SinglePlateDilutionNabAssayRun extends NabAssayRun { - protected List _plates; - private DilutionSummary[] _dilutionSummaries; + protected final List _plates; + private final DilutionSummary[] _dilutionSummaries; - public SinglePlateDilutionNabAssayRun(DilutionAssayProvider provider, ExpRun run, List plates, + public SinglePlateDilutionNabAssayRun(DilutionAssayProvider provider, ExpRun run, List plates, User user, List cutoffs, StatsService.CurveFitType renderCurveFitType) { super(provider, run, user, cutoffs, renderCurveFitType); @@ -56,21 +57,16 @@ public SinglePlateDilutionNabAssayRun(DilutionAssayProvider provider, ExpRun run { String virusName = plate.getProperty(NabAssayProvider.VIRUS_NAME_PROPERTY_NAME).toString(); String key = SinglePlateDilutionSamplePropertyHelper.getKey(virusName, sample.getName()); - List groups = sampleGroups.get(key); - if (groups == null) - { - groups = new ArrayList<>(); - sampleGroups.put(key, groups); - } + List groups = sampleGroups.computeIfAbsent(key, k -> new ArrayList<>()); groups.add(sample); } } List dilutionSummaries = new ArrayList<>(); for (Map.Entry> sample : sampleGroups.entrySet()) - dilutionSummaries.add(new MultiVirusDilutionSummary(this, sample.getValue(), null, _renderedCurveFitType)); + dilutionSummaries.add(new MultiVirusDilutionSummary(this, sample.getValue(), null, _renderedCurveFitType, _run.getContainer())); - _dilutionSummaries = dilutionSummaries.toArray(new DilutionSummary[dilutionSummaries.size()]); + _dilutionSummaries = dilutionSummaries.toArray(new DilutionSummary[0]); } @Override @@ -87,8 +83,6 @@ public List getPlates() /** * Generate a key for the sample level property map - * @param material - * @return */ @Override protected String getSampleKey(ExpMaterial material) @@ -105,8 +99,6 @@ protected String getSampleKey(ExpMaterial material) /** * Generate a key for the sample level property map - * @param summary - * @return */ @Override protected String getSampleKey(DilutionSummary summary) @@ -119,9 +111,9 @@ protected String getSampleKey(DilutionSummary summary) private static class MultiVirusDilutionSummary extends DilutionSummary { - public MultiVirusDilutionSummary(Luc5Assay assay, List sampleGroups, String lsid, StatsService.CurveFitType curveFitType) + public MultiVirusDilutionSummary(Luc5Assay assay, List sampleGroups, String lsid, StatsService.CurveFitType curveFitType, Container container) { - super(assay, sampleGroups, lsid, curveFitType); + super(assay, sampleGroups, lsid, curveFitType, container); } } } diff --git a/nab/src/org/labkey/nab/multiplate/SinglePlateDilutionNabDataHandler.java b/nab/src/org/labkey/nab/multiplate/SinglePlateDilutionNabDataHandler.java index e1e809197..9c08e2c77 100644 --- a/nab/src/org/labkey/nab/multiplate/SinglePlateDilutionNabDataHandler.java +++ b/nab/src/org/labkey/nab/multiplate/SinglePlateDilutionNabDataHandler.java @@ -25,10 +25,8 @@ import org.labkey.api.assay.plate.WellGroup; import org.labkey.api.data.statistics.StatsService; import org.labkey.api.exp.ExperimentException; -import org.labkey.api.exp.Lsid; import org.labkey.api.exp.PropertyDescriptor; import org.labkey.api.exp.api.DataType; -import org.labkey.api.exp.api.ExpData; import org.labkey.api.exp.api.ExpMaterial; import org.labkey.api.exp.api.ExpRun; import org.labkey.api.exp.api.ExperimentService; @@ -167,7 +165,7 @@ protected List createPlates(File dataFile, Plate template) throws Experim } @Override - protected Map> getMaterialWellGroupMapping(DilutionAssayProvider provider, List plates, Map sampleInputs) throws ExperimentException + protected Map> getMaterialWellGroupMapping(DilutionAssayProvider provider, List plates, Map sampleInputs) throws ExperimentException { Map nameToMaterial = new HashMap<>(); for (Map.Entry e : sampleInputs.entrySet()) @@ -189,12 +187,7 @@ protected Map> getMaterialWellGroupMapping(Dilution throw new ExperimentException("Unable to find sample metadata for sample well group \"" + name + "\": your sample metadata file may contain incorrect well group names, or it may not list all required samples."); } - List materialWellGroups = mapping.get(material); - if (materialWellGroups == null) - { - materialWellGroups = new ArrayList<>(); - mapping.put(material, materialWellGroups); - } + List materialWellGroups = mapping.computeIfAbsent(material, k -> new ArrayList<>()); materialWellGroups.add(specimenGroup); } } @@ -202,25 +195,11 @@ protected Map> getMaterialWellGroupMapping(Dilution } @Override - protected DilutionAssayRun createDilutionAssayRun(DilutionAssayProvider provider, ExpRun run, List plates, User user, List sortedCutoffs, StatsService.CurveFitType fit) + protected DilutionAssayRun createDilutionAssayRun(DilutionAssayProvider provider, ExpRun run, List plates, User user, List sortedCutoffs, StatsService.CurveFitType fit) { return new SinglePlateDilutionNabAssayRun(provider, run, plates, user, sortedCutoffs, fit); } - public Lsid getDataRowLSID(ExpData data, String wellGroupName, Map sampleProperties) - { - String virusName = ""; - for (Map.Entry entry : sampleProperties.entrySet()) - { - if (entry.getKey().getName().equals(NabAssayProvider.VIRUS_NAME_PROPERTY_NAME)) - virusName = entry.getValue().toString(); - } - Lsid.LsidBuilder dataRowLsid = new Lsid.LsidBuilder(data.getLSID()); - dataRowLsid.setNamespacePrefix(NAB_DATA_ROW_LSID_PREFIX); - dataRowLsid.setObjectId(dataRowLsid.getObjectId() + "-" + virusName + "-" + wellGroupName); - return dataRowLsid.build(); - } - @Override public Map getDilutionSummaries(User user, StatsService.CurveFitType fit, int... dataObjectIds) throws ExperimentException {