-
Notifications
You must be signed in to change notification settings - Fork 76
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft PR that targets the work done towards TrackMate v9 #308
Draft
tinevez
wants to merge
219
commits into
v8-new
Choose a base branch
from
v9
base: v8-new
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Still not good enough, the vertices are not iterated in a monotonic manner.
Better but still not good enough: some points on the contours are repeated.
Also do not add duplicate points on the contour (happens often when there is no smoothing). Still not good: there are some cases where the loop breaks too early.
Much cleaner. Still does not work for not simple meshes. Probably because of border cases where we have vertices that lie exactly on the plane we are interesecting with.
This class is the 3D counterpart of SpotRoi. It stores the object shape as a mesh, and has (for now) a few methods to facilitate painting it and creating it. The mesh are stored with coordinates relative to the spot center (mesh center is at 0,0,0). The same for the bounding box. The mesh coordinates are expected to be in physical coordinates, not pixel coordinates.
and write them in holders provided by the user.
We simply reslice the mesh at the Z slice currently displayed, and paint the intersection as a collection of segments. I also took the opportunity to refactor a bit the SpotOverlay. Right now this works but is not optimal: 1/ There are weird stuff happening at the *top* of the mesh: it's like we miss some part of it. 2/ The slice routine generates a list of disconnected segments. It does not show when we paint them, but maybe would be nice to reconstruct the collection of contours resulting from the intersection of a mesh with a plane. 3/ We could optimize the slice() routinemaybe by having an index that sorts triangles by their minZ value, and another index that sorts them by their maxZ value. This way we could quickly retrieve the triangles to sort by two binary-search and one set intersection.
While we try to make better slices.
It is working for simple meshes but the ones we have have too many border cases and make it fail.
Not good enough yet.
At least on star-convex objects, but does not assume they are. Still very tiny final border cases, where the iteration stops early at the poles of an object, but it's nothing unsurmontable. Tomorrow.
…ard. But because the other table, trackscheme and bvv buttons take too much place, we don't see it without resizing the window.
- We don't depend on labels anymore, but directly operate and compare the index images (before modification and after). Because the index is directly related to the spot ID, we can get a match from previous spot to novel spot in an easy manner. - The spots from the edited version are created directly from the novel index image, using something adapted from the label image detector code, so again, just one pass. We use the fact that we can provide it with a 'quality' image, and read the index of the label image 'under' the spot and write it into its quality value. This way we can retrieve the id of the matching previous spot in an easy manner. - The price to pay for not working with labels anymore is that we don't have access to the label name, but that's life. - We make only one pass over the image to collect the ids of the spots that have been modified, instead of one pass per spot. Also, this pass is multithreaded (thanks LoopBuilder). - I have also learned that I should not use weakListeners() if I am doing something with threads inside the listener. Using listeners() instead works, but I do not know why the other one does not. Probably something arcane with Java WeakReferences being collected. - As a result of all this the performance is much better than before and the 'return to TrackMate' should happen without the user noticing the process.
This test fails because of the LegacyService, see the stack trace below. If I add the static { net.imagej.patcher.LegacyInjector.preinit(); } initializer block as suggested here: https://forum.image.sc/t/imagej-legacy-error/23013 then the test passes in Eclipse, but still fails in Maven. So this commit at least adds the initializer so that it works in Eclipse. Note that it still fails on Maven, and proably with deploy actions too. [INFO] Running fiji.plugin.trackmate.TrackMatePluginTest [ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.787 s <<< FAILURE! -- in fiji.plugin.trackmate.TrackMatePluginTest [ERROR] fiji.plugin.trackmate.TrackMatePluginTest.testTrackMateRegistration -- Time elapsed: 0.787 s <<< ERROR! java.lang.ExceptionInInitializerError at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at org.junit.runners.BlockJUnit4ClassRunner.createTest(BlockJUnit4ClassRunner.java:250) at org.junit.runners.BlockJUnit4ClassRunner.createTest(BlockJUnit4ClassRunner.java:260) at org.junit.runners.BlockJUnit4ClassRunner$2.runReflectiveCall(BlockJUnit4ClassRunner.java:309) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.BlockJUnit4ClassRunner.methodBlock(BlockJUnit4ClassRunner.java:306) at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63) at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329) at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293) at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306) at org.junit.runners.ParentRunner.run(ParentRunner.java:413) at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:316) at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:240) at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:214) at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:155) at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:385) at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:162) at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:507) at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:495) Caused by: java.lang.RuntimeException: Found incompatible ImageJ class at net.imagej.patcher.LegacyEnvironment.initialize(LegacyEnvironment.java:112) at net.imagej.patcher.LegacyEnvironment.applyPatches(LegacyEnvironment.java:494) at net.imagej.patcher.LegacyInjector.preinit(LegacyInjector.java:400) at net.imagej.patcher.LegacyInjector.preinit(LegacyInjector.java:379) at fiji.plugin.trackmate.TrackMatePluginTest.<clinit>(TrackMatePluginTest.java:40) ... 28 more Caused by: java.lang.RuntimeException: Cannot load class: ij.gui.ImageWindow (loader: sun.misc.Launcher$AppClassLoader@18b4aac2) It appears that this class was already defined in the class loader! Please make sure that you initialize the LegacyService before using any ImageJ 1.x class. You can do that by adding this static initializer: static { LegacyInjector.preinit(); } To debug this issue, start the JVM with the option: -javaagent:/Users/tinevez/.m2/repository/net/imagej/ij1-patcher/1.2.6/ij1-patcher-1.2.6.jar To enforce pre-initialization, start the JVM with the option: -javaagent:/Users/tinevez/.m2/repository/net/imagej/ij1-patcher/1.2.6/ij1-patcher-1.2.6.jar=init at net.imagej.patcher.CodeHacker.javaAgentHint(CodeHacker.java:826) at net.imagej.patcher.CodeHacker.loadClass(CodeHacker.java:805) at net.imagej.patcher.CodeHacker.loadClasses(CodeHacker.java:853) at net.imagej.patcher.LegacyInjector.injectHooks(LegacyInjector.java:114) at net.imagej.patcher.LegacyEnvironment.initialize(LegacyEnvironment.java:100) ... 32 more Caused by: java.lang.ClassFormatError: loader (instance of sun/misc/Launcher$AppClassLoader): attempted duplicate class definition for name: "ij/gui/ImageWindow" at javassist.util.proxy.DefineClassHelper$Java7.defineClass(DefineClassHelper.java:182) at javassist.util.proxy.DefineClassHelper.toClass(DefineClassHelper.java:260) at javassist.ClassPool.toClass(ClassPool.java:1240) at javassist.CtClass.toClass(CtClass.java:1392) at net.imagej.patcher.CodeHacker.loadClass(CodeHacker.java:799) ... 35 more
The re-importing of labels from Tabkit to TrackMate could fail for 2D images and labels with a large index. For instance, it failed consistently when trying to re-import labels with an index larger than 65643. This problem roots in the getSpots() method of LabkitImporter. It relies on a trick: We get the new label image, and create spots from this label image. But we want the new spots to keep track of the index in the label image they were generated from. For this, in 2D, we use the SpotRoiUtils.from2DLabelingWithRoi() method. These methods accept an image as last argument used to read a value in the label image within the spot, that is normally used for the quality value of the new spot. But the SpotRoiUtils.from2DLabelingWithRoi() method converted the extra image to ImagePlus (because I was lazy). So the label image was effectively cast on ushort for an IntegerType image, hence the problem with the max label being 65453. The solution is to rewrite the from2DLabelingWithRoi() so that it does not rely on converting to ImagePlus, but on good old iteration with imglib2.
Moving the plugin implementation out of the test class and removing the legacy injector make the test pass in maven.
Instead of the interval, so that this is consistent across TrackMate.
For the beta phase.
This works around a test failure in TrackMatePluginTest caused by the original ImageJ classes being loaded too soon. There are other ways of working around this problem, such as creating a SciJava context more eagerly, but it's a distraction from the business of testing TrackMate, and anyway we don't need imagej-legacy on the classpath. The only reason labkit-ui has imagej-legacy as a dependency is for one line of code, which can be refactored to avoid it, so hopefully the exclusion will be able to disappear later after labkit-ui is updated.
* Avoid SNAPSHOT versions. * Factor out version pins to properties. * Avoid jogamp *-main uber-JARs.
We want to retrieve spots as a map feom labels to corresponding spots.
When editing the whole movie, if the label of a new spot was using the label of an existing spot in another time-point, the existing one was removed. Because the new spot was identified as a modification of the existing one. The solution is to pass to the importer only the list of existing spots in the current time-frame.
Counterpart to the same one in SpotRoiUtils. Nota: the methods signature order should be harmonized between the two utility classes.
There is one discrepancy with the 2D part, linked to TrackMate: In 2D, one connected components will give one spot, even if several connected components belong to the same label. In 3D, it is possible to have one spot made of several disconnected components. Will have to document this.
Not implemented yet, but at least symmetric with the 2D case.
tinevez
changed the title
Draft PR that targets the work done towards TrackMate v9.
Draft PR that targets the work done towards TrackMate v9
Nov 7, 2024
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Reopened from #263
Support 3D segmentation by adding spots with triangular meshes.
A 3D viewer for TrackMate based on the BVV.
#280
A tool to configure a sub-selection of feature analyzers.
#261
There is now a new 'plugin' that launches a configuration panel for the TrackMate feature analyzers.
It can be launched with the menu item: Edit > Options > Configure TrackMate feature analyzers.... and show this dialog:
It allows selecting or deselecting feature analyzers.
Upon pressing the Save to user defaults button, a JSON file is created:
This selection will be used next time the user launches the TrackMate GUI.
This allows skipping the computation of analyzers that the users do not need. This will become useful in particular for 3D analysis with segmentation, where iterating through all the pixels of all meshes might be very long.
However it brings a risk: because TrackMate does not manage dependencies, the user might remove an analyzer that is needed by another one (example: spot SNR requires spot intensity). This risk is not mitigated yet.
Spot is now an interface, with 3 derived class.
Spot
-> the main interface, used by default in trackers. Define basic methods to get and store feature values.SpotBase
-> Plain spots, like for TrackMate v<7SpotRoi
-> spot has a polygon as a contour in 2DSpotMesh
-> spot has a 3D meshMore elegant and extensible to app consuming TrackMate trackers with special objects.
The detection preview is cancelable.
Of course it only actually cancels the preview if the detector that is used is itself cancelable.