From 6a542052c6f16b35c5bbad5eb09eb775058aeb8c Mon Sep 17 00:00:00 2001 From: SteffenHeu Date: Fri, 8 Mar 2024 19:04:36 +0100 Subject: [PATCH] review #1 --- .../factories/FxComponentFactory.java | 7 +++- .../mzmine/datamodel/AbundanceMeasure.java | 7 ++++ .../chartthemes/EStandardChartTheme.java | 2 + .../renderers/ColoredXYShapeRenderer.java | 3 +- .../gui/framework/fx/FxControllerBinding.java | 8 +++- .../dataanalysis/pca_new/PCAController.java | 4 -- ...Provider.java => PCALoadingsProvider.java} | 37 +++++++++-------- .../pca_new/PCANotComputedException.java | 33 --------------- .../dataanalysis/pca_new/PCAResult.java | 40 ++++++++++++++++++- ...esProvider.java => PCAScoresProvider.java} | 11 +++-- .../dataanalysis/pca_new/PCAUpdateTask.java | 8 ++-- .../dataanalysis/pca_new/PCAUtils.java | 14 +++++++ .../dataanalysis/pca_new/PCAViewBuilder.java | 12 +++--- .../rowsboxplot/RowsBoxplotController.java | 14 ++++--- .../significance/StatisticUtils.java | 2 +- .../projectmetadata/table/MetadataTable.java | 15 ++++++- .../annotations/CompoundAnnotationUtils.java | 2 +- 17 files changed, 130 insertions(+), 89 deletions(-) rename mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/{LoadingsProvider.java => PCALoadingsProvider.java} (80%) delete mode 100644 mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/PCANotComputedException.java rename mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/{ScoresProvider.java => PCAScoresProvider.java} (93%) diff --git a/javafx-framework/src/main/java/io/github/mzmine/javafx/components/factories/FxComponentFactory.java b/javafx-framework/src/main/java/io/github/mzmine/javafx/components/factories/FxComponentFactory.java index 70c140db0b..aafc6badc3 100644 --- a/javafx-framework/src/main/java/io/github/mzmine/javafx/components/factories/FxComponentFactory.java +++ b/javafx-framework/src/main/java/io/github/mzmine/javafx/components/factories/FxComponentFactory.java @@ -27,18 +27,21 @@ import javafx.beans.property.Property; import javafx.collections.ObservableList; +import javafx.geometry.Pos; import javafx.scene.control.ComboBox; import javafx.scene.control.Label; import javafx.scene.layout.HBox; public class FxComponentFactory { - public static HBox createLabelledComboBox(String label, ObservableList values, + public static HBox createLabeledComboBox(String label, ObservableList values, Property modelProperty) { final Label lab = new Label(label); final ComboBox comboBox = new ComboBox<>(values); comboBox.valueProperty().bindBidirectional(modelProperty); lab.setLabelFor(comboBox); - return new HBox(5, lab, comboBox); + final HBox hBox = new HBox(5, lab, comboBox); + hBox.setAlignment(Pos.CENTER_LEFT); + return hBox; } } diff --git a/mzmine-community/src/main/java/io/github/mzmine/datamodel/AbundanceMeasure.java b/mzmine-community/src/main/java/io/github/mzmine/datamodel/AbundanceMeasure.java index 833036b415..06cd53fdf4 100644 --- a/mzmine-community/src/main/java/io/github/mzmine/datamodel/AbundanceMeasure.java +++ b/mzmine-community/src/main/java/io/github/mzmine/datamodel/AbundanceMeasure.java @@ -58,4 +58,11 @@ public Float get(@Nullable ModularDataModel featureOrRow) { return featureOrRow.get(type); } + public Float getOrNaN(@Nullable ModularDataModel featureOrRow) { + if (featureOrRow == null) { + return Float.NaN; + } + return featureOrRow.get(type); + } + } diff --git a/mzmine-community/src/main/java/io/github/mzmine/gui/chartbasics/chartthemes/EStandardChartTheme.java b/mzmine-community/src/main/java/io/github/mzmine/gui/chartbasics/chartthemes/EStandardChartTheme.java index ef07e6f6fb..f5ce294361 100644 --- a/mzmine-community/src/main/java/io/github/mzmine/gui/chartbasics/chartthemes/EStandardChartTheme.java +++ b/mzmine-community/src/main/java/io/github/mzmine/gui/chartbasics/chartthemes/EStandardChartTheme.java @@ -76,6 +76,8 @@ public class EStandardChartTheme extends StandardChartTheme { private static final boolean DEFAULT_CROSS_HAIR_VISIBLE = true; private static final Stroke DEFAULT_CROSS_HAIR_STROKE = new BasicStroke(1.0F, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 1.0f, new float[]{5.0F, 3.0F}, 0.0F); + + public static final BasicStroke DEFAULT_STROKE = new BasicStroke(2f); // master font protected Font masterFont; protected Color masterFontColor; diff --git a/mzmine-community/src/main/java/io/github/mzmine/gui/chartbasics/simplechart/renderers/ColoredXYShapeRenderer.java b/mzmine-community/src/main/java/io/github/mzmine/gui/chartbasics/simplechart/renderers/ColoredXYShapeRenderer.java index b3e1f43d54..76e8edf19c 100644 --- a/mzmine-community/src/main/java/io/github/mzmine/gui/chartbasics/simplechart/renderers/ColoredXYShapeRenderer.java +++ b/mzmine-community/src/main/java/io/github/mzmine/gui/chartbasics/simplechart/renderers/ColoredXYShapeRenderer.java @@ -62,9 +62,8 @@ public class ColoredXYShapeRenderer extends XYShapeRenderer { private static final int defaultSize = 7; private final Shape dataPointsShape; - private final boolean drawOutlinesOnly; - private BasicStroke outlineStroke = new BasicStroke(2.0f); + private final BasicStroke outlineStroke = EStandardChartTheme.DEFAULT_STROKE; public ColoredXYShapeRenderer(boolean drawOutlinesOnly, Shape shape) { super(); diff --git a/mzmine-community/src/main/java/io/github/mzmine/gui/framework/fx/FxControllerBinding.java b/mzmine-community/src/main/java/io/github/mzmine/gui/framework/fx/FxControllerBinding.java index 7564ef33b7..460b7b8b5c 100644 --- a/mzmine-community/src/main/java/io/github/mzmine/gui/framework/fx/FxControllerBinding.java +++ b/mzmine-community/src/main/java/io/github/mzmine/gui/framework/fx/FxControllerBinding.java @@ -29,8 +29,14 @@ public sealed interface FxControllerBinding permits SelectedAbundanceMeasureCont SelectedMetadataColumnController, SelectedRowsController, SelectedFeaturesController, SelectedFilesController, SelectedFeatureListsController { + public static void bindExposedProperties(Object master, Object child) { + if (master instanceof FxControllerBinding && child instanceof FxControllerBinding) { + bindExposedProperties(master, child); + } + } + public static void bindExposedProperties(FxControllerBinding master, FxControllerBinding child) { - if(master == null ||child == null) { + if (master == null || child == null) { return; } diff --git a/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/PCAController.java b/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/PCAController.java index d8290203f3..16149e4ac3 100644 --- a/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/PCAController.java +++ b/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/PCAController.java @@ -57,10 +57,6 @@ public ObjectProperty> selectedRowsProperty() { return model.selectedRowsProperty(); } - public ObjectProperty> featureListsProperty() { - return model.flistsProperty(); - } - private void initListeners() { model.flistsProperty().addListener(_ -> update()); model.domainPcProperty().addListener(_ -> update()); diff --git a/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/LoadingsProvider.java b/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/PCALoadingsProvider.java similarity index 80% rename from mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/LoadingsProvider.java rename to mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/PCALoadingsProvider.java index 0b95710fc2..df16998686 100644 --- a/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/LoadingsProvider.java +++ b/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/PCALoadingsProvider.java @@ -25,9 +25,6 @@ package io.github.mzmine.modules.dataanalysis.pca_new; -import static io.github.mzmine.util.annotations.CompoundAnnotationUtils.getAnnotationTypesByPriority; -import static io.github.mzmine.util.annotations.CompoundAnnotationUtils.rankUniqueAnnotationTypes; - import io.github.mzmine.datamodel.features.FeatureListRow; import io.github.mzmine.datamodel.features.types.DataType; import io.github.mzmine.datamodel.features.types.DataTypes; @@ -38,6 +35,7 @@ import io.github.mzmine.gui.chartbasics.simplechart.providers.ZCategoryProvider; import io.github.mzmine.main.MZmineCore; import io.github.mzmine.taskcontrol.TaskStatus; +import io.github.mzmine.util.annotations.CompoundAnnotationUtils; import io.github.mzmine.util.color.SimpleColorPalette; import java.awt.Color; import java.util.Map; @@ -47,12 +45,12 @@ import org.jfree.chart.renderer.LookupPaintScale; import org.jfree.chart.renderer.PaintScale; -public class LoadingsProvider extends SimpleXYProvider implements PlotXYZDataProvider, +public class PCALoadingsProvider extends SimpleXYProvider implements PlotXYZDataProvider, ZCategoryProvider, XYItemObjectProvider { private final PCARowsResult result; - private final int loadingsY; - private final int loadingsX; + private final int loadingsIndexY; + private final int loadingsIndexX; private int[] zCategories; private int numberOfCategories; @@ -60,20 +58,20 @@ public class LoadingsProvider extends SimpleXYProvider implements PlotXYZDataPro private String[] legendNames; /** - * @param loadingsX index of the principal component used for domain axis, subtract 1 from the - * number since the pc matrix starts at 0. - * @param loadingsY index of the principal component used for range axis, subtract 1 from the - * number since the pc matrix starts at 0. + * @param loadingsIndexX index of the principal component used for domain axis, subtract 1 from + * the number since the pc matrix starts at 0. + * @param loadingsIndexY index of the principal component used for range axis, subtract 1 from the + * number since the pc matrix starts at 0. */ - public LoadingsProvider(PCARowsResult result, String seriesKey, Color awt, int loadingsX, - int loadingsY) { + public PCALoadingsProvider(PCARowsResult result, String seriesKey, Color awt, int loadingsIndexX, + int loadingsIndexY) { super(seriesKey, awt); this.result = result; - this.loadingsX = loadingsX; - this.loadingsY = loadingsY; + this.loadingsIndexX = loadingsIndexX; + this.loadingsIndexY = loadingsIndexY; } - public LoadingsProvider(PCARowsResult result, String seriesKey, Color awt) { + public PCALoadingsProvider(PCARowsResult result, String seriesKey, Color awt) { this(result, seriesKey, awt, 0, 1); } @@ -83,11 +81,12 @@ public void computeValues(Property status) { final RealMatrix loadingsMatrix = pcaResult.getLoadingsMatrix(); - final Map> bestRowAnnotationType = getAnnotationTypesByPriority( + final Map> bestRowAnnotationType = CompoundAnnotationUtils.mapBestAnnotationTypesByPriority( result.rows(), true); // only create order of actually existing annotaiton types - Map, Integer> typesInOrder = rankUniqueAnnotationTypes(bestRowAnnotationType.values()); + Map, Integer> typesInOrder = CompoundAnnotationUtils.rankUniqueAnnotationTypes( + bestRowAnnotationType.values()); numberOfCategories = typesInOrder.size(); double[] domainData = new double[loadingsMatrix.getColumnDimension()]; @@ -97,8 +96,8 @@ public void computeValues(Property status) { final MissingValueType missing = DataTypes.get(MissingValueType.class); for (int i = 0; i < loadingsMatrix.getColumnDimension(); i++) { - domainData[i] = loadingsMatrix.getEntry(loadingsX, i); - rangeData[i] = loadingsMatrix.getEntry(loadingsY, i); + domainData[i] = loadingsMatrix.getEntry(loadingsIndexX, i); + rangeData[i] = loadingsMatrix.getEntry(loadingsIndexY, i); // find annotation type or missing type FeatureListRow row = result.rows().get(i); final DataType bestTypeWithValue = bestRowAnnotationType.get(row); diff --git a/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/PCANotComputedException.java b/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/PCANotComputedException.java deleted file mode 100644 index 81127933fa..0000000000 --- a/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/PCANotComputedException.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2004-2024 The MZmine Development Team - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -package io.github.mzmine.modules.dataanalysis.pca_new; - -public class PCANotComputedException extends RuntimeException { - - public PCANotComputedException() { - super("Computation of this PCA has not finished or has not started yet."); - } -} diff --git a/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/PCAResult.java b/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/PCAResult.java index c0eeeaa700..1e29f3193a 100644 --- a/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/PCAResult.java +++ b/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/PCAResult.java @@ -31,18 +31,36 @@ import org.apache.commons.math3.linear.SingularValueDecomposition; import org.jetbrains.annotations.NotNull; +/** + * A pca based on singular value decomposition. The data matrix X is decomposed into X = U*S*V. + * Columns of U contrain the principal components, S are the singular values, which can be projected + * into the PC space using U and a submatrix of S, which creates the scores plot. Loadings are the + * transpose of V. + * + * https://stats.stackexchange.com/questions/134282/relationship-between-svd-and-pca-how-to-use-svd-to-perform-pca + */ public record PCAResult(RealMatrix data, RealMatrix dataMeanCentered, SingularValueDecomposition svd) { + /** + * @param numComponents + * @return Returns a sub-matrix the first n principal components of the decomposition. + */ public RealMatrix firstNComponents(int numComponents) { - return svd.getU().getSubMatrix(0, svd.getU().getRowDimension() - 1, 0, - numComponents - 1); + return svd.getU().getSubMatrix(0, svd.getU().getRowDimension() - 1, 0, numComponents - 1); } public RealMatrix principalComponentsMatrix() { + // the u matrix of an svd contains the principal components. return svd.getU(); } + /** + * Projects the data matrix onto the principal components. The result is n dimensional and is + * called "scores" matrix and is used for the scores plot. + * + * @param numComponents the number of components n. + */ public RealMatrix projectDataToScores(int numComponents) { final RealMatrix firstNComponents = firstNComponents(numComponents); final RealMatrix subMatrixS = svd.getS() @@ -51,15 +69,25 @@ public RealMatrix projectDataToScores(int numComponents) { return projectedData; } + /** + * Projects the data matrix onto the selected principal components. The result is 2 dimensional + * and is called "scores" matrix and is used for the scores plot. + * + * @see #projectDataToScores(int) + */ public RealMatrix projectDataToScores(int domainColIndex, int rangeColIndex) { final RealMatrix pcMatrix = pcMatrix(domainColIndex, rangeColIndex); final RealMatrix projected = pcMatrix.multiply(svd.getS().getSubMatrix(0, 1, 0, 1)); return projected; } + /** + * Retrieves two specific PCs from the PC matrix. + */ @NotNull private RealMatrix pcMatrix(int domainColIndex, int rangeColIndex) { final RealMatrix pcs = svd.getU(); + // the vectors are the respective components. final RealVector domainVector = pcs.getColumnVector(domainColIndex); final RealVector rangeVector = pcs.getColumnVector(rangeColIndex); RealMatrix pcMatrix = new Array2DRowRealMatrix(pcs.getRowDimension(), 2); @@ -69,8 +97,16 @@ private RealMatrix pcMatrix(int domainColIndex, int rangeColIndex) { return pcMatrix; } + /** + * Retrieves the loadings (importance of each observed feature) from the pca. After svd the + * loadings are the transpose of the v matrix. + */ public RealMatrix getLoadingsMatrix() { final RealMatrix transpose = svd.getV().transpose(); return transpose; } + + public int componentCount() { + return principalComponentsMatrix().getRowDimension(); + } } diff --git a/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/ScoresProvider.java b/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/PCAScoresProvider.java similarity index 93% rename from mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/ScoresProvider.java rename to mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/PCAScoresProvider.java index 7c4e2718d2..ee2a6a8338 100644 --- a/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/ScoresProvider.java +++ b/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/PCAScoresProvider.java @@ -47,7 +47,7 @@ import org.jfree.chart.renderer.LookupPaintScale; import org.jfree.chart.renderer.PaintScale; -public class ScoresProvider extends SimpleXYProvider implements PlotXYZDataProvider, +public class PCAScoresProvider extends SimpleXYProvider implements PlotXYZDataProvider, ZCategoryProvider, XYItemObjectProvider { private final PCARowsResult result; @@ -66,7 +66,7 @@ public class ScoresProvider extends SimpleXYProvider implements PlotXYZDataProvi * @param pcY index of the principal component used for range axis, subtract 1 from the number * since the pc matrix starts at 0. */ - public ScoresProvider(PCARowsResult result, String seriesKey, Color awt, int pcX, int pcY, + public PCAScoresProvider(PCARowsResult result, String seriesKey, Color awt, int pcX, int pcY, MetadataColumn groupingColumn) { super(seriesKey, awt); this.result = result; @@ -75,7 +75,7 @@ public ScoresProvider(PCARowsResult result, String seriesKey, Color awt, int pcX this.groupingColumn = groupingColumn; } - public ScoresProvider(PCARowsResult result, String seriesKey, Color awt) { + public PCAScoresProvider(PCARowsResult result, String seriesKey, Color awt) { this(result, seriesKey, awt, 0, 1, null); } @@ -86,9 +86,8 @@ public void computeValues(Property status) { final RealMatrix scores = pcaResult.projectDataToScores(pcX, pcY); final List files = result.files(); - final Map> groupedFiles = - groupingColumn != null ? MZmineCore.getProjectMetadata().groupFilesByColumn(groupingColumn) - : Map.of(); + final Map> groupedFiles = MZmineCore.getProjectMetadata() + .groupFilesByColumn(groupingColumn); numberOfCategories = Math.max(groupedFiles.size(), 1); groupNames = new String[Math.max(groupedFiles.size(), 1)]; diff --git a/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/PCAUpdateTask.java b/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/PCAUpdateTask.java index d14c4a5754..b8bfc1f4a5 100644 --- a/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/PCAUpdateTask.java +++ b/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/PCAUpdateTask.java @@ -93,13 +93,13 @@ protected void process() { pcaRowsResult = PCAUtils.performPCAOnRows(flists.get(0).getRows(), abundance); progressProvider.getAndIncrement(); - final ScoresProvider scores = new ScoresProvider(pcaRowsResult, "Scores", Color.RED, + final PCAScoresProvider scores = new PCAScoresProvider(pcaRowsResult, "Scores", Color.RED, domainPcIndex, rangePcIndex, MZmineCore.getProjectMetadata().getColumnByName(metadataColumn)); final ColoredXYZDataset scoresDS = new ColoredXYZDataset(scores, RunOption.THIS_THREAD); progressProvider.getAndIncrement(); - final LoadingsProvider loadings = new LoadingsProvider(pcaRowsResult, "Loadings", Color.RED, + final PCALoadingsProvider loadings = new PCALoadingsProvider(pcaRowsResult, "Loadings", Color.RED, domainPcIndex, rangePcIndex); final ColoredXYZDataset loadingsDS = new ColoredXYZDataset(loadings, RunOption.THIS_THREAD); progressProvider.getAndIncrement(); @@ -123,12 +123,12 @@ protected void updateGuiModel() { if (rangePcIndex < components.size()) { model.setRangePc(rangePcIndex + 1); } else { - model.setRangePc(components.getLast() + 1); + model.setRangePc(components.getLast()); } if (domainPcIndex < components.size()) { model.setDomainPc(domainPcIndex + 1); } else { - model.setDomainPc(components.getLast() + 1); + model.setDomainPc(components.getLast()); } } diff --git a/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/PCAUtils.java b/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/PCAUtils.java index cf5d12805b..a09216d560 100644 --- a/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/PCAUtils.java +++ b/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/PCAUtils.java @@ -38,6 +38,13 @@ public class PCAUtils { private static final Logger logger = Logger.getLogger(PCAUtils.class.getName()); + /** + * Calculates the PCA of a matrix by singular value decomposition (svd). + * https://stats.stackexchange.com/questions/134282/relationship-between-svd-and-pca-how-to-use-svd-to-perform-pca + * + * @param data the data + * @return A pca result. + */ public static PCAResult calculatePCA(RealMatrix data) { logger.finest(() -> "Performing scaling mean centering"); @@ -49,6 +56,13 @@ public static PCAResult calculatePCA(RealMatrix data) { return new PCAResult(data, centeredMatrix, svd); } + /** + * Performs a PCA on a list of feature list rows. Imputes missing values as 0s. + * + * @param rows The rows. + * @param measure The abundance to use. + * @return A pca result that can be mapped to the used rows. + */ public static PCARowsResult performPCAOnRows(List rows, AbundanceMeasure measure) { final List files = rows.stream().flatMap(row -> row.getRawDataFiles().stream()) diff --git a/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/PCAViewBuilder.java b/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/PCAViewBuilder.java index bd1416571b..02a48a1134 100644 --- a/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/PCAViewBuilder.java +++ b/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/pca_new/PCAViewBuilder.java @@ -55,8 +55,8 @@ public class PCAViewBuilder extends FxViewBuilder { private static final int space = 5; - private final SimpleXYChart scoresPlot = new SimpleXYChart<>("Scores plot", "PC1", "PC2"); - private final SimpleXYChart loadingsPlot = new SimpleXYChart<>("Loadings plot", "PC1", "PC2"); + private final SimpleXYChart scoresPlot = new SimpleXYChart<>("Scores", "PC1", "PC2"); + private final SimpleXYChart loadingsPlot = new SimpleXYChart<>("Loadings", "PC1", "PC2"); public PCAViewBuilder(PCAModel model) { super(model); @@ -68,12 +68,12 @@ public Region build() { loadingsPlot.setStickyZeroRangeAxis(false); final BorderPane pane = new BorderPane(); - final HBox domain = FxComponentFactory.createLabelledComboBox("Domain PC", + final HBox domain = FxComponentFactory.createLabeledComboBox("Domain PC", model.getAvailablePCs(), model.domainPcProperty()); - final HBox range = FxComponentFactory.createLabelledComboBox("Range PC", + final HBox range = FxComponentFactory.createLabeledComboBox("Range PC", model.getAvailablePCs(), model.rangePcProperty()); final HBox coloring = createMetadataBox(); - final HBox abundance = FxComponentFactory.createLabelledComboBox("Abundance", + final HBox abundance = FxComponentFactory.createLabeledComboBox("Abundance", FXCollections.observableArrayList(AbundanceMeasure.values()), model.abundanceProperty()); final TitledPane controls = new TitledPane("Controls", @@ -125,8 +125,6 @@ private void initDatasetListeners() { if (newValue == null || newValue.isEmpty()) { return; } - newValue.forEach(d -> loadingsPlot.addDataset(d.dataset(), d.renderer())); - LegendItemCollection collection = new LegendItemCollection(); newValue.forEach(d -> { loadingsPlot.addDataset(d.dataset(), d.renderer()); diff --git a/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/rowsboxplot/RowsBoxplotController.java b/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/rowsboxplot/RowsBoxplotController.java index c464a9c708..54ac2871ac 100644 --- a/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/rowsboxplot/RowsBoxplotController.java +++ b/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/rowsboxplot/RowsBoxplotController.java @@ -53,12 +53,14 @@ public RowsBoxplotController() { } private void updateDataset(List n) { - if (n == null || n.isEmpty()) { - model.setDataset(null); - return; - } - model.setDataset( - new RowBarDataset(n.getFirst(), model.getGroupingColumn(), model.getAbundanceMeasure())); + onGuiThread(() -> { + if (n == null || n.isEmpty()) { + model.setDataset(null); + return; + } + model.setDataset( + new RowBarDataset(n.getFirst(), model.getGroupingColumn(), model.getAbundanceMeasure())); + }); } @Override diff --git a/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/significance/StatisticUtils.java b/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/significance/StatisticUtils.java index d289935759..ec3b96775b 100644 --- a/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/significance/StatisticUtils.java +++ b/mzmine-community/src/main/java/io/github/mzmine/modules/dataanalysis/significance/StatisticUtils.java @@ -153,7 +153,7 @@ public static RealMatrix createDatasetFromRows(List rows, final double abundance; if (feature != null) { - abundance = measure.get((ModularDataModel) feature); + abundance = measure.getOrNaN((ModularDataModel) feature); } else { abundance = Double.NaN; } diff --git a/mzmine-community/src/main/java/io/github/mzmine/modules/visualization/projectmetadata/table/MetadataTable.java b/mzmine-community/src/main/java/io/github/mzmine/modules/visualization/projectmetadata/table/MetadataTable.java index 4a8d92c5f8..c563b3285b 100644 --- a/mzmine-community/src/main/java/io/github/mzmine/modules/visualization/projectmetadata/table/MetadataTable.java +++ b/mzmine-community/src/main/java/io/github/mzmine/modules/visualization/projectmetadata/table/MetadataTable.java @@ -242,8 +242,21 @@ public String[] getColumnTitles() { return getColumns().stream().map(MetadataColumn::getTitle).toArray(String[]::new); } - public Map> groupFilesByColumn(@NotNull MetadataColumn column) + /** + * Groups the files by the value in the metadata column. + * + * @param + * @return If the column is null, an empty map is returned. If the column is not in the table, an + * error is thrown. + * @throws MetadataColumnDoesNotExistException If the column does not exist. Does not throw if the + * column is null. + */ + @NotNull + public Map> groupFilesByColumn(@Nullable MetadataColumn column) throws MetadataColumnDoesNotExistException { + if (column == null) { + return Map.of(); + } final Map fileValueMap = data.get(column); if (fileValueMap == null) { throw new MetadataColumnDoesNotExistException(column.getTitle()); diff --git a/mzmine-community/src/main/java/io/github/mzmine/util/annotations/CompoundAnnotationUtils.java b/mzmine-community/src/main/java/io/github/mzmine/util/annotations/CompoundAnnotationUtils.java index 258cd35cdf..1ae1cca3a6 100644 --- a/mzmine-community/src/main/java/io/github/mzmine/util/annotations/CompoundAnnotationUtils.java +++ b/mzmine-community/src/main/java/io/github/mzmine/util/annotations/CompoundAnnotationUtils.java @@ -70,7 +70,7 @@ public static Map, List> groupRowsByAnnotationPriori * @return a map of best annotation types per row */ @NotNull - public static Map> getAnnotationTypesByPriority( + public static Map> mapBestAnnotationTypesByPriority( List rows, boolean mapMissingValues) { var orderedTypes = FeatureAnnotationPriority.getDataTypesInOrder(); var notAnnotatedType = mapMissingValues ? DataTypes.get(MissingValueType.class) : null;