Skip to content

Commit

Permalink
Merge branch 'main' into metadata_update
Browse files Browse the repository at this point in the history
  • Loading branch information
cmalinmayor authored Aug 13, 2024
2 parents 81fec83 + 825a461 commit 65a8b5e
Show file tree
Hide file tree
Showing 28 changed files with 208 additions and 647 deletions.
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ ci:

repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.5.0
rev: v0.5.6
hooks:
- id: ruff
args: [--fix, --unsafe-fixes]
- id: ruff-format

- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.10.1
rev: v1.11.1
hooks:
- id: mypy
files: "^motile/"
10 changes: 1 addition & 9 deletions docs/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ All costs inherit from the following base class:

.. automodule:: motile.costs

.. autoclass:: Costs
.. autoclass:: Cost
:members:

The following lists all costs that are already implemented in ``motile``.
Expand Down Expand Up @@ -156,11 +156,3 @@ Pin
^^^
.. autoclass:: Pin
:show-inheritance:

SelectEdgeNodes (internal use)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. autoclass:: SelectEdgeNodes
:show-inheritance:



40 changes: 20 additions & 20 deletions docs/source/extending.rst
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ object and each edge a potential link of objects between frames:

.. jupyter-execute::

from motile.plot import draw_track_graph
from motile_toolbox.visualization import draw_track_graph

draw_track_graph(graph, alpha_attribute="score", label_attribute="score")

Expand All @@ -81,20 +81,20 @@ model is:

solver = motile.Solver(graph)

solver.add_constraints(MaxParents(1))
solver.add_constraints(MaxChildren(1))
solver.add_constraint(MaxParents(1))
solver.add_constraint(MaxChildren(1))

solver.add_costs(NodeSelection(weight=-1, attribute="score"))
solver.add_costs(EdgeSelection(weight=-1, attribute="score"))
solver.add_costs(Appear(constant=1))
solver.add_cost(NodeSelection(weight=-1, attribute="score"))
solver.add_cost(EdgeSelection(weight=-1, attribute="score"))
solver.add_cost(Appear(constant=1))

solver.solve()

...and our initial solution looks like this:

.. jupyter-execute::

from motile.plot import draw_solution
from motile_toolbox.visualization import draw_solution

draw_solution(graph, solver, label_attribute="score")

Expand Down Expand Up @@ -155,7 +155,7 @@ instantiating the new class:
.. jupyter-execute::
:hide-output:

solver.add_constraints(LimitNumTracks(1))
solver.add_constraint(LimitNumTracks(1))
solver.solve()

.. jupyter-execute::
Expand All @@ -170,18 +170,18 @@ Adding Costs
We might want to add custom costs to ``motile`` that are not already covered by
the existing ones. For the sake of this tutorial, let's say we want to make the
selection of nodes cheaper the higher up the node is in space. For obvious
reasons, let's call this new cost ``SillyCosts``.
reasons, let's call this new cost ``SillyCost``.

Costs in ``motile`` are added by subclassing :class:`Costs
<motile.costs.Costs>` and implementing the :func:`apply
<motile.costs.Costs.apply>` method:
Costs in ``motile`` are added by subclassing :class:`Cost
<motile.costs.Cost>` and implementing the :func:`apply
<motile.costs.Cost.apply>` method:

.. jupyter-execute::

from motile.variables import NodeSelected


class SillyCosts(motile.costs.Costs):
class SillyCost(motile.costs.Cost):

def __init__(self, position_attribute, weight=1.0):
self.position_attribute = position_attribute
Expand All @@ -208,15 +208,15 @@ We can now add those costs in the same way others are added, i.e.:

.. jupyter-execute::

print("Before adding silly costs:")
print("Before adding silly cost:")
print(solver.get_variables(NodeSelected))

solver.add_costs(SillyCosts('x', weight=0.02))
solver.add_cost(SillyCost('x', weight=0.02))

print("After adding silly costs:")
print("After adding silly cost:")
print(solver.get_variables(NodeSelected))

As we can see, our new costs have been applied to each ``NodeSelected``
As we can see, our new cost have been applied to each ``NodeSelected``
variable and nodes with a larger ``x`` value are now cheaper than others.

Solving again will now select the upper one of the possible tracks in the track
Expand Down Expand Up @@ -322,12 +322,12 @@ The complete variable declaration looks like this:
Variables on their own, however, don't do anything yet. They only start to
affect the solution if they are involved in constraints or have a cost.

The following defines costs on our new variables, which loosely approximate the
The following defines a cost on our new variables, which loosely approximate the
local curvature of the track:

.. jupyter-execute::

class CurvatureCosts(motile.costs.Costs):
class CurvatureCost(motile.costs.Cost):

def __init__(self, position_attribute, weight=1.0):
self.position_attribute = position_attribute
Expand Down Expand Up @@ -364,7 +364,7 @@ added variables:
.. jupyter-execute::
:hide-output:

solver.add_costs(CurvatureCosts('x', weight=0.1))
solver.add_cost(CurvatureCost('x', weight=0.1))
solver.solve()

Let's inspect the solution!
Expand Down
12 changes: 6 additions & 6 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ object and each edge a potential link of objects between frames:

import motile
from motile.variables import NodeSelected, EdgeSelected
from motile.plot import draw_track_graph, draw_solution
from motile_toolbox.visualization import draw_track_graph, draw_solution


.. jupyter-execute::
Expand Down Expand Up @@ -90,21 +90,21 @@ subject to certain constraints. This can be done with ``motile`` as follows:
solver = motile.Solver(graph)

# tell it how to compute costs for selecting nodes and edges
solver.add_costs(
solver.add_cost(
NodeSelection(
weight=-1.0,
attribute='score'))
solver.add_costs(
solver.add_cost(
EdgeSelection(
weight=-1.0,
attribute='score'))

# add a small penalty to start a new track
solver.add_costs(Appear(constant=1.0))
solver.add_cost(Appear(constant=1.0))

# add constraints on the solution (no splits, no merges)
solver.add_constraints(MaxParents(1))
solver.add_constraints(MaxChildren(1))
solver.add_constraint(MaxParents(1))
solver.add_constraint(MaxChildren(1))

# solve
solution = solver.solve()
Expand Down
28 changes: 14 additions & 14 deletions docs/source/learning.rst
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ object and each edge a potential link of objects between frames:

.. jupyter-execute::

from motile.plot import draw_track_graph
from motile_toolbox.visualization import draw_track_graph

draw_track_graph(graph, alpha_attribute="score", label_attribute="score")

Expand All @@ -88,12 +88,12 @@ model is:

solver = motile.Solver(graph)

solver.add_constraints(MaxParents(1))
solver.add_constraints(MaxChildren(1))
solver.add_constraint(MaxParents(1))
solver.add_constraint(MaxChildren(1))

solver.add_costs(NodeSelection(weight=1, attribute="score"))
solver.add_costs(EdgeSelection(weight=-2, attribute="score", constant=1))
solver.add_costs(Appear(constant=1))
solver.add_cost(NodeSelection(weight=1, attribute="score"))
solver.add_cost(EdgeSelection(weight=-2, attribute="score", constant=1))
solver.add_cost(Appear(constant=1))

Each of those costs is calculated as the product of `weights` and `features`:

Expand Down Expand Up @@ -144,7 +144,7 @@ Our initial weights are just a guess, let's solve...
:hide-output:

from motile.variables import NodeSelected, EdgeSelected
from motile.plot import draw_solution
from motile_toolbox.visualization import draw_solution

solver.solve()

Expand All @@ -158,10 +158,10 @@ Our initial weights are just a guess, let's solve...
draw_solution(graph, solver, label_attribute="score")

None of the nodes or edges were selected, which is indeed the cost minimal
solution: the costs for selecting nodes or edges is too high.
solution: the cost for selecting nodes or edges is too high.

We can use the ``solver.weights`` object to directly modify the weights on the
costs. Here, we further lower the costs of edges for example:
costs. Here, we further lower the cost of edges for example:

.. jupyter-execute::
:hide-output:
Expand Down Expand Up @@ -252,12 +252,12 @@ To see whether those weights are any good, we will solve again...

solver = motile.Solver(graph)

solver.add_constraints(MaxParents(1))
solver.add_constraints(MaxChildren(1))
solver.add_constraint(MaxParents(1))
solver.add_constraint(MaxChildren(1))

solver.add_costs(NodeSelection(weight=1, attribute="score"))
solver.add_costs(EdgeSelection(weight=-2, attribute="score", constant=1))
solver.add_costs(Appear(constant=1))
solver.add_cost(NodeSelection(weight=1, attribute="score"))
solver.add_cost(EdgeSelection(weight=-2, attribute="score", constant=1))
solver.add_cost(Appear(constant=1))

solver.weights.from_ndarray(optimal_weights.to_ndarray())

Expand Down
18 changes: 9 additions & 9 deletions docs/source/quickstart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ object and each edge a potential link of objects between frames:
.. jupyter-execute::

import motile
from motile.plot import draw_track_graph, draw_solution
from motile_toolbox.visualization import draw_track_graph, draw_solution

draw_track_graph(graph, alpha_attribute='score', label_attribute='score')

Expand Down Expand Up @@ -88,7 +88,7 @@ First, we have to create a :class:`Solver` for our track graph:
solver = motile.Solver(graph)

Once a solver is created, we can add costs and constraints to it. We start with
the most basic ones: the costs for selecting a node or an edge. Both nodes and
the most basic ones: the cost for selecting a node or an edge. Both nodes and
edges in our example graph have an attribute ``score``, which indicates how
likely the node or edge is a true positive and should therefore be selected. A
higher score is better.
Expand All @@ -104,11 +104,11 @@ classes :class:`costs.NodeSelection` and

from motile.costs import NodeSelection, EdgeSelection

solver.add_costs(
solver.add_cost(
NodeSelection(
weight=-1.0,
attribute='score'))
solver.add_costs(
solver.add_cost(
EdgeSelection(
weight=-1.0,
attribute='score'))
Expand Down Expand Up @@ -169,8 +169,8 @@ sure that tracks don't merge or split:

from motile.constraints import MaxParents, MaxChildren

solver.add_constraints(MaxParents(1))
solver.add_constraints(MaxChildren(1))
solver.add_constraint(MaxParents(1))
solver.add_constraint(MaxChildren(1))

If we solve again, the solution does now look like this:

Expand All @@ -195,8 +195,8 @@ track consisting of just one node. To avoid those short tracks, we can add a
constant cost for the appearance of a track: only tracks that are long enough
to offset this cost will then be selected.

Adding Costs for Starting a Track
---------------------------------
Adding a Cost for Starting a Track
----------------------------------

``motile`` provides :class:`costs.Appear`, which we can add to our solver to
discourage selection of short tracks. We add them similarly to how we added the
Expand All @@ -206,7 +206,7 @@ node and edge selection costs:

from motile.costs import Appear

solver.add_costs(Appear(constant=1.0))
solver.add_cost(Appear(constant=1.0))

And if we solve the tracking problem again with those costs...

Expand Down
2 changes: 0 additions & 2 deletions motile/constraints/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
from .max_children import MaxChildren
from .max_parents import MaxParents
from .pin import Pin
from .select_edge_nodes import SelectEdgeNodes

__all__ = [
"Constraint",
Expand All @@ -13,5 +12,4 @@
"MaxChildren",
"MaxParents",
"Pin",
"SelectEdgeNodes",
]
39 changes: 0 additions & 39 deletions motile/constraints/select_edge_nodes.py

This file was deleted.

4 changes: 2 additions & 2 deletions motile/costs/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from .appear import Appear
from .costs import Costs
from .cost import Cost
from .disappear import Disappear
from .edge_distance import EdgeDistance
from .edge_selection import EdgeSelection
Expand All @@ -11,7 +11,7 @@

__all__ = [
"Appear",
"Costs",
"Cost",
"Disappear",
"EdgeDistance",
"EdgeSelection",
Expand Down
Loading

0 comments on commit 65a8b5e

Please sign in to comment.