Graph3D - Ersetzen Sie Scheitelpunkte durch MoleculePlot3D

Aug 24 2020

Wie können wir die Eckpunkte in einem 3-Dim-Diagramm durch einzelne Graphics3DObjekte ersetzen ?

In meinem konkreten Fall möchte ich ein chemisches Netzwerk visualisieren und Eckpunkte durch ihre jeweiligen MoleculePlot3DDarstellungen ersetzen . Als Teaser ist dies das aktuelle 3D-Diagramm, mit dem ich arbeite. Sie können sich wahrscheinlich die endgültige Bewerbung vorstellen :)

Ich habe die Ideen aus diesem Beitrag verwendet , um die Koordinaten festzulegen.

Die roten Kugeln sollten durch 3-Dim-Molekül-Diagramme ersetzt werden.

Betrachten Sie dieses minimale Beispiel:

Graph3D[{"CO" \[DirectedEdge] "C", "CO" \[DirectedEdge] "O"}]

Einrichten der entsprechenden MoleculePlot3DInstanzen:

vert = AssociationThread[
  {"CO", "C", "O"} -> {
   MoleculePlot3D[Molecule[{Atom["[C]"], Atom["[O]"]}, {Bond[{1, 2}, "Double"]}]], 
   MoleculePlot3D[Molecule[{Atom["[C]"]}]], 
   MoleculePlot3D[Molecule[{Atom["[O]"]}]]}]

Ich habe jedoch Schwierigkeiten, die Eckpunkte im Graph3DProgramm programmatisch zu ersetzen . Ich habe es geschafft, das 2D-Diagramm zu ändern:

Graph[{
    Annotation["CO", VertexShapeFunction -> (Inset[vert["CO"], #1, Center, 2*#3] &), VertexSize -> 0.2],
    Annotation["C",  VertexShapeFunction -> (Inset[vert["C"], #1, Center, 2*#3] &),  VertexSize -> 0.2],   
    Annotation["O",  VertexShapeFunction -> (Inset[vert["O"], #1, Center, 2*#3] &),  VertexSize -> 0.2]}, 
    {"CO" \[DirectedEdge] "C", "CO" \[DirectedEdge] "O"}]

Wie kann ich das in Graph3D machen? Im vollen Fall werde ich mit folgenden Molekülen arbeiten:

{"C", "C+", "CH", "CH+", "CN", "CO", "CS", "CS+", "H", "H2", "HCO+", 
 "HCS+", "He", "N", "O", "OH", "S", "SO", "CH2+", "CO+", "O+", "OCS+", 
 "S+", "SO+", "CH2", "CN+", "H2O", "HCN", "HS", "H3O+", "HS+", "CH3+", 
 "HNC", "H3CO+", "CH4", "N+", "N2", "H+", "OH+", "OCS", "H2O+", "H2+", 
 "H2S+", "H3+", "He+", "O2", "SO2"}

Also relativ kleine Moleküle ohne die Notwendigkeit einer extremen Skalierung in den MoleculePlots.

Antworten

2 JasonB. Aug 25 2020 at 02:35

Diese Antwort vermeidet Insetzusammen und packt die Graphikgrundelemente von innen dem Ausdruck von einem System MoleculePlot3Dund ist daher ein wenig zerbrechlich , weil es in einer zukünftigen Version brechen könnte, die die Ausgabe von restrukturieren MoleculePlot3D.

Die Inspektion zeigt, dass die von MoleculePlot3D zurückgegebene Graphics3D immer ein GraphicsComplexmit allen Atomen und Bindungen enthält. Wir können das also verwenden GraphicsComplexund es einwickeln GeometricTransformation, damit die Scheitelpunktform funktioniert

molVertex[mol_][coords_, vertex_, scale_] := Module[
    {graphic = MoleculePlot3D @ mol, gc},
    gc = Cases[graphic, _GraphicsComplex, Infinity];
    GeometricTransformation[
        gc, 
        TranslationTransform[coords] @* ScalingTransform[scale]
    ]
]

Hier ist ein Beispiel,

SeedRandom @ 42;
g = RandomGraph @ {5, 8};
mols = Map[
    Molecule,
    {"CCCC(C)(C)OCC", "SC1CCCC1", "O=P(O)(O)CCO", "CCCC", "F[Ti](Cl)(Cl)Cl"}
];
Graph3D[
    Annotation[#,
        VertexShapeFunction -> molVertex[mols[[#]]],
        VertexSize -> 0.2
    ]& /@ VertexList[g],
    EdgeList @ g
]