Skip to main content

JSON Pipeline Format

Pipelines serialize to the SerializedPipeline v3 JSON format. This format is used by:

  • The VS Code extension (*.megane.json files open as a pipeline)
  • The pipeline editor (File → Import pipeline… / Export pipeline, which downloads pipeline.megane.json; Copy share link… embeds the same JSON, compressed, in the URL)
  • The TypeScript pipe.toObject() / pipe.toJSON() methods
  • The Python pipe.to_dict() / pipe.to_json() / pipe.save(path) methods, and Pipeline.from_dict() / Pipeline.from_json() / Pipeline.load(path) to read it back

JSON pipelines can be saved, shared, and version-controlled. You can write them by hand or generate them from Python or TypeScript.

For real-world examples, see the Gallery.

Format​

{
"version": 3,
"nodes": [
{
"id": "s1",
"type": "load_structure",
"position": { "x": 0, "y": 0 },
"fileName": "protein.pdb",
"fileUrl": "protein.pdb",
"hasTrajectory": false,
"hasCell": false
},
{
"id": "ab1",
"type": "add_bond",
"position": { "x": 0, "y": 150 },
"bondSource": "distance"
},
{
"id": "v1",
"type": "viewport",
"position": { "x": 0, "y": 300 },
"perspective": false,
"cellAxesVisible": false,
"pivotMarkerVisible": false
}
],
"edges": [
{ "source": "s1", "target": "ab1", "sourceHandle": "particle", "targetHandle": "particle" },
{ "source": "s1", "target": "v1", "sourceHandle": "particle", "targetHandle": "particle" },
{ "source": "ab1", "target": "v1", "sourceHandle": "bond", "targetHandle": "bond" }
]
}

Top-level Fields​

FieldTypeDescription
versionnumberAlways 3; other versions are rejected
nodesarrayArray of node objects
edgesarrayArray of edge objects connecting nodes

Node Fields​

Every node has the following common fields:

FieldTypeDescription
idstringUnique node identifier
typestringNode type (see below)
position{ x, y }Position in the pipeline editor canvas
enabledboolean?Optional. Set to false to bypass this node (default: true)

Any parameter a node leaves out takes its default (the defaults are listed in the Node Reference). Ephemeral data — parsed topology bonds, volumetric grids, decoded spectra, trajectory frames — is never serialized by the editor; only file names are. (Python's AddBonds(top=…) is the one exception: it embeds the topology's parsed bond pairs as bondFileData, so the JSON draws those bonds without the topology file.)

Node Types and Parameters​

load_structure​

FieldTypeDescription
fileNamestring | nullPath/name of the structure file
fileUrlstring?Optional URL the React PipelineViewer fetches the file from
hasTrajectorybooleanWhether the file contains trajectory data
hasCellbooleanWhether the file contains unit cell data
editsEditOp[]?Optional structure edits replayed, in order, on the file as loaded — the Megane Builder history format (see below)

Each edits entry is an object whose op is one of add_atom, delete_atoms, move_atoms, set_element, add_bond, delete_bond, add_fragment, set_cell, supercell, slab, expand_symmetry, wrap, or center. Atom references are either indices into the file's atoms (numbers) or the id of an atom created by an earlier op in the list (strings; the whole-structure ops supercell / slab / expand_symmetry re-key every atom as <id>:<k>). Elements are atomic numbers and positions are in Å:

"edits": [
{ "op": "set_element", "atoms": [3], "element": 7 },
{ "op": "add_atom", "id": "h1", "element": 1, "position": [1.2, 0.0, 0.4], "bondTo": 3 }
]

The full op schema is in the Node Reference.

load_trajectory​

FieldTypeDescription
fileNamestring | nullPath/name of the trajectory file (XTC, DCD, NetCDF, LAMMPS dump)
source"file" | "structure""file" (default) plays the trajectory file; "structure" forwards the frames embedded in a multi-frame structure file (XYZ/PDB/.traj)

streaming​

FieldTypeDescription
connectedbooleanWhether the WebSocket stream is connected (default false)

load_vector​

FieldTypeDescription
fileNamestring | nullPath to vector data file (null: none yet)

filter​

FieldTypeDescription
querystringAtom selection query
bond_querystring?Bond selection query

modify​

FieldTypeDescription
scalenumberAtom sphere radius multiplier; on a bond stream, the bond width multiplier for the whole stream (the editor slider spans 0.1–2.0)
opacitynumberTransparency (0–1)

symmetry​

Expands a CIF's asymmetric unit into the full unit cell using the space-group operations the parser captured. Structures without symmetry operations or without a cell pass through unchanged. Ports: particle, trajectory in and out.

FieldTypeDescription
mode"expand" | "none""expand" (default) applies the operations; "none" passes through

wrap​

Periodic-image coordinate mapping for the particle stream and its trajectory. Ports: particle, trajectory in and out.

FieldTypeDescription
mode"none" | "wrap" | "unwrap""none" (default) passes through; "wrap" folds atoms into the home cell; "unwrap" makes molecules split across a periodic face whole

replicate​

Builds an nx × ny × nz supercell, copying atoms and bonds and enlarging the cell. Requires a unit cell. Ports: particle, cell, trajectory in and out.

FieldTypeDescription
nx, ny, nznumberRepeats along lattice vectors a, b, c (integers ≥ 1, default 1)

color​

Per-stream coloring (Ovito-style). Accepts a particle input on the in handle and emits the recolored particle stream on out.

FieldTypeDescription
modestring"uniform", "byElement", "byResidue", "byChain", "byBFactor", "byProperty", or "illustrative"
uniformColorstringHex color used when mode === "uniform"
range[number, number]?Optional [min, max] for byBFactor / byProperty

representation​

Per-stream representation override (Ovito-style). The Viewport resolves the mode per atom: each atom takes the mode of the first stream that covers it and carries an override, with selection (filtered) streams taking precedence over whole-structure streams. Atoms no override covers use the first non-"line" override, or "atoms" when no stream carries one. Branches that disagree are drawn per atom, so one viewport can mix representations. Accepts a particle input on the in handle and emits the tagged particle stream on out.

FieldTypeDescription
modestring"atoms" (default), "licorice", "cartoon", "both", "surface", "line", or "illustrative"

add_bond​

FieldTypeDescription
bondSourcestring"structure" (bonds from the structure file), "distance" (VDW inference, the default), "file" (a separate topology file), or "none"
bondFileNamestring?Optional. Name of the topology file used when bondSource is "file" (the editor does not serialize the parsed bonds; Python's AddBonds(top=…) writes them as bondFileData)
vdwScalenumberOptional. Threshold scale for "distance" mode: atoms bond when their separation is ≤ (vdw_i + vdw_j) * vdwScale. Higher loosens (more bonds), lower tightens. Defaults to 0.6.

label_generator​

FieldTypeDescription
sourcestring"element", "resname", or "index"

drawing_boundary​

Creates periodic display copies in an inclusive fractional-coordinate range. It does not change structural atom indices or enlarge the unit cell.

FieldTypeDescription
xMin, xMaxnumberInclusive bounds along lattice vector a (default 0, 1)
yMin, yMaxnumberInclusive bounds along lattice vector b (default 0, 1)
zMin, zMaxnumberInclusive bounds along lattice vector c (default 0, 1)

boundary_completion​

Adds bond-connected periodic display copies outside Drawing Boundary without changing crystallographic coordinates. It requires both particle and bond inputs and emits completed versions of both streams.

FieldTypeDescription
modestring"neighbors" completes one bond shell; "components" completes only finite connected components (default "neighbors")

coordination_generator​

Finds directed relationships between center atoms and their bonded neighbors. It consumes Drawing Boundary copies and emits both reusable coordination data and a renderable bond stream.

FieldTypeDescription
excludedCentersnumber[]Atomic numbers excluded from center detection (default [])
excludedLigandsnumber[]Atomic numbers excluded from neighbor detection (default [])
cutoffTolerancenumberMultiplier applied to the sum of covalent radii (default 1.15)
boundaryModestring"complete" includes periodic neighbors outside the drawing range when needed by a visible center; "inside" searches only displayed atoms

polyhedron_generator​

Converts incoming center-neighbor coordination data to convex polyhedron meshes. It owns only mesh appearance; periodic atom display and completing neighbors outside the drawing range are handled upstream.

FieldTypeDescription
opacitynumberFace transparency (0–1)
showEdgesbooleanDisplay wireframe edges
edgeColorstringWireframe edge color (hex)
edgeWidthnumberWireframe edge width (px)

surface_mesh​

FieldTypeDescription
alphaRadiusnumberProbe sphere radius in Å (alpha value). Larger = smoother surface, smaller = more detail.
colorstringSurface color (hex, e.g. "#4488ff")
opacitynumberSurface transparency (0–1)

load_volumetric​

FieldTypeDescription
fileNamestring | nullDisplay name of the volumetric file (CUBE or OpenDX). Volumetric data (volumetricData) is ephemeral and not serialized.

isosurface​

FieldTypeDescription
isoLevelnumberContour value for the positive isosurface
colorstringHex color for the positive isosurface
opacitynumberSurface transparency (0–1)
showNegativebooleanShow a second isosurface at −isoLevel (dual-contour for ESP maps)
negativeColorstringHex color for the negative isosurface
colorMode"solid" | "volume""volume" paints the surface by sampling the volume connected to the colorVolumetric input (e.g. ESP on a density)
colormap"rwb" | "bwr" | "rainbow"Colormap for colorMode: "volume" (rwb = red→white→blue, the chemistry ESP convention)
colorRange[number, number] (optional)Explicit colormap range; omit for auto (symmetric around 0 for the diverging maps)

To color a charge-density isosurface by electrostatic potential, add a second load_volumetric node for the ESP cube and connect its volumetric output to the isosurface node's colorVolumetric input, then set colorMode to "volume".

load_spectrum​

Loads a JCAMP-DX spectrum (.jdx / .jcamp). A spectrum has no 3D coordinates, so its spectrum output feeds spectrum_plot, not the Viewport.

FieldTypeDescription
fileNamestring | nullDisplay name of the JCAMP-DX file. The decoded spectrum is not serialized.

spectrum_plot​

Terminal node that draws its spectrum input as a 2D line chart.

FieldTypeDescription
reverseXbooleanDraw the x axis high-to-low, the IR/NMR convention (default true)
colorstringHex stroke color of the trace (default "#84cc16")

vector_overlay​

FieldTypeDescription
scalenumberVector arrow length multiplier

viewport​

FieldTypeDescription
perspectivebooleanPerspective (true) or orthographic (false, default) projection
cellAxesVisiblebooleanShow unit cell axes (default true)
pivotMarkerVisiblebooleanShow rotation pivot marker (default true)

Edge Fields​

FieldTypeDescription
sourcestringSource node id
targetstringTarget node id
sourceHandlestringOutput port name (e.g., "particle", "bond", "mesh")
targetHandlestringInput port name (e.g., "particle", "bond", "in")

Loading Behavior​

When a pipeline is loaded (editor import, a share link, a .megane.json in VS Code, PipelineViewer), Megane:

  • rejects any version other than 3 and any unknown node type;

  • fills missing parameters with the node's defaults and drops fields from older formats (e.g. colorScheme / representationMode on viewport, color fields on modify);

  • migrates the older particle → polyhedron_generator shape by inserting drawing_boundary and coordination_generator nodes;

  • completes the canonical load_structure → add_bond → viewport wiring for each structure loader, against the viewport its particle stream reaches (through filter / modify / symmetry / wrap / replicate / drawing-boundary / boundary-completion nodes), or the first viewport when it reaches none:

    • an add_bond node is injected unless the loader's particle output already feeds an add_bond or a bond stream derived from the loader already reaches the viewport's bond input;
    • the loader's particle is connected to the viewport only when no particle path exists, its cell only when the viewport has no cell input yet, and its trajectory when hasTrajectory is true.

    Existing nodes and edges are never removed.

File names are resolved per host. VS Code and JupyterLab read every loader's fileName (load_structure, load_trajectory, load_vector, load_volumetric, load_spectrum) and add_bond's bondFileName relative to the .megane.json file's directory (absolute paths and paths that leave that directory are ignored). The React PipelineViewer fetches each load_structure node's fileUrl. Python's Pipeline.from_dict() resolves relative paths from the current working directory.

Example: Crystal with Polyhedra​

{
"version": 3,
"nodes": [
{
"id": "s1",
"type": "load_structure",
"position": { "x": 0, "y": 0 },
"fileName": "perovskite_srtio3_3x3x3.xyz",
"fileUrl": "perovskite_srtio3_3x3x3.xyz",
"hasTrajectory": false,
"hasCell": true
},
{
"id": "boundary1",
"type": "drawing_boundary",
"position": { "x": 0, "y": 180 },
"xMin": 0,
"xMax": 1,
"yMin": 0,
"yMax": 1,
"zMin": 0,
"zMax": 1
},
{
"id": "coord1",
"type": "coordination_generator",
"position": { "x": 0, "y": 360 },
"excludedCenters": [38],
"excludedLigands": [],
"cutoffTolerance": 1.15,
"boundaryMode": "complete"
},
{
"id": "poly1",
"type": "polyhedron_generator",
"position": { "x": 170, "y": 530 },
"opacity": 0.5,
"showEdges": true,
"edgeColor": "#dddddd",
"edgeWidth": 2
},
{
"id": "v1",
"type": "viewport",
"position": { "x": 0, "y": 615 },
"perspective": false,
"cellAxesVisible": true,
"pivotMarkerVisible": true
}
],
"edges": [
{
"source": "s1",
"target": "boundary1",
"sourceHandle": "particle",
"targetHandle": "particle"
},
{
"source": "boundary1",
"target": "coord1",
"sourceHandle": "particle",
"targetHandle": "particle"
},
{
"source": "boundary1",
"target": "v1",
"sourceHandle": "particle",
"targetHandle": "particle"
},
{ "source": "s1", "target": "v1", "sourceHandle": "cell", "targetHandle": "cell" },
{ "source": "coord1", "target": "v1", "sourceHandle": "bond", "targetHandle": "bond" },
{
"source": "coord1",
"target": "poly1",
"sourceHandle": "coordination",
"targetHandle": "coordination"
},
{ "source": "poly1", "target": "v1", "sourceHandle": "mesh", "targetHandle": "mesh" }
]
}

Example: Atom Filter with Branching​

{
"version": 3,
"nodes": [
{
"id": "s1",
"type": "load_structure",
"position": { "x": 170, "y": 0 },
"fileName": "caffeine_water.pdb",
"fileUrl": "caffeine_water.pdb",
"hasTrajectory": false,
"hasCell": false
},
{
"id": "fc1",
"type": "filter",
"position": { "x": 0, "y": 150 },
"query": "index < 24"
},
{
"id": "mc1",
"type": "modify",
"position": { "x": 0, "y": 300 },
"scale": 3.0,
"opacity": 1.0
},
{
"id": "fw1",
"type": "filter",
"position": { "x": 340, "y": 150 },
"query": "index >= 24"
},
{
"id": "mw1",
"type": "modify",
"position": { "x": 340, "y": 300 },
"scale": 1.0,
"opacity": 0.15
},
{
"id": "v1",
"type": "viewport",
"position": { "x": 170, "y": 450 },
"perspective": false,
"cellAxesVisible": false,
"pivotMarkerVisible": false
}
],
"edges": [
{ "source": "s1", "target": "fc1", "sourceHandle": "particle", "targetHandle": "in" },
{ "source": "fc1", "target": "mc1", "sourceHandle": "out", "targetHandle": "in" },
{ "source": "mc1", "target": "v1", "sourceHandle": "out", "targetHandle": "particle" },
{ "source": "s1", "target": "fw1", "sourceHandle": "particle", "targetHandle": "in" },
{ "source": "fw1", "target": "mw1", "sourceHandle": "out", "targetHandle": "in" },
{ "source": "mw1", "target": "v1", "sourceHandle": "out", "targetHandle": "particle" }
]
}