macro "AutoHyperstackReg" { Stack.getPosition(channel, slice, anchorFrame); Stack.getDimensions(width, height, channels, slices, frames); getVoxelSize(pixelWidth, pixelHeight, voxelDepth, unit); title=getTitle(); if (slices>1 || channels>1) { Dialog.create("AutoRegistration options"); if (channels>1) Dialog.addNumber("Reference channel:", channel); Dialog.addCheckbox("Correct lateral drift:", 1); if (slices>1) Dialog.addCheckbox("Correct focus drift:", 1); Dialog.addCheckbox("Generate a Max projection preview of the result", 1); Dialog.show(); if (channels>1) refChannel=Dialog.getNumber(); else refChannel=1; xyCorrect=Dialog.getCheckbox(); if (slices>1) zCorrect=Dialog.getCheckbox(); else zCorrect=0; displayPreview=Dialog.getCheckbox(); } else { refChannel=1; xyCorrect=1; zCorrect=0; displayPreview=0; } if (xyCorrect==0 && zCorrect==0) exit; setBatchMode(true); selectWindow(title); setBatchMode("hide"); //Get LUTs and metadata REDS=newArray(channels*256); GREENS=newArray(channels*256); BLUES=newArray(channels*256); MINSMAXS=newArray(channels*2); index=0; for (c=1; c<=channels; c++) { Stack.setChannel(c); getLut(reds, greens, blues); for (n=0; n<256; n++) REDS[n+index*256]=reds[n]; for (n=0; n<256; n++) GREENS[n+index*256]=greens[n]; for (n=0; n<256; n++) BLUES[n+index*256]=blues[n]; getMinAndMax(MINSMAXS[index*2], MINSMAXS[1+index*2]); index=index+1; } Stack.setSlice(1); Stack.setChannel(1); metadata=newArray(frames); for (t=1; t<=frames; t++) { Stack.setFrame(t); metadata[t-1]=getMetadata("Label"); } //Correct XY - preparing reference and doing registration if (xyCorrect==1) { showStatus("!Preparing for lateral drift correction..."); if (slices>1) { run("Z Project...", "projection=[Sum Slices] all"); selectWindow("SUM_"+title); run("Duplicate...", "title=ref duplicate channels="+refChannel+"-"+refChannel+" slices=1-1 frames=1-"+frames); selectWindow("SUM_"+title); close(); } else if (channels>1) run("Duplicate...", "title=ref duplicate channels="+refChannel); else run("Duplicate...", "title=ref duplicate"); selectWindow("ref"); run("Enhance Contrast", "saturated=15"); run("8-bit"); run("16-bit"); makeOval((width/2-6), (height/2-4), 9, 9); run("Multiply...", "value=0 stack"); run("Add...", "value=400 stack"); Stack.setPosition(1, 1, anchorFrame); run("MultiStackReg", "stack_1=ref action_1=Align file_1=[] stack_2=None action_2=Ignore file_2=[] transformation=Translation"); run("Select None"); run("Subtract...", "value=315 stack"); invertSlicesFrames=0; centerOfMassX=newArray(frames); centerOfMassY=newArray(frames); run("Properties...", "unit=pixel pixel_width=1 pixel_height=1 voxel_depth=1"); for (t=1; t<=frames; t++) { Stack.setFrame(t); List.setMeasurements; centerOfMassX[t-1]=List.getValue("XM"); centerOfMassY[t-1]=List.getValue("YM"); } anchorFrameX=centerOfMassX[anchorFrame-1]; anchorFrameY=centerOfMassY[anchorFrame-1]; for (t=1; t<=frames; t++) { centerOfMassX[t-1]=centerOfMassX[t-1]-anchorFrameX; centerOfMassY[t-1]=centerOfMassY[t-1]-anchorFrameY; } selectWindow("ref"); close(); //Correct XY - translations selectWindow(title); for (t=1; t<=frames; t++) { Stack.setFrame(t); showStatus("!Correcting lateral drift, frame "+t+"/"+frames); for (c=1; c<=channels; c++) { Stack.setChannel(c); for (z=1; z<=slices; z++) { Stack.setSlice(z); run("Translate...", "x="+centerOfMassX[t-1]+" y="+centerOfMassY[t-1]+" interpolation=Bicubic slice"); } if (zCorrect==1) showProgress(t/(frames*2)); else showProgress(t/frames); } } } //Correct Z - preparing reference 1 (left reslice) and doing registration if (zCorrect==1) { showStatus("!Preparing for focus drift correction..."); makeRectangle(round(width*0.35), 0, round(width*0.3), height); run("Reslice [/]...", "output="+pixelWidth+" start=Left avoid"); selectWindow("Reslice of "+title); run("Z Project...", "projection=[Sum Slices] all"); selectWindow("Reslice of "+title); close(); selectWindow("SUM_Reslice of "+title); run("Duplicate...", "title=ref duplicate channels="+refChannel+"-"+refChannel+" slices=1-1 frames=1-"+frames+""); selectWindow("SUM_Reslice of "+title); close(); selectWindow("ref"); run("Enhance Contrast", "saturated=15"); run("8-bit"); run("16-bit"); makeOval((width/2-2), (slices/2-2), 5, 5); run("Multiply...", "value=0 stack"); run("Add...", "value=400 stack"); run("Canvas Size...", "width="+round(height*0.7)+" height="+slices+" position=Center zero"); Stack.setPosition(1, 1, anchorFrame); run("MultiStackReg", "stack_1=ref action_1=Align file_1=[] stack_2=None action_2=Ignore file_2=[] transformation=Translation"); run("Select None"); run("Subtract...", "value=315 stack"); centerOfMassX2=newArray(frames); centerOfMassY2=newArray(frames); run("Properties...", "unit=pixel pixel_width=1 pixel_height=1 voxel_depth=1"); for (t=1; t<=frames; t++) { Stack.setFrame(t); List.setMeasurements; centerOfMassX2[t-1]=List.getValue("XM"); centerOfMassY2[t-1]=List.getValue("YM"); } anchorFrameX=centerOfMassX2[anchorFrame-1]; anchorFrameY=centerOfMassY2[anchorFrame-1]; for (t=1; t<=frames; t++) { centerOfMassX2[t-1]=centerOfMassX2[t-1]-anchorFrameX; centerOfMassY2[t-1]=centerOfMassY2[t-1]-anchorFrameY; } selectWindow("ref"); close(); //Correct Z - preparing reference 2 (top reslice) and doing registration selectWindow(title); run("Select None"); run("Reslice [/]...", "output="+pixelWidth+" start=Top avoid"); selectWindow(title); close(); selectWindow("Reslice of "+title); rename(title); run("Z Project...", "start="+round(height*0.35)+" stop="+round(height*0.65)+" projection=[Sum Slices] all"); selectWindow("SUM_"+title); run("Duplicate...", "title=ref duplicate channels="+refChannel+"-"+refChannel+" slices=1-1 frames=1-"+frames+""); selectWindow("SUM_"+title); close(); selectWindow("ref"); run("Enhance Contrast", "saturated=15"); run("8-bit"); run("16-bit"); makeOval((width/2-2), (slices/2-2), 5, 5); run("Multiply...", "value=0 stack"); run("Add...", "value=400 stack"); run("Canvas Size...", "width="+round(width*0.7)+" height="+slices+" position=Center zero"); Stack.setPosition(1, 1, anchorFrame); run("MultiStackReg", "stack_1=ref action_1=Align file_1=[] stack_2=None action_2=Ignore file_2=[] transformation=Translation"); run("Select None"); run("Subtract...", "value=315 stack"); centerOfMassX=newArray(frames); centerOfMassY=newArray(frames); run("Properties...", "unit=pixel pixel_width=1 pixel_height=1 voxel_depth=1"); for (t=1; t<=frames; t++) { Stack.setFrame(t); List.setMeasurements; centerOfMassX[t-1]=List.getValue("XM"); centerOfMassY[t-1]=List.getValue("YM"); } anchorFrameX=centerOfMassX[anchorFrame-1]; anchorFrameY=centerOfMassY[anchorFrame-1]; for (t=1; t<=frames; t++) { centerOfMassX[t-1]=centerOfMassX[t-1]-anchorFrameX; centerOfMassY[t-1]=centerOfMassY[t-1]-anchorFrameY; } selectWindow("ref"); close(); //Correct Z - averaging the 2 registrations for (t=1; t<=frames; t++) { centerOfMassX[t-1]=(centerOfMassX[t-1]+centerOfMassX2[t-1])/2; centerOfMassY[t-1]=(centerOfMassY[t-1]+centerOfMassY2[t-1])/2; } //Correct Z - applying the translations selectWindow(title); for (t=1; t<=frames; t++) { Stack.setFrame(t); showStatus("!Correcting focus drift, frame "+t+"/"+frames); for (c=1; c<=channels; c++) { Stack.setChannel(c); for (z=1; z<=height; z++) { Stack.setSlice(z); run("Translate...", "x="+centerOfMassX[t-1]+" y="+centerOfMassY[t-1]+" interpolation=Bicubic slice"); } } if (xyCorrect==1) showProgress((t+frames)/(frames*2)); else showProgress(t/frames); } rename("resliceAligned"); run("Reslice [/]...", "output="+pixelWidth+" start=Top avoid"); selectWindow("resliceAligned"); close(); selectWindow("Reslice of resliceAligned"); rename(title+"_aligned"); index=0; for (c=1; c<=channels; c++) { Stack.setChannel(c); for (n=0; n<256; n++) reds[n]=REDS[n+index*256]; for (n=0; n<256; n++) greens[n]=GREENS[n+index*256]; for (n=0; n<256; n++) blues[n]=BLUES[n+index*256]; setLut(reds, greens, blues); setMinAndMax(MINSMAXS[index*2], MINSMAXS[1+index*2]); index=index+1; } for (t=1; t<=frames; t++) { Stack.setFrame(t); for (c=1; c<=channels ; c++) { Stack.setChannel(c); for (z=1 ; z<=slices; z++) { Stack.setSlice(z); setMetadata("Label", metadata[t-1]); } } } } else rename(title+"_aligned"); //Generating MaxProj preview if (displayPreview==1) { showStatus("!Generating the preview"); run("Z Project...", "projection=[Max Intensity] all"); if (slices>1) { selectWindow(title+"_aligned"); makeRectangle(0, round(height*0.4), width, round(height*0.2)); run("Reslice [/]...", "output="+pixelWidth*5+" start=Top"); selectWindow(title+"_aligned"); run("Select None"); selectWindow("Reslice of "+title+"_aligned"); run("Z Project...", "projection=[Max Intensity] all"); selectWindow("Reslice of "+title+"_aligned"); close(); selectWindow("MAX_Reslice of "+title+"_aligned"); Stack.getDimensions(irrelevant, resliceHeight, irrelevant, irrelevant, irrelevant); run("Canvas Size...", "width="+width+" height="+resliceHeight+3+" position=Bottom-Left zero"); run("Combine...", "stack1=[MAX_"+title+"_aligned] stack2=[MAX_Reslice of "+title+"_aligned] combine"); selectWindow("Combined Stacks"); rename(title+"_aligned_MAX"); } else rename(title+"_aligned_MAX"); index=0; for (c=1; c<=channels; c++) { Stack.setChannel(c); for (n=0; n<256; n++) reds[n]=REDS[n+index*256]; for (n=0; n<256; n++) greens[n]=GREENS[n+index*256]; for (n=0; n<256; n++) blues[n]=BLUES[n+index*256]; setLut(reds, greens, blues); setMinAndMax(MINSMAXS[index*2], MINSMAXS[1+index*2]); index=index+1; run("Enhance Contrast", "saturated=0.5"); } for (t=1; t<=frames; t++) { Stack.setFrame(t); for (c=1; c<=channels ; c++) { Stack.setChannel(c); setMetadata("Label", metadata[t-1]); } } selectWindow(title+"_aligned"); } setBatchMode("exit and display"); showStatus("Done!"); }