/* * GUI MACRO to select one image on which to define the rotation * It returns a file called transformation.txt that is used by the TissueMiner framework * */ // Select trafo method and image file to rotate path=select_image_file(); // Define image directory and file name separately dir=File.getParent(path)+File.separator(); //print("dir",dir); fileName=File.getName(path); open(dir + fileName); imID=getImageID(); //transfoType=newArray("Draw an axis","Ellipse Major Axis"); transfoType=newArray("Draw a new X-axis", "Draw a new Y-axis"); //Dialog.create("Transformation options"); Dialog.create("Rotation options"); //Dialog.addCheckbox("Rotate ?", true); Dialog.addChoice("Method: ",transfoType); //Dialog.addCheckbox("Enable flip options ?", false); Dialog.addNumber("Pixel size in micron (optional): ",0.207); Dialog.show(); //isRotate=Dialog.getCheckbox(); isRotate=true; rotMethod=Dialog.getChoice(); //isFlip=Dialog.getCheckbox(); isFlip=false; pxsize=Dialog.getNumber(); selectImage(imID); close(); // Cases: rotate only and rotate&flip if (isRotate) { // Apply trafo trafo=rotate_drawAxis(dir, fileName, pxsize, rotMethod); // rotate the tissue by drawing an axis print("trafo:", trafo); if (isFlip) { Dialog.create("Select the flips to apply"); Dialog.addChoice("Flip: ", newArray("Horizontal (left-rigth exchange)","Vertical (up-side-down)", "Horizontal and Vertical", "None")); Dialog.show(); flipMethod=Dialog.getChoice(); if (flipMethod=="Horizontal (left-rigth exchange)") { run("Flip Horizontally"); IsVerticalFlip=0; IsHorizontalFlip=1; trafo=update_trafo(dir, trafo, IsVerticalFlip, IsHorizontalFlip); print(trafo); } else if (flipMethod=="Vertical (up-side-down)") { run("Flip Vertically"); IsVerticalFlip=1; IsHorizontalFlip=0; trafo=update_trafo(dir, trafo, IsVerticalFlip, IsHorizontalFlip); print(trafo); } else if (flipMethod=="Horizontal and Vertical") { run("Flip Horizontally");run("Flip Vertically"); IsVerticalFlip=1; IsHorizontalFlip=1; trafo=update_trafo(dir, trafo, IsVerticalFlip, IsHorizontalFlip); print(trafo); } else if (flipMethod=="None") { IsVerticalFlip=0; IsHorizontalFlip=0; trafo=update_trafo(dir, trafo, IsVerticalFlip, IsHorizontalFlip); print(trafo); } } wait(2000); close(); } // Case flip only if (!isRotate && isFlip) { print("flip only"); open(dir + fileName); imID=getImageID(); // get image dimensions of original width = getWidth(); height = getHeight(); rotationcenterx = width/2; rotationcentery = height/2; rotationcenternewx = rotationcenterx; rotationcenternewy = rotationcentery; sep=" "; trafo= toString(0) + sep + rotationcenterx + sep + rotationcentery + sep + rotationcenternewx + sep + rotationcenternewy + sep + toString(0) + sep + toString(0) + sep + width + sep + height + sep + "FlipOnly"; print(trafo); Dialog.create("Select the flips to apply"); Dialog.addChoice("Flip: ", newArray("Horizontal (left-rigth exchange)","Vertical (up-side-down)", "Horizontal and Vertical","None")); Dialog.show(); flipMethod=Dialog.getChoice(); if (flipMethod=="Horizontal (left-rigth exchange)") { run("Flip Horizontally"); IsVerticalFlip=0; IsHorizontalFlip=1; trafo=update_trafo(dir, trafo, IsVerticalFlip, IsHorizontalFlip); print(trafo); } else if (flipMethod=="Vertical (up-side-down)") { run("Flip Vertically"); IsVerticalFlip=1; IsHorizontalFlip=0; trafo=update_trafo(dir, trafo, IsVerticalFlip, IsHorizontalFlip); print(trafo); } else if (flipMethod=="Horizontal and Vertical") { run("Flip Horizontally");run("Flip Vertically"); IsVerticalFlip=1; IsHorizontalFlip=1; trafo=update_trafo(dir, trafo, IsVerticalFlip, IsHorizontalFlip); print(trafo); } else if (flipMethod=="None") { IsVerticalFlip=0; IsHorizontalFlip=0; trafo=update_trafo(dir, trafo, IsVerticalFlip, IsHorizontalFlip); print(trafo); } f=File.open(dir+"transformation.txt"); header="Angle_rad rotationCenterOld_x rotationCenterOld_y rotationCenterNew_x rotationCenterNew_y IsVerticalFlip IsHorizontalFlip newWidth newImHeight method"; print(f, header); print(f, trafo); File.close(f); wait(3000); close(); } exit(); function select_image_file(){ inputpath = File.openDialog("Please, select an image to process"); return inputpath; } function select_trafo(transfoType){ Dialog.create("Type of transformation to be performed"); Dialog.addChoice("Type: ",transfoType,"rotate_ellipse"); Dialog.show(); transfo=Dialog.getChoice(); return transfo; } function update_trafo(dir, trafo, IsVerticalFlip,IsHorizontalFlip){ sep=" "; fields=split(trafo, sep); fields[5]=IsVerticalFlip; fields[6]=IsHorizontalFlip; newTrafo = toString(fields[0]) + sep + fields[1] + sep + fields[2] + sep + fields[3] + sep + fields[4] + sep + fields[5] + sep + fields[6] + sep + fields[7] + sep + fields[8] + sep + fields[9]; f=File.open(dir+"transformation.txt"); header="Angle_rad rotationCenterOld_x rotationCenterOld_y rotationCenterNew_x rotationCenterNew_y IsVerticalFlip IsHorizontalFlip newImWidth newImHeight method"; print(f, header); print(f, newTrafo); File.close(f); return newTrafo; } function rotate_drawAxis(dir, file, pxsize,rotMethod){ //print("Draw a line to be aligned on the horizontal"); // Perform axis selection + transformation do { // open selected file open(dir + file); imID=getImageID(); // get image dimensions of original width = getWidth(); height = getHeight(); // set scale in microns based on user-defined pixel size run("Set Scale...", "distance=1 known="+pxsize+" unit=micron"); // manually draw points on tissue setTool("line"); run("ROI Manager..."); waitForUser("Please, select a line and click OK to validate"); roiManager("Add"); // get axis angle roiManager("Measure"); rotation=getResult("Angle", 0); if (rotMethod=="Draw a new X-axis") { print("angle with respect to horizontal:", rotation); } else { rotation=rotation-90; print("angle with respect to vertical:", rotation); } // Get center positions before rotation rotationcenterx = width/2; rotationcentery = height/2; // Clockwise rotation based on the image center (y-axis pointing downward) print("Rotation angle =" + rotation); // Rotation can only be enlarged if no roi on top of image: workaround = duplicate the image and rotate the duplicated image selectImage(imID); run("Duplicate...", "rot template");rotImID=getImageID(); selectImage(imID);close(); setBackgroundColor(255,0,0); run("Rotate... ", "angle=&rotation grid=1 interpolation=Bilinear fill enlarge"); // Update coordinates for the new system of coordinates (new orientation => new boundaries) // Rotate the four images corners A, B, C, D by the rotation matrix R(theta) // convert rotation angle in radian rotationRad=rotation*PI/180; A=newArray(-width/2, -height/2); B=newArray(-1*-width/2, -height/2);//"-1*-" is needed in first place because of bug in macro language C=newArray(-1*-width/2, height/2); D=newArray(-width/2, height/2); // Clockwise rotation but bounded box would be the same by symmetry if counter-clockwise rotation Arot=newArray(A[0]*cos(rotationRad)-A[1]*sin(rotationRad),A[0]*sin(rotationRad)+A[1]*cos(rotationRad)); Brot=newArray(B[0]*cos(rotationRad)-B[1]*sin(rotationRad),B[0]*sin(rotationRad)+B[1]*cos(rotationRad)); Crot=newArray(C[0]*cos(rotationRad)-C[1]*sin(rotationRad),C[0]*sin(rotationRad)+C[1]*cos(rotationRad)); Drot=newArray(D[0]*cos(rotationRad)-D[1]*sin(rotationRad),D[0]*sin(rotationRad)+D[1]*cos(rotationRad)); // counter-clockwise rotation //Arot=newArray(A[0]*cos(rotation)+A[1]*sin(rotation),-A[0]*sin(rotation)+A[1]*cos(rotation)); //Brot=newArray(B[0]*cos(rotation)+B[1]*sin(rotation),-B[0]*sin(rotation)+B[1]*cos(rotation)); //Crot=newArray(C[0]*cos(rotation)+C[1]*sin(rotation),-C[0]*sin(rotation)+C[1]*cos(rotation)); //Drot=newArray(D[0]*cos(rotation)+D[1]*sin(rotation),-D[0]*sin(rotation)+D[1]*cos(rotation)); xCoord=newArray(Arot[0],Brot[0],Crot[0],Drot[0]); Array.sort(xCoord); yCoord=newArray(Arot[1],Brot[1],Crot[1],Drot[1]); Array.sort(yCoord); boundedBoxDim=newArray(-1*-floor(abs(xCoord[0])+xCoord[3]+1),floor(abs(yCoord[0])+yCoord[3])+1); widthnew = getWidth(); heightnew = getHeight(); //rotationcenternewx = widthnew / 2; //rotationcenternewy = heightnew / 2; rotationcenternewx = boundedBoxDim[0] / 2; rotationcenternewy = boundedBoxDim[1] / 2; print("Fiji bounded box dim: ", widthnew, heightnew); print("Calculated bounded box dim:", boundedBoxDim[0],boundedBoxDim[1]); success=getBoolean("Rotation OK?"); if (!success) {selectImage(rotImID);close();} selectWindow("ROI Manager");run("Close"); selectWindow("Results");run("Close"); } while (success==0); //END OF LOOP // Save transformation in transformation.txt // HEADER // Angle (rad) postive sign is anticlockwise: (invert the sign) // "Rotation center coordinates in old system: rotationCenterOld_x and rotationCenterOld_y // "Rotation center coordinates in new system: rotationCenterNew_x and rotationCenterNew_y // "Put the anterior compartment up if it isn't: isVerticalFlip" f=File.open(dir+"transformation.txt"); header="Angle_rad rotationCenterOld_x rotationCenterOld_y rotationCenterNew_x rotationCenterNew_y IsVerticalFlip IsHorizontalFlip newImWidth newImHeight method"; print(f, header); sep=" "; isVerticalFlip=0; isHorizontalFlip=0; values=toString(rotationRad) + sep + rotationcenterx + sep + rotationcentery + sep + rotationcenternewx + sep + rotationcenternewy + sep + isVerticalFlip + sep + isHorizontalFlip + sep + boundedBoxDim[0] + sep + boundedBoxDim[1] + sep + "drawAxis"; print(f, values); File.close(f); // Clean up memory //selectImage(rotImID); //close(); return values; } exit(); function rotate_ellipse(dir, file){ print("Order of points: SO1 in proximal hinge ; SO2 on L3; SO3 on L3; any pt in post. compartment"); open(dir + file); // for png files, better use open(); //run("Bio-Formats Importer", "open="+ dir + file+" autoscale color_mode=Default view=[Standard ImageJ] stack_order=Default"); imID=getImageID(); //gets image dimensions of original width = getWidth(); height = getHeight(); // Perform point selection + transformation do { selectImage(imID); setTool("line"); //gets points on wings leftButton=16; rightButton = 4; insideROI = 32; ctrl = 2; x2=-1; y2=-1; z2=-1; flags2=-1; printed = false; currentpoint=0; maxpoints=4; xCoords = newArray(maxpoints); yCoords = newArray(maxpoints); while (currentpoint=-180) {rotation=angle+90;} //else if(angle<=0 && angle >-90) {rotation=angle+90;} //else if(angle>0 && angle <=90) {rotation=angle+90;} //else if(angle>90 && angle <=180) {rotation=angle+90;} rotation=angle+90; // always valid because 'angle' is oriented rotationRad=rotation*PI/180; print("rotation",rotation); // Get center positions before rotation rotationcenterx = width / 2; rotationcentery = height / 2; // Clockwise rotation based on the image center print("Rotation angle =" + rotation); run("Rotate... ", "angle=&rotation grid=1 interpolation=Bilinear fill enlarge"); // Caculate point coordinates in the new system of coordinates (new orientation and new boundaries) widthnew = getWidth(); heightnew = getHeight(); rotationcenternewx = widthnew / 2; rotationcenternewy = heightnew / 2; success=getBoolean("Rotation OK?"); if (!success) {run("Undo");} } while (success==0); f=File.open(dir+"transformation.txt"); //HEADER // Angle (rad) postive sign is anticlockwise: (invert the sign) // "Rotation center coordinates in old system: rotationCenterOld_x and rotationCenterOld_y // "Rotation center coordinates in new system: rotationCenterNew_x and rotationCenterNew_y // "Put the anterior compartment up if it isn't: isVerticalFlip" header="Angle_rad rotationCenterOld_x rotationCenterOld_y rotationCenterNew_x rotationCenterNew_y IsVerticalFlip newImHeight method"; print(f, header); sep=" "; isFlip=0; values=toString(rotationRad) + sep + rotationcenterx + sep + rotationcentery + sep + rotationcenternewx + sep + rotationcenternewy + sep + isFlip + sep + heightnew + sep + "rotate_wing_disk"; print(f, values); File.close(f); selectImage(imID); close(); }