Updated TNG to version 1.8
[gromacs.git] / src / external / tng_io / src / lib / tng_io.c
blobd5e14a64804d06ae299fa679b99a31d3fdda884f
1 /* This code is part of the tng binary trajectory format.
3 * Written by Magnus Lundborg
4 * Copyright (c) 2012-2017, The GROMACS development team.
5 * Check out http://www.gromacs.org for more information.
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the Revised BSD License.
12 /* These three definitions are required to enforce 64 bit file sizes. */
13 /* Force 64 bit variants of file access calls. */
14 #define _FILE_OFFSET_BITS 64
15 /* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
16 #define _LARGEFILE_SOURCE
17 /* Define for large files, on AIX-style hosts. */
18 #define _LARGE_FILES
20 #include "tng/tng_io.h"
22 #ifdef USE_STD_INTTYPES_H
23 #include <inttypes.h>
24 #endif
26 #include <limits.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <time.h>
30 #include <math.h>
31 #include <zlib.h>
33 #include "tng/md5.h"
34 #include "compression/tng_compress.h"
35 #include "tng/version.h"
37 #if defined( _WIN32 ) || defined( _WIN64 )
38 #ifndef fseeko
39 #define fseeko _fseeki64
40 #endif
41 #ifndef ftello
42 #ifdef __MINGW32__
43 #define ftello ftello64
44 #else
45 #define ftello _ftelli64
46 #endif
47 #endif
48 #endif
50 struct tng_bond {
51 /** One of the atoms of the bond */
52 int64_t from_atom_id;
53 /** The other atom of the bond */
54 int64_t to_atom_id;
57 struct tng_atom {
58 /** The residue containing this atom */
59 tng_residue_t residue;
60 /** A unique (per molecule) ID number of the atom */
61 int64_t id;
62 /** The atom_type (depending on the forcefield) */
63 char *atom_type;
64 /** The name of the atom */
65 char *name;
68 struct tng_residue {
69 /** The chain containing this residue */
70 tng_chain_t chain;
71 /** A unique (per chain) ID number of the residue */
72 int64_t id;
73 /** The name of the residue */
74 char *name;
75 /** The number of atoms in the residue */
76 int64_t n_atoms;
77 /** A list of atoms in the residue */
78 int64_t atoms_offset;
81 struct tng_chain {
82 /** The molecule containing this chain */
83 tng_molecule_t molecule;
84 /** A unique (per molecule) ID number of the chain */
85 int64_t id;
86 /** The name of the chain */
87 char *name;
88 /** The number of residues in the chain */
89 int64_t n_residues;
90 /** A list of residues in the chain */
91 tng_residue_t residues;
94 struct tng_molecule {
95 /** A unique ID number of the molecule */
96 int64_t id;
97 /** Quaternary structure of the molecule.
98 * 1 => monomeric
99 * 2 => dimeric
100 * 3 => trimeric
101 * etc */
102 int64_t quaternary_str;
103 /** The number of chains in the molecule */
104 int64_t n_chains;
105 /** The number of residues in the molecule */
106 int64_t n_residues;
107 /** The number of atoms in the molecule */
108 int64_t n_atoms;
109 /** The number of bonds in the molecule. If the bonds are not specified this
110 * value can be 0. */
111 int64_t n_bonds;
112 /** The name of the molecule */
113 char *name;
114 /** A list of chains in the molecule */
115 tng_chain_t chains;
116 /** A list of residues in the molecule */
117 tng_residue_t residues;
118 /** A list of the atoms in the molecule */
119 tng_atom_t atoms;
120 /** A list of the bonds in the molecule */
121 tng_bond_t bonds;
124 struct tng_gen_block {
125 /** The size of the block header in bytes */
126 int64_t header_contents_size;
127 /** The size of the block contents in bytes */
128 int64_t block_contents_size;
129 /** The ID of the block to determine its type */
130 int64_t id;
131 /** The MD5 hash of the block to verify integrity */
132 char md5_hash[TNG_MD5_HASH_LEN];
133 /** The name of the block */
134 char *name;
135 /** The library version used to write the block */
136 int64_t block_version;
137 int64_t alt_hash_type;
138 int64_t alt_hash_len;
139 char *alt_hash;
140 int64_t signature_type;
141 int64_t signature_len;
142 char *signature;
143 /** The full block header contents */
144 char *header_contents;
145 /** The full block contents */
146 char *block_contents;
149 struct tng_particle_mapping {
150 /** The index number of the first particle in this mapping block */
151 int64_t num_first_particle;
152 /** The number of particles list in this mapping block */
153 int64_t n_particles;
154 /** the mapping of index numbers to the real particle numbers in the
155 * trajectory. real_particle_numbers[0] is the real particle number
156 * (as it is numbered in the molecular system) of the first particle
157 * in the data blocks covered by this particle mapping block */
158 int64_t *real_particle_numbers;
161 struct tng_trajectory_frame_set {
162 /** The number of different particle mapping blocks present. */
163 int64_t n_mapping_blocks;
164 /** The atom mappings of this frame set */
165 struct tng_particle_mapping *mappings;
166 /** The first frame of this frame set */
167 int64_t first_frame;
168 /** The number of frames in this frame set */
169 int64_t n_frames;
170 /** The number of written frames in this frame set (used when writing one
171 * frame at a time). */
172 int64_t n_written_frames;
173 /** The number of frames not yet written to file in this frame set
174 * (used from the utility functions to finish the writing properly. */
175 int64_t n_unwritten_frames;
178 /** A list of the number of each molecule type - only used when using
179 * variable number of atoms */
180 int64_t *molecule_cnt_list;
181 /** The number of particles/atoms - only used when using variable number
182 * of atoms */
183 int64_t n_particles;
184 /** The file position of the next frame set */
185 int64_t next_frame_set_file_pos;
186 /** The file position of the previous frame set */
187 int64_t prev_frame_set_file_pos;
188 /** The file position of the frame set one long stride step ahead */
189 int64_t medium_stride_next_frame_set_file_pos;
190 /** The file position of the frame set one long stride step behind */
191 int64_t medium_stride_prev_frame_set_file_pos;
192 /** The file position of the frame set one long stride step ahead */
193 int64_t long_stride_next_frame_set_file_pos;
194 /** The file position of the frame set one long stride step behind */
195 int64_t long_stride_prev_frame_set_file_pos;
196 /** Time stamp (in seconds) of first frame in frame set */
197 double first_frame_time;
199 /* The data blocks in a frame set are trajectory data blocks */
200 /** The number of trajectory data blocks of particle dependent data */
201 int n_particle_data_blocks;
202 /** A list of data blocks containing particle dependent data */
203 struct tng_data *tr_particle_data;
204 /** The number of trajectory data blocks independent of particles */
205 int n_data_blocks;
206 /** A list of data blocks containing particle indepdendent data */
207 struct tng_data *tr_data;
210 /* FIXME: Should there be a pointer to a tng_gen_block from each data block? */
211 struct tng_data {
212 /** The block ID of the data block containing this particle data.
213 * This is used to determine the kind of data that is stored */
214 int64_t block_id;
215 /** The name of the data block. This is used to determine the kind of
216 * data that is stored */
217 char *block_name;
218 /** The type of data stored. */
219 char datatype;
220 /** A flag to indicate if this data block contains frame and/or particle dependent
221 * data */
222 char dependency;
223 /** The frame number of the first data value */
224 int64_t first_frame_with_data;
225 /** The number of frames in this frame set */
226 int64_t n_frames;
227 /** The number of values stored per frame */
228 int64_t n_values_per_frame;
229 /** The number of frames between each data point - e.g. when
230 * storing sparse data. */
231 int64_t stride_length;
232 /** ID of the CODEC used for compression 0 == no compression. */
233 int64_t codec_id;
234 /** If reading one frame at a time this is the last read frame */
235 int64_t last_retrieved_frame;
236 /** The multiplier used for getting integer values for compression */
237 double compression_multiplier;
238 /** A 1-dimensional array of values of length
239 * [sizeof (datatype)] * n_frames * n_particles * n_values_per_frame */
240 void *values;
241 /** If storing character data store it in a 3-dimensional array */
242 char ****strings;
246 struct tng_trajectory {
247 /** The path of the input trajectory file */
248 char *input_file_path;
249 /** A handle to the input file */
250 FILE *input_file;
251 /** The length of the input file */
252 int64_t input_file_len;
253 /** The path of the output trajectory file */
254 char *output_file_path;
255 /** A handle to the output file */
256 FILE *output_file;
257 /** Function to swap 32 bit values to and from the endianness of the
258 * input file */
259 tng_function_status (*input_endianness_swap_func_32)(const tng_trajectory_t, uint32_t *);
260 /** Function to swap 64 bit values to and from the endianness of the
261 * input file */
262 tng_function_status (*input_endianness_swap_func_64)(const tng_trajectory_t, uint64_t *);
263 /** Function to swap 32 bit values to and from the endianness of the
264 * input file */
265 tng_function_status (*output_endianness_swap_func_32)(const tng_trajectory_t, uint32_t *);
266 /** Function to swap 64 bit values to and from the endianness of the
267 * input file */
268 tng_function_status (*output_endianness_swap_func_64)(const tng_trajectory_t, uint64_t *);
269 /** The endianness of 32 bit values of the current computer */
270 char endianness_32;
271 /** The endianness of 64 bit values of the current computer */
272 char endianness_64;
274 /** The name of the program producing this trajectory */
275 char *first_program_name;
276 /** The forcefield used in the simulations */
277 char *forcefield_name;
278 /** The name of the user running the simulations */
279 char *first_user_name;
280 /** The name of the computer on which the simulations were performed */
281 char *first_computer_name;
282 /** The PGP signature of the user creating the file. */
283 char *first_pgp_signature;
284 /** The name of the program used when making last modifications to the
285 * file */
286 char *last_program_name;
287 /** The name of the user making the last modifications to the file */
288 char *last_user_name;
289 /** The name of the computer on which the last modifications were made */
290 char *last_computer_name;
291 /** The PGP signature of the user making the last modifications to the
292 * file. */
293 char *last_pgp_signature;
294 /** The time (n seconds since 1970) when the file was created */
295 int64_t time;
296 /** The exponential of the value of the distance unit used. The default
297 * distance unit is nm (1e-9), i.e. distance_unit_exponential = -9. If
298 * the measurements are in Ã… the distance_unit_exponential = -10. */
299 int64_t distance_unit_exponential;
301 /** A flag indicating if the number of atoms can vary throughout the
302 * simulation, e.g. using a grand canonical ensemble */
303 char var_num_atoms_flag;
304 /** The number of frames in a frame set. It is allowed to have frame sets
305 * with fewer frames, but this will help searching for specific frames */
306 int64_t frame_set_n_frames;
307 /** The number of frame sets in a medium stride step */
308 int64_t medium_stride_length;
309 /** The number of frame sets in a long stride step */
310 int64_t long_stride_length;
311 /** The current (can change from one frame set to another) time length
312 * (in seconds) of one frame */
313 double time_per_frame;
315 /** The number of different kinds of molecules in the trajectory */
316 int64_t n_molecules;
317 /** A list of molecules in the trajectory */
318 tng_molecule_t molecules;
319 /** A list of the count of each molecule - if using variable number of
320 * particles this will be specified in each frame set */
321 int64_t *molecule_cnt_list;
322 /** The total number of particles/atoms. If using variable number of
323 * particles this will be specified in each frame set */
324 int64_t n_particles;
326 /** The pos in the src file of the first frame set */
327 int64_t first_trajectory_frame_set_input_file_pos;
328 /** The pos in the dest file of the first frame set */
329 int64_t first_trajectory_frame_set_output_file_pos;
330 /** The pos in the src file of the last frame set */
331 int64_t last_trajectory_frame_set_input_file_pos;
332 /** The pos in the dest file of the last frame set */
333 int64_t last_trajectory_frame_set_output_file_pos;
334 /** The currently active frame set */
335 struct tng_trajectory_frame_set current_trajectory_frame_set;
336 /** The pos in the src file of the current frame set */
337 int64_t current_trajectory_frame_set_input_file_pos;
338 /** The pos in the dest file of the current frame set */
339 int64_t current_trajectory_frame_set_output_file_pos;
340 /** The number of frame sets in the trajectory N.B. Not saved in file and
341 * cannot be trusted to be up-to-date */
342 int64_t n_trajectory_frame_sets;
344 /* These data blocks are non-trajectory data blocks */
345 /** The number of non-frame dependent particle dependent data blocks */
346 int n_particle_data_blocks;
347 /** A list of data blocks containing particle dependent data */
348 struct tng_data *non_tr_particle_data;
350 /** The number of frame and particle independent data blocks */
351 int n_data_blocks;
352 /** A list of frame and particle indepdendent data blocks */
353 struct tng_data *non_tr_data;
355 /** TNG compression algorithm for compressing positions */
356 int *compress_algo_pos;
357 /** TNG compression algorithm for compressing velocities */
358 int *compress_algo_vel;
359 /** The precision used for lossy compression */
360 double compression_precision;
363 #ifndef USE_WINDOWS
364 #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)
365 #define USE_WINDOWS
366 #endif /* win32... */
367 #endif /* not defined USE_WINDOWS */
369 #ifdef USE_WINDOWS
370 #define TNG_INLINE __inline
371 #define TNG_SNPRINTF _snprintf
372 #else
373 #define TNG_INLINE inline
374 #define TNG_SNPRINTF snprintf
375 #endif
377 static TNG_INLINE size_t tng_min_size(const size_t a, const size_t b)
379 return (a < b ? a : b);
382 static TNG_INLINE int64_t tng_min_i64(const int64_t a, const int64_t b)
384 return (a < b ? a : b);
387 static TNG_INLINE int64_t tng_max_i64(const int64_t a, const int64_t b)
389 return (a > b ? a : b);
393 * @brief This function swaps the byte order of a 32 bit numerical variable
394 * to big endian.
395 * @param tng_data is a trajectory data container.
396 * @param v is a pointer to a 32 bit numerical value (float or integer).
397 * @details The function does not only work with integer, but e.g. floats need casting.
398 * If the byte order is already big endian no change is needed.
399 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
400 * byte order is not recognised.
402 static tng_function_status tng_swap_byte_order_big_endian_32
403 (const tng_trajectory_t tng_data, uint32_t *v)
405 switch(tng_data->endianness_32)
407 case TNG_LITTLE_ENDIAN_32: /* Byte order is reversed. */
408 *v = ((*v & 0xFF000000) >> 24) | /* Move first byte to end */
409 ((*v & 0x00FF0000) >> 8) | /* Move 2nd byte to pos 3 */
410 ((*v & 0x0000FF00) << 8) | /* Move 3rd byte to pos 2 */
411 ((*v & 0x000000FF) << 24); /* Move last byte to first */
413 return(TNG_SUCCESS);
415 case TNG_BYTE_PAIR_SWAP_32: /* byte pair swap */
416 *v = ((*v & 0xFFFF0000) >> 16) |
417 ((*v & 0x0000FFFF) << 16);
419 return(TNG_SUCCESS);
421 case TNG_BIG_ENDIAN_32: /* Already correct */
422 return(TNG_SUCCESS);
424 default:
425 return(TNG_FAILURE);
430 * @brief This function swaps the byte order of a 64 bit numerical variable
431 * to big endian.
432 * @param tng_data is a trajectory data container.
433 * @param v is a pointer to a 64 bit numerical value (double or integer).
434 * @details The function does not only work with integer, but e.g. floats need casting.
435 * The byte order swapping routine can convert four different byte
436 * orders to big endian.
437 * If the byte order is already big endian no change is needed.
438 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
439 * byte order is not recognised.
441 static tng_function_status tng_swap_byte_order_big_endian_64
442 (const tng_trajectory_t tng_data, uint64_t *v)
444 switch(tng_data->endianness_64)
446 case TNG_LITTLE_ENDIAN_64: /* Byte order is reversed. */
447 *v = ((*v & 0xFF00000000000000LL) >> 56) | /* Move first byte to end */
448 ((*v & 0x00FF000000000000LL) >> 40) | /* Move 2nd byte to pos 7 */
449 ((*v & 0x0000FF0000000000LL) >> 24) | /* Move 3rd byte to pos 6 */
450 ((*v & 0x000000FF00000000LL) >> 8 ) | /* Move 4th byte to pos 5 */
451 ((*v & 0x00000000FF000000LL) << 8 ) | /* Move 5th byte to pos 4 */
452 ((*v & 0x0000000000FF0000LL) << 24) | /* Move 6th byte to pos 3 */
453 ((*v & 0x000000000000FF00LL) << 40) | /* Move 7th byte to pos 2 */
454 ((*v & 0x00000000000000FFLL) << 56); /* Move last byte to first */
456 return(TNG_SUCCESS);
458 case TNG_QUAD_SWAP_64: /* Byte quad swap */
459 *v = ((*v & 0xFFFFFFFF00000000LL) >> 32) |
460 ((*v & 0x00000000FFFFFFFFLL) << 32);
462 return(TNG_SUCCESS);
464 case TNG_BYTE_PAIR_SWAP_64: /* Byte pair swap */
465 *v = ((*v & 0xFFFF0000FFFF0000LL) >> 16) |
466 ((*v & 0x0000FFFF0000FFFFLL) << 16);
468 return(TNG_SUCCESS);
470 case TNG_BYTE_SWAP_64: /* Byte swap */
471 *v = ((*v & 0xFF00FF00FF00FF00LL) >> 8) |
472 ((*v & 0x00FF00FF00FF00FFLL) << 8);
474 return(TNG_SUCCESS);
476 case TNG_BIG_ENDIAN_64: /* Already correct */
477 return(TNG_SUCCESS);
479 default:
480 return(TNG_FAILURE);
485 * @brief This function swaps the byte order of a 32 bit numerical variable
486 * to little endian.
487 * @param tng_data is a trajectory data container.
488 * @param v is a pointer to a 32 bit numerical value (float or integer).
489 * @details The function does not only work with integer, but e.g. floats need casting.
490 * If the byte order is already little endian no change is needed.
491 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
492 * byte order is not recognised.
494 static tng_function_status tng_swap_byte_order_little_endian_32
495 (const tng_trajectory_t tng_data, uint32_t *v)
497 switch(tng_data->endianness_32)
499 case TNG_LITTLE_ENDIAN_32: /* Already correct */
500 return(TNG_SUCCESS);
502 case TNG_BYTE_PAIR_SWAP_32: /* byte pair swapped big endian to little endian */
503 *v = ((*v & 0xFF00FF00) >> 8) |
504 ((*v & 0x00FF00FF) << 8);
506 return(TNG_SUCCESS);
508 case TNG_BIG_ENDIAN_32: /* Byte order is reversed. */
509 *v = ((*v & 0xFF000000) >> 24) | /* Move first byte to end */
510 ((*v & 0x00FF0000) >> 8) | /* Move 2nd byte to pos 3 */
511 ((*v & 0x0000FF00) << 8) | /* Move 3rd byte to pos 2 */
512 ((*v & 0x000000FF) << 24); /* Move last byte to first */
514 return(TNG_SUCCESS);
516 default:
517 return(TNG_FAILURE);
522 * @brief This function swaps the byte order of a 64 bit numerical variable
523 * to little endian.
524 * @param tng_data is a trajectory data container.
525 * @param v is a pointer to a 64 bit numerical value (double or integer).
526 * @details The function does not only work with integer, but e.g. floats need casting.
527 * The byte order swapping routine can convert four different byte
528 * orders to little endian.
529 * If the byte order is already little endian no change is needed.
530 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
531 * byte order is not recognised.
533 static tng_function_status tng_swap_byte_order_little_endian_64
534 (const tng_trajectory_t tng_data, uint64_t *v)
536 switch(tng_data->endianness_64)
538 case TNG_LITTLE_ENDIAN_64: /* Already correct */
539 return(TNG_SUCCESS);
541 case TNG_QUAD_SWAP_64: /* Byte quad swapped big endian to little endian */
542 *v = ((*v & 0xFF000000FF000000LL) >> 24) |
543 ((*v & 0x00FF000000FF0000LL) >> 8) |
544 ((*v & 0x0000FF000000FF00LL) << 8) |
545 ((*v & 0x000000FF000000FFLL) << 24);
547 return(TNG_SUCCESS);
549 case TNG_BYTE_PAIR_SWAP_64: /* Byte pair swapped big endian to little endian */
550 *v = ((*v & 0xFF00FF0000000000LL) >> 40) |
551 ((*v & 0x00FF00FF00000000LL) >> 24) |
552 ((*v & 0x00000000FF00FF00LL) << 24) |
553 ((*v & 0x0000000000FF00FFLL) << 40);
555 return(TNG_SUCCESS);
557 case TNG_BYTE_SWAP_64: /* Byte swapped big endian to little endian */
558 *v = ((*v & 0xFFFF000000000000LL) >> 48) |
559 ((*v & 0x0000FFFF00000000LL) >> 16) |
560 ((*v & 0x00000000FFFF0000LL) << 16) |
561 ((*v & 0x000000000000FFFFLL) << 48);
563 return(TNG_SUCCESS);
565 case TNG_BIG_ENDIAN_64: /* Byte order is reversed. */
566 *v = ((*v & 0xFF00000000000000LL) >> 56) | /* Move first byte to end */
567 ((*v & 0x00FF000000000000LL) >> 40) | /* Move 2nd byte to pos 7 */
568 ((*v & 0x0000FF0000000000LL) >> 24) | /* Move 3rd byte to pos 6 */
569 ((*v & 0x000000FF00000000LL) >> 8 ) | /* Move 4th byte to pos 5 */
570 ((*v & 0x00000000FF000000LL) << 8 ) | /* Move 5th byte to pos 4 */
571 ((*v & 0x0000000000FF0000LL) << 24) | /* Move 6th byte to pos 3 */
572 ((*v & 0x000000000000FF00LL) << 40) | /* Move 7th byte to pos 2 */
573 ((*v & 0x00000000000000FFLL) << 56); /* Move last byte to first */
575 return(TNG_SUCCESS);
577 default:
578 return(TNG_FAILURE);
583 * @brief Read a NULL terminated string from a file.
584 * @param tng_data is a trajectory data container
585 * @param str is a pointer to the character string that will
586 * contain the read string. *str is reallocated in the function
587 * and must be NULL or pointing at already allocated memory.
588 * @param hash_mode is an option to decide whether to use the md5 hash or not.
589 * @param md5_state is a pointer to the current md5 storage, which will be
590 * appended with str if hash_mode == TNG_USE_HASH.
591 * @param line_nr is the line number where this function was called, to be
592 * able to give more useful error messages.
594 static tng_function_status tng_freadstr(const tng_trajectory_t tng_data,
595 char **str,
596 const char hash_mode,
597 md5_state_t *md5_state,
598 const int line_nr)
600 char temp[TNG_MAX_STR_LEN], *temp_alloc;
601 int c, count = 0;
605 c = fgetc(tng_data->input_file);
607 if (c == EOF)
609 /* Clear file error flag and return -1 if EOF is read.*/
610 clearerr(tng_data->input_file);
611 return TNG_FAILURE;
613 else
615 /* Cast c to char */
616 temp[count++] = (char) c;
618 } while ((temp[count-1] != '\0') && (count < TNG_MAX_STR_LEN));
620 temp_alloc = (char *)realloc(*str, count);
621 if(!temp_alloc)
623 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n", __FILE__, line_nr);
624 free(*str);
625 *str = 0;
626 return TNG_FAILURE;
628 *str = temp_alloc;
630 strncpy(*str, temp, count);
632 if(hash_mode == TNG_USE_HASH)
634 md5_append(md5_state, (md5_byte_t *)*str, count);
637 return TNG_SUCCESS;
641 * @brief Write a NULL terminated string to a file.
642 * @param tng_data is a trajectory data container
643 * @param str is a pointer to the character string should be written.
644 * @param hash_mode is an option to decide whether to use the md5 hash or not.
645 * @param md5_state is a pointer to the current md5 storage, which will be
646 * appended with str if hash_mode == TNG_USE_HASH.
647 * @param line_nr is the line number where this function was called, to be
648 * able to give more useful error messages.
650 static TNG_INLINE tng_function_status tng_fwritestr(tng_trajectory_t tng_data,
651 const char *str,
652 const char hash_mode,
653 md5_state_t *md5_state,
654 const int line_nr)
656 size_t len;
658 len = tng_min_size(strlen(str) + 1, TNG_MAX_STR_LEN);
660 if(fwrite(str, len, 1, tng_data->output_file) != 1)
662 fprintf(stderr, "TNG library: Could not write block data. %s: %d\n", __FILE__, line_nr);
663 return(TNG_CRITICAL);
666 if(hash_mode == TNG_USE_HASH)
668 md5_append(md5_state, (md5_byte_t *)str, len);
671 return(TNG_SUCCESS);
675 * @brief Read a numerical value from file.
676 * The byte order will be swapped if need be.
677 * @param tng_data is a trajectory data container
678 * @param dest is a pointer to where to store the read data.
679 * @param len is the length (in bytes) of the numerical data type. Should
680 * be 8 for 64 bit, 4 for 32 bit or 1 for a single byte flag.
681 * @param hash_mode is an option to decide whether to use the md5 hash or not.
682 * @param md5_state is a pointer to the current md5 storage, which will be
683 * appended with str if hash_mode == TNG_USE_HASH.
684 * @param line_nr is the line number where this function was called, to be
685 * able to give more useful error messages.
687 static TNG_INLINE tng_function_status tng_file_input_numerical
688 (const tng_trajectory_t tng_data,
689 void *dest,
690 const size_t len,
691 const char hash_mode,
692 md5_state_t *md5_state,
693 const int line_nr)
695 if(fread(dest, len, 1, tng_data->input_file) == 0)
697 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, line_nr);
698 return(TNG_CRITICAL);
700 if(hash_mode == TNG_USE_HASH)
702 md5_append(md5_state, (md5_byte_t *)dest, len);
704 switch(len)
706 case 8:
707 if(tng_data->input_endianness_swap_func_64 &&
708 tng_data->input_endianness_swap_func_64(tng_data, (uint64_t *)dest) != TNG_SUCCESS)
710 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
711 __FILE__, line_nr);
713 break;
714 case 4:
715 if(tng_data->input_endianness_swap_func_32 &&
716 tng_data->input_endianness_swap_func_32(tng_data, (uint32_t *)dest) != TNG_SUCCESS)
718 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
719 __FILE__, line_nr);
721 break;
722 default:
723 break;
726 return(TNG_SUCCESS);
730 * @brief Write a numerical value to file.
731 * The byte order will be swapped if need be.
732 * @param tng_data is a trajectory data container
733 * @param src is a pointer to the data to write.
734 * @param len is the length (in bytes) of the numerical data type. Should
735 * be 8 for 64 bit, 4 for 32 bit or 1 for a single byte flag.
736 * @param hash_mode is an option to decide whether to use the md5 hash or not.
737 * @param md5_state is a pointer to the current md5 storage, which will be
738 * appended with str if hash_mode == TNG_USE_HASH.
739 * @param line_nr is the line number where this function was called, to be
740 * able to give more useful error messages.
742 static TNG_INLINE tng_function_status tng_file_output_numerical
743 (const tng_trajectory_t tng_data,
744 const void *src,
745 const size_t len,
746 const char hash_mode,
747 md5_state_t *md5_state,
748 const int line_nr)
750 uint32_t temp_i32;
751 uint64_t temp_i64;
753 switch(len)
755 case 8:
756 temp_i64 = *((uint64_t *)src);
757 if(tng_data->output_endianness_swap_func_64 &&
758 tng_data->output_endianness_swap_func_64(tng_data, &temp_i64) != TNG_SUCCESS)
760 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
761 __FILE__, line_nr);
763 if(fwrite(&temp_i64, len, 1, tng_data->output_file) != 1)
765 fprintf(stderr, "TNG library: Could not write data. %s: %d\n", __FILE__, line_nr);
766 return(TNG_CRITICAL);
768 if(hash_mode == TNG_USE_HASH)
770 md5_append(md5_state, (md5_byte_t *)&temp_i64, len);
772 break;
773 case 4:
774 temp_i32 = *((uint32_t *)src);
775 if(tng_data->output_endianness_swap_func_32 &&
776 tng_data->output_endianness_swap_func_32(tng_data, &temp_i32) != TNG_SUCCESS)
778 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
779 __FILE__, line_nr);
781 if(fwrite(&temp_i32, len, 1, tng_data->output_file) != 1)
783 fprintf(stderr, "TNG library: Could not write data. %s: %d\n", __FILE__, line_nr);
784 return(TNG_CRITICAL);
786 if(hash_mode == TNG_USE_HASH)
788 md5_append(md5_state, (md5_byte_t *)&temp_i32, len);
790 break;
791 default:
792 if(fwrite(src, len, 1, tng_data->output_file) != 1)
794 fprintf(stderr, "TNG library: Could not write data. %s: %d\n", __FILE__, line_nr);
795 return(TNG_CRITICAL);
797 if(hash_mode == TNG_USE_HASH)
799 md5_append(md5_state, (md5_byte_t *)src, len);
801 break;
804 return(TNG_SUCCESS);
808 * @brief Generate the md5 hash of a block.
809 * The hash is created based on the actual block contents.
810 * @param block is a general block container.
811 * @return TNG_SUCCESS (0) if successful.
813 static tng_function_status tng_block_md5_hash_generate(const tng_gen_block_t block)
815 md5_state_t md5_state;
817 md5_init(&md5_state);
818 md5_append(&md5_state, (md5_byte_t *)block->block_contents,
819 (int)block->block_contents_size);
820 md5_finish(&md5_state, (md5_byte_t *)block->md5_hash);
822 return(TNG_SUCCESS);
826 * @brief If there is data left in the block read that to append that to the MD5 hash.
827 * @param tng_data is a trajectory data container.
828 * @param block is the data block that is being read.
829 * @param start_pos is the file position where the block started.
830 * @param md5_state is the md5 to which the md5 of the remaining block
831 * will be appended.
832 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
833 * error has occured.
835 static tng_function_status tng_md5_remaining_append(const tng_trajectory_t tng_data,
836 const tng_gen_block_t block,
837 const int64_t start_pos,
838 md5_state_t *md5_state)
840 int64_t curr_file_pos;
841 char *temp_data;
843 curr_file_pos = ftello(tng_data->input_file);
844 if(curr_file_pos < start_pos + block->block_contents_size)
846 temp_data = (char *)malloc(start_pos + block->block_contents_size - curr_file_pos);
847 if(!temp_data)
849 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
850 __FILE__, __LINE__);
851 return(TNG_CRITICAL);
853 if(fread(temp_data, start_pos + block->block_contents_size - curr_file_pos,
854 1, tng_data->input_file) == 0)
856 fprintf(stderr, "TNG library: Cannot read remaining part of block to generate MD5 sum. %s: %d\n", __FILE__, __LINE__);
857 free(temp_data);
858 return(TNG_CRITICAL);
860 md5_append(md5_state, (md5_byte_t *)temp_data,
861 start_pos + block->block_contents_size - curr_file_pos);
862 free(temp_data);
865 return(TNG_SUCCESS);
869 * @brief Open the input file if it is not already opened.
870 * @param tng_data is a trajectory data container.
871 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
872 * error has occured.
874 static tng_function_status tng_input_file_init(const tng_trajectory_t tng_data)
876 int64_t file_pos;
878 if(!tng_data->input_file)
880 if(!tng_data->input_file_path)
882 fprintf(stderr, "TNG library: No file specified for reading. %s: %d\n",
883 __FILE__, __LINE__);
884 return(TNG_CRITICAL);
886 tng_data->input_file = fopen(tng_data->input_file_path, "rb");
887 if(!tng_data->input_file)
889 fprintf(stderr, "TNG library: Cannot open file %s. %s: %d\n",
890 tng_data->input_file_path, __FILE__, __LINE__);
891 return(TNG_CRITICAL);
895 if(!tng_data->input_file_len)
897 file_pos = ftello(tng_data->input_file);
898 fseeko(tng_data->input_file, 0, SEEK_END);
899 tng_data->input_file_len = ftello(tng_data->input_file);
900 fseeko(tng_data->input_file, file_pos, SEEK_SET);
903 return(TNG_SUCCESS);
907 * @brief Open the output file if it is not already opened
908 * @param tng_data is a trajectory data container.
909 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
910 * error has occured.
912 static tng_function_status tng_output_file_init(const tng_trajectory_t tng_data)
914 if(!tng_data->output_file)
916 if(!tng_data->output_file_path)
918 fprintf(stderr, "TNG library: No file specified for writing. %s: %d\n",
919 __FILE__, __LINE__);
920 return(TNG_CRITICAL);
923 tng_data->output_file = fopen(tng_data->output_file_path, "wb+");
925 if(!tng_data->output_file)
927 fprintf(stderr, "TNG library: Cannot open file %s. %s: %d\n",
928 tng_data->output_file_path, __FILE__, __LINE__);
929 return(TNG_CRITICAL);
932 return(TNG_SUCCESS);
936 * @brief Setup a file block container.
937 * @param block_p a pointer to memory to initialise as a file block container.
938 * @details Memory is allocated during initialisation.
939 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
940 * error has occured.
942 static tng_function_status tng_block_init(struct tng_gen_block **block_p)
944 tng_gen_block_t block;
946 *block_p = (struct tng_gen_block *)malloc(sizeof(struct tng_gen_block));
947 if(!*block_p)
949 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n", __FILE__, __LINE__);
950 return(TNG_CRITICAL);
953 block = *block_p;
955 block->id = -1;
956 /* Reset the md5_hash */
957 memset(block->md5_hash, '\0', TNG_MD5_HASH_LEN);
958 block->name = 0;
959 block->block_version = TNG_API_VERSION;
960 block->header_contents = 0;
961 block->header_contents_size = 0;
962 block->block_contents = 0;
963 block->block_contents_size = 0;
965 return(TNG_SUCCESS);
969 * @brief Clean up a file block container.
970 * @param block_p a pointer to the file block container to destroy.
971 * @details All allocated memory in the data structure is freed, as well as
972 * block_p itself.
973 * @return TNG_SUCCESS (0) if successful.
975 static tng_function_status tng_block_destroy(struct tng_gen_block **block_p)
977 tng_gen_block_t block = *block_p;
979 if(!*block_p)
981 return(TNG_SUCCESS);
984 /* fprintf(stderr, "TNG library: Destroying block\n"); */
985 if(block->name)
987 free(block->name);
988 block->name = 0;
990 if(block->header_contents)
992 free(block->header_contents);
993 block->header_contents = 0;
995 if(block->block_contents)
997 free(block->block_contents);
998 block->block_contents = 0;
1001 free(*block_p);
1002 *block_p = 0;
1004 return(TNG_SUCCESS);
1008 * @brief Read the header of a data block, regardless of its type
1009 * @param tng_data is a trajectory data container.
1010 * @param block is a general block container.
1011 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE(1) if a minor
1012 * error has occured (not able to read the header size, thus skipping
1013 * the block) or TNG_CRITICAL (2) if a major error has occured.
1015 static tng_function_status tng_block_header_read
1016 (const tng_trajectory_t tng_data, const tng_gen_block_t block)
1018 int64_t start_pos;
1020 TNG_ASSERT(block != 0, "TNG library: Trying to read to uninitialized block (NULL pointer).");
1022 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
1024 return(TNG_CRITICAL);
1027 start_pos = ftello(tng_data->input_file);
1029 /* First read the header size to be able to read the whole header. */
1030 if(fread(&block->header_contents_size, sizeof(block->header_contents_size),
1031 1, tng_data->input_file) == 0)
1033 fprintf(stderr, "TNG library: Cannot read header size. %s: %d\n",
1034 __FILE__, __LINE__);
1035 return(TNG_CRITICAL);
1038 if(block->header_contents_size == 0)
1040 block->id = -1;
1041 return(TNG_FAILURE);
1044 /* If this was the size of the general info block check the endianness */
1045 if(ftello(tng_data->input_file) < 9)
1047 /* File is little endian */
1048 if ( *((const char*)&block->header_contents_size) != 0x00 &&
1049 *((const char*)(&block->header_contents_size) + 7) == 0x00)
1051 /* If the architecture endianness is little endian no byte swap
1052 * will be needed. Otherwise use the functions to swap to little
1053 * endian */
1054 if(tng_data->endianness_32 == TNG_LITTLE_ENDIAN_32)
1056 tng_data->input_endianness_swap_func_32 = 0;
1058 else
1060 tng_data->input_endianness_swap_func_32 =
1061 &tng_swap_byte_order_little_endian_32;
1063 if(tng_data->endianness_64 == TNG_LITTLE_ENDIAN_64)
1065 tng_data->input_endianness_swap_func_64 = 0;
1067 else
1069 tng_data->input_endianness_swap_func_64 =
1070 &tng_swap_byte_order_little_endian_64;
1073 /* File is big endian */
1074 else
1076 /* If the architecture endianness is big endian no byte swap
1077 * will be needed. Otherwise use the functions to swap to big
1078 * endian */
1079 if(tng_data->endianness_32 == TNG_BIG_ENDIAN_32)
1081 tng_data->input_endianness_swap_func_32 = 0;
1083 else
1085 tng_data->input_endianness_swap_func_32 =
1086 &tng_swap_byte_order_big_endian_32;
1088 if(tng_data->endianness_64 == TNG_BIG_ENDIAN_64)
1090 tng_data->input_endianness_swap_func_64 = 0;
1092 else
1094 tng_data->input_endianness_swap_func_64 =
1095 &tng_swap_byte_order_big_endian_64;
1100 if(tng_data->input_endianness_swap_func_64 &&
1101 tng_data->input_endianness_swap_func_64(tng_data, (uint64_t *)&block->header_contents_size) != TNG_SUCCESS)
1103 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1104 __FILE__, __LINE__);
1107 if(tng_file_input_numerical(tng_data, &block->block_contents_size,
1108 sizeof(block->block_contents_size),
1109 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
1111 return(TNG_CRITICAL);
1114 if(tng_file_input_numerical(tng_data, &block->id,
1115 sizeof(block->id),
1116 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
1118 return(TNG_CRITICAL);
1121 if(fread(block->md5_hash, TNG_MD5_HASH_LEN, 1, tng_data->input_file) == 0)
1123 fprintf(stderr, "TNG library: Cannot read block header. %s: %d\n", __FILE__, __LINE__);
1124 return(TNG_CRITICAL);
1127 tng_freadstr(tng_data, &block->name, TNG_SKIP_HASH, 0, __LINE__);
1129 if(tng_file_input_numerical(tng_data, &block->block_version,
1130 sizeof(block->block_version),
1131 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
1133 return(TNG_CRITICAL);
1136 fseeko(tng_data->input_file, start_pos + block->header_contents_size, SEEK_SET);
1138 return(TNG_SUCCESS);
1142 * @brief Write a whole block, both header and contents, regardless of it type
1143 * @param tng_data is a trajectory data container.
1144 * @param block is a general block container.
1145 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if a minor error
1146 * has occurred or TNG_CRITICAL (2) if a major error has occured.
1148 /* Disabled until it is used.*/
1150 // static tng_function_status tng_block_verbatim_write(tng_trajectory_t tng_data,
1151 // tng_gen_block_t block)
1152 // {
1153 // if(!block->header_contents)
1154 // {
1155 // fprintf(stderr, "TNG library: No contents to write. %s: %d\n", __FILE__, __LINE__);
1156 // return(TNG_FAILURE);
1157 // }
1158 // if(fwrite(block->header_contents, block->header_contents_size, 1,
1159 // tng_data->output_file) != 1)
1160 // {
1161 // fprintf(stderr, "TNG library: Could not write all header data. %s: %d\n",
1162 // __FILE__, __LINE__);
1163 // return(TNG_CRITICAL);
1164 // }
1166 // if(!block->block_contents)
1167 // {
1168 // fprintf(stderr, "TNG library: No block data to write. %s: %d\n",
1169 // __FILE__, __LINE__);
1170 // return(TNG_FAILURE);
1171 // }
1172 // if(fwrite(block->block_contents, block->block_contents_size, 1,
1173 // tng_data->output_file) != 1)
1174 // {
1175 // fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n",
1176 // __FILE__, __LINE__);
1177 // return(TNG_CRITICAL);
1178 // }
1179 // return(TNG_SUCCESS);
1180 // }
1184 * @brief Update the md5 hash of a block already written to the file
1185 * @param tng_data is a trajectory data container.
1186 * @param block is the block, of which to update the md5 hash.
1187 * @param header_start_pos is the file position where the block header starts.
1188 * @param contents_start_pos is the file position where the block contents
1189 * start.
1190 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
1191 * error has occured.
1193 static tng_function_status tng_md5_hash_update(const tng_trajectory_t tng_data,
1194 const tng_gen_block_t block,
1195 const int64_t header_start_pos,
1196 const int64_t contents_start_pos)
1198 if(block->block_contents)
1200 free(block->block_contents);
1203 block->block_contents = (char *)malloc(block->block_contents_size);
1204 if(!block->block_contents)
1206 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n", __FILE__, __LINE__);
1207 return(TNG_CRITICAL);
1210 fseeko(tng_data->output_file, contents_start_pos, SEEK_SET);
1211 if(fread(block->block_contents, block->block_contents_size, 1,
1212 tng_data->output_file) == 0)
1214 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
1215 return(TNG_CRITICAL);
1218 tng_block_md5_hash_generate(block);
1220 fseeko(tng_data->output_file, header_start_pos + 3 * sizeof(int64_t),
1221 SEEK_SET);
1222 fwrite(block->md5_hash, TNG_MD5_HASH_LEN, 1, tng_data->output_file);
1224 return(TNG_SUCCESS);
1228 * @brief Update the frame set pointers in the file header (general info block),
1229 * already written to disk
1230 * @param tng_data is a trajectory data container.
1231 * @param hash_mode specifies whether to update the block md5 hash when
1232 * updating the pointers.
1233 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
1234 * error has occured.
1236 static tng_function_status tng_header_pointers_update
1237 (const tng_trajectory_t tng_data, const char hash_mode)
1239 tng_gen_block_t block;
1240 FILE *temp = tng_data->input_file;
1241 uint64_t output_file_pos, pos, contents_start_pos;
1243 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
1245 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
1246 __FILE__, __LINE__);
1247 return(TNG_CRITICAL);
1250 tng_data->input_file = tng_data->output_file;
1252 tng_block_init(&block);
1254 output_file_pos = ftello(tng_data->output_file);
1255 fseeko(tng_data->output_file, 0, SEEK_SET);
1257 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1259 fprintf(stderr, "TNG library: Cannot read general info header. %s: %d\n",
1260 __FILE__, __LINE__);
1261 tng_data->input_file = temp;
1262 tng_block_destroy(&block);
1263 return(TNG_CRITICAL);
1266 contents_start_pos = ftello(tng_data->output_file);
1268 fseeko(tng_data->output_file, block->block_contents_size - 5 *
1269 sizeof(int64_t), SEEK_CUR);
1271 tng_data->input_file = temp;
1273 pos = tng_data->first_trajectory_frame_set_output_file_pos;
1275 if(tng_data->input_endianness_swap_func_64)
1277 if(tng_data->input_endianness_swap_func_64(tng_data,
1278 &pos)
1279 != TNG_SUCCESS)
1281 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1282 __FILE__, __LINE__);
1286 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1288 tng_block_destroy(&block);
1289 return(TNG_CRITICAL);
1292 pos = tng_data->last_trajectory_frame_set_output_file_pos;
1294 if(tng_data->input_endianness_swap_func_64)
1296 if(tng_data->input_endianness_swap_func_64(tng_data,
1297 &pos)
1298 != TNG_SUCCESS)
1300 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1301 __FILE__, __LINE__);
1305 if(fwrite(&pos,
1306 sizeof(int64_t), 1, tng_data->output_file) != 1)
1308 tng_block_destroy(&block);
1309 return(TNG_CRITICAL);
1312 if(hash_mode == TNG_USE_HASH)
1314 tng_md5_hash_update(tng_data, block, 0, contents_start_pos);
1317 tng_block_destroy(&block);
1319 fseeko(tng_data->output_file, output_file_pos, SEEK_SET);
1321 return(TNG_SUCCESS);
1325 * @brief Update the frame set pointers in the current frame set block, already
1326 * written to disk. It also updates the pointers of the blocks pointing to
1327 * the current frame set block.
1328 * @param tng_data is a trajectory data container.
1329 * @param hash_mode specifies whether to update the block md5 hash when
1330 * updating the pointers.
1331 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
1332 * error has occured.
1334 static tng_function_status tng_frame_set_pointers_update
1335 (const tng_trajectory_t tng_data, const char hash_mode)
1337 tng_gen_block_t block;
1338 tng_trajectory_frame_set_t frame_set;
1339 FILE *temp = tng_data->input_file;
1340 uint64_t pos, output_file_pos, contents_start_pos;
1342 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
1344 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
1345 __FILE__, __LINE__);
1346 return(TNG_CRITICAL);
1349 tng_block_init(&block);
1350 output_file_pos = ftello(tng_data->output_file);
1352 tng_data->input_file = tng_data->output_file;
1354 frame_set = &tng_data->current_trajectory_frame_set;
1356 pos = tng_data->current_trajectory_frame_set_output_file_pos;
1358 /* Update next frame set */
1359 if(frame_set->next_frame_set_file_pos > 0)
1361 fseeko(tng_data->output_file, frame_set->next_frame_set_file_pos, SEEK_SET);
1363 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1365 fprintf(stderr, "TNG library: Cannot read frame header. %s: %d\n",
1366 __FILE__, __LINE__);
1367 tng_data->input_file = temp;
1368 tng_block_destroy(&block);
1369 return(TNG_CRITICAL);
1372 contents_start_pos = ftello(tng_data->output_file);
1374 fseeko(tng_data->output_file, block->block_contents_size - (5 *
1375 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
1377 if(tng_data->input_endianness_swap_func_64)
1379 if(tng_data->input_endianness_swap_func_64(tng_data,
1380 &pos)
1381 != TNG_SUCCESS)
1383 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1384 __FILE__, __LINE__);
1388 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1390 tng_data->input_file = temp;
1391 tng_block_destroy(&block);
1392 return(TNG_CRITICAL);
1395 if(hash_mode == TNG_USE_HASH)
1397 tng_md5_hash_update(tng_data, block, frame_set->next_frame_set_file_pos,
1398 contents_start_pos);
1401 /* Update previous frame set */
1402 if(frame_set->prev_frame_set_file_pos > 0)
1404 fseeko(tng_data->output_file, frame_set->prev_frame_set_file_pos,
1405 SEEK_SET);
1407 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1409 fprintf(stderr, "TNG library: Cannot read frame header. %s: %d\n",
1410 __FILE__, __LINE__);
1411 tng_data->input_file = temp;
1412 tng_block_destroy(&block);
1413 return(TNG_CRITICAL);
1416 contents_start_pos = ftello(tng_data->output_file);
1418 fseeko(tng_data->output_file, block->block_contents_size - (6 *
1419 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
1421 if(tng_data->input_endianness_swap_func_64)
1423 if(tng_data->input_endianness_swap_func_64(tng_data,
1424 &pos)
1425 != TNG_SUCCESS)
1427 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1428 __FILE__, __LINE__);
1432 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1434 tng_data->input_file = temp;
1435 tng_block_destroy(&block);
1436 return(TNG_CRITICAL);
1439 if(hash_mode == TNG_USE_HASH)
1441 tng_md5_hash_update(tng_data, block, frame_set->prev_frame_set_file_pos,
1442 contents_start_pos);
1446 /* Update the frame set one medium stride step after */
1447 if(frame_set->medium_stride_next_frame_set_file_pos > 0)
1449 fseeko(tng_data->output_file,
1450 frame_set->medium_stride_next_frame_set_file_pos,
1451 SEEK_SET);
1453 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1455 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
1456 __FILE__, __LINE__);
1457 tng_data->input_file = temp;
1458 tng_block_destroy(&block);
1459 return(TNG_CRITICAL);
1462 contents_start_pos = ftello(tng_data->output_file);
1464 fseeko(tng_data->output_file, block->block_contents_size - (3 *
1465 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
1467 if(tng_data->input_endianness_swap_func_64)
1469 if(tng_data->input_endianness_swap_func_64(tng_data,
1470 &pos)
1471 != TNG_SUCCESS)
1473 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1474 __FILE__, __LINE__);
1478 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1480 tng_data->input_file = temp;
1481 tng_block_destroy(&block);
1482 return(TNG_CRITICAL);
1485 if(hash_mode == TNG_USE_HASH)
1487 tng_md5_hash_update(tng_data, block,
1488 frame_set->medium_stride_next_frame_set_file_pos,
1489 contents_start_pos);
1492 /* Update the frame set one medium stride step before */
1493 if(frame_set->medium_stride_prev_frame_set_file_pos > 0)
1495 fseeko(tng_data->output_file,
1496 frame_set->medium_stride_prev_frame_set_file_pos,
1497 SEEK_SET);
1499 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1501 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
1502 __FILE__, __LINE__);
1503 tng_data->input_file = temp;
1504 tng_block_destroy(&block);
1505 return(TNG_CRITICAL);
1508 contents_start_pos = ftello(tng_data->output_file);
1510 fseeko(tng_data->output_file, block->block_contents_size - (4 *
1511 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
1513 if(tng_data->input_endianness_swap_func_64)
1515 if(tng_data->input_endianness_swap_func_64(tng_data,
1516 &pos)
1517 != TNG_SUCCESS)
1519 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1520 __FILE__, __LINE__);
1524 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1526 tng_data->input_file = temp;
1527 tng_block_destroy(&block);
1528 return(TNG_CRITICAL);
1531 if(hash_mode == TNG_USE_HASH)
1533 tng_md5_hash_update(tng_data, block,
1534 frame_set->medium_stride_prev_frame_set_file_pos,
1535 contents_start_pos);
1539 /* Update the frame set one long stride step after */
1540 if(frame_set->long_stride_next_frame_set_file_pos > 0)
1542 fseeko(tng_data->output_file,
1543 frame_set->long_stride_next_frame_set_file_pos,
1544 SEEK_SET);
1546 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1548 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
1549 __FILE__, __LINE__);
1550 tng_data->input_file = temp;
1551 tng_block_destroy(&block);
1552 return(TNG_CRITICAL);
1555 contents_start_pos = ftello(tng_data->output_file);
1557 fseeko(tng_data->output_file, block->block_contents_size - (1 *
1558 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
1560 if(tng_data->input_endianness_swap_func_64)
1562 if(tng_data->input_endianness_swap_func_64(tng_data,
1563 &pos)
1564 != TNG_SUCCESS)
1566 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1567 __FILE__, __LINE__);
1571 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1573 tng_data->input_file = temp;
1574 tng_block_destroy(&block);
1575 return(TNG_CRITICAL);
1578 if(hash_mode == TNG_USE_HASH)
1580 tng_md5_hash_update(tng_data, block,
1581 frame_set->long_stride_next_frame_set_file_pos,
1582 contents_start_pos);
1585 /* Update the frame set one long stride step before */
1586 if(frame_set->long_stride_prev_frame_set_file_pos > 0)
1588 fseeko(tng_data->output_file,
1589 frame_set->long_stride_prev_frame_set_file_pos,
1590 SEEK_SET);
1592 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1594 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
1595 __FILE__, __LINE__);
1596 tng_data->input_file = temp;
1597 tng_block_destroy(&block);
1598 return(TNG_CRITICAL);
1601 contents_start_pos = ftello(tng_data->output_file);
1603 fseeko(tng_data->output_file, block->block_contents_size - (2 *
1604 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
1606 if(tng_data->input_endianness_swap_func_64)
1608 if(tng_data->input_endianness_swap_func_64(tng_data,
1609 &pos)
1610 != TNG_SUCCESS)
1612 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1613 __FILE__, __LINE__);
1617 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1619 tng_data->input_file = temp;
1620 tng_block_destroy(&block);
1621 return(TNG_CRITICAL);
1624 if(hash_mode == TNG_USE_HASH)
1626 tng_md5_hash_update(tng_data, block,
1627 frame_set->long_stride_prev_frame_set_file_pos,
1628 contents_start_pos);
1632 fseeko(tng_data->output_file, output_file_pos, SEEK_SET);
1634 tng_data->input_file = temp;
1636 tng_block_destroy(&block);
1638 return(TNG_SUCCESS);
1641 static tng_function_status tng_reread_frame_set_at_file_pos
1642 (const tng_trajectory_t tng_data,
1643 const int64_t pos)
1645 tng_gen_block_t block;
1646 tng_function_status stat;
1648 tng_block_init(&block);
1650 fseeko(tng_data->input_file, pos, SEEK_SET);
1651 if(pos > 0)
1653 stat = tng_block_header_read(tng_data, block);
1654 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
1656 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n", pos,
1657 __FILE__, __LINE__);
1658 tng_block_destroy(&block);
1659 return(TNG_FAILURE);
1662 if(tng_block_read_next(tng_data, block,
1663 TNG_SKIP_HASH) != TNG_SUCCESS)
1665 tng_block_destroy(&block);
1666 return(TNG_CRITICAL);
1670 tng_block_destroy(&block);
1672 return(TNG_SUCCESS);
1675 static tng_function_status tng_file_pos_of_subsequent_trajectory_block_get
1676 (const tng_trajectory_t tng_data,
1677 int64_t *pos)
1679 int64_t orig_pos, curr_frame_set_pos;
1680 tng_gen_block_t block;
1681 tng_function_status stat;
1682 tng_trajectory_frame_set_t frame_set =
1683 &tng_data->current_trajectory_frame_set;
1685 orig_pos = ftello(tng_data->input_file);
1686 curr_frame_set_pos = tng_data->current_trajectory_frame_set_input_file_pos;
1688 *pos = tng_data->first_trajectory_frame_set_input_file_pos;
1690 if(*pos <= 0)
1692 return(TNG_SUCCESS);
1695 fseeko(tng_data->input_file, *pos, SEEK_SET);
1697 tng_block_init(&block);
1698 /* Read block headers first to see that a frame set block is found. */
1699 stat = tng_block_header_read(tng_data, block);
1700 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
1702 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n", *pos,
1703 __FILE__, __LINE__);
1704 tng_block_destroy(&block);
1705 return(TNG_FAILURE);
1708 if(tng_block_read_next(tng_data, block,
1709 TNG_SKIP_HASH) != TNG_SUCCESS)
1711 tng_block_destroy(&block);
1712 return(TNG_CRITICAL);
1715 /* Read all frame set blocks (not the blocks between them) */
1716 while(frame_set->next_frame_set_file_pos > 0)
1718 fseeko(tng_data->input_file, frame_set->next_frame_set_file_pos, SEEK_SET);
1719 stat = tng_block_header_read(tng_data, block);
1720 if(stat == TNG_CRITICAL)
1722 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n", *pos,
1723 __FILE__, __LINE__);
1724 tng_block_destroy(&block);
1725 return(TNG_CRITICAL);
1727 if(stat != TNG_SUCCESS || block->id != TNG_TRAJECTORY_FRAME_SET)
1729 return(TNG_FAILURE);
1732 stat = tng_block_read_next(tng_data, block, TNG_SKIP_HASH);
1733 if(stat != TNG_SUCCESS)
1735 tng_block_destroy(&block);
1736 return(stat);
1738 /* Update *pos if this is the earliest frame set so far (after orig_pos) */
1739 if(tng_data->current_trajectory_frame_set_input_file_pos < *pos &&
1740 tng_data->current_trajectory_frame_set_input_file_pos > orig_pos)
1742 *pos = tng_data->current_trajectory_frame_set_input_file_pos;
1746 /* Re-read the frame set that used to be the current one */
1747 tng_reread_frame_set_at_file_pos(tng_data, curr_frame_set_pos);
1749 fseeko(tng_data->input_file, orig_pos, SEEK_SET);
1751 tng_block_destroy(&block);
1753 return(TNG_SUCCESS);
1757 * @brief Migrate a whole frame set from one position in the file to another.
1758 * @param tng_data is a trajectory data container.
1759 * @param block_start_pos is the starting position in the file of the frame set.
1760 * @param block_len is the length of the whole frame set (including all data blocks etc).
1761 * @param new_pos is the new position in the file of the frame set.
1762 * @param hash_mode is an option to decide whether to generate/update the relevant md5 hashes.
1764 static tng_function_status tng_frame_set_complete_migrate
1765 (const tng_trajectory_t tng_data,
1766 const int64_t block_start_pos,
1767 const int64_t block_len,
1768 const int64_t new_pos,
1769 const char hash_mode)
1771 tng_bool updated = TNG_FALSE;
1773 char *contents;
1775 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
1777 return(TNG_CRITICAL);
1780 fseeko(tng_data->input_file, block_start_pos, SEEK_SET);
1782 contents = (char *)malloc(block_len);
1783 if(!contents)
1785 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n", __FILE__, __LINE__);
1786 return(TNG_CRITICAL);
1789 if(fread(contents, block_len, 1, tng_data->input_file) == 0)
1791 fprintf(stderr, "TNG library: Cannot read data from file when migrating data. %s: %d\n",
1792 __FILE__, __LINE__);
1793 free(contents);
1794 return(TNG_CRITICAL);
1796 fseeko(tng_data->output_file, new_pos, SEEK_SET);
1798 if(fwrite(contents, block_len, 1, tng_data->output_file) != 1)
1800 fprintf(stderr, "TNG library: Could not write data to file when migrating data. %s: %d\n",
1801 __FILE__, __LINE__);
1802 free(contents);
1803 return(TNG_CRITICAL);
1806 tng_data->current_trajectory_frame_set_output_file_pos = new_pos;
1807 if(tng_data->input_file == tng_data->output_file)
1809 tng_data->current_trajectory_frame_set_input_file_pos = new_pos;
1812 tng_frame_set_pointers_update(tng_data, hash_mode);
1814 /* Update the general info block if needed */
1815 if(block_start_pos == tng_data->first_trajectory_frame_set_output_file_pos)
1817 tng_data->first_trajectory_frame_set_output_file_pos = new_pos;
1818 updated = TNG_TRUE;
1820 if(block_start_pos == tng_data->last_trajectory_frame_set_output_file_pos)
1822 tng_data->last_trajectory_frame_set_output_file_pos = new_pos;
1823 updated = TNG_TRUE;
1825 if(updated)
1827 tng_header_pointers_update(tng_data, hash_mode);
1830 /* Fill the block with NULL to avoid confusion. */
1831 memset(contents, '\0', block_len);
1832 fseeko(tng_data->output_file, block_start_pos, SEEK_SET);
1834 /* FIXME: casting block_len to size_t is dangerous */
1835 fwrite(contents, 1, block_len, tng_data->output_file);
1837 free(contents);
1839 return(TNG_SUCCESS);
1842 static tng_function_status tng_length_of_current_frame_set_contents_get
1843 (const tng_trajectory_t tng_data,
1844 int64_t *len)
1846 int64_t orig_pos, pos, curr_frame_set_pos;
1847 tng_gen_block_t block;
1848 tng_function_status stat;
1850 orig_pos = ftello(tng_data->input_file);
1851 curr_frame_set_pos = pos = tng_data->current_trajectory_frame_set_input_file_pos;
1853 *len = 0;
1855 fseeko(tng_data->input_file, curr_frame_set_pos, SEEK_SET);
1857 tng_block_init(&block);
1858 /* Read block headers first to see that a frame set block is found. */
1859 stat = tng_block_header_read(tng_data, block);
1860 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
1862 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
1863 curr_frame_set_pos, __FILE__, __LINE__);
1864 tng_block_destroy(&block);
1865 return(TNG_FAILURE);
1868 /* Read the headers of all blocks in the frame set (not the actual contents of them) */
1869 while(stat == TNG_SUCCESS)
1871 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
1872 *len += block->header_contents_size + block->block_contents_size;
1873 pos += block->header_contents_size + block->block_contents_size;
1874 if(pos >= tng_data->input_file_len)
1876 break;
1878 stat = tng_block_header_read(tng_data, block);
1879 if(block->id == TNG_TRAJECTORY_FRAME_SET)
1881 break;
1885 /* Re-read the frame set that used to be the current one */
1886 tng_reread_frame_set_at_file_pos(tng_data, curr_frame_set_pos);
1888 fseeko(tng_data->input_file, orig_pos, SEEK_SET);
1890 tng_block_destroy(&block);
1892 return(TNG_SUCCESS);
1896 * @brief Migrate blocks in the file to make room for new data in a block. This
1897 * is required e.g. when adding data to a block or extending strings in a
1898 * block.
1899 * @param tng_data is a trajectory data container.
1900 * @param start_pos is the position from which to start moving data, usually
1901 * the byte after the end of the block to which data was added.
1902 * @param offset is the number of bytes that were inserted.
1903 * @param hash_mode is an option to decide whether to generate/update the relevant md5 hashes.
1904 * @details Trajectory blocks (frame sets and their related blocks) are moved
1905 * to the end of the file (if needed) in order to make room for non-trajectory
1906 * data.
1908 static tng_function_status tng_migrate_data_in_file
1909 (const tng_trajectory_t tng_data,
1910 const int64_t start_pos,
1911 const int64_t offset,
1912 const char hash_mode)
1914 int64_t traj_start_pos, empty_space, orig_file_pos, frame_set_length;
1915 tng_gen_block_t block;
1916 tng_function_status stat;
1918 if(offset <= 0)
1920 return(TNG_SUCCESS);
1923 stat = tng_file_pos_of_subsequent_trajectory_block_get(tng_data, &traj_start_pos);
1924 if(stat != TNG_SUCCESS)
1926 return(stat);
1929 tng_data->current_trajectory_frame_set_input_file_pos = traj_start_pos;
1931 empty_space = traj_start_pos - (start_pos - 1);
1933 if(empty_space >= offset)
1935 return(TNG_SUCCESS);
1938 orig_file_pos = ftello(tng_data->input_file);
1939 tng_block_init(&block);
1941 while(empty_space < offset)
1943 fseeko(tng_data->input_file, traj_start_pos, SEEK_SET);
1944 stat = tng_block_header_read(tng_data, block);
1945 if(stat == TNG_CRITICAL)
1947 fprintf(stderr, "TNG library: Cannot read block header. %s: %d\n",
1948 __FILE__, __LINE__);
1949 tng_block_destroy(&block);
1950 return(TNG_CRITICAL);
1952 if(stat != TNG_SUCCESS || block->id != TNG_TRAJECTORY_FRAME_SET)
1954 tng_block_destroy(&block);
1955 return(TNG_FAILURE);
1957 stat = tng_length_of_current_frame_set_contents_get(tng_data, &frame_set_length);
1958 if(stat != TNG_SUCCESS)
1960 tng_block_destroy(&block);
1961 return(stat);
1963 stat = tng_frame_set_complete_migrate(tng_data, traj_start_pos,
1964 frame_set_length, tng_data->input_file_len,
1965 hash_mode);
1966 if(stat != TNG_SUCCESS)
1968 tng_block_destroy(&block);
1969 return(stat);
1972 empty_space += frame_set_length;
1974 fseeko(tng_data->input_file, orig_file_pos, SEEK_SET);
1975 tng_block_destroy(&block);
1977 return(TNG_SUCCESS);
1980 static tng_function_status tng_block_header_len_calculate
1981 (const tng_trajectory_t tng_data,
1982 const tng_gen_block_t block,
1983 int64_t *len)
1985 int name_len;
1986 (void)tng_data;
1988 /* If the string is unallocated allocate memory for just string
1989 * termination */
1990 if(!block->name)
1992 block->name = (char *)malloc(1);
1993 if(!block->name)
1995 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
1996 __FILE__, __LINE__);
1997 return(TNG_CRITICAL);
1999 block->name[0] = 0;
2002 name_len = tng_min_size(strlen(block->name) + 1, TNG_MAX_STR_LEN);
2004 /* Calculate the size of the header to write */
2005 *len = sizeof(block->header_contents_size) +
2006 sizeof(block->block_contents_size) +
2007 sizeof(block->id) +
2008 sizeof(block->block_version) +
2009 TNG_MD5_HASH_LEN +
2010 name_len;
2012 return (TNG_SUCCESS);
2016 * @brief Write the header of a data block, regardless of its type
2017 * @param tng_data is a trajectory data container.
2018 * @param block is a general block container.
2019 * @param hash_mode is an option to decide whether to use the md5 hash or not.
2020 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
2021 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
2022 * error has occured.
2024 static tng_function_status tng_block_header_write
2025 (const tng_trajectory_t tng_data,
2026 const tng_gen_block_t block)
2028 TNG_ASSERT(block != 0, "TNG library: Trying to write uninitialized block (NULL pointer).");
2030 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
2032 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
2033 __FILE__, __LINE__);
2034 return(TNG_CRITICAL);
2037 if(tng_block_header_len_calculate(tng_data, block, &block->header_contents_size) !=
2038 TNG_SUCCESS)
2040 fprintf(stderr, "TNG library: Cannot calculate length of block header. %s: %d\n",
2041 __FILE__, __LINE__);
2042 return(TNG_CRITICAL);
2045 if(tng_file_output_numerical(tng_data, &block->header_contents_size,
2046 sizeof(block->header_contents_size),
2047 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
2049 return(TNG_CRITICAL);
2052 if(tng_file_output_numerical(tng_data, &block->block_contents_size,
2053 sizeof(block->block_contents_size),
2054 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
2056 return(TNG_CRITICAL);
2059 if(tng_file_output_numerical(tng_data, &block->id,
2060 sizeof(block->id),
2061 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
2063 return(TNG_CRITICAL);
2066 if(fwrite(block->md5_hash, TNG_MD5_HASH_LEN, 1, tng_data->output_file) != 1)
2068 fprintf(stderr, "TNG library: Could not write header data. %s: %d\n", __FILE__, __LINE__);
2069 return(TNG_CRITICAL);
2072 if(tng_fwritestr(tng_data, block->name, TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
2074 return(TNG_CRITICAL);
2077 if(tng_file_output_numerical(tng_data, &block->block_version,
2078 sizeof(block->block_version),
2079 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
2081 return(TNG_CRITICAL);
2084 return(TNG_SUCCESS);
2087 static tng_function_status tng_general_info_block_len_calculate
2088 (const tng_trajectory_t tng_data,
2089 int64_t *len)
2091 size_t first_program_name_len, first_user_name_len;
2092 size_t first_computer_name_len, first_pgp_signature_len;
2093 size_t last_program_name_len, last_user_name_len;
2094 size_t last_computer_name_len, last_pgp_signature_len;
2095 size_t forcefield_name_len;
2097 /* If the strings are unallocated allocate memory for just string
2098 * termination */
2099 if(!tng_data->first_program_name)
2101 tng_data->first_program_name = (char *)malloc(1);
2102 if(!tng_data->first_program_name)
2104 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
2105 __FILE__, __LINE__);
2106 return(TNG_CRITICAL);
2108 tng_data->first_program_name[0] = 0;
2110 if(!tng_data->last_program_name)
2112 tng_data->last_program_name = (char *)malloc(1);
2113 if(!tng_data->last_program_name)
2115 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
2116 __FILE__, __LINE__);
2117 return(TNG_CRITICAL);
2119 tng_data->last_program_name[0] = 0;
2121 if(!tng_data->first_user_name)
2123 tng_data->first_user_name = (char *)malloc(1);
2124 if(!tng_data->first_user_name)
2126 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
2127 __FILE__, __LINE__);
2128 return(TNG_CRITICAL);
2130 tng_data->first_user_name[0] = 0;
2132 if(!tng_data->last_user_name)
2134 tng_data->last_user_name = (char *)malloc(1);
2135 if(!tng_data->last_user_name)
2137 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
2138 __FILE__, __LINE__);
2139 return(TNG_CRITICAL);
2141 tng_data->last_user_name[0] = 0;
2143 if(!tng_data->first_computer_name)
2145 tng_data->first_computer_name = (char *)malloc(1);
2146 if(!tng_data->first_computer_name)
2148 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
2149 __FILE__, __LINE__);
2150 return(TNG_CRITICAL);
2152 tng_data->first_computer_name[0] = 0;
2154 if(!tng_data->last_computer_name)
2156 tng_data->last_computer_name = (char *)malloc(1);
2157 if(!tng_data->last_computer_name)
2159 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
2160 __FILE__, __LINE__);
2161 return(TNG_CRITICAL);
2163 tng_data->last_computer_name[0] = 0;
2165 if(!tng_data->first_pgp_signature)
2167 tng_data->first_pgp_signature = (char *)malloc(1);
2168 if(!tng_data->first_pgp_signature)
2170 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
2171 __FILE__, __LINE__);
2172 return(TNG_CRITICAL);
2174 tng_data->first_pgp_signature[0] = 0;
2176 if(!tng_data->last_pgp_signature)
2178 tng_data->last_pgp_signature = (char *)malloc(1);
2179 if(!tng_data->last_pgp_signature)
2181 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
2182 __FILE__, __LINE__);
2183 return(TNG_CRITICAL);
2185 tng_data->last_pgp_signature[0] = 0;
2187 if(!tng_data->forcefield_name)
2189 tng_data->forcefield_name = (char *)malloc(1);
2190 if(!tng_data->forcefield_name)
2192 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
2193 __FILE__, __LINE__);
2194 return(TNG_CRITICAL);
2196 tng_data->forcefield_name[0] = 0;
2199 first_program_name_len = tng_min_size(strlen(tng_data->first_program_name) + 1,
2200 TNG_MAX_STR_LEN);
2201 last_program_name_len = tng_min_size(strlen(tng_data->last_program_name) + 1,
2202 TNG_MAX_STR_LEN);
2203 first_user_name_len = tng_min_size(strlen(tng_data->first_user_name) + 1,
2204 TNG_MAX_STR_LEN);
2205 last_user_name_len = tng_min_size(strlen(tng_data->last_user_name) + 1,
2206 TNG_MAX_STR_LEN);
2207 first_computer_name_len = tng_min_size(strlen(tng_data->first_computer_name) + 1,
2208 TNG_MAX_STR_LEN);
2209 last_computer_name_len = tng_min_size(strlen(tng_data->last_computer_name) + 1,
2210 TNG_MAX_STR_LEN);
2211 first_pgp_signature_len = tng_min_size(strlen(tng_data->first_pgp_signature) + 1,
2212 TNG_MAX_STR_LEN);
2213 last_pgp_signature_len = tng_min_size(strlen(tng_data->last_pgp_signature) + 1,
2214 TNG_MAX_STR_LEN);
2215 forcefield_name_len = tng_min_size(strlen(tng_data->forcefield_name) + 1,
2216 TNG_MAX_STR_LEN);
2218 *len = sizeof(tng_data->time) +
2219 sizeof(tng_data->var_num_atoms_flag) +
2220 sizeof(tng_data->frame_set_n_frames) +
2221 sizeof(tng_data->first_trajectory_frame_set_input_file_pos) +
2222 sizeof(tng_data->last_trajectory_frame_set_input_file_pos) +
2223 sizeof(tng_data->medium_stride_length) +
2224 sizeof(tng_data->long_stride_length) +
2225 sizeof(tng_data->distance_unit_exponential) +
2226 first_program_name_len +
2227 last_program_name_len +
2228 first_user_name_len +
2229 last_user_name_len +
2230 first_computer_name_len +
2231 last_computer_name_len +
2232 first_pgp_signature_len +
2233 last_pgp_signature_len +
2234 forcefield_name_len;
2236 return(TNG_SUCCESS);
2240 * @brief Read a general info block. This is the first block of a TNG file.
2241 * Populate the fields in tng_data.
2242 * @param tng_data is a trajectory data container.
2243 * @param block is a general block container.
2244 * @param hash_mode is an option to decide whether to use the md5 hash or not.
2245 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
2246 * compared to the md5 hash of the read contents to ensure valid data.
2247 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
2248 * error has occured.
2250 static tng_function_status tng_general_info_block_read
2251 (const tng_trajectory_t tng_data,
2252 const tng_gen_block_t block,
2253 const char hash_mode)
2255 int64_t start_pos;
2256 char hash[TNG_MD5_HASH_LEN];
2257 md5_state_t md5_state;
2259 TNG_ASSERT(block != 0, "TNG library: Trying to read data to an uninitialized block (NULL pointer)");
2261 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
2263 return(TNG_CRITICAL);
2266 start_pos = ftello(tng_data->input_file);
2268 if(hash_mode == TNG_USE_HASH)
2270 md5_init(&md5_state);
2273 tng_freadstr(tng_data, &tng_data->first_program_name, hash_mode, &md5_state, __LINE__);
2275 tng_freadstr(tng_data, &tng_data->last_program_name, hash_mode, &md5_state, __LINE__);
2277 tng_freadstr(tng_data, &tng_data->first_user_name, hash_mode, &md5_state, __LINE__);
2279 tng_freadstr(tng_data, &tng_data->last_user_name, hash_mode, &md5_state, __LINE__);
2281 tng_freadstr(tng_data, &tng_data->first_computer_name, hash_mode, &md5_state, __LINE__);
2283 tng_freadstr(tng_data, &tng_data->last_computer_name, hash_mode, &md5_state, __LINE__);
2285 tng_freadstr(tng_data, &tng_data->first_pgp_signature, hash_mode, &md5_state, __LINE__);
2287 tng_freadstr(tng_data, &tng_data->last_pgp_signature, hash_mode, &md5_state, __LINE__);
2289 tng_freadstr(tng_data, &tng_data->forcefield_name, hash_mode, &md5_state, __LINE__);
2291 if(tng_file_input_numerical(tng_data, &tng_data->time, sizeof(tng_data->time),
2292 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2294 return(TNG_CRITICAL);
2298 if(tng_file_input_numerical(tng_data, &tng_data->var_num_atoms_flag,
2299 sizeof(tng_data->var_num_atoms_flag),
2300 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2302 return(TNG_CRITICAL);
2305 if(tng_file_input_numerical(tng_data, &tng_data->frame_set_n_frames,
2306 sizeof(tng_data->frame_set_n_frames),
2307 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2309 return(TNG_CRITICAL);
2312 if(tng_file_input_numerical(tng_data,
2313 &tng_data->first_trajectory_frame_set_input_file_pos,
2314 sizeof(tng_data->first_trajectory_frame_set_input_file_pos),
2315 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2317 return(TNG_CRITICAL);
2320 tng_data->current_trajectory_frame_set.next_frame_set_file_pos =
2321 tng_data->first_trajectory_frame_set_input_file_pos;
2323 if(tng_file_input_numerical(tng_data,
2324 &tng_data->last_trajectory_frame_set_input_file_pos,
2325 sizeof(tng_data->last_trajectory_frame_set_input_file_pos),
2326 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2328 return(TNG_CRITICAL);
2331 if(tng_file_input_numerical(tng_data,
2332 &tng_data->medium_stride_length,
2333 sizeof(tng_data->medium_stride_length),
2334 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2336 return(TNG_CRITICAL);
2339 if(tng_file_input_numerical(tng_data,
2340 &tng_data->long_stride_length,
2341 sizeof(tng_data->long_stride_length),
2342 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2344 return(TNG_CRITICAL);
2347 if(block->block_version >= 3)
2349 if(tng_file_input_numerical(tng_data,
2350 &tng_data->distance_unit_exponential,
2351 sizeof(tng_data->distance_unit_exponential),
2352 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2354 return(TNG_CRITICAL);
2358 if(hash_mode == TNG_USE_HASH)
2360 /* If there is data left in the block that the current version of the library
2361 * cannot interpret still read that to generate the MD5 hash. */
2362 tng_md5_remaining_append(tng_data, block, start_pos, &md5_state);
2364 md5_finish(&md5_state, (md5_byte_t *)hash);
2365 if(strncmp(block->md5_hash, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", TNG_MD5_HASH_LEN) != 0)
2367 if(strncmp(block->md5_hash, hash, TNG_MD5_HASH_LEN) != 0)
2369 fprintf(stderr, "TNG library: General info block contents corrupt. Hashes do not match. "
2370 "%s: %d\n", __FILE__, __LINE__);
2374 else
2376 /* Seek to the end of the block */
2377 fseeko(tng_data->input_file, start_pos + block->block_contents_size, SEEK_SET);
2380 return(TNG_SUCCESS);
2384 * @brief Write a general info block. This is the first block of a TNG file.
2385 * @param tng_data is a trajectory data container.
2386 * @param hash_mode is an option to decide whether to use the md5 hash or not.
2387 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
2388 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
2389 * error has occured.
2391 static tng_function_status tng_general_info_block_write
2392 (const tng_trajectory_t tng_data,
2393 const char hash_mode)
2395 int64_t header_file_pos, curr_file_pos;
2396 size_t name_len;
2397 tng_gen_block_t block;
2398 md5_state_t md5_state;
2400 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
2402 return(TNG_CRITICAL);
2405 fseeko(tng_data->output_file, 0, SEEK_SET);
2407 tng_block_init(&block);
2409 name_len = strlen("GENERAL INFO");
2411 block->name = (char *)malloc(name_len + 1);
2412 if(!block->name)
2414 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n", __FILE__, __LINE__);
2415 tng_block_destroy(&block);
2416 return(TNG_CRITICAL);
2419 strcpy(block->name, "GENERAL INFO");
2420 block->id = TNG_GENERAL_INFO;
2422 if(tng_general_info_block_len_calculate(tng_data, &block->block_contents_size) !=
2423 TNG_SUCCESS)
2425 fprintf(stderr, "TNG library: Cannot calculate length of general info block. %s: %d\n",
2426 __FILE__, __LINE__);
2427 tng_block_destroy(&block);
2428 return(TNG_CRITICAL);
2431 header_file_pos = 0;
2433 if(tng_block_header_write(tng_data, block) != TNG_SUCCESS)
2435 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
2436 tng_data->output_file_path, __FILE__, __LINE__);
2437 tng_block_destroy(&block);
2438 return(TNG_CRITICAL);
2441 if(hash_mode == TNG_USE_HASH)
2443 md5_init(&md5_state);
2446 if(tng_fwritestr(tng_data, tng_data->first_program_name,
2447 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2449 return(TNG_CRITICAL);
2452 if(tng_fwritestr(tng_data, tng_data->last_program_name,
2453 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2455 return(TNG_CRITICAL);
2458 if(tng_fwritestr(tng_data, tng_data->first_user_name,
2459 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2461 return(TNG_CRITICAL);
2464 if(tng_fwritestr(tng_data, tng_data->last_user_name,
2465 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2467 return(TNG_CRITICAL);
2470 if(tng_fwritestr(tng_data, tng_data->first_computer_name,
2471 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2473 return(TNG_CRITICAL);
2476 if(tng_fwritestr(tng_data, tng_data->last_computer_name,
2477 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2479 return(TNG_CRITICAL);
2482 if(tng_fwritestr(tng_data, tng_data->first_pgp_signature,
2483 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2485 return(TNG_CRITICAL);
2488 if(tng_fwritestr(tng_data, tng_data->last_pgp_signature,
2489 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2491 return(TNG_CRITICAL);
2494 if(tng_fwritestr(tng_data, tng_data->forcefield_name,
2495 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2497 return(TNG_CRITICAL);
2501 if(tng_file_output_numerical(tng_data, &tng_data->time, sizeof(tng_data->time),
2502 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2504 return(TNG_CRITICAL);
2507 if(tng_file_output_numerical(tng_data, &tng_data->var_num_atoms_flag,
2508 sizeof(tng_data->var_num_atoms_flag),
2509 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2511 return(TNG_CRITICAL);
2514 if(tng_file_output_numerical(tng_data, &tng_data->frame_set_n_frames,
2515 sizeof(tng_data->frame_set_n_frames),
2516 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2518 return(TNG_CRITICAL);
2521 if(tng_file_output_numerical(tng_data, &tng_data->first_trajectory_frame_set_output_file_pos,
2522 sizeof(tng_data->first_trajectory_frame_set_output_file_pos),
2523 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2525 return(TNG_CRITICAL);
2528 if(tng_file_output_numerical(tng_data, &tng_data->last_trajectory_frame_set_output_file_pos,
2529 sizeof(tng_data->last_trajectory_frame_set_output_file_pos),
2530 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2532 return(TNG_CRITICAL);
2535 if(tng_file_output_numerical(tng_data, &tng_data->medium_stride_length,
2536 sizeof(tng_data->medium_stride_length),
2537 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2539 return(TNG_CRITICAL);
2542 if(tng_file_output_numerical(tng_data, &tng_data->long_stride_length,
2543 sizeof(tng_data->long_stride_length),
2544 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2546 return(TNG_CRITICAL);
2549 if(tng_file_output_numerical(tng_data, &tng_data->distance_unit_exponential,
2550 sizeof(tng_data->distance_unit_exponential),
2551 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2553 return(TNG_CRITICAL);
2555 if(hash_mode == TNG_USE_HASH)
2557 md5_finish(&md5_state, (md5_byte_t *)block->md5_hash);
2558 curr_file_pos = ftello(tng_data->output_file);
2559 fseeko(tng_data->output_file, header_file_pos +
2560 3 * sizeof(int64_t), SEEK_SET);
2561 if(fwrite(block->md5_hash, TNG_MD5_HASH_LEN, 1, tng_data->output_file) != 1)
2563 fprintf(stderr, "TNG library: Could not write MD5 hash. %s: %d\n", __FILE__,
2564 __LINE__);
2565 return(TNG_CRITICAL);
2567 fseeko(tng_data->output_file, curr_file_pos, SEEK_SET);
2570 tng_block_destroy(&block);
2572 return(TNG_SUCCESS);
2576 * @brief Read the chain data of a molecules block.
2577 * @param tng_data is a trajectory data container.
2578 * @param chain is the chain data container.
2579 * @param hash_mode is an option to decide whether to generate/update the relevant md5 hashes.
2580 * @param md5_state is a pointer to the current md5 storage, which will be updated appropriately
2581 * if hash_mode == TNG_USE_HASH.
2582 * @return TNG_SUCCESS(0) is successful.
2584 static tng_function_status tng_chain_data_read(const tng_trajectory_t tng_data,
2585 const tng_chain_t chain,
2586 const char hash_mode,
2587 md5_state_t *md5_state)
2589 if(tng_file_input_numerical(tng_data, &chain->id,
2590 sizeof(chain->id),
2591 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
2593 return(TNG_CRITICAL);
2596 tng_freadstr(tng_data, &chain->name, hash_mode, md5_state, __LINE__);
2598 if(tng_file_input_numerical(tng_data, &chain->n_residues,
2599 sizeof(chain->n_residues),
2600 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
2602 return(TNG_CRITICAL);
2605 return(TNG_SUCCESS);
2609 * @brief Write the chain data of a molecules block.
2610 * @param tng_data is a trajectory data container.
2611 * @param chain is the chain data container.
2612 * @param hash_mode is an option to decide whether to generate/update the relevant md5 hashes.
2613 * @param md5_state is a pointer to the current md5 storage, which will be updated appropriately
2614 * if hash_mode == TNG_USE_HASH.
2615 * @return TNG_SUCCESS(0) is successful.
2617 static tng_function_status tng_chain_data_write(const tng_trajectory_t tng_data,
2618 const tng_chain_t chain,
2619 const char hash_mode,
2620 md5_state_t *md5_state)
2622 if(tng_file_output_numerical(tng_data, &chain->id,
2623 sizeof(chain->id),
2624 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
2626 return(TNG_CRITICAL);
2629 if(tng_fwritestr(tng_data, chain->name, hash_mode,
2630 md5_state, __LINE__) == TNG_CRITICAL)
2632 return(TNG_CRITICAL);
2635 if(tng_file_output_numerical(tng_data, &chain->n_residues,
2636 sizeof(chain->n_residues),
2637 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
2639 return(TNG_CRITICAL);
2642 return(TNG_SUCCESS);
2646 * @brief Read the residue data of a molecules block.
2647 * @param tng_data is a trajectory data container.
2648 * @param residue is the residue data container.
2649 * @param hash_mode is an option to decide whether to generate/update the relevant md5 hashes.
2650 * @param md5_state is a pointer to the current md5 storage, which will be updated appropriately
2651 * if hash_mode == TNG_USE_HASH.
2652 * @return TNG_SUCCESS(0) is successful.
2654 static tng_function_status tng_residue_data_read(const tng_trajectory_t tng_data,
2655 const tng_residue_t residue,
2656 const char hash_mode,
2657 md5_state_t *md5_state)
2659 if(tng_file_input_numerical(tng_data, &residue->id,
2660 sizeof(residue->id),
2661 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
2663 return(TNG_CRITICAL);
2666 tng_freadstr(tng_data, &residue->name, hash_mode, md5_state, __LINE__);
2668 if(tng_file_input_numerical(tng_data, &residue->n_atoms,
2669 sizeof(residue->n_atoms),
2670 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
2672 return(TNG_CRITICAL);
2675 return(TNG_SUCCESS);
2679 * @brief Write the residue data of a molecules block.
2680 * @param tng_data is a trajectory data container.
2681 * @param residue is the residue data container.
2682 * @param hash_mode is an option to decide whether to generate/update the relevant md5 hashes.
2683 * @param md5_state is a pointer to the current md5 storage, which will be updated appropriately
2684 * if hash_mode == TNG_USE_HASH.
2685 * @return TNG_SUCCESS(0) is successful.
2687 static tng_function_status tng_residue_data_write(const tng_trajectory_t tng_data,
2688 const tng_residue_t residue,
2689 const char hash_mode,
2690 md5_state_t *md5_state)
2692 if(tng_file_output_numerical(tng_data, &residue->id,
2693 sizeof(residue->id),
2694 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
2696 return(TNG_CRITICAL);
2699 if(tng_fwritestr(tng_data, residue->name, hash_mode,
2700 md5_state, __LINE__) == TNG_CRITICAL)
2702 return(TNG_CRITICAL);
2705 if(tng_file_output_numerical(tng_data, &residue->n_atoms,
2706 sizeof(residue->n_atoms),
2707 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
2709 return(TNG_CRITICAL);
2712 return(TNG_SUCCESS);
2716 * @brief Read the atom data of a molecules block.
2717 * @param tng_data is a trajectory data container.
2718 * @param atom is the atom data container.
2719 * @param hash_mode is an option to decide whether to generate/update the relevant md5 hashes.
2720 * @param md5_state is a pointer to the current md5 storage, which will be updated appropriately
2721 * if hash_mode == TNG_USE_HASH.
2722 * @return TNG_SUCCESS(0) is successful.
2724 static tng_function_status tng_atom_data_read(const tng_trajectory_t tng_data,
2725 const tng_atom_t atom,
2726 const char hash_mode,
2727 md5_state_t *md5_state)
2729 if(tng_file_input_numerical(tng_data, &atom->id,
2730 sizeof(atom->id),
2731 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
2733 return(TNG_CRITICAL);
2736 tng_freadstr(tng_data, &atom->name, hash_mode, md5_state, __LINE__);
2738 tng_freadstr(tng_data, &atom->atom_type, hash_mode, md5_state, __LINE__);
2740 return(TNG_SUCCESS);
2744 * @brief Write the atom data of a molecules block.
2745 * @param tng_data is a trajectory data container.
2746 * @param atom is the atom data container.
2747 * @param hash_mode is an option to decide whether to generate/update the relevant md5 hashes.
2748 * @param md5_state is a pointer to the current md5 storage, which will be updated appropriately
2749 * if hash_mode == TNG_USE_HASH.
2750 * @return TNG_SUCCESS(0) is successful.
2752 static tng_function_status tng_atom_data_write(const tng_trajectory_t tng_data,
2753 const tng_atom_t atom,
2754 const char hash_mode,
2755 md5_state_t *md5_state)
2757 if(tng_file_output_numerical(tng_data, &atom->id,
2758 sizeof(atom->id),
2759 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
2761 return(TNG_CRITICAL);
2764 if(tng_fwritestr(tng_data, atom->name, hash_mode,
2765 md5_state, __LINE__) == TNG_CRITICAL)
2767 return(TNG_CRITICAL);
2770 if(tng_fwritestr(tng_data, atom->atom_type, hash_mode,
2771 md5_state, __LINE__) == TNG_CRITICAL)
2773 return(TNG_CRITICAL);
2776 return(TNG_SUCCESS);
2779 static tng_function_status tng_molecules_block_len_calculate
2780 (const tng_trajectory_t tng_data,
2781 int64_t *len)
2783 int64_t i, j;
2784 tng_molecule_t molecule;
2785 tng_chain_t chain;
2786 tng_residue_t residue;
2787 tng_atom_t atom;
2788 tng_bond_t bond;
2790 *len = 0;
2792 for(i = 0; i < tng_data->n_molecules; i++)
2794 molecule = &tng_data->molecules[i];
2795 if(!molecule->name)
2797 molecule->name = (char *)malloc(1);
2798 if(!molecule->name)
2800 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
2801 __FILE__, __LINE__);
2802 return(TNG_CRITICAL);
2804 molecule->name[0] = 0;
2806 *len += tng_min_size(strlen(molecule->name) + 1, TNG_MAX_STR_LEN);
2808 chain = molecule->chains;
2809 for(j = 0; j < molecule->n_chains; j++)
2811 *len += sizeof(chain->id);
2813 if(!chain->name)
2815 chain->name = (char *)malloc(1);
2816 if(!chain->name)
2818 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
2819 __FILE__, __LINE__);
2820 return(TNG_CRITICAL);
2822 chain->name[0] = 0;
2824 *len += tng_min_size(strlen(chain->name) + 1, TNG_MAX_STR_LEN);
2826 *len += sizeof(chain->n_residues);
2828 chain++;
2831 residue = molecule->residues;
2832 for(j = 0; j < molecule->n_residues; j++)
2834 *len += sizeof(residue->id);
2836 if(!residue->name)
2838 residue->name = (char *)malloc(1);
2839 if(!residue->name)
2841 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
2842 __FILE__, __LINE__);
2843 return(TNG_CRITICAL);
2845 residue->name[0] = 0;
2847 *len += tng_min_size(strlen(residue->name) + 1, TNG_MAX_STR_LEN);
2849 *len += sizeof(residue->n_atoms);
2851 residue++;
2854 atom = molecule->atoms;
2855 for(j = 0; j < molecule->n_atoms; j++)
2857 *len += sizeof(atom->id);
2858 if(!atom->name)
2860 atom->name = (char *)malloc(1);
2861 if(!atom->name)
2863 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
2864 __FILE__, __LINE__);
2865 return(TNG_CRITICAL);
2867 atom->name[0] = 0;
2869 *len += tng_min_size(strlen(atom->name) + 1, TNG_MAX_STR_LEN);
2871 if(!atom->atom_type)
2873 atom->atom_type = (char *)malloc(1);
2874 if(!atom->atom_type)
2876 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
2877 __FILE__, __LINE__);
2878 return(TNG_CRITICAL);
2880 atom->atom_type[0] = 0;
2882 *len += tng_min_size(strlen(atom->atom_type) + 1, TNG_MAX_STR_LEN);
2884 atom++;
2887 for(j = 0; j < molecule->n_bonds; j++)
2889 *len += sizeof(bond->from_atom_id) + sizeof(bond->to_atom_id);
2892 *len += sizeof(tng_data->n_molecules) +
2893 (sizeof(molecule->id) +
2894 sizeof(molecule->quaternary_str) +
2895 sizeof(molecule->n_chains) +
2896 sizeof(molecule->n_residues) +
2897 sizeof(molecule->n_atoms) +
2898 sizeof(molecule->n_bonds)) *
2899 tng_data->n_molecules;
2901 if(!tng_data->var_num_atoms_flag)
2903 *len += tng_data->n_molecules * sizeof(int64_t);
2906 return(TNG_SUCCESS);
2910 * @brief Read a molecules block. Contains chain, residue and atom data
2911 * @param tng_data is a trajectory data container.
2912 * @param block is a general block container.
2913 * @param hash_mode is an option to decide whether to use the md5 hash or not.
2914 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
2915 * compared to the md5 hash of the read contents to ensure valid data.
2916 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
2917 * error has occured.
2919 static tng_function_status tng_molecules_block_read
2920 (const tng_trajectory_t tng_data,
2921 const tng_gen_block_t block,
2922 const char hash_mode)
2924 int64_t start_pos, i, j, k, l;
2925 tng_molecule_t molecule;
2926 tng_chain_t chain;
2927 tng_residue_t residue;
2928 tng_atom_t atom;
2929 tng_bond_t bond;
2930 char hash[TNG_MD5_HASH_LEN];
2931 md5_state_t md5_state;
2933 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
2935 return(TNG_CRITICAL);
2938 start_pos = ftello(tng_data->input_file);
2940 /* FIXME: Does not check if the size of the contents matches the expected
2941 * size or if the contents can be read. */
2943 if(tng_data->molecules)
2945 for(i=0; i<tng_data->n_molecules; i++)
2947 tng_molecule_destroy(tng_data, &tng_data->molecules[i]);
2949 free(tng_data->molecules);
2950 tng_data->molecules = 0;
2951 tng_data->n_molecules = 0;
2954 if(hash_mode == TNG_USE_HASH)
2956 md5_init(&md5_state);
2959 if(tng_file_input_numerical(tng_data, &tng_data->n_molecules,
2960 sizeof(tng_data->n_molecules),
2961 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2963 return(TNG_CRITICAL);
2966 if(tng_data->molecules)
2968 free(tng_data->molecules);
2971 tng_data->n_particles = 0;
2973 tng_data->molecules = (struct tng_molecule *)malloc(tng_data->n_molecules *
2974 sizeof(struct tng_molecule));
2975 if(!tng_data->molecules)
2977 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n", __FILE__, __LINE__);
2978 return(TNG_CRITICAL);
2981 if(!tng_data->var_num_atoms_flag)
2983 if(tng_data->molecule_cnt_list)
2985 free(tng_data->molecule_cnt_list);
2987 tng_data->molecule_cnt_list = (int64_t *)malloc(sizeof(int64_t) *
2988 tng_data->n_molecules);
2989 if(!tng_data->molecule_cnt_list)
2991 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n", __FILE__, __LINE__);
2992 return(TNG_CRITICAL);
2996 /* Read each molecule from file */
2997 for(i=0; i < tng_data->n_molecules; i++)
2999 molecule = &tng_data->molecules[i];
3001 molecule->name = 0;
3003 if(tng_file_input_numerical(tng_data, &molecule->id,
3004 sizeof(molecule->id),
3005 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3007 return(TNG_CRITICAL);
3010 /* fprintf(stderr, "TNG library: Read id: %" PRId64 " offset: %d\n", molecule->id, offset);*/
3011 tng_freadstr(tng_data, &molecule->name, hash_mode, &md5_state, __LINE__);
3013 if(tng_file_input_numerical(tng_data, &molecule->quaternary_str,
3014 sizeof(molecule->quaternary_str),
3015 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3017 return(TNG_CRITICAL);
3020 if(!tng_data->var_num_atoms_flag)
3022 if(tng_file_input_numerical(tng_data, &tng_data->molecule_cnt_list[i],
3023 sizeof(int64_t),
3024 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3026 return(TNG_CRITICAL);
3030 if(tng_file_input_numerical(tng_data, &molecule->n_chains,
3031 sizeof(molecule->n_chains),
3032 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3034 return(TNG_CRITICAL);
3037 if(tng_file_input_numerical(tng_data, &molecule->n_residues,
3038 sizeof(molecule->n_residues),
3039 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3041 return(TNG_CRITICAL);
3044 if(tng_file_input_numerical(tng_data, &molecule->n_atoms,
3045 sizeof(molecule->n_atoms),
3046 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3048 return(TNG_CRITICAL);
3051 tng_data->n_particles += molecule->n_atoms *
3052 tng_data->molecule_cnt_list[i];
3054 if(molecule->n_chains > 0)
3056 molecule->chains = (struct tng_chain *)malloc(molecule->n_chains *
3057 sizeof(struct tng_chain));
3058 if(!molecule->chains)
3060 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
3061 __FILE__, __LINE__);
3062 return(TNG_CRITICAL);
3065 chain = molecule->chains;
3067 else
3069 chain = 0;
3072 if(molecule->n_residues > 0)
3074 molecule->residues = (struct tng_residue *)malloc(molecule->n_residues *
3075 sizeof(struct tng_residue));
3076 if(!molecule->residues)
3078 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
3079 __FILE__, __LINE__);
3080 if(molecule->chains)
3082 free(molecule->chains);
3083 molecule->chains = 0;
3085 return(TNG_CRITICAL);
3088 residue = molecule->residues;
3090 else
3092 residue = 0;
3095 molecule->atoms = (struct tng_atom *)malloc(molecule->n_atoms *
3096 sizeof(struct tng_atom));
3097 if(!molecule->atoms)
3099 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
3100 __FILE__, __LINE__);
3101 if(molecule->chains)
3103 free(molecule->chains);
3104 molecule->chains = 0;
3106 if(molecule->residues)
3108 free(molecule->residues);
3109 molecule->residues = 0;
3111 return(TNG_CRITICAL);
3114 atom = molecule->atoms;
3116 if(molecule->n_chains > 0)
3118 /* Read the chains of the molecule */
3119 for(j=0; j<molecule->n_chains; j++)
3121 chain->molecule = molecule;
3123 chain->name = 0;
3125 tng_chain_data_read(tng_data, chain, hash_mode, &md5_state);
3127 if(j==0)
3129 chain->residues = molecule->residues;
3130 residue = chain->residues;
3132 else
3134 chain->residues = residue;
3137 /* Read the residues of the chain */
3138 for(k=0; k<chain->n_residues; k++)
3140 residue->chain = chain;
3142 residue->name = 0;
3144 tng_residue_data_read(tng_data, residue, hash_mode, &md5_state);
3146 residue->atoms_offset = atom - molecule->atoms;
3147 /* Read the atoms of the residue */
3148 for(l=0; l<residue->n_atoms; l++)
3150 atom->residue = residue;
3152 atom->name = 0;
3153 atom->atom_type = 0;
3155 tng_atom_data_read(tng_data,atom, hash_mode, &md5_state);
3157 atom++;
3159 residue++;
3161 chain++;
3164 else
3166 if(molecule->n_residues > 0)
3168 for(k=0; k<molecule->n_residues; k++)
3170 residue->chain = 0;
3172 residue->name = 0;
3174 tng_residue_data_read(tng_data, residue, hash_mode, &md5_state);
3176 residue->atoms_offset = atom - molecule->atoms;
3177 /* Read the atoms of the residue */
3178 for(l=0; l<residue->n_atoms; l++)
3180 atom->residue = residue;
3182 tng_atom_data_read(tng_data, atom, hash_mode, &md5_state);
3184 atom++;
3186 residue++;
3189 else
3191 for(l=0; l<molecule->n_atoms; l++)
3193 atom->residue = 0;
3195 atom->name = 0;
3196 atom->atom_type = 0;
3198 tng_atom_data_read(tng_data, atom, hash_mode, &md5_state);
3200 atom++;
3205 if(tng_file_input_numerical(tng_data, &molecule->n_bonds,
3206 sizeof(molecule->n_bonds),
3207 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3209 return(TNG_CRITICAL);
3212 if(molecule->n_bonds > 0)
3214 tng_data->molecules[i].bonds = (struct tng_bond *)malloc(molecule->n_bonds *
3215 sizeof(struct tng_bond));
3216 if(!molecule->bonds)
3218 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
3219 __FILE__, __LINE__);
3220 if(molecule->chains)
3222 free(molecule->chains);
3223 molecule->chains = 0;
3225 if(molecule->residues)
3227 free(molecule->residues);
3228 molecule->residues = 0;
3230 if(molecule->atoms)
3232 free(molecule->atoms);
3233 molecule->atoms = 0;
3235 return(TNG_CRITICAL);
3238 bond = molecule->bonds;
3240 for(j=0; j<molecule->n_bonds; j++)
3242 if(tng_file_input_numerical(tng_data, &bond->from_atom_id,
3243 sizeof(bond->from_atom_id),
3244 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3246 return(TNG_CRITICAL);
3249 if(tng_file_input_numerical(tng_data, &bond->to_atom_id,
3250 sizeof(bond->to_atom_id),
3251 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3253 return(TNG_CRITICAL);
3256 bond++;
3259 else
3261 molecule->bonds = 0;
3265 if(hash_mode == TNG_USE_HASH)
3267 /* If there is data left in the block that the current version of the library
3268 * cannot interpret still read that to generate the MD5 hash. */
3269 tng_md5_remaining_append(tng_data, block, start_pos, &md5_state);
3271 md5_finish(&md5_state, (md5_byte_t *)hash);
3272 if(strncmp(block->md5_hash, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", TNG_MD5_HASH_LEN) != 0)
3274 if(strncmp(block->md5_hash, hash, TNG_MD5_HASH_LEN) != 0)
3276 fprintf(stderr, "TNG library: Molecules block contents corrupt. Hashes do not match. "
3277 "%s: %d\n", __FILE__, __LINE__);
3282 else
3284 /* Seek to the end of the block */
3285 fseeko(tng_data->input_file, start_pos + block->block_contents_size, SEEK_SET);
3288 return(TNG_SUCCESS);
3292 * @brief Write a molecules block.
3293 * @param tng_data is a trajectory data container.
3294 * @param hash_mode is an option to decide whether to use the md5 hash or not.
3295 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
3296 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
3297 * error has occured.
3299 static tng_function_status tng_molecules_block_write
3300 (const tng_trajectory_t tng_data,
3301 const char hash_mode)
3303 int name_len;
3304 int64_t i, j, k, l, header_file_pos, curr_file_pos;
3305 tng_molecule_t molecule;
3306 tng_chain_t chain;
3307 tng_residue_t residue;
3308 tng_atom_t atom;
3309 tng_bond_t bond;
3310 tng_gen_block_t block;
3311 md5_state_t md5_state;
3313 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
3315 return(TNG_CRITICAL);
3318 tng_block_init(&block);
3320 name_len = (unsigned int)strlen("MOLECULES");
3322 block->name = (char *)malloc(name_len + 1);
3323 if(!block->name)
3325 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n", __FILE__, __LINE__);
3326 tng_block_destroy(&block);
3327 return(TNG_CRITICAL);
3330 strcpy(block->name, "MOLECULES");
3331 block->id = TNG_MOLECULES;
3333 if(tng_molecules_block_len_calculate(tng_data, &block->block_contents_size) !=
3334 TNG_SUCCESS)
3336 fprintf(stderr, "TNG library: Cannot calculate length of molecules block. %s: %d\n",
3337 __FILE__, __LINE__);
3338 tng_block_destroy(&block);
3339 return(TNG_CRITICAL);
3342 header_file_pos = ftello(tng_data->output_file);
3344 if(tng_block_header_write(tng_data, block) != TNG_SUCCESS)
3346 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
3347 tng_data->output_file_path, __FILE__, __LINE__);
3348 tng_block_destroy(&block);
3349 return(TNG_CRITICAL);
3352 if(hash_mode == TNG_USE_HASH)
3354 md5_init(&md5_state);
3357 if(tng_file_output_numerical(tng_data, &tng_data->n_molecules,
3358 sizeof(tng_data->n_molecules),
3359 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3361 return(TNG_CRITICAL);
3364 for(i = 0; i < tng_data->n_molecules; i++)
3366 molecule = &tng_data->molecules[i];
3368 if(tng_file_output_numerical(tng_data, &molecule->id,
3369 sizeof(molecule->id),
3370 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3372 return(TNG_CRITICAL);
3375 if(tng_fwritestr(tng_data, molecule->name, hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3377 return(TNG_CRITICAL);
3380 if(tng_file_output_numerical(tng_data, &molecule->quaternary_str,
3381 sizeof(molecule->quaternary_str),
3382 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3384 return(TNG_CRITICAL);
3387 if(!tng_data->var_num_atoms_flag)
3389 if(tng_file_output_numerical(tng_data, &tng_data->molecule_cnt_list[i],
3390 sizeof(int64_t),
3391 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3393 return(TNG_CRITICAL);
3397 if(tng_file_output_numerical(tng_data, &molecule->n_chains,
3398 sizeof(molecule->n_chains),
3399 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3401 return(TNG_CRITICAL);
3404 if(tng_file_output_numerical(tng_data, &molecule->n_residues,
3405 sizeof(molecule->n_residues),
3406 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3408 return(TNG_CRITICAL);
3411 if(tng_file_output_numerical(tng_data, &molecule->n_atoms,
3412 sizeof(molecule->n_atoms),
3413 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3415 return(TNG_CRITICAL);
3418 if(molecule->n_chains > 0)
3420 chain = molecule->chains;
3421 for(j = 0; j < molecule->n_chains; j++)
3423 tng_chain_data_write(tng_data, chain, hash_mode, &md5_state);
3425 residue = chain->residues;
3426 for(k = 0; k < chain->n_residues; k++)
3428 tng_residue_data_write(tng_data, residue, hash_mode, &md5_state);
3430 atom = molecule->atoms + residue->atoms_offset;
3431 for(l = 0; l < residue->n_atoms; l++)
3433 tng_atom_data_write(tng_data, atom, hash_mode, &md5_state);
3435 atom++;
3437 residue++;
3439 chain++;
3442 else
3444 if(molecule->n_residues > 0)
3446 residue = molecule->residues;
3447 for(k = 0; k < molecule->n_residues; k++)
3449 tng_residue_data_write(tng_data, residue, hash_mode, &md5_state);
3451 atom = molecule->atoms + residue->atoms_offset;
3452 for(l = 0; l < residue->n_atoms; l++)
3454 tng_atom_data_write(tng_data, atom, hash_mode, &md5_state);
3456 atom++;
3458 residue++;
3461 else
3463 atom = molecule->atoms;
3464 for(l = 0; l < molecule->n_atoms; l++)
3466 tng_atom_data_write(tng_data, atom, hash_mode, &md5_state);
3468 atom++;
3473 if(tng_file_output_numerical(tng_data, &molecule->n_bonds,
3474 sizeof(molecule->n_bonds),
3475 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3477 return(TNG_CRITICAL);
3480 bond = molecule->bonds;
3481 for(j = 0; j < molecule->n_bonds; j++)
3483 if(tng_file_output_numerical(tng_data, &bond->from_atom_id,
3484 sizeof(bond->from_atom_id),
3485 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3487 return(TNG_CRITICAL);
3490 if(tng_file_output_numerical(tng_data, &bond->to_atom_id,
3491 sizeof(bond->to_atom_id),
3492 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3494 return(TNG_CRITICAL);
3497 bond++;
3500 if(hash_mode == TNG_USE_HASH)
3502 md5_finish(&md5_state, (md5_byte_t *)block->md5_hash);
3503 curr_file_pos = ftello(tng_data->output_file);
3504 fseeko(tng_data->output_file, header_file_pos +
3505 3 * sizeof(int64_t), SEEK_SET);
3506 if(fwrite(block->md5_hash, TNG_MD5_HASH_LEN, 1, tng_data->output_file) != 1)
3508 fprintf(stderr, "TNG library: Could not write MD5 hash. %s: %d\n", __FILE__,
3509 __LINE__);
3510 return(TNG_CRITICAL);
3512 fseeko(tng_data->output_file, curr_file_pos, SEEK_SET);
3515 tng_block_destroy(&block);
3517 return(TNG_SUCCESS);
3520 static tng_function_status tng_frame_set_block_len_calculate
3521 (const tng_trajectory_t tng_data,
3522 int64_t *len)
3524 *len = sizeof(int64_t) * 8;
3525 *len += sizeof(double) * 2;
3527 if(tng_data->var_num_atoms_flag)
3529 *len += sizeof(int64_t) * tng_data->n_molecules;
3531 return(TNG_SUCCESS);
3535 * @brief Read a frame set block. Update tng_data->current_trajectory_frame_set
3536 * @param tng_data is a trajectory data container.
3537 * @param block is a general block container.
3538 * @param hash_mode is an option to decide whether to use the md5 hash or not.
3539 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
3540 * compared to the md5 hash of the read contents to ensure valid data.
3541 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
3542 * error has occured.
3544 static tng_function_status tng_frame_set_block_read
3545 (tng_trajectory_t tng_data,
3546 tng_gen_block_t block,
3547 const char hash_mode)
3549 int64_t file_pos, start_pos, i, prev_n_particles;
3550 tng_trajectory_frame_set_t frame_set =
3551 &tng_data->current_trajectory_frame_set;
3552 char hash[TNG_MD5_HASH_LEN];
3553 md5_state_t md5_state;
3555 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
3557 return(TNG_CRITICAL);
3560 start_pos = ftello(tng_data->input_file);
3562 /* FIXME: Does not check if the size of the contents matches the expected
3563 * size or if the contents can be read. */
3565 file_pos = start_pos - block->header_contents_size;
3567 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
3569 tng_frame_set_particle_mapping_free(tng_data);
3571 if(hash_mode == TNG_USE_HASH)
3573 md5_init(&md5_state);
3575 if(tng_file_input_numerical(tng_data, &frame_set->first_frame,
3576 sizeof(frame_set->first_frame),
3577 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3579 return(TNG_CRITICAL);
3582 if(tng_file_input_numerical(tng_data, &frame_set->n_frames,
3583 sizeof(frame_set->n_frames),
3584 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3586 return(TNG_CRITICAL);
3589 if(tng_data->var_num_atoms_flag)
3591 prev_n_particles = frame_set->n_particles;
3592 frame_set->n_particles = 0;
3593 /* If the list of molecule counts has already been created assume that
3594 * it is of correct size. */
3595 if(!frame_set->molecule_cnt_list)
3597 frame_set->molecule_cnt_list =
3598 (int64_t *)malloc(sizeof(int64_t) * tng_data->n_molecules);
3600 if(!frame_set->molecule_cnt_list)
3602 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
3603 __FILE__, __LINE__);
3604 return(TNG_CRITICAL);
3607 for(i = 0; i < tng_data->n_molecules; i++)
3609 if(tng_file_input_numerical(tng_data, &frame_set->molecule_cnt_list[i],
3610 sizeof(int64_t),
3611 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3613 return(TNG_CRITICAL);
3616 frame_set->n_particles += tng_data->molecules[i].n_atoms *
3617 frame_set->molecule_cnt_list[i];
3619 if(prev_n_particles && frame_set->n_particles != prev_n_particles)
3621 /* FIXME: Particle dependent data memory management */
3625 if(tng_file_input_numerical(tng_data, &frame_set->next_frame_set_file_pos,
3626 sizeof(frame_set->next_frame_set_file_pos),
3627 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3629 return(TNG_CRITICAL);
3632 if(tng_file_input_numerical(tng_data, &frame_set->prev_frame_set_file_pos,
3633 sizeof(frame_set->prev_frame_set_file_pos),
3634 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3636 return(TNG_CRITICAL);
3639 if(tng_file_input_numerical(tng_data, &frame_set->medium_stride_next_frame_set_file_pos,
3640 sizeof(frame_set->medium_stride_next_frame_set_file_pos),
3641 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3643 return(TNG_CRITICAL);
3646 if(tng_file_input_numerical(tng_data, &frame_set->medium_stride_prev_frame_set_file_pos,
3647 sizeof(frame_set->medium_stride_prev_frame_set_file_pos),
3648 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3650 return(TNG_CRITICAL);
3653 if(tng_file_input_numerical(tng_data, &frame_set->long_stride_next_frame_set_file_pos,
3654 sizeof(frame_set->long_stride_next_frame_set_file_pos),
3655 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3657 return(TNG_CRITICAL);
3660 if(tng_file_input_numerical(tng_data, &frame_set->long_stride_prev_frame_set_file_pos,
3661 sizeof(frame_set->long_stride_prev_frame_set_file_pos),
3662 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3664 return(TNG_CRITICAL);
3667 if(block->block_version >= 3)
3669 if(tng_file_input_numerical(tng_data, &frame_set->first_frame_time,
3670 sizeof(frame_set->first_frame_time),
3671 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3673 return(TNG_CRITICAL);
3676 if(tng_file_input_numerical(tng_data, &tng_data->time_per_frame,
3677 sizeof(tng_data->time_per_frame),
3678 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3680 return(TNG_CRITICAL);
3683 else
3685 frame_set->first_frame_time = -1;
3686 tng_data->time_per_frame = -1;
3689 if(hash_mode == TNG_USE_HASH)
3691 /* If there is data left in the block that the current version of the library
3692 * cannot interpret still read that to generate the MD5 hash. */
3693 tng_md5_remaining_append(tng_data, block, start_pos, &md5_state);
3695 md5_finish(&md5_state, (md5_byte_t *)hash);
3696 if(strncmp(block->md5_hash, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", TNG_MD5_HASH_LEN) != 0)
3698 if(strncmp(block->md5_hash, hash, TNG_MD5_HASH_LEN) != 0)
3700 fprintf(stderr, "TNG library: Frame set block contents corrupt (first frame %" PRId64 "). Hashes do not match. "
3701 "%s: %d\n", frame_set->first_frame, __FILE__, __LINE__);
3705 else
3707 /* Seek to the end of the block */
3708 fseeko(tng_data->input_file, start_pos + block->block_contents_size, SEEK_SET);
3711 /* If the output file and the input files are the same the number of
3712 * frames in the file are the same number as has just been read.
3713 * This is updated here to later on see if there have been new frames
3714 * added and thereby the frame set needs to be rewritten. */
3715 if(tng_data->output_file == tng_data->input_file)
3717 frame_set->n_written_frames = frame_set->n_frames;
3720 return(TNG_SUCCESS);
3724 * @brief Write tng_data->current_trajectory_frame_set to file
3725 * @param tng_data is a trajectory data container.
3726 * @param block is a general block container.
3727 * @param hash_mode is an option to decide whether to use the md5 hash or not.
3728 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
3729 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
3730 * error has occured.
3732 static tng_function_status tng_frame_set_block_write
3733 (const tng_trajectory_t tng_data,
3734 const tng_gen_block_t block,
3735 const char hash_mode)
3737 char *temp_name;
3738 int64_t i, header_file_pos, curr_file_pos;
3739 unsigned int name_len;
3740 tng_trajectory_frame_set_t frame_set =
3741 &tng_data->current_trajectory_frame_set;
3742 md5_state_t md5_state;
3744 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
3746 return(TNG_CRITICAL);
3749 name_len = (unsigned int)strlen("TRAJECTORY FRAME SET");
3751 if(!block->name || strlen(block->name) < name_len)
3753 temp_name = (char *)realloc(block->name, name_len + 1);
3754 if(!temp_name)
3756 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
3757 __FILE__, __LINE__);
3758 free(block->name);
3759 block->name = 0;
3760 return(TNG_CRITICAL);
3762 block->name = temp_name;
3764 strcpy(block->name, "TRAJECTORY FRAME SET");
3765 block->id = TNG_TRAJECTORY_FRAME_SET;
3767 if(tng_frame_set_block_len_calculate(tng_data, &block->block_contents_size) !=
3768 TNG_SUCCESS)
3770 fprintf(stderr, "TNG library: Cannot calculate length of frame set block. %s: %d\n",
3771 __FILE__, __LINE__);
3772 return(TNG_CRITICAL);
3775 header_file_pos = ftello(tng_data->output_file);
3777 if(tng_block_header_write(tng_data, block) != TNG_SUCCESS)
3779 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
3780 tng_data->output_file_path, __FILE__, __LINE__);
3781 return(TNG_CRITICAL);
3784 if(hash_mode == TNG_USE_HASH)
3786 md5_init(&md5_state);
3788 if(tng_file_output_numerical(tng_data, &frame_set->first_frame,
3789 sizeof(frame_set->first_frame),
3790 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3792 return(TNG_CRITICAL);
3795 if(tng_file_output_numerical(tng_data, &frame_set->n_frames,
3796 sizeof(frame_set->n_frames),
3797 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3799 return(TNG_CRITICAL);
3802 if(tng_data->var_num_atoms_flag)
3804 for(i = 0; i < tng_data->n_molecules; i++)
3806 if(tng_file_output_numerical(tng_data, &frame_set->molecule_cnt_list[i],
3807 sizeof(int64_t),
3808 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3810 return(TNG_CRITICAL);
3815 if(tng_file_output_numerical(tng_data, &frame_set->next_frame_set_file_pos,
3816 sizeof(frame_set->next_frame_set_file_pos),
3817 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3819 return(TNG_CRITICAL);
3822 if(tng_file_output_numerical(tng_data, &frame_set->prev_frame_set_file_pos,
3823 sizeof(frame_set->prev_frame_set_file_pos),
3824 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3826 return(TNG_CRITICAL);
3829 if(tng_file_output_numerical(tng_data, &frame_set->medium_stride_next_frame_set_file_pos,
3830 sizeof(frame_set->medium_stride_next_frame_set_file_pos),
3831 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3833 return(TNG_CRITICAL);
3836 if(tng_file_output_numerical(tng_data, &frame_set->medium_stride_prev_frame_set_file_pos,
3837 sizeof(frame_set->medium_stride_prev_frame_set_file_pos),
3838 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3840 return(TNG_CRITICAL);
3843 if(tng_file_output_numerical(tng_data, &frame_set->long_stride_next_frame_set_file_pos,
3844 sizeof(frame_set->long_stride_next_frame_set_file_pos),
3845 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3847 return(TNG_CRITICAL);
3850 if(tng_file_output_numerical(tng_data, &frame_set->long_stride_prev_frame_set_file_pos,
3851 sizeof(frame_set->long_stride_prev_frame_set_file_pos),
3852 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3854 return(TNG_CRITICAL);
3857 if(tng_file_output_numerical(tng_data, &frame_set->first_frame_time,
3858 sizeof(frame_set->first_frame_time),
3859 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3861 return(TNG_CRITICAL);
3864 if(tng_file_output_numerical(tng_data, &tng_data->time_per_frame,
3865 sizeof(tng_data->time_per_frame),
3866 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3868 return(TNG_CRITICAL);
3870 if(hash_mode == TNG_USE_HASH)
3872 md5_finish(&md5_state, (md5_byte_t *)block->md5_hash);
3873 curr_file_pos = ftello(tng_data->output_file);
3874 fseeko(tng_data->output_file, header_file_pos +
3875 3 * sizeof(int64_t), SEEK_SET);
3876 if(fwrite(block->md5_hash, TNG_MD5_HASH_LEN, 1, tng_data->output_file) != 1)
3878 fprintf(stderr, "TNG library: Could not write MD5 hash. %s: %d\n", __FILE__,
3879 __LINE__);
3880 return(TNG_CRITICAL);
3882 fseeko(tng_data->output_file, curr_file_pos, SEEK_SET);
3885 return(TNG_SUCCESS);
3888 static tng_function_status tng_trajectory_mapping_block_len_calculate
3889 (const tng_trajectory_t tng_data,
3890 const int64_t n_particles,
3891 int64_t *len)
3893 (void)tng_data;
3894 *len = sizeof(int64_t) * (2 + n_particles);
3896 return(TNG_SUCCESS);
3900 * @brief Read an atom mappings block (translating between real atom indexes and how
3901 * the atom info is written in this frame set).
3902 * @param tng_data is a trajectory data container.
3903 * @param block is a general block container.
3904 * @param hash_mode is an option to decide whether to use the md5 hash or not.
3905 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
3906 * compared to the md5 hash of the read contents to ensure valid data.
3907 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
3908 * error has occured.
3910 static tng_function_status tng_trajectory_mapping_block_read
3911 (const tng_trajectory_t tng_data,
3912 const tng_gen_block_t block,
3913 const char hash_mode)
3915 int64_t start_pos, i;
3916 tng_trajectory_frame_set_t frame_set =
3917 &tng_data->current_trajectory_frame_set;
3918 tng_particle_mapping_t mapping, mappings;
3919 char hash[TNG_MD5_HASH_LEN];
3920 md5_state_t md5_state;
3922 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
3924 return(TNG_CRITICAL);
3927 start_pos = ftello(tng_data->input_file);
3929 /* FIXME: Does not check if the size of the contents matches the expected
3930 * size or if the contents can be read. */
3932 frame_set->n_mapping_blocks++;
3933 mappings = (tng_particle_mapping_t)realloc(frame_set->mappings,
3934 sizeof(struct tng_particle_mapping) *
3935 frame_set->n_mapping_blocks);
3936 if(!mappings)
3938 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
3939 __FILE__, __LINE__);
3940 free(frame_set->mappings);
3941 frame_set->mappings = 0;
3942 return(TNG_CRITICAL);
3944 frame_set->mappings = mappings;
3945 mapping = &mappings[frame_set->n_mapping_blocks - 1];
3948 if(hash_mode == TNG_USE_HASH)
3950 md5_init(&md5_state);
3953 if(tng_file_input_numerical(tng_data, &mapping->num_first_particle,
3954 sizeof(mapping->num_first_particle),
3955 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3957 return(TNG_CRITICAL);
3960 if(tng_file_input_numerical(tng_data, &mapping->n_particles,
3961 sizeof(mapping->n_particles),
3962 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3964 return(TNG_CRITICAL);
3967 mapping->real_particle_numbers = (int64_t *)malloc(mapping->n_particles *
3968 sizeof(int64_t));
3969 if(!mapping->real_particle_numbers)
3971 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
3972 __FILE__, __LINE__);
3973 return(TNG_CRITICAL);
3976 /* If the byte order needs to be swapped the data must be read one value at
3977 * a time and swapped */
3978 if(tng_data->input_endianness_swap_func_64)
3980 for(i = 0; i < mapping->n_particles; i++)
3982 if(tng_file_input_numerical(tng_data, &mapping->real_particle_numbers[i],
3983 sizeof(int64_t),
3984 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3986 return(TNG_CRITICAL);
3990 /* Otherwise the data can be read all at once */
3991 else
3993 if(fread(mapping->real_particle_numbers, mapping->n_particles * sizeof(int64_t),
3994 1, tng_data->input_file) == 0)
3996 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
3997 return(TNG_CRITICAL);
3999 if(hash_mode == TNG_USE_HASH)
4001 md5_append(&md5_state, (md5_byte_t *)mapping->real_particle_numbers, mapping->n_particles * sizeof(int64_t));
4005 if(hash_mode == TNG_USE_HASH)
4007 /* If there is data left in the block that the current version of the library
4008 * cannot interpret still read that to generate the MD5 hash. */
4009 tng_md5_remaining_append(tng_data, block, start_pos, &md5_state);
4011 md5_finish(&md5_state, (md5_byte_t *)hash);
4012 if(strncmp(block->md5_hash, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", TNG_MD5_HASH_LEN) != 0)
4014 if(strncmp(block->md5_hash, hash, TNG_MD5_HASH_LEN) != 0)
4016 fprintf(stderr, "TNG library: Particle mapping block contents corrupt. Hashes do not match. "
4017 "%s: %d\n", __FILE__, __LINE__);
4021 else
4023 /* Seek to the end of the block */
4024 fseeko(tng_data->input_file, start_pos + block->block_contents_size, SEEK_SET);
4027 return(TNG_SUCCESS);
4031 * @brief Write the atom mappings of the current trajectory frame set
4032 * @param tng_data is a trajectory data container.
4033 * @param block is a general block container.
4034 * @param mapping_block_nr is the index of the mapping block to write.
4035 * @param hash_mode is an option to decide whether to use the md5 hash or not.
4036 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
4037 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if a minor error
4038 * has occurred or TNG_CRITICAL (2) if a major error has occured.
4040 static tng_function_status tng_trajectory_mapping_block_write
4041 (const tng_trajectory_t tng_data,
4042 const tng_gen_block_t block,
4043 const int mapping_block_nr,
4044 const char hash_mode)
4046 int64_t header_file_pos, curr_file_pos;
4047 char *temp_name;
4048 int i;
4049 unsigned int name_len;
4050 md5_state_t md5_state;
4051 tng_particle_mapping_t mapping =
4052 &tng_data->current_trajectory_frame_set.mappings[mapping_block_nr];
4054 if(mapping_block_nr >=
4055 tng_data->current_trajectory_frame_set.n_mapping_blocks)
4057 fprintf(stderr, "TNG library: Mapping block index out of bounds. %s: %d\n",
4058 __FILE__, __LINE__);
4059 return(TNG_FAILURE);
4062 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
4064 return(TNG_CRITICAL);
4067 name_len = (unsigned int)strlen("PARTICLE MAPPING");
4069 if(!block->name || strlen(block->name) < name_len)
4071 temp_name = (char *)realloc(block->name, name_len + 1);
4072 if(!temp_name)
4074 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
4075 __FILE__, __LINE__);
4076 free(block->name);
4077 block->name = 0;
4078 return(TNG_CRITICAL);
4080 block->name = temp_name;
4082 strcpy(block->name, "PARTICLE MAPPING");
4083 block->id = TNG_PARTICLE_MAPPING;
4085 if(tng_trajectory_mapping_block_len_calculate(tng_data,
4086 mapping->n_particles,
4087 &block->block_contents_size) !=
4088 TNG_SUCCESS)
4090 fprintf(stderr, "TNG library: Cannot calculate length of atom mapping block. %s: %d\n",
4091 __FILE__, __LINE__);
4092 return(TNG_CRITICAL);
4095 header_file_pos = ftello(tng_data->output_file);
4097 if(tng_block_header_write(tng_data, block) != TNG_SUCCESS)
4099 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
4100 tng_data->output_file_path, __FILE__, __LINE__);
4101 return(TNG_CRITICAL);
4104 if(hash_mode == TNG_USE_HASH)
4106 md5_init(&md5_state);
4108 if(tng_file_output_numerical(tng_data, &mapping->num_first_particle,
4109 sizeof(mapping->num_first_particle),
4110 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
4112 return(TNG_CRITICAL);
4115 if(tng_file_output_numerical(tng_data, &mapping->n_particles,
4116 sizeof(mapping->n_particles),
4117 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
4119 return(TNG_CRITICAL);
4122 if(tng_data->output_endianness_swap_func_64)
4124 for(i = 0; i < mapping->n_particles; i++)
4126 if(tng_file_output_numerical(tng_data, &mapping->real_particle_numbers[i],
4127 sizeof(int64_t),
4128 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
4130 return(TNG_CRITICAL);
4134 else
4136 if(fwrite(mapping->real_particle_numbers,
4137 mapping->n_particles * sizeof(int64_t),
4138 1, tng_data->output_file) != 1)
4140 fprintf(stderr, "TNG library: Could not write block data. %s: %d\n", __FILE__, __LINE__);
4141 return(TNG_CRITICAL);
4143 if(hash_mode == TNG_USE_HASH)
4145 md5_append(&md5_state, (md5_byte_t *)mapping->real_particle_numbers,
4146 mapping->n_particles * sizeof(int64_t));
4150 if(hash_mode == TNG_USE_HASH)
4152 md5_finish(&md5_state, (md5_byte_t *)block->md5_hash);
4153 curr_file_pos = ftello(tng_data->output_file);
4154 fseeko(tng_data->output_file, header_file_pos +
4155 3 * sizeof(int64_t), SEEK_SET);
4156 if(fwrite(block->md5_hash, TNG_MD5_HASH_LEN, 1, tng_data->output_file) != 1)
4158 fprintf(stderr, "TNG library: Could not write MD5 hash. %s: %d\n", __FILE__,
4159 __LINE__);
4160 return(TNG_CRITICAL);
4162 fseeko(tng_data->output_file, curr_file_pos, SEEK_SET);
4165 return(TNG_SUCCESS);
4169 * @brief Prepare a block for storing particle data
4170 * @param tng_data is a trajectory data container.
4171 * @param block_type_flag specifies if this is a trajectory block or a
4172 * non-trajectory block. (TNG_TRAJECTORY_BLOCK or TNG_NON_TRAJECTORY_BLOCK)
4173 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
4174 * error has occured.
4176 static tng_function_status tng_particle_data_block_create
4177 (const tng_trajectory_t tng_data,
4178 const char block_type_flag)
4180 tng_trajectory_frame_set_t frame_set =
4181 &tng_data->current_trajectory_frame_set;
4183 tng_data_t data;
4185 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
4187 frame_set->n_particle_data_blocks++;
4188 data = (tng_data_t)realloc(frame_set->tr_particle_data,
4189 sizeof(struct tng_data) *
4190 frame_set->n_particle_data_blocks);
4191 if(!data)
4193 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
4194 __FILE__, __LINE__);
4195 free(frame_set->tr_particle_data);
4196 frame_set->tr_particle_data = 0;
4197 return(TNG_CRITICAL);
4199 frame_set->tr_particle_data = data;
4201 else
4203 tng_data->n_particle_data_blocks++;
4204 data = (tng_data_t)realloc(tng_data->non_tr_particle_data,
4205 sizeof(struct tng_data) *
4206 tng_data->n_particle_data_blocks);
4207 if(!data)
4209 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
4210 __FILE__, __LINE__);
4211 free(tng_data->non_tr_particle_data);
4212 tng_data->non_tr_particle_data = 0;
4213 return(TNG_CRITICAL);
4215 tng_data->non_tr_particle_data = data;
4218 return(TNG_SUCCESS);
4221 static tng_function_status tng_compress(const tng_trajectory_t tng_data,
4222 const tng_gen_block_t block,
4223 const int64_t n_frames,
4224 const int64_t n_particles,
4225 const char type,
4226 char **data,
4227 int64_t *new_len)
4229 int nalgo;
4230 int compressed_len;
4231 int *alt_algo = 0;
4232 char *dest;
4233 int64_t algo_find_n_frames = -1;
4234 float f_precision;
4235 double d_precision;
4237 if(block->id != TNG_TRAJ_POSITIONS &&
4238 block->id != TNG_TRAJ_VELOCITIES)
4240 fprintf(stderr, "TNG library: Can only compress positions and velocities with the "
4241 "TNG method. %s: %d\n", __FILE__, __LINE__);
4242 return(TNG_FAILURE);
4244 if(type != TNG_FLOAT_DATA && type != TNG_DOUBLE_DATA)
4246 fprintf(stderr, "TNG library: Data type not supported. %s: %d\n", __FILE__, __LINE__);
4247 return(TNG_FAILURE);
4250 if(n_frames <= 0 || n_particles <= 0)
4252 fprintf(stderr, "TNG library: Missing frames or particles. Cannot compress data "
4253 "with the TNG method. %s: %d\n", __FILE__, __LINE__);
4254 return(TNG_FAILURE);
4257 f_precision = 1/(float)tng_data->compression_precision;
4258 d_precision = 1/tng_data->compression_precision;
4260 if(block->id == TNG_TRAJ_POSITIONS)
4262 /* If there is only one frame in this frame set and there might be more
4263 * do not store the algorithm as the compression algorithm, but find
4264 * the best one without storing it */
4265 if(n_frames == 1 && tng_data->frame_set_n_frames > 1)
4267 nalgo = tng_compress_nalgo();
4268 alt_algo = (int *)malloc(nalgo * sizeof *tng_data->compress_algo_pos);
4270 /* If we have already determined the initial coding and
4271 * initial coding parameter do not determine them again. */
4272 if(tng_data->compress_algo_pos)
4274 alt_algo[0] = tng_data->compress_algo_pos[0];
4275 alt_algo[1] = tng_data->compress_algo_pos[1];
4276 alt_algo[2] = tng_data->compress_algo_pos[2];
4277 alt_algo[3] = tng_data->compress_algo_pos[3];
4279 else
4281 alt_algo[0] = -1;
4282 alt_algo[1] = -1;
4283 alt_algo[2] = -1;
4284 alt_algo[3] = -1;
4287 /* If the initial coding and initial coding parameter are -1
4288 * they will be determined in tng_compress_pos/_float/. */
4289 if(type == TNG_FLOAT_DATA)
4291 dest = tng_compress_pos_float((float *)*data, (int)n_particles,
4292 (int)n_frames,
4293 f_precision,
4294 0, alt_algo,
4295 &compressed_len);
4298 else
4300 dest = tng_compress_pos((double *)*data, (int)n_particles,
4301 (int)n_frames,
4302 d_precision,
4303 0, alt_algo,
4304 &compressed_len);
4306 /* If there had been no algorithm determined before keep the initial coding
4307 * and initial coding parameter so that they won't have to be determined again. */
4308 if(!tng_data->compress_algo_pos)
4310 nalgo = tng_compress_nalgo();
4311 tng_data->compress_algo_pos = (int *)malloc(nalgo *
4312 sizeof *tng_data->compress_algo_pos);
4313 tng_data->compress_algo_pos[0] = alt_algo[0];
4314 tng_data->compress_algo_pos[1] = alt_algo[1];
4315 tng_data->compress_algo_pos[2] = -1;
4316 tng_data->compress_algo_pos[3] = -1;
4319 else if(!tng_data->compress_algo_pos || tng_data->compress_algo_pos[2] == -1 ||
4320 tng_data->compress_algo_pos[2] == -1)
4322 if(n_frames > 6)
4324 algo_find_n_frames = 5;
4326 else
4328 algo_find_n_frames = n_frames;
4331 /* If the algorithm parameters are -1 they will be determined during the
4332 * compression. */
4333 if(!tng_data->compress_algo_pos)
4335 nalgo = tng_compress_nalgo();
4336 tng_data->compress_algo_pos = (int *)malloc(nalgo *
4337 sizeof *tng_data->compress_algo_pos);
4338 tng_data->compress_algo_pos[0] = -1;
4339 tng_data->compress_algo_pos[1] = -1;
4340 tng_data->compress_algo_pos[2] = -1;
4341 tng_data->compress_algo_pos[3] = -1;
4343 if(type == TNG_FLOAT_DATA)
4345 dest = tng_compress_pos_float((float *)*data, (int)n_particles,
4346 (int)algo_find_n_frames,
4347 f_precision,
4348 0, tng_data->
4349 compress_algo_pos,
4350 &compressed_len);
4352 if(algo_find_n_frames < n_frames)
4354 free(dest);
4355 dest = tng_compress_pos_float((float *)*data, (int)n_particles,
4356 (int)n_frames,
4357 f_precision,
4358 0, tng_data->compress_algo_pos,
4359 &compressed_len);
4362 else
4364 dest = tng_compress_pos((double *)*data, (int)n_particles,
4365 (int)algo_find_n_frames,
4366 d_precision,
4367 0, tng_data->
4368 compress_algo_pos,
4369 &compressed_len);
4371 if(algo_find_n_frames < n_frames)
4373 free(dest);
4374 dest = tng_compress_pos((double *)*data, (int)n_particles,
4375 (int)n_frames,
4376 d_precision, 0,
4377 tng_data->compress_algo_pos,
4378 &compressed_len);
4382 else
4384 if(type == TNG_FLOAT_DATA)
4386 dest = tng_compress_pos_float((float *)*data, (int)n_particles,
4387 (int)n_frames,
4388 f_precision, 0,
4389 tng_data->compress_algo_pos, &compressed_len);
4391 else
4393 dest = tng_compress_pos((double *)*data, (int)n_particles,
4394 (int)n_frames,
4395 d_precision, 0,
4396 tng_data->compress_algo_pos,
4397 &compressed_len);
4401 else if(block->id == TNG_TRAJ_VELOCITIES)
4403 /* If there is only one frame in this frame set and there might be more
4404 * do not store the algorithm as the compression algorithm, but find
4405 * the best one without storing it */
4406 if(n_frames == 1 && tng_data->frame_set_n_frames > 1)
4408 nalgo = tng_compress_nalgo();
4409 alt_algo = (int *)malloc(nalgo * sizeof *tng_data->compress_algo_vel);
4411 /* If we have already determined the initial coding and
4412 * initial coding parameter do not determine them again. */
4413 if(tng_data->compress_algo_vel)
4415 alt_algo[0] = tng_data->compress_algo_vel[0];
4416 alt_algo[1] = tng_data->compress_algo_vel[1];
4417 alt_algo[2] = tng_data->compress_algo_vel[2];
4418 alt_algo[3] = tng_data->compress_algo_vel[3];
4420 else
4422 alt_algo[0] = -1;
4423 alt_algo[1] = -1;
4424 alt_algo[2] = -1;
4425 alt_algo[3] = -1;
4428 /* If the initial coding and initial coding parameter are -1
4429 * they will be determined in tng_compress_pos/_float/. */
4430 if(type == TNG_FLOAT_DATA)
4432 dest = tng_compress_vel_float((float *)*data, (int)n_particles,
4433 (int)n_frames,
4434 f_precision,
4435 0, alt_algo,
4436 &compressed_len);
4439 else
4441 dest = tng_compress_vel((double *)*data, (int)n_particles,
4442 (int)n_frames,
4443 d_precision,
4444 0, alt_algo,
4445 &compressed_len);
4447 /* If there had been no algorithm determined before keep the initial coding
4448 * and initial coding parameter so that they won't have to be determined again. */
4449 if(!tng_data->compress_algo_vel)
4451 nalgo = tng_compress_nalgo();
4452 tng_data->compress_algo_vel = (int *)malloc(nalgo *
4453 sizeof *tng_data->compress_algo_vel);
4454 tng_data->compress_algo_vel[0] = alt_algo[0];
4455 tng_data->compress_algo_vel[1] = alt_algo[1];
4456 tng_data->compress_algo_vel[2] = -1;
4457 tng_data->compress_algo_vel[3] = -1;
4460 else if(!tng_data->compress_algo_vel || tng_data->compress_algo_vel[2] == -1 ||
4461 tng_data->compress_algo_vel[2] == -1)
4463 if(n_frames > 6)
4465 algo_find_n_frames = 5;
4467 else
4469 algo_find_n_frames = n_frames;
4472 /* If the algorithm parameters are -1 they will be determined during the
4473 * compression. */
4474 if(!tng_data->compress_algo_vel)
4476 nalgo = tng_compress_nalgo();
4477 tng_data->compress_algo_vel = (int *)malloc(nalgo *
4478 sizeof *tng_data->compress_algo_vel);
4479 tng_data->compress_algo_vel[0] = -1;
4480 tng_data->compress_algo_vel[1] = -1;
4481 tng_data->compress_algo_vel[2] = -1;
4482 tng_data->compress_algo_vel[3] = -1;
4484 if(type == TNG_FLOAT_DATA)
4486 dest = tng_compress_vel_float((float *)*data, (int)n_particles,
4487 (int)algo_find_n_frames,
4488 f_precision,
4489 0, tng_data->
4490 compress_algo_vel,
4491 &compressed_len);
4492 if(algo_find_n_frames < n_frames)
4494 free(dest);
4495 dest = tng_compress_vel_float((float *)*data, (int)n_particles,
4496 (int)n_frames,
4497 f_precision,
4498 0, tng_data->compress_algo_vel,
4499 &compressed_len);
4502 else
4504 dest = tng_compress_vel((double *)*data, (int)n_particles,
4505 (int)algo_find_n_frames,
4506 d_precision,
4507 0, tng_data->
4508 compress_algo_vel,
4509 &compressed_len);
4510 if(algo_find_n_frames < n_frames)
4512 free(dest);
4513 dest = tng_compress_vel((double *)*data, (int)n_particles,
4514 (int)n_frames,
4515 d_precision,
4516 0, tng_data->compress_algo_vel,
4517 &compressed_len);
4521 else
4523 if(type == TNG_FLOAT_DATA)
4525 dest = tng_compress_vel_float((float *)*data, (int)n_particles,
4526 (int)n_frames,
4527 f_precision,
4528 0, tng_data->
4529 compress_algo_vel,
4530 &compressed_len);
4532 else
4534 dest = tng_compress_vel((double *)*data, (int)n_particles,
4535 (int)n_frames,
4536 d_precision,
4537 0, tng_data->
4538 compress_algo_vel,
4539 &compressed_len);
4543 else
4545 fprintf(stderr, "TNG library: Can only compress positions and velocities using TNG-MF1 algorithms.\n");
4546 return(TNG_FAILURE);
4549 if(alt_algo)
4551 free(alt_algo);
4554 free(*data);
4556 *data = (char *)dest;
4558 *new_len = compressed_len;
4560 return(TNG_SUCCESS);
4563 static tng_function_status tng_uncompress(const tng_trajectory_t tng_data,
4564 const tng_gen_block_t block,
4565 const char type,
4566 char **data,
4567 const int64_t uncompressed_len)
4569 double *d_dest = 0;
4570 float *f_dest = 0;
4571 int result;
4572 (void)tng_data;
4574 TNG_ASSERT(uncompressed_len, "TNG library: The full length of the uncompressed data must be > 0.");
4576 if(block->id != TNG_TRAJ_POSITIONS &&
4577 block->id != TNG_TRAJ_VELOCITIES)
4579 fprintf(stderr, "TNG library: Can only uncompress positions and velocities with the"
4580 "TNG method.\n");
4581 return(TNG_FAILURE);
4583 if(type != TNG_FLOAT_DATA && type != TNG_DOUBLE_DATA)
4585 fprintf(stderr, "TNG library: Data type not supported.\n");
4586 return(TNG_FAILURE);
4589 if(type == TNG_FLOAT_DATA)
4591 f_dest = (float *)malloc(uncompressed_len);
4592 if(!f_dest)
4594 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
4595 __FILE__, __LINE__);
4596 return(TNG_CRITICAL);
4598 result = tng_compress_uncompress_float(*data, f_dest);
4600 free(*data);
4602 *data = (char *)f_dest;
4604 else
4606 d_dest = (double *)malloc(uncompressed_len);
4607 if(!d_dest)
4609 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
4610 __FILE__, __LINE__);
4611 return(TNG_CRITICAL);
4613 result = tng_compress_uncompress(*data, d_dest);
4615 free(*data);
4617 *data = (char *)d_dest;
4620 if(result == 1)
4622 fprintf(stderr, "TNG library: Cannot uncompress TNG compressed block.\n");
4623 return(TNG_FAILURE);
4626 return(TNG_SUCCESS);
4629 static tng_function_status tng_gzip_compress(const tng_trajectory_t tng_data,
4630 char **data, const int64_t len,
4631 int64_t *new_len)
4633 Bytef *dest;
4634 uLongf stat, max_len;
4635 (void)tng_data;
4637 max_len = compressBound(len);
4638 dest = (Bytef *)malloc(max_len);
4639 if(!dest)
4641 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
4642 __FILE__, __LINE__);
4643 return(TNG_CRITICAL);
4646 stat = compress(dest, &max_len, (Bytef *)*data, len);
4647 if(stat != (unsigned long)Z_OK)
4649 free(dest);
4650 if(stat == (unsigned long)Z_MEM_ERROR)
4652 fprintf(stderr, "TNG library: Not enough memory. ");
4654 else if(stat == (unsigned long)Z_BUF_ERROR)
4656 fprintf(stderr, "TNG library: Destination buffer too small. ");
4658 fprintf(stderr, "TNG library: Error gzipping data. %s: %d\n", __FILE__, __LINE__);
4659 return(TNG_FAILURE);
4662 *new_len = max_len;
4664 free(*data);
4666 *data = (char *)dest;
4668 return(TNG_SUCCESS);
4671 static tng_function_status tng_gzip_uncompress(const tng_trajectory_t tng_data,
4672 char **data,
4673 const int64_t compressed_len,
4674 const int64_t uncompressed_len)
4676 Bytef *dest;
4677 unsigned long stat;
4678 (void)tng_data;
4679 uLongf new_len = uncompressed_len;
4681 dest = (Bytef *)malloc(uncompressed_len);
4682 if(!dest)
4684 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
4685 __FILE__, __LINE__);
4686 return(TNG_CRITICAL);
4689 stat = uncompress(dest, &new_len, (Bytef *) *data,
4690 compressed_len);
4692 if(stat != Z_OK)
4694 free(dest);
4695 if(stat == (unsigned long)Z_MEM_ERROR)
4697 fprintf(stderr, "TNG library: Not enough memory. ");
4699 else if(stat == (unsigned long)Z_BUF_ERROR)
4701 fprintf(stderr, "TNG library: Destination buffer too small. ");
4703 else if(stat == (unsigned long)Z_DATA_ERROR)
4705 fprintf(stderr, "TNG library: Data corrupt. ");
4707 fprintf(stderr, "TNG library: Error uncompressing gzipped data. %s: %d\n", __FILE__,
4708 __LINE__);
4709 return(TNG_FAILURE);
4712 free(*data);
4714 *data = (char *)dest;
4716 return(TNG_SUCCESS);
4720 * @brief Allocate memory for storing particle data.
4721 * The allocated block will be refered to by data->values.
4722 * @param tng_data is a trajectory data container.
4723 * @param data is the data struct, which will contain the allocated memory in
4724 * data->values.
4725 * @param n_frames is the number of frames of data to store.
4726 * @param n_particles is the number of particles with data.
4727 * @param n_values_per_frame is the number of data values per particle and
4728 * frame.
4729 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
4730 * error has occured.
4732 static tng_function_status tng_allocate_particle_data_mem
4733 (const tng_trajectory_t tng_data,
4734 const tng_data_t data,
4735 int64_t n_frames,
4736 const int64_t stride_length,
4737 const int64_t n_particles,
4738 const int64_t n_values_per_frame)
4740 void ***values;
4741 int64_t i, j, k, size, frame_alloc;
4742 (void)tng_data;
4744 if(n_particles == 0 || n_values_per_frame == 0)
4746 return(TNG_FAILURE);
4749 if(data->strings && data->datatype == TNG_CHAR_DATA)
4751 for(i = 0; i < data->n_frames; i++)
4753 for(j = 0; j < n_particles; j++)
4755 for(k = 0; k < data->n_values_per_frame; k++)
4757 if(data->strings[i][j][k])
4759 free(data->strings[i][j][k]);
4762 free(data->strings[i][j]);
4764 free(data->strings[i]);
4766 free(data->strings);
4768 data->n_frames = n_frames;
4769 n_frames = tng_max_i64(1, n_frames);
4770 data->stride_length = tng_max_i64(1, stride_length);
4771 data->n_values_per_frame = n_values_per_frame;
4772 frame_alloc = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
4774 if(data->datatype == TNG_CHAR_DATA)
4776 data->strings = (char ****)malloc(sizeof(char ***) * frame_alloc);
4777 for(i = 0; i < frame_alloc; i++)
4779 data->strings[i] = (char ***)malloc(sizeof(char **) *
4780 n_particles);
4781 if(!data->strings[i])
4783 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
4784 __FILE__, __LINE__);
4785 return(TNG_CRITICAL);
4787 for(j = 0; j < n_particles; j++)
4789 data->strings[i][j] = (char **)malloc(sizeof(char *) *
4790 n_values_per_frame);
4791 if(!data->strings[i][j])
4793 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
4794 __FILE__, __LINE__);
4795 return(TNG_CRITICAL);
4797 for(k = 0; k < n_values_per_frame; k++)
4799 data->strings[i][j][k] = 0;
4804 else
4806 switch(data->datatype)
4808 case TNG_INT_DATA:
4809 size = sizeof(int64_t);
4810 break;
4811 case TNG_FLOAT_DATA:
4812 size = sizeof(float);
4813 break;
4814 case TNG_DOUBLE_DATA:
4815 default:
4816 size = sizeof(double);
4819 values = (void ***)realloc(data->values,
4820 size * frame_alloc *
4821 n_particles * n_values_per_frame);
4822 if(!values)
4824 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
4825 __FILE__, __LINE__);
4826 free(data->values);
4827 data->values = 0;
4828 return(TNG_CRITICAL);
4830 data->values = values;
4832 return(TNG_SUCCESS);
4835 static tng_function_status tng_particle_data_find
4836 (const tng_trajectory_t tng_data,
4837 const int64_t id,
4838 tng_data_t *data)
4840 int64_t block_index, i;
4841 tng_trajectory_frame_set_t frame_set = &tng_data->
4842 current_trajectory_frame_set;
4843 char block_type_flag;
4845 if(tng_data->current_trajectory_frame_set_input_file_pos > 0 ||
4846 tng_data->current_trajectory_frame_set_output_file_pos > 0)
4848 block_type_flag = TNG_TRAJECTORY_BLOCK;
4850 else
4852 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
4855 block_index = -1;
4856 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
4858 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
4860 *data = &frame_set->tr_particle_data[i];
4861 if((*data)->block_id == id)
4863 block_index = i;
4864 break;
4868 else
4870 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
4872 *data = &tng_data->non_tr_particle_data[i];
4873 if((*data)->block_id == id)
4875 block_index = i;
4876 break;
4880 if(block_index == -1)
4882 return(TNG_FAILURE);
4884 return(TNG_SUCCESS);
4887 static tng_function_status tng_data_find
4888 (const tng_trajectory_t tng_data,
4889 const int64_t id,
4890 tng_data_t *data)
4892 int64_t block_index, i;
4893 tng_trajectory_frame_set_t frame_set = &tng_data->
4894 current_trajectory_frame_set;
4895 char block_type_flag;
4897 if(tng_data->current_trajectory_frame_set_input_file_pos > 0 ||
4898 tng_data->current_trajectory_frame_set_output_file_pos > 0)
4900 block_type_flag = TNG_TRAJECTORY_BLOCK;
4902 else
4904 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
4907 block_index = -1;
4908 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
4910 for(i = 0; i < frame_set->n_data_blocks; i++)
4912 *data = &frame_set->tr_data[i];
4913 if((*data)->block_id == id)
4915 block_index = i;
4916 break;
4919 if(block_index == -1)
4921 for(i = 0; i < tng_data->n_data_blocks; i++)
4923 *data = &tng_data->non_tr_data[i];
4924 if((*data)->block_id == id)
4926 block_index = i;
4927 break;
4932 else
4934 for(i = 0; i < tng_data->n_data_blocks; i++)
4936 *data = &tng_data->non_tr_data[i];
4937 if((*data)->block_id == id)
4939 block_index = i;
4940 break;
4944 if(block_index == -1)
4946 return(TNG_FAILURE);
4948 return(TNG_SUCCESS);
4951 static tng_function_status tng_data_block_len_calculate
4952 (const tng_trajectory_t tng_data,
4953 const tng_data_t data,
4954 const tng_bool is_particle_data,
4955 const int64_t n_frames,
4956 const int64_t frame_step,
4957 const int64_t stride_length,
4958 const int64_t num_first_particle,
4959 const int64_t n_particles,
4960 int64_t *data_start_pos,
4961 int64_t *len)
4963 int size;
4964 int64_t i, j, k;
4965 char ***first_dim_values, **second_dim_values;
4966 (void)tng_data;
4968 if(data == 0)
4970 return(TNG_SUCCESS);
4973 switch(data->datatype)
4975 case TNG_CHAR_DATA:
4976 size = 1;
4977 break;
4978 case TNG_INT_DATA:
4979 size = sizeof(int64_t);
4980 break;
4981 case TNG_FLOAT_DATA:
4982 size = sizeof(float);
4983 break;
4984 case TNG_DOUBLE_DATA:
4985 default:
4986 size = sizeof(double);
4989 *len = sizeof(char) * 2 + sizeof(data->n_values_per_frame) +
4990 sizeof(data->codec_id);
4991 if(is_particle_data)
4993 *len += sizeof(num_first_particle) + sizeof(n_particles);
4996 if(stride_length > 1)
4998 *len += sizeof(data->first_frame_with_data) +
4999 sizeof(data->stride_length);
5002 if(data->codec_id != TNG_UNCOMPRESSED)
5004 *len += sizeof(data->compression_multiplier);
5007 if(data->dependency & TNG_FRAME_DEPENDENT)
5009 *len += sizeof(char);
5012 *data_start_pos = *len;
5014 if(data->datatype == TNG_CHAR_DATA)
5016 if(is_particle_data)
5018 for(i = 0; i < n_frames; i++)
5020 first_dim_values = data->strings[i];
5021 for(j = num_first_particle; j < num_first_particle + n_particles;
5022 j++)
5024 second_dim_values = first_dim_values[j];
5025 for(k = 0; k < data->n_values_per_frame; k++)
5027 *len += strlen(second_dim_values[k]) + 1;
5032 else
5034 for(i = 0; i < n_frames; i++)
5036 second_dim_values = data->strings[0][i];
5037 for(j = 0; j < data->n_values_per_frame; j++)
5039 *len += strlen(second_dim_values[j]) + 1;
5044 else
5046 *len += size * frame_step * n_particles * data->n_values_per_frame;
5049 return(TNG_SUCCESS);
5052 /* TEST: */
5054 * @brief Create a non-particle data block
5055 * @param tng_data is a trajectory data container.
5056 * @param block_type_flag specifies if this is a trajectory block or a
5057 * non-trajectory block. (TNG_TRAJECTORY_BLOCK or TNG_NON_TRAJECTORY_BLOCK)
5058 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5059 * error has occured.
5061 static tng_function_status tng_data_block_create
5062 (const tng_trajectory_t tng_data,
5063 const char block_type_flag)
5065 tng_trajectory_frame_set_t frame_set =
5066 &tng_data->current_trajectory_frame_set;
5068 tng_data_t data;
5070 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5072 frame_set->n_data_blocks++;
5073 data = (tng_data_t)realloc(frame_set->tr_data, sizeof(struct tng_data) *
5074 frame_set->n_data_blocks);
5075 if(!data)
5077 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
5078 __FILE__, __LINE__);
5079 free(frame_set->tr_data);
5080 frame_set->tr_data = 0;
5081 return(TNG_CRITICAL);
5083 frame_set->tr_data = data;
5085 else
5087 tng_data->n_data_blocks++;
5088 data = (tng_data_t)realloc(tng_data->non_tr_data, sizeof(struct tng_data) *
5089 tng_data->n_data_blocks);
5090 if(!data)
5092 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
5093 __FILE__, __LINE__);
5094 free(tng_data->non_tr_data);
5095 tng_data->non_tr_data = 0;
5096 return(TNG_CRITICAL);
5098 tng_data->non_tr_data = data;
5101 return(TNG_SUCCESS);
5104 /* TEST: */
5106 * @brief Allocate memory for storing non-particle data.
5107 * The allocated block will be refered to by data->values.
5108 * @param tng_data is a trajectory data container.
5109 * @param data is the data struct, which will contain the allocated memory in
5110 * data->values.
5111 * @param n_frames is the number of frames of data to store.
5112 * @param n_values_per_frame is the number of data values per frame.
5113 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5114 * error has occured.
5116 static tng_function_status tng_allocate_data_mem
5117 (const tng_trajectory_t tng_data,
5118 const tng_data_t data,
5119 int64_t n_frames,
5120 const int64_t stride_length,
5121 const int64_t n_values_per_frame)
5123 void **values;
5124 int64_t i, j, size, frame_alloc;
5125 (void)tng_data;
5127 if(n_values_per_frame == 0)
5129 return(TNG_FAILURE);
5132 if(data->strings && data->datatype == TNG_CHAR_DATA)
5134 for(i = 0; i < data->n_frames; i++)
5136 for(j = 0; j < data->n_values_per_frame; j++)
5138 if(data->strings[0][i][j])
5140 free(data->strings[0][i][j]);
5141 data->strings[0][i][j] = 0;
5144 free(data->strings[0][i]);
5145 data->strings[0][i] = 0;
5147 free(data->strings[0]);
5148 data->strings[0] = 0;
5149 free(data->strings);
5151 data->n_frames = n_frames;
5152 data->stride_length = tng_max_i64(1, stride_length);
5153 n_frames = tng_max_i64(1, n_frames);
5154 data->n_values_per_frame = n_values_per_frame;
5155 frame_alloc = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
5157 if(data->datatype == TNG_CHAR_DATA)
5159 data->strings = (char ****)malloc(sizeof(char ***));
5160 data->strings[0] = (char ***)malloc(sizeof(char **) * frame_alloc);
5161 for(i = 0; i < frame_alloc; i++)
5163 data->strings[0][i] = (char **)malloc(sizeof(char *) * n_values_per_frame);
5164 if(!data->strings[0][i])
5166 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
5167 __FILE__, __LINE__);
5168 return(TNG_CRITICAL);
5170 for(j = 0; j < n_values_per_frame; j++)
5172 data->strings[0][i][j] = 0;
5176 else
5178 switch(data->datatype)
5180 case TNG_INT_DATA:
5181 size = sizeof(int64_t);
5182 break;
5183 case TNG_FLOAT_DATA:
5184 size = sizeof(float);
5185 break;
5186 case TNG_DOUBLE_DATA:
5187 default:
5188 size = sizeof(double);
5191 values = (void **)realloc(data->values,
5192 size * frame_alloc *
5193 n_values_per_frame);
5194 if(!values)
5196 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
5197 __FILE__, __LINE__);
5198 free(data->values);
5199 data->values = 0;
5200 return(TNG_CRITICAL);
5202 data->values = values;
5205 return(TNG_SUCCESS);
5209 * @brief Read the values of a data block
5210 * @param tng_data is a trajectory data container.
5211 * @param block is the block to store the data (should already contain
5212 * the block headers and the block contents).
5213 * @param block_data_len is the length of the data contents of the block.
5214 * @param datatype is the type of data of the data block (char, int, float or
5215 * double).
5216 * @param num_first_particle is the number of the first particle in the data
5217 * block. This should be the same as in the corresponding particle mapping
5218 * block. Only used if reading particle dependent data.
5219 * @param n_particles is the number of particles in the data block. This should
5220 * be the same as in the corresponding particle mapping block. Only used if
5221 * reading particle dependent data.
5222 * @param first_frame_with_data is the frame number of the first frame with data
5223 * in this data block.
5224 * @param stride_length is the number of frames between each data entry.
5225 * @param n_frames is the number of frames in this data block.
5226 * @param n_values is the number of values per frame stored in this data block.
5227 * @param codec_id is the ID of the codec to compress the data.
5228 * @param multiplier is the multiplication factor applied to each data value
5229 * before compression. This factor is applied since some compression algorithms
5230 * work only on integers.
5231 * @param hash_mode is an option to decide whether to generate/update the relevant md5 hashes.
5232 * @param md5_state is a pointer to the current md5 storage, which will be updated appropriately
5233 * if hash_mode == TNG_USE_HASH.
5234 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5235 * error has occured.
5237 static tng_function_status tng_data_read(const tng_trajectory_t tng_data,
5238 const tng_gen_block_t block,
5239 const int64_t block_data_len,
5240 const char datatype,
5241 const int64_t num_first_particle,
5242 const int64_t n_particles,
5243 const int64_t first_frame_with_data,
5244 const int64_t stride_length,
5245 int64_t n_frames,
5246 const int64_t n_values,
5247 const int64_t codec_id,
5248 const double multiplier,
5249 const char hash_mode,
5250 md5_state_t *md5_state)
5252 int64_t i, j, k, tot_n_particles, n_frames_div, offset;
5253 int64_t full_data_len;
5254 int size, len;
5255 char ***first_dim_values, **second_dim_values;
5256 tng_data_t data;
5257 tng_trajectory_frame_set_t frame_set =
5258 &tng_data->current_trajectory_frame_set;
5259 char block_type_flag, *contents;
5260 tng_bool is_particle_data;
5261 tng_function_status stat;
5263 /* fprintf(stderr, "TNG library: %s\n", block->name);*/
5265 switch(datatype)
5267 case TNG_CHAR_DATA:
5268 size = 1;
5269 break;
5270 case TNG_INT_DATA:
5271 size = sizeof(int64_t);
5272 break;
5273 case TNG_FLOAT_DATA:
5274 size = sizeof(float);
5275 break;
5276 case TNG_DOUBLE_DATA:
5277 default:
5278 size = sizeof(double);
5281 if(n_particles > 0)
5283 is_particle_data = TNG_TRUE;
5285 else
5287 if(codec_id == TNG_XTC_COMPRESSION || codec_id == TNG_TNG_COMPRESSION)
5289 fprintf(stderr, "TNG library: Cannot uncompress data block. %s: %d\n", __FILE__,
5290 __LINE__);
5291 return(TNG_FAILURE);
5293 is_particle_data = TNG_FALSE;
5296 if(is_particle_data == TNG_TRUE)
5298 stat = tng_particle_data_find(tng_data, block->id, &data);
5300 else
5302 stat = tng_data_find(tng_data, block->id, &data);
5305 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
5307 block_type_flag = TNG_TRAJECTORY_BLOCK;
5309 else
5311 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5314 /* If the block does not exist, create it */
5315 if(stat != TNG_SUCCESS)
5317 if(is_particle_data == TNG_TRUE)
5319 stat = tng_particle_data_block_create(tng_data, block_type_flag);
5321 else
5323 stat = tng_data_block_create(tng_data, block_type_flag);
5326 if(stat != TNG_SUCCESS)
5328 fprintf(stderr, "TNG library: Cannot create data block. %s: %d\n",
5329 __FILE__, __LINE__);
5330 return(TNG_CRITICAL);
5333 if(is_particle_data == TNG_TRUE)
5335 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5337 data = &frame_set->tr_particle_data[frame_set->
5338 n_particle_data_blocks - 1];
5340 else
5342 data = &tng_data->non_tr_particle_data[tng_data->
5343 n_particle_data_blocks - 1];
5346 else
5348 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5350 data = &frame_set->tr_data[frame_set->n_data_blocks - 1];
5352 else
5354 data = &tng_data->non_tr_data[tng_data->n_data_blocks - 1];
5358 data->block_id = block->id;
5360 data->block_name = (char *)malloc(strlen(block->name) + 1);
5361 if(!data->block_name)
5363 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
5364 __FILE__, __LINE__);
5365 return(TNG_CRITICAL);
5367 strcpy(data->block_name, block->name);
5369 data->datatype = datatype;
5371 data->values = 0;
5372 /* FIXME: Memory leak from strings. */
5373 data->strings = 0;
5374 data->n_frames = 0;
5375 data->dependency = 0;
5376 if(is_particle_data == TNG_TRUE)
5378 data->dependency += TNG_PARTICLE_DEPENDENT;
5380 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
5381 (n_frames > 1 ||
5382 frame_set->n_frames == n_frames ||
5383 stride_length > 1))
5385 data->dependency += TNG_FRAME_DEPENDENT;
5387 data->codec_id = codec_id;
5388 data->compression_multiplier = multiplier;
5389 data->last_retrieved_frame = -1;
5392 if(is_particle_data == TNG_TRUE)
5394 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
5395 tng_data->var_num_atoms_flag)
5397 tot_n_particles = frame_set->n_particles;
5399 else
5401 tot_n_particles = tng_data->n_particles;
5404 /* If there are no particles in this data block, still set tot_n_particles = 1
5405 * to calculate block lengths etc properly. */
5406 else
5408 tot_n_particles = 1;
5411 n_frames_div = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
5413 contents = (char *)malloc(block_data_len);
5414 if(!contents)
5416 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
5417 __FILE__, __LINE__);
5418 return(TNG_CRITICAL);
5421 if(fread(contents, block_data_len, 1, tng_data->input_file) == 0)
5423 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
5424 return(TNG_CRITICAL);
5427 if(hash_mode == TNG_USE_HASH)
5429 md5_append(md5_state, (md5_byte_t *)contents, block_data_len);
5432 if(codec_id != TNG_UNCOMPRESSED)
5434 full_data_len = n_frames_div * size * n_values;
5435 if(is_particle_data == TNG_TRUE)
5437 full_data_len *= n_particles;
5439 switch(codec_id)
5441 case TNG_XTC_COMPRESSION:
5442 fprintf(stderr, "TNG library: XTC compression not implemented yet.\n");
5443 break;
5444 case TNG_TNG_COMPRESSION:
5445 /* fprintf(stderr, "TNG library: Before TNG uncompression: %" PRId64 "\n", block->block_contents_size);*/
5446 if(tng_uncompress(tng_data, block, datatype,
5447 &contents, full_data_len) != TNG_SUCCESS)
5449 fprintf(stderr, "TNG library: Could not read tng compressed block data. %s: %d\n",
5450 __FILE__, __LINE__);
5451 free(contents);
5452 return(TNG_CRITICAL);
5454 /* fprintf(stderr, "TNG library: After TNG uncompression: %" PRId64 "\n", block->block_contents_size);*/
5455 break;
5456 case TNG_GZIP_COMPRESSION:
5457 /* fprintf(stderr, "TNG library: Before compression: %" PRId64 "\n", block->block_contents_size); */
5458 if(tng_gzip_uncompress(tng_data, &contents,
5459 block_data_len, full_data_len) != TNG_SUCCESS)
5461 fprintf(stderr, "TNG library: Could not read gzipped block data. %s: %d\n", __FILE__,
5462 __LINE__);
5463 free(contents);
5464 return(TNG_CRITICAL);
5466 /* fprintf(stderr, "TNG library: After compression: %" PRId64 "\n", block->block_contents_size); */
5467 break;
5470 else
5472 full_data_len = block_data_len;
5475 /* Allocate memory */
5476 if(!data->values || data->n_frames != n_frames ||
5477 data->n_values_per_frame != n_values)
5479 if(is_particle_data == TNG_TRUE)
5481 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
5482 stride_length,
5483 tot_n_particles, n_values);
5485 else
5487 stat = tng_allocate_data_mem(tng_data, data, n_frames, stride_length,
5488 n_values);
5490 if(stat != TNG_SUCCESS)
5492 fprintf(stderr, "TNG library: Cannot allocate memory for data. %s: %d\n",
5493 __FILE__, __LINE__);
5494 free(contents);
5495 return(TNG_CRITICAL);
5499 data->first_frame_with_data = first_frame_with_data;
5501 if(datatype == TNG_CHAR_DATA)
5503 offset = 0;
5504 /* Strings are stores slightly differently if the data block contains particle
5505 * data (frames * particles * n_values) or not (frames * n_values). */
5506 if(is_particle_data == TNG_TRUE)
5508 for(i = 0; i < n_frames_div; i++)
5510 first_dim_values = data->strings[i];
5511 for(j = num_first_particle; j < num_first_particle + n_particles;
5512 j++)
5514 second_dim_values = first_dim_values[j];
5515 for(k = 0; k < n_values; k++)
5517 len = tng_min_size(strlen(contents+offset) + 1,
5518 TNG_MAX_STR_LEN);
5519 if(second_dim_values[k])
5521 free(second_dim_values[k]);
5523 second_dim_values[k] = (char *)malloc(len);
5524 if(!second_dim_values[k])
5526 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
5527 __FILE__, __LINE__);
5528 free(contents);
5529 return(TNG_CRITICAL);
5531 strncpy(second_dim_values[k], contents+offset, len);
5532 offset += len;
5537 else
5539 for(i = 0; i < n_frames_div; i++)
5541 for(j = 0; j < n_values; j++)
5543 len = tng_min_size(strlen(contents+offset) + 1,
5544 TNG_MAX_STR_LEN);
5545 if(data->strings[0][i][j])
5547 free(data->strings[0][i][j]);
5549 data->strings[0][i][j] = (char *)malloc(len);
5550 if(!data->strings[0][i][j])
5552 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
5553 __FILE__, __LINE__);
5554 free(contents);
5555 return(TNG_CRITICAL);
5557 strncpy(data->strings[0][i][j], contents+offset, len);
5558 offset += len;
5563 else
5565 if(is_particle_data)
5567 memcpy((char *)data->values + n_frames_div * size * n_values *
5568 num_first_particle, contents, full_data_len);
5570 else
5572 memcpy(data->values, contents, full_data_len);
5574 /* Endianness is handled by the TNG compression library. TNG compressed blocks are always written
5575 * as little endian by the compression library. */
5576 if(codec_id != TNG_TNG_COMPRESSION)
5578 switch(datatype)
5580 case TNG_FLOAT_DATA:
5581 if(tng_data->input_endianness_swap_func_32)
5583 for(i = 0; i < full_data_len; i+=size)
5585 if(tng_data->input_endianness_swap_func_32(tng_data,
5586 (uint32_t *)((char *)data->values + i))
5587 != TNG_SUCCESS)
5589 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5590 __FILE__, __LINE__);
5594 break;
5595 case TNG_INT_DATA:
5596 case TNG_DOUBLE_DATA:
5597 if(tng_data->input_endianness_swap_func_64)
5599 for(i = 0; i < full_data_len; i+=size)
5601 if(tng_data->input_endianness_swap_func_64(tng_data,
5602 (uint64_t *)((char *)data->values + i))
5603 != TNG_SUCCESS)
5605 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5606 __FILE__, __LINE__);
5610 break;
5611 case TNG_CHAR_DATA:
5612 break;
5617 free(contents);
5619 return(TNG_SUCCESS);
5623 * @brief Write a data block (particle or non-particle data)
5624 * @param tng_data is a trajectory data container.
5625 * @param block is the block to store the data (should already contain
5626 * the block headers and the block contents).
5627 * @param block_index is the index number of the data block in the frame set.
5628 * @param is_particle_data is a flag to specify if the data to write is
5629 * particle dependent or not.
5630 * @param mapping is the particle mapping that is relevant for the data block.
5631 * Only relevant if writing particle dependent data.
5632 * @param hash_mode is an option to decide whether to use the md5 hash or not.
5633 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
5634 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5635 * error has occured.
5637 static tng_function_status tng_data_block_write(const tng_trajectory_t tng_data,
5638 const tng_gen_block_t block,
5639 const int64_t block_index,
5640 const tng_bool is_particle_data,
5641 const tng_particle_mapping_t mapping,
5642 const char hash_mode)
5644 int64_t n_particles, num_first_particle, n_frames, stride_length;
5645 int64_t full_data_len, block_data_len, frame_step, data_start_pos;
5646 int64_t i, j, k, curr_file_pos, header_file_pos;
5647 int size;
5648 size_t len;
5649 tng_function_status stat;
5650 char temp, *temp_name, ***first_dim_values, **second_dim_values, *contents;
5651 double multiplier;
5652 tng_trajectory_frame_set_t frame_set =
5653 &tng_data->current_trajectory_frame_set;
5654 tng_data_t data;
5655 char block_type_flag;
5656 md5_state_t md5_state;
5658 /* If we have already started writing frame sets it is too late to write
5659 * non-trajectory data blocks */
5660 if(tng_data->current_trajectory_frame_set_output_file_pos > 0)
5662 block_type_flag = TNG_TRAJECTORY_BLOCK;
5664 else
5666 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5669 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
5671 return(TNG_CRITICAL);
5674 if(is_particle_data == TNG_TRUE)
5676 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5678 data = &frame_set->tr_particle_data[block_index];
5680 /* If this data block has not had any data added in this frame set
5681 * do not write it. */
5682 if(data->first_frame_with_data < frame_set->first_frame)
5684 return(TNG_SUCCESS);
5687 stride_length = tng_max_i64(1, data->stride_length);
5689 else
5691 data = &tng_data->non_tr_particle_data[block_index];
5692 stride_length = 1;
5695 else
5697 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5699 data = &frame_set->tr_data[block_index];
5701 /* If this data block has not had any data added in this frame set
5702 * do not write it. */
5703 if(data->first_frame_with_data < frame_set->first_frame)
5705 return(TNG_SUCCESS);
5708 stride_length = tng_max_i64(1, data->stride_length);
5710 else
5712 data = &tng_data->non_tr_data[block_index];
5713 stride_length = 1;
5717 switch(data->datatype)
5719 case TNG_CHAR_DATA:
5720 size = 1;
5721 break;
5722 case TNG_INT_DATA:
5723 size = sizeof(int64_t);
5724 break;
5725 case TNG_FLOAT_DATA:
5726 size = sizeof(float);
5727 break;
5728 case TNG_DOUBLE_DATA:
5729 default:
5730 size = sizeof(double);
5733 len = strlen(data->block_name) + 1;
5735 if(!block->name || strlen(block->name) < len)
5737 temp_name = (char *)realloc(block->name, len);
5738 if(!temp_name)
5740 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
5741 __FILE__, __LINE__);
5742 free(block->name);
5743 block->name = 0;
5744 return(TNG_CRITICAL);
5746 block->name = temp_name;
5748 strncpy(block->name, data->block_name, len);
5749 block->id = data->block_id;
5751 /* If writing frame independent data data->n_frames is 0, but n_frames
5752 is used for the loop writing the data (and reserving memory) and needs
5753 to be at least 1 */
5754 n_frames = tng_max_i64(1, data->n_frames);
5756 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5758 /* If the frame set is finished before writing the full number of frames
5759 make sure the data block is not longer than the frame set. */
5760 n_frames = tng_min_i64(n_frames, frame_set->n_frames);
5762 n_frames -= (data->first_frame_with_data - frame_set->first_frame);
5765 frame_step = (n_frames % stride_length) ? n_frames / stride_length + 1:
5766 n_frames / stride_length;
5768 /* TNG compression will use compression precision to get integers from
5769 * floating point data. The compression multiplier stores that information
5770 * to be able to return the precision of the compressed data. */
5771 if(data->codec_id == TNG_TNG_COMPRESSION)
5773 data->compression_multiplier = tng_data->compression_precision;
5775 /* Uncompressed data blocks do not use compression multipliers at all.
5776 * GZip compression does not need it either. */
5777 else if(data->codec_id == TNG_UNCOMPRESSED || data->codec_id == TNG_GZIP_COMPRESSION)
5779 data->compression_multiplier = 1.0;
5782 if(data->dependency & TNG_PARTICLE_DEPENDENT)
5784 if(mapping && mapping->n_particles != 0)
5786 n_particles = mapping->n_particles;
5787 num_first_particle = mapping->num_first_particle;
5789 else
5791 num_first_particle = 0;
5792 if(tng_data->var_num_atoms_flag)
5794 n_particles = frame_set->n_particles;
5796 else
5798 n_particles = tng_data->n_particles;
5802 else
5804 /* This just appeases gcc-7 -Wmaybe-uninitialized.
5805 * FIXME: It would be better to refactor so that
5806 * TNG_PARTICLE_DEPENDENT triggers two distinct code paths.
5808 num_first_particle = -1;
5809 n_particles = -1;
5812 if(data->dependency & TNG_PARTICLE_DEPENDENT)
5814 if(tng_data_block_len_calculate(tng_data, data, TNG_TRUE, n_frames,
5815 frame_step, stride_length, num_first_particle,
5816 n_particles, &data_start_pos,
5817 &block->block_contents_size) != TNG_SUCCESS)
5819 fprintf(stderr, "TNG library: Cannot calculate length of particle data block. %s: %d\n",
5820 __FILE__, __LINE__);
5821 return(TNG_CRITICAL);
5824 else
5826 if(tng_data_block_len_calculate(tng_data, data, TNG_FALSE, n_frames,
5827 frame_step, stride_length, 0,
5828 1, &data_start_pos,
5829 &block->block_contents_size) != TNG_SUCCESS)
5831 fprintf(stderr, "TNG library: Cannot calculate length of non-particle data block. %s: %d\n",
5832 __FILE__, __LINE__);
5833 return(TNG_CRITICAL);
5837 header_file_pos = ftello(tng_data->output_file);
5839 if(tng_block_header_write(tng_data, block) != TNG_SUCCESS)
5841 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
5842 tng_data->output_file_path, __FILE__, __LINE__);
5843 return(TNG_CRITICAL);
5846 if(hash_mode == TNG_USE_HASH)
5848 md5_init(&md5_state);
5851 if(tng_file_output_numerical(tng_data, &data->datatype,
5852 sizeof(data->datatype),
5853 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5855 return(TNG_CRITICAL);
5858 if(tng_file_output_numerical(tng_data, &data->dependency,
5859 sizeof(data->dependency),
5860 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5862 return(TNG_CRITICAL);
5865 if(data->dependency & TNG_FRAME_DEPENDENT)
5867 if(stride_length > 1)
5869 temp = 1;
5871 else
5873 temp = 0;
5875 if(tng_file_output_numerical(tng_data, &temp,
5876 sizeof(temp),
5877 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5879 return(TNG_CRITICAL);
5883 if(tng_file_output_numerical(tng_data, &data->n_values_per_frame,
5884 sizeof(data->n_values_per_frame),
5885 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5887 return(TNG_CRITICAL);
5890 if(tng_file_output_numerical(tng_data, &data->codec_id,
5891 sizeof(data->codec_id),
5892 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5894 return(TNG_CRITICAL);
5897 if(data->codec_id != TNG_UNCOMPRESSED)
5899 if(tng_file_output_numerical(tng_data, &data->compression_multiplier,
5900 sizeof(data->compression_multiplier),
5901 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5903 return(TNG_CRITICAL);
5907 if(data->n_frames > 0 && stride_length > 1)
5909 /* FIXME: first_frame_with_data is not reliably set */
5910 if(data->first_frame_with_data == 0)
5912 data->first_frame_with_data = frame_set->first_frame;
5914 if(tng_file_output_numerical(tng_data, &data->first_frame_with_data,
5915 sizeof(data->first_frame_with_data),
5916 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5918 return(TNG_CRITICAL);
5921 if(tng_file_output_numerical(tng_data, &stride_length,
5922 sizeof(stride_length),
5923 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5925 return(TNG_CRITICAL);
5929 if(data->dependency & TNG_PARTICLE_DEPENDENT)
5931 if(tng_file_output_numerical(tng_data, &num_first_particle,
5932 sizeof(num_first_particle),
5933 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5935 return(TNG_CRITICAL);
5938 if(tng_file_output_numerical(tng_data, &n_particles,
5939 sizeof(n_particles),
5940 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5942 return(TNG_CRITICAL);
5946 if(data->datatype == TNG_CHAR_DATA)
5948 if(data->strings)
5950 if(data->dependency & TNG_PARTICLE_DEPENDENT)
5952 for(i = 0; i < frame_step; i++)
5954 first_dim_values = data->strings[i];
5955 for(j = num_first_particle; j < num_first_particle + n_particles;
5956 j++)
5958 second_dim_values = first_dim_values[j];
5959 for(k = 0; k < data->n_values_per_frame; k++)
5961 if(tng_fwritestr(tng_data, second_dim_values[k],
5962 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5964 return(TNG_CRITICAL);
5970 else
5972 for(i = 0; i < frame_step; i++)
5974 for(j = 0; j < data->n_values_per_frame; j++)
5976 if(tng_fwritestr(tng_data, data->strings[0][i][j],
5977 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5979 return(TNG_CRITICAL);
5986 else
5988 if(data->dependency & TNG_PARTICLE_DEPENDENT)
5990 full_data_len = size * frame_step * n_particles * data->n_values_per_frame;
5992 else
5994 full_data_len = size * frame_step * data->n_values_per_frame;
5996 contents = (char *)malloc(full_data_len);
5997 if(!contents)
5999 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
6000 __FILE__, __LINE__);
6001 return(TNG_CRITICAL);
6004 if(data->values)
6006 memcpy(contents, data->values, full_data_len);
6007 /* If writing TNG compressed data the endianness is taken into account by the compression
6008 * routines. TNG compressed data is always written as little endian. */
6009 if(data->codec_id != TNG_TNG_COMPRESSION)
6011 switch(data->datatype)
6013 case TNG_FLOAT_DATA:
6014 if(data->codec_id == TNG_UNCOMPRESSED || data->codec_id == TNG_GZIP_COMPRESSION)
6016 if(tng_data->output_endianness_swap_func_32)
6018 for(i = 0; i < full_data_len; i+=size)
6020 if(tng_data->output_endianness_swap_func_32(tng_data,
6021 (uint32_t *)(contents + i))
6022 != TNG_SUCCESS)
6024 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6025 __FILE__, __LINE__);
6030 else
6032 multiplier = data->compression_multiplier;
6033 if(fabs(multiplier - 1.0) > 0.00001 ||
6034 tng_data->output_endianness_swap_func_32)
6036 for(i = 0; i < full_data_len; i+=size)
6038 *(float *)(contents + i) *= (float)multiplier;
6039 if(tng_data->output_endianness_swap_func_32 &&
6040 tng_data->output_endianness_swap_func_32(tng_data,
6041 (uint32_t *)(contents + i))
6042 != TNG_SUCCESS)
6044 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6045 __FILE__, __LINE__);
6050 break;
6051 case TNG_INT_DATA:
6052 if(tng_data->output_endianness_swap_func_64)
6054 for(i = 0; i < full_data_len; i+=size)
6056 if(tng_data->output_endianness_swap_func_64(tng_data,
6057 (uint64_t *)(contents + i))
6058 != TNG_SUCCESS)
6060 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6061 __FILE__, __LINE__);
6065 break;
6066 case TNG_DOUBLE_DATA:
6067 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION)
6069 if(tng_data->output_endianness_swap_func_64)
6071 for(i = 0; i < full_data_len; i+=size)
6073 if(tng_data->output_endianness_swap_func_64(tng_data,
6074 (uint64_t *)(contents + i))
6075 != TNG_SUCCESS)
6077 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6078 __FILE__, __LINE__);
6083 else
6085 multiplier = data->compression_multiplier;
6086 if(fabs(multiplier - 1.0) > 0.00001 ||
6087 tng_data->output_endianness_swap_func_64)
6089 for(i = 0; i < full_data_len; i+=size)
6091 *(double *)(contents + i) *= multiplier;
6092 if(tng_data->output_endianness_swap_func_64 &&
6093 tng_data->output_endianness_swap_func_64(tng_data,
6094 (uint64_t *)(contents + i))
6095 != TNG_SUCCESS)
6097 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6098 __FILE__, __LINE__);
6103 break;
6104 case TNG_CHAR_DATA:
6105 break;
6109 else
6111 memset(contents, 0, full_data_len);
6114 block_data_len = full_data_len;
6116 switch(data->codec_id)
6118 case TNG_XTC_COMPRESSION:
6119 fprintf(stderr, "TNG library: XTC compression not implemented yet.\n");
6120 data->codec_id = TNG_UNCOMPRESSED;
6121 break;
6122 case TNG_TNG_COMPRESSION:
6123 stat = tng_compress(tng_data, block, frame_step,
6124 n_particles, data->datatype,
6125 &contents, &block_data_len);
6126 if(stat != TNG_SUCCESS)
6128 fprintf(stderr, "TNG library: Could not write TNG compressed block data. %s: %d\n",
6129 __FILE__, __LINE__);
6130 if(stat == TNG_CRITICAL)
6132 return(TNG_CRITICAL);
6134 /* Set the data again, but with no compression (to write only
6135 * the relevant data) */
6136 data->codec_id = TNG_UNCOMPRESSED;
6137 stat = tng_data_block_write(tng_data, block,
6138 block_index, is_particle_data, mapping,
6139 hash_mode);
6140 free(contents);
6141 return(stat);
6143 break;
6144 case TNG_GZIP_COMPRESSION:
6145 /* fprintf(stderr, "TNG library: Before compression: %" PRId64 "\n", block->block_contents_size); */
6146 stat = tng_gzip_compress(tng_data,
6147 &contents,
6148 full_data_len,
6149 &block_data_len);
6150 if(stat != TNG_SUCCESS)
6152 fprintf(stderr, "TNG library: Could not write gzipped block data. %s: %d\n", __FILE__,
6153 __LINE__);
6154 if(stat == TNG_CRITICAL)
6156 return(TNG_CRITICAL);
6158 data->codec_id = TNG_UNCOMPRESSED;
6160 /* fprintf(stderr, "TNG library: After compression: %" PRId64 "\n", block->block_contents_size); */
6161 break;
6163 if(block_data_len != full_data_len)
6165 block->block_contents_size -= full_data_len - block_data_len;
6167 curr_file_pos = ftello(tng_data->output_file);
6168 fseeko(tng_data->output_file, header_file_pos + sizeof(block->header_contents_size), SEEK_SET);
6170 if(tng_file_output_numerical(tng_data, &block->block_contents_size,
6171 sizeof(block->block_contents_size),
6172 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
6174 return(TNG_CRITICAL);
6176 fseeko(tng_data->output_file, curr_file_pos, SEEK_SET);
6178 if(fwrite(contents, block_data_len, 1, tng_data->output_file) != 1)
6180 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__,
6181 __LINE__);
6182 return(TNG_CRITICAL);
6184 if(hash_mode == TNG_USE_HASH)
6186 md5_append(&md5_state, (md5_byte_t *)contents, block_data_len);
6189 free(contents);
6192 if(hash_mode == TNG_USE_HASH)
6194 md5_finish(&md5_state, (md5_byte_t *)block->md5_hash);
6195 curr_file_pos = ftello(tng_data->output_file);
6196 fseeko(tng_data->output_file, header_file_pos +
6197 3 * sizeof(int64_t), SEEK_SET);
6198 if(fwrite(block->md5_hash, TNG_MD5_HASH_LEN, 1, tng_data->output_file) != 1)
6200 fprintf(stderr, "TNG library: Could not write MD5 hash. %s: %d\n", __FILE__,
6201 __LINE__);
6202 return(TNG_CRITICAL);
6204 fseeko(tng_data->output_file, curr_file_pos, SEEK_SET);
6207 frame_set->n_written_frames += frame_set->n_unwritten_frames;
6208 frame_set->n_unwritten_frames = 0;
6210 return(TNG_SUCCESS);
6214 * @brief Read the meta information of a data block (particle or non-particle data).
6215 * @param tng_data is a trajectory data container.
6216 * @param datatype is set to the datatype of the data block.
6217 * @param dependency is set to the dependency (particle and/or frame dependent)
6218 * @param sparse_data is set to TRUE if data is not written every frame.
6219 * @param n_values is set to the number of values per frame of the data.
6220 * @param codec_id is set to the ID of the codec used to compress the data.
6221 * @param first_frame_with_data is set to the first frame with data (only relevant if
6222 * sparse_data == TRUE).
6223 * @param stride_length is set to the writing interval of the data (1 if sparse_data
6224 * == FALSE).
6225 * @param num_first_particle is set to the number of the first particle with data written
6226 * in this block.
6227 * @param block_n_particles is set to the number of particles in this data block.
6228 * @param multiplier is set to the compression multiplier.
6229 * @param hash_mode specifies whether to check if the hash matches the contents or not.
6230 * @param md5_state is the md5 hash of the block (only used if hash_mode == TNG_USE_HASH).
6231 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6232 * error has occured.
6234 static tng_function_status tng_data_block_meta_information_read
6235 (const tng_trajectory_t tng_data,
6236 char *datatype,
6237 char *dependency,
6238 char *sparse_data,
6239 int64_t *n_values,
6240 int64_t *codec_id,
6241 int64_t *first_frame_with_data,
6242 int64_t *stride_length,
6243 int64_t *n_frames,
6244 int64_t *num_first_particle,
6245 int64_t *block_n_particles,
6246 double *multiplier,
6247 const char hash_mode,
6248 md5_state_t *md5_state)
6250 if(tng_file_input_numerical(tng_data, datatype,
6251 sizeof(*datatype),
6252 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6254 return(TNG_CRITICAL);
6257 if(tng_file_input_numerical(tng_data, dependency,
6258 sizeof(*dependency),
6259 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6261 return(TNG_CRITICAL);
6264 if(*dependency & TNG_FRAME_DEPENDENT)
6266 if(tng_file_input_numerical(tng_data, sparse_data,
6267 sizeof(*sparse_data),
6268 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6270 return(TNG_CRITICAL);
6274 if(tng_file_input_numerical(tng_data, n_values,
6275 sizeof(*n_values),
6276 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6278 return(TNG_CRITICAL);
6281 if(tng_file_input_numerical(tng_data, codec_id,
6282 sizeof(*codec_id),
6283 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6285 return(TNG_CRITICAL);
6288 if(*codec_id != TNG_UNCOMPRESSED)
6290 if(tng_file_input_numerical(tng_data, multiplier,
6291 sizeof(*multiplier),
6292 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6294 return(TNG_CRITICAL);
6297 else
6299 *multiplier = 1;
6302 if(*dependency & TNG_FRAME_DEPENDENT)
6304 if(*sparse_data)
6306 if(tng_file_input_numerical(tng_data, first_frame_with_data,
6307 sizeof(*first_frame_with_data),
6308 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6310 return(TNG_CRITICAL);
6313 if(tng_file_input_numerical(tng_data, stride_length,
6314 sizeof(*stride_length),
6315 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6317 return(TNG_CRITICAL);
6320 *n_frames = tng_data->current_trajectory_frame_set.n_frames -
6321 (*first_frame_with_data -
6322 tng_data->current_trajectory_frame_set.first_frame);
6324 else
6326 *first_frame_with_data = tng_data->current_trajectory_frame_set.first_frame;
6327 *stride_length = 1;
6328 *n_frames = tng_data->current_trajectory_frame_set.n_frames;
6331 else
6333 *first_frame_with_data = 0;
6334 *stride_length = 1;
6335 *n_frames = 1;
6338 if (*dependency & TNG_PARTICLE_DEPENDENT)
6340 if(tng_file_input_numerical(tng_data, num_first_particle,
6341 sizeof(*num_first_particle),
6342 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6344 return(TNG_CRITICAL);
6347 if(tng_file_input_numerical(tng_data, block_n_particles,
6348 sizeof(*block_n_particles),
6349 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6351 return(TNG_CRITICAL);
6354 else
6356 *num_first_particle = -1;
6357 *block_n_particles = 0;
6360 return(TNG_SUCCESS);
6364 * @brief Read the contents of a data block (particle or non-particle data).
6365 * @param tng_data is a trajectory data container.
6366 * @param block is the block to store the data (should already contain
6367 * the block headers).
6368 * @param hash_mode is an option to decide whether to use the md5 hash or not.
6369 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
6370 * compared to the md5 hash of the read contents to ensure valid data.
6371 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6372 * error has occured.
6374 static tng_function_status tng_data_block_contents_read
6375 (const tng_trajectory_t tng_data,
6376 const tng_gen_block_t block,
6377 const char hash_mode)
6379 int64_t start_pos, n_values, codec_id, n_frames, first_frame_with_data;
6380 int64_t remaining_len, stride_length, block_n_particles, num_first_particle;
6381 double multiplier;
6382 char datatype, dependency, sparse_data;
6383 tng_function_status stat = TNG_SUCCESS;
6384 char hash[TNG_MD5_HASH_LEN];
6385 md5_state_t md5_state;
6387 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
6389 return(TNG_CRITICAL);
6392 start_pos = ftello(tng_data->input_file);
6394 if(hash_mode == TNG_USE_HASH)
6396 md5_init(&md5_state);
6399 /* FIXME: Does not check if the size of the contents matches the expected
6400 * size or if the contents can be read. */
6402 if(tng_data_block_meta_information_read(tng_data,
6403 &datatype,
6404 &dependency, &sparse_data,
6405 &n_values, &codec_id,
6406 &first_frame_with_data,
6407 &stride_length, &n_frames,
6408 &num_first_particle,
6409 &block_n_particles,
6410 &multiplier,
6411 hash_mode,
6412 &md5_state) == TNG_CRITICAL)
6414 fprintf(stderr, "TNG library: Cannot read data block (%s) meta information. %s: %d\n",
6415 block->name, __FILE__, __LINE__);
6416 return(TNG_CRITICAL);
6419 remaining_len = block->block_contents_size - (ftello(tng_data->input_file) - start_pos);
6421 stat = tng_data_read(tng_data, block,
6422 remaining_len,
6423 datatype,
6424 num_first_particle,
6425 block_n_particles,
6426 first_frame_with_data,
6427 stride_length,
6428 n_frames, n_values,
6429 codec_id, multiplier,
6430 hash_mode,
6431 &md5_state);
6433 if(hash_mode == TNG_USE_HASH)
6435 /* If there is data left in the block that the current version of the library
6436 * cannot interpret still read that to generate the MD5 hash. */
6437 tng_md5_remaining_append(tng_data, block, start_pos, &md5_state);
6439 md5_finish(&md5_state, (md5_byte_t *)hash);
6440 if(strncmp(block->md5_hash, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", TNG_MD5_HASH_LEN) != 0)
6442 if(strncmp(block->md5_hash, hash, TNG_MD5_HASH_LEN) != 0)
6444 fprintf(stderr, "TNG library: Data block contents corrupt (%s). Hashes do not match. "
6445 "%s: %d\n", block->name, __FILE__, __LINE__);
6449 else
6451 /* Seek to the end of the block */
6452 fseeko(tng_data->input_file, start_pos + block->block_contents_size, SEEK_SET);
6455 return(stat);
6459 // ** Move the blocks in a frame set so that there is no unused space between
6460 // * them. This can only be done on the last frame set in the file and should
6461 // * be done e.g. if the last frame set in the file has fewer frames than
6462 // * default or after compressing data blocks in a frame set.
6463 // * @param tng_data is a trajectory data container.
6464 // * @details the current_trajectory_frame_set is the one that will be modified.
6465 // * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the frame set
6466 // * cannot be aligned or TNG_CRITICAL (2) if a major error has occured.
6467 // * FIXME: This function is not finished!!!
6468 // *
6469 // static tng_function_status tng_frame_set_align(tng_trajectory_t tng_data)
6470 // {
6471 // tng_gen_block_t block;
6472 // tng_trajectory_frame_set_t frame_set;
6473 // FILE *temp = tng_data->input_file;
6474 // int64_t pos, contents_start_pos, output_file_len;
6476 // frame_set = &tng_data->current_trajectory_frame_set;
6478 // if(frame_set->n_written_frames == frame_set->n_frames)
6479 // {
6480 // return(TNG_SUCCESS);
6481 // }
6483 // if(tng_data->current_trajectory_frame_set_output_file_pos !=
6484 // tng_data->last_trajectory_frame_set_output_file_pos)
6485 // {
6486 // }
6488 // if(tng_output_file_init(tng_data) != TNG_SUCCESS)
6489 // {
6490 // fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
6491 // __FILE__, __LINE__);
6492 // return(TNG_CRITICAL);
6493 // }
6495 // tng_block_init(&block);
6496 // // output_file_pos = ftello(tng_data->output_file);
6498 // tng_data->input_file = tng_data->output_file;
6500 // pos = tng_data->current_trajectory_frame_set_output_file_pos;
6502 // fseeko(tng_data->output_file, pos, SEEK_SET);
6503 // if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
6504 // {
6505 // fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
6506 // __FILE__, __LINE__);
6507 // tng_data->input_file = temp;
6508 // tng_block_destroy(&block);
6509 // return(TNG_CRITICAL);
6510 // }
6512 // contents_start_pos = ftello(tng_data->output_file);
6514 // fseeko(tng_data->output_file, 0, SEEK_END);
6515 // output_file_len = ftello(tng_data->output_file);
6516 // pos = contents_start_pos + block->block_contents_size;
6517 // fseeko(tng_data->output_file, pos,
6518 // SEEK_SET);
6520 // while(pos < output_file_len)
6521 // {
6522 // if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
6523 // {
6524 // fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n", pos,
6525 // __FILE__, __LINE__);
6526 // tng_data->input_file = temp;
6527 // tng_block_destroy(&block);
6528 // return(TNG_CRITICAL);
6529 // }
6530 // pos += block->header_contents_size + block->block_contents_size;
6531 // fseeko(tng_data->output_file, pos, SEEK_SET);
6532 // }
6534 // return(TNG_SUCCESS);
6535 // }
6538 * @brief Finish writing the current frame set. Update the number of frames
6539 * and the hashes of the frame set and all its data blocks (if hash_mode
6540 * == TNG_USE_HASH).
6541 * @param tng_data is a trajectory data container.
6542 * @param hash_mode specifies whether to update the block md5 hash when
6543 * updating the pointers.
6544 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6545 * error has occured.
6547 static tng_function_status tng_frame_set_finalize
6548 (const tng_trajectory_t tng_data,
6549 const char hash_mode)
6551 tng_gen_block_t block;
6552 tng_trajectory_frame_set_t frame_set;
6553 FILE *temp = tng_data->input_file;
6554 int64_t pos, curr_file_pos;
6556 frame_set = &tng_data->current_trajectory_frame_set;
6558 if(frame_set->n_written_frames == frame_set->n_frames)
6560 return(TNG_SUCCESS);
6563 frame_set->n_written_frames = frame_set->n_frames;
6565 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
6567 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
6568 __FILE__, __LINE__);
6569 return(TNG_CRITICAL);
6572 tng_block_init(&block);
6573 /* output_file_pos = ftello(tng_data->output_file); */
6575 tng_data->input_file = tng_data->output_file;
6577 curr_file_pos = ftello(tng_data->output_file);
6579 pos = tng_data->current_trajectory_frame_set_output_file_pos;
6581 fseeko(tng_data->output_file, pos, SEEK_SET);
6583 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
6585 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
6586 __FILE__, __LINE__);
6587 tng_data->input_file = temp;
6588 tng_block_destroy(&block);
6589 return(TNG_CRITICAL);
6592 // contents_start_pos = ftello(tng_data->output_file);
6594 fseeko(tng_data->output_file, sizeof(frame_set->first_frame), SEEK_CUR);
6595 if(fwrite(&frame_set->n_frames, sizeof(frame_set->n_frames),
6596 1, tng_data->output_file) != 1)
6598 tng_data->input_file = temp;
6599 tng_block_destroy(&block);
6600 return(TNG_CRITICAL);
6603 if(hash_mode == TNG_USE_HASH)
6605 tng_md5_hash_update(tng_data, block, pos,
6606 pos + block->header_contents_size);
6609 fseeko(tng_data->output_file, curr_file_pos, SEEK_SET);
6611 tng_data->input_file = temp;
6612 tng_block_destroy(&block);
6613 return(TNG_SUCCESS);
6617 // ** Sets the name of a file contents block
6618 // * @param tng_data is a trajectory data container.
6619 // * @param block is the block, of which to change names.
6620 // * @param new_name is the new name of the block.
6621 // * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6622 // * error has occured.
6624 // static tng_function_status tng_block_name_set(tng_trajectory_t tng_data,
6625 // tng_gen_block_t block,
6626 // const char *new_name)
6627 // {
6628 // int len;
6630 // len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
6632 // * If the currently stored string length is not enough to store the new
6633 // * string it is freed and reallocated. *
6634 // if(block->name && strlen(block->name) < len)
6635 // {
6636 // free(block->name);
6637 // block->name = 0;
6638 // }
6639 // if(!block->name)
6640 // {
6641 // block->name = (char *)malloc(len);
6642 // if(!block->name)
6643 // {
6644 // fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
6645 // __FILE__, __LINE__);
6646 // return(TNG_CRITICAL);
6647 // }
6648 // }
6650 // strncpy(block->name, new_name, len);
6652 // return(TNG_SUCCESS);
6653 // }
6656 tng_function_status DECLSPECDLLEXPORT tng_atom_residue_get
6657 (const tng_trajectory_t tng_data,
6658 const tng_atom_t atom,
6659 tng_residue_t *residue)
6661 (void) tng_data;
6663 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
6665 *residue = atom->residue;
6667 return(TNG_SUCCESS);
6670 tng_function_status DECLSPECDLLEXPORT tng_atom_name_get
6671 (const tng_trajectory_t tng_data,
6672 const tng_atom_t atom,
6673 char *name,
6674 const int max_len)
6676 (void) tng_data;
6677 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
6678 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
6680 strncpy(name, atom->name, max_len - 1);
6681 name[max_len - 1] = 0;
6683 if(strlen(atom->name) > (unsigned int)max_len - 1)
6685 return(TNG_FAILURE);
6687 return(TNG_SUCCESS);
6690 tng_function_status DECLSPECDLLEXPORT tng_atom_name_set
6691 (const tng_trajectory_t tng_data,
6692 const tng_atom_t atom,
6693 const char *new_name)
6695 unsigned int len;
6696 (void)tng_data;
6698 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
6699 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
6701 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
6703 /* If the currently stored string length is not enough to store the new
6704 * string it is freed and reallocated. */
6705 if(atom->name && strlen(atom->name) < len)
6707 free(atom->name);
6708 atom->name = 0;
6710 if(!atom->name)
6712 atom->name = (char *)malloc(len);
6713 if(!atom->name)
6715 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
6716 __FILE__, __LINE__);
6717 return(TNG_CRITICAL);
6721 strncpy(atom->name, new_name, len);
6723 return(TNG_SUCCESS);
6726 tng_function_status DECLSPECDLLEXPORT tng_atom_type_get
6727 (const tng_trajectory_t tng_data,
6728 const tng_atom_t atom,
6729 char *type,
6730 const int max_len)
6732 (void) tng_data;
6733 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
6734 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer");
6736 strncpy(type, atom->atom_type, max_len - 1);
6737 type[max_len - 1] = 0;
6739 if(strlen(atom->atom_type) > (unsigned int)max_len - 1)
6741 return(TNG_FAILURE);
6743 return(TNG_SUCCESS);
6746 tng_function_status DECLSPECDLLEXPORT tng_atom_type_set
6747 (const tng_trajectory_t tng_data,
6748 const tng_atom_t atom,
6749 const char *new_type)
6751 unsigned int len;
6752 (void)tng_data;
6754 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
6755 TNG_ASSERT(new_type, "TNG library: new_type must not be a NULL pointer.");
6757 len = tng_min_size(strlen(new_type) + 1, TNG_MAX_STR_LEN);
6759 /* If the currently stored string length is not enough to store the new
6760 * string it is freed and reallocated. */
6761 if(atom->atom_type && strlen(atom->atom_type) < len)
6763 free(atom->atom_type);
6764 atom->atom_type = 0;
6766 if(!atom->atom_type)
6768 atom->atom_type = (char *)malloc(len);
6769 if(!atom->atom_type)
6771 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
6772 __FILE__, __LINE__);
6773 return(TNG_CRITICAL);
6777 strncpy(atom->atom_type, new_type, len);
6779 return(TNG_SUCCESS);
6783 * @brief Initialise an atom struct
6784 * @param atom is the atom to initialise.
6785 * @return TNG_SUCCESS (0) if successful.
6787 static tng_function_status tng_atom_init(const tng_atom_t atom)
6789 atom->name = 0;
6790 atom->atom_type = 0;
6792 return(TNG_SUCCESS);
6796 * @brief Free the memory in an atom struct
6797 * @param atom is the atom to destroy.
6798 * @return TNG_SUCCESS (0) if successful.
6800 static tng_function_status tng_atom_destroy(const tng_atom_t atom)
6802 if(atom->name)
6804 free(atom->name);
6805 atom->name = 0;
6807 if(atom->atom_type)
6809 free(atom->atom_type);
6810 atom->atom_type = 0;
6813 return(TNG_SUCCESS);
6817 * @brief Update chain->residue pointers (after new memory for
6818 * molecule->residues has been allocated).
6819 * @param tng_data The trajectory container containing the molecule.
6820 * @param mol The molecule that contains the chains that need to be
6821 * updated.
6822 * @returns TNG_SUCCESS (0) if successful.
6824 static tng_function_status tng_molecule_chains_residue_pointers_update
6825 (const tng_trajectory_t tng_data,
6826 const tng_molecule_t mol)
6828 tng_chain_t chain;
6829 int64_t i, res_cnt = 0;
6830 (void)tng_data;
6832 for(i = 0; i < mol->n_chains; i++)
6834 chain = &mol->chains[i];
6835 chain->residues = mol->residues + res_cnt;
6836 res_cnt += chain->n_residues;
6838 return(TNG_SUCCESS);
6841 tng_function_status DECLSPECDLLEXPORT tng_version_major
6842 (const tng_trajectory_t tng_data,
6843 int *version)
6845 (void)tng_data;
6847 *version = TNG_VERSION_MAJOR;
6849 return(TNG_SUCCESS);
6852 tng_function_status DECLSPECDLLEXPORT tng_version_minor
6853 (const tng_trajectory_t tng_data,
6854 int *version)
6856 (void)tng_data;
6858 *version = TNG_VERSION_MINOR;
6860 return(TNG_SUCCESS);
6863 tng_function_status DECLSPECDLLEXPORT tng_version_patchlevel
6864 (const tng_trajectory_t tng_data,
6865 int *patch_level)
6867 (void)tng_data;
6869 *patch_level = TNG_VERSION_PATCHLEVEL;
6871 return(TNG_SUCCESS);
6874 tng_function_status DECLSPECDLLEXPORT tng_version
6875 (const tng_trajectory_t tng_data,
6876 char *version,
6877 const int max_len)
6879 (void)tng_data;
6880 TNG_ASSERT(version, "TNG library: version must not be a NULL pointer");
6882 TNG_SNPRINTF(version, max_len, "%s", TNG_VERSION);
6884 return(TNG_SUCCESS);
6887 tng_function_status DECLSPECDLLEXPORT tng_molecule_add
6888 (const tng_trajectory_t tng_data,
6889 const char *name,
6890 tng_molecule_t *molecule)
6892 int64_t id;
6894 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
6895 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
6897 /* Set ID to the ID of the last molecule + 1 */
6898 if(tng_data->n_molecules)
6900 id = tng_data->molecules[tng_data->n_molecules-1].id + 1;
6902 else
6904 id = 1;
6907 return(tng_molecule_w_id_add(tng_data, name, id, molecule));
6910 tng_function_status DECLSPECDLLEXPORT tng_molecule_w_id_add
6911 (const tng_trajectory_t tng_data,
6912 const char *name,
6913 const int64_t id,
6914 tng_molecule_t *molecule)
6916 tng_molecule_t new_molecules;
6917 int64_t *new_molecule_cnt_list;
6918 tng_function_status stat = TNG_SUCCESS;
6920 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
6921 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
6923 new_molecules = (tng_molecule_t)realloc(tng_data->molecules,
6924 sizeof(struct tng_molecule) *
6925 (tng_data->n_molecules + 1));
6927 if(!new_molecules)
6929 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
6930 __FILE__, __LINE__);
6931 free(tng_data->molecules);
6932 tng_data->molecules = 0;
6933 return(TNG_CRITICAL);
6936 new_molecule_cnt_list = (int64_t *)realloc(tng_data->molecule_cnt_list,
6937 sizeof(int64_t) *
6938 (tng_data->n_molecules + 1));
6940 if(!new_molecule_cnt_list)
6942 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
6943 __FILE__, __LINE__);
6944 free(tng_data->molecule_cnt_list);
6945 tng_data->molecule_cnt_list = 0;
6946 free(new_molecules);
6947 return(TNG_CRITICAL);
6950 tng_data->molecules = new_molecules;
6951 tng_data->molecule_cnt_list = new_molecule_cnt_list;
6953 *molecule = &new_molecules[tng_data->n_molecules];
6955 tng_molecule_init(tng_data, *molecule);
6956 tng_molecule_name_set(tng_data, *molecule, name);
6958 /* FIXME: Should this be a function argument instead? */
6959 tng_data->molecule_cnt_list[tng_data->n_molecules] = 0;
6961 (*molecule)->id = id;
6963 tng_data->n_molecules++;
6965 return(stat);
6968 tng_function_status DECLSPECDLLEXPORT tng_molecule_existing_add
6969 (const tng_trajectory_t tng_data,
6970 tng_molecule_t *molecule_p)
6972 int64_t *new_molecule_cnt_list, id;
6973 tng_molecule_t new_molecules, molecule;
6975 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
6977 /* Set ID to the ID of the last molecule + 1 */
6978 if(tng_data->n_molecules)
6980 id = tng_data->molecules[tng_data->n_molecules-1].id + 1;
6982 else
6984 id = 1;
6987 new_molecules = (tng_molecule_t)realloc(tng_data->molecules,
6988 sizeof(struct tng_molecule) *
6989 (tng_data->n_molecules + 1));
6991 if(!new_molecules)
6993 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
6994 __FILE__, __LINE__);
6995 free(tng_data->molecules);
6996 tng_data->molecules = 0;
6997 return(TNG_CRITICAL);
7000 new_molecule_cnt_list = (int64_t *)realloc(tng_data->molecule_cnt_list,
7001 sizeof(int64_t) *
7002 (tng_data->n_molecules + 1));
7004 if(!new_molecule_cnt_list)
7006 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
7007 __FILE__, __LINE__);
7008 free(tng_data->molecule_cnt_list);
7009 tng_data->molecule_cnt_list = 0;
7010 free(new_molecules);
7011 return(TNG_CRITICAL);
7014 molecule = *molecule_p;
7016 tng_data->molecules = new_molecules;
7017 tng_data->molecule_cnt_list = new_molecule_cnt_list;
7019 new_molecules[tng_data->n_molecules] = *molecule;
7021 tng_data->molecule_cnt_list[tng_data->n_molecules] = 0;
7023 free(*molecule_p);
7025 molecule = &new_molecules[tng_data->n_molecules];
7027 *molecule_p = molecule;
7029 molecule->id = id;
7031 tng_data->n_molecules++;
7033 return(TNG_SUCCESS);
7036 tng_function_status tng_molecule_name_get(const tng_trajectory_t tng_data,
7037 const tng_molecule_t molecule,
7038 char *name,
7039 const int max_len)
7041 (void) tng_data;
7042 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
7043 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
7045 strncpy(name, molecule->name, max_len - 1);
7046 name[max_len - 1] = 0;
7048 if(strlen(molecule->name) > (unsigned int)max_len - 1)
7050 return(TNG_FAILURE);
7052 return(TNG_SUCCESS);
7055 tng_function_status DECLSPECDLLEXPORT tng_molecule_name_set
7056 (const tng_trajectory_t tng_data,
7057 const tng_molecule_t molecule,
7058 const char *new_name)
7060 unsigned int len;
7061 (void)tng_data;
7063 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7064 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
7066 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
7068 /* If the currently stored string length is not enough to store the new
7069 * string it is freed and reallocated. */
7070 if(molecule->name && strlen(molecule->name) < len)
7072 free(molecule->name);
7073 molecule->name = 0;
7075 if(!molecule->name)
7077 molecule->name = (char *)malloc(len);
7078 if(!molecule->name)
7080 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
7081 __FILE__, __LINE__);
7082 return(TNG_CRITICAL);
7086 strncpy(molecule->name, new_name, len);
7088 return(TNG_SUCCESS);
7091 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_get
7092 (const tng_trajectory_t tng_data,
7093 const tng_molecule_t molecule,
7094 int64_t *cnt)
7096 int64_t i, index = -1;
7098 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7099 TNG_ASSERT(cnt, "TNG library: cnt must not be a NULL pointer.");
7101 for(i = 0; i < tng_data->n_molecules; i++)
7103 if(&tng_data->molecules[i] == molecule)
7105 index = i;
7106 break;
7109 if(index == -1)
7111 return(TNG_FAILURE);
7113 *cnt = tng_data->molecule_cnt_list[index];
7115 return(TNG_SUCCESS);
7118 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_set
7119 (const tng_trajectory_t tng_data,
7120 const tng_molecule_t molecule,
7121 const int64_t cnt)
7123 int64_t i, old_cnt, index = -1;
7125 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7127 for(i = 0; i < tng_data->n_molecules; i++)
7129 if(&tng_data->molecules[i] == molecule)
7131 index = i;
7132 break;
7135 if(index == -1)
7137 fprintf(stderr, "TNG library: Could not find molecule in TNG trajectory. %s: %d\n",
7138 __FILE__, __LINE__);
7139 return(TNG_FAILURE);
7141 if(tng_data->var_num_atoms_flag == TNG_CONSTANT_N_ATOMS)
7143 old_cnt = tng_data->molecule_cnt_list[index];
7144 tng_data->molecule_cnt_list[index] = cnt;
7146 tng_data->n_particles += (cnt-old_cnt) *
7147 tng_data->molecules[index].n_atoms;
7149 else
7151 old_cnt = tng_data->current_trajectory_frame_set.molecule_cnt_list[index];
7152 tng_data->current_trajectory_frame_set.molecule_cnt_list[index] = cnt;
7154 tng_data->current_trajectory_frame_set.n_particles += (cnt-old_cnt) *
7155 tng_data->molecules[index].n_atoms;
7158 return(TNG_SUCCESS);
7161 tng_function_status DECLSPECDLLEXPORT tng_molecule_find
7162 (const tng_trajectory_t tng_data,
7163 const char *name,
7164 const int64_t nr,
7165 tng_molecule_t *molecule)
7167 int64_t i, n_molecules;
7169 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7170 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7171 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
7173 n_molecules = tng_data->n_molecules;
7175 for(i = n_molecules - 1; i >= 0; i--)
7177 *molecule = &tng_data->molecules[i];
7178 if(name[0] == 0 || strcmp(name, (*molecule)->name) == 0)
7180 if(nr == -1 || nr == (*molecule)->id)
7182 return(TNG_SUCCESS);
7187 *molecule = 0;
7189 return(TNG_FAILURE);
7192 tng_function_status DECLSPECDLLEXPORT tng_molecule_of_index_get
7193 (const tng_trajectory_t tng_data,
7194 const int64_t index,
7195 tng_molecule_t *molecule)
7197 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7198 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
7200 if(index >= tng_data->n_molecules)
7202 *molecule = 0;
7203 return(TNG_FAILURE);
7205 *molecule = &tng_data->molecules[index];
7206 return(TNG_SUCCESS);
7209 tng_function_status DECLSPECDLLEXPORT tng_molecule_system_copy(const tng_trajectory_t tng_data_src,
7210 const tng_trajectory_t tng_data_dest)
7212 tng_molecule_t molecule, molecule_temp;
7213 tng_chain_t chain, chain_temp;
7214 tng_residue_t residue, residue_temp;
7215 tng_atom_t atom, atom_temp;
7216 tng_bond_t bond_temp;
7217 tng_function_status stat;
7218 int64_t i, j, k, l, *list_temp;
7220 TNG_ASSERT(tng_data_src, "TNG library: Trajectory container not properly setup.");
7221 TNG_ASSERT(tng_data_dest, "TNG library: Trajectory container not properly setup.");
7223 for(i = 0; i < tng_data_dest->n_molecules; i++)
7225 molecule = &tng_data_dest->molecules[i];
7226 tng_molecule_destroy(tng_data_dest, molecule);
7229 tng_data_dest->n_molecules = 0;
7230 tng_data_dest->n_particles = 0;
7232 molecule_temp = (tng_molecule_t)realloc(tng_data_dest->molecules,
7233 sizeof(struct tng_molecule) * tng_data_src->n_molecules);
7234 if(!molecule_temp)
7236 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
7237 __FILE__, __LINE__);
7238 free(tng_data_dest->molecules);
7239 tng_data_dest->molecules = 0;
7240 return(TNG_CRITICAL);
7242 list_temp = (int64_t *)realloc(tng_data_dest->molecule_cnt_list,
7243 sizeof(int64_t) * tng_data_src->n_molecules);
7244 if(!list_temp)
7246 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
7247 __FILE__, __LINE__);
7248 free(tng_data_dest->molecule_cnt_list);
7249 tng_data_dest->molecule_cnt_list = 0;
7250 free(molecule_temp);
7251 return(TNG_CRITICAL);
7254 tng_data_dest->molecules = molecule_temp;
7255 tng_data_dest->molecule_cnt_list = list_temp;
7257 for(i = 0; i < tng_data_src->n_molecules; i++)
7259 molecule = &tng_data_src->molecules[i];
7260 stat = tng_molecule_w_id_add(tng_data_dest, molecule->name, molecule->id,
7261 &molecule_temp);
7262 if(stat != TNG_SUCCESS)
7264 fprintf(stderr, "TNG library: Cannot create new molecule to make a copy. %s: %d\n",
7265 __FILE__, __LINE__);
7266 return(stat);
7268 molecule_temp->quaternary_str = molecule->quaternary_str;
7269 for(j = 0; j < molecule->n_chains; j++)
7271 chain = &molecule->chains[j];
7272 stat = tng_molecule_chain_w_id_add(tng_data_dest, molecule_temp,
7273 chain->name, chain->id,
7274 &chain_temp);
7275 if(stat != TNG_SUCCESS)
7277 fprintf(stderr, "TNG library: Cannot create new chain to make a copy. %s: %d\n",
7278 __FILE__, __LINE__);
7279 return(stat);
7281 for(k = 0; k < chain->n_residues; k++)
7283 residue = &chain->residues[k];
7284 stat = tng_chain_residue_w_id_add(tng_data_dest, chain_temp,
7285 residue->name, residue->id,
7286 &residue_temp);
7287 if(stat != TNG_SUCCESS)
7289 fprintf(stderr, "TNG library: Cannot create new residue to make a copy. %s: %d\n",
7290 __FILE__, __LINE__);
7291 return(stat);
7293 for(l = 0; l < residue->n_atoms; l++)
7295 atom = &molecule->atoms[residue->atoms_offset + l];
7296 stat = tng_residue_atom_w_id_add(tng_data_dest, residue_temp,
7297 atom->name, atom->atom_type,
7298 atom->id, &atom_temp);
7299 if(stat != TNG_SUCCESS)
7301 fprintf(stderr, "TNG library: Cannot create new atom to make a copy. %s: %d\n",
7302 __FILE__, __LINE__);
7303 return(stat);
7308 molecule_temp->n_bonds = molecule->n_bonds;
7309 if(molecule->n_bonds > 0)
7311 bond_temp = (tng_bond_t)realloc(molecule_temp->bonds, sizeof(struct tng_bond) *
7312 molecule->n_bonds);
7313 if(!bond_temp)
7315 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
7316 __FILE__, __LINE__);
7317 free(molecule_temp->bonds);
7318 molecule_temp->n_bonds = 0;
7319 return(TNG_CRITICAL);
7321 molecule_temp->bonds = bond_temp;
7322 for(j = 0; j < molecule->n_bonds; j++)
7324 molecule_temp->bonds[j] = molecule->bonds[j];
7327 stat = tng_molecule_cnt_set(tng_data_dest, molecule_temp,
7328 tng_data_src->molecule_cnt_list[i]);
7329 if(stat != TNG_SUCCESS)
7331 fprintf(stderr, "TNG library: Cannot set molecule count. %s: %d.\n",
7332 __FILE__, __LINE__);
7333 return(stat);
7336 return(TNG_SUCCESS);
7339 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_chains_get
7340 (const tng_trajectory_t tng_data,
7341 const tng_molecule_t molecule,
7342 int64_t *n)
7344 (void) tng_data;
7345 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
7346 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
7348 *n = molecule->n_chains;
7350 return(TNG_SUCCESS);
7353 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_of_index_get
7354 (const tng_trajectory_t tng_data,
7355 const tng_molecule_t molecule,
7356 const int64_t index,
7357 tng_chain_t *chain)
7359 (void) tng_data;
7360 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
7361 TNG_ASSERT(chain, "TNG library: chain must not be a NULL pointer.");
7363 if(index >= molecule->n_chains)
7365 *chain = 0;
7366 return(TNG_FAILURE);
7368 *chain = &molecule->chains[index];
7369 return(TNG_SUCCESS);
7372 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_residues_get
7373 (const tng_trajectory_t tng_data,
7374 const tng_molecule_t molecule,
7375 int64_t *n)
7377 (void) tng_data;
7378 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
7379 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
7381 *n = molecule->n_residues;
7383 return(TNG_SUCCESS);
7386 tng_function_status DECLSPECDLLEXPORT tng_molecule_residue_of_index_get
7387 (const tng_trajectory_t tng_data,
7388 const tng_molecule_t molecule,
7389 const int64_t index,
7390 tng_residue_t *residue)
7392 (void) tng_data;
7393 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
7394 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
7396 if(index >= molecule->n_residues)
7398 *residue = 0;
7399 return(TNG_FAILURE);
7401 *residue = &molecule->residues[index];
7402 return(TNG_SUCCESS);
7405 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_atoms_get
7406 (const tng_trajectory_t tng_data,
7407 const tng_molecule_t molecule,
7408 int64_t *n)
7410 (void) tng_data;
7411 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
7412 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
7414 *n = molecule->n_atoms;
7416 return(TNG_SUCCESS);
7419 tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_of_index_get
7420 (const tng_trajectory_t tng_data,
7421 const tng_molecule_t molecule,
7422 const int64_t index,
7423 tng_atom_t *atom)
7425 (void) tng_data;
7426 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
7427 TNG_ASSERT(atom, "TNG library: atom must not be a NULL pointer.");
7429 if(index >= molecule->n_atoms)
7431 *atom = 0;
7432 return(TNG_FAILURE);
7434 *atom = &molecule->atoms[index];
7435 return(TNG_SUCCESS);
7438 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_find
7439 (const tng_trajectory_t tng_data,
7440 const tng_molecule_t molecule,
7441 const char *name,
7442 const int64_t nr,
7443 tng_chain_t *chain)
7445 int64_t i, n_chains;
7446 (void)tng_data;
7448 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7449 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7451 n_chains = molecule->n_chains;
7453 for(i = n_chains - 1; i >= 0; i--)
7455 *chain = &molecule->chains[i];
7456 if(name[0] == 0 || strcmp(name, (*chain)->name) == 0)
7458 if(nr == -1 || nr == (*chain)->id)
7460 return(TNG_SUCCESS);
7465 *chain = 0;
7467 return(TNG_FAILURE);
7470 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_add
7471 (const tng_trajectory_t tng_data,
7472 const tng_molecule_t molecule,
7473 const char *name,
7474 tng_chain_t *chain)
7476 int64_t id;
7478 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7479 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7481 /* Set ID to the ID of the last chain + 1 */
7482 if(molecule->n_chains)
7484 id = molecule->chains[molecule->n_chains-1].id + 1;
7486 else
7488 id = 1;
7491 return(tng_molecule_chain_w_id_add(tng_data, molecule, name,
7492 id, chain));
7495 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_w_id_add
7496 (const tng_trajectory_t tng_data,
7497 const tng_molecule_t molecule,
7498 const char *name,
7499 const int64_t id,
7500 tng_chain_t *chain)
7502 tng_chain_t new_chains;
7503 tng_function_status stat = TNG_SUCCESS;
7505 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7506 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7508 new_chains = (tng_chain_t)realloc(molecule->chains,
7509 sizeof(struct tng_chain) *
7510 (molecule->n_chains + 1));
7512 if(!new_chains)
7514 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
7515 __FILE__, __LINE__);
7516 free(molecule->chains);
7517 molecule->chains = 0;
7518 return(TNG_CRITICAL);
7521 molecule->chains = new_chains;
7523 *chain = &new_chains[molecule->n_chains];
7524 (*chain)->name = 0;
7526 tng_chain_name_set(tng_data, *chain, name);
7528 (*chain)->molecule = molecule;
7529 (*chain)->n_residues = 0;
7531 molecule->n_chains++;
7533 (*chain)->id = id;
7535 return(stat);
7538 tng_function_status DECLSPECDLLEXPORT tng_molecule_bond_add
7539 (const tng_trajectory_t tng_data,
7540 const tng_molecule_t molecule,
7541 const int64_t from_atom_id,
7542 const int64_t to_atom_id,
7543 tng_bond_t *bond)
7545 tng_bond_t new_bonds;
7546 (void)tng_data;
7548 new_bonds = (tng_bond_t)realloc(molecule->bonds,
7549 sizeof(struct tng_bond) *
7550 (molecule->n_bonds + 1));
7552 if(!new_bonds)
7554 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
7555 __FILE__, __LINE__);
7556 *bond = 0;
7557 free(molecule->bonds);
7558 molecule->bonds = 0;
7559 return(TNG_CRITICAL);
7562 molecule->bonds = new_bonds;
7564 *bond = &new_bonds[molecule->n_bonds];
7566 (*bond)->from_atom_id = from_atom_id;
7567 (*bond)->to_atom_id = to_atom_id;
7569 molecule->n_bonds++;
7571 return(TNG_SUCCESS);
7574 tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_find
7575 (const tng_trajectory_t tng_data,
7576 const tng_molecule_t molecule,
7577 const char *name,
7578 const int64_t id,
7579 tng_atom_t *atom)
7581 int64_t i, n_atoms;
7582 (void)tng_data;
7584 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7586 n_atoms = molecule->n_atoms;
7588 for(i = n_atoms - 1; i >= 0; i--)
7590 *atom = &molecule->atoms[i];
7591 if(name[0] == 0 || strcmp(name, (*atom)->name) == 0)
7593 if(id == -1 || id == (*atom)->id)
7595 return(TNG_SUCCESS);
7600 *atom = 0;
7602 return(TNG_FAILURE);
7605 tng_function_status tng_chain_name_get(const tng_trajectory_t tng_data,
7606 const tng_chain_t chain,
7607 char *name,
7608 const int max_len)
7610 (void) tng_data;
7611 TNG_ASSERT(chain, "TNG library: chain must not be NULL");
7612 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
7614 strncpy(name, chain->name, max_len - 1);
7615 name[max_len - 1] = 0;
7617 if(strlen(chain->name) > (unsigned int)max_len - 1)
7619 return(TNG_FAILURE);
7621 return(TNG_SUCCESS);
7624 tng_function_status DECLSPECDLLEXPORT tng_chain_name_set
7625 (const tng_trajectory_t tng_data,
7626 const tng_chain_t chain,
7627 const char *new_name)
7629 unsigned int len;
7630 (void)tng_data;
7632 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
7634 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
7636 /* If the currently stored string length is not enough to store the new
7637 * string it is freed and reallocated. */
7638 if(chain->name && strlen(chain->name) < len)
7640 free(chain->name);
7641 chain->name = 0;
7643 if(!chain->name)
7645 chain->name = (char *)malloc(len);
7646 if(!chain->name)
7648 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
7649 __FILE__, __LINE__);
7650 return(TNG_CRITICAL);
7654 strncpy(chain->name, new_name, len);
7656 return(TNG_SUCCESS);
7659 tng_function_status DECLSPECDLLEXPORT tng_chain_num_residues_get
7660 (const tng_trajectory_t tng_data,
7661 const tng_chain_t chain,
7662 int64_t *n)
7664 (void) tng_data;
7665 TNG_ASSERT(chain, "TNG library: chain must not be NULL");
7666 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
7668 *n = chain->n_residues;
7670 return(TNG_SUCCESS);
7673 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_of_index_get
7674 (const tng_trajectory_t tng_data,
7675 const tng_chain_t chain,
7676 const int64_t index,
7677 tng_residue_t *residue)
7679 (void) tng_data;
7680 TNG_ASSERT(chain, "TNG library: chain must not be a NULL pointer.");
7681 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
7683 if(index >= chain->n_residues)
7685 *residue = 0;
7686 return(TNG_FAILURE);
7688 *residue = &chain->residues[index];
7689 return(TNG_SUCCESS);
7692 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_find
7693 (const tng_trajectory_t tng_data,
7694 const tng_chain_t chain,
7695 const char *name,
7696 const int64_t id,
7697 tng_residue_t *residue)
7699 int64_t i, n_residues;
7700 (void)tng_data;
7702 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7704 n_residues = chain->n_residues;
7706 for(i = n_residues - 1; i >= 0; i--)
7708 *residue = &chain->residues[i];
7709 if(name[0] == 0 || strcmp(name, (*residue)->name) == 0)
7711 if(id == -1 || id == (*residue)->id)
7713 return(TNG_SUCCESS);
7718 *residue = 0;
7720 return(TNG_FAILURE);
7723 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_add
7724 (const tng_trajectory_t tng_data,
7725 const tng_chain_t chain,
7726 const char *name,
7727 tng_residue_t *residue)
7729 int64_t id;
7731 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7732 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7734 /* Set ID to the ID of the last residue + 1 */
7735 if(chain->n_residues)
7737 id = chain->residues[chain->n_residues-1].id + 1;
7739 else
7741 id = 0;
7744 return(tng_chain_residue_w_id_add(tng_data, chain, name,
7745 id, residue));
7748 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_w_id_add
7749 (const tng_trajectory_t tng_data,
7750 const tng_chain_t chain,
7751 const char *name,
7752 const int64_t id,
7753 tng_residue_t *residue)
7755 int64_t curr_index;
7756 tng_residue_t new_residues, temp_residue, last_residue;
7757 tng_molecule_t molecule = chain->molecule;
7758 tng_function_status stat = TNG_SUCCESS;
7760 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7761 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7763 if(chain->n_residues)
7765 curr_index = chain->residues - molecule->residues;
7767 else
7769 curr_index = -1;
7772 new_residues = (tng_residue_t)realloc(molecule->residues,
7773 sizeof(struct tng_residue) *
7774 (molecule->n_residues + 1));
7776 if(!new_residues)
7778 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
7779 __FILE__, __LINE__);
7780 free(molecule->residues);
7781 molecule->residues = 0;
7782 return(TNG_CRITICAL);
7785 molecule->residues = new_residues;
7787 if(curr_index != -1)
7789 chain->residues = new_residues + curr_index;
7790 if(molecule->n_residues)
7792 last_residue = &new_residues[molecule->n_residues - 1];
7794 temp_residue = chain->residues + (chain->n_residues - 1);
7795 /* Make space in list of residues to add the new residues together with the other
7796 * residues of this chain */
7797 if(temp_residue != last_residue)
7799 ++temp_residue;
7800 memmove(temp_residue + 1, temp_residue,
7801 last_residue - temp_residue);
7805 else
7807 curr_index = molecule->n_residues;
7810 *residue = &molecule->residues[curr_index + chain->n_residues];
7812 tng_molecule_chains_residue_pointers_update(tng_data, molecule);
7814 (*residue)->name = 0;
7815 tng_residue_name_set(tng_data, *residue, name);
7817 (*residue)->chain = chain;
7818 (*residue)->n_atoms = 0;
7819 (*residue)->atoms_offset = 0;
7821 chain->n_residues++;
7822 molecule->n_residues++;
7824 (*residue)->id = id;
7826 return(stat);
7829 tng_function_status tng_residue_name_get(const tng_trajectory_t tng_data,
7830 const tng_residue_t residue,
7831 char *name,
7832 const int max_len)
7834 (void) tng_data;
7835 TNG_ASSERT(residue, "TNG library: residue must not be NULL");
7836 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
7838 strncpy(name, residue->name, max_len - 1);
7839 name[max_len - 1] = 0;
7841 if(strlen(residue->name) > (unsigned int)max_len - 1)
7843 return(TNG_FAILURE);
7845 return(TNG_SUCCESS);
7848 tng_function_status DECLSPECDLLEXPORT tng_residue_name_set(const tng_trajectory_t tng_data,
7849 const tng_residue_t residue,
7850 const char *new_name)
7852 unsigned int len;
7853 (void)tng_data;
7855 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7856 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
7858 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
7860 /* If the currently stored string length is not enough to store the new
7861 * string it is freed and reallocated. */
7862 if(residue->name && strlen(residue->name) < len)
7864 free(residue->name);
7865 residue->name = 0;
7867 if(!residue->name)
7869 residue->name = (char *)malloc(len);
7870 if(!residue->name)
7872 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
7873 __FILE__, __LINE__);
7874 return(TNG_CRITICAL);
7878 strncpy(residue->name, new_name, len);
7880 return(TNG_SUCCESS);
7883 tng_function_status DECLSPECDLLEXPORT tng_residue_num_atoms_get
7884 (const tng_trajectory_t tng_data,
7885 const tng_residue_t residue,
7886 int64_t *n)
7888 (void) tng_data;
7889 TNG_ASSERT(residue, "TNG library: residue must not be NULL");
7890 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
7892 *n = residue->n_atoms;
7894 return(TNG_SUCCESS);
7897 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_of_index_get
7898 (const tng_trajectory_t tng_data,
7899 const tng_residue_t residue,
7900 const int64_t index,
7901 tng_atom_t *atom)
7903 tng_chain_t chain;
7904 tng_molecule_t molecule;
7906 (void) tng_data;
7907 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
7908 TNG_ASSERT(atom, "TNG library: atom must not be a NULL pointer.");
7910 if(index >= residue->n_atoms)
7912 *atom = 0;
7913 return(TNG_FAILURE);
7915 chain = residue->chain;
7916 molecule = chain->molecule;
7918 if(index + residue->atoms_offset >= molecule->n_atoms)
7920 *atom = 0;
7921 return(TNG_FAILURE);
7924 *atom = &molecule->atoms[residue->atoms_offset + index];
7925 return(TNG_SUCCESS);
7928 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_add
7929 (const tng_trajectory_t tng_data,
7930 const tng_residue_t residue,
7931 const char *atom_name,
7932 const char *atom_type,
7933 tng_atom_t *atom)
7935 int64_t id;
7937 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7938 TNG_ASSERT(atom_name, "TNG library: atom_name must not be a NULL pointer.");
7939 TNG_ASSERT(atom_type, "TNG library: atom_type must not be a NULL pointer.");
7941 /* Set ID to the ID of the last atom + 1 */
7942 if(residue->chain->molecule->n_atoms)
7944 id = residue->chain->molecule->atoms[residue->chain->molecule->n_atoms-1].id + 1;
7946 else
7948 id = 0;
7951 return(tng_residue_atom_w_id_add(tng_data, residue, atom_name, atom_type,
7952 id, atom));
7955 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_w_id_add
7956 (const tng_trajectory_t tng_data,
7957 const tng_residue_t residue,
7958 const char *atom_name,
7959 const char *atom_type,
7960 const int64_t id,
7961 tng_atom_t *atom)
7963 tng_atom_t new_atoms;
7964 tng_molecule_t molecule = residue->chain->molecule;
7965 tng_function_status stat = TNG_SUCCESS;
7967 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7968 TNG_ASSERT(atom_name, "TNG library: atom_name must not be a NULL pointer.");
7969 TNG_ASSERT(atom_type, "TNG library: atom_type must not be a NULL pointer.");
7971 if(!residue->n_atoms)
7973 residue->atoms_offset = molecule->n_atoms;
7976 new_atoms = (tng_atom_t)realloc(molecule->atoms,
7977 sizeof(struct tng_atom) *
7978 (molecule->n_atoms + 1));
7980 if(!new_atoms)
7982 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
7983 __FILE__, __LINE__);
7984 free(molecule->atoms);
7985 molecule->atoms = 0;
7986 return(TNG_CRITICAL);
7989 molecule->atoms = new_atoms;
7991 *atom = &new_atoms[molecule->n_atoms];
7993 tng_atom_init(*atom);
7994 tng_atom_name_set(tng_data, *atom, atom_name);
7995 tng_atom_type_set(tng_data, *atom, atom_type);
7997 (*atom)->residue = residue;
7999 residue->n_atoms++;
8000 molecule->n_atoms++;
8002 (*atom)->id = id;
8004 return(stat);
8007 tng_function_status DECLSPECDLLEXPORT tng_molecule_alloc(const tng_trajectory_t tng_data,
8008 tng_molecule_t *molecule_p)
8010 *molecule_p = (tng_molecule_t)malloc(sizeof(struct tng_molecule));
8011 if(!*molecule_p)
8013 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
8014 __FILE__, __LINE__);
8015 return(TNG_CRITICAL);
8018 tng_molecule_init(tng_data, *molecule_p);
8020 return(TNG_SUCCESS);
8023 tng_function_status DECLSPECDLLEXPORT tng_molecule_free(const tng_trajectory_t tng_data,
8024 tng_molecule_t *molecule_p)
8026 if(!*molecule_p)
8028 return(TNG_SUCCESS);
8031 tng_molecule_destroy(tng_data, *molecule_p);
8033 free(*molecule_p);
8034 *molecule_p = 0;
8036 return(TNG_SUCCESS);
8039 tng_function_status DECLSPECDLLEXPORT tng_molecule_init(const tng_trajectory_t tng_data,
8040 const tng_molecule_t molecule)
8042 (void)tng_data;
8043 molecule->quaternary_str = 1;
8044 molecule->name = 0;
8045 molecule->n_chains = 0;
8046 molecule->chains = 0;
8047 molecule->n_residues = 0;
8048 molecule->residues = 0;
8049 molecule->n_atoms = 0;
8050 molecule->atoms = 0;
8051 molecule->n_bonds = 0;
8052 molecule->bonds = 0;
8054 return(TNG_SUCCESS);
8057 tng_function_status DECLSPECDLLEXPORT tng_molecule_destroy(const tng_trajectory_t tng_data,
8058 const tng_molecule_t molecule)
8060 int64_t i;
8061 (void)tng_data;
8063 if(molecule->name)
8065 free(molecule->name);
8066 molecule->name = 0;
8069 if(molecule->chains)
8071 for(i = 0; i < molecule->n_chains; i++)
8073 if(molecule->chains[i].name)
8075 free(molecule->chains[i].name);
8076 molecule->chains[i].name = 0;
8079 free(molecule->chains);
8080 molecule->chains = 0;
8082 molecule->n_chains = 0;
8084 if(molecule->residues)
8086 for(i = 0; i < molecule->n_residues; i++)
8088 if(molecule->residues[i].name)
8090 free(molecule->residues[i].name);
8091 molecule->residues[i].name = 0;
8094 free(molecule->residues);
8095 molecule->residues = 0;
8097 molecule->n_residues = 0;
8099 if(molecule->atoms)
8101 for(i = 0; i < molecule->n_atoms; i++)
8103 tng_atom_destroy(&molecule->atoms[i]);
8105 free(molecule->atoms);
8106 molecule->atoms = 0;
8108 molecule->n_atoms = 0;
8110 if(molecule->bonds)
8112 free(molecule->bonds);
8113 molecule->bonds = 0;
8115 molecule->n_bonds = 0;
8117 return(TNG_SUCCESS);
8120 tng_function_status DECLSPECDLLEXPORT tng_molecule_name_of_particle_nr_get
8121 (const tng_trajectory_t tng_data,
8122 const int64_t nr,
8123 char *name,
8124 const int max_len)
8126 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8127 tng_molecule_t mol;
8128 tng_bool found = TNG_FALSE;
8130 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8131 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8133 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8135 if(!molecule_cnt_list)
8137 return(TNG_FAILURE);
8140 for(i = 0; i < tng_data->n_molecules; i++)
8142 mol = &tng_data->molecules[i];
8143 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8145 cnt += mol->n_atoms * molecule_cnt_list[i];
8146 continue;
8148 found = TNG_TRUE;
8149 break;
8151 if(!found)
8153 return(TNG_FAILURE);
8156 strncpy(name, mol->name, max_len - 1);
8157 name[max_len - 1] = 0;
8159 if(strlen(mol->name) > (unsigned int)max_len - 1)
8161 return(TNG_FAILURE);
8163 return(TNG_SUCCESS);
8166 tng_function_status DECLSPECDLLEXPORT tng_molecule_id_of_particle_nr_get
8167 (const tng_trajectory_t tng_data,
8168 const int64_t nr,
8169 int64_t *id)
8171 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8172 tng_molecule_t mol;
8173 tng_bool found = TNG_FALSE;
8175 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8176 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
8178 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8180 if(!molecule_cnt_list)
8182 return(TNG_FAILURE);
8185 for(i = 0; i < tng_data->n_molecules; i++)
8187 mol = &tng_data->molecules[i];
8188 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8190 cnt += mol->n_atoms * molecule_cnt_list[i];
8191 continue;
8193 found = TNG_TRUE;
8194 break;
8196 if(!found)
8198 return(TNG_FAILURE);
8201 *id = mol->id;
8203 return(TNG_SUCCESS);
8206 tng_function_status DECLSPECDLLEXPORT tng_molsystem_bonds_get
8207 (const tng_trajectory_t tng_data,
8208 int64_t *n_bonds,
8209 int64_t **from_atoms,
8210 int64_t **to_atoms)
8212 int64_t atom_cnt = 0, cnt, mol_cnt, i, j, k;
8213 int64_t from_atom, to_atom, *molecule_cnt_list = 0;
8214 tng_molecule_t mol;
8215 tng_bond_t bond;
8217 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8218 TNG_ASSERT(n_bonds, "TNG library: n_bonds must not be a NULL pointer.");
8219 TNG_ASSERT(from_atoms, "TNG library: from_atoms must not be a NULL pointer.");
8220 TNG_ASSERT(to_atoms, "TNG library: to_atoms must not be a NULL pointer.");
8222 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8224 if(!molecule_cnt_list)
8226 return(TNG_FAILURE);
8229 *n_bonds = 0;
8230 /* First count the total number of bonds to allocate memory */
8231 for(i = 0; i < tng_data->n_molecules; i++)
8233 mol = &tng_data->molecules[i];
8234 mol_cnt = molecule_cnt_list[i];
8235 *n_bonds += mol_cnt * mol->n_bonds;
8237 if(*n_bonds == 0)
8239 return(TNG_SUCCESS);
8242 *from_atoms = (int64_t *)malloc(sizeof(int64_t) * (*n_bonds));
8243 if(!*from_atoms)
8245 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
8246 __FILE__, __LINE__);
8247 return(TNG_CRITICAL);
8249 *to_atoms = (int64_t *)malloc(sizeof(int64_t) * (*n_bonds));
8250 if(!*to_atoms)
8252 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
8253 __FILE__, __LINE__);
8254 free(*from_atoms);
8255 *from_atoms = 0;
8256 return(TNG_CRITICAL);
8259 cnt = 0;
8260 for(i = 0; i < tng_data->n_molecules; i++)
8262 mol = &tng_data->molecules[i];
8263 mol_cnt = molecule_cnt_list[i];
8264 for(j = 0; j < mol_cnt; j++)
8266 for(k = 0; k < mol->n_bonds; k++)
8268 bond = &mol->bonds[k];
8269 from_atom = atom_cnt + bond->from_atom_id;
8270 to_atom = atom_cnt + bond->to_atom_id;
8271 (*from_atoms)[cnt] = from_atom;
8272 (*to_atoms)[cnt++] = to_atom;
8274 atom_cnt += mol->n_atoms;
8278 return(TNG_SUCCESS);
8281 tng_function_status DECLSPECDLLEXPORT tng_chain_name_of_particle_nr_get
8282 (const tng_trajectory_t tng_data,
8283 const int64_t nr,
8284 char *name,
8285 const int max_len)
8287 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8288 tng_molecule_t mol;
8289 tng_atom_t atom;
8290 tng_bool found = TNG_FALSE;
8292 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8293 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8295 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8297 if(!molecule_cnt_list)
8299 return(TNG_FAILURE);
8302 for(i = 0; i < tng_data->n_molecules; i++)
8304 mol = &tng_data->molecules[i];
8305 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8307 cnt += mol->n_atoms * molecule_cnt_list[i];
8308 continue;
8310 atom = &mol->atoms[nr % mol->n_atoms];
8311 found = TNG_TRUE;
8312 break;
8314 if(!found)
8316 return(TNG_FAILURE);
8318 if(!atom->residue || !atom->residue->chain)
8320 return(TNG_FAILURE);
8323 strncpy(name, atom->residue->chain->name, max_len - 1);
8324 name[max_len - 1] = 0;
8326 if(strlen(atom->residue->chain->name) > (unsigned int)max_len - 1)
8328 return(TNG_FAILURE);
8330 return(TNG_SUCCESS);
8333 tng_function_status DECLSPECDLLEXPORT tng_residue_name_of_particle_nr_get
8334 (const tng_trajectory_t tng_data,
8335 const int64_t nr,
8336 char *name,
8337 const int max_len)
8339 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8340 tng_molecule_t mol;
8341 tng_atom_t atom;
8342 tng_bool found = TNG_FALSE;
8344 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8345 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8347 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8349 if(!molecule_cnt_list)
8351 return(TNG_FAILURE);
8354 for(i = 0; i < tng_data->n_molecules; i++)
8356 mol = &tng_data->molecules[i];
8357 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8359 cnt += mol->n_atoms * molecule_cnt_list[i];
8360 continue;
8362 atom = &mol->atoms[nr % mol->n_atoms];
8363 found = TNG_TRUE;
8364 break;
8366 if(!found)
8368 return(TNG_FAILURE);
8370 if(!atom->residue)
8372 return(TNG_FAILURE);
8375 strncpy(name, atom->residue->name, max_len - 1);
8376 name[max_len - 1] = 0;
8378 if(strlen(atom->residue->name) > (unsigned int)max_len - 1)
8380 return(TNG_FAILURE);
8382 return(TNG_SUCCESS);
8385 tng_function_status DECLSPECDLLEXPORT tng_residue_id_of_particle_nr_get
8386 (const tng_trajectory_t tng_data,
8387 const int64_t nr,
8388 int64_t *id)
8390 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8391 tng_molecule_t mol;
8392 tng_atom_t atom;
8393 tng_bool found = TNG_FALSE;
8395 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8396 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
8398 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8400 if(!molecule_cnt_list)
8402 return(TNG_FAILURE);
8405 for(i = 0; i < tng_data->n_molecules; i++)
8407 mol = &tng_data->molecules[i];
8408 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8410 cnt += mol->n_atoms * molecule_cnt_list[i];
8411 continue;
8413 atom = &mol->atoms[nr % mol->n_atoms];
8414 found = TNG_TRUE;
8415 break;
8417 if(!found)
8419 return(TNG_FAILURE);
8421 if(!atom->residue)
8423 return(TNG_FAILURE);
8426 *id = atom->residue->id;
8428 return(TNG_SUCCESS);
8431 tng_function_status DECLSPECDLLEXPORT tng_global_residue_id_of_particle_nr_get
8432 (const tng_trajectory_t tng_data,
8433 const int64_t nr,
8434 int64_t *id)
8436 int64_t cnt = 0, i, offset = 0, *molecule_cnt_list = 0;
8437 tng_molecule_t mol;
8438 tng_atom_t atom;
8439 tng_bool found = TNG_FALSE;
8441 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8442 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
8444 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8446 if(!molecule_cnt_list)
8448 return(TNG_FAILURE);
8451 for(i = 0; i < tng_data->n_molecules; i++)
8453 mol = &tng_data->molecules[i];
8454 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8456 cnt += mol->n_atoms * molecule_cnt_list[i];
8457 offset += mol->n_residues * molecule_cnt_list[i];
8458 continue;
8460 atom = &mol->atoms[nr % mol->n_atoms];
8461 found = TNG_TRUE;
8462 break;
8464 if(!found)
8466 return(TNG_FAILURE);
8468 if(!atom->residue)
8470 return(TNG_FAILURE);
8473 offset += mol->n_residues * ((nr - cnt) / mol->n_atoms);
8475 *id = atom->residue->id + offset;
8477 return(TNG_SUCCESS);
8480 tng_function_status DECLSPECDLLEXPORT tng_atom_name_of_particle_nr_get
8481 (const tng_trajectory_t tng_data,
8482 const int64_t nr,
8483 char *name,
8484 const int max_len)
8486 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8487 tng_molecule_t mol;
8488 tng_atom_t atom;
8489 tng_bool found = TNG_FALSE;
8491 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8492 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8494 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8496 if(!molecule_cnt_list)
8498 return(TNG_FAILURE);
8501 for(i = 0; i < tng_data->n_molecules; i++)
8503 mol = &tng_data->molecules[i];
8504 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8506 cnt += mol->n_atoms * molecule_cnt_list[i];
8507 continue;
8509 atom = &mol->atoms[nr % mol->n_atoms];
8510 found = TNG_TRUE;
8511 break;
8513 if(!found)
8515 return(TNG_FAILURE);
8518 strncpy(name, atom->name, max_len - 1);
8519 name[max_len - 1] = 0;
8521 if(strlen(atom->name) > (unsigned int)max_len - 1)
8523 return(TNG_FAILURE);
8525 return(TNG_SUCCESS);
8528 tng_function_status tng_atom_type_of_particle_nr_get
8529 (const tng_trajectory_t tng_data,
8530 const int64_t nr,
8531 char *type,
8532 const int max_len)
8534 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8535 tng_molecule_t mol;
8536 tng_atom_t atom;
8537 tng_bool found = TNG_FALSE;
8539 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8540 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
8542 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8544 if(!molecule_cnt_list)
8546 return(TNG_FAILURE);
8549 for(i = 0; i < tng_data->n_molecules; i++)
8551 mol = &tng_data->molecules[i];
8552 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8554 cnt += mol->n_atoms * molecule_cnt_list[i];
8555 continue;
8557 atom = &mol->atoms[nr % mol->n_atoms];
8558 found = TNG_TRUE;
8559 break;
8561 if(!found)
8563 return(TNG_FAILURE);
8566 strncpy(type, atom->atom_type, max_len - 1);
8567 type[max_len - 1] = 0;
8569 if(strlen(atom->atom_type) > (unsigned int)max_len - 1)
8571 return(TNG_FAILURE);
8573 return(TNG_SUCCESS);
8576 tng_function_status DECLSPECDLLEXPORT tng_particle_mapping_add
8577 (const tng_trajectory_t tng_data,
8578 const int64_t num_first_particle,
8579 const int64_t n_particles,
8580 const int64_t *mapping_table)
8582 int64_t i;
8583 tng_particle_mapping_t mapping;
8584 tng_trajectory_frame_set_t frame_set;
8586 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8588 frame_set = &tng_data->current_trajectory_frame_set;
8590 /* Sanity check of the particle ranges. Split into multiple if
8591 * statements for improved readability */
8592 for(i = 0; i < frame_set->n_mapping_blocks; i++)
8594 mapping = &frame_set->mappings[i];
8595 if(num_first_particle >= mapping->num_first_particle &&
8596 num_first_particle < mapping->num_first_particle +
8597 mapping->n_particles)
8599 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
8600 return(TNG_FAILURE);
8602 if(num_first_particle + n_particles >=
8603 mapping->num_first_particle &&
8604 num_first_particle + n_particles <
8605 mapping->num_first_particle + mapping->n_particles)
8607 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
8608 return(TNG_FAILURE);
8610 if(mapping->num_first_particle >= num_first_particle &&
8611 mapping->num_first_particle < num_first_particle +
8612 n_particles)
8614 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
8615 return(TNG_FAILURE);
8617 if(mapping->num_first_particle + mapping->n_particles >
8618 num_first_particle &&
8619 mapping->num_first_particle + mapping->n_particles <
8620 num_first_particle + n_particles)
8622 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
8623 return(TNG_FAILURE);
8627 frame_set->n_mapping_blocks++;
8629 mapping = (tng_particle_mapping_t)realloc(frame_set->mappings, sizeof(struct tng_particle_mapping) *
8630 frame_set->n_mapping_blocks);
8632 if(!mapping)
8634 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
8635 __FILE__, __LINE__);
8636 free(frame_set->mappings);
8637 frame_set->mappings = 0;
8638 return(TNG_CRITICAL);
8640 frame_set->mappings = mapping;
8642 frame_set->mappings[frame_set->n_mapping_blocks - 1].num_first_particle = num_first_particle;
8643 frame_set->mappings[frame_set->n_mapping_blocks - 1].n_particles = n_particles;
8645 frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers = (int64_t *)malloc(sizeof(int64_t) * n_particles);
8646 if(!frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers)
8648 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
8649 __FILE__, __LINE__);
8650 return(TNG_CRITICAL);
8653 for(i=0; i<n_particles; i++)
8655 frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers[i] = mapping_table[i];
8658 return(TNG_SUCCESS);
8661 tng_function_status DECLSPECDLLEXPORT tng_frame_set_particle_mapping_free(const tng_trajectory_t tng_data)
8663 tng_trajectory_frame_set_t frame_set;
8664 tng_particle_mapping_t mapping;
8665 int64_t i;
8667 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8669 frame_set = &tng_data->current_trajectory_frame_set;
8671 if(frame_set->n_mapping_blocks && frame_set->mappings)
8673 for(i = 0; i < frame_set->n_mapping_blocks; i++)
8675 mapping = &frame_set->mappings[i];
8676 if(mapping->real_particle_numbers)
8678 free(mapping->real_particle_numbers);
8679 mapping->real_particle_numbers = 0;
8682 free(frame_set->mappings);
8683 frame_set->mappings = 0;
8684 frame_set->n_mapping_blocks = 0;
8687 return(TNG_SUCCESS);
8690 tng_function_status DECLSPECDLLEXPORT tng_trajectory_init(tng_trajectory_t *tng_data_p)
8692 time_t seconds;
8693 tng_trajectory_frame_set_t frame_set;
8694 tng_trajectory_t tng_data;
8696 *tng_data_p = (tng_trajectory_t)malloc(sizeof(struct tng_trajectory));
8697 if(!*tng_data_p)
8699 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
8700 __FILE__, __LINE__);
8701 return(TNG_CRITICAL);
8704 tng_data = *tng_data_p;
8706 frame_set = &tng_data->current_trajectory_frame_set;
8708 tng_data->input_file_path = 0;
8709 tng_data->input_file = 0;
8710 tng_data->input_file_len = 0;
8711 tng_data->output_file_path = 0;
8712 tng_data->output_file = 0;
8714 tng_data->first_program_name = 0;
8715 tng_data->first_user_name = 0;
8716 tng_data->first_computer_name = 0;
8717 tng_data->first_pgp_signature = 0;
8718 tng_data->last_program_name = 0;
8719 tng_data->last_user_name = 0;
8720 tng_data->last_computer_name = 0;
8721 tng_data->last_pgp_signature = 0;
8722 tng_data->forcefield_name = 0;
8724 seconds = time(0);
8725 if ( seconds == -1)
8727 fprintf(stderr, "TNG library: Cannot get time. %s: %d\n", __FILE__, __LINE__);
8729 else
8731 tng_data->time = seconds;
8734 tng_data->var_num_atoms_flag = TNG_CONSTANT_N_ATOMS;
8735 tng_data->first_trajectory_frame_set_input_file_pos = -1;
8736 tng_data->last_trajectory_frame_set_input_file_pos = -1;
8737 tng_data->current_trajectory_frame_set_input_file_pos = -1;
8738 tng_data->first_trajectory_frame_set_output_file_pos = -1;
8739 tng_data->last_trajectory_frame_set_output_file_pos = -1;
8740 tng_data->current_trajectory_frame_set_output_file_pos = -1;
8741 tng_data->frame_set_n_frames = 100;
8742 tng_data->n_trajectory_frame_sets = 0;
8743 tng_data->medium_stride_length = 100;
8744 tng_data->long_stride_length = 10000;
8746 tng_data->time_per_frame = -1;
8748 tng_data->n_particle_data_blocks = 0;
8749 tng_data->n_data_blocks = 0;
8751 tng_data->non_tr_particle_data = 0;
8752 tng_data->non_tr_data = 0;
8754 tng_data->compress_algo_pos = 0;
8755 tng_data->compress_algo_vel = 0;
8756 tng_data->compression_precision = 1000;
8757 tng_data->distance_unit_exponential = -9;
8759 frame_set->first_frame = -1;
8760 frame_set->n_mapping_blocks = 0;
8761 frame_set->mappings = 0;
8762 frame_set->molecule_cnt_list = 0;
8764 frame_set->n_particle_data_blocks = 0;
8765 frame_set->n_data_blocks = 0;
8767 frame_set->tr_particle_data = 0;
8768 frame_set->tr_data = 0;
8770 frame_set->n_written_frames = 0;
8771 frame_set->n_unwritten_frames = 0;
8773 frame_set->next_frame_set_file_pos = -1;
8774 frame_set->prev_frame_set_file_pos = -1;
8775 frame_set->medium_stride_next_frame_set_file_pos = -1;
8776 frame_set->medium_stride_prev_frame_set_file_pos = -1;
8777 frame_set->long_stride_next_frame_set_file_pos = -1;
8778 frame_set->long_stride_prev_frame_set_file_pos = -1;
8780 frame_set->first_frame_time = -1;
8782 tng_data->n_molecules = 0;
8783 tng_data->molecules = 0;
8784 tng_data->molecule_cnt_list = 0;
8785 tng_data->n_particles = 0;
8788 /* Check the endianness of the computer */
8789 static int32_t endianness_32 = 0x01234567;
8790 /* 0x01234567 */
8791 if ( *(const unsigned char*)&endianness_32 == 0x01 )
8793 tng_data->endianness_32 = TNG_BIG_ENDIAN_32;
8796 /* 0x67452301 */
8797 else if( *(const unsigned char*)&endianness_32 == 0x67 )
8799 tng_data->endianness_32 = TNG_LITTLE_ENDIAN_32;
8803 /* 0x45670123 */
8804 else if ( *(const unsigned char*)&endianness_32 == 0x45 )
8806 tng_data->endianness_32 = TNG_BYTE_PAIR_SWAP_32;
8810 static int64_t endianness_64 = 0x0123456789ABCDEFLL;
8811 /* 0x0123456789ABCDEF */
8812 if ( *(const unsigned char*)&endianness_64 == 0x01 )
8814 tng_data->endianness_64 = TNG_BIG_ENDIAN_64;
8817 /* 0xEFCDAB8967452301 */
8818 else if ( *(const unsigned char*)&endianness_64 == 0xEF )
8820 tng_data->endianness_64 = TNG_LITTLE_ENDIAN_64;
8823 /* 0x89ABCDEF01234567 */
8824 else if ( *(const unsigned char*)&endianness_64 == 0x89 )
8826 tng_data->endianness_64 = TNG_QUAD_SWAP_64;
8829 /* 0x45670123CDEF89AB */
8830 else if ( *(const unsigned char*)&endianness_64 == 0x45 )
8832 tng_data->endianness_64 = TNG_BYTE_PAIR_SWAP_64;
8835 /* 0x23016745AB89EFCD */
8836 else if ( *(const unsigned char*)&endianness_64 == 0x23 )
8838 tng_data->endianness_64 = TNG_BYTE_SWAP_64;
8842 /* By default do not swap the byte order, i.e. keep the byte order of the
8843 * architecture. The input file endianness will be set when reading the
8844 * header. The output endianness can be changed - before the file is
8845 * written. */
8846 tng_data->input_endianness_swap_func_32 = 0;
8847 tng_data->input_endianness_swap_func_64 = 0;
8848 tng_data->output_endianness_swap_func_32 = 0;
8849 tng_data->output_endianness_swap_func_64 = 0;
8851 tng_data->current_trajectory_frame_set.next_frame_set_file_pos = -1;
8852 tng_data->current_trajectory_frame_set.prev_frame_set_file_pos = -1;
8853 tng_data->current_trajectory_frame_set.n_frames = 0;
8855 return(TNG_SUCCESS);
8858 tng_function_status DECLSPECDLLEXPORT tng_trajectory_destroy(tng_trajectory_t *tng_data_p)
8860 int64_t i, j, k, l;
8861 int64_t n_particles, n_values_per_frame;
8862 tng_trajectory_t tng_data = *tng_data_p;
8863 tng_trajectory_frame_set_t frame_set;
8865 if(!*tng_data_p)
8867 return(TNG_SUCCESS);
8870 frame_set = &tng_data->current_trajectory_frame_set;
8872 if(tng_data->input_file)
8874 if(tng_data->output_file == tng_data->input_file)
8876 tng_frame_set_finalize(tng_data, TNG_USE_HASH);
8877 tng_data->output_file = 0;
8879 fclose(tng_data->input_file);
8880 tng_data->input_file = 0;
8883 if(tng_data->input_file_path)
8885 free(tng_data->input_file_path);
8886 tng_data->input_file_path = 0;
8889 if(tng_data->output_file)
8891 /* FIXME: Do not always write the hash */
8892 tng_frame_set_finalize(tng_data, TNG_USE_HASH);
8893 fclose(tng_data->output_file);
8894 tng_data->output_file = 0;
8897 if(tng_data->output_file_path)
8899 free(tng_data->output_file_path);
8900 tng_data->output_file_path = 0;
8903 if(tng_data->first_program_name)
8905 free(tng_data->first_program_name);
8906 tng_data->first_program_name = 0;
8909 if(tng_data->last_program_name)
8911 free(tng_data->last_program_name);
8912 tng_data->last_program_name = 0;
8915 if(tng_data->first_user_name)
8917 free(tng_data->first_user_name);
8918 tng_data->first_user_name = 0;
8921 if(tng_data->last_user_name)
8923 free(tng_data->last_user_name);
8924 tng_data->last_user_name = 0;
8927 if(tng_data->first_computer_name)
8929 free(tng_data->first_computer_name);
8930 tng_data->first_computer_name = 0;
8933 if(tng_data->last_computer_name)
8935 free(tng_data->last_computer_name);
8936 tng_data->last_computer_name = 0;
8939 if(tng_data->first_pgp_signature)
8941 free(tng_data->first_pgp_signature);
8942 tng_data->first_pgp_signature = 0;
8945 if(tng_data->last_pgp_signature)
8947 free(tng_data->last_pgp_signature);
8948 tng_data->last_pgp_signature = 0;
8951 if(tng_data->forcefield_name)
8953 free(tng_data->forcefield_name);
8954 tng_data->forcefield_name = 0;
8957 tng_frame_set_particle_mapping_free(tng_data);
8959 if(frame_set->molecule_cnt_list)
8961 free(frame_set->molecule_cnt_list);
8962 frame_set->molecule_cnt_list = 0;
8965 if(tng_data->var_num_atoms_flag)
8967 n_particles = frame_set->n_particles;
8969 else
8971 n_particles = tng_data->n_particles;
8974 if(tng_data->non_tr_particle_data)
8976 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
8978 if(tng_data->non_tr_particle_data[i].values)
8980 free(tng_data->non_tr_particle_data[i].values);
8981 tng_data->non_tr_particle_data[i].values = 0;
8984 if(tng_data->non_tr_particle_data[i].strings)
8986 n_values_per_frame = tng_data->non_tr_particle_data[i].
8987 n_values_per_frame;
8988 if(tng_data->non_tr_particle_data[i].strings[0])
8990 for(j = 0; j < n_particles; j++)
8992 if(tng_data->non_tr_particle_data[i].strings[0][j])
8994 for(k = 0; k < n_values_per_frame; k++)
8996 if(tng_data->non_tr_particle_data[i].
8997 strings[0][j][k])
8999 free(tng_data->non_tr_particle_data[i].
9000 strings[0][j][k]);
9001 tng_data->non_tr_particle_data[i].
9002 strings[0][j][k] = 0;
9005 free(tng_data->non_tr_particle_data[i].
9006 strings[0][j]);
9007 tng_data->non_tr_particle_data[i].strings[0][j] = 0;
9010 free(tng_data->non_tr_particle_data[i].strings[0]);
9011 tng_data->non_tr_particle_data[i].strings[0] = 0;
9013 free(tng_data->non_tr_particle_data[i].strings);
9014 tng_data->non_tr_particle_data[i].strings = 0;
9017 if(tng_data->non_tr_particle_data[i].block_name)
9019 free(tng_data->non_tr_particle_data[i].block_name);
9020 tng_data->non_tr_particle_data[i].block_name = 0;
9023 free(tng_data->non_tr_particle_data);
9024 tng_data->non_tr_particle_data = 0;
9027 if(tng_data->non_tr_data)
9029 for(i = 0; i < tng_data->n_data_blocks; i++)
9031 if(tng_data->non_tr_data[i].values)
9033 free(tng_data->non_tr_data[i].values);
9034 tng_data->non_tr_data[i].values = 0;
9037 if(tng_data->non_tr_data[i].strings)
9039 n_values_per_frame = tng_data->non_tr_data[i].
9040 n_values_per_frame;
9041 if(tng_data->non_tr_data[i].strings[0][0])
9043 for(j = 0; j < n_values_per_frame; j++)
9045 if(tng_data->non_tr_data[i].strings[0][0][j])
9047 free(tng_data->non_tr_data[i].strings[0][0][j]);
9048 tng_data->non_tr_data[i].strings[0][0][j] = 0;
9051 free(tng_data->non_tr_data[i].strings[0][0]);
9052 tng_data->non_tr_data[i].strings[0][0] = 0;
9054 free(tng_data->non_tr_data[i].strings[0]);
9055 tng_data->non_tr_data[i].strings[0] = 0;
9056 free(tng_data->non_tr_data[i].strings);
9057 tng_data->non_tr_data[i].strings = 0;
9060 if(tng_data->non_tr_data[i].block_name)
9062 free(tng_data->non_tr_data[i].block_name);
9063 tng_data->non_tr_data[i].block_name = 0;
9066 free(tng_data->non_tr_data);
9067 tng_data->non_tr_data = 0;
9070 tng_data->n_particle_data_blocks = 0;
9071 tng_data->n_data_blocks = 0;
9073 if(tng_data->compress_algo_pos)
9075 free(tng_data->compress_algo_pos);
9076 tng_data->compress_algo_pos = 0;
9078 if(tng_data->compress_algo_vel)
9080 free(tng_data->compress_algo_vel);
9081 tng_data->compress_algo_vel = 0;
9084 if(frame_set->tr_particle_data)
9086 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
9088 if(frame_set->tr_particle_data[i].values)
9090 free(frame_set->tr_particle_data[i].values);
9091 frame_set->tr_particle_data[i].values = 0;
9094 if(frame_set->tr_particle_data[i].strings)
9096 n_values_per_frame = frame_set->tr_particle_data[i].
9097 n_values_per_frame;
9098 for(j = 0; j < frame_set->tr_particle_data[i].n_frames; j++)
9100 if(frame_set->tr_particle_data[i].strings[j])
9102 for(k = 0; k < n_particles; k++)
9104 if(frame_set->tr_particle_data[i].
9105 strings[j][k])
9107 for(l = 0; l < n_values_per_frame; l++)
9109 if(frame_set->tr_particle_data[i].
9110 strings[j][k][l])
9112 free(frame_set->tr_particle_data[i].
9113 strings[j][k][l]);
9114 frame_set->tr_particle_data[i].
9115 strings[j][k][l] = 0;
9118 free(frame_set->tr_particle_data[i].
9119 strings[j][k]);
9120 frame_set->tr_particle_data[i].
9121 strings[j][k] = 0;
9124 free(frame_set->tr_particle_data[i].strings[j]);
9125 frame_set->tr_particle_data[i].strings[j] = 0;
9128 free(frame_set->tr_particle_data[i].strings);
9129 frame_set->tr_particle_data[i].strings = 0;
9132 if(frame_set->tr_particle_data[i].block_name)
9134 free(frame_set->tr_particle_data[i].block_name);
9135 frame_set->tr_particle_data[i].block_name = 0;
9138 free(frame_set->tr_particle_data);
9139 frame_set->tr_particle_data = 0;
9142 if(frame_set->tr_data)
9144 for(i = 0; i < frame_set->n_data_blocks; i++)
9146 if(frame_set->tr_data[i].values)
9148 free(frame_set->tr_data[i].values);
9149 frame_set->tr_data[i].values = 0;
9152 if(frame_set->tr_data[i].strings)
9154 n_values_per_frame = frame_set->tr_data[i].
9155 n_values_per_frame;
9156 for(j = 0; j < frame_set->tr_data[i].n_frames; j++)
9158 if(frame_set->tr_data[i].strings[j])
9160 for(k = 0; k < n_values_per_frame; k++)
9162 if(frame_set->tr_data[i].strings[j][k])
9164 free(frame_set->tr_data[i].strings[j][k]);
9165 frame_set->tr_data[i].strings[j][k] = 0;
9168 free(frame_set->tr_data[i].strings[j]);
9169 frame_set->tr_data[i].strings[j] = 0;
9172 free(frame_set->tr_data[i].strings);
9173 frame_set->tr_data[i].strings = 0;
9176 if(frame_set->tr_data[i].block_name)
9178 free(frame_set->tr_data[i].block_name);
9179 frame_set->tr_data[i].block_name = 0;
9182 free(frame_set->tr_data);
9183 frame_set->tr_data = 0;
9186 frame_set->n_particle_data_blocks = 0;
9187 frame_set->n_data_blocks = 0;
9189 if(tng_data->molecules)
9191 for(i = 0; i < tng_data->n_molecules; i++)
9193 tng_molecule_destroy(tng_data, &tng_data->molecules[i]);
9195 free(tng_data->molecules);
9196 tng_data->molecules = 0;
9197 tng_data->n_molecules = 0;
9199 if(tng_data->molecule_cnt_list)
9201 free(tng_data->molecule_cnt_list);
9202 tng_data->molecule_cnt_list = 0;
9205 free(*tng_data_p);
9206 *tng_data_p = 0;
9208 return(TNG_SUCCESS);
9211 tng_function_status DECLSPECDLLEXPORT tng_trajectory_init_from_src
9212 (const tng_trajectory_t src,
9213 tng_trajectory_t *dest_p)
9215 tng_trajectory_frame_set_t frame_set;
9216 tng_trajectory_t dest;
9218 TNG_ASSERT(src != 0, "TNG library: Source trajectory must not be NULL.");
9220 *dest_p = (tng_trajectory_t)malloc(sizeof(struct tng_trajectory));
9221 if(!*dest_p)
9223 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
9224 __FILE__, __LINE__);
9225 return(TNG_CRITICAL);
9228 dest = *dest_p;
9230 frame_set = &dest->current_trajectory_frame_set;
9232 if(src->input_file_path)
9234 dest->input_file_path = (char *)malloc(strlen(src->input_file_path) + 1);
9235 if(!dest->input_file_path)
9237 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
9238 __FILE__, __LINE__);
9239 return(TNG_CRITICAL);
9241 strcpy(dest->input_file_path, src->input_file_path);
9242 dest->input_file_len = src->input_file_len;
9244 else
9246 dest->input_file_path = 0;
9248 dest->input_file = 0;
9249 if(src->output_file_path)
9251 dest->output_file_path = (char *)malloc(strlen(src->output_file_path) + 1);
9252 if(!dest->output_file_path)
9254 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
9255 __FILE__, __LINE__);
9256 return(TNG_CRITICAL);
9258 strcpy(dest->output_file_path, src->output_file_path);
9260 else
9262 dest->output_file_path = 0;
9264 dest->output_file = 0;
9266 dest->first_program_name = 0;
9267 dest->first_user_name = 0;
9268 dest->first_computer_name = 0;
9269 dest->first_pgp_signature = 0;
9270 dest->last_program_name = 0;
9271 dest->last_user_name = 0;
9272 dest->last_computer_name = 0;
9273 dest->last_pgp_signature = 0;
9274 dest->forcefield_name = 0;
9276 dest->var_num_atoms_flag = src->var_num_atoms_flag;
9277 dest->first_trajectory_frame_set_input_file_pos =
9278 src->first_trajectory_frame_set_input_file_pos;
9279 dest->last_trajectory_frame_set_input_file_pos =
9280 src->last_trajectory_frame_set_input_file_pos;
9281 dest->current_trajectory_frame_set_input_file_pos =
9282 src->current_trajectory_frame_set_input_file_pos;
9283 dest->first_trajectory_frame_set_output_file_pos =
9284 src->first_trajectory_frame_set_output_file_pos;
9285 dest->last_trajectory_frame_set_output_file_pos =
9286 src->last_trajectory_frame_set_output_file_pos;
9287 dest->current_trajectory_frame_set_output_file_pos =
9288 src->current_trajectory_frame_set_output_file_pos;
9289 dest->frame_set_n_frames = src->frame_set_n_frames;
9290 dest->n_trajectory_frame_sets = src->n_trajectory_frame_sets;
9291 dest->medium_stride_length = src->medium_stride_length;
9292 dest->long_stride_length = src->long_stride_length;
9294 dest->time_per_frame = src->time_per_frame;
9296 /* Currently the non trajectory data blocks are not copied since it
9297 * can lead to problems when freeing memory in a parallel block. */
9298 dest->n_particle_data_blocks = 0;
9299 dest->n_data_blocks = 0;
9300 dest->non_tr_particle_data = 0;
9301 dest->non_tr_data = 0;
9303 dest->compress_algo_pos = 0;
9304 dest->compress_algo_vel = 0;
9305 dest->distance_unit_exponential = -9;
9306 dest->compression_precision = 1000;
9308 frame_set->n_mapping_blocks = 0;
9309 frame_set->mappings = 0;
9310 frame_set->molecule_cnt_list = 0;
9312 frame_set->n_particle_data_blocks = 0;
9313 frame_set->n_data_blocks = 0;
9315 frame_set->tr_particle_data = 0;
9316 frame_set->tr_data = 0;
9318 frame_set->n_written_frames = 0;
9319 frame_set->n_unwritten_frames = 0;
9321 frame_set->next_frame_set_file_pos = -1;
9322 frame_set->prev_frame_set_file_pos = -1;
9323 frame_set->medium_stride_next_frame_set_file_pos = -1;
9324 frame_set->medium_stride_prev_frame_set_file_pos = -1;
9325 frame_set->long_stride_next_frame_set_file_pos = -1;
9326 frame_set->long_stride_prev_frame_set_file_pos = -1;
9327 frame_set->first_frame = -1;
9329 dest->n_molecules = 0;
9330 dest->molecules = 0;
9331 dest->molecule_cnt_list = 0;
9332 dest->n_particles = src->n_particles;
9334 dest->endianness_32 = src->endianness_32;
9335 dest->endianness_64 = src->endianness_64;
9336 dest->input_endianness_swap_func_32 = src->input_endianness_swap_func_32;
9337 dest->input_endianness_swap_func_64 = src->input_endianness_swap_func_64;
9338 dest->output_endianness_swap_func_32 = src->output_endianness_swap_func_32;
9339 dest->output_endianness_swap_func_64 = src->output_endianness_swap_func_64;
9341 dest->current_trajectory_frame_set.next_frame_set_file_pos = -1;
9342 dest->current_trajectory_frame_set.prev_frame_set_file_pos = -1;
9343 dest->current_trajectory_frame_set.n_frames = 0;
9345 return(TNG_SUCCESS);
9348 tng_function_status DECLSPECDLLEXPORT tng_input_file_get
9349 (const tng_trajectory_t tng_data,
9350 char *file_name,
9351 const int max_len)
9353 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9354 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
9356 strncpy(file_name, tng_data->input_file_path, max_len - 1);
9357 file_name[max_len - 1] = 0;
9359 if(strlen(tng_data->input_file_path) > (unsigned int)max_len - 1)
9361 return(TNG_FAILURE);
9363 return(TNG_SUCCESS);
9366 tng_function_status DECLSPECDLLEXPORT tng_input_file_set
9367 (const tng_trajectory_t tng_data,
9368 const char *file_name)
9370 unsigned int len;
9371 char *temp;
9373 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9374 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
9377 if(tng_data->input_file_path && strcmp(tng_data->input_file_path,
9378 file_name) == 0)
9380 return(TNG_SUCCESS);
9383 if(tng_data->input_file)
9385 fclose(tng_data->input_file);
9388 len = tng_min_size(strlen(file_name) + 1, TNG_MAX_STR_LEN);
9389 temp = (char *)realloc(tng_data->input_file_path, len);
9390 if(!temp)
9392 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
9393 __FILE__, __LINE__);
9394 free(tng_data->input_file_path);
9395 tng_data->input_file_path = 0;
9396 return(TNG_CRITICAL);
9398 tng_data->input_file_path = temp;
9400 strncpy(tng_data->input_file_path, file_name, len);
9402 return(tng_input_file_init(tng_data));
9405 tng_function_status tng_output_file_get
9406 (const tng_trajectory_t tng_data,
9407 char *file_name,
9408 const int max_len)
9410 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9411 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
9413 strncpy(file_name, tng_data->output_file_path, max_len - 1);
9414 file_name[max_len - 1] = 0;
9416 if(strlen(tng_data->output_file_path) > (unsigned int)max_len - 1)
9418 return(TNG_FAILURE);
9420 return(TNG_SUCCESS);
9423 tng_function_status DECLSPECDLLEXPORT tng_output_file_set
9424 (const tng_trajectory_t tng_data,
9425 const char *file_name)
9427 int len;
9428 char *temp;
9430 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9431 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
9433 if(tng_data->output_file_path &&
9434 strcmp(tng_data->output_file_path, file_name) == 0)
9436 return(TNG_SUCCESS);
9439 if(tng_data->output_file)
9441 fclose(tng_data->output_file);
9444 len = tng_min_size(strlen(file_name) + 1, TNG_MAX_STR_LEN);
9445 temp = (char *)realloc(tng_data->output_file_path, len);
9446 if(!temp)
9448 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
9449 __FILE__, __LINE__);
9450 free(tng_data->output_file_path);
9451 tng_data->output_file_path = 0;
9452 return(TNG_CRITICAL);
9454 tng_data->output_file_path = temp;
9456 strncpy(tng_data->output_file_path, file_name, len);
9458 return(tng_output_file_init(tng_data));
9461 tng_function_status DECLSPECDLLEXPORT tng_output_append_file_set
9462 (const tng_trajectory_t tng_data,
9463 const char *file_name)
9465 int len;
9466 char *temp;
9468 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9469 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
9471 if(tng_data->output_file_path &&
9472 strcmp(tng_data->output_file_path, file_name) == 0)
9474 return(TNG_SUCCESS);
9477 if(tng_data->output_file)
9479 fclose(tng_data->output_file);
9482 len = tng_min_size(strlen(file_name) + 1, TNG_MAX_STR_LEN);
9483 temp = (char *)realloc(tng_data->output_file_path, len);
9484 if(!temp)
9486 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
9487 __FILE__, __LINE__);
9488 free(tng_data->output_file_path);
9489 tng_data->output_file_path = 0;
9490 return(TNG_CRITICAL);
9492 tng_data->output_file_path = temp;
9494 strncpy(tng_data->output_file_path, file_name, len);
9496 tng_data->output_file = fopen(tng_data->output_file_path, "rb+");
9497 if(!tng_data->output_file)
9499 fprintf(stderr, "TNG library: Cannot open file %s. %s: %d\n",
9500 tng_data->output_file_path, __FILE__, __LINE__);
9501 return(TNG_CRITICAL);
9503 tng_data->input_file = tng_data->output_file;
9505 return(TNG_SUCCESS);
9508 tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_get
9509 (const tng_trajectory_t tng_data, tng_file_endianness *endianness)
9511 tng_endianness_32 end_32;
9512 tng_endianness_64 end_64;
9514 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9515 TNG_ASSERT(endianness, "TNG library: endianness must not be a NULL pointer");
9517 if(tng_data->output_endianness_swap_func_32)
9519 /* If other endianness variants are added they must be added here as well */
9520 if(tng_data->output_endianness_swap_func_32 ==
9521 &tng_swap_byte_order_big_endian_32)
9523 end_32 = TNG_BIG_ENDIAN_32;
9525 else if(tng_data->output_endianness_swap_func_32 ==
9526 &tng_swap_byte_order_little_endian_32)
9528 end_32 = TNG_LITTLE_ENDIAN_32;
9530 else
9532 return(TNG_FAILURE);
9535 else
9537 end_32 = (tng_endianness_32)tng_data->endianness_32;
9540 if(tng_data->output_endianness_swap_func_64)
9542 /* If other endianness variants are added they must be added here as well */
9543 if(tng_data->output_endianness_swap_func_64 ==
9544 &tng_swap_byte_order_big_endian_64)
9546 end_64 = TNG_BIG_ENDIAN_64;
9548 else if(tng_data->output_endianness_swap_func_64 ==
9549 &tng_swap_byte_order_little_endian_64)
9551 end_64 = TNG_LITTLE_ENDIAN_64;
9553 else
9555 return(TNG_FAILURE);
9558 else
9560 end_64 = (tng_endianness_64)tng_data->endianness_64;
9563 if((int)end_32 != (int)end_64)
9565 return(TNG_FAILURE);
9568 if(end_32 == TNG_LITTLE_ENDIAN_32)
9570 *endianness = TNG_LITTLE_ENDIAN;
9573 else if(end_32 == TNG_BIG_ENDIAN_32)
9575 *endianness = TNG_BIG_ENDIAN;
9577 else
9579 return(TNG_FAILURE);
9582 return(TNG_SUCCESS);
9585 tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_set
9586 (const tng_trajectory_t tng_data,
9587 const tng_file_endianness endianness)
9589 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9591 /* Tne endianness cannot be changed if the data has already been written
9592 * to the output file. */
9593 if(ftello(tng_data->output_file) > 0)
9595 return(TNG_FAILURE);
9598 if(endianness == TNG_BIG_ENDIAN)
9600 if(tng_data->endianness_32 == TNG_BIG_ENDIAN_32)
9602 tng_data->output_endianness_swap_func_32 = 0;
9604 else
9606 tng_data->output_endianness_swap_func_32 =
9607 &tng_swap_byte_order_big_endian_32;
9609 if(tng_data->endianness_64 == TNG_BIG_ENDIAN_64)
9611 tng_data->output_endianness_swap_func_64 = 0;
9613 else
9615 tng_data->output_endianness_swap_func_64 =
9616 &tng_swap_byte_order_big_endian_64;
9618 return(TNG_SUCCESS);
9620 else if(endianness == TNG_LITTLE_ENDIAN)
9622 if(tng_data->endianness_32 == TNG_LITTLE_ENDIAN_32)
9624 tng_data->output_endianness_swap_func_32 = 0;
9626 else
9628 tng_data->output_endianness_swap_func_32 =
9629 &tng_swap_byte_order_little_endian_32;
9631 if(tng_data->endianness_64 == TNG_LITTLE_ENDIAN_64)
9633 tng_data->output_endianness_swap_func_64 = 0;
9635 else
9637 tng_data->output_endianness_swap_func_64 =
9638 &tng_swap_byte_order_little_endian_64;
9640 return(TNG_SUCCESS);
9643 /* If the specified endianness is neither big nor little endian return a
9644 * failure. */
9645 return(TNG_FAILURE);
9648 tng_function_status DECLSPECDLLEXPORT tng_first_program_name_get
9649 (const tng_trajectory_t tng_data,
9650 char *name,
9651 const int max_len)
9653 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9654 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
9656 strncpy(name, tng_data->first_program_name, max_len - 1);
9657 name[max_len - 1] = 0;
9659 if(strlen(tng_data->first_program_name) > (unsigned int)max_len - 1)
9661 return(TNG_FAILURE);
9663 return(TNG_SUCCESS);
9666 tng_function_status DECLSPECDLLEXPORT tng_first_program_name_set
9667 (const tng_trajectory_t tng_data,
9668 const char *new_name)
9670 unsigned int len;
9672 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9673 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
9675 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
9677 if(tng_data->first_program_name && strlen(tng_data->first_program_name) < len)
9679 free(tng_data->first_program_name);
9680 tng_data->first_program_name = 0;
9682 if(!tng_data->first_program_name)
9684 tng_data->first_program_name = (char *)malloc(len);
9685 if(!tng_data->first_program_name)
9687 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
9688 __FILE__, __LINE__);
9689 return(TNG_CRITICAL);
9693 strncpy(tng_data->first_program_name, new_name, len);
9695 return(TNG_SUCCESS);
9698 tng_function_status DECLSPECDLLEXPORT tng_last_program_name_get
9699 (const tng_trajectory_t tng_data,
9700 char *name, const int max_len)
9702 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9703 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
9705 strncpy(name, tng_data->last_program_name, max_len - 1);
9706 name[max_len - 1] = 0;
9708 if(strlen(tng_data->last_program_name) > (unsigned int)max_len - 1)
9710 return(TNG_FAILURE);
9712 return(TNG_SUCCESS);
9715 tng_function_status DECLSPECDLLEXPORT tng_last_program_name_set
9716 (const tng_trajectory_t tng_data,
9717 const char *new_name)
9719 unsigned int len;
9721 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9722 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
9724 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
9726 if(tng_data->last_program_name && strlen(tng_data->last_program_name) < len)
9728 free(tng_data->last_program_name);
9729 tng_data->last_program_name = 0;
9731 if(!tng_data->last_program_name)
9733 tng_data->last_program_name = (char *)malloc(len);
9734 if(!tng_data->last_program_name)
9736 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
9737 __FILE__, __LINE__);
9738 return(TNG_CRITICAL);
9742 strncpy(tng_data->last_program_name, new_name, len);
9744 return(TNG_SUCCESS);
9747 tng_function_status DECLSPECDLLEXPORT tng_first_user_name_get
9748 (const tng_trajectory_t tng_data,
9749 char *name, const int max_len)
9751 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9752 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
9754 strncpy(name, tng_data->first_user_name, max_len - 1);
9755 name[max_len - 1] = 0;
9757 if(strlen(tng_data->first_user_name) > (unsigned int)max_len - 1)
9759 return(TNG_FAILURE);
9761 return(TNG_SUCCESS);
9764 tng_function_status DECLSPECDLLEXPORT tng_first_user_name_set
9765 (const tng_trajectory_t tng_data,
9766 const char *new_name)
9768 unsigned int len;
9770 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9771 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
9773 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
9775 /* If the currently stored string length is not enough to store the new
9776 * string it is freed and reallocated. */
9777 if(tng_data->first_user_name && strlen(tng_data->first_user_name) < len)
9779 free(tng_data->first_user_name);
9780 tng_data->first_user_name = 0;
9782 if(!tng_data->first_user_name)
9784 tng_data->first_user_name = (char *)malloc(len);
9785 if(!tng_data->first_user_name)
9787 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
9788 __FILE__, __LINE__);
9789 return(TNG_CRITICAL);
9793 strncpy(tng_data->first_user_name, new_name, len);
9795 return(TNG_SUCCESS);
9798 tng_function_status DECLSPECDLLEXPORT tng_last_user_name_get
9799 (const tng_trajectory_t tng_data,
9800 char *name, const int max_len)
9802 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9803 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
9805 strncpy(name, tng_data->last_user_name, max_len - 1);
9806 name[max_len - 1] = 0;
9808 if(strlen(tng_data->last_user_name) > (unsigned int)max_len - 1)
9810 return(TNG_FAILURE);
9812 return(TNG_SUCCESS);
9815 tng_function_status DECLSPECDLLEXPORT tng_last_user_name_set
9816 (const tng_trajectory_t tng_data,
9817 const char *new_name)
9819 unsigned int len;
9821 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9822 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
9824 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
9826 /* If the currently stored string length is not enough to store the new
9827 * string it is freed and reallocated. */
9828 if(tng_data->last_user_name && strlen(tng_data->last_user_name) < len)
9830 free(tng_data->last_user_name);
9831 tng_data->last_user_name = 0;
9833 if(!tng_data->last_user_name)
9835 tng_data->last_user_name = (char *)malloc(len);
9836 if(!tng_data->last_user_name)
9838 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
9839 __FILE__, __LINE__);
9840 return(TNG_CRITICAL);
9844 strncpy(tng_data->last_user_name, new_name, len);
9846 return(TNG_SUCCESS);
9849 tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_get
9850 (const tng_trajectory_t tng_data,
9851 char *name, const int max_len)
9853 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9854 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
9856 strncpy(name, tng_data->first_computer_name, max_len - 1);
9857 name[max_len - 1] = 0;
9859 if(strlen(tng_data->first_computer_name) > (unsigned int)max_len - 1)
9861 return(TNG_FAILURE);
9863 return(TNG_SUCCESS);
9866 tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_set
9867 (const tng_trajectory_t tng_data,
9868 const char *new_name)
9870 unsigned int len;
9872 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9873 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
9875 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
9877 /* If the currently stored string length is not enough to store the new
9878 * string it is freed and reallocated. */
9879 if(tng_data->first_computer_name && strlen(tng_data->first_computer_name) < len)
9881 free(tng_data->first_computer_name);
9882 tng_data->first_computer_name = 0;
9884 if(!tng_data->first_computer_name)
9886 tng_data->first_computer_name = (char *)malloc(len);
9887 if(!tng_data->first_computer_name)
9889 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
9890 __FILE__, __LINE__);
9891 return(TNG_CRITICAL);
9895 strncpy(tng_data->first_computer_name, new_name, len);
9897 return(TNG_SUCCESS);
9900 tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_get
9901 (const tng_trajectory_t tng_data,
9902 char *name, const int max_len)
9904 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9905 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
9907 strncpy(name, tng_data->last_computer_name, max_len - 1);
9908 name[max_len - 1] = 0;
9910 if(strlen(tng_data->last_computer_name) > (unsigned int)max_len - 1)
9912 return(TNG_FAILURE);
9914 return(TNG_SUCCESS);
9917 tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_set
9918 (const tng_trajectory_t tng_data,
9919 const char *new_name)
9921 unsigned int len;
9923 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9924 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
9926 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
9928 /* If the currently stored string length is not enough to store the new
9929 * string it is freed and reallocated. */
9930 if(tng_data->last_computer_name && strlen(tng_data->last_computer_name) <
9931 len)
9933 free(tng_data->last_computer_name);
9934 tng_data->last_computer_name = 0;
9936 if(!tng_data->last_computer_name)
9938 tng_data->last_computer_name = (char *)malloc(len);
9939 if(!tng_data->last_computer_name)
9941 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
9942 __FILE__, __LINE__);
9943 return(TNG_CRITICAL);
9947 strncpy(tng_data->last_computer_name, new_name, len);
9949 return(TNG_SUCCESS);
9952 tng_function_status DECLSPECDLLEXPORT tng_first_signature_get
9953 (const tng_trajectory_t tng_data,
9954 char *signature, const int max_len)
9956 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9957 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
9959 strncpy(signature, tng_data->first_pgp_signature, max_len - 1);
9960 signature[max_len - 1] = 0;
9962 if(strlen(tng_data->first_pgp_signature) > (unsigned int)max_len - 1)
9964 return(TNG_FAILURE);
9966 return(TNG_SUCCESS);
9969 tng_function_status DECLSPECDLLEXPORT tng_first_signature_set
9970 (const tng_trajectory_t tng_data,
9971 const char *signature)
9973 unsigned int len;
9975 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9976 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
9978 len = tng_min_size(strlen(signature) + 1, TNG_MAX_STR_LEN);
9980 /* If the currently stored string length is not enough to store the new
9981 * string it is freed and reallocated. */
9982 if(tng_data->first_pgp_signature && strlen(tng_data->first_pgp_signature) <
9983 len)
9985 free(tng_data->first_pgp_signature);
9986 tng_data->first_pgp_signature = 0;
9988 if(!tng_data->first_pgp_signature)
9990 tng_data->first_pgp_signature = (char *)malloc(len);
9991 if(!tng_data->first_pgp_signature)
9993 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
9994 __FILE__, __LINE__);
9995 return(TNG_CRITICAL);
9999 strncpy(tng_data->first_pgp_signature, signature, len);
10001 return(TNG_SUCCESS);
10004 tng_function_status DECLSPECDLLEXPORT tng_last_signature_get
10005 (const tng_trajectory_t tng_data,
10006 char *signature, const int max_len)
10008 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10009 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
10011 strncpy(signature, tng_data->last_pgp_signature, max_len - 1);
10012 signature[max_len - 1] = 0;
10014 if(strlen(tng_data->last_pgp_signature) > (unsigned int)max_len - 1)
10016 return(TNG_FAILURE);
10018 return(TNG_SUCCESS);
10021 tng_function_status DECLSPECDLLEXPORT tng_last_signature_set
10022 (const tng_trajectory_t tng_data,
10023 const char *signature)
10025 unsigned int len;
10027 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10028 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
10030 len = tng_min_size(strlen(signature) + 1, TNG_MAX_STR_LEN);
10032 /* If the currently stored string length is not enough to store the new
10033 * string it is freed and reallocated. */
10034 if(tng_data->last_pgp_signature && strlen(tng_data->last_pgp_signature) <
10035 len)
10037 free(tng_data->last_pgp_signature);
10038 tng_data->last_pgp_signature = 0;
10040 if(!tng_data->last_pgp_signature)
10042 tng_data->last_pgp_signature = (char *)malloc(len);
10043 if(!tng_data->last_pgp_signature)
10045 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
10046 __FILE__, __LINE__);
10047 return(TNG_CRITICAL);
10051 strncpy(tng_data->last_pgp_signature, signature, len);
10053 return(TNG_SUCCESS);
10056 tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_get
10057 (const tng_trajectory_t tng_data,
10058 char *name, const int max_len)
10060 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10061 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10063 strncpy(name, tng_data->forcefield_name, max_len - 1);
10064 name[max_len - 1] = 0;
10066 if(strlen(tng_data->forcefield_name) > (unsigned int)max_len - 1)
10068 return(TNG_FAILURE);
10070 return(TNG_SUCCESS);
10073 tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_set
10074 (const tng_trajectory_t tng_data,
10075 const char *new_name)
10077 unsigned int len;
10079 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10080 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10082 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
10084 /* If the currently stored string length is not enough to store the new
10085 * string it is freed and reallocated. */
10086 if(tng_data->forcefield_name && strlen(tng_data->forcefield_name) < len)
10088 free(tng_data->forcefield_name);
10089 tng_data->forcefield_name = 0;
10091 if(!tng_data->forcefield_name)
10093 tng_data->forcefield_name = (char *)malloc(len);
10094 if(!tng_data->forcefield_name)
10096 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
10097 __FILE__, __LINE__);
10098 return(TNG_CRITICAL);
10102 strncpy(tng_data->forcefield_name, new_name, len);
10104 return(TNG_SUCCESS);
10107 tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_get
10108 (const tng_trajectory_t tng_data,
10109 int64_t *len)
10111 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10112 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
10114 *len = tng_data->medium_stride_length;
10116 return(TNG_SUCCESS);
10119 tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_set
10120 (const tng_trajectory_t tng_data,
10121 const int64_t len)
10123 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10125 if(len >= tng_data->long_stride_length)
10127 return(TNG_FAILURE);
10129 tng_data->medium_stride_length = len;
10131 return(TNG_SUCCESS);
10134 tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_get
10135 (const tng_trajectory_t tng_data,
10136 int64_t *len)
10138 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10139 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
10141 *len = tng_data->long_stride_length;
10143 return(TNG_SUCCESS);
10146 tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_set
10147 (const tng_trajectory_t tng_data,
10148 const int64_t len)
10150 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10152 if(len <= tng_data->medium_stride_length)
10154 return(TNG_FAILURE);
10156 tng_data->long_stride_length = len;
10158 return(TNG_SUCCESS);
10161 tng_function_status DECLSPECDLLEXPORT tng_time_per_frame_get
10162 (const tng_trajectory_t tng_data,
10163 double *time)
10165 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10166 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
10168 *time = tng_data->time_per_frame;
10170 return(TNG_SUCCESS);
10173 tng_function_status DECLSPECDLLEXPORT tng_time_per_frame_set
10174 (const tng_trajectory_t tng_data,
10175 const double time)
10177 tng_trajectory_frame_set_t frame_set;
10179 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10180 TNG_ASSERT(time >= 0, "TNG library: The time per frame must be >= 0.");
10182 if(fabs(time - tng_data->time_per_frame) < 0.00001)
10184 return(TNG_SUCCESS);
10187 frame_set = &tng_data->current_trajectory_frame_set;
10189 /* If the current frame set is not finished write it to disk before
10190 changing time per frame. */
10191 if(tng_data->time_per_frame > 0 && frame_set->n_unwritten_frames > 0)
10193 frame_set->n_frames = frame_set->n_unwritten_frames;
10194 tng_frame_set_write(tng_data, TNG_USE_HASH);
10196 tng_data->time_per_frame = time;
10198 return(TNG_SUCCESS);
10201 tng_function_status DECLSPECDLLEXPORT tng_input_file_len_get
10202 (const tng_trajectory_t tng_data,
10203 int64_t *len)
10205 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10206 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
10208 *len = tng_data->input_file_len;
10210 return(TNG_SUCCESS);
10213 tng_function_status DECLSPECDLLEXPORT tng_num_frames_get
10214 (const tng_trajectory_t tng_data,
10215 int64_t *n)
10217 tng_gen_block_t block;
10218 tng_function_status stat;
10219 int64_t file_pos, last_file_pos, first_frame, n_frames;
10221 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10222 TNG_ASSERT(tng_data->input_file, "TNG library: An input file must be open to find the next frame set");
10223 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10225 file_pos = ftello(tng_data->input_file);
10226 last_file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
10228 if(last_file_pos <= 0)
10230 return(TNG_FAILURE);
10233 tng_block_init(&block);
10234 fseeko(tng_data->input_file,
10235 last_file_pos,
10236 SEEK_SET);
10237 /* Read block headers first to see that a frame set block is found. */
10238 stat = tng_block_header_read(tng_data, block);
10239 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10241 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n", last_file_pos,
10242 __FILE__, __LINE__);
10243 tng_block_destroy(&block);
10244 return(TNG_FAILURE);
10246 tng_block_destroy(&block);
10248 if(tng_file_input_numerical(tng_data, &first_frame,
10249 sizeof(first_frame),
10250 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
10252 return(TNG_CRITICAL);
10255 if(tng_file_input_numerical(tng_data, &n_frames,
10256 sizeof(n_frames),
10257 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
10259 return(TNG_CRITICAL);
10262 fseeko(tng_data->input_file, file_pos, SEEK_SET);
10264 *n = first_frame + n_frames;
10266 return(TNG_SUCCESS);
10269 tng_function_status DECLSPECDLLEXPORT tng_compression_precision_get
10270 (const tng_trajectory_t tng_data,
10271 double *precision)
10273 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10275 *precision = tng_data->compression_precision;
10277 return(TNG_SUCCESS);
10280 tng_function_status DECLSPECDLLEXPORT tng_compression_precision_set
10281 (const tng_trajectory_t tng_data,
10282 const double precision)
10284 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10286 tng_data->compression_precision = precision;
10288 return(TNG_SUCCESS);
10291 tng_function_status DECLSPECDLLEXPORT tng_implicit_num_particles_set
10292 (const tng_trajectory_t tng_data,
10293 const int64_t n)
10295 tng_molecule_t mol;
10296 tng_chain_t chain;
10297 tng_residue_t res;
10298 tng_atom_t atom;
10299 tng_function_status stat;
10300 int64_t diff, n_mod, n_impl;
10302 TNG_ASSERT(n >= 0, "TNG library: The requested number of particles must be >= 0");
10304 diff = n - tng_data->n_particles;
10306 stat = tng_molecule_find(tng_data, "TNG_IMPLICIT_MOL", -1, &mol);
10307 if(stat == TNG_SUCCESS)
10309 if(tng_molecule_cnt_get(tng_data, mol, &n_impl) != TNG_SUCCESS)
10311 fprintf(stderr, "TNG library: Cannot get the number of implicit molecules. %s: %d\n",
10312 __FILE__, __LINE__);
10313 return(TNG_FAILURE);
10315 diff -= n_impl * mol->n_atoms;
10318 if(diff == 0)
10320 if(stat == TNG_SUCCESS)
10322 stat = tng_molecule_cnt_set(tng_data, mol, 0);
10323 return(stat);
10325 return(TNG_SUCCESS);
10327 else if(diff < 0)
10329 fprintf(stderr, "TNG library: Already more actual particles than requested implicit ");
10330 fprintf(stderr, "particle count.\n");
10331 fprintf(stderr, "TNG library: Cannot set implicit particle count. %s: %d\n",
10332 __FILE__, __LINE__);
10333 /* FIXME: Should we set the count of all other molecules to 0 and add
10334 * implicit molecules? */
10335 return(TNG_FAILURE);
10337 if(stat != TNG_SUCCESS)
10339 stat = tng_molecule_add(tng_data,
10340 "TNG_IMPLICIT_MOL",
10341 &mol);
10342 if(stat != TNG_SUCCESS)
10344 return(stat);
10346 stat = tng_molecule_chain_add(tng_data, mol, "", &chain);
10347 if(stat != TNG_SUCCESS)
10349 return(stat);
10351 stat = tng_chain_residue_add(tng_data, chain, "", &res);
10352 if(stat != TNG_SUCCESS)
10354 return(stat);
10356 stat = tng_residue_atom_add(tng_data, res, "", "", &atom);
10357 if(stat != TNG_SUCCESS)
10359 return(stat);
10362 else
10364 if(mol->n_atoms > 1)
10366 n_mod = diff % mol->n_atoms;
10367 if(n_mod != 0)
10369 fprintf(stderr, "TNG library: Number of atoms in implicit molecule ");
10370 fprintf(stderr, "not compatible with requested implicit particle cnt.\n");
10371 fprintf(stderr, "TNG library: Cannot set implicit particle count. %s: %d\n",
10372 __FILE__, __LINE__);
10373 return(TNG_FAILURE);
10375 diff /= mol->n_atoms;
10378 stat = tng_molecule_cnt_set(tng_data, mol, diff);
10380 return(stat);
10383 tng_function_status DECLSPECDLLEXPORT tng_num_particles_get
10384 (const tng_trajectory_t tng_data,
10385 int64_t *n)
10387 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10388 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10390 if(tng_data->var_num_atoms_flag == TNG_CONSTANT_N_ATOMS)
10392 *n = tng_data->n_particles;
10394 else
10396 *n = tng_data->current_trajectory_frame_set.n_particles;
10399 return(TNG_SUCCESS);
10402 tng_function_status DECLSPECDLLEXPORT tng_num_particles_variable_get
10403 (const tng_trajectory_t tng_data,
10404 char *variable)
10406 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10407 TNG_ASSERT(variable, "TNG library: variable must not be a NULL pointer");
10409 *variable = tng_data->var_num_atoms_flag;
10411 return(TNG_SUCCESS);
10414 tng_function_status DECLSPECDLLEXPORT tng_num_molecule_types_get
10415 (const tng_trajectory_t tng_data,
10416 int64_t *n)
10418 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10419 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10421 *n = tng_data->n_molecules;
10423 return(TNG_SUCCESS);
10426 tng_function_status DECLSPECDLLEXPORT tng_num_molecules_get
10427 (const tng_trajectory_t tng_data,
10428 int64_t *n)
10430 int64_t *cnt_list = 0, cnt = 0, i;
10432 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10433 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10435 tng_molecule_cnt_list_get(tng_data, &cnt_list);
10437 if(!cnt_list)
10439 return(TNG_FAILURE);
10442 for(i = 0; i < tng_data->n_molecules; i++)
10444 cnt += cnt_list[i];
10447 *n = cnt;
10449 return(TNG_SUCCESS);
10452 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_list_get
10453 (const tng_trajectory_t tng_data,
10454 int64_t **mol_cnt_list)
10456 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10458 if(tng_data->var_num_atoms_flag)
10460 *mol_cnt_list = tng_data->current_trajectory_frame_set.
10461 molecule_cnt_list;
10463 else
10465 *mol_cnt_list = tng_data->molecule_cnt_list;
10467 if(*mol_cnt_list == 0)
10469 return(TNG_FAILURE);
10471 return(TNG_SUCCESS);
10474 tng_function_status DECLSPECDLLEXPORT tng_distance_unit_exponential_get
10475 (const tng_trajectory_t tng_data,
10476 int64_t *exp)
10478 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10479 TNG_ASSERT(exp, "TNG library: exp must not be a NULL pointer");
10481 *exp = tng_data->distance_unit_exponential;
10483 return(TNG_SUCCESS);
10486 tng_function_status DECLSPECDLLEXPORT tng_distance_unit_exponential_set
10487 (const tng_trajectory_t tng_data,
10488 const int64_t exp)
10490 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10492 tng_data->distance_unit_exponential = exp;
10494 return(TNG_SUCCESS);
10497 tng_function_status DECLSPECDLLEXPORT tng_num_frames_per_frame_set_get
10498 (const tng_trajectory_t tng_data,
10499 int64_t *n)
10501 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10502 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10504 *n = tng_data->frame_set_n_frames;
10506 return(TNG_SUCCESS);
10509 tng_function_status DECLSPECDLLEXPORT tng_num_frames_per_frame_set_set
10510 (const tng_trajectory_t tng_data,
10511 const int64_t n)
10513 tng_trajectory_frame_set_t frame_set;
10514 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10516 tng_data->frame_set_n_frames = n;
10517 frame_set = &tng_data->current_trajectory_frame_set;
10518 if(frame_set)
10520 frame_set->n_frames = n;
10523 return(TNG_SUCCESS);
10526 tng_function_status DECLSPECDLLEXPORT tng_num_frame_sets_get
10527 (const tng_trajectory_t tng_data,
10528 int64_t *n)
10530 int64_t long_stride_length, medium_stride_length;
10531 int64_t file_pos, orig_frame_set_file_pos;
10532 tng_trajectory_frame_set_t frame_set;
10533 struct tng_trajectory_frame_set orig_frame_set;
10534 tng_gen_block_t block;
10535 tng_function_status stat;
10536 int64_t cnt = 0;
10538 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10539 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10541 orig_frame_set = tng_data->current_trajectory_frame_set;
10543 frame_set = &tng_data->current_trajectory_frame_set;
10545 orig_frame_set_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
10546 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
10548 if(file_pos < 0)
10550 *n = tng_data->n_trajectory_frame_sets = cnt;
10551 return(TNG_SUCCESS);
10554 tng_block_init(&block);
10555 fseeko(tng_data->input_file,
10556 file_pos,
10557 SEEK_SET);
10558 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
10559 /* Read block headers first to see what block is found. */
10560 stat = tng_block_header_read(tng_data, block);
10561 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10563 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n", file_pos,
10564 __FILE__, __LINE__);
10565 tng_block_destroy(&block);
10566 return(TNG_CRITICAL);
10569 if(tng_block_read_next(tng_data, block,
10570 TNG_SKIP_HASH) != TNG_SUCCESS)
10572 tng_block_destroy(&block);
10573 return(TNG_CRITICAL);
10576 ++cnt;
10578 long_stride_length = tng_data->long_stride_length;
10579 medium_stride_length = tng_data->medium_stride_length;
10581 /* Take long steps forward until a long step forward would be too long or
10582 * the last frame set is found */
10583 file_pos = frame_set->long_stride_next_frame_set_file_pos;
10584 while(file_pos > 0)
10586 if(file_pos > 0)
10588 cnt += long_stride_length;
10589 fseeko(tng_data->input_file, file_pos, SEEK_SET);
10590 /* Read block headers first to see what block is found. */
10591 stat = tng_block_header_read(tng_data, block);
10592 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10594 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
10595 file_pos, __FILE__, __LINE__);
10596 tng_block_destroy(&block);
10597 return(TNG_CRITICAL);
10600 if(tng_block_read_next(tng_data, block,
10601 TNG_SKIP_HASH) != TNG_SUCCESS)
10603 tng_block_destroy(&block);
10604 return(TNG_CRITICAL);
10607 file_pos = frame_set->long_stride_next_frame_set_file_pos;
10610 /* Take medium steps forward until a medium step forward would be too long
10611 * or the last frame set is found */
10612 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
10613 while(file_pos > 0)
10615 if(file_pos > 0)
10617 cnt += medium_stride_length;
10618 fseeko(tng_data->input_file,
10619 file_pos,
10620 SEEK_SET);
10621 /* Read block headers first to see what block is found. */
10622 stat = tng_block_header_read(tng_data, block);
10623 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10625 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
10626 file_pos, __FILE__, __LINE__);
10627 tng_block_destroy(&block);
10628 return(TNG_CRITICAL);
10631 if(tng_block_read_next(tng_data, block,
10632 TNG_SKIP_HASH) != TNG_SUCCESS)
10634 tng_block_destroy(&block);
10635 return(TNG_CRITICAL);
10638 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
10641 /* Take one step forward until the last frame set is found */
10642 file_pos = frame_set->next_frame_set_file_pos;
10643 while(file_pos > 0)
10645 if(file_pos > 0)
10647 ++cnt;
10648 fseeko(tng_data->input_file,
10649 file_pos,
10650 SEEK_SET);
10651 /* Read block headers first to see what block is found. */
10652 stat = tng_block_header_read(tng_data, block);
10653 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10655 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
10656 file_pos, __FILE__, __LINE__);
10657 tng_block_destroy(&block);
10658 return(TNG_CRITICAL);
10661 if(tng_block_read_next(tng_data, block,
10662 TNG_SKIP_HASH) != TNG_SUCCESS)
10664 tng_block_destroy(&block);
10665 return(TNG_CRITICAL);
10668 file_pos = frame_set->next_frame_set_file_pos;
10671 tng_block_destroy(&block);
10673 *n = tng_data->n_trajectory_frame_sets = cnt;
10675 *frame_set = orig_frame_set;
10676 /* The mapping block in the original frame set has been freed when reading
10677 * other frame sets. */
10678 frame_set->mappings = 0;
10679 frame_set->n_mapping_blocks = 0;
10681 fseeko(tng_data->input_file,
10682 tng_data->first_trajectory_frame_set_input_file_pos,
10683 SEEK_SET);
10685 tng_data->current_trajectory_frame_set_input_file_pos = orig_frame_set_file_pos;
10687 return(TNG_SUCCESS);
10690 tng_function_status DECLSPECDLLEXPORT tng_current_frame_set_get
10691 (const tng_trajectory_t tng_data,
10692 tng_trajectory_frame_set_t *frame_set_p)
10694 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10696 *frame_set_p = &tng_data->current_trajectory_frame_set;
10698 return(TNG_SUCCESS);
10701 tng_function_status DECLSPECDLLEXPORT tng_frame_set_nr_find
10702 (const tng_trajectory_t tng_data,
10703 const int64_t nr)
10705 int64_t long_stride_length, medium_stride_length;
10706 int64_t file_pos, curr_nr = 0, n_frame_sets;
10707 tng_trajectory_frame_set_t frame_set;
10708 tng_gen_block_t block;
10709 tng_function_status stat;
10711 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10712 TNG_ASSERT(nr >= 0, "The frame set number (nr) must be >= 0");
10714 frame_set = &tng_data->current_trajectory_frame_set;
10716 stat = tng_num_frame_sets_get(tng_data, &n_frame_sets);
10718 if(stat != TNG_SUCCESS)
10720 return(stat);
10723 if(nr >= n_frame_sets)
10725 return(TNG_FAILURE);
10728 long_stride_length = tng_data->long_stride_length;
10729 medium_stride_length = tng_data->medium_stride_length;
10731 /* FIXME: The frame set number of the current frame set is not stored */
10733 if(nr < n_frame_sets - 1 - nr)
10735 /* Start from the beginning */
10736 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
10738 else
10740 /* Start from the end */
10741 file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
10742 curr_nr = n_frame_sets - 1;
10744 if(file_pos <= 0)
10746 return(TNG_FAILURE);
10749 tng_block_init(&block);
10750 fseeko(tng_data->input_file,
10751 file_pos,
10752 SEEK_SET);
10753 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
10754 /* Read block headers first to see what block is found. */
10755 stat = tng_block_header_read(tng_data, block);
10756 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10758 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n", file_pos,
10759 __FILE__, __LINE__);
10760 tng_block_destroy(&block);
10761 return(TNG_CRITICAL);
10764 if(tng_block_read_next(tng_data, block,
10765 TNG_SKIP_HASH) != TNG_SUCCESS)
10767 tng_block_destroy(&block);
10768 return(TNG_CRITICAL);
10771 if(curr_nr == nr)
10773 tng_block_destroy(&block);
10774 return(TNG_SUCCESS);
10777 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
10779 /* Take long steps forward until a long step forward would be too long or
10780 * the right frame set is found */
10781 while(file_pos > 0 && curr_nr + long_stride_length <= nr)
10783 file_pos = frame_set->long_stride_next_frame_set_file_pos;
10784 if(file_pos > 0)
10786 curr_nr += long_stride_length;
10787 fseeko(tng_data->input_file, file_pos, SEEK_SET);
10788 /* Read block headers first to see what block is found. */
10789 stat = tng_block_header_read(tng_data, block);
10790 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10792 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
10793 file_pos, __FILE__, __LINE__);
10794 tng_block_destroy(&block);
10795 return(TNG_CRITICAL);
10798 if(tng_block_read_next(tng_data, block,
10799 TNG_SKIP_HASH) != TNG_SUCCESS)
10801 tng_block_destroy(&block);
10802 return(TNG_CRITICAL);
10804 if(curr_nr == nr)
10806 tng_block_destroy(&block);
10807 return(TNG_SUCCESS);
10812 /* Take medium steps forward until a medium step forward would be too long
10813 * or the right frame set is found */
10814 while(file_pos > 0 && curr_nr + medium_stride_length <= nr)
10816 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
10817 if(file_pos > 0)
10819 curr_nr += medium_stride_length;
10820 fseeko(tng_data->input_file,
10821 file_pos,
10822 SEEK_SET);
10823 /* Read block headers first to see what block is found. */
10824 stat = tng_block_header_read(tng_data, block);
10825 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10827 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
10828 file_pos, __FILE__, __LINE__);
10829 tng_block_destroy(&block);
10830 return(TNG_CRITICAL);
10833 if(tng_block_read_next(tng_data, block,
10834 TNG_SKIP_HASH) != TNG_SUCCESS)
10836 tng_block_destroy(&block);
10837 return(TNG_CRITICAL);
10839 if(curr_nr == nr)
10841 tng_block_destroy(&block);
10842 return(TNG_SUCCESS);
10847 /* Take one step forward until the right frame set is found */
10848 while(file_pos > 0 && curr_nr < nr)
10850 file_pos = frame_set->next_frame_set_file_pos;
10852 if(file_pos > 0)
10854 ++curr_nr;
10855 fseeko(tng_data->input_file,
10856 file_pos,
10857 SEEK_SET);
10858 /* Read block headers first to see what block is found. */
10859 stat = tng_block_header_read(tng_data, block);
10860 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10862 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
10863 file_pos, __FILE__, __LINE__);
10864 tng_block_destroy(&block);
10865 return(TNG_CRITICAL);
10868 if(tng_block_read_next(tng_data, block,
10869 TNG_SKIP_HASH) != TNG_SUCCESS)
10871 tng_block_destroy(&block);
10872 return(TNG_CRITICAL);
10874 if(curr_nr == nr)
10876 tng_block_destroy(&block);
10877 return(TNG_SUCCESS);
10882 /* Take long steps backward until a long step backward would be too long
10883 * or the right frame set is found */
10884 while(file_pos > 0 && curr_nr - long_stride_length >= nr)
10886 file_pos = frame_set->long_stride_prev_frame_set_file_pos;
10887 if(file_pos > 0)
10889 curr_nr -= long_stride_length;
10890 fseeko(tng_data->input_file,
10891 file_pos,
10892 SEEK_SET);
10893 /* Read block headers first to see what block is found. */
10894 stat = tng_block_header_read(tng_data, block);
10895 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10897 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
10898 file_pos, __FILE__, __LINE__);
10899 tng_block_destroy(&block);
10900 return(TNG_CRITICAL);
10903 if(tng_block_read_next(tng_data, block,
10904 TNG_SKIP_HASH) != TNG_SUCCESS)
10906 tng_block_destroy(&block);
10907 return(TNG_CRITICAL);
10909 if(curr_nr == nr)
10911 tng_block_destroy(&block);
10912 return(TNG_SUCCESS);
10917 /* Take medium steps backward until a medium step backward would be too long
10918 * or the right frame set is found */
10919 while(file_pos > 0 && curr_nr - medium_stride_length >= nr)
10921 file_pos = frame_set->medium_stride_prev_frame_set_file_pos;
10922 if(file_pos > 0)
10924 curr_nr -= medium_stride_length;
10925 fseeko(tng_data->input_file,
10926 file_pos,
10927 SEEK_SET);
10928 /* Read block headers first to see what block is found. */
10929 stat = tng_block_header_read(tng_data, block);
10930 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10932 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
10933 file_pos, __FILE__, __LINE__);
10934 tng_block_destroy(&block);
10935 return(TNG_CRITICAL);
10938 if(tng_block_read_next(tng_data, block,
10939 TNG_SKIP_HASH) != TNG_SUCCESS)
10941 tng_block_destroy(&block);
10942 return(TNG_CRITICAL);
10944 if(curr_nr == nr)
10946 tng_block_destroy(&block);
10947 return(TNG_SUCCESS);
10952 /* Take one step backward until the right frame set is found */
10953 while(file_pos > 0 && curr_nr > nr)
10955 file_pos = frame_set->prev_frame_set_file_pos;
10956 if(file_pos > 0)
10958 --curr_nr;
10959 fseeko(tng_data->input_file,
10960 file_pos,
10961 SEEK_SET);
10962 /* Read block headers first to see what block is found. */
10963 stat = tng_block_header_read(tng_data, block);
10964 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10966 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
10967 file_pos, __FILE__, __LINE__);
10968 tng_block_destroy(&block);
10969 return(TNG_CRITICAL);
10972 if(tng_block_read_next(tng_data, block,
10973 TNG_SKIP_HASH) != TNG_SUCCESS)
10975 tng_block_destroy(&block);
10976 return(TNG_CRITICAL);
10978 if(curr_nr == nr)
10980 tng_block_destroy(&block);
10981 return(TNG_SUCCESS);
10986 /* If for some reason the current frame set is not yet found,
10987 * take one step forward until the right frame set is found */
10988 while(file_pos > 0 && curr_nr < nr)
10990 file_pos = frame_set->next_frame_set_file_pos;
10991 if(file_pos > 0)
10993 ++curr_nr;
10994 fseeko(tng_data->input_file,
10995 file_pos,
10996 SEEK_SET);
10997 /* Read block headers first to see what block is found. */
10998 stat = tng_block_header_read(tng_data, block);
10999 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11001 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
11002 file_pos, __FILE__, __LINE__);
11003 tng_block_destroy(&block);
11004 return(TNG_CRITICAL);
11007 if(tng_block_read_next(tng_data, block,
11008 TNG_SKIP_HASH) != TNG_SUCCESS)
11010 tng_block_destroy(&block);
11011 return(TNG_CRITICAL);
11013 if(curr_nr == nr)
11015 tng_block_destroy(&block);
11016 return(TNG_SUCCESS);
11021 tng_block_destroy(&block);
11022 return(TNG_FAILURE);
11025 tng_function_status DECLSPECDLLEXPORT tng_frame_set_of_frame_find
11026 (const tng_trajectory_t tng_data,
11027 const int64_t frame)
11029 int64_t first_frame, last_frame, n_frames_per_frame_set;
11030 int64_t long_stride_length, medium_stride_length;
11031 int64_t file_pos, temp_frame, n_frames;
11032 tng_trajectory_frame_set_t frame_set;
11033 tng_gen_block_t block;
11034 tng_function_status stat;
11036 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11037 TNG_ASSERT(frame >= 0, "TNG library: frame must be >= 0.");
11039 frame_set = &tng_data->current_trajectory_frame_set;
11041 tng_block_init(&block);
11043 if(tng_data->current_trajectory_frame_set_input_file_pos < 0)
11045 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
11046 fseeko(tng_data->input_file,
11047 file_pos,
11048 SEEK_SET);
11049 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
11050 /* Read block headers first to see what block is found. */
11051 stat = tng_block_header_read(tng_data, block);
11052 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11054 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
11055 file_pos, __FILE__, __LINE__);
11056 tng_block_destroy(&block);
11057 return(TNG_CRITICAL);
11060 if(tng_block_read_next(tng_data, block,
11061 TNG_SKIP_HASH) != TNG_SUCCESS)
11063 tng_block_destroy(&block);
11064 return(TNG_CRITICAL);
11068 first_frame = tng_max_i64(frame_set->first_frame, 0);
11069 last_frame = first_frame + frame_set->n_frames - 1;
11070 /* Is this the right frame set? */
11071 if(first_frame <= frame && frame <= last_frame)
11073 tng_block_destroy(&block);
11074 return(TNG_SUCCESS);
11077 n_frames_per_frame_set = tng_data->frame_set_n_frames;
11078 long_stride_length = tng_data->long_stride_length;
11079 medium_stride_length = tng_data->medium_stride_length;
11081 if(tng_first_frame_nr_of_next_frame_set_get(tng_data, &temp_frame) ==
11082 TNG_SUCCESS)
11084 if(temp_frame - first_frame > n_frames_per_frame_set)
11086 n_frames_per_frame_set = temp_frame - first_frame;
11090 tng_num_frames_get(tng_data, &n_frames);
11092 if(frame >= n_frames)
11094 tng_block_destroy(&block);
11095 return(TNG_FAILURE);
11098 if(first_frame - frame >= frame ||
11099 frame - last_frame >
11100 tng_data->n_trajectory_frame_sets * n_frames_per_frame_set - frame)
11102 /* Start from the beginning */
11103 if(first_frame - frame >= frame)
11105 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
11107 if(file_pos <= 0)
11109 tng_block_destroy(&block);
11110 return(TNG_FAILURE);
11113 /* Start from the end */
11114 else if(frame - first_frame > (n_frames - 1) - frame)
11116 file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
11118 /* If the last frame set position is not set start from the current
11119 * frame set, since it will be closer than the first frame set. */
11121 /* Start from current */
11122 else
11124 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
11127 if(file_pos > 0)
11129 fseeko(tng_data->input_file,
11130 file_pos,
11131 SEEK_SET);
11132 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
11133 /* Read block headers first to see what block is found. */
11134 stat = tng_block_header_read(tng_data, block);
11135 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11137 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
11138 file_pos, __FILE__, __LINE__);
11139 tng_block_destroy(&block);
11140 return(TNG_CRITICAL);
11143 if(tng_block_read_next(tng_data, block,
11144 TNG_SKIP_HASH) != TNG_SUCCESS)
11146 tng_block_destroy(&block);
11147 return(TNG_CRITICAL);
11152 first_frame = tng_max_i64(frame_set->first_frame, 0);
11153 last_frame = first_frame + frame_set->n_frames - 1;
11155 if(frame >= first_frame && frame <= last_frame)
11157 tng_block_destroy(&block);
11158 return(TNG_SUCCESS);
11161 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
11163 /* Take long steps forward until a long step forward would be too long or
11164 * the right frame set is found */
11165 while(file_pos > 0 && first_frame + long_stride_length *
11166 n_frames_per_frame_set <= frame)
11168 file_pos = frame_set->long_stride_next_frame_set_file_pos;
11169 if(file_pos > 0)
11171 fseeko(tng_data->input_file, file_pos, SEEK_SET);
11172 /* Read block headers first to see what block is found. */
11173 stat = tng_block_header_read(tng_data, block);
11174 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11176 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
11177 file_pos, __FILE__, __LINE__);
11178 tng_block_destroy(&block);
11179 return(TNG_CRITICAL);
11182 if(tng_block_read_next(tng_data, block,
11183 TNG_SKIP_HASH) != TNG_SUCCESS)
11185 tng_block_destroy(&block);
11186 return(TNG_CRITICAL);
11189 first_frame = tng_max_i64(frame_set->first_frame, 0);
11190 last_frame = first_frame + frame_set->n_frames - 1;
11191 if(frame >= first_frame && frame <= last_frame)
11193 tng_block_destroy(&block);
11194 return(TNG_SUCCESS);
11198 /* Take medium steps forward until a medium step forward would be too long
11199 * or the right frame set is found */
11200 while(file_pos > 0 && first_frame + medium_stride_length *
11201 n_frames_per_frame_set <= frame)
11203 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
11204 if(file_pos > 0)
11206 fseeko(tng_data->input_file,
11207 file_pos,
11208 SEEK_SET);
11209 /* Read block headers first to see what block is found. */
11210 stat = tng_block_header_read(tng_data, block);
11211 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11213 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
11214 file_pos, __FILE__, __LINE__);
11215 tng_block_destroy(&block);
11216 return(TNG_CRITICAL);
11219 if(tng_block_read_next(tng_data, block,
11220 TNG_SKIP_HASH) != TNG_SUCCESS)
11222 tng_block_destroy(&block);
11223 return(TNG_CRITICAL);
11226 first_frame = tng_max_i64(frame_set->first_frame, 0);
11227 last_frame = first_frame + frame_set->n_frames - 1;
11228 if(frame >= first_frame && frame <= last_frame)
11230 tng_block_destroy(&block);
11231 return(TNG_SUCCESS);
11235 /* Take one step forward until the right frame set is found */
11236 while(file_pos > 0 && first_frame < frame && last_frame < frame)
11238 file_pos = frame_set->next_frame_set_file_pos;
11239 if(file_pos > 0)
11241 fseeko(tng_data->input_file,
11242 file_pos,
11243 SEEK_SET);
11244 /* Read block headers first to see what block is found. */
11245 stat = tng_block_header_read(tng_data, block);
11246 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11248 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
11249 file_pos, __FILE__, __LINE__);
11250 tng_block_destroy(&block);
11251 return(TNG_CRITICAL);
11254 if(tng_block_read_next(tng_data, block,
11255 TNG_SKIP_HASH) != TNG_SUCCESS)
11257 tng_block_destroy(&block);
11258 return(TNG_CRITICAL);
11261 first_frame = tng_max_i64(frame_set->first_frame, 0);
11262 last_frame = first_frame + frame_set->n_frames - 1;
11263 if(frame >= first_frame && frame <= last_frame)
11265 tng_block_destroy(&block);
11266 return(TNG_SUCCESS);
11270 /* Take long steps backward until a long step backward would be too long
11271 * or the right frame set is found */
11272 while(file_pos > 0 && first_frame - long_stride_length *
11273 n_frames_per_frame_set >= frame)
11275 file_pos = frame_set->long_stride_prev_frame_set_file_pos;
11276 if(file_pos > 0)
11278 fseeko(tng_data->input_file,
11279 file_pos,
11280 SEEK_SET);
11281 /* Read block headers first to see what block is found. */
11282 stat = tng_block_header_read(tng_data, block);
11283 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11285 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
11286 file_pos, __FILE__, __LINE__);
11287 tng_block_destroy(&block);
11288 return(TNG_CRITICAL);
11291 if(tng_block_read_next(tng_data, block,
11292 TNG_SKIP_HASH) != TNG_SUCCESS)
11294 tng_block_destroy(&block);
11295 return(TNG_CRITICAL);
11298 first_frame = tng_max_i64(frame_set->first_frame, 0);
11299 last_frame = first_frame + frame_set->n_frames - 1;
11300 if(frame >= first_frame && frame <= last_frame)
11302 tng_block_destroy(&block);
11303 return(TNG_SUCCESS);
11307 /* Take medium steps backward until a medium step backward would be too long
11308 * or the right frame set is found */
11309 while(file_pos > 0 && first_frame - medium_stride_length *
11310 n_frames_per_frame_set >= frame)
11312 file_pos = frame_set->medium_stride_prev_frame_set_file_pos;
11313 if(file_pos > 0)
11315 fseeko(tng_data->input_file,
11316 file_pos,
11317 SEEK_SET);
11318 /* Read block headers first to see what block is found. */
11319 stat = tng_block_header_read(tng_data, block);
11320 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11322 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
11323 file_pos, __FILE__, __LINE__);
11324 tng_block_destroy(&block);
11325 return(TNG_CRITICAL);
11328 if(tng_block_read_next(tng_data, block,
11329 TNG_SKIP_HASH) != TNG_SUCCESS)
11331 tng_block_destroy(&block);
11332 return(TNG_CRITICAL);
11335 first_frame = tng_max_i64(frame_set->first_frame, 0);
11336 last_frame = first_frame + frame_set->n_frames - 1;
11337 if(frame >= first_frame && frame <= last_frame)
11339 tng_block_destroy(&block);
11340 return(TNG_SUCCESS);
11344 /* Take one step backward until the right frame set is found */
11345 while(file_pos > 0 && first_frame > frame && last_frame > frame)
11347 file_pos = frame_set->prev_frame_set_file_pos;
11348 if(file_pos > 0)
11350 fseeko(tng_data->input_file,
11351 file_pos,
11352 SEEK_SET);
11353 /* Read block headers first to see what block is found. */
11354 stat = tng_block_header_read(tng_data, block);
11355 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11357 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
11358 file_pos, __FILE__, __LINE__);
11359 tng_block_destroy(&block);
11360 return(TNG_CRITICAL);
11363 if(tng_block_read_next(tng_data, block,
11364 TNG_SKIP_HASH) != TNG_SUCCESS)
11366 tng_block_destroy(&block);
11367 return(TNG_CRITICAL);
11370 first_frame = tng_max_i64(frame_set->first_frame, 0);
11371 last_frame = first_frame + frame_set->n_frames - 1;
11372 if(frame >= first_frame && frame <= last_frame)
11374 tng_block_destroy(&block);
11375 return(TNG_SUCCESS);
11379 /* If for some reason the current frame set is not yet found,
11380 * take one step forward until the right frame set is found */
11381 while(file_pos > 0 && first_frame < frame && last_frame < frame)
11383 file_pos = frame_set->next_frame_set_file_pos;
11384 if(file_pos > 0)
11386 fseeko(tng_data->input_file,
11387 file_pos,
11388 SEEK_SET);
11389 /* Read block headers first to see what block is found. */
11390 stat = tng_block_header_read(tng_data, block);
11391 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11393 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
11394 file_pos, __FILE__, __LINE__);
11395 tng_block_destroy(&block);
11396 return(TNG_CRITICAL);
11399 if(tng_block_read_next(tng_data, block,
11400 TNG_SKIP_HASH) != TNG_SUCCESS)
11402 tng_block_destroy(&block);
11403 return(TNG_CRITICAL);
11406 first_frame = tng_max_i64(frame_set->first_frame, 0);
11407 last_frame = first_frame + frame_set->n_frames - 1;
11408 if(frame >= first_frame && frame <= last_frame)
11410 tng_block_destroy(&block);
11411 return(TNG_SUCCESS);
11415 tng_block_destroy(&block);
11416 return(TNG_FAILURE);
11419 tng_function_status DECLSPECDLLEXPORT tng_frame_set_next_frame_set_file_pos_get
11420 (const tng_trajectory_t tng_data,
11421 const tng_trajectory_frame_set_t frame_set,
11422 int64_t *pos)
11424 (void)tng_data;
11426 TNG_ASSERT(frame_set, "TNG library: frame_set not initialised before accessing data.");
11427 TNG_ASSERT(pos, "TNG library: pos must not be a NULL pointer");
11429 *pos = frame_set->next_frame_set_file_pos;
11431 return(TNG_SUCCESS);
11434 tng_function_status DECLSPECDLLEXPORT tng_frame_set_prev_frame_set_file_pos_get
11435 (const tng_trajectory_t tng_data,
11436 const tng_trajectory_frame_set_t frame_set,
11437 int64_t *pos)
11439 (void)tng_data;
11441 TNG_ASSERT(frame_set, "TNG library: frame_set not initialised before accessing data.");
11442 TNG_ASSERT(pos, "TNG library: pos must not be a NULL pointer");
11444 *pos = frame_set->prev_frame_set_file_pos;
11446 return(TNG_SUCCESS);
11449 tng_function_status DECLSPECDLLEXPORT tng_frame_set_frame_range_get
11450 (const tng_trajectory_t tng_data,
11451 const tng_trajectory_frame_set_t frame_set,
11452 int64_t *first_frame,
11453 int64_t *last_frame)
11455 (void)tng_data;
11457 TNG_ASSERT(first_frame, "TNG library: first_frame must not be a NULL pointer");
11458 TNG_ASSERT(last_frame, "TNG library: last_frame must not be a NULL pointer");
11459 TNG_ASSERT(frame_set, "TNG library: frame_set must not be a NULL pointer");
11461 *first_frame = frame_set->first_frame;
11462 *last_frame = *first_frame + frame_set->n_frames - 1;
11464 return(TNG_SUCCESS);
11468 * @brief Translate from the particle numbering used in a frame set to the real
11469 * particle numbering - used in the molecule description.
11470 * @param frame_set is the frame_set containing the mappings to use.
11471 * @param local is the index number of the atom in this frame set
11472 * @param real is set to the index of the atom in the molecular system.
11473 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the mapping
11474 * cannot be found.
11476 static TNG_INLINE tng_function_status tng_particle_mapping_get_real_particle
11477 (const tng_trajectory_frame_set_t frame_set,
11478 const int64_t local,
11479 int64_t *real)
11481 int64_t i, n_blocks = frame_set->n_mapping_blocks, first;
11482 tng_particle_mapping_t mapping;
11483 if(n_blocks <= 0)
11485 *real = local;
11486 return(TNG_SUCCESS);
11488 for(i = 0; i < n_blocks; i++)
11490 mapping = &frame_set->mappings[i];
11491 first = mapping->num_first_particle;
11492 if(local < first ||
11493 local >= first + mapping->n_particles)
11495 continue;
11497 *real = mapping->real_particle_numbers[local-first];
11498 return(TNG_SUCCESS);
11500 *real = local;
11501 return(TNG_FAILURE);
11505 * @brief Translate from the real particle numbering to the particle numbering
11506 * used in a frame set.
11507 * @param frame_set is the frame_set containing the mappings to use.
11508 * @param real is the index number of the atom in the molecular system.
11509 * @param local is set to the index of the atom in this frame set.
11510 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the mapping
11511 * cannot be found.
11513 /*static TNG_INLINE tng_function_status tng_particle_mapping_get_local_particle
11514 (const tng_trajectory_frame_set_t frame_set,
11515 const int64_t real,
11516 int64_t *local)
11518 int64_t i, j, n_blocks = frame_set->n_mapping_blocks;
11519 tng_particle_mapping_t mapping;
11520 if(n_blocks <= 0)
11522 *local = real;
11523 return(TNG_SUCCESS);
11525 for(i = 0; i < n_blocks; i++)
11527 mapping = &frame_set->mappings[i];
11528 for(j = mapping->n_particles; j--;)
11530 if(mapping->real_particle_numbers[j] == real)
11532 *local = j;
11533 return(TNG_SUCCESS);
11537 return(TNG_FAILURE);
11541 static tng_function_status tng_file_headers_len_get
11542 (const tng_trajectory_t tng_data,
11543 int64_t *len)
11545 int64_t orig_pos;
11546 tng_gen_block_t block;
11548 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11550 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
11552 return(TNG_CRITICAL);
11555 *len = 0;
11557 orig_pos = ftello(tng_data->input_file);
11559 fseeko(tng_data->input_file, 0, SEEK_SET);
11561 tng_block_init(&block);
11562 /* Read through the headers of non-trajectory blocks (they come before the
11563 * trajectory blocks in the file) */
11564 while (*len < tng_data->input_file_len &&
11565 tng_block_header_read(tng_data, block) != TNG_CRITICAL &&
11566 block->id != -1 &&
11567 block->id != TNG_TRAJECTORY_FRAME_SET)
11569 *len += block->header_contents_size + block->block_contents_size;
11570 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
11573 fseeko(tng_data->input_file, orig_pos, SEEK_SET);
11575 tng_block_destroy(&block);
11577 return(TNG_SUCCESS);
11580 tng_function_status DECLSPECDLLEXPORT tng_file_headers_read
11581 (const tng_trajectory_t tng_data,
11582 const char hash_mode)
11584 int64_t prev_pos = 0;
11585 tng_gen_block_t block;
11587 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11589 tng_data->n_trajectory_frame_sets = 0;
11591 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
11593 return(TNG_CRITICAL);
11596 fseeko(tng_data->input_file, 0, SEEK_SET);
11598 tng_block_init(&block);
11599 /* Non trajectory blocks (they come before the trajectory
11600 * blocks in the file) */
11601 while (prev_pos < tng_data->input_file_len &&
11602 tng_block_header_read(tng_data, block) != TNG_CRITICAL &&
11603 block->id != -1 &&
11604 block->id != TNG_TRAJECTORY_FRAME_SET)
11606 tng_block_read_next(tng_data, block, hash_mode);
11607 prev_pos = ftello(tng_data->input_file);
11610 /* Go back if a trajectory block was encountered */
11611 if(block->id == TNG_TRAJECTORY_FRAME_SET)
11613 fseeko(tng_data->input_file, prev_pos, SEEK_SET);
11616 tng_block_destroy(&block);
11618 return(TNG_SUCCESS);
11621 tng_function_status DECLSPECDLLEXPORT tng_file_headers_write
11622 (const tng_trajectory_t tng_data,
11623 const char hash_mode)
11625 int i;
11626 int64_t len, orig_len, tot_len = 0, data_start_pos, temp_pos = -1;
11627 tng_function_status stat;
11628 tng_gen_block_t block;
11630 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11632 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
11634 return(TNG_CRITICAL);
11637 if(tng_data->n_trajectory_frame_sets > 0)
11639 stat = tng_file_headers_len_get(tng_data, &orig_len);
11640 if(stat != TNG_SUCCESS)
11642 return(stat);
11645 tng_block_init(&block);
11646 block->name = (char *)malloc(TNG_MAX_STR_LEN);
11647 if(!block->name)
11649 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
11650 __FILE__, __LINE__);
11651 tng_block_destroy(&block);
11652 return(TNG_CRITICAL);
11654 strcpy(block->name, "GENERAL INFO");
11655 tng_block_header_len_calculate(tng_data, block, &len);
11656 tot_len += len;
11657 tng_general_info_block_len_calculate(tng_data, &len);
11658 tot_len += len;
11659 strcpy(block->name, "MOLECULES");
11660 tng_block_header_len_calculate(tng_data, block, &len);
11661 tot_len += len;
11662 tng_molecules_block_len_calculate(tng_data, &len);
11663 tot_len += len;
11665 for(i = 0; i < tng_data->n_data_blocks; i++)
11667 strcpy(block->name, tng_data->non_tr_data[i].block_name);
11668 tng_block_header_len_calculate(tng_data, block, &len);
11669 tot_len += len;
11670 tng_data_block_len_calculate(tng_data,
11671 (tng_data_t)&tng_data->non_tr_data[i],
11672 TNG_FALSE, 1, 1, 1, 0, 1,
11673 &data_start_pos,
11674 &len);
11675 tot_len += len;
11677 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
11679 strcpy(block->name, tng_data->non_tr_particle_data[i].block_name);
11680 tng_block_header_len_calculate(tng_data, block, &len);
11681 tot_len += len;
11682 tng_data_block_len_calculate(tng_data,
11683 &tng_data->non_tr_particle_data[i],
11684 TNG_TRUE, 1, 1, 1, 0,
11685 tng_data->n_particles,
11686 &data_start_pos,
11687 &len);
11688 tot_len += len;
11690 tng_block_destroy(&block);
11692 if(tot_len > orig_len)
11694 tng_migrate_data_in_file(tng_data, orig_len+1, tot_len - orig_len, hash_mode);
11695 tng_data->last_trajectory_frame_set_input_file_pos = tng_data->last_trajectory_frame_set_output_file_pos;
11698 stat = tng_reread_frame_set_at_file_pos(tng_data, tng_data->last_trajectory_frame_set_input_file_pos);
11699 if(stat == TNG_CRITICAL)
11701 fprintf(stderr, "TNG library: Cannot read frame set. %s: %d\n",
11702 __FILE__, __LINE__);
11703 return(TNG_CRITICAL);
11706 /* In order to write non-trajectory data the current_trajectory_frame_set_output_file_pos
11707 * must temporarily be reset */
11708 temp_pos = tng_data->current_trajectory_frame_set_output_file_pos;
11709 tng_data->current_trajectory_frame_set_output_file_pos = -1;
11712 if(tng_general_info_block_write(tng_data, hash_mode)
11713 != TNG_SUCCESS)
11715 fprintf(stderr, "TNG library: Error writing general info block of file %s. %s: %d\n",
11716 tng_data->input_file_path, __FILE__, __LINE__);
11717 return(TNG_CRITICAL);
11720 if(tng_molecules_block_write(tng_data, hash_mode)
11721 != TNG_SUCCESS)
11723 fprintf(stderr, "TNG library: Error writing atom names block of file %s. %s: %d\n",
11724 tng_data->input_file_path, __FILE__, __LINE__);
11725 return(TNG_CRITICAL);
11728 /* FIXME: Currently writing non-trajectory data blocks here.
11729 * Should perhaps be moved. */
11730 tng_block_init(&block);
11731 for(i = 0; i < tng_data->n_data_blocks; i++)
11733 block->id = tng_data->non_tr_data[i].block_id;
11734 tng_data_block_write(tng_data, block,
11735 i, TNG_FALSE, 0, hash_mode);
11738 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
11740 block->id = tng_data->non_tr_particle_data[i].block_id;
11741 tng_data_block_write(tng_data, block,
11742 i, TNG_TRUE, 0, hash_mode);
11745 tng_block_destroy(&block);
11747 /* Continue writing at the end of the file. */
11748 fseeko(tng_data->output_file, 0, SEEK_END);
11749 if(temp_pos > 0)
11751 tng_data->current_trajectory_frame_set_output_file_pos = temp_pos;
11754 return(TNG_SUCCESS);
11757 tng_function_status DECLSPECDLLEXPORT tng_block_read_next
11758 (const tng_trajectory_t tng_data,
11759 const tng_gen_block_t block,
11760 const char hash_mode)
11762 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11763 TNG_ASSERT(block, "TNG library: block must be initialised and must not be a NULL pointer.");
11765 switch(block->id)
11767 case TNG_TRAJECTORY_FRAME_SET:
11768 return(tng_frame_set_block_read(tng_data, block, hash_mode));
11769 case TNG_PARTICLE_MAPPING:
11770 return(tng_trajectory_mapping_block_read(tng_data, block, hash_mode));
11771 case TNG_GENERAL_INFO:
11772 return(tng_general_info_block_read(tng_data, block, hash_mode));
11773 case TNG_MOLECULES:
11774 return(tng_molecules_block_read(tng_data, block, hash_mode));
11775 default:
11776 if(block->id >= TNG_TRAJ_BOX_SHAPE)
11778 return(tng_data_block_contents_read(tng_data, block, hash_mode));
11780 else
11782 /* Skip to the next block */
11783 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
11784 return(TNG_FAILURE);
11789 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read
11790 (const tng_trajectory_t tng_data,
11791 const char hash_mode)
11793 int64_t file_pos;
11794 tng_gen_block_t block;
11795 tng_function_status stat;
11797 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11799 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
11801 return(TNG_CRITICAL);
11804 file_pos = ftello(tng_data->input_file);
11806 tng_block_init(&block);
11808 /* Read block headers first to see what block is found. */
11809 stat = tng_block_header_read(tng_data, block);
11810 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET ||
11811 block->id == -1)
11813 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
11814 file_pos, __FILE__, __LINE__);
11815 tng_block_destroy(&block);
11816 return(TNG_CRITICAL);
11819 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
11821 if(tng_block_read_next(tng_data, block,
11822 hash_mode) == TNG_SUCCESS)
11824 tng_data->n_trajectory_frame_sets++;
11825 file_pos = ftello(tng_data->input_file);
11826 /* Read all blocks until next frame set block */
11827 stat = tng_block_header_read(tng_data, block);
11828 while(file_pos < tng_data->input_file_len &&
11829 stat != TNG_CRITICAL &&
11830 block->id != TNG_TRAJECTORY_FRAME_SET &&
11831 block->id != -1)
11833 stat = tng_block_read_next(tng_data, block,
11834 hash_mode);
11835 if(stat != TNG_CRITICAL)
11837 file_pos = ftello(tng_data->input_file);
11838 if(file_pos < tng_data->input_file_len)
11840 stat = tng_block_header_read(tng_data, block);
11844 if(stat == TNG_CRITICAL)
11846 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
11847 file_pos, __FILE__, __LINE__);
11848 tng_block_destroy(&block);
11849 return(stat);
11852 if(block->id == TNG_TRAJECTORY_FRAME_SET)
11854 fseeko(tng_data->input_file, file_pos, SEEK_SET);
11858 tng_block_destroy(&block);
11860 return(TNG_SUCCESS);
11864 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_current_only_data_from_block_id
11865 (const tng_trajectory_t tng_data,
11866 const char hash_mode,
11867 const int64_t block_id)
11869 int64_t file_pos;
11870 tng_gen_block_t block;
11871 tng_function_status stat;
11872 int found_flag = 1;
11874 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11876 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
11878 return(TNG_CRITICAL);
11881 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
11883 if(file_pos < 0)
11885 /* No current frame set. This means that the first frame set must be
11886 * read */
11887 found_flag = 0;
11888 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
11891 if(file_pos > 0)
11893 fseeko(tng_data->input_file,
11894 file_pos,
11895 SEEK_SET);
11897 else
11899 return(TNG_FAILURE);
11902 tng_block_init(&block);
11904 /* Read block headers first to see what block is found. */
11905 stat = tng_block_header_read(tng_data, block);
11906 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11908 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
11909 file_pos, __FILE__, __LINE__);
11910 tng_block_destroy(&block);
11911 return(TNG_CRITICAL);
11913 /* If the current frame set had already been read skip its block contents */
11914 if(found_flag)
11916 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
11918 /* Otherwise read the frame set block */
11919 else
11921 stat = tng_block_read_next(tng_data, block,
11922 hash_mode);
11923 if(stat != TNG_SUCCESS)
11925 fprintf(stderr, "TNG library: Cannot read frame set block. %s: %d\n", __FILE__, __LINE__);
11926 tng_block_destroy(&block);
11927 return(stat);
11930 file_pos = ftello(tng_data->input_file);
11932 found_flag = 0;
11934 /* Read only blocks of the requested ID
11935 * until next frame set block */
11936 stat = tng_block_header_read(tng_data, block);
11937 while(file_pos < tng_data->input_file_len &&
11938 stat != TNG_CRITICAL &&
11939 block->id != TNG_TRAJECTORY_FRAME_SET &&
11940 block->id != -1)
11942 if(block->id == block_id)
11944 stat = tng_block_read_next(tng_data, block,
11945 hash_mode);
11946 if(stat != TNG_CRITICAL)
11948 file_pos = ftello(tng_data->input_file);
11949 found_flag = 1;
11950 if(file_pos < tng_data->input_file_len)
11952 stat = tng_block_header_read(tng_data, block);
11956 else
11958 file_pos += block->block_contents_size + block->header_contents_size;
11959 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
11960 if(file_pos < tng_data->input_file_len)
11962 stat = tng_block_header_read(tng_data, block);
11966 if(stat == TNG_CRITICAL)
11968 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
11969 file_pos, __FILE__, __LINE__);
11970 tng_block_destroy(&block);
11971 return(stat);
11974 if(block->id == TNG_TRAJECTORY_FRAME_SET)
11976 fseeko(tng_data->input_file, file_pos, SEEK_SET);
11979 tng_block_destroy(&block);
11981 if(found_flag)
11983 return(TNG_SUCCESS);
11985 else
11987 return(TNG_FAILURE);
11991 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next
11992 (const tng_trajectory_t tng_data,
11993 const char hash_mode)
11995 int64_t file_pos;
11997 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11999 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12001 return(TNG_CRITICAL);
12004 file_pos = tng_data->current_trajectory_frame_set.next_frame_set_file_pos;
12006 if(file_pos < 0 && tng_data->current_trajectory_frame_set_input_file_pos <= 0)
12008 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
12011 if(file_pos > 0)
12013 fseeko(tng_data->input_file,
12014 file_pos,
12015 SEEK_SET);
12017 else
12019 return(TNG_FAILURE);
12022 return(tng_frame_set_read(tng_data, hash_mode));
12025 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next_only_data_from_block_id
12026 (const tng_trajectory_t tng_data,
12027 const char hash_mode,
12028 const int64_t block_id)
12030 int64_t file_pos;
12031 tng_gen_block_t block;
12032 tng_function_status stat;
12034 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12036 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12038 return(TNG_CRITICAL);
12041 file_pos = tng_data->current_trajectory_frame_set.next_frame_set_file_pos;
12043 if(file_pos < 0 && tng_data->current_trajectory_frame_set_input_file_pos <= 0)
12045 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
12048 if(file_pos > 0)
12050 fseeko(tng_data->input_file,
12051 file_pos,
12052 SEEK_SET);
12054 else
12056 return(TNG_FAILURE);
12059 tng_block_init(&block);
12061 /* Read block headers first to see what block is found. */
12062 stat = tng_block_header_read(tng_data, block);
12063 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12065 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
12066 file_pos, __FILE__, __LINE__);
12067 tng_block_destroy(&block);
12068 return(TNG_CRITICAL);
12071 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
12073 if(tng_block_read_next(tng_data, block,
12074 hash_mode) == TNG_SUCCESS)
12076 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, hash_mode, block_id);
12079 tng_block_destroy(&block);
12081 return(stat);
12084 tng_function_status tng_frame_set_write
12085 (const tng_trajectory_t tng_data,
12086 const char hash_mode)
12088 int i, j;
12089 tng_gen_block_t block;
12090 tng_trajectory_frame_set_t frame_set;
12091 tng_function_status stat;
12093 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12095 frame_set = &tng_data->current_trajectory_frame_set;
12097 if(frame_set->n_written_frames == frame_set->n_frames)
12099 return(TNG_SUCCESS);
12102 tng_data->current_trajectory_frame_set_output_file_pos =
12103 ftello(tng_data->output_file);
12104 tng_data->last_trajectory_frame_set_output_file_pos =
12105 tng_data->current_trajectory_frame_set_output_file_pos;
12107 if(tng_data->current_trajectory_frame_set_output_file_pos <= 0)
12109 return(TNG_FAILURE);
12112 if(tng_data->first_trajectory_frame_set_output_file_pos == -1)
12114 tng_data->first_trajectory_frame_set_output_file_pos =
12115 tng_data->current_trajectory_frame_set_output_file_pos;
12118 tng_block_init(&block);
12120 if(tng_frame_set_block_write(tng_data, block, hash_mode) != TNG_SUCCESS)
12122 tng_block_destroy(&block);
12123 return(TNG_FAILURE);
12126 /* Write non-particle data blocks */
12127 for(i = 0; i<frame_set->n_data_blocks; i++)
12129 block->id = frame_set->tr_data[i].block_id;
12130 tng_data_block_write(tng_data, block, i, TNG_FALSE, 0, hash_mode);
12132 /* Write the mapping blocks and particle data blocks*/
12133 if(frame_set->n_mapping_blocks)
12135 for(i = 0; i < frame_set->n_mapping_blocks; i++)
12137 block->id = TNG_PARTICLE_MAPPING;
12138 if(frame_set->mappings[i].n_particles > 0)
12140 tng_trajectory_mapping_block_write(tng_data, block, i, hash_mode);
12141 for(j = 0; j<frame_set->n_particle_data_blocks; j++)
12143 block->id = frame_set->tr_particle_data[j].block_id;
12144 tng_data_block_write(tng_data, block,
12145 j, TNG_TRUE, &frame_set->mappings[i],
12146 hash_mode);
12151 else
12153 for(i = 0; i<frame_set->n_particle_data_blocks; i++)
12155 block->id = frame_set->tr_particle_data[i].block_id;
12156 tng_data_block_write(tng_data, block,
12157 i, TNG_TRUE, 0, hash_mode);
12162 /* Update pointers in the general info block */
12163 stat = tng_header_pointers_update(tng_data, hash_mode);
12165 if(stat == TNG_SUCCESS)
12167 stat = tng_frame_set_pointers_update(tng_data, hash_mode);
12170 tng_block_destroy(&block);
12172 frame_set->n_unwritten_frames = 0;
12174 fflush(tng_data->output_file);
12176 return(stat);
12179 tng_function_status DECLSPECDLLEXPORT tng_frame_set_premature_write
12180 (const tng_trajectory_t tng_data,
12181 const char hash_mode)
12183 tng_trajectory_frame_set_t frame_set;
12185 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12187 frame_set = &tng_data->current_trajectory_frame_set;
12189 if(frame_set->n_unwritten_frames == 0)
12191 return(TNG_SUCCESS);
12193 frame_set->n_frames = frame_set->n_unwritten_frames;
12195 return(tng_frame_set_write(tng_data, hash_mode));
12198 tng_function_status DECLSPECDLLEXPORT tng_frame_set_new
12199 (const tng_trajectory_t tng_data,
12200 const int64_t first_frame,
12201 const int64_t n_frames)
12203 tng_gen_block_t block;
12204 tng_trajectory_frame_set_t frame_set;
12205 FILE *temp = tng_data->input_file;
12206 int64_t curr_file_pos;
12208 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12209 TNG_ASSERT(first_frame >= 0, "TNG library: first_frame must be >= 0.");
12210 TNG_ASSERT(n_frames >= 0, "TNG library: n_frames must be >= 0.");
12212 frame_set = &tng_data->current_trajectory_frame_set;
12214 curr_file_pos = ftello(tng_data->output_file);
12216 if(curr_file_pos <= 10)
12218 tng_file_headers_write(tng_data, TNG_USE_HASH);
12221 /* Set pointer to previous frame set to the one that was loaded
12222 * before.
12223 * FIXME: This is a bit risky. If they are not added in order
12224 * it will be wrong. */
12225 if(tng_data->n_trajectory_frame_sets)
12227 frame_set->prev_frame_set_file_pos =
12228 tng_data->last_trajectory_frame_set_output_file_pos;
12231 frame_set->next_frame_set_file_pos = -1;
12233 tng_data->current_trajectory_frame_set_output_file_pos =
12234 ftello(tng_data->output_file);
12236 tng_data->n_trajectory_frame_sets++;
12238 /* Set the medium range pointers */
12239 if(tng_data->n_trajectory_frame_sets == tng_data->medium_stride_length + 1)
12241 frame_set->medium_stride_prev_frame_set_file_pos =
12242 tng_data->first_trajectory_frame_set_output_file_pos;
12244 else if(tng_data->n_trajectory_frame_sets > tng_data->medium_stride_length + 1)
12246 /* FIXME: Currently only working if the previous frame set has its
12247 * medium stride pointer already set. This might need some fixing. */
12248 if(frame_set->medium_stride_prev_frame_set_file_pos != -1 &&
12249 frame_set->medium_stride_prev_frame_set_file_pos != 0)
12251 tng_block_init(&block);
12252 tng_data->input_file = tng_data->output_file;
12254 curr_file_pos = ftello(tng_data->output_file);
12255 fseeko(tng_data->output_file,
12256 frame_set->medium_stride_prev_frame_set_file_pos,
12257 SEEK_SET);
12259 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
12261 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
12262 __FILE__, __LINE__);
12263 tng_data->input_file = temp;
12264 tng_block_destroy(&block);
12265 return(TNG_CRITICAL);
12268 /* Read the next frame set from the previous frame set and one
12269 * medium stride step back */
12270 fseeko(tng_data->output_file, block->block_contents_size - (6 *
12271 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
12272 if(fread(&frame_set->medium_stride_prev_frame_set_file_pos,
12273 sizeof(frame_set->medium_stride_prev_frame_set_file_pos),
12274 1, tng_data->output_file) == 0)
12276 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
12277 tng_data->input_file = temp;
12278 tng_block_destroy(&block);
12279 return(TNG_CRITICAL);
12282 if(tng_data->input_endianness_swap_func_64)
12284 if(tng_data->input_endianness_swap_func_64(tng_data,
12285 (uint64_t *)&frame_set->medium_stride_prev_frame_set_file_pos)
12286 != TNG_SUCCESS)
12288 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
12289 __FILE__, __LINE__);
12293 tng_block_destroy(&block);
12295 /* Set the long range pointers */
12296 if(tng_data->n_trajectory_frame_sets == tng_data->long_stride_length + 1)
12298 frame_set->long_stride_prev_frame_set_file_pos =
12299 tng_data->first_trajectory_frame_set_output_file_pos;
12301 else if(tng_data->n_trajectory_frame_sets > tng_data->medium_stride_length + 1)
12303 /* FIXME: Currently only working if the previous frame set has its
12304 * long stride pointer already set. This might need some fixing. */
12305 if(frame_set->long_stride_prev_frame_set_file_pos != -1 &&
12306 frame_set->long_stride_prev_frame_set_file_pos != 0)
12308 tng_block_init(&block);
12309 tng_data->input_file = tng_data->output_file;
12311 fseeko(tng_data->output_file,
12312 frame_set->long_stride_prev_frame_set_file_pos,
12313 SEEK_SET);
12315 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
12317 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
12318 __FILE__, __LINE__);
12319 tng_data->input_file = temp;
12320 tng_block_destroy(&block);
12321 return(TNG_CRITICAL);
12324 /* Read the next frame set from the previous frame set and one
12325 * long stride step back */
12326 fseeko(tng_data->output_file, block->block_contents_size - (6 *
12327 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
12329 tng_block_destroy(&block);
12331 if(fread(&frame_set->long_stride_prev_frame_set_file_pos,
12332 sizeof(frame_set->long_stride_prev_frame_set_file_pos),
12333 1, tng_data->output_file) == 0)
12335 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
12336 tng_data->input_file = temp;
12337 return(TNG_CRITICAL);
12340 if(tng_data->input_endianness_swap_func_64)
12342 if(tng_data->input_endianness_swap_func_64(tng_data,
12343 (uint64_t *)&frame_set->long_stride_prev_frame_set_file_pos)
12344 != TNG_SUCCESS)
12346 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
12347 __FILE__, __LINE__);
12354 tng_data->input_file = temp;
12355 fseeko(tng_data->output_file, curr_file_pos, SEEK_SET);
12359 frame_set->first_frame = first_frame;
12360 frame_set->n_frames = n_frames;
12361 frame_set->n_written_frames = 0;
12362 frame_set->n_unwritten_frames = 0;
12363 frame_set->first_frame_time = -1;
12365 if(tng_data->first_trajectory_frame_set_output_file_pos == -1 ||
12366 tng_data->first_trajectory_frame_set_output_file_pos == 0)
12368 tng_data->first_trajectory_frame_set_output_file_pos =
12369 tng_data->current_trajectory_frame_set_output_file_pos;
12371 /* FIXME: Should check the frame number instead of the file_pos,
12372 * in case frame sets are not in order */
12373 if(tng_data->last_trajectory_frame_set_output_file_pos == -1 ||
12374 tng_data->last_trajectory_frame_set_output_file_pos == 0 ||
12375 tng_data->last_trajectory_frame_set_output_file_pos <
12376 tng_data->current_trajectory_frame_set_output_file_pos)
12378 tng_data->last_trajectory_frame_set_output_file_pos =
12379 tng_data->current_trajectory_frame_set_output_file_pos;
12382 return(TNG_SUCCESS);
12385 tng_function_status DECLSPECDLLEXPORT tng_frame_set_with_time_new
12386 (const tng_trajectory_t tng_data,
12387 const int64_t first_frame,
12388 const int64_t n_frames,
12389 const double first_frame_time)
12391 tng_function_status stat;
12393 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12394 TNG_ASSERT(first_frame >= 0, "TNG library: first_frame must be >= 0.");
12395 TNG_ASSERT(n_frames >= 0, "TNG library: n_frames must be >= 0.");
12396 TNG_ASSERT(first_frame_time >= 0, "TNG library: first_frame_time must be >= 0.");
12399 stat = tng_frame_set_new(tng_data, first_frame, n_frames);
12400 if(stat != TNG_SUCCESS)
12402 return(stat);
12404 stat = tng_frame_set_first_frame_time_set(tng_data, first_frame_time);
12406 return(stat);
12409 tng_function_status DECLSPECDLLEXPORT tng_frame_set_first_frame_time_set
12410 (const tng_trajectory_t tng_data,
12411 const double first_frame_time)
12413 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12414 TNG_ASSERT(first_frame_time >= 0, "TNG library: first_frame_time must be >= 0.");
12416 tng_data->current_trajectory_frame_set.first_frame_time = first_frame_time;
12418 return(TNG_SUCCESS);
12421 tng_function_status DECLSPECDLLEXPORT tng_first_frame_nr_of_next_frame_set_get
12422 (const tng_trajectory_t tng_data,
12423 int64_t *frame)
12425 int64_t file_pos, next_frame_set_file_pos;
12426 tng_gen_block_t block;
12427 tng_function_status stat;
12429 tng_trajectory_frame_set_t frame_set;
12431 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12432 TNG_ASSERT(tng_data->input_file, "TNG library: An input file must be open to find the next frame set");
12433 TNG_ASSERT(frame, "TNG library: frame must not be a NULL pointer");
12435 file_pos = ftello(tng_data->input_file);
12437 if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
12439 next_frame_set_file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
12441 else
12443 frame_set = &tng_data->current_trajectory_frame_set;
12444 next_frame_set_file_pos = frame_set->next_frame_set_file_pos;
12447 if(next_frame_set_file_pos <= 0)
12449 return(TNG_FAILURE);
12452 fseeko(tng_data->input_file, next_frame_set_file_pos, SEEK_SET);
12453 /* Read block headers first to see that a frame set block is found. */
12454 tng_block_init(&block);
12455 stat = tng_block_header_read(tng_data, block);
12456 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12458 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
12459 file_pos, __FILE__, __LINE__);
12460 return(TNG_CRITICAL);
12462 /* if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
12464 tng_block_read_next(tng_data, block, TNG_USE_HASH);
12466 tng_block_destroy(&block);
12468 if(fread(frame, sizeof(int64_t), 1, tng_data->input_file) == 0)
12470 fprintf(stderr, "TNG library: Cannot read first frame of next frame set. %s: %d\n",
12471 __FILE__, __LINE__);
12472 return(TNG_CRITICAL);
12474 fseeko(tng_data->input_file, file_pos, SEEK_SET);
12476 return(TNG_SUCCESS);
12479 static tng_function_status tng_gen_data_block_add
12480 (const tng_trajectory_t tng_data,
12481 const int64_t id,
12482 const tng_bool is_particle_data,
12483 const char *block_name,
12484 const char datatype,
12485 const char block_type_flag,
12486 int64_t n_frames,
12487 const int64_t n_values_per_frame,
12488 int64_t stride_length,
12489 const int64_t num_first_particle,
12490 const int64_t n_particles,
12491 const int64_t codec_id,
12492 void *new_data)
12494 int i, size, len;
12495 int64_t j, k;
12496 int64_t tot_n_particles, n_frames_div;
12497 char ***first_dim_values, **second_dim_values;
12498 tng_trajectory_frame_set_t frame_set;
12499 tng_data_t data;
12500 char *new_data_c = (char *)new_data;
12501 tng_function_status stat;
12503 frame_set = &tng_data->current_trajectory_frame_set;
12505 if(stride_length <= 0)
12507 stride_length = 1;
12510 if(is_particle_data)
12512 stat = tng_particle_data_find(tng_data, id, &data);
12514 else
12516 stat = tng_data_find(tng_data, id, &data);
12518 /* If the block does not exist, create it */
12519 if(stat != TNG_SUCCESS)
12521 if(is_particle_data)
12523 stat = tng_particle_data_block_create(tng_data, block_type_flag);
12525 else
12527 stat = tng_data_block_create(tng_data, block_type_flag);
12530 if(stat != TNG_SUCCESS)
12532 fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
12533 __FILE__, __LINE__);
12534 return(TNG_CRITICAL);
12536 if(is_particle_data)
12538 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
12540 data = &frame_set->tr_particle_data[frame_set->
12541 n_particle_data_blocks - 1];
12543 else
12545 data = &tng_data->non_tr_particle_data[tng_data->
12546 n_particle_data_blocks - 1];
12549 else
12551 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
12553 data = &frame_set->tr_data[frame_set->n_data_blocks - 1];
12555 else
12557 data = &tng_data->non_tr_data[tng_data->n_data_blocks - 1];
12560 data->block_id = id;
12562 data->block_name = (char *)malloc(strlen(block_name) + 1);
12563 if(!data->block_name)
12565 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
12566 __FILE__, __LINE__);
12567 return(TNG_CRITICAL);
12569 strncpy(data->block_name, block_name, strlen(block_name) + 1);
12571 data->values = 0;
12572 /* FIXME: Memory leak from strings. */
12573 data->strings = 0;
12574 data->last_retrieved_frame = -1;
12577 data->datatype = datatype;
12578 data->stride_length = tng_max_i64(stride_length, 1);
12579 data->n_values_per_frame = n_values_per_frame;
12580 data->n_frames = n_frames;
12581 if(is_particle_data)
12583 data->dependency = TNG_PARTICLE_DEPENDENT;
12585 else
12587 data->dependency = 0;
12589 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
12590 (n_frames > 1 ||
12591 frame_set->n_frames == n_frames ||
12592 stride_length > 1))
12594 data->dependency += TNG_FRAME_DEPENDENT;
12596 data->codec_id = codec_id;
12597 data->compression_multiplier = 1.0;
12598 /* FIXME: This can cause problems. */
12599 data->first_frame_with_data = frame_set->first_frame;
12601 if(is_particle_data)
12603 if(block_type_flag == TNG_TRAJECTORY_BLOCK && tng_data->var_num_atoms_flag)
12605 tot_n_particles = frame_set->n_particles;
12607 else
12609 tot_n_particles = tng_data->n_particles;
12612 /* This is just to keep the compiler happy - avoid it considering tot_n_particles
12613 * uninitialized. */
12614 else
12616 tot_n_particles = 0;
12619 /* If data values are supplied add that data to the data block. */
12620 if(new_data_c)
12622 /* Allocate memory */
12623 if(is_particle_data)
12625 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
12626 stride_length, tot_n_particles,
12627 n_values_per_frame);
12629 else
12631 stat = tng_allocate_data_mem(tng_data, data, n_frames, stride_length,
12632 n_values_per_frame);
12634 if(stat != TNG_SUCCESS)
12636 fprintf(stderr, "TNG library: Cannot allocate particle data memory. %s: %d\n",
12637 __FILE__, __LINE__);
12638 return(TNG_CRITICAL);
12641 if(n_frames > frame_set->n_unwritten_frames)
12643 frame_set->n_unwritten_frames = n_frames;
12646 n_frames_div = (n_frames % stride_length) ?
12647 n_frames / stride_length + 1:
12648 n_frames / stride_length;
12650 if(datatype == TNG_CHAR_DATA)
12652 if(is_particle_data)
12654 for(i = 0; i < n_frames_div; i++)
12656 first_dim_values = data->strings[i];
12657 for(j = num_first_particle; j < num_first_particle + n_particles;
12658 j++)
12660 second_dim_values = first_dim_values[j];
12661 for(k = 0; k < n_values_per_frame; k++)
12663 len = tng_min_size(strlen(new_data_c) + 1,
12664 TNG_MAX_STR_LEN);
12665 if(second_dim_values[k])
12667 free(second_dim_values[k]);
12669 second_dim_values[k] = (char *)malloc(len);
12670 if(!second_dim_values[k])
12672 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
12673 __FILE__, __LINE__);
12674 return(TNG_CRITICAL);
12676 strncpy(second_dim_values[k],
12677 new_data_c, len);
12678 new_data_c += len;
12683 else
12685 for(i = 0; i < n_frames_div; i++)
12687 second_dim_values = data->strings[0][i];
12688 for(j = 0; j < n_values_per_frame; j++)
12690 len = tng_min_size(strlen(new_data_c) + 1,
12691 TNG_MAX_STR_LEN);
12692 if(second_dim_values[j])
12694 free(second_dim_values[j]);
12696 second_dim_values[j] = (char *)malloc(len);
12697 if(!second_dim_values[j])
12699 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
12700 __FILE__, __LINE__);
12701 return(TNG_CRITICAL);
12703 strncpy(second_dim_values[j],
12704 new_data_c, len);
12705 new_data_c += len;
12710 else
12712 switch(datatype)
12714 case TNG_INT_DATA:
12715 size = sizeof(int64_t);
12716 break;
12717 case TNG_FLOAT_DATA:
12718 size = sizeof(float);
12719 break;
12720 case TNG_DOUBLE_DATA:
12721 default:
12722 size = sizeof(double);
12725 if(is_particle_data)
12727 memcpy(data->values, new_data, size * n_frames_div *
12728 n_particles * n_values_per_frame);
12730 else
12732 memcpy(data->values, new_data, size * n_frames_div *
12733 n_values_per_frame);
12738 return(TNG_SUCCESS);
12741 tng_function_status DECLSPECDLLEXPORT tng_data_block_add
12742 (const tng_trajectory_t tng_data,
12743 const int64_t id,
12744 const char *block_name,
12745 const char datatype,
12746 const char block_type_flag,
12747 int64_t n_frames,
12748 const int64_t n_values_per_frame,
12749 int64_t stride_length,
12750 const int64_t codec_id,
12751 void *new_data)
12753 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12754 TNG_ASSERT(block_name, "TNG library: block_name must not be a NULL pointer.");
12755 TNG_ASSERT(n_values_per_frame > 0, "TNG library: n_values_per_frame must be a positive integer.");
12757 return(tng_gen_data_block_add(tng_data, id, TNG_FALSE, block_name, datatype,
12758 block_type_flag, n_frames, n_values_per_frame,
12759 stride_length, 0, 0, codec_id, new_data));
12762 tng_function_status DECLSPECDLLEXPORT tng_particle_data_block_add
12763 (const tng_trajectory_t tng_data,
12764 const int64_t id,
12765 const char *block_name,
12766 const char datatype,
12767 const char block_type_flag,
12768 int64_t n_frames,
12769 const int64_t n_values_per_frame,
12770 int64_t stride_length,
12771 const int64_t num_first_particle,
12772 const int64_t n_particles,
12773 const int64_t codec_id,
12774 void *new_data)
12776 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12777 TNG_ASSERT(block_name, "TNG library: block_name mustnot be a NULL pointer.");
12778 TNG_ASSERT(n_values_per_frame > 0, "TNG library: n_values_per_frame must be a positive integer.");
12779 TNG_ASSERT(num_first_particle >= 0, "TNG library: num_first_particle must be >= 0.");
12780 TNG_ASSERT(n_particles >= 0, "TNG library: n_particles must be >= 0.");
12782 return(tng_gen_data_block_add(tng_data, id, TNG_TRUE, block_name, datatype,
12783 block_type_flag, n_frames, n_values_per_frame,
12784 stride_length, num_first_particle, n_particles,
12785 codec_id, new_data));
12788 tng_function_status DECLSPECDLLEXPORT tng_data_block_name_get
12789 (const tng_trajectory_t tng_data,
12790 const int64_t block_id,
12791 char *name,
12792 const int max_len)
12794 int64_t i;
12795 tng_trajectory_frame_set_t frame_set;
12796 tng_function_status stat;
12797 tng_data_t data;
12798 int block_type = -1;
12800 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12801 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
12803 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
12805 data = &tng_data->non_tr_particle_data[i];
12806 if(data->block_id == block_id)
12808 strncpy(name, data->block_name, max_len);
12809 name[max_len - 1] = '\0';
12810 return(TNG_SUCCESS);
12813 for(i = 0; i < tng_data->n_data_blocks; i++)
12815 data = &tng_data->non_tr_data[i];
12816 if(data->block_id == block_id)
12818 strncpy(name, data->block_name, max_len);
12819 name[max_len - 1] = '\0';
12820 return(TNG_SUCCESS);
12824 frame_set = &tng_data->current_trajectory_frame_set;
12826 stat = tng_particle_data_find(tng_data, block_id, &data);
12827 if(stat == TNG_SUCCESS)
12829 block_type = TNG_PARTICLE_BLOCK_DATA;
12831 else
12833 stat = tng_data_find(tng_data, block_id, &data);
12834 if(stat == TNG_SUCCESS)
12836 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
12838 else
12840 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
12841 if(stat != TNG_SUCCESS)
12843 return(stat);
12845 stat = tng_particle_data_find(tng_data, block_id, &data);
12846 if(stat == TNG_SUCCESS)
12848 block_type = TNG_PARTICLE_BLOCK_DATA;
12850 else
12852 stat = tng_data_find(tng_data, block_id, &data);
12853 if(stat == TNG_SUCCESS)
12855 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
12860 if(block_type == TNG_PARTICLE_BLOCK_DATA)
12862 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
12864 data = &frame_set->tr_particle_data[i];
12865 if(data->block_id == block_id)
12867 strncpy(name, data->block_name, max_len);
12868 name[max_len - 1] = '\0';
12869 return(TNG_SUCCESS);
12873 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
12875 for(i = 0; i < frame_set->n_data_blocks; i++)
12877 data = &frame_set->tr_data[i];
12878 if(data->block_id == block_id)
12880 strncpy(name, data->block_name, max_len);
12881 name[max_len - 1] = '\0';
12882 return(TNG_SUCCESS);
12887 return(TNG_FAILURE);
12890 tng_function_status DECLSPECDLLEXPORT tng_data_block_dependency_get
12891 (const tng_trajectory_t tng_data,
12892 const int64_t block_id,
12893 int *block_dependency)
12895 int64_t i;
12896 tng_function_status stat;
12897 tng_data_t data;
12899 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12900 TNG_ASSERT(block_dependency, "TNG library: block_dependency must not be a NULL pointer.");
12902 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
12904 data = &tng_data->non_tr_particle_data[i];
12905 if(data->block_id == block_id)
12907 *block_dependency = TNG_PARTICLE_DEPENDENT;
12908 return(TNG_SUCCESS);
12911 for(i = 0; i < tng_data->n_data_blocks; i++)
12913 data = &tng_data->non_tr_data[i];
12914 if(data->block_id == block_id)
12916 *block_dependency = 0;
12917 return(TNG_SUCCESS);
12921 stat = tng_particle_data_find(tng_data, block_id, &data);
12922 if(stat == TNG_SUCCESS)
12924 *block_dependency = TNG_PARTICLE_DEPENDENT + TNG_FRAME_DEPENDENT;
12925 return(TNG_SUCCESS);
12927 else
12929 stat = tng_data_find(tng_data, block_id, &data);
12930 if(stat == TNG_SUCCESS)
12932 *block_dependency = TNG_FRAME_DEPENDENT;
12933 return(TNG_SUCCESS);
12935 else
12937 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
12938 if(stat != TNG_SUCCESS)
12940 return(stat);
12942 stat = tng_particle_data_find(tng_data, block_id, &data);
12943 if(stat == TNG_SUCCESS)
12945 *block_dependency = TNG_PARTICLE_DEPENDENT + TNG_FRAME_DEPENDENT;
12946 return(TNG_SUCCESS);
12948 else
12950 stat = tng_data_find(tng_data, block_id, &data);
12951 if(stat == TNG_SUCCESS)
12953 *block_dependency = TNG_FRAME_DEPENDENT;
12954 return(TNG_SUCCESS);
12960 return(TNG_FAILURE);
12963 tng_function_status DECLSPECDLLEXPORT tng_data_block_num_values_per_frame_get
12964 (const tng_trajectory_t tng_data,
12965 const int64_t block_id,
12966 int64_t *n_values_per_frame)
12968 int64_t i;
12969 tng_function_status stat;
12970 tng_data_t data;
12972 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12973 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
12975 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
12977 data = &tng_data->non_tr_particle_data[i];
12978 if(data->block_id == block_id)
12980 *n_values_per_frame = data->n_values_per_frame;
12981 return(TNG_SUCCESS);
12984 for(i = 0; i < tng_data->n_data_blocks; i++)
12986 data = &tng_data->non_tr_data[i];
12987 if(data->block_id == block_id)
12989 *n_values_per_frame = data->n_values_per_frame;
12990 return(TNG_SUCCESS);
12994 stat = tng_particle_data_find(tng_data, block_id, &data);
12995 if(stat == TNG_SUCCESS)
12997 *n_values_per_frame = data->n_values_per_frame;
12998 return(TNG_SUCCESS);
13000 else
13002 stat = tng_data_find(tng_data, block_id, &data);
13003 if(stat == TNG_SUCCESS)
13005 *n_values_per_frame = data->n_values_per_frame;
13006 return(TNG_SUCCESS);
13008 else
13010 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
13011 if(stat != TNG_SUCCESS)
13013 return(stat);
13015 stat = tng_particle_data_find(tng_data, block_id, &data);
13016 if(stat == TNG_SUCCESS)
13018 *n_values_per_frame = data->n_values_per_frame;
13019 return(TNG_SUCCESS);
13021 else
13023 stat = tng_data_find(tng_data, block_id, &data);
13024 if(stat == TNG_SUCCESS)
13026 *n_values_per_frame = data->n_values_per_frame;
13027 return(TNG_SUCCESS);
13033 return(TNG_FAILURE);
13036 tng_function_status DECLSPECDLLEXPORT tng_frame_set_n_frames_of_data_block_get
13037 (const tng_trajectory_t tng_data,
13038 const int64_t block_id,
13039 int64_t *n_frames)
13041 tng_gen_block_t block;
13042 tng_function_status stat;
13043 char datatype, dependency, sparse_data;
13044 int64_t n_values, codec_id, first_frame_with_data, stride_length, curr_n_frames;
13045 int64_t num_first_particle, block_n_particles;
13046 double multiplier;
13047 md5_state_t md5_state;
13048 int found = TNG_FALSE;
13050 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13052 tng_block_init(&block);
13054 stat = tng_block_header_read(tng_data, block);
13055 /* If the block header could not be read the reading position might not have been
13056 * at the start of a block. Try again from the file position of the current frame
13057 * set. */
13058 if(stat != TNG_SUCCESS)
13060 fseeko(tng_data->input_file, tng_data->current_trajectory_frame_set_input_file_pos, SEEK_SET);
13061 stat = tng_block_header_read(tng_data, block);
13062 if(stat != TNG_SUCCESS)
13064 tng_block_destroy(&block);
13065 return(stat);
13068 if(block->id == TNG_TRAJECTORY_FRAME_SET)
13070 stat = tng_block_read_next(tng_data, block, TNG_SKIP_HASH);
13071 if(stat != TNG_SUCCESS)
13073 tng_block_destroy(&block);
13074 return(stat);
13076 stat = tng_block_header_read(tng_data, block);
13078 while(stat == TNG_SUCCESS && block->id != TNG_TRAJECTORY_FRAME_SET && found == TNG_FALSE)
13080 if(block->id == block_id)
13082 stat = tng_data_block_meta_information_read(tng_data, &datatype,
13083 &dependency, &sparse_data,
13084 &n_values, &codec_id,
13085 &first_frame_with_data,
13086 &stride_length, &curr_n_frames,
13087 &num_first_particle,
13088 &block_n_particles,
13089 &multiplier, TNG_SKIP_HASH,
13090 &md5_state);
13091 if(stat == TNG_SUCCESS)
13093 found = TNG_TRUE;
13096 else
13098 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
13099 stat = tng_block_header_read(tng_data, block);
13102 if(found == TNG_TRUE)
13104 *n_frames = (tng_data->current_trajectory_frame_set.n_frames -
13105 (tng_data->current_trajectory_frame_set.first_frame - first_frame_with_data)) / stride_length;
13107 else if(stat == TNG_SUCCESS)
13109 *n_frames = 0;
13112 tng_block_destroy(&block);
13114 return(stat);
13117 static tng_function_status tng_frame_gen_data_write
13118 (const tng_trajectory_t tng_data,
13119 const int64_t frame_nr,
13120 const int64_t block_id,
13121 const tng_bool is_particle_data,
13122 const int64_t val_first_particle,
13123 const int64_t val_n_particles,
13124 const void *values,
13125 const char hash_mode)
13127 int64_t header_pos, file_pos, tot_n_particles;
13128 int64_t output_file_len, n_values_per_frame, size, contents_size;
13129 int64_t header_size, temp_first, temp_last;
13130 int64_t mapping_block_end_pos, num_first_particle, block_n_particles;
13131 int64_t i, last_frame, temp_current, write_n_particles;
13132 tng_gen_block_t block;
13133 tng_trajectory_frame_set_t frame_set;
13134 FILE *temp = tng_data->input_file;
13135 struct tng_data data;
13136 tng_function_status stat;
13137 tng_particle_mapping_t mapping;
13138 char dependency, sparse_data, datatype;
13139 void *copy;
13141 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
13143 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
13144 __FILE__, __LINE__);
13145 return(TNG_CRITICAL);
13148 temp_first = tng_data->first_trajectory_frame_set_input_file_pos;
13149 temp_last = tng_data->last_trajectory_frame_set_input_file_pos;
13150 temp_current = tng_data->current_trajectory_frame_set_input_file_pos;
13151 tng_data->first_trajectory_frame_set_input_file_pos =
13152 tng_data->first_trajectory_frame_set_output_file_pos;
13153 tng_data->last_trajectory_frame_set_input_file_pos =
13154 tng_data->last_trajectory_frame_set_output_file_pos;
13155 tng_data->current_trajectory_frame_set_input_file_pos =
13156 tng_data->current_trajectory_frame_set_output_file_pos;
13158 tng_data->input_file = tng_data->output_file;
13160 stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
13162 frame_set = &tng_data->current_trajectory_frame_set;
13164 if(stat != TNG_SUCCESS)
13166 last_frame = frame_set->first_frame +
13167 frame_set->n_frames - 1;
13168 /* If the wanted frame would be in the frame set after the last
13169 * frame set create a new frame set. */
13170 if(stat == TNG_FAILURE &&
13171 last_frame < frame_nr)
13172 /* (last_frame < frame_nr &&
13173 tng_data->current_trajectory_frame_set.first_frame +
13174 tng_data->frame_set_n_frames >= frame_nr))*/
13176 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
13178 last_frame = frame_nr - 1;
13180 tng_frame_set_new(tng_data,
13181 last_frame+1,
13182 tng_data->frame_set_n_frames);
13183 file_pos = ftello(tng_data->output_file);
13184 fseeko(tng_data->output_file, 0, SEEK_END);
13185 output_file_len = ftello(tng_data->output_file);
13186 fseeko(tng_data->output_file, file_pos, SEEK_SET);
13188 /* Read mapping blocks from the last frame set */
13189 tng_block_init(&block);
13191 stat = tng_block_header_read(tng_data, block);
13192 while(file_pos < output_file_len &&
13193 stat != TNG_CRITICAL &&
13194 block->id != TNG_TRAJECTORY_FRAME_SET &&
13195 block->id != -1)
13197 if(block->id == TNG_PARTICLE_MAPPING)
13199 tng_trajectory_mapping_block_read(tng_data, block,
13200 hash_mode);
13202 else
13204 fseeko(tng_data->output_file, block->block_contents_size,
13205 SEEK_CUR);
13207 file_pos = ftello(tng_data->output_file);
13208 if(file_pos < output_file_len)
13210 stat = tng_block_header_read(tng_data, block);
13214 tng_block_destroy(&block);
13215 /* Write the frame set to disk */
13216 if(tng_frame_set_write(tng_data, hash_mode) != TNG_SUCCESS)
13218 fprintf(stderr, "TNG library: Error writing frame set. %s: %d\n", __FILE__, __LINE__);
13219 return(TNG_CRITICAL);
13222 else
13224 tng_data->input_file = temp;
13225 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13226 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13227 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13228 return(stat);
13232 tng_block_init(&block);
13234 file_pos = tng_data->current_trajectory_frame_set_output_file_pos;
13236 fseeko(tng_data->output_file, 0, SEEK_END);
13237 output_file_len = ftello(tng_data->output_file);
13238 fseeko(tng_data->output_file, file_pos, SEEK_SET);
13240 /* Read past the frame set block first */
13241 stat = tng_block_header_read(tng_data, block);
13242 if(stat == TNG_CRITICAL)
13244 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
13245 file_pos, __FILE__, __LINE__);
13246 tng_block_destroy(&block);
13247 tng_data->input_file = temp;
13249 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13250 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13251 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13252 return(stat);
13254 fseeko(tng_data->output_file, block->block_contents_size,
13255 SEEK_CUR);
13257 if(is_particle_data == TNG_TRUE)
13259 if(tng_data->var_num_atoms_flag)
13261 tot_n_particles = frame_set->n_particles;
13263 else
13265 tot_n_particles = tng_data->n_particles;
13268 if(val_n_particles < tot_n_particles)
13270 mapping_block_end_pos = -1;
13271 /* Read all mapping blocks to find the right place to put the data */
13272 stat = tng_block_header_read(tng_data, block);
13273 while(file_pos < output_file_len &&
13274 stat != TNG_CRITICAL &&
13275 block->id != TNG_TRAJECTORY_FRAME_SET &&
13276 block->id != -1)
13278 if(block->id == TNG_PARTICLE_MAPPING)
13280 tng_trajectory_mapping_block_read(tng_data, block, hash_mode);
13282 else
13284 fseeko(tng_data->output_file, block->block_contents_size,
13285 SEEK_CUR);
13287 file_pos = ftello(tng_data->output_file);
13288 if(block->id == TNG_PARTICLE_MAPPING)
13290 mapping = &frame_set->mappings[frame_set->n_mapping_blocks - 1];
13291 if(val_first_particle >= mapping->num_first_particle &&
13292 val_first_particle < mapping->num_first_particle +
13293 mapping->n_particles &&
13294 val_first_particle + val_n_particles <=
13295 mapping->num_first_particle + mapping->n_particles)
13297 mapping_block_end_pos = file_pos;
13300 if(file_pos < output_file_len)
13302 stat = tng_block_header_read(tng_data, block);
13305 if(stat == TNG_CRITICAL)
13307 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
13308 file_pos, __FILE__, __LINE__);
13309 tng_block_destroy(&block);
13310 tng_data->input_file = temp;
13312 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13313 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13314 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13315 return(stat);
13317 if(mapping_block_end_pos < 0)
13319 tng_block_destroy(&block);
13320 tng_data->input_file = temp;
13322 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13323 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13324 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13325 return(TNG_FAILURE);
13327 fseeko(tng_data->output_file, mapping_block_end_pos, SEEK_SET);
13331 /* Read all block headers until next frame set block or
13332 * until the wanted block id is found */
13333 stat = tng_block_header_read(tng_data, block);
13334 while(file_pos < output_file_len &&
13335 stat != TNG_CRITICAL &&
13336 block->id != block_id &&
13337 (is_particle_data != TNG_TRUE || block->id != TNG_PARTICLE_MAPPING) &&
13338 block->id != TNG_TRAJECTORY_FRAME_SET &&
13339 block->id != -1)
13341 fseeko(tng_data->output_file, block->block_contents_size, SEEK_CUR);
13342 file_pos = ftello(tng_data->output_file);
13343 if(file_pos < output_file_len)
13345 stat = tng_block_header_read(tng_data, block);
13348 if(stat == TNG_CRITICAL)
13350 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
13351 file_pos, __FILE__, __LINE__);
13352 tng_block_destroy(&block);
13353 tng_data->input_file = temp;
13354 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13355 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13356 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13357 return(stat);
13360 contents_size = block->block_contents_size;
13361 header_size = block->header_contents_size;
13363 header_pos = ftello(tng_data->output_file) - header_size;
13364 frame_set = &tng_data->current_trajectory_frame_set;
13366 if(tng_file_input_numerical(tng_data, &datatype,
13367 sizeof(datatype),
13368 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13370 tng_block_destroy(&block);
13371 return(TNG_CRITICAL);
13373 if(tng_file_input_numerical(tng_data, &dependency,
13374 sizeof(dependency),
13375 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13377 tng_block_destroy(&block);
13378 return(TNG_CRITICAL);
13380 data.datatype = datatype;
13382 if(!(dependency & TNG_FRAME_DEPENDENT) ||
13383 (is_particle_data == TNG_FALSE && dependency & TNG_PARTICLE_DEPENDENT) ||
13384 (is_particle_data == TNG_TRUE && !(dependency & TNG_PARTICLE_DEPENDENT)))
13386 tng_block_destroy(&block);
13387 tng_data->input_file = temp;
13389 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13390 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13391 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13392 return(TNG_FAILURE);
13395 if(tng_file_input_numerical(tng_data, &sparse_data,
13396 sizeof(sparse_data),
13397 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13399 tng_block_destroy(&block);
13400 return(TNG_CRITICAL);
13403 if(tng_file_input_numerical(tng_data, &data.n_values_per_frame,
13404 sizeof(data.n_values_per_frame),
13405 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13407 tng_block_destroy(&block);
13408 return(TNG_CRITICAL);
13411 if(tng_file_input_numerical(tng_data, &data.codec_id,
13412 sizeof(data.codec_id),
13413 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13415 tng_block_destroy(&block);
13416 return(TNG_CRITICAL);
13419 if(data.codec_id != TNG_UNCOMPRESSED)
13421 if(tng_file_input_numerical(tng_data, &data.compression_multiplier,
13422 sizeof(data.compression_multiplier),
13423 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13425 tng_block_destroy(&block);
13426 return(TNG_CRITICAL);
13429 else
13431 data.compression_multiplier = 1;
13434 if(sparse_data)
13436 if(tng_file_input_numerical(tng_data, &data.first_frame_with_data,
13437 sizeof(data.first_frame_with_data),
13438 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13440 tng_block_destroy(&block);
13441 return(TNG_CRITICAL);
13444 if(tng_file_input_numerical(tng_data, &data.stride_length,
13445 sizeof(data.stride_length),
13446 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13448 tng_block_destroy(&block);
13449 return(TNG_CRITICAL);
13452 else
13454 data.first_frame_with_data = 0;
13455 data.stride_length = 1;
13457 data.n_frames = tng_data->current_trajectory_frame_set.n_frames;
13459 if(is_particle_data == TNG_TRUE)
13461 if(tng_file_input_numerical(tng_data, &num_first_particle,
13462 sizeof(num_first_particle),
13463 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13465 tng_block_destroy(&block);
13466 return(TNG_CRITICAL);
13469 if(tng_file_input_numerical(tng_data, &block_n_particles,
13470 sizeof(block_n_particles),
13471 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13473 tng_block_destroy(&block);
13474 return(TNG_CRITICAL);
13478 tng_data->input_file = temp;
13480 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13481 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13482 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13484 switch(data.datatype)
13486 case(TNG_INT_DATA):
13487 size = sizeof(int64_t);
13488 break;
13489 case(TNG_FLOAT_DATA):
13490 size = sizeof(float);
13491 break;
13492 case(TNG_DOUBLE_DATA):
13493 size = sizeof(double);
13494 break;
13495 default:
13496 fprintf(stderr, "TNG library: Cannot calculate writing locations. %s: %d.\n", __FILE__,
13497 __LINE__);
13498 tng_block_destroy(&block);
13499 return(TNG_FAILURE);
13502 n_values_per_frame = data.n_values_per_frame;
13504 file_pos = (frame_nr - tng_max_i64(frame_set->first_frame,
13505 data.first_frame_with_data)) /
13506 data.stride_length;
13507 if(is_particle_data == TNG_TRUE)
13509 file_pos *= block_n_particles * size * n_values_per_frame;
13511 else
13513 file_pos *= size * n_values_per_frame;
13516 if(file_pos > contents_size)
13518 fprintf(stderr, "TNG library: Attempting to write outside the block. %s: %d\n", __FILE__,
13519 __LINE__);
13520 tng_block_destroy(&block);
13521 return(TNG_FAILURE);
13524 fseeko(tng_data->output_file, file_pos, SEEK_CUR);
13526 if(is_particle_data == TNG_TRUE)
13528 write_n_particles = val_n_particles;
13530 else
13532 write_n_particles = 1;
13535 /* If the endianness is not big endian the data needs to be swapped */
13536 if((data.datatype == TNG_INT_DATA ||
13537 data.datatype == TNG_DOUBLE_DATA) &&
13538 tng_data->output_endianness_swap_func_64)
13540 copy = (char *)malloc(write_n_particles * n_values_per_frame * size);
13541 memcpy(copy, values, write_n_particles * n_values_per_frame * size);
13542 for(i = 0; i < write_n_particles * n_values_per_frame; i++)
13544 if(tng_data->output_endianness_swap_func_64(tng_data,
13545 (uint64_t *) copy+i)
13546 != TNG_SUCCESS)
13548 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13549 __FILE__, __LINE__);
13552 fwrite(copy, write_n_particles * n_values_per_frame, size,
13553 tng_data->output_file);
13554 free(copy);
13556 else if(data.datatype == TNG_FLOAT_DATA &&
13557 tng_data->output_endianness_swap_func_32)
13559 copy = (char *)malloc(write_n_particles * n_values_per_frame * size);
13560 memcpy(copy, values, write_n_particles * n_values_per_frame * size);
13561 for(i = 0; i < write_n_particles * n_values_per_frame; i++)
13563 if(tng_data->output_endianness_swap_func_32(tng_data,
13564 (uint32_t *) copy+i)
13565 != TNG_SUCCESS)
13567 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13568 __FILE__, __LINE__);
13571 fwrite(copy, write_n_particles * n_values_per_frame, size,
13572 tng_data->output_file);
13573 free(copy);
13576 else
13578 fwrite(values, write_n_particles * n_values_per_frame, size, tng_data->output_file);
13581 fflush(tng_data->output_file);
13583 /* Update the number of written frames in the frame set. */
13584 if(frame_nr - frame_set->first_frame + 1 > frame_set->n_written_frames)
13586 frame_set->n_written_frames = frame_nr - frame_set->first_frame + 1;
13589 /* If the last frame has been written update the hash */
13590 if(hash_mode == TNG_USE_HASH && (frame_nr + data.stride_length -
13591 data.first_frame_with_data) >=
13592 frame_set->n_frames)
13594 tng_md5_hash_update(tng_data, block, header_pos, header_pos +
13595 header_size);
13598 tng_block_destroy(&block);
13600 return(TNG_SUCCESS);
13603 tng_function_status DECLSPECDLLEXPORT tng_frame_data_write
13604 (const tng_trajectory_t tng_data,
13605 const int64_t frame_nr,
13606 const int64_t block_id,
13607 const void *values,
13608 const char hash_mode)
13610 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13611 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
13612 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer.");
13614 /* This is now just calling the generic data writing function. This
13615 * function must keep its signature to let the API be backwards
13616 * compatible. */
13617 return(tng_frame_gen_data_write(tng_data, frame_nr, block_id,
13618 TNG_FALSE, 0, 0, values, hash_mode));
13621 tng_function_status DECLSPECDLLEXPORT tng_frame_particle_data_write
13622 (const tng_trajectory_t tng_data,
13623 const int64_t frame_nr,
13624 const int64_t block_id,
13625 const int64_t val_first_particle,
13626 const int64_t val_n_particles,
13627 const void *values,
13628 const char hash_mode)
13630 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13631 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
13632 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer.");
13633 TNG_ASSERT(val_first_particle >= 0, "TNG library: val_first_particle must be >= 0.");
13634 TNG_ASSERT(val_n_particles >= 0, "TNG library: val_n_particles must be >= 0.");
13636 /* This is now just calling the generic data writing function. This
13637 * function must keep its signature to let the API be backwards
13638 * compatible. */
13639 return(tng_frame_gen_data_write(tng_data, frame_nr, block_id,
13640 TNG_TRUE, val_first_particle, val_n_particles,
13641 values, hash_mode));
13644 static tng_function_status tng_data_values_alloc
13645 (const tng_trajectory_t tng_data,
13646 union data_values ***values,
13647 const int64_t n_frames,
13648 const int64_t n_values_per_frame,
13649 const char type)
13651 int64_t i;
13652 tng_function_status stat;
13654 if(n_frames <= 0 || n_values_per_frame <= 0)
13656 return(TNG_FAILURE);
13659 if(*values)
13661 stat = tng_data_values_free(tng_data, *values, n_frames,
13662 n_values_per_frame,
13663 type);
13664 if(stat != TNG_SUCCESS)
13666 fprintf(stderr, "TNG library: Cannot free particle data values. %s: %d\n",
13667 __FILE__, __LINE__);
13668 return(stat);
13671 *values = (union data_values **)malloc(sizeof(union data_values *) * n_frames);
13672 if(!*values)
13674 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
13675 __FILE__, __LINE__);
13676 return(TNG_CRITICAL);
13680 for(i = 0; i < n_frames; i++)
13682 (*values)[i] = (union data_values *)malloc(sizeof(union data_values) *
13683 n_values_per_frame);
13684 if(!(*values)[i])
13686 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
13687 __FILE__, __LINE__);
13688 free(values);
13689 values = 0;
13690 return(TNG_CRITICAL);
13693 return(TNG_SUCCESS);
13696 /* FIXME: This needs ***values */
13697 tng_function_status DECLSPECDLLEXPORT tng_data_values_free
13698 (const tng_trajectory_t tng_data,
13699 union data_values **values,
13700 const int64_t n_frames,
13701 const int64_t n_values_per_frame,
13702 const char type)
13704 int64_t i, j;
13705 (void)tng_data;
13707 if(values)
13709 for(i = 0; i < n_frames; i++)
13711 if(values[i])
13713 if(type == TNG_CHAR_DATA)
13715 for(j = 0; j < n_values_per_frame; j++)
13717 if(values[i][j].c)
13719 free(values[i][j].c);
13720 values[i][j].c = 0;
13724 free(values[i]);
13725 values[i] = 0;
13728 free(values);
13729 values = 0;
13732 return(TNG_SUCCESS);
13735 static tng_function_status tng_particle_data_values_alloc
13736 (const tng_trajectory_t tng_data,
13737 union data_values ****values,
13738 const int64_t n_frames,
13739 const int64_t n_particles,
13740 const int64_t n_values_per_frame,
13741 const char type)
13743 int64_t i, j;
13744 tng_function_status stat;
13746 if(n_particles == 0 || n_values_per_frame == 0)
13748 return(TNG_FAILURE);
13751 if(*values)
13753 stat = tng_particle_data_values_free(tng_data, *values, n_frames,
13754 n_particles, n_values_per_frame,
13755 type);
13756 if(stat != TNG_SUCCESS)
13758 fprintf(stderr, "TNG library: Cannot free particle data values. %s: %d\n",
13759 __FILE__, __LINE__);
13760 return(stat);
13763 *values = (union data_values ***)malloc(sizeof(union data_values **) * n_frames);
13764 if(!*values)
13766 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
13767 __FILE__, __LINE__);
13768 return(TNG_CRITICAL);
13772 for(i = 0; i < n_frames; i++)
13774 (*values)[i] = (union data_values **)malloc(sizeof(union data_values *) *
13775 n_particles);
13776 if(!(*values)[i])
13778 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
13779 __FILE__, __LINE__);
13780 free(*values);
13781 *values = 0;
13782 return(TNG_CRITICAL);
13784 for(j = 0; j < n_particles; j++)
13786 (*values)[i][j] = (union data_values *)malloc(sizeof(union data_values) *
13787 n_values_per_frame);
13788 if(!(*values)[i][j])
13790 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
13791 __FILE__, __LINE__);
13792 tng_particle_data_values_free(tng_data, *values, n_frames,
13793 n_particles, n_values_per_frame,
13794 type);
13795 *values = 0;
13796 return(TNG_CRITICAL);
13800 return(TNG_SUCCESS);
13803 /* FIXME: This needs ****values */
13804 tng_function_status DECLSPECDLLEXPORT tng_particle_data_values_free
13805 (const tng_trajectory_t tng_data,
13806 union data_values ***values,
13807 const int64_t n_frames,
13808 const int64_t n_particles,
13809 const int64_t n_values_per_frame,
13810 const char type)
13812 int64_t i, j, k;
13813 (void)tng_data;
13815 if(values)
13817 for(i = 0; i < n_frames; i++)
13819 if(values[i])
13821 for(j = 0; j < n_particles; j++)
13823 if(type == TNG_CHAR_DATA)
13825 for(k = 0; k < n_values_per_frame; k++)
13827 if(values[i][j][k].c)
13829 free(values[i][j][k].c);
13830 values[i][j][k].c = 0;
13834 free(values[i][j]);
13835 values[i][j] = 0;
13837 free(values[i]);
13838 values[i] = 0;
13841 free(values);
13842 values = 0;
13845 return(TNG_SUCCESS);
13848 static tng_function_status tng_gen_data_get
13849 (const tng_trajectory_t tng_data,
13850 const int64_t block_id,
13851 const tng_bool is_particle_data,
13852 union data_values ****values,
13853 int64_t *n_frames,
13854 int64_t *n_particles,
13855 int64_t *n_values_per_frame,
13856 char *type)
13858 int64_t i, j, k, mapping, file_pos, i_step, block_index;
13859 int size;
13860 size_t len;
13861 tng_data_t data;
13862 tng_trajectory_frame_set_t frame_set;
13863 tng_gen_block_t block;
13864 char block_type_flag;
13865 tng_function_status stat;
13867 frame_set = &tng_data->current_trajectory_frame_set;
13869 block_index = -1;
13870 data = 0;
13872 if(is_particle_data == TNG_TRUE)
13874 stat = tng_particle_data_find(tng_data, block_id, &data);
13876 else
13878 stat = tng_data_find(tng_data, block_id, &data);
13881 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
13883 block_type_flag = TNG_TRAJECTORY_BLOCK;
13885 else
13887 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
13890 if(stat != TNG_SUCCESS)
13892 tng_block_init(&block);
13893 file_pos = ftello(tng_data->input_file);
13894 /* Read all blocks until next frame set block */
13895 stat = tng_block_header_read(tng_data, block);
13896 while(file_pos < tng_data->input_file_len &&
13897 stat != TNG_CRITICAL &&
13898 block->id != TNG_TRAJECTORY_FRAME_SET &&
13899 block->id != -1)
13901 /* Use hash by default */
13902 stat = tng_block_read_next(tng_data, block,
13903 TNG_USE_HASH);
13904 if(stat != TNG_CRITICAL)
13906 file_pos = ftello(tng_data->input_file);
13907 if(file_pos < tng_data->input_file_len)
13909 stat = tng_block_header_read(tng_data, block);
13913 tng_block_destroy(&block);
13914 if(stat == TNG_CRITICAL)
13916 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
13917 file_pos, __FILE__, __LINE__);
13918 return(stat);
13921 if(is_particle_data == TNG_TRUE)
13923 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
13925 data = &frame_set->tr_particle_data[i];
13926 if(data->block_id == block_id)
13928 block_index = i;
13929 block_type_flag = TNG_TRAJECTORY_BLOCK;
13930 break;
13934 else
13936 for(i = 0; i < frame_set->n_data_blocks; i++)
13938 data = &frame_set->tr_data[i];
13939 if(data->block_id == block_id)
13941 block_index = i;
13942 break;
13946 if(block_index < 0)
13948 return(TNG_FAILURE);
13952 if(is_particle_data == TNG_TRUE)
13954 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
13955 tng_data->var_num_atoms_flag)
13957 *n_particles = frame_set->n_particles;
13959 else
13961 *n_particles = tng_data->n_particles;
13965 *n_frames = tng_max_i64(1, data->n_frames);
13966 *n_values_per_frame = data->n_values_per_frame;
13967 *type = data->datatype;
13969 if(is_particle_data == TNG_TRUE)
13971 if(*values == 0)
13973 if(tng_particle_data_values_alloc(tng_data, values, *n_frames,
13974 *n_particles, *n_values_per_frame,
13975 *type) != TNG_SUCCESS)
13977 return(TNG_CRITICAL);
13981 i_step = (*n_particles) * (*n_values_per_frame);
13983 /* It's not very elegant to reuse so much of the code in the different case
13984 * statements, but it's unnecessarily slow to have the switch-case block
13985 * inside the for loops. */
13986 switch(*type)
13988 case TNG_CHAR_DATA:
13989 for(i = 0; i < *n_frames; i++)
13991 for(j = 0; j < *n_particles; j++)
13993 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
13994 for(k = 0; k < *n_values_per_frame; k++)
13996 len = strlen(data->strings[i][j][k]) + 1;
13997 (*values)[i][mapping][k].c = (char *)malloc(len);
13998 strncpy((*values)[i][mapping][k].c,
13999 data->strings[i][j][k], len);
14003 break;
14004 case TNG_INT_DATA:
14005 size = sizeof(int);
14006 for(i = 0; i < *n_frames; i++)
14008 for(j = 0; j < *n_particles; j++)
14010 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14011 for(k = 0; k < *n_values_per_frame; k++)
14013 (*values)[i][mapping][k].i = *(int *)
14014 ((char *)data->values + size *
14015 (i * i_step + j *
14016 (*n_values_per_frame) + k));
14020 break;
14021 case TNG_FLOAT_DATA:
14022 size = sizeof(float);
14023 for(i = 0; i < *n_frames; i++)
14025 for(j = 0; j < *n_particles; j++)
14027 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14028 for(k = 0; k < *n_values_per_frame; k++)
14030 (*values)[i][mapping][k].f = *(float *)
14031 ((char *)data->values + size *
14032 (i * i_step + j *
14033 (*n_values_per_frame) + k));
14037 break;
14038 case TNG_DOUBLE_DATA:
14039 default:
14040 size = sizeof(double);
14041 for(i = 0; i < *n_frames; i++)
14043 for(j = 0; j < *n_particles; j++)
14045 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14046 for(k = 0; k < *n_values_per_frame; k++)
14048 (*values)[i][mapping][k].d = *(double *)
14049 ((char *)data->values + size *
14050 (i * i_step + j *
14051 (*n_values_per_frame) + k));
14057 else
14059 if(*(values[0]) == 0)
14061 if(tng_data_values_alloc(tng_data, values[0], *n_frames,
14062 *n_values_per_frame,
14063 *type) != TNG_SUCCESS)
14065 return(TNG_CRITICAL);
14068 switch(*type)
14070 case TNG_CHAR_DATA:
14071 for(i = 0; i < *n_frames; i++)
14073 for(j = 0; j < *n_values_per_frame; j++)
14075 len = strlen(data->strings[0][i][j]) + 1;
14076 (*values)[0][i][j].c = (char *)malloc(len);
14077 strncpy((*values)[0][i][j].c, data->strings[0][i][j], len);
14080 break;
14081 case TNG_INT_DATA:
14082 size = sizeof(int);
14083 for(i = 0; i < *n_frames; i++)
14085 for(j = 0; j < *n_values_per_frame; j++)
14087 (*values)[0][i][j].i = *(int *)((char *)data->values + size *
14088 (i*(*n_values_per_frame) + j));
14091 break;
14092 case TNG_FLOAT_DATA:
14093 size = sizeof(float);
14094 for(i = 0; i < *n_frames; i++)
14096 for(j = 0; j < *n_values_per_frame; j++)
14098 (*values)[0][i][j].f = *(float *)((char *)data->values + size *
14099 (i*(*n_values_per_frame) + j));
14102 break;
14103 case TNG_DOUBLE_DATA:
14104 default:
14105 size = sizeof(double);
14106 for(i = 0; i < *n_frames; i++)
14108 for(j = 0; j < *n_values_per_frame; j++)
14110 (*values)[0][i][j].d = *(double *)((char *)data->values + size *
14111 (i*(*n_values_per_frame) + j));
14117 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
14119 return(TNG_SUCCESS);
14122 tng_function_status DECLSPECDLLEXPORT tng_data_get
14123 (const tng_trajectory_t tng_data,
14124 const int64_t block_id,
14125 union data_values ***values,
14126 int64_t *n_frames,
14127 int64_t *n_values_per_frame,
14128 char *type)
14130 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14131 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
14132 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
14133 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
14135 return(tng_gen_data_get(tng_data, block_id, TNG_FALSE, &values, n_frames, 0,
14136 n_values_per_frame, type));
14139 static tng_function_status tng_gen_data_vector_get
14140 (const tng_trajectory_t tng_data,
14141 const int64_t block_id,
14142 const tng_bool is_particle_data,
14143 void **values,
14144 int64_t *n_frames,
14145 int64_t *stride_length,
14146 int64_t *n_particles,
14147 int64_t *n_values_per_frame,
14148 char *type)
14150 int64_t i, j, mapping, file_pos, i_step, full_data_len, n_frames_div;
14151 int64_t block_index;
14152 int size;
14153 tng_data_t data;
14154 tng_trajectory_frame_set_t frame_set;
14155 tng_gen_block_t block;
14156 void *temp;
14157 char block_type_flag;
14158 tng_function_status stat;
14160 frame_set = &tng_data->current_trajectory_frame_set;
14162 block_index = -1;
14163 data = 0;
14165 if(is_particle_data == TNG_TRUE)
14167 stat = tng_particle_data_find(tng_data, block_id, &data);
14169 else
14171 stat = tng_data_find(tng_data, block_id, &data);
14174 if(stat != TNG_SUCCESS)
14176 tng_block_init(&block);
14177 file_pos = ftello(tng_data->input_file);
14178 /* Read all blocks until next frame set block */
14179 stat = tng_block_header_read(tng_data, block);
14180 while(file_pos < tng_data->input_file_len &&
14181 stat != TNG_CRITICAL &&
14182 block->id != TNG_TRAJECTORY_FRAME_SET &&
14183 block->id != -1)
14185 /* Use hash by default */
14186 stat = tng_block_read_next(tng_data, block,
14187 TNG_USE_HASH);
14188 if(stat != TNG_CRITICAL)
14190 file_pos = ftello(tng_data->input_file);
14191 if(file_pos < tng_data->input_file_len)
14193 stat = tng_block_header_read(tng_data, block);
14197 tng_block_destroy(&block);
14198 if(stat == TNG_CRITICAL)
14200 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
14201 file_pos, __FILE__, __LINE__);
14202 return(stat);
14205 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
14207 data = &frame_set->tr_particle_data[i];
14208 if(data->block_id == block_id)
14210 block_index = i;
14211 break;
14214 if(block_index < 0)
14216 return(TNG_FAILURE);
14220 if(is_particle_data == TNG_TRUE)
14222 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
14224 block_type_flag = TNG_TRAJECTORY_BLOCK;
14226 else
14228 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
14231 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
14232 tng_data->var_num_atoms_flag)
14234 *n_particles = frame_set->n_particles;
14236 else
14238 *n_particles = tng_data->n_particles;
14242 *type = data->datatype;
14244 switch(*type)
14246 case TNG_CHAR_DATA:
14247 return(TNG_FAILURE);
14248 case TNG_INT_DATA:
14249 size = sizeof(int64_t);
14250 break;
14251 case TNG_FLOAT_DATA:
14252 size = sizeof(float);
14253 break;
14254 case TNG_DOUBLE_DATA:
14255 default:
14256 size = sizeof(double);
14259 *n_frames = tng_max_i64(1, data->n_frames);
14260 *n_values_per_frame = data->n_values_per_frame;
14261 *stride_length = data->stride_length;
14263 n_frames_div = (*n_frames % *stride_length) ?
14264 *n_frames / *stride_length + 1:
14265 *n_frames / *stride_length;
14267 full_data_len = n_frames_div * size *
14268 (*n_values_per_frame);
14269 if(is_particle_data == TNG_TRUE)
14271 full_data_len *= (*n_particles);
14274 temp = (char *)realloc(*values, full_data_len);
14275 if(!temp)
14277 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
14278 __FILE__, __LINE__);
14279 free(*values);
14280 *values = 0;
14281 return(TNG_CRITICAL);
14284 *values = temp;
14286 if(is_particle_data != TNG_TRUE || frame_set->n_mapping_blocks <= 0)
14288 memcpy(*values, data->values, full_data_len);
14290 else
14292 i_step = (*n_particles) * (*n_values_per_frame);
14293 for(i = 0; i < *n_frames; i++)
14295 for(j = 0; j < *n_particles; j++)
14297 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14298 memcpy(((char *)*values) + size * (i * i_step + mapping *
14299 (*n_values_per_frame)),
14300 (char *)data->values + size *
14301 (i * i_step + j * (*n_values_per_frame)),
14302 size * (*n_values_per_frame));
14307 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
14309 return(TNG_SUCCESS);
14312 tng_function_status DECLSPECDLLEXPORT tng_data_vector_get
14313 (const tng_trajectory_t tng_data,
14314 const int64_t block_id,
14315 void **values,
14316 int64_t *n_frames,
14317 int64_t *stride_length,
14318 int64_t *n_values_per_frame,
14319 char *type)
14321 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14322 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
14323 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
14324 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
14325 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
14327 return(tng_gen_data_vector_get(tng_data, block_id, TNG_FALSE, values,
14328 n_frames, stride_length, 0, n_values_per_frame,
14329 type));
14332 static tng_function_status tng_gen_data_interval_get
14333 (const tng_trajectory_t tng_data,
14334 const int64_t block_id,
14335 const tng_bool is_particle_data,
14336 const int64_t start_frame_nr,
14337 const int64_t end_frame_nr,
14338 const char hash_mode,
14339 union data_values ****values,
14340 int64_t *n_particles,
14341 int64_t *n_values_per_frame,
14342 char *type)
14344 int64_t i, j, k, mapping, n_frames, file_pos, current_frame_pos, i_step;
14345 int64_t first_frame, block_index;
14346 int size;
14347 size_t len;
14348 tng_data_t data;
14349 tng_trajectory_frame_set_t frame_set;
14350 tng_gen_block_t block;
14351 char block_type_flag;
14352 tng_function_status stat;
14354 block_index = -1;
14356 frame_set = &tng_data->current_trajectory_frame_set;
14357 first_frame = frame_set->first_frame;
14359 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
14360 if(stat != TNG_SUCCESS)
14362 return(stat);
14365 /* Do not re-read the frame set. */
14366 if((is_particle_data == TNG_TRUE &&
14367 (first_frame != frame_set->first_frame ||
14368 frame_set->n_particle_data_blocks <= 0)) ||
14369 (is_particle_data == TNG_FALSE &&
14370 (first_frame != frame_set->first_frame ||
14371 frame_set->n_data_blocks <= 0)))
14373 tng_block_init(&block);
14374 file_pos = ftello(tng_data->input_file);
14375 /* Read all blocks until next frame set block */
14376 stat = tng_block_header_read(tng_data, block);
14377 while(file_pos < tng_data->input_file_len &&
14378 stat != TNG_CRITICAL &&
14379 block->id != TNG_TRAJECTORY_FRAME_SET &&
14380 block->id != -1)
14382 stat = tng_block_read_next(tng_data, block,
14383 hash_mode);
14384 if(stat != TNG_CRITICAL)
14386 file_pos = ftello(tng_data->input_file);
14387 if(file_pos < tng_data->input_file_len)
14389 stat = tng_block_header_read(tng_data, block);
14393 tng_block_destroy(&block);
14394 if(stat == TNG_CRITICAL)
14396 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
14397 file_pos, __FILE__, __LINE__);
14398 return(stat);
14402 /* See if there is already a data block of this ID.
14403 * Start checking the last read frame set */
14404 if(is_particle_data == TNG_TRUE)
14406 for(i = frame_set->n_particle_data_blocks; i-- ;)
14408 data = &frame_set->tr_particle_data[i];
14409 if(data->block_id == block_id)
14411 block_index = i;
14412 block_type_flag = TNG_TRAJECTORY_BLOCK;
14413 break;
14417 else
14419 for(i = 0; i < frame_set->n_data_blocks; i++)
14421 data = &frame_set->tr_data[i];
14422 if(data->block_id == block_id)
14424 block_index = i;
14425 break;
14430 if(block_index < 0)
14432 fprintf(stderr, "TNG library: Could not find particle data block with id %" PRId64 ". %s: %d\n",
14433 block_id, __FILE__, __LINE__);
14434 return(TNG_FAILURE);
14437 if(is_particle_data == TNG_TRUE)
14439 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
14440 tng_data->var_num_atoms_flag)
14442 *n_particles = frame_set->n_particles;
14444 else
14446 *n_particles = tng_data->n_particles;
14450 n_frames = end_frame_nr - start_frame_nr + 1;
14451 *n_values_per_frame = data->n_values_per_frame;
14452 *type = data->datatype;
14454 if(*values == 0)
14456 if(is_particle_data == TNG_TRUE)
14458 if(tng_particle_data_values_alloc(tng_data, values, n_frames,
14459 *n_particles, *n_values_per_frame,
14460 *type) != TNG_SUCCESS)
14462 return(TNG_CRITICAL);
14465 else
14467 if(tng_data_values_alloc(tng_data, *values, n_frames,
14468 *n_values_per_frame,
14469 *type) != TNG_SUCCESS)
14471 return(TNG_CRITICAL);
14476 current_frame_pos = start_frame_nr - frame_set->first_frame;
14478 if(is_particle_data == TNG_TRUE)
14480 i_step = (*n_particles) * (*n_values_per_frame);
14482 else
14484 i_step = (*n_values_per_frame);
14486 /* It's not very elegant to reuse so much of the code in the different case
14487 * statements, but it's unnecessarily slow to have the switch-case block
14488 * inside the for loops. */
14489 switch(*type)
14491 case TNG_CHAR_DATA:
14492 for(i=0; i<n_frames; i++)
14494 if(current_frame_pos == frame_set->n_frames)
14496 stat = tng_frame_set_read_next(tng_data, hash_mode);
14497 if(stat != TNG_SUCCESS)
14499 return(stat);
14501 current_frame_pos = 0;
14503 if(is_particle_data == TNG_TRUE)
14505 for(j = 0; j < *n_particles; j++)
14507 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14508 for(k = 0; k < *n_values_per_frame; k++)
14510 len = strlen(data->strings[current_frame_pos][j][k]) + 1;
14511 (*values)[i][mapping][k].c = (char *)malloc(len);
14512 strncpy((*values)[i][mapping][k].c, data->strings[current_frame_pos][j][k], len);
14516 else
14518 for(j = 0; j < *n_values_per_frame; j++)
14520 len = strlen(data->strings[0][current_frame_pos][j]) + 1;
14521 (*values)[0][i][j].c = (char *)malloc(len);
14522 strncpy((*values)[0][i][j].c, data->strings[0][current_frame_pos][j], len);
14525 current_frame_pos++;
14527 break;
14528 case TNG_INT_DATA:
14529 size = sizeof(int);
14530 for(i=0; i<n_frames; i++)
14532 if(current_frame_pos == frame_set->n_frames)
14534 stat = tng_frame_set_read_next(tng_data, hash_mode);
14535 if(stat != TNG_SUCCESS)
14537 return(stat);
14539 current_frame_pos = 0;
14541 if(is_particle_data == TNG_TRUE)
14543 for(j = 0; j < *n_particles; j++)
14545 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14546 for(k = 0; k < *n_values_per_frame; k++)
14548 (*values)[i][mapping][k].i = *(int *)
14549 ((char *)data->values + size *
14550 (current_frame_pos *
14551 i_step + j *
14552 (*n_values_per_frame) + k));
14555 current_frame_pos++;
14557 else
14559 for(j = 0; j < *n_values_per_frame; j++)
14561 (*values)[0][i][j].i = *(int *)((char *)data->values + size *
14562 (current_frame_pos *
14563 i_step + j));
14567 break;
14568 case TNG_FLOAT_DATA:
14569 size = sizeof(float);
14570 for(i=0; i<n_frames; i++)
14572 if(current_frame_pos == frame_set->n_frames)
14574 stat = tng_frame_set_read_next(tng_data, hash_mode);
14575 if(stat != TNG_SUCCESS)
14577 return(stat);
14579 current_frame_pos = 0;
14581 if(is_particle_data == TNG_TRUE)
14583 for(j=0; j<*n_particles; j++)
14585 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14586 for(k=0; k<*n_values_per_frame; k++)
14588 (*values)[i][mapping][k].f = *(float *)
14589 ((char *)data->values + size *
14590 (current_frame_pos *
14591 i_step + j *
14592 (*n_values_per_frame) + k));
14596 else
14598 for(j = 0; j < *n_values_per_frame; j++)
14600 (*values)[0][i][j].f = *(float *)((char *)data->values + size *
14601 (current_frame_pos *
14602 i_step + j));
14605 current_frame_pos++;
14607 break;
14608 case TNG_DOUBLE_DATA:
14609 default:
14610 size = sizeof(double);
14611 for(i=0; i<n_frames; i++)
14613 if(current_frame_pos == frame_set->n_frames)
14615 stat = tng_frame_set_read_next(tng_data, hash_mode);
14616 if(stat != TNG_SUCCESS)
14618 return(stat);
14620 current_frame_pos = 0;
14622 if(is_particle_data == TNG_TRUE)
14624 for(j=0; j<*n_particles; j++)
14626 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14627 for(k=0; k<*n_values_per_frame; k++)
14629 (*values)[i][mapping][k].d = *(double *)
14630 ((char *)data->values + size *
14631 (current_frame_pos *
14632 i_step + j *
14633 (*n_values_per_frame) + k));
14637 else
14639 for(j = 0; j < *n_values_per_frame; j++)
14641 (*values)[0][i][j].d = *(double *)((char *)data->values + size *
14642 (current_frame_pos *
14643 i_step + j));
14646 current_frame_pos++;
14650 data->last_retrieved_frame = end_frame_nr;
14652 return(TNG_SUCCESS);
14655 tng_function_status DECLSPECDLLEXPORT tng_data_interval_get
14656 (const tng_trajectory_t tng_data,
14657 const int64_t block_id,
14658 const int64_t start_frame_nr,
14659 const int64_t end_frame_nr,
14660 const char hash_mode,
14661 union data_values ***values,
14662 int64_t *n_values_per_frame,
14663 char *type)
14665 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14666 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
14667 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
14668 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
14670 return(tng_gen_data_interval_get(tng_data, block_id, TNG_FALSE, start_frame_nr,
14671 end_frame_nr, hash_mode, &values, 0,
14672 n_values_per_frame, type));
14675 static tng_function_status tng_gen_data_vector_interval_get
14676 (const tng_trajectory_t tng_data,
14677 const int64_t block_id,
14678 const tng_bool is_particle_data,
14679 const int64_t start_frame_nr,
14680 const int64_t end_frame_nr,
14681 const char hash_mode,
14682 void **values,
14683 int64_t *n_particles,
14684 int64_t *stride_length,
14685 int64_t *n_values_per_frame,
14686 char *type)
14688 int64_t n_frames, tot_n_frames, n_frames_div, n_frames_div_2, first_frame;
14689 int64_t file_pos, current_frame_pos, last_frame_pos, full_data_len, frame_size;
14690 int size;
14691 tng_trajectory_frame_set_t frame_set;
14692 tng_data_t data;
14693 tng_gen_block_t block;
14694 void *current_values = 0, *temp;
14695 tng_function_status stat;
14697 frame_set = &tng_data->current_trajectory_frame_set;
14698 first_frame = frame_set->first_frame;
14700 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
14701 if(stat != TNG_SUCCESS)
14703 return(stat);
14706 /* Do not re-read the frame set and only need the requested block + particle mapping blocks. */
14707 /* TODO: Test that blocks are read correctly now that now all of them are read at the same time. */
14708 if(is_particle_data == TNG_TRUE)
14710 stat = tng_particle_data_find(tng_data, block_id, &data);
14712 else
14714 stat = tng_data_find(tng_data, block_id, &data);
14717 if(first_frame != frame_set->first_frame ||
14718 stat != TNG_SUCCESS)
14720 tng_block_init(&block);
14721 if(stat != TNG_SUCCESS)
14723 fseeko(tng_data->input_file,
14724 tng_data->current_trajectory_frame_set_input_file_pos,
14725 SEEK_SET);
14726 stat = tng_block_header_read(tng_data, block);
14727 if(stat != TNG_SUCCESS)
14729 fprintf(stderr, "TNG library: Cannot read block header. %s: %d\n",
14730 __FILE__, __LINE__);
14731 return(stat);
14734 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
14736 file_pos = ftello(tng_data->input_file);
14737 /* Read until next frame set block */
14738 stat = tng_block_header_read(tng_data, block);
14739 while(file_pos < tng_data->input_file_len &&
14740 stat != TNG_CRITICAL &&
14741 block->id != TNG_TRAJECTORY_FRAME_SET &&
14742 block->id != -1)
14744 if(block->id == block_id || block->id == TNG_PARTICLE_MAPPING)
14746 stat = tng_block_read_next(tng_data, block,
14747 hash_mode);
14748 if(stat != TNG_CRITICAL)
14750 file_pos = ftello(tng_data->input_file);
14751 if(file_pos < tng_data->input_file_len)
14753 stat = tng_block_header_read(tng_data, block);
14757 else
14759 file_pos += block->block_contents_size + block->header_contents_size;
14760 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
14761 if(file_pos < tng_data->input_file_len)
14763 stat = tng_block_header_read(tng_data, block);
14767 tng_block_destroy(&block);
14768 if(stat == TNG_CRITICAL)
14770 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
14771 file_pos, __FILE__, __LINE__);
14772 return(stat);
14775 if(is_particle_data == TNG_TRUE)
14777 stat = tng_particle_data_find(tng_data, block_id, &data);
14779 else
14781 stat = tng_data_find(tng_data, block_id, &data);
14783 if(stat != TNG_SUCCESS)
14785 return(stat);
14788 stat = tng_gen_data_vector_get(tng_data, block_id, is_particle_data,
14789 &current_values, &n_frames, stride_length,
14790 n_particles, n_values_per_frame, type);
14792 if(stat != TNG_SUCCESS || (is_particle_data && *n_particles == 0))
14794 if(current_values)
14796 free(current_values);
14798 return(stat);
14801 if(n_frames == 1 && n_frames < frame_set->n_frames)
14803 tot_n_frames = 1;
14805 else
14807 tot_n_frames = end_frame_nr - start_frame_nr + 1;
14810 switch(*type)
14812 case TNG_CHAR_DATA:
14813 return(TNG_FAILURE);
14814 case TNG_INT_DATA:
14815 size = sizeof(int64_t);
14816 break;
14817 case TNG_FLOAT_DATA:
14818 size = sizeof(float);
14819 break;
14820 case TNG_DOUBLE_DATA:
14821 default:
14822 size = sizeof(double);
14825 n_frames_div = (tot_n_frames % *stride_length) ?
14826 tot_n_frames / *stride_length + 1:
14827 tot_n_frames / *stride_length;
14829 full_data_len = n_frames_div * size * (*n_values_per_frame);
14830 if(is_particle_data)
14832 full_data_len *= (*n_particles);
14835 temp = (char *)realloc(*values, full_data_len);
14836 if(!temp)
14838 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
14839 __FILE__, __LINE__);
14840 free(*values);
14841 *values = 0;
14842 return(TNG_CRITICAL);
14845 *values = temp;
14847 if( n_frames == 1 && n_frames < frame_set->n_frames)
14849 if(is_particle_data)
14851 memcpy(*values, current_values, size * (*n_particles) *
14852 (*n_values_per_frame));
14854 else
14856 memcpy(*values, current_values, size * (*n_values_per_frame));
14859 else
14861 current_frame_pos = start_frame_nr - frame_set->first_frame;
14863 frame_size = size * (*n_values_per_frame);
14864 if(is_particle_data)
14866 frame_size *= (*n_particles);
14869 last_frame_pos = tng_min_i64(n_frames,
14870 end_frame_nr - start_frame_nr);
14872 n_frames_div = current_frame_pos / *stride_length;
14873 n_frames_div_2 = (last_frame_pos % *stride_length) ?
14874 last_frame_pos / *stride_length + 1:
14875 last_frame_pos / *stride_length;
14876 n_frames_div_2 = tng_max_i64(1, n_frames_div_2 + 1);
14878 memcpy(*values, (char *)current_values + n_frames_div * frame_size,
14879 n_frames_div_2 * frame_size);
14881 current_frame_pos += n_frames - current_frame_pos;
14883 while(current_frame_pos <= end_frame_nr - start_frame_nr)
14885 stat = tng_frame_set_read_next(tng_data, hash_mode);
14886 if(stat != TNG_SUCCESS)
14888 if(current_values)
14890 free(current_values);
14892 free(*values);
14893 *values = 0;
14894 return(stat);
14897 stat = tng_gen_data_vector_get(tng_data, block_id, is_particle_data,
14898 &current_values, &n_frames,
14899 stride_length, n_particles,
14900 n_values_per_frame, type);
14902 if(stat != TNG_SUCCESS)
14904 if(current_values)
14906 free(current_values);
14908 free(*values);
14909 *values = 0;
14910 return(stat);
14913 last_frame_pos = tng_min_i64(n_frames,
14914 end_frame_nr - current_frame_pos);
14916 n_frames_div = current_frame_pos / *stride_length;
14917 n_frames_div_2 = (last_frame_pos % *stride_length) ?
14918 last_frame_pos / *stride_length + 1:
14919 last_frame_pos / *stride_length;
14920 n_frames_div_2 = tng_max_i64(1, n_frames_div_2);
14922 memcpy(((char *)*values) + n_frames_div * frame_size,
14923 current_values,
14924 n_frames_div_2 * frame_size);
14926 current_frame_pos += n_frames;
14930 if(current_values)
14932 free(current_values);
14935 data->last_retrieved_frame = end_frame_nr;
14937 return(TNG_SUCCESS);
14941 tng_function_status DECLSPECDLLEXPORT tng_data_vector_interval_get
14942 (const tng_trajectory_t tng_data,
14943 const int64_t block_id,
14944 const int64_t start_frame_nr,
14945 const int64_t end_frame_nr,
14946 const char hash_mode,
14947 void **values,
14948 int64_t *stride_length,
14949 int64_t *n_values_per_frame,
14950 char *type)
14952 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14953 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than the end_frame_nr.");
14954 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
14955 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
14956 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
14958 return(tng_gen_data_vector_interval_get(tng_data, block_id, TNG_FALSE,
14959 start_frame_nr, end_frame_nr,
14960 hash_mode, values, 0, stride_length,
14961 n_values_per_frame, type));
14964 tng_function_status DECLSPECDLLEXPORT tng_particle_data_get
14965 (const tng_trajectory_t tng_data,
14966 const int64_t block_id,
14967 union data_values ****values,
14968 int64_t *n_frames,
14969 int64_t *n_particles,
14970 int64_t *n_values_per_frame,
14971 char *type)
14973 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14974 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
14975 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
14976 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
14977 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
14979 return(tng_gen_data_get(tng_data, block_id, TNG_TRUE, values, n_frames, n_particles,
14980 n_values_per_frame, type));
14983 tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_get
14984 (const tng_trajectory_t tng_data,
14985 const int64_t block_id,
14986 void **values,
14987 int64_t *n_frames,
14988 int64_t *stride_length,
14989 int64_t *n_particles,
14990 int64_t *n_values_per_frame,
14991 char *type)
14993 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14994 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
14995 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
14996 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
14997 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
14999 return(tng_gen_data_vector_get(tng_data, block_id, TNG_TRUE, values,
15000 n_frames, stride_length, n_particles,
15001 n_values_per_frame, type));
15004 tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
15005 (const tng_trajectory_t tng_data,
15006 const int64_t block_id,
15007 const int64_t start_frame_nr,
15008 const int64_t end_frame_nr,
15009 const char hash_mode,
15010 union data_values ****values,
15011 int64_t *n_particles,
15012 int64_t *n_values_per_frame,
15013 char *type)
15015 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15016 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
15017 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
15018 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15019 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15021 return(tng_gen_data_interval_get(tng_data, block_id, TNG_TRUE, start_frame_nr,
15022 end_frame_nr, hash_mode, values, n_particles,
15023 n_values_per_frame, type));
15026 tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_interval_get
15027 (const tng_trajectory_t tng_data,
15028 const int64_t block_id,
15029 const int64_t start_frame_nr,
15030 const int64_t end_frame_nr,
15031 const char hash_mode,
15032 void **values,
15033 int64_t *n_particles,
15034 int64_t *stride_length,
15035 int64_t *n_values_per_frame,
15036 char *type)
15038 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15039 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
15040 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
15041 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
15042 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15043 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15045 return(tng_gen_data_vector_interval_get(tng_data, block_id, TNG_TRUE,
15046 start_frame_nr, end_frame_nr,
15047 hash_mode, values, n_particles,
15048 stride_length, n_values_per_frame,
15049 type));
15052 tng_function_status DECLSPECDLLEXPORT tng_data_get_stride_length
15053 (const tng_trajectory_t tng_data,
15054 const int64_t block_id,
15055 int64_t frame,
15056 int64_t *stride_length)
15058 tng_function_status stat;
15059 tng_data_t data;
15060 int64_t orig_file_pos, file_pos;
15061 int is_particle_data;
15063 if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
15065 frame = 0;
15068 if(frame >= 0)
15070 stat = tng_frame_set_of_frame_find(tng_data, frame);
15071 if(stat != TNG_SUCCESS)
15073 return(stat);
15076 orig_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
15077 stat = tng_data_find(tng_data, block_id, &data);
15078 if(stat != TNG_SUCCESS)
15080 stat = tng_particle_data_find(tng_data, block_id, &data);
15081 if(stat != TNG_SUCCESS)
15083 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15084 /* If no specific frame was required read until this data block is found */
15085 if(frame < 0)
15087 file_pos = ftello(tng_data->input_file);
15088 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
15090 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15091 file_pos = ftello(tng_data->input_file);
15094 if(stat != TNG_SUCCESS)
15096 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
15098 return(stat);
15100 stat = tng_data_find(tng_data, block_id, &data);
15101 if(stat != TNG_SUCCESS)
15103 stat = tng_particle_data_find(tng_data, block_id, &data);
15104 if(stat != TNG_SUCCESS)
15106 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
15108 return(stat);
15110 else
15112 is_particle_data = 1;
15115 else
15117 is_particle_data = 0;
15120 else
15122 is_particle_data = 1;
15125 else
15127 is_particle_data = 0;
15129 if(is_particle_data)
15131 *stride_length = data->stride_length;
15133 else
15135 *stride_length = data->stride_length;
15137 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
15139 return(TNG_SUCCESS);
15142 tng_function_status DECLSPECDLLEXPORT tng_time_get_str
15143 (const tng_trajectory_t tng_data,
15144 char *time)
15146 struct tm *time_data;
15147 time_t secs;
15149 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15150 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
15152 secs = tng_data->time;
15154 time_data = localtime(&secs); /* Returns a statically allocated variable. */
15155 TNG_SNPRINTF(time, TNG_MAX_DATE_STR_LEN,
15156 "%4d-%02d-%02d %02d:%02d:%02d",
15157 time_data->tm_year+1900, time_data->tm_mon+1, time_data->tm_mday,
15158 time_data->tm_hour, time_data->tm_min, time_data->tm_sec);
15160 return(TNG_SUCCESS);
15164 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_open
15165 (const char *filename,
15166 const char mode,
15167 tng_trajectory_t *tng_data_p)
15169 tng_function_status stat;
15171 TNG_ASSERT(filename, "TNG library: filename must not be a NULL pointer.");
15173 if(mode != 'r' && mode != 'w' && mode != 'a')
15175 return(TNG_FAILURE);
15178 if(tng_trajectory_init(tng_data_p) != TNG_SUCCESS)
15180 tng_trajectory_destroy(tng_data_p);
15181 return(TNG_CRITICAL);
15184 if(mode == 'w')
15186 stat = tng_output_file_set(*tng_data_p, filename);
15187 return(stat);
15189 tng_input_file_set(*tng_data_p, filename);
15191 /* Read the file headers */
15192 tng_file_headers_read(*tng_data_p, TNG_USE_HASH);
15194 stat = tng_num_frame_sets_get(*tng_data_p, &(*tng_data_p)->n_trajectory_frame_sets);
15196 if(stat != TNG_SUCCESS)
15198 return(stat);
15201 if(mode == 'a')
15203 if((*tng_data_p)->output_file)
15205 fclose((*tng_data_p)->output_file);
15207 (*tng_data_p)->output_file = (*tng_data_p)->input_file;
15208 fseeko((*tng_data_p)->input_file,
15209 (*tng_data_p)->last_trajectory_frame_set_input_file_pos,
15210 SEEK_SET);
15212 stat = tng_frame_set_read(*tng_data_p, TNG_USE_HASH);
15213 if(stat != TNG_SUCCESS)
15215 fprintf(stderr, "TNG library: Cannot read frame set and related blocks. %s: %d\n",
15216 __FILE__, __LINE__);
15218 (*tng_data_p)->output_file = 0;
15220 (*tng_data_p)->first_trajectory_frame_set_output_file_pos =
15221 (*tng_data_p)->first_trajectory_frame_set_input_file_pos;
15222 (*tng_data_p)->last_trajectory_frame_set_output_file_pos =
15223 (*tng_data_p)->last_trajectory_frame_set_input_file_pos;
15224 (*tng_data_p)->current_trajectory_frame_set_output_file_pos =
15225 (*tng_data_p)->current_trajectory_frame_set_input_file_pos;
15226 if((*tng_data_p)->input_file)
15228 fclose((*tng_data_p)->input_file);
15229 (*tng_data_p)->input_file = 0;
15231 if((*tng_data_p)->input_file_path)
15233 free((*tng_data_p)->input_file_path);
15234 (*tng_data_p)->input_file_path = 0;
15236 tng_output_append_file_set(*tng_data_p, filename);
15238 fseeko((*tng_data_p)->output_file, 0, SEEK_END);
15240 (*tng_data_p)->output_endianness_swap_func_32 = (*tng_data_p)->input_endianness_swap_func_32;
15241 (*tng_data_p)->output_endianness_swap_func_64 = (*tng_data_p)->input_endianness_swap_func_64;
15244 return(stat);
15247 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_close
15248 (tng_trajectory_t *tng_data_p)
15250 tng_trajectory_frame_set_t frame_set;
15252 if(tng_data_p == 0)
15254 fprintf(stderr, "TNG library: Empty pointer to trajectory when attempting to close. %s: %d\n",
15255 __FILE__, __LINE__);
15256 return(TNG_FAILURE);
15259 if(*tng_data_p == 0)
15261 return(TNG_SUCCESS);
15264 frame_set = &(*tng_data_p)->current_trajectory_frame_set;
15266 if(frame_set->n_unwritten_frames > 0)
15268 frame_set->n_frames = frame_set->n_unwritten_frames;
15269 tng_frame_set_write(*tng_data_p, TNG_USE_HASH);
15272 return(tng_trajectory_destroy(tng_data_p));
15275 tng_function_status DECLSPECDLLEXPORT tng_util_time_of_frame_get
15276 (const tng_trajectory_t tng_data,
15277 const int64_t frame_nr,
15278 double *time)
15280 int64_t first_frame;
15281 tng_trajectory_frame_set_t frame_set;
15282 tng_function_status stat;
15284 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15285 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
15287 stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
15288 if(stat != TNG_SUCCESS)
15290 fprintf(stderr, "TNG library: Cannot find frame nr %" PRId64 ". %s: %d\n",
15291 frame_nr, __FILE__, __LINE__);
15292 return(stat);
15295 frame_set = &tng_data->current_trajectory_frame_set;
15296 first_frame = frame_set->first_frame;
15298 if(tng_data->time_per_frame <= 0)
15300 return(TNG_FAILURE);
15303 *time = frame_set->first_frame_time + (tng_data->time_per_frame * (frame_nr - first_frame));
15305 return(TNG_SUCCESS);
15309 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecules_get
15310 (const tng_trajectory_t tng_data,
15311 int64_t *n_mols,
15312 int64_t **molecule_cnt_list,
15313 tng_molecule_t *mols)
15315 tng_trajectory_frame_set_t frame_set;
15317 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15318 TNG_ASSERT(n_mols, "TNG library: n_mols must not be a NULL pointer.");
15320 *n_mols = tng_data->n_molecules;
15322 frame_set = &tng_data->current_trajectory_frame_set;
15323 if(tng_data->var_num_atoms_flag && frame_set && frame_set->molecule_cnt_list)
15325 *molecule_cnt_list = frame_set->molecule_cnt_list;
15327 else
15329 *molecule_cnt_list = tng_data->molecule_cnt_list;
15332 *mols = tng_data->molecules;
15334 return(TNG_SUCCESS);
15338 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecule_add
15339 (const tng_trajectory_t tng_data,
15340 const char *name,
15341 const int64_t cnt,
15342 tng_molecule_t *mol)
15344 tng_function_status stat;
15346 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
15347 TNG_ASSERT(cnt>=0, "TNG library: cnt must be >= 0");
15349 stat = tng_molecule_add(tng_data, name, mol);
15350 if(stat != TNG_SUCCESS)
15352 return(stat);
15354 stat = tng_molecule_cnt_set(tng_data, *mol, cnt);
15356 return(stat);
15359 tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_get
15360 (const tng_trajectory_t tng_data,
15361 const tng_molecule_t mol,
15362 int64_t *n_particles,
15363 char ***names,
15364 char ***types,
15365 char ***res_names,
15366 int64_t **res_ids,
15367 char ***chain_names,
15368 int64_t **chain_ids)
15370 tng_atom_t atom;
15371 tng_residue_t res;
15372 tng_chain_t chain;
15373 int64_t i;
15374 (void)tng_data;
15376 *n_particles = mol->n_atoms;
15378 *names = (char **)malloc(sizeof(char *) * *n_particles);
15379 *types = (char **)malloc(sizeof(char *) * *n_particles);
15380 *res_names = (char **)malloc(sizeof(char *) * *n_particles);
15381 *chain_names = (char **)malloc(sizeof(char *) * *n_particles);
15382 *res_ids = (int64_t *)malloc(sizeof(int64_t) * *n_particles);
15383 *chain_ids = (int64_t *)malloc(sizeof(int64_t) * *n_particles);
15385 for(i = 0; i < *n_particles; i++)
15387 atom = &mol->atoms[i];
15388 res = atom->residue;
15389 chain = res->chain;
15390 (*names)[i] = (char *)malloc(strlen(atom->name));
15391 strcpy(*names[i], atom->name);
15392 (*types)[i] = (char *)malloc(strlen(atom->atom_type));
15393 strcpy(*types[i], atom->atom_type);
15394 (*res_names)[i] = (char *)malloc(strlen(res->name));
15395 strcpy(*res_names[i], res->name);
15396 (*chain_names)[i] = (char *)malloc(strlen(chain->name));
15397 strcpy(*chain_names[i], chain->name);
15398 (*res_ids)[i] = res->id;
15399 (*chain_ids)[i] = chain->id;
15402 return(TNG_SUCCESS);
15405 tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_set
15406 (const tng_trajectory_t tng_data,
15407 const tng_molecule_t mol,
15408 const int64_t n_particles,
15409 const char **names,
15410 const char **types,
15411 const char **res_names,
15412 const int64_t *res_ids,
15413 const char **chain_names,
15414 const int64_t *chain_ids)
15416 int64_t i;
15417 tng_chain_t chain;
15418 tng_residue_t residue;
15419 tng_atom_t atom;
15420 tng_function_status stat;
15422 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15423 TNG_ASSERT(names, "TNG library: names must not be a NULL pointer");
15424 TNG_ASSERT(types, "TNG library: types must not be a NULL pointer");
15425 TNG_ASSERT(res_names, "TNG library: res_names must not be a NULL pointer");
15426 TNG_ASSERT(res_ids, "TNG library: res_ids must not be a NULL pointer");
15427 TNG_ASSERT(chain_names, "TNG library: chain_names must not be a NULL pointer");
15428 TNG_ASSERT(chain_ids, "TNG library: chain_ids must not be a NULL pointer");
15430 for(i = 0; i < n_particles; i++)
15432 if(tng_molecule_chain_find(tng_data, mol, chain_names[i], chain_ids[i],
15433 &chain) == TNG_FAILURE)
15435 stat = tng_molecule_chain_add(tng_data, mol, chain_names[i],
15436 &chain);
15437 if(stat != TNG_SUCCESS)
15439 return(stat);
15442 if(tng_chain_residue_find(tng_data, chain, res_names[i], res_ids[i],
15443 &residue) == TNG_FAILURE)
15445 stat = tng_chain_residue_add(tng_data, chain, res_names[i],
15446 &residue);
15447 if(stat != TNG_SUCCESS)
15449 return(stat);
15452 stat = tng_residue_atom_add(tng_data, residue, names[i], types[i], &atom);
15453 if(stat != TNG_SUCCESS)
15455 return(stat);
15458 return(TNG_SUCCESS);
15461 tng_function_status DECLSPECDLLEXPORT tng_util_pos_read
15462 (const tng_trajectory_t tng_data,
15463 float **positions, int64_t *stride_length)
15465 int64_t n_frames, n_particles, n_values_per_frame;
15466 char type;
15467 tng_function_status stat;
15469 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15470 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
15471 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
15473 stat = tng_num_frames_get(tng_data, &n_frames);
15474 if(stat != TNG_SUCCESS)
15476 return(stat);
15479 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_POSITIONS,
15480 0, n_frames - 1, TNG_USE_HASH,
15481 (void **)positions,
15482 &n_particles,
15483 stride_length,
15484 &n_values_per_frame,
15485 &type);
15487 if(stat == TNG_SUCCESS && type != TNG_FLOAT_DATA)
15489 return(TNG_FAILURE);
15492 return(stat);
15495 tng_function_status DECLSPECDLLEXPORT tng_util_vel_read
15496 (const tng_trajectory_t tng_data,
15497 float **velocities, int64_t *stride_length)
15499 int64_t n_frames, n_particles, n_values_per_frame;
15500 char type;
15501 tng_function_status stat;
15503 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15504 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
15505 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
15507 stat = tng_num_frames_get(tng_data, &n_frames);
15508 if(stat != TNG_SUCCESS)
15510 return(stat);
15513 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_VELOCITIES,
15514 0, n_frames - 1, TNG_USE_HASH,
15515 (void **)velocities,
15516 &n_particles,
15517 stride_length,
15518 &n_values_per_frame,
15519 &type);
15521 if(stat == TNG_SUCCESS && type != TNG_FLOAT_DATA)
15523 return(TNG_FAILURE);
15526 return(stat);
15529 tng_function_status DECLSPECDLLEXPORT tng_util_force_read
15530 (const tng_trajectory_t tng_data,
15531 float **forces, int64_t *stride_length)
15533 int64_t n_frames, n_particles, n_values_per_frame;
15534 char type;
15535 tng_function_status stat;
15537 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15538 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
15539 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
15541 stat = tng_num_frames_get(tng_data, &n_frames);
15542 if(stat != TNG_SUCCESS)
15544 return(stat);
15547 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_FORCES,
15548 0, n_frames - 1, TNG_USE_HASH,
15549 (void **)forces,
15550 &n_particles,
15551 stride_length,
15552 &n_values_per_frame,
15553 &type);
15555 if(stat == TNG_SUCCESS && type != TNG_FLOAT_DATA)
15557 return(TNG_FAILURE);
15560 return(stat);
15563 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read
15564 (const tng_trajectory_t tng_data,
15565 float **box_shape,
15566 int64_t *stride_length)
15568 int64_t n_frames, n_values_per_frame;
15569 char type;
15570 tng_function_status stat;
15572 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15573 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
15574 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
15576 stat = tng_num_frames_get(tng_data, &n_frames);
15577 if(stat != TNG_SUCCESS)
15579 return(stat);
15582 stat = tng_data_vector_interval_get(tng_data, TNG_TRAJ_BOX_SHAPE,
15583 0, n_frames - 1, TNG_USE_HASH,
15584 (void **)box_shape,
15585 stride_length,
15586 &n_values_per_frame,
15587 &type);
15589 if(stat == TNG_SUCCESS && type != TNG_FLOAT_DATA)
15591 return(TNG_FAILURE);
15594 return(stat);
15597 tng_function_status DECLSPECDLLEXPORT tng_util_particle_data_next_frame_read
15598 (const tng_trajectory_t tng_data,
15599 const int64_t block_id,
15600 void **values,
15601 char *data_type,
15602 int64_t *retrieved_frame_number,
15603 double *retrieved_time)
15605 tng_trajectory_frame_set_t frame_set;
15606 tng_data_t data = 0;
15607 tng_function_status stat;
15608 int size;
15609 int64_t i, full_data_len, n_particles;
15610 void *temp;
15611 int64_t file_pos;
15613 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15614 TNG_ASSERT(values, "TNG library: The pointer to the values array must not be a NULL pointer");
15615 TNG_ASSERT(data_type, "TNG library: The pointer to the data type of the returned data must not be a NULL pointer");
15616 TNG_ASSERT(retrieved_frame_number, "TNG library: The pointer to the frame number of the returned data must not be a NULL pointer");
15617 TNG_ASSERT(retrieved_time, "TNG library: The pointer to the time of the returned data must not be a NULL pointer");
15619 frame_set = &tng_data->current_trajectory_frame_set;
15621 stat = tng_particle_data_find(tng_data, block_id, &data);
15622 if(stat != TNG_SUCCESS)
15624 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15625 file_pos = ftello(tng_data->input_file);
15626 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
15628 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15629 file_pos = ftello(tng_data->input_file);
15631 if(stat != TNG_SUCCESS)
15633 return(stat);
15635 stat = tng_particle_data_find(tng_data, block_id, &data);
15636 if(stat != TNG_SUCCESS)
15638 return(stat);
15641 if(data->last_retrieved_frame < 0)
15643 fseeko(tng_data->input_file,
15644 tng_data->first_trajectory_frame_set_input_file_pos,
15645 SEEK_SET);
15646 stat = tng_frame_set_read(tng_data, TNG_USE_HASH);
15647 if(stat != TNG_SUCCESS)
15649 return(stat);
15651 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15652 if(stat != TNG_SUCCESS)
15654 return(stat);
15657 i = data->first_frame_with_data;
15659 else
15661 if(data->n_frames == 1 && frame_set->n_frames == 1)
15663 i = data->last_retrieved_frame + 1;
15665 else
15667 i = data->last_retrieved_frame + data->stride_length;
15669 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
15671 stat = tng_frame_set_of_frame_find(tng_data, i);
15672 if(stat != TNG_SUCCESS)
15674 /* If the frame set search found the frame set after the starting
15675 * frame set there is a gap in the frame sets. So, even if the frame
15676 * was not found the next frame with data is still in the found
15677 * frame set. */
15678 if(stat == TNG_CRITICAL)
15680 return(stat);
15682 if(frame_set->first_frame + frame_set->n_frames - 1 < i)
15684 return(TNG_FAILURE);
15686 i = frame_set->first_frame;
15689 if(data->last_retrieved_frame < frame_set->first_frame)
15691 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15692 if(stat != TNG_SUCCESS)
15694 return(stat);
15698 data->last_retrieved_frame = i;
15699 *retrieved_frame_number = i;
15700 if(frame_set->first_frame_time >= 0 && tng_data->time_per_frame >= 0)
15702 *retrieved_time = frame_set->first_frame_time +
15703 (i - frame_set->first_frame) *
15704 tng_data->time_per_frame;
15706 else
15708 *retrieved_time = 0;
15711 if(data->stride_length > 1)
15713 i = (i - data->first_frame_with_data) / data->stride_length;
15715 else
15717 i = (i - frame_set->first_frame);
15720 tng_num_particles_get(tng_data, &n_particles);
15722 *data_type = data->datatype;
15724 switch(*data_type)
15726 case TNG_CHAR_DATA:
15727 return(TNG_FAILURE);
15728 case TNG_INT_DATA:
15729 size = sizeof(int64_t);
15730 break;
15731 case TNG_FLOAT_DATA:
15732 size = sizeof(float);
15733 break;
15734 case TNG_DOUBLE_DATA:
15735 default:
15736 size = sizeof(double);
15739 full_data_len = size * n_particles * data->n_values_per_frame;
15741 // fprintf(stderr, "TNG library: TEMP: i = %" PRId64 ", full_data_len = %" PRId64 ", size = %d, n_particles = %" PRId64 ", n_values_per_frame = %" PRId64 "\n",
15742 // i, full_data_len, size, n_particles, data->n_values_per_frame);
15744 temp = (char *)realloc(*values, full_data_len);
15745 if(!temp)
15747 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
15748 __FILE__, __LINE__);
15749 free(*values);
15750 *values = 0;
15751 return(TNG_CRITICAL);
15754 *values = temp;
15756 memcpy(*values, (char *)data->values + i * full_data_len, full_data_len);
15758 return(TNG_SUCCESS);
15761 tng_function_status DECLSPECDLLEXPORT tng_util_non_particle_data_next_frame_read
15762 (const tng_trajectory_t tng_data,
15763 const int64_t block_id,
15764 void **values,
15765 char *data_type,
15766 int64_t *retrieved_frame_number,
15767 double *retrieved_time)
15769 tng_trajectory_frame_set_t frame_set;
15770 tng_data_t data = 0;
15771 tng_function_status stat;
15772 int size;
15773 int64_t i, full_data_len;
15774 void *temp;
15775 int64_t file_pos;
15777 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15778 TNG_ASSERT(values, "TNG library: The pointer to the values array must not be a NULL pointer");
15779 TNG_ASSERT(data_type, "TNG library: The pointer to the data type of the returned data must not be a NULL pointer");
15780 TNG_ASSERT(retrieved_frame_number, "TNG library: The pointer to the frame number of the returned data must not be a NULL pointer");
15781 TNG_ASSERT(retrieved_time, "TNG library: The pointer to the time of the returned data must not be a NULL pointer");
15783 frame_set = &tng_data->current_trajectory_frame_set;
15785 stat = tng_data_find(tng_data, block_id, &data);
15786 if(stat != TNG_SUCCESS)
15788 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15789 file_pos = ftello(tng_data->input_file);
15790 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
15792 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15793 file_pos = ftello(tng_data->input_file);
15795 if(stat != TNG_SUCCESS)
15797 return(stat);
15799 stat = tng_data_find(tng_data, block_id, &data);
15800 if(stat != TNG_SUCCESS)
15802 return(stat);
15805 if(data->last_retrieved_frame < 0)
15807 fseeko(tng_data->input_file,
15808 tng_data->first_trajectory_frame_set_input_file_pos,
15809 SEEK_SET);
15810 stat = tng_frame_set_read(tng_data, TNG_USE_HASH);
15811 if(stat != TNG_SUCCESS)
15813 return(stat);
15815 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15816 if(stat != TNG_SUCCESS)
15818 return(stat);
15821 i = data->first_frame_with_data;
15823 else
15825 if(data->n_frames == 1 && frame_set->n_frames == 1)
15827 i = data->last_retrieved_frame + 1;
15829 else
15831 i = data->last_retrieved_frame + data->stride_length;
15833 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
15835 stat = tng_frame_set_of_frame_find(tng_data, i);
15836 if(stat != TNG_SUCCESS)
15838 /* If the frame set search found the frame set after the starting
15839 * frame set there is a gap in the frame sets. So, even if the frame
15840 * was not found the next frame with data is still in the found
15841 * frame set. */
15842 if(stat == TNG_CRITICAL)
15844 return(stat);
15846 if(frame_set->first_frame + frame_set->n_frames - 1 < i)
15848 return(TNG_FAILURE);
15850 i = frame_set->first_frame;
15853 if(data->last_retrieved_frame < frame_set->first_frame)
15855 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15856 if(stat != TNG_SUCCESS)
15858 return(stat);
15862 data->last_retrieved_frame = i;
15863 *retrieved_frame_number = i;
15864 if(frame_set->first_frame_time >= 0 && tng_data->time_per_frame >= 0)
15866 *retrieved_time = frame_set->first_frame_time +
15867 (i - frame_set->first_frame) *
15868 tng_data->time_per_frame;
15870 else
15872 *retrieved_time = 0;
15875 if(data->stride_length > 1)
15877 i = (i - data->first_frame_with_data) / data->stride_length;
15879 else
15881 i = (i - frame_set->first_frame);
15884 *data_type = data->datatype;
15886 switch(*data_type)
15888 case TNG_CHAR_DATA:
15889 return(TNG_FAILURE);
15890 case TNG_INT_DATA:
15891 size = sizeof(int64_t);
15892 break;
15893 case TNG_FLOAT_DATA:
15894 size = sizeof(float);
15895 break;
15896 case TNG_DOUBLE_DATA:
15897 default:
15898 size = sizeof(double);
15901 full_data_len = size * data->n_values_per_frame;
15903 temp = (char *)realloc(*values, full_data_len);
15904 if(!temp)
15906 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
15907 __FILE__, __LINE__);
15908 free(*values);
15909 *values = 0;
15910 return(TNG_CRITICAL);
15913 *values = temp;
15915 memcpy(*values, (char *)data->values + i * full_data_len, full_data_len);
15917 return(TNG_SUCCESS);
15920 tng_function_status DECLSPECDLLEXPORT tng_util_pos_read_range
15921 (const tng_trajectory_t tng_data,
15922 const int64_t first_frame,
15923 const int64_t last_frame,
15924 float **positions,
15925 int64_t *stride_length)
15927 int64_t n_particles, n_values_per_frame;
15928 char type;
15929 tng_function_status stat;
15931 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15932 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
15933 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
15934 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
15936 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_POSITIONS,
15937 first_frame, last_frame,
15938 TNG_USE_HASH,
15939 (void **)positions,
15940 &n_particles,
15941 stride_length,
15942 &n_values_per_frame,
15943 &type);
15945 if(stat == TNG_SUCCESS && type != TNG_FLOAT_DATA)
15947 return(TNG_FAILURE);
15950 return(stat);
15953 tng_function_status DECLSPECDLLEXPORT tng_util_vel_read_range
15954 (const tng_trajectory_t tng_data,
15955 const int64_t first_frame,
15956 const int64_t last_frame,
15957 float **velocities,
15958 int64_t *stride_length)
15960 int64_t n_particles, n_values_per_frame;
15961 char type;
15962 tng_function_status stat;
15964 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15965 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
15966 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
15967 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
15969 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_VELOCITIES,
15970 first_frame, last_frame,
15971 TNG_USE_HASH,
15972 (void **)velocities,
15973 &n_particles,
15974 stride_length,
15975 &n_values_per_frame,
15976 &type);
15978 if(stat == TNG_SUCCESS && type != TNG_FLOAT_DATA)
15980 return(TNG_FAILURE);
15983 return(stat);
15986 tng_function_status DECLSPECDLLEXPORT tng_util_force_read_range
15987 (const tng_trajectory_t tng_data,
15988 const int64_t first_frame,
15989 const int64_t last_frame,
15990 float **forces,
15991 int64_t *stride_length)
15993 int64_t n_particles, n_values_per_frame;
15994 char type;
15995 tng_function_status stat;
15997 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15998 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
15999 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
16000 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
16002 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_FORCES,
16003 first_frame, last_frame,
16004 TNG_USE_HASH,
16005 (void **)forces,
16006 &n_particles,
16007 stride_length,
16008 &n_values_per_frame,
16009 &type);
16011 if(stat == TNG_SUCCESS && type != TNG_FLOAT_DATA)
16013 return(TNG_FAILURE);
16016 return(stat);
16019 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read_range
16020 (const tng_trajectory_t tng_data,
16021 const int64_t first_frame,
16022 const int64_t last_frame,
16023 float **box_shape,
16024 int64_t *stride_length)
16026 int64_t n_values_per_frame;
16027 char type;
16028 tng_function_status stat;
16030 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16031 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
16032 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
16033 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
16035 stat = tng_data_vector_interval_get(tng_data, TNG_TRAJ_BOX_SHAPE,
16036 first_frame, last_frame,
16037 TNG_USE_HASH,
16038 (void **)box_shape,
16039 stride_length,
16040 &n_values_per_frame,
16041 &type);
16043 if(stat == TNG_SUCCESS && type != TNG_FLOAT_DATA)
16045 return(TNG_FAILURE);
16048 return(stat);
16051 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_set
16052 (const tng_trajectory_t tng_data,
16053 const int64_t i,
16054 const int64_t n_values_per_frame,
16055 const int64_t block_id,
16056 const char *block_name,
16057 const char particle_dependency,
16058 const char compression)
16060 tng_trajectory_frame_set_t frame_set;
16061 tng_data_t data;
16062 int64_t n_particles, n_frames;
16063 tng_function_status stat;
16065 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16066 TNG_ASSERT(i >= 0, "TNG library: i (writing interval) must be >= 0.");
16068 if(i <= 0)
16070 fprintf(stderr, "TNG library: Cannot set writing frequency to %" PRId64 ". %s: %d\n",
16071 i, __FILE__, __LINE__);
16072 return(TNG_FAILURE);
16075 frame_set = &tng_data->current_trajectory_frame_set;
16077 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
16079 n_frames = tng_data->frame_set_n_frames;
16081 stat = tng_frame_set_new(tng_data, 0, n_frames);
16082 if(stat != TNG_SUCCESS)
16084 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
16085 __LINE__);
16086 return(stat);
16089 else
16091 n_frames = frame_set->n_frames;
16094 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
16096 tng_num_particles_get(tng_data, &n_particles);
16097 if(n_particles <= 0)
16099 return(TNG_FAILURE);
16102 if(tng_particle_data_find(tng_data, block_id, &data)
16103 != TNG_SUCCESS)
16105 stat = tng_particle_data_block_add(tng_data, block_id,
16106 block_name,
16107 TNG_FLOAT_DATA,
16108 TNG_TRAJECTORY_BLOCK,
16109 n_frames, n_values_per_frame, i,
16110 0, n_particles,
16111 compression, 0);
16112 if(stat != TNG_SUCCESS)
16114 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16115 __FILE__, __LINE__);
16116 return(stat);
16118 data = &frame_set->tr_particle_data[frame_set->
16119 n_particle_data_blocks - 1];
16120 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
16121 i, n_particles,
16122 n_values_per_frame);
16123 if(stat != TNG_SUCCESS)
16125 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16126 __FILE__, __LINE__);
16127 return(stat);
16130 else
16132 if(data->stride_length != i)
16134 data->stride_length = i;
16135 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
16136 i, n_particles,
16137 n_values_per_frame);
16138 if(stat != TNG_SUCCESS)
16140 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16141 __FILE__, __LINE__);
16142 return(stat);
16147 else
16149 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
16151 stat = tng_data_block_add(tng_data, block_id, block_name,
16152 TNG_FLOAT_DATA, TNG_TRAJECTORY_BLOCK,
16153 n_frames, n_values_per_frame,
16154 i, compression, 0);
16155 if(stat != TNG_SUCCESS)
16157 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16158 __FILE__, __LINE__);
16159 return(stat);
16161 data = &frame_set->tr_data[frame_set->
16162 n_data_blocks - 1];
16163 stat = tng_allocate_data_mem(tng_data, data, n_frames,
16164 i, n_values_per_frame);
16165 if(stat != TNG_SUCCESS)
16167 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16168 __FILE__, __LINE__);
16169 return(stat);
16172 else
16174 if(data->stride_length != i)
16176 data->stride_length = i;
16177 stat = tng_allocate_data_mem(tng_data, data, n_frames,
16178 i, n_values_per_frame);
16179 if(stat != TNG_SUCCESS)
16181 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16182 __FILE__, __LINE__);
16183 return(stat);
16189 return(TNG_SUCCESS);
16192 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_double_set
16193 (const tng_trajectory_t tng_data,
16194 const int64_t i,
16195 const int64_t n_values_per_frame,
16196 const int64_t block_id,
16197 const char *block_name,
16198 const char particle_dependency,
16199 const char compression)
16201 tng_trajectory_frame_set_t frame_set;
16202 tng_data_t data;
16203 int64_t n_particles, n_frames;
16204 tng_function_status stat;
16206 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16207 TNG_ASSERT(i >= 0, "TNG library: i (writing interval) must be >= 0.");
16209 if(i <= 0)
16211 fprintf(stderr, "TNG library: Cannot set writing frequency to %" PRId64 ". %s: %d\n",
16212 i, __FILE__, __LINE__);
16213 return(TNG_FAILURE);
16216 frame_set = &tng_data->current_trajectory_frame_set;
16218 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
16220 n_frames = tng_data->frame_set_n_frames;
16222 stat = tng_frame_set_new(tng_data, 0, n_frames);
16223 if(stat != TNG_SUCCESS)
16225 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
16226 __LINE__);
16227 return(stat);
16230 else
16232 n_frames = frame_set->n_frames;
16235 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
16237 tng_num_particles_get(tng_data, &n_particles);
16239 if(n_particles <= 0)
16241 return(TNG_FAILURE);
16244 if(tng_particle_data_find(tng_data, block_id, &data)
16245 != TNG_SUCCESS)
16247 stat = tng_particle_data_block_add(tng_data, block_id,
16248 block_name,
16249 TNG_DOUBLE_DATA,
16250 TNG_TRAJECTORY_BLOCK,
16251 n_frames, n_values_per_frame, i,
16252 0, n_particles,
16253 compression, 0);
16254 if(stat != TNG_SUCCESS)
16256 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16257 __FILE__, __LINE__);
16258 return(stat);
16260 data = &frame_set->tr_particle_data[frame_set->
16261 n_particle_data_blocks - 1];
16262 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
16263 i, n_particles,
16264 n_values_per_frame);
16265 if(stat != TNG_SUCCESS)
16267 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16268 __FILE__, __LINE__);
16269 return(stat);
16272 else
16274 data->stride_length = i;
16277 else
16279 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
16281 stat = tng_data_block_add(tng_data, block_id, block_name,
16282 TNG_DOUBLE_DATA, TNG_TRAJECTORY_BLOCK,
16283 n_frames, n_values_per_frame,
16284 i, compression, 0);
16285 if(stat != TNG_SUCCESS)
16287 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16288 __FILE__, __LINE__);
16289 return(stat);
16291 data = &frame_set->tr_data[frame_set->
16292 n_data_blocks - 1];
16293 stat = tng_allocate_data_mem(tng_data, data, n_frames,
16294 i, n_values_per_frame);
16295 if(stat != TNG_SUCCESS)
16297 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16298 __FILE__, __LINE__);
16299 return(stat);
16302 else
16304 data->stride_length = i;
16308 return(TNG_SUCCESS);
16311 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_frequency_set
16312 (const tng_trajectory_t tng_data,
16313 const int64_t i,
16314 const int64_t n_values_per_frame,
16315 const int64_t block_id,
16316 const char *block_name,
16317 const char particle_dependency,
16318 const char compression)
16320 fprintf(stderr, "TNG library: Using obsolete function tng_util_generic_write_frequency_set(). "
16321 "See documentation. %s: %d", __FILE__, __LINE__);
16322 return(tng_util_generic_write_interval_set(tng_data, i, n_values_per_frame,
16323 block_id, block_name,
16324 particle_dependency,
16325 compression));
16327 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_set
16328 (const tng_trajectory_t tng_data,
16329 const int64_t i)
16331 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16332 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
16334 return(tng_util_generic_write_interval_set(tng_data, i, 3,
16335 TNG_TRAJ_POSITIONS,
16336 "POSITIONS",
16337 TNG_PARTICLE_BLOCK_DATA,
16338 TNG_TNG_COMPRESSION));
16341 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_double_set
16342 (const tng_trajectory_t tng_data,
16343 const int64_t i)
16345 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16346 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
16348 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
16349 TNG_TRAJ_POSITIONS,
16350 "POSITIONS",
16351 TNG_PARTICLE_BLOCK_DATA,
16352 TNG_TNG_COMPRESSION));
16355 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_frequency_set
16356 (const tng_trajectory_t tng_data,
16357 const int64_t i)
16359 fprintf(stderr, "TNG library: Using obsolete function tng_util_pos_write_frequency_set(). "
16360 "See documentation. %s: %d", __FILE__, __LINE__);
16361 return(tng_util_pos_write_interval_set(tng_data, i));
16364 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_set
16365 (const tng_trajectory_t tng_data,
16366 const int64_t i)
16368 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16369 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
16371 return(tng_util_generic_write_interval_set(tng_data, i, 3,
16372 TNG_TRAJ_VELOCITIES,
16373 "VELOCITIES",
16374 TNG_PARTICLE_BLOCK_DATA,
16375 TNG_TNG_COMPRESSION));
16378 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_double_set
16379 (const tng_trajectory_t tng_data,
16380 const int64_t i)
16382 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16383 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
16385 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
16386 TNG_TRAJ_VELOCITIES,
16387 "VELOCITIES",
16388 TNG_PARTICLE_BLOCK_DATA,
16389 TNG_TNG_COMPRESSION));
16392 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_frequency_set
16393 (const tng_trajectory_t tng_data,
16394 const int64_t i)
16396 fprintf(stderr, "TNG library: Using obsolete function tng_util_vel_write_frequency_set(). "
16397 "See documentation. %s: %d", __FILE__, __LINE__);
16398 return(tng_util_vel_write_interval_set(tng_data, i));
16401 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_set
16402 (const tng_trajectory_t tng_data,
16403 const int64_t i)
16405 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16406 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
16408 return(tng_util_generic_write_interval_set(tng_data, i, 3,
16409 TNG_TRAJ_FORCES,
16410 "FORCES",
16411 TNG_PARTICLE_BLOCK_DATA,
16412 TNG_GZIP_COMPRESSION));
16415 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_double_set
16416 (const tng_trajectory_t tng_data,
16417 const int64_t i)
16419 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16420 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
16422 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
16423 TNG_TRAJ_FORCES,
16424 "FORCES",
16425 TNG_PARTICLE_BLOCK_DATA,
16426 TNG_GZIP_COMPRESSION));
16429 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_frequency_set
16430 (const tng_trajectory_t tng_data,
16431 const int64_t i)
16433 fprintf(stderr, "TNG library: Using obsolete function tng_util_force_write_frequency_set(). "
16434 "See documentation. %s: %d", __FILE__, __LINE__);
16435 return(tng_util_force_write_interval_set(tng_data, i));
16438 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_set
16439 (const tng_trajectory_t tng_data,
16440 const int64_t i)
16442 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16443 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
16445 return(tng_util_generic_write_interval_set(tng_data, i, 9,
16446 TNG_TRAJ_BOX_SHAPE,
16447 "BOX SHAPE",
16448 TNG_NON_PARTICLE_BLOCK_DATA,
16449 TNG_GZIP_COMPRESSION));
16452 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_double_set
16453 (const tng_trajectory_t tng_data,
16454 const int64_t i)
16456 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16457 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
16459 return(tng_util_generic_write_interval_double_set(tng_data, i, 9,
16460 TNG_TRAJ_BOX_SHAPE,
16461 "BOX SHAPE",
16462 TNG_NON_PARTICLE_BLOCK_DATA,
16463 TNG_GZIP_COMPRESSION));
16466 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_frequency_set
16467 (const tng_trajectory_t tng_data,
16468 const int64_t i)
16470 fprintf(stderr, "TNG library: Using obsolete function tng_util_box_shape_write_frequency_set(). "
16471 "See documentation. %s: %d", __FILE__, __LINE__);
16472 return(tng_util_box_shape_write_interval_set(tng_data, i));
16475 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write
16476 (const tng_trajectory_t tng_data,
16477 const int64_t frame_nr,
16478 const float *values,
16479 const int64_t n_values_per_frame,
16480 const int64_t block_id,
16481 const char *block_name,
16482 const char particle_dependency,
16483 const char compression)
16485 tng_trajectory_frame_set_t frame_set;
16486 tng_data_t data;
16487 int64_t n_particles = 0, n_frames, stride_length = 100, frame_pos;
16488 int64_t last_frame;
16489 int is_first_frame_flag = 0;
16490 char block_type_flag;
16491 tng_function_status stat;
16493 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16494 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
16496 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
16498 tng_num_particles_get(tng_data, &n_particles);
16499 TNG_ASSERT(n_particles > 0, "TNG library: There must be particles in the system to write particle data.");
16502 if(values == 0)
16504 return(TNG_FAILURE);
16507 frame_set = &tng_data->current_trajectory_frame_set;
16509 if(frame_nr < 0)
16511 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
16512 n_frames = stride_length = 1;
16514 else
16516 block_type_flag = TNG_TRAJECTORY_BLOCK;
16518 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
16520 stat = tng_frame_set_new(tng_data, 0, tng_data->frame_set_n_frames);
16521 if(stat != TNG_SUCCESS)
16523 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
16524 __LINE__);
16525 return(stat);
16528 last_frame = frame_set->first_frame +
16529 frame_set->n_frames - 1;
16530 if(frame_nr > last_frame)
16532 stat = tng_frame_set_write(tng_data, TNG_USE_HASH);
16533 if(stat != TNG_SUCCESS)
16535 fprintf(stderr, "TNG library: Cannot write frame set. %s: %d\n", __FILE__,
16536 __LINE__);
16537 return(stat);
16539 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
16541 last_frame = frame_nr - 1;
16543 stat = tng_frame_set_new(tng_data, last_frame + 1,
16544 tng_data->frame_set_n_frames);
16545 if(stat != TNG_SUCCESS)
16547 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
16548 __LINE__);
16549 return(stat);
16552 if(frame_set->n_unwritten_frames == 0)
16554 is_first_frame_flag = 1;
16556 frame_set->n_unwritten_frames = frame_nr -
16557 frame_set->first_frame + 1;
16559 n_frames = frame_set->n_frames;
16562 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
16564 if(tng_particle_data_find(tng_data, block_id, &data)
16565 != TNG_SUCCESS)
16567 stat = tng_particle_data_block_add(tng_data, block_id,
16568 block_name,
16569 TNG_FLOAT_DATA,
16570 block_type_flag,
16571 n_frames, n_values_per_frame,
16572 stride_length,
16573 0, n_particles,
16574 compression, 0);
16575 if(stat != TNG_SUCCESS)
16577 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16578 __FILE__, __LINE__);
16579 return(stat);
16581 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16583 data = &frame_set->tr_particle_data[frame_set->
16584 n_particle_data_blocks - 1];
16586 else
16588 data = &tng_data->non_tr_particle_data[tng_data->
16589 n_particle_data_blocks - 1];
16591 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
16592 stride_length, n_particles,
16593 n_values_per_frame);
16594 if(stat != TNG_SUCCESS)
16596 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16597 __FILE__, __LINE__);
16598 return(stat);
16601 /* FIXME: Here we must be able to handle modified n_particles as well. */
16602 else if(n_frames > data->n_frames)
16604 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
16605 data->stride_length, n_particles,
16606 n_values_per_frame);
16607 if(stat != TNG_SUCCESS)
16609 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16610 __FILE__, __LINE__);
16611 return(stat);
16615 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16617 stride_length = data->stride_length;
16619 if(is_first_frame_flag || data->first_frame_with_data < frame_set->first_frame)
16621 data->first_frame_with_data = frame_nr;
16622 frame_pos = 0;
16624 else
16626 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
16629 memcpy((char *)data->values + sizeof(float) * frame_pos * n_particles *
16630 n_values_per_frame, values, sizeof(float) *
16631 n_particles * n_values_per_frame);
16633 else
16635 memcpy(data->values, values, sizeof(float) * n_particles *
16636 n_values_per_frame);
16639 else
16641 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
16643 stat = tng_data_block_add(tng_data, block_id, block_name,
16644 TNG_FLOAT_DATA, block_type_flag,
16645 n_frames, n_values_per_frame,
16646 stride_length, compression, 0);
16647 if(stat != TNG_SUCCESS)
16649 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16650 __FILE__, __LINE__);
16651 return(stat);
16653 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16655 data = &frame_set->tr_data[frame_set->
16656 n_data_blocks - 1];
16658 else
16660 data = &tng_data->non_tr_data[tng_data->
16661 n_data_blocks - 1];
16663 stat = tng_allocate_data_mem(tng_data, data, n_frames,
16664 stride_length, n_values_per_frame);
16665 if(stat != TNG_SUCCESS)
16667 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16668 __FILE__, __LINE__);
16669 return(stat);
16672 /* FIXME: Here we must be able to handle modified n_particles as well. */
16673 else if(n_frames > data->n_frames)
16675 stat = tng_allocate_data_mem(tng_data, data, n_frames,
16676 data->stride_length, n_values_per_frame);
16677 if(stat != TNG_SUCCESS)
16679 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16680 __FILE__, __LINE__);
16681 return(stat);
16685 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16687 stride_length = data->stride_length;
16689 if(is_first_frame_flag || data->first_frame_with_data < frame_set->first_frame)
16691 data->first_frame_with_data = frame_nr;
16692 frame_pos = 0;
16694 else
16696 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
16699 memcpy((char *)data->values + sizeof(float) * frame_pos *
16700 n_values_per_frame, values, sizeof(float) *
16701 n_values_per_frame);
16703 else
16705 memcpy(data->values, values, sizeof(float) * n_values_per_frame);
16709 return(TNG_SUCCESS);
16712 tng_function_status DECLSPECDLLEXPORT tng_util_generic_double_write
16713 (const tng_trajectory_t tng_data,
16714 const int64_t frame_nr,
16715 const double *values,
16716 const int64_t n_values_per_frame,
16717 const int64_t block_id,
16718 const char *block_name,
16719 const char particle_dependency,
16720 const char compression)
16722 tng_trajectory_frame_set_t frame_set;
16723 tng_data_t data;
16724 int64_t n_particles = 0, n_frames, stride_length = 100, frame_pos;
16725 int64_t last_frame;
16726 int is_first_frame_flag = 0;
16727 char block_type_flag;
16728 tng_function_status stat;
16730 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16731 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
16733 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
16735 tng_num_particles_get(tng_data, &n_particles);
16736 TNG_ASSERT(n_particles > 0, "TNG library: There must be particles in the system to write particle data.");
16739 if(values == 0)
16741 return(TNG_FAILURE);
16744 frame_set = &tng_data->current_trajectory_frame_set;
16746 if(frame_nr < 0)
16748 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
16749 n_frames = stride_length = 1;
16751 else
16753 block_type_flag = TNG_TRAJECTORY_BLOCK;
16755 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
16757 stat = tng_frame_set_new(tng_data, 0, tng_data->frame_set_n_frames);
16758 if(stat != TNG_SUCCESS)
16760 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
16761 __LINE__);
16762 return(stat);
16765 last_frame = frame_set->first_frame +
16766 frame_set->n_frames - 1;
16767 if(frame_nr > last_frame)
16769 stat = tng_frame_set_write(tng_data, TNG_USE_HASH);
16770 if(stat != TNG_SUCCESS)
16772 fprintf(stderr, "TNG library: Cannot write frame set. %s: %d\n", __FILE__,
16773 __LINE__);
16774 return(stat);
16776 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
16778 last_frame = frame_nr - 1;
16780 stat = tng_frame_set_new(tng_data, last_frame + 1,
16781 tng_data->frame_set_n_frames);
16782 if(stat != TNG_SUCCESS)
16784 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
16785 __LINE__);
16786 return(stat);
16789 if(frame_set->n_unwritten_frames == 0)
16791 is_first_frame_flag = 1;
16793 frame_set->n_unwritten_frames = frame_nr -
16794 frame_set->first_frame + 1;
16796 n_frames = frame_set->n_frames;
16800 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
16802 if(tng_particle_data_find(tng_data, block_id, &data)
16803 != TNG_SUCCESS)
16805 stat = tng_particle_data_block_add(tng_data, block_id,
16806 block_name,
16807 TNG_DOUBLE_DATA,
16808 block_type_flag,
16809 n_frames, n_values_per_frame,
16810 stride_length,
16811 0, n_particles,
16812 compression, 0);
16813 if(stat != TNG_SUCCESS)
16815 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16816 __FILE__, __LINE__);
16817 return(stat);
16819 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16821 data = &frame_set->tr_particle_data[frame_set->
16822 n_particle_data_blocks - 1];
16824 else
16826 data = &tng_data->non_tr_particle_data[tng_data->
16827 n_particle_data_blocks - 1];
16829 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
16830 stride_length, n_particles,
16831 n_values_per_frame);
16832 if(stat != TNG_SUCCESS)
16834 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16835 __FILE__, __LINE__);
16836 return(stat);
16839 /* FIXME: Here we must be able to handle modified n_particles as well. */
16840 else if(n_frames > data->n_frames)
16842 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
16843 data->stride_length, n_particles,
16844 n_values_per_frame);
16845 if(stat != TNG_SUCCESS)
16847 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16848 __FILE__, __LINE__);
16849 return(stat);
16853 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16855 stride_length = data->stride_length;
16857 if(is_first_frame_flag || data->first_frame_with_data < frame_set->first_frame)
16859 data->first_frame_with_data = frame_nr;
16860 frame_pos = 0;
16862 else
16864 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
16867 memcpy((char *)data->values + sizeof(double) * frame_pos * n_particles *
16868 n_values_per_frame, values, sizeof(double) *
16869 n_particles * n_values_per_frame);
16871 else
16873 memcpy(data->values, values, sizeof(double) * n_particles *
16874 n_values_per_frame);
16877 else
16879 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
16881 stat = tng_data_block_add(tng_data, block_id, block_name,
16882 TNG_DOUBLE_DATA, block_type_flag,
16883 n_frames, n_values_per_frame,
16884 stride_length, compression, 0);
16885 if(stat != TNG_SUCCESS)
16887 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16888 __FILE__, __LINE__);
16889 return(stat);
16891 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16893 data = &frame_set->tr_data[frame_set->
16894 n_data_blocks - 1];
16896 else
16898 data = &tng_data->non_tr_data[tng_data->
16899 n_data_blocks - 1];
16901 stat = tng_allocate_data_mem(tng_data, data, n_frames,
16902 stride_length, n_values_per_frame);
16903 if(stat != TNG_SUCCESS)
16905 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16906 __FILE__, __LINE__);
16907 return(stat);
16910 /* FIXME: Here we must be able to handle modified n_particles as well. */
16911 else if(n_frames > data->n_frames)
16913 stat = tng_allocate_data_mem(tng_data, data, n_frames,
16914 data->stride_length, n_values_per_frame);
16915 if(stat != TNG_SUCCESS)
16917 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16918 __FILE__, __LINE__);
16919 return(stat);
16923 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16925 stride_length = data->stride_length;
16927 if(is_first_frame_flag || data->first_frame_with_data < frame_set->first_frame)
16929 data->first_frame_with_data = frame_nr;
16930 frame_pos = 0;
16932 else
16934 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
16937 memcpy((char *)data->values + sizeof(double) * frame_pos *
16938 n_values_per_frame, values, sizeof(double) *
16939 n_values_per_frame);
16941 else
16943 memcpy(data->values, values, sizeof(double) * n_values_per_frame);
16947 return(TNG_SUCCESS);
16950 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write
16951 (const tng_trajectory_t tng_data,
16952 const int64_t frame_nr,
16953 const float *positions)
16955 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16956 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
16958 return(tng_util_generic_write(tng_data, frame_nr, positions, 3,
16959 TNG_TRAJ_POSITIONS, "POSITIONS",
16960 TNG_PARTICLE_BLOCK_DATA,
16961 TNG_TNG_COMPRESSION));
16964 tng_function_status DECLSPECDLLEXPORT tng_util_pos_double_write
16965 (const tng_trajectory_t tng_data,
16966 const int64_t frame_nr,
16967 const double *positions)
16969 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16970 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
16972 return(tng_util_generic_double_write(tng_data, frame_nr, positions, 3,
16973 TNG_TRAJ_POSITIONS, "POSITIONS",
16974 TNG_PARTICLE_BLOCK_DATA,
16975 TNG_TNG_COMPRESSION));
16978 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write
16979 (const tng_trajectory_t tng_data,
16980 const int64_t frame_nr,
16981 const float *velocities)
16983 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16984 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
16986 return(tng_util_generic_write(tng_data, frame_nr, velocities, 3,
16987 TNG_TRAJ_VELOCITIES, "VELOCITIES",
16988 TNG_PARTICLE_BLOCK_DATA,
16989 TNG_TNG_COMPRESSION));
16992 tng_function_status DECLSPECDLLEXPORT tng_util_vel_double_write
16993 (const tng_trajectory_t tng_data,
16994 const int64_t frame_nr,
16995 const double *velocities)
16997 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16998 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
17000 return(tng_util_generic_double_write(tng_data, frame_nr, velocities, 3,
17001 TNG_TRAJ_VELOCITIES, "VELOCITIES",
17002 TNG_PARTICLE_BLOCK_DATA,
17003 TNG_TNG_COMPRESSION));
17006 tng_function_status DECLSPECDLLEXPORT tng_util_force_write
17007 (const tng_trajectory_t tng_data,
17008 const int64_t frame_nr,
17009 const float *forces)
17011 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17012 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17014 return(tng_util_generic_write(tng_data, frame_nr, forces, 3,
17015 TNG_TRAJ_FORCES, "FORCES",
17016 TNG_PARTICLE_BLOCK_DATA,
17017 TNG_GZIP_COMPRESSION));
17020 tng_function_status DECLSPECDLLEXPORT tng_util_force_double_write
17021 (const tng_trajectory_t tng_data,
17022 const int64_t frame_nr,
17023 const double *forces)
17025 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17026 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17028 return(tng_util_generic_double_write(tng_data, frame_nr, forces, 3,
17029 TNG_TRAJ_FORCES, "FORCES",
17030 TNG_PARTICLE_BLOCK_DATA,
17031 TNG_GZIP_COMPRESSION));
17034 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write
17035 (const tng_trajectory_t tng_data,
17036 const int64_t frame_nr,
17037 const float *box_shape)
17039 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17040 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17042 return(tng_util_generic_write(tng_data, frame_nr, box_shape, 9,
17043 TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
17044 TNG_NON_PARTICLE_BLOCK_DATA,
17045 TNG_GZIP_COMPRESSION));
17048 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_double_write
17049 (const tng_trajectory_t tng_data,
17050 const int64_t frame_nr,
17051 const double *box_shape)
17053 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17054 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17056 return(tng_util_generic_double_write(tng_data, frame_nr, box_shape, 9,
17057 TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
17058 TNG_NON_PARTICLE_BLOCK_DATA,
17059 TNG_GZIP_COMPRESSION));
17062 tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_write
17063 (const tng_trajectory_t tng_data,
17064 const int64_t frame_nr,
17065 const double time,
17066 const float *values,
17067 const int64_t n_values_per_frame,
17068 const int64_t block_id,
17069 const char *block_name,
17070 const char particle_dependency,
17071 const char compression)
17073 tng_trajectory_frame_set_t frame_set;
17074 tng_function_status stat;
17076 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17077 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17078 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17079 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
17081 stat = tng_util_generic_write(tng_data, frame_nr, values, n_values_per_frame,
17082 block_id, block_name,
17083 particle_dependency,
17084 compression);
17086 if(stat != TNG_SUCCESS)
17088 return(stat);
17091 frame_set = &tng_data->current_trajectory_frame_set;
17093 /* first_frame_time is -1 when it is not yet set. */
17094 if(frame_set->first_frame_time < -0.1)
17096 if(frame_nr > frame_set->first_frame)
17098 stat = tng_frame_set_first_frame_time_set(tng_data,
17099 time -
17100 (frame_nr -
17101 frame_set->first_frame) *
17102 tng_data->time_per_frame);
17104 else
17106 stat = tng_frame_set_first_frame_time_set(tng_data, time);
17109 return(stat);
17112 tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_double_write
17113 (const tng_trajectory_t tng_data,
17114 const int64_t frame_nr,
17115 const double time,
17116 const double *values,
17117 const int64_t n_values_per_frame,
17118 const int64_t block_id,
17119 const char *block_name,
17120 const char particle_dependency,
17121 const char compression)
17123 tng_trajectory_frame_set_t frame_set;
17124 tng_function_status stat;
17126 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17127 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17128 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17129 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
17131 stat = tng_util_generic_double_write(tng_data, frame_nr, values, n_values_per_frame,
17132 block_id, block_name,
17133 particle_dependency,
17134 compression);
17136 if(stat != TNG_SUCCESS)
17138 return(stat);
17141 frame_set = &tng_data->current_trajectory_frame_set;
17143 /* first_frame_time is -1 when it is not yet set. */
17144 if(frame_set->first_frame_time < -0.1)
17146 if(frame_nr > frame_set->first_frame)
17148 stat = tng_frame_set_first_frame_time_set(tng_data,
17149 time -
17150 (frame_nr -
17151 frame_set->first_frame) *
17152 tng_data->time_per_frame);
17154 else
17156 stat = tng_frame_set_first_frame_time_set(tng_data, time);
17159 return(stat);
17162 tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_write
17163 (const tng_trajectory_t tng_data,
17164 const int64_t frame_nr,
17165 const double time,
17166 const float *positions)
17168 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17169 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17170 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17171 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
17173 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, positions,
17174 3, TNG_TRAJ_POSITIONS, "POSITIONS",
17175 TNG_PARTICLE_BLOCK_DATA,
17176 TNG_TNG_COMPRESSION));
17179 tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_double_write
17180 (const tng_trajectory_t tng_data,
17181 const int64_t frame_nr,
17182 const double time,
17183 const double *positions)
17185 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17186 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17187 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17188 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
17190 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
17191 positions, 3,
17192 TNG_TRAJ_POSITIONS,
17193 "POSITIONS",
17194 TNG_PARTICLE_BLOCK_DATA,
17195 TNG_TNG_COMPRESSION));
17198 tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_write
17199 (const tng_trajectory_t tng_data,
17200 const int64_t frame_nr,
17201 const double time,
17202 const float *velocities)
17204 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17205 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17206 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17207 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
17209 return(tng_util_generic_with_time_write(tng_data, frame_nr, time,
17210 velocities, 3,
17211 TNG_TRAJ_VELOCITIES,
17212 "VELOCITIES",
17213 TNG_PARTICLE_BLOCK_DATA,
17214 TNG_TNG_COMPRESSION));
17217 tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_double_write
17218 (const tng_trajectory_t tng_data,
17219 const int64_t frame_nr,
17220 const double time,
17221 const double *velocities)
17223 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17224 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17225 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17226 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
17228 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
17229 velocities, 3,
17230 TNG_TRAJ_VELOCITIES,
17231 "VELOCITIES",
17232 TNG_PARTICLE_BLOCK_DATA,
17233 TNG_TNG_COMPRESSION));
17236 tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_write
17237 (const tng_trajectory_t tng_data,
17238 const int64_t frame_nr,
17239 const double time,
17240 const float *forces)
17242 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17243 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17244 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17245 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17247 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, forces,
17248 3, TNG_TRAJ_FORCES, "FORCES",
17249 TNG_PARTICLE_BLOCK_DATA,
17250 TNG_GZIP_COMPRESSION));
17253 tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_double_write
17254 (const tng_trajectory_t tng_data,
17255 const int64_t frame_nr,
17256 const double time,
17257 const double *forces)
17259 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17260 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17261 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17262 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17264 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
17265 forces, 3,
17266 TNG_TRAJ_FORCES, "FORCES",
17267 TNG_PARTICLE_BLOCK_DATA,
17268 TNG_GZIP_COMPRESSION));
17271 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_write
17272 (const tng_trajectory_t tng_data,
17273 const int64_t frame_nr,
17274 const double time,
17275 const float *box_shape)
17277 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17278 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17279 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17280 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17282 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, box_shape,
17283 9, TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
17284 TNG_NON_PARTICLE_BLOCK_DATA,
17285 TNG_GZIP_COMPRESSION));
17288 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_double_write
17289 (const tng_trajectory_t tng_data,
17290 const int64_t frame_nr,
17291 const double time,
17292 const double *box_shape)
17294 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17295 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17296 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17297 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17299 return(tng_util_generic_with_time_double_write(tng_data, frame_nr,
17300 time, box_shape, 9,
17301 TNG_TRAJ_BOX_SHAPE,
17302 "BOX SHAPE",
17303 TNG_NON_PARTICLE_BLOCK_DATA,
17304 TNG_GZIP_COMPRESSION));
17307 tng_function_status DECLSPECDLLEXPORT tng_util_frame_current_compression_get
17308 (const tng_trajectory_t tng_data,
17309 const int64_t block_id,
17310 int64_t *codec_id,
17311 double *factor)
17313 tng_trajectory_frame_set_t frame_set;
17314 tng_data_t data = 0;
17315 tng_function_status stat;
17316 int64_t i;
17317 int block_type = -1;
17319 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17320 TNG_ASSERT(codec_id, "TNG library: The pointer to the returned codec id must not be a NULL pointer.");
17321 TNG_ASSERT(factor, "TNG library: The pointer to the returned multiplication factor must not be a NULL pointer.");
17323 frame_set = &tng_data->current_trajectory_frame_set;
17325 stat = tng_particle_data_find(tng_data, block_id, &data);
17326 if(stat == TNG_SUCCESS)
17328 block_type = TNG_PARTICLE_BLOCK_DATA;
17330 else
17332 stat = tng_data_find(tng_data, block_id, &data);
17333 if(stat == TNG_SUCCESS)
17335 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
17337 else
17339 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17340 if(stat != TNG_SUCCESS)
17342 return(stat);
17344 stat = tng_particle_data_find(tng_data, block_id, &data);
17345 if(stat == TNG_SUCCESS)
17347 block_type = TNG_PARTICLE_BLOCK_DATA;
17349 else
17351 stat = tng_data_find(tng_data, block_id, &data);
17352 if(stat == TNG_SUCCESS)
17354 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
17356 else
17358 return(stat);
17363 if(block_type == TNG_PARTICLE_BLOCK_DATA)
17365 if(data->last_retrieved_frame < 0)
17367 i = data->first_frame_with_data;
17369 else
17371 i = data->last_retrieved_frame;
17374 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
17376 if(data->last_retrieved_frame < 0)
17378 i = data->first_frame_with_data;
17380 else
17382 i = data->last_retrieved_frame;
17385 else
17387 return(TNG_FAILURE);
17389 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
17391 stat = tng_frame_set_of_frame_find(tng_data, i);
17392 if(stat != TNG_SUCCESS)
17394 return(stat);
17396 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17397 if(stat != TNG_SUCCESS)
17399 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
17400 __FILE__, __LINE__);
17401 return(stat);
17404 if(block_type == TNG_PARTICLE_BLOCK_DATA)
17406 *codec_id = data->codec_id;
17407 *factor = data->compression_multiplier;
17409 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
17411 *codec_id = data->codec_id;
17412 *factor = data->compression_multiplier;
17414 return(TNG_SUCCESS);
17417 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_next_frame_present_data_blocks_find
17418 (const tng_trajectory_t tng_data,
17419 int64_t current_frame,
17420 const int64_t n_requested_data_block_ids,
17421 const int64_t *requested_data_block_ids,
17422 int64_t *next_frame,
17423 int64_t *n_data_blocks_in_next_frame,
17424 int64_t **data_block_ids_in_next_frame)
17426 tng_trajectory_frame_set_t frame_set;
17427 tng_function_status stat;
17428 tng_data_t data;
17429 tng_gen_block_t block;
17430 int64_t i, j, block_id, *temp;
17431 int64_t data_frame, frame_diff, min_diff;
17432 int64_t size, frame_set_file_pos;
17433 int found, read_all = 0;
17434 int64_t file_pos;
17436 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17437 TNG_ASSERT(next_frame, "TNG library: The pointer to the next frame must not be NULL.");
17438 TNG_ASSERT(n_data_blocks_in_next_frame, "TNG library: The pointer to n_data_blocks_in_next_frame must not be NULL.");
17439 TNG_ASSERT(data_block_ids_in_next_frame, "TNG library: The pointer to the list of data block IDs must not be NULL.");
17441 if(n_requested_data_block_ids)
17443 TNG_ASSERT(requested_data_block_ids, "TNG library: If the number of requested data blocks is > 0 then the array of data block IDs must not be NULL.");
17444 size = sizeof(int64_t) * n_requested_data_block_ids;
17445 temp = (int64_t *)realloc(*data_block_ids_in_next_frame, size);
17446 if(!temp)
17448 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
17449 __FILE__, __LINE__);
17450 free(*data_block_ids_in_next_frame);
17451 *data_block_ids_in_next_frame = 0;
17452 return(TNG_CRITICAL);
17454 *data_block_ids_in_next_frame = temp;
17457 frame_set = &tng_data->current_trajectory_frame_set;
17459 current_frame += 1;
17461 if(current_frame < frame_set->first_frame ||
17462 current_frame >= frame_set->first_frame + frame_set->n_frames)
17464 frame_set_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
17465 stat = tng_frame_set_of_frame_find(tng_data, current_frame);
17466 if(stat != TNG_SUCCESS)
17468 /* If the frame set search found the frame set after the starting
17469 * frame set there is a gap in the frame sets. So, even if the frame
17470 * was not found the next frame with data is still in the found
17471 * frame set. */
17472 if(stat == TNG_CRITICAL || frame_set->prev_frame_set_file_pos !=
17473 frame_set_file_pos)
17475 return(stat);
17477 current_frame = frame_set->first_frame;
17481 /* Check for data blocks only if they have not already been found. */
17482 if(frame_set->n_particle_data_blocks <= 0 && frame_set->n_data_blocks <= 0)
17484 file_pos = ftello(tng_data->input_file);
17485 if(file_pos < tng_data->input_file_len)
17487 tng_block_init(&block);
17488 stat = tng_block_header_read(tng_data, block);
17489 while(file_pos < tng_data->input_file_len &&
17490 stat != TNG_CRITICAL &&
17491 block->id != TNG_TRAJECTORY_FRAME_SET &&
17492 block->id != -1)
17494 stat = tng_block_read_next(tng_data, block,
17495 TNG_USE_HASH);
17496 if(stat != TNG_CRITICAL)
17498 file_pos = ftello(tng_data->input_file);
17499 if(file_pos < tng_data->input_file_len)
17501 stat = tng_block_header_read(tng_data, block);
17505 tng_block_destroy(&block);
17506 if(stat == TNG_CRITICAL)
17508 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
17509 file_pos, __FILE__, __LINE__);
17510 return(stat);
17513 read_all = 1;
17516 min_diff = -1;
17518 *n_data_blocks_in_next_frame = 0;
17520 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
17522 data = &frame_set->tr_particle_data[i];
17523 block_id = data->block_id;
17525 if(n_requested_data_block_ids > 0)
17527 found = 0;
17528 for(j = 0; j < n_requested_data_block_ids; j++)
17530 if(block_id == requested_data_block_ids[j])
17532 found = 1;
17533 break;
17536 if(!found)
17538 continue;
17542 if(!read_all && (data->last_retrieved_frame < frame_set->first_frame ||
17543 data->last_retrieved_frame >=
17544 frame_set->first_frame + frame_set->n_frames))
17546 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data,
17547 TNG_USE_HASH, block_id);
17548 if(stat == TNG_CRITICAL)
17550 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
17551 __FILE__, __LINE__);
17552 return(stat);
17554 if(stat == TNG_FAILURE)
17556 continue;
17559 if(frame_set->first_frame != current_frame &&
17560 data->last_retrieved_frame >= 0)
17562 data_frame = data->last_retrieved_frame + data->stride_length;
17564 else
17566 data_frame = data->first_frame_with_data;
17568 frame_diff = data_frame - current_frame;
17569 if(frame_diff < 0)
17571 continue;
17573 if(min_diff == -1 || frame_diff <= min_diff)
17575 if(frame_diff < min_diff)
17577 *n_data_blocks_in_next_frame = 1;
17579 else
17581 *n_data_blocks_in_next_frame += 1;
17583 if(n_requested_data_block_ids <= 0)
17585 size = sizeof(int64_t) * (*n_data_blocks_in_next_frame);
17586 temp = (int64_t *)realloc(*data_block_ids_in_next_frame, size);
17587 if(!temp)
17589 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
17590 __FILE__, __LINE__);
17591 free(*data_block_ids_in_next_frame);
17592 *data_block_ids_in_next_frame = 0;
17593 return(TNG_CRITICAL);
17595 *data_block_ids_in_next_frame = temp;
17597 else
17599 TNG_ASSERT(*n_data_blocks_in_next_frame <= n_requested_data_block_ids, "TNG library: Array of data block IDs out of bounds");
17601 (*data_block_ids_in_next_frame)[(*n_data_blocks_in_next_frame) - 1] = block_id;
17603 min_diff = frame_diff;
17606 for(i = 0; i < frame_set->n_data_blocks; i++)
17608 data = &frame_set->tr_data[i];
17609 block_id = data->block_id;
17611 if(n_requested_data_block_ids > 0)
17613 found = 0;
17614 for(j = 0; j < n_requested_data_block_ids; j++)
17616 if(block_id == requested_data_block_ids[j])
17618 found = 1;
17619 break;
17622 if(!found)
17624 continue;
17628 if(!read_all && (data->last_retrieved_frame < frame_set->first_frame ||
17629 data->last_retrieved_frame >=
17630 frame_set->first_frame + frame_set->n_frames))
17632 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data,
17633 TNG_USE_HASH, block_id);
17634 if(stat == TNG_CRITICAL)
17636 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
17637 __FILE__, __LINE__);
17638 return(stat);
17640 if(stat == TNG_FAILURE)
17642 continue;
17645 if(frame_set->first_frame != current_frame &&
17646 data->last_retrieved_frame >= 0)
17648 data_frame = data->last_retrieved_frame + data->stride_length;
17650 else
17652 data_frame = data->first_frame_with_data;
17654 frame_diff = data_frame - current_frame;
17655 if(frame_diff < 0)
17657 continue;
17659 if(min_diff == -1 || frame_diff <= min_diff)
17661 if(frame_diff < min_diff)
17663 *n_data_blocks_in_next_frame = 1;
17665 else
17667 *n_data_blocks_in_next_frame += 1;
17669 if(n_requested_data_block_ids <= 0)
17671 size = sizeof(int64_t) * (*n_data_blocks_in_next_frame);
17672 temp = (int64_t *)realloc(*data_block_ids_in_next_frame, size);
17673 if(!temp)
17675 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
17676 __FILE__, __LINE__);
17677 free(*data_block_ids_in_next_frame);
17678 *data_block_ids_in_next_frame = 0;
17679 return(TNG_CRITICAL);
17681 *data_block_ids_in_next_frame = temp;
17683 else
17685 TNG_ASSERT(*n_data_blocks_in_next_frame <= n_requested_data_block_ids, "TNG library: Array of data block IDs out of bounds");
17687 (*data_block_ids_in_next_frame)[(*n_data_blocks_in_next_frame) - 1] = block_id;
17689 min_diff = frame_diff;
17692 if(min_diff < 0)
17694 return(TNG_FAILURE);
17696 *next_frame = current_frame + min_diff;
17698 return(TNG_SUCCESS);
17702 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_all_data_block_types_get
17703 (const tng_trajectory_t tng_data,
17704 int64_t *n_data_blocks,
17705 int64_t **data_block_ids,
17706 char ***data_block_names,
17707 int64_t **stride_lengths,
17708 int64_t **n_values_per_frame,
17709 char **block_types,
17710 char **dependencies,
17711 char **compressions)
17713 tng_gen_block_t block;
17714 int64_t orig_file_pos, file_pos;
17716 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17717 TNG_ASSERT(n_data_blocks, "TNG library: The pointer to n_data_blocks must not be NULL.");
17718 TNG_ASSERT(data_block_ids, "TNG library: The pointer to the list of data block IDs must not be NULL.");
17719 TNG_ASSERT(data_block_names, "TNG library: The pointer to the list of data block names must not be NULL.");
17720 TNG_ASSERT(stride_lengths, "TNG library: The pointer to the list of stride lengths must not be NULL.");
17722 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
17724 return(TNG_CRITICAL);
17727 orig_file_pos = ftello(tng_data->input_file);
17729 fseeko(tng_data->input_file, 0, SEEK_SET);
17730 file_pos = 0;
17732 *n_data_blocks = 0;
17734 tng_block_init(&block);
17736 while(file_pos < tng_data->input_file_len &&
17737 tng_block_header_read(tng_data, block) != TNG_CRITICAL)
17739 if(block->id > TNG_TRAJECTORY_FRAME_SET)
17743 file_pos += (block->block_contents_size + block->header_contents_size);
17744 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
17747 fseeko(tng_data->input_file, orig_file_pos, SEEK_SET);
17749 return(TNG_SUCCESS);
17752 tng_function_status DECLSPECDLLEXPORT tng_util_prepare_append_after_frame
17753 (const tng_trajectory_t tng_data,
17754 const int64_t prev_frame)
17756 tng_function_status stat;
17757 FILE *temp = tng_data->input_file;
17759 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17760 TNG_ASSERT(prev_frame >= 0, "TNG library: The previous frame must not be negative.");
17762 tng_data->input_file = tng_data->output_file;
17764 stat = tng_frame_set_of_frame_find(tng_data, prev_frame);
17765 if(stat != TNG_SUCCESS)
17767 return(stat);
17770 tng_data->current_trajectory_frame_set_output_file_pos =
17771 tng_data->current_trajectory_frame_set_input_file_pos;
17773 tng_data->input_file = temp;
17775 return(TNG_SUCCESS);
17778 tng_function_status DECLSPECDLLEXPORT tng_util_num_frames_with_data_of_block_id_get
17779 (const tng_trajectory_t tng_data,
17780 const int64_t block_id,
17781 int64_t *n_frames)
17783 int64_t curr_file_pos, first_frame_set_file_pos, curr_n_frames;
17784 tng_function_status stat;
17786 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17788 *n_frames = 0;
17790 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
17792 return(TNG_CRITICAL);
17795 first_frame_set_file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
17796 curr_file_pos = ftello(tng_data->input_file);
17797 fseeko(tng_data->input_file, first_frame_set_file_pos, SEEK_SET);
17799 stat = tng_frame_set_n_frames_of_data_block_get(tng_data, block_id, &curr_n_frames);
17801 while(stat == TNG_SUCCESS && tng_data->current_trajectory_frame_set.next_frame_set_file_pos != -1)
17803 *n_frames += curr_n_frames;
17804 fseeko(tng_data->input_file,
17805 tng_data->current_trajectory_frame_set.next_frame_set_file_pos,
17806 SEEK_SET);
17807 stat = tng_frame_set_n_frames_of_data_block_get(tng_data, block_id, &curr_n_frames);
17809 if(stat == TNG_SUCCESS)
17811 *n_frames += curr_n_frames;
17813 fseeko(tng_data->input_file, curr_file_pos, SEEK_SET);
17814 if(stat == TNG_CRITICAL)
17816 return(TNG_CRITICAL);
17818 return(TNG_SUCCESS);