Определение структуры полихлорированных бифенилов (ПХБ) и публикация через EntityStore
Полихлорированный бифенил (ПХБ) представляет собой органическое соединение с химической формулой . В прошлом ПХБ имели ряд промышленных применений, в том числе, использовались в электрических трансформатарах. В данном примере, мы проиллюстрируем генерацию и хранение формул всех возможных полихлорированных бифенилов (ПХБ) в качестве объектов пользователя.
Данные о химических соединениях ChemicalData уже содержат информацию о ПХБ, часто под названием "дифенил" или "бифенил".

Entity["Chemical", "Biphenyl"]["ColorStructureDiagram"]

ChemicalData также содержит соединения молекулы ПХБ.

Entity["Chemical", "PCB"][
EntityProperty["Chemical", "ColorStructureDiagram"]]

Общая структура ПХБ включает в себя 10 сторон, обозначенных ниже крестиками. Для того, чтобы получить все возможные моно- дека-хлорированные производные (соединения), хлор-заместители присоединяются к молекуле ПХБ различными способами. Общая структура молекулы в формате "MOL" загружается из заранее созданного объекта файловой системы CloudObject.

molString = CloudGet[CloudObject[
"https://www.wolframcloud.com/objects/user-722de5bb-ef39-4cbd-\
999d-546c888892d6/PCB_scaffold"]][[2]];

ImportString[molString, "MOL"]

С учетом базовой теории групп мы можем перечислить все структуры ПХБ. Существенным свойством данной структуры будет симметрия, служащая в качестве основы для молекулярных соединений.

biphenylSymmetry =
PermutationGroup[{Cycles[{{6, 10}, {7, 9}}],
Cycles[{{1, 5}, {2, 4}}],
Cycles[{{1, 6}, {2, 7}, {3, 8}, {4, 9}, {5, 10}}]}];
Сформируем цикличный индекс для многочлена на основе теоремы Полна и будем варьировать коэффициенты данного индекса, чтобы получить 210 возможных соединений (включая незамещенную углеводородную структуру, которая не является ПБХ из-за отсутствия хлора).

ci = Factor[
CycleIndexPolynomial[biphenylSymmetry, Array[Subscript[x, #] &, 4]]]


Total[CoefficientList[Expand[ci /. Subscript[x, i_] -> (x^i + 1)], x]]

Далее, генерируем 209 наименования полученных соединений в соответствии со стандартами организации IUPAC (Международный союз теоретической и прикладной химии).

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'"}];

(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

Аналогичным образом генерируем все возможные структуры соединений.

PCBstruct =
ImportString[
StringReplacePart[molString, #, StringPosition[molString, "X"]],
"MOL"] & /@
Flatten[(First /@
GroupOrbits[biphenylSymmetry, Permutations[#],
Permute]) & /@ (LowerTriangularize[
ConstantArray["Cl", {10, 10}]] /. 0 -> "H"), 1];

TextGrid[Transpose[{names, PCBstruct}] // Take[#, 2] &,
Dividers -> All]

Для того, чтобы включить в наши данные более подробные свойства полученных соединений, импортируем данныe o ПХБ из уже существующего объектa облачной файловой системы, CloudObject.

imp = CloudGet[CloudObject[
"https://www.wolframcloud.com/objects/user-722de5bb-ef39-4cbd-\
999d-546c888892d6/PCB_congeners_propertylist"]];

TextGrid[Take[imp, 5], Background -> {Automatic, {LightBlue}},
Dividers -> All]

Объединим импортированные данные с ранее вычисленными структурами и названиями.

TextGrid[(PCBdata =
SortBy[MapThread[
Flatten[{#1,
Pick[imp[[3 ;;]], imp[[3 ;;, 1]], #2]}] &, {PCBstruct,
names}], #[[3]] &]) // Take[#, 2] &, Dividers -> All]

Сохраним информацию о полученных структурах ПХБ в качестве информационного объекта "entity store" (букв. хранилище сущностей).

store = EntityStore[
"PCB" -> <|
"Label" -> "polychlorinated biphenyl",
"LabelPlural" -> "polychlorinated biphenyls",
"Entities" -> entities,
"Properties" -> properties,
"EntityClasses" -> classes
|>]

Зарегистрируем информацию, подготовленную в данной рабочей сессии.

PrependTo[$EntityStores, store];
Протестируем, доступна ли сохраненная информация для дальнейшего использования.

EntityValue[RandomEntity["PCB"], "PropertyAssociation"]

Для того, чтобы все пользовательские информационные объекты были доступны к использованию в дальнейшем (например, для общественных приложений), их необходимо сохранить в качестве объекта облачной системы файлов, CloudObject.

CloudPut[store, "PCB_entity_store", Permissions -> "Public"]