Synthesis
Abstract
This tutorial guides you through an example material synthesis workflow using the CRIPT Python SDK.
Installation¶
Before you start, be sure the cript python package is installed.
Connect to CRIPT¶
To connect to CRIPT, you must enter a host
and an API Token
. For most users, host
will be https://api.criptapp.org/
.
Keep API Token Secure
To ensure security, avoid storing sensitive information like tokens directly in your code. Instead, use environment variables. Storing tokens in code shared on platforms like GitHub can lead to security incidents. Anyone that possesses your token can impersonate you on the CRIPT platform. Consider alternative methods for loading tokens with the CRIPT API Client. In case your token is exposed be sure to immediately generate a new token to revoke the access of the old one and keep the new token safe.
import cript
with cript.API(host="https://api.criptapp.org/", api_token="123456", storage_token="987654") as api:
pass
Note
You may notice, that we are not executing any code inside the context manager block. If you were to write a python script, compared to a jupyter notebook, you would add all the following code inside that block. Here in a jupyter notebook, we need to connect manually. We just have to remember to disconnect at the end.
api = cript.API(host="https://api.criptapp.org/", api_token=None, storage_token="123456")
api = api.connect()
Create a Project¶
All data uploaded to CRIPT must be associated with a project node. Project can be thought of as an overarching research goal. For example, finding a replacement for an existing material from a sustainable feedstock.
Create a Collection node¶
For this project, you can create multiple collections, which represent a set of experiments. For example, you can create a collection for a specific manuscript, or you can create a collection for initial screening of candidates and one for later refinements etc.
So, let's create a collection node and add it to the project.
collection = cript.Collection(name="Initial screening")
# We add this collection to the project as a list.
project.collection += [collection]
Viewing CRIPT JSON
Note, that if you are interested into the inner workings of CRIPT, you can obtain a JSON representation of your data graph at any time to see what is being sent to the API.
Create an Experiment node¶
The collection node holds a series of Experiment nodes nodes.
And we can add this experiment to the collection of the project.
experiment = cript.Experiment(name="Anionic Polymerization of Styrene with SecBuLi")
collection.experiment += [experiment]
Create an Inventory¶
An Inventory contains materials, that are well known and usually not of polymeric nature. They are for example the chemical you buy commercially and use as input into your synthesis.
For this we create this inventory by adding the Material we need one by one.
These materials are simple, notice how we use the SMILES notation here as an identifier for the material. Similarly, we can create more initial materials.
toluene = cript.Material(name="toluene", smiles="Cc1ccccc1", pubchem_cid = 1140)
styrene = cript.Material(name="styrene", smiles = "c1ccccc1C=C", inchi = "InChI=1S/C8H8/c1-2-8-6-4-3-5-7-8/h2-7H,1H2")
butanol = cript.Material(name="1-butanol", smiles = "OCCCC", inchi_key = "InChIKey=LRHPLDYGYMQRHN-UHFFFAOYSA-N")
methanol = cript.Material(name="methanol", smiles = "CO", names = ["Butan-1-ol", "Butyric alcohol", "Methylolpropane", "n-Butan-1-ol", "methanol"])
Now that we defined those materials, we can combine them into an inventory for easy access and sharing between experiments/projects.
inventory = cript.Inventory(
name="Common chemicals for poly-styrene synthesis",
material=[solution, toluene, styrene, butanol, methanol],
)
collection.inventory += [inventory]
Create a Process node¶
A Process is a step in an experiment. You decide how many Process are required for your experiment, so you can list details for your experiment as fine-grained as desired. Here we use just one step to describe the entire synthesis.
process = cript.Process(
name="Anionic of Synthesis Poly-Styrene",
type="multistep",
description="In an argon filled glove box, a round bottom flask was filled with 216 ml of dried toluene. The "
"solution of secBuLi (3 ml, 3.9 mmol) was added next, followed by styrene (22.3 g, 176 mmol) to "
"initiate the polymerization. The reaction mixture immediately turned orange. After 30 min, "
"the reaction was quenched with the addition of 3 ml of methanol. The polymer was isolated by "
"precipitation in methanol 3 times and dried under vacuum.",
)
experiment.process += [process]
Add Ingredients to a Process¶
From a chemistry standpoint, most experimental processes, regardless of whether they are carried out in the lab or simulated using computer code, consist of input ingredients that are transformed in some way. Let's add ingredients to the Process that we just created. For this we use the materials from the inventory. Next, define Quantities nodes indicating the amount of each Ingredient that we will use in the Process.
initiator_qty = cript.Quantity(key="volume", value=1.7e-8, unit="m**3")
solvent_qty = cript.Quantity(key="volume", value=1e-4, unit="m**3")
monomer_qty = cript.Quantity(key="mass", value=0.455e-3, unit="kg")
quench_qty = cript.Quantity(key="volume", value=5e-3, unit="m**3")
workup_qty = cript.Quantity(key="volume", value=0.1, unit="m**3")
Now we can create an Ingredient node for each ingredient using the Material and quantities attributes.
initiator = cript.Ingredient(
keyword=["initiator"], material=solution, quantity=[initiator_qty]
)
solvent = cript.Ingredient(
keyword=["solvent"], material=toluene, quantity=[solvent_qty]
)
monomer = cript.Ingredient(
keyword=["monomer"], material=styrene, quantity=[monomer_qty]
)
quench = cript.Ingredient(
keyword=["quench"], material=butanol, quantity=[quench_qty]
)
workup = cript.Ingredient(
keyword=["workup"], material=methanol, quantity=[workup_qty]
)
Finally, we can add the Ingredient
nodes to the Process
node.
Add Conditions to the Process¶
Its possible that our Process
was carried out under specific physical conditions. We can codify this by adding
Condition nodes to the process.
temp = cript.Condition(key="temperature", type="value", value=25, unit="celsius")
time = cript.Condition(key="time_duration", type="value", value=60, unit="min")
process.condition = [temp, time]
Add a Property to a Process¶
We may also want to associate our process with certain properties. We can do this by adding Property nodes to the process.
yield_mass = cript.Property(key="yield_mass", type="number", value=47e-5, unit="kilogram", method="scale")
process.property += [yield_mass]
Create a Material node (process product)¶
Along with input Ingredients, our Process may also produce product materials.
First, let's create the Material
that will serve as our product. We give the material a name
attribute and add it to our
[Project]((../../nodes/primary_nodes/project).
polystyrene = cript.Material(name="polystyrene", bigsmiles="[H]{[>][<]C(C[>])c1ccccc1[<]}C(C)CC")
project.material += [polystyrene]
Let's add some Identifiers
to the material to make it easier to identify and search.
Next, we'll add some Property nodes to the Material , which represent its physical or virtual (in the case of a simulated material) properties.
# create a phase property
phase = cript.Property(key="phase", value="solid", type="none", unit=None)
# create a color property
color = cript.Property(key="color", value="white", type="none", unit=None)
# add the properties to the material
polystyrene.property += [phase, color]
Congratulations! You've just created a process that represents the polymerization reaction of Polystyrene, starting with a set of input ingredients in various quantities, and ending with a new polymer with specific identifiers and physical properties.
Now we can save the project to CRIPT via the api object.