pyLoopSage 1.0.16__tar.gz → 1.0.18__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.
- {pyloopsage-1.0.16/pyLoopSage.egg-info → pyloopsage-1.0.18}/PKG-INFO +66 -9
- {pyloopsage-1.0.16 → pyloopsage-1.0.18}/README.md +54 -7
- {pyloopsage-1.0.16 → pyloopsage-1.0.18}/loopsage/__init__.py +1 -1
- {pyloopsage-1.0.16 → pyloopsage-1.0.18}/loopsage/args_definition.py +4 -1
- {pyloopsage-1.0.16 → pyloopsage-1.0.18}/loopsage/md.py +26 -30
- {pyloopsage-1.0.16 → pyloopsage-1.0.18}/loopsage/run.py +2 -2
- {pyloopsage-1.0.16 → pyloopsage-1.0.18}/loopsage/stochastic_simulation.py +42 -28
- {pyloopsage-1.0.16 → pyloopsage-1.0.18/pyLoopSage.egg-info}/PKG-INFO +66 -9
- {pyloopsage-1.0.16 → pyloopsage-1.0.18}/setup.py +1 -1
- {pyloopsage-1.0.16 → pyloopsage-1.0.18}/LICENSE +0 -0
- {pyloopsage-1.0.16 → pyloopsage-1.0.18}/loopsage/em.py +0 -0
- {pyloopsage-1.0.16 → pyloopsage-1.0.18}/loopsage/forcefields/classic_sm_ff.xml +0 -0
- {pyloopsage-1.0.16 → pyloopsage-1.0.18}/loopsage/initial_structures.py +0 -0
- {pyloopsage-1.0.16 → pyloopsage-1.0.18}/loopsage/plots.py +0 -0
- {pyloopsage-1.0.16 → pyloopsage-1.0.18}/loopsage/preproc.py +0 -0
- {pyloopsage-1.0.16 → pyloopsage-1.0.18}/loopsage/utils.py +0 -0
- {pyloopsage-1.0.16 → pyloopsage-1.0.18}/loopsage/vizualization_tools.py +0 -0
- {pyloopsage-1.0.16 → pyloopsage-1.0.18}/pyLoopSage.egg-info/SOURCES.txt +0 -0
- {pyloopsage-1.0.16 → pyloopsage-1.0.18}/pyLoopSage.egg-info/dependency_links.txt +0 -0
- {pyloopsage-1.0.16 → pyloopsage-1.0.18}/pyLoopSage.egg-info/entry_points.txt +0 -0
- {pyloopsage-1.0.16 → pyloopsage-1.0.18}/pyLoopSage.egg-info/requires.txt +0 -0
- {pyloopsage-1.0.16 → pyloopsage-1.0.18}/pyLoopSage.egg-info/top_level.txt +0 -0
- {pyloopsage-1.0.16 → pyloopsage-1.0.18}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: pyLoopSage
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.18
|
|
4
4
|
Summary: An energy-based stochastic model of loop extrusion in chromatin.
|
|
5
5
|
Home-page: https://github.com/SFGLab/pyLoopSage
|
|
6
6
|
Author: Sebastian Korsak
|
|
@@ -31,6 +31,16 @@ Requires-Dist: statsmodels
|
|
|
31
31
|
Requires-Dist: imageio
|
|
32
32
|
Requires-Dist: imageio[ffmpeg]
|
|
33
33
|
Requires-Dist: pillow
|
|
34
|
+
Dynamic: author
|
|
35
|
+
Dynamic: author-email
|
|
36
|
+
Dynamic: classifier
|
|
37
|
+
Dynamic: description
|
|
38
|
+
Dynamic: description-content-type
|
|
39
|
+
Dynamic: home-page
|
|
40
|
+
Dynamic: license
|
|
41
|
+
Dynamic: requires-dist
|
|
42
|
+
Dynamic: requires-python
|
|
43
|
+
Dynamic: summary
|
|
34
44
|
|
|
35
45
|
# pyLoopSage
|
|
36
46
|
Updated version of the stochastic loop extrusion model: LoopSage with capability to run incredibly fast, parallelized across CPU cores. This package is even more user-friendly and it can be installed via PyPI.
|
|
@@ -44,11 +54,6 @@ Updated version of the stochastic loop extrusion model: LoopSage with capability
|
|
|
44
54
|
- Visualization functions.
|
|
45
55
|
- Capability to run form terminal with a simple command `loopsage -c config.ini`.
|
|
46
56
|
|
|
47
|
-
## Publication
|
|
48
|
-
Please cite the method paper in case that you would like to use this model for your work,
|
|
49
|
-
|
|
50
|
-
* Korsak, Sevastianos, and Dariusz Plewczynski. "LoopSage: An energy-based Monte Carlo approach for the loop extrusion modelling of chromatin." Methods (2024).
|
|
51
|
-
|
|
52
57
|
## The model
|
|
53
58
|
|
|
54
59
|
### Stochastic Simulation
|
|
@@ -74,7 +79,7 @@ These $L(\cdot), R(\cdot)$ functions are two functions that define the binding p
|
|
|
74
79
|
|
|
75
80
|
$$c_{\text{fold}}=-\dfrac{N_{\text{beads}}f}{N_{\text{lef}}\log(N_{\text{beads}}/N_{\text{lef}})},\quad c_{\text{bind}}=-\dfrac{N_{\text{beads}}b}{\sum_i \left(L(m_i)+R(n_i)\right)},\quad c_{\text{cross}}=\kappa \times 10^4.$$
|
|
76
81
|
|
|
77
|
-
The parameters are defined in such a way that when $f=b=\kappa=1$, the three terms of the stochastic energy are balanced.
|
|
82
|
+
The parameters are defined in such a way that when $f=b=\kappa=1$, the three terms of the stochastic energy are balanced. To clarrify, this parametrization is slightly different than this of the original paper. We multiply with $N_{\text{beads}}$, so as to keep the input parameters $f,b,\kappa$ simpler close to 1. Therefore, a value $f=0.1$ leads to unfolded structures, and a value $f=2$ it leads to very fast propagating long loops.
|
|
78
83
|
|
|
79
84
|
And the energy difference can be expressed as the energy difference of each term,
|
|
80
85
|
|
|
@@ -113,7 +118,7 @@ For the implementation of this model in python, we used OpenMM and CUDA accelera
|
|
|
113
118
|
In general the user can run simulation in two different ways:
|
|
114
119
|
|
|
115
120
|
1. **Energy minimization (EM)**: It means that for each sample of cohesin positions $C_{t_i}=(m_j(t_i),n_j(t_i))$ start from a different initial structure (usually 3D random walk) and we apply the forcefield. For each structure we start from a different initial condition. In general, it is suggested to run the model in this way because it is faster, less prone to errors and the structures are not correlated to each other.
|
|
116
|
-
2. **Molecular Dynamics (MD)**: In this case we have only one initial structure, we minimize the energy according to the forcefield only once and then we run a molecular dynamics simulation over time. This creates a continuous trajectory of structures, and it is cool for visualization pruposes.
|
|
121
|
+
2. **Molecular Dynamics (MD)**: In this case we have only one initial structure, we minimize the energy according to the forcefield only once and then we run a molecular dynamics simulation over time. This creates a continuous trajectory of structures, and it is cool for visualization pruposes. It is also biophysically more correct, in the sense that loop extrusion should be time-dependent, and the structure at time $t_i$ has to me correlated with structures at time $t_{i\pm1}$. It is a little bit more prone to error, and you may need to change the simulation frequence and step in case of instability (smaller frequency and more steps to stabilize it).
|
|
117
122
|
|
|
118
123
|
## Installation
|
|
119
124
|
|
|
@@ -262,3 +267,55 @@ In the output folder there are another three subfolders:
|
|
|
262
267
|
An example, illustrated with Chimera software, simulated trajectory of structures after running Simulated Annealing and molecular dynamics.
|
|
263
268
|
|
|
264
269
|

|
|
270
|
+
|
|
271
|
+
### Long-table of LoopSage arguments
|
|
272
|
+
|
|
273
|
+
| Argument Name | Description | Type | Default Value |
|
|
274
|
+
|------------------------|-----------------------------------------------------------------------------------------------------------------|------------|---------------------|
|
|
275
|
+
| PLATFORM | Name of the platform. Available choices: CPU, CUDA, OpenCL | str | CPU |
|
|
276
|
+
| DEVICE | Device index for CUDA or OpenCL (count from 0) | str | None |
|
|
277
|
+
| N_BEADS | Number of Simulation Beads. | int | None |
|
|
278
|
+
| BEDPE_PATH | A .bedpe file path with loops. It is required. | str | None |
|
|
279
|
+
| OUT_PATH | Output folder name. | str | ../results |
|
|
280
|
+
| REGION_START | Starting region coordinate. | int | None |
|
|
281
|
+
| REGION_END | Ending region coordinate. | int | None |
|
|
282
|
+
| CHROM | Chromosome that corresponds to the modeling region of interest. | str | None |
|
|
283
|
+
| LEF_RW | True if cohesins slide as a random walk instead of one direction. | bool | True |
|
|
284
|
+
| LEF_DRIFT | True if LEFs are pushed back when they encounter other LEFs. | bool | False |
|
|
285
|
+
| N_STEPS | Number of Monte Carlo steps. | int | 40000 |
|
|
286
|
+
| N_LEF | Number of loop extrusion factors. | int | None |
|
|
287
|
+
| N_LEF2 | Number of second family loop extrusion factors. | int | 0 |
|
|
288
|
+
| MC_STEP | Monte Carlo frequency to avoid autocorrelated ensembles. | int | 200 |
|
|
289
|
+
| BURNIN | Burn-in period (steps before equilibrium). | int | 1000 |
|
|
290
|
+
| T_INIT | Initial Temperature of the Stochastic Model. | float | 2.0 |
|
|
291
|
+
| T_FINAL | Final Temperature of the Stochastic Model. | float | 1.0 |
|
|
292
|
+
| METHOD | Stochastic modeling method (Metropolis or Simulated Annealing). | str | 'Annealing' |
|
|
293
|
+
| FOLDING_COEFF | Folding coefficient. | float | 1.0 |
|
|
294
|
+
| FOLDING_COEFF2 | Folding coefficient for the second family of LEFs. | float | 0.0 |
|
|
295
|
+
| CROSS_COEFF | LEF crossing coefficient. | float | 1.0 |
|
|
296
|
+
| CROSS_LOOP | True if the penalty is applied when mi<mj<ni<nj. False if it applies only when mj=ni. When false it is better to enable LEF_DRIFT as well. | bool |True |
|
|
297
|
+
| BIND_COEFF | CTCF binding coefficient. | float | 1.0 |
|
|
298
|
+
| SAVE_PLOTS | True to save diagnostic plots. | bool | True |
|
|
299
|
+
| SAVE_MDT | True to save metadata of the stochastic simulation. | bool | True |
|
|
300
|
+
| INITIAL_STRUCTURE_TYPE | Choose from: rw, confined_rw, self_avoiding_rw, helix, circle, spiral, sphere. | str | rw |
|
|
301
|
+
| SIMULATION_TYPE | Either EM (energy minimizations) or MD (molecular dynamics). | str | None |
|
|
302
|
+
| INTEGRATOR_STEP | Step of the integrator. | Quantity | 100 femtosecond |
|
|
303
|
+
| FORCEFIELD_PATH | Path to XML file with forcefield. | str | default_xml_path |
|
|
304
|
+
| ANGLE_FF_STRENGTH | Angle force strength. | float | 200.0 |
|
|
305
|
+
| LE_FF_LENGTH | Equilibrium distance of loop forces. | float | 0.1 |
|
|
306
|
+
| LE_FF_STRENGTH | Interaction Strength of loop forces. | float | 50000.0 |
|
|
307
|
+
| EV_P | Probability that excluded volume is disabled. Enable it only in case of topoisomerase activity simulation. | float | 0.0 |
|
|
308
|
+
| EV_FF_STRENGTH | Excluded-volume strength. | float | 100.0 |
|
|
309
|
+
| EV_FF_POWER | Excluded-volume power. | float | 3.0 |
|
|
310
|
+
| FRICTION | Friction coefficient of the Langevin integrator. | float | 0.1 |
|
|
311
|
+
| TOLERANCE | Stopping condition for energy minimization. | float | 0.001 |
|
|
312
|
+
| VIZ_HEATS | True to visualize the output average heatmap. | bool | True |
|
|
313
|
+
| SIM_TEMP | Temperature of the 3D simulation (EM or MD). | Quantity | 310 kelvin |
|
|
314
|
+
| SIM_STEP | Amount of simulation steps for loop force adjustments. | int | 1000 |
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
## Citation
|
|
318
|
+
Please cite the method and biological paper in case that you would like to use this model for your work,
|
|
319
|
+
|
|
320
|
+
* Korsak, Sevastianos, and Dariusz Plewczynski. "LoopSage: An energy-based Monte Carlo approach for the loop extrusion modelling of chromatin." Methods (2024).
|
|
321
|
+
* Jodkowska, K., Parteka-Tojek, Z., Agarwal, A., Denkiewicz, M., Korsak, S., Chiliński, M., Banecki, K., & Plewczynski, D. (2024). Improved cohesin HiChIP protocol and bioinformatic analysis for robust detection of chromatin loops and stripes. In bioRxiv (p. 2024.05.16.594268). https://doi.org/10.1101/2024.05.16.594268
|
|
@@ -10,11 +10,6 @@ Updated version of the stochastic loop extrusion model: LoopSage with capability
|
|
|
10
10
|
- Visualization functions.
|
|
11
11
|
- Capability to run form terminal with a simple command `loopsage -c config.ini`.
|
|
12
12
|
|
|
13
|
-
## Publication
|
|
14
|
-
Please cite the method paper in case that you would like to use this model for your work,
|
|
15
|
-
|
|
16
|
-
* Korsak, Sevastianos, and Dariusz Plewczynski. "LoopSage: An energy-based Monte Carlo approach for the loop extrusion modelling of chromatin." Methods (2024).
|
|
17
|
-
|
|
18
13
|
## The model
|
|
19
14
|
|
|
20
15
|
### Stochastic Simulation
|
|
@@ -40,7 +35,7 @@ These $L(\cdot), R(\cdot)$ functions are two functions that define the binding p
|
|
|
40
35
|
|
|
41
36
|
$$c_{\text{fold}}=-\dfrac{N_{\text{beads}}f}{N_{\text{lef}}\log(N_{\text{beads}}/N_{\text{lef}})},\quad c_{\text{bind}}=-\dfrac{N_{\text{beads}}b}{\sum_i \left(L(m_i)+R(n_i)\right)},\quad c_{\text{cross}}=\kappa \times 10^4.$$
|
|
42
37
|
|
|
43
|
-
The parameters are defined in such a way that when $f=b=\kappa=1$, the three terms of the stochastic energy are balanced.
|
|
38
|
+
The parameters are defined in such a way that when $f=b=\kappa=1$, the three terms of the stochastic energy are balanced. To clarrify, this parametrization is slightly different than this of the original paper. We multiply with $N_{\text{beads}}$, so as to keep the input parameters $f,b,\kappa$ simpler close to 1. Therefore, a value $f=0.1$ leads to unfolded structures, and a value $f=2$ it leads to very fast propagating long loops.
|
|
44
39
|
|
|
45
40
|
And the energy difference can be expressed as the energy difference of each term,
|
|
46
41
|
|
|
@@ -79,7 +74,7 @@ For the implementation of this model in python, we used OpenMM and CUDA accelera
|
|
|
79
74
|
In general the user can run simulation in two different ways:
|
|
80
75
|
|
|
81
76
|
1. **Energy minimization (EM)**: It means that for each sample of cohesin positions $C_{t_i}=(m_j(t_i),n_j(t_i))$ start from a different initial structure (usually 3D random walk) and we apply the forcefield. For each structure we start from a different initial condition. In general, it is suggested to run the model in this way because it is faster, less prone to errors and the structures are not correlated to each other.
|
|
82
|
-
2. **Molecular Dynamics (MD)**: In this case we have only one initial structure, we minimize the energy according to the forcefield only once and then we run a molecular dynamics simulation over time. This creates a continuous trajectory of structures, and it is cool for visualization pruposes.
|
|
77
|
+
2. **Molecular Dynamics (MD)**: In this case we have only one initial structure, we minimize the energy according to the forcefield only once and then we run a molecular dynamics simulation over time. This creates a continuous trajectory of structures, and it is cool for visualization pruposes. It is also biophysically more correct, in the sense that loop extrusion should be time-dependent, and the structure at time $t_i$ has to me correlated with structures at time $t_{i\pm1}$. It is a little bit more prone to error, and you may need to change the simulation frequence and step in case of instability (smaller frequency and more steps to stabilize it).
|
|
83
78
|
|
|
84
79
|
## Installation
|
|
85
80
|
|
|
@@ -228,3 +223,55 @@ In the output folder there are another three subfolders:
|
|
|
228
223
|
An example, illustrated with Chimera software, simulated trajectory of structures after running Simulated Annealing and molecular dynamics.
|
|
229
224
|
|
|
230
225
|

|
|
226
|
+
|
|
227
|
+
### Long-table of LoopSage arguments
|
|
228
|
+
|
|
229
|
+
| Argument Name | Description | Type | Default Value |
|
|
230
|
+
|------------------------|-----------------------------------------------------------------------------------------------------------------|------------|---------------------|
|
|
231
|
+
| PLATFORM | Name of the platform. Available choices: CPU, CUDA, OpenCL | str | CPU |
|
|
232
|
+
| DEVICE | Device index for CUDA or OpenCL (count from 0) | str | None |
|
|
233
|
+
| N_BEADS | Number of Simulation Beads. | int | None |
|
|
234
|
+
| BEDPE_PATH | A .bedpe file path with loops. It is required. | str | None |
|
|
235
|
+
| OUT_PATH | Output folder name. | str | ../results |
|
|
236
|
+
| REGION_START | Starting region coordinate. | int | None |
|
|
237
|
+
| REGION_END | Ending region coordinate. | int | None |
|
|
238
|
+
| CHROM | Chromosome that corresponds to the modeling region of interest. | str | None |
|
|
239
|
+
| LEF_RW | True if cohesins slide as a random walk instead of one direction. | bool | True |
|
|
240
|
+
| LEF_DRIFT | True if LEFs are pushed back when they encounter other LEFs. | bool | False |
|
|
241
|
+
| N_STEPS | Number of Monte Carlo steps. | int | 40000 |
|
|
242
|
+
| N_LEF | Number of loop extrusion factors. | int | None |
|
|
243
|
+
| N_LEF2 | Number of second family loop extrusion factors. | int | 0 |
|
|
244
|
+
| MC_STEP | Monte Carlo frequency to avoid autocorrelated ensembles. | int | 200 |
|
|
245
|
+
| BURNIN | Burn-in period (steps before equilibrium). | int | 1000 |
|
|
246
|
+
| T_INIT | Initial Temperature of the Stochastic Model. | float | 2.0 |
|
|
247
|
+
| T_FINAL | Final Temperature of the Stochastic Model. | float | 1.0 |
|
|
248
|
+
| METHOD | Stochastic modeling method (Metropolis or Simulated Annealing). | str | 'Annealing' |
|
|
249
|
+
| FOLDING_COEFF | Folding coefficient. | float | 1.0 |
|
|
250
|
+
| FOLDING_COEFF2 | Folding coefficient for the second family of LEFs. | float | 0.0 |
|
|
251
|
+
| CROSS_COEFF | LEF crossing coefficient. | float | 1.0 |
|
|
252
|
+
| CROSS_LOOP | True if the penalty is applied when mi<mj<ni<nj. False if it applies only when mj=ni. When false it is better to enable LEF_DRIFT as well. | bool |True |
|
|
253
|
+
| BIND_COEFF | CTCF binding coefficient. | float | 1.0 |
|
|
254
|
+
| SAVE_PLOTS | True to save diagnostic plots. | bool | True |
|
|
255
|
+
| SAVE_MDT | True to save metadata of the stochastic simulation. | bool | True |
|
|
256
|
+
| INITIAL_STRUCTURE_TYPE | Choose from: rw, confined_rw, self_avoiding_rw, helix, circle, spiral, sphere. | str | rw |
|
|
257
|
+
| SIMULATION_TYPE | Either EM (energy minimizations) or MD (molecular dynamics). | str | None |
|
|
258
|
+
| INTEGRATOR_STEP | Step of the integrator. | Quantity | 100 femtosecond |
|
|
259
|
+
| FORCEFIELD_PATH | Path to XML file with forcefield. | str | default_xml_path |
|
|
260
|
+
| ANGLE_FF_STRENGTH | Angle force strength. | float | 200.0 |
|
|
261
|
+
| LE_FF_LENGTH | Equilibrium distance of loop forces. | float | 0.1 |
|
|
262
|
+
| LE_FF_STRENGTH | Interaction Strength of loop forces. | float | 50000.0 |
|
|
263
|
+
| EV_P | Probability that excluded volume is disabled. Enable it only in case of topoisomerase activity simulation. | float | 0.0 |
|
|
264
|
+
| EV_FF_STRENGTH | Excluded-volume strength. | float | 100.0 |
|
|
265
|
+
| EV_FF_POWER | Excluded-volume power. | float | 3.0 |
|
|
266
|
+
| FRICTION | Friction coefficient of the Langevin integrator. | float | 0.1 |
|
|
267
|
+
| TOLERANCE | Stopping condition for energy minimization. | float | 0.001 |
|
|
268
|
+
| VIZ_HEATS | True to visualize the output average heatmap. | bool | True |
|
|
269
|
+
| SIM_TEMP | Temperature of the 3D simulation (EM or MD). | Quantity | 310 kelvin |
|
|
270
|
+
| SIM_STEP | Amount of simulation steps for loop force adjustments. | int | 1000 |
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
## Citation
|
|
274
|
+
Please cite the method and biological paper in case that you would like to use this model for your work,
|
|
275
|
+
|
|
276
|
+
* Korsak, Sevastianos, and Dariusz Plewczynski. "LoopSage: An energy-based Monte Carlo approach for the loop extrusion modelling of chromatin." Methods (2024).
|
|
277
|
+
* Jodkowska, K., Parteka-Tojek, Z., Agarwal, A., Denkiewicz, M., Korsak, S., Chiliński, M., Banecki, K., & Plewczynski, D. (2024). Improved cohesin HiChIP protocol and bioinformatic analysis for robust detection of chromatin loops and stripes. In bioRxiv (p. 2024.05.16.594268). https://doi.org/10.1101/2024.05.16.594268
|
|
@@ -145,6 +145,7 @@ args = ListOfArgs([
|
|
|
145
145
|
|
|
146
146
|
# Stochastic Simulation parameters
|
|
147
147
|
Arg('LEF_RW', help="True in case that you would like to make cohesins slide as random walk, instead of sliding only in one direction.", type=bool, default='True', val='True'),
|
|
148
|
+
Arg('LEF_DRIFT', help="True in case that LEFs are pushed back when they encounter other LEFs.", type=bool, default='False', val='False'),
|
|
148
149
|
Arg('N_STEPS', help="Number of Monte Carlo steps.", type=int, default='40000', val='40000'),
|
|
149
150
|
Arg('N_LEF', help="Number of loop extrusion factors (condensins and cohesins). If you leave it empty it would add for LEFs twice the number of CTCFs.", type=int, default='', val=''),
|
|
150
151
|
Arg('N_LEF2', help="Number of second family loop extrusion factors, in case that you would like to simulate a second group with different speed.", type=int, default='0', val='0'),
|
|
@@ -156,6 +157,7 @@ args = ListOfArgs([
|
|
|
156
157
|
Arg('FOLDING_COEFF', help="Folding coefficient.", type=float, default='1.0', val='1.0'),
|
|
157
158
|
Arg('FOLDING_COEFF2', help="Folding coefficient for the second family of LEFs.", type=float, default='0.0', val='0.0'),
|
|
158
159
|
Arg('CROSS_COEFF', help="LEF crossing coefficient.", type=float, default='1.0', val='1.0'),
|
|
160
|
+
Arg('CROSS_LOOP', help="It true if the penalty is applied for situations mi<mj<ni<nj and mi=nj, and false if it is applied only for mi=nj.", type=bool, default='True', val='True'),
|
|
159
161
|
Arg('BIND_COEFF', help="CTCF binding coefficient.", type=float, default='1.0', val='1.0'),
|
|
160
162
|
Arg('SAVE_PLOTS', help="It should be true in case that you would like to save diagnostic plots. In case that you use small MC_STEP or large N_STEPS is better to mark it as False.", type=bool, default='True', val='True'),
|
|
161
163
|
Arg('SAVE_MDT', help="In case that you would liketo save metadata of the stochastic simulation.", type=bool, default='True', val='True'),
|
|
@@ -168,7 +170,8 @@ args = ListOfArgs([
|
|
|
168
170
|
Arg('ANGLE_FF_STRENGTH', help="Angle force strength.", type=float, default='200.0', val='200.0'),
|
|
169
171
|
Arg('LE_FF_LENGTH', help="Equillibrium distance of loop forces.", type=float, default='0.1', val='0.1'),
|
|
170
172
|
Arg('LE_FF_STRENGTH', help="Interaction Strength of loop forces.", type=float, default='50000.0', val='50000.0'),
|
|
171
|
-
Arg('
|
|
173
|
+
Arg('EV_P', help="Probability that randomly excluded volume may be disabled.", type=float, default='0.0', val='0.0'),
|
|
174
|
+
Arg('EV_FF_STRENGTH', help="Excluded-volume strength.", type=float, default='100.0', val='100.0'),
|
|
172
175
|
Arg('EV_FF_POWER', help="Excluded-volume power.", type=float, default='3.0', val='3.0'),
|
|
173
176
|
Arg('FRICTION',help='Friction coefficient of the Langevin integrator.',type=float, default='0.1', val='0.1'),
|
|
174
177
|
Arg('TOLERANCE', help="Tolerance that works as stopping condition for energy minimization.", type=float, default='0.001', val='0.001'),
|
|
@@ -12,20 +12,11 @@ from sys import stdout
|
|
|
12
12
|
from mdtraj.reporters import HDF5Reporter
|
|
13
13
|
from scipy import ndimage
|
|
14
14
|
from openmm.app import PDBFile, PDBxFile, ForceField, Simulation, PDBReporter, PDBxReporter, DCDReporter, StateDataReporter, CharmmPsfFile
|
|
15
|
-
import importlib.resources
|
|
16
15
|
from .utils import *
|
|
17
16
|
from .initial_structures import *
|
|
18
17
|
|
|
19
|
-
# Dynamically set the default path to the XML file in the package
|
|
20
|
-
try:
|
|
21
|
-
with importlib.resources.path('loopsage.forcefields', 'classic_sm_ff.xml') as default_xml_path:
|
|
22
|
-
default_xml_path = str(default_xml_path)
|
|
23
|
-
except FileNotFoundError:
|
|
24
|
-
# If running in a development setup without the resource installed, fallback to a relative path
|
|
25
|
-
default_xml_path = 'loopsage/forcefields/classic_sm_ff.xml'
|
|
26
|
-
|
|
27
18
|
class MD_LE:
|
|
28
|
-
def __init__(self,M,N,N_beads,
|
|
19
|
+
def __init__(self,M,N,N_beads,path=None,platform='CPU',angle_ff_strength=200,le_distance=0.1,le_ff_strength=50000.0,ev_ff_strength=100.0,ev_ff_power=3.0,tolerance=0.001):
|
|
29
20
|
'''
|
|
30
21
|
M, N (np arrays): Position matrix of two legs of cohesin m,n.
|
|
31
22
|
Rows represent loops/cohesins and columns represent time
|
|
@@ -35,8 +26,8 @@ class MD_LE:
|
|
|
35
26
|
'''
|
|
36
27
|
self.M, self.N = M, N
|
|
37
28
|
self.N_coh, self.N_steps = M.shape
|
|
38
|
-
self.N_beads
|
|
39
|
-
self.path = path
|
|
29
|
+
self.N_beads = N_beads
|
|
30
|
+
self.path = path if path!=None else make_folder('../output')
|
|
40
31
|
self.platform = platform
|
|
41
32
|
self.angle_ff_strength = angle_ff_strength
|
|
42
33
|
self.le_distance = le_distance
|
|
@@ -45,15 +36,12 @@ class MD_LE:
|
|
|
45
36
|
self.ev_ff_power = ev_ff_power
|
|
46
37
|
self.tolerance = tolerance
|
|
47
38
|
|
|
48
|
-
def run_pipeline(self,run_MD=True, friction=0.1, integrator_step=
|
|
39
|
+
def run_pipeline(self,run_MD=True, friction=0.1, integrator_step=10 * mm.unit.femtosecond, sim_step=100, ff_path = 'forcefields/classic_sm_ff.xml',temperature=310, p_ev=0, plots=False):
|
|
49
40
|
'''
|
|
50
41
|
This is the basic function that runs the molecular simulation pipeline.
|
|
51
42
|
'''
|
|
52
43
|
# Parameters
|
|
53
|
-
self.
|
|
54
|
-
self.le_distance=0.1
|
|
55
|
-
self.le_ff_strength=300000.0
|
|
56
|
-
self.tolerance=0.001
|
|
44
|
+
self.p_ev = p_ev
|
|
57
45
|
|
|
58
46
|
# Define initial structure
|
|
59
47
|
print('Building initial structure...')
|
|
@@ -91,15 +79,17 @@ class MD_LE:
|
|
|
91
79
|
start = time.time()
|
|
92
80
|
heats = list()
|
|
93
81
|
for i in range(1,self.N_steps):
|
|
82
|
+
# Define probabilities that EV would be disabled
|
|
83
|
+
if p_ev>0: self.ps_ev = np.random.rand(self.N_beads)
|
|
84
|
+
# Change forcefield
|
|
94
85
|
self.change_loop(i)
|
|
86
|
+
self.change_ev()
|
|
95
87
|
self.simulation.step(sim_step)
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
heats.append(get_heatmap(self.state.getPositions(),save=False))
|
|
88
|
+
self.state = self.simulation.context.getState(getPositions=True)
|
|
89
|
+
PDBxFile.writeFile(pdb.topology, self.state.getPositions(), open(self.path+f'/ensemble/MDLE_{i}.cif', 'w'))
|
|
90
|
+
heats.append(get_heatmap(self.state.getPositions(),save=False))
|
|
100
91
|
end = time.time()
|
|
101
92
|
elapsed = end - start
|
|
102
|
-
|
|
103
93
|
print(f'Everything is done! Simulation finished succesfully!\nMD finished in {elapsed/60:.2f} minutes.\n')
|
|
104
94
|
|
|
105
95
|
self.avg_heat = np.average(heats,axis=0)
|
|
@@ -111,6 +101,12 @@ class MD_LE:
|
|
|
111
101
|
self.plot_heat(self.avg_heat,f'/plots/avg_heatmap.svg')
|
|
112
102
|
self.plot_heat(self.std_heat,f'/plots/std_heatmap.svg')
|
|
113
103
|
return self.avg_heat
|
|
104
|
+
|
|
105
|
+
def change_ev(self):
|
|
106
|
+
ev_strength = (self.ps_ev>self.p_ev).astype(int)*np.sqrt(self.ev_ff_strength) if self.p_ev>0 else np.sqrt(self.ev_ff_strength)*np.ones(self.N_beads)
|
|
107
|
+
for n in range(self.N_beads):
|
|
108
|
+
self.ev_force.setParticleParameters(n,[ev_strength[n],0.05])
|
|
109
|
+
self.ev_force.updateParametersInContext(self.simulation.context)
|
|
114
110
|
|
|
115
111
|
def change_loop(self,i):
|
|
116
112
|
force_idx = self.system.getNumForces()-1
|
|
@@ -121,12 +117,12 @@ class MD_LE:
|
|
|
121
117
|
|
|
122
118
|
def add_evforce(self):
|
|
123
119
|
'Leonard-Jones potential for excluded volume'
|
|
124
|
-
self.ev_force = mm.CustomNonbondedForce(f'
|
|
125
|
-
self.ev_force.addGlobalParameter('
|
|
126
|
-
self.ev_force.addGlobalParameter('r_small', defaultValue=0.01)
|
|
120
|
+
self.ev_force = mm.CustomNonbondedForce(f'(epsilon1*epsilon2*(sigma1*sigma2)/(r+r_small))^{self.ev_ff_power}')
|
|
121
|
+
self.ev_force.addGlobalParameter('r_small', defaultValue=0.1)
|
|
127
122
|
self.ev_force.addPerParticleParameter('sigma')
|
|
123
|
+
self.ev_force.addPerParticleParameter('epsilon')
|
|
128
124
|
for i in range(self.N_beads):
|
|
129
|
-
self.ev_force.addParticle([0.05])
|
|
125
|
+
self.ev_force.addParticle([np.sqrt(self.ev_ff_strength),0.05])
|
|
130
126
|
self.system.addForce(self.ev_force)
|
|
131
127
|
|
|
132
128
|
def add_bonds(self):
|
|
@@ -173,7 +169,7 @@ class MD_LE:
|
|
|
173
169
|
|
|
174
170
|
def main():
|
|
175
171
|
# A potential example
|
|
176
|
-
M = np.load('/home/skorsak/
|
|
177
|
-
N = np.load('/home/skorsak/
|
|
178
|
-
md = MD_LE(
|
|
179
|
-
md.run_pipeline()
|
|
172
|
+
M = np.load('/home/skorsak/Projects/mine/RepliSage/output/other/Ms.npy')
|
|
173
|
+
N = np.load('/home/skorsak/Projects/mine/RepliSage/output/other/Ns.npy')
|
|
174
|
+
md = MD_LE(M,N,np.max(N)+1,platform='CUDA')
|
|
175
|
+
md.run_pipeline()
|
|
@@ -70,11 +70,11 @@ def main():
|
|
|
70
70
|
|
|
71
71
|
# Run Simulation
|
|
72
72
|
sim = StochasticSimulation(region,chrom,bedpe_file,out_dir=output_name,N_beads=N_beads,N_lef=N_lef,N_lef2=N_lef2)
|
|
73
|
-
Es, Ms, Ns, Bs, Ks, Fs, ufs = sim.run_energy_minimization(N_steps,MC_step,burnin,T,T_min,mode=mode,viz=args.SAVE_PLOTS,save=args.SAVE_MDT,lef_rw=args.LEF_RW,f=f,f2=f2,b=b,kappa=kappa)
|
|
73
|
+
Es, Ms, Ns, Bs, Ks, Fs, ufs = sim.run_energy_minimization(N_steps,MC_step,burnin,T,T_min,mode=mode,viz=args.SAVE_PLOTS,save=args.SAVE_MDT,lef_rw=args.LEF_RW,f=f,f2=f2,b=b,kappa=kappa,lef_drift=args.LEF_DRIFT,cross_loop=args.CROSS_LOOP)
|
|
74
74
|
if args.SIMULATION_TYPE=='EM':
|
|
75
75
|
sim.run_EM(args.PLATFORM,args.ANGLE_FF_STRENGTH,args.LE_FF_LENGTH,args.LE_FF_STRENGTH,args.EV_FF_STRENGTH,args.EV_FF_POWER,args.TOLERANCE,args.FRICTION,args.INTEGRATOR_STEP,args.SIM_TEMP,args.VIZ_HEATS,args.FORCEFIELD_PATH)
|
|
76
76
|
elif args.SIMULATION_TYPE=='MD':
|
|
77
|
-
sim.run_MD(args.PLATFORM,args.ANGLE_FF_STRENGTH,args.LE_FF_LENGTH,args.LE_FF_STRENGTH,args.EV_FF_STRENGTH,args.EV_FF_POWER,args.TOLERANCE,args.FRICTION,args.INTEGRATOR_STEP,args.SIM_TEMP,args.SIM_STEP,args.VIZ_HEATS,args.FORCEFIELD_PATH)
|
|
77
|
+
sim.run_MD(args.PLATFORM,args.ANGLE_FF_STRENGTH,args.LE_FF_LENGTH,args.LE_FF_STRENGTH,args.EV_FF_STRENGTH,args.EV_FF_POWER,args.TOLERANCE,args.FRICTION,args.INTEGRATOR_STEP,args.SIM_TEMP,args.SIM_STEP,args.VIZ_HEATS,args.FORCEFIELD_PATH,args.EV_P)
|
|
78
78
|
elif args.SIMULATION_TYPE==None:
|
|
79
79
|
print('\n3D simulation did not run because it was not specified. Please specify argument SIMULATION_TYPE as EM or MD.')
|
|
80
80
|
else:
|
|
@@ -5,6 +5,7 @@ import random as rd
|
|
|
5
5
|
import scipy.stats as stats
|
|
6
6
|
from numba import njit, prange
|
|
7
7
|
from tqdm import tqdm
|
|
8
|
+
import importlib.resources
|
|
8
9
|
|
|
9
10
|
# scipy
|
|
10
11
|
from scipy.stats import norm
|
|
@@ -16,14 +17,23 @@ from .plots import *
|
|
|
16
17
|
from .md import *
|
|
17
18
|
from .em import *
|
|
18
19
|
|
|
20
|
+
# Dynamically set the default path to the XML file in the package
|
|
21
|
+
try:
|
|
22
|
+
with importlib.resources.path('loopsage.forcefields', 'classic_sm_ff.xml') as default_xml_path:
|
|
23
|
+
default_xml_path = str(default_xml_path)
|
|
24
|
+
except FileNotFoundError:
|
|
25
|
+
# If running in a development setup without the resource installed, fallback to a relative path
|
|
26
|
+
default_xml_path = 'loopsage/forcefields/classic_sm_ff.xml'
|
|
27
|
+
|
|
19
28
|
@njit
|
|
20
|
-
def Kappa(mi,ni,mj,nj):
|
|
29
|
+
def Kappa(mi,ni,mj,nj,cross_loop=True):
|
|
21
30
|
'''
|
|
22
31
|
Computes the crossing function of LoopSage.
|
|
23
32
|
'''
|
|
24
33
|
k=0.0
|
|
25
|
-
if
|
|
26
|
-
|
|
34
|
+
if cross_loop:
|
|
35
|
+
if mi<mj and mj<ni and ni<nj: k+=1 # np.abs(ni-mj)+1
|
|
36
|
+
if mj<mi and mi<nj and nj<ni: k+=1 # np.abs(nj-mi)+1
|
|
27
37
|
if mj==ni or mi==nj or ni==nj or mi==mj: k+=1
|
|
28
38
|
return k
|
|
29
39
|
|
|
@@ -37,14 +47,14 @@ def E_bind(L, R, ms, ns, bind_norm):
|
|
|
37
47
|
return E_b
|
|
38
48
|
|
|
39
49
|
@njit
|
|
40
|
-
def E_cross(ms, ns, k_norm):
|
|
50
|
+
def E_cross(ms, ns, k_norm, cross_loop):
|
|
41
51
|
'''
|
|
42
52
|
The crossing energy.
|
|
43
53
|
'''
|
|
44
54
|
crossing = 0.0
|
|
45
55
|
for i in prange(len(ms)):
|
|
46
56
|
for j in range(i + 1, len(ms)):
|
|
47
|
-
crossing += Kappa(ms[i], ns[i], ms[j], ns[j])
|
|
57
|
+
crossing += Kappa(ms[i], ns[i], ms[j], ns[j], cross_loop)
|
|
48
58
|
return k_norm * crossing
|
|
49
59
|
|
|
50
60
|
@njit
|
|
@@ -56,12 +66,12 @@ def E_fold(ms, ns, fold_norm):
|
|
|
56
66
|
return fold_norm * folding
|
|
57
67
|
|
|
58
68
|
@njit
|
|
59
|
-
def get_E(L, R, bind_norm, fold_norm, fold_norm2, k_norm, ms, ns, N_lef, N_lef2):
|
|
69
|
+
def get_E(L, R, bind_norm, fold_norm, fold_norm2, k_norm, ms, ns, N_lef, N_lef2, cross_loop):
|
|
60
70
|
''''
|
|
61
71
|
The total energy.
|
|
62
72
|
'''
|
|
63
|
-
energy = E_bind(L, R, ms, ns, bind_norm) + E_cross(ms, ns, k_norm) + E_fold(ms, ns, fold_norm)
|
|
64
|
-
if fold_norm2!=0: energy += E_fold(ms[N_lef:N_lef+N_lef2],ns[N_lef:N_lef+N_lef2],fold_norm2)
|
|
73
|
+
energy = E_bind(L, R, ms, ns, bind_norm) + E_cross(ms, ns, k_norm, cross_loop) + E_fold(ms, ns, fold_norm)
|
|
74
|
+
if fold_norm2!=0: energy += E_fold(ms[N_lef:N_lef+N_lef2],ns[N_lef:N_lef+N_lef2], fold_norm2)
|
|
65
75
|
return energy
|
|
66
76
|
|
|
67
77
|
@njit
|
|
@@ -79,19 +89,19 @@ def get_dE_fold(fold_norm,ms,ns,m_new,n_new,idx):
|
|
|
79
89
|
return fold_norm*(np.log(n_new-m_new)-np.log(ns[idx]-ms[idx]))
|
|
80
90
|
|
|
81
91
|
@njit
|
|
82
|
-
def get_dE_cross(ms, ns, m_new, n_new, idx, k_norm):
|
|
92
|
+
def get_dE_cross(ms, ns, m_new, n_new, idx, k_norm, cross_loop):
|
|
83
93
|
'''
|
|
84
94
|
Energy difference for crossing energy.
|
|
85
95
|
'''
|
|
86
96
|
K1, K2 = 0, 0
|
|
87
97
|
for i in prange(len(ms)):
|
|
88
98
|
if i != idx:
|
|
89
|
-
K1 += Kappa(ms[idx], ns[idx], ms[i], ns[i])
|
|
90
|
-
K2 += Kappa(m_new, n_new, ms[i], ns[i])
|
|
99
|
+
K1 += Kappa(ms[idx], ns[idx], ms[i], ns[i], cross_loop)
|
|
100
|
+
K2 += Kappa(m_new, n_new, ms[i], ns[i], cross_loop)
|
|
91
101
|
return k_norm * (K2 - K1)
|
|
92
102
|
|
|
93
103
|
@njit
|
|
94
|
-
def get_dE(L, R, bind_norm, fold_norm, fold_norm2, k_norm, ms, ns, m_new, n_new, idx, N_lef, N_lef2):
|
|
104
|
+
def get_dE(L, R, bind_norm, fold_norm, fold_norm2, k_norm, ms, ns, m_new, n_new, idx, N_lef, N_lef2, cross_loop):
|
|
95
105
|
'''
|
|
96
106
|
Total energy difference.
|
|
97
107
|
'''
|
|
@@ -99,9 +109,9 @@ def get_dE(L, R, bind_norm, fold_norm, fold_norm2, k_norm, ms, ns, m_new, n_new,
|
|
|
99
109
|
if idx<N_lef:
|
|
100
110
|
dE += get_dE_fold(fold_norm,ms[:N_lef],ns[:N_lef],m_new,n_new,idx)
|
|
101
111
|
else:
|
|
102
|
-
dE += get_dE_fold(fold_norm2,ms[N_lef:N_lef+N_lef2],ns[N_lef:N_lef2],m_new,n_new,idx-N_lef)
|
|
112
|
+
dE += get_dE_fold(fold_norm2,ms[N_lef:N_lef+N_lef2],ns[N_lef:N_lef+N_lef2],m_new,n_new,idx-N_lef)
|
|
103
113
|
dE += get_dE_bind(L, R, bind_norm, ms, ns, m_new, n_new, idx)
|
|
104
|
-
dE += get_dE_cross(ms, ns, m_new, n_new, idx, k_norm)
|
|
114
|
+
dE += get_dE_cross(ms, ns, m_new, n_new, idx, k_norm, cross_loop)
|
|
105
115
|
return dE
|
|
106
116
|
|
|
107
117
|
@njit
|
|
@@ -114,7 +124,7 @@ def unbind_bind(N_beads):
|
|
|
114
124
|
return int(m_new), int(n_new)
|
|
115
125
|
|
|
116
126
|
@njit
|
|
117
|
-
def slide(m_old, n_old, N_beads, rw=True):
|
|
127
|
+
def slide(m_old, n_old, ms, ns, N_beads, rw=True, drift=True):
|
|
118
128
|
'''
|
|
119
129
|
Sliding Monte-Carlo step.
|
|
120
130
|
'''
|
|
@@ -122,7 +132,11 @@ def slide(m_old, n_old, N_beads, rw=True):
|
|
|
122
132
|
r1 = np.random.choice(choices) if rw else -1
|
|
123
133
|
r2 = np.random.choice(choices) if rw else 1
|
|
124
134
|
m_new = m_old + r1 if m_old + r1>=0 else 0
|
|
135
|
+
if np.any(ns==m_new) and drift and m_old-r1<n_old-1:
|
|
136
|
+
m_new = m_old - r1 if m_old + r1>=0 else 0
|
|
125
137
|
n_new = n_old + r2 if n_old + r2<N_beads else N_beads-1
|
|
138
|
+
if np.any(ms==n_new) and drift and n_old-r2>m_old+1:
|
|
139
|
+
n_new = n_old - r2 if n_old + r2>=0 else 0
|
|
126
140
|
return int(m_new), int(n_new)
|
|
127
141
|
|
|
128
142
|
@njit
|
|
@@ -148,14 +162,14 @@ def initialize(N_beads,N_lef):
|
|
|
148
162
|
return ms, ns
|
|
149
163
|
|
|
150
164
|
@njit
|
|
151
|
-
def run_simulation(N_beads,N_steps,MC_step,burnin,T,T_min,fold_norm,fold_norm2,bind_norm,k_norm,N_lef,N_lef2,L,R,mode,lef_rw=True):
|
|
165
|
+
def run_simulation(N_beads,N_steps,MC_step,burnin,T,T_min,fold_norm,fold_norm2,bind_norm,k_norm,N_lef,N_lef2,L,R,mode,lef_rw=True,lef_drift=True,cross_loop=True):
|
|
152
166
|
'''
|
|
153
167
|
Runs the Monte Carlo simulation.
|
|
154
168
|
'''
|
|
155
169
|
Ti = T
|
|
156
170
|
bi = burnin//MC_step
|
|
157
171
|
ms, ns = initialize(N_beads,N_lef+N_lef2)
|
|
158
|
-
E = get_E(L, R, bind_norm, fold_norm, fold_norm2, k_norm, ms, ns, N_lef, N_lef2)
|
|
172
|
+
E = get_E(L, R, bind_norm, fold_norm, fold_norm2, k_norm, ms, ns, N_lef, N_lef2, cross_loop)
|
|
159
173
|
Es,Ks,Fs,Bs,ufs = np.zeros(N_steps//MC_step, dtype=np.float64),np.zeros(N_steps//MC_step, dtype=np.float64),np.zeros(N_steps//MC_step, dtype=np.float64),np.zeros(N_steps//MC_step, dtype=np.float64),np.zeros(N_steps//MC_step, dtype=np.float64)
|
|
160
174
|
Ms, Ns = np.zeros((N_lef+N_lef2,N_steps//MC_step), dtype=np.int64), np.zeros((N_lef+N_lef2,N_steps//MC_step), dtype=np.int64)
|
|
161
175
|
|
|
@@ -167,10 +181,10 @@ def run_simulation(N_beads,N_steps,MC_step,burnin,T,T_min,fold_norm,fold_norm2,b
|
|
|
167
181
|
if r==0:
|
|
168
182
|
m_new, n_new = unbind_bind(N_beads)
|
|
169
183
|
else:
|
|
170
|
-
m_new, n_new = slide(ms[j],ns[j],N_beads,lef_rw)
|
|
184
|
+
m_new, n_new = slide(ms[j],ns[j],ms,ns,N_beads,lef_rw,lef_drift)
|
|
171
185
|
|
|
172
186
|
# Compute energy difference
|
|
173
|
-
dE = get_dE(L, R, bind_norm, fold_norm, fold_norm2, k_norm, ms, ns, m_new, n_new, j, N_lef, N_lef2)
|
|
187
|
+
dE = get_dE(L, R, bind_norm, fold_norm, fold_norm2, k_norm, ms, ns, m_new, n_new, j, N_lef, N_lef2, cross_loop)
|
|
174
188
|
|
|
175
189
|
if dE <= 0 or np.exp(-dE/Ti) > np.random.rand():
|
|
176
190
|
ms[j], ns[j] = m_new, n_new
|
|
@@ -183,7 +197,7 @@ def run_simulation(N_beads,N_steps,MC_step,burnin,T,T_min,fold_norm,fold_norm2,b
|
|
|
183
197
|
if i%MC_step==0:
|
|
184
198
|
ufs[i//MC_step] = unfolding_metric(ms,ns,N_beads)
|
|
185
199
|
Es[i//MC_step] = E
|
|
186
|
-
Ks[i//MC_step] = E_cross(ms,ns,k_norm)
|
|
200
|
+
Ks[i//MC_step] = E_cross(ms,ns,k_norm,cross_loop)
|
|
187
201
|
Fs[i//MC_step] = E_fold(ms,ns,fold_norm)
|
|
188
202
|
Bs[i//MC_step] = E_bind(L,R,ms,ns,bind_norm)
|
|
189
203
|
return Ms, Ns, Es, Ks, Fs, Bs, ufs
|
|
@@ -213,7 +227,7 @@ class StochasticSimulation:
|
|
|
213
227
|
print('Number of LEFs:',self.N_lef+self.N_lef2)
|
|
214
228
|
self.path = make_folder(out_dir)
|
|
215
229
|
|
|
216
|
-
def run_energy_minimization(self,N_steps,MC_step,burnin,T=1,T_min=0,mode='Metropolis',viz=False,save=False, f=1.0, f2=0.0, b=1.0, kappa=1.0, lef_rw=True):
|
|
230
|
+
def run_energy_minimization(self,N_steps,MC_step,burnin,T=1,T_min=0,mode='Metropolis',viz=False,save=False, f=1.0, f2=0.0, b=1.0, kappa=1.0, lef_rw=True, lef_drift=True, cross_loop=True):
|
|
217
231
|
'''
|
|
218
232
|
Implementation of the stochastic Monte Carlo simulation.
|
|
219
233
|
|
|
@@ -233,7 +247,7 @@ class StochasticSimulation:
|
|
|
233
247
|
print('\nRunning simulation (with parallelization across CPU cores)...')
|
|
234
248
|
start = time.time()
|
|
235
249
|
self.burnin = burnin
|
|
236
|
-
self.Ms, self.Ns, self.Es, self.Ks, self.Fs, self.Bs, self.ufs = run_simulation(self.N_beads,N_steps,MC_step,burnin,T,T_min,fold_norm,fold_norm2,bind_norm,k_norm,self.N_lef,self.N_lef2,self.L,self.R,mode,lef_rw)
|
|
250
|
+
self.Ms, self.Ns, self.Es, self.Ks, self.Fs, self.Bs, self.ufs = run_simulation(self.N_beads,N_steps,MC_step,burnin,T,T_min,fold_norm,fold_norm2,bind_norm,k_norm,self.N_lef,self.N_lef2,self.L,self.R,mode,lef_rw,lef_drift,cross_loop)
|
|
237
251
|
end = time.time()
|
|
238
252
|
elapsed = end - start
|
|
239
253
|
print(f'Computation finished succesfully in {elapsed//3600:.0f} hours, {elapsed%3600//60:.0f} minutes and {elapsed%60:.0f} seconds.')
|
|
@@ -242,13 +256,13 @@ class StochasticSimulation:
|
|
|
242
256
|
if save:
|
|
243
257
|
f = open(self.path+'/other/info.txt', "w")
|
|
244
258
|
f.write(f'Number of beads {self.N_beads}.\n')
|
|
245
|
-
f.write(f'Number of cohesins {self.N_lef}. Number of CTCFs {self.N_CTCF}
|
|
259
|
+
f.write(f'Number of cohesins {self.N_lef}. Number of cohesins in second family {self.N_lef2}. Number of CTCFs {self.N_CTCF}. \n')
|
|
246
260
|
f.write(f'Bedpe file for CTCF binding is {self.bedpe_file}.\n')
|
|
247
261
|
f.write(f'Initial temperature {T}. Minimum temperature {T_min}.\n')
|
|
248
262
|
f.write(f'Monte Carlo optimization method: {mode}.\n')
|
|
249
263
|
f.write(f'Monte Carlo steps {N_steps}. Sampling frequency {MC_step}. Burnin period {burnin}.\n')
|
|
250
264
|
f.write(f'Crossing energy in equilibrium is {np.average(self.Ks[burnin//MC_step:]):.2f}. Crossing coefficient kappa={kappa}.\n')
|
|
251
|
-
f.write(f'Folding energy in equilibrium is {np.average(self.Fs[burnin//MC_step:]):.2f}. Folding coefficient f={f}
|
|
265
|
+
f.write(f'Folding energy in equilibrium is {np.average(self.Fs[burnin//MC_step:]):.2f}. Folding coefficient f={f}. Folding coefficient for the second family f2={f2}\n')
|
|
252
266
|
f.write(f'Binding energy in equilibrium is {np.average(self.Bs[burnin//MC_step:]):.2f}. Binding coefficient b={b}.\n')
|
|
253
267
|
f.write(f'Energy at equillibrium: {np.average(self.Es[burnin//MC_step:]):.2f}.\n')
|
|
254
268
|
f.close()
|
|
@@ -274,14 +288,14 @@ class StochasticSimulation:
|
|
|
274
288
|
self.N_CTCF = np.max([np.count_nonzero(self.L),np.count_nonzero(self.R)])
|
|
275
289
|
print('Number of CTCF:',self.N_CTCF)
|
|
276
290
|
|
|
277
|
-
def run_EM(self,platform='CPU',angle_ff_strength=200,le_distance=0.0,le_ff_strength=300000.0,ev_ff_strength=10.0,ev_ff_power=3.0,tolerance=0.001,friction=0.1,integrator_step=100*mm.unit.femtosecond,temperature=310,save_plots=True,ff_path=
|
|
291
|
+
def run_EM(self,platform='CPU',angle_ff_strength=200,le_distance=0.0,le_ff_strength=300000.0,ev_ff_strength=10.0,ev_ff_power=3.0,tolerance=0.001,friction=0.1,integrator_step=100*mm.unit.femtosecond,temperature=310,save_plots=True,ff_path=default_xml_path):
|
|
278
292
|
em = EM_LE(self.Ms,self.Ns,self.N_beads,self.burnin,self.MC_step,self.path,platform,angle_ff_strength,le_distance,le_ff_strength,ev_ff_strength,ev_ff_power,tolerance)
|
|
279
293
|
sim_heat = em.run_pipeline(plots=save_plots,friction=friction,integrator_step=integrator_step,temperature=temperature,ff_path=ff_path)
|
|
280
294
|
corr_exp_heat(sim_heat,self.bedpe_file,self.region,self.chrom,self.N_beads,self.path)
|
|
281
295
|
|
|
282
|
-
def run_MD(self,platform='CPU',angle_ff_strength=200,le_distance=0.0,le_ff_strength=300000.0,ev_ff_strength=10.0,ev_ff_power=3.0,tolerance=0.001,friction=0.1,integrator_step=100*mm.unit.femtosecond,temperature=310,sim_step=1000,save_plots=True,ff_path=
|
|
283
|
-
md = MD_LE(self.Ms,self.Ns,self.N_beads,self.
|
|
284
|
-
sim_heat = md.run_pipeline(plots=save_plots,sim_step=sim_step,friction=friction,integrator_step=integrator_step,temperature=temperature,ff_path=ff_path)
|
|
296
|
+
def run_MD(self,platform='CPU',angle_ff_strength=200,le_distance=0.0,le_ff_strength=300000.0,ev_ff_strength=10.0,ev_ff_power=3.0,tolerance=0.001,friction=0.1,integrator_step=100*mm.unit.femtosecond,temperature=310,sim_step=1000,save_plots=True,ff_path=default_xml_path,p_ev=0):
|
|
297
|
+
md = MD_LE(self.Ms,self.Ns,self.N_beads,self.path,platform,angle_ff_strength,le_distance,le_ff_strength,ev_ff_strength,ev_ff_power,tolerance)
|
|
298
|
+
sim_heat = md.run_pipeline(plots=save_plots,sim_step=sim_step,friction=friction,integrator_step=integrator_step,temperature=temperature,ff_path=ff_path,p_ev=p_ev)
|
|
285
299
|
corr_exp_heat(sim_heat,self.bedpe_file,self.region,self.chrom,self.N_beads,self.path)
|
|
286
300
|
|
|
287
301
|
def main():
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: pyLoopSage
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.18
|
|
4
4
|
Summary: An energy-based stochastic model of loop extrusion in chromatin.
|
|
5
5
|
Home-page: https://github.com/SFGLab/pyLoopSage
|
|
6
6
|
Author: Sebastian Korsak
|
|
@@ -31,6 +31,16 @@ Requires-Dist: statsmodels
|
|
|
31
31
|
Requires-Dist: imageio
|
|
32
32
|
Requires-Dist: imageio[ffmpeg]
|
|
33
33
|
Requires-Dist: pillow
|
|
34
|
+
Dynamic: author
|
|
35
|
+
Dynamic: author-email
|
|
36
|
+
Dynamic: classifier
|
|
37
|
+
Dynamic: description
|
|
38
|
+
Dynamic: description-content-type
|
|
39
|
+
Dynamic: home-page
|
|
40
|
+
Dynamic: license
|
|
41
|
+
Dynamic: requires-dist
|
|
42
|
+
Dynamic: requires-python
|
|
43
|
+
Dynamic: summary
|
|
34
44
|
|
|
35
45
|
# pyLoopSage
|
|
36
46
|
Updated version of the stochastic loop extrusion model: LoopSage with capability to run incredibly fast, parallelized across CPU cores. This package is even more user-friendly and it can be installed via PyPI.
|
|
@@ -44,11 +54,6 @@ Updated version of the stochastic loop extrusion model: LoopSage with capability
|
|
|
44
54
|
- Visualization functions.
|
|
45
55
|
- Capability to run form terminal with a simple command `loopsage -c config.ini`.
|
|
46
56
|
|
|
47
|
-
## Publication
|
|
48
|
-
Please cite the method paper in case that you would like to use this model for your work,
|
|
49
|
-
|
|
50
|
-
* Korsak, Sevastianos, and Dariusz Plewczynski. "LoopSage: An energy-based Monte Carlo approach for the loop extrusion modelling of chromatin." Methods (2024).
|
|
51
|
-
|
|
52
57
|
## The model
|
|
53
58
|
|
|
54
59
|
### Stochastic Simulation
|
|
@@ -74,7 +79,7 @@ These $L(\cdot), R(\cdot)$ functions are two functions that define the binding p
|
|
|
74
79
|
|
|
75
80
|
$$c_{\text{fold}}=-\dfrac{N_{\text{beads}}f}{N_{\text{lef}}\log(N_{\text{beads}}/N_{\text{lef}})},\quad c_{\text{bind}}=-\dfrac{N_{\text{beads}}b}{\sum_i \left(L(m_i)+R(n_i)\right)},\quad c_{\text{cross}}=\kappa \times 10^4.$$
|
|
76
81
|
|
|
77
|
-
The parameters are defined in such a way that when $f=b=\kappa=1$, the three terms of the stochastic energy are balanced.
|
|
82
|
+
The parameters are defined in such a way that when $f=b=\kappa=1$, the three terms of the stochastic energy are balanced. To clarrify, this parametrization is slightly different than this of the original paper. We multiply with $N_{\text{beads}}$, so as to keep the input parameters $f,b,\kappa$ simpler close to 1. Therefore, a value $f=0.1$ leads to unfolded structures, and a value $f=2$ it leads to very fast propagating long loops.
|
|
78
83
|
|
|
79
84
|
And the energy difference can be expressed as the energy difference of each term,
|
|
80
85
|
|
|
@@ -113,7 +118,7 @@ For the implementation of this model in python, we used OpenMM and CUDA accelera
|
|
|
113
118
|
In general the user can run simulation in two different ways:
|
|
114
119
|
|
|
115
120
|
1. **Energy minimization (EM)**: It means that for each sample of cohesin positions $C_{t_i}=(m_j(t_i),n_j(t_i))$ start from a different initial structure (usually 3D random walk) and we apply the forcefield. For each structure we start from a different initial condition. In general, it is suggested to run the model in this way because it is faster, less prone to errors and the structures are not correlated to each other.
|
|
116
|
-
2. **Molecular Dynamics (MD)**: In this case we have only one initial structure, we minimize the energy according to the forcefield only once and then we run a molecular dynamics simulation over time. This creates a continuous trajectory of structures, and it is cool for visualization pruposes.
|
|
121
|
+
2. **Molecular Dynamics (MD)**: In this case we have only one initial structure, we minimize the energy according to the forcefield only once and then we run a molecular dynamics simulation over time. This creates a continuous trajectory of structures, and it is cool for visualization pruposes. It is also biophysically more correct, in the sense that loop extrusion should be time-dependent, and the structure at time $t_i$ has to me correlated with structures at time $t_{i\pm1}$. It is a little bit more prone to error, and you may need to change the simulation frequence and step in case of instability (smaller frequency and more steps to stabilize it).
|
|
117
122
|
|
|
118
123
|
## Installation
|
|
119
124
|
|
|
@@ -262,3 +267,55 @@ In the output folder there are another three subfolders:
|
|
|
262
267
|
An example, illustrated with Chimera software, simulated trajectory of structures after running Simulated Annealing and molecular dynamics.
|
|
263
268
|
|
|
264
269
|

|
|
270
|
+
|
|
271
|
+
### Long-table of LoopSage arguments
|
|
272
|
+
|
|
273
|
+
| Argument Name | Description | Type | Default Value |
|
|
274
|
+
|------------------------|-----------------------------------------------------------------------------------------------------------------|------------|---------------------|
|
|
275
|
+
| PLATFORM | Name of the platform. Available choices: CPU, CUDA, OpenCL | str | CPU |
|
|
276
|
+
| DEVICE | Device index for CUDA or OpenCL (count from 0) | str | None |
|
|
277
|
+
| N_BEADS | Number of Simulation Beads. | int | None |
|
|
278
|
+
| BEDPE_PATH | A .bedpe file path with loops. It is required. | str | None |
|
|
279
|
+
| OUT_PATH | Output folder name. | str | ../results |
|
|
280
|
+
| REGION_START | Starting region coordinate. | int | None |
|
|
281
|
+
| REGION_END | Ending region coordinate. | int | None |
|
|
282
|
+
| CHROM | Chromosome that corresponds to the modeling region of interest. | str | None |
|
|
283
|
+
| LEF_RW | True if cohesins slide as a random walk instead of one direction. | bool | True |
|
|
284
|
+
| LEF_DRIFT | True if LEFs are pushed back when they encounter other LEFs. | bool | False |
|
|
285
|
+
| N_STEPS | Number of Monte Carlo steps. | int | 40000 |
|
|
286
|
+
| N_LEF | Number of loop extrusion factors. | int | None |
|
|
287
|
+
| N_LEF2 | Number of second family loop extrusion factors. | int | 0 |
|
|
288
|
+
| MC_STEP | Monte Carlo frequency to avoid autocorrelated ensembles. | int | 200 |
|
|
289
|
+
| BURNIN | Burn-in period (steps before equilibrium). | int | 1000 |
|
|
290
|
+
| T_INIT | Initial Temperature of the Stochastic Model. | float | 2.0 |
|
|
291
|
+
| T_FINAL | Final Temperature of the Stochastic Model. | float | 1.0 |
|
|
292
|
+
| METHOD | Stochastic modeling method (Metropolis or Simulated Annealing). | str | 'Annealing' |
|
|
293
|
+
| FOLDING_COEFF | Folding coefficient. | float | 1.0 |
|
|
294
|
+
| FOLDING_COEFF2 | Folding coefficient for the second family of LEFs. | float | 0.0 |
|
|
295
|
+
| CROSS_COEFF | LEF crossing coefficient. | float | 1.0 |
|
|
296
|
+
| CROSS_LOOP | True if the penalty is applied when mi<mj<ni<nj. False if it applies only when mj=ni. When false it is better to enable LEF_DRIFT as well. | bool |True |
|
|
297
|
+
| BIND_COEFF | CTCF binding coefficient. | float | 1.0 |
|
|
298
|
+
| SAVE_PLOTS | True to save diagnostic plots. | bool | True |
|
|
299
|
+
| SAVE_MDT | True to save metadata of the stochastic simulation. | bool | True |
|
|
300
|
+
| INITIAL_STRUCTURE_TYPE | Choose from: rw, confined_rw, self_avoiding_rw, helix, circle, spiral, sphere. | str | rw |
|
|
301
|
+
| SIMULATION_TYPE | Either EM (energy minimizations) or MD (molecular dynamics). | str | None |
|
|
302
|
+
| INTEGRATOR_STEP | Step of the integrator. | Quantity | 100 femtosecond |
|
|
303
|
+
| FORCEFIELD_PATH | Path to XML file with forcefield. | str | default_xml_path |
|
|
304
|
+
| ANGLE_FF_STRENGTH | Angle force strength. | float | 200.0 |
|
|
305
|
+
| LE_FF_LENGTH | Equilibrium distance of loop forces. | float | 0.1 |
|
|
306
|
+
| LE_FF_STRENGTH | Interaction Strength of loop forces. | float | 50000.0 |
|
|
307
|
+
| EV_P | Probability that excluded volume is disabled. Enable it only in case of topoisomerase activity simulation. | float | 0.0 |
|
|
308
|
+
| EV_FF_STRENGTH | Excluded-volume strength. | float | 100.0 |
|
|
309
|
+
| EV_FF_POWER | Excluded-volume power. | float | 3.0 |
|
|
310
|
+
| FRICTION | Friction coefficient of the Langevin integrator. | float | 0.1 |
|
|
311
|
+
| TOLERANCE | Stopping condition for energy minimization. | float | 0.001 |
|
|
312
|
+
| VIZ_HEATS | True to visualize the output average heatmap. | bool | True |
|
|
313
|
+
| SIM_TEMP | Temperature of the 3D simulation (EM or MD). | Quantity | 310 kelvin |
|
|
314
|
+
| SIM_STEP | Amount of simulation steps for loop force adjustments. | int | 1000 |
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
## Citation
|
|
318
|
+
Please cite the method and biological paper in case that you would like to use this model for your work,
|
|
319
|
+
|
|
320
|
+
* Korsak, Sevastianos, and Dariusz Plewczynski. "LoopSage: An energy-based Monte Carlo approach for the loop extrusion modelling of chromatin." Methods (2024).
|
|
321
|
+
* Jodkowska, K., Parteka-Tojek, Z., Agarwal, A., Denkiewicz, M., Korsak, S., Chiliński, M., Banecki, K., & Plewczynski, D. (2024). Improved cohesin HiChIP protocol and bioinformatic analysis for robust detection of chromatin loops and stripes. In bioRxiv (p. 2024.05.16.594268). https://doi.org/10.1101/2024.05.16.594268
|
|
@@ -6,7 +6,7 @@ with open('README.md', 'r', encoding='utf-8') as f:
|
|
|
6
6
|
|
|
7
7
|
setup(
|
|
8
8
|
name='pyLoopSage', # Package name
|
|
9
|
-
version='1.0.
|
|
9
|
+
version='1.0.18', # Version of the software
|
|
10
10
|
description='An energy-based stochastic model of loop extrusion in chromatin.',
|
|
11
11
|
long_description=long_description,
|
|
12
12
|
long_description_content_type='text/markdown',
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|