我知道编辑这个网站吗?
the ImageJ2 platform本页介绍与 the ImageJ2 platform 相关的内容。点击徽标查看详情。

Groovy 脚本

简介

Groovy是Java虚拟机的一种敏捷且动态的语言。它建立在Java之上的优势,但具有受PythonRuby和Smalltalk语言等指令的额外强大功能。

快速入门

  • ⌃ Ctrl + R调出Script Editor
  • Templates[by language]Groovy 菜单中选择示例 Groovy 脚本。
  • [运行脚本!

在 ImageJ 中编写 groovy 脚本的技巧

For an introduction in ImageJ scripting visit the page Scripting basics.

简介

本页的目的不是教授如何使用 Groovy 进行编程。Groovy Quick Start可以更好地实现这一目的。本页的重点是展示如何最好地在 ImageJ 中使用 Groovy 编写脚本

使用IDE进行Groovy脚本编写

由于 Groovy 构建于 Java 之上,因此它可以在斐济的成熟 IDE 中使用。如果有兴趣,请遵循此 tutorial

何时使用 Groovy

以下列表将帮助您确定 Groovy 是否为 ImageJ 创建脚本的正确选择:

  • 如果您有Java经验,您可以轻松使用Groovy进行ImageJ脚本编写。

  • 如果您希望能够快速构建原型并调用外部库,Groovy 是一个不错的选择。

  • 如果您没有 Java 经验,但又想获得一些经验,那么使用 Groovy 编写的脚本可能是一个很好的学习方法。

  • 如果您在编程方面经验很少或没有,您可能会喜欢探索Jython,因为它是一种易于阅读但功能丰富的语言。

说明

从根本上来说,Groovy 与 Java 非常相似。随着你对它越来越熟悉,你会发现它可以做一些 Java 做不到的事情。 与 Java 一样,Groovy 可以访问类路径中存在的任何类库。这允许您包含第三方库,这些库可能不会立即出现在 Fiji/ImageJ 中,但您可以下载。示例包括数据库连接、用于通信目的的库,这个列表很长!

ImageJ 的 Groovy 基础知识

For an introduction in ImageJ scripting visit the page Scripting basics.

###你好,世界!

- 使用 print / println

print 和 println 命令将输出发送到控制台,不同的地方位于 println 总是在消耗附加换行符

println "Hello, World!"
// Let's show it handling numbers too
println "Result of 2 + 2: " + (2+2)

// what happens if we don't use the parentheses?
print "Result of 2 + 2: " + 2+2

注意 - printprintln将其输出发送到独立控制台(如果它打开)。如果没有,将会转到斐济编辑脚本器的控制台。示例是您想要某种文本输出(以显示值、进度等),但您不希望用户弹出。

- 使用 IJ.log()

IJ.log() 是 ImageJ java 函数(也称为方法)的示例。 它在 ImageJ 中创建一个窗口(如果尚未打开)其中读取文本。 双方通话时都会有附加换行符。

import ij.IJ

IJ.log("Hello, World!")
// Let's show it handling numbers too
IJ.log("Result of 2 + 2: " + (2+2))

// what happens if we don't use the parentheses?
IJ.log("Result of 2 + 2: " + 2+2)

如果您尝试了结束示例,则包含 (2+2) 的行将被计算为 4,而没有逗号的行将被视为字符串,给出 22

使用 GenericDialog 类选择图像

此示例脚本将创建最多 10 个新图像,并创建一个 GenericDialog 以选择其中的 3 个。最后,所选图像的名称将打印到日志窗口。建议将代码复制到Script Editor中自行运行。

// Import the classes that are needed. 

import ij.IJ							          
import ij.WindowManager					    
import ij.gui.GenericDialog				  
import ij.plugin.frame.RoiManager		

// The IJ class contains a number of utilities. For this script, it provides the "log" functionality
// A class which gives access to the window objects
// A class which allows for creation of custom dialogs with relative ease.
// The ROI Manager - useful for accessing ROIs.

// next we'll define some functions. 

// Function to create a test image
def createTestImage() {
    int imageWidth = 512			// here, we're using explicit types - int holds an integer.
    int imageHeight = 512
    int boxWidth = 128
    int boxHeight = 128
    int offsetX = (int) 192 * 2 * Math.random()  // (int) causes the rest of the statement to be forced to an integer - no decimal places!
    int offsetY = (int) 192 * 2 * Math.random()
    int counts = 64
    int stdv = 16

    // The following are nested definitions. They are not available outside the "createTestImage" function.
    // the following line is called a closure. It's a short-hand way of creating a function.
    // This one returns a string:  makeTitle("Testing", 1, 2) will give 'Testing: 1, 2' as the output.
    def makeTitle = { prefix, x, y -> "${prefix}: ${x}, ${y}" }
      
    // we'll now call the makeTitle function and store the result in a variable called "title"
    // note that it's not a pre-defined type, instead the interpreter will decide what to use.
    def title = makeTitle('TestImage', offsetX, offsetY)
	
    // This closure looks a bit more like a java function. It's going to return either true or false.
    def checkExistence = { titleToCheck ->
        def idList = WindowManager.getIDList()    // get the list of open images
        if (idList == null) return false          // if the list is empty, return false.
        
        // 'collect', in the next line, is a Groovy method that iterates through whatever it is attached to 
        // and executes the code inside the curly brackets on each item it encounters.
        // In this case, it retrieves the title of each image into a list.
        def imageTitles = idList.collect { WindowManager.getImage(it).getTitle() }
        return imageTitles.contains(titleToCheck)
    }

    // That's it for the nested definitions, now lets use them.

    // Check if the image *doesn't* exist..
    if (!checkExistence(title)) {
        // if not, create an ImagePlus with the title, and image dimensions given
        def imp = IJ.createImage(title, "8-bit black", imageWidth, imageHeight, 1)	
        imp.show()

        // The following lines use calls to functionality that's already available - no need to reinvent the wheel.
        // Use the ImageJ mathematical function to add the value of "counts" to the current pixel values.
        IJ.run(imp, "Add...", "value=${counts}")
        // Create a simple rectangular ROI
        imp.setRoi(offsetX, offsetY, boxWidth, boxHeight)
        // and use the Add function again. This will only apply to the ROI
        IJ.run(imp, "Add...", "value=${counts}")
        // Select None removes the ROI - the whole image is now "active"                                    
        IJ.run("Select None")
        // Add noise to the image
        IJ.run(imp, "Add Specified Noise...", "standard=${stdv}")
        // That was a groovy-styled way of building the required parameter string
        // In Java, you would use "standard=" + stdv)

        // Tell ImageJ we're not interested in changes
        imp.changes = false
        // Display the image.
        imp.show()                                                                  
        
    }
}

// Another function to help us to build a dialog to show to the user. 
// It uses the GenericDialog class and takes 3 arguments: titles, defaults and a string for the dialog title.
def createSelectionDialog(imageTitles, defaults, dialogTitle) {                           
    // create a new instance of GenericDialog
    def gd = new GenericDialog(dialogTitle)

    // A quick way to loop through an object, adding choices as we go.
    defaults.eachWithIndex { defVal, index ->
        gd.addChoice("Image_${index + 1}", imageTitles as String[], imageTitles[defVal]) 
    }

    // show the dialog to the user
    gd.showDialog()                                                                       
    if (gd.wasCanceled()) return null   // if the user clicks cancel, return Null. 

    // the next line won't execute if the previous one evaluated as true, because the return statement causes the function to terminate.    
    return defaults.collect { gd.getNextChoiceIndex() }    
}

// Main script execution
def runScript() {
    while (WindowManager.getImageCount() < 10) {            // create a test image as long as the count is less than 10
        createTestImage()
    }

    // retrieve a list of the image titles using the WindowManager class.
    def imageTitles = WindowManager.getIDList().collect { WindowManager.getImage(it).getTitle() }
    
    // now we'll pass this to the createSelectionDialog function that was defined earlier.
    def selectedIndices = createSelectionDialog(imageTitles, [0, 1, 2], 'Select images for processing')
    if (selectedIndices == null) {                          // check if the user clicked cancel - see above!!
        println "Script was canceled."                      // print this to the console (Not the log window)
        return                                              // return without a value
    }
	
    // if selectedIndices wasn't null, the following code will execute
    // get a list of the avilable images (as ImagePlus objects)
    def selectedImages = selectedIndices.collect { WindowManager.getImage(WindowManager.getIDList()[it]) }

    // Display info on the ImageJ log.
    selectedImages.each { imp -> IJ.log("The image '${imp.getTitle()}' has been selected.") }	
}

// This is the only line of code that can actually be run - all the others have to be called.
// So the "runScript" function is called, which subsequently calls other functions.
runScript()

This page is under construction. Check back for updates.