Skip to content, Skip to search

Changes

Jython Scripting

16,713 bytes removed, 07:41, 15 December 2016
Using the GitHub extension to load code examples.
<source lang{{GitHubEmbed|org='python'># The module __future__ contains some useful functions:# https://docs.python.org/2/library/__future__.htmlfrom __future__ import with_statement, division# This imports the function random from the module random.from random import random# Next we import Java Classes into Jython.# This is how we can acces the ImageJ API:# https://imagej.nih.gov/ij/developer/api/allclasses-noframe.htmlfrom ij import IJ, WindowManagerfrom ij.gui import GenericDialog # A function is created with the def keyword.# This function does not need any parameters.def create_test_image(): # Python uses indentation to create code blocks  # Local variables are assigned. # We can assign the same value to more than one variable. image_width |repo= image_height = 512 box_width = box_height = 128 offset_x = offset_y = 192 counts = 64 stdv = 16 # The build in function int() is used to convert float to int. # The variable random contains a function that is called by adding parentheses. offset_x = int(2 * random() * offset_x) offset_y = int(2 * random() * offset_y) # We can define a function inside a function. # Outside of create_test_image() this function is not available. # By adding an asterisk to a parameter, all given parameters are combined to a tuple. def make_title(*to_concat): prefix = 'TestImage' # To create a tuple with a single entry the comma is necessary. # The 2 tuples are concatenated by using the + operator. to_join = (prefix,) + to_concat # We create a generator that converts every singe entry of the tuple to a string. strings_to_join = (str(arg) for arg in to_join) # The string ',' has a join method to concatenate values of a tuple with the string as seperator. # The result is a string. return ','.join(strings_to_join) def check_existence(title): if WindowManager.getIDList() is None: return False image_titles = (WindowManager.getImage(id).getTitle() for id in WindowManager.getIDList()) return title in image_titles # To negate an expression put not in front of it. if not check_existence(make_title(offset_x, offset_y)): # The following code has been created by using the Recorder of ImageJ, set to output Java code. # By removing the semicolons, the code can be used in Jython. # The parameters can be modified by using variables and string concatenation. imp = IJ.createImage(make_title(offset_x, offset_y), "8imagej-bit black", image_width, image_height, 1) # The build in function str() is used to convert int to string. IJ.run(imp, "Add...", "value=" + str(counts)) imp.setRoi(offset_x , offset_y, box_width, box_height) IJ.run(imp, "Add...", "value=" + str(counts)) IJ.run(imp, "Select None", "") IJ.run(imp, "Add Specified Noise...", "standard=" + str(stdv)); # We don't want to confirm when closing one of the newly created images. imp.changes = False imp.show() # This function uses parameters.# A default value is given to the third parameter.def create_selection_dialog(image_titles, defaults, title='Select images for processing'): gd scripting|path= GenericDialog(title) # The build in function enumerate() returns two values: # The index and the value stored in the tuplesrc/list. for index, default in enumerate(defaults): # for each loop we add a new choice element to the dialog. gd.addChoice('Image_'+ str(index + 1), image_titles, image_titles[default]) gd.showDialog() if gd.wasCanceled(): return None # This function returns a list. # _ is used as a placeholder for values we don't use. # The for loop is used to call gd.getNextChoiceIndex() len(defaults) times. return [gd.getNextChoiceIndex() for _ in defaults] # It's best practice to create a function that contains the code that is executed when running the script.# This enables us to stop the script by just calling return.def run_script(): while WindowManager.getImageCount() < 10: create_test_image() image_titles = [WindowManager.getImage(id).getTitle() for id in WindowManager.getIDList()] # range(3) will create the list [0, 1, 2]. selected_indices = create_selection_dialog(image_titles, range(3)) # The script stops if the dialog has ben canceld (None was returned from create_selection_dialog). if selected_indices is None: print('Script was canceld.') return # We have to get the corresponding IMagePlus objects. selected_imps = [WindowManager.getImage(id) for id in [WindowManager.getIDList()[index] for index in selected_indices]] # The previous line can be split into 2 lines: # selected_ids = [WindowManager.getIDList()[index] for index in selected_indices] # selected_imps = [WindowManager.getImage(id) for id in selected_ids] for imp in selected_imps: # Strings can be formated using the % operator: # http:main/resources/www.learnpython.orgscript_templates/enTutorials/String_Formatting IJWiki_Jython_Tutorial_1.log('The image \'%s\' has been selected.' % imp.getTitle()) # If a Jython script is run, the variable __name__ contains the string '__main__'.# If a script is loaded as module, __name__ has a different value.if __name__ == '__main__': run_script()</source>py}}
=== Using Scripting Parameters ===
<source lang{{GitHubEmbed|org='python'># @String(value='Please set some parameters.', visibility='MESSAGE') message# @Short(label='Image size', value=512, min=128, max=2048, stepSize=128, style="slider") img_size# @Double(label='Image amplitude', value=100) amplitude# @Short(label='Spacing', value=16, minimagej|repo=8) spacing # The parameters in front of this comment are populated before the script runs.# Details on Script parameters can be found at# http://imagej.net/Script_parameters # The module __future__ contains some useful functions:# https://docs.python.org/2/library/__future__.htmlfrom __future__ import with_statement, division # It's best practice to create a function that contains the code that is executed when running the script.# This enables us to stop the script by just calling return.def run_script(): # We can use import inside of code blocks to limit the scope. import math from ij import IJ, ImagePlus from ij.process import FloatProcessor blank = IJ.createImage("Blank", "32-bit black", img_size, img_size, 1) # This create a list of lists. Each inner list represents a line. # pixel_matrix[0] is the first line where yscripting|path=0. pixel_matrix = split_list(blank.getProcessor().getPixels(), wanted_parts=img_size) # This swaps x and y coordinates. # http:src//stackoverflow.com/questions/8421337/rotating-a-two-dimensional-array-in-python # As zip() creates tuples, we have to convert each one by using list(). pixel_matrix = [list(x) for x in zip(*pixel_matrix)] for y in range(img_size): for x in range(img_size): # This function oszillates between 0 and 1. # The distance of 2 maxima in a row/column is given by spacing. val = (0.5 * (math.cos(2*math.pi/spacing*x) + math.sin(2*math.pi/spacing*y)))**2 # When assigning, we multiply the value by the amplitude. pixel_matrix[x][y] = amplitude * val # The constructor of FloatProcessor works fine with a 2D Python list. crystal = ImagePlus("Crystal", FloatProcessor(pixel_matrix)) # Crop without selection is used to duplicate an image. crystal_with_noise = crystal.crop() crystal_with_noise.setTitle("Crystal with noise") IJ.run(crystal_with_noise, "Add Specified Noise...", "standard=%d" % int(amplitude/math.sqrt(2))) # As this is a demo, we don't want to be ask to save an image on closing it. # In Python True and False start with capital letters. crystal_with_noise.changes = False crystal.show() crystal_with_noise.show() filtered = fft_filter(crystal_with_noise) # We create a lambda function to be used as a parameter of img_calc(). subtract = lambda values: values[0] - values[1] """ This is a short form for: def subtract(values): return values[0] - values[1] """ # The first time we call img_calc with 2 images. difference = img_calc(subtract, crystal, filtered, title="Difference of 2") difference.show() # The first time we call img_calc with 3 images. minimum = img_calc(min, crystal, filtered, crystal_with_noise, title="Minimum of 3") minimum.show() for imp in (crystal, crystal_with_noise, filtered, difference, minimum): IJ.run(imp, "Measure", "") # Functions can be defined after they are used.# This is only possible if the main code is encapsulated into a function.# The main function has to be called at the end of the script. def img_calc(func, *imps, **kwargs): """Runs the given function on each pixel of the given list of images. An additional parameter, the title of the result, is passed as keyword parameter. We assume that each image has the same size. This is not checked by this function. """ # If the keyword parameter is not passed, it is set to a default value. if not kwargs['title']: kwargs['title'] = "Result" # This is a 2D list: list[number of images][pixels per image] . pixels = [imp.getProcessor().getPixels() for imp in imps] # The function is called pixel by pixel. # zip(*pixels) rotates the 2D list: list[pixels per image][mumber of images]. result = [func(vals) for vals in zip(*pixels)] # result is a 1D list and can be used to create an ImagePlus object. from ij import ImagePlus from ij.process import FloatProcessor return ImagePlus(kwargs['title'], FloatProcessor(img_size, img_size, result)) def split_list(alist, wanted_parts=1): """Split a list to the given number of parts.""" length = len(alist) # alist[a:b:step] is used to get only a subsection of the list 'alist'. # alist[a:b] is the same as [a:b:1]. # '/resources/' is an integer division. # Without 'from __future__ import division' 'script_templates/' would be an integer division. return [ alist[i*length Tutorials// wanted_parts: (i+1)*length // wanted_parts] for i in range(wanted_parts) ] def fft_filter(imp): """ Removing noise from an image by using a FFT filter This are operations copied from the ImageJ macro recorderWiki_Jython_Tutorial_2. Jython does not complain when you forget to remove the semicolons. """ from ij import IJ IJ.run(imp, "FFT", ""); # No ImagePlus is returned by the FFT function of ImageJ. # We need to use the WindowManager to select the newly created image. from ij import WindowManager as wm fft = wm.getImage("FFT of " + imp.getTitle()) IJ.run(fft, "Find Maxima...", "noise=64 output=[Point Selection] exclude"); # Enlarging the point selectins from Find Maxima. IJ.run(fft, "Enlarge...", "enlarge=2"); # Inverting the selection. IJ.run(fft, "Make Inverse", ""); IJ.run(fft, "Macro...", "code=v=0"); IJ.run(fft, "Inverse FFT", ""); fft.changes = False fft.close() imp_filtered = wm.getImage("Inverse FFT of " + imp.getTitle()) imp_filtered.setTitle("Filtered " + imp.getTitle()) imp_filtered.changes = False return imp_filtered  # If a Jython script is run, the variable __name__ contains the string '__main__'.# If a script is loaded as module, __name__ has a different value.if __name__ == '__main__': run_script()</source>py}}
=== A batch opener using <code>os.walk()</code> ===
* [https://docs.python.org/2/library/stdtypes.html#truth-value-testing Truth Value Testing]
<source lang='python'>
# @File(label='Choose a directory', style='directory') import_dir
# @String(label='File types', value='tif;png') file_types
# @String(label='Filter', value='') filters
# @Boolean(label='Recursive search', value=True) do_recursive
 
# We do only include the module os,
# as we can use os.path.walk()
# to access functions of the submodule.
import os
from java.io import File
 
from ij import IJ
 
def batch_open_images(path, file_type=None, name_filter=None, recursive=False):
'''Open all files in the given folder.
:param path: The path from were to open the images. String and java.io.File are allowed.
:param file_type: Only accept files with the given extension (default: None).
:param name_filter: Only accept files that contain the given string (default: None).
:param recursive: Process directories recursively (default: False).
'''
# Converting a File object to a string.
if isinstance(path, File):
path = path.getAbsolutePath()
 
def check_type(string):
'''This function is used to check the file type.
It is possible to use a single string or a list/tuple of strings as filter.
This function can access the variables of the surrounding function.
:param string: The filename to perform the check on.
'''
if file_type:
# The first branch is used if file_type is a list or a tuple.
if type(file_type) in [list, tuple]:
for file_type_ in file_type:
if string.endswith(file_type_):
# Exit the function with True.
return True
else:
# Next iteration of the for loop.
continue
# The second branch is used if file_type is a string.
elif isinstance(file_type, string):
if string.endswith(file_type):
return True
else:
return False
return False
# Accept all files if file_type is None.
else:
return True
 
def check_filter(string):
'''This function is used to check for a given filter.
It is possible to use a single string or a list/tuple of strings as filter.
This function can access the variables of the surrounding function.
:param string: The filename to perform the filtering on.
'''
if name_filter:
# The first branch is used if name_filter is a list or a tuple.
if type(name_filter) in [list, tuple]:
for name_filter_ in name_filter:
if name_filter_ in string:
# Exit the function with True.
return True
else:
# Next iteration of the for loop.
continue
# The second branch is used if name_filter is a string.
elif isinstance(name_filter, string):
if name_filter in string:
return True
else:
return False
return False
else:
# Accept all files if name_filter is None.
return True
 
# We collect all files to open in a list.
path_to_images = []
# Replacing some abbreviations (e.g. $HOME on Linux).
path = os.path.expanduser(path)
path = os.path.expandvars(path)
# If we don't want a recursive search, we can use os.listdir().
if not recursive:
for file_name in os.listdir(path):
full_path = os.path.join(path, file_name)
if os.path.isfile(full_path):
if check_type(file_name):
if check_filter(file_name):
path_to_images.append(full_path)
# For a recursive search os.walk() is used.
else:
# os.walk() is iterable.
# Each iteration of the for loop processes a different directory.
# the first return value represents the current directory.
# The second return value is a list of included directories.
# The third return value is a list of included files.
for directory, dir_names, file_names in os.walk(path):
# We are only interested in files.
for file_name in file_names:
# The list contains only the file names.
# The full path needs to be reconstructed.
full_path = os.path.join(directory, file_name)
# Both checks are performed to filter the files.
if check_type(file_name):
if check_filter(file_name):
# Add the file to the list of images to open.
path_to_images.append(full_path)
# Create the list that will be returned by this function.
images = []
for img_path in path_to_images:
# IJ.openImage() returns an ImagePlus object or None.
imp = IJ.openImage(img_path)
# An object equals True and None equals False.
if imp:
images.append(imp)
return images
 
def split_string(input_string):
'''Split a string to a list and strip it
:param input_string: A string that contains semicolons as separators.
'''
string_splitted = input_string.split(';')
# Remove whitespace at the beginning and end of each string
strings_striped = [string.strip() for string in string_splitted]
return strings_striped
if __name__ {{GitHubEmbed|org=imagej|repo= '__main__': '''Run the batch_open_images() function using the Scripting Parameters. ''' images imagej-scripting|path= batch_open_images(import_dir, split_string(file_types), split_string(filters), do_recursive ) for image in images: # Call the toString() method of each ImagePlus objectsrc/main/resources/script_templates/Tutorials/Wiki_Jython_Tutorial_3. print(image)</source>py}}
== Self written Jython modules for ImageJ ==
247
edits