//qFunctions function montageMaker(dir) { // get name of original image and use a modified form for save at the end win = getTitle(); // check how many slices/channels Stack.getDimensions(width, height, channels, slices, frames); getPixelSize(unit, pixelWidth, pixelHeight); run("Stack to Images"); numImages = nImages; imgArray = newArray(numImages); colArray = newArray(numImages); mArray = newArray(numImages + 1); mArray[0] = "*None*"; grayChoiceArray = newArray(numImages); for (i=0; i theWidth) vChoice = true; len = imgArray.length; // Standard sizes grout = 16; res = 300; sblen = 10; mag = 0.069; // estimate grout if(vChoice) { estgrout = groutEstimator(theHeight,theWidth); } else { estgrout = groutEstimator(theWidth,theHeight); } if (estgrout > 0) grout = estgrout * 2; // Make dialog box Dialog.create("Compile the montages"); // variations based on number of files if (vChoice == true) { Dialog.addMessage("Detected columns.\rSelect order for your compilation, left to right"); } else { Dialog.addMessage("Detected rows.\rSelect order for your compilation, top to bottom"); } for (i = 0; i < len; i ++) { labStr = d2s(i+1,0); Dialog.addChoice(labStr, rowArray); } Dialog.addNumber("Row gap (px, default = 2 x grout):", grout); Dialog.addNumber("dpi", res); Dialog.addCheckbox("Include scale bar?", false); Dialog.addNumber("Scale bar size (µm):", sblen); Dialog.addNumber("Scaling, 1 px is how many µm?", mag); Dialog.addCheckbox("Force other orientation:", false); Dialog.show(); // variations based on number of files for (i = 0; i < len; i ++) { nameArray[i] = Dialog.getChoice(); } grout = Dialog.getNumber(); res = Dialog.getNumber(); sbchoice = Dialog.getCheckbox(); sblen = Dialog.getNumber(); mag = Dialog.getNumber(); forceChoice = Dialog.getCheckbox(); // forceChoice reverses the logic of vChoice if(vChoice == true && forceChoice == true) vChoice = false; else if(vChoice == false && forceChoice == true) vChoice = true; // decisions collected setBatchMode(true); // setup for save win = getTitle(); dir1 = getDirectory("image"); newName = "cmp" + len + win; // get dimensions wArray = newArray(len); hArray = newArray(len); hPosArray = newArray(len+1); hPosArray[0] = 0; width = 0; height = 0; for (i=0; i 1 && ff > 1) exit ("Reduce dimensions before making montage"); if (cc > 1 && ss * ff == 1) checker = true; // if cc is 1 or more AND either ss or ff is > 1; checker stays false } else if (bitDepth() == 24) { // it is possible to have an RGB hyperstack, so the only acceptable // form for a montage is a single RGB image if (cc * ss * ff == 1) { run("Split Channels"); run("Images to Stack"); checker = true; } } else exit ("Input image does not meet requirements for montage"); return checker; } function getListOfImages() { numImages = nImages; winArray = newArray(numImages); for (i = 0; i < numImages; i ++) { selectImage(i + 1); winArray[i] = getTitle(); // ensure grayscale while we are here run("Grays"); } return winArray; } function convertChoicesToWindows(choiceArray,winArray) { convertedArray = newArray(choiceArray.length); for (i = 0; i < choiceArray.length; i ++) { arrayItem = choiceArray[i]; if (choiceArray[i] == "*None*") { convertedArray[i] = "*None*"; } else { lookupInteger = parseInt(replace(arrayItem,"C","")); convertedArray[i] = winArray[lookupInteger - 1]; } } return convertedArray; } function generateMontage(newName, vChoice, gVar, mVar, width, height, grout, res, sbchoice, sblen, mag, gNameArray, m1NameArray, m2NameArray) { len = gVar + mVar; newImage(newName, "RGB", ((width * len) + (grout * (len - 1))), height, 1); // paste in grayscales for (j = 0; j < gVar; j++) { wName = gNameArray[j]; selectImage(wName); run("Copy"); selectImage(newName); makeRectangle((width * j) + (grout * j), 0, width, height); run("Paste"); } // build mergeString(s) merge1String = ""; merge2String = ""; for (i = 0; i < 7; i++) { if (mVar > 0) merge1String += "c" + d2s(i+1,0) + "=[" + m1NameArray[i] + "] "; if (mVar == 2) merge2String += "c" + d2s(i+1,0) + "=[" + m2NameArray[i] + "] "; } merge1String += "keep"; merge2String += "keep"; // make array to hold merge names mImgArray = newArray("merge1","merge2"); // paste in the merge(s) for (i = 0; i < mVar; i++) { if (i == 0) { run("Merge Channels...", merge1String); rename("merge1"); } else { run("Merge Channels...", merge2String); rename("merge2"); } selectImage(mImgArray[i]); run("Copy"); selectImage(newName); makeRectangle(((width * gVar) + (grout * gVar)) + ((width * i) + (grout * i)), 0, width, height); run("Paste"); } selectImage(newName); // rotate right? if (vChoice == true) run("Rotate 90 Degrees Right"); // add scale bar (height of bar is same as grout)? if (sbchoice==true) { getDimensions(w, h, c, slices, frames); setColor(255,255,255); fillRect(w - (grout + (sblen / mag)), h - (2 * grout), sblen / mag, grout); } // specify dpi default is 300 dpi run("Set Scale...", "distance=" + res + " known=1 unit=inch"); run("Select None"); } function groutEstimator(ww,hh) { // we assume that montage is 1 panel high (hh) and that panel is square (ww == hh) // if is a vertical montage, width and height are swapped before as parameters // grout is unlikely to be more than half a panel width estNPanel = floor(ww / hh); estW = hh; totalGrout = ww - (estW * estNPanel); grout = totalGrout / (estNPanel - 1); if(estNPanel <= 1) return 0; return grout; } // -------------------------------------------------------------------------------- // Change Montage Merge Functions // -------------------------------------------------------------------------------- function autoChangeMontage(lutstring) { // assumes merge is on the right/bottom and therefore not inverted lutarray = makeLutArray(lutstring); custarray = makeCustArray(lutstring); lutdir = getDirectory("luts"); title = getTitle(); dir1 = getDirectory("image"); newName = "RGB2" + lutstring + "_" + title; run("Select None"); getDimensions(w, h, c, numSlices, nFrames); // deal with multiple frames or slices nShots = maxOf(numSlices,nFrames); if (numSlices > 1 && nFrames > 1) exit("Number of slices and frames is greater than one"); if (numSlices == 1) sliceOrFrame = 0; if (numSlices > 1) sliceOrFrame = 1; if (nFrames > 1) sliceOrFrame = 2; // work out grout size if (w == h) { nCol = 1; nRow = 1; grout = 0; nPanel = 1; vChoice = ""; ww = w; hh = h; } else if (w > h) { nCol = floor(w/h); nRow = 1; grout = (w - (nCol * h)) / (nCol - 1); nPanel = nCol; vChoice = ""; ww = h; hh = h; } else { nCol = 1; nRow = floor(h/w); grout = (h - (nRow * w)) / (nRow - 1); nPanel = nRow; vChoice = "vert"; ww = w; hh = w; } // collect decisions panelDecisions = newArray(nPanel); for (i=0; i