MultiMM 1.0.1__tar.gz → 1.0.3__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.

Potentially problematic release.


This version of MultiMM might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: MultiMM
3
- Version: 1.0.1
3
+ Version: 1.0.3
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
@@ -25,10 +25,8 @@ Requires-Dist: typing-extensions
25
25
  Requires-Dist: pyBigWig
26
26
  Requires-Dist: hilbertcurve
27
27
  Requires-Dist: tqdm
28
- Provides-Extra: viz
29
- Requires-Dist: pyvista[all]; extra == "viz"
30
- Provides-Extra: simulations
31
- Requires-Dist: OpenMM; extra == "simulations"
28
+ Requires-Dist: pyvista[all]
29
+ Requires-Dist: OpenMM
32
30
 
33
31
  # MultiMM: An OpenMM-based software for whole genome 3D structure reconstruction
34
32
 
@@ -0,0 +1,17 @@
1
+ LICENSE
2
+ README.md
3
+ setup.py
4
+ MultiMM.egg-info/PKG-INFO
5
+ MultiMM.egg-info/SOURCES.txt
6
+ MultiMM.egg-info/dependency_links.txt
7
+ MultiMM.egg-info/entry_points.txt
8
+ MultiMM.egg-info/requires.txt
9
+ MultiMM.egg-info/top_level.txt
10
+ simulation/__init__.py
11
+ simulation/args_definition.py
12
+ simulation/initial_structure_tools.py
13
+ simulation/nucleosome_interpolation.py
14
+ simulation/plots.py
15
+ simulation/run.py
16
+ simulation/utils.py
17
+ simulation/validation.py
@@ -11,9 +11,5 @@ typing-extensions
11
11
  pyBigWig
12
12
  hilbertcurve
13
13
  tqdm
14
-
15
- [simulations]
16
- OpenMM
17
-
18
- [viz]
19
14
  pyvista[all]
15
+ OpenMM
@@ -0,0 +1 @@
1
+ simulation
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: MultiMM
3
- Version: 1.0.1
3
+ Version: 1.0.3
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
@@ -25,10 +25,8 @@ Requires-Dist: typing-extensions
25
25
  Requires-Dist: pyBigWig
26
26
  Requires-Dist: hilbertcurve
27
27
  Requires-Dist: tqdm
28
- Provides-Extra: viz
29
- Requires-Dist: pyvista[all]; extra == "viz"
30
- Provides-Extra: simulations
31
- Requires-Dist: OpenMM; extra == "simulations"
28
+ Requires-Dist: pyvista[all]
29
+ Requires-Dist: OpenMM
32
30
 
33
31
  # MultiMM: An OpenMM-based software for whole genome 3D structure reconstruction
34
32
 
@@ -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.1', # Version of the software
9
+ version='1.0.3', # 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',
@@ -29,11 +29,9 @@ setup(
29
29
  'pyBigWig',
30
30
  'hilbertcurve',
31
31
  'tqdm',
32
+ 'pyvista[all]',
33
+ 'OpenMM',
32
34
  ],
33
- extras_require={ # Optional dependencies
34
- 'viz': ['pyvista[all]'],
35
- 'simulations': ['OpenMM'],
36
- },
37
35
  entry_points={
38
36
  'console_scripts': [
39
37
  'MultiMM=simulation.run:main', # MultiMM command points to run.py's main function
@@ -0,0 +1,4 @@
1
+ # Importing specific functions or classes from submodules
2
+ from .run import main
3
+
4
+ __version__ = "1.0.0"
@@ -0,0 +1,224 @@
1
+ import datetime
2
+ import re
3
+ from dataclasses import dataclass
4
+ from math import pi
5
+ from typing import Union
6
+ import argparse
7
+ import openmm as mm
8
+ from openmm.unit import Quantity
9
+
10
+ @dataclass
11
+ class Arg(object):
12
+ name: str
13
+ help: str
14
+ type: type
15
+ default: Union[str, float, int, bool, Quantity, None]
16
+ val: Union[str, float, int, bool, Quantity, None]
17
+
18
+ # Define custom type to parse list from string
19
+ def parse_list(s):
20
+ try:
21
+ return [int(x.strip()) for x in s.strip('[]').split(',')]
22
+ except ValueError:
23
+ raise argparse.ArgumentTypeError("Invalid list format. Must be a comma-separated list of integers.")
24
+
25
+ class ListOfArgs(list):
26
+ quantity_regexp = re.compile(r'(?P<value>[-+]?\d+(?:\.\d+)?) ?(?P<unit>\w+)')
27
+
28
+ def get_arg(self, name: str) -> Arg:
29
+ """Stupid arg search in list of args"""
30
+ name = name.upper()
31
+ for i in self:
32
+ if i.name == name:
33
+ return i
34
+ raise ValueError(f"No such arg: {name}")
35
+
36
+ def __getattr__(self, item):
37
+ return self.get_arg(item).val
38
+
39
+ def parse_args(self):
40
+ parser = argparse.ArgumentParser()
41
+ for arg in self.arg_list:
42
+ parser.add_argument(arg['name'], help=arg['help'], type=arg.get('type', str), default=arg.get('default', ''), val=arg.get('val', ''))
43
+
44
+ args = parser.parse_args()
45
+ parsed_args = {arg['name']: getattr(args, arg['name']) for arg in self.arg_list}
46
+ return parsed_args
47
+
48
+ def parse_quantity(self, val: str) -> Union[Quantity, None]:
49
+ if val == '':
50
+ return None
51
+ match_obj = self.quantity_regexp.match(val)
52
+ value, unit = match_obj.groups()
53
+ try:
54
+ unit = getattr(mm.unit, unit)
55
+ except AttributeError:
56
+ raise ValueError(f"I Can't recognise unit {unit} in expression {val}. Example of valid quantity: 12.3 femtosecond.")
57
+ return Quantity(value=float(value), unit=unit)
58
+
59
+ def to_python(self):
60
+ """Casts string args to ints, floats, bool..."""
61
+ for i in self:
62
+ if i.val == '':
63
+ i.val = None
64
+ elif i.name == "HR_K_PARAM": # Workaround for complex unit
65
+ i.val = Quantity(float(i.val), mm.unit.kilojoule_per_mole / mm.unit.nanometer ** 2)
66
+ elif i.type == str:
67
+ continue
68
+ elif i.type == int:
69
+ i.val = int(i.val)
70
+ elif i.type == float:
71
+ i.val = float(i.val)
72
+ elif i.type == bool:
73
+ if i.val.lower() in ['true', '1', 'y', 'yes']:
74
+ i.val = True
75
+ elif i.val.lower() in ['false', '0', 'n', 'no']:
76
+ i.val = False
77
+ else:
78
+ raise ValueError(f"Can't convert {i.val} into bool type.")
79
+ elif i.type == Quantity:
80
+ try:
81
+ i.val = self.parse_quantity(i.val)
82
+ except AttributeError:
83
+ raise ValueError(f"Can't parse: {i.name} = {i.val}")
84
+ else:
85
+ raise ValueError(f"Can't parse: {i.name} = {i.val}")
86
+
87
+ def get_complete_config(self) -> str:
88
+ w = "####################\n"
89
+ w += "# MultiMM Model #\n"
90
+ w += "####################\n\n"
91
+ w += "# This is automatically generated config file.\n"
92
+ w += f"# Generated at: {datetime.datetime.now().isoformat()}\n\n"
93
+ w += "# Notes:\n"
94
+ w += "# Some fields require units. Units are represented as objects from mm.units module.\n"
95
+ w += "# Simple units are parsed directly. For example: \n"
96
+ w += "# HR_R0_PARAM = 0.2 nanometer\n"
97
+ w += "# But more complex units does not have any more sophisticated parser written, and will fail.'\n"
98
+ w += "# In such cases the unit is fixed (and noted in comment), so please convert complex units manually if needed.\n"
99
+ w += "# <float> and <int> types does not require any unit. Quantity require unit.\n\n"
100
+ w += "# Default values does not mean valid value. In many places it's only a empty field that need to be filled.\n\n"
101
+
102
+ w += '[Main]'
103
+ for i in self:
104
+ w += f'; {i.help}, type: {i.type.__name__}, default: {i.default}\n'
105
+ if i.val is None:
106
+ w += f'{i.name} = \n\n'
107
+ else:
108
+ if i.type == Quantity:
109
+ # noinspection PyProtectedMember
110
+ w += f'{i.name} = {i.val._value} {i.val.unit.get_name()}\n\n'
111
+ else:
112
+ w += f'{i.name} = {i.val}\n\n'
113
+ w = w[:-2]
114
+ return w
115
+
116
+ def write_config_file(self):
117
+ auto_config_filename = 'config_auto.ini'
118
+ with open(auto_config_filename, 'w') as f:
119
+ f.write(self.get_complete_config())
120
+ print(f"Automatically generated config file saved in {auto_config_filename}")
121
+
122
+
123
+ available_platforms = [mm.Platform.getPlatform(i).getName() for i in range(mm.Platform.getNumPlatforms())]
124
+
125
+ args = ListOfArgs([
126
+ # Platform settings
127
+ Arg('PLATFORM', help=f"name of the platform. Available choices: {' '.join(available_platforms)}", type=str, default='', val=''),
128
+ Arg('DEVICE', help="device index for CUDA or OpenCL (count from 0)", type=str, default='', val=''),
129
+
130
+ # Input data
131
+ Arg('INITIAL_STRUCTURE_PATH', help="Path to CIF file.", type=str, default='', val=''),
132
+ Arg('BUILD_INITIAL_STRUCTURE', help="To build a new initial structure.", type=bool, default='True', val='True'),
133
+ 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=''),
135
+ Arg('N_BEADS', help="Number of Simulation Beads.", type=int, default='50000', val='50000'),
136
+ Arg('COMPARTMENT_PATH', help="It can be either .bed file with subcompartments from Calder or .BigWig signal.", type=str, default='', val=''),
137
+ Arg('LOOPS_PATH', help="A .bedpe file path with loops. It is required.", type=str, default='', val=''),
138
+ Arg('ATACSEQ_PATH', help="A .bw or .BigWig file path with atacseq data. It is not required.", type=str, default='', val=''),
139
+ Arg('OUT_PATH', help="Output folder name.", type=str, default='results', val='results'),
140
+ Arg('LOC_START', help="Starting region coordinate.", type=int, default='', val=''),
141
+ Arg('LOC_END', help="Ending region coordinate.", type=int, default='', val=''),
142
+ Arg('CHROM', help="Chromosome that corresponds the the modelling region of interest (in case that you do not want to model the whole genome).", type=str, default='', val=''),
143
+ Arg('SHUFFLE_CHROMS', help="Shuffle the chromosomes.", type=bool, default='False', val='False'),
144
+ Arg('SHUFFLING_SEED', help="Shuffling random seed.", type=int, default='0', val='0'),
145
+ Arg('SAVE_PLOTS', help='Save plots.', type=bool, default='True', val='True'),
146
+
147
+ # Basic Polymer Bond
148
+ Arg('POL_USE_HARMONIC_BOND', help="Use harmonic bond interaction.", type=bool, default='True', val='True'),
149
+ Arg('POL_HARMONIC_BOND_R0', help="harmonic bond distance equilibrium constant", type=float, default='0.1', val='0.1'),
150
+ Arg('POL_HARMONIC_BOND_K', help="harmonic bond force constant (fixed unit: kJ/mol/nm^2)", type=float, default='300000.0', val='300000.0'),
151
+
152
+ # Basic polymer stiffness
153
+ Arg('POL_USE_HARMONIC_ANGLE', help="Use harmonic angle interaction.", type=bool, default='True', val='True'),
154
+ Arg('POL_HARMONIC_ANGLE_R0', help="harmonic angle distance equilibrium constant", type=float, default=str(pi), val=str(pi)),
155
+ Arg('POL_HARMONIC_ANGLE_CONSTANT_K', help="harmonic angle force constant (fixed unit: kJ/mol/radian^2)", type=float, default='100.0', val='100.0'),
156
+
157
+ # Long-Range loop bonds
158
+ Arg('LE_USE_HARMONIC_BOND', help="Use harmonic bond interaction for long range loops.", type=bool, default='True', val='True'),
159
+ Arg('LE_FIXED_DISTANCES', help="For fixed distances between loops. False if you want to correlate with the hatmap strength.", type=bool, default='False', val='False'),
160
+ Arg('LE_HARMONIC_BOND_R0', help="harmonic bond distance equilibrium constant", type=float, default='0.1', val='0.1'),
161
+ Arg('LE_HARMONIC_BOND_K', help="harmonic bond force constant (fixed unit: kJ/mol/nm^2)", type=float, default='30000.0', val='30000.0'),
162
+
163
+ # Excluded Volume
164
+ Arg('EV_USE_EXCLUDED_VOLUME', help="Use excluded volume.", type=bool, default='True', val='True'),
165
+ Arg('EV_EPSILON', help="Epsilon parameter.", type=float, default='100.0', val='100.0'),
166
+ Arg('EV_R_SMALL', help="Add something small in denominator to make it not exploding all the time.", type=float, default='0.05', val='0.05'),
167
+ Arg('EV_POWER', help="Power in the exponent of EV potential.", type=float, default='3.0', val='3.0'),
168
+
169
+ # Spherical container
170
+ Arg('SC_USE_SPHERICAL_CONTAINER', help='Use Spherical container', type=bool, default='False', val='False'),
171
+ Arg('SC_RADIUS1', help='Spherical container radius,', type=float, default='', val=''),
172
+ Arg('SC_RADIUS2', help='Spherical container radius,', type=float, default='', val=''),
173
+ Arg('SC_SCALE', help='Spherical container scaling factor', type=float, default='1000.0', val='1000.0'),
174
+
175
+ # Chromosomal Blocks
176
+ Arg('CHB_USE_CHROMOSOMAL_BLOCKS', help='Use Chromosomal Blocks.', type=bool, default='False', val='False'),
177
+ Arg('CHB_KC', help='Block copolymer width parameter.', type=float, default='0.3', val='0.3'),
178
+ Arg('CHB_DE', help='Energy factor for block copolymer chromosomal model.', type=float, default='1e-5', val='1e-5'),
179
+
180
+ # Compartment Blocks
181
+ Arg('COB_USE_COMPARTMENT_BLOCKS', help='Use Compartment Blocks.', type=bool, default='False', val='False'),
182
+ Arg('COB_DISTANCE', help='Block copolymer equilibrium distance for chromosomal blocks.', type=float, default='', val=''),
183
+ Arg('COB_EA', help='Energy strength for A compartment.', type=float, default='1.0', val='1.0'),
184
+ Arg('COB_EB', help='Energy strength for B compartment.', type=float, default='2.0', val='2.0'),
185
+
186
+ # Subcompartment Blocks
187
+ Arg('SCB_USE_SUBCOMPARTMENT_BLOCKS', help='Use Subcompartment Blocks.', type=bool, default='False', val='False'),
188
+ Arg('SCB_DISTANCE', help='Block copolymer equilibrium distance for chromosomal blocks.', type=float, default='', val=''),
189
+ Arg('SCB_EA1', help='Energy strength for A1 compartment.', type=float, default='1.0', val='1.0'),
190
+ Arg('SCB_EA2', help='Energy strength for A2 compartment.', type=float, default='1.33', val='1.33'),
191
+ Arg('SCB_EB1', help='Energy strength for B1 compartment.', type=float, default='1.66', val='1.66'),
192
+ Arg('SCB_EB2', help='Energy strength for B2 compartment.', type=float, default='2.0', val='2.0'),
193
+
194
+ # Interactions of B compartment with lamina
195
+ Arg('IBL_USE_B_LAMINA_INTERACTION', help='Interactions of B compartment with lamina.', type=bool, default='False', val='False'),
196
+ Arg('IBL_SCALE', help='Scaling factor for B comoartment interaction with lamina.', type=float, default='400.0', val='400.0'),
197
+
198
+ # Central Force for Smaller Chromosomes Attraction to the Nucleolus
199
+ Arg('CF_USE_CENTRAL_FORCE', help='Attraction of smaller chromosomes.', type=bool, default='False', val='False'),
200
+ Arg('CF_STRENGTH', help='Strength of Interaction', type=float, default='100.0', val='100.0'),
201
+
202
+ # Nucleosome interpolation
203
+ Arg('NUC_DO_INTERPOLATION', help='Attraction of smaller chromosomes.', type=bool, default='False', val='False'),
204
+ Arg('MAX_NUCS_PER_BEAD', help='Maximum amount of nucleosomes per single bead.', type=int, default='4', val='4'),
205
+ Arg('NUC_RADIUS', help='The radius of the single nucleosome helix.', type=float, default='0.1', val='0.1'),
206
+ Arg('POINTS_PER_NUC', help='The number of points that consist a nucleosome helix.', type=int, default='20', val='20'),
207
+ Arg('PHI_NORM', help='Zig zag angle. ', type=float, default=str(pi/5), val=str(pi/5)),
208
+
209
+ # Simulation parameters
210
+ Arg('SIM_RUN_MD', help='Do you want to run MD simulation?', type=bool, default='False', val='False'),
211
+ Arg('SIM_N_STEPS', help='Number of steps in MD simulation', type=int, default='', val=''),
212
+ Arg('SIM_ERROR_TOLERANCE', help='Error tolerance for variable MD simulation', type=float, default='0.01', val='0.01'),
213
+ Arg('SIM_AMD_ALPHA', help='Alpha of AMD simulation.', type=float, default='100.0', val='100.0'),
214
+ Arg('SIM_AMD_E', help='E (energy) of AMD simulation.', type=float, default='1000.0', val='1000.0'),
215
+ Arg('SIM_SAMPLING_STEP', help='It determines in t how many steps we save a structure.', type=int, default='100', val='100'),
216
+ Arg('SIM_INTEGRATOR_TYPE', help='Alternative: langevin, verlet', type=str, default='langevin', val='langevin'),
217
+ Arg('SIM_INTEGRATOR_STEP', help='The step of integrator.', type=Quantity, default='1 femtosecond', val='1 femtosecond'),
218
+ Arg('SIM_FRICTION_COEFF', help='Friction coefficient (Used only with langevin integrator)', type=float, default='0.5', val='0.5'),
219
+ Arg('SIM_SET_INITIAL_VELOCITIES', help='Sets initial velocities based on Boltzmann distribution', type=bool, default='False', val='False'),
220
+ Arg('SIM_TEMPERATURE', help='Simulation temperature', type=Quantity, default='310 kelvin', val='310 kelvin'),
221
+
222
+ # Trajectory settings
223
+ Arg('TRJ_FRAMES', help='Number of trajectory frames to save.', type=int, default='2000', val='2000'),
224
+ ])