Skip to content

Commit e077db2

Browse files
committed
Create a path_graph argument and update to_compound to allow for visualization
1 parent 08aa3e9 commit e077db2

File tree

1 file changed

+65
-7
lines changed

1 file changed

+65
-7
lines changed

mbuild/path.py

Lines changed: 65 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import math
44
from abc import abstractmethod
5+
import os
6+
import tempfile
57

68
import freud
79
import numpy as np
@@ -13,7 +15,8 @@
1315

1416

1517
class Path:
16-
def __init__(self, N=None, coordinates=None, bond_graph=None):
18+
def __init__(self, N=None, coordinates=None, bond_graph=None, path_graph=None):
19+
self.path_graph = path_graph
1720
self.bond_graph = bond_graph
1821
# Only N is defined, make empty coordinates array with size N
1922
# Use case: Random walks
@@ -35,6 +38,12 @@ def __init__(self, N=None, coordinates=None, bond_graph=None):
3538
self.generate()
3639
if self.N is None:
3740
self.N = len(self.coordinates)
41+
if self.path_graph == "linear":
42+
self.path_graph = BondGraph()
43+
self.path_graph.add_node(tuple(coordinates[0]))
44+
for point1, point2 in zip(self.coordinates, self.coordinates[1:]):
45+
self.path_graph.add_node(tuple(point2))
46+
self.path_graph.add_edge(tuple(point1), tuple(point2))
3847

3948
@classmethod
4049
def from_coordinates(cls, coordinates, bond_graph=None):
@@ -70,13 +79,28 @@ def neighbor_list(self, r_max, query_points, coordinates=None, box=None):
7079
return nlist
7180

7281
def to_compound(self, bead_name="_A", bead_mass=1):
73-
"""Visualize a path as an mBuild Compound."""
82+
"""Create an mBuild Compound using the coordinates and path_graph of a Path."""
7483
compound = Compound()
7584
for xyz in self.coordinates:
7685
compound.add(Compound(name=bead_name, mass=bead_mass, pos=xyz))
77-
if self.bond_graph:
78-
compound.set_bond_graph(self.bond_graph)
86+
if self.path_graph:
87+
# use the path_graph to create a bond graph
88+
bond_graph = self.path_graph_to_bond_graph(compound)
89+
compound.set_bond_graph(bond_graph)
7990
return compound
91+
92+
def path_graph_to_bond_graph(self, compound):
93+
"""Take a preset path_graph and return a bond_graph with the particles of a given compound."""
94+
bond_graph = BondGraph()
95+
for i in range(compound.n_particles):
96+
bond_graph.add_node(i) # needs to be the index of compound
97+
if self.path_graph:
98+
path_to_index_map = {tuple(coord):i for i, coord in enumerate(self.coordinates)}
99+
for point1, point2 in self.path_graph.edges:
100+
index1 = path_to_index_map[tuple(point1)]
101+
index2 = path_to_index_map[tuple(point2)]
102+
bond_graph.add_edge(index1, index2)
103+
return bond_graph
80104

81105
def apply_mapping(self):
82106
# TODO: Finish, add logic to align orientation with path site pos and bond graph
@@ -95,6 +119,37 @@ def _path_history(self):
95119
"""
96120
pass
97121

122+
def visualize(self, bead_color="#5d8aa8"):
123+
"""Visualize in 3D space using py3Dmol of the Path as a Compound."""
124+
py3Dmol = import_("py3Dmol")
125+
compound = self.to_compound()
126+
color_scheme = {"C": bead_color} # just use default Carbon element to set color
127+
for particle in compound.particles():
128+
particle.name = "C"
129+
tmp_dir = tempfile.mkdtemp()
130+
compound.save(
131+
os.path.join(tmp_dir, "tmp.mol2"),
132+
include_ports=False,
133+
overwrite=True,
134+
)
135+
136+
view = py3Dmol.view()
137+
with open(os.path.join(tmp_dir, "tmp.mol2"), "r") as f:
138+
view.addModel(f.read(), "mol2", keepH=True)
139+
140+
view.setStyle(
141+
{
142+
"stick": {"radius": 0.3, "color": "grey"},
143+
"sphere": {
144+
"radius": self.radius*10/2 if self.radius else 1.7/2, # angstroms
145+
"colorscheme": color_scheme,
146+
},
147+
}
148+
)
149+
view.zoomTo()
150+
151+
return view
152+
98153

99154
class HardSphereRandomWalk(Path):
100155
def __init__(
@@ -114,6 +169,7 @@ def __init__(
114169
trial_batch_size=20,
115170
tolerance=1e-5,
116171
bond_graph=None,
172+
path_graph=None,
117173
):
118174
"""Generates coordinates from a self avoiding random walk using
119175
fixed bond lengths, hard spheres, and minimum and maximum angles
@@ -151,6 +207,9 @@ def __init__(
151207
Tolerance used for rounding and checkig for overlaps.
152208
bond_graph : networkx.graph.Graph; optional
153209
Sets the bonding of sites along the path.
210+
path_graph : str; optional, default=None
211+
A passable string to define the bond_graph used in the Path. Options are:
212+
`linear`: each coordinate is connected to the previous coordinate to create a linear path.
154213
155214
Notes
156215
-----
@@ -184,8 +243,7 @@ def __init__(
184243
self.attempts = 0
185244
self.start_from_path_index = start_from_path_index
186245
self.start_from_path = start_from_path
187-
188-
# This random walk is including a previous path
246+
self.path_graph = path_graph
189247
if start_from_path:
190248
coordinates = np.concatenate(
191249
(
@@ -209,7 +267,7 @@ def __init__(
209267
self.rng = np.random.default_rng(seed)
210268

211269
super(HardSphereRandomWalk, self).__init__(
212-
coordinates=coordinates, N=None, bond_graph=bond_graph
270+
coordinates=coordinates, N=None, bond_graph=bond_graph, path_graph=path_graph
213271
)
214272

215273
def generate(self):

0 commit comments

Comments
 (0)