documents:110822jsip_cooking:javascript_imagej_cookbook
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revisionLast revisionBoth sides next revision | ||
documents:110822jsip_cooking:javascript_imagej_cookbook [2012/08/29 18:47] – [Writing Values in the Results Table] kota | documents:110822jsip_cooking:javascript_imagej_cookbook [2017/06/07 03:15] – kota | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== Javascript (+ ImageJ) Cookbook ====== | ||
+ | |||
+ | For scripting with ImageJ and Fiji using Javascript, an concise introduction is available at the [[http:// | ||
+ | |||
+ | If you need more examples, Jython examples are recommended. Their usage of ImageJ Java classes provides many hints. | ||
+ | |||
+ | * [[http:// | ||
+ | * [[http:// | ||
+ | |||
+ | ===== Data I/O ===== | ||
+ | |||
+ | ==== Getting Directory Path Interactively ==== | ||
+ | |||
+ | <code javascript> | ||
+ | dc = DirectoryChooser(" | ||
+ | dir = dc.getDirectory(); | ||
+ | IJ.log(dir); | ||
+ | </ | ||
+ | |||
+ | ==== Getting File Path Interactively ==== | ||
+ | |||
+ | <code js> | ||
+ | importClass(Packages.ij.io.OpenDialog); | ||
+ | |||
+ | od = new OpenDialog(" | ||
+ | directory = od.getDirectory(); | ||
+ | name = od.getFileName(); | ||
+ | path = directory + name; | ||
+ | IJ.log(path); | ||
+ | </ | ||
+ | |||
+ | ==== Path String Management ==== | ||
+ | <code javascript> | ||
+ | // Example code for managing path strings. | ||
+ | // Kota Miura (miura@embl.de) | ||
+ | // ... assumes Unix style path | ||
+ | // ... assumes that the script is executed from command line. | ||
+ | // ... argment should be in the form <a path>:< | ||
+ | |||
+ | args = getArgument(); | ||
+ | importClass(Packages.ij.util.Tools); | ||
+ | argA = Tools.split(args, | ||
+ | IJ.log(argA[0]); | ||
+ | IJ.log(argA[1]); | ||
+ | |||
+ | fpA = Tools.split(argA[0], | ||
+ | path = "/"; | ||
+ | for (i in fpA){ | ||
+ | if (i != (fpA.length - 1)) | ||
+ | path = path + fpA[i] + "/"; | ||
+ | else | ||
+ | file = fpA[i]; | ||
+ | } | ||
+ | traindata =argA[1]; | ||
+ | IJ.log(path); | ||
+ | IJ.log(file); | ||
+ | IJ.log(traindata); | ||
+ | |||
+ | </ | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | ==== Loading CSV file (data table) ==== | ||
+ | |||
+ | Note that line 21 uses java.lang.String class explicitly, for using endsWith() method in the line 22. Otherwise the string variable " | ||
+ | |||
+ | <code javascript> | ||
+ | // Example javascript for loading data from a series of CSV files in a folder. | ||
+ | // | ||
+ | // Assumes that these files are data output from other processing, | ||
+ | // and all data has same format. | ||
+ | // This script uses openCSV, which is included in Fiji. | ||
+ | // for more details on openCSV, visit the URLbelow. | ||
+ | // http:// | ||
+ | // 20110822 Kota Miura (miura@embl.de) | ||
+ | |||
+ | importPackage(Packages.util.opencsv); | ||
+ | importPackage(java.io); | ||
+ | |||
+ | //path = "/ | ||
+ | path = " | ||
+ | |||
+ | dir = new File(path); | ||
+ | filesA = dir.list(); | ||
+ | sp = File.separator; | ||
+ | |||
+ | for (var i=0; i< | ||
+ | filepath = java.lang.String(dir + sp + filesA[i]); | ||
+ | if (filepath.endsWith(" | ||
+ | IJ.log(filepath); | ||
+ | readCSV(filepath); | ||
+ | } else { | ||
+ | IJ.log(" | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // reads out 5th column in the CSV file | ||
+ | // using readALL method | ||
+ | function readCSV(filepath) { | ||
+ | var reader = new CSVReader(new FileReader(filepath), | ||
+ | var ls = reader.readAll(); | ||
+ | var it = ls.iterator(); | ||
+ | while (it.hasNext()){ | ||
+ | var carray = it.next(); | ||
+ | IJ.log(carray[4]); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // reads out 5th column in the CSV file | ||
+ | // using readNext method, output is similar to readAll | ||
+ | function readCSVbyLine(filepath) { | ||
+ | var reader = new CSVReader(new FileReader(filepath), | ||
+ | while ((nextLine = reader.readNext()) != null) { | ||
+ | // nextLine[] is an array of values from the line | ||
+ | IJ.log(nextLine[4]); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | ==== Saving CSV file (data table) ==== | ||
+ | |||
+ | This example is in Jython (Python style Java scripting). | ||
+ | <code python> | ||
+ | from util.opencsv import CSVWriter | ||
+ | from java.io import FileWriter | ||
+ | from java.lang.reflect import Array | ||
+ | from java.lang import String, Class | ||
+ | |||
+ | writer = CSVWriter(FileWriter(" | ||
+ | data = Array.newInstance(Class.forName(" | ||
+ | #String[] entries = " | ||
+ | data[0] = str(11) | ||
+ | data[1] = str(23) | ||
+ | data[2] = str(5555) | ||
+ | writer.writeNext(data) | ||
+ | writer.close() | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ===== Bitwise AND ===== | ||
+ | |||
+ | Bitwise AND is often used as switching ON/OFF multiple options. For Example: | ||
+ | |||
+ | <code javascript> | ||
+ | DISPLAY_SUMMARY = 256; | ||
+ | SHOW_ROI_MASKS = 4096; | ||
+ | options = SHOW_ROI_MASKS + DISPLAY_SUMMARY; | ||
+ | if ((options& | ||
+ | IJ.log(" | ||
+ | </ | ||
+ | |||
+ | Switching ON/OFF is controlled using 16bit binary a.k.a 16 digit binary number. 256 is | ||
+ | < | ||
+ | 0000000100000000 | ||
+ | </ | ||
+ | 9th digit from the right is " | ||
+ | 4096 is | ||
+ | < | ||
+ | 0001000000000000 | ||
+ | </ | ||
+ | 13th digit controls the ON/OFF of SHOW_ROI_MASKS. | ||
+ | If you need to turn these options on, | ||
+ | < | ||
+ | 0001000100000000 | ||
+ | </ | ||
+ | both 9th and 13th digits should be 1. To construct this binary number, it simply is: | ||
+ | < | ||
+ | 256 + 4096 = 4352 | ||
+ | bin(4352) = 0001000100000000 | ||
+ | </ | ||
+ | To check if " | ||
+ | < | ||
+ | (0001000100000000) | ||
+ | AND | ||
+ | (0001000000000000) | ||
+ | |||
+ | result: 0001000000000000 | ||
+ | </ | ||
+ | meaning that | ||
+ | <code javascript> | ||
+ | ((options& | ||
+ | </ | ||
+ | is true. | ||
+ | |||
+ | Above is a short example made for showing how to control ParticleAnalyzer options. | ||
+ | |||
+ | ===== Arguments of Function could be with Variable Length ===== | ||
+ | |||
+ | Javascript Function is a class that takes variable length of arguments. Even if there is no arguments declared in the function, one could add ones in runtime and could be retrieved from inside the function using Functions object ' | ||
+ | |||
+ | <code javascript> | ||
+ | // normal way of writing function | ||
+ | function add01(a, b) { | ||
+ | return a+b; | ||
+ | } | ||
+ | |||
+ | //using ' | ||
+ | function add02(a, b) { | ||
+ | return arguments[0] + arguments[1]; | ||
+ | } | ||
+ | |||
+ | IJ.log(add01(1, | ||
+ | IJ.log(add02(1, | ||
+ | |||
+ | IJ.log(" | ||
+ | |||
+ | // a bit more with arguments | ||
+ | // to show that ' | ||
+ | function sum() { | ||
+ | var result = 0; | ||
+ | for (var i = 0, n = arguments.length; | ||
+ | result += arguments[i]; | ||
+ | } | ||
+ | return result; | ||
+ | } | ||
+ | |||
+ | IJ.log(sum(1, | ||
+ | IJ.log(sum(1, | ||
+ | </ | ||
+ | ===== Writing Values in the Results Table ===== | ||
+ | |||
+ | <code javascript> | ||
+ | rt = ResultsTable(); | ||
+ | for (var i = 0; i < 10; i++){ | ||
+ | rt.incrementCounter(); | ||
+ | rownum = rt.getCounter()-1; | ||
+ | rt.setValue(" | ||
+ | } | ||
+ | rt.show(" | ||
+ | </ | ||
+ | |||
+ | ===== Aborting the script ===== | ||
+ | |||
+ | To abort the running script, use the following function. | ||
+ | I got this from [[http:// | ||
+ | <code javascript> | ||
+ | function javascript_abort(){ | ||
+ | throw new Error(' | ||
+ | }</ | ||
+ | ===== Arrays ===== | ||
+ | |||
+ | ==== Converting Java array to javascript array ==== | ||
+ | |||
+ | Keep in mind that java array and Javascript array are different types. | ||
+ | |||
+ | For some array treatments, this matters a lot and keeping your arrays either Java array or Javascript array is pretty important. Below is an example of Java > javascript array conversion and also how to check the object type. For constructing Java array in javascript, [[http:// | ||
+ | |||
+ | <code javascript> | ||
+ | //as an example, you first get an array from | ||
+ | //Results table in ImageJ. | ||
+ | // this array is Java array. | ||
+ | |||
+ | rt = ResultsTable.getResultsTable(); | ||
+ | sliceA = rt.getColumn(rt.getColumnIndex(" | ||
+ | |||
+ | // | ||
+ | |||
+ | sliceJSA = []; | ||
+ | for (var i =0; i < sliceA.length; | ||
+ | sliceJSA.push(sliceA[i]); | ||
+ | |||
+ | //check object types | ||
+ | IJ.log(" | ||
+ | IJ.log(" | ||
+ | </ | ||
+ | ==== Sorting Numerical Array ==== | ||
+ | <code javascript> | ||
+ | //prepare some data | ||
+ | data = [10.0, 100.0, -1.0, 9.0, 200.0, 1.0]; | ||
+ | |||
+ | data.sort(); | ||
+ | |||
+ | IJ.log(data.valueOf()); | ||
+ | |||
+ | // Comparator should be created. | ||
+ | //here we go again | ||
+ | |||
+ | data = [10.0, 100.0, -1.0, 9.0, 200.0, 1.0]; | ||
+ | |||
+ | // create a comparator | ||
+ | function comp(a, b){ | ||
+ | return (a - b); | ||
+ | } | ||
+ | |||
+ | data.sort(comp); | ||
+ | |||
+ | IJ.log(data.valueOf()); | ||
+ | |||
+ | </ | ||
+ | |||
+ | ==== Sorting a List of Numbered Files ==== | ||
+ | |||
+ | Consider a situation of having a list of file names in an array filesA in the follwoing order, and we want to sort the name so the numbering is in ascending order. | ||
+ | < | ||
+ | 110608wt2.tif.proc.tif.noseg.tif8_9.txt | ||
+ | 110608wt2.tif.proc.tif.noseg.tif9_10.txt | ||
+ | 110608wt2.tif.proc.tif.noseg.tif10_11.txt | ||
+ | 110608wt2.tif.proc.tif.noseg.tif0_1.txt | ||
+ | 110608wt2.tif.proc.tif.noseg.tif1_2.txt | ||
+ | 110608wt2.tif.proc.tif.noseg.tif2_3.txt | ||
+ | 110608wt2.tif.proc.tif.noseg.tif3_4.txt | ||
+ | 110608wt2.tif.proc.tif.noseg.tif4_5.txt | ||
+ | 110608wt2.tif.proc.tif.noseg.tif5_6.txt | ||
+ | 110608wt2.tif.proc.tif.noseg.tif6_7.txt | ||
+ | 110608wt2.tif.proc.tif.noseg.tif7_8.txt | ||
+ | </ | ||
+ | Such sorting could be done by combining regular expression matching. | ||
+ | |||
+ | <code javascript> | ||
+ | importPackage(java.io); | ||
+ | path = " | ||
+ | dir = new File(path); | ||
+ | filesA = dir.list(); | ||
+ | sp = File.separator; | ||
+ | |||
+ | filesA.sort(comparator); | ||
+ | |||
+ | for (var i=0; i< | ||
+ | filepath = java.lang.String(dir + sp + filesA[i]); | ||
+ | if (filepath.endsWith(" | ||
+ | IJ.log(filesA[i]); | ||
+ | else | ||
+ | IJ.log(" | ||
+ | } | ||
+ | |||
+ | function comparator(stra, | ||
+ | // regular expression to extract numberings | ||
+ | var patt1 = / | ||
+ | regexa = stra.match(patt1); | ||
+ | regexb = strb.match(patt1); | ||
+ | return (regexa[1] - regexb[1]) | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Above code will then prints out: | ||
+ | < | ||
+ | 110608wt2.tif.proc.tif.noseg.tif0_1.txt | ||
+ | 110608wt2.tif.proc.tif.noseg.tif1_2.txt | ||
+ | 110608wt2.tif.proc.tif.noseg.tif2_3.txt | ||
+ | 110608wt2.tif.proc.tif.noseg.tif3_4.txt | ||
+ | 110608wt2.tif.proc.tif.noseg.tif4_5.txt | ||
+ | 110608wt2.tif.proc.tif.noseg.tif5_6.txt | ||
+ | 110608wt2.tif.proc.tif.noseg.tif6_7.txt | ||
+ | 110608wt2.tif.proc.tif.noseg.tif7_8.txt | ||
+ | 110608wt2.tif.proc.tif.noseg.tif8_9.txt | ||
+ | 110608wt2.tif.proc.tif.noseg.tif9_10.txt | ||
+ | 110608wt2.tif.proc.tif.noseg.tif10_11.txt | ||
+ | </ | ||
+ | |||
+ | To study more about Javascript regular expression, [[http:// | ||
+ | |||
+ | ==== Getting the Minimum and the Maximum value of Javascript array ==== | ||
+ | |||
+ | I thought of Math.max(array.valueOf()) seemingly should work, but it doesn' | ||
+ | <code javascript> | ||
+ | var testa = Array(); | ||
+ | |||
+ | testa[0] = 10.3; | ||
+ | testa[1] = 20.1; | ||
+ | testa[2] = 100.9; | ||
+ | testa[3] = 5.1; | ||
+ | |||
+ | minval = Math.min.apply(Math, | ||
+ | maxval = Math.max.apply(Math, | ||
+ | IJ.log(" | ||
+ | IJ.log(" | ||
+ | </ | ||
+ | |||
+ | This is because Math.min and Math.max methods only takes individual numbers, not an array. To unpack an array, apply() method of class Function is used. An example below depicts its usage. | ||
+ | |||
+ | <code javascript> | ||
+ | var sum = function(){ | ||
+ | var result = 0; | ||
+ | for (var i = 0, n = arguments.length; | ||
+ | result += arguments[i]; | ||
+ | } | ||
+ | return result; | ||
+ | }; | ||
+ | |||
+ | data01 = [1, 2, 3]; | ||
+ | data02 = [1, 2, 3, 4, 5, 6]; | ||
+ | |||
+ | ans = sum.apply(sum, | ||
+ | IJ.log(ans); | ||
+ | |||
+ | ans = sum.apply(sum, | ||
+ | IJ.log(ans); | ||
+ | </ | ||
+ | |||
+ | ... I mean if you want to sum up, you don't really have to be bulky but method apply() has so many flexibility in applying methods to any objects. | ||
+ | |||
+ | ==== Apply function to Each Element of Array ==== | ||
+ | |||
+ | Use Array.forEach(function) method. | ||
+ | |||
+ | <code javascript> | ||
+ | data = [10.0, 100.0, -1.0, 9.0, 200.0, 1.0]; | ||
+ | |||
+ | data.forEach(printArray); | ||
+ | IJ.log(" | ||
+ | data.forEach(squaredArray); | ||
+ | |||
+ | function printArray(x, | ||
+ | | ||
+ | } | ||
+ | |||
+ | function squaredArray(x, | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | < | ||
+ | [0] = 10 | ||
+ | [1] = 100 | ||
+ | [2] = -1 | ||
+ | [3] = 9 | ||
+ | [4] = 200 | ||
+ | [5] = 1 | ||
+ | --- | ||
+ | [0] = 100 | ||
+ | [1] = 10000 | ||
+ | [2] = 1 | ||
+ | [3] = 81 | ||
+ | [4] = 40000 | ||
+ | [5] = 1 | ||
+ | </ | ||
+ | |||
+ | Source array is not affected in this case. If you want to modify the array itself, use Array.map(function) examples in the following. | ||
+ | See more examples at [[http:// | ||
+ | |||
+ | ==== Object Oriented processing of Arrays using Array.map()==== | ||
+ | |||
+ | map() function is convenient if you want to have an output array after processing each element. | ||
+ | |||
+ | <code javascript> | ||
+ | // this will be an example array | ||
+ | xA = [5, 25, 75, 100]; | ||
+ | |||
+ | // create an object with a field ' | ||
+ | var obj = { | ||
+ | factor: 2, | ||
+ | multiply: function (x){ | ||
+ | return x * this.factor; | ||
+ | } | ||
+ | } | ||
+ | // ... factor 2 will then be the default value. | ||
+ | |||
+ | //use Array.map(function, | ||
+ | |||
+ | array = xA.map(obj.multiply, | ||
+ | IJ.log(array.join()); | ||
+ | |||
+ | //replace the factor. | ||
+ | obj.factor = 4; | ||
+ | |||
+ | array = xA.map(obj.multiply, | ||
+ | IJ.log(array.join()); | ||
+ | |||
+ | </ | ||
+ | |||
+ | ==== Slicing Multidimensional Array ==== | ||
+ | |||
+ | Here are examples of horizontal and vertical slicing of a 2D array. | ||
+ | Vertical slicing is a bit complex, but I could not figure out other ways. | ||
+ | If you know one, please tell me. What supposed to be something like v1 = allA[:, 1] in Python would be much easier. | ||
+ | |||
+ | <code javascript> | ||
+ | // | ||
+ | |||
+ | print = IJ.log; | ||
+ | |||
+ | xA = [1, 2, 3]; | ||
+ | yA = [40, 50, 60]; | ||
+ | zA = [-1, -2, -3]; | ||
+ | allA = [xA, yA, zA]; //this is a multidimensional array | ||
+ | |||
+ | print(allA[1][2]); | ||
+ | print(allA[1]); | ||
+ | |||
+ | v1 = allA.map(function (v){return v[1]; | ||
+ | print(v1); | ||
+ | print(v1[2]); | ||
+ | |||
+ | //--- here is another way of vartical slicing, | ||
+ | // longer but more clear with what's happening. | ||
+ | |||
+ | var obj = {sliceindex: | ||
+ | v1 = allA.map(returnVert, | ||
+ | //with context of object ' | ||
+ | //prints three lines of 'slice index: | ||
+ | print(v1); | ||
+ | |||
+ | |||
+ | |||
+ | // v: one dimensional array passed from map function | ||
+ | // id: index of the one dimensional array passed, within | ||
+ | // the multidimensional array | ||
+ | // a: parent array (= itself, in our case allA) | ||
+ | function returnVert(v, | ||
+ | print(" | ||
+ | return a[id][this.sliceindex]; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== Matrix Transpose ==== | ||
+ | |||
+ | An application of vertical slicing, matrix transposition. | ||
+ | <code javascript> | ||
+ | // | ||
+ | |||
+ | function transp(incoords){ | ||
+ | var transposed = [] | ||
+ | // for(var i = 0; i < incoords[0].length; | ||
+ | for(var i in incoords[0]){ | ||
+ | transposed.push(incoords.map(function(v){return v[i];})); | ||
+ | } | ||
+ | return transposed; | ||
+ | } | ||
+ | |||
+ | data = [ [0, 1, 2], | ||
+ | [3, 4, 5], | ||
+ | [6, 7, 8]]; | ||
+ | |||
+ | var tdata = transp(data); | ||
+ | |||
+ | for (i in data) IJ.log(data[i]); | ||
+ | /* prints | ||
+ | 0,1,2 | ||
+ | 3,4,5 | ||
+ | 6,7,8 | ||
+ | */ | ||
+ | for (i in tdata) IJ.log(tdata[i]); | ||
+ | /* prints | ||
+ | 0,3,6 | ||
+ | 1,4,7 | ||
+ | 2,5,8 | ||
+ | */ | ||
+ | </ | ||
+ | |||
+ | ===== Windows ===== | ||
+ | |||
+ | ==== Duplicating current Results table with different title ==== | ||
+ | |||
+ | <code js> | ||
+ | ResultsTable.getResultsTable().clone().show(" | ||
+ | </ | ||
+ | |||
+ | ==== Activating / Deactivating BatchMode ==== | ||
+ | |||
+ | To suppress creation of image windows, you could activate BatchMode. Corresponding function in ImageJ is setBatchMode(true) and setBatchMode(false). | ||
+ | |||
+ | <code javascript> | ||
+ | importClass(Packages.ij.macro.Interpreter); | ||
+ | macro = new Interpreter(); | ||
+ | |||
+ | // activate batchmode (= setBatchMode(true) in IJ macro) | ||
+ | macro.batchMode = true; | ||
+ | |||
+ | //when error occurrs and execution is terminated during batchmode=true, | ||
+ | //you might not see any images anymore (even if you try to open a new one manually). | ||
+ | // To avoid, do something like below to catch error and deactivate the batchmode. | ||
+ | try { | ||
+ | IJ.run(imp, | ||
+ | catch(err){ | ||
+ | macro.batchMode = false; | ||
+ | IJ.log(" | ||
+ | IJ.log(err.rhinoException.toString()); | ||
+ | IJ.log(err.javaException.toString()); | ||
+ | } | ||
+ | |||
+ | // | ||
+ | macro.batchMode = false; | ||
+ | </ | ||
+ | |||
+ | |||
+ | ==== Closing All Image Windows ==== | ||
+ | |||
+ | <code javascript> | ||
+ | function imagewinKiller(){ | ||
+ | var wins = WindowManager.getIDList(); | ||
+ | for (var i = 0; i < wins.length; | ||
+ | WindowManager.getImage(wins[i]).close(); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== Adding Mouse Listener to an Image ==== | ||
+ | |||
+ | <code javascript> | ||
+ | // example of implementing and extending java interface | ||
+ | |||
+ | importPackage(java.awt.event); | ||
+ | |||
+ | // extends MouseAdapter, | ||
+ | var mouseListener = new JavaAdapter(MouseAdapter, | ||
+ | mouseClicked: | ||
+ | IJ.log(" | ||
+ | }, | ||
+ | mouseDragged: | ||
+ | IJ.log(" | ||
+ | }, | ||
+ | mouseMoved: function(event) { | ||
+ | } | ||
+ | }); | ||
+ | |||
+ | imp = IJ.getImage(); | ||
+ | var win = imp.getWindow(); | ||
+ | |||
+ | win.getCanvas().addMouseListener(mouseListener); | ||
+ | win.getCanvas().addMouseMotionListener(mouseListener); | ||
+ | |||
+ | </ | ||
+ | |||
+ | As of 20131120, above code works with " | ||
+ | |||
+ | <code javascript> | ||
+ | var mouseListener = new JavaAdapter(MouseListener, | ||
+ | mouseClicked: | ||
+ | IJ.log(" | ||
+ | }, | ||
+ | mouseDragged: | ||
+ | IJ.log(" | ||
+ | }, | ||
+ | mouseMoved: function(event) { | ||
+ | } | ||
+ | }); | ||
+ | </ | ||
+ | |||
+ | ==== Adding Overlays to an Image ==== | ||
+ | |||
+ | An example of overlay function in ImageJ / Fiji.\\ | ||
+ | For drawing Arrows, use commented out lines. | ||
+ | |||
+ | <code javascript> | ||
+ | overlayLine(10, | ||
+ | overlayLine(40, | ||
+ | |||
+ | function overlayLine(x1, | ||
+ | importClass(Packages.ij.gui.Overlay); | ||
+ | importClass(Packages.java.awt.Color); | ||
+ | imp = IJ.getImage(); | ||
+ | //roi1 = Arrow( 110, 245, 111, 246); | ||
+ | roi1 = Line(x1, y1, x2, y2); | ||
+ | // | ||
+ | // | ||
+ | imp.setRoi(roi1); | ||
+ | overlay = imp.getOverlay(); | ||
+ | if (overlay != null) | ||
+ | overlay.add(roi1); | ||
+ | else | ||
+ | overlay = Overlay(roi1); | ||
+ | red = Color(1, 0, 0); | ||
+ | overlay.setStrokeColor(red); | ||
+ | imp.setOverlay(overlay); | ||
+ | imp.updateAndDraw() ; | ||
+ | |||
+ | // | ||
+ | // | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===== Image Processing ===== | ||
+ | |||
+ | ==== Creating a Partial Stack of an Original Stack with shared ImageProcessor objects ==== | ||
+ | |||
+ | <code javascript> | ||
+ | function alias2frames(imp, | ||
+ | var stack = imp.getStack(); | ||
+ | var tempstk = new ImageStack(imp.getWidth(), | ||
+ | tempstk.addSlice(String(i), | ||
+ | tempstk.addSlice(String(i+1), | ||
+ | var imp2 = new ImagePlus(" | ||
+ | return imp2 | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== Background Subtraction by ImageMath ==== | ||
+ | |||
+ | <code javascript> | ||
+ | //Example Javascript for Background substraction using ImageMath | ||
+ | // Kota Miura (miura@embl.de) | ||
+ | |||
+ | //get ImagePlus of the active window | ||
+ | imp = IJ.getImage(); | ||
+ | |||
+ | //duplicate and blurr images | ||
+ | blurrimp = imp.duplicate(); | ||
+ | IJ.run(blurrimp, | ||
+ | |||
+ | //subtract the blurred from the original | ||
+ | ic = new ImageCalculator(); | ||
+ | for (var i=1; i< | ||
+ | imp.setSlice(i); | ||
+ | blurrimp.setSlice(i); | ||
+ | ic.run(" | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | ==== Batch Trainable Segmentation using Trained Data ==== | ||
+ | |||
+ | <code javascript> | ||
+ | // Example script for using trainable segmentation | ||
+ | // -- assumes that an extra plugin by Kota is installed | ||
+ | // -- assumes that you already have " | ||
+ | // 20110819 | ||
+ | // Kota Miura (miura@embl.de) | ||
+ | |||
+ | // get currently active image / image stack | ||
+ | imp = IJ.getImage(); | ||
+ | |||
+ | //path to the arff data | ||
+ | traindata = " | ||
+ | |||
+ | importClass(Packages.emblcmci.DotSegmentByTrained); | ||
+ | dbt = new DotSegmentByTrained(traindata, | ||
+ | binimp = dbt.runsilent(); | ||
+ | binimp.show(); | ||
+ | </ | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | Another version without using the plugin above. | ||
+ | <code javascript> | ||
+ | importClass(Packages.trainableSegmentation.WekaSegmentation); | ||
+ | imp = IJ.getImage(); | ||
+ | ws = WekaSegmentation(imp); | ||
+ | ws.loadTrainingData(' | ||
+ | if (ws.trainClassifier()){ | ||
+ | impout = ws.getClassifiedImage(); | ||
+ | if (impout == null) | ||
+ | IJ.log(" | ||
+ | else { | ||
+ | impout.show(); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== Using 3D processor plugin ==== | ||
+ | |||
+ | 3D processing generally consumes long long time for calculation, | ||
+ | |||
+ | %gist(1663061)% | ||
+ | [gist cmci/ | ||
+ | |||
+ | ==== Transformation of 3D stack according to given landmark pairs ==== | ||
+ | |||
+ | Works in Fiji. Note the use of JavaImporter() from line 12 to 15 for avoiding conflicts in name space. | ||
+ | |||
+ | <code javascript> | ||
+ | // affinetransform3D.js | ||
+ | // Created: 201107120 by Kota Miura (CMCI, EMBL miura@embl.de) | ||
+ | // | ||
+ | // Collaborater: | ||
+ | // | ||
+ | // written according to the advice from Stephan Saalfeld@mpicbg | ||
+ | // http:// | ||
+ | // TODO try using moving least square. | ||
+ | // http:// | ||
+ | // http:// | ||
+ | importPackage(Packages.java.util); | ||
+ | var mpimodel | ||
+ | var trakmodel = new JavaImporter(); | ||
+ | var mpistack | ||
+ | var jarray | ||
+ | mpimodel.importPackage(Packages.mpicbg.models); | ||
+ | trakmodel.importPackage(Packages.mpicbg.trakem2.transform); | ||
+ | mpistack.importPackage(Packages.mpicbg.ij.stack); | ||
+ | jarray.importPackage(Packages.java.lang.reflect); | ||
+ | |||
+ | pointPairs = new ArrayList(); | ||
+ | testFillPoints(pointPairs); | ||
+ | |||
+ | //LS fitting | ||
+ | modelM = new trakmodel.AffineModel3D(); | ||
+ | modelM.fit( pointPairs ); | ||
+ | IJ.log(modelM.toDataString()); | ||
+ | |||
+ | // --- preparing target stack size, offsets --- | ||
+ | |||
+ | imp = IJ.getImage(); | ||
+ | ww = imp.getWidth(); | ||
+ | hh = imp.getHeight(); | ||
+ | dd = imp.getImageStackSize(); | ||
+ | |||
+ | // need to use java native array for estimateBounds() method. | ||
+ | minA = jarray.Array.newInstance(java.lang.Float.TYPE, | ||
+ | maxA = jarray.Array.newInstance(java.lang.Float.TYPE, | ||
+ | |||
+ | minA[0] = 0.0; | ||
+ | minA[1] = 0.0; | ||
+ | minA[2] = 0.0; | ||
+ | maxA[0] = ww; | ||
+ | maxA[1] = hh; | ||
+ | maxA[2] = dd; | ||
+ | |||
+ | IJ.log(" | ||
+ | |||
+ | destsizeA = ReCalcStackSize(modelM, | ||
+ | |||
+ | ww = destsizeA[0]; | ||
+ | hh = destsizeA[1]; | ||
+ | dd = destsizeA[2]; | ||
+ | |||
+ | for (var i in minA) IJ.log(minA[i]); | ||
+ | for (var i in maxA) IJ.log(maxA[i]); | ||
+ | |||
+ | outstr = " | ||
+ | for (var i in minA) outstr = outstr + destsizeA[i] + ","; | ||
+ | IJ.log(outstr); | ||
+ | |||
+ | ReCalcOffset(modelM, | ||
+ | IJ.log(modelM.toDataString()); | ||
+ | |||
+ | // --- stack transformation --- | ||
+ | |||
+ | mapping = mpistack.InverseTransformMapping( modelM ); | ||
+ | |||
+ | ip = imp.getStack().getProcessor( 1 ).createProcessor( 1, 1 ); | ||
+ | target = new ImageStack(ww, | ||
+ | for ( var s = 0; s < dd; ++s ) { | ||
+ | ip = ip.createProcessor( ww, hh ); | ||
+ | mapping.setSlice( s ); | ||
+ | try { | ||
+ | mapping.mapInterpolated( imp.getStack(), | ||
+ | } catch ( err ) { | ||
+ | alert(' | ||
+ | } | ||
+ | target.addSlice( "", | ||
+ | } | ||
+ | impout = ImagePlus(" | ||
+ | impout.show(); | ||
+ | |||
+ | |||
+ | function testFillPoints(pointPairs) { | ||
+ | var p11 = [1, 0, 0]; | ||
+ | var p12 = [0, 1, 0]; | ||
+ | |||
+ | var p21 = [0, 1, 0]; | ||
+ | var p22 = [0, 0, 1]; | ||
+ | |||
+ | var p31 = [0, 0, 1]; | ||
+ | var p32 = [1, 0, 0]; | ||
+ | |||
+ | var p41 = [0.5, 0, 0]; | ||
+ | var p42 = [0, 0.5, 0]; | ||
+ | |||
+ | pointPairs.add(mpimodel.PointMatch(mpimodel.Point(p11), | ||
+ | pointPairs.add(mpimodel.PointMatch(mpimodel.Point(p21), | ||
+ | pointPairs.add(mpimodel.PointMatch(mpimodel.Point(p31), | ||
+ | pointPairs.add(mpimodel.PointMatch(mpimodel.Point(p41), | ||
+ | IJ.log(pointPairs.toString()); | ||
+ | } | ||
+ | |||
+ | function ReCalcStackSize(transM, | ||
+ | transM.estimateBounds(minA, | ||
+ | var newsizeA = [0.0, 0.0, 0.0]; | ||
+ | for (var i in newsizeA) | ||
+ | newsizeA[i] = Math.ceil(maxA[i] - minA[i]); | ||
+ | return newsizeA; | ||
+ | } | ||
+ | |||
+ | function ReCalcOffset(transM, | ||
+ | var shift = new mpimodel.TranslationModel3D(); | ||
+ | var shift.set( -1*minA[0], -1*minA[1], -1*minA[2] ); | ||
+ | transM.preConcatenate(shift); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | ==== 3D tracking of spots, and plotting of the resulted spots in a new Stack ==== | ||
+ | |||
+ | <code javascript> | ||
+ | /* | ||
+ | * script for creating a stack with same size of the current stack, and plot xyz dots listed in results window.\ | ||
+ | * | ||
+ | * Kota Miura | ||
+ | */ | ||
+ | |||
+ | imp = IJ.getImage(); | ||
+ | impdimA = imp.getDimensions(); | ||
+ | |||
+ | |||
+ | pt = IJ.runPlugIn(imp, | ||
+ | pt.transferParticlesToResultsTable(); | ||
+ | |||
+ | //imp2 = imp.createImagePlus(); | ||
+ | ims = imp.createEmptyStack(); | ||
+ | for (var i = 0; i < impdimA[3]; i++) | ||
+ | ims.addSlice(i, | ||
+ | imp2 = new ImagePlus(" | ||
+ | |||
+ | nSlices = imp2.getNSlices(); | ||
+ | |||
+ | rt = ResultsTable.getResultsTable(); | ||
+ | xindex = rt.getColumnIndex(" | ||
+ | yindex = rt.getColumnIndex(" | ||
+ | zindex = rt.getColumnIndex(" | ||
+ | xA = rt.getColumn(xindex); | ||
+ | yA = rt.getColumn(yindex); | ||
+ | zA = rt.getColumn(zindex); | ||
+ | for (var i = 0; i < xA.length; i++){ | ||
+ | IJ.log(xA[i]); | ||
+ | cslice=Math.round(zA[i])+1; | ||
+ | if ((cslice > 0) && (cslice <= nSlices)) { | ||
+ | ip = imp2.getStack().getProcessor(cslice); | ||
+ | // | ||
+ | // | ||
+ | ip.set(Math.round(yA[i]), | ||
+ | |||
+ | } | ||
+ | } | ||
+ | imp2.show(); | ||
+ | </ | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | ===== Math ===== | ||
+ | |||
+ | ==== Statistics using Apache Commons Math ==== | ||
+ | |||
+ | Below is an example of calculating statistical values using Apache Commons Math library (already included in Fiji). There are many more you could do with it so explore the API. | ||
+ | <code javascript> | ||
+ | //first example, using static methods " | ||
+ | importClass(Packages.org.apache.commons.math.stat.StatUtils); | ||
+ | |||
+ | test = [1 , 3, 4, 8, 100]; | ||
+ | IJ.log(test[2]); | ||
+ | mn = StatUtils.mean(test); | ||
+ | IJ.log(mn); | ||
+ | |||
+ | //above static method is limited with number of things that could be done. | ||
+ | //use DescriptiveStatistics then (but consumes more memory) | ||
+ | importClass(Packages.org.apache.commons.math.stat.descriptive.DescriptiveStatistics); | ||
+ | |||
+ | stats = new DescriptiveStatistics(); | ||
+ | |||
+ | // Add the data from the array | ||
+ | for(i = 0; i < test.length; | ||
+ | stats.addValue(test[i]); | ||
+ | } | ||
+ | |||
+ | // Compute some statistics | ||
+ | mean = stats.getMean(); | ||
+ | std = stats.getStandardDeviation(); | ||
+ | median = stats.getPercentile(50); | ||
+ | |||
+ | IJ.log(mean); | ||
+ | IJ.log(std); | ||
+ | </ | ||
+ | |||
+ | ==== 3D vector ==== | ||
+ | |||
+ | Using 3D vector class in apache commons math. | ||
+ | <code javascript> | ||
+ | importClass(Packages.org.apache.commons.math.geometry.euclidean.threed.Vector3D); | ||
+ | |||
+ | //construct 2 vectors | ||
+ | va = new Vector3D(0.0, | ||
+ | vb = new Vector3D(2.0, | ||
+ | |||
+ | //angle between va and vb | ||
+ | ang = Vector3D.angle(va, | ||
+ | IJ.log(ang); | ||
+ | |||
+ | //add va and vb, and out puts a new vector as a result | ||
+ | vc = new Vector3D(1.0, | ||
+ | |||
+ | //prints out elements of the vector vc | ||
+ | IJ.log("" | ||
+ | |||
+ | //dot (inner) product of va abd vb | ||
+ | dp = va.dotProduct(vb); | ||
+ | IJ.log(dp); | ||
+ | |||
+ | //cross product of va abd vb | ||
+ | vd = va.crossProduct(vb); | ||
+ | IJ.log("" | ||
+ | </ | ||
+ | |||
+ | ==== Solving Quadratic Formula ==== | ||
+ | For this, I borrowed a code by Gary Jones published in | ||
+ | |||
+ | [[http:// | ||
+ | |||
+ | <code javascript> | ||
+ | //Solving quadratic formula | ||
+ | /** | ||
+ | * Rounds number to " | ||
+ | * | ||
+ | * @author Gary Jones | ||
+ | * @link http:// | ||
+ | */ | ||
+ | function chop(number, | ||
+ | { | ||
+ | var multiplier = Math.pow(10, | ||
+ | number = ( Math.round( number * multiplier ) ) / multiplier; | ||
+ | /* if ( document.layers ){ // Tidies Netscape 4.x appearance. | ||
+ | if ( number < 1 && number >= 0 ) number = " | ||
+ | if ( number < 0 && number >-1 ) number = " | ||
+ | } | ||
+ | */ return number; | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Finds two roots. | ||
+ | * | ||
+ | * For ax^2 + bx + c = 0, use quadratic(" | ||
+ | */ | ||
+ | function quadratic(aq, | ||
+ | { | ||
+ | var complex, | ||
+ | lambda, | ||
+ | lambdaone, | ||
+ | lambdatwo, | ||
+ | plusminusone, | ||
+ | plusminustwo, | ||
+ | bsmfac = bq * bq - 4 * aq * cq, | ||
+ | precision = 3; | ||
+ | if ( bsmfac < 0 ) { // Accounts for complex roots. | ||
+ | plusminusone = " + "; | ||
+ | plusminustwo = " - "; | ||
+ | bsmfac *= -1; | ||
+ | complex = Math.sqrt( bsmfac ) / ( 2 * aq ); | ||
+ | if ( aq < 0 ){ // if negative imaginary term, tidies appearance. | ||
+ | plusminusone = " - "; | ||
+ | plusminustwo = " + "; | ||
+ | complex *= -1; | ||
+ | } | ||
+ | lambdaone = chop( -bq / ( 2 * aq ), precision ) + plusminusone + chop( complex, precision ) + ' | ||
+ | lambdatwo = chop( -bq / ( 2 * aq ), precision ) + plusminustwo + chop( complex, precision ) + ' | ||
+ | } else if ( 0 == bsmfac ){ // Simplifies if b^2 = 4ac (real roots). | ||
+ | lambdaone = chop( -bq / ( 2 * aq ), precision ); | ||
+ | lambdatwo = chop( -bq / ( 2 * aq ), precision ); | ||
+ | } else { // Finds real roots when b^2 != 4ac. | ||
+ | lambdaone = (-bq + (Math.sqrt( bsmfac ))) / ( 2 * aq ); | ||
+ | lambdaone = chop( lambdaone, precision ); | ||
+ | lambdatwo = (-bq - (Math.sqrt( bsmfac ))) / ( 2 * aq ); | ||
+ | lambdatwo = chop( lambdatwo, precision ); | ||
+ | } | ||
+ | ( ' | ||
+ | return lambda; // Returns either root based on parameter " | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | ==== Gaussian fitting of Intensity Profile ==== | ||
+ | |||
+ | In the second function, profileA is an array with intensity profile, and doPlot is an boolean flag for plotting the curve fitting result. | ||
+ | |||
+ | Note Line 18 and 19, where type conversion between Java array and javascript array is done. | ||
+ | |||
+ | <code javascript> | ||
+ | // cf: class CurveFitter | ||
+ | // cfp: fitted parameter array | ||
+ | // estD: estimated diameter | ||
+ | function PlotFitted(xA, | ||
+ | var fitA = []; | ||
+ | for (i in yA) | ||
+ | fitA[i] = cf.f(cfp, i); | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | |||
+ | //returns diameter and goodness of fit in addition to the fit results parameters. | ||
+ | function GaussFitReturnPara(profileA, | ||
+ | //var pixx = []; | ||
+ | var resultsA = []; | ||
+ | var pixx = java.lang.reflect.Array.newInstance(java.lang.Double.TYPE, | ||
+ | for (var i=0; i< | ||
+ | cf = new CurveFitter(pixx, | ||
+ | cf.doFit(cf.GAUSSIAN); | ||
+ | IJ.log(cf.getResultString()); | ||
+ | cfp = cf.getParams(); | ||
+ | //diameter = 2.355*cfp[3]; | ||
+ | diameter = 4*cfp[3]; | ||
+ | EstimatedDiameter = " | ||
+ | IJ.log(" | ||
+ | IJ.log(" | ||
+ | if (doPlot) PlotFitted(pixx, | ||
+ | |||
+ | var resA = HashMap(); | ||
+ | resA.put(headerA[0], | ||
+ | resA.put(headerA[1], | ||
+ | resA.put(headerA[2], | ||
+ | resA.put(headerA[3], | ||
+ | resA.put(headerA[4], | ||
+ | resA.put(headerA[5], | ||
+ | resA.put(headerA[6], | ||
+ | return resA; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | |||
+ | ===== 3DViewer ===== | ||
+ | |||
+ | 3DViewer has many capability in plotting 3D scenes, including time series. | ||
+ | Api is available at [[http:// | ||
+ | |||
+ | ==== Checking Java3D version ==== | ||
+ | |||
+ | Version of Java3D is a critical issue for programming 3DViewer. Since upgrading Java does not in many cases means automatic upgrading of Java3D in your Java extension folder, this could be a problem during development. Here is a way to check your Java3D version. | ||
+ | |||
+ | %gist(1663134)% | ||
+ | [gist cmci/ | ||
+ | |||
+ | ==== Plotting Mesh shapes: an example with tubes ==== | ||
+ | [{{ : | ||
+ | I use tubes for plotting trajectories. Here is an example. | ||
+ | It seems that there will be newer class called [[http:// | ||
+ | |||
+ | <code javascript> | ||
+ | // test for Mesh_Maker, | ||
+ | |||
+ | importClass(Packages.java.util.Vector); | ||
+ | importPackage(Packages.ij3d); | ||
+ | importClass(Packages.customnode.CustomTriangleMesh); | ||
+ | importClass(Packages.javax.vecmath.Color3f); | ||
+ | |||
+ | col = Color3f(0, 1.0, 0.5); | ||
+ | col2 = Color3f(1.0, | ||
+ | colw = Color3f(1.0, | ||
+ | |||
+ | var xA = javaArray(1, | ||
+ | var yA = javaArray(1, | ||
+ | var zA = javaArray(1, | ||
+ | var rA = javaArray(1, | ||
+ | var tube = Mesh_Maker.createTube(xA, | ||
+ | var xA = javaArray(10, | ||
+ | var yA = javaArray(10, | ||
+ | var zA = javaArray(10, | ||
+ | var rA = javaArray(1, | ||
+ | var tube2 = Mesh_Maker.createTube(xA, | ||
+ | var tubes = Vector(); | ||
+ | tubes.addAll(tube); | ||
+ | tubes.addAll(tube2); | ||
+ | var csp = CustomTriangleMesh(tubes, | ||
+ | var ccs = ContentCreator.createContent(csp, | ||
+ | univ = new Image3DUniverse(); | ||
+ | univ.show(); | ||
+ | univ.addContent(ccs); | ||
+ | |||
+ | function javaArray(sp, | ||
+ | ja = new java.lang.reflect.Array.newInstance(java.lang.Double.TYPE, | ||
+ | ja[0] = sp; | ||
+ | ja[1] = ep; | ||
+ | return ja; | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | [{{ : |
documents/110822jsip_cooking/javascript_imagej_cookbook.txt · Last modified: 2020/11/26 08:24 by kota