/**
   * Links all the spots in the selection, in time-forward order.
   *
   * @param model the model to modify.
   * @param selectionModel the selection that contains the spots to link.
   */
  public static void linkSpots(final Model model, final SelectionModel selectionModel) {

    /*
     * Configure tracker
     */

    final TrackableObjectCollection<Spot> spots =
        new DefaultTOCollection<Spot>(selectionModel.getSpotSelection());
    final Map<String, Object> settings = new HashMap<String, Object>(1);
    settings.put(KEY_LINKING_MAX_DISTANCE, Double.POSITIVE_INFINITY);
    final NearestNeighborTracker<Spot> tracker = new NearestNeighborTracker<Spot>(spots, settings);
    tracker.setNumThreads(1);

    /*
     * Execute tracking
     */

    if (!tracker.checkInput() || !tracker.process()) {
      System.err.println("Problem while computing spot links: " + tracker.getErrorMessage());
      return;
    }
    final SimpleWeightedGraph<Spot, DefaultWeightedEdge> graph = tracker.getResult();

    /*
     * Copy found links in source model
     */

    model.beginUpdate();
    try {
      for (final DefaultWeightedEdge edge : graph.edgeSet()) {
        final Spot source = graph.getEdgeSource(edge);
        final Spot target = graph.getEdgeTarget(edge);
        model.addEdge(source, target, graph.getEdgeWeight(edge));
      }
    } finally {
      model.endUpdate();
    }
  }
 /**
  * Sets the content of the specified selection model to be the whole tracks the selected spots
  * belong to, but searched for only backward in time (backward). Other selected edges are removed
  * from the selection.
  *
  * @param selectionModel the {@link SelectionModel} that will be updated by this call.
  */
 public static <T extends TrackableObject> void selectTrackUpward(
     final SelectionModel selectionModel) {
   selectionModel.clearEdgeSelection();
   selectionModel.selectTrack(
       selectionModel.getSpotSelection(), Collections.<DefaultWeightedEdge>emptyList(), 1);
 }