La guía o código que verás en este artículo es la resolución más sencilla y válida que encontramos a tu duda o problema.
Solución:
Jason B vio esto antes que yo, pero creo que lo siguiente reproduce razonablemente bien algunos de los ejemplos de entrada de JUEGOS.
f[mol_] := Module[al, out,
al = AtomList[Molecule[mol],
All, "AtomicNumber", "AtomCoordinates"];
out = QuantityMagnitude /@
Flatten /@ al[[First /@ Molecule[mol]["SymmetryEquivalentAtoms"]]];
out /. z_Integer :> Sequence[ElementData[z, "Abbreviation"], z]
]
f["Toluene"]
El plan general para resolver esto es
- Genere todas las transformaciones de simetría para una molécula dada.
- Aplique estas transformaciones a cada coordenada de átomo, dando una lista de coordenadas para cada átomo.
- Los átomos del grupo que dan las listas de coordenadas equivalentes se consideran equivalentes.
Lamentablemente, los desarrolladores de Wolfram no brindan las funciones de transformación reales asociadas con un elemento de simetría dado a través de ninguna función integrada. Pero sí nos dan suficiente información en el "SymmetryElements"
propiedad para construirlos nosotros mismos:
In[26]:= Molecule["methane"]["SymmetryElements"] // pf2
Out[26]=
<
Al examinar la estructura de esa salida, podemos escribir una función para devolver la transformación del elemento de simetría. me gusta usar KeyValuePattern
para definiciones fácilmente legibles:
symmetryOperation[KeyValuePattern["Operation"->"Rotation","Degree"->d_,"RotationAxis"->InfiniteLine[point_,direction_]]] := RotationTransform[(2 * Pi) / d, direction, point];
symmetryOperation[KeyValuePattern["Operation"->"ImproperRotation","Degree"->d_,"RotationAxis"->InfiniteLine[point_,direction_]]] := ReflectionTransform[direction, point] @* RotationTransform[(2 * Pi) / d, direction, point];
reflectpoint[point_, center_] := point + 2 * (center + -point);
symmetryOperation[KeyValuePattern["Operation"->"Inversion","InversionCenter"->Point[center_]]] := Composition[
ReflectionTransform[1, 0, 0, center],
ReflectionTransform[0, 1, 0, center],
ReflectionTransform[0, 0, 1, center]
];
symmetryOperation[KeyValuePattern["Operation"->"Reflection","SymmetryPlane"->Hyperplane[normal_,point_]]] := ReflectionTransform[normal, point]
Ahora tomamos escribir una función para devolver todas las transformaciones de simetría de una molécula, corrigiendo el descuido que Wolfram ha hecho al no incluir el elemento Identidad:
symmetryTransforms[mol_] := Join[Identity, Map[symmetryOperation, mol @ "SymmetryElements"]];
Ahora envuélvalo todo junto con una función para aplicar cada transformación a cada coordenada de átomo, y luego reúna aquellos que producen la misma lista de coordenadas:
symmetryUniqueAtomIndices[mol_, tolerance_:0.1] := Module[
transforms = symmetryTransforms @ mol,
points = QuantityMagnitude @ mol @ "AtomCoordinates"
,
PrependTo[transforms, Identity];
GatherBy[Range @ Length @ points,
Sort[
DeleteDuplicates[Round[Through[transforms[Part[points, #]]], tolerance]]
]&
]
]
Esto usa GatherBy
para agrupar átomos equivalentes. La parte importante aquí es hacer una función para canonicalizar las coordenadas transformadas, y para eso solo estoy redondeando los valores numéricos, eliminando los duplicados y luego clasificándolos. Probablemente haya margen de mejora en este paso.
Puede ver las diferentes conformaciones de ciclohexano de este ejemplo:
labels = "planar", "chair", "twist-boat", "boat", "half-boat", "half-chair";
conformers = AssociationThread[
labels -> CloudImport[
CloudObject["https://www.wolframcloud.com/objects/555b1b48-9f89-45ef-a9e2-49c8fe5228b6"],
"SDF"
]
];
Compara la simetría de las diferentes conformaciones:
In[10]:= symmetryUniqueAtomIndices /@ conformers
Out[10]= <|"planar" -> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
14, 15, 16, 17, 18,
"chair" -> 1, 2, 3, 4, 5, 6, 7, 9, 12, 13, 16, 18, 8, 10, 11,
14, 15, 17,
"twist-boat" -> 1, 4, 2, 3, 5, 6, 7, 8, 13, 14, 9, 12, 15,
17, 10, 11, 16, 18,
"boat" -> 1, 4, 2, 3, 5, 6, 7, 14, 8, 13, 9, 11, 15,
18, 10, 12, 16, 17,
"half-boat" -> 1, 2, 6, 3, 5, 4, 7, 8, 9, 18, 10,
17, 11, 15, 12, 16, 13, 14,
"half-chair" -> 1, 4, 2, 3, 5, 6, 7, 13, 8, 14, 9,
12, 10, 11, 15, 17, 16, 18|>
Si desea solo un átomo de cada grupo de equivalencia, use algo como
In[11]:= Map[First] /@ %
Out[11]= <|"planar" -> 1, 7, "chair" -> 1, 7, 8,
"twist-boat" -> 1, 2, 7, 9, 10, "boat" -> 1, 2, 7, 8, 9, 10,
"half-boat" -> 1, 2, 3, 4, 7, 8, 9, 10, 11, 12, 13, 14,
"half-chair" -> 1, 2, 5, 7, 8, 9, 10, 15, 16|>
Puede visualizar los grupos de simetría a través de algo como
MoleculePlot3D[conformers["chair"],
[email protected]
["chair"]]
En esta imagen, todos los átomos de un color dado son equivalentes según las operaciones de simetría disponibles. Puede ver que los átomos de hidrógeno ahora se dividen en dos categorías, el ecuatorial (que irradia 'fuera' del anillo) en púrpura y el axial (con enlaces paralelos al eje de simetría principal) en azul.
valoraciones y comentarios
Tienes la opción de añadir valor a nuestra información tributando tu veteranía en las referencias.