factoriax.analysis.recipe_graph#
Render a recipe DAG as a layered crafting diagram.
Public surface:
RecipeSpec: plain-Python recipe, decoupled from the JAX-backed engine so callers can render diagrams from a JSON dump.Layout: geometry constants.render(): top-level entry that consumes recipes and writes a PNG (or SVG, by file extension).
The renderer runs as a chain of helpers. Each one takes the values it
needs and returns plain data. Only the _draw_* helpers call
matplotlib.
The chain builds the adjacency map, then the positions, then the node
colors through factoriax.analysis.categories.item_palette(). It
then assigns the ports of each two-input recipe, gives every edge a
channel, and routes each edge. A route takes one of three forms:
between neighboring tiers, across a lane between rows, or over the
skyway above the top row. The boxes and edges are drawn last.
Module Attributes
Ports on the left edge of a box. |
- class factoriax.analysis.recipe_graph.Layout(box_w: float = 4.0, box_h: float = 0.7, tier_x_step: float = 6.0, row_y_step: float = 1.5, port_offset_frac: float = 0.3, left_inset: float = 0.06, right_inset: float = 0.06, input_name_max_chars: int = 14, hub_threshold: int = 4, hub_alpha: float = 0.55, normal_alpha: float = 1.0, fallback_color: str = '#cccccc', stroke_darken: float = 0.55)#
Geometry constants for the recipe DAG render.
The defaults are tuned against the easy-rocket recipe set. Pass a different instance through the
layoutargument ofrender()when a figure needs other proportions.Distances are matplotlib data units. The aspect ratio is locked to 1, so one unit along x equals one unit along y.
- box_w, box_h
The size of one node box.
- tier_x_step#
The distance from one tier column to the next. It must be larger than
box_w, or the gap between columns closes and the edge channels have nowhere to go.- Type:
- port_offset_frac#
The offset of the two ports from the middle of a box, as a fraction of
box_h. Seeport_offset.- Type:
- left_inset, right_inset
The padding inside a box, before the input labels on the left and the result label on the right.
- input_name_max_chars#
Where to cut an input label. A longer name is truncated with an ellipsis.
- Type:
- hub_threshold#
An item that feeds this many recipes counts as a hub. Its outgoing edges are drawn with
hub_alpha.- Type:
- hub_alpha, normal_alpha
The opacity of an edge from a hub, and from any other node. Fading the hub edges keeps a busy node such as a plate from hiding the rest of the graph.
- factoriax.analysis.recipe_graph.MAX_PORTS: int = 2#
Ports on the left edge of a box. This value limits how many inputs a recipe drawn here can have. It equals
MAX_RECIPE_INPUTSin the engine, but is repeated to keep the JAX-backed import out of this module.
- class factoriax.analysis.recipe_graph.RecipeSpec(output: str, inputs: tuple[tuple[str, int], ...], ticks: int, output_count: int = 1, name: str = '')#
Plain-Python recipe used by the renderer.
This mirrors
factoriax.engine.recipes.Recipe, but names items with strings instead of enum values. A caller can therefore draw a diagram from a JSON dump with no import of the JAX-backed engine module.- output#
The item this recipe makes. It is also the key under which the layout code finds the recipe.
- Type:
- inputs#
((item_name, count), ...). The order is kept, because two inputs at the same height fall back to it when they choose ports. A recipe must have one or two inputs, which_assign_ports()checks.
- ticks#
How long one craft takes, in engine ticks. It is shown in the box subtitle and used nowhere else.
- Type:
- factoriax.analysis.recipe_graph.render(recipes: Sequence[RecipeSpec], out_path: Path | str, *, title: str = '', layout: Layout | None = None) Path#
Draw the recipe graph and return the path of the new file.
The pipeline runs in stages. Tiers and rows come from
factoriax.analysis.graph_layout. Positions come from_positions(), ports from_assign_ports(), and channels from_allocate_edge_channels()._route_edge()gives each edge its corners. The_draw_*helpers then put those numbers on the axes.- Parameters:
recipes – The recipes to draw. Each must have one or two inputs. Every item named as an input gets a box, whether or not it has a recipe of its own.
out_path – Where to write the image. The extension sets the format, and matplotlib accepts PNG and SVG among others. Missing parent directories are created.
title – A title over the figure, or
""for none.layout – Geometry constants, or
Nonefor the defaults.
- Returns:
out_pathas aPath, after the write.- Return type:
- Raises:
ValueError – When a recipe has no inputs or more than
MAX_PORTS, or when the recipes hold a cycle, or whenrecipesis empty.
Notes
The function writes a file and closes its own figure. The figure size grows with the tier count and the tallest column. A large recipe set therefore gives a large image, and not a crowded one.