vibesketch.document¶
The vibe-sketch document: model, file I/O and JSON schema.
>>> from vibesketch.document import load, save
>>> document = load("scheme.vsk")
>>> document.species[0].charge
0
>>> save(document, "copy.vsk")
- class vibesketch.document.Canvas(*, format, data=<factory>)¶
Bases:
_StrictThe drawing as the canvas engine stores it, embedded verbatim.
- format: Literal['ket']¶
- model_config = {'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class vibesketch.document.Conformer(*, method, symbols, xyz_angstrom, source=None)¶
Bases:
_StrictOne 3D structure of a species: element symbols and Cartesian coordinates.
- Parameters:
- method: _Token¶
- electron_count(charge)¶
Electrons in the neutral atoms, less the charge.
- model_config = {'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class vibesketch.document.Constraint(*, kind, atoms, value=None)¶
Bases:
_StrictA coordinate an optimisation holds fixed.
Atoms are 0-based indices into the species’ conformer: the drawing’s atoms first, then the hydrogens.
- Parameters:
- kind: Literal['distance', 'angle', 'dihedral', 'position']¶
- model_config = {'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class vibesketch.document.Document(*, schema='vibe-sketch/1', revision=0, canvas=<factory>, species=<factory>, reactions=<factory>, jobs=<factory>, recipes=<factory>, highlights=<factory>, generics=<factory>, rgroups=<factory>, surfaces=<factory>, style=<factory>, provenance)¶
Bases:
_StrictA vibe-sketch document, schema version 1.
- Parameters:
- model_config = {'extra': 'forbid', 'json_schema_extra': {'description': 'A .vsk file: a drawing and what to compute from it.'}, 'populate_by_name': True, 'title': 'vibe-sketch document', 'validate_assignment': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- schema_id: Literal['vibe-sketch/1']¶
- provenance: Provenance¶
- species_by_id(identifier)¶
The species with
identifier; raisesKeyErrorwhen there is none.
- job_by_id(identifier)¶
The job with
identifier; raisesKeyErrorwhen there is none.
- exception vibesketch.document.DocumentError(errors)¶
Bases:
ValueErrorA document that is not valid JSON or not a valid vibe-sketch document.
errorslists every problem as"location: message", the form the CLI prints and the REST API returns.
- exception vibesketch.document.SaveRefused¶
Bases:
ValueErrorWriting would discard QVF result data or replace a changed target.
- class vibesketch.document.Edit(*, revision, at, actor, client=None, summary)¶
Bases:
_StrictOne revision of the document: who changed it, through what, and why.
- Parameters:
revision (int)
at (AwareDatetime)
actor (Literal['human', 'agent', 'system'])
client (Annotated[str, StringConstraints(strip_whitespace=None, to_upper=None, to_lower=None, strict=None, min_length=None, max_length=None, pattern=^[a-z0-9][a-z0-9_.:+-]{0,63}$, ascii_only=None)] | None)
summary (Annotated[str, StringConstraints(strip_whitespace=None, to_upper=None, to_lower=None, strict=None, min_length=1, max_length=500, pattern=None, ascii_only=None)])
- at: AwareDatetime¶
- actor: Literal['human', 'agent', 'system']¶
- summary: _Text¶
- model_config = {'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class vibesketch.document.Job(*, id, species, program, spec, runs=None)¶
Bases:
_StrictA calculation to run on one species with one program.
- Parameters:
id (Annotated[str, StringConstraints(strip_whitespace=None, to_upper=None, to_lower=None, strict=None, min_length=None, max_length=None, pattern=^[A-Za-z][A-Za-z0-9_-]{0,63}$, ascii_only=None)])
species (Annotated[str, StringConstraints(strip_whitespace=None, to_upper=None, to_lower=None, strict=None, min_length=None, max_length=None, pattern=^[A-Za-z][A-Za-z0-9_-]{0,63}$, ascii_only=None)])
program (Annotated[str, StringConstraints(strip_whitespace=None, to_upper=None, to_lower=None, strict=None, min_length=None, max_length=None, pattern=^[a-z0-9][a-z0-9_.:+-]{0,63}$, ascii_only=None)])
spec (JobSpec)
- id: _Identifier¶
- species: _Identifier¶
- program: _Token¶
- model_config = {'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class vibesketch.document.JobSpec(*, task, method=None, basis=None, aux_basis=None, approximation=None, dispersion=None, solvent=None, states=None, constraints=None, resources=None)¶
Bases:
_StrictA program-neutral description of a calculation.
Writers translate it into one program’s input and refuse, with a reason, whatever they cannot express (AGENTS.md, ground rule 5). The model only checks that the specification is consistent in itself.
- Parameters:
task (Literal['geometry', 'sp', 'opt', 'freq', 'opt+freq', 'tddft', 'nmr'])
method (Annotated[str, StringConstraints(strip_whitespace=None, to_upper=None, to_lower=None, strict=None, min_length=None, max_length=None, pattern=^[A-Za-z0-9][A-Za-z0-9()+*/,_.-]{0,63}$, ascii_only=None)] | None)
basis (Annotated[str, StringConstraints(strip_whitespace=None, to_upper=None, to_lower=None, strict=None, min_length=None, max_length=None, pattern=^[A-Za-z0-9][A-Za-z0-9()+*/_.-]{0,63}$, ascii_only=None)] | None)
aux_basis (Annotated[str, StringConstraints(strip_whitespace=None, to_upper=None, to_lower=None, strict=None, min_length=None, max_length=None, pattern=^[A-Za-z0-9][A-Za-z0-9()+*/_.-]{0,63}$, ascii_only=None)] | None)
approximation (Annotated[str, StringConstraints(strip_whitespace=None, to_upper=None, to_lower=None, strict=None, min_length=None, max_length=None, pattern=^[A-Za-z0-9][A-Za-z0-9()_-]{0,31}$, ascii_only=None)] | None)
dispersion (Annotated[str, StringConstraints(strip_whitespace=None, to_upper=None, to_lower=None, strict=None, min_length=None, max_length=None, pattern=^[A-Za-z0-9][A-Za-z0-9()_-]{0,31}$, ascii_only=None)] | None)
solvent (Solvent | None)
states (int | None)
constraints (list[Constraint] | None)
resources (Resources | None)
- constraints: list[Constraint] | None¶
- static calculation_fields()¶
The fields that only mean something for a calculation.
- model_config = {'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class vibesketch.document.Name(*, value, source, confidence)¶
Bases:
_StrictA name for a species, with where it came from and how sure it is.
- Parameters:
value (Annotated[str, StringConstraints(strip_whitespace=None, to_upper=None, to_lower=None, strict=None, min_length=1, max_length=500, pattern=None, ascii_only=None)])
source (Annotated[str, StringConstraints(strip_whitespace=None, to_upper=None, to_lower=None, strict=None, min_length=None, max_length=None, pattern=^[a-z0-9][a-z0-9_.:+-]{0,63}$, ascii_only=None)])
confidence (Literal['high', 'medium', 'low'])
- value: _Text¶
- source: _Token¶
- confidence: Literal['high', 'medium', 'low']¶
- model_config = {'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class vibesketch.document.Provenance(*, app, created=<factory>, edits=<factory>)¶
Bases:
_StrictWhere the document came from.
- Parameters:
- app: _Text¶
- created: AwareDatetime¶
- model_config = {'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class vibesketch.document.Reaction(*, id, reactants, reagents=<factory>, products, arrow='forward', conditions=<factory>, yield_=None, amounts=<factory>, coefficients=<factory>, electrons=None, states=<factory>, quantities=<factory>)¶
Bases:
_StrictOne step of a scheme: who reacts, under which conditions, to give what.
- Parameters:
id (Annotated[str, StringConstraints(strip_whitespace=None, to_upper=None, to_lower=None, strict=None, min_length=None, max_length=None, pattern=^[A-Za-z][A-Za-z0-9_-]{0,63}$, ascii_only=None)])
reactants (list[Annotated[str, StringConstraints(strip_whitespace=None, to_upper=None, to_lower=None, strict=None, min_length=None, max_length=None, pattern=^[A-Za-z][A-Za-z0-9_-]{0,63}$, ascii_only=None)]])
reagents (list[Annotated[str, StringConstraints(strip_whitespace=None, to_upper=None, to_lower=None, strict=None, min_length=None, max_length=None, pattern=^[A-Za-z][A-Za-z0-9_-]{0,63}$, ascii_only=None)]])
products (list[Annotated[str, StringConstraints(strip_whitespace=None, to_upper=None, to_lower=None, strict=None, min_length=None, max_length=None, pattern=^[A-Za-z][A-Za-z0-9_-]{0,63}$, ascii_only=None)]])
arrow (Literal['forward', 'equilibrium', 'retrosynthetic', 'resonance'])
conditions (list[Annotated[str, StringConstraints(strip_whitespace=None, to_upper=None, to_lower=None, strict=None, min_length=1, max_length=500, pattern=None, ascii_only=None)]])
yield_ (Annotated[str, StringConstraints(strip_whitespace=None, to_upper=None, to_lower=None, strict=None, min_length=1, max_length=500, pattern=None, ascii_only=None)] | None)
amounts (list[Amount])
coefficients (list[Coefficient])
electrons (Electrons | None)
states (list[StateLabel])
- id: _Identifier¶
- coefficients: list[Coefficient]¶
- states: list[StateLabel]¶
- coefficient(species)¶
The drawn coefficient of
species, 1 when none is drawn.
- model_config = {'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class vibesketch.document.Resources(*, nprocs=1, maxcore_mb=None)¶
Bases:
_StrictWhat a job may use on the machine that runs it.
- model_config = {'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class vibesketch.document.Run(*, queue='vibe-queue', host='localhost', id, submitted, directory=None, container=None, group=None, result=None)¶
Bases:
_StrictOne submission of a job to a queue.
- Parameters:
queue (Literal['vibe-queue'])
host (Annotated[str, StringConstraints(strip_whitespace=None, to_upper=None, to_lower=None, strict=None, min_length=None, max_length=None, pattern=^[A-Za-z0-9][A-Za-z0-9_.-]{0,63}$, ascii_only=None)])
id (Annotated[str, StringConstraints(strip_whitespace=None, to_upper=None, to_lower=None, strict=None, min_length=None, max_length=None, pattern=^[A-Za-z0-9_-]{1,64}$, ascii_only=None)])
submitted (AwareDatetime)
directory (Annotated[str, StringConstraints(strip_whitespace=None, to_upper=None, to_lower=None, strict=None, min_length=1, max_length=4096, pattern=None, ascii_only=None)] | None)
container (Annotated[str, StringConstraints(strip_whitespace=None, to_upper=None, to_lower=None, strict=None, min_length=1, max_length=4096, pattern=None, ascii_only=None)] | None)
group (Annotated[str, StringConstraints(strip_whitespace=None, to_upper=None, to_lower=None, strict=None, min_length=None, max_length=None, pattern=^[A-Za-z][A-Za-z0-9_-]{0,63}$, ascii_only=None)] | None)
result (RunResult | None)
- queue: Literal['vibe-queue']¶
- submitted: AwareDatetime¶
- model_config = {'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class vibesketch.document.Solvent(*, model, name)¶
Bases:
_StrictAn implicit solvation model and the solvent it describes.
- Parameters:
- model: Literal['CPCM', 'SMD']¶
- name: _SolventName¶
- model_config = {'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class vibesketch.document.Species(*, id, label=None, smiles=None, inchikey=None, charge=0, multiplicity=1, name=None, conformers=<factory>, sequence=None, nanostructure=None, capped=None, solid=None)¶
Bases:
_StrictA molecule or ion that appears in the drawing.
- Parameters:
id (Annotated[str, StringConstraints(strip_whitespace=None, to_upper=None, to_lower=None, strict=None, min_length=None, max_length=None, pattern=^[A-Za-z][A-Za-z0-9_-]{0,63}$, ascii_only=None)])
label (Annotated[str, StringConstraints(strip_whitespace=None, to_upper=None, to_lower=None, strict=None, min_length=1, max_length=500, pattern=None, ascii_only=None)] | None)
smiles (Annotated[str, StringConstraints(strip_whitespace=None, to_upper=None, to_lower=None, strict=None, min_length=None, max_length=None, pattern=^\S+$, ascii_only=None)] | None)
inchikey (Annotated[str, StringConstraints(strip_whitespace=None, to_upper=None, to_lower=None, strict=None, min_length=None, max_length=None, pattern=^[A-Z]{14}-[A-Z]{10}-[A-Z]$, ascii_only=None)] | None)
charge (int)
multiplicity (int)
name (Name | None)
sequence (Sequence | None)
nanostructure (Nanostructure | None)
capped (Capping | None)
solid (SolidFormula | None)
- id: _Identifier¶
- nanostructure: Nanostructure | None¶
- solid: SolidFormula | None¶
- model_config = {'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class vibesketch.document.Style(*, preset='acs-1996')¶
Bases:
_StrictHow exported figures look.
- Parameters:
preset (Annotated[str, StringConstraints(strip_whitespace=None, to_upper=None, to_lower=None, strict=None, min_length=None, max_length=None, pattern=^[a-z0-9][a-z0-9_.:+-]{0,63}$, ascii_only=None)])
- preset: _Token¶
- model_config = {'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class vibesketch.document.Surface(*, id, kind='surface', material, facet=None, layers=<factory>, diameter_nm=None, ligand_shell=None, nanotube=None, count=5, anchors=<factory>)¶
Bases:
_StrictA schematic surface, not a physical atomistic or periodic model (#140).
- Parameters:
id (Annotated[str, StringConstraints(strip_whitespace=None, to_upper=None, to_lower=None, strict=None, min_length=None, max_length=None, pattern=^[A-Za-z][A-Za-z0-9_-]{0,63}$, ascii_only=None)])
kind (Literal['surface', 'electrode', 'stack', 'nanoparticle', 'nanotube-array'])
material (str)
facet (str | None)
diameter_nm (float | None)
ligand_shell (str | None)
nanotube (Annotated[str, StringConstraints(strip_whitespace=None, to_upper=None, to_lower=None, strict=None, min_length=None, max_length=None, pattern=^[A-Za-z][A-Za-z0-9_-]{0,63}$, ascii_only=None)] | None)
count (int)
anchors (dict[Annotated[str, StringConstraints(strip_whitespace=None, to_upper=None, to_lower=None, strict=None, min_length=None, max_length=None, pattern=^[A-Za-z][A-Za-z0-9_-]{0,63}$, ascii_only=None)], SurfaceAnchor])
- id: _Identifier¶
- kind: Literal['surface', 'electrode', 'stack', 'nanoparticle', 'nanotube-array']¶
- anchors: dict[_Identifier, SurfaceAnchor]¶
- model_config = {'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class vibesketch.document.SurfaceAnchor(*, u=0.5, v=0, dx=0, dy=1, site=None, repeat=1, generics=<factory>)¶
Bases:
_StrictA schematic attachment point, fractions of the image box; y runs down.
- Parameters:
u (float)
v (float)
dx (float)
dy (float)
site (Literal['top', 'bridge', 'hollow'] | None)
repeat (int)
generics (list[Annotated[str, StringConstraints(strip_whitespace=None, to_upper=None, to_lower=None, strict=None, min_length=None, max_length=None, pattern=^[A-Za-z][A-Za-z0-9_-]{0,63}$, ascii_only=None)]])
- model_config = {'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- vibesketch.document.document_json_schema()¶
The JSON schema (draft 2020-12) of a version-1 document.
- vibesketch.document.check_output(path)¶
Refuse a protected QVF destination before an operation with side effects.
write_output()checks again at the actual write; this preflight is useful before submitting jobs whose run records must be saved in place.
- vibesketch.document.dumps(document)¶
The document as
.vsktext.
- vibesketch.document.from_data(data)¶
Validate already-parsed JSON data as a document, within
vibesketch.limits.
- vibesketch.document.load(path)¶
Read and validate a document: a
.qvfarchive or a.vskfile.
- vibesketch.document.loads(text)¶
Parse and validate a document from JSON text, within
vibesketch.limits.
- vibesketch.document.new_document(app=None)¶
An empty document stamped with this application and the current time.
- vibesketch.document.save(document, path, *, expect=None)¶
Write
documenttopathatomically; returns the path written.A
.qvfpath gets a QVF archive (raisingQvfUnavailablewithout qvf-writer), any other a.vsk. A file that exists keeps its permissions; a new one gets the umask’s. QVF results and archives with data outside the native sketch raiseSaveRefused; save the sketch to another path instead. Withexpect(adigest_of()), a file that no longer holds those bytes is not replaced either.
- vibesketch.document.with_edit(document, *, actor, client, summary)¶
documentwith an edit recorded for its next revision.A run of alike edits (same actor, client and summary) folds into one entry, so a drawing session does not leave hundreds. The revision itself is the caller’s to advance: the server’s store does it on commit.
- vibesketch.document.write_output(path, content, *, expect=None)¶
Atomically write exported bytes, protecting existing QVF result files.
This also guards explicit format overrides (such as SVG sent to a QVF filename). Symlinks retain their link and write through to their target. With
expect, the file must still hold the bytes thatdigest_of()measured (or still be absent), before writing and again at the rename; otherwiseSaveRefused, and the file is left as it is.The new bytes reach the disk before they replace the old ones, and the directory entry after, so a crash or a full disk leaves either the old file or the new one, never a mixture. A crash at the wrong moment can leave a hidden
.NAME.*.tmpbeside it, which is safe to delete.
Modules
Abbreviations such as Ph, Boc and OTf: contracted and expanded on a drawn species (#90). |
|
Laboratory apparatus pictograms drawn from ordinary shapes and text (#91). |
|
Compile a saved recipe into a vibe-queue campaign, and follow it (#42). |
|
Electronic reaction reports from accepted campaign artifacts, without invented runs. |
|
Binary CDX, ChemDraw's native format, read by translating it to CDXML (#95). |
|
CDXML, ChemDraw's XML format: the whole drawing written (#95) and read (#24). |
|
Clean up the drawing: standard bond lengths and angles, everything else kept. |
|
Species from 3D structures other programs wrote: QVF sections, XYZ frames. |
|
Derive the normalized layer of a document from its canvas. |
|
Electrochemical half-reactions: electrons, states, coefficients and potentials (#141). |
|
Explicit aqueous reduction and finite-cluster binding recipes (#146). |
|
3D structures for a document's species, cached in the document. |
|
Finite, exhaustive R-group enumeration, preserving the generic drawing. |
|
Explicit, hash-pinned direct-API chain evidence, never invented campaign runs. |
|
Import and export: SMILES, MOL, SDF, RXN, CDXML, InChI, names, KET and XYZ. |
|
Generic structures in the drawing as document entries: R-group cores, their definitions and bracketed groups (#90). |
|
Checked, additive geometry returns from a viewer, without deriving a new drawing. |
|
Atoms and bonds marked in colour, on the canvas and in figures (#91). |
|
Read and write |
|
The KET bridge: between the canvas engine's JSON and RDKit molecules. |
|
The vibe-sketch document, schema version 1. |
|
Peptide modifications beyond RDKit's HELM library, from a curated table (#98). |
|
CTfile multiple groups: explicit copies, parent atoms and multiplier. |
|
Generated nanostructures as species of a document (#137). |
|
Calculated NMR shieldings and shifts of a run's result (#97). |
|
ORCA files opened as documents: outputs and Hessian files (#86). |
|
Species property tables and property text under a structure (#93). |
|
QVF, the vibyverse's file format, as vibe-sketch's document format. |
|
Offline named-reaction catalogue and editable examples or unfinished scaffolds. |
|
Saved staged workflows on a document: the publication baseline, set, show, remove. |
|
Relaxed 3D structures for a document's species, kept in the document. |
|
Same-orientation renders of a recipe campaign's stages, from its archived artifacts (#42). |
|
Explicit, provenance-bound result imports and reaction energies (#28). |
|
Evidence-bound, immutable review continuations of completed recipe calculations. |
|
R-group files: R-group cores and their definitions in one V3000 molfile (#90). |
|
The JSON schema of the document, generated from the model. |
|
Tidy scheme: a whole reaction drawing laid out the way chemists draw schemes (#20). |
|
Peptides and nucleic acids from a sequence or HELM, as ordinary structures (#98). |
|
Solids given by their formula as participants of a drawn reaction (#142). |
|
Calculated IR, Raman and UV-Vis spectra of a run's result (#87). |
|
Stereodescriptors of a document's species, and as labels in its drawing (#92). |
|
The stoichiometry table of a drawn reaction, as in a lab notebook (#99). |
|
Editable schematic surface partners and labelled grafts (#140). |
|
CSV, Markdown and booktabs tables from the validated result report (#30). |
|
Offline compounds, open-attachment fragments and the full named-reaction index. |
|
A thin-layer chromatography plate drawn from ordinary shapes and text (#91). |