/* Original method by Volker Backer via https://www.reddit.com/r/ImageJ/comments/qleu36/reordering_particlesrois/ v260420 1st ASC mod (just adds user input via dialog). v260421 Renames original Results table if called results to avoid add to original when re-Measuring. Adds prefs. Adds diagnotics option. */ macroL = "Sort_ROIs_by_Grid_v260421.ijm"; if (isOpen("ROI Manager")) nROIs = RoiManager.size(); else { nROIs = 0; run("ROI Manager..."); } columnsN = round(sqrt(nROIs)); rowsN = nROIs / columnsN; tableN = Table.size(); if (tableN != nROIs) exit("Mismatch between number of Results \(" + tableN + "\), and the number of ROIs \(" + nROIs + "\)"); tableName = Table.title; columnNames = newArray("A1", "B1", "C1", "D1", "E1", "F1", "G1", "H1", "I1", "J1", "K1", "L1", "M1", "N1", "O1", "P1", "Q1", "R1", "S1", "T1", "U1", "V1", "W1", "X1", "Y1", "Z1", "A2", "B2", "C2", "D2", "E2", "F2", "G2", "H2", "I2", "J2", "K2", "L2", "M2", "N2", "O2", "P2", "Q2", "R2", "S2", "T2", "U2", "V2", "W2", "X2", "Y2", "Z2"); rowNames = columnNames; if (tableN != nROIs) exit(tableN + " Results vs " + nROIs + " ROIs mismatch"); else if (tableN < 2) exit("No results to sort to"); Dialog.create(macroL); Dialog.addMessage("This macro assumes that the " + nROIs + "objects are in a rectangular array,\nso only the row count is needed", 12, "#798541"); Dialog.addNumber("Number of rows", rowsN, 0, 3, ""); Dialog.addCheckbox("Measure ROIs and create new Results Table \(old Results will be in incorrect order\) ", call("ij.Prefs.get", "asc.sortROIGrid.reMeasure", true)); Dialog.addCheckbox("Close original " + tableName + " table", call("ij.Prefs.get", "asc.sortROIGrid.closeUnsorted", true)); Dialog.addCheckbox("Diagnostics", false); Dialog.show(); rowsN = Dialog.getNumber(); columnsN = nROIs / rowsN; if (nROIs != rowsN * round(columnsN) || nROIs != rowsN * Math.ceil(columnsN)) exit("Either this is not a rectangular grid or the row count \(" + rowsN + "\) is incorrect "); reMeasure = Dialog.getCheckbox(); closeUnsorted = Dialog.getCheckbox(); diagnostics = Dialog.getCheckbox(); call("ij.Prefs.set", "asc.sortROIGrid.reMeasure", reMeasure); call("ij.Prefs.set", "asc.sortROIGrid.reMeasure", closeUnsorted); if (maxOf(rowsN, columnsN) > 52) exit(maxOf(rowsN, columnsN) + " exceeds the maximum number of columns or rows, this can easily \(if tediously\) be extended if there is a need"); // run("Set Measurements...", "area mean standard min centroid center bounding integrated limit display redirect=None decimal=3"); for (row = 0; row < rowsN; row++) { xCoords = newArray(); for (column = 0; column < columnsN; column++) { roiManager("select", columnsN * row + column); getSelectionBounds(x, y, width, height); xCoords = Array.concat(xCoords, x); } rankPositions = Array.rankPositions(Array.rankPositions(xCoords)); if (diagnostics){ IJ.log("Row " + row + " xCoords:"); Array.print(xCoords); IJ.log("Row " + row + " rankPositions:"); Array.print(rankPositions); } for (column = 0; column < columnsN; column++) { roiManager("select", columnsN * row + column); roiManager("rename", rowNames[row] + "-" + columnNames[rankPositions[column]]); } } roiManager("Deselect"); roiManager("Sort"); for (i = 0; i < roiManager("count"); i++) { roiManager("select", i); roiManager("Rename", IJ.pad(i + 1, 4)); } if (closeUnsorted){ selectWindow(tableName); run("Close"); } roiManager("Show None"); roiManager("Show All"); /* Re-"Measure" the ROIs in the ROI manager */ if (reMeasure){ if (!closeUnsorted && tableName == "Results") Table.rename("Results", "Unsorted_Results"); roiManager("Measure"); rename(tableName + "_resortedROIs"); }