Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • Jun 27 20:02

    ctrueden on roitree-to-mask-converters

    (compare)

  • Jun 27 20:02

    ctrueden on master

    First cut: ROITree to SuperElli… Fill out ROITree <-> single mas… Add RealMask support and 9 more (compare)

  • Jun 27 20:02
    ctrueden closed #101
  • Jun 27 20:01
    ctrueden commented #101
  • Jun 27 19:11
    gselzer commented #101
  • Jun 27 19:03
    ctrueden synchronize #101
  • Jun 27 19:03

    ctrueden on roitree-to-mask-converters

    First cut: ROITree to SuperElli… Fill out ROITree <-> single mas… Add RealMask support and 8 more (compare)

  • Jun 27 18:36
    gselzer commented #101
  • Jun 27 13:44
    imagesc-bot commented #26
  • Jun 26 20:40

    ctrueden on master

    POM: add main-class for quick t… (compare)

  • Jun 23 19:12
    hinerm commented #644
  • Jun 23 18:01
    gselzer commented #644
  • Jun 23 17:32
    gselzer commented #644
  • Jun 23 17:07
    hinerm commented #644
  • Jun 23 08:44

    tinevez on dev

    Add Vlado as a contributor Merge pull request #178 from xu… (compare)

  • Jun 23 08:44
    tinevez closed #178
  • Jun 22 22:26
    xulman opened #178
  • Jun 22 21:57
    ctrueden synchronize #644
  • Jun 22 21:57

    ctrueden on opSearchResult-improvements

    Use stream(), not parallelStrea… OpListingInfo: ensure OpService… OpList: improve equals implemen… (compare)

  • Jun 22 19:43
    ctrueden synchronize #644
Curtis Rueden
@ctrueden
As in: you want to bind a mask to an image and iterate the samples that are not masked out. Right? While knowing their positions?
Let's see...
Right now, you do:
Jan Eglinger
@imagejan
Actually, in my case, having the positions would be enough, no need to sample the values. So I'm fine with localizingCursor I guess.
Curtis Rueden
@ctrueden
RealMaskRealInterval myMask = ...;
RandomAccessible<T> myImage = ...;
IterableInterval<T> myMaskedImage = Regions.sample(myMask, myImage);
Cursor<T> c = myMaskedImage.localizingCursor();
long[] pos = new long[c.numDimensions()];
while (c.hasNext()) {
  T value = c.next();
  c.localize(pos);
  // and now we do something with the position and sample value
}
However, there are some limitations:
  1. myMask has to be a RealMaskRealInterval, not a RealMask. This is unfortunate. We could add a Regions.sample(RealMask, RandomAccessibleInterval) that creates a RealMaskRealInterval matching the bounds of the given RAI. I think?
  2. This myMaskedImage cannot be used with LoopBuilder because LoopBuilder only supports RAI images, not II images. So we have to use this clunkier cursor code, rather than a nice lambda. ¯\_(ツ)_/¯
Jan Eglinger
@imagejan
Thanks for the explanations!
Curtis Rueden
@ctrueden
It's partly explanations, and partly me figuring things out and thinking about to make it better.
Do you agree with (1) that we could have a better utility method here?
Because I think the most common thing is that you have a RealMask (not necessarily a RealMaskRealInterval) and a RAI and you want to combine them.
Jan Eglinger
@imagejan
Yes, agreed.
Curtis Rueden
@ctrueden
I feel dumb, but I'm not finding the mechanism to convert an unbounded mask (RealMask) into a bounded one (RealMaskRealInterval).
Jan Eglinger
@imagejan
Hm, so far I've only seen examples of this in discrete space, i.e. going via RandomAccessible and IntervalView, see imagej-roi-course
Curtis Rueden
@ctrueden
I wish someone besides me (looks at @maarzt in this case) would make more tutorial notebooks in imagej/tutorials. The imagej-roi-course belongs as a notebook there. And likely also a Maven project.
It makes sense as its own project during the learnathons... but then why not follow up by migrating shared useful materials out of learnathon space and into the official tutorials repo?
Kyle I S Harrington
@kephale
whoa, there is an imagej-roi course!
Curtis Rueden
@ctrueden
@kephale It was from the last Learnathon @ CSBD. Evolved over a couple of them, IIRC.
Unfortunately, they have been a hodge-podge of git repositories. Which ends up being fine during the event, and really tough afterward to see what's been presented.
Curtis Rueden
@ctrueden
@imagejan @kephale imglib/imglib2-roi#50
Jan Eglinger
@imagejan
:+1:
Christian Tischer
@tischi

@NicoKiaru I have the following workflow:

  1. I open a XML/H5 (that contains only a single Source) and view it in BDV.
  2. In BDV I change its AffineTransform using the manual transform UI of BDV
  3. Now I would like to save a new *.xml file that looks exactly as the original one that I opened, but I want a new <affine>...</affine> content, reflecting the additional transform that I manually added in BDV.

Do you know how to do this most efficiently? Do I have to construct a new SpimData object from the TransformedSource and then use XmlIoSpimData.save()? If so, would you have code already to construct SpimData from a single Source and the path to the corresponding .h5 file? Or are there other ways to save such an .xml file?

Nicolas Chiaruttini
@NicoKiaru
Hi Christian, you can use this spimData.getViewRegistrations().getViewRegistration(timePoint,iViewSetup).preconcatenateTransform(myAffineTransform); or spimData.getViewRegistrations().getViewRegistration(timePoint,iViewSetup).concatenateTransform(myAffineTransform);, with myAffineTransform being the transform retrieved from the TransformedSource. Then you can resave the dataset. FYI, I also found a trick to update the spimData when it's shown in the bdv (thanks to reflection to access a private method see https://github.com/BIOP/bigdataviewer_scijava/blob/master/src/main/java/ch/epfl/biop/bdv/scijava/command/spimdata/UpdateSpimDataDisplay.java)
Christian Tischer
@tischi
thanks!! ok, does that mean that spimData.getViewRegistrations().getViewRegistration(timePoint,iViewSetup).preconcatenateTransform(myAffineTransform); will not change the spimData displayed in Bdv?! (unless one does your trick)
Nicolas Chiaruttini
@NicoKiaru
For the moment yes, you're correct. If the loadTimepoint method in AbstractSpimSource was made public, then it would be a bit easier. (https://github.com/bigdataviewer/bigdataviewer-core/blob/5be52618026c6734911d9c150a9e2ba1140799e0/src/main/java/bdv/AbstractSpimSource.java#L187)
Stephan Preibisch
@StephanPreibisch
you have to call data.getViewRegistrations().getViewRegistration( 0, 0 ).updateModel();
to update the final model
@tischi
after concatenating or preconcatenating
it just adds it to the list of transformations
we do not automatically re-compute the final model every time you add
Christian Tischer
@tischi
thanks!
Christian Tischer
@tischi

@StephanPreibisch somehow I do not manage. It is not updating the image in BDV. Probably I am doing something wrong:

final Source< ? > source = bdv.getBdvHandle().getViewerPanel().getState().getSources().get( currentSource ).getSpimSource();
final SpimData spimData = sourceToSpimData.get( source );
spimData.getViewRegistrations().getViewRegistration( 0, 0 ).concatenateTransform( new ViewTransformAffine( "My transform", myTransfrom ) );
spimData.getViewRegistrations().getViewRegistration( 0, 0 ).updateModel();
bdv.getBdvHandle().getViewerPanel().requestRepaint();

sourceToSpimData is a Map that I generate while adding new SpimData to BDV in order to keep track of things.

Nicolas Chiaruttini
@NicoKiaru
@tischi I'm pretty sure you need to do the trick I showed you for the Bdv update when using BdvFunctions (at least for the versions I'm using in the POM file). I don't know how the update is done in BigStitcher. But that would be interesting to know! I guess calling the updateModelfunction is useful for updating properly the SpimData object before saving it, but I'm nor sure..
Stephan Preibisch
@StephanPreibisch
BDV caches the transforms additonally if I remember this correctly @tischi
if you would close and open BDV it should update
check this code out
Stephan Preibisch
@StephanPreibisch
here we update registrations interactively
Nicolas Chiaruttini
@NicoKiaru
Thanks @StephanPreibisch ! And you're also using reflection: you call the non public SpimSource.loadTimepoints method through reflection
Christian Tischer
@tischi

Thanks @NicoKiaru & @StephanPreibisch !
It looks like that both of your codes you are calling a method of the Source that is wrapped by the TransformedSource, which is the object BDV is using to display the source. What I did initially was simply:

final TransformedSource transformedSource = ( TransformedSource ) source;
transformedSource.setFixedTransform( myTransform );
bdv.getBdvHandle().getViewerPanel().requestRepaint();

This updates the display of the TransformedSource in the BDV and is much simpler code. I think the difference is that the TransformedSource is something that only exists in BDV and is not talking back to the SpimData object that was initially put into BDV for display. My feeling is that if one just wants to add additional transforms to Sources and display those in BDV, using the TransformedSource.setFixedTransform() approach might be cleaner?! In fact, the only reason I now also want to modify the SpimData object is because I want to save a new xml with myTransform appearing as additional <affine>...<\affine> tags. What do you think?

Christian Tischer
@tischi
...what I need for our users is a solution that works consistently for both adding a ManualTransformation (by pressing T in BDV) and/or adding any kind of other transformation, e.g. as obtained by a phase-correlation algorithm. And they should play well together. E.g. a user might do a rough manual pre-alignment (using T) and then press, e.g., P to compute a fine phase-correlation alignment on top of the manual pre-alignment. I am a bit worried right now that the current ManualTransformation in bdv-core relies on the TransformedSource, while our solutions seem to rather work through SpimData, and thus things might become messy, but I might be wrong as I am still not fully grasping everything...
Nicolas Chiaruttini
@NicoKiaru
That's also what I understood @tischi. If you want to resave, I think it's better to go for the SpimData option. Extra advantage of using SpimData is that the volatile view is taken care of also. It may not be the case fot the TransformedSource ? An alternative : every time you want to save the SpimData, check the transform of the TransformedSource: if it's not identity, then push it to SpimData.
But you may end up with a long chain of transform if the user is doing many attempts.
Christian Tischer
@tischi
image.png
Christian Tischer
@tischi
I am confused :-) I applied the ViewRegistration in the SpimData and also applied your reflection trick, in above example applying a simple translation along the x-axis. The result in BDV is that the yellow box is shifted along the x-axis relative to the grey square (see screenshot). However the coordinates of the upper left corner of the image are still at x=0 and y=0 if you hover there with the mouse. If I would change the transformation via the TransformedSource.setFixTransform() this would be different: the coordinates of the image would actually be shifted. Can someone explain me the meaning of the gray square and why the coordinates do not change using the SpimData approach? (...for me, I think the coordinates really would need to change because I need to move around the relative location of multiple Sources in a physical coordinate system).
Curtis Rueden
@ctrueden
Is there a one-liner in ImgLib2 for copying an image's contents into another image, without using a lambda? I know about imglib/imglib2/pull/237 but that isn't merged. I know about LoopBuilder but that requires a lambda. I want to do this from Python and I'm concerned that writing the lambda will not be elegant and/or performant. My current approach is to use Ops (ij.op().run("copy.rai", result, rai)) but @haesleinhuepf says in imagej/pyimagej#46 that it is too slow and must be fixed immediately.
Christian Tischer
@tischi
@NicoKiaru and @StephanPreibisch ...the solution is that I have to call the loadTimepoint method for both the Source< ? > and the Source< ? extends <Volatile< ? >>. An alternative to twice calling the private loadTimepoint() method via reflection seems to be to simply use transformedSource.setFixedTransform( transform ). This also properly updates the BDV. I don't understand yet what the pros and cons are...
Nicolas Chiaruttini
@NicoKiaru
Ah indeed @tischi! Sorry I forgot about it, and that gave me some headache as well. ... but yeah it was in the first link I sent you.