Skip to content

Commit b45ca12

Browse files
author
Stefan Hahmann
committed
Add unit tests for BranchPcaFeature and SpotPcaFeature
1 parent f48caa2 commit b45ca12

File tree

2 files changed

+301
-0
lines changed

2 files changed

+301
-0
lines changed
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
/*-
2+
* #%L
3+
* mastodon-deep-lineage
4+
* %%
5+
* Copyright (C) 2022 - 2024 Stefan Hahmann
6+
* %%
7+
* Redistribution and use in source and binary forms, with or without
8+
* modification, are permitted provided that the following conditions are met:
9+
*
10+
* 1. Redistributions of source code must retain the above copyright notice,
11+
* this list of conditions and the following disclaimer.
12+
* 2. Redistributions in binary form must reproduce the above copyright notice,
13+
* this list of conditions and the following disclaimer in the documentation
14+
* and/or other materials provided with the distribution.
15+
*
16+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
20+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26+
* POSSIBILITY OF SUCH DAMAGE.
27+
* #L%
28+
*/
29+
package org.mastodon.mamut.feature.branch.dimensionalityreduction.pca;
30+
31+
import static org.junit.jupiter.api.Assertions.assertFalse;
32+
import static org.junit.jupiter.api.Assertions.assertNotEquals;
33+
import static org.junit.jupiter.api.Assertions.assertNotNull;
34+
import static org.junit.jupiter.api.Assertions.assertTrue;
35+
36+
import java.io.IOException;
37+
import java.util.Collections;
38+
import java.util.Iterator;
39+
import java.util.List;
40+
import java.util.function.Supplier;
41+
42+
import net.imglib2.util.Cast;
43+
44+
import org.junit.jupiter.api.BeforeEach;
45+
import org.junit.jupiter.api.Test;
46+
import org.mastodon.feature.Dimension;
47+
import org.mastodon.feature.FeatureModel;
48+
import org.mastodon.feature.FeatureProjection;
49+
import org.mastodon.feature.FeatureProjectionSpec;
50+
import org.mastodon.mamut.feature.AbstractFeatureTest;
51+
import org.mastodon.mamut.feature.FeatureComputerTestUtils;
52+
import org.mastodon.mamut.feature.FeatureSerializerTestUtils;
53+
import org.mastodon.mamut.feature.FeatureUtils;
54+
import org.mastodon.mamut.feature.branch.BranchDisplacementDurationFeature;
55+
import org.mastodon.mamut.feature.branch.exampleGraph.ExampleGraph7;
56+
import org.mastodon.mamut.feature.branch.sinuosity.BranchSinuosityFeature;
57+
import org.mastodon.mamut.feature.dimensionalityreduction.DimensionalityReductionAlgorithm;
58+
import org.mastodon.mamut.feature.dimensionalityreduction.DimensionalityReductionController;
59+
import org.mastodon.mamut.feature.dimensionalityreduction.util.InputDimension;
60+
import org.mastodon.mamut.model.Model;
61+
import org.mastodon.mamut.model.branch.BranchLink;
62+
import org.mastodon.mamut.model.branch.BranchSpot;
63+
import org.scijava.Context;
64+
65+
public class BranchPcaFeatureTest extends AbstractFeatureTest< BranchSpot >
66+
{
67+
private BranchPcaFeature pcaFeature;
68+
69+
private final ExampleGraph7 graph7 = new ExampleGraph7();
70+
71+
private FeatureProjectionSpec spec0;
72+
73+
private FeatureProjectionSpec spec1;
74+
75+
@BeforeEach
76+
public void setUp()
77+
{
78+
try (Context context = new Context())
79+
{
80+
Model model = graph7.getModel();
81+
FeatureModel featureModel = model.getFeatureModel();
82+
83+
// declare some features as input dimensions
84+
BranchDisplacementDurationFeature branchDisplacementDurationFeature = Cast.unchecked(
85+
FeatureComputerTestUtils.getFeature( context, model, BranchDisplacementDurationFeature.SPEC ) );
86+
featureModel.declareFeature( branchDisplacementDurationFeature );
87+
BranchSinuosityFeature branchSinuosityFeature = Cast.unchecked(
88+
FeatureComputerTestUtils.getFeature( context, model, BranchSinuosityFeature.BRANCH_SINUOSITY_FEATURE_SPEC ) );
89+
featureModel.declareFeature( branchSinuosityFeature );
90+
List< InputDimension< BranchSpot > > inputDimensions =
91+
InputDimension.getListFromFeatureModel( featureModel, BranchSpot.class, BranchLink.class );
92+
93+
// set up the controller and compute the feature
94+
Supplier< List< InputDimension< BranchSpot > > > inputDimensionsSupplier = () -> inputDimensions;
95+
DimensionalityReductionController controller = new DimensionalityReductionController( graph7.getModel(), context );
96+
controller.setModelGraph( false );
97+
controller.setAlgorithm( DimensionalityReductionAlgorithm.PCA );
98+
controller.computeFeature( inputDimensionsSupplier );
99+
pcaFeature = FeatureUtils.getFeature( graph7.getModel(), BranchPcaFeature.BranchSpotPcaFeatureSpec.class );
100+
assertNotNull( pcaFeature );
101+
spec0 = new FeatureProjectionSpec( pcaFeature.getProjectionName( 0 ), Dimension.NONE );
102+
spec1 = new FeatureProjectionSpec( pcaFeature.getProjectionName( 1 ), Dimension.NONE );
103+
104+
}
105+
}
106+
107+
@Test
108+
@Override
109+
public void testFeatureComputation()
110+
{
111+
assertNotNull( pcaFeature );
112+
FeatureProjection< BranchSpot > projection0 = getProjection( pcaFeature, spec0 );
113+
FeatureProjection< BranchSpot > projection1 = getProjection( pcaFeature, spec1 );
114+
Iterator< BranchSpot > branchSpotIterator = graph7.getModel().getBranchGraph().vertices().iterator();
115+
BranchSpot branchSpot = branchSpotIterator.next();
116+
assertFalse( Double.isNaN( projection0.value( branchSpot ) ) );
117+
assertNotEquals( 0, projection0.value( branchSpot ) );
118+
assertFalse( Double.isNaN( projection1.value( branchSpot ) ) );
119+
assertNotEquals( 0, projection1.value( branchSpot ) );
120+
}
121+
122+
@Test
123+
@Override
124+
public void testFeatureSerialization() throws IOException
125+
{
126+
BranchPcaFeature pcaFeatureReloaded;
127+
try (Context context = new Context())
128+
{
129+
pcaFeatureReloaded =
130+
( BranchPcaFeature ) FeatureSerializerTestUtils.saveAndReload( context, graph7.getModel(), this.pcaFeature );
131+
}
132+
assertNotNull( pcaFeatureReloaded );
133+
Iterator< BranchSpot > branchSpotIterator = graph7.getModel().getBranchGraph().vertices().iterator();
134+
BranchSpot branchSpot = branchSpotIterator.next();
135+
// check that the feature has correct values after saving and reloading
136+
assertTrue( FeatureSerializerTestUtils.checkFeatureProjectionEquality( this.pcaFeature, pcaFeatureReloaded,
137+
Collections.singleton( branchSpot ) ) );
138+
}
139+
140+
@Test
141+
@Override
142+
public void testFeatureInvalidate()
143+
{
144+
Iterator< BranchSpot > branchSpotIterator = graph7.getModel().getBranchGraph().vertices().iterator();
145+
BranchSpot branchSpot = branchSpotIterator.next();
146+
147+
// test, if features are not NaN before invalidation
148+
assertFalse( Double.isNaN( getProjection( pcaFeature, spec0 ).value( branchSpot ) ) );
149+
assertFalse( Double.isNaN( getProjection( pcaFeature, spec1 ).value( branchSpot ) ) );
150+
151+
// invalidate feature
152+
pcaFeature.invalidate( branchSpot );
153+
154+
// test, if features are NaN after invalidation
155+
assertTrue( Double.isNaN( getProjection( pcaFeature, spec0 ).value( branchSpot ) ) );
156+
assertTrue( Double.isNaN( getProjection( pcaFeature, spec1 ).value( branchSpot ) ) );
157+
}
158+
}
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
/*-
2+
* #%L
3+
* mastodon-deep-lineage
4+
* %%
5+
* Copyright (C) 2022 - 2024 Stefan Hahmann
6+
* %%
7+
* Redistribution and use in source and binary forms, with or without
8+
* modification, are permitted provided that the following conditions are met:
9+
*
10+
* 1. Redistributions of source code must retain the above copyright notice,
11+
* this list of conditions and the following disclaimer.
12+
* 2. Redistributions in binary form must reproduce the above copyright notice,
13+
* this list of conditions and the following disclaimer in the documentation
14+
* and/or other materials provided with the distribution.
15+
*
16+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
20+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26+
* POSSIBILITY OF SUCH DAMAGE.
27+
* #L%
28+
*/
29+
package org.mastodon.mamut.feature.spot.dimensionalityreduction.pca;
30+
31+
import static org.junit.jupiter.api.Assertions.assertFalse;
32+
import static org.junit.jupiter.api.Assertions.assertNotEquals;
33+
import static org.junit.jupiter.api.Assertions.assertNotNull;
34+
import static org.junit.jupiter.api.Assertions.assertTrue;
35+
36+
import java.io.IOException;
37+
import java.util.Collections;
38+
import java.util.Iterator;
39+
import java.util.List;
40+
import java.util.function.Supplier;
41+
42+
import org.junit.jupiter.api.BeforeEach;
43+
import org.junit.jupiter.api.Test;
44+
import org.mastodon.feature.Dimension;
45+
import org.mastodon.feature.FeatureModel;
46+
import org.mastodon.feature.FeatureProjection;
47+
import org.mastodon.feature.FeatureProjectionSpec;
48+
import org.mastodon.mamut.feature.AbstractFeatureTest;
49+
import org.mastodon.mamut.feature.FeatureSerializerTestUtils;
50+
import org.mastodon.mamut.feature.FeatureUtils;
51+
import org.mastodon.mamut.feature.branch.exampleGraph.ExampleGraph7;
52+
import org.mastodon.mamut.feature.dimensionalityreduction.DimensionalityReductionAlgorithm;
53+
import org.mastodon.mamut.feature.dimensionalityreduction.DimensionalityReductionController;
54+
import org.mastodon.mamut.feature.dimensionalityreduction.util.InputDimension;
55+
import org.mastodon.mamut.model.Link;
56+
import org.mastodon.mamut.model.Spot;
57+
import org.scijava.Context;
58+
59+
public class SpotPcaFeatureTest extends AbstractFeatureTest< Spot >
60+
{
61+
private SpotPcaFeature spotPcaFeature;
62+
63+
private final ExampleGraph7 graph7 = new ExampleGraph7();
64+
65+
private FeatureProjectionSpec spec0;
66+
67+
private FeatureProjectionSpec spec1;
68+
69+
@BeforeEach
70+
public void setUp()
71+
{
72+
try (Context context = new Context())
73+
{
74+
FeatureModel featureModel = graph7.getModel().getFeatureModel();
75+
DimensionalityReductionController controller = new DimensionalityReductionController( graph7.getModel(), context );
76+
controller.setAlgorithm( DimensionalityReductionAlgorithm.PCA );
77+
Supplier< List< InputDimension< Spot > > > inputDimensionsSupplier =
78+
() -> InputDimension.getListFromFeatureModel( featureModel, Spot.class, Link.class );
79+
controller.computeFeature( inputDimensionsSupplier );
80+
spotPcaFeature = FeatureUtils.getFeature( graph7.getModel(), SpotPcaFeature.SpotPcaFeatureSpec.class );
81+
assertNotNull( spotPcaFeature );
82+
spec0 = new FeatureProjectionSpec( spotPcaFeature.getProjectionName( 0 ), Dimension.NONE );
83+
spec1 = new FeatureProjectionSpec( spotPcaFeature.getProjectionName( 1 ), Dimension.NONE );
84+
}
85+
}
86+
87+
@Test
88+
@Override
89+
public void testFeatureComputation()
90+
{
91+
assertNotNull( spotPcaFeature );
92+
FeatureProjection< Spot > projection0 = getProjection( spotPcaFeature, spec0 );
93+
FeatureProjection< Spot > projection1 = getProjection( spotPcaFeature, spec1 );
94+
Iterator< Spot > spotIterator = graph7.getModel().getGraph().vertices().iterator();
95+
Spot spot0 = spotIterator.next();
96+
assertTrue( Double.isNaN( projection0.value( spot0 ) ) );
97+
assertTrue( Double.isNaN( projection1.value( spot0 ) ) );
98+
Spot spot1 = spotIterator.next();
99+
assertFalse( Double.isNaN( projection0.value( spot1 ) ) );
100+
assertFalse( Double.isNaN( projection1.value( spot1 ) ) );
101+
assertNotEquals( 0, projection0.value( spot1 ) );
102+
assertNotEquals( 0, projection1.value( spot1 ) );
103+
}
104+
105+
@Test
106+
@Override
107+
public void testFeatureSerialization() throws IOException
108+
{
109+
SpotPcaFeature spotPcaFeatureReloaded;
110+
try (Context context = new Context())
111+
{
112+
spotPcaFeatureReloaded =
113+
( SpotPcaFeature ) FeatureSerializerTestUtils.saveAndReload( context, graph7.getModel(), spotPcaFeature );
114+
}
115+
assertNotNull( spotPcaFeatureReloaded );
116+
// check that the feature has correct values after saving and reloading
117+
Iterator< Spot > spotIterator = graph7.getModel().getGraph().vertices().iterator();
118+
spotIterator.next();
119+
Spot spot1 = spotIterator.next();
120+
assertTrue( FeatureSerializerTestUtils.checkFeatureProjectionEquality(
121+
spotPcaFeature, spotPcaFeatureReloaded,
122+
Collections.singleton( spot1 ) ) );
123+
}
124+
125+
@Test
126+
@Override
127+
public void testFeatureInvalidate()
128+
{
129+
// test, if features are not NaN before invalidation
130+
Iterator< Spot > spotIterator = graph7.getModel().getGraph().vertices().iterator();
131+
spotIterator.next();
132+
Spot spot1 = spotIterator.next();
133+
assertFalse( Double.isNaN( getProjection( spotPcaFeature, spec0 ).value( spot1 ) ) );
134+
assertFalse( Double.isNaN( getProjection( spotPcaFeature, spec1 ).value( spot1 ) ) );
135+
136+
// invalidate feature
137+
spotPcaFeature.invalidate( spot1 );
138+
139+
// test, if features are NaN after invalidation
140+
assertTrue( Double.isNaN( getProjection( spotPcaFeature, spec0 ).value( spot1 ) ) );
141+
assertTrue( Double.isNaN( getProjection( spotPcaFeature, spec1 ).value( spot1 ) ) );
142+
}
143+
}

0 commit comments

Comments
 (0)