Creating project from command line

Hello, I am fairly new to QuPath, but I have a project I’m working on that requires detachment from the GUI. I have a groovy script working when I already have a project with images loaded, but I am wondering if there is a way to create a project, populate it from a list of image paths, and run the groovy script on all of the images in the project. The third part I think I’ve seen answers to in the forums, but is the first two even possible? My workaround so far is to just run QuPath on a loop on individual images, but I feel like that’s computationally inefficient. Any input will be greatly appreciated!

It is possible, but I find it a bit awkward.
Here is a little script that you can use, which will create a QuPath project in a specified directory, then add one image to it.

import java.awt.image.BufferedImage
import qupath.lib.images.servers.ImageServerProvider

// Paths
def directory = new File("Path/to/your/empty/directory")
def imagePath = "D:/QuPath/data/Capture.PNG"

// Create project
def project = Projects.createProject(directory , BufferedImage.class)

// Get serverBuilder
def support = ImageServerProvider.getPreferredUriImageSupport(BufferedImage.class, imagePath, "")
def builder = support.builders.get(0)

// Make sure we don't have null 
if (builder == null) {
    print "Image not supported"
    return
}

// Add the image as entry to the project
project.addImage(builder)

// Changes should now be reflected in the project directory
project.syncChanges()

Note that if you now open your project with the GUI, you will need to Right click > Refresh thumbnail on the project entry to see the thumbnail being properly loaded.

It’s probably not be the best way to do this, but I can’t think of another way right now.

2 Likes

Hi all,

I’ve added some braces around @melvingelbard’s code to

  • select an image folder via a file dialog (check if the selection dialog is buried under QuPath’s windows, not sure why this is happening yet)
  • create a project directory inside the folder
  • iterate through all the files in the original folder and create a list of image paths matching a certain type (.ndpi for me)
  • iterate through the image paths in the list and add them as project entries. I’ve added code to flesh out these entries with a name (the filename), a thumbnail and a default image type (HDAB here).

Let me know if this works. Thanks to @melvingelbard and @petebankhead for their help!

import groovy.io.FileType
import java.awt.image.BufferedImage
import qupath.lib.images.servers.ImageServerProvider
import qupath.lib.gui.commands.ProjectCommands

selectedDir = Dialogs.promptForDirectory(null)
//selectedDir = new File("Path/to/your/image/folder")

if (selectedDir == null)
    return
    
//Check if we already have a QuPath Project directory in there...
projectName = "QuPathProject"
File directory = new File(selectedDir.toString() + File.separator + projectName)

if (!directory.exists())
{
    print("No project directory, creating one!")
    directory.mkdirs()
}

// Create project
def project = Projects.createProject(directory , BufferedImage.class)

// Build a list of files
def files = []
selectedDir.eachFileRecurse (FileType.FILES) { file ->
    if (file.getName().toLowerCase().endsWith(".ndpi"))
    {
        files << file
        print(file.getCanonicalPath())      
    }
}

// Add files to the project
for (file in files) {
    def imagePath = file.getCanonicalPath()
    
    // Get serverBuilder
    def support = ImageServerProvider.getPreferredUriImageSupport(BufferedImage.class, imagePath, "")
    def builder = support.builders.get(0)

    // Make sure we don't have null 
    if (builder == null) {
       print "Image not supported: " + imagePath
       continue
    }
    
    // Add the image as entry to the project
    print "Adding: " + imagePath
    entry = project.addImage(builder)
    
    // Set a particular image type
    def imageData = entry.readImageData()
    imageData.setImageType(ImageData.ImageType.BRIGHTFIELD_H_DAB)
    entry.saveImageData(imageData)
    
    // Write a thumbnail if we can
    var img = ProjectCommands.getThumbnailRGB(imageData.getServer());
    entry.setThumbnail(img)
    
    // Add an entry name (the filename)
    entry.setImageName(file.getName())
}

// Changes should now be reflected in the project directory
project.syncChanges()

EDIT! This is now all taken care of: Adding an image type (e.g. ImageData.ImageType.BRIGHTFIELD_H_DAB) to the images and creating proper names and thumbnails is next on my list (if creating thumbnails doesn’t slow things down too much).

I’ll report back when I’m done. Thanks for your help! :slight_smile:

1 Like

If you’re calling this from QuPath, I’d recommend using a JavaFX dialog instead. In fact, there’s a method in QuPath to make this especially easy:

Using selectedDir = Dialogs.promptForDirectory(null) should avoid threading/focus troubles.

1 Like