Holoscan SDK v3.11.0

Class Subgraph

class Subgraph

A reusable subgraph that directly populates a Fragment’s operator graph.

Subgraph receives Fragment* during construction and directly adds operators and flows to the Fragment’s main graph during compose().

Usage example:

Copy
Copied!
            

class CameraSubgraph : public Subgraph { public: CameraSubgraph(Fragment* fragment, const std::string& name) : Subgraph(fragment, name) {} void compose() override { auto source = make_operator<V4L2VideoOp>("source", from_config("v4l2")); auto converter = make_operator<FormatConverterOp>("converter", from_config("format_converter")); add_flow(source, converter); // Directly added to Fragment's main graph // Expose interface ports for external connections // The "tensor" output port of converter will be exposed as "video_out" add_output_interface_port("video_out", converter, "tensor"); } }; // In Fragment::compose(): // Note that for subgraph name "camera1" and "camera2", the operator names will become // "camera1_source", "camera2_source", "camera1_converter", "camera2_converter". auto camera1 = make_subgraph<CameraSubgraph>("camera1"); auto camera2 = make_subgraph<CameraSubgraph>("camera2"); auto visualizer = make_operator<HolovizOp>("visualizer", from_config("holoviz")); // Direct connection to other operators (or subgraphs) via interface ports add_flow(camera1, visualizer, {{"video_out", "receivers"}}); add_flow(camera2, visualizer, {{"video_out", "receivers"}});

Public Functions

Subgraph(Fragment *fragment, const std::string &name, const std::string &config_file = "")

Construct Subgraph with target Fragment.

Parameters
  • fragment – Target Fragment to populate with operators

  • name – Unique instance name for operator qualification

  • config_file – Optional path to a YAML configuration file for this subgraph. If provided, the configuration is loaded before compose() is called, making from_config() available during composition.

virtual ~Subgraph() = default
virtual void compose() = 0

Define the internal structure of the subgraph.

This method should create operators and flows, which will be directly added to the Fragment’s main graph with qualified names.

inline const std::string &name() const

Get the name for this subgraph.

inline const std::string &instance_name() const

Get the instance name for this subgraph.

Deprecated:

Use name() instead. This method will be removed in a future release.

inline Fragment *fragment()

Get the Fragment that this subgraph belongs to.

Returns

Pointer to the fragment this subgraph belongs to

inline const Fragment *fragment() const

Get the Fragment that this subgraph belongs to (const version)

Returns

Const pointer to the fragment this subgraph belongs to

inline std::string get_qualified_name(const std::string &object_name, const std::string &type_name = "operator") const

Create qualified operator name: subgraph_name + “_” + operator_name.

template<typename OperatorT, typename StringT, typename ...ArgsT, typename = std::enable_if_t<std::is_constructible_v<std::string, StringT>>>
std::shared_ptr<OperatorT> make_operator(StringT name, ArgsT&&... args)
template<typename OperatorT, typename ...ArgsT>
std::shared_ptr<OperatorT> make_operator(ArgsT&&... args)
template<typename ConditionT, typename StringT, typename ...ArgsT, typename = std::enable_if_t<std::is_constructible_v<std::string, StringT>>>
std::shared_ptr<ConditionT> make_condition(StringT name, ArgsT&&... args)
template<typename ConditionT, typename ...ArgsT>
std::shared_ptr<ConditionT> make_condition(ArgsT&&... args)
template<typename ResourceT, typename StringT, typename ...ArgsT, typename = std::enable_if_t<std::is_constructible_v<std::string, StringT>>>
std::shared_ptr<ResourceT> make_resource(StringT name, ArgsT&&... args)
template<typename ResourceT, typename ...ArgsT>
std::shared_ptr<ResourceT> make_resource(ArgsT&&... args)
template<typename ServiceT>
bool register_service(const std::shared_ptr<ServiceT> &svc, std::string_view id = "")

Register an existing service instance with the fragment.

Registers an already created service instance with the fragment. This allows the service to be retrieved later using Fragment::service().

Template Parameters

ServiceT – The type of the service (must inherit from Resource or FragmentService).

Parameters
  • svc – The shared pointer to the service instance to register.

  • id – The identifier for the service registration. If empty, uses the service type or resource name as identifier.

Returns

true if the service was successfully registered, false otherwise.

template<typename SubgraphT, typename ...ArgsT>
inline std::shared_ptr<SubgraphT> make_subgraph(const std::string &child_name, ArgsT&&... args)

Create a nested subgraph within this subgraph.

This enables hierarchical Subgraph composition. The nested Subgraph will use the same Fragment* and will have its operators added directly to the Fragment’s main graph with hierarchical qualified names (parent_name_child_name_operator).

Template Parameters

SubgraphT – The nested subgraph class type

Parameters
  • child_name – Name for the nested subgraph

  • args – Additional arguments for the nested subgraph constructor

Returns

Shared pointer to the nested subgraph

void add_operator(const std::shared_ptr<Operator> &op)

Add an operator to the Fragment’s main graph with qualified name.

This directly calls fragment_->add_operator() with a qualified name, eliminating the need for intermediate graph storage.

void add_subgraph(const std::shared_ptr<Subgraph> &subgraph)

Add a subgraph to the Fragment.

This method ensures the subgraph is composed and its operators are added to the fragment. Use this method when a nested subgraph has no interface ports and doesn’t need to be connected to other operators or subgraphs via add_flow.

Parameters

subgraph – The subgraph to be added.

void add_flow(const std::shared_ptr<Operator> &upstream, const std::shared_ptr<Operator> &downstream, std::set<std::pair<std::string, std::string>> port_pairs = {})

Add a flow between two operators directly in the Fragment’s main graph.

This directly calls fragment_->add_flow(), eliminating the need for intermediate flow storage.

void add_flow(const std::shared_ptr<Operator> &upstream_op, const std::shared_ptr<Subgraph> &downstream_subgraph, std::set<std::pair<std::string, std::string>> port_pairs = {})

Connect Operator to Subgraph within this Subgraph.

Parameters
  • upstream_op – The upstream operator

  • downstream_subgraph – The downstream subgraph

  • port_pairs – Port connections: {upstream_port, subgraph_interface_port}

void add_flow(const std::shared_ptr<Subgraph> &upstream_subgraph, const std::shared_ptr<Operator> &downstream_op, std::set<std::pair<std::string, std::string>> port_pairs = {})

Connect Subgraph to Operator within this Subgraph.

Parameters
  • upstream_subgraph – The upstream subgraph

  • downstream_op – The downstream operator

  • port_pairs – Port connections: {subgraph_interface_port, downstream_port}

void add_flow(const std::shared_ptr<Subgraph> &upstream_subgraph, const std::shared_ptr<Subgraph> &downstream_subgraph, std::set<std::pair<std::string, std::string>> port_pairs = {})

Connect Subgraph to Subgraph within this Subgraph.

Parameters
  • upstream_subgraph – The upstream subgraph

  • downstream_subgraph – The downstream subgraph

  • port_pairs – Port connections: {upstream_interface_port, downstream_interface_port}

void add_flow(const std::shared_ptr<Operator> &upstream_op, const std::shared_ptr<Subgraph> &downstream_subgraph, const IOSpec::ConnectorType connector_type)

Connect Operator to Subgraph with connector type.

Parameters
  • upstream_op – The upstream operator

  • downstream_subgraph – The downstream subgraph

  • connector_type – The connector type

void add_flow(const std::shared_ptr<Operator> &upstream_op, const std::shared_ptr<Subgraph> &downstream_subgraph, std::set<std::pair<std::string, std::string>> port_pairs, const IOSpec::ConnectorType connector_type)

Connect Operator to Subgraph with port pairs and connector type.

Parameters
  • upstream_op – The upstream operator

  • downstream_subgraph – The downstream subgraph

  • port_pairs – Port connections: {upstream_port, subgraph_interface_port}

  • connector_type – The connector type

void add_flow(const std::shared_ptr<Subgraph> &upstream_subgraph, const std::shared_ptr<Operator> &downstream_op, const IOSpec::ConnectorType connector_type)

Connect Subgraph to Operator with connector type.

Parameters
  • upstream_subgraph – The upstream subgraph

  • downstream_op – The downstream operator

  • connector_type – The connector type

void add_flow(const std::shared_ptr<Subgraph> &upstream_subgraph, const std::shared_ptr<Operator> &downstream_op, std::set<std::pair<std::string, std::string>> port_pairs, const IOSpec::ConnectorType connector_type)

Connect Subgraph to Operator with port pairs and connector type.

Parameters
  • upstream_subgraph – The upstream subgraph

  • downstream_op – The downstream operator

  • port_pairs – Port connections: {subgraph_interface_port, downstream_port}

  • connector_type – The connector type

void add_flow(const std::shared_ptr<Subgraph> &upstream_subgraph, const std::shared_ptr<Subgraph> &downstream_subgraph, const IOSpec::ConnectorType connector_type)

Connect Subgraph to Subgraph with connector type.

Parameters
  • upstream_subgraph – The upstream subgraph

  • downstream_subgraph – The downstream subgraph

  • connector_type – The connector type

void add_flow(const std::shared_ptr<Subgraph> &upstream_subgraph, const std::shared_ptr<Subgraph> &downstream_subgraph, std::set<std::pair<std::string, std::string>> port_pairs, const IOSpec::ConnectorType connector_type)

Connect Subgraph to Subgraph with port pairs and connector type.

Parameters
  • upstream_subgraph – The upstream subgraph

  • downstream_subgraph – The downstream subgraph

  • port_pairs – Port connections: {upstream_interface_port, downstream_interface_port}

  • connector_type – The connector type

virtual void set_dynamic_flows(const std::shared_ptr<Operator> &op, const std::function<void(const std::shared_ptr<Operator>&)> &dynamic_flow_func)

Set a callback function to define dynamic flows for an operator at runtime.

This method allows operators to modify their connections with other operators during execution. The callback function is called after the operator executes and can add dynamic flows using the operator’s add_dynamic_flow() methods.

Parameters
  • op – The operator to set dynamic flows for

  • dynamic_flow_func – The callback function that defines the dynamic flows. Takes a shared pointer to the operator as input and returns void.

void add_data_logger(const std::shared_ptr<DataLogger> &logger)

Add a data logger to the fragment.

This method dispatches to the fragment’s add_data_logger method.

Parameters

logger – The data logger to add.

void add_interface_port(const std::string &external_name, const std::shared_ptr<Operator> &internal_op, std::optional<std::string> internal_port = std::nullopt, std::optional<bool> is_input = std::nullopt)

Add an interface port that can be connected from external Subgraphs/Operators.

Validates that the internal operator has the specified port. If is_input is not specified, the method automatically detects whether the port is an input or output. If the port name exists in both inputs and outputs, a runtime_error is thrown requiring explicit specification.

Parameters
  • external_name – The name of the interface port (used in add_flow calls)

  • internal_op – The internal operator that owns the actual port

  • internal_port – The port name on the internal operator (defaults to external_name if not specified)

  • is_input – Whether this is an input port (true) or output port (false). If not specified, the port direction is auto-detected from the operator’s port definitions.

void add_input_interface_port(const std::string &external_name, const std::shared_ptr<Operator> &internal_op, std::optional<std::string> internal_port = std::nullopt)

Add an input interface port (convenience method)

Parameters
  • external_name – The name of the interface port (used in add_flow calls)

  • internal_op – The internal operator that owns the actual port

  • internal_port – The port name on the internal operator (defaults to external_name if not specified)

void add_output_interface_port(const std::string &external_name, const std::shared_ptr<Operator> &internal_op, std::optional<std::string> internal_port = std::nullopt)

Add an output interface port (convenience method)

Parameters
  • external_name – The name of the interface port (used in add_flow calls)

  • internal_op – The internal operator that owns the actual port

  • internal_port – The port name on the internal operator (defaults to external_name if not specified)

void add_interface_port(const std::string &external_name, const std::shared_ptr<Subgraph> &internal_subgraph, std::optional<std::string> internal_interface_port = std::nullopt, std::optional<bool> is_input = std::nullopt)

Add an interface port that exposes a nested subgraph’s interface port.

This method enables hierarchical port composition by exposing an interface port from a nested subgraph as an external interface port of the current subgraph. The nested subgraph’s interface port is resolved to find the underlying operator and port, which are then registered as the current subgraph’s interface port.

If is_input is not specified, the port direction is auto-detected from the nested subgraph’s interface port definition.

Parameters
  • external_name – The name of the interface port (used in add_flow calls)

  • internal_subgraph – The nested subgraph whose interface port to expose

  • internal_interface_port – The interface port name on the nested subgraph (defaults to external_name if not specified)

  • is_input – Whether this is an input port (true) or output port (false). If not specified, the port direction is auto-detected from the nested subgraph’s interface port.

void add_input_interface_port(const std::string &external_name, const std::shared_ptr<Subgraph> &internal_subgraph, std::optional<std::string> internal_interface_port = std::nullopt)

Add an input interface port from a nested subgraph (convenience method)

Parameters
  • external_name – The name of the interface port (used in add_flow calls)

  • internal_subgraph – The nested subgraph whose interface port to expose

  • internal_interface_port – The interface port name on the nested subgraph (defaults to external_name if not specified)

void add_output_interface_port(const std::string &external_name, const std::shared_ptr<Subgraph> &internal_subgraph, std::optional<std::string> internal_interface_port = std::nullopt)

Add an output interface port from a nested subgraph (convenience method)

Parameters
  • external_name – The name of the interface port (used in add_flow calls)

  • internal_subgraph – The nested subgraph whose interface port to expose

  • internal_interface_port – The interface port name on the nested subgraph (defaults to external_name if not specified)

void add_input_exec_interface_port(const std::string &external_name, const std::shared_ptr<Operator> &internal_op)

Add an input execution interface port for control flow.

Exposes an execution port from an internal operator for control flow connections. The internal operator must be a Native operator with an input execution spec.

Parameters
  • external_name – The name of the interface port (used in add_flow calls)

  • internal_op – The internal operator that has the execution port

void add_output_exec_interface_port(const std::string &external_name, const std::shared_ptr<Operator> &internal_op)

Add an output execution interface port for control flow.

Exposes an execution port from an internal operator for control flow connections. The internal operator must be a Native operator with an output execution spec.

Parameters
  • external_name – The name of the interface port (used in add_flow calls)

  • internal_op – The internal operator that has the execution port

void add_input_exec_interface_port(const std::string &external_name, const std::shared_ptr<Subgraph> &internal_subgraph, std::optional<std::string> internal_interface_port = std::nullopt)

Add an input execution interface port from a nested subgraph.

Exposes an execution interface port from a nested subgraph as this subgraph’s execution interface port, enabling hierarchical control flow composition.

Parameters
  • external_name – The name of the interface port (used in add_flow calls)

  • internal_subgraph – The nested subgraph whose exec interface port to expose

  • internal_interface_port – The exec interface port name on the nested subgraph (defaults to external_name if not specified)

void add_output_exec_interface_port(const std::string &external_name, const std::shared_ptr<Subgraph> &internal_subgraph, std::optional<std::string> internal_interface_port = std::nullopt)

Add an output execution interface port from a nested subgraph.

Exposes an execution interface port from a nested subgraph as this subgraph’s execution interface port, enabling hierarchical control flow composition.

Parameters
  • external_name – The name of the interface port (used in add_flow calls)

  • internal_subgraph – The nested subgraph whose exec interface port to expose

  • internal_interface_port – The exec interface port name on the nested subgraph (defaults to external_name if not specified)

inline const std::unordered_map<std::string, InterfacePort> &interface_ports() const

Get data interface ports.

Returns a map of interface port names to InterfacePort objects. Each InterfacePort can contain multiple mappings for broadcast input ports.

inline const std::unordered_map<std::string, InterfacePort> &exec_interface_ports() const

Get execution interface ports.

std::pair<std::shared_ptr<Operator>, std::string> get_interface_operator_port(const std::string &port_name) const

Get the first operator/port for a data interface port name.

This method first checks local interface ports, then recursively checks nested subgraphs for hierarchical port resolution.

For broadcast input ports that have multiple mappings, this returns only the first mapping. Access the InterfacePort directly via interface_ports() to get all mappings.

Parameters

port_name – The interface port name

Returns

Pair of (operator, actual_port_name) or (nullptr, “”) if not found

std::pair<std::shared_ptr<Operator>, std::string> get_exec_interface_operator_port(const std::string &port_name) const

Get the operator/port for an execution interface port name.

This method first checks local exec interface ports, then recursively checks nested subgraphs for hierarchical port resolution.

Parameters

port_name – The exec interface port name

Returns

Pair of (operator, actual_port_name) or (nullptr, “”) if not found

inline bool is_composed() const

Check if the subgraph has been composed.

inline void set_composed(bool composed)

Set the composed state of the subgraph.

std::vector<std::shared_ptr<Operator>> operators() const

Get all operators belonging to this subgraph and its nested subgraphs.

This method returns all operators whose names are prefixed with this subgraph’s name followed by an underscore. This includes operators from nested subgraphs since their names are also prefixed with the parent subgraph’s name.

Returns

Vector of shared pointers to the operators.

Config &config()

Get the configuration of the subgraph.

Returns

The reference to the configuration of the subgraph (Config object.)

std::shared_ptr<Config> config_shared()

Get the shared pointer to the configuration of the subgraph.

Returns

The shared pointer to the configuration of the subgraph.

ArgList from_config(const std::string &key)

Get the value of a configuration key as an ArgList.

This method retrieves the value from the subgraph’s configuration for the given key. You can use ‘.’ (dot) to access nested fields. The returned ArgList can be passed directly to make_operator() or other methods that accept configuration arguments.

Example usage:

Copy
Copied!
            

auto op = make_operator<MyOp>("my_op", from_config("my_op"));

Parameters

key – The key of the configuration.

Returns

The argument list of the configuration for the key.

std::unordered_set<std::string> config_keys()

Determine the set of keys present in the subgraph’s config.

Returns

The set of valid keys.

Protected Functions

void config(const std::string &config_file, const std::string &prefix = "")

Set the configuration of the subgraph from a file.

The configuration file is a YAML file that contains parameter values that can be accessed via from_config(). This is useful when a subgraph needs its own configuration separate from the main application configuration.

Note

This method is protected because configuration must be set before compose() runs. Pass the config_file to the Subgraph constructor instead.

Note

Loading GXF extensions is not supported from the subgraph config file. GXF extensions should be loaded via the application-level configuration only.

Parameters
  • config_file – The path to the configuration file.

  • prefix – The prefix string that is prepended to the key of the configuration.

Throws

RuntimeError – if the config_file is non-empty and the file doesn’t exist.

Previous Class StreamOrderedAllocator
Next Class SyntheticClock
© Copyright 2022-2026, NVIDIA. Last updated on Feb 4, 2026