[docs]classThreeDMolecule(OpenGLGroup,AbstractMolecule):"""Draws a 3D Molecule Requires using opengl renderer. Examples: --------- .. code-block:: python from manim_chemistry import * class ThreeDMoleculeFromFile(Scene): def construct(self): config.renderer = "opengl" molecule = GraphMolecule.molecule_from_file( "../examples/molecule_files/mol_files/acetone_3d.mol" ) self.wait() self.play(Write(molecule)) self.wait() .. code-block:: python from manim_chemistry import * class ThreeDMoleculeFromFileWithHydrogens(Scene): def construct(self): config.renderer = "opengl" molecule = ThreeDMolecule.molecule_from_file( "../examples/molecule_files/mol_files/acetone_3d.mol", ignore_hydrogens=False ) self.wait() self.play(Write(molecule)) self.wait() .. code-block:: python from manim_chemistry import * class ThreeDMoleculeFromPubChem(Scene): def construct(self): config.renderer = "opengl" molecule = ThreeDMolecule.molecule_from_pubchem(name="acetone") self.wait() self.play(Write(molecule)) self.wait() .. code-block:: python from manim_chemistry import * class ThreeDMoleculeFromPubChemThreeD(Scene): def construct(self): config.renderer = "opengl" molecule = ThreeDMolecule.molecule_from_pubchem( name="acetone", three_d=True, ignore_hydrogens=False ) self.wait() self.play(Write(molecule)) self.wait() """group_class=OpenGLGroupdef__init__(self,atoms_dict,bonds_dict,source_csv:Optional[str]=None,add_bonds=True,add_atoms=True,*mobjects,**kwargs,):ifconfig.renderer!=RendererType.OPENGL:raiseException("ThreeDMolecule requires using a OpenGL renderer. You can use it adding the `--renderer=opengl` flag or adding `config.renderer = opengl` to your python file.")self.atoms_dict=atoms_dictself.bonds_dict=bonds_dictself.source_csv=source_csvself.atoms=self.get_atoms_from_csv()self.bonds=self.get_bonds()super().__init__(**kwargs)self.add(*mobjects)ifadd_bonds:self.add(self.bonds)ifadd_atoms:self.add(self.atoms)self.move_to(ORIGIN)defget_atoms_from_csv(self):atoms=OpenGLGroup()for_,atominself.atoms_dict.items():ifself.source_csv:element=Element.from_csv_file(self.source_csv,atom.get("element"))else:element=MC_ELEMENT_DICT.get(atom.get("element"))atoms.add(ThreeDAtom(element,atom.get("coords")))returnatomsdefget_bonds(self):bonds=OpenGLGroup()forindex,bonds_listinself.bonds_dict.items():from_atom=self.atoms[index-1]forbondinbonds_list:to_atom=self.atoms[bond.get("to")-1]bond_type=bond.get("type")bonds.add(ThreeDBond(from_atom=from_atom,to_atom=to_atom,bond_type=int(bond_type)))returnbonds
[docs]@staticmethoddefmc_molecule_to_atoms_and_bonds(mc_molecule:MCMolecule):""" Transforms the structure of a mc_molecule to a (atoms, bonds) tuple with the following structure: - Vertices: {<atom_index>: MCAtom} - Edges: {(<from_atom_index>, <to_atom_index>): MCBond} Args: mc_molecule (MCMolecule): The origin MCMolecule Returns: Tuple[Dict, Dict]: See above. """atoms={}forindex,atominmc_molecule.atoms_by_index.items():bond_to={}forbondinatom.bonds:# TODO: This patches an issue with from_atom and to_atom but does not solve it completely.# Fix later the root causeifbond.from_atom.molecule_index==index:bond_to[bond.to_atom.molecule_index]=bond.to_atom.element.symbolelse:bond_to[bond.from_atom.molecule_index]=(bond.from_atom.element.symbol)atom_data={"coords":atom.coords,"element":atom.element.symbol,"bond_to":bond_to,}atoms[index]=atom_databonds={}foratom_indexinatoms.keys():atom_bonds=[]forbondinmc_molecule.bonds:ifatom_index==bond.to_atom.molecule_index:atom_bonds.append({"to":bond.from_atom.molecule_index,"type":bond.bond_type,"stereo":bond.stereo,"topology":bond.topology,"reacting_center_status":bond.reacting_center_status,})ifatom_bonds:bonds[atom_index]=atom_bondsreturnatoms,bonds