API Reference

This document provides detailed API documentation for extending Granny with new analysis modules and interfaces.

Core Classes

Analysis Base Class

class Analysis

Abstract base class for all analysis modules.

All custom analyses must inherit from this class and implement the abstract methods.

Location: Granny/Analyses/Analysis.py

Class Attributes:

__analysis_name__: str

Machine-readable name for the analysis. Used in CLI --analysis argument.

Example: "segmentation", "starch", "blush"

Instance Attributes:

in_params: Dict[str, Value]

Dictionary of input parameters. Keys are parameter names, values are Value objects.

ret_values: Dict[str, Value]

Dictionary of return values that other analyses can use.

compatibility: Dict[str, Dict[str, str]]

Mapping of compatible analyses. Format:

{
    "other_analysis_name": {
        "my_param": "their_return_value"
    }
}
metadata: List[Value]

List of metadata values automatically added to all analyses: - dt - Analysis date/time - id - Unique analysis identifier (UUID) - path - Current directory path

cpu: IntValue

Number of CPU cores for parallel processing. Default 0 = auto (80% of cores).

images: List[Image]

List of loaded images (populated by performAnalysis()).

Methods:

__init__()

Initialize the analysis. Must call super().__init__() first.

Subclasses should: - Initialize instance variables - Define input parameters using Value objects - Set default values for parameters - Register parameters with addInParam()

addInParam(*params: Value) None

Add one or more input parameters to the analysis.

Parameters

params (Value) – Variable number of Value objects to register

Example:

threshold = IntValue("th", "threshold", "Detection threshold")
self.addInParam(threshold)
getInParams() Dict[str, Value]

Get all input parameters.

Returns

Dictionary of parameter names to Value objects

Return type

Dict[str, Value]

resetInParams() None

Clear all input parameters. Used when re-configuring an analysis instance.

addRetValue(*values: Value) None

Add one or more return values that other analyses can use.

Parameters

values (Value) – Variable number of Value objects

getRetValues() Dict[str, Value]

Get all return values.

Returns

Dictionary of return value names to Value objects

Return type

Dict[str, Value]

resetRetValues() None

Clear all return values.

performAnalysis() List[Image]

Perform the analysis on input images. Do not override this method.

The default implementation: 1. Loads images from input_images parameter via ImageListValue.readValue() 2. Calls _preRun() for setup 3. Processes images in parallel using multiprocessing.Pool 4. Calls _postRun() with results

Returns

List of processed Image objects (from _postRun())

Return type

List[Image]

Abstract Methods (must implement):

abstract _preRun() None

Setup before image processing begins. Called once before any images are processed.

Use this for: - Initializing result containers - Loading models or resources - Printing analysis parameters

abstract _processImage(image: Image) Image

Process a single image. Runs in parallel across CPU cores.

Parameters

image – Input Image instance

Returns

Processed Image instance

Return type

Image

Important: This method runs in separate processes. Avoid modifying shared state.

abstract _postRun(results: List[Image]) List[Image]

Post-processing after all images are done. Called once with all results.

Use this for: - Saving images to disk - Generating CSV reports - Computing aggregate statistics

Parameters

results – List of processed Image objects from _processImage()

Returns

Final list of result images

Return type

List[Image]

GrannyUI Base Class

class GrannyUI

Abstract base class for user interfaces.

Location: Granny/Interfaces/UI/GrannyUI.py

Constructor:

__init__(parser: ArgumentParser)

Initialize the interface.

Parameters

parser (argparse.ArgumentParser) – ArgumentParser instance for command-line arguments

Instance Attributes:

parser: ArgumentParser

The argparse ArgumentParser instance used for handling command-line arguments.

Abstract Methods:

abstract run() None

ABSTRACT: Execute the interface.

This method is called to start the interface and must be implemented by all subclasses.

Typical implementation: 1. Parse command-line arguments 2. Get user input (CLI args, GUI forms, web requests, etc.) 3. Instantiate selected analysis 4. Set analysis parameters from user input 5. Call analysis.performAnalysis() 6. Handle/display results

Note: addProgramArgs() is commonly implemented but not required by the base class. See GrannyCLI for an example implementation.

Value Classes

All Value classes inherit from the abstract Value base class and provide type-safe parameter handling.

Location: Granny/Models/Values/

Value Base Class

class Value

Abstract base class for all parameter value types.

Location: Granny/Models/Values/Value.py

Constructor:

__init__(name: str, label: str, help: str)
Parameters
  • name – Machine-readable parameter name

  • label – Human-readable label (used for CLI arguments)

  • help – Help text describing the parameter

Attributes:

name: str

Machine-readable name for the value.

label: str

Human-readable label. Becomes CLI argument: --{label}

help: str

Help text displayed to users.

type: Type

Python type of the value (int, float, str, etc.).

value: Any

The current value.

is_set: bool

Whether the user has set this value.

Methods:

abstract validate(value: Any) bool

Validate that the value meets constraints. Must be implemented by subclasses.

getName() str

Get the machine-readable name.

getLabel() str

Get the human-readable label (used for CLI args).

getHelp() str

Get the help text.

getType() Type

Get the Python type of this value.

setType(type: Type) None

Set the Python type.

setValue(value: Any) None

Set the value. Calls validate() first.

getValue() Any

Get the current value.

isSet() bool

Check if the user has set this value.

setIsRequired(is_required: bool) None

Set whether this parameter is required.

getIsRequired() bool

Check if this parameter is required.

IntValue

class IntValue(Value)

Integer parameter type with min/max constraints.

Location: Granny/Models/Values/IntValue.py

Additional Methods:

setMin(min_val: int) None

Set minimum allowed value.

getMin() int

Get minimum allowed value.

setMax(max_val: int) None

Set maximum allowed value.

getMax() int

Get maximum allowed value.

Example:

threshold = IntValue("th", "threshold", "Detection threshold (0-255)")
threshold.setMin(0)
threshold.setMax(255)
threshold.setValue(128)
threshold.setIsRequired(False)

FloatValue

class FloatValue(Value)

Floating-point parameter type with min/max constraints.

Location: Granny/Models/Values/FloatValue.py

Additional Methods:

setMin(min_val: float) None

Set minimum allowed value.

getMin() float

Get minimum allowed value.

setMax(max_val: float) None

Set maximum allowed value.

getMax() float

Get maximum allowed value.

Example:

alpha = FloatValue("alpha", "mask_alpha", "Mask transparency (0.0-1.0)")
alpha.setMin(0.0)
alpha.setMax(1.0)
alpha.setValue(0.5)

StringValue

class StringValue(Value)

String parameter type.

Location: Granny/Models/Values/StringValue.py

Example:

model = StringValue("model", "model", "Model name or path")
model.setValue("pome_fruit-v1_0")

BoolValue

class BoolValue(Value)

Boolean flag parameter type.

Location: Granny/Models/Values/BoolValue.py

Example:

debug = BoolValue("debug", "debug", "Enable debug mode")
debug.setValue(False)

FileNameValue

class FileNameValue(Value)

File path parameter type. Validates that path is a file or a valid model name.

Location: Granny/Models/Values/FileNameValue.py

Example:

input_file = FileNameValue("input", "input_file", "Path to input file")
input_file.setValue("/path/to/file.jpg")

FileDirValue

class FileDirValue(Value)

Directory path parameter type. Creates directory if it doesn’t exist.

Location: Granny/Models/Values/FileDirValue.py

Example:

output = FileDirValue("out", "output", "Output directory")
output.setValue("./results/analysis")  # Directory will be created

ImageListValue

class ImageListValue(FileDirValue)

Image list/directory parameter type. Represents a directory containing images. Handles loading and saving of image lists.

Location: Granny/Models/Values/ImageListValue.py

Additional Methods:

readValue() None

Load all images from the directory into the internal image list. Called automatically by Analysis.performAnalysis().

writeValue() None

Save all images in the internal list to the directory.

getImageList() List[Image]

Get the list of loaded Image objects.

setImageList(images: List[Image]) None

Set the list of Image objects.

Example:

input_images = ImageListValue(
    "input",
    "input",
    "Directory containing input images"
)
input_images.setIsRequired(True)
input_images.setValue("./demo/images")

# After readValue() is called:
images = input_images.getImageList()

MetaDataValue

class MetaDataValue(Value)

Metadata storage parameter type. Used for results directories and metadata.

Location: Granny/Models/Values/MetaDataValue.py

Example:

results = MetaDataValue(
    "results",
    "results",
    "Results output directory"
)
results.setValue("./results/analysis_2024-01-01")

Image Classes

Image Base Class

class Image

Abstract base class for images in Granny.

Location: Granny/Models/Images/Image.py

Constructor:

__init__(filepath: str)

Initialize the Image with a file path.

Parameters

filepath – Path to the image file

Attributes:

filepath: str

Absolute file path of the image.

image: NDArray[np.uint8]

The image data as a NumPy array.

metadata: Dict[str, Value]

Dictionary of metadata values attached to this image.

results: Any

Segmentation results (for use with YOLO models).

Methods:

addValue(*values: Value) None

Add metadata values to the image.

Parameters

values – One or more Value objects to attach

Example:

score = FloatValue("score", "score", "Analysis score")
score.setValue(95.5)
image.addValue(score)
getValue(key: str) Value

Get a metadata value by name.

Parameters

key – The name of the metadata value

Returns

The Value object

getFilePath() str

Get the absolute file path.

getImageName() str

Get the filename (without path).

getShape() tuple

Get the image dimensions (height, width, channels).

Abstract Methods:

abstract loadImage(image_io: ImageIO) None

Load image data using the provided ImageIO instance.

abstract saveImage(image_io: ImageIO, folder: str) None

Save image data to the specified folder.

abstract getImage() NDArray[np.uint8]

Get the image data as a NumPy array.

abstract setImage(image: NDArray[np.uint8]) None

Set the image data from a NumPy array.

abstract getMetaData() Dict[str, Value]

Get all metadata attached to this image.

abstract setMetaData(metadata: Dict[str, Value]) None

Set the metadata for the image.

RGBImage

class RGBImage(Image)

RGB color image type. The most common image type used in Granny analyses.

Location: Granny/Models/Images/RGBImage.py

Constructor:

__init__(filepath: str)

Initialize with a file path.

Parameters

filepath – Path to the image file

Additional Methods:

toRGB() None

Convert image from BGR to RGB format.

toBGR() None

Convert image from RGB to BGR format.

rotateImage() None

Rotate the image 90 degrees clockwise.

Example:

# Load an image
image = RGBImage("/path/to/image.jpg")
image_io = RGBImageFile()
image_io.setFilePath(image.getFilePath())
image.loadImage(image_io)

# Process the image
img_array = image.getImage()
processed = cv2.cvtColor(img_array, cv2.COLOR_BGR2GRAY)
image.setImage(processed)

# Add metadata
score = FloatValue("score", "score", "Analysis score")
score.setValue(95.5)
image.addValue(score)

# Save
image.saveImage(image_io, "./output")

ImageIO Classes

ImageIO Base Class

class ImageIO

Abstract base class for image file handlers. Handles loading and saving individual images.

Location: Granny/Models/IO/ImageIO.py

Attributes:

filepath: str

Full path to the image file.

image_dir: str

Directory containing the image.

image_name: str

Filename of the image.

Methods:

setFilePath(filepath: str) None

Set the file path and extract directory/filename.

Parameters

filepath – Full path to the image file

Abstract Methods:

abstract loadImage() NDArray[np.uint8]

Load and return the image data.

abstract saveImage(image: NDArray[np.uint8], output_path: str) None

Save the image to the specified directory.

abstract getType() str

Get the image type (e.g., “rgb”, “gray”).

RGBImageFile

class RGBImageFile(ImageIO)

RGB image file handler. Uses OpenCV for loading/saving.

Location: Granny/Models/IO/RGBImageFile.py

Images are loaded/saved in BGR format (OpenCV convention).

Example:

from Granny.Models.IO.RGBImageFile import RGBImageFile

# Load an image
image_io = RGBImageFile()
image_io.setFilePath("/path/to/image.jpg")
img_array = image_io.loadImage()  # Returns NDArray in BGR format

# Save an image
image_io.saveImage(img_array, "/output/directory")

Scheduler Class

class Scheduler

Manages dependencies between analyses and executes them in correct order.

Location: Granny/Interfaces/Scheduler/Scheduler.py

Uses a directed acyclic graph (DAG) with topological sorting to handle analysis dependencies.

Methods:

__init__()

Initialize the scheduler.

add_analysis(analysis: Analysis, dependencies: List[Analysis]) None

Add an analysis with its dependencies.

Parameters
  • analysis – Analysis to add

  • dependencies – List of Analysis objects this analysis depends on

Example:

scheduler = Scheduler()

segmentation = Segmentation()
starch = StarchArea()

scheduler.add_analysis(segmentation, [])
scheduler.add_analysis(starch, [segmentation])
schedule() List[int]

Determine execution order based on dependencies.

Returns

List of analysis IDs in the order they should be run

Raises

ValueError – If there is a cycle in the dependencies

run() None

Execute all analyses in dependency order.

Calls schedule() internally, then runs each analysis via performAnalysis().

Utility Functions

Analysis Discovery

To discover all available analyses:

from Granny.Analyses.Analysis import Analysis

# Get all analysis classes
analyses = Analysis.__subclasses__()

# Get analysis by name
for cls in analyses:
    if cls.__analysis_name__ == "segmentation":
        analysis = cls()
        break

Parameter Introspection

To inspect parameters of an analysis:

analysis = StarchArea()
params = analysis.getInParams()

for param_name, param_obj in params.items():
    print(f"Parameter: {param_obj.getLabel()}")
    print(f"  Type: {param_obj.getType()}")
    print(f"  Default: {param_obj.getValue()}")
    print(f"  Required: {param_obj.getIsRequired()}")
    print(f"  Help: {param_obj.getHelp()}")

    if hasattr(param_obj, 'getMin'):
        print(f"  Range: {param_obj.getMin()} - {param_obj.getMax()}")

Common Patterns

Loading and Processing Images

from Granny.Models.Images.RGBImage import RGBImage
from Granny.Models.IO.RGBImageFile import RGBImageFile

# In _processImage():
def _processImage(self, image: Image) -> Image:
    # Load image data
    image_io = RGBImageFile()
    image_io.setFilePath(image.getFilePath())
    image.loadImage(image_io)

    # Get NumPy array (BGR format)
    img_array = image.getImage()

    # Process with OpenCV/NumPy
    result = cv2.cvtColor(img_array, cv2.COLOR_BGR2GRAY)

    # Update image
    image.setImage(result)
    return image

Saving Results in _postRun()

from Granny.Models.IO.RGBImageFile import RGBImageFile

def _postRun(self, results: List[Image]) -> List[Image]:
    output_dir = self.output_images.getValue()

    image_io = RGBImageFile()
    for image in results:
        image.saveImage(image_io, output_dir)

    return results

Adding Metadata to Images

from Granny.Models.Values.StringValue import StringValue
from Granny.Models.Values.FloatValue import FloatValue

# Add metadata in _processImage()
score = FloatValue("score", "score", "Analysis score")
score.setValue(95.5)
image.addValue(score)

# Retrieve metadata in _postRun()
for image in results:
    metadata = image.getMetaData()
    if "score" in metadata:
        score_value = metadata["score"].getValue()

Setting Analysis Parameters (in interfaces)

# Get parameters
params = analysis.getInParams()

# Clear and reset
analysis.resetInParams()

# Set each parameter
for param in params.values():
    label = param.getLabel()
    if label in user_values:
        param.setValue(user_values[label])
    # else: uses default value

    analysis.addInParam(param)

Type Annotations

For better type checking, use these type hints:

from typing import List, Dict, Any, Optional
from numpy.typing import NDArray

from Granny.Models.Images.Image import Image
from Granny.Models.Values.Value import Value

def _processImage(self, image: Image) -> Image:
    ...

def _postRun(self, results: List[Image]) -> List[Image]:
    ...

def getInParams(self) -> Dict[str, Value]:
    ...

def process_array(self, img: NDArray) -> NDArray:
    ...

See Also