Skip to content

Commit bae92e6

Browse files
committed
Make the detection preview extensible.
1 parent ef7684e commit bae92e6

1 file changed

Lines changed: 129 additions & 74 deletions

File tree

src/main/java/fiji/plugin/trackmate/util/DetectionPreview.java

Lines changed: 129 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@
2323

2424
import java.util.ArrayList;
2525
import java.util.HashMap;
26-
import java.util.Iterator;
2726
import java.util.Map;
2827
import java.util.function.DoubleConsumer;
2928
import java.util.function.Supplier;
3029

3130
import javax.swing.JFormattedTextField;
3231

32+
import fiji.plugin.trackmate.Logger;
3333
import fiji.plugin.trackmate.Model;
3434
import fiji.plugin.trackmate.Settings;
3535
import fiji.plugin.trackmate.Spot;
@@ -40,13 +40,15 @@
4040
import fiji.plugin.trackmate.features.FeatureFilter;
4141
import fiji.plugin.trackmate.features.FeatureUtils;
4242
import fiji.plugin.trackmate.gui.displaysettings.DisplaySettings.TrackMateObject;
43+
import net.imglib2.util.Pair;
44+
import net.imglib2.util.ValuePair;
4345

4446
public class DetectionPreview
4547
{
4648

4749
private final DetectionPreviewPanel panel;
4850

49-
private DetectionPreview(
51+
protected DetectionPreview(
5052
final Model model,
5153
final Settings settings,
5254
final SpotDetectorFactoryBase< ? > detectorFactory,
@@ -71,7 +73,12 @@ public DetectionPreviewPanel getPanel()
7173
return panel;
7274
}
7375

74-
private final void preview(
76+
public Logger getLogger()
77+
{
78+
return panel.logger;
79+
}
80+
81+
protected void preview(
7582
final Model model,
7683
final Settings settings,
7784
final SpotDetectorFactoryBase< ? > detectorFactory,
@@ -87,78 +94,22 @@ public void run()
8794
{
8895
try
8996
{
90-
91-
// Configure local settings.
92-
final Settings lSettings = new Settings( settings.imp );
93-
lSettings.tstart = frame;
94-
lSettings.tend = frame;
95-
settings.setRoi( settings.imp.getRoi() );
96-
97-
lSettings.detectorFactory = detectorFactory;
98-
lSettings.detectorSettings = new HashMap<>( detectorSettings );
99-
100-
/*
101-
* If we have a threshold parameter, we set it to 0, then we
102-
* will filter out with real value later.
103-
*/
104-
// Does this detector have a THRESHOLD parameter?
105-
final boolean hasThreshold = ( thresholdKey != null ) && ( detectorSettings.containsKey( thresholdKey ) );
106-
final double threshold;
107-
if ( hasThreshold )
108-
{
109-
threshold = ( ( Double ) detectorSettings.get( thresholdKey ) ).doubleValue();
110-
lSettings.detectorSettings.put( thresholdKey, Double.valueOf( Double.NEGATIVE_INFINITY ) );
111-
}
112-
else
113-
{
114-
threshold = Double.NaN;
115-
}
116-
117-
// Execute preview.
118-
final TrackMate trackmate = new TrackMate( lSettings );
119-
trackmate.getModel().setLogger( panel.logger );
120-
121-
final boolean detectionOk = trackmate.execDetection();
122-
if ( !detectionOk )
123-
{
124-
panel.logger.error( trackmate.getErrorMessage() );
97+
// Run preview.
98+
final Pair< Model, Double > out = runPreviewDetection(
99+
settings,
100+
frame,
101+
detectorFactory,
102+
detectorSettings,
103+
thresholdKey );
104+
if ( out == null )
125105
return;
126-
}
127-
128-
if ( hasThreshold )
129-
// Filter by the initial threshold value.
130-
trackmate.getModel().getSpots().filter( new FeatureFilter( Spot.QUALITY, threshold, true ) );
131-
else
132-
// Make them all visible.
133-
trackmate.getModel().getSpots().setVisible( true );
134-
panel.logger.log( "Found " + trackmate.getModel().getSpots().getNSpots( true ) + " spots." );
135-
136-
// Wrap new spots in a list.
137-
final SpotCollection newspots = trackmate.getModel().getSpots();
138-
final Iterator< Spot > it = newspots.iterator( frame, true );
139-
final ArrayList< Spot > spotsToCopy = new ArrayList<>( newspots.getNSpots( frame, true ) );
140-
while ( it.hasNext() )
141-
spotsToCopy.add( it.next() );
142-
143-
if ( model != null )
144-
{
145-
// Pass new spot list to model.
146-
model.getSpots().put( frame, spotsToCopy );
147-
// Make them visible
148-
for ( final Spot spot : spotsToCopy )
149-
spot.putFeature( SpotCollection.VISIBILITY, SpotCollection.ONE );
150-
151-
// Generate event for listener to reflect changes.
152-
model.setSpots( model.getSpots(), true );
153-
}
154-
155-
// Update histogram if any.
156-
if ( panel.chart != null )
157-
{
158-
final double[] values = FeatureUtils.collectFeatureValues(
159-
Spot.QUALITY, TrackMateObject.SPOTS, trackmate.getModel(), false );
160-
panel.chart.displayHistogram( values, threshold );
161-
}
106+
107+
final Model sourceModel = out.getA();
108+
final Double threshold = out.getB();
109+
panel.logger.log( "Found " + sourceModel.getSpots().getNSpots( true ) + " spots." );
110+
111+
// Update target model.
112+
updateModelAndHistogram( model, sourceModel, frame, threshold );
162113
}
163114
catch ( final Exception e )
164115
{
@@ -173,6 +124,110 @@ public void run()
173124
}.start();
174125
}
175126

127+
/**
128+
* Runs the preview with the specified parameters.
129+
*
130+
* @param settings
131+
* the settings object to use as preview. Will be used for its
132+
* image and ROI fields.
133+
* @param frame
134+
* the frame in which to perform the preview.
135+
* @param detectorFactory
136+
* the detector to use for the preview.
137+
* @param detectorSettings
138+
* suitable detection settings for the detector.
139+
* @param thresholdKey
140+
* a key to a parameter that is used by the detector to threshold
141+
* spots based on their quality. This will be used to configure
142+
* the preview so that the generated histogram is interactive. If
143+
* <code>null</code> or not used by the detector, this is simply
144+
* ignored.
145+
* @return a pair of objects: A) The model that contains the results of the
146+
* preview (normally, the visible spots in the specified frame). B)
147+
* The threshold value in case the <code>thresholdKey</code>
148+
* parameter is used. This threshold value is to be used with the
149+
* {@link #updateModelAndHistogram(Model, Model, int, double)}
150+
* method to properly display the quality histogram.
151+
*/
152+
protected Pair< Model, Double > runPreviewDetection(
153+
final Settings settings,
154+
final int frame,
155+
final SpotDetectorFactoryBase< ? > detectorFactory,
156+
final Map< String, Object > detectorSettings,
157+
final String thresholdKey )
158+
{
159+
// Configure local settings.
160+
final Settings lSettings = new Settings( settings.imp );
161+
lSettings.tstart = frame;
162+
lSettings.tend = frame;
163+
settings.setRoi( settings.imp.getRoi() );
164+
165+
lSettings.detectorFactory = detectorFactory;
166+
lSettings.detectorSettings = new HashMap<>( detectorSettings );
167+
168+
// Does this detector have a THRESHOLD parameter?
169+
final boolean hasThreshold = ( thresholdKey != null ) && ( detectorSettings.containsKey( thresholdKey ) );
170+
final double threshold;
171+
if ( hasThreshold )
172+
{
173+
threshold = ( ( Double ) detectorSettings.get( thresholdKey ) ).doubleValue();
174+
lSettings.detectorSettings.put( thresholdKey, Double.valueOf( Double.NEGATIVE_INFINITY ) );
175+
}
176+
else
177+
{
178+
threshold = Double.NaN;
179+
}
180+
181+
// Execute preview.
182+
final TrackMate trackmate = new TrackMate( lSettings );
183+
trackmate.getModel().setLogger( panel.logger );
184+
185+
final boolean detectionOk = trackmate.execDetection();
186+
if ( !detectionOk )
187+
{
188+
panel.logger.error( trackmate.getErrorMessage() );
189+
return null;
190+
}
191+
192+
if ( hasThreshold )
193+
// Filter by the initial threshold value.
194+
trackmate.getModel().getSpots().filter( new FeatureFilter( Spot.QUALITY, threshold, true ) );
195+
else
196+
// Make them all visible.
197+
trackmate.getModel().getSpots().setVisible( true );
198+
199+
return new ValuePair< Model, Double >( trackmate.getModel(), Double.valueOf( threshold ) );
200+
}
201+
202+
protected void updateModelAndHistogram( final Model targetModel, final Model sourceModel, final int frame, final double threshold )
203+
{
204+
final int nSpots = sourceModel.getSpots().getNSpots( frame, true );
205+
final ArrayList< Spot > spotsToCopy = new ArrayList<>( nSpots );
206+
final Iterable< Spot > it = sourceModel.getSpots().iterable( frame, true );
207+
for ( final Spot spot : it )
208+
spotsToCopy.add( spot );
209+
210+
if ( targetModel != null )
211+
{
212+
// Pass new spot list to model.
213+
targetModel.getSpots().put( frame, spotsToCopy );
214+
// Make them visible
215+
for ( final Spot spot : spotsToCopy )
216+
spot.putFeature( SpotCollection.VISIBILITY, SpotCollection.ONE );
217+
218+
// Generate event for listener to reflect changes.
219+
targetModel.setSpots( targetModel.getSpots(), true );
220+
}
221+
222+
// Update histogram if any.
223+
if ( panel.chart != null )
224+
{
225+
final double[] values = FeatureUtils.collectFeatureValues(
226+
Spot.QUALITY, TrackMateObject.SPOTS, sourceModel, false );
227+
panel.chart.displayHistogram( values, threshold );
228+
}
229+
}
230+
176231
public static Builder create()
177232
{
178233
return new Builder();

0 commit comments

Comments
 (0)