//This is useful to correct for z- and xy- drift across timepoints. //Uses TurboRegplugin 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 turboregstring="TurboReg"; List.setCommands; if(List.get(turboregstring)=="")turboregstring="TurboReg "; if(List.get(turboregstring)=="") exit("This macro requires TurboReg"); title=getTitle(); IID=getImageID(); oIID=IID; getVoxelSize(px,py,pz,unit); getDimensions(w,h,chs,sls,frms); substack="1-"+sls; bits=bitDepth(); if(bits!=24)textLuts=getTextLUTs(); logarray=false; setPasteMode("Copy"); Zname=title + "-Zalign"; if(sls<2 && frms< 2) exit("Requires hyperstack with multi frames"); if(bits==24){ charray=newArray("all","red","green","blue"); }else{ charray=newArray(chs); for(i=0;i-1 && indexOf(Table.headings,"SourceX1")>-1 ){ print("\\Update:Results Table found: "+list[i]+" as a StackReg Table"); ptarray=true; srarray=true; } } } } } if(nResults>0 && nResults%frms==0) {ptarray=true;} if(!ptarray){ logstr=split(getInfo("log"),"\n"); ll=logstr.length; st=-1;end=-1; for(i=0;i1) run("Stack to RGB"); title=getTitle(); for(i=1;i<=frms;i++){ selectWindow(title); run("Duplicate...", "title="+i+" duplicate frames="+i); if(chs>1)Stack.setChannel(chchoice); run(stackregstr, "transformation=Affine"); if(i!=1) run("Concatenate...", "stack1=1 stack2="+i+" title=AJZALIGNTEMP"); } rename(title+"-slicealign"); run("Stack to Hyperstack...", "order=xyczt(default) channels="chs" slices="+sls+" frames="+frms); exit(); } startsub=1; endsub=sls; if(substack!="") { if(indexOf(substack,"-")==-1){ startsub=round(substack); endsub=round(substack); } else { substa=split(substack,"-"); startsub=parseInt(substa[0]); endsub=parseInt(substa[1]); } if(startsub>endsub) {tempsub=startsub; startsub=endsub; endsub=tempsub;} } if(mode=="Auto") ptarray=false; else ptarray=true; //setBatchMode(true); //setBatchMode("exit and display"); z=newArray(frms); x=newArray(frms); y=newArray(frms); r=newArray(frms); accepted=true; if(logarray){ for(i=1;i1) zinits[n]=parseFloat(getResult("Slice",n)); }else{ x[i]+=(parseFloat(getResult("X",i*rsn+n))/px)-xinits[n]; y[i]+=(parseFloat(getResult("Y",i*rsn+n))/py)-yinits[n]; if(sls>1) z[i]+=(parseFloat(getResult("Slice",i*rsn+n)))-zinits[n]; } } x[i]/=rsn; y[i]/=rsn; if(sls>1) z[i]/=rsn; r[i]=0; //not coded (yet) } } }else if(srarray){ isxz=false; headings=Table.headings; rh=split(headings,"\t"); for(i=0;islicesmin+z[k]+noslices-1)){ print("\\Update:ch"+i+"/"+chs+" sl"+j+"/"+sls+" fr"+k+"/"+frms+" n"+n); setSlice(n+1+i+(j*chs)+(k*chs*sls)); run("Delete Slice", "delete=slice"); n--; } } } } run("Stack to Hyperstack...", "order=xyczt(default) channels="+chs+" slices="+noslices+" frames="+frms+" display=Composite"); mdata=""+z[0]; for(i=1;i1){ run("Duplicate...", "title=frm"+(i+1)+" duplicate channels=1-"+chs+" slices=1-"+sls+" frames=1"); run("Hyperstack to Stack"); if(i>0){ selectWindow("frm"+(i+1)); makeRectangle(x[i],y[i],w,h); run("Crop"); torb="Bottom"; rorl="Right"; if(x[i]>0) rorl="Left"; if(y[i]>0) torb="Top"; run("Canvas Size...", "width="+w+" height="+h+" position="+torb+"-"+rorl+" zero"); if(abs(r[i])>0.5)run("Rotate... ", "angle="+r[i]+" grid=0 interpolation=None"); run("Concatenate...", " title=["+XYname+"] image1=["+XYname+"] image2=frm"+(i+1)); } else rename(XYname); selectImage(IID); Stack.setFrame(1); if(i<(frms-1)){run("Delete Slice", "delete=frame");}else{close();} }else{ if(i>0){ for(ich=0;ich0.5)run("Rotate... ", "angle="+r[i]+" grid=0 interpolation=None slice"); } } } } selectWindow(XYname); if(sls>1){ run("Stack to Hyperstack...", "order=xyczt(default) channels="+chs+" slices="+sls+" frames="+frms+" display=Composite"); }else{ Stack.setFrame(1); run("Select None"); } if(bits!=24)setTextLuts(textLuts); call("java.lang.System.gc"); } //if(doxy && stilldo) print("XYZ Registration completed"); wait(100); showProgress(0.5); wait(100); 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; rotangle=0; //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); } //print("Translation: " + dx1 +" by "+dy1+" rot:"+rotangle); return newArray(dx1, dy1, rotangle); } function addArray(item, array){ temparray=newArray(array.length+1); for(i=0; i