Skip to content

Instantly share code, notes, and snippets.

@schiklen
Forked from miura/TurboRegMacro.ijm
Created September 17, 2012 09:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save schiklen/3736509 to your computer and use it in GitHub Desktop.
Save schiklen/3736509 to your computer and use it in GitHub Desktop.
Using TurboReg from ImageJ macro, to output shifts.
/*
* A 2D drift correction macro for multichannel multislide stacks
* by Kota Miura
* and Christoph Schikenk, schiklen@embl.de
*
* still missing: write calculations to metadata and retrieve it,
* or import results automatically when opening.
*
*/
var npos = 0; // number of imaged positions for batch-mode
var directapply = 0;// "boolean" user input direct application of driftcorrect
var crop = 0; // "boolean" user input crop to ROI after drift correction
var splitch = 0; // "boolean" user input splitting of channels after drift correction
var targetstack = 1;// ImageID of the stack that is to be processed
var dir; // Directory of open image
var cropxmax = 0;
var cropymax = 0;
var maxout = 0;
var startout = 0;
macro "Driftcorrect_" {
ipos = 0; // imaged position currently processed
ch = 0;
frame = 0;
slice = 0;
// -------------- Start of actual code ----------------
setBatchMode(true);
dropdown = newArray(nImages()+2); // creating dropdown array for startup dialog
for (i = 0; i < nImages; i++)
{
selectImage(i+1);
dropdown[i] = getTitle();
}
dropdown[dropdown.length-2] = "Open single stack";
dropdown[dropdown.length-1] = "Batch-process folder";
setBatchMode(false);
Dialog.create("Driftcorrect"); // creating startup dialog
Dialog.addChoice("Driftcorrect", dropdown);
Dialog.addCheckbox("Show corrected stack(s)", true);
Dialog.addCheckbox("Crop to covered region", true);
Dialog.addCheckbox("Split channels after correction", false);
Dialog.show();
dropdownselect = Dialog.getChoice();
directapply = Dialog.getCheckbox();
crop = Dialog.getCheckbox();
splitch = Dialog.getCheckbox();
// maybe add here: select, which channel should be used as reference.
//---- single mode -----
if (dropdownselect == "Open single stack")
{
npos = 0;
ipos = 0;
dir = File.openDialog("Please select the stack");
print(dropdownselect + ": " + dir);
run("Bio-Formats Importer",
"open=[" + dir +"]"
+ " autoscale"
+ " color_mode=Grayscale"
+ " view=Hyperstack"
+ " stack_order=XYCZT"
);
openimage = getImageID();
measure_driftcorrect(openimage, false);
if (directapply == true)
{
selectImage(openimage);
apply_driftcorrect(openimage, crop);
}
Stack.getDimensions(w, h, chn, sln, frn);
if (splitch == true && chn > 1)
{
selectImage(openimage);
run("Split Channels");
}
} // end of if: Open single stack mode
//------- batch-process mode -------
else
{
if (dropdownselect == "Batch-process folder")
{
print("Batch/Folder mode");
setBatchMode(true);
dir = getDirectory("Please select a folder containing stacks");
list = getFileList(dir); // .dv file counter and list maker
dv_list = newArray(list.length);
for (i = 0; i < list.length; i++)
{
if (endsWith(list[i], ".dv") == true)
{
dv_list[npos] = list[i];
npos++;
}
}
dv_list = Array.trim(dv_list, npos);
if (npos <= 0)
exit("No *.dv files in chosen directory.");
else
{
write(npos + " *.dv files found in chosen directory: ");
Array.print(dv_list);
} // End of .dv file counter and list maker
for (ipos = 0 ; ipos < npos; ipos++) //Image importer loop.
{
run("Bio-Formats Importer",
"open=[" + dir + dv_list[ipos] + "]"
+ " autoscale"
+ " color_mode=Grayscale"
+ " view=Hyperstack"
+ " stack_order=XYCZT"
+ " use_virtual_stack");
openimage = getImageID();
measure_driftcorrect(openimage, true); // true is for driftcorrect's batchmode=true
}
setBatchMode(false);
}
//----------- already opened image mode ------------
else
{
print("Opened image mode - " + dropdownselect);
selectWindow(dropdownselect);
dir = getInfo("image.filename"); // getting path of open image. Problem: what if not saved??
openimage = getImageID();
measure_driftcorrect(openimage, false); // false is for folder-mode = false
if (directapply == true)
{
selectImage(openimage);
apply_driftcorrect(openimage, crop);
}
Stack.getDimensions(w, h, chn, sln, frn);
if (splitch == true && chn > 1)
{
selectImage(openimage);
run("Split Channels");
}
}
}
print("I'm done.");
} // end Macro
// ------ function definitions -------
function measure_driftcorrect(dcstack, foldermode) // add arg. refchannel
{
setBatchMode(true);
if (isOpen(dcstack) != true) //check that target-window open
exit("The stack you want to correct for drift is not open!");
else
{
selectImage(dcstack);
Stack.getDimensions(w, h, chn, sln, frn);
filename = getInfo("image.filename");
dcresultsx = newArray(frn+1);
dcresultsy = newArray(frn+1);
// SET CHANNEL HERE.?? function machen?
if (chn > 1)
{
Stack.setChannel(refchannel);
}
// print("Using channel" + + "as basis.");
if (sln > 1)
{
cenSl = sln/2; // go to central Z-postition. dirty here! needs to be rounded up! cenSl: central slice
write("Moving to slice " + cenSl + " of " + sln);
Stack.setSlice(cenSl); // better: z-projection (but which mode? avg/max/min/stdev). make selectable in dialog.
run("Reduce Dimensionality...", " frames keep");
dcstack = getImageID(); //
selectImage(dcstack); // select new window with the reduced timepoint
Stack.setFrame(0); // set to first time frame - for StackReg as reference
write("Starting driftcorrect calculation on position " + ipos + ", slide " + cenSl);
}
for (frame = 0; frame <= frn; frame++)
{
selectImage(dcstack);
Stack.setFrame(frame);
run("Duplicate...", "title=sourceimage");
frame1 = "sourceimage"; // a frame in a sequence
selectImage(dcstack);
Stack.setFrame(frame + 1); // select next frame.
run("Duplicate...", "title=targetimage");
frame2 = "targetimage"; // next frame in the sequence
selectWindow(frame1);
width = getWidth();
height = getWidth();
run("TurboReg ",
"-align "
+ "-window " + frame1 + " "// Source (window reference).
+ " 0 0 " + (width - 1) + " " + (height - 1)
+ " -window " + frame2 + " "// Target (window reference).
+ " 0 0 " + (width - 1) + " " + (height - 1)
+ " -translation"
+ " " + (width / 2) + " " + (height / 2)
+ " " + (width / 2) + " " + (height / 2)
+ " -hideOutput"
);
sourceX0 = getResult("sourceX", 0); // First line of the table.
sourceY0 = getResult("sourceY", 0);
targetX0 = getResult("targetX", 0);
targetY0 = getResult("targetY", 0);
xoffset = sourceX0 - targetX0; // calculate offsets in respect to previous image.
yoffset = sourceY0 - targetY0;
xoffsetsum = xoffsetsum + xoffset; // x and yoffsetsums: value each frame has to be aligned in respect to first frame.
yoffsetsum = yoffsetsum + yoffset;
dcresultsx[frame] = xoffsetsum; // saving results for each frame in arrays
dcresultsy[frame] = yoffsetsum;
print("Frame " + frame + " - x: " + xoffsetsum + " y: " + yoffsetsum);
selectWindow(frame1);
close();
selectWindow(frame2);
close();
} // closes for (frame = 0; frame <= driftcorfrn; frame++);
} //closes else
if (sln > 1)
{
selectImage(dcstack);
close();
}
print("Done calculating drift in position " + ipos+1);
run("Clear Results"); // transferring results to results-table
for (i = 0; i < dcresultsx.length; i++)
{
setResult("Frame", i, i);
setResult("X-offsetsum", i, dcresultsx[i]);
setResult("Y-offsetsum", i, dcresultsy[i]);
}
absolute_max(dcresultsx); // absolute maxfunction
setResult("X-max", 0, maxout);
setResult("X-start", 0, startout);
absolute_max(dcresultsy);
setResult("Y-max", 0, maxout);
setResult("Y-start", 0, startout);
updateResults();
selectWindow("Results");
filename1 = split(filename, ".");
print("Saving results as " + filename1[0] + "driftcor.xls");
saveAs("Results", filename1[0] + "driftcor.xls"); // saves resultstable as a file.
if (foldermode == true)
{
selectImage(dcstack);
close();
}
setBatchMode(false);
} // end of function
function apply_driftcorrect(targetstack, croparg) // targetstack is ImageID
{
selectImage(targetstack);
Stack.getDimensions(w, h, chn, sln, frn);
for (frame = 0; frame <= frn; frame++) // frame <= frn!!
{
corx = getResult("X-offsetsum", frame); // load corrected x-position from results-table
cory = getResult("Y-offsetsum", frame); // load corrected y-position
for (slice = 1; slice <= sln; slice++) // shift all z-slices of one frame
{
for (channel = 1; channel <= chn; channel++)
{
selectImage(targetstack);
Stack.setPosition(channel, slice, frame);
run("Translate...", "x=" + corx + " y=" + cory + " interpolation=None slice");
}
}
}
if (croparg == true)
{
makeRectangle(getResult("X-start", 0), getResult("Y-start", 0), w-abs(getResult("X-max", 0)), h-abs(getResult("Y-max",0)));
run("Crop");
}
} // end of function
function absolute_max(array)
{
Array.getStatistics(array, min, max, mean, stdDev);
startout = max;
if (abs(min) <= abs(max))
{
maxout = max;
}
if (abs(min) > abs(max))
{
maxout = min;
}
} // end of function
// End of code
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment