//These macros were written by Steve Rothery
//FILM - Facility for Imaging in Light Microscopy, Imperial College London
//http://www3.imperial.ac.uk/imagingfacility/


//////////////////////////////////////////////////////////////1

macro "Tilted Roataion Movie Action Tool - Cg00 O428f L8288 L82d2 Ceee F226b C00g O06f8 L2466 L763b"
{

//initialise
fn=getTitle();
getDimensions(ImageWidth, ImageHeight, ImageChannels, ImageSlices, ImageFrames);
comb="final open ";

//dialog
Dialog.create("Options");
Dialog.addMessage("Important! - Make sure all other images are closed");
Dialog.addChoice("Projection Method", newArray("Brightest Point","Mean Value"));
Dialog.addMessage("Tilt Options");
Dialog.addNumber("Final Angle of Tilt (degrees)", 60);
Dialog.addNumber("Step Size Angle of Tilt (degrees)", 2);
Dialog.addMessage("Rotation Options");
Dialog.addNumber("Angle of Rotation Step Size (degrees)", 5);
Dialog.show();

//responses
method=Dialog.getChoice();
Tilt_Angle=Dialog.getNumber();
Tilt_step_size=Dialog.getNumber();
Rotation_Step=Dialog.getNumber();
rotation_number=360/Rotation_Step;

//start pre tilt process
setBatchMode("hide");
run("3D Project...", "projection=["+method+"] axis=X-Axis initial=0 total="+Tilt_Angle+" rotation="+Tilt_step_size+" interpolate");
run("Canvas Size...", "width="+ImageWidth*1.5+" height="+ImageHeight*1.5+" position=Center zero");
rename("pre-tilt");


//start rotation process
for (rotation=1;rotation<rotation_number;rotation++){
selectWindow(fn);
run("Duplicate...", "title="+rotation+" duplicate");
run("Rotate... ", "angle="+Rotation_Step*rotation+" grid=1 interpolation=Bilinear enlarge stack");
run("3D Project...", "projection=["+method+"] axis=X-Axis initial="+Tilt_Angle+" total=0 rotation=0 interpolate");

run("Canvas Size...", "width="+ImageWidth*1.5+" height="+ImageHeight*1.5+" position=Center zero");
rename("Rotation"+rotation);
selectWindow(rotation);
close();
comb=comb+"image"+rotation+"=[Rotation"+rotation+"] ";
showProgress(rotation, rotation_number);
print("Rotation "+rotation+" done");
}

//print(comb);
//join images
run("Concatenate...", comb);
rename("Rotate_Series");
run("Concatenate...", "open image1=[pre-tilt] image2=[Rotate_Series] image3=[-- None --]");
rename("Rotation Series");
setBatchMode("exit and display");

}

//////////////////////////////////////////////////////2

macro "3D Tilt Movie Action Tool - C000 T37103 T9710D  T3g08t T7g08i Tag08l Teg08t"
{


//initialise
fn=getTitle();
getDimensions(ImageWidth, ImageHeight, ImageChannels, ImageSlices, ImageFrames);
comb="final open ";

//dialog
Dialog.create("Options");
Dialog.addMessage("Important! - Make sure all other images are closed");
Dialog.addChoice("Projection Method", newArray("Brightest Point","Mean Value"));
Dialog.addNumber("Step Size Angle of Tilt (degrees)", 30);
Dialog.addNumber("Wobble Step Size (degrees)", 15);
Dialog.show();


//responses
method=Dialog.getChoice();
Tilt_Angle=Dialog.getNumber();
Rotation_Step=Dialog.getNumber();
rotation_number=360/Rotation_Step;

//start process
setBatchMode("hide");
for (rotation=1;rotation<rotation_number;rotation++){
selectWindow(fn);
run("Duplicate...", "title="+rotation+" duplicate");
run("Rotate... ", "angle="+Rotation_Step*rotation+" grid=1 interpolation=Bilinear enlarge stack");
run("3D Project...", "projection=["+method+"] axis=X-Axis initial="+Tilt_Angle+" total=0 rotation=0 interpolate");
run("Rotate... ", "angle="+Rotation_Step*-rotation+" grid=1 interpolation=Bilinear enlarge stack");
run("Canvas Size...", "width="+ImageWidth*1.5+" height="+ImageHeight*1.5+" position=Center zero");
rename("Rotation"+rotation);
selectWindow(rotation);
close();
comb=comb+"image"+rotation+"=[Rotation"+rotation+"] ";
showProgress(rotation, rotation_number);
print("Rotation "+rotation+" done");
}

//print(comb);
//join images
run("Concatenate...", comb);
rename("Tilt Series");
setBatchMode("exit and display");


}


//////////////////////////////////////////////////////3
macro "Multi 3D Rotations Action Tool - Cg00 O06f8 Cg00 L6a9e L6h9e Ceee Dae Dbe Dbd C000 T35103 Ta510D"
{

fn=getTitle();
getDimensions(ImageWidth, ImageHeight, ImageChannels, ImageSlices, ImageFrames);
getVoxelSize(px, py, pz, unit);

n=getNumber("Get number of rotational series", 3);


st=newArray(0,30,-30,0,30,-30,0,0,0,0);
an=newArray(30,60,30,30,60,30,0,0,0,0);
stp=newArray(5,-5,5,5,-5,5,0,0,0,0);


type=newArray(n);
axis=newArray(n);
start=newArray(n);
range=newArray(n);
step=newArray(n);


Dialog.create("Projection options");
TypeOptions=newArray("Nearest Point","Brightest Point","Mean Value");
AxisOptions=newArray("X","Y","Z");
AxisOptions=newArray("X","Y","Z");

for (op=0;op<n;op++){
Dialog.addMessage("Rotation:"+op+1);
Dialog.addChoice("Projection Method:", TypeOptions, TypeOptions[1]);
Dialog.addChoice("Axis of Rotation:", AxisOptions, AxisOptions[1]);
Dialog.addNumber("Start Angle (-360 to +360): ", st[op]);
Dialog.addNumber("Total Angle Change (0 to 360): ", an[op]);
Dialog.addNumber("Angle Step Size ( (+/-) for direction): ", stp[op]);
}
Dialog.show(); 
 
for (op=0;op<n;op++){
type[op]=Dialog.getChoice();
axis[op]=Dialog.getChoice();
start[op]=Dialog.getNumber();
if (start[op]<0){
	start[op]= start[op]+360;
}
range[op]=Dialog.getNumber();
step[op]=Dialog.getNumber();

selectWindow(fn);
run("3D Project...", "projection=["+type[op]+"] axis="+axis[op]+"-Axis slice="+pz+" initial="+start[op]+" total="+range[op]+" rotation="+step[op]+" lower=1 upper=255 opacity=0 surface=100 interior=50 interpolate");
rename("Projection"+op);
}


for (op=1;op<n;op++){
run("Concatenate...", "  title=temp image1=[Projection0] image2=[Projection"+op+"] image3=[-- None --]");
rename("Projection0");
}
rename("Final 3D Projection of "+fn);

}



///////////////////////////////////////////////////////4

macro "Coloured Coded Z stack and projection Action Tool - C00g F00hh C0g0 V2279 V44aa V9376 V2cb4 Cgg0 V4436 V8865 Va443 V4c53 Cg00 V9922 V5523 Cggg F0a77 C000 T1h07Z" 
{

//initialise
fn=getTitle();
getDimensions(OrigWidth, OrigHeight, OrigChannels, OrigSlices, OrigFrames);
getVoxelSize(px, py, pz, unit);
setBackgroundColor(255,255,255);

//error check
if (OrigSlices==1 && OrigFrames==1){
	exit("This macro requires a Z or T series");
}
if (OrigSlices==1 && OrigFrames>1){
	ans=getBoolean("This is a time series, convert to Z series?", "Convert", "Exit");
if (ans==true){
	Stack.setDimensions(OrigChannels, OrigFrames, OrigSlices);
	getDimensions(OrigWidth, OrigHeight, OrigChannels, OrigSlices, OrigFrames);
	}else{exit();}
	}

//get constants
tp=(round(OrigSlices*pz*100))/100;
md=(round(tp/2*100))/100;
LutList=newArray("BCGYRM Spectrum","Fire","Heat map","Ice","royal","16 colors","Cyan Hot","cool","Spectrum","gem","Green Fire Blue","thal");
proc=newArray(OrigChannels);


//dialog
Dialog.create("Options");
for (ch=0;ch<OrigChannels;ch++){
	Dialog.addCheckbox("Process channel "+ch+1, true);
}
Dialog.addChoice("Look-up table", LutList);
Dialog.addCheckbox("Create maximum Intensity Projection", true);
Dialog.addCheckbox("Add Calibration Scale", true);
Dialog.show();

//responses
for (ch=0;ch<OrigChannels;ch++){
	proc[ch]=Dialog.getCheckbox();
}
SelLut=Dialog.getChoice();
proj=Dialog.getCheckbox();
calbar=Dialog.getCheckbox();

//create and join channels
ChanNum=1;
for (ch=0;ch<OrigChannels;ch++){
if	(proc[ch]==true){
	selectWindow(fn);
    run("Duplicate...", "title="+ChanNum+" duplicate channels="+ch+1);
    if (calbar==true){
    run("Canvas Size...", "width="+OrigWidth+3+" height="+OrigHeight+" position=Center-Left");
    }
    ChanNum=ChanNum+1;
}
}
for (join=1;join<ChanNum-1;join++){
run("Combine...", "stack1="+join+" stack2="+join+1);
run("Stack to Hyperstack...", "order=xyzct channels=1 slices="+OrigSlices+" frames="+OrigFrames+" display=Color");
selectWindow("Combined Stacks");
rename(join+1);
}
rename("Colour Stack");
getDimensions(ImageWidth, ImageHeight, ImageChannels, ImageSlices, ImageFrames);


//create LUT range
newImage("range", "8-bit black", ImageSlices+1, 30, 1);
for (ln=0;ln<=ImageSlices;ln++){
makeRectangle(ln, 0, 1, 30);
run("Set...", "value="+ln*(255/(ImageSlices)));
}
run(SelLut);
run("RGB Color");

//change slices to channels
selectWindow("Colour Stack");
run("Stack to Hyperstack...", "order=xyczt(default) channels="+ImageSlices+" slices=1 frames=1 display=Color");

//add LUT's
for (ln=1;ln<=ImageSlices;ln++){
selectWindow("range");
makePoint(ln, 1);
getSelectionCoordinates(x, y);
	pxValue=getPixel(x[0],y[0]);
       redmax=(pxValue>>16)&0xff;  // extract red byte (bits 23-17)
       greenmax=(pxValue>>8)&0xff; // extract green byte (bits 15-8)
       bluemax=pxValue&0xff;       // extract blue byte (bits 7-0)

red=newArray(256);
green=newArray(256);
blue=newArray(256);
for (i=0;i<256;i++){
	red[i]=floor(i*(redmax+1)/256);
	green[i]=floor(i*(greenmax+1)/256);
	blue[i]=floor(i*(bluemax+1)/256);
}
selectWindow("Colour Stack");
Stack.setChannel(ln);
setLut(red, green, blue);		
}

//convert to RGB - converts to z stack
selectWindow("Colour Stack");
run("RGB Color");
rename(fn+" Colour Stack");
selectWindow("Colour Stack");
close();

//end of main process


//calibration bar
if (calbar==true){
setBackgroundColor(0, 0, 0);
run("Canvas Size...", "width="+ImageWidth+113+" height="+ImageHeight+" position=Center-Left");
selectWindow("range");
run("Select None");
run("Size...", "width=256 height=32 depth=1 average interpolation=Bilinear");
run("Canvas Size...", "width=300 height=100 position=Top-Center zero");
makeRectangle(0, 32, 300, 68);
setBackgroundColor(0, 0, 0);
run("Clear", "slice");
drawString("Height ("+unit+")", 100, 95);
run("Rotate 90 Degrees Left");
drawString(tp, 40, 30);
drawString(md, 40, 158);
drawString("0", 40, 285);

//resisze if necessary
if (ImageHeight<300){
selectWindow("range");
run("Size...", "width=85 height=256 constrain average interpolation=Bilinear");
}
getDimensions(smallwidth, smallheight, smallchannels, smallslices, smallframes);


selectWindow("range");
run("Copy");
selectWindow(fn+" Colour Stack");
for (ch=1;ch<=ImageSlices;ch++){
	Stack.setSlice(ch);
	makeRectangle(ImageWidth+10,(ImageHeight-smallheight)/2, smallwidth, smallheight);
	run("Paste");
}
}
run("Select None");


//Z project
if (proj==true){
selectWindow(fn+" Colour Stack");
run("Z Project...", "projection=[Max Intensity]");
rename(fn+" Max Projection");
}

//finish Up
selectWindow("range");
close();

}


//////////////////////////////////////////////////////5

macro "Coloured Coded Height Projection Action Tool - C00g F00hh C0g0 V2279 V44aa V9376 V2cb4 Cgg0 V4436 V8865 Va443 V4c53 Cg00 V9922 V5523 Cggg F0a77 C000 T1h07P" 
{

//initialise
fn=getTitle();
getDimensions(OrigWidth, OrigHeight, OrigChannels, OrigSlices, OrigFrames);
getVoxelSize(px, py, pz, unit);
setBackgroundColor(255,255,255);

Sc_factor=(OrigHeight/300)*0.75;
BarWidth=round(Sc_factor*120);

//error check
if (OrigSlices==1){
	exit("This macro requires a Z stack");
}

//get constants
tp=(round(OrigSlices*pz*100))/100;
md=(round(tp/2*100))/100;
LutList=newArray("BCGYRM Spectrum","Fire","Heat map","Ice","royal","16 colors","Cyan Hot","cool","Spectrum","gem","Green Fire Blue","thal");
proc=newArray(OrigChannels);


//dialog
Dialog.create("Options");
for (ch=0;ch<OrigChannels;ch++){
	Dialog.addCheckbox("Process channel "+ch+1, true);
}
Dialog.addChoice("Look-up table", LutList);
Dialog.show();

//responses
for (ch=0;ch<OrigChannels;ch++){
	proc[ch]=Dialog.getCheckbox();
}
SelLut=Dialog.getChoice();



//create channels
ChanNum=1;
for (ch=0;ch<OrigChannels;ch++){
if	(proc[ch]==true){
	selectWindow(fn);
    run("Duplicate...", "title="+ChanNum+" duplicate channels="+ch+1);
    run("Canvas Size...", "width="+OrigWidth+3+" height="+OrigHeight+" position=Center-Left");
    ChanNum=ChanNum+1;
}
}

for (join=1;join<ChanNum-1;join++){
run("Combine...", "stack1="+join+" stack2="+join+1);
run("Stack to Hyperstack...", "order=xyzct channels=1 slices="+OrigSlices+" frames="+OrigFrames+" display=Color");
selectWindow("Combined Stacks");
rename(join+1);
}
rename("dup");
getDimensions(ImageWidth, ImageHeight, ImageChannels, ImageSlices, ImageFrames);




//multiframe
if (ImageFrames>1){	
//initial duplicate
selectWindow("dup");
run("Duplicate...", "title=dup1 duplicate frames=1");
run("Temporal-Color Code", "lut=["+SelLut+"] start=1 end="+ImageSlices+" create");
selectWindow("dup1");
close();
selectWindow("MAX_colored");
rename("sequence");
for (im= 2; im<=ImageFrames; im++) {
	selectWindow("dup");
	run("Duplicate...", "title=dup1 duplicate frames="+im);
run("Temporal-Color Code", "lut=Fire start=1 end="+ImageSlices);
run("Concatenate...", "  image1=sequence image2=MAX_colored image3=[-- None --]");
rename("sequence");

selectWindow("dup1");
close();
}
rename("MAX_colored");

selectWindow("dup");
close();
//single frame
}else{
run("Temporal-Color Code", "lut=["+SelLut+"] start=1 end="+ImageSlices+" create");
selectWindow("dup");
close();
}


//calibrate and resize max image
selectWindow("MAX_colored");
setVoxelSize(px, py, pz, unit);
run("Canvas Size...", "width="+ImageWidth+BarWidth+" height="+ImageHeight+" position=Center-Left zero");

if (ImageFrames>1){
run("Stack to Hyperstack...", "order=xyctz channels=1 slices=1 frames="+ImageFrames+" display=Color");
}

//calibration bar
selectWindow("color time scale");
run("Canvas Size...", "width=300 height=100 position=Top-Center zero");
makeRectangle(0, 32, 300, 68);
setBackgroundColor(0, 0, 0);
run("Clear", "slice");
drawString("Height ("+unit+")", 100, 95);
run("Rotate 90 Degrees Left");
drawString(tp, 40, 30);
drawString(md, 40, 158);
drawString("0", 40, 285);




//resisze scale
selectWindow("color time scale");
run("Scale...", "x="+Sc_factor+" y="+Sc_factor+" interpolation=Bilinear average create");
rename("CTS");
run("Unsharp Mask...", "radius=1 mask=0.60");
getDimensions(smallwidth, smallheight, smallchannels, smallslices, smallframes);
selectWindow("color time scale");
close();

//paste in calibration bar
selectWindow("CTS");
run("Copy");
selectWindow("MAX_colored");
for (Fr=1;Fr<=ImageFrames;Fr++){
	if (ImageFrames>1){
	Stack.setFrame(Fr);
	}
	makeRectangle(ImageWidth+10,(ImageHeight-smallheight)/2, smallwidth, smallheight);
	run("Paste");
}


//finish up
run("Select None");
rename(fn+" height map");
selectWindow("CTS");
close();
selectWindow("Log");
run("Close");

}

//////////////////////////////////////////////////////6

macro "Height Map using Intensity Threshold Action Tool - C00g F00hh C0g0 V2279 V44aa V9376 V2cb4 Cgg0 V4436 V8865 Va443 V4c53 Cg00 V9922 V5523 Cggg F0a77 C000 T1h07H" 
{

fn=getTitle();
getDimensions(ImageWidth, ImageHeight, ImageChannels, ImageSlices, ImageFrames);
if (ImageChannels>1 || ImageFrames>1){
	exit("This macro does not work on a Time series or Multichannel image");
}


Dialog.create("Get options");
	Dialog.addCheckbox("Pre-scale Image", false);
	Dialog.addNumber("Scale in X & Y", 2);
	Dialog.addNumber("Scale in Z ", 2);
	Dialog.addCheckbox("Add Calibration Bar", false);
Dialog.show(); 

//get response
PreScale=Dialog.getCheckbox();
ScaleXY=Dialog.getNumber();
ScaleZ=Dialog.getNumber();
CalBar=Dialog.getCheckbox();



if (PreScale==true){
	getDimensions(PreWidth, PreHeight, PreChannels, PreSlices, PreFrames);
	wd=PreWidth*ScaleXY;
	ht=PreHeight*ScaleXY;
	Z=PreSlices*ScaleZ;
	run("Scale...", "x="+ScaleXY+" y="+ScaleXY+" z="+ScaleZ+" width="+wd+" height="+ht+" depth="+Z+" interpolation=Bilinear average process create");
	rename("map");
}
else {
run("Duplicate...", "title=map duplicate");
}


getDimensions(ImageWidth, ImageHeight, ImageChannels, ImageSlices, ImageFrames);
getVoxelSize(px, py, pz, unit);
calzoom=floor(ImageHeight/1000)+1;

if (ImageSlices==1){
	exit("This Image is not a Z stack");
}



	Stack.setSlice(ImageSlices/2);
setAutoThreshold("Default dark");
run("Threshold...");
waitForUser("Threshold", "Set threshold " );

setOption("BlackBackground", false);
run("Convert to Mask", "method=Default background=Dark");
run("Fill Holes", "stack");

run("Subtract...", "value=254 stack");
run("32-bit");

for (sl=1;sl<=ImageSlices;sl++){
	Stack.setSlice(sl);
	run("Multiply...", "value="+(sl*pz)+" slice");
}


run("Z Project...", "projection=[Max Intensity]");
rename(fn+" Height Map");


run("royal");
resetMinAndMax();


if (CalBar==true){
UnitLen=lengthOf(unit);	
factor=floor(ImageWidth/1000)+1;
run("Calibration Bar...", "location=[Upper Right] fill=White label=Black number=5 decimal=0 font=12 zoom=calzoom overlay");
setFont("Arial", 12*factor, "bold antialiased");
Overlay.drawString(unit, ImageWidth-(factor*50)- (factor*UnitLen), factor*12);
Overlay.show();
run("Flatten");
}


selectWindow("map");
close();
}




//////////////////////////////////////////////////////7

macro "Thickness Map using Intensity Threshold Action Tool - C00g F00hh C0g0 V2279 V44aa V9376 V2cb4 Cgg0 V4436 V8865 Va443 V4c53 Cg00 V9922 V5523 Cggg F0a77 C000 T1h07T" 
{

fn=getTitle();
getDimensions(ImageWidth, ImageHeight, ImageChannels, ImageSlices, ImageFrames);
if (ImageChannels>1 || ImageFrames>1){
	exit("This macro does not work on a Time series or Multichannel image");
}

Dialog.create("Get options");
	Dialog.addCheckbox("Pre-scale Image", false);
	Dialog.addNumber("Scale in X & Y", 2);
	Dialog.addNumber("Scale in Z ", 2);
	Dialog.addCheckbox("Add Calibration Bar", false);
Dialog.show(); 

//get response
PreScale=Dialog.getCheckbox();
ScaleXY=Dialog.getNumber();
ScaleZ=Dialog.getNumber();
CalBar=Dialog.getCheckbox();



if (PreScale==true){
	getDimensions(PreWidth, PreHeight, PreChannels, PreSlices, PreFrames);
	wd=PreWidth*ScaleXY;
	ht=PreHeight*ScaleXY;
	Z=PreSlices*ScaleZ;
	run("Scale...", "x="+ScaleXY+" y="+ScaleXY+" z="+ScaleZ+" width="+wd+" height="+ht+" depth="+Z+" interpolation=Bilinear average process create");
	rename("map");
}
else {
run("Duplicate...", "title=map duplicate");
}


getDimensions(ImageWidth, ImageHeight, ImageChannels, ImageSlices, ImageFrames);
getVoxelSize(px, py, pz, unit);
calzoom=floor(ImageHeight/1000)+1;

if (ImageSlices==1){
	exit("This Image is not a Z stack");
}



	Stack.setSlice(ImageSlices/2);
setAutoThreshold("Default dark");
run("Threshold...");
waitForUser("Threshold", "Set threshold " );

setOption("BlackBackground", false);
run("Convert to Mask", "method=Default background=Dark");
run("Fill Holes", "stack");

run("Subtract...", "value=254 stack");
run("Z Project...", "projection=[Sum Slices]");
rename(fn+" Thickness Map");

run("Multiply...", "value="+pz);
run("royal");
resetMinAndMax();


if (CalBar==true){
UnitLen=lengthOf(unit);	
factor=floor(ImageWidth/1000)+1;
run("Calibration Bar...", "location=[Upper Right] fill=White label=Black number=5 decimal=0 font=12 zoom=calzoom overlay");
setFont("Arial", 12*factor, "bold antialiased");
Overlay.drawString(unit, ImageWidth-(factor*50)- (factor*UnitLen), factor*12);
Overlay.show();
run("Flatten");
}


selectWindow("map");
close();
}




//////////////////////////////////////////////////////8

macro "Add a Fixed Image to a Lambda Colour Coded Seies Action Tool - C00g L118d L360d C000 T9910+ Tfa10I"
{


waitForUser("","select Lambda image \n then press OK");
fnL=getTitle();
getDimensions(ImageWidth, ImageHeight, ImageChannels, ImageSlices, ImageFrames);

run("RGB Color");
fnL_RGB=getTitle();

waitForUser("","select image to add to lambda image \n then press OK");
fnF=getTitle();

setBatchMode("hide");


for (Image=1;Image<=ImageChannels;Image++){
selectWindow(fnL);
Stack.setChannel(Image);
run("Duplicate...", "title=Lambda_Channel duplicate channels=Image");

selectWindow(fnF);
//Stack.setSlice(Image);
run("Duplicate...", "title=Image_to_add");
run("Merge Channels...", "c1=Lambda_Channel c2=Image_to_add create");
rename("temp_image");
run("RGB Color");
rename("New_Combined_image");
run("Copy");
selectWindow(fnL_RGB);
Stack.setSlice(Image);
run("Paste");

selectWindow("New_Combined_image");
close();
selectWindow("temp_image");
close();
}

setBatchMode("exit and display");

selectWindow(fnL_RGB);
rename(fnL_RGB+" combined");
run("Select None");
}


macro "Blank2 Action Tool - "
{
}