= Description =
This extension, with source located at rQPEBIOP is the current 'fourre-tout' for all the new features we are currently implementing for QuPath to make our users' lives simpler.
== Requirements ==
Because some features (Like saving display settigns) were not programmer-accessible (`private`), we had to modify QuPath's code. Which is why most features are only available if you are running *QuPath v0.1.4**.
== Contents ==
=== GUI Utilities ===
==== applyDisplaySettingsToProject() ====
Will apply the current display settings (Visible Channels, Histogram Min-Max, Channel Colors) to all images in the project with **the same image type and number of channels**
lang=java
import ch.epfl.biop.qupath.utils.GUIUtils
GUIUtils.applyDisplaySettingsToProject()
==== getChannelMinMax(int channel) ====
Returns a list of Integers with the min and max display values for the current channel (one-based)
lang=java
import ch.epfl.biop.qupath.utils.GUIUtils
def channel = 3
def min_max = GUIUtils.getChannelMinMax( channel )
println( sprintf( "Max is %d for channel %d", min_max[1], channel ) )
==== getChannelMinMax(java.lang.String channel) ====
Returns a list with the minimum and maximum display values for the given channel defined by its name
lang=java
import ch.epfl.biop.qupath.utils.GUIUtils
// Image is RGB H&E
def channel = "Optical density sum"
def min_max = GUIUtils.getChannelMinMax( channel )
println( sprintf( "Max is %d for channel %s", min_max[1], channel ) )
==== getImagePlus(qupath.lib.objects.PathObject pathObject, int downsample, boolean sendPathObjectAsRoi, boolean sendChildObjectsInOverlay)
Returns an ImagePlus object with or without a ROI and with or without an overlay (if there are child objects)
lang=java
import ch.epfl.biop.qupath.utils.GUIUtils
def object = getSelectedObject()
def downsample = 4
def sendObject = false
def sendChildObjects = false
def imp = GUIUtils.getImagePlus( object, downsample, sendObject, sendChildObjects )
imp.show()
==== loadDisplaySettings(java.io.File fileToLoad) ====
Loads the display settings (Brightness, contrast, LUT, Min-Max) from a json serialized file created with **saveDisplaySettings()**
```lang=java
import ch.epfl.biop.qupath.utils.GUIUtils
def settingsDir = buildFilePath( PROJECT_BASE_DIR, "settings" )
mkdirs(settingsDir)
def loadFile = new File( settingsDir, 'CustomSettings.json')
GUIUtils.loadDisplaySettings( loadFile )
```
==== saveDisplaySettings(java.io.File fileToSave) ====
Saves the current display settings (Brightness, contrast, LUT, Min-Max) to a json serialized file that can be used with with **loadDisplaySettings()**
```lang=java
import ch.epfl.biop.qupath.utils.GUIUtils
def settingsDir = buildFilePath( PROJECT_BASE_DIR, "settings" )
mkdirs(settingsDir)
def saveFile = new File( settingsDir, 'CustomSettings.json')
GUIUtils.loadDisplaySettings( saveFile )
```
==== setActiveChannels(java.util.ArrayList<java.lang.Integer> theChannels) ====
Sets the channels in the list to active and deactivates the ones not in it
```lang=java
import ch.epfl.biop.qupath.utils.GUIUtils
def activeChannels = [1,3]
GUIUtils.setActiveChannels( activeChannels )
```
IMPORTANT: This command does not update the "Brightness and Contrast" window, which no longer reflects the current state until you change something
static void setActiveChannelsByName(java.util.ArrayList<java.lang.String> channelNames)
Sets the channels in the list to active and deactivated the ones not in it
static void setChannelColor(int channel, javafx.scene.paint.Color color)
Sets the color of the selected channel
static void setChannelColor(java.lang.String channelName, javafx.scene.paint.Color color)
Sets the color of the selected channel
static void setChannelMinMax(int channelID, int min, int max)
Sets the minimum and maximum display range for a channel, defined by its index (1 based)
static void setChannelMinMax(java.lang.String channelName, int min, int max)
Sets the minimum and maximum display range for a channel, defined by its name
static void setChannelsMinMax(java.util.List<java.lang.Integer> channelIndexes, java.util.List<java.lang.Integer> minValues, java.util.List<java.lang.Integer> maxValues)
=== Utils ===
Utils contains utilities that are not linked to the user interface
==== sendResultsToFile(ArrayList<String> resultColumns, ArrayList<PathObject> objects, File resultsFile) ===
Sends the selected results from the selected objects to the selected file. The cool thing is that as long as you list all the results with the same column names as the ones in the GUI's Measurements, it will be available for export.
```lang=java
import ch.epfl.biop.qupath.utils.Utils
// Settings to establish, the name of the folder and the name of the results file
def results_folder_name = 'results'
def results_file_name = 'results.txt'
// Get the micrometers name
def um = Utils.um
// Choose the measurements you want to export
// sendResultsToFile will automatically append the image and subimage names as the first columns
def measurements = [ "Name", "Class", "Parent", "Area "+um+"^2"]
// Choose the objects for whom you want to have measurements
def objects = getAnnotationObjects()
// --------------------- Magic happens below --------------------- //
// Build the results directory
def res_directory = buildFilePath( PROJECT_BASE_DIR, results_folder_name )
// Build the results file
def res_file = new File( res_directory, results_file_name )
// Make sure the folder exists
mkdirs( res_directory )
// The method below creates a results table
// THE TABLE IS CREATED ONCE and THEN APPENDED
Utils.sendResultsToFile( measurements, objects, res_file )
```
==== getAllMeasurements() ====
Returns all the measurements available in QuPath for the all pathObjects Then we can use things like getStringValue() and getDoubleValue() and get ANY measurement as it is written in the Measurements GUI
```lang=java
import ch.epfl.biop.qupath.utils.Utils
def um = Utils.um;
def m = Utils.getAllMeasurements()
def object = getSelectedObject()
println( m.getNumericValue( object, 'Perimeter '+um ) )
```
==== getAllMeasurements(java.util.List<qupath.lib.objects.PathObject> pathObjects) ====
Creates an ObservableMeasurementTableData for the requested PathObjects, which might be a bit faster as it does not need to compute the measurements for all the objects, but just for the ones we need.
=== GUI Utilities ===
These utilities deal with how we can interact with QuPath's GUI, mostly dealing with Image Display
==== applyDisplaySettingsToProject() ====
Will apply the current display settings (Visible Channels, Histogram Min-Max, Channel Colors) to all images in the project with **the same image type and number of channels**
lang=java
import ch.epfl.biop.qupath.utils.GUIUtils
GUIUtils.applyDisplaySettingsToProject()
==== getChannelMinMax(int channel) ====
Returns a list of Integers with the min and max display values for the current channel (one-based)
lang=java
import ch.epfl.biop.qupath.utils.GUIUtils
def channel = 3
def min_max = GUIUtils.getChannelMinMax( channel )
println( sprintf( "Max is %d for channel %d", min_max[1], channel ) )
==== getChannelMinMax(java.lang.String channel) ====
Returns a list with the minimum and maximum display values for the given channel defined by its name
lang=java
import ch.epfl.biop.qupath.utils.GUIUtils
// Image is RGB H&E
def channel = "Optical density sum"
def min_max = GUIUtils.getChannelMinMax( channel )
println( sprintf( "Max is %d for channel %s", min_max[1], channel ) )
==== getImagePlus(qupath.lib.objects.PathObject pathObject, int downsample, boolean sendPathObjectAsRoi, boolean sendChildObjectsInOverlay)
Returns an ImagePlus object with or without a ROI and with or without an overlay (if there are child objects)
lang=java
import ch.epfl.biop.qupath.utils.GUIUtils
def object = getSelectedObject()
def downsample = 4
def sendObject = false
def sendChildObjects = false
def imp = GUIUtils.getImagePlus( object, downsample, sendObject, sendChildObjects )
imp.show()
==== loadDisplaySettings(java.io.File fileToLoad) ====
Loads the display settings (Brightness, contrast, LUT, Min-Max) from a json serialized file created with **saveDisplaySettings()**
```lang=java
import ch.epfl.biop.qupath.utils.GUIUtils
def settingsDir = buildFilePath( PROJECT_BASE_DIR, "settings" )
mkdirs(settingsDir)
def loadFile = new File( settingsDir, 'CustomSettings.json')
GUIUtils.loadDisplaySettings( loadFile )
```
==== saveDisplaySettings(java.io.File fileToSave) ====
Saves the current display settings (Brightness, contrast, LUT, Min-Max) to a json serialized file that can be used with with **loadDisplaySettings()**
```lang=java
import ch.epfl.biop.qupath.utils.GUIUtils
def settingsDir = buildFilePath( PROJECT_BASE_DIR, "settings" )
mkdirs(settingsDir)
def saveFile = new File( settingsDir, 'CustomSettings.json')
GUIUtils.loadDisplaySettings( saveFile )
```
==== setActiveChannels(java.util.ArrayList<java.lang.Integer> theChannels) ====
Sets the channels in the list to active and deactivates the ones not in it
```lang=java
import ch.epfl.biop.qupath.utils.GUIUtils
def activeChannels = [1,3]
GUIUtils.setActiveChannels( activeChannels )
```
IMPORTANT: This command does not update the "Brightness and Contrast" window, which no longer reflects the current state until you change something
==== setActiveChannelsByName(java.util.ArrayList<java.lang.String> channelNames) ====
Sets the channels in the list to active and deactivated the ones not in it
```lang=java
import ch.epfl.biop.qupath.utils.GUIUtils
def activeChannels = ["Channel 1","Channel 3"]
GUIUtils.setActiveChannelsByName( activeChannels )
```
NOTE: The name of the method is different because Java does not know how to differentiate `ArrayList<String>` from `ArrayList<Integer>`
==== setChannelColor(int channel, javafx.scene.paint.Color color) ====
Sets the color of the selected channel. See [[https://docs.oracle.com/javafx/2/api/javafx/scene/paint/Color.html | JavaFX's Color Class]]
```lang=java
import ch.epfl.biop.qupath.utils.GUIUtils
import javafx.scene.paint.Color;
def c1Color = Color.YELLOW
def c2Color = Color.rgb(255,128,128)
def c3Color = Color.web("0055FF")
GUIUtils.setChannelColor( 1, c1Color )
GUIUtils.setChannelColor( 2, c2Color )
GUIUtils.setChannelColor( 3, c3Color )
```
IMPORTANT: This command does not update the "Brightness and Contrast" window, which no longer reflects the current state until you change something
==== setChannelColor(java.lang.String channelName, javafx.scene.paint.Color color) ====
Same as above, but the channel can be selected with a String
==== setChannelMinMax(int channelID, int min, int max) ====
Sets the minimum and maximum display range for a channel, defined by its index (1 based)
```lang=java
import ch.epfl.biop.qupath.utils.GUIUtils
GUIUtils.setChannelMinMax(1, 0, 5000)
```
==== setChannelMinMax(java.lang.String channelName, int min, int max)
Sets the minimum and maximum display range for a channel, defined by its name
=== PathObject Utilities ===
These methods are for helping us manipulate pathObjects as needed
==== LineToArea(qupath.lib.roi.interfaces.ROI line, double thickness) ====
Converts a line to a very thin 4 sided polygon, so it has an area. returns a ROI which can be placed into a PathObject
```lang=java
import ch.epfl.biop.qupath.utils.PathUtils
import qupath.lib.objects.PathAnnotationObject;
object = getSelectedObject()
def area = PathUtils.LineToArea( object.getROI(), 100.0 )
def areaObject = new PathAnnotationObject( area )
getCurrentHierarchy().addPathObject( areaObject, true, true )
```
==== splitObject(qupath.lib.objects.PathObject pathObject, qupath.lib.objects.PathObject splitter) ====
Splits the defined pathobject using the provided splitter. The return value is a List of PathObjects, as the split might have generated more than one separate object
This is useful when trying to split an object with a line to cut it in half, for example.
```lang=java
import ch.epfl.biop.qupath.utils.PathUtils
import qupath.lib.objects.PathAnnotationObject;
import qupath.lib.objects.PathAnnotationObject;
// First create a polygon object, then make a line that goes through it
def objects = getAnnotationObjects()
def resultingObjects = PathUtils.splitObject( objects[0], objects[1] )
resultingObjects.each{ it.setPathClass( getPathClass( "Split" ) ) }
getCurrentHierarchy().addPathObjects( resultingObjects, true )
```
=== ScriptableMacroRunner ===
This class wraps the ImageJ Macro runner into a more user friendly class to use with scripts
```lang=java
import ch.epfl.biop.qupath.utils.ScriptableMacroRunner
// Call the scriptable macro runner
def mr = new ScriptableMacroRunner()
// Most important MacroRunner Command
// You can set the macro text directly here
mr.setMacroText("makeOval(200,200,100,100);");
// Easiest way is to send it text from an .ijm file
def macroFile = new File("SomePath/someMacro.ijm")
mr.setMacroText(macroFile.text)
// Optional, define the region to send
def region = getSelectedObject()
// All settings below are OPTIONAL
mr.setDownsample(10) // Otherwise will set downsample to 1
mr.setPathObject(region) // Sets the region that will be sent to ImageJ, if unset, will work on whole region
mr.setSendROI(false) // Sends the pathObject to ImageJ as a ROI
mr.setSendOverlay(false) // Sends the childern of the pathObject to ImageJ as Overlay
mr.setClearObjects(false) // Clears the current child objects of the pathobject being sent
mr.setGetROI(false) // Get ImageJ Current ROI As annotation
mr.setGetOverlay(false) // Get ImageJ Overlay back to QuPath
mr.setGetOverlayAs("Annotations") // or "Detections
// Runs the whole thing and returns what we want
mr.run()
// After this, the results should be in QuPath
```