MultiMM 1.0.6__tar.gz → 1.0.8__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: MultiMM
3
- Version: 1.0.6
3
+ Version: 1.0.8
4
4
  Summary: A tool for chromatin modeling from nucleosomes to chromosomal territories.
5
5
  Home-page: https://github.com/SFGLab/MultiMM
6
6
  Author: Sebastian Korsak
@@ -27,6 +27,16 @@ Requires-Dist: hilbertcurve
27
27
  Requires-Dist: tqdm
28
28
  Requires-Dist: pyvista[all]
29
29
  Requires-Dist: OpenMM
30
+ Dynamic: author
31
+ Dynamic: author-email
32
+ Dynamic: classifier
33
+ Dynamic: description
34
+ Dynamic: description-content-type
35
+ Dynamic: home-page
36
+ Dynamic: license
37
+ Dynamic: requires-dist
38
+ Dynamic: requires-python
39
+ Dynamic: summary
30
40
 
31
41
  # MultiMM: An OpenMM-based software for whole genome 3D structure reconstruction
32
42
 
@@ -175,7 +185,7 @@ This version should now be more precise and polished. Let me know if you'd like
175
185
  | DEVICE | str | None | None | device index for CUDA or OpenCL (count from 0) |
176
186
  | INITIAL_STRUCTURE_PATH | str | None | None | Path to CIF file. |
177
187
  | BUILD_INITIAL_STRUCTURE | bool | True | None | To build a new initial structure. |
178
- | INITIAL_STRUCTURE_TYPE | str | hilbert | None | you can choose between: hilbert, circle. |
188
+ | INITIAL_STRUCTURE_TYPE | str | hilbert | None | you can choose between: hilbert, circle, rw, confined_rw, self_avoiding_rw, helix, spiral, sphere, knot. |
179
189
  | FORCEFIELD_PATH | str | None | None | Path to XML file with forcefield. |
180
190
  | N_BEADS | int | 50000 | None | Number of Simulation Beads. |
181
191
  | COMPARTMENT_PATH | str | None | None | It should be a `.bed` file with subcompartments from Calder. |
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: MultiMM
3
- Version: 1.0.6
3
+ Version: 1.0.8
4
4
  Summary: A tool for chromatin modeling from nucleosomes to chromosomal territories.
5
5
  Home-page: https://github.com/SFGLab/MultiMM
6
6
  Author: Sebastian Korsak
@@ -27,6 +27,16 @@ Requires-Dist: hilbertcurve
27
27
  Requires-Dist: tqdm
28
28
  Requires-Dist: pyvista[all]
29
29
  Requires-Dist: OpenMM
30
+ Dynamic: author
31
+ Dynamic: author-email
32
+ Dynamic: classifier
33
+ Dynamic: description
34
+ Dynamic: description-content-type
35
+ Dynamic: home-page
36
+ Dynamic: license
37
+ Dynamic: requires-dist
38
+ Dynamic: requires-python
39
+ Dynamic: summary
30
40
 
31
41
  # MultiMM: An OpenMM-based software for whole genome 3D structure reconstruction
32
42
 
@@ -175,7 +185,7 @@ This version should now be more precise and polished. Let me know if you'd like
175
185
  | DEVICE | str | None | None | device index for CUDA or OpenCL (count from 0) |
176
186
  | INITIAL_STRUCTURE_PATH | str | None | None | Path to CIF file. |
177
187
  | BUILD_INITIAL_STRUCTURE | bool | True | None | To build a new initial structure. |
178
- | INITIAL_STRUCTURE_TYPE | str | hilbert | None | you can choose between: hilbert, circle. |
188
+ | INITIAL_STRUCTURE_TYPE | str | hilbert | None | you can choose between: hilbert, circle, rw, confined_rw, self_avoiding_rw, helix, spiral, sphere, knot. |
179
189
  | FORCEFIELD_PATH | str | None | None | Path to XML file with forcefield. |
180
190
  | N_BEADS | int | 50000 | None | Number of Simulation Beads. |
181
191
  | COMPARTMENT_PATH | str | None | None | It should be a `.bed` file with subcompartments from Calder. |
@@ -145,7 +145,7 @@ This version should now be more precise and polished. Let me know if you'd like
145
145
  | DEVICE | str | None | None | device index for CUDA or OpenCL (count from 0) |
146
146
  | INITIAL_STRUCTURE_PATH | str | None | None | Path to CIF file. |
147
147
  | BUILD_INITIAL_STRUCTURE | bool | True | None | To build a new initial structure. |
148
- | INITIAL_STRUCTURE_TYPE | str | hilbert | None | you can choose between: hilbert, circle. |
148
+ | INITIAL_STRUCTURE_TYPE | str | hilbert | None | you can choose between: hilbert, circle, rw, confined_rw, self_avoiding_rw, helix, spiral, sphere, knot. |
149
149
  | FORCEFIELD_PATH | str | None | None | Path to XML file with forcefield. |
150
150
  | N_BEADS | int | 50000 | None | Number of Simulation Beads. |
151
151
  | COMPARTMENT_PATH | str | None | None | It should be a `.bed` file with subcompartments from Calder. |
@@ -6,7 +6,7 @@ with open('README.md', 'r', encoding='utf-8') as f:
6
6
 
7
7
  setup(
8
8
  name='MultiMM', # Package name
9
- version='1.0.6', # Version of the software
9
+ version='1.0.8', # Version of the software
10
10
  description='A tool for chromatin modeling from nucleosomes to chromosomal territories.',
11
11
  long_description=long_description,
12
12
  long_description_content_type='text/markdown',
@@ -1,4 +1,4 @@
1
1
  # Importing specific functions or classes from submodules
2
2
  from .run import main
3
3
 
4
- __version__ = "1.0.4"
4
+ __version__ = "1.0.8"
@@ -7,6 +7,14 @@ import argparse
7
7
  import openmm as mm
8
8
  from openmm.unit import Quantity
9
9
 
10
+ # Dynamically set the default path to the XML file in the package
11
+ try:
12
+ with importlib.resources.path('loopsage.forcefields', 'classic_sm_ff.xml') as default_xml_path:
13
+ default_xml_path = str(default_xml_path)
14
+ except FileNotFoundError:
15
+ # If running in a development setup without the resource installed, fallback to a relative path
16
+ default_xml_path = 'simulation/forcefields/ff.xml'
17
+
10
18
  @dataclass
11
19
  class Arg(object):
12
20
  name: str
@@ -131,7 +139,7 @@ args = ListOfArgs([
131
139
  Arg('INITIAL_STRUCTURE_PATH', help="Path to CIF file.", type=str, default='', val=''),
132
140
  Arg('BUILD_INITIAL_STRUCTURE', help="To build a new initial structure.", type=bool, default='True', val='True'),
133
141
  Arg('INITIAL_STRUCTURE_TYPE', help="you can choose between: hilbert, circle.", type=str, default='hilbert', val='hilbert'),
134
- Arg('FORCEFIELD_PATH', help="Path to XML file with forcefield.", type=str, default='', val=''),
142
+ Arg('FORCEFIELD_PATH', help="Path to XML file with forcefield.", type=str, default=default_xml_path, val=default_xml_path),
135
143
  Arg('N_BEADS', help="Number of Simulation Beads.", type=int, default='50000', val='50000'),
136
144
  Arg('COMPARTMENT_PATH', help="It can be either .bed file with subcompartments from Calder or .BigWig signal.", type=str, default='', val=''),
137
145
  Arg('LOOPS_PATH', help="A .bedpe file path with loops. It is required.", type=str, default='', val=''),
@@ -136,33 +136,11 @@ def read_compartments(file,ch,reg,res,binary=True):
136
136
  def generate_hilbert_curve(n_points,p=8,n=3,displacement_sigma=0.1,scale=6,viz=False,add_noise=False):
137
137
  hilbert_curve = HilbertCurve(p, n)
138
138
 
139
- distances = list(range(n_points)) # if n_points>4095 else list(range(n_points))
139
+ distances = list(range(n_points))
140
140
  points = np.array(hilbert_curve.points_from_distances(distances))
141
-
142
- #if n_points>4095:
143
- # x_sim, y_sim, z_sim = points[:,0], points[:,1], points[:,2]
144
- # tck, u = interpolate.splprep(x=[x_sim,y_sim,z_sim], s=2)
145
- # u_fine = np.linspace(0,1,n_points)
146
- # x_fine, y_fine, z_fine = interpolate.splev(u_fine, tck)
147
- # V_interpol = np.vstack((x_fine,y_fine,z_fine)).T
148
- #else:
149
- # V_interpol = points
150
141
  if add_noise:
151
142
  displacement = np.random.normal(loc=0.0, scale=displacement_sigma, size=n_points*3).reshape(n_points,3)
152
143
  V_interpol = V_interpol + displacement
153
- #max_dist = np.max(np.linalg.norm(V_interpol,axis=1))
154
-
155
- #if viz:
156
- # fig = plt.figure()
157
- # ax = plt.axes(projection='3d')
158
-
159
- # z = V_interpol[:,2]
160
- # x = V_interpol[:,0]
161
- # y = V_interpol[:,1]
162
-
163
- # ax.plot3D (x, y, z, 'green')
164
- # ax.set_title('Hilbert Curve')
165
- # plt.show()
166
144
 
167
145
  return points
168
146
 
@@ -181,13 +159,97 @@ def polymer_circle(n: int, z_stretch: float = 1.0, radius: float = 5.0) -> np.nd
181
159
  points = np.array(points)
182
160
  return points
183
161
 
162
+ def helix_structure(N_beads, radius=1, pitch=2):
163
+ theta = np.linspace(0, 4 * np.pi, N_beads) # 2 full turns
164
+ x = radius * np.cos(theta)
165
+ y = radius * np.sin(theta)
166
+ z = np.linspace(0, pitch * N_beads, N_beads)
167
+ V = np.column_stack((x, y, z))
168
+ return V
169
+
170
+ def spiral_structure(N_beads, initial_radius=1, pitch=1, growth_factor=0.05):
171
+ theta = np.linspace(0, 4 * np.pi, N_beads)
172
+ radius = initial_radius + growth_factor * np.arange(N_beads)
173
+ x = radius * np.cos(theta)
174
+ y = radius * np.sin(theta)
175
+ z = np.linspace(0, pitch * N_beads, N_beads)
176
+ V = np.column_stack((x, y, z))
177
+ return V
178
+
179
+ def sphere_surface_structure(N_beads, radius=1):
180
+ phi = np.random.uniform(0, 2 * np.pi, N_beads)
181
+ costheta = np.random.uniform(-1, 1, N_beads)
182
+ u = np.random.uniform(0, 1, N_beads)
183
+
184
+ theta = np.arccos(costheta)
185
+ r = radius * u ** (1/3)
186
+
187
+ x = r * np.sin(theta) * np.cos(phi)
188
+ y = r * np.sin(theta) * np.sin(phi)
189
+ z = r * np.cos(theta)
190
+
191
+ V = np.column_stack((x, y, z))
192
+ return V
193
+
194
+ def confined_random_walk(N_beads, box_size=5):
195
+ V = np.zeros((N_beads, 3))
196
+ for i in range(1, N_beads):
197
+ step = np.random.choice([-1, 1], size=3) # Random step in x, y, z
198
+ V[i] = V[i-1] + step
199
+ # Keep the points within a confined box (folding in)
200
+ V[i] = np.clip(V[i], -box_size, box_size)
201
+ return V
202
+
203
+ def trefoil_knot_structure(N_beads, scale=5):
204
+ t = np.linspace(0, 2 * np.pi, N_beads)
205
+ x = scale * (np.sin(t) + 2 * np.sin(2 * t))
206
+ y = scale * (np.cos(t) - 2 * np.cos(2 * t))
207
+ z = -scale * np.sin(3 * t)
208
+
209
+ V = np.column_stack((x, y, z))
210
+ return V
211
+
212
+ def random_walk_structure(N_beads, step_size=1):
213
+ # Initialize the structure array
214
+ V = np.zeros((N_beads, 3))
215
+
216
+ # Loop over each bead, starting from the second one
217
+ for i in range(1, N_beads):
218
+ # Randomly pick a direction for each step
219
+ step_direction = np.random.normal(size=3)
220
+ step_direction /= np.linalg.norm(step_direction) # Normalize to make it unit length
221
+
222
+ # Move the current bead from the last bead by a fixed step size
223
+ V[i] = V[i-1] + step_size * step_direction
224
+
225
+ return V
226
+
227
+ def compute_init_struct(N_beads,mode='rw',scale=5):
228
+ match mode:
229
+ case 'rw':
230
+ return random_walk_structure(N_beads)
231
+ case 'confined_rw':
232
+ return confined_random_walk(N_beads)
233
+ case 'knot':
234
+ return trefoil_knot_structure(N_beads)
235
+ case 'self_avoiding_rw':
236
+ return self_avoiding_random_walk(N_beads)
237
+ case 'circle':
238
+ return polymer_circle(N_beads,50,5)
239
+ case 'helix':
240
+ return helix_structure(N_beads)
241
+ case 'spiral':
242
+ return spiral_structure(N_beads)
243
+ case 'sphere':
244
+ return sphere_surface_structure(N_beads)
245
+ case 'hilbert':
246
+ return generate_hilbert_curve(n_dna,scale=scale)
247
+ case _:
248
+ return IndentationError('Invalid option for initial structure.')
249
+
184
250
  def build_init_mmcif(n_dna,chrom_ends,psf=True,path='',curve='hilbert',scale=5):
185
251
  # Define the initial coordinates of histones and the structure of DNA
186
- if curve=='hilbert':
187
- dna_points = generate_hilbert_curve(n_dna,scale=scale)
188
- elif curve=='circle':
189
- dna_points = polymer_circle(n_dna,50,5)
190
-
252
+ dna_points = compute_init_struct(n_dna,mode=curve,scale=scale)
191
253
  # Write the positions in .mmcif file
192
254
  atoms = ''
193
255
 
File without changes
File without changes
File without changes
File without changes
File without changes