User Tools

Site Tools


documents:120206pyip_cooking:python_imagej_cookbook

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
documents:120206pyip_cooking:python_imagej_cookbook [2021/12/08 06:55] – [Path operations] added ApacheIO FilenameUtil kotadocuments:120206pyip_cooking:python_imagej_cookbook [2022/10/16 07:12] (current) – [Using Java8 Stream] kota
Line 242: Line 242:
 </code> </code>
  
-Fiji comes with ApacheIO library, and can be used quite conveniently for disintegrating file paths. +Fiji comes with ApacheIO library, and can be used quite conveniently for disintegrating file paths. See [[https://commons.apache.org/proper/commons-io/javadocs/api-release/org/apache/commons/io/FilenameUtils.html|Javadoc]] for many other convenient methods
 <code python linenums:1> <code python linenums:1>
 from org.apache.commons.io import FilenameUtils from org.apache.commons.io import FilenameUtils
Line 787: Line 787:
 zip command creates a list of tuples from elements of arrays a and b. zip command creates a list of tuples from elements of arrays a and b.
  
 +==== Using Java8 Stream ====
 +
 +Stream-related syntax introduced from Java8 is useful for writing clear codes, but cannot be directly used in Jython. Below is a way to use StreamAPI, by introducing Jython classes implementing the Consumer interface. I took this idea from [[https://stackoverflow.com/questions/45417732/jython-function-to-java-consumer|here]]. For the Java Stream API, this page is useful: [[https://www.baeldung.com/java-8-streams|The Java 8 Stream API Tutorial]]
 +
 +<code python>
 +from java.util.Arrays import asList
 +from java.util.function import Predicate, Consumer, Function
 +from java.util.stream import Collectors
 +from java.util import Arrays
 +
 +
 +class jc(Consumer):
 +    def __init__(self, fn):
 +        self.accept=fn
 +
 +class jf(Function):
 +    def __init__(self, fn):
 +        self.apply = fn
 +
 +class jp(Predicate):
 +    def __init__(self, fn):
 +        self.test = fn
 +        
 +def jprint(x):
 + print x
 +
 +tt = ["a", "b", "c"]
 +c = Arrays.stream(tt).count()
 +print c
 +
 +print "forEach printing"
 +Arrays.stream(tt).forEach(jc(lambda x: jprint("="+x)))
 +
 +print "forEach printing parallelly"
 +Arrays.stream(tt).parallel().forEach(jc(lambda x: jprint("="+x)))
 +
 +print "has b?", Arrays.stream(tt).anyMatch(jp(lambda x: x=="b"))
 +print "has z?", Arrays.stream(tt).anyMatch(jp(lambda x: x=="z"))
 +
 +# convert to Java List<>
 +jtt = Arrays.asList(tt)
 +
 +jtt.stream().forEach(jc(lambda x: jprint("+"+x)))
 +</code>
 ===== Event Listener ===== ===== Event Listener =====
  
Line 839: Line 883:
 </code> </code>
  
 +===== GUI: wait for user =====
 +
 +To pause the script processing and wait for the user input (e.g. creating amanual ROI), use WaitForUserDialog class. 
 +
 +<code python>
 +from ij.gui import WaitForUserDialog
 +
 +print("start")
 +wud = WaitForUserDialog("test: wait for user", "Click OK if you are done with your manual work")
 +print("waiting...")
 +wud.show()
 +print("done")
 +</code>
  
 ===== HashMap ===== ===== HashMap =====
Line 968: Line 1025:
 outimp.show() outimp.show()
 </code> </code>
 +
 +Another example with the map function
 +
 +<code python>
 +# splits multichannel-zstack hyperstack and apply zprojection
 +from ij import IJ
 +from ij.plugin import ZProjector
 +from ij.plugin import ChannelSplitter
 +
 +def sumzp( imp ):
 + zp = ZProjector(imp)
 + zp.setMethod(ZProjector.SUM_METHOD)
 + zp.doProjection() 
 + zpimp = zp.getProjection()
 + return zpimp
 +
 +imp = IJ.getImage()
 +imps = ChannelSplitter.split( imp )
 +zpimps = map(sumzp, imps)
 +zpimps[0].show()
 +</code>
 +
  
 ==== Threshold to create a mask (Binary) ==== ==== Threshold to create a mask (Binary) ====
Line 1001: Line 1080:
 maskimp.show() maskimp.show()
 </code> </code>
 +
 +=== Stack to Mask by a threshold value ===
 +
 +Here is an example script to create a mask from an 8-bit stack using intensity thresholding. 
 +The threshold value is derived by the Otsu algorithm using the full stack histogram. 
 +
 +<code>
 +from ij import IJ, ImagePlus, ImageStack
 +from ij.plugin import ChannelSplitter
 +from ij.process import StackStatistics
 +from fiji.threshold import Auto_Threshold
 +
 +#imp = IJ.openImage("http://imagej.nih.gov/ij/images/confocal-series.zip")
 +imp = IJ.getImage()
 +imps = ChannelSplitter.split( imp )
 +imp1 = imps[0] 
 +imp1bin = imp1.duplicate()
 +
 +# get auto threshold value
 +stats = StackStatistics(imp1bin)
 +histdouble = stats.histogram()
 +
 +# need this conversion from double to int
 +histint = map(lambda x:int(x), histdouble)
 +th = Auto_Threshold.Otsu(histint)
 +
 +for i in range(imp1bin.getStackSize()):
 + ip = imp1bin.getStack().getProcessor( i + 1)
 + ip.threshold(th)
 +
 +IJ.run(imp1bin, "Grays", "");
 +imp1bin.show()
 +</code>
 +
 +To do this by accessing the pixel array of the stack, here is the way. It takes a longer time than above, so this is just to show the technique to process by pixel values using float processor pixel array object. 
 +
 +<code python>
 +
 +from ij import IJ, ImagePlus, ImageStack
 +from ij.plugin import ChannelSplitter
 +from ij.process import StackStatistics
 +from ij.process import FloatProcessor
 +from fiji.threshold import Auto_Threshold
 +import jarray
 +
 +imp = IJ.openImage("http://imagej.nih.gov/ij/images/confocal-series.zip")
 +#imp = IJ.getImage()
 +imps = ChannelSplitter.split( imp )
 +imp1 = imps[0] 
 +ww = imp1.getWidth()
 +hh = imp1.getHeight()
 +binstack = ImageStack( ww, hh)
 +
 +# get auto threshold value
 +stats = StackStatistics(imp1)
 +histdouble = stats.histogram()
 +histint = map(lambda x:int(x), histdouble)
 +th = Auto_Threshold.Otsu(histint)
 +
 +for i in range(imp1.getStackSize()):
 + slicepixA = imp1.getStack().duplicate().convertToFloat().getPixels(i + 1)
 +# pixmin = reduce(min, slicepixA)
 +# pixmax = reduce(max, slicepixA)
 +# print "pixvalue range:", pixmin, " - " ,pixmax
 + slicepixA = map(lambda x: 0.0 if x<th else 255.0, slicepixA)
 + fp = FloatProcessor( ww, hh, slicepixA, None)
 + bp = fp.convertToByteProcessor()
 + binstack.addSlice(str(i+1), bp)
 +
 +binimp = ImagePlus("bin", binstack)
 +binimp.show()
 +</code>
 +
  
 ==== ROI manager ==== ==== ROI manager ====
Line 1047: Line 1199:
  istats = ip.getStatistics()  istats = ip.getStatistics()
  print istats.mean  print istats.mean
 +</code>
 +
 +=== Saving All ROIs as a single zip file ===
 +
 +<code py>
 +import os, jarray
 +from ij.plugins.frame.RoiManager
 +
 +outdir = "/Users/miura/Downloads"
 +roizipname = "myROIs.zip"
 +roizippath = os.path.join(outdir, roizipname)
 +rm = RoiManager.getInstance()
 +if rm.getCount() > 0:
 +    roiindex = jarray.array(range(0, rm.getCount()), 'i')
 +    rm.setSelectedIndexes(roiindex)
 +    rm.runCommand('Save', roizippath)
 </code> </code>
  
Line 1781: Line 1949:
 fullimps[0].show() fullimps[0].show()
 </code> </code>
 +
 +If you do not want to open all images (called sereies) in multi-image CZI files, replace 
 +<code>
 +open.setOpenAllSeries(True) 
 +</code>
 +with 
 +<code>
 +options.setSeriesOn(seriesIndex, True)
 +</code>
 +with "sereiesIndex" being the seriesID e.g. 1 or 2 or 3 ... 
  
 See here for more on metadata parsing and so on: [[https://gist.github.com/ctrueden/6282856|bio-formats.py]] See here for more on metadata parsing and so on: [[https://gist.github.com/ctrueden/6282856|bio-formats.py]]
Line 2203: Line 2381:
 ===== Plugin: MorphoLibJ ===== ===== Plugin: MorphoLibJ =====
  
 +Javadoc: [[http://ijpb.github.io/MorphoLibJ/javadoc/]]
 ==== Distance Transform Watershed 3D ==== ==== Distance Transform Watershed 3D ====
  
Line 2244: Line 2423:
 outimp.setTitle(imp.getShortTitle() + "-labeled") outimp.setTitle(imp.getShortTitle() + "-labeled")
 outimp.show() outimp.show()
 +</code>
 +
 +==== Kill Border Objects, 2D Binary image ====
 +
 +<code py>
 +from ij import IJ, ImagePlus
 +from inra.ijpb.morphology import Reconstruction
 +
 +imp = IJ.getImage() #binary image
 +newip = Reconstruction.killBorders(imp.getProcessor())
 +newimp = ImagePlus("BorderKilled", newip)
 +newimp.show()
 </code> </code>
  
Line 2252: Line 2443:
  
 The plugin webpage is here: [[https://framagit.org/mcib3d/mcib3d-core/-/wikis/home|3D ImageJ Suite]] The plugin webpage is here: [[https://framagit.org/mcib3d/mcib3d-core/-/wikis/home|3D ImageJ Suite]]
 +
 +The real power of 3D Suite is using it as a library from scripts and plugins. Many useful classes are implemented for processing, segmenting, and most notably measuring 3D objects. 
 + 
 +Source codes are located under framagit:
 +
 +  * [[https://framagit.org/mcib3d/mcib3d-core|MCIB-Core source]]
 +  * [[https://framagit.org/mcib3d/mcib3d-plugins|MCIB-Plugins source]]
 +
 +The Javadoc I created (Core and Plugins are merged):
 +
 +  * [[https://wiki.cmci.info/mcib-javadoc/| MCIB3D Javadoc]]
  
 ==== Measureing Spherical 3D ROI positions ==== ==== Measureing Spherical 3D ROI positions ====
Line 2443: Line 2645:
 ===== JAVADOCS ===== ===== JAVADOCS =====
  
-  * 3D ImageJ Suite [[http://wiki.cmci.info/javaapi/mcib-javadoc/|JAVADOC]] (2019 version)+  * 3D ImageJ Suite  
 +    * [[http://wiki.cmci.info/javaapi/mcib-javadoc/|JAVADOC]] (2019 version, deprecated) 
 +    * [[https://wiki.cmci.info/mcib-javadoc/| MCIB3D Javadoc]] (2022 version)
     * [[https://github.com/mcib3d/mcib3d-core|Core Source (old)]]      * [[https://github.com/mcib3d/mcib3d-core|Core Source (old)]] 
     * [[https://framagit.org/mcib3d/mcib3d-core|Core Source (2021-)]]     * [[https://framagit.org/mcib3d/mcib3d-core|Core Source (2021-)]]
documents/120206pyip_cooking/python_imagej_cookbook.1638946557.txt.gz · Last modified: 2021/12/08 06:55 by kota

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki