Skip to content

Commit

Permalink
Merge pull request #11 from ilastik/reproducible-merger-resolvers
Browse files Browse the repository at this point in the history
Reproducible merger resolvers
  • Loading branch information
k-dominik authored Jan 30, 2023
2 parents 3a9ebe9 + 9fb47e0 commit fd7342d
Show file tree
Hide file tree
Showing 11 changed files with 113 additions and 79 deletions.
40 changes: 0 additions & 40 deletions .circleci/config.yml

This file was deleted.

35 changes: 35 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: deploy

on:
push:
tags:
- '*'


jobs:
deploy-to-ilastik-forge:
# noarch build - build on linux, only
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: actions/checkout@v3
with:
repository: ilastik/ilastik-conda-recipes
path: ilastik-conda-recipes
- uses: conda-incubator/setup-miniconda@v2
with:
auto-update-conda: true
auto-activate-base: true
activate-environment: ""
miniforge-variant: Mambaforge
use-mamba: true
- name: linux conda build and upload
shell: bash -l {0}
env:
ANACONDA_API_TOKEN: ${{ secrets.ANACONDA_TOKEN }}
run: |
mamba install -n base -c conda-forge boa setuptools_scm anaconda-client -y
mamba config --set anaconda_upload yes
conda mambabuild -c ilastik-forge -c conda-forge -m ilastik-conda-recipes/ilastik-pins.yaml --user ilastik-forge conda-recipe
40 changes: 40 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: test

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
test-w-conda-recipe:
strategy:
fail-fast: false
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- uses: conda-incubator/setup-miniconda@v2
with:
activate-environment: ""
auto-activate-base: true
auto-update-conda: true
miniforge-variant: Mambaforge
use-mamba: true
- name: install build deps
run: mamba install -n base -c conda-forge boa setuptools_scm -y
- name: linux conda build test
if: matrix.os == 'ubuntu-latest'
shell: bash -l {0}
run: conda mambabuild -c ilastik-forge -c conda-forge conda-recipe
- name: osx test
if: matrix.os == 'macos-latest'
shell: bash -l {0}
run: conda mambabuild -c ilastik-forge -c conda-forge conda-recipe
- name: windows conda-build
if: matrix.os == 'windows-latest'
shell: cmd /C CALL {0}
run: conda mambabuild -c ilastik-forge -c conda-forge conda-recipe
6 changes: 3 additions & 3 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Tracking Toolbox of the IAL Lab @ uni-heidelberg.de

Build status: [![CircleCI](https://circleci.com/gh/ilastik/hytra.svg?style=svg)](https://circleci.com/gh/ilastik/hytra)

By Carsten Haubold, Steffen Wolf, Letitia Parcalabescu, Bernhard Kausler, Martin Schiegg, Jaime I. Cervantes, Janez Ales and more.

* Build status: [ ![Circle CI](https://circleci.com/gh/ilastik/hytra.png?style=shield&circle-token=27b4fff289dfdb41575cecfab8e865c7cac6a099) ](https://circleci.com/gh/chaubold/hytra)

* build status: [![test](https://github.com/ilastik/hytra/actions/workflows/test.yml/badge.svg)](https://github.com/ilastik/hytra/actions/workflows/test.yml)
* conda: ![last updated](https://anaconda.org/ilastik-forge/hytra/badges/latest_release_date.svg) ![latest-version](https://anaconda.org/ilastik-forge/hytra/badges/version.svg)
* Usage documentation can be found in this [Google document](https://docs.google.com/document/d/1jxkYGlTEUCPqH03pip03eDBBX2pVYEhPGHHvbegHiWw/edit?usp=sharing)
* [API Docs](http://chaubold.github.io/hytra/hytra/index.html)
* Run tests using `nosetests tests` from the root folder
20 changes: 0 additions & 20 deletions appveyor.yml

This file was deleted.

2 changes: 1 addition & 1 deletion conda-recipe/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,6 @@ test:
- nosetests tests

about:
home: https://github.com/chaubold/hytra
home: https://github.com/ilastik/hytra
license: MIT
summary: 'Python tracking framework developed at the IAL lab @ University of Heidelberg'
12 changes: 7 additions & 5 deletions hytra/core/divisionfeatures.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,11 +266,13 @@ def computeFeatures_at(self, feats_cur, feats_next, img_next, feat_names, label_
# find roi around the center of the current object
idx_cur = [round(x) for x in com_cur]

roi = []
for idx, coord in enumerate(idx_cur):
start = max(coord - self.template_size / 2, 0)
stop = min(coord + self.template_size / 2, img_next.shape[idx])
roi.append(slice(int(start), int(stop)))
roi = tuple(
slice(
int(max(coord - self.template_size / 2, 0)),
int(min(coord + self.template_size / 2, img_next.shape[idx])),
)
for idx, coord in enumerate(idx_cur)
)

# find all coms in the neighborhood of com_cur by checking the next frame's labelimage in the roi
subimg_next = img_next[roi]
Expand Down
11 changes: 8 additions & 3 deletions hytra/core/ilastikmergerresolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@ def __init__(
withFullGraph=False,
numSplits=None,
verbose=False,
random_state=None,
):
super(IlastikMergerResolver, self).__init__(pluginPaths, numSplits, verbose)
trackingGraph = hypothesesGraph.toTrackingGraph(noFeatures=True)
self.model = trackingGraph.model
self.result = hypothesesGraph.getSolutionDictionary()
self.hypothesesGraph = hypothesesGraph
self._random_state = random_state

# Find mergers in the given model and result
traxelIdPerTimestepToUniqueIdMap, uuidToTraxelMap = hytra.core.jsongraph.getMappingsBetweenUUIDsAndTraxels(
Expand Down Expand Up @@ -205,9 +207,8 @@ def fitAndRefineNodesForTimestep(self, coordinatesForObjectIds, maxObjectId, tim
nextObjectId = maxObjectId + 1

t = str(timestep)
detections = self.detectionsPerTimestep[t]

for idx, coordinates in coordinatesForObjectIds.items():
for idx, coordinates in sorted(coordinatesForObjectIds.items(), key=lambda x: x[0]):
node = (timestep, idx)
if node not in self.resolvedGraph:
continue
Expand All @@ -228,7 +229,11 @@ def fitAndRefineNodesForTimestep(self, coordinatesForObjectIds, maxObjectId, tim
logger.debug("Looking at node {} in timestep {} with count {}".format(idx, t, count))

# use merger resolving plugin to fit `count` objects
fittedObjects = list(self.mergerResolverPlugin.resolveMergerForCoords(coordinates, count, initializations))
fittedObjects = list(
self.mergerResolverPlugin.resolveMergerForCoords(
coordinates, count, initializations, random_state=self._random_state
)
)

assert len(fittedObjects) == count

Expand Down
11 changes: 6 additions & 5 deletions hytra/plugins/merger_resolver/gmm_merger_resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ class GMMMergerResolver(merger_resolver_plugin.MergerResolverPlugin):
Computes the subtraction of features in the feature vector
"""

def initGMM(self, mergerCount, object_init_list=None):
gmm = mixture.GaussianMixture(n_components=mergerCount)
def initGMM(self, mergerCount, object_init_list=None, random_state=None):
gmm = mixture.GaussianMixture(n_components=mergerCount, random_state=random_state)
if object_init_list is not None and len(object_init_list) > 0:
gmm.weights_ = np.array([o[0] for o in object_init_list])
gmm.covariances_ = np.array([o[1] for o in object_init_list])
Expand All @@ -23,12 +23,13 @@ def initGMM(self, mergerCount, object_init_list=None):
def getObjectInitializationList(self, gmm):
return zip(gmm.weights_, gmm.covariances_, gmm.means_, gmm.precisions_cholesky_)

def resolveMergerForCoords(self, coordinates, mergerCount, initializations=None):
def resolveMergerForCoords(self, coordinates, mergerCount, initializations=None, random_state=None):
"""
Resolve the pixel coordinates belonging to an object ID, into `mergerCount`
new segments by fitting some kind of model. The `initializations` provide fits
in the preceding frame of all possible incomings (list may be empty, but could
also be more than `mergerCount`).
also be more than `mergerCount`). `random_state` can be supplied for consistent
results.
`coordinates` pixel coordinates that belong to a merger ID in labelImage
Expand All @@ -38,7 +39,7 @@ def resolveMergerForCoords(self, coordinates, mergerCount, initializations=None)
"""

# fit GMM to label image data
gmm = self.initGMM(mergerCount, initializations)
gmm = self.initGMM(mergerCount, initializations, random_state)
gmm.fit(coordinates)
assert gmm.converged_

Expand Down
5 changes: 3 additions & 2 deletions hytra/pluginsystem/merger_resolver_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,13 @@ def deactivate(self):
"""
pass

def resolveMergerForCoords(self, coordinates, mergerCount, initializations=None):
def resolveMergerForCoords(self, coordinates, mergerCount, initializations=None, random_state=None):
"""
Resolve the pixel coordinates belonging to an object ID, into `mergerCount`
new segments by fitting some kind of model. The `initializations` provide fits
in the preceding frame of all possible incomings (list may be empty, but could
also be more than `mergerCount`).
also be more than `mergerCount`). `random_state` can be supplied for consistent
results.
`coordinates` pixel coordinates that belong to a merger ID in labelImage
Expand Down
10 changes: 10 additions & 0 deletions tests/core/test_hypothesesgraph.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@
import networkx as nx
from hytra.core.probabilitygenerator import Traxel

# For reason `test_insertEnergies` will error out with 1ULP accuracy on github
# linux CI. Not on any other machines I could test
import os
import platform

ULP = 1
if os.environ.get("CI") and (platform.system() == "Linux"):
ULP = 2


def test_trackletgraph():
h = hg.HypothesesGraph()
Expand Down Expand Up @@ -231,6 +240,7 @@ def transProbFunc(traxelA, traxelB):
[0.45867514538708193],
[1.0 + skipLinkBias * (frame_gap - 1)],
],
maxulp=ULP
)


Expand Down

0 comments on commit fd7342d

Please sign in to comment.