diff --git a/src/main/java/org/mastodon/mamut/feature/branch/dimensionalityreduction/tsne/BranchTSneFeature.java b/src/main/java/org/mastodon/mamut/feature/branch/dimensionalityreduction/tsne/BranchTSneFeature.java new file mode 100644 index 000000000..3bffc13e3 --- /dev/null +++ b/src/main/java/org/mastodon/mamut/feature/branch/dimensionalityreduction/tsne/BranchTSneFeature.java @@ -0,0 +1,85 @@ +/*- + * #%L + * mastodon-deep-lineage + * %% + * Copyright (C) 2022 - 2024 Stefan Hahmann + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package org.mastodon.mamut.feature.branch.dimensionalityreduction.tsne; + +import java.util.List; + +import org.mastodon.feature.Feature; +import org.mastodon.feature.FeatureProjectionKey; +import org.mastodon.feature.FeatureProjectionSpec; +import org.mastodon.feature.FeatureSpec; +import org.mastodon.feature.Multiplicity; +import org.mastodon.mamut.feature.dimensionalityreduction.tsne.feature.AbstractTSneFeature; +import org.mastodon.mamut.model.branch.BranchSpot; +import org.mastodon.properties.DoublePropertyMap; +import org.scijava.plugin.Plugin; + +/** + * Represents a t-SNE feature for BranchSpots in the Mastodon project. + *
+ * This feature is used to store the t-SNE outputs for BranchSpots. + *
+ * The t-SNE outputs are stored in a list of {@link DoublePropertyMap}s. The size of the list is equal to the number of dimensions of the t-SNE output. + */ +public class BranchTSneFeature extends AbstractTSneFeature< BranchSpot > +{ + public static final String KEY = "Branch t-SNE outputs"; + + private final BranchSpotTSneFeatureSpec adaptedSpec; + + public static final BranchSpotTSneFeatureSpec GENERIC_SPEC = new BranchSpotTSneFeatureSpec(); + + public BranchTSneFeature( final List< DoublePropertyMap< BranchSpot > > outputMaps ) + { + super( outputMaps ); + FeatureProjectionSpec[] projectionSpecs = + projectionMap.keySet().stream().map( FeatureProjectionKey::getSpec ).toArray( FeatureProjectionSpec[]::new ); + this.adaptedSpec = new BranchSpotTSneFeatureSpec( projectionSpecs ); + } + + @Plugin( type = FeatureSpec.class ) + public static class BranchSpotTSneFeatureSpec extends FeatureSpec< BranchTSneFeature, BranchSpot > + { + public BranchSpotTSneFeatureSpec() + { + super( KEY, HELP_STRING, BranchTSneFeature.class, BranchSpot.class, Multiplicity.SINGLE ); + } + + public BranchSpotTSneFeatureSpec( final FeatureProjectionSpec... projectionSpecs ) + { + super( KEY, HELP_STRING, BranchTSneFeature.class, BranchSpot.class, Multiplicity.SINGLE, projectionSpecs ); + } + } + + @Override + public FeatureSpec< ? extends Feature< BranchSpot >, BranchSpot > getSpec() + { + return adaptedSpec; + } +} diff --git a/src/main/java/org/mastodon/mamut/feature/branch/dimensionalityreduction/tsne/BranchTSneFeatureComputer.java b/src/main/java/org/mastodon/mamut/feature/branch/dimensionalityreduction/tsne/BranchTSneFeatureComputer.java new file mode 100644 index 000000000..f167f20cb --- /dev/null +++ b/src/main/java/org/mastodon/mamut/feature/branch/dimensionalityreduction/tsne/BranchTSneFeatureComputer.java @@ -0,0 +1,76 @@ +/*- + * #%L + * mastodon-deep-lineage + * %% + * Copyright (C) 2022 - 2024 Stefan Hahmann + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package org.mastodon.mamut.feature.branch.dimensionalityreduction.tsne; + +import java.util.Collection; +import java.util.List; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import org.mastodon.RefPool; +import org.mastodon.mamut.feature.dimensionalityreduction.tsne.feature.AbstractTSneFeature; +import org.mastodon.mamut.feature.dimensionalityreduction.tsne.feature.AbstractTSneFeatureComputer; +import org.mastodon.mamut.model.Model; +import org.mastodon.mamut.model.branch.BranchLink; +import org.mastodon.mamut.model.branch.BranchSpot; +import org.mastodon.mamut.model.branch.ModelBranchGraph; +import org.mastodon.properties.DoublePropertyMap; +import org.scijava.Context; + +public class BranchTSneFeatureComputer extends AbstractTSneFeatureComputer< BranchSpot, BranchLink, ModelBranchGraph > +{ + + public BranchTSneFeatureComputer( final Model model, final Context context ) + { + super( model, context ); + } + + @Override + protected AbstractTSneFeature< BranchSpot > createFeatureInstance( final List< DoublePropertyMap< BranchSpot > > umapOutputMaps ) + { + return new BranchTSneFeature( umapOutputMaps ); + } + + @Override + protected RefPool< BranchSpot > getRefPool() + { + return model.getBranchGraph().vertices().getRefPool(); + } + + @Override + protected ReentrantReadWriteLock getLock( final ModelBranchGraph branchGraph ) + { + return branchGraph.getLock(); + } + + @Override + protected Collection< BranchSpot > getVertices() + { + return model.getBranchGraph().vertices(); + } +} diff --git a/src/main/java/org/mastodon/mamut/feature/branch/dimensionalityreduction/tsne/BranchTSneFeatureSerializer.java b/src/main/java/org/mastodon/mamut/feature/branch/dimensionalityreduction/tsne/BranchTSneFeatureSerializer.java new file mode 100644 index 000000000..8ffae45a1 --- /dev/null +++ b/src/main/java/org/mastodon/mamut/feature/branch/dimensionalityreduction/tsne/BranchTSneFeatureSerializer.java @@ -0,0 +1,72 @@ +/*- + * #%L + * mastodon-deep-lineage + * %% + * Copyright (C) 2022 - 2024 Stefan Hahmann + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package org.mastodon.mamut.feature.branch.dimensionalityreduction.tsne; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +import org.mastodon.feature.FeatureSpec; +import org.mastodon.feature.io.FeatureSerializer; +import org.mastodon.io.FileIdToObjectMap; +import org.mastodon.io.ObjectToFileIdMap; +import org.mastodon.mamut.feature.branch.BranchFeatureSerializer; +import org.mastodon.mamut.feature.branch.dimensionalityreduction.BranchOutputSerializerTools; +import org.mastodon.mamut.model.ModelGraph; +import org.mastodon.mamut.model.Spot; +import org.mastodon.mamut.model.branch.BranchSpot; +import org.mastodon.mamut.model.branch.ModelBranchGraph; +import org.scijava.plugin.Plugin; + +/** + * De-/serializes {@link BranchTSneFeature} + */ +@Plugin( type = FeatureSerializer.class ) +public class BranchTSneFeatureSerializer implements BranchFeatureSerializer< BranchTSneFeature, BranchSpot, Spot > +{ + @Override + public FeatureSpec< BranchTSneFeature, BranchSpot > getFeatureSpec() + { + return BranchTSneFeature.GENERIC_SPEC; + } + + @Override + public void serialize( final BranchTSneFeature feature, final ObjectToFileIdMap< Spot > idmap, final ObjectOutputStream oos, + final ModelBranchGraph branchGraph, final ModelGraph graph ) throws IOException + { + BranchOutputSerializerTools.serialize( feature, idmap, oos, branchGraph, graph ); + } + + @Override + public BranchTSneFeature deserialize( final FileIdToObjectMap< Spot > idmap, final ObjectInputStream ois, + final ModelBranchGraph branchGraph, final ModelGraph graph ) throws ClassNotFoundException, IOException + { + return BranchOutputSerializerTools.deserialize( idmap, ois, branchGraph, graph, BranchTSneFeature::new ); + } +} diff --git a/src/main/java/org/mastodon/mamut/feature/dimensionalityreduction/DimensionalityReductionController.java b/src/main/java/org/mastodon/mamut/feature/dimensionalityreduction/DimensionalityReductionController.java index 618bd351a..c1bde32f4 100644 --- a/src/main/java/org/mastodon/mamut/feature/dimensionalityreduction/DimensionalityReductionController.java +++ b/src/main/java/org/mastodon/mamut/feature/dimensionalityreduction/DimensionalityReductionController.java @@ -37,11 +37,14 @@ import org.mastodon.graph.Edge; import org.mastodon.graph.ReadOnlyGraph; import org.mastodon.graph.Vertex; +import org.mastodon.mamut.feature.branch.dimensionalityreduction.tsne.BranchTSneFeatureComputer; import org.mastodon.mamut.feature.branch.dimensionalityreduction.umap.BranchUmapFeatureComputer; import org.mastodon.mamut.feature.dimensionalityreduction.tsne.TSneSettings; +import org.mastodon.mamut.feature.dimensionalityreduction.tsne.feature.AbstractTSneFeatureComputer; import org.mastodon.mamut.feature.dimensionalityreduction.umap.UmapSettings; import org.mastodon.mamut.feature.dimensionalityreduction.umap.feature.AbstractUmapFeatureComputer; import org.mastodon.mamut.feature.dimensionalityreduction.util.InputDimension; +import org.mastodon.mamut.feature.spot.dimensionalityreduction.tsne.SpotTSneFeatureComputer; import org.mastodon.mamut.feature.spot.dimensionalityreduction.umap.SpotUmapFeatureComputer; import org.mastodon.mamut.model.Link; import org.mastodon.mamut.model.Model; @@ -177,10 +180,23 @@ public void setAlgorithm( final DimensionalityReductionAlgorithm algorithm ) throw new IllegalArgumentException( "Number of output dimensions (" + commonSettings.getNumberOfOutputDimensions() + ") must be smaller than the number of input features (" + inputDimensions.size() + ")." ); G graph = getGraph( isModelGraph ); - AbstractUmapFeatureComputer< V, E, G > umapFeatureComputer = - isModelGraph ? Cast.unchecked( new SpotUmapFeatureComputer( model, context ) ) - : Cast.unchecked( new BranchUmapFeatureComputer( model, context ) ); - umapFeatureComputer.computeFeature( commonSettings, umapSettings, inputDimensions, graph ); + switch ( algorithm ) + { + case UMAP: + AbstractUmapFeatureComputer< V, E, G > umapFeatureComputer = + isModelGraph ? Cast.unchecked( new SpotUmapFeatureComputer( model, context ) ) + : Cast.unchecked( new BranchUmapFeatureComputer( model, context ) ); + umapFeatureComputer.computeFeature( commonSettings, umapSettings, inputDimensions, graph ); + break; + case TSNE: + AbstractTSneFeatureComputer< V, E, G > tSneFeatureComputer = + isModelGraph ? Cast.unchecked( new SpotTSneFeatureComputer( model, context ) ) + : Cast.unchecked( new BranchTSneFeatureComputer( model, context ) ); + tSneFeatureComputer.computeFeature( commonSettings, tSneSettings, inputDimensions, graph ); + break; + default: + throw new IllegalArgumentException( "Unknown algorithm: " + algorithm ); + } } private < V extends Vertex< E >, E extends Edge< V >, G extends ReadOnlyGraph< V, ? > > G getGraph( boolean isSpotGraph ) diff --git a/src/main/java/org/mastodon/mamut/feature/dimensionalityreduction/tsne/feature/AbstractTSneFeature.java b/src/main/java/org/mastodon/mamut/feature/dimensionalityreduction/tsne/feature/AbstractTSneFeature.java new file mode 100644 index 000000000..099cacf01 --- /dev/null +++ b/src/main/java/org/mastodon/mamut/feature/dimensionalityreduction/tsne/feature/AbstractTSneFeature.java @@ -0,0 +1,59 @@ +/*- + * #%L + * mastodon-deep-lineage + * %% + * Copyright (C) 2022 - 2024 Stefan Hahmann + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package org.mastodon.mamut.feature.dimensionalityreduction.tsne.feature; + +import java.util.List; + +import org.mastodon.graph.Vertex; +import org.mastodon.mamut.feature.dimensionalityreduction.AbstractOutputFeature; +import org.mastodon.properties.DoublePropertyMap; + +/** + * This generic feature is used to store the t-SNE outputs. + *
+ * The t-SNE outputs are stored in a list of {@link DoublePropertyMap}s. The size of the list is equal to the number of dimensions of the t-SNE output. + */ +public abstract class AbstractTSneFeature< V extends Vertex< ? > > extends AbstractOutputFeature< V > +{ + private static final String PROJECTION_NAME_TEMPLATE = "tSNE%d"; + + protected static final String HELP_STRING = + "Computes the t-SNE according to the selected input dimensions, number of target dimensions, the perplexity value and maximum number of iterations."; + + protected AbstractTSneFeature( final List< DoublePropertyMap< V > > umapOutputMaps ) + { + super( umapOutputMaps ); + } + + @Override + protected String getProjectionNameTemplate() + { + return PROJECTION_NAME_TEMPLATE; + } +} diff --git a/src/main/java/org/mastodon/mamut/feature/dimensionalityreduction/tsne/feature/AbstractTSneFeatureComputer.java b/src/main/java/org/mastodon/mamut/feature/dimensionalityreduction/tsne/feature/AbstractTSneFeatureComputer.java new file mode 100644 index 000000000..44f747194 --- /dev/null +++ b/src/main/java/org/mastodon/mamut/feature/dimensionalityreduction/tsne/feature/AbstractTSneFeatureComputer.java @@ -0,0 +1,114 @@ +/*- + * #%L + * mastodon-deep-lineage + * %% + * Copyright (C) 2022 - 2024 Stefan Hahmann + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package org.mastodon.mamut.feature.dimensionalityreduction.tsne.feature; + +import java.lang.invoke.MethodHandles; +import java.util.List; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import com.jujutsu.tsne.TSneConfiguration; +import com.jujutsu.tsne.barneshut.BarnesHutTSne; +import com.jujutsu.tsne.barneshut.ParallelBHTsne; +import com.jujutsu.utils.TSneUtils; + +import org.mastodon.RefPool; +import org.mastodon.graph.Edge; +import org.mastodon.graph.ReadOnlyGraph; +import org.mastodon.graph.Vertex; +import org.mastodon.mamut.feature.dimensionalityreduction.AbstractOutputFeatureComputer; +import org.mastodon.mamut.feature.dimensionalityreduction.CommonSettings; +import org.mastodon.mamut.feature.dimensionalityreduction.tsne.TSneSettings; +import org.mastodon.mamut.feature.dimensionalityreduction.util.InputDimension; +import org.mastodon.mamut.model.Model; +import org.mastodon.properties.DoublePropertyMap; +import org.scijava.Context; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Abstract class for computing t-SNE features in the Mastodon project. + *
+ * This provides the base implementation for computing t-SNE features on vertices in a read-only graph. + * It handles the setup, execution, and caching of t-SNE computations. + *
+ * This class connects the t-SNE library to the Mastodon project by providing the necessary data and settings. + * It ensures that only valid data rows (i.e. rows where the selected feature projections do not have values, such as {@link Double#NaN} or {@link Double#POSITIVE_INFINITY}) are used for t-SNE computations. + * + * @param the type of vertex + * @param the type of read-only graph + */ +public abstract class AbstractTSneFeatureComputer< V extends Vertex< E >, E extends Edge< V >, G extends ReadOnlyGraph< V, E > > + extends AbstractOutputFeatureComputer< V, E, G > +{ + + private static final Logger logger = LoggerFactory.getLogger( MethodHandles.lookup().lookupClass() ); + + private TSneSettings tSneSettings; + + private double[][] tSneResult; + + protected AbstractTSneFeatureComputer( final Model model, final Context context ) + { + super( model, context ); + } + + public void computeFeature( final CommonSettings commonSettings, final TSneSettings tSneSettings, + final List< InputDimension< V > > inputDimensions, final G graph ) + { + this.tSneSettings = tSneSettings; + super.computeFeature( commonSettings, inputDimensions, graph ); + } + + @Override + protected void computeAlgorithm( double[][] dataMatrix ) + { + TSneConfiguration tSneConfig = + TSneUtils.buildConfig( dataMatrix, settings.getNumberOfOutputDimensions(), TSneSettings.INITIAL_DIMENSIONS, + tSneSettings.getPerplexity(), + tSneSettings.getMaxIterations(), TSneSettings.USE_PCA, TSneSettings.THETA, false, true ); + + BarnesHutTSne tsne = new ParallelBHTsne(); + logger.info( "Computing t-SNE. Data matrix has {} rows x {} columns.", dataMatrix.length, dataMatrix[ 0 ].length ); + tSneResult = tsne.tsne( tSneConfig ); + logger.info( "Finished computing t-SNE. Results has {} rows x {} columns.", tSneResult.length, + tSneResult.length > 0 ? tSneResult[ 0 ].length : 0 ); + } + + @Override + protected double[][] getResult() + { + return tSneResult; + } + + protected abstract AbstractTSneFeature< V > createFeatureInstance( final List< DoublePropertyMap< V > > umapOutputMaps ); + + protected abstract RefPool< V > getRefPool(); + + protected abstract ReentrantReadWriteLock getLock( final G graph ); +} diff --git a/src/main/java/org/mastodon/mamut/feature/spot/dimensionalityreduction/tsne/SpotTSneFeature.java b/src/main/java/org/mastodon/mamut/feature/spot/dimensionalityreduction/tsne/SpotTSneFeature.java new file mode 100644 index 000000000..5293f76a0 --- /dev/null +++ b/src/main/java/org/mastodon/mamut/feature/spot/dimensionalityreduction/tsne/SpotTSneFeature.java @@ -0,0 +1,85 @@ +/*- + * #%L + * mastodon-deep-lineage + * %% + * Copyright (C) 2022 - 2024 Stefan Hahmann + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package org.mastodon.mamut.feature.spot.dimensionalityreduction.tsne; + +import java.util.List; + +import org.mastodon.feature.Feature; +import org.mastodon.feature.FeatureProjectionKey; +import org.mastodon.feature.FeatureProjectionSpec; +import org.mastodon.feature.FeatureSpec; +import org.mastodon.feature.Multiplicity; +import org.mastodon.mamut.feature.dimensionalityreduction.tsne.feature.AbstractTSneFeature; +import org.mastodon.mamut.model.Spot; +import org.mastodon.properties.DoublePropertyMap; +import org.scijava.plugin.Plugin; + +/** + * Represents a t-SNE feature for spots in the Mastodon project. + *
+ * This feature is used to store the t-SNE outputs for spots. + *
+ * The t-SNE outputs are stored in a list of {@link DoublePropertyMap}s. The size of the list is equal to the number of dimensions of the t-SNE output. + */ +public class SpotTSneFeature extends AbstractTSneFeature< Spot > +{ + public static final String KEY = "Spot t-SNE outputs"; + + private final SpotTSneFeatureSpec adaptedSpec; + + public static final SpotTSneFeatureSpec GENERIC_SPEC = new SpotTSneFeatureSpec(); + + public SpotTSneFeature( final List< DoublePropertyMap< Spot > > outputMaps ) + { + super( outputMaps ); + FeatureProjectionSpec[] projectionSpecs = + projectionMap.keySet().stream().map( FeatureProjectionKey::getSpec ).toArray( FeatureProjectionSpec[]::new ); + this.adaptedSpec = new SpotTSneFeatureSpec( projectionSpecs ); + } + + @Plugin( type = FeatureSpec.class ) + public static class SpotTSneFeatureSpec extends FeatureSpec< SpotTSneFeature, Spot > + { + public SpotTSneFeatureSpec() + { + super( KEY, HELP_STRING, SpotTSneFeature.class, Spot.class, Multiplicity.SINGLE ); + } + + public SpotTSneFeatureSpec( final FeatureProjectionSpec... projectionSpecs ) + { + super( KEY, HELP_STRING, SpotTSneFeature.class, Spot.class, Multiplicity.SINGLE, projectionSpecs ); + } + } + + @Override + public FeatureSpec< ? extends Feature< Spot >, Spot > getSpec() + { + return adaptedSpec; + } +} diff --git a/src/main/java/org/mastodon/mamut/feature/spot/dimensionalityreduction/tsne/SpotTSneFeatureComputer.java b/src/main/java/org/mastodon/mamut/feature/spot/dimensionalityreduction/tsne/SpotTSneFeatureComputer.java new file mode 100644 index 000000000..aad5cf950 --- /dev/null +++ b/src/main/java/org/mastodon/mamut/feature/spot/dimensionalityreduction/tsne/SpotTSneFeatureComputer.java @@ -0,0 +1,76 @@ +/*- + * #%L + * mastodon-deep-lineage + * %% + * Copyright (C) 2022 - 2024 Stefan Hahmann + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package org.mastodon.mamut.feature.spot.dimensionalityreduction.tsne; + +import java.util.Collection; +import java.util.List; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import org.mastodon.RefPool; +import org.mastodon.mamut.feature.dimensionalityreduction.tsne.feature.AbstractTSneFeature; +import org.mastodon.mamut.feature.dimensionalityreduction.tsne.feature.AbstractTSneFeatureComputer; +import org.mastodon.mamut.model.Link; +import org.mastodon.mamut.model.Model; +import org.mastodon.mamut.model.ModelGraph; +import org.mastodon.mamut.model.Spot; +import org.mastodon.properties.DoublePropertyMap; +import org.scijava.Context; + +public class SpotTSneFeatureComputer extends AbstractTSneFeatureComputer< Spot, Link, ModelGraph > +{ + + public SpotTSneFeatureComputer( final Model model, final Context context ) + { + super( model, context ); + } + + @Override + protected AbstractTSneFeature< Spot > createFeatureInstance( final List< DoublePropertyMap< Spot > > outputMaps ) + { + return new SpotTSneFeature( outputMaps ); + } + + @Override + protected RefPool< Spot > getRefPool() + { + return model.getGraph().vertices().getRefPool(); + } + + @Override + protected ReentrantReadWriteLock getLock( final ModelGraph graph ) + { + return graph.getLock(); + } + + @Override + protected Collection< Spot > getVertices() + { + return model.getGraph().vertices(); + } +} diff --git a/src/main/java/org/mastodon/mamut/feature/spot/dimensionalityreduction/tsne/SpotTSneFeatureSerializer.java b/src/main/java/org/mastodon/mamut/feature/spot/dimensionalityreduction/tsne/SpotTSneFeatureSerializer.java new file mode 100644 index 000000000..7fc696396 --- /dev/null +++ b/src/main/java/org/mastodon/mamut/feature/spot/dimensionalityreduction/tsne/SpotTSneFeatureSerializer.java @@ -0,0 +1,70 @@ +/*- + * #%L + * mastodon-deep-lineage + * %% + * Copyright (C) 2022 - 2024 Stefan Hahmann + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package org.mastodon.mamut.feature.spot.dimensionalityreduction.tsne; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +import org.mastodon.collection.RefCollection; +import org.mastodon.feature.FeatureSpec; +import org.mastodon.feature.io.FeatureSerializer; +import org.mastodon.io.FileIdToObjectMap; +import org.mastodon.io.ObjectToFileIdMap; +import org.mastodon.mamut.feature.spot.dimensionalityreduction.SpotOutputFeatureSerializerTools; +import org.mastodon.mamut.model.Spot; +import org.scijava.plugin.Plugin; + +/** + * De-/serializes {@link SpotTSneFeature} + */ +@Plugin( type = FeatureSerializer.class ) +public class SpotTSneFeatureSerializer implements FeatureSerializer< SpotTSneFeature, Spot > +{ + + @Override + public FeatureSpec< SpotTSneFeature, Spot > getFeatureSpec() + { + return SpotTSneFeature.GENERIC_SPEC; + } + + @Override + public void serialize( final SpotTSneFeature feature, final ObjectToFileIdMap< Spot > idMap, final ObjectOutputStream oos ) + throws IOException + { + SpotOutputFeatureSerializerTools.serialize( feature, idMap, oos ); + } + + @Override + public SpotTSneFeature deserialize( final FileIdToObjectMap< Spot > idMap, final RefCollection< Spot > pool, + final ObjectInputStream ois ) throws IOException, ClassNotFoundException + { + return SpotOutputFeatureSerializerTools.deserialize( idMap, pool, ois, SpotTSneFeature::new ); + } +}