User Tools

Site Tools


documents:120206pyip_cooking:python_imagej_cookbook

Table of Contents

Python + ImageJ, Fiji Cookbook

This page was last edited at: 2024/10/08 17:45

For learning image processing using Fiji and Jython scripting, go to excellent tutorials written by Albert Cardona, such as here in his website or here in ImageJ.net. The former is in a tutorial style so if you want to learn how to do scripting using Jython, that's the place where you go. Recently, there is a very good tutorial page for real beginners: here (UVA Research Computing Learning Portal).

This page is like a cookbook: there are no details about how to do programming, but more centered on how to use Classes built in ImageJ and its plugins. This is because the style how each algorithm is implemented is not consistent (they are written by 1000 different people!) so it takes a while to figure out how to use them when we are writing a bioimage analysis workflow. Examples below show how they are actually used in Jython scripts, to save our time for reading the source code of each.

Other resources:

The Jython book "The Definitive Guide to Jython": it's saying that the book is a version from 2009, but the latest commit is in Oct. 2018.

Jython Interpreter

A way to run jython script from jython interpreter, interactively.

#simply do
>>> execfile('path/to/script.py')

#if you want to have global variables returned, then
>>> paras = {} 
>>> execfile('path/to/script.py', paras)
>>> print paras
# ... you will see that the objects retained in global variable
# as dictionary key-value pair. You could then get for example
>>> imp_returned = paras['imp']

Of course you could do this by clicking 'run' for scripts opened in script editor as well, but in this way, you could still interact with the objects created by the execfile.

Singed/Unsigned value conversions

Java normally uses signed values but images are generally not signed (for 8 bit, 16 bit images). For this reason, when you work with images as an single array, there will be some need for conversion between signed value to unsigned value, and vice versa. In Jython, one could use functions in struct. Below is an example of converting an 8-bit pixel array extracted from a image to unsigned 8-bit values.

  1. from ij import IJ
  2. import struct
  3.  
  4. def s2u8bit(v):
  5. return struct.unpack("B", struct.pack("b", v))[0]
  6. imp = IJ.getImage()
  7. signedpix = imp.getProcessor().getPixels()
  8. pix = map(s2u8bit,signedpix)
  9. #check that the conversion worked.
  10. # this example was made for binary image, to print only values 255
  11. for j in range(len(pix)):
  12. curval = pix[j]
  13. #curval = s2u8bit(curval)
  14. if curval is 0:
  15. print '--'
  16. else:
  17. print curval

Singed/Unsigned value conversions with bitwise & operator

Here is another example of going back and forth between signed and unsigned values. The scripts load “blobs.gif” example image from NIH server, then replaces pixels with values between 50 and 200 to 0. A kind of density slicing workflow.

  1. from ij import IJ
  2. import jarray
  3.  
  4. imp = IJ.openImage("http://imagej.nih.gov/ij/images/blobs.gif")
  5. imp.show()
  6.  
  7. # ImageProcessor.getPixels() returns an array of signed pixel values
  8. signedpix = imp.getProcessor().getPixels()
  9.  
  10. # converting signed pixel values to unsigned using bitwise operation.
  11. # & 0xff : 8bit
  12. # & 0xffff : 16bit
  13. # & 0xffffffff : 32bit
  14. unsignedpix = map(lambda p: p & 0xff, signedpix)
  15.  
  16. # replace pixels with value more than 50 and less than 200 to 0.
  17. replaced_unsignedpix = map(lambda p: p if (p < 200) and (p > 50) else 0, unsignedpix)
  18.  
  19. # convert signed pixel values to unsigned.
  20. replaced_signedpix = map(lambda p: (p - 256) if p > 127 else p, replaced_unsignedpix)
  21.  
  22. # python array to java array.
  23. jreplaced_signedpix = jarray.array(replaced_signedpix, 'b')
  24.  
  25. imp.getProcessor().setPixels(jreplaced_signedpix)
  26. imp.updateAndDraw()

Same processing could be also done by replacing L7 to L23 by

  1. for j in range(imp.getHeight()):
  2.  

ImageJ2 / SciJava

Running a script from another script

#@ ScriptService scriptService

fullscript = "#@ String A_STRING\n" + \
"#@ Boolean (label='An Option', value=true) OPTION"

scriptmodule = scriptService.run(".py", fullscript, True).get()
scriptInputmaps = scriptmodule.getInputs()

print scriptmodule.getOutputs()
print scriptInputmaps
# how can we know the dialog was Canceled?
print scriptmodule.isInputResolved('A_STRING')

Data IO

Getting path to a file interactively

  1. from ij.io import OpenDialog
  2. op = OpenDialog("Choose Track Data...", "")
  3. print op.getDirectory()+ op.getFileName()

Getting the directory where the curently opened image is stored

from ij import IJ

imp = IJ.getImage()
print imp.getOriginalFileInfo().directory

… can also be done by IJ.getDirectory("image"), but with this IJ method, one cannot specify target ImagePlus object. See also the source code of IJ.getDirectory

Be careful not to mix with the usage of getFileInfo. This does not hold directory information.

Regular Expression to get meta information from file name

Here is an example, using re package. To construct pattern, several web services are available such as:

http://www.pythonregex.com/
or
https://regex101.com/

  1. import re
  2.  
  3. filename = '/Volumes/data/0076-14--2006-01-23/data/--W00088--P00001--Z00000--T00000--nucleus-dapi.tif'
  4. #filename = '--W00088--P00001--Z00000--T00000--nucleus-dapi.tif'
  5. pattern = re.compile('(.*)--W(.*)--P(.*)--Z(.*)--T(.*)--(.*)\.(.*)')
  6. res = re.search(pattern, filename)
  7. basename = res.group(1)
  8. spot = res.group(2)
  9. position = res.group(3)
  10. zpos = res.group(4)
  11. tpos = res.group(5)
  12. imgtype = res.group(6)
  13. filetype = res.group(7)
  14. print 'prefix', basename
  15. print 'spot', spot
  16. print 'position', position

Loading Image from File system.

Four ways to open image

  1. from ij import IJ, ImagePlus
  2. from ij.io import Opener
  3.  
  4. srcpath = '/tt/img.tif'
  5.  
  6. # uisng constructor
  7. imp1 = ImagePlus(srcpath)
  8.  
  9. # using IJ static method
  10. imp2 = IJ.openImage(srcpath)
  11.  
  12. # Using Opener class
  13. imp3 = Opener().openImage(srcpath)
  14.  
  15. # using LOCI BioFormats
  16. from loci.plugins import BF
  17. # returned is an array of ImagePlus, in many cases just one imp.
  18. imps = BF.openImagePlus(src)
  19. imp4 = imps[0]

Retrieving Image Properties

To know image pixel resolution, TiffDecoder class is useful as it does not load image data. For big images this is important since getting image properties would be much faster.

  1. from ij.io import TiffDecoder
  2.  
  3. # using 'mitosis (5d)' sample image.
  4. directory = '/tmp/examples/'
  5. filename = 'mitosis.tif'
  6. td = TiffDecoder(directory, filename)
  7. imginfos = td.getTiffInfo()
  8. print 'Resolution: ', imginfos[0].unit, '/ pixel'
  9. print 'x resoluition:', imginfos[0].pixelWidth
  10. print 'y resoluition:', imginfos[0].pixelHeight
  11.  
  12. # to print various image parameters
  13. print imginfos[0].description
  14. print '---'
  15. # to print imgage optional info
  16. print imginfos[0].info

Path operations

To extract file name and file name without extension,

  1. import os
  2. srcpath = '/Users/miura/tmp/data.csv'
  3. filename = os.path.basename(srcpath)
  4. print filename #prints data.csv
  5.  
  6. parentdirectory = os.path.dirname(srcpath)
  7. print parentdirectory #prints /Users/miura/tmp
  8.  
  9. print os.path.join(parentdirectory, filename) #prints same as srcpath
  10.  
  11. #above is enough to join directory and file name,
  12. # but if you specifically want to use path separator of the os
  13. print os.sep
  14.  
  15. #filename without extension
  16. print os.path.splitext(filename)[0] #prints /Users/miura/tmp/data

Alternatively, one could use File class in Java.

  1. from java.io import File
  2. imgpath = 'Z:\\20_23h_firstSample\\20h_shifted.tif'
  3. ff = File(imgpath)
  4. print ff.getParent()
  5. print ff.getName()

Fiji comes with ApacheIO library, and can be used quite conveniently for disintegrating file paths. See Javadoc for many other convenient methods.

  1. from org.apache.commons.io import FilenameUtils
  2.  
  3. srcpath = '/Users/miura/tmp/data.csv'
  4.  
  5.  
  6. baseName = FilenameUtils.getBaseName(srcpath)
  7. print "Basename: ", baseName
  8.  
  9. ext = FilenameUtils.getExtension(srcpath)
  10. print "Extension: ", ext
  11.  
  12. filename = FilenameUtils.getName(srcpath)
  13. print "File name: ", filename
  14.  
  15. pathWOext = FilenameUtils.removeExtension(srcpath)
  16. print "Fullpath without ext: ", pathWOext
  17.  
  18. # outputs
  19. #
  20. # Basename: data
  21. # Extension: csv
  22. # File name: data.csv
  23. # Fullpath without ext: /Users/miura/tmp/data

Loading a textfile as String

  1. path = "/Users/miura/data.txt"
  2. with open(inpath, 'r') as myfile:
  3. data = myfile.read()
  4. print data

Saving String as a textfile

  1. with open("/Users/miura/Downloads/testOutput.txt", "w") as text_file:
  2. text_file.write("The first line\nAnother line")
  3. text_file.close()

Loading CSV file

  1. from ij import IJ
  2. from util.opencsv import CSVReader
  3. from java.io import FileReader
  4.  
  5. def readCSV(filepath):
  6. reader = CSVReader(FileReader(filepath), ",")
  7. ls = reader.readAll()
  8. for item in ls:
  9. IJ.log(item[4])
  10.  
  11. filepath = '/Users/miura/test.csv'
  12. readCSV(filepath)

WIth purely pythonic way:

  1. import csv
  2.  
  3. filepath = '/Users/miura/Dropbox/ToDo/Pavel/data.txt'
  4. f = open(filepath, 'rb')
  5. data = csv.reader(f, delimiter=' ')
  6. for row in data:
  7. print(len(row))
  8. print ', '.join(row)

In this case, imported array is python array. to convert this to Java array, use

  1. from jarray import array
  2. javaarray = array(pythonarray, 'type')

see here for more details.

Saving CSV file (data table)

Uses opencsv library, which is preinstalled in Fiji.

  1. from util.opencsv import CSVWriter
  2. from java.io import FileWriter
  3. from java.lang.reflect import Array
  4. from java.lang import String, Class
  5. writer = CSVWriter(FileWriter("c:/temp/testcsv.csv"), ',')
  6. data = Array.newInstance(Class.forName("java.lang.String"), 3)
  7. #String[] entries = "first#second#third".split("#");
  8. data[0] = str(11)
  9. data[1] = str(23)
  10. data[2] = str(5555)
  11. writer.writeNext(data)
  12. writer.close()

This could be rewritten in a bit more simple way using jarray module.

  1. from util.opencsv import CSVWriter
  2. from java.io import FileWriter
  3. from java.lang import String
  4. from jarray import array as jarr
  5. writer = CSVWriter(FileWriter("/Users/miura/Desktop/eggs1.csv"), ',')
  6. header = ['x', 'y', 'z']
  7. jheader = jarr(header, String)
  8. data = [11,23,5555]
  9. datas = map(str, data)
  10. jdata = jarr(datas, String)
  11. writer.writeNext(jheader)
  12. writer.writeNext(jdata)
  13. writer.close()

… or purely in pythonic way using csv module. This example is very simple since it does not use Java array at all. If you need to use the array for some other purpose in Java classes, python array must be converted.

  1. import csv
  2.  
  3. f = open('/Users/miura/Desktop/eggs2.csv', 'wb')
  4. writer = csv.writer(f)
  5. writer.writerow(['does this work'])
  6. writer.writerow(['Spam', 'Lovely Spam', 'Wonderful Spam'])
  7. #can chop down more
  8. writer.writerows(['Spam', 'Lovely Spam', 'Wonderful Spam'])
  9. f.close()

… a bit more realistic, writing numerical data.

  1. '''
  2. writing data to a csv file.
  3. '''
  4. import os, csv
  5.  
  6. # prepare test data to wirte to a csv file
  7. data1 = range(10)
  8. data2 = [x * x for x in data1]
  9. data3 = [pow(x, 3) for x in data1]
  10. print data3
  11.  
  12. # prepare path
  13. root = "/Users/miura/Desktop"
  14. filename = "testdata.csv"
  15. fullpath = os.path.join(root, filename)
  16. print fullpath
  17.  
  18. # open the file first (if its not there, newly created)
  19. f = open(fullpath, 'wb')
  20.  
  21. # create csv writer
  22. writer = csv.writer(f)
  23.  
  24. # for loop to write each row
  25. for i in range(len(data1)):
  26. row = [data1[i], data2[i], data3[i]]
  27. writer.writerow(row)
  28.  
  29. #writer.writerows([data1, data2, data3])
  30.  
  31. # close the file.
  32. f.close()

Accessing multiple files to load image sequences

A simple way is to use glob package (file not loaded in this example).

  1. import glob, os
  2. from ij.io import DirectoryChooser
  3.  
  4. srcDir = DirectoryChooser("Choose!").getDirectory()
  5. for filename in glob.glob(os.path.join(srcDir, "*.tif")):
  6. print(os.path.basename(filename))

Here is a cool script written by Christian Tischer for loading image series using file prefix as dictionary keys.

  1. from ij import IJ
  2. from ij.io import DirectoryChooser
  3. import os
  4.  
  5. def run():
  6. srcDir = DirectoryChooser("Choose!").getDirectory()
  7. IJ.log("directory: "+srcDir)
  8. theIndex = {}
  9. for root, directories, filenames in os.walk(srcDir):
  10. for filename in filenames:
  11. if not filename.endswith(".tif"):
  12. continue
  13. #IJ.log(filename)
  14. treatment, well, position, z, time, channel = filename.split("--")
  15. identifier = treatment + '--' + well + '--' + position
  16. theIndex[identifier] = theIndex.get(identifier, []) + [time]
  17. #IJ.log("identifier: "+identifier)
  18. #IJ.log("time: "+time)
  19.  
  20. print(theIndex.keys())
  21.  
  22. for index in theIndex.keys():
  23. print(index)
  24. cmd = "Image Sequence..."
  25. options = "open="+srcDir+" or="+index+".*--gfp.tif sort"
  26. IJ.run(cmd, options)
  27. run()

Accessing tiff stack via Virtual Stack class

  1. from ij.io import OpenDialog
  2. from ij.io import TiffDecoder
  3. from ij.plugin import FileInfoVirtualStack
  4. od = OpenDialog("stack", "")
  5. td = TiffDecoder(od.getDirectory(), od.getFileName())
  6. info = td.getTiffInfo()
  7. fi = info[0]
  8. print fi.nImages
  9. vs = FileInfoVirtualStack(fi, False)
  10. for i in range(1,fi.nImages):
  11. ip = vs.getProcessor(i)
  12. print i

Viewing tiff stack as Virtual Stack

A bit of modification of above code allows you to view a stack as a virtual stack. Since FileInfoVirtualStack is an extended class of ImageStack, a ImagePlus can be directly created.

  1. from ij.io import OpenDialog
  2. from ij.io import TiffDecoder
  3. from ij.plugin import FileInfoVirtualStack
  4. from ij import ImagePlus
  5. od = OpenDialog("stack", "")
  6. td = TiffDecoder(od.getDirectory(), od.getFileName())
  7. info = td.getTiffInfo()
  8. fi = info[0]
  9. print fi.nImages
  10. vs = FileInfoVirtualStack(fi, False)
  11. imp = ImagePlus("testVirtual", vs)
  12. imp.show()

Saving Hyperstack as Separate 2D files

If you have let's say a 5D hyperstack and you want to save them as separate 2D tiff files with each file name having file_c00_t0001_z_0000.tif and so on, here is an example script.

  1. from ij import IJ
  2. import os
  3.  
  4. savepath = IJ.getDirectory("")
  5. imp = IJ.getImage()
  6. ssize = imp.getStackSize()
  7. titleext = imp.getTitle()
  8. title = os.path.splitext(titleext)[0]
  9. dimA = imp.getDimensions()
  10. for c in range(dimA[2]):
  11. for z in range(dimA[3]):
  12. for t in range(dimA[4]):
  13. imp.setPosition(c+1, z+1, t+1)
  14. print c, z, t
  15. numberedtitle = \
  16. title + "_c" + IJ.pad(c, 2) + \
  17. "_z" + IJ.pad(z, 4) + \
  18. "_t" + IJ.pad(t, 4) + ".tif"
  19. stackindex = imp.getStackIndex(c + 1, z + 1, t + 1)
  20. aframe = ImagePlus(numberedtitle, imp.getStack().getProcessor(stackindex))
  21. IJ.saveAs(aframe, "TIFF", savepath + numberedtitle)
  22. IJ.log("saved:" + numberedtitle)

Loading Separate Image Files as a Hyperstack

This is an expaple of using regular expression to match file names, and to collect images as a ImagePlus array then convert it to a Hyperstack.

https://gist.github.com/miura/6453158

  1. import os
  2. import re
  3. from ij import IJ
  4. from ij.io import Opener
  5. from ij.plugin import Concatenator
  6. from jarray import array
  7. srcpath = IJ.getFilePath('Choose the first file')
  8. filename = os.path.basename(srcpath)
  9. srcDir = os.path.dirname(srcpath)
  10. #chosefile = '20130711_R1_GR001_B1_L2.lsm'
  11. #pattern = re.compile('(.*)_R(.*)_GR(.*)_B(.*)_L(.*)\.lsm')
  12. pattern = re.compile('(.*)_R(.*)_GR(.*)_B(.*)_L(.*)\.(.*)')
  13. res = re.search(pattern, filename)
  14. basename = res.group(1)
  15. repetition = res.group(2)
  16. grouprepetition = res.group(3)
  17. block = res.group(4)
  18. location = res.group(5)
  19. extension = res.group(6)
  20. GRlist = []
  21. for root, directories, filenames in os.walk(srcDir):
  22. for filename in filenames:
  23. match = re.search(pattern, filename)
  24. if match is not None:
  25. #print filename, match.group(3)
  26. GRlist.append(match.group(3))
  27. print srcDir
  28. print 'files: ', len(GRlist)
  29. GRlist = sorted(GRlist)
  30. timeseries = []
  31. for timepoint in GRlist:
  32. thisfile = basename + '_R' + repetition + '_GR' + timepoint + '_B' + block + '_L' + location + '.' + extension
  33. print thisfile
  34. imp = Opener.openUsingBioFormats(os.path.join(srcDir, thisfile))
  35. imp.setOpenAsHyperStack(False)
  36. timeseries.append(imp)
  37. newname = basename + '_R' + repetition + '_B' + block + '_L' + location + '.' + extension
  38. calib = timeseries[0].getCalibration()
  39. dimA = timeseries[0].getDimensions()
  40. jaimp = array(timeseries, ImagePlus)
  41. ccc = Concatenator()
  42. #allimp = ccc.concatenateHyperstacks(jaimp, newname, False)
  43. allimp = ccc.concatenate(jaimp, False)
  44. allimp.setDimensions(dimA[2], dimA[3], len(GRlist))
  45. allimp.setCalibration(calib)
  46. allimp.setOpenAsHyperStack(True)
  47. allimp.show()

Wait until a file is created

There are cases that you need to wait till a file is created. Below two lines does this waiting task.

  1. while not os.path.exists(filepath):
  2. time.sleep(1)

Downloading a CSV file from Internet and save locally

Using IJ method.

  1. from ij import IJ
  2. from java.io import PrintWriter
  3. content = IJ.openUrlAsString('http://cmci.info/imgdata/tenFrameResults.csv')
  4. out = PrintWriter('/Users/miura/tmp/test1.csv')
  5. out.print(content)
  6. out.close()

Only in Java

  1. from ij import IJ
  2. from ij.io import Opener
  3. from java.io import File, FileOutputStream
  4. from java.net import URL
  5. from java.lang import Long
  6. from java.nio.channels import Channels
  7.  
  8.  
  9. websitecsv = URL("http://cmci.info/imgdata/tenFrameResults.csv")
  10. csvchannel = Channels.newChannel(websitecsv.openStream())
  11.  
  12. ff = File("/Users/miura/tmp/test.csv")
  13. if not ff.exists():
  14. ff.createNewFile()
  15. fos = FileOutputStream(ff)
  16. fos.getChannel().transferFrom(csvchannel, 0, Long.MAX_VALUE)
  17. fos.close()
  18. IJ.log("done")

Creating JSON object

JSON object can be directly created from Java Maps. Here, we use TreeMap to keep the ordering of Map elements.

from java.util import TreeMap
from org.json import JSONObject

amap = TreeMap()
amap.put("red", 0.6)
amap.put("green", 1)
amap.put("blue", 0.3)
jo = JSONObject(amap)
print str(jo)

This code yields:

{"blue":0.3,"green":1,"red":0.6}

Generating Time Stamp String

from java.util import Date
from java.text import SimpleDateFormat

timeStamp = SimpleDateFormat("yyyy.MM.dd.HH.mm.ss").format(Date())
print timeStamp

Arrays (Lists)

“Array” is called “List” in python. When using list in jython, we should be very very careful whether an array (or list) is Java array or Python list: they both are set of numbers, but they sometimes require conversion. This happens especially when you want to use array in the argument of certain Java methods.

We first start with Python list (or for me is “python array”):

Appending Elements to a List

Two ways to append an element to a list.

a = []
a.append(1)
a.append(2)
print a
# [1, 2]

b = []
b = b + [1]
b = b + [2]
print b
# [1, 2]
#... can be also written like
b = []
b += [1]
b += [2]
print b
# [1, 2]

Concatenate lists

  1. a = [1, 2, 3]
  2. b = [4, 5, 6]
  3. a = a + b
  4. print a

will prints

[1, 2, 3, 4, 5, 6]

in the console.

Remove redundant elements in an Array

  1. a=[1,2,3,4,5,5]
  2. a=list(set(a))
  3. a.sort()
  4. print a

ImagePlus Array

Some arguments ask for an array of specific type. Since Python array is not java array, one should generate a Java array. For this, you could use jarray package.

  1. import jarray
  2.  
  3. ja = jarray.array([0, 1, 2, 3], 'i')

The second argument specifies the type.

z boolean
c char
b byte
h short
i int
l long
f float
d double

What if you want to make a java array of a specific class? You could then name the class as the second argument. For example,

  1. import jarray
  2. from ij import IJ
  3. from ij.plugin RGBStackMerge
  4.  
  5. imp1 = IJ.openImage(path1)
  6. imp2 = IJ.openImage(path2)
  7. imgarray = jarray.array([imp1, imp2], ImagePlus)
  8. colorimp = RGBStackMerge().mergeHyperstacks(imgarray, False)

Converting Java array types

Sometimes we need to convert the type of Java array e.g. double[] to int[]. For this, there is no magic trick and need to run a loop. Below is a code fragment.

 
from ij.process import StackStatistics
import jarray

stackstats = StackStatistics(imp)
histD = stackstats.histogram()
hist = jarray.zeros(len(histD), 'i')
for i in range(len(histD)):
    hist[i] = int(histD[i])

Combined Sort of Lists

  1. from operator import itemgetter
  2. ll = [1, 2, 3, 4]
  3. ll2 = [5, 7, 8, 6]
  4. aa = sorted(zip(ll, ll2), key=itemgetter(1), reverse=True)
  5. print aa
  6. ll, ll2 = zip(*aa)
  7. print list(ll)
  8. print list(ll2)
  9. # in one line
  10. # ll, ll2 = (list(t) for t in zip(*sorted(zip(ll, ll2))))

… results in:

[(3, 8), (2, 7), (4, 6), (1, 5)]
(3, 2, 4, 1)
(8, 7, 6, 5)

Looping Two Arrays Simultaneously

Python fo-looping is pretty flexible.

  1. a = [1, 2, 3, 4]
  2. b = [10, 20, 30, 40]
  3.  
  4. for aa, bb in zip(a, b):
  5. c = aa + bb
  6. print c

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 here. For the Java Stream API, this page is useful: The Java 8 Stream API Tutorial

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)))

Event Listener

An example of implementing KeyListener, written by Christoph Schiklenk. This script loads a tab-delimited text file, show it in a results-table style that accepts key-press down event and loads the data in the currently selected row.

  1. from java.awt.event import KeyEvent, KeyAdapter
  2. from os.path import basename, splitext
  3.  
  4. path = "/Users/miura/Desktop/tmp/val_p1_c2.tsv"
  5. filename = splitext(basename(path))[0]
  6.  
  7. # imp will be something like a global variable. accessible from
  8. # funcitons.
  9. imp = IJ.getImage()
  10.  
  11. def doSomething(imp, keyEvent):
  12. """ A function to react to key being pressed on an image canvas. """
  13. IJ.log("clicked keyCode " + str(keyEvent.getKeyCode()) + " on image " +
  14. str(imp.getTitle()))
  15. # Prevent further propagation of the key event:
  16. keyEvent.consume()
  17.  
  18. class ListenToKey(KeyAdapter):
  19. def keyPressed(this, event):
  20. eventSrc = event.getSource()
  21. tp = eventSrc.getParent() #panel is the parent, canvas being component.
  22. print eventSrc
  23. print tp
  24. print "selected line:", tp.getSelectionEnd()
  25. print "...", tp.getLine(tp.getSelectionEnd())
  26. #imp = event.getSource()
  27. doSomething(imp, event)
  28.  
  29. # - - - M A I N - - -
  30.  
  31. listener = ListenToKey()
  32.  
  33. txtfile = open(path)
  34. tw = TextWindow("Results_" + filename, txtfile.readlines(1)[0], "", 300,
  35. 700)
  36.  
  37. for line in txtfile.readlines():
  38. frame, dist, volChI, volChII = line.split("\t")
  39. tw.append(str(frame) + "\t" + str(dist) + "\t" + str(volChI) + "\t" +
  40. str(volChII))
  41.  
  42. tw.getTextPanel().addKeyListener(listener)
  43.  

GUI: wait for user

To pause the script processing and wait for the user input (e.g. creating amanual ROI), use WaitForUserDialog class.

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")

HashMap

Python

Maps are called Dictionary in Python.

To split a dictionary to key lists and value lists:

  1. results = {'mean': 10.0, 'sd': 3.3}
  2. headers = results.keys()
  3. values = results.values()
  4. print headers
  5. print values

Java

Getting the max number of keys, in case if the key is integer.

  1. from java.util import HashMap, Collections
  2.  
  3. tt = HashMap()
  4. tt.put(1, "1")
  5. tt.put(200, "2")
  6. tt.put(2, "2")
  7.  
  8. print Collections.max(tt.keySet())

Canvas Resizing

The code below grabs currently active 2D image and creates another image with additional 100 pixels at the bottom.

from ij import IJ, ImagePlus
from ij.plugin import CanvasResizer

ip = IJ.getImage().getProcessor()
cd = CanvasResizer()
bigip = cd.expandImage(ip, ip.getWidth(), ip.getHeight() + 100, 0, 0)
ImagePlus("resized", bigip).show()

Type Conversion

In all cases shown below the image will be overwritten. If you do not want that, Duplicate image fist by

imp2 = imp.duplicate()

or

  1. from ij.plugin import Duplicator
  2. imp2 = Duplicator().run(imp)

to RGB

  1. from ij import IJ
  2. from ij.process import ImageConverter
  3. imp = IJ.getImage()
  4. ImageConverter(imp).convertToRGB()

to 8bit grayscale

  1. from ij import IJ
  2. from ij.process import ImageConverter
  3. imp = IJ.getImage()
  4. ImageConverter(imp).convertToGray8()

Channel Splitter

[Image > Color > Split Channels]

  1. from ij import IJ
  2. from ij.plugin import ChannelSplitter
  3. imp = IJ.getImage()
  4. imps = ChannelSplitter.split(imp)
  5. imps[0].show() # Channel 1
  6. imps[1].show() # Channel 2

Channel Merge

[Image > Color > Merge Channels…]

  1. from ij import ImagePlus
  2. from ij.plugin import RGBStackMerge, RGBStackConverter
  3.  
  4. impc1 = ImagePlus("path/to/image.tif")
  5. impc2 = ImagePlus("path/to/image.tif")
  6.  
  7. mergeimp = RGBStackMerge.mergeChannels([impc2, None, impc1, None, None, None, None], True)
  8.  
  9. # convert the composite image to the RGB image
  10. RGBStackConverter.convertToRGB(mergeimp)
  11.  
  12. mergeimp.show()

Z projection

  1. # example script for z projection
  2. # extracts first time point from a 4D stack and do maximum intensity Z-projection
  3. from ij import IJ
  4. from ij.plugin import ZProjector
  5. from emblcmci import Extractfrom4D
  6.  
  7. def maxZprojection(stackimp):
  8. zp = ZProjector(stackimp)
  9. zp.setMethod(ZProjector.MAX_METHOD)
  10. zp.doProjection()
  11. zpimp = zp.getProjection()
  12. return zpimp
  13.  
  14. imp = IJ.getImage()
  15. e4d = Extractfrom4D()
  16. e4d.setGstarttimepoint(1)
  17. IJ.log("current time point" + str(1))
  18. aframe = e4d.coreheadless(imp, 3)
  19. outimp = maxZprojection(aframe)
  20. outimp.show()

Another example with the map function

# 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()

Threshold to create a mask (Binary)

Single Threshold Value

With single threshold value, pixels lower than or equal to the value will be 0 and otherwise 255.

# an example with a threshold value of 125. 
from ij import IJ
imp = IJ.getImage()
imp.getProcessor().threshold(125)
imp.updateAndDraw()

Lower and Upper Threshold Value

With lower and upper threshold values, there is no really direct way but to convert the thresholded area to a selection (ROI), apply ROI to the image then convert it to a mask.

There is also a lower way by evaluating pixel by pixel, but this should be obvious.

  1. # an example with lower and upper threshold values, 100 and 125.
  2. from ij import IJ, ImagePlus
  3. from ij.process import ImageProcessor
  4. from ij.plugin.filter import ThresholdToSelection
  5. imp = IJ.getImage()
  6. imp.getProcessor().setThreshold(100, 125, ImageProcessor.NO_LUT_UPDATE)
  7. roi = ThresholdToSelection.run(imp)
  8. imp.setRoi(roi)
  9. maskimp = ImagePlus("Mask", imp.getMask())
  10. maskimp.show()

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.

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()	

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.


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()	

ROI manager

Removing all ROIs from the ROI manager.

  1. rm = RoiManager.getInstance()
  2. ht = rm.getList()
  3. ht.removeAll()

which is equivalent to

  1. rm = RoiManager.getInstance()
  2. rm.runCommand('reset')

Loading image silently and do multiple measurements for all ROIs, without showing the RoiManager associated dialog. In other words, the silent version of macro command:

roiManager("Multi Measure")
  1. # loading an image from the imagej site
  2. # if you want to load an image from local, replace the URL with a file path
  3. imp = ImagePlus('http://imagej.nih.gov/ij/images/boats.gif')
  4.  
  5. # uncomment the following line if you want to see the image
  6. #imp.show()
  7.  
  8. # RoiManager should be present
  9. rm = RoiManager.getInstance()
  10.  
  11. ip = imp.getProcessor()
  12. #rm.setVisible(False)
  13.  
  14. # Instead of multimeasure command in RoiManager, get an array of ROIs.
  15. ra = rm.getRoisAsArray()
  16.  
  17. # loop through ROI array and do measurements.
  18. # here is only listing mean intensity of ROIs
  19. # if you want more, see
  20. # http://rsbweb.nih.gov/ij/developer/api/ij/process/ImageStatistics.html
  21. for r in ra:
  22. ip.setRoi(r)
  23. istats = ip.getStatistics()
  24. print istats.mean

Saving All ROIs as a single zip file

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)

Union of multiple ROIs

For combining multiple ROIs, ShapeRoi class is useful.

  1. from ij.gui import ShaprRoi
  2. sr1 = ShapeRoi(roi1)
  3. sr2 = ShapeRoi(roi2)
  4. sr3 = sr1.or(sr2)

sr3 is then a combination of ROIs roi1 and roi2. In similar way, there are AND, XOR, NOT and so on, logical operations.

Mask to selection (Binary to Selection)

[Edit > Selection > Create Selection]

Suppose that the active image is a black and white binary image, and to create a selection from black pixels and store the resulted ROI in the RoiManager, do the following.

  1. from ij.plugin.filter import ThresholdToSelection
  2. from ij.plugin.frame import RoiManager
  3.  
  4. rm = RoiManager()
  5. segimp = IJ.getImage()
  6. segimp.getProcessor().setThreshold(0, 0, ImageProcessor.NO_LUT_UPDATE)
  7. boundroi = ThresholdToSelection.run(segimp)
  8. rm.addRoi(boundroi)

Adding Overlay in 3D Stack (ROI to Overlay)

from ij import IJ
from ij.gui import OvalRoi, Overlay

imp = IJ.getImage()
roi = OvalRoi(170, 160, 22, 22)
roi.setPosition(19)

ol = Overlay()
ol.add(roi)
imp.setOverlay(ol)
ol.setStrokeWidth(2) 

Export ROIs in RoiManager to a SVG file

To export ROIs as a vector drawing for use in other applications (e.g. PDF, Adobe Illustrator), one way is to export them in SVG format. This file format is nothing more than text (XML), so it's pretty good for programmatically using it to export ImageJ ROIs. Johannes Schindeline once even suggested to export ROIs using ImageJ Macro by directly writing texts in SVG format.

The code below uses a free library called jfreeSVG from Jfreechart group. This is a separate package not included in jfreechart so it should be downloaded and installed in Fiji (jfreechart is included in Fiji package). Javadoc for jfreeSVG is here.

For more details about SVG format, see here.

  1. import sys
  2. from java.awt import Color
  3. from java.io import File
  4. from ij import IJ
  5. from ij.gui import ShapeRoi
  6. from ij.plugin.frame import RoiManager
  7. from org.jfree.graphics2d.svg import SVGGraphics2D, SVGUtils
  8.  
  9. imp = IJ.getImage()
  10. rm = RoiManager.getInstance()
  11. if rm is None:
  12. print 'None'
  13. sys.exit()
  14.  
  15. # convert ROIs in RoiManager to an array of shapeRois
  16. jrois = rm.getRoisAsArray()
  17. srois = [ShapeRoi(jroi) for jroi in jrois]
  18.  
  19. # http://www.jfree.org/jfreesvg/javadoc/
  20. g2 = SVGGraphics2D(imp.getWidth(), imp.getHeight())
  21. g2.setPaint(Color.BLACK)
  22. px = 0.0
  23. py = 0.0
  24. for sroi in srois:
  25. g2.translate(px*-1, py*-1)
  26. px = sroi.getBounds().x
  27. py = sroi.getBounds().y
  28. g2.translate(px, py)
  29. g2.draw(sroi.getShape())
  30. se = g2.getSVGElement()
  31.  
  32. # writing the file
  33. path = "/Users/miura/tmp/testsvg3.svg"
  34. SVGUtils.writeToSVG(File(path), se)

One problematic aspect of ROIs are that they could be various, such as lines, rectangles, ovals and polygons. In SVG these different types of ROIs should be treated as different shapes (use different tags). jfreeSVG allows to draw various shapes just by passing java.awt.Shape object, so we do not have to deal with different ROI types in ImageJ and can be moderately generic: IJ ROIs can be converted to IJ ShapeRoi object, which can then be directly converted to java.awt.Shape class.

There are other IJ plugins implementing SVG access. I tried IJ1ROIsToSVGFileWriter, a class in plugin Slide Set. It works for simple ROIs like Rect. ROIs, but for polygons it returns out of memory errors.

There is also plugin ScienFig which should have some SVG export methods implemented but have not looked at it in depth.

Automatic Brightness/Contrast Button

In the legacy “Brightness/Contrast” GUI, there is a button labeled “Auto” which calculates the minimum and the maximum pixel values for enhancing contrast of the current image (the GUI then updates the LUT accordingly). Following are the steps how these values are found out.

  1. get the number of total pixel number (pixelCount)
  2. set the limit of pixel number. (limit = pixelCount/10)
  3. set the threshold value. (threshold = pixelCount/5000)
  4. get an array of pixel intensity histogram of the current image.
  5. then there are two independent loops, one for finding the lower and another for finding the upper value.
    1. lower value finder: loop starts from histogram[0] and increments. For every pixel intensity,
      1. if the count exceeds “limit”, then count becomes 0
      2. if the count is larger than “threshold”, then that value is the minimum.
    2. higher value finder: loop starts from histogram[255] and decrements. For every pixel intensity,
      1. if the count exceeds “limit”, then count becomes 0
      2. if the count is larger than “threshold”, then that value is the maximum.

Explanation in human language: this algorithm first determines two values “limit” and “Threshold”.

“Threshold” is the parameter that actually sets the min and the max of the contrast curve for the automatic enhancement. Starting from the lowest pixel value (0) or the highest value (255), the algorithm determines the number of pixels with that pixel value. If the number exceeds 0.02% of total pixel number, then that pixel value becomes wither the min or the max for enhancing the contrast. For this decision to ignore background pixels, the algorithm also needs to have another decision determining the background pixel value.

“limit” actually is a fixed number for each image to decide which of black (0) or white (255) is the background. If the number of pixels with current pixel value is more than 10% of total pixel number, then that value is considered to be the background of the image. For example, when the number of pixels with the value of 0 is 15%, then pixels with 0 values are background. In the next step, if pixels with the value of 1 are still over 10% like 11%, then pixels with values ⇐ 1 are background. When the background is white, then similar decision takes place in the second loop.

The Jython script shown below is the re-written version based on original Java code. You could see the Java code of method “autoadjust” in the git repo, line 780-829.

  1. # rewriting "Auto contrast adjustment" button of "Brightness/Contrast"
  2. # Kota Miura
  3. # 20120515
  4.  
  5. autoThreshold = 0
  6. AUTO_THRESHOLD = 5000
  7.  
  8. imp = IJ.getImage()
  9. cal = imp.getCalibration()
  10. imp.setCalibration(None)
  11. stats = imp.getStatistics() # get uncalibrated stats
  12. imp.setCalibration(cal)
  13. limit = int(stats.pixelCount/10)
  14. histogram = stats.histogram #int[]
  15. if autoThreshold<10:
  16. autoThreshold = AUTO_THRESHOLD
  17. else:
  18. autoThreshold /= 2
  19. threshold = int(stats.pixelCount/autoThreshold) #int
  20. print "pixelCount", stats.pixelCount
  21. print "threshold", threshold
  22. print "limit", limit
  23. i = -1
  24. found = False
  25. count = 0 # int
  26. while True:
  27. i += 1
  28. count = histogram[i]
  29. if count>limit:
  30. count = 0
  31. found = count> threshold
  32. if found or i>=255:
  33. # if 0 not in (!found, i<255) :
  34. break
  35. hmin = i #int
  36. i = 256
  37. while True:
  38. i -= 1
  39. count = histogram[i]
  40. if count>limit:
  41. count = 0
  42. found = count> threshold
  43. if found or i<1:
  44. # if 0 not in (!found, i<255) :
  45. break
  46. hmax = i #int
  47.  
  48. print "minimum", hmin
  49. print "maximum", hmax

Lines 17-18 seems to be not accessed at all, and seems to be not required.

Here is the same written in ImageJ macro language.

 AUTO_THRESHOLD = 5000;
 getRawStatistics(pixcount);
 limit = pixcount/10;
 threshold = pixcount/AUTO_THRESHOLD;
 nBins = 256;
 getHistogram(values, histA, nBins);
 i = -1;
 found = false;
 do {
         counts = histA[++i];
         if (counts > limit) counts = 0;
         found = counts > threshold;
 }while ((!found) && (i < histA.length-1))
 hmin = values[i];
 
 i = histA.length;
 do {
         counts = histA[--i];
         if (counts > limit) counts = 0; 
         found = counts > threshold;
 } while ((!found) && (i > 0))
 hmax = values[i];

 setMinAndMax(hmin, hmax);
 print(hmin, hmax);

Counting number of pixels with a specific value in a stack

In the example below, the code counts pixels with a value of 100. List comprehensions are a bit cryptic, but by getting use to it, it avoids looping.

  1. from ij import IJ
  2.  
  3. imp = IJ.getImage()
  4. pixval = 100
  5. count = 0
  6. ips = [imp.getStack().getProcessor(i + 1).getPixels() for i in range(imp.getStackSize())]
  7. ipl = [p for pvals in ips for p in pvals]
  8. count = len(filter(lambda x: x==pixval, ipl))
  9. print "pixval=", pixval, " count:", count

RGB (Color) Image, Enhance Contrast each channel

To separately set min/max displayed pixel values, add the 3rd argument in setMinAndMax methods of ImageProcessor (in fact, this will be ColorProcessor).

  1. from ij import IJ
  2.  
  3. imp = IJ.getImage()
  4. stk = imp.getStack()
  5. for i in range(stk.getSize()):
  6. ip = stk.getProcessor(i + 1)
  7. # red channel = 4
  8. ip.setMinAndMax(46, 301, 4)
  9. # green channel = 2
  10. ip.setMinAndMax(29, 80, 2)
  11. # blue channel = 1
  12. ip.setMinAndMax(29, 80, 1)
  13. imp.updateAndDraw()

Translation of 3D image using ImgLib2

Translation of image using ImgLib2 affine transform, taking “flybrain” sample image as an example. A work of Christian Tischer with advices from Stephan Saalfeld.

  1. from ij import IJ, ImagePlus, Prefs
  2. from net.imglib2.img.imageplus import ImagePlusImgs
  3. from net.imglib2.view import Views
  4. from net.imglib2.realtransform import RealViews, Translation3D
  5. from net.imglib2.interpolation.randomaccess import NLinearInterpolatorFactory
  6. from net.imglib2.img.display.imagej import ImageJFunctions
  7.  
  8. # get fly brain sample image
  9. imp = ImagePlus(Prefs.getImagesURL() + "flybrain.zip")
  10.  
  11. # display the image before translation
  12. imp.show()
  13.  
  14. # convert ImagePlus to Img
  15. img = ImagePlusImgs.from(imp) # any different to the method above?
  16. print img
  17.  
  18. # prepare image for translation using interpolation: padding
  19. extended = Views.extendBorder(img)
  20. # prepare image for translation using interpolation: interpolate the image to get continuous image
  21. interpolant = Views.interpolate(extended, NLinearInterpolatorFactory())
  22.  
  23. # translation parameters
  24. dx=100; dy=50; dz=0;
  25. # construct Translation3D object
  26. transform = Translation3D(dx, dy, dz)
  27. # transformation
  28. transformed = RealViews.affine(interpolant, transform)
  29. # crop transformed image with the interval of original image
  30. cropped = Views.interval(transformed, img)
  31.  
  32. # display the image after translation in ImageJ1 frame work.
  33. ImageJFunctions.show(cropped)

Filters

Binary

With binary operations, it's important to explicitly set if the background is dark or light. In GUI this could be set by [Process > Binary > Options…] and check 'Black background'. Within scripts, you could do the same by

  1. from ij import Prefs
  2. Prefs.blackBackground = True

For those under [Process > Binary]:

  1. from ij.plugin.filter import Binary
  2.  
  3. imp = IJ.getImage()
  4. ip = imp.getProcessor()
  5. binner = Binary()
  6. binner.setup("fill", None)
  7. binner.run(ip)
  8. binner.setup("erode", None)
  9. binner.run(ip)
  10. binner.run(ip)
  11. binner.setup("dilate", None)
  12. binner.run(ip)
  13. binner.run(ip)

See the source:

Rank Filters

[Process > Filters > Minimum], with radius 20.

  1. from ij.plugin.filter import RankFilters
  2.  
  3. imp = IJ.getImage()
  4. imp2 = imp.duplicate()
  5. rf = RankFilters()
  6. rf.rank(imp2.getProcessor(), 20, RankFilters.MIN)
  7. imp2.show()

Gaussian Blur

For a radius of 2.0, following does the blurring same as GUI Gaussian Blur.

  1. from ij.plugin.filter import GaussianBlur
  2. radius = 2.0
  3. accuracy = 0.01
  4. GaussianBlur().blurGaussian( imp2.getProcessor(), radius, radius, accuracy)

As this works only with single 2D image, for-looping is required to process all frames / slices in a stack. For example:

  1. from ij.plugin.filter import GaussianBlur
  2. radius = 10.0
  3. accuracy = 0.01
  4. for i in range(imp2.getStackSize()):
  5. GaussianBlur().blurGaussian(imp2.getStack().getProcessor(i+1), radius, radius, accuracy)

For more explanation about this processing, see the explanation in javadoc.

Background Subtraction (Rolling Ball)

Menu item [Process > Subtract Background]

from ij import IJ
from ij.plugin.filter import BackgroundSubtracter

imp = IJ.getImage()

ip = imp.getProcessor()
radius = 50.0
createBackground = False
lightBackground = False
useParaboloid = False
doPresmooth = False
correctCorners = False

bs = BackgroundSubtracter()
bs.rollingBallBackground(ip, radius, createBackground, lightBackground, useParaboloid, doPresmooth, correctCorners)
imp.updateAndDraw()

If the image is in RGB, then use a different method (rollingBallBrightnessBackground​).

For more explanation about this processing, see the explanation in javadoc.

ImageCalculator

Combined use of erosion and Image Calculator to extract contour from binary image.

  1. from ij import IJ
  2. from ij.plugin.filter import Binary
  3. from ij.plugin import ImageCalculator
  4. from ij.plugin import Duplicator
  5.  
  6. imp = IJ.getImage()
  7. imp2 = Duplicator().run(imp)
  8. eroder = Binary()
  9. eroder.setup("erode", None)
  10. eroder.run(imp2.getProcessor())
  11. ImageCalculator().run("Subtract", imp, imp2)

The last line first argument should be added with more options to create a new image and / or to process stack. Below is an example to process all frames / slices in a stack and also create a new ImagePlus.

  1. imp3 = ImageCalculator().run("Subtract create stack", imp, imp2)

Watershed

  1. from ij.plugin.filter import EDM
  2.  
  3. ip = IJ.getImage().getProcessor()
  4. edm = EDM()
  5. if ip.isBinary is False:
  6. IJ.log("8-bit binary image (0 and 255) required.")
  7. else:
  8. edm.setup("watershed", None)
  9. edm.run(ip)

Source:

Find Maxima (+ RGB Merge)

Find Maxima has watershed based segmentation capability. This example segments images and then merges the segmented binary on top of the original image.

  1. from ij.plugin import RGBStackMerge
  2. from ij import ImagePlus, IJ
  3. from ij.process import ImageProcessor
  4. from ij.plugin.filter import MaximumFinder
  5. from jarray import array
  6. from ij import Prefs
  7. from ij.plugin.filter import Binary
  8.  
  9. imp = IJ.getImage()
  10. ip = imp.getProcessor()
  11. segip = MaximumFinder().findMaxima( ip, 10, ImageProcessor.NO_THRESHOLD, MaximumFinder.SEGMENTED , False, False)
  12. segip.invert()
  13. segimp = ImagePlus("seg", segip)
  14. segimp.show()
  15. mergeimp = RGBStackMerge.mergeChannels(array([segimp, None, None, imp, None, None, None], ImagePlus), True)
  16. mergeimp.show()

Filter 3D

[Process > Filters > Median 3D…]

Command recorder would log

IJ.run(imp, "Median 3D...", "x=4 y=4 z=4") 

This is OK, but to use the class in behind directly, below is the code written by Tiago Ferreira (see this link).

  1. from ij import IJ
  2. from ij import ImagePlus
  3. from ij.plugin import Filters3D
  4.  
  5. # 1. get image
  6. get = IJ.openImage("http://imagej.net/images/clown.jpg");
  7.  
  8. # 2. get the image stack within the ImagePlus
  9. stack = get.getStack()
  10.  
  11. # 3. Instantiate plugin [1]
  12. f3d = Filters3D()
  13.  
  14. # 4. Retrieve filtered stack
  15. newStack = f3d.filter(stack, f3d.MEDIAN, 4.0, 4.0, 4.0)
  16.  
  17. # 5. Construct an ImagePlus from the stack
  18. newImage = ImagePlus("Filtered Clown", newStack);
  19.  
  20. # 6. Display result
  21. newImage.show()

Analysis

Descriptive statistics

For calculating descriptive statistics, one way is to use apache commons math library. Below is an elementary example, but more could be done: for more, see here

  1. from org.apache.commons.math3.stat.descriptive import DescriptiveStatistics as DSS
  2.  
  3. rt = ResultsTable.getResultsTable()
  4. area = rt.getColumnAsDoubles(rt.getColumnIndex("Area"))
  5. print "Mean",dss.getMean()
  6. print "Meadian",dss.getPercentile(50)
  7. print dss

Weka has basic statistics classes under weka.experiment(especially the Class e.g. Stats), but I have not used them. I think I need weka textbook for the use of this rich resource.

JfreeChart also has statistics classes. See here. An example of detecting outliers is shown in below.

Particle Analysis

An example of applying particle analysis to a stack.

  1. from ij import IJ, ImagePlus
  2. from ij.plugin.filter import ParticleAnalyzer as PA
  3. from ij.measure import ResultsTable
  4.  
  5. imp = IJ.getImage()
  6.  
  7. MAXSIZE = 10000;
  8. MINSIZE = 100;
  9. options = PA.SHOW_ROI_MASKS \
  10. + PA.EXCLUDE_EDGE_PARTICLES \
  11. + PA.INCLUDE_HOLES \
  12. + PA.SHOW_RESULTS \
  13. rt = ResultsTable()
  14. p = PA(options, PA.AREA + PA.STACK_POSITION, rt, MINSIZE, MAXSIZE)
  15. p.setHideOutputImage(True)
  16. stk = ImageStack(imp.getWidth(), imp.getHeight())
  17.  
  18. for i in range(imp.getStackSize()):
  19. imp.setSliceWithoutUpdate(i + 1)
  20. p.analyze(imp)
  21. mmap = p.getOutputImage()
  22. stk.addSlice(mmap.getProcessor())
  23.  
  24. ImagePlus("tt", stk).show()

Detect Outliers

Outlier detection based on jfree library.

  1. from org.jfree.data.statistics import BoxAndWhiskerCalculator
  2. #http://www.jfree.org/jfreechart/api/javadoc/org/jfree/data/statistics/BoxAndWhiskerCalculator.html
  3. from java.util import ArrayList, Arrays
  4.  
  5. class InstBWC(BoxAndWhiskerCalculator):
  6. def __init__(self):
  7. pass
  8. rt = ResultsTable.getResultsTable()
  9. yposA = rt.getColumn(rt.getColumnIndex('x'))
  10. xposA = rt.getColumn(rt.getColumnIndex('y'))
  11. zposA = rt.getColumn(rt.getColumnIndex('z'))
  12. m0A = rt.getColumn(rt.getColumnIndex('m0'))
  13. scoreA = rt.getColumn(rt.getColumnIndex('NPscore'))
  14.  
  15. m0list = ArrayList(Arrays.asList(scoreA.tolist()))
  16. print m0list.size()
  17.  
  18. #bwc = BoxAndWhiskerCalculator()
  19. bwc = InstBWC()
  20. ans = bwc.calculateBoxAndWhiskerStatistics(m0list)
  21.  
  22. #http://www.jfree.org/jfreechart/api/javadoc/org/jfree/data/statistics/BoxAndWhiskerItem.html
  23.  
  24. print ans.toString()
  25. print ans.getOutliers()

Curve Fitting

Curve fitting using ImageJ CurveFitter class.

  1. from ij.measure import CurveFitter
  2. import jarray
  3.  
  4. #creat example data arrays
  5. xa = [1, 2, 3, 4]
  6. ya = [3, 3.5, 4, 4.5]
  7.  
  8. #convert to java array
  9. jxa = jarray.array(xa, 'd')
  10. jya = jarray.array(ya, 'd')
  11.  
  12. #construct a CurveFitter instance
  13. cf = CurveFitter(jxa, jya)
  14. #actual fitting
  15. #fit models: see http://rsb.info.nih.gov/ij/developer/api/constant-values.html#ij.measure.CurveFitter.STRAIGHT_LINE
  16. cf.doFit(CurveFitter.STRAIGHT_LINE)
  17. #print out fitted parameters.
  18. print cf.getParams()[0], cf.getParams()[1]

3D Viewer

Rotating, Zooming

Grab currently opened 3Dviewer (Image3DUniverse instance) and control the rotation and zooming. There seems to be several ways possible, and using ij3d.behaviors.ViewPlatformTransformer seems to be convenient.

  1. from ij3d import Image3DUniverse as i3d
  2. from javax.vecmath import Vector3d as v3d
  3. import sys
  4. from javax.media.j3d import Transform3D
  5. from ij3d.behaviors import ViewPlatformTransformer
  6. import time
  7.  
  8. univs = i3d.universes
  9. if univs.size() is 0:
  10. print 'no 3D viewer on desktop!'
  11. sys.exit(1)
  12. univ = univs.get(0)
  13.  
  14. vtf = ViewPlatformTransformer(univ, univ)
  15. x1z1 = v3d(1, 0, 1)
  16. univ.rotateToPositiveXY()
  17. vtf.zoomTo(1000)
  18. for zm in range(1,3000, 10):
  19. vtf.zoomTo(zm)
  20. vtf.rotate(x1z1, 0.03)
  21. time.sleep(0.01)
  22.  
  23. for zm in range(3000, 1000, -10):
  24. vtf.zoomTo(zm)
  25. vtf.rotate(x1z1, 0.03)
  26. time.sleep(0.01)

Accessing Time Line in 4D

Controlling animations of time series movie.

  1. from ij3d import Image3DUniverse as i3d
  2. import sys
  3. univs = i3d.universes
  4. if univs.size() is 0:
  5. print 'no 3D viewer on desktop!'
  6. sys.exit(1)
  7. univ = univs.get(0)
  8. tl = univ.getTimeline()
  9. tl.first()
  10. frames = tl.size()
  11. for i in range(frames):
  12. try:
  13. Thread.sleep(50)
  14. except InterruptedException, e:
  15. print 'wait error'
  16. tl.next()

Combined application with movie saving

Combination of aboves + saving snapshots as a stack.

  1. # movie making, using 4D stacks and 3D viewer
  2. from ij3d import Image3DUniverse as i3d
  3. from javax.vecmath import Vector3d as v3d
  4. import sys
  5. from javax.media.j3d import Transform3D
  6. from ij3d.behaviors import ViewPlatformTransformer
  7. import time
  8. univs = i3d.universes
  9. if univs.size() is 0:
  10. print 'no 3D viewer on desktop!'
  11. sys.exit(1)
  12. univ = univs.get(0)
  13.  
  14. vtf = ViewPlatformTransformer(univ, univ)
  15. x1z1 = v3d(1, 0, 1)
  16.  
  17. tl = univ.getTimeline()
  18. tl.first()
  19. frames = tl.size()
  20. rad = 0
  21. #win = univ.getWindow()
  22. imp = univ.takeSnapshot()
  23. stk = ImageStack(imp.width, imp.height)
  24. stk.addSlice(imp.getProcessor())
  25. while rad < 4:
  26. for i in range(frames):
  27. time.sleep(0.05)
  28. vtf.rotate(x1z1, 0.04)
  29. rad += 0.03
  30. stk.addSlice(univ.takeSnapshot().getProcessor())
  31. time.sleep(0.05)
  32. tl.next()
  33. tl.first()
  34.  
  35. ImagePlus('movie', stk).show()

Visualizing XYZ positions listed in Results table in 3Dviewer

I often need to visualize 3D distribution of XYZ coordiantes listed in the results table in 3D viewer. Below is an example of using results from ParticleTracker 2D/3D being plotted in the 3D viewer.

For using this with orther plugins such as ObjectCounter 3D, column header names need to be replaced.

  1. from javax.vecmath import Point3f, Color3f
  2. from java.util import ArrayList
  3. from ij3d import Image3DUniverse
  4. from customnode import CustomPointMesh
  5.  
  6. rt = ResultsTable.getResultsTable()
  7. yposA = rt.getColumn(rt.getColumnIndex('x'))
  8. xposA = rt.getColumn(rt.getColumnIndex('y'))
  9. zposA = rt.getColumn(rt.getColumnIndex('z'))
  10.  
  11. mesh = ArrayList()
  12. for i in range(len(xposA)):
  13. mesh.add(Point3f(xposA[i], yposA[i], zposA[i]))
  14.  
  15. univ = Image3DUniverse()
  16. univ.showAttribute(Image3DUniverse.ATTRIBUTE_COORD_SYSTEM, False)
  17. univ.show()
  18.  
  19. cm = CustomPointMesh(mesh)
  20. cm.setColor(Color3f(0, 1, 0))
  21. univ.addCustomMesh(cm, "points")
  22. cm.setPointSize(3)

Plugin: LOCI BioFormats

Importing CZI file

  1. from loci.plugins import BF
  2. from loci.plugins.in import ImporterOptions
  3.  
  4. filepath = "/path/to/image/my.czi"
  5.  
  6. # Options for Bioformats plugin, includeing the image path
  7. options = ImporterOptions()
  8. options.setOpenAllSeries(True)
  9. options.setShowOMEXML(False)
  10. options.setStitchTiles(False)
  11. options.setId(filepath)
  12. fullimps = BF.openImagePlus(options)
  13.  
  14. #fullimps now holds multiple images contained within the czi file.
  15. # open the first one.
  16. fullimps[0].show()

If you do not want to open all images (called sereies) in multi-image CZI files, replace

open.setOpenAllSeries(True) 

with

options.setSeriesOn(seriesIndex, True)

with “sereiesIndex” being the seriesID e.g. 1 or 2 or 3 …

See here for more on metadata parsing and so on: bio-formats.py

Count the number of image data set in a CZI file

For just knowing the number of images contained in a CZI file, you do not need to load full image (then it's faster).

  1. from loci.formats import ImageReader
  2.  
  3. r = ImageReader()
  4. filepath = '/to/my.czi'
  5. r.setId( filepath )
  6. print r.getSeriesCount()

Replacing OME-TIFF XML

  1. from loci.formats.tiff import TiffParser
  2. from loci.formats.tiff import TiffSaver
  3. from loci.common import DataTools
  4. from loci.common import RandomAccessInputStream
  5. from loci.common import RandomAccessOutputStream
  6. filepath = '/Users/miura/Desktop/test.ome.tif'
  7. # test reading out (no new lines)
  8. comment = TiffParser(filepath).getComment()
  9. print comment
  10. # replacing OME-XML
  11. xmlpath = '/Users/miura/Desktop/ometest.xml'
  12. newComment = DataTools.readFile(xmlpath)
  13. filein = RandomAccessInputStream(filepath)
  14. fileout = RandomAccessOutputStream(filepath)
  15. saver = TiffSaver(fileout, filepath)
  16. saver.overwriteComment(filein, newComment)
  17. filein.close()
  18. fileout.close()

If you are accessing from commandline, use “TiffComment” Bioformat Tool. For example,

tiffcomment test.ome.tif | xmlindent

outputs xml in your console. More on the udage of command line tools for dealing with OME-XML could be found here.

Plugin: FeatureJ

FeatureJ uses its own abstract class representing image data (imagescience.image.Image). For this, you first need to wrap ImagePlus object as Image object and do the processing.

Laplacian

  1. from ij import IJ
  2. from imagescience.image import Image as FJimage
  3. from imagescience.feature import Laplacian
  4.  
  5. imp = IJ.getImage()
  6. fjimg = FJimage.wrap(imp)
  7. fjimglap = Laplacian().run(fjimg, 1.0)
  8. imp2 = fjimglap.imageplus()
  9. imp2.show()

Plugin: Extended Depth of Field (Easy mode)

Usage of a plugin Extended Depth of Field (Easy mode) from script.

  1.  
  2. import jarray
  3. from edfgui import BasicDialog
  4.  
  5. imp = IJ.getImage()
  6. '''
  7. here need to check conditions of the image, it should not be less than
  8. - 4 pixel width
  9. - 4 pixel height
  10. - 2 slices
  11. '''
  12. imagesize = jarray.array([imp.getHeight(), imp.getHeight()], 'i')
  13. color = imp.getType() == ImagePlus.COLOR_RGB
  14. dl = BasicDialog(imagesize, color, False)
  15. # "quality='1' topology='0' show-view='on' show-topology='off'"
  16. quality = 1
  17. topology = 0
  18. showview = True
  19. showtopology= False
  20. dl.parameters.setQualitySettings(quality)
  21. dl.parameters.setTopologySettings(topology)
  22. dl.parameters.show3dView = showview
  23. dl.parameters.showTopology = showtopology
  24. dl.process()
  25.  

Plugin: Using Find Connected Regions

Find Connected Regions is a plugin that outputs connected regions as pixel-value-labeled image of connected regions. This function is similar to “Particle Analysis” and selecting “count masks” as output, but with a bit more capability in settings with less outputs (meaning less complex), and does even 3D connected components. Here is an example function.

def getNucLabels(segimp):
  fcrresults = FCR().run(segimp, True, True, True, True, True, False, False, 100, 600, 100, True)
  allregionimp =  fcrresults.allRegions
  perRegionlist = fcrresults.perRegion
  infolist =  fcrresults.regionInfo
  return allregionimp, perRegionlist, infolist

Returned values in the above example are:

  • allregionimp … a single image with labels for each region. Psudo color image.
  • perRegionlist … a list of binary label images, one slice per label.
  • infolist … a list of region infos.

Arguments for the run method are many, and here is what they are: <codes> run( ij.ImagePlus imagePlus, boolean diagonal, boolean imagePerRegion, boolean imageAllRegions, boolean showResults, boolean mustHaveSameValue, boolean startFromPointROI, boolean autoSubtract, double valuesOverDouble, double minimumPointsInRegionDouble, int stopAfterNumberOfRegions, boolean noUI) </code> More details of each of these setting parameters are available here. The source code is FindConnectedRegions.java within VIB.jar and could be accessed is here, which is a bit hidden as the plugin class (Find_Connected_Regions.java, in VIB_.jar) is a wrapper.

Some interesting discussions could be found in this fiji-dev thread.

Javadoc

Plugin: Anisotropic Diffusion

  1. from anisotropic_diffusion import Anisotropic_Diffusion_2D as AD
  2. def aniso2D(imp):
  3. ad = AD()
  4. ad.setNumOfIterations(20)
  5. ad.setSmoothings(10)
  6. ad.setSaveSteps(20)
  7. ad.setLimiterMinimalVariations(0.40)
  8. ad.setLimiterMaximalVariations(0.90)
  9. ad.setTimeSteps(20)
  10. ad.setEdgeThreshold(10.0)
  11. ad.setup("",imp)
  12. adimp = ad.runTD(imp.getProcessor())
  13. return adimp
  14.  
  15. imagepath = '/Volumes/D/20130305/l5c1-128.tif'
  16. imp = IJ.openImage(imagepath)
  17. adimp = aniso2D(imp)
  18. adimp.show()

Plugin: Advanced Weka Segmentation

Adding Eamples from ROI

Training and get Probability image using ROI set as examples (labels).

  1. from trainableSegmentation import WekaSegmentation
  2. from ij.plugin.frame import RoiManager
  3. from ij import IJ
  4. from ij.io import FileSaver
  5.  
  6. imp = IJ.openImage('http://imagej.nih.gov/ij/images/blobs.gif') #blobs
  7.  
  8. weka = WekaSegmentation()
  9. weka.setTrainingImage(imp)
  10.  
  11. rm = RoiManager(True)
  12. rm.runCommand('Open', '/Users/miura/Desktop/tmp/RoiSetc1.zip')
  13. roitable =rm.getROIs()
  14. keys = roitable.keys()
  15. for key in keys:
  16. weka.addExample(0, roitable.get(key), 1)
  17.  
  18. rm2 = RoiManager(True)
  19. rm2.runCommand('Open', '/Users/miura/Desktop/tmp/RoiSetc2.zip')
  20. roitable =rm2.getROIs()
  21. keys = roitable.keys()
  22. for key in keys:
  23. weka.addExample(1, roitable.get(key), 1)
  24.  
  25. if weka.trainClassifier():
  26. weka.applyClassifier(True)
  27. classifiedImage = weka.getClassifiedImage()
  28. classifiedImage.show()

Merging ARFF data files

import weka.core.Version
from weka.core import Instances
from weka.core.converters import ConverterUtils

print weka.core.Version().toString()
pp = '/ARFFdata/'
data1path = pp+ 'data1.arff'
data2path = pp+ 'data2.arff'

data1 = ConverterUtils.DataSource.read(data1path)
data2 = ConverterUtils.DataSource.read(data2path)
print "data1: ", data1.size()
print "data2: ", data2.size()

for i in range(data2.size()):
	data1.add(data2.get(i))

dataMerged = data1
print "Merged: ", dataMerged.size()

# if data1 and data2 have the same size, the line below can be used. 
#dataMerged = Instances.mergeInstances(data1, data2)

dataMargedPath = pp + "dataMerged.arff"

ConverterUtils.DataSink.write(dataMargedPath, dataMerged )

Merging ARFF data files in another way, train and apply classifier

from trainableSegmentation import WekaSegmentation
from ij import IJ

# == merging

pp = '/ARFFdata/'
data1path = pp+ 'data1.arff'
data2path = pp+ 'data2.arff'

ws = WekaSegmentation()
data1 = ws.readDataFromARFF(data1path)
data2 = ws.readDataFromARFF(data2path)
ws.mergeDataInPlace(data1, data2) #this concatenates data2 to data2
dataBalanced = WekaSegmentation.balanceTrainingData(data1) #optional: can balance the classes
ws.setLoadedTrainingData(dataBalanced)

dataOutpath = pp+ 'dataBalanced.arff'
ws.writeDataToARFF(dataBalanced, dataOutpath)

# == now train and apply a classifier to an image

if ws.trainClassifier():
	imp = IJ.getImage()
	classifiedImage = ws.applyClassifier(imp, 0, True)
	classifiedImage.show()

Plugin: CLAHE

Fiji plugin for local contrast enhancements.

  1. from mpicbg.ij.clahe import Flat, FastFlat
  2.  
  3. def stackCLAHE2(imp):
  4. for i in range(imp.getStackSize()):
  5. imp.setSlice(i+1)
  6. Flat.getInstance().run(imp, 49, 256, 3.0, None) # slow, as this will be more precise.
  7. #Flat.getFastInstance().run(imp, 49, 256, 3.0, None, False) # FastFlat will be faster and less acculate.
  8.  
  9. imp = IJ.getImage()
  10. stackCLAHE2(imp)

Javadoc

In case if you need to use “fast but not precise” method, use the class

Plugin: Gray Morphology

Here is an example of grayscale eroding.

  1. from mmorpho import StructureElement
  2. from mmorpho import MorphoProcessor
  3.  
  4. imp = IJ.getImage()
  5. se = StructureElement(StructureElement.CIRCLE, 0, 10.0, StructureElement.OFFSET0)
  6. morph = MorphoProcessor(se)
  7. morph.erode(imp.getProcessor())
  8. imp.updateAndDraw()

For other operations, see Javadoc

Plugin: Shape Smoothing

Shape smoothing by reducing the number of Fourier descriptors. The plugin page is here. The github page is here.

from ij import IJ
from de.biomedical_imaging.ij.shapeSmoothing import ShapeSmoothingUtil

# https://github.com/thorstenwagner/ij-shape-smoothing/blob/master/src/main/java/de/biomedical_imaging/ij/shapeSmoothing/ShapeSmoothingUtil.java

imp = IJ.getImage()
ss = ShapeSmoothingUtil()
ss.setBlackBackground(True)
# Relative proportion FDs (%) 
thresholdValue = 2
# FD in % or absolute number
thresholdIsPercentual = True
# If True, a table, containing all FDs, will be shown after processing
doOutputDescriptors = False

ss.fourierFilter(imp.getProcessor(), thresholdValue, thresholdIsPercentual, doOutputDescriptors)

Plugin: Auto Threshold

This example uses automatic threshoulder class in Fiji. THere is also a way to use original imageJ thresholder. See here.

  1. from fiji.threshold import Auto_Threshold
  2.  
  3. imp = IJ.getImage()
  4. hist = imp.getProcessor().getHistogram()
  5. lowTH = Auto_Threshold.Otsu(hist)
  6. print lowTH
  7.  
  8. # if you want to convert to mask, then
  9. imp.getProcessor().threshold(lowTH)

For the other algorithms for the automatic threshold value estimation, see the Javadoc.

Plugin: Auto Local Threshold

Here is an example using Bernsen method.

  1. from fiji.threshold import Auto_Local_Threshold as ALT
  2.  
  3. imp = IJ.getImage()
  4. #IJ.run(imp, "Auto Local Threshold", "method=Bernsen radius=45 parameter_1=0 parameter_2=0 white");
  5. thimp = ALT().exec(imp, "Bernsen", 45, 0, 0, False)
  6. print len(imp)
  7. imps[0].show()

Available methods are:

  • Bernsen
  • Mean
  • Median
  • MidGrey
  • Niblack
  • Sauvola

Returned value of the exec method is an array of object, namely ImagePlus. Array contains scaled images, if such option is selected.

Javadoc

Source

GLCM (Texture analysis)

Measureing Haralick features.

Clone the project below, compile and install it as a plugin. https://github.com/miura/GLCM2

  1. from emblcmci.glcm import GLCMtexture
  2. from ij import IJ
  3.  
  4. imp = IJ.getImage()
  5.  
  6. glmc = GLCMtexture(1, 45, True, False)
  7. ip = imp.getProcessor()
  8. ip8 = ip.convertToByte(True)
  9. glmc.calcGLCM(ip8)
  10. resmap = glmc.getResultsArray()
  11. pa = glmc.paramA
  12. for p in pa:
  13. print p, resmap.get(p)

Plugin: MiToBo h-dome transformation

h-dome is useful for spot detection in a noisy background. For example, see this reference. The example here uses Plugin MiToBo, a huge collection of various components.

from de.unihalle.informatik.MiToBo.core.datatypes.images import MTBImage
from de.unihalle.informatik.MiToBo.morphology import HDomeTransform3D
from ij import IJ

imp = IJ.getImage()
mtb = MTBImage.createMTBImage( imp.duplicate() )
hdome = HDomeTransform3D(mtb, 10.0)
hdome.runOp()
mtbdone = hdome.getResultImage()
imp2 = mtbdone.getImagePlus()
imp2.show()

Plugin: MorphoLibJ

Distance Transform Watershed 3D

from ij import IJ, ImagePlus
from inra.ijpb.binary import BinaryImages
from inra.ijpb.binary import ChamferWeights3D
from inra.ijpb.data.image import Images3D
from inra.ijpb.watershed import ExtendedMinimaWatershed


imp = IJ.getImage()

normalize = True
dynamic = 2
connectivity = 6

#weights = ChamferWeights3D.fromLabel(  ChamferWeights3D.BORGEFORS.toString() )
#weights = ChamferWeights3D.fromLabel(  "Borgefors (3,4,5)" )
weights = ChamferWeights3D.BORGEFORS.getShortWeights()
dist = BinaryImages.distanceMap( imp.getImageStack(),weights , normalize )
Images3D.invert( dist )
#public static final ImageStack extendedMinimaWatershed( ImageStack image, ImageStack mask, int dynamic, int connectivity, int outputType, boolean verbose )
# @param dynamic the maximum difference between the minima and the boundary of a basin
result = ExtendedMinimaWatershed.extendedMinimaWatershed(dist, imp.getImageStack(), dynamic, connectivity, 16, False )
outimp = ImagePlus( imp.getShortTitle() + "dist-watershed", result )
outimp.show()

Connected Component 3D labeling

from ij import IJ, ImagePlus
from inra.ijpb.binary import BinaryImages

imp = IJ.getImage()

connectivity = 6
outbitDepth = 16
outimp = BinaryImages.componentsLabeling(imp, connectivity, outbitDepth)
outimp.setTitle(imp.getShortTitle() + "-labeled")
outimp.show()

Kill Border Objects, 2D Binary image

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()

Plugin 3D ImageJ Suite

3D Suite plugin allows you to process / segment / measure 3D image data. In Fiji, all 3D suite related commands are available under: Plugins > 3D >

The plugin webpage is here: 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:

The Javadoc I created (Core and Plugins are merged):

Measureing Spherical 3D ROI positions

The code below shows how to measure spherical 3D ROI in an image. We first create 3 3D spheres and then use them for measuring the mean pixel intensity of those 3D ROIs within a synthetic gradient 3D image.

from ij import IJ, ImagePlus
from mcib3d.geom import ObjectCreator3D
from mcib3d.image3d import ImageHandler

oc3d = ObjectCreator3D(200, 200, 50)
oc3d.createSphere(50, 50, 10, 3, 1, False)
oc3d.createSphere(50, 50, 20, 3, 2, False)
oc3d.createSphere(50, 50, 30, 3, 3, False)

imp = oc3d.getPlus() 
#imp.show()

obj1 = 	oc3d.getObject3DVoxels(1)
obj2 = 	oc3d.getObject3DVoxels(2)
obj3 = 	oc3d.getObject3DVoxels(3)
 

impnew = IJ.createImage("Measured", 200,200, 50, 16)
stack = impnew.getStack()
for i in range(stack.getSize()):
	ip = stack.getProcessor(i + 1)
	ip.setColor( i * 5 )
	ip.fill()

ima = ImageHandler.wrap( impnew )

print "Obj1: ", obj1.getPixMeanValue(ima)
print "Obj2: ",obj2.getPixMeanValue(ima)
print "Obj3: ",obj3.getPixMeanValue(ima)

R: Multi-Peak fitting using R

This is an example script using R function to fit peak positions within intensity profile along a selected line ROI. For installation of Rserve, see here. The script uses the R package "Peaks".

The library “Peaks” only works under R version 2.x. With 3.0.1 and 3.0.2, it fails to work with an error message “#Error in .Call(“R_SpectrumSearchHighRes”, as.vector(y), …”.

  1. from org.rosuda.REngine.Rserve import RConnection
  2. from ij.gui import Roi, Overlay
  3. c = RConnection()
  4. x = c.eval("R.version.string")
  5. print x.asString()
  6. print c.eval("library(Peaks)").asString()
  7. imp = IJ.getImage()
  8. roi = imp.getRoi()
  9. if roi.getType() == Roi.LINE:
  10. print "a line roi"
  11. profile = roi.getPixels()
  12. c.assign("prof", profile)
  13. pks = c.eval("SpectrumSearch(prof, sigma=1, threshold=80, background=FALSE, iterations=20, markov=TRUE, window=10)").asList()
  14. pksX = pks[0].asIntegers()
  15. rois = []
  16. for i in pksX:
  17. print roi.x1, i
  18. rois.append(PointRoi(roi.x1, roi.y1 + i))
  19. ol = Overlay()
  20. for aroi in rois:
  21. ol.add(aroi)
  22. imp.setOverlay(ol)
  23. c.close()

Misc examples

Running a macro file from Jython

To run your custom ImageJ macro from Jython, here is an example.

from java.io import File
from ij.macro import MacroRunner

macropath = "/Users/miura/test.ijm"
macrofile =  File(macropath)
mr = MacroRunner(macrofile)

ImageJ Macro Keywords and Functions

Printing out ImageJ macro reserved words.

  1. from ij.macro import MacroConstants as MC
  2.  
  3. print "=== keywords ==="
  4. for f in MC.keywords:
  5. print f
  6.  
  7. print "=== functions (void) ==="
  8. for f in MC.functions:
  9. print f
  10.  
  11. print "=== functions (numeric) ==="
  12. for f in MC.numericFunctions:
  13. print f
  14.  
  15. print "=== funcitons (string) ==="
  16. for f in MC.stringFunctions:
  17. print f
  18.  
  19. print "=== functions (arrays) ==="
  20. for f in MC.arrayFunctions:
  21. print f

Implementing Interface

Here is an example of implementing PlugIn interface.

  1. from ij.plugin import PlugIn
  2.  
  3. class GreatPlugin(PlugIn):
  4. def __init__ (self):
  5. print "This is GreatPlugin class which implements a java interface ij.plugin.Plugin"
  6. def run(self):
  7. IJ.open('http://imagej.nih.gov/ij/images/blobs.gif')
  8. def anotherrun(self):
  9. imp = IJ.openImage('http://imagej.nih.gov/ij/images/blobs.gif')
  10. imp.getProcessor().invert()
  11. imp.show()
  12.  
  13. gp = GreatPlugin()
  14. gp.run()
  15. gp.anotherrun()

See explanation in here.

Shell Command

To run Shell command in OSX, here is an example.

from java.lang import Runtime
from java.util import Scanner

def runShellCommand( cmd ):
	proc = Runtime.getRuntime().exec(cmd)
	istream = proc.getInputStream()
	scan = Scanner(istream).useDelimiter("\\n")
	for ss in scan:
		print ss
		

runShellCommand( "pwd" )
runShellCommand( "ls -la" )

Is docker daemon running?

Check if the docker daemon is running ():

  1. from java.lang import Runtime
  2. from java.util import Scanner
  3.  
  4.  
  5. def checkDockerRunning( cmd ):
  6. proc = Runtime.getRuntime().exec(cmd)
  7. inputst = proc.getInputStream()
  8. s = Scanner(inputst).useDelimiter("\\n")
  9. if not s.hasNext():
  10. print "Please start docker desktop!"
  11. return False
  12. for ss in s:
  13. print ss
  14. if ss.startswith("CONTAINER ID"):
  15. return True
  16. else:
  17. print "Please start docker desktop!"
  18. return False
  19.  
  20. # below is for OSX. WIth win, just "docker ps"
  21. cmd = "/usr/local/bin/docker ps"
  22. if checkDockerRunning( cmd ):
  23. print "Docker running"
  24. else:
  25. print "Docker not running"

JAVADOCS

Discussions?

I closed the discussion interface below, as it became the target of spam server. Please post your comments / questions to twitter (@cmci_).

documents/120206pyip_cooking/python_imagej_cookbook.txt · Last modified: 2024/10/08 17:45 by kota

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki