User Tools

Site Tools


Sidebar

documents:120206pyip_cooking:python_imagej_cookbook

Table of Contents

Python + ImageJ, Fiji Cookbook

This page was last edited at: 2016/07/04 06:16

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.

from ij import IJ
import struct

def s2u8bit(v):
    return struct.unpack("B", struct.pack("b", v))[0]
 
imp = IJ.getImage()
signedpix = imp.getProcessor().getPixels()
 
pix = map(s2u8bit,signedpix)
 
#check that the conversion worked. 
# this example was made for binary image, to print only values 255  
for j in range(len(pix)):
        curval = pix[j]
        #curval = s2u8bit(curval)
        if curval is 0:
            print '--'
        else:
            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.

from ij import IJ
import jarray

imp = IJ.openImage("http://imagej.nih.gov/ij/images/blobs.gif")
imp.show()

# ImageProcessor.getPixels() returns an array of signed pixel values
signedpix = imp.getProcessor().getPixels()

# converting signed pixel values to unsigned using bitwise operation. 
# & 0xff : 8bit
# & 0xffff : 16bit
# & 0xffffffff : 32bit 
unsignedpix = map(lambda p: p & 0xff, signedpix)

# replace pixels with value more than 50 and less than 200 to 0. 
replaced_unsignedpix = map(lambda p: p if (p < 200) and (p > 50) else 0, unsignedpix)

# convert signed pixel values to unsigned. 
replaced_signedpix = map(lambda p: (p - 256) if p > 127 else p, replaced_unsignedpix)

# python array to java array. 
jreplaced_signedpix = jarray.array(replaced_signedpix, 'b')

imp.getProcessor().setPixels(jreplaced_signedpix)
imp.updateAndDraw()

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

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

Data IO

Getting path to a file interactively

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

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/

import re

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

Loading Image from File system.

Four ways to open image

from ij import IJ, ImagePlus
from ij.io import Opener

srcpath = '/tt/img.tif'

# uisng constructor
imp1 = ImagePlus(srcpath)

# using IJ static method
imp2 = IJ.openImage(srcpath)

# Using Opener class
imp3 = Opener().openImage(srcpath)

# using LOCI BioFormats
from loci.plugins import BF
# returned is an array of ImagePlus, in many cases just one imp.  
imps = BF.openImagePlus(src)
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.

from ij.io import TiffDecoder

# using 'mitosis (5d)' sample image. 
directory = '/tmp/examples/'
filename = 'mitosis.tif'
td = TiffDecoder(directory, filename)
imginfos = td.getTiffInfo()
print 'Resolution: ', imginfos[0].unit, '/ pixel' 
print 'x resoluition:', imginfos[0].pixelWidth
print 'y resoluition:', imginfos[0].pixelHeight

# to print various image parameters
print imginfos[0].description
print '---'
# to print imgage optional info
print imginfos[0].info

Path operations

To extract file name and file name without extension,

import os 
srcpath = '/Users/miura/tmp/data.csv'
filename = os.path.basename(srcpath)
print filename #prints data.csv

parentdirectory = os.path.dirname(srcpath)
print parentdirectory #prints /Users/miura/tmp

print os.path.join(parentdirectory, filename) #prints same as srcpath

#above is enough to join directory and file name,
# but if you specifically want to use path separator of the os
print os.sep 

#filename without extension
print os.path.splitext(filename)[0] #prints /Users/miura/tmp/data

Alternatively, one could use File class in Java.

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

Loading CSV file

from ij import IJ
from util.opencsv import CSVReader
from java.io import FileReader

def readCSV(filepath):
   reader = CSVReader(FileReader(filepath), ",")
   ls = reader.readAll()
   for item in ls:
   	  IJ.log(item[4])

filepath = '/Users/miura/test.csv'
readCSV(filepath)

WIth purely pythonic way:

import csv

filepath = '/Users/miura/Dropbox/ToDo/Pavel/data.txt'
f = open(filepath, 'rb')
data = csv.reader(f, delimiter=' ')
for row in data:
	print(len(row))
	print ', '.join(row)

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

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

see here for more details.

Saving CSV file (data table)

Uses opencsv library, which is preinstalled in Fiji.

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("c:/temp/testcsv.csv"), ',')
data = Array.newInstance(Class.forName("java.lang.String"), 3)
#String[] entries = "first#second#third".split("#");
data[0] = str(11)
data[1] = str(23)
data[2] = str(5555)
writer.writeNext(data)
writer.close()

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

from util.opencsv import CSVWriter
from java.io import FileWriter
from java.lang import String
from jarray import array as jarr
 
writer = CSVWriter(FileWriter("/Users/miura/Desktop/eggs1.csv"), ',')
header = ['x', 'y', 'z']
jheader = jarr(header, String)
data = [11,23,5555]
datas = map(str, data)
jdata = jarr(datas, String)
writer.writeNext(jheader)
writer.writeNext(jdata)
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.

import csv

f = open('/Users/miura/Desktop/eggs2.csv', 'wb')
writer = csv.writer(f)
writer.writerow(['does this work'])
writer.writerow(['Spam', 'Lovely Spam', 'Wonderful Spam'])
#can chop down more
writer.writerows(['Spam', 'Lovely Spam', 'Wonderful Spam'])
f.close()

… a bit more realistic, writing numerical data.

'''
writing data to a csv file. 
'''
import os, csv

# prepare test data to wirte to a csv file
data1 = range(10)
data2 = [x * x for x in data1]
data3 = [pow(x, 3) for x in data1]
print data3

# prepare path
root = "/Users/miura/Desktop"
filename = "testdata.csv"
fullpath = os.path.join(root, filename)
print fullpath

# open the file first (if its not there, newly created)
f = open(fullpath, 'wb')

# create csv writer
writer = csv.writer(f)

# for loop to write each row
for i in range(len(data1)):
	row = [data1[i], data2[i], data3[i]]
	writer.writerow(row)

#writer.writerows([data1, data2, data3])

# close the file. 
f.close()

Accessing multiple files to load image sequences

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

from ij import IJ
from ij.io import DirectoryChooser 
import os

def run():
   srcDir = DirectoryChooser("Choose!").getDirectory()
   IJ.log("directory: "+srcDir)
   theIndex = {}
   for root, directories, filenames in os.walk(srcDir):
      for filename in filenames:
         if not filename.endswith(".tif"):
            continue
         #IJ.log(filename)
         treatment, well, position, z, time, channel = filename.split("--")
         identifier = treatment + '--' + well + '--' + position
         theIndex[identifier] = theIndex.get(identifier, []) + [time]
         #IJ.log("identifier: "+identifier)
         #IJ.log("time: "+time)

   print(theIndex.keys())

   for index in theIndex.keys():
      print(index)
      cmd = "Image Sequence..."
      options = "open="+srcDir+"  or="+index+".*--gfp.tif sort"	
      IJ.run(cmd, options)
      
run()

Accessing tiff stack via Virtual Stack class

from ij.io import OpenDialog
from ij.io import TiffDecoder
from ij.plugin import FileInfoVirtualStack
 
od = OpenDialog("stack", "")
td = TiffDecoder(od.getDirectory(), od.getFileName())
info = td.getTiffInfo()
fi = info[0]
print fi.nImages
vs = FileInfoVirtualStack(fi, False)
for i in range(1,fi.nImages):
    ip = vs.getProcessor(i)
    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.

from ij.io import OpenDialog
from ij.io import TiffDecoder
from ij.plugin import FileInfoVirtualStack
from ij import ImagePlus
 
od = OpenDialog("stack", "")
td = TiffDecoder(od.getDirectory(), od.getFileName())
info = td.getTiffInfo()
fi = info[0]
print fi.nImages
vs = FileInfoVirtualStack(fi, False)
imp = ImagePlus("testVirtual", vs)
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.

from ij import IJ
import os

savepath = IJ.getDirectory("")
imp = IJ.getImage()
ssize = imp.getStackSize()
titleext = imp.getTitle()
title = os.path.splitext(titleext)[0]
dimA = imp.getDimensions()
for c in range(dimA[2]):
	for z in range(dimA[3]):
		for t in range(dimA[4]):
			imp.setPosition(c+1, z+1, t+1)
			print c, z, t
			numberedtitle = \
			title + "_c" + IJ.pad(c, 2) + \
			"_z" + IJ.pad(z, 4) + \
			"_t" + IJ.pad(t, 4) + ".tif"
			stackindex = imp.getStackIndex(c + 1, z + 1, t + 1)
			aframe = ImagePlus(numberedtitle, imp.getStack().getProcessor(stackindex))
			IJ.saveAs(aframe, "TIFF", savepath + numberedtitle)
			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/cmci/6453158

import os
import re
from ij import IJ
from ij.io import Opener
from ij.plugin import Concatenator
from jarray import array
 
srcpath = IJ.getFilePath('Choose the first file')
filename = os.path.basename(srcpath)
srcDir = os.path.dirname(srcpath)
 
#chosefile = '20130711_R1_GR001_B1_L2.lsm'
#pattern = re.compile('(.*)_R(.*)_GR(.*)_B(.*)_L(.*)\.lsm')
pattern = re.compile('(.*)_R(.*)_GR(.*)_B(.*)_L(.*)\.(.*)')
 
res = re.search(pattern, filename)
 
basename = res.group(1)
repetition = res.group(2)
grouprepetition = res.group(3)
block = res.group(4)
location = res.group(5)
extension = res.group(6)
 
GRlist = []
for root, directories, filenames in os.walk(srcDir):
	for filename in filenames:
		match = re.search(pattern, filename)
		if match is not None:
			#print filename, match.group(3)
			GRlist.append(match.group(3))
 
print srcDir
print 'files: ', len(GRlist)
 
GRlist = sorted(GRlist)
timeseries = []
 
for timepoint in GRlist:
	thisfile = basename + '_R' + repetition + '_GR' + timepoint + '_B' + block + '_L' + location + '.' + extension
	print thisfile
	imp = Opener.openUsingBioFormats(os.path.join(srcDir, thisfile))
	imp.setOpenAsHyperStack(False)
	timeseries.append(imp)
 
newname = basename + '_R' + repetition + '_B' + block + '_L' + location + '.' + extension
calib = timeseries[0].getCalibration()
dimA = timeseries[0].getDimensions()
jaimp = array(timeseries, ImagePlus)
ccc = Concatenator()
#allimp = ccc.concatenateHyperstacks(jaimp, newname, False)
allimp = ccc.concatenate(jaimp, False)
allimp.setDimensions(dimA[2], dimA[3], len(GRlist))
allimp.setCalibration(calib)
allimp.setOpenAsHyperStack(True)
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.

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

Downloading a CSV file from Internet and save locally

Using IJ method.

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

Only in Java

from ij import IJ
from ij.io import Opener
from java.io import File, FileOutputStream
from java.net import URL
from java.lang import Long
from java.nio.channels import Channels


websitecsv = URL("http://cmci.info/imgdata/tenFrameResults.csv")
csvchannel  = Channels.newChannel(websitecsv.openStream())

ff = File("/Users/miura/tmp/test.csv")
if not ff.exists():
   ff.createNewFile()
fos = FileOutputStream(ff)
fos.getChannel().transferFrom(csvchannel, 0, Long.MAX_VALUE)
fos.close()
IJ.log("done")

Arrays

Concatenate Arrays

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

will prints

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

in the console.

Remove redundant elements in an Array

a=[1,2,3,4,5,5] 
a=list(set(a))
a.sort()
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.

import jarray

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,

import jarray
from ij import IJ
from ij.plugin RGBStackMerge

imp1 = IJ.openImage(path1)
imp2 = IJ.openImage(path2)
imgarray = jarray.array([imp1, imp2], ImagePlus)
colorimp = RGBStackMerge().mergeHyperstacks(imgarray, False) 

Combined Sort of Lists

from operator import itemgetter
ll = [1, 2, 3, 4]
ll2 = [5, 7, 8, 6]
aa = sorted(zip(ll, ll2), key=itemgetter(1), reverse=True)
print aa
ll, ll2 = zip(*aa)
print list(ll)
print list(ll2)
# in one line
# 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.

a = [1, 2, 3, 4]
b = [10, 20, 30, 40]

for aa, bb in zip(a, b):
	c = aa + bb
	print c

zip command creates a list of tuples from elements of arrays a and b.

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.

from java.awt.event import KeyEvent, KeyAdapter
from os.path import basename, splitext

path = "/Users/miura/Desktop/tmp/val_p1_c2.tsv"
filename = splitext(basename(path))[0]

# imp will be something like a global variable. accessible from 
# funcitons. 
imp = IJ.getImage()

def doSomething(imp, keyEvent):
   """ A function to react to key being pressed on an image canvas. """
   IJ.log("clicked keyCode " + str(keyEvent.getKeyCode()) + " on image " +
str(imp.getTitle()))
   # Prevent further propagation of the key event:
   keyEvent.consume()

class ListenToKey(KeyAdapter):
   def keyPressed(this, event):
      eventSrc = event.getSource()
      tp = eventSrc.getParent() #panel is the parent, canvas being component. 
      print eventSrc
      print tp
      print "selected line:", tp.getSelectionEnd()
      print "...", tp.getLine(tp.getSelectionEnd()) 
      
      #imp = event.getSource()
      doSomething(imp, event)

# - - - M A I N - - -

listener = ListenToKey()

txtfile = open(path)
tw = TextWindow("Results_" + filename, txtfile.readlines(1)[0], "", 300,
700)

for line in txtfile.readlines():
   frame, dist, volChI, volChII = line.split("\t")
   tw.append(str(frame) + "\t" + str(dist) + "\t" + str(volChI) + "\t" +
str(volChII))

tw.getTextPanel().addKeyListener(listener)

HashMap

Python

Maps are called Dictionary in Python.

To split a dictionary to key lists and value lists:

results = {'mean': 10.0, 'sd': 3.3}
headers = results.keys()
values = results.values()
print headers
print values

Java

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

from java.util import HashMap, Collections

tt = HashMap()
tt.put(1, "1")
tt.put(200, "2")
tt.put(2, "2")

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

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

to RGB

from ij import IJ
from ij.process import ImageConverter
imp = IJ.getImage()
ImageConverter(imp).convertToRGB() 

to 8bit grayscale

from ij import IJ
from ij.process import ImageConverter
imp = IJ.getImage()
ImageConverter(imp).convertToGray8() 

Channel Splitter

[Image > Color > Split Channels]

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

Z projection

# example script for z projection
# extracts first time point from a 4D stack and do maximum intensity Z-projection
from ij import IJ
from ij.plugin import ZProjector
from emblcmci import Extractfrom4D

def maxZprojection(stackimp):
	zp = ZProjector(stackimp)
	zp.setMethod(ZProjector.MAX_METHOD)
	zp.doProjection()
	zpimp = zp.getProjection()
	return zpimp

imp = IJ.getImage()
e4d = Extractfrom4D()
e4d.setGstarttimepoint(1)
IJ.log("current time point" + str(1))
aframe = e4d.coreheadless(imp, 3)
outimp = maxZprojection(aframe)
outimp.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.

# an example with lower and upper threshold values, 100 and 125.
from ij import IJ, ImagePlus
from ij.process import ImageProcessor
from ij.plugin.filter import ThresholdToSelection
 
imp = IJ.getImage()
imp.getProcessor().setThreshold(100, 125, ImageProcessor.NO_LUT_UPDATE)
roi = ThresholdToSelection.run(imp)
imp.setRoi(roi)
maskimp = ImagePlus("Mask", imp.getMask())
maskimp.show()

ROI manager

Removing all ROIs from the ROI manager.

rm = RoiManager.getInstance()
ht = rm.getList()
ht.removeAll()

which is equivalent to

rm = RoiManager.getInstance()
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")
# loading an image from the imagej site
# if you want to load an image from local, replace the URL with a file path
imp = ImagePlus('http://imagej.nih.gov/ij/images/boats.gif') 

# uncomment the following line if you want to see the image
#imp.show() 

# RoiManager should be present
rm = RoiManager.getInstance()

ip = imp.getProcessor()
#rm.setVisible(False) 

# Instead of multimeasure command in RoiManager, get an array of ROIs.
ra = rm.getRoisAsArray()

# loop through ROI array and do measurements. 
# here is only listing mean intensity of ROIs
# if you want more, see 
# http://rsbweb.nih.gov/ij/developer/api/ij/process/ImageStatistics.html
for r in ra:
	ip.setRoi(r)
	istats = ip.getStatistics()
	print istats.mean

Associating multiple ROIs

For combining multiple ROIs, ShapeRoi class is useful.

sr1 = ShapeRoi(roi1)
sr2 = ShapeRoi(roi2)
sr3 = sr1.or(sr2)

sr3 is then a combination of ROIs roi1 and roi2.

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.

from ij.plugin.filter import ThresholdToSelection
from ij.plugin.frame import RoiManager

rm = RoiManager()
segimp = IJ.getImage()
segimp.getProcessor().setThreshold(0, 0, ImageProcessor.NO_LUT_UPDATE)
boundroi = ThresholdToSelection.run(segimp)
rm.addRoi(boundroi)

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.

The jython script shown below is the re-written version based on original Java code. You could see the Java code in the git repo, line 739-767.

# rewriting "Auto contrast adjustment" button of "Brightness/Contrast" 
# Kota Miura
# 20120515

autoThreshold = 0
AUTO_THRESHOLD = 5000

imp = IJ.getImage()
cal = imp.getCalibration()
imp.setCalibration(None)
stats = imp.getStatistics() # get uncalibrated stats
imp.setCalibration(cal)
limit = int(stats.pixelCount/10)
histogram = stats.histogram #int[]
if autoThreshold<10:
	autoThreshold = AUTO_THRESHOLD
else:
	autoThreshold /= 2
threshold = int(stats.pixelCount/autoThreshold)	#int
print "pixelCount", stats.pixelCount
print "threshold", threshold
print "limit", limit
i = -1
found = False
count = 0 # int
while True:
   i += 1
   count = histogram[i]
   if count>limit:
      count = 0
   found = count> threshold
   if found or i>=255:
#   if 0 not in (!found, i<255) :
      break
hmin = i #int
i = 256
while True:
   i -= 1
   count = histogram[i]
   if count>limit:
      count = 0
   found = count> threshold
   if found or i<1:
#   if 0 not in (!found, i<255) :
      break
hmax = i #int

print "minimum", hmin
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.

from ij import IJ

imp = IJ.getImage()
pixval = 100
count = 0
ips = [imp.getStack().getProcessor(i + 1).getPixels() for i in range(imp.getStackSize())]
ipl = [p for pvals in ips for p in pvals]
count = len(filter(lambda x: x==pixval, ipl))
print "pixval=", pixval, " count:", count

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.

from ij import IJ, ImagePlus, Prefs
from net.imglib2.img.imageplus import ImagePlusImgs
from net.imglib2.view import Views
from net.imglib2.realtransform import RealViews, Translation3D
from net.imglib2.interpolation.randomaccess import NLinearInterpolatorFactory
from net.imglib2.img.display.imagej import ImageJFunctions

# get fly brain sample image
imp = ImagePlus(Prefs.getImagesURL() + "flybrain.zip")

# display the image before translation
imp.show()

# convert ImagePlus to Img
img = ImagePlusImgs.from(imp) # any different to the method above?
print img

# prepare image for translation using interpolation: padding 
extended = Views.extendBorder(img) 
# prepare image for translation using interpolation: interpolate the image to get continuous image
interpolant = Views.interpolate(extended, NLinearInterpolatorFactory()) 

# translation parameters
dx=100; dy=50; dz=0;
# construct Translation3D object
transform = Translation3D(dx, dy, dz)
# transformation
transformed = RealViews.affine(interpolant, transform)
# crop transformed image with the interval of original image
cropped = Views.interval(transformed, img)

# display the image after translation in ImageJ1 frame work. 
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

from ij import Prefs
Prefs.blackBackground = True

For those under [Process > Binary]:

from ij.plugin.filter import Binary

imp = IJ.getImage()
ip = imp.getProcessor()
binner = Binary()
binner.setup("fill", None)
binner.run(ip)
binner.setup("erode", None)
binner.run(ip)
binner.run(ip)
binner.setup("dilate", None)
binner.run(ip)
binner.run(ip)

See the source:

Rank Filters

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

from ij.plugin.filter import RankFilters

imp = IJ.getImage()
imp2 = imp.duplicate()
rf = RankFilters()
rf.rank(imp2.getProcessor(), 20, RankFilters.MIN)
imp2.show()

Gaussian Blur

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

from ij.plugin.filter import GaussianBlur
radius = 2.0
accuracy = 0.01
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:

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

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.

from ij import IJ
from ij.plugin.filter import Binary
from ij.plugin import ImageCalculator
from ij.plugin import Duplicator

imp = IJ.getImage()
imp2 = Duplicator().run(imp)
eroder = Binary()
eroder.setup("erode", None)
eroder.run(imp2.getProcessor())
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.

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

Watershed

from ij.plugin.filter import EDM

ip = IJ.getImage().getProcessor()
edm = EDM()
if ip.isBinary is False:
	IJ.log("8-bit binary image (0 and 255) required.")
else:
	edm.setup("watershed", None)
	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.

from ij.plugin import RGBStackMerge
from ij import ImagePlus, IJ
from ij.process import ImageProcessor
from ij.plugin.filter import MaximumFinder
from jarray import array
from ij import Prefs
from ij.plugin.filter import Binary

imp = IJ.getImage()
ip = imp.getProcessor()
segip = MaximumFinder().findMaxima( ip, 10, ImageProcessor.NO_THRESHOLD, MaximumFinder.SEGMENTED , False, False)
segip.invert()
segimp = ImagePlus("seg", segip)
segimp.show()
mergeimp = RGBStackMerge.mergeChannels(array([segimp, None, None, imp, None, None, None], ImagePlus), True)
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).

from ij import IJ 
from ij import ImagePlus 
from ij.plugin import Filters3D 

# 1. get image 
get = IJ.openImage("http://imagej.net/images/clown.jpg"); 

# 2. get the image stack within the ImagePlus 
stack = get.getStack() 

# 3. Instantiate plugin [1] 
f3d = Filters3D() 

# 4. Retrieve filtered stack 
newStack = f3d.filter(stack, f3d.MEDIAN, 4.0, 4.0, 4.0) 

# 5. Construct an ImagePlus from the stack 
newImage = ImagePlus("Filtered Clown", newStack); 

# 6. Display result 
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

from org.apache.commons.math3.stat.descriptive import DescriptiveStatistics as DSS

rt = ResultsTable.getResultsTable()
area = rt.getColumnAsDoubles(rt.getColumnIndex("Area"))
print "Mean",dss.getMean()
print "Meadian",dss.getPercentile(50)
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.

from ij.plugin.filter import ParticleAnalyzer as PA
imp = IJ.getImage()

MAXSIZE = 10000;
MINSIZE = 100;
options = PA.SHOW_ROI_MASKS \
	+ PA.EXCLUDE_EDGE_PARTICLES \
	+ PA.INCLUDE_HOLES \
	+ PA.SHOW_RESULTS \
rt = ResultsTable()
p = PA(options, PA.AREA + PA.STACK_POSITION, rt, MINSIZE, MAXSIZE)
p.setHideOutputImage(True)
stk = ImageStack(imp.getWidth(), imp.getHeight())

for i in range(imp.getStackSize()):
	imp.setSliceWithoutUpdate(i + 1)
	p.analyze(imp)
	mmap = p.getOutputImage()
	stk.addSlice(mmap.getProcessor())

ImagePlus("tt", stk).show()

Detect Outliers

Outlier detection based on jfree library.

from org.jfree.data.statistics import BoxAndWhiskerCalculator
#http://www.jfree.org/jfreechart/api/javadoc/org/jfree/data/statistics/BoxAndWhiskerCalculator.html
from java.util import ArrayList, Arrays

class InstBWC(BoxAndWhiskerCalculator):
    def __init__(self):
        pass
rt = ResultsTable.getResultsTable()
yposA = rt.getColumn(rt.getColumnIndex('x'))
xposA = rt.getColumn(rt.getColumnIndex('y'))
zposA = rt.getColumn(rt.getColumnIndex('z'))
m0A = rt.getColumn(rt.getColumnIndex('m0'))
scoreA = rt.getColumn(rt.getColumnIndex('NPscore'))

m0list = ArrayList(Arrays.asList(scoreA.tolist()))
print m0list.size()

#bwc = BoxAndWhiskerCalculator()
bwc = InstBWC()
ans = bwc.calculateBoxAndWhiskerStatistics(m0list)

#http://www.jfree.org/jfreechart/api/javadoc/org/jfree/data/statistics/BoxAndWhiskerItem.html

print ans.toString()
print ans.getOutliers()

Curve Fitting

Curve fitting using ImageJ CurveFitter class.

from ij.measure import CurveFitter
import jarray

#creat example data arrays
xa = [1, 2, 3, 4]
ya = [3, 3.5, 4, 4.5]

#convert to java array
jxa = jarray.array(xa, 'd')
jya = jarray.array(ya, 'd')

#construct a CurveFitter instance
cf = CurveFitter(jxa, jya)
 
#actual fitting
#fit models: see http://rsb.info.nih.gov/ij/developer/api/constant-values.html#ij.measure.CurveFitter.STRAIGHT_LINE
cf.doFit(CurveFitter.STRAIGHT_LINE)
 
#print out fitted parameters.
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.

from ij3d import Image3DUniverse as i3d
from javax.vecmath import Vector3d as v3d
import sys
from javax.media.j3d import Transform3D
from ij3d.behaviors import ViewPlatformTransformer
import time

univs = i3d.universes
if univs.size() is 0:
   print 'no 3D viewer on desktop!'
   sys.exit(1)
univ = univs.get(0)

vtf = ViewPlatformTransformer(univ, univ)
x1z1 = v3d(1, 0, 1)
univ.rotateToPositiveXY()
vtf.zoomTo(1000)
for zm in range(1,3000, 10):
	vtf.zoomTo(zm)
	vtf.rotate(x1z1, 0.03)
	time.sleep(0.01)

for zm in range(3000, 1000, -10):
	vtf.zoomTo(zm)
	vtf.rotate(x1z1, 0.03)
	time.sleep(0.01)

Accessing Time Line in 4D

Controlling animations of time series movie.

from ij3d import Image3DUniverse as i3d
import sys
 
univs = i3d.universes
if univs.size() is 0:
   print 'no 3D viewer on desktop!'
   sys.exit(1)
univ = univs.get(0)
tl = univ.getTimeline()
tl.first()
frames = tl.size()
for i in range(frames):
	try:
		Thread.sleep(50)
	except InterruptedException, e:
		print 'wait error'
	tl.next()

Combined application with movie saving

Combination of aboves + saving snapshots as a stack.

# movie making, using 4D stacks and 3D viewer
from ij3d import Image3DUniverse as i3d
from javax.vecmath import Vector3d as v3d
import sys
from javax.media.j3d import Transform3D
from ij3d.behaviors import ViewPlatformTransformer
import time
 
univs = i3d.universes
if univs.size() is 0:
   print 'no 3D viewer on desktop!'
   sys.exit(1)
univ = univs.get(0)

vtf = ViewPlatformTransformer(univ, univ)
x1z1 = v3d(1, 0, 1)

tl = univ.getTimeline()
tl.first()
frames = tl.size()
rad = 0
#win = univ.getWindow()
imp = univ.takeSnapshot()
stk = ImageStack(imp.width, imp.height)
stk.addSlice(imp.getProcessor())
while rad < 4:
	for i in range(frames):
		time.sleep(0.05)
		vtf.rotate(x1z1, 0.04)
		rad += 0.03
		stk.addSlice(univ.takeSnapshot().getProcessor())
		time.sleep(0.05)
		tl.next()
	tl.first()

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.

from javax.vecmath import Point3f, Color3f
from java.util import ArrayList
from ij3d import Image3DUniverse
from customnode import CustomPointMesh

rt = ResultsTable.getResultsTable()
yposA = rt.getColumn(rt.getColumnIndex('x'))
xposA = rt.getColumn(rt.getColumnIndex('y'))
zposA = rt.getColumn(rt.getColumnIndex('z'))

mesh = ArrayList()
for i in range(len(xposA)):
	mesh.add(Point3f(xposA[i], yposA[i], zposA[i]))

univ = Image3DUniverse()
univ.showAttribute(Image3DUniverse.ATTRIBUTE_COORD_SYSTEM, False)
univ.show()

cm = CustomPointMesh(mesh)
cm.setColor(Color3f(0, 1, 0))
univ.addCustomMesh(cm, "points")
cm.setPointSize(3)

Plugin: LOCI BioFormats, Replacing OME-TIFF XML

from loci.formats.tiff import TiffParser
from loci.formats.tiff import TiffSaver
from loci.common import DataTools
from loci.common import RandomAccessInputStream
from loci.common import RandomAccessOutputStream
 
filepath = '/Users/miura/Desktop/test.ome.tif'
 
# test reading out (no new lines)
comment = TiffParser(filepath).getComment()
print comment
 
# replacing OME-XML
xmlpath = '/Users/miura/Desktop/ometest.xml'
newComment = DataTools.readFile(xmlpath)
filein = RandomAccessInputStream(filepath)
fileout = RandomAccessOutputStream(filepath)
saver = TiffSaver(fileout, filepath)
saver.overwriteComment(filein, newComment)
filein.close()
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

from ij import IJ
from imagescience.image import Image as FJimage
from imagescience.feature import Laplacian

imp = IJ.getImage()
fjimg = FJimage.wrap(imp)
fjimglap = Laplacian().run(fjimg, 1.0)
imp2 = fjimglap.imageplus()
imp2.show()

Plugin: Extended Depth of Field (Easy mode)

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


import jarray
from edfgui import BasicDialog

imp = IJ.getImage()
'''
here need to check conditions of the image, it should not be less than 
- 4 pixel width
- 4 pixel height
- 2 slices
'''
imagesize = jarray.array([imp.getHeight(), imp.getHeight()], 'i')
color = imp.getType() == ImagePlus.COLOR_RGB
dl = BasicDialog(imagesize, color, False)
#  "quality='1' topology='0' show-view='on' show-topology='off'"
quality = 1
topology = 0
showview = True
showtopology= False
dl.parameters.setQualitySettings(quality)
dl.parameters.setTopologySettings(topology)
dl.parameters.show3dView = showview 
dl.parameters.showTopology = showtopology
dl.process()

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

from anisotropic_diffusion import Anisotropic_Diffusion_2D as AD
def aniso2D(imp):
	ad = AD()
	ad.setNumOfIterations(20)
	ad.setSmoothings(10)
	ad.setSaveSteps(20)
	ad.setLimiterMinimalVariations(0.40) 
	ad.setLimiterMaximalVariations(0.90)
	ad.setTimeSteps(20)
	ad.setEdgeThreshold(10.0)
	ad.setup("",imp)
	adimp = ad.runTD(imp.getProcessor())
	return adimp

imagepath = '/Volumes/D/20130305/l5c1-128.tif'
imp = IJ.openImage(imagepath)
adimp = aniso2D(imp)
adimp.show()

Plugin: Advanced Weka Segmentation

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

from trainableSegmentation import WekaSegmentation
from ij.plugin.frame import RoiManager
from ij import IJ
from ij.io import FileSaver

imp = IJ.openImage('http://imagej.nih.gov/ij/images/blobs.gif') #blobs

weka = WekaSegmentation()
weka.setTrainingImage(imp)

rm = RoiManager(True) 
rm.runCommand('Open', '/Users/miura/Desktop/tmp/RoiSetc1.zip')
roitable =rm.getROIs()
keys = roitable.keys()
for key in keys:
	weka.addExample(0, roitable.get(key), 1)

rm2 = RoiManager(True) 
rm2.runCommand('Open', '/Users/miura/Desktop/tmp/RoiSetc2.zip')
roitable =rm2.getROIs()
keys = roitable.keys()
for key in keys:
	weka.addExample(1, roitable.get(key), 1)

if weka.trainClassifier():
	weka.applyClassifier(True)
	classifiedImage = weka.getClassifiedImage()
	classifiedImage.show()

Plugin: CLAHE

Fiji plugin for local contrast enhancements.

from mpicbg.ij.clahe import Flat, FastFlat

def stackCLAHE2(imp):
  for i in range(imp.getStackSize()):
    imp.setSlice(i+1)
    Flat.getInstance().run(imp, 49, 256, 3.0, None) # slow, as this will be more precise. 
    #Flat.getFastInstance().run(imp, 49, 256, 3.0, None, False) # FastFlat will be faster and less acculate.
    

imp = IJ.getImage()
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.

from mmorpho import StructureElement
from mmorpho import MorphoProcessor

imp = IJ.getImage()
se = StructureElement(StructureElement.CIRCLE, 0, 10.0, StructureElement.OFFSET0)
morph = MorphoProcessor(se)
morph.erode(imp.getProcessor())
imp.updateAndDraw()

For other operations, see Javadoc

Plugin: Auto Threshold

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

from fiji.threshold import Auto_Threshold

imp = IJ.getImage()
hist = imp.getProcessor().getHistogram()
lowTH = Auto_Threshold.Otsu(hist)
print lowTH

# if you want to convert to mask, then
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.

from fiji.threshold import Auto_Local_Threshold as ALT

imp = IJ.getImage()
#IJ.run(imp, "Auto Local Threshold", "method=Bernsen radius=45 parameter_1=0 parameter_2=0 white");
thimp = ALT().exec(imp, "Bernsen", 45, 0, 0, False)
print len(imp)
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/cmci/GLCM2

from emblcmci.glcm import GLCMtexture
from ij import IJ

imp = IJ.getImage()

glmc = GLCMtexture(1, 45, True, False)
ip = imp.getProcessor()
ip8 = ip.convertToByte(True)
glmc.calcGLCM(ip8)
resmap = glmc.getResultsArray()
pa = glmc.paramA
for p in pa:
    print p, resmap.get(p)

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), …”.

from org.rosuda.REngine.Rserve import RConnection
from ij.gui import Roi, Overlay
 
c = RConnection()
x = c.eval("R.version.string")
print x.asString()
print c.eval("library(Peaks)").asString()
 
imp = IJ.getImage()
roi = imp.getRoi()
if roi.getType() == Roi.LINE:
  print "a line roi"
	profile = roi.getPixels()
	c.assign("prof", profile)
	pks = c.eval("SpectrumSearch(prof, sigma=1, threshold=80, background=FALSE, iterations=20, markov=TRUE, window=10)").asList()
	pksX = pks[0].asIntegers()
	rois = []
	for i in pksX:
		print roi.x1, i
		rois.append(PointRoi(roi.x1, roi.y1 + i))
	ol = Overlay() 
	for aroi in rois:
		ol.add(aroi)
	imp.setOverlay(ol)
	
c.close()

Misc examples

ImageJ Macro Keywords and Functions

Printing out ImageJ macro reserved words.

from ij.macro import MacroConstants as MC

print "=== keywords ==="
for f in MC.keywords:
	print f

print "=== functions (void) ==="
for f in MC.functions:
	print f

print "=== functions (numeric) ==="
for f in MC.numericFunctions:
	print f

print "=== funcitons (string) ==="
for f in MC.stringFunctions:
	print f

print "=== functions (arrays) ==="
for f in MC.arrayFunctions:
	print f

Implementing Interface

Here is an example of implementing PlugIn interface.

from ij.plugin import PlugIn

class GreatPlugin(PlugIn):
   def __init__ (self):
      print "This is GreatPlugin class which implements a java interface ij.plugin.Plugin"
   def run(self):
      IJ.open('http://imagej.nih.gov/ij/images/blobs.gif')
   def anotherrun(self):
      imp = IJ.openImage('http://imagej.nih.gov/ij/images/blobs.gif')
      imp.getProcessor().invert()
      imp.show()     

gp = GreatPlugin()
gp.run()
gp.anotherrun()

See explanation in here.

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: 2016/07/04 06:16 by kota