Skip to content
Open Garphield

Projects

A .gph project holds the graph and the visual workspace around it: positions, encodings, filters, history, sets, and story.

The R package reads and writes the same .gph format. See garphieldr when an analysis starts in R and continues in Garphield or Python.

import garphield as gph
project = gph.Project.load("project.gph")
project.save("copy.gph")

Loading validates against the schema bundled with the package. Saving produces deterministic, readable JSON, so project files diff cleanly in version control.

Use dictionaries when the project is already in memory:

project = gph.Project.from_dict(payload)
payload = project.to_dict()

Project is immutable at its public boundary. Display a project to edit its view:

view = gph.show(project)
edited = view.to_project()
edited.save("project.gph")

Write an interactive HTML shell when the project needs to open outside the notebook:

project.save_html("graph.html", chrome=["minimap"])

The HTML loads Garphield’s remote /embed renderer in an iframe. It needs network access and a host/browser context that permits framing; it is not an offline bundle.

Installing the Python package also installs the garphield command. CSV input requires the tables extra:

Terminal window
pip install "garphield[tables]"
garphield build edges.csv --source source --target target \
--node-size algorithm:degree --layout force -o network.gph
garphield validate network.gph --json
garphield sources network.gph
garphield share network.gph

build, validate, sources, and share accept a CSV edge list or an existing .gph/.json project. CSV columns default to source and target; use --directed for directed edges. Binding flags accept a field name or algorithm:<id>. Use sources to discover available IDs.

Add --dry-run to build to validate and report the encoded size without writing the output file. Add --json to a subcommand for machine-readable success output on stdout and operation errors on stderr. Failed operations exit nonzero. share creates a URL locally; it does not upload the project. When the graph is too large for a URL, share the .gph file instead.

The render subcommand is a placeholder and exits with an error. Use the browser workbench to export PNGs, or Project.widget()/Project.save_html() for an interactive view.

Project.from_networkx() and Project.from_pandas() take visual bindings directly, so you can author a styled project in a code sandbox with no mounted view:

import garphield as gph
project = gph.Project.from_networkx(
graph,
node_color="kind", # an existing attribute
node_size=gph.algorithm("degree"), # a computed source
node_label="name",
layout="force",
)

The channel keywords are snake_case (node_color, node_size, node_label, edge_color, edge_width) and map to the camelCase wire channels. From NetworkX a channel also accepts a mapping, a callable, or a partition (a list of node sets); from pandas, bind a column name, an algorithm(...) spec, pos, or layout, and add a column for anything per-row.

Discover the bindable ids and their types before you bind, still headless:

for source in project.sources():
print(source.id, source.kind, source.target, source.result_type)

Bindings are validated when the project is built: an unknown channel, a missing field, an unknown algorithm, or a result type the channel does not accept raises BindingError in Python instead of leaving a dead binding that renders nothing. See the Binding grammar for the full vocabulary.

share_string = gph.share_string(project)
url = gph.share_url(project)
custom = gph.share_url(project, base="https://example.com/garphield")

These pure functions perform no network I/O. They compact repeated node IDs in link endpoints, serialize canonical JSON, and encode zlib plus unpadded base64url in #p=z2.…. Opening the URL preserves a complete saved embedding; if positions are absent, the live workbench runs Garphield’s normal selected layout. The browser still reads existing z1. carriers. ProjectShareTooLargeError is raised when the encoded carrier exceeds 262,144 characters. Share larger projects as .gph files.

project.semantic_fingerprint()
project.project_fingerprint()

The semantic fingerprint covers graph data. The project fingerprint covers the whole document, including the view. Compare them to tell “same graph, different visual work” from “same project”.

before = gph.Project.load("before.gph")
after = gph.Project.load("after.gph")
same_graph = before.semantic_fingerprint() == after.semantic_fingerprint()
same_project = before.project_fingerprint() == after.project_fingerprint()

Both use RFC 8785 canonical bytes; formatting in the saved JSON does not affect the result. See Canonical bytes for the exported functions.