Tutorial: Defining Specifications in a Spreadsheet#

When a project has many pipes, hand-writing a Port, PipeType and Specification for each one in Python becomes tedious and error-prone. Specification can instead read your pipe definitions directly from a spreadsheet — either a single Excel workbook or a pair of CSV files — and return a ready-to-route list[Specification].

This is the natural entry point for spreadsheet-driven workflows and for engineers who prefer to maintain routing data in Excel rather than in code.

The Data Model: Two Tables#

Both the Excel and the CSV variant use the same two-table layout:

  • pipe_types — one row per pipe type (its radius, curvature constraints, color, …).

  • specifications — one row per pipe to route, referencing a pipe type by name and giving the start and end port of the route.

In Excel these are two sheets (named exactly pipe_types and specifications) in one workbook. In CSV they are two separate files.

Pipe types are deduplicated by name: every specification that references the same pipe_type name shares a single PipeType instance.

Loading from Excel (.xlsx)#

Wrap the file in a BinaryFile stream and call from_xlsx():

from dessia_common.files import BinaryFile

from routing.core.core import Specification

stream = BinaryFile.from_file("specifications.xlsx")
specifications = Specification.from_xlsx(stream)

print(f"Loaded {len(specifications)} specifications")
for spec in specifications:
    pipe_type = spec.pipe_type
    print(f"  {spec.name}: pipe_type={pipe_type.name}, "
          f"radius={pipe_type.section.radius_equivalent}")
    print(f"    start={spec.start.coordinates} -> end={spec.end.coordinates}")

from_xlsx returns a flat list[Specification]. Specifications that reference the same pipe type share one PipeType object:

# Two specs that both use "hydraulic_12" point to the same instance
assert specifications[0].pipe_type is specifications[2].pipe_type

Loading from CSV#

The CSV variant takes the two file paths directly — no stream wrapper needed:

from routing.core.core import Specification

specifications = Specification.from_csv(
    "pipe_types.csv",
    "specifications.csv",
)

The columns are identical to the Excel sheets (see the reference tables below).

Routing the Loaded Specifications#

The returned list plugs straight into the normal routing pipeline — it is the same list[Specification] you would otherwise have built by hand:

from routing.core.finders import SmartFinder
from routing.core.route_planner import RoutePlanner

# cadmap built as usual from your CAD environment (see basic_routing)
finder = SmartFinder("AStar", "manhattan", "never")
route_planner = RoutePlanner(cadmap, finder)
routing_result = route_planner.generate(specifications, 0, False)
routing_result.display_3d()

See Tutorial: Routing Pipes Through a CAD Assembly for how to build the cadmap from your CAD model.

Column Reference: pipe_types#

One row per pipe type. The first row is the header. name and radius are required; empty cells in optional columns fall back to the PipeType default shown below.

Column

Required

Default

Description

name

yes

Unique pipe-type identifier, referenced from the specifications sheet.

radius

yes

Equivalent section radius, in metres.

radius_of_curvature_ratio

no

1.0

Minimum ratio between bend radius and pipe radius.

min_straight_length

no

0.0

Minimum straight length before a turn, in metres.

min_slope

no

no constraint

Minimum allowed slope (useful for gravity systems; negative value).

max_slope

no

no constraint

Maximum allowed slope.

number_turn_max

no

0 (unlimited)

Maximum number of turns allowed (0 means no limit).

pooling_type

no

"None"

Pooling group for this pipe type.

priority_index

no

none

Routing priority (lower routes first).

color_r

no

0.1

Red component of the display color (0–1).

color_g

no

0.1

Green component of the display color (0–1).

color_b

no

0.1

Blue component of the display color (0–1).

Column Reference: specifications#

One row per route. All columns are required. start_* columns describe the start port, end_* columns the end port.

Column

Description

Unit

name

Specification name.

pipe_type

Pipe-type name; must match a name in the pipe_types table.

start_x / start_y / start_z

Start-port coordinates.

metres

start_dx / start_dy / start_dz

Start-port exit direction (need not be normalized).

start_length

Straight length imposed at the start port before the first turn.

metres

end_x / end_y / end_z

End-port coordinates.

metres

end_dx / end_dy / end_dz

End-port exit direction (need not be normalized).

end_length

Straight length imposed at the end port.

metres

All lengths and coordinates are in metres, consistent with the rest of the routing module. Direction vectors are normalized automatically.

Example Data#

A minimal pipe_types.csv:

name,radius,radius_of_curvature_ratio,min_straight_length,pooling_type,color_r,color_g,color_b,priority_index,number_turn_max
hydraulic_12,0.012,2.0,0.05,hydraulic,0.8,0.2,0.1,1,
electric_8,0.008,,,electric,0.1,0.1,0.8,2,5

A matching specifications.csv:

name,pipe_type,start_x,start_y,start_z,start_dx,start_dy,start_dz,start_length,end_x,end_y,end_z,end_dx,end_dy,end_dz,end_length
spec_1,hydraulic_12,0.0,0.0,0.0,1.0,0.0,0.0,0.1,1.0,1.0,0.0,-1.0,0.0,0.0,0.1
spec_2,electric_8,0.5,0.0,0.0,0.0,1.0,0.0,0.05,0.5,2.0,1.0,0.0,-1.0,0.0,0.05
spec_3,hydraulic_12,0.0,0.0,1.0,0.0,0.0,1.0,0.08,1.0,1.0,1.0,0.0,0.0,-1.0,0.08

Here spec_1 and spec_3 both reference hydraulic_12 and will therefore share one PipeType instance.

A runnable version of this workflow, with sample .xlsx and .csv files, lives in scripts/simple_test_cases/specification_from_spreadsheet.py.

Next Steps#