htpolynet 2.0.0__py3-none-any.whl
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.
- htpolynet/__init__.py +2 -0
- htpolynet/analysis/__init__.py +0 -0
- htpolynet/analysis/analyze.py +256 -0
- htpolynet/analysis/plot.py +588 -0
- htpolynet/analysis/postsim.py +444 -0
- htpolynet/analysis/utils.py +399 -0
- htpolynet/cli.py +488 -0
- htpolynet/core/__init__.py +0 -0
- htpolynet/core/bondtemplate.py +112 -0
- htpolynet/core/configuration.py +83 -0
- htpolynet/core/coordinates.py +644 -0
- htpolynet/core/molecule.py +998 -0
- htpolynet/core/projectfilesystem.py +616 -0
- htpolynet/core/runtime.py +774 -0
- htpolynet/core/topocoord.py +2044 -0
- htpolynet/core/topology.py +1138 -0
- htpolynet/cure/__init__.py +0 -0
- htpolynet/cure/chain.py +135 -0
- htpolynet/cure/curecontroller.py +746 -0
- htpolynet/cure/expandreactions.py +294 -0
- htpolynet/cure/reaction.py +280 -0
- htpolynet/external/__init__.py +0 -0
- htpolynet/external/ambertools.py +97 -0
- htpolynet/external/command.py +73 -0
- htpolynet/external/gromacs.py +308 -0
- htpolynet/external/slurm.py +111 -0
- htpolynet/external/software.py +183 -0
- htpolynet/geometry/__init__.py +0 -0
- htpolynet/geometry/bondlist.py +205 -0
- htpolynet/geometry/lattice.py +32 -0
- htpolynet/geometry/linkcell.py +210 -0
- htpolynet/geometry/matrix4.py +110 -0
- htpolynet/geometry/ring.py +274 -0
- htpolynet/io/__init__.py +6 -0
- htpolynet/io/gro.py +195 -0
- htpolynet/io/mol2.py +210 -0
- htpolynet/io/pdb.py +157 -0
- htpolynet/resources/README.md +20 -0
- htpolynet/resources/__init__.py +0 -0
- htpolynet/resources/cfg/DGE-PAC-hi.yaml +115 -0
- htpolynet/resources/cfg/DGE-PAC-lo.yaml +115 -0
- htpolynet/resources/cfg/FDE-DFDA-hi.yaml +116 -0
- htpolynet/resources/cfg/FDE-DFDA-lo.yaml +116 -0
- htpolynet/resources/cfg/GMASTY-hi.yaml +158 -0
- htpolynet/resources/cfg/GMASTY-lo.yaml +158 -0
- htpolynet/resources/cfg/README.md +1 -0
- htpolynet/resources/cfg/STY.yaml +23 -0
- htpolynet/resources/cfg/pMSTY-hi.yaml +101 -0
- htpolynet/resources/cfg/pMSTY-lo.yaml +101 -0
- htpolynet/resources/cfg/pSTY-hi.yaml +101 -0
- htpolynet/resources/cfg/pSTY-lo.yaml +101 -0
- htpolynet/resources/example_depot/0-liquid-styrene.sh +134 -0
- htpolynet/resources/example_depot/0-liquid-styrene.tgz +0 -0
- htpolynet/resources/example_depot/1-polystyrene.sh +202 -0
- htpolynet/resources/example_depot/1-polystyrene.tgz +0 -0
- htpolynet/resources/example_depot/2-bisgma-styrene-thermoset.sh +353 -0
- htpolynet/resources/example_depot/2-bisgma-styrene-thermoset.tgz +0 -0
- htpolynet/resources/example_depot/3-pacm-dgeba-epoxy-thermoset.sh +242 -0
- htpolynet/resources/example_depot/3-pacm-dgeba-epoxy-thermoset.tgz +0 -0
- htpolynet/resources/example_depot/4-dfda-fde-epoxy-thermoset.sh +216 -0
- htpolynet/resources/example_depot/4-dfda-fde-epoxy-thermoset.tgz +0 -0
- htpolynet/resources/mdp/README.md +1 -0
- htpolynet/resources/mdp/drag-min.mdp +13 -0
- htpolynet/resources/mdp/drag-npt.mdp +36 -0
- htpolynet/resources/mdp/drag-nvt.mdp +31 -0
- htpolynet/resources/mdp/min.mdp +14 -0
- htpolynet/resources/mdp/npt.mdp +37 -0
- htpolynet/resources/mdp/nvt.mdp +29 -0
- htpolynet/resources/mdp/relax-min.mdp +13 -0
- htpolynet/resources/mdp/relax-npt.mdp +37 -0
- htpolynet/resources/mdp/relax-nvt.mdp +31 -0
- htpolynet/resources/mdp/single-molecule-min.mdp +12 -0
- htpolynet/resources/mdp/single-molecule-nvt.mdp +25 -0
- htpolynet/resources/molecules/inputs/DFA.pdb +62 -0
- htpolynet/resources/molecules/inputs/DGE.mol2 +115 -0
- htpolynet/resources/molecules/inputs/EMB.mol2 +50 -0
- htpolynet/resources/molecules/inputs/FDE.pdb +72 -0
- htpolynet/resources/molecules/inputs/GMA.mol2 +163 -0
- htpolynet/resources/molecules/inputs/PAC.mol2 +91 -0
- htpolynet/resources/molecules/inputs/STY.mol2 +44 -0
- htpolynet/resources/molecules/make-monomers.sh +64 -0
- htpolynet/resources/molecules/pics/DFA.png +0 -0
- htpolynet/resources/molecules/pics/DGE.png +0 -0
- htpolynet/resources/molecules/pics/EMB.png +0 -0
- htpolynet/resources/molecules/pics/FDE.png +0 -0
- htpolynet/resources/molecules/pics/GMA.png +0 -0
- htpolynet/resources/molecules/pics/PAC.png +0 -0
- htpolynet/resources/molecules/pics/STY.png +0 -0
- htpolynet/resources/molecules/sample-inputs/DFA.pdb +62 -0
- htpolynet/resources/molecules/sample-inputs/DGE.mol2 +115 -0
- htpolynet/resources/molecules/sample-inputs/EMB.mol2 +50 -0
- htpolynet/resources/molecules/sample-inputs/FDE.pdb +72 -0
- htpolynet/resources/molecules/sample-inputs/GMA.mol2 +163 -0
- htpolynet/resources/molecules/sample-inputs/PAC.mol2 +91 -0
- htpolynet/resources/molecules/sample-inputs/STY.mol2 +44 -0
- htpolynet/resources/tcl/readbonds.tcl +32 -0
- htpolynet/resources/tcl/readgrx.tcl +46 -0
- htpolynet/resources/tcl/render.tcl +74 -0
- htpolynet/utils/__init__.py +0 -0
- htpolynet/utils/banner.py +34 -0
- htpolynet/utils/checkpoint.py +85 -0
- htpolynet/utils/dataframetools.py +92 -0
- htpolynet/utils/inputcheck.py +49 -0
- htpolynet/utils/logsetup.py +44 -0
- htpolynet/utils/stringthings.py +39 -0
- htpolynet-2.0.0.dist-info/METADATA +78 -0
- htpolynet-2.0.0.dist-info/RECORD +110 -0
- htpolynet-2.0.0.dist-info/WHEEL +4 -0
- htpolynet-2.0.0.dist-info/entry_points.txt +2 -0
- htpolynet-2.0.0.dist-info/licenses/LICENSE +21 -0
htpolynet/__init__.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
"""Handles the analyze subcommand.
|
|
2
|
+
|
|
3
|
+
Author: Cameron F. Abrams <cfa22@drexel.edu>
|
|
4
|
+
"""
|
|
5
|
+
import json
|
|
6
|
+
import logging
|
|
7
|
+
import os
|
|
8
|
+
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
import yaml
|
|
12
|
+
|
|
13
|
+
from ..core import projectfilesystem as pfs
|
|
14
|
+
from ..core.configuration import Configuration
|
|
15
|
+
from ..external import software as software
|
|
16
|
+
from ..external.gromacs import gmx_command
|
|
17
|
+
from ..utils.logsetup import setup_logging
|
|
18
|
+
|
|
19
|
+
logger=logging.getLogger(__name__)
|
|
20
|
+
|
|
21
|
+
class Analyze:
|
|
22
|
+
allowed_keys=['gromacs','command','subdir','options','links','outfile','console-input','matchlines']
|
|
23
|
+
required_keys=['command','subdir']
|
|
24
|
+
default_params={
|
|
25
|
+
'gromacs' : {
|
|
26
|
+
'gmx': 'gmx'
|
|
27
|
+
},
|
|
28
|
+
}
|
|
29
|
+
def __init__(self,indict,strict=True):
|
|
30
|
+
self.params={}
|
|
31
|
+
for p,v in self.default_params.items():
|
|
32
|
+
self.params[p]=indict.get(p,v)
|
|
33
|
+
for p,v in indict.items():
|
|
34
|
+
if not p in self.allowed_keys:
|
|
35
|
+
if strict:
|
|
36
|
+
logger.info(f'Ignoring directive \'{p}\' in yaml input file')
|
|
37
|
+
if p in self.default_params:
|
|
38
|
+
logger.info(f'Overwriting default {p} value')
|
|
39
|
+
self.params[p]=v
|
|
40
|
+
self.console_output=None
|
|
41
|
+
|
|
42
|
+
def do(self,**gromacs_dict):
|
|
43
|
+
"""Handles executing the analysis."""
|
|
44
|
+
p=self.params
|
|
45
|
+
print(p)
|
|
46
|
+
for rk in self.required_keys:
|
|
47
|
+
assert rk in p, f'Error: no {rk} value found'
|
|
48
|
+
# logger.info(f'do {p}')
|
|
49
|
+
# if a gromacs dict is passed in, assume this overrides the one read in from the file
|
|
50
|
+
if gromacs_dict:
|
|
51
|
+
software.set_gmx_preferences(gromacs_dict)
|
|
52
|
+
else:
|
|
53
|
+
software.set_gmx_preferences(p['gromacs'])
|
|
54
|
+
logger.info(f'going to {p["subdir"]}')
|
|
55
|
+
pfs.go_to(p['subdir'])
|
|
56
|
+
# make symlinks to requested files
|
|
57
|
+
symlinks=p.get('links',[])
|
|
58
|
+
for input_file in symlinks:
|
|
59
|
+
srcnm=os.path.join(pfs.proj(),input_file)
|
|
60
|
+
bsnm=os.path.basename(srcnm)
|
|
61
|
+
chk=Path(bsnm)
|
|
62
|
+
if not chk.is_symlink():
|
|
63
|
+
os.symlink(srcnm,bsnm)
|
|
64
|
+
else:
|
|
65
|
+
logger.info(f'Symlink {bsnm} already exists.')
|
|
66
|
+
cfile=''
|
|
67
|
+
if 'console-input' in p:
|
|
68
|
+
cfile='console-in.txt'
|
|
69
|
+
ci=p['console-input']
|
|
70
|
+
with open(cfile,'w') as f:
|
|
71
|
+
for ch in ci:
|
|
72
|
+
f.write(ch+'\n')
|
|
73
|
+
self.console_output=gmx_command(p['command'],p.get('options',{}),console_in=cfile)
|
|
74
|
+
logger.info(f'Command {p["command"]} completed.')
|
|
75
|
+
|
|
76
|
+
def parse_console_output(self):
|
|
77
|
+
if not self.console_output:
|
|
78
|
+
logger.info(f'No console output')
|
|
79
|
+
return
|
|
80
|
+
p=self.params
|
|
81
|
+
# either we are grepping out lines from console output or putting it all out there
|
|
82
|
+
if not 'outfile' in p:
|
|
83
|
+
logger.info(f'Here is the console output')
|
|
84
|
+
logger.info(self.console_output)
|
|
85
|
+
else:
|
|
86
|
+
if not 'matchlines' in p:
|
|
87
|
+
with open(p['outfile'],'w') as f:
|
|
88
|
+
f.write(self.console_output)
|
|
89
|
+
else:
|
|
90
|
+
svlns=[]
|
|
91
|
+
console_lines=self.console_output.split('\n')
|
|
92
|
+
for cl in console_lines:
|
|
93
|
+
for ml in p['matchlines']:
|
|
94
|
+
if ml in cl:
|
|
95
|
+
svlns.append(cl)
|
|
96
|
+
with open(p['outfile'],'w') as f:
|
|
97
|
+
for s in svlns:
|
|
98
|
+
f.write(s+'\n')
|
|
99
|
+
logger.info(f'Created {p["outfile"]} in {p["subdir"]}')
|
|
100
|
+
|
|
101
|
+
class AnalyzeDensity(Analyze):
|
|
102
|
+
""" Analyze class for handling trajectory density profile calculation
|
|
103
|
+
"""
|
|
104
|
+
default_params={
|
|
105
|
+
'subdir': 'analyze/density',
|
|
106
|
+
'links': [f'{pfs.Dirs.postsim}/equilibrate/equilibrate.tpr',f'{pfs.Dirs.postsim}/equilibrate/equilibrate.trr'],
|
|
107
|
+
'gromacs' : {
|
|
108
|
+
'gmx': 'gmx'
|
|
109
|
+
},
|
|
110
|
+
'command': 'density',
|
|
111
|
+
'options': {
|
|
112
|
+
's':'equilibrate.tpr',
|
|
113
|
+
'f':'equilibrate.trr',
|
|
114
|
+
'o':'density.xvg',
|
|
115
|
+
'xvg': 'none',
|
|
116
|
+
'b': 0,
|
|
117
|
+
'd': 'Z',
|
|
118
|
+
'sl': 50
|
|
119
|
+
},
|
|
120
|
+
'console-input': ['0']
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
class AnalyzeFFV(Analyze):
|
|
124
|
+
default_params={
|
|
125
|
+
'subdir': 'analyze/freevolume',
|
|
126
|
+
'links': [f'{pfs.Dirs.postsim}/equilibrate/equilibrate.tpr',f'{pfs.Dirs.postsim}/equilibrate/equilibrate.trr'],
|
|
127
|
+
'gromacs' : {
|
|
128
|
+
'gmx': 'gmx'
|
|
129
|
+
},
|
|
130
|
+
'command': 'freevolume',
|
|
131
|
+
'options': {
|
|
132
|
+
's':'equilibrate.tpr',
|
|
133
|
+
'f':'equilibrate.trr',
|
|
134
|
+
'o':'ffv.xvg',
|
|
135
|
+
'xvg': 'none',
|
|
136
|
+
'b': 0.0
|
|
137
|
+
},
|
|
138
|
+
'outfile': 'ffv.dat',
|
|
139
|
+
'matchlines': ['Free volume','Total volume','Number of molecules','Average molar mass','Density','Molecular volume Vm assuming homogeneity:','Molecular van der Waals volume assuming homogeneity:','Fractional free volume']
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class AnalyzeConfiguration:
|
|
144
|
+
""" handles reading and parsing an analysis input config file.
|
|
145
|
+
Config file format
|
|
146
|
+
|
|
147
|
+
- { key1: {<paramdict>}}
|
|
148
|
+
- { key2: {<paramdict>}}
|
|
149
|
+
|
|
150
|
+
...
|
|
151
|
+
|
|
152
|
+
The config file is a list of single-element dictionaries, whose single keyword
|
|
153
|
+
indicates the type of analysis to be run; analyses are run in the order
|
|
154
|
+
they appear in the config file.
|
|
155
|
+
|
|
156
|
+
"""
|
|
157
|
+
default_class=Analyze
|
|
158
|
+
predefined_classes={'density':AnalyzeDensity,'freevolume':AnalyzeFFV}
|
|
159
|
+
def __init__(self):
|
|
160
|
+
self.cfgFile=''
|
|
161
|
+
self.baselist=[]
|
|
162
|
+
self.stagelist=[]
|
|
163
|
+
|
|
164
|
+
@classmethod
|
|
165
|
+
def read(cls,filename,parse=True,**kwargs):
|
|
166
|
+
"""Generates a new PostsimConfiguration object by reading in the JSON or YAML file indicated by filename.
|
|
167
|
+
|
|
168
|
+
Args:
|
|
169
|
+
filename (str): name of file from which to read new PostsimConfiguration object
|
|
170
|
+
parse (bool): if True, parse the input configuration file, defaults to True
|
|
171
|
+
|
|
172
|
+
Raises:
|
|
173
|
+
Exception: if extension of filename is not '.json' or '.yaml' or '.yml'
|
|
174
|
+
|
|
175
|
+
Returns:
|
|
176
|
+
PostsimConfiguration: a new PostsimConfiguration object
|
|
177
|
+
"""
|
|
178
|
+
basename,extension=os.path.splitext(filename)
|
|
179
|
+
if extension=='.json':
|
|
180
|
+
return cls._read_json(filename,parse,**kwargs)
|
|
181
|
+
elif extension=='.yaml' or extension=='.yml':
|
|
182
|
+
return cls._read_yaml(filename,parse,**kwargs)
|
|
183
|
+
else:
|
|
184
|
+
raise Exception(f'Unknown config file extension {extension}')
|
|
185
|
+
|
|
186
|
+
@classmethod
|
|
187
|
+
def _read_json(cls,filename,parse=True,**kwargs):
|
|
188
|
+
"""Creates a new PostsimConfiguration object by reading from JSON input.
|
|
189
|
+
|
|
190
|
+
Args:
|
|
191
|
+
filename (str): name of JSON file
|
|
192
|
+
parse (bool): if True, parse the JSON data, defaults to True
|
|
193
|
+
|
|
194
|
+
Returns:
|
|
195
|
+
PostsimConfiguration: a new PostsimConfiguration object
|
|
196
|
+
"""
|
|
197
|
+
inst=cls()
|
|
198
|
+
inst.cfgFile=filename
|
|
199
|
+
with open(filename,'r') as f:
|
|
200
|
+
inst.baselist=json.load(f)
|
|
201
|
+
assert type(inst.baselist)==list,f'Poorly formatted {filename}'
|
|
202
|
+
if parse: inst.parse(**kwargs)
|
|
203
|
+
return inst
|
|
204
|
+
|
|
205
|
+
@classmethod
|
|
206
|
+
def _read_yaml(cls,filename,parse=True,**kwargs):
|
|
207
|
+
"""Creates a new PostsimConfiguration object by reading from YAML input.
|
|
208
|
+
|
|
209
|
+
Args:
|
|
210
|
+
filename (str): name of YAML file
|
|
211
|
+
parse (bool): if True, parse the YAML data, defaults to True
|
|
212
|
+
|
|
213
|
+
Returns:
|
|
214
|
+
PostsimConfiguration: a new PostsimConfiguration object
|
|
215
|
+
"""
|
|
216
|
+
inst=cls()
|
|
217
|
+
inst.cfgFile=filename
|
|
218
|
+
with open(filename,'r') as f:
|
|
219
|
+
inst.baselist=yaml.safe_load(f)
|
|
220
|
+
assert type(inst.baselist)==list,f'Poorly formatted {filename}'
|
|
221
|
+
if parse: inst.parse(**kwargs)
|
|
222
|
+
return inst
|
|
223
|
+
|
|
224
|
+
def parse(self,**kwargs):
|
|
225
|
+
"""Parses a PostsimConfiguration file to build the list of stages to run."""
|
|
226
|
+
for content in self.baselist:
|
|
227
|
+
analysistype=content['command']
|
|
228
|
+
if analysistype in self.predefined_classes:
|
|
229
|
+
self.stagelist.append(self.predefined_classes[analysistype](content))
|
|
230
|
+
else:
|
|
231
|
+
self.stagelist.append(self.default_class(content))
|
|
232
|
+
|
|
233
|
+
def analyze(args):
|
|
234
|
+
"""Handles the analyze subcommand for managing gromacs-based trajectory analyses.
|
|
235
|
+
|
|
236
|
+
Args:
|
|
237
|
+
args (argparse.Namespace): command-line arguments
|
|
238
|
+
"""
|
|
239
|
+
setup_logging(args.loglevel, no_banner=args.no_banner)
|
|
240
|
+
ess='y' if len(args.proj)==0 else 'ies'
|
|
241
|
+
ogromacs={}
|
|
242
|
+
if args.ocfg:
|
|
243
|
+
ocfg=Configuration.read(args.ocfg)
|
|
244
|
+
ogromacs=ocfg.gromacs
|
|
245
|
+
cfg=AnalyzeConfiguration.read(args.cfg)
|
|
246
|
+
logger.debug(f'{cfg.baselist}')
|
|
247
|
+
logger.info(f'Project director{ess}: {args.proj}')
|
|
248
|
+
software.sw_setup()
|
|
249
|
+
logger.debug(f'ogromacs {ogromacs}')
|
|
250
|
+
for d in args.proj:
|
|
251
|
+
pfs.pfs_setup(root=os.getcwd(),topdirs=pfs.Dirs.analyze_topdirs,verbose=True,projdir=d,reProject=False,userlibrary=args.lib)
|
|
252
|
+
pfs.go_to(pfs.Dirs.analyze)
|
|
253
|
+
for stage in cfg.stagelist:
|
|
254
|
+
stage.do(**ogromacs)
|
|
255
|
+
stage.parse_console_output()
|
|
256
|
+
pfs.go_root()
|