Skip to content

Types and Nodes#

Every procedure in CaptureGraph has a return type and fits into a node category. Understanding these is essential for building valid workflows.

The PType System#

Every procedure returns a PType:

import capturegraph.procedures as cgp

image: cgp.Procedure[cgp.PImage] = cgp.CaptureImage(label="Take a photo")
text: cgp.Procedure[cgp.PString] = cgp.UserInputString(label="Enter notes")
flag: cgp.Procedure[cgp.PBool] = cgp.UserInputBool(label="Is this correct?")

Note: You always work with Procedure[PType] objects, not raw PType values. The procedure represents the node that will produce the value at runtime.

Common PTypes#

Type Description Example
PImage Photo or image data cgp.CaptureImage()
PString Text data cgp.UserInputString()
PNumber Numeric value cgp.UserInputNumber()
PBool Boolean flag cgp.UserInputBool()
PLocation GPS coordinates cgp.CaptureLocation()
PDirectory Directory reference cgp.GetRootDirectory()
PFile File reference session.new_file("x")
PVoid No return value session.new_file("x").save(...)

PVoid and ProcedureSequence#

ProcedureSequence chains multiple procedures together. All sub-procedures must return PVoid:

return cgp.ProcedureSequence(
    label="My Workflow",
    procedures=[
        # .save() returns PVoid ✓
        session.new_file("photo").save(cgp.CaptureImage()),
        session.new_file("notes").save(cgp.UserInputString(label="Notes")),
    ]
)

If you accidentally use a procedure that returns data instead of PVoid:

cgp.ProcedureSequence(
    procedures=[
        # .cache() returns PImage, not PVoid ✗
        session.new_file("photo").cache(cgp.CaptureImage()),
    ]
)

You'll get a clear error:

TypeError: Substeps for 'ProcedureSequence' must return 'PVoid',
but 'CacheProcedureToFile' returns 'PImage' instead.

Node Taxonomy#

Nodes are categorized by their runtime behavior:

Automatic Nodes (Invisible)#

Execute instantly without user interaction:

  • Control: cgp.IfThenElse, cgp.switch_case
  • Operators: cgp.BoolAnd, comparisons
  • Constants: cgp.ConstantString, cgp.ConstantNumber, cgp.ConstantBool
  • Conversions: cgp.ConvertImageToThumbnail
  • Structural: cgp.ProcedureSequence, cgp.ProcedureSet

These handle computation and logic—users never see them directly. See the Automatic Nodes API.

Action Nodes (Visible)#

Block execution until user input is provided:

  • Capture: cgp.CaptureImage, cgp.CaptureLocation, cgp.CaptureImageSequence
  • User Input: cgp.UserInputString, cgp.UserInputNumber, cgp.UserInputBool, cgp.UserInputOptimalSolarTime

These render UI elements in the app. See the Action Nodes API.

Storage Nodes#

Handle file system operations. See the Filesystem Nodes API.

Labels#

Any node can have a label parameter, but only Action Nodes display it to users:

# Label shown to user
cgp.CaptureImage(label="Take the daily photo")

# Label used for debugging only
cgp.ConvertImageToThumbnail(label="generate thumbnail", image=photo)

Keyword Arguments#

All procedure parameters must be keyword arguments:

# ✗ Wrong - positional argument
cgp.ProcedureSequence([
    session.new_file("photo").save(image),
])

# ✓ Correct - keyword argument
cgp.ProcedureSequence(
    procedures=[
        session.new_file("photo").save(image),
    ]
)

This ensures clarity and prevents parameter ordering mistakes.

Type Validation#

Type checking happens at three stages:

  1. Static analysis via Python type hints
  2. Runtime via __post_init__ validation
  3. Device execution in the iOS app

This catches errors before they reach the device, speeding up development.

See Also#