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").
![Click for copyable input](assets.en/enumerate-pcb-structures-and-share-via-an-entityst/In_113.png)
Entity["Chemical", "Biphenyl"]["ColorStructureDiagram"]
![](assets.en/enumerate-pcb-structures-and-share-via-an-entityst/O_84.png)
ChemicalData also contains a particular congener of the PCB molecule.
![Click for copyable input](assets.en/enumerate-pcb-structures-and-share-via-an-entityst/In_114.png)
Entity["Chemical", "PCB"][
EntityProperty["Chemical", "ColorStructureDiagram"]]
![](assets.en/enumerate-pcb-structures-and-share-via-an-entityst/O_85.png)
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.
![Click for copyable input](assets.en/enumerate-pcb-structures-and-share-via-an-entityst/In_115.png)
molString = CloudGet[CloudObject[
"https://www.wolframcloud.com/objects/user-722de5bb-ef39-4cbd-\
999d-546c888892d6/PCB_scaffold"]][[2]];
![Click for copyable input](assets.en/enumerate-pcb-structures-and-share-via-an-entityst/In_116.png)
ImportString[molString, "MOL"]
![](assets.en/enumerate-pcb-structures-and-share-via-an-entityst/O_86.png)
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.
![Click for copyable input](assets.en/enumerate-pcb-structures-and-share-via-an-entityst/In_117.png)
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).
![Click for copyable input](assets.en/enumerate-pcb-structures-and-share-via-an-entityst/In_118.png)
ci = Factor[
CycleIndexPolynomial[biphenylSymmetry, Array[Subscript[x, #] &, 4]]]
![](assets.en/enumerate-pcb-structures-and-share-via-an-entityst/O_87.png)
![Click for copyable input](assets.en/enumerate-pcb-structures-and-share-via-an-entityst/In_119.png)
Total[CoefficientList[Expand[ci /. Subscript[x, i_] -> (x^i + 1)], x]]
![](assets.en/enumerate-pcb-structures-and-share-via-an-entityst/O_88.png)
After renaming the locant positions using simple string replacements, all 209 IUPAC-compliant names are generated.
![Click for copyable input](assets.en/enumerate-pcb-structures-and-share-via-an-entityst/In_120.png)
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'"}];
![Click for copyable input](assets.en/enumerate-pcb-structures-and-share-via-an-entityst/In_121.png)
(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
![](assets.en/enumerate-pcb-structures-and-share-via-an-entityst/O_89.png)
In a similar manner, exhaustively generate all congener structures.
![Click for copyable input](assets.en/enumerate-pcb-structures-and-share-via-an-entityst/In_122.png)
PCBstruct =
ImportString[
StringReplacePart[molString, #, StringPosition[molString, "X"]],
"MOL"] & /@
Flatten[(First /@
GroupOrbits[biphenylSymmetry, Permutations[#],
Permute]) & /@ (LowerTriangularize[
ConstantArray["Cl", {10, 10}]] /. 0 -> "H"), 1];
![Click for copyable input](assets.en/enumerate-pcb-structures-and-share-via-an-entityst/In_123.png)
TextGrid[Transpose[{names, PCBstruct}] // Take[#, 2] &,
Dividers -> All]
![](assets.en/enumerate-pcb-structures-and-share-via-an-entityst/O_90.png)
To include more detailed properties of the congeners, import PCB as a dataset from a precomputed CloudObject.
![Click for copyable input](assets.en/enumerate-pcb-structures-and-share-via-an-entityst/In_124.png)
imp = CloudGet[CloudObject[
"https://www.wolframcloud.com/objects/user-722de5bb-ef39-4cbd-\
999d-546c888892d6/PCB_congeners_propertylist"]];
![Click for copyable input](assets.en/enumerate-pcb-structures-and-share-via-an-entityst/In_125.png)
TextGrid[Take[imp, 5], Background -> {Automatic, {LightBlue}},
Dividers -> All]
![](assets.en/enumerate-pcb-structures-and-share-via-an-entityst/O_91.png)
Combine the imported data with the previously computed structures and names.
![Click for copyable input](assets.en/enumerate-pcb-structures-and-share-via-an-entityst/In_126.png)
TextGrid[(PCBdata =
SortBy[MapThread[
Flatten[{#1,
Pick[imp[[3 ;;]], imp[[3 ;;, 1]], #2]}] &, {PCBstruct,
names}], #[[3]] &]) // Take[#, 2] &, Dividers -> All]
![](assets.en/enumerate-pcb-structures-and-share-via-an-entityst/O_92.png)
Create a custom entity store for these PCB structures.
![Click for copyable input](assets.en/enumerate-pcb-structures-and-share-via-an-entityst/In_130.png)
store = EntityStore[
"PCB" -> <|
"Label" -> "polychlorinated biphenyl",
"LabelPlural" -> "polychlorinated biphenyls",
"Entities" -> entities,
"Properties" -> properties,
"EntityClasses" -> classes
|>]
![](assets.en/enumerate-pcb-structures-and-share-via-an-entityst/O_93.png)
Register the store for this session.
![Click for copyable input](assets.en/enumerate-pcb-structures-and-share-via-an-entityst/In_131.png)
PrependTo[$EntityStores, store];
Test the entity store by calling a random entity.
![Click for copyable input](assets.en/enumerate-pcb-structures-and-share-via-an-entityst/In_132.png)
EntityValue[RandomEntity["PCB"], "PropertyAssociation"]
![](assets.en/enumerate-pcb-structures-and-share-via-an-entityst/O_94.png)
In order to make all custom entities available in future sessions or for public applications, write the entity store to a CloudObject.
![Click for copyable input](assets.en/enumerate-pcb-structures-and-share-via-an-entityst/In_133.png)
CloudPut[store, "PCB_entity_store", Permissions -> "Public"]