Simulation example workflow¶
Refer to Quickstart for installation instructions.
Connect to the public API¶
Note
Your API token can be found in the UI under Account Settings.
Create a Project node¶
Note
Project names are globally unique.
Create a Collection node¶
Create an Experiment node¶
Get the relevant Software nodes¶
python = cript.Software.get(
name = "python",
version = "3.9"
)
rdkit = cript.Software.get(
name = "rdkit",
version = "2020.9"
)
stage = cript.Software.get(
name = "stage",
source = "https://doi.org/10.1021/jp505332p"
)
packmol = cript.Software.get(
name = "Packmol",
source = "http://m3g.iqm.unicamp.br/packmol",
version = "N/A"
)
openmm = cript.Software.get(
name = "openmm",
version = "7.5"
)
Create Software Configurations¶
python_config = cript.SoftwareConfiguration(software=python)
rdkit_config = cript.SoftwareConfiguration(software=rdkit)
stage_config = cript.SoftwareConfiguration(software=stage)
openmm_config = cript.SoftwareConfiguration(
software = openmm,
algorithms = [
cript.Algorithm(key="+energy_minimization", type="initialization")
]
)
packmol_config = cript.SoftwareConfiguration(
software = packmol,
algorithms = [
cript.Algorithm(
key="+molecule_packing",
type="initialization",
parameters = [
cript.Parameter(key="+maxit", value=50),
cript.Parameter(key="+nloop", value=10),
cript.Parameter(key="+tolerance", value=4.0, unit="angstrom"),
]
)
]
)
Create Computations¶
init = cript.Computation.create(
experiment = expt,
name = "Initial snapshot and force-field generation",
type = "initialization",
software_configurations = [
python_config,
rdkit_config,
stage_config,
packmol_config,
openmm_config,
]
)
equi = cript.Computation.create(
experiment = expt,
name = "Equilibrate data prior to measurement",
type = "MD",
software_configurations = [python_config, openmm_config],
conditions = [
cript.Condition(key="time_duration", value=100.0, unit="ns"),
cript.Condition(key="temperature", value=450.0, unit="K"),
cript.Condition(key="pressure", value=1.0, unit="bar"),
cript.Condition(key="number", value=31),
],
prerequisite_computation = init,
)
bulk = cript.Computation.create(
experiment = expt,
name = "Bulk simulation for measurement",
type = "MD",
software_configurations = [python_config, openmm_config],
conditions = [
cript.Condition(key="time_duration", value=50.0, unit="ns"),
cript.Condition(key="temperature", value=450.0, unit="K"),
cript.Condition(key="pressure", value=1.0, unit="bar"),
cript.Condition(key="number", value=31),
],
prerequisite_computation = equi,
)
ana = cript.Computation.create(
experiment = expt,
name = "Density analysis",
type = "analysis",
software_configurations = [python_config],
prerequisite_computation = bulk,
)
Note
Notice the use of create()
here, which instantiates and saves the object in one go.
Create and Upload Files¶
First, we'll instantiate our File nodes.
packing_file = cript.File(project=proj, source="path/to/local/file")
forcefield_file = cript.File(project=proj, source="path/to/local/file")
snap_file = cript.File(project=proj, source="path/to/local/file")
final_file = cript.File(project=proj, source="path/to/local/file")
Note
The source
field should point to any file on your local filesystem.
Info
Depending on the file size, there could be a delay while the checksum is generated.
Next, we'll upload the local files by saving the File nodes. Follow all prompts that appear.
Create Data¶
First, we'll create a few Data nodes.
packing_data = cript.Data.create(
experiment = expt,
name = "Loosely packed chains",
type = "computation_config",
files = [packing_file],
computations = [init],
notes = "PDB file without topology describing an initial system.",
)
forcefield_data = cript.Data.create(
experiment = expt,
name = "OpenMM forcefield",
type = "computation_forcefield",
files = [forcefield_file],
computations = [init],
notes = "Full forcefield definition and topology.",
)
equi_snap = cript.Data.create(
experiment = expt,
name = "Equilibrated simulation snapshot",
type = "computation_config",
files = [snap_file],
computations = [equi],
)
final_data = cript.Data.create(
experiment = expt,
name = "Logged volume during simulation",
type = "+raw_data",
files = [final_file],
computations = [bulk],
)
Next, we'll add these to the appropriate Computation nodes.
init.update(output_data=[packing_data, forcefield_data])
equi.update(
input_data=[packing_data, forcefield_data],
output_data=[equi_snap]
)
ana.update(input_data=[final_data])
bulk.update(output_data=[final_data])
Note
Notice the use of update()
here, which updates and saves the object in one go.
Create a virtual Material¶
First, we'll instantiate our Material node:
Next, we'll add some Identifiers nodes:
names = cript.Identifier(
key="names",
value=["poly(styrene)", "poly(vinylbenzene)"]
)
bigsmiles = cript.Identifier(
key="bigsmiles",
value="[H]{[>][<]C(C[>])c1ccccc1[<]}C(C)CC"
)
chem_repeat = cript.Identifier(key="chem_repeat", value="C8H8")
polystyrene.add_identifier(names)
polystyrene.add_identifier(chem_repeat)
polystyrene.add_identifier(bigsmiles)
... and Property nodes:
phase = cript.Property(key="phase", value="solid")
color = cript.Property(key="color", value="white")
polystyrene.add_property(phase)
polystyrene.add_property(color)
Last, we'll create a ComputationalForcefield node and add it to the Material:
forcefield = cript.ComputationalForcefield(
key = "opls_aa",
building_block = "atom",
source = "Custom determination via STAGE",
data = forcefield_data
)
polystyrene.computational_forcefield = forcefield
polystyrene.save()
Conclusion¶
You made it! We hope this tutorial has been helpful.
Please let us know how you think it could be improved.