WolframChemistry  Paclets

(RowDefault[, (Spacer1), , (Spacer1), ])  #WolframTechConf

The Outline Slide

A Brief Overview of Wolfram Language Chemistry

Introduction to the Wolfram Language Paclet Repository

WolframChemistry paclets

MoleculeFingerprints

IsomerGeneration

Selfies

ForceFields

Credits, etc

A Brief Overview of Wolfram Language Chemistry

TimelinePlot[<|"Version 6.0: ChemicalData"->(DateObject["May 2007", DateObject[{2007,5},"Month","Gregorian",-5.`]]),"Vers. 10.0: Chemical Entities"->(DateObject["Jul 2014", DateObject[{2014,7},"Month","Gregorian",-5.`]]),"PubChem Service Connection"->(DateObject["Mar 2016", DateObject[{2016,3},"Month"]]),"Vers. 12.0: Molecule, MoleculePattern & MoleculePlot3D"->(DateObject["Apr 2019", DateObject[{2019,4},"Month"]]),"Vers. 12.1: MoleculeRecognize"->(DateObject["Mar 2020", DateObject[{2020,3},"Month"]]),"Vers. 12.2: MoleculeDraw"->(DateObject["Dec 2020", DateObject[{2020,12},"Month"]]),"Vers. 12.3: MoleculeAlign & MoleculeName"->(DateObject["May 2021", DateObject[{2021,5},"Month"]]),"Vers. 13.0: ChemicalFormula & ChemicalReaction"->(DateObject["Dec 2021", DateObject[{2021,12},"Month"]]),"Vers. 13.1: ApplyReaction & ChemicalConvert"->(DateObject["Jun 2022", DateObject[{2022,6},"Month"]])|>,PlotLayout->"Stacked",ImageSize->Full]

ChemicalData, ElementData, IsotopeData

provide access to curated data in a compiled form

?IsotopeData

Entity and EntityValue extend this to a host of domains

WordCloud[EntityValue[],WordOrientation->"HorizontalVertical"]

Properties are precomputed and stored in a database, retrieved when you ask for them

EntityProperties["Chemical"]

A Brief Overview of Wolfram Language Chemistry - 2

Starting in Version 12.0 we have new data structures to represent arbitrary chemical objects

Atom - represents a single atom in a molecule, can have a specified charge or mass number

Bond - a bond between atoms in a molecule

Molecule - an arbitrary chemical structure composed of atoms and bonds, with or without specified coordinates or stereochemistry

MoleculePattern - a pattern for a molecule substructure, can be written as SMARTS or using Atom and Bond primitives

BioSequence - a representation of a bio molecular sequence (“DNA”, “RNA”, “Peptide”, etc)

ChemicalReaction - represents a single elementary reaction

PatternReaction - a template reaction composed of molecule patterns

ChemicalFormula - sometimes all you have is the formula, without structural information

ChemicalInstance - an instance of a chemical - “5 grams HCl”, “2 moles of nitrogen at 77K”

BioSequence["Peptide","T"]

Molecule@%

ToEntity@%

ChemicalFormula@%

MoleculeMatchQ[BioSequence[],(RowDefault[(Subscript["C", 4]), (Subscript["H", 9]), "N", (Subscript["O", 3])])]

Introduction to the Wolfram Language Paclet Repository

The paclet repository is a new, long-requested feature

Internal and External submissions

Fast turnaround for bug fixes

Easy notebook interface for submitting paclets

We are using the publisher ID "WolframChemistry":

Fast prototyping - these can be put together and published on a fast timeframe

Niche functionality - possibly not for a wider audience

Wrapper packages around external frameworks - there are many packages in chem- and bioinformatics that are only available in python. Re-implementing them in WL can be time consuming, an alternative is to use ExternalEvaluate

Adding a documented interface to some functionality that is only available in WL “super functions” - like FeatureExtract, MoleculeModify, MoleculeValue, etc

MoleculeFingerprints

Molecule fingerprints are a numeric representation of the features in a molecule.

By encoding a molecule to a sequence of bits, fingerprints allow fast meaningful similarity comparisons.

This paclet provides a interface to the molecular featurization functions used by FeatureExtract, allowing full customization.

Needs["WolframChemistry`MoleculeFingerprints`"]

?WolframChemistry`MoleculeFingerprints`*

MoleculeFingerprints - Substructure Keys

How do we determine how ‘similar’ two molecules are?

MoleculePlot@{m1=Molecule[],m2=Molecule[]}

The MoleculeFingerprints paclet comes with two sets of predefined molecule patterns

patts=Get[PacletObject["WolframChemistry/MoleculeFingerprints"]["AssetLocation","FP3 Substructure Keys"]]

We can look at which patterns are common to both molecules:

MoleculePlot[#,patts]&/@{m1,m2}//Row

We can find the number of times each substructure occurs in each molecule:

SubstructureKeyFingerprint[patts,"CountVector"]@m1

SubstructureKeyFingerprint[patts,"CountVector"]@m2

N@ResourceFunction["MultisetJaccardDissimilarity"][%,%%]

MoleculeDistance[m1,m2,"FingerprintType"->SubstructureKeyFingerprint[patts,"CountVector"]]

MoleculeFingerprints - Hash-based fingerprints

Hash-based fingerprints do not have a predefined set of substructures - substructures are generated algorithmically from each molecule.

These substructures, along with certain atom and bond properties, are used to create a “hash” - often a 64-bit integer

Properties commonly used include vertex degree, bond conjugation, π-electron counts, and more

Each substructure is then hashed to a 64-bit integer, resulting in a very sparse vector

Each molecule will set a small number of bits, tens to hundreds, out of a total of (2^64)-1 possible bits

If desired, this sparse vector is “folded down” to a more modestly sized bit vector

This results in a smaller fingerprint, with faster similarity comparisons

Can result in “bit collisions” where two different substructures end up setting the same bit

Molecule similarity can change greatly depending on the fingerprint type used:

Grid@Table[MoleculeDistance[m1,m2,"FingerprintType"->fpt,DistanceFunction->df],{fpt,{AtomPairFingerprint,TopologicalFingerprint,ExtendedConnectivityFingerprint,LayeredFingerprint,PatternFingerprint}},{df,{JaccardDissimilarity,DiceDissimilarity,SokalSneathDissimilarity}}]

Atom Pairs

Atom pairs are molecular substructures defined by two atoms and the number of bonds along the shortest path between them.

MoleculePlot[Molecule@"2,3,4,5-tetrahydroxyhexanedioic acid",{MoleculePattern[{Atom["O","PiElectronCount"->0,"HeavyAtomCoordinationNumber"->1],_,_,_,_,_,_,Atom["O","PiElectronCount"->0,"HeavyAtomCoordinationNumber"->1]},{Bond[{1,2}],Bond[{2,3}],Bond[{3,4}],Bond[{4,5}],Bond[{5,6}],Bond[{6,7}],Bond[{7,8}]}],MoleculePattern[{Atom["O","PiElectronCount"->1,"HeavyAtomCoordinationNumber"->1],_,_,_,Atom["O","PiElectronCount"->0,"HeavyAtomCoordinationNumber"->1]},{Bond[{1,2}],Bond[{2,3}],Bond[{3,4}],Bond[{4,5}]}]},
PlotLegends->Placed[SwatchLegend[{Text["OX1\[Hyphen](7)\[Hyphen]OX1"],Text["O·X1\[Hyphen](4)\[Hyphen]OX1"]},LegendMarkers->"Bubble",LegendLabel->Text["Atom pairs"]],Scaled[{.95,.1}]]]

AtomPairFingerprint[Molecule[]]

ExtendedConnectivityFingerprint

Extended connectivity fingerprints are also known as "Circular fingerprints" or "Morgan fingerprints" and are generated using a variation on the "Morgan algorithm", described in (ExternalIdentifierURL[ExternalIdentifier["DOI","10.1021/c160017a018"], "DOI", "10.1021/c160017a018", https://doi.org/10.1021/c160017a018]).  Atom environments are generated by starting with a given atom and finding all atoms within a given radius:

FeatureSpacePlot[
Import[PacletObject["WolframChemistry/MoleculeFingerprints"]["AssetLocation","SMILES strings for 300 antibiotic molecules"]],
FeatureExtractor->ExtendedConnectivityFingerprint[],
LabelingFunction->(Placed[Dynamic[MoleculePlot[#1]],Tooltip]&)
]

IsomerGeneration

(RowDefault[, ({{PacletInstall["WolframChemistry/IsomerGeneration"]}, {Needs["WolframChemistry`IsomerGeneration`"]}})])

Starting from a chemical formula, generate all possible molecular structures with correct valence.

Quickly create millions of isomers or more and read them in as "SMILES" strings or Molecule objects using a stream-like interface.

Customize the structure generation by filtering out predefined substructure patterns, e.g. triple bonds in small rings or molecules with bridging double bonds, or define new valence rules for atoms outside the common organic set.

This package uses the external application surge, based on the canonical generation path method.

Elements supported include carbon, boron, nitrogen, phosphorus, oxygen, sulfur, hydrogen, chlorine, fluorine, bromine, and iodine at their lowest valences.  Other elements can be included by providing their valence.

Ions (charged molecules) and zwitterions (neutral molecules with positive and negative parts) are not supported.

Stereoisomers are not generated.

For many chemical formulas it is possible to generate billions of isomers, with memory footprints of many gigabytes.  The isomers are stored as text files filled with "SMILES" strings, located easily in your $WolframDocumentsDirectory.

IsomerGeneration - 2

Needs["WolframChemistry`IsomerGeneration`"]

List and plot all the isomers of dichlorobutane:

ListIsomers["C4H8Cl2"]

MoleculePlot/@%

?FindIsomers

FindIsomers will call PubChem for a list of compounds with the same formula in their database:

Length@FindIsomers[(Entity["2-ethyl-4-(2,2,3-trimethyl-3-cyclopenten-1-yl)-2-buten-1-ol", Entity["Chemical","2Ethyl4,2,2,3Trimethyl3Cyclopenten1Yl2Buten1Ol"], "Entity[\"Chemical\", \"2Ethyl4,2,2,3Trimethyl3Cyclopenten1Yl2Buten1Ol\"]", "chemical"])]

This is just a drop in the bucket compared to the seventy-five million possible isomers:

CountIsomers[(Entity["2-ethyl-4-(2,2,3-trimethyl-3-cyclopenten-1-yl)-2-buten-1-ol", Entity["Chemical","2Ethyl4,2,2,3Trimethyl3Cyclopenten1Yl2Buten1Ol"], "Entity[\"Chemical\", \"2Ethyl4,2,2,3Trimethyl3Cyclopenten1Yl2Buten1Ol\"]", "chemical"])]//AbsoluteTiming

Filtering out unphysical substructures and you still have fifty-six million isomers:

CountIsomers[(Entity["2-ethyl-4-(2,2,3-trimethyl-3-cyclopenten-1-yl)-2-buten-1-ol", Entity["Chemical","2Ethyl4,2,2,3Trimethyl3Cyclopenten1Yl2Buten1Ol"], "Entity[\"Chemical\", \"2Ethyl4,2,2,3Trimethyl3Cyclopenten1Yl2Buten1Ol\"]", "chemical"]),"ForbiddenSubstructures"->All]

iso=GenerateIsomers[(Entity["2-ethyl-4-(2,2,3-trimethyl-3-cyclopenten-1-yl)-2-buten-1-ol", Entity["Chemical","2Ethyl4,2,2,3Trimethyl3Cyclopenten1Yl2Buten1Ol"], "Entity[\"Chemical\", \"2Ethyl4,2,2,3Trimethyl3Cyclopenten1Yl2Buten1Ol\"]", "chemical"]),"ForbiddenSubstructures"->All]

iso

MoleculePlot/@iso[[;;200;;50]]

Other formulas will create many more isomers:

CountIsomers["C9H14N2O2"]

Be aware if you generate those isomers they will likely take 40 to 60 GB of disk space

Selfies

(RowDefault[, ({{PacletInstall["WolframChemistry/Selfies"]}, {Needs["WolframChemistry`Selfies`"]}})])

Take a given SELFIES string and rearrange the components and you are left with a valid SELFIES string, with no exception.

This is in contrast to the SMILES representation, where an unmatched parenthesis or ring closure can lead to a syntactically invalid string.

The aim of SELFIES is to provide a framework for generative machine learning models, to create entirely new molecules from mixing and matching components from existing molecules.

Based on Self-Referencing Embedded Strings (SELFIES): A 100% robust molecular string representation
Mario Krenn, Florian Haese, AkshatKumar Nigam, Pascal Friederich, Alan Aspuru-Guzik

The Selfies paclet requires a working python installation, version 3.7 or greater, with the pyzmq package installed.  See Configure Python for ExternalEvaluate for more instructions.  The selfies python package will be installed via the pip package installer, and is used for converting between SMILES and SELFIES strings.

Selfies - 2

We can start with a SMILES string and create a molecule from it:

smi="O[C@H]1C[C@H]([N+]2C=CC(N)=C(C)C2=O)O[C@@H]1COP(=O)(O)O";
MoleculePlot[m=Molecule[smi]]

Each atom in the molecule is represented by a SMILES token

smilesTokens=MoleculeValue[m,"AtomSMILES",IncludeHydrogens->False]

But simply shuffling these tokens will always lead to either an invalid SMILES string or just a straight chain without branching or cycles:

Table[MoleculePlot@StringJoin@RandomSample[smilesTokens],5]

Instead we can conver the SMILES into a SELFIES string:

selfies=ToSelfies[smi]

Now the branches and rings are individual tokens rather than pairs of tokens that have to appear in the proper order

selfiesTokens=SplitSelfies[selfies]

Table[MoleculePlot@FromSelfies@StringJoin@RandomSample[selfiesTokens],10]

We can easily create thousands of random permutations of these tokens

newMols=FromSelfies[Table[StringJoin@RandomSample[selfiesTokens],10000],Molecule];

Now find the three newly generated molecules which are ‘closest’ to the original molecule

TakeSmallestBy[newMols,MoleculeDistance[m,#]&,3]

MoleculePlot/@%

These molecules do not appear among the one hundred million compounds in PubChem:

MoleculeValue[%%,"PubChemCompoundID"]

ForceFields

This paclet provides implementations of the "MMFF94", "MMFF94s", and "UFF" force fields via the RDKit library, and the "GAFF" and "Ghemical" force fields via the external application OpenBabel.

Functions for minimizing energy with respect to a given force field, adding distance, angle, or torsion constraints

Under active development, expect release shortly

The Last Slide

The Wolfram Chemistry Team

ImageCollage[RandomSample@{,,,,,,,},Background->None]

What's New in Chemical Education

What's New for Physics Education: Formulas and Quantities

Office Hour: Wolfram Language Chemistry