Skip to content

Instantly share code, notes, and snippets.

@petebankhead
Last active November 16, 2023 15:28
Show Gist options
  • Save petebankhead/3bca9f2a87ea061a50822bcaa4e7e203 to your computer and use it in GitHub Desktop.
Save petebankhead/3bca9f2a87ea061a50822bcaa4e7e203 to your computer and use it in GitHub Desktop.
QuPath script to create a .bat file to launch QuPath using paths from a conda environment
/**
* Groovy script to generate a batch script to launch QuPath while setting the PATH
* from a conda environment.
*
* This is useful to add GPU support with Deep Java Library (DJL) without needing to install
* CUDA system-wide.
*
* This script was written for QuPath v0.5.
* You should read the top part and change the variables to match what you need.
*/
// Specify path to conda environment
def condaPath = "C:/Users/yourname/miniforge3/envs/pytorch-qupath"
// Path to the output batch file to write
// By default this is on the desktop
def outputFile = "${System.getProperty("user.home")}/Desktop/launch_qupath.bat"
// Specify whether to overwrite an existing batch file or not
def overwriteExisting = true
// Specify QuPath executable (optional)
// If not provided, the script will try to identify the exe for the running QuPath
def qupathExe = ""
// Optional variables for PyTorch
// Specify PyTorch version, e.g. "1.13.1" (must be supported by DJL) (optional)
def pytorchVersion = ""
// Pytorch library path; if not specified, DJL will try to download a compatible version (optional)
def pytorchLibraryPath = ""
// PyTorch flavor, e.g. "cpu", "cu118", "mkl" (optional)
def pytorchFlavor = ""
//---------------
// Generate launch command
def pathVar
if (condaPath) {
def paths = ['', '/bin', '/Library/bin'].collect(d -> "${condaPath}${d}")
paths.add("%PATH%")
pathVar = String.join(File.pathSeparator, paths)
}
def lines = []
if (pytorchVersion)
lines << "set PYTORCH_VERSION=${pytorchVersion}"
if (pytorchLibraryPath)
lines << "set PYTORCH_LIBRARY_PATH=${pytorchVersion}"
if (pytorchFlavor)
lines << "set PYTORCH_FLAVOR=${pytorchFlavor}"
if (pathVar)
lines << "set PATH=${pathVar}"
// Command to launch QuPath itself
if (!qupathExe)
qupathExe = findQuPathExecutable()
lines << qupathExe
// Generate batch command and write to file
def batch = String.join(System.lineSeparator(), lines)
def file = new File(outputFile)
if (file.exists()) {
if (overwriteExisting)
println "Existing batch file will be overwritten!"
else {
println "${file} file exists! Choose a new file name, or set 'overwriteExisting = true'"
return
}
}
if (!file.getParentFile().exists())
println "Directory ${file.getParentFile()} does not exist! Can't write batch file"
else {
println "Batch file written ${file}"
file.text = batch
return
}
/**
* Try to find the QuPath executable from the running instance.
* This is assumed to be a final build, i.e. we aren't running from an IDE or gradle.
*/
String findQuPathExecutable() {
def file = new File(qupath.lib.gui.QuPathGUI.class.getProtectionDomain()
.getCodeSource()
.getLocation()
.getFile())
if (file.isDirectory())
throw new UnsupportedOperationException("QuPath must be packaged to find executable")
def dir = file.getParentFile()
if (dir.getName().equals("app"))
dir = dir.getParentFile()
def exes = dir.listFiles().findAll {f -> f.isFile() && f.getName().toLowerCase().endsWith('.exe')}
if (exes.isEmpty())
throw new IllegalArgumentException("No QuPath executable found!")
else if (exes.size() == 1)
return exes[0].getAbsolutePath()
else {
// Return the executable with the longest name
// This should be the 'console' exe, which is better for debugging
exes.sort(Comparator.comparingInt(f -> f.getAbsolutePath().size()))
return exes[-1].getAbsolutePath()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment