packmol-memgen-minimal 1.1.16__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 (71) hide show
  1. packmol_memgen/__init__.py +2 -0
  2. packmol_memgen/__version__.py +34 -0
  3. packmol_memgen/data/LICENSE.Apache-2.0 +201 -0
  4. packmol_memgen/data/extra_solvents.lib +789 -0
  5. packmol_memgen/data/frcmod.lipid_ext +97 -0
  6. packmol_memgen/data/frcmod.solvents +129 -0
  7. packmol_memgen/data/insane_lipids.txt +138 -0
  8. packmol_memgen/data/insane_solvents.txt +45 -0
  9. packmol_memgen/data/leaprc.extra_solvents +42 -0
  10. packmol_memgen/data/leaprc.lipid_ext +48 -0
  11. packmol_memgen/data/lipid_ext.lib +12312 -0
  12. packmol_memgen/data/martini_v3.0.0.itp +356605 -0
  13. packmol_memgen/data/memgen.parm +4082 -0
  14. packmol_memgen/data/pdbs.tar.gz +0 -0
  15. packmol_memgen/data/solvent.parm +14 -0
  16. packmol_memgen/example/example.sh +31 -0
  17. packmol_memgen/lib/__init__.py +0 -0
  18. packmol_memgen/lib/amber.py +77 -0
  19. packmol_memgen/lib/charmmlipid2amber/__init__.py +0 -0
  20. packmol_memgen/lib/charmmlipid2amber/charmmlipid2amber.csv +7164 -0
  21. packmol_memgen/lib/charmmlipid2amber/charmmlipid2amber.py +225 -0
  22. packmol_memgen/lib/pdbremix/LICENSE +21 -0
  23. packmol_memgen/lib/pdbremix/__init__.py +0 -0
  24. packmol_memgen/lib/pdbremix/_version.py +1 -0
  25. packmol_memgen/lib/pdbremix/amber.py +1103 -0
  26. packmol_memgen/lib/pdbremix/asa.py +227 -0
  27. packmol_memgen/lib/pdbremix/data/aminoacid.pdb +334 -0
  28. packmol_memgen/lib/pdbremix/data/binaries.json +26 -0
  29. packmol_memgen/lib/pdbremix/data/charmm22.parameter +2250 -0
  30. packmol_memgen/lib/pdbremix/data/charmm22.topology +1635 -0
  31. packmol_memgen/lib/pdbremix/data/color_b.py +682 -0
  32. packmol_memgen/lib/pdbremix/data/hin.lib +130 -0
  33. packmol_memgen/lib/pdbremix/data/hydroxide.lib +88 -0
  34. packmol_memgen/lib/pdbremix/data/make_chi.py +92 -0
  35. packmol_memgen/lib/pdbremix/data/opls.parameter +1108 -0
  36. packmol_memgen/lib/pdbremix/data/opls.topology +1869 -0
  37. packmol_memgen/lib/pdbremix/data/phd.frcmod +82 -0
  38. packmol_memgen/lib/pdbremix/data/phd.leaprc +4 -0
  39. packmol_memgen/lib/pdbremix/data/phd.prepin +35 -0
  40. packmol_memgen/lib/pdbremix/data/template.pdb +334 -0
  41. packmol_memgen/lib/pdbremix/data/znb.frcmod +24 -0
  42. packmol_memgen/lib/pdbremix/data/znb.leaprc +7 -0
  43. packmol_memgen/lib/pdbremix/data/znb.lib +69 -0
  44. packmol_memgen/lib/pdbremix/data.py +264 -0
  45. packmol_memgen/lib/pdbremix/fetch.py +102 -0
  46. packmol_memgen/lib/pdbremix/force.py +627 -0
  47. packmol_memgen/lib/pdbremix/gromacs.py +978 -0
  48. packmol_memgen/lib/pdbremix/lib/__init__.py +0 -0
  49. packmol_memgen/lib/pdbremix/lib/docopt.py +579 -0
  50. packmol_memgen/lib/pdbremix/lib/pyqcprot.py +305 -0
  51. packmol_memgen/lib/pdbremix/namd.py +1078 -0
  52. packmol_memgen/lib/pdbremix/pdbatoms.py +543 -0
  53. packmol_memgen/lib/pdbremix/pdbtext.py +120 -0
  54. packmol_memgen/lib/pdbremix/protein.py +311 -0
  55. packmol_memgen/lib/pdbremix/pymol.py +480 -0
  56. packmol_memgen/lib/pdbremix/rmsd.py +203 -0
  57. packmol_memgen/lib/pdbremix/simulate.py +420 -0
  58. packmol_memgen/lib/pdbremix/spacehash.py +73 -0
  59. packmol_memgen/lib/pdbremix/trajectory.py +286 -0
  60. packmol_memgen/lib/pdbremix/util.py +273 -0
  61. packmol_memgen/lib/pdbremix/v3.py +16 -0
  62. packmol_memgen/lib/pdbremix/v3array.py +482 -0
  63. packmol_memgen/lib/pdbremix/v3numpy.py +350 -0
  64. packmol_memgen/lib/pdbremix/volume.py +155 -0
  65. packmol_memgen/lib/utils.py +1017 -0
  66. packmol_memgen/main.py +2827 -0
  67. packmol_memgen_minimal-1.1.16.dist-info/METADATA +664 -0
  68. packmol_memgen_minimal-1.1.16.dist-info/RECORD +71 -0
  69. packmol_memgen_minimal-1.1.16.dist-info/WHEEL +4 -0
  70. packmol_memgen_minimal-1.1.16.dist-info/entry_points.txt +2 -0
  71. packmol_memgen_minimal-1.1.16.dist-info/licenses/LICENSE +338 -0
@@ -0,0 +1,286 @@
1
+ # encoding: utf-8
2
+
3
+ __doc__ = """
4
+
5
+ Interface to read molecular-dynamics trajectories.
6
+
7
+ Simulation trajectories are read into a Trajectory object
8
+ that provides a Soup object, which is updated everytime a
9
+ frame is requested. All operations on Soup are available,
10
+ including the writing of PDB files, and extracting fragments
11
+ for further interrogation.
12
+
13
+ Trajectory object:
14
+ Attributes:
15
+ basename
16
+ n_frame
17
+ i_frame
18
+ soup
19
+ Methods:
20
+ load_frame
21
+
22
+ Currently supported trajectories:
23
+ - AMBER: .top .trj .vel.trj
24
+ - GROMACS: .top .gro .trr
25
+ - NAMD: .psf .dcd .vel.dcd
26
+ """
27
+
28
+
29
+ import os
30
+ import copy
31
+
32
+ from . import util
33
+ from . import v3
34
+ from . import pdbatoms
35
+ from . import data
36
+ from . import rmsd
37
+ from . import force
38
+
39
+ from . import namd
40
+ from . import amber
41
+ from . import gromacs
42
+
43
+
44
+
45
+ def open_trajectory(basename):
46
+ """
47
+ Returns Trajectory object by guessing the type from basename.
48
+ """
49
+ if os.path.isfile(basename + '.trr'):
50
+ print("Detected GROMACS trajectory")
51
+ return gromacs.Trajectory(basename)
52
+ if os.path.isfile(basename + '.psf'):
53
+ print("Detected NAMD trajectory")
54
+ return namd.Trajectory(basename)
55
+ if os.path.isfile(basename + '.top'):
56
+ print("Detected AMBER trajectory")
57
+ return amber.Trajectory(basename)
58
+ raise ValueError("No trajectories found at all!")
59
+
60
+
61
+ def make_equilibrium_pdb(trajectory, pdb, start=None, end=None):
62
+ """
63
+ Calculates the equilibrium structure between start and end
64
+ frames. Default: last half of trajectory.
65
+ """
66
+ if start is None:
67
+ start = trajectory.n_frame // 2
68
+ if end is None:
69
+ end = trajectory.n_frame
70
+
71
+ if start < 0 or start >= trajectory.n_frame:
72
+ raise IndexError("Start frame out of range")
73
+ if end < 0 or end > trajectory.n_frame+1:
74
+ raise IndexError("End frame out of range")
75
+
76
+ # sum_soup stores cumulative values
77
+ sum_soup = trajectory.soup.copy()
78
+ for a in sum_soup.atoms():
79
+ v3.set_vector(a.pos, 0, 0, 0)
80
+
81
+ n_frame = 0
82
+ for i in range(start, end):
83
+ trajectory.load_frame(i)
84
+ n_frame += 1
85
+ for sum_atom, atom in zip(
86
+ sum_soup.atoms(), trajectory.soup.atoms()):
87
+ sum_atom.pos += atom.pos
88
+
89
+ for a in sum_soup.atoms():
90
+ x = a.pos.x / float(n_frame)
91
+ y = a.pos.y / float(n_frame)
92
+ z = a.pos.z / float(n_frame)
93
+ v3.set_vector(a.pos, x, y, z)
94
+
95
+ trajectory.soup.write_pdb(pdb)
96
+
97
+
98
+ def make_pdb_from_trajectory(
99
+ basename, i_frame, out_pdb, res_bfactors=None):
100
+ """
101
+ Make a PDB from the ith frame of a trajectory described by
102
+ basename. Optional residue bfactors are loaded into residues.
103
+ """
104
+ trajectory = open_trajectory(basename)
105
+ trajectory.load_frame(i_frame)
106
+ if res_bfactors is not None:
107
+ trajectory.soup.load_residue_bfactors(res_bfactors)
108
+ trajectory.soup.write_pdb(out_pdb)
109
+ del trajectory
110
+
111
+
112
+
113
+ class TrajectoryAnalyzer(object):
114
+ """
115
+ Abstract strategy object to analyze the frames of a trajectory
116
+ and write the results to a text file.
117
+ """
118
+ var_name = 'override'
119
+
120
+ def __init__(self, trj, n_frame_per_ps, ref_pdb):
121
+ self.trj = trj
122
+ self.soup = self.trj.soup
123
+ self.n_frame_per_ps = n_frame_per_ps
124
+
125
+ # for reference frame
126
+ if ref_pdb:
127
+ self.ref_soup = pdbatoms.Soup(ref_pdb)
128
+ else:
129
+ self.ref_soup = self.soup.copy()
130
+
131
+ # output files
132
+ fname = trj.basename + '.' + self.var_name + '.per_frame'
133
+ self.file_per_frame = open(fname, 'w')
134
+ fname = trj.basename + '.' + self.var_name + '.per_ps'
135
+ self.file_per_ps = open(fname, 'w')
136
+
137
+ # cumul results for ps save
138
+ self.cumul_results = None
139
+ self.n_cumul_frame = 0
140
+
141
+ def calculate_results(self):
142
+ """
143
+ To be overriden: return list of results to print out
144
+ """
145
+ return []
146
+
147
+ def process_frame_on_ps(self):
148
+ for i in range(len(self.cumul_results)):
149
+ self.cumul_results[i] /= float(self.n_cumul_frame)
150
+
151
+ # save results for ps calculation
152
+ s = ' '.join(map(str, self.cumul_results))
153
+ t = round(self.trj.i_frame / float(self.n_frame_per_ps))
154
+ self.file_per_ps.write('%.f %s\n' % (t, s))
155
+
156
+ # clear for next ps
157
+ if self.trj.i_frame > 0:
158
+ for i in range(len(self.cumul_results)):
159
+ self.cumul_results[i] = 0.0
160
+ self.n_cumul_frame = 0
161
+
162
+ def process_frame(self):
163
+ results = self.calculate_results()
164
+
165
+ # write results to file_per_frame
166
+ s = " ".join(map(str, results))
167
+ frame = self.trj.i_frame
168
+ self.file_per_frame.write("%d %s\n" % (frame, s))
169
+
170
+ # initialize on first frame
171
+ if self.cumul_results is None:
172
+ self.cumul_results = [0.0 for i in range(len(results))]
173
+
174
+ # add results to cumul_results
175
+ for i in range(len(results)):
176
+ self.cumul_results[i] += results[i]
177
+ self.n_cumul_frame += 1
178
+
179
+ def close(self):
180
+ self.file_per_frame.close()
181
+ self.file_per_ps.close()
182
+
183
+
184
+
185
+ class CaRmsdAnalyzer(TrajectoryAnalyzer):
186
+ """
187
+ TrajectoryAnalyzer to calculate C-alpha RMSD.
188
+ """
189
+ var_name = 'rmsd'
190
+ def calculate_results(self):
191
+ return [rmsd.rmsd_of_soups(self.ref_soup, self.soup)]
192
+
193
+
194
+ class KineticEnergyAnalyzer(TrajectoryAnalyzer):
195
+ """
196
+ TrajectoryAnalyzer to calculate kinetic energy of residues.
197
+ """
198
+ var_name = 'kin'
199
+ def calculate_results(self):
200
+ results = []
201
+ for residue in self.soup.residues():
202
+ if residue.type not in data.solvent_res_types:
203
+ atoms = residue.atoms()
204
+ energy = force.kinetic_energy(atoms)/float(len(atoms))
205
+ results.append(energy)
206
+ return results
207
+
208
+
209
+ class ResidueDeviationAnalyzer(TrajectoryAnalyzer):
210
+ """
211
+ TrajectoryAnalyzer to calculate kinetic energy of residues.
212
+ """
213
+ var_name = 'dev'
214
+ def calculate_results(self):
215
+ ref_crds = []
216
+ crds = []
217
+ for ref_residue, residue in zip(self.ref_soup.residues(), self.soup.residues()):
218
+ if residue.type not in data.solvent_res_types:
219
+ if residue.has_atom('CA'):
220
+ ref_crds.append(ref_residue.atom('CA').pos.copy())
221
+ crds.append(residue.atom('CA').pos.copy())
222
+ center = v3.get_center(crds)
223
+ crds = [c - center for c in crds]
224
+ ref_center = v3.get_center(ref_crds)
225
+ ref_crds = [c - ref_center for c in ref_crds]
226
+ rmsd_val, transform_ref_to_this = rmsd.calc_rmsd_rot(ref_crds, crds)
227
+ ref_crds = [v3.transform(transform_ref_to_this, c) for c in ref_crds]
228
+ return [v3.distance(crd, ref_crd) for crd, ref_crd in zip(crds, ref_crds)]
229
+
230
+
231
+ def guess_n_frame_per_ps(basename):
232
+ """
233
+ Returns the n_frame_per_ps of a trajectory by reading any
234
+ .config files that would have been generated using simualte.py.
235
+ """
236
+ config = basename + ".config"
237
+ try:
238
+ params = util.read_dict(config)
239
+ # assuming 1fs time step
240
+ n_step_per_ps = 1000
241
+ if 'n_step_per_snapshot' in params:
242
+ n_step_per_snapshot = params['n_step_per_snapshot']
243
+ n_frame_per_ps = n_step_per_ps / n_step_per_snapshot
244
+ except:
245
+ n_frame_per_ps = 50
246
+ return n_frame_per_ps
247
+
248
+
249
+
250
+ def analyze_trajectory(
251
+ basename, n_frame_per_ps=None,
252
+ analyzer_classes=None, ref_pdb=None):
253
+ """"
254
+ Calculates trajectory variables for the residues in the
255
+ system using the TrajectoryAnalyzer straegy objects in
256
+ analyzers.
257
+ """
258
+ trj = open_trajectory(basename)
259
+
260
+ # Instantiate analyzers
261
+ if n_frame_per_ps is None:
262
+ n_frame_per_ps = guess_n_frame_per_ps(basename)
263
+ if analyzer_classes is None:
264
+ analyzer_classes = \
265
+ [KineticEnergyAnalyzer, CaRmsdAnalyzer, ResidueDeviationAnalyzer]
266
+ analyzers = [a(trj, n_frame_per_ps, ref_pdb) \
267
+ for a in analyzer_classes]
268
+
269
+ # Go through frame by frame
270
+ for i_frame in range(trj.n_frame):
271
+ print("Processing frame %d/%d" % (i_frame, trj.n_frame))
272
+ trj.load_frame(i_frame)
273
+ for analyzer in analyzers:
274
+ analyzer.process_frame()
275
+ # A whole ps has been save to file_per_ps
276
+ if (i_frame+1) % n_frame_per_ps == 0 or i_frame == 0:
277
+ analyzer.process_frame_on_ps()
278
+
279
+ # At last frame
280
+ trj.soup.write_pdb(basename + '.last.pdb')
281
+
282
+ for analyzer in analyzers:
283
+ analyzer.close()
284
+
285
+
286
+
@@ -0,0 +1,273 @@
1
+ # encoding: utf-8
2
+
3
+ __doc__ = """
4
+
5
+ Utility functions.
6
+
7
+ - directory handling
8
+ - pathname mangling
9
+ - running shell commands
10
+ - timer
11
+ - file checking
12
+ """
13
+
14
+ import os
15
+ import stat
16
+ import tempfile
17
+ import copy
18
+ import re
19
+ import glob
20
+ import json
21
+ import subprocess
22
+ import time
23
+ import math
24
+ import pprint
25
+ import sys
26
+
27
+
28
+ def re_glob(dir_tag, reg_exp=""):
29
+ fnames = glob.glob(dir_tag)
30
+ return [f for f in fnames if re.search(reg_exp, f)]
31
+
32
+
33
+ def check_dir(dirname):
34
+ if dirname.strip() == '':
35
+ return
36
+ if not os.path.isdir(dirname):
37
+ os.makedirs(dirname)
38
+
39
+
40
+ def goto_dir(new_dir):
41
+ if new_dir.strip() == '':
42
+ return
43
+ if not os.path.isdir(new_dir):
44
+ os.makedirs(new_dir)
45
+ os.chdir(new_dir)
46
+
47
+
48
+ def relpath(path):
49
+ if path == '':
50
+ return ''
51
+ dirpath, basename = os.path.split(path)
52
+ dirpath = os.path.relpath(dirpath, os.getcwd())
53
+ if dirpath == '' or dirpath == '.':
54
+ return basename
55
+ return os.path.join(dirpath, basename)
56
+
57
+
58
+ def temp_fname(suffix=''):
59
+ fd, fname = tempfile.mkstemp(suffix, 'tmp-', '.')
60
+ f = os.fdopen(fd, 'w')
61
+ f.close()
62
+ os.unlink(fname)
63
+ return os.path.basename(fname)
64
+
65
+
66
+ def fname_variant(fname):
67
+ root, ext = os.path.splitext(fname)
68
+ i = 1
69
+ new_fname = "%s-%d%s" % (root, i, ext)
70
+ while os.path.isfile(new_fname):
71
+ i += 1
72
+ new_fname = "%s-%d%s" % (root, i, ext)
73
+ return new_fname
74
+
75
+
76
+ def clean_fname(*fnames):
77
+ for fname in fnames:
78
+ if os.path.isdir(fname):
79
+ for root, dirs, files in os.walk(fname, topdown=False):
80
+ for name in files:
81
+ os.remove(os.path.join(root, name))
82
+ for name in dirs:
83
+ os.rmdir(os.path.join(root, name))
84
+ os.rmdir(fname)
85
+ elif os.path.isfile(fname):
86
+ try:
87
+ os.remove(fname)
88
+ except:
89
+ pass
90
+
91
+
92
+ def get_floats_from_string(s):
93
+ val_strs = re.finditer(r'[-+]?([0-9]*\.[0-9]+|[0-9]+)', s)
94
+ return [float(v.group()) for v in val_strs]
95
+
96
+
97
+ def write_dict(fname, d, indent=2):
98
+ pprint.pprint(d, indent=2, stream=open(fname, "w"))
99
+
100
+
101
+ def read_dict(fname):
102
+ try:
103
+ txt = open(fname).read()
104
+ d = eval(txt)
105
+ if not isinstance(d, dict):
106
+ raise Exception('Not a dictionary in ' + fname)
107
+ return d
108
+ except:
109
+ raise Exception('Couldn\'t parse dictionary in ' + fname)
110
+
111
+
112
+ def is_same_dict_in_file(d, fname):
113
+ try:
114
+ saved_d = read_dict(fname)
115
+ return saved_d == d
116
+ except:
117
+ return False
118
+
119
+
120
+ def words_in_file(fname):
121
+ result = []
122
+ for line in open(fname).readlines():
123
+ result.extend(line.split())
124
+ return result
125
+
126
+
127
+ def elapsed_time_str(time):
128
+ s = str(time) + ' '
129
+ minute = math.floor(time / 60.0)
130
+ if minute > 60:
131
+ hour = math.floor(minute / 60.0)
132
+ partial_minute = math.fmod(time, 60.0)
133
+ s += "%.f:%02.f:" % (hour, partial_minute)
134
+ elif minute >= 1:
135
+ s += "%.f:" % minute
136
+ sec = math.fmod(time, 60.0)
137
+ if sec < 0.01:
138
+ s += "%07.4fs" % sec
139
+ else:
140
+ s += "%05.2fs" % sec
141
+ return s
142
+
143
+
144
+ class Timer:
145
+ def __init__(self):
146
+ self._elapsed = 0;
147
+ self._start = time.time()
148
+
149
+ def start(self):
150
+ self._start = time.time()
151
+ self._elapsed = 0
152
+
153
+ def stop(self):
154
+ self._elapsed = time.time() - self._start
155
+
156
+ def elapsed(self):
157
+ if self._elapsed == 0:
158
+ return time.time() - self._start
159
+ else:
160
+ return self._elapsed
161
+
162
+ def str(self):
163
+ elapsed_time = self.elapsed()
164
+ return elapsed_time_str(elapsed_time)
165
+
166
+ def __str__(self):
167
+ return self.str()
168
+
169
+
170
+ def val_range(start, end, step):
171
+ vals = []
172
+ v = start
173
+ while v <= end:
174
+ vals.append(v)
175
+ v += step
176
+ return vals
177
+
178
+
179
+ class FileException(Exception):
180
+ pass
181
+
182
+
183
+ def check_files(*fnames):
184
+ """
185
+ Checks for existence of fnames. Raises error if not found.
186
+ """
187
+ for fname in fnames:
188
+ if not os.path.isfile(fname):
189
+ raise FileException("Can't find {}".format(fname))
190
+
191
+
192
+ def which(program, other_binary_dirs=[]):
193
+ """
194
+ Reproduces Unix 'which' and looks in other_binary_dirs
195
+ """
196
+
197
+ def is_binary(fpath):
198
+ return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
199
+
200
+ fpath, fname = os.path.split(program)
201
+ if fpath:
202
+ if is_binary(program):
203
+ return program
204
+ else:
205
+ binary_dirs = os.environ["PATH"].split(os.pathsep)
206
+ binary_dirs.extend(other_binary_dirs)
207
+ for path in binary_dirs:
208
+ exe_file = os.path.join(path, program)
209
+ if is_binary(exe_file):
210
+ return exe_file
211
+ return None
212
+
213
+
214
+ def check_program(program):
215
+ if not which(program):
216
+ raise FileException("Can't find executable: " + program)
217
+
218
+
219
+ def check_output(fname, bad_words=[]):
220
+ if not os.path.isfile(fname):
221
+ raise FileException("Can't find output file: " + fname)
222
+ txt = open(fname).read()
223
+ if txt.strip() == '':
224
+ raise Exception("Empty file: " + fname)
225
+ for bad_word in bad_words:
226
+ for i_line, line in enumerate(txt.splitlines()):
227
+ if bad_word in line:
228
+ raise Exception(
229
+ "Output indicates %s error in line %d: %s" % (bad_word, i_line+1, fname))
230
+
231
+ def run_with_output(cmd):
232
+ p = subprocess.Popen(
233
+ cmd,
234
+ shell=True,
235
+ stdout=subprocess.PIPE,
236
+ stderr=subprocess.PIPE)
237
+ return p.stdout.read()
238
+
239
+
240
+ def run_with_output_file(cmd, out_fname=None, in_fname=None):
241
+ in_f = None
242
+ out_f = None
243
+
244
+ if in_fname and os.path.isfile(in_fname):
245
+ in_f = open(in_fname)
246
+
247
+ if out_fname:
248
+ log_file = out_fname + '.log'
249
+ out_f = open(log_file, 'w')
250
+ sh_file = out_fname + '.sh'
251
+ sh_cmd = cmd
252
+ if in_f:
253
+ sh_cmd += ' < ' + in_fname
254
+ if log_file:
255
+ sh_cmd += ' &> ' + log_file
256
+ open(sh_file, 'w').write(sh_cmd)
257
+ os.chmod(sh_file, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR)
258
+ stopwatch = Timer()
259
+
260
+ subprocess.call(
261
+ cmd,
262
+ shell=True,
263
+ stdin=in_f,
264
+ stdout=out_f,
265
+ stderr=out_f)
266
+
267
+ if out_fname:
268
+ stopwatch.stop()
269
+ open(out_fname + '.time', 'w').write(stopwatch.str())
270
+ out_f.close()
271
+
272
+
273
+
@@ -0,0 +1,16 @@
1
+ # encoding: utf-8
2
+
3
+ __doc__ = """
4
+
5
+ Interface 3D vector geometry library.
6
+
7
+ This is an interface to choose between the pure Python version
8
+ or the numpy version. This depends on numpy availability.
9
+ """
10
+
11
+ try:
12
+ import numpy
13
+ from .v3numpy import *
14
+ except:
15
+ from .v3array import *
16
+