Skip to content

Commit a2c0494

Browse files
committed
Fix box and time writing
1 parent 6b9d31d commit a2c0494

File tree

1 file changed

+91
-12
lines changed

1 file changed

+91
-12
lines changed

pytng/pytng.pyx

Lines changed: 91 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,12 @@ np.import_array()
1515
ctypedef enum tng_function_status: TNG_SUCCESS, TNG_FAILURE, TNG_CRITICAL
1616
ctypedef enum tng_data_type: TNG_CHAR_DATA, TNG_INT_DATA, TNG_FLOAT_DATA, TNG_DOUBLE_DATA
1717
ctypedef enum tng_hash_mode: TNG_SKIP_HASH, TNG_USE_HASH
18+
ctypedef enum tng_block_type: TNG_NON_TRAJECTORY_BLOCK, TNG_TRAJECTORY_BLOCK
19+
ctypedef enum tng_compression: TNG_UNCOMPRESSED, TNG_XTC_COMPRESSION, TNG_TNG_COMPRESSION, TNG_GZIP_COMPRESSION
20+
ctypedef enum tng_particle_dependency: TNG_NON_PARTICLE_BLOCK_DATA, TNG_PARTICLE_BLOCK_DATA
1821

1922
cdef long long TNG_TRAJ_BOX_SHAPE = 0x0000000010000000LL
23+
cdef long long TNG_TRAJ_POSITIONS = 0x0000000010000001LL
2024

2125
status_error_message = ['OK', 'Failure', 'Critical']
2226

@@ -135,6 +139,42 @@ cdef extern from "tng/tng_io.h":
135139
const tng_trajectory_t tng_data,
136140
const int64_t n)
137141

142+
tng_function_status tng_util_generic_with_time_write(
143+
const tng_trajectory_t tng_data,
144+
const int64_t frame_nr,
145+
const double time,
146+
const float *values,
147+
const int64_t n_values_per_frame,
148+
const int64_t block_id,
149+
const char *block_name,
150+
const char particle_dependency,
151+
const char compression)
152+
153+
tng_function_status tng_time_per_frame_set(
154+
const tng_trajectory_t tng_data,
155+
const double time)
156+
157+
tng_function_status tng_util_generic_with_time_write(
158+
const tng_trajectory_t tng_data,
159+
const int64_t frame_nr,
160+
const double time,
161+
const float *values,
162+
const int64_t n_values_per_frame,
163+
const int64_t block_id,
164+
const char *block_name,
165+
const char particle_dependency,
166+
const char compression)
167+
168+
tng_function_status tng_util_generic_write_interval_set(
169+
const tng_trajectory_t tng_data,
170+
const int64_t i,
171+
const int64_t n_values_per_frame,
172+
const int64_t block_id,
173+
const char *block_name,
174+
const char particle_dependency,
175+
const char compression)
176+
177+
138178
TNGFrame = namedtuple("TNGFrame", "positions time step box")
139179

140180
cdef class TNGFile:
@@ -348,14 +388,37 @@ cdef class TNGFile:
348388
cdef int64_t ok
349389
cdef np.ndarray[float, ndim=2, mode='c'] xyz
350390
cdef np.ndarray[float, ndim=2, mode='c'] box_contiguous
391+
cdef double dt
351392

352393
if self._n_frames == 0:
394+
# TODO: The number of frames per frame set should be tunable.
353395
ok = tng_num_frames_per_frame_set_set(self._traj, 1)
396+
if_not_ok(ok, 'Could not set the number of frames per frame set')
397+
# The number of atoms must be set either with a full description
398+
# of the system content (topology), or with just the number of
399+
# particles. We should fall back on the latter, but being
400+
# able to write the topology would be a nice addition
401+
# in the future.
354402
self._n_atoms = positions.shape[0]
355403
ok = tng_implicit_num_particles_set(self._traj, self.n_atoms)
356404
if_not_ok(ok, 'Could not set the number of particles')
405+
# Set the writing interval to 1 for all blocks.
406+
ok = tng_util_pos_write_interval_set(self._traj, 1)
407+
if_not_ok(ok, 'Could not set the writing interval for positions')
408+
# When we use the "tn_util_box_shape_*" functions to write the box
409+
# shape, gromacs tools fail to uncompress the data block. Instead of
410+
# using the default gzip to compress the box, we do not compress it.
411+
# ok = tng_util_box_shape_write_interval_set(self._traj, 1)
412+
ok = tng_util_generic_write_interval_set(
413+
self._traj, 1, 9,
414+
TNG_TRAJ_BOX_SHAPE,
415+
"BOX SHAPE",
416+
TNG_NON_PARTICLE_BLOCK_DATA,
417+
TNG_UNCOMPRESSED
418+
)
419+
if_not_ok(ok, 'Could not set the writing interval for the box shape')
357420
elif self.n_atoms != positions.shape[0]:
358-
message = ('Only fixed number of particles is supported. '
421+
message = ('Only fixed number of particles is currently supported. '
359422
'Cannot write {} particles instead of {}.'
360423
.format(positions.shape[0], self.n_atoms))
361424
raise NotImplementedError(message)
@@ -368,6 +431,33 @@ cdef class TNGFile:
368431
time *= 1e-12
369432
except ValueError:
370433
raise ValueError('time must be a real number or None')
434+
# The time per frame has to be set for the time to be written in
435+
# the frames.
436+
# To be able to set an arbitrary time, we need to set the time per
437+
# frame to 0 and to use one frame per frame set. Using the actual
438+
# time difference between consecutive frames can cause issues if
439+
# the difference is negative, or if the difference is 0 and the
440+
# frame is not the first of the frame set.
441+
ok = tng_time_per_frame_set(self._traj, 0)
442+
if_not_ok(ok, 'Could not set the time per frame')
443+
444+
box_contiguous = np.ascontiguousarray(box, dtype=np.float32)
445+
if time is None:
446+
ok = tng_util_box_shape_write(self._traj, self.step,
447+
&box_contiguous[0, 0])
448+
else:
449+
#ok = tng_util_box_shape_with_time_write(self._traj,
450+
# self.step,
451+
# time,
452+
# &box_contiguous[0, 0])
453+
ok = tng_util_generic_with_time_write(
454+
self._traj, self.step, time,
455+
&box[0, 0],
456+
9, TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
457+
TNG_NON_PARTICLE_BLOCK_DATA,
458+
TNG_UNCOMPRESSED
459+
)
460+
if_not_ok(ok, 'Could not write box shape')
371461

372462
xyz = np.ascontiguousarray(positions, dtype=np.float32)
373463
if time is None:
@@ -377,17 +467,6 @@ cdef class TNGFile:
377467
time, &xyz[0, 0])
378468
if_not_ok(ok, 'Could not write positions')
379469

380-
box_contiguous = np.ascontiguousarray(box, dtype=np.float32)
381-
if time is None:
382-
ok = tng_util_box_shape_write(self._traj, self.step,
383-
&box_contiguous[0, 0])
384-
else:
385-
ok = tng_util_box_shape_with_time_write(self._traj,
386-
self.step,
387-
time,
388-
&box_contiguous[0, 0])
389-
if_not_ok(ok, 'Could not write box shape')
390-
391470
self.step += 1
392471
self._n_frames += 1
393472

0 commit comments

Comments
 (0)