Correct 3D drift: erratic behaviour with two channel stacks



Hi there

@Larisa acquired these gorgeous multi-channel 3D time-series. We developed a pipeline to pre-process them before analysis.
Now recently (a couple of weeks ago) we noticed unusual and unexpected results after correcting the time-drift with the “Correct 3D drift” python script.
We usually use the options “Multi time scale computation…” and “Sub pixel drift correction …” and compute the drift on the channel 2.
After the computation the intensity values are changed proportionally, and the stack looks like there was a lot of bleed-through between the channels. In other words the signal from the two channels seems to get mixed up.

I checked the changes of the script, but they date as far back as March this year:

This is suggesting that it is not directly a bug in the script itself but rather on in one of its dependencies.

There are two cases where it still works more or less:

  1. the trivial one being to work only on a single channel stack. But then it’s cumbersome to transform the other channel separatly
  2. without the “Sub pixel drift correction …” the result resembles more the original stack (in terms of image intensities) but the correction does not correct much.

I put an example stack on my ftp-server:

Could one of the developers maybe try to reproduce the problem?



@Christian_Tischer can I pick your brain on this?


Hi Felix,
Indeed I did not change anything.
I will download your data and have a look!


Hi Felix,
In fact, for me it does not work at all anymore; I have to dig into it.
Meanwhile I attach an older version that uses different dependencies.
You have to go to [Fiji>Update>Manage Update Sites] and add ImageScience.
Then run attached script. (7.1 KB)
Does it work for you?
For me it works on your data using:

  • Channel 1 as reference
  • with Subpixel-drift enabled
  • with Multi-timescale enabled
  • with Edge-enhancement enabled



Hi Curtis,

Can you have a quick glance at below code and see why it would not work anymore?
It worked fine a few months ago.


    def translate_single_stack_using_imglib2(imp, dx, dy, dz):
      # wrap into a float imglib2 and translate
      #   conversion into float is necessary due to "overflow of n-linear interpolation due to accuracy limits of unsigned bytes"
      #   see:
      img = ImagePlusImgs.from(imp.duplicate())
      extended = Views.extendBorder(img)
      converted = Converters.convert(extended, RealFloatSamplerConverter())
      interpolant = Views.interpolate(converted, NLinearInterpolatorFactory())
      transformed = RealViews.affine(interpolant, Translation3D(dx, dy, dz))
      cropped = Views.interval(transformed, img)
      # wrap back into bit depth of input image and return
      bd = imp.getBitDepth()
      if bd==8:
      elif bd == 16:
      elif bd == 32:
        return None


Are you saying that the changes you made to use ImgLib2 instead of ImageScience worked fine a few months ago, when you tested it, but now they no longer work?

I have no more insight than you do regarding why this code might not work. It would take a debugging session to figure it out.


“the changes you made to use ImgLib2 instead of ImageScience worked fine a few months ago, when you tested it, but now they no longer work?”

Yes. Exactly.
I thought you might see it immediately.
I can also try to debug myself, but I am not very fluent in imglib2.


Yes, it does. Thanks a lot for taking the time to download and test with @Larisa’s data .


I found the reason why it is not working.
In fact, I am wondering now why it ever worked.

@FelixM: Are you sure you did the exact same thing some months ago, i.e. 2 channel z-stack time-lapse with sub-pixel drift correction? (without sub-pixel drift correction it should have worked anyway)
@ctrueden: Just by chance, do you know whether the default behavior of the conversion from stacks to hyperstacks changed recently? default currently is xyczt; parts of my code only worked for xyzct.

I will work on a corrected version and upload to Fiji github. For now, Felix, please use the code that I sent you.


Pretty sure, yes. We developed the pre-processing pipe-line at the beginning of April.


I do not completely understand what is going on but at least I found a fix :slight_smile:

Felix, could you maybe do me a favor and be a beta-tester of attached script?

Correct_3D_Drift_Plus– (6.8 KB)

It would be super cool if you could try it in as many scenarios as possible (2D, 3D, 1Ch, 2Ch, with and without sub-pixel drift correction). I tried already a bunch of things but you never know…

If everything works fine I will push it to the official Fiji.


Thank you very much for investigating and fixing this!


I did a couple of assays on channel 2:


Hi Christian, Hi Felix,
Thanks a lot for offering the solution for my data processing and for the time invested into this issue. It’s great to be part of a community like this.



@ctrueden, I would like to contribute the updated script.
This time I would like to do it as properly as possible, as described here:
However, I could not find Correct_3D_drift as a stand-alone repo on Does that mean I should fork the fiji repo ( and add it there? Or would it maybe be cleaner if there was a Correct_3D_Drift repo?


Hi Christian,

Have you already put the updated on Fiji site? I found the Correct_3D_Drift plugin on Fiji is not the one you mentioned (Correct_3D_Drift_ Plus– ) on this topic.

Btw, this plugin seems not to be able to correct z drift on an xyz-stack. I mean the 3D stack is an xyz but neither an xyt nor xyzt stack. Should the time-lapse factor(t) be essential to this plugin? There is a stack(xyz) for testing if you are interested.




Nope, I have not updated yet; I was waiting for @ctrueden for instructions on how to do this best, because last time I created a bit of a mess :slight_smile:

This script should work:
Correct_3D_Drift_Plus– (7.5 KB)
Drag&Drop onto Fiji and Click [Run].

And yes, it only corrects over time, also 2D data. That means xyt should work. If not, please send me your data and I will see what is going on.


Hi Christian,

Thank you for your script. It can do the drift correction both on xyt and xyzt stacks.

As for those xyz stacks, I can use other registration plugins in Fiji.



For anyone else who stumbles across this old topic, and wonders what happened: the script became its own dedicated repository on GitHub:


@ctrueden: Thanks again a lot for setting it up like this! This makes it so much easier to commit changes!