Wolfram Language

Richer Knowledgebase Access

Enumerate PCB Structures and Share via an EntityStore

A polychlorinated biphenyl (PCB) is an organic compound with chemical formula given by . PCBs were formerly used for a number of industrial applications, including in electrical transformers. Here, the generation and storing of all possible polychlorinated biphenyls (PCBs) as custom entities in an entity store is illustrated.

ChemicalData already contains the PCB scaffold, diphenyl (also often called "biphenyl").

In[1]:=
Click for copyable input
Entity["Chemical", "Biphenyl"]["ColorStructureDiagram"]
Out[1]=

ChemicalData also contains a particular congener of the PCB molecule.

In[2]:=
Click for copyable input
Entity["Chemical", "PCB"][ EntityProperty["Chemical", "ColorStructureDiagram"]]
Out[2]=

The generic PCB structure involves 10 sites, indicated below with X's. To obtain all possible mono- to deca-chlorinated derivatives (i.e. congeners), attach chloro-substituents at these 10 locants in all possible ways. Here, the generic structure as "MOL" format representation is loaded from a predefined CloudObject.

In[3]:=
Click for copyable input
molString = CloudGet[CloudObject[ "https://www.wolframcloud.com/objects/user-722de5bb-ef39-4cbd-\ 999d-546c888892d6/PCB_scaffold"]][[2]];
In[4]:=
Click for copyable input
ImportString[molString, "MOL"]
Out[4]=

With some basic group theory, all PCB structures can be enumerated. The essential symmetry property of the whole scaffold, expressed as a permutation group, is the starting point.

In[5]:=
Click for copyable input
biphenylSymmetry = PermutationGroup[{Cycles[{{6, 10}, {7, 9}}], Cycles[{{1, 5}, {2, 4}}], Cycles[{{1, 6}, {2, 7}, {3, 8}, {4, 9}, {5, 10}}]}];

Form the cycle index polynomial from Pólya's counting theorem and manipulate its coefficients to obtain a count of 210 congeners (including the unsubstituted hydrocarbon structure, which is not a PCB due to its lack of chlorine).

In[6]:=
Click for copyable input
ci = Factor[ CycleIndexPolynomial[biphenylSymmetry, Array[Subscript[x, #] &, 4]]]
Out[6]=
In[7]:=
Click for copyable input
Total[CoefficientList[Expand[ci /. Subscript[x, i_] -> (x^i + 1)], x]]
Out[7]=

After renaming the locant positions using simple string replacements, all 209 IUPAC-compliant names are generated.

In[8]:=
Click for copyable input
conPos = Flatten[(PositionIndex /@ First /@ GroupOrbits[biphenylSymmetry, Permutations[#], Permute]) & /@ (LowerTriangularize[ ConstantArray["Cl", {10, 10}]] /. 0 -> "H")] /. Thread[Range[10] -> {"2", "3", "4", "5", "6", "2'", "3'", "4'", "5'", "6'"}];
In[9]:=
Click for copyable input
(names = Flatten[{StringJoin[Riffle[Sort[#["Cl"]], ","]] <> "-" <> (Length[#["Cl"]] /. Thread[Range[10] -> {"Chloro", "Dichloro", "Trichloro", "Tetrachloro", "Pentachloro", "Hexachloro", "Heptachloro", "Octachloro", "Nonachloro", "Decachloro"}]) <> "biphenyl"} & /@ conPos] /. "2,2',3,3',4,4',5,5',6,6'-Decachlorobiphenyl" -> "Decachlorobiphenyl") // Short
Out[9]//Short=

In a similar manner, exhaustively generate all congener structures.

In[10]:=
Click for copyable input
PCBstruct = ImportString[ StringReplacePart[molString, #, StringPosition[molString, "X"]], "MOL"] & /@ Flatten[(First /@ GroupOrbits[biphenylSymmetry, Permutations[#], Permute]) & /@ (LowerTriangularize[ ConstantArray["Cl", {10, 10}]] /. 0 -> "H"), 1];
In[11]:=
Click for copyable input
TextGrid[Transpose[{names, PCBstruct}] // Take[#, 2] &, Dividers -> All]
Out[11]=

To include more detailed properties of the congeners, import PCB as a dataset from a precomputed CloudObject.

In[12]:=
Click for copyable input
imp = CloudGet[CloudObject[ "https://www.wolframcloud.com/objects/user-722de5bb-ef39-4cbd-\ 999d-546c888892d6/PCB_congeners_propertylist"]];
In[13]:=
Click for copyable input
TextGrid[Take[imp, 5], Background -> {Automatic, {LightBlue}}, Dividers -> All]
Out[13]=

Combine the imported data with the previously computed structures and names.

In[14]:=
Click for copyable input
TextGrid[(PCBdata = SortBy[MapThread[ Flatten[{#1, Pick[imp[[3 ;;]], imp[[3 ;;, 1]], #2]}] &, {PCBstruct, names}], #[[3]] &]) // Take[#, 2] &, Dividers -> All]
Out[14]=

Create a custom entity store for these PCB structures.

show complete Wolfram Language input
In[15]:=
Click for copyable input
entities = Association @@ Map["PCB" <> ToString[#[[3]]] -> <| "ColorStructureDiagram" -> #[[1]], "IUPACName" -> #[[2]], "CASNumber" -> #[[4]], "BZNumber" -> #[[3]], "PCBDescriptors" -> #[[5]], "Label" -> "PCB-BZ#" <> ToString[#[[3]]] |> &, PCBdata];
In[16]:=
Click for copyable input
properties = <| "ColorStructureDiagram" -> <|"Label" -> "structure diagram"|>, "IUPACName" -> <|"Label" -> "IUPAC name"|>, "CASNumber" -> <|"Label" -> "CAS number"|>, "BZNumber" -> <|"Label" -> "Ballschmiter-Zell number"|>, "PCBDescriptors" -> <|"Label" -> "congener shorthand notation"|>, "Toxicity" -> <| "DefaultFunction" -> Function[e, If[StringCount[e["PCBDescriptors"], ","] == 3, "highly toxic", "toxic"]], "Label" -> "dioxin-like toxicity" |>, "NumberOfChlorineSubstituents" -> <| "DefaultFunction" -> Function[e, If[e["IUPACName"] == "Decachlorobiphenyl", 10, StringCount[e["IUPACName"], NumberString]]], "Label" -> "number of chlorine substituents" |> |>;
In[17]:=
Click for copyable input
classes = <| "CoplanarPCB" -> <| "Entities" -> {"IUPACName" -> (StringFreeQ[ "2" | "2'" | "6" | "6'" | "Deca"])}, "Label" -> "Coplanar or non-ortho PCBs" |>, "NoncoplanarPCB" -> <| "Entities" -> {"IUPACName" -> StringContainsQ["2" | "2'" | "6" | "6'"]}, "Label" -> "Noncoplanar PCBs" |> |>;
In[18]:=
Click for copyable input
store = EntityStore[ "PCB" -> <| "Label" -> "polychlorinated biphenyl", "LabelPlural" -> "polychlorinated biphenyls", "Entities" -> entities, "Properties" -> properties, "EntityClasses" -> classes |>]
Out[18]=

Register the store for this session.

In[19]:=
Click for copyable input
PrependTo[$EntityStores, store];

Test the entity store by calling a random entity.

In[20]:=
Click for copyable input
EntityValue[RandomEntity["PCB"], "PropertyAssociation"]
Out[20]=

In order to make all custom entities available in future sessions or for public applications, write the entity store to a CloudObject.

In[21]:=
Click for copyable input
CloudPut[store, "PCB_entity_store", Permissions -> "Public"]
Out[21]=

Related Examples

de es fr ja ko pt-br ru zh