//This is useful to correct for z- and xy- drift across timepoints. //Uses turboreg plugin to align a hyperstack in z and/or in xy. //The alignment is based on a max projection of the xz reslice for //the z-alignment, and a regular xy max projection for xy alignment //Currently only can use one of the channels to align. //This will not align the slices of a particular individual time point, //for that use Align Z forEachTimePoint title=getTitle(); IID=getImageID(); getVoxelSize(px,py,pz,unit); getDimensions(w,h,chs,sls,frms); bits=bitDepth(); if(bits!=24)textLuts=getTextLUTs(); setPasteMode("Copy"); Zname=title + "-Zalign"; if(sls<2 && frms< 2) exit("Requires hyperstack with multi z and frames"); if(bits==24){ charray=newArray("all","red","green","blue"); }else{ charray=newArray(chs); for(i=0;i0 && nResults%frms==0) ptarray=true; mchoices=newArray("Auto","Manual with suggestion", "Manual"); if(ptarray) mchoices=newArray("Use Results locations (pt array)","Auto","Manual with suggestion", "Manual"); Dialog.create("Choices"); Dialog.addCheckbox("Z-align?",true); Dialog.addCheckbox("XY-align?",true); Dialog.addChoice("Ch:", charray, "2"); Dialog.addChoice("Mode", mchoices, mchoices[0]); Dialog.addCheckbox("Auto bright?", false); Dialog.addCheckbox("Auto accept?", true); Dialog.addMessage("Manual means line up the two stacks and push Space"); Dialog.show(); doz=Dialog.getCheckbox; doxy=Dialog.getCheckbox; chchoice=Dialog.getChoice(); mode=Dialog.getChoice(); autobright=Dialog.getCheckbox(); autoaccept=Dialog.getCheckbox(); accepted=true; chcrgb=""; if(chs==1) {chcrgb=chchoice; chchoice="1"; if(chcrgb=="red") rgbc=3; else if(chcrgb=="green") rgbc=5; else if(chcrgb=="blue") rgbc=6;} chchoice=parseInt(chchoice); automode=false; manualmode=false; if(mode=="Auto"||mode=="Manual with suggestion") automode=true; if(mode=="Manual"||mode=="Manual with suggestion") manualmode=true; if(mode!="Use Results locations (pt array)") ptarray=false; //if(!manualmode && autoaccept && doz) setBatchMode(true); //setBatchMode("exit and display"); x=newArray(frms); y=newArray(frms); z=newArray(frms); if(ptarray){ rsn=nResults/frms; for(i=0;i1) z[i]+=parseFloat(getResult("Slice",i*rsn+n)); } x[i]/=rsn; y[i]/=rsn; if(sls>1) z[i]/=rsn; if(i>0){x[i]-=x[0]; y[i]-=y[0]; z[i]-=z[0];} } x[0]=0; y[0]=0; z[0]=0; } if(doz){ if(!ptarray){ z[0]=0; ctot=0; dytot=0; dxtot=0; for(i=0; islicesmin+z[k]+noslices-1)){ setSlice(n+1+i+(j*chs)+(k*chs*sls)); run("Delete Slice"); n--; } } } } run("Stack to Hyperstack...", "order=xyczt(default) channels="+chs+" slices="+noslices+" frames="+frms+" display=Composite"); mdata=""+z[0]; for(i=1;i0) rorl="Left"; if(ypos>0) torb="Top"; run("Canvas Size...", "width="+w+" height="+h+" position="+torb+"-"+rorl+" zero"); if(abs(rotangle)>0.5)run("Rotate... ", "angle="+rotangle+" grid=0 interpolation=None"); run("Concatenate...", "stack1=frm"+(i)+" stack2=frm"+(i+1)+" title=frm"+(i+1)); } selectWindow("frm"+i); run("Stack to Hyperstack...", "order=xyczt(default) channels="+chs+" slices="+sls+" frames="+frms+" display=Composite"); rename("XYalign"); if(bits!=24)setTextLuts(textLuts); if(!ptarray){selectWindow("targ"); close(); } accepted=true; if(!autoaccept) { run("Z Project...", "projection=[Max Intensity] all"); zxyID=getImageID(); setLocation(800,300); selectImage(zID); setLocation(100,300); waitForUser("Check z-projections"); accepted=getBoolean("Accept xy-reg changes?"); } if(!ptarray){selectImage(zID); close(); } if(!autoaccept){selectImage(zxyID); close;} if(accepted) { selectWindow("XYalign"); rename(XYname); if(doz){ rename(title+"-XYZalign"); selectWindow(Zname); close;} } else {selectWindow("XYalign"); close;} print("XY Registration concluded"); if(isOpen("Refined Landmarks")){ print("[Refined Landmarks]","\\Clear"); print("[Refined Landmarks]","\\Close"); } } //if(doxy && stilldo) wait(100); showProgress(0.5); showProgress(1.0); function getRegData(){ sourceX0 = getResult("sourceX", 0); // First line of the table. sourceY0 = getResult("sourceY", 0); targetX0 = getResult("targetX", 0); targetY0 = getResult("targetY", 0); dx1 = sourceX0 - targetX0; dy1 = sourceY0 - targetY0; //print("\\Update:Translation [pixel]: " + dx1 +" in X and "+dy1+" in Y"); //translation = sqrt(dx1 * dx1 + dy1 * dy1); // Amount of translation, in pixel units. if(nResults>1){ sourceX1 = getResult("sourceX", 1); // Second line of the table. sourceY1 = getResult("sourceY", 1); targetX1 = getResult("targetX", 1); targetY1 = getResult("targetY", 1); sourceX2 = getResult("sourceX", 2); // Third line of the table. sourceY2 = getResult("sourceY", 2); targetX2 = getResult("targetX", 2); targetY2 = getResult("targetY", 2); dx = sourceX2 - sourceX1; dy = sourceY2 - sourceY1; sourceAngle = atan2(dy, dx); dx = targetX2 - targetX1; dy = targetY2 - targetY1; targetAngle = atan2(dy, dx); rotation = targetAngle - sourceAngle; // Amount of rotation, in radian units. //print("Amount of rotation [degree]: " + (rotation * 180.0 / PI)); rotangle=(rotation * 180.0 / PI); return newArray(dx1, dy1, rotangle); } else return newArray(dx1,dy1); } function addArray(item, array){ temparray=newArray(array.length+1); for(i=0; i