//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(); 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;i0 && nResults%frms==0) {ptarray=true;} else{ logstr=split(getInfo("log"),"\n"); ll=logstr.length; st=-1;end=-1; for(i=0;i-1) stackregstr="StackReg"; if(isOpen("AJZALIGNTEMP")) exit("Please close AJZALIGNTEMP"); //if(chs>1) run("Stack to RGB"); title=getTitle(); for(i=1;i<=frms;i++){ selectWindow(title); i=1; 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=="Use Results locations (pt array)" && !ptarray) exit("Pt array requires one or a set of points to be measured for each time point"); 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) } } } zaccepted=false; if(doz){ if(!ptarray){ z[0]=0; ctot=0; dytot=0; dxtot=0; if(selec)waitForUser("Place selection for reslice now (currently only xz reslice)"); tpstr=newArray(1); tpstr[0]="TP: 01:x"; print("\\Clear"); lstrn=0; 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