//27.02.22, 20:31 var files, users, IDs, focusWidth = 800, //px focusZoom = 100, // % Zvalue = 165, // grid constant should be same as in .ojj file snapX = newArray(0), snapY = newArray(0), teamWidth = 1000, Linked = "", ; //one ojj file must be open macro "Create Team.tif"{ run("ObjectJ "); requires("1.53h"); ojRequires("1.05g"); //close("User_Table.tsv"); close("Team*.tif"); prPath = ojGetProjectPath(); prName = ojGetProjectName(); files = getFileList(prPath); colors = split(ojGetItemColors()); run("Clear Results"); nFiles = files.length; users = newArray(nFiles); //IDs = newArray(nFiles); ojjFiles = newArray(nFiles); nn = 0; for(jj = 0; jj < nFiles; jj++){ file = files[jj]; if(indexOf(file, "__") >=0) exit("__ not allowed: " + file); fileNoExt = File.getNameWithoutExtension(file); parts = split(fileNoExt, "_"); len = parts.length; if(len == 4 && file.endsWith(".ojj")){ //IDs[nn] = parts[2]; users[nn] = parts[2] + "_" +parts[3]; //setResult("ID", nn, IDs[nn]); setResult("User", nn, users[nn]); ojjFiles[nn] = file; nn++; updateResults; } } users = Array.trim(users,nn); //IDs = Array.trim(IDs,nn); ojjFiles = Array.trim(ojjFiles,nn); //updateResults;//users are in Resultstable for user feedback //IJ.renameResults("User_Table.tsv"); //saveAs("Results", prPath + "User_Table.tsv"); populateScript = createScript2(prPath ,ojjFiles);//prepare script text, not executing yet print("\\Clear"); print(populateScript); selectWindow("Log"); //waitForUser("Log window shows JavaScript to be executed.\n \nClick OK to continue"); close("Team*"); ww1 = ojGetImageValue(1, "width"); hh1 = ojGetImageValue(1, "height"); linkedName = ojGetImageName(1); factor = teamWidth/ww1; ww2 = teamWidth; hh2 = hh1 * factor; //debug; newImage("Team.tif", "8-bit black", ww2, hh2, users.length); meta = ""; meta += "Linked=" + linkedName + "\n"; meta += "width=" + ww1 + "\n"; meta += "height=" + hh1 + "\n"; //meta += "prPath=" + prPath + "\n"; //meta += "prName=" + prName + "\n"; items = split(ojGetItemNames()); colors = split(ojGetItemColors()); meta += "\n"; meta += "nUsers=" + users.length + "\n"; for(jj = 0; jj< users.length; jj++) meta += "user" + (jj+1) + "=" + users[jj] + "\n"; meta += "\n"; meta += "nItems=" + items.length + "\n"; for(jj = 0; jj< items.length; jj++) meta += "item" + (jj+1) + "=" + items[jj] + "\n"; for(jj = 0; jj< colors.length; jj++) meta += "color" + (jj+1) + "=" + colors[jj] + "\n"; //meta+="Crazy Names " + setMetadata("Info", meta); //print("\\Clear"); //print(meta); //exit; saveAs("Tiff", prPath + "Team.tif"); run("Set... ", "zoom=50"); for(jj = 0; jj < users.length; jj++){ setSlice(jj+1); //meta = IDs[jj] +"_" + users[jj]; meta = users[jj]; setMetadata("label", meta); } customLUT(); ojSetUnchanged(); close("Log"); //exit("hello-2"; eval("js", populateScript);//calls e.g. 15 x Populate Team showMessage("I won't be reached!"); } function createScript2(prPath, files){ script = ""; left = "IJ.runMacro(\'"; right = "\')" + "\n"; for(jj = 0; jj < files.length; jj++){ fullPath = prPath + files[jj]; script += 'IJ.open("' + fullPath + '");' + '\n'; script += 'IJ.runMacro("run(\'<->Populate Team.tif\');");'+ "\n"; } script += left + 'run("Save");' + right; script += left + 'showMessage("Finished");' + right; return script; } /*Employs the particle analyzer in all observer slices and creates overlayed letters onto the linked jpg image*/ macro "Build Image with User-IDs as Overlay"{ List.setCommands; val=List.get("ObjectJ "); if(val != ""){//If ObjectJ is installed ... ojRequires("1.05m"); prName = ojGetProjectName();//.. then no project must be open if(prName != "") exit("First choose ObjectJ>Project>Close Project"); } if(nImages != 1 || getTitle != "Team.tif") exit("Only 'Team.tif' must be open"); setBatchMode("Hide"); setBatchMode(true); // imgNames = getList("image.titles"); // for(jj = 0; jj < imgNames.length; jj++){ // if(startsWith(imgNames[jj], "Team-")){ // selectWindow(imgNames[jj]); // msg = imgNames[jj] + ": name starts with 'Team-'"; // msg += "\n(probably renamed during opening.)"; // msg += "\n \nClose all images?"; // showMessageWithCancel(msg); // close("*"); // return; // } // } // if(isOpen("Team.tif")){ // selectImage("Team.tif"); // close("\\Others"); // } // else // exit("Team.tif must be in front"); info = getMetadata("Info"); List.setList(info); nUsers = List.get("nUsers"); nCats = List.get("nItems"); Linked = List.get("Linked"); imgPath = getDir("image"); print("\\Clear"); print(info); getSnapCenters(); //if(!isOpen("User_Table.tsv")) // open(imgPath + "User_Table.tsv"); //selectWindow("User_Table.tsv"); selectImage("Team.tif"); roiManager("reset"); //note we still have the names in the array run("Clear Results");//results grow run("Set Measurements...", "area mean modal centroid median limit decimal=0"); oldCount = 0; resetThreshold; getLut(reds, greens, blues); for(user = 0; user < nUsers; user++){ name = List.get("user" + (user + 1)); showStatus("!user=" + user); setSlice(user + 1); for(color = 1; color <= nCats; color++){ setThreshold(color, color); run("Analyze Particles...", "size=100-Infinity display exclude include slice"); resetThreshold; newCount = nResults; for(jj = oldCount; jj < newCount; jj++){ colorStr = Color.toString(reds[color], greens[color], blues[color]); setResult("Color", jj, colorStr); setResult("User#", jj, user); setResult("User", jj, name); } updateResults; oldCount = newCount; } }//results table contains all cluster centers of all users ww1 = getWidth; hh1 = getHeight; showStatus("!Opening large image, please wait..."); close(Linked); open(imgPath + Linked); run("Out [-]"); run("Out [-]"); showStatus("Done"); ww2 = getWidth; hh2 = getHeight; factor = ww2/ww1;//approx. 17 Overlay.remove; for(jj = 0; jj < nResults; jj++){ x1 = getResult("X", jj) * factor;//cluster center in big jpg y1 = getResult("Y", jj) * factor; user = getResult("User#", jj); name = getResultString("User", jj); letter = substring(name, 0, 1); letterHeight = 100; letterWidth = round(letterHeight * 0.6); setFont("Monospaced", letterHeight); snapPos = getSnapPos(x1/factor, y1/factor); if(snapPos[0] > 0){ x1 = snapPos[0] * factor; y1 = snapPos[1]* factor; } x2 = x1 + (user%8) * letterWidth - 8/2* letterWidth;//put in user coumn y2 = y1 + floor(user/8) * letterHeight - 1/2 * letterHeight;//put in user row setColor(getResultString("Color", jj)); Overlay.drawString(letter, x2, y2); Overlay.show(); } close("Results"); // selectImage("Team.tif"); // setBatchMode("Show"); // selectImage(Linked); //setBatchMode("Show"); setBatchMode("exit and display"); } //Set LUT arrays from catColors, e.g. first item in ObjectJ tools is red, so reds[1] = 0xff etc function customLUT(){ catColors = split("black " + ojGetItemColors());//one-based nCats = catColors.length - 1; reds = newArray(256); greens = newArray(256); blues = newArray(256); for (x=0; x < catColors.length; x++){ rgbArr = Color.toArray(catColors[x]); reds[x] = rgbArr[0]; greens[x] = rgbArr[1]; blues[x] = rgbArr[2]; } setLut(reds, greens, blues); } macro "Focus Tool - C05e o21dd L880f L981f C4f0T7b10F" { if (getTitle == "Focus") return; getCursorLoc(x, y, z, flags); if (getTitle == "Team.tif"){ makeOval(x-20, y-20, 40, 40); wait(100); run("Select None"); ww1 = getWidth; //ojShowImage(1); selectImage(Linked); ww2 = getWidth; x= x * ww2/ww1; y= y * ww2/ww1; } selectImage(Linked); //ojShowImage(1); makeRectangle(x-focusWidth/2, y-focusWidth/2, focusWidth, focusWidth); call("ij.gui.ImageWindow.setNextLocation",10, 100); run("Duplicate...", " "); close("Focus"); rename("Focus"); run("Set... ", "zoom=" + focusZoom); setOption("Changes", false); } function getSnapCenters(){//for snapping text to common cluster center selectImage("Team.tif"); run("Select None"); run("Duplicate...", "title=Tmp duplicate"); for(slc = 1; slc <=nSlices; slc++){ setSlice(slc); changeValues(1, 255, 5); } run("Z Project...", "projection=[Sum Slices]"); run("Gaussian Blur...", "sigma=10"); run("Find Maxima...", "prominence=1 output=[Point Selection]"); getSelectionCoordinates(snapX, snapY); close("Tmp"); close("SUM_*"); } function getSnapPos(x, y){ result = newArray(2); len = snapX.length; if(len == 0) exit("error: snap array"); dMin = 25;//snap if closer than 25 px in Teams.tif for(jj = 0; jj < len; jj++){ d = sqrt(Math.sqr(snapX[jj] - x) + Math.sqr(snapY[jj] - y) ); if(d < dMin){ dMin = d; result[0] = snapX[jj]; result[1] = snapY[jj]; } } return result; } //creates an outline of all visited parts and //adds it as overlay to Team.tif macro "Show/Hide Visited Islands [o]"{ selectImage("Team.tif"); if (Overlay.size == 0){ run("Overlay Options...", "stroke=none width=0 fill=none"); run("Select None"); run("Z Project...", "projection=[Sum Slices]"); run("Remove Overlay"); run("8-bit"); changeValues(1, 999, 255); run("Maximum...", "radius=2"); run("Find Edges"); rename("Edges"); selectImage("Team.tif"); run("Remove Overlay"); run("Add Image...", "image=Edges x=0 y=0 opacity=50 zero"); close("Edges"); Overlay.show; return; } if (Overlay.hidden) Overlay.show; else Overlay.hide; } macro "Show/Hide User Names"{ selectWindow("Team.tif"); sl = getSliceNumber; label = getMetadata("label"); visible = indexOf(label,"_") >= 0; for(slc =1; slc <= nSlices; slc++){ setSlice(slc); label = getMetadata("label"); if(visible) label = replace(label, "_", "\n"); else label = replace(label, "\n", "_"); setMetadata("label", label); } setSlice(sl); } /* This command will be called periodically by JavaScript from 'Prepare Team'. It paints colored circles into the slice of the corresponding observer. */ macro "<->Populate Team.tif"{//called by script ww1 = ojGetImageValue(1, "width"); factor = teamWidth/ww1; close("UserTable"); selectImage("Team.tif"); prName = ojGetProjectName(); for(slc = 1; slc <= nSlices; slc++){//find matching slice setSlice(slc); name = getMetadata("label"); name = replace(name, "\n", "_"); if(prName.endsWith("_" + name)){ for(obj = 1; obj <= ojNObjects(); obj++){ ojSelectObject(obj); x = ojXPos(1); y = ojYPos(1); code = ojResult("Code", obj); makeOval((x-Zvalue/2) * factor, (y-Zvalue/2) * factor, Zvalue * factor, Zvalue * factor); changeValues(0, 255, code); } run("Select None"); ojSelectObject(0); ojSetUnchanged(); return; } } showStatus("!" + prName); }