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.
Files changed (110) hide show
  1. htpolynet/__init__.py +2 -0
  2. htpolynet/analysis/__init__.py +0 -0
  3. htpolynet/analysis/analyze.py +256 -0
  4. htpolynet/analysis/plot.py +588 -0
  5. htpolynet/analysis/postsim.py +444 -0
  6. htpolynet/analysis/utils.py +399 -0
  7. htpolynet/cli.py +488 -0
  8. htpolynet/core/__init__.py +0 -0
  9. htpolynet/core/bondtemplate.py +112 -0
  10. htpolynet/core/configuration.py +83 -0
  11. htpolynet/core/coordinates.py +644 -0
  12. htpolynet/core/molecule.py +998 -0
  13. htpolynet/core/projectfilesystem.py +616 -0
  14. htpolynet/core/runtime.py +774 -0
  15. htpolynet/core/topocoord.py +2044 -0
  16. htpolynet/core/topology.py +1138 -0
  17. htpolynet/cure/__init__.py +0 -0
  18. htpolynet/cure/chain.py +135 -0
  19. htpolynet/cure/curecontroller.py +746 -0
  20. htpolynet/cure/expandreactions.py +294 -0
  21. htpolynet/cure/reaction.py +280 -0
  22. htpolynet/external/__init__.py +0 -0
  23. htpolynet/external/ambertools.py +97 -0
  24. htpolynet/external/command.py +73 -0
  25. htpolynet/external/gromacs.py +308 -0
  26. htpolynet/external/slurm.py +111 -0
  27. htpolynet/external/software.py +183 -0
  28. htpolynet/geometry/__init__.py +0 -0
  29. htpolynet/geometry/bondlist.py +205 -0
  30. htpolynet/geometry/lattice.py +32 -0
  31. htpolynet/geometry/linkcell.py +210 -0
  32. htpolynet/geometry/matrix4.py +110 -0
  33. htpolynet/geometry/ring.py +274 -0
  34. htpolynet/io/__init__.py +6 -0
  35. htpolynet/io/gro.py +195 -0
  36. htpolynet/io/mol2.py +210 -0
  37. htpolynet/io/pdb.py +157 -0
  38. htpolynet/resources/README.md +20 -0
  39. htpolynet/resources/__init__.py +0 -0
  40. htpolynet/resources/cfg/DGE-PAC-hi.yaml +115 -0
  41. htpolynet/resources/cfg/DGE-PAC-lo.yaml +115 -0
  42. htpolynet/resources/cfg/FDE-DFDA-hi.yaml +116 -0
  43. htpolynet/resources/cfg/FDE-DFDA-lo.yaml +116 -0
  44. htpolynet/resources/cfg/GMASTY-hi.yaml +158 -0
  45. htpolynet/resources/cfg/GMASTY-lo.yaml +158 -0
  46. htpolynet/resources/cfg/README.md +1 -0
  47. htpolynet/resources/cfg/STY.yaml +23 -0
  48. htpolynet/resources/cfg/pMSTY-hi.yaml +101 -0
  49. htpolynet/resources/cfg/pMSTY-lo.yaml +101 -0
  50. htpolynet/resources/cfg/pSTY-hi.yaml +101 -0
  51. htpolynet/resources/cfg/pSTY-lo.yaml +101 -0
  52. htpolynet/resources/example_depot/0-liquid-styrene.sh +134 -0
  53. htpolynet/resources/example_depot/0-liquid-styrene.tgz +0 -0
  54. htpolynet/resources/example_depot/1-polystyrene.sh +202 -0
  55. htpolynet/resources/example_depot/1-polystyrene.tgz +0 -0
  56. htpolynet/resources/example_depot/2-bisgma-styrene-thermoset.sh +353 -0
  57. htpolynet/resources/example_depot/2-bisgma-styrene-thermoset.tgz +0 -0
  58. htpolynet/resources/example_depot/3-pacm-dgeba-epoxy-thermoset.sh +242 -0
  59. htpolynet/resources/example_depot/3-pacm-dgeba-epoxy-thermoset.tgz +0 -0
  60. htpolynet/resources/example_depot/4-dfda-fde-epoxy-thermoset.sh +216 -0
  61. htpolynet/resources/example_depot/4-dfda-fde-epoxy-thermoset.tgz +0 -0
  62. htpolynet/resources/mdp/README.md +1 -0
  63. htpolynet/resources/mdp/drag-min.mdp +13 -0
  64. htpolynet/resources/mdp/drag-npt.mdp +36 -0
  65. htpolynet/resources/mdp/drag-nvt.mdp +31 -0
  66. htpolynet/resources/mdp/min.mdp +14 -0
  67. htpolynet/resources/mdp/npt.mdp +37 -0
  68. htpolynet/resources/mdp/nvt.mdp +29 -0
  69. htpolynet/resources/mdp/relax-min.mdp +13 -0
  70. htpolynet/resources/mdp/relax-npt.mdp +37 -0
  71. htpolynet/resources/mdp/relax-nvt.mdp +31 -0
  72. htpolynet/resources/mdp/single-molecule-min.mdp +12 -0
  73. htpolynet/resources/mdp/single-molecule-nvt.mdp +25 -0
  74. htpolynet/resources/molecules/inputs/DFA.pdb +62 -0
  75. htpolynet/resources/molecules/inputs/DGE.mol2 +115 -0
  76. htpolynet/resources/molecules/inputs/EMB.mol2 +50 -0
  77. htpolynet/resources/molecules/inputs/FDE.pdb +72 -0
  78. htpolynet/resources/molecules/inputs/GMA.mol2 +163 -0
  79. htpolynet/resources/molecules/inputs/PAC.mol2 +91 -0
  80. htpolynet/resources/molecules/inputs/STY.mol2 +44 -0
  81. htpolynet/resources/molecules/make-monomers.sh +64 -0
  82. htpolynet/resources/molecules/pics/DFA.png +0 -0
  83. htpolynet/resources/molecules/pics/DGE.png +0 -0
  84. htpolynet/resources/molecules/pics/EMB.png +0 -0
  85. htpolynet/resources/molecules/pics/FDE.png +0 -0
  86. htpolynet/resources/molecules/pics/GMA.png +0 -0
  87. htpolynet/resources/molecules/pics/PAC.png +0 -0
  88. htpolynet/resources/molecules/pics/STY.png +0 -0
  89. htpolynet/resources/molecules/sample-inputs/DFA.pdb +62 -0
  90. htpolynet/resources/molecules/sample-inputs/DGE.mol2 +115 -0
  91. htpolynet/resources/molecules/sample-inputs/EMB.mol2 +50 -0
  92. htpolynet/resources/molecules/sample-inputs/FDE.pdb +72 -0
  93. htpolynet/resources/molecules/sample-inputs/GMA.mol2 +163 -0
  94. htpolynet/resources/molecules/sample-inputs/PAC.mol2 +91 -0
  95. htpolynet/resources/molecules/sample-inputs/STY.mol2 +44 -0
  96. htpolynet/resources/tcl/readbonds.tcl +32 -0
  97. htpolynet/resources/tcl/readgrx.tcl +46 -0
  98. htpolynet/resources/tcl/render.tcl +74 -0
  99. htpolynet/utils/__init__.py +0 -0
  100. htpolynet/utils/banner.py +34 -0
  101. htpolynet/utils/checkpoint.py +85 -0
  102. htpolynet/utils/dataframetools.py +92 -0
  103. htpolynet/utils/inputcheck.py +49 -0
  104. htpolynet/utils/logsetup.py +44 -0
  105. htpolynet/utils/stringthings.py +39 -0
  106. htpolynet-2.0.0.dist-info/METADATA +78 -0
  107. htpolynet-2.0.0.dist-info/RECORD +110 -0
  108. htpolynet-2.0.0.dist-info/WHEEL +4 -0
  109. htpolynet-2.0.0.dist-info/entry_points.txt +2 -0
  110. htpolynet-2.0.0.dist-info/licenses/LICENSE +21 -0
htpolynet/__init__.py ADDED
@@ -0,0 +1,2 @@
1
+ from importlib.metadata import version
2
+ HTPOLYNET_VERSION = version('htpolynet')
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()