trackmate-sc / TrackMate

TrackMate is your buddy for your everyday tracking.
https://imagej.net/plugins/trackmate
GNU General Public License v3.0
169 stars 76 forks source link

Draft PR that tracks the work towards TrackMate v8 #309

Open tinevez opened 2 weeks ago

tinevez commented 2 weeks ago

TrackMate v8 - better integration of external segmentation algorithms and interactive segmentation editor

A LabKit launcher made to edit spots in the current frame

This launcher catches what time-point is currently displayed, and wrap all information needed for LabKit to edit the spot it contains, as labels.

TrackMate-LabKit_01 TrackMate-LabKit_02 TrackMate-LabKit_03

While the user edits the labels in LabKit, the TrackMate UI is disabled. Once the user closes the LabKit window, the modifications they made are inspected. This class compares the new labels with the previous ones, and can determine whether a spot has been added, removed or modified. In the last case it updates the model with the modified spots, and reintroduces it in the tracks as it should.

TrackMate-LabKit_04

All features of modified spots and their edges are recomputed.

If a label has several connected components, they are added as separate spots. The one closest to the original spot is reintroduced in the tracks.

For developers: tools to integrate algorithms run from a command line interface

There is now a small framework to make it simpler and faster to integrate in TrackMate segmentation or tracking algorithms that can be run from a command line interface (CLI). Examples of such CLI components are cellpose, omnipose, YOLO, Trackastra, etc.

The CLI framework is in the fiji.plugin.trackmate.util.cli package. A developer that wants to integrate a CLI component needs to extend the class CLIConfigurator, declaring the parameters that the CLI will accept. The syntax is made to resemble that of Python argparse For instance for Trackastra (another module):

public class TrackastraCLI extends CondaCLIConfigurator
{
// ...

    public TrackastraCLI( final int nChannels )
    {
        this.modelPretrained = addChoiceArgument()
                .name( "Model pretrained" )
                .help( "Name of pretrained Trackastra model." )
                .argument( "--model-pretrained" )
                .addChoice( "general_2d" )
                .addChoice( "ctc" )
                .defaultValue( DEFAULT_TRACKASTRA_MODEL )
                .key( KEY_TRACKASTRA_MODEL )
                .get();

        this.customModelPath = addPathArgument()
                .name( "Path to a custom model" )
                .argument( "--model-custom" )
                .help( "Local folder with custom model." )
                .defaultValue( DEFAULT_TRACKASTRA_CUSTOM_MODEL_FOLDER )
                .key( KEY_TRACKASTRA_CUSTOM_MODEL_FOLDER )
                .get();

        // ...

The addChoiceArgument() method will declare an argument that can accept a series of discrete values (specified by addChoice). The addPathArgument() method will declare an argument that is actually a path to a file. They take the shape of a Builder pattern, where:

Let's carry on with example from YOLO integration:

        this.conf = addDoubleArgument()
                .name( "Confidence threshold" )
                .argument( "conf=" )
                .defaultValue( DEFAULT_YOLO_CONF )
                .min( 0. )
                .max( 1. )
                .help( "Sets the minimum confidence threshold for detections. Objects detected "
                        + "with confidence below this threshold will be disregarded. Adjusting "
                        + "this value can help reduce false positives." )
                .key( KEY_YOLO_CONF )
                .get();

This builder adds an argument that accept floating point argument, as doubles.

        addFlag()
                .name( "Save detections to text files" )
                .help( "Whether the detections will be saved as a text files." )
                .argument( "save_txt=" )
                .defaultValue( true )
                .required( true )
                .visible( false )
                .key( null )
                .get();

The addFlag() builder adds a boolean switch argument. In the CLI tools we have been trying to implement, they exist in two flavors.

In this specific case, we want to tell YOLO to save results to text files so that TrackMate can read them and import detection results from them. We want to set the value of this argument to always true and don't let the user change this value in TrackMate. To this aim:

We use the same strategy for the arguments that say where to load the input images from. This parameter is set by TrackMate when it exports the image to disk for YOLO, and must not be set by the user. This is how it is done:

        this.imageFolder = addPathArgument()
                .name( "Input image folder path" )
                .help( "Directory with series of .tif files." )
                .argument( "source=" )
                .visible( false )
                .required( true )
                .key( null )
                .get();

visible( false ) and key( null ) make sure the argument won't be visible in the UI, and won't be serialized in the TrackMate XML file, but because there is a argument, the CLI will have it, configured by the TrackMate detector.