@@ -15,8 +15,12 @@ np.import_array()
15
15
ctypedef enum tng_function_status: TNG_SUCCESS, TNG_FAILURE, TNG_CRITICAL
16
16
ctypedef enum tng_data_type: TNG_CHAR_DATA, TNG_INT_DATA, TNG_FLOAT_DATA, TNG_DOUBLE_DATA
17
17
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
18
21
19
22
cdef long long TNG_TRAJ_BOX_SHAPE = 0x0000000010000000L L
23
+ cdef long long TNG_TRAJ_POSITIONS = 0x0000000010000001L L
20
24
21
25
status_error_message = [' OK' , ' Failure' , ' Critical' ]
22
26
@@ -135,6 +139,42 @@ cdef extern from "tng/tng_io.h":
135
139
const tng_trajectory_t tng_data,
136
140
const int64_t n)
137
141
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
+
138
178
TNGFrame = namedtuple(" TNGFrame" , " positions time step box" )
139
179
140
180
cdef class TNGFile:
@@ -348,14 +388,37 @@ cdef class TNGFile:
348
388
cdef int64_t ok
349
389
cdef np.ndarray[float , ndim= 2 , mode= ' c' ] xyz
350
390
cdef np.ndarray[float , ndim= 2 , mode= ' c' ] box_contiguous
391
+ cdef double dt
351
392
352
393
if self ._n_frames == 0 :
394
+ # TODO: The number of frames per frame set should be tunable.
353
395
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.
354
402
self ._n_atoms = positions.shape[0 ]
355
403
ok = tng_implicit_num_particles_set(self ._traj, self .n_atoms)
356
404
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' )
357
420
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. '
359
422
' Cannot write {} particles instead of {}.'
360
423
.format(positions.shape[0 ], self .n_atoms))
361
424
raise NotImplementedError (message)
@@ -368,6 +431,33 @@ cdef class TNGFile:
368
431
time *= 1e-12
369
432
except ValueError :
370
433
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' )
371
461
372
462
xyz = np.ascontiguousarray(positions, dtype = np.float32)
373
463
if time is None :
@@ -377,17 +467,6 @@ cdef class TNGFile:
377
467
time, & xyz[0 , 0 ])
378
468
if_not_ok(ok, ' Could not write positions' )
379
469
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
-
391
470
self .step += 1
392
471
self ._n_frames += 1
393
472
0 commit comments