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. */
20 #include "tng/tng_io.h"
22 #ifdef USE_STD_INTTYPES_H
34 #include "compression/tng_compress.h"
35 #include "tng/version.h"
37 #if defined( _WIN32 ) || defined( _WIN64 )
39 #define fseeko _fseeki64
43 #define ftello ftello64
45 #define ftello _ftelli64
51 /** One of the atoms of the bond */
53 /** The other atom of the bond */
58 /** The residue containing this atom */
59 tng_residue_t residue;
60 /** A unique (per molecule) ID number of the atom */
62 /** The atom_type (depending on the forcefield) */
64 /** The name of the atom */
69 /** The chain containing this residue */
71 /** A unique (per chain) ID number of the residue */
73 /** The name of the residue */
75 /** The number of atoms in the residue */
77 /** A list of atoms in the residue */
82 /** The molecule containing this chain */
83 tng_molecule_t molecule;
84 /** A unique (per molecule) ID number of the chain */
86 /** The name of the chain */
88 /** The number of residues in the chain */
90 /** A list of residues in the chain */
91 tng_residue_t residues;
95 /** A unique ID number of the molecule */
97 /** Quaternary structure of the molecule.
102 int64_t quaternary_str;
103 /** The number of chains in the molecule */
105 /** The number of residues in the molecule */
107 /** The number of atoms in the molecule */
109 /** The number of bonds in the molecule. If the bonds are not specified this
112 /** The name of the molecule */
114 /** A list of chains in the molecule */
116 /** A list of residues in the molecule */
117 tng_residue_t residues;
118 /** A list of the atoms in the molecule */
120 /** A list of the bonds in the molecule */
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 */
131 /** The MD5 hash of the block to verify integrity */
132 char md5_hash[TNG_MD5_HASH_LEN];
133 /** The name of the block */
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;
140 int64_t signature_type;
141 int64_t signature_len;
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 */
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 */
168 /** The number of frames in this frame set */
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
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 */
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? */
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 */
215 /** The name of the data block. This is used to determine the kind of
216 * data that is stored */
218 /** The type of data stored. */
220 /** A flag to indicate if this data block contains frame and/or particle dependent
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 */
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. */
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 */
241 /** If storing character data store it in a 3-dimensional array */
246 struct tng_trajectory {
247 /** The path of the input trajectory file */
248 char *input_file_path;
249 /** A handle to the 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 */
257 /** Function to swap 32 bit values to and from the endianness of the
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
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
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
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 */
271 /** The endianness of 64 bit values of the current computer */
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
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
293 char *last_pgp_signature;
294 /** The time (n seconds since 1970) when the file was created */
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 */
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 */
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 */
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;
364 #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)
366 #endif /* win32... */
367 #endif /* not defined USE_WINDOWS */
370 #define TNG_INLINE __inline
371 #define TNG_SNPRINTF _snprintf
373 #define TNG_INLINE inline
374 #define TNG_SNPRINTF snprintf
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
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 */
415 case TNG_BYTE_PAIR_SWAP_32: /* byte pair swap */
416 *v = ((*v & 0xFFFF0000) >> 16) |
417 ((*v & 0x0000FFFF) << 16);
421 case TNG_BIG_ENDIAN_32: /* Already correct */
430 * @brief This function swaps the byte order of a 64 bit numerical variable
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 */
458 case TNG_QUAD_SWAP_64: /* Byte quad swap */
459 *v = ((*v & 0xFFFFFFFF00000000LL) >> 32) |
460 ((*v & 0x00000000FFFFFFFFLL) << 32);
464 case TNG_BYTE_PAIR_SWAP_64: /* Byte pair swap */
465 *v = ((*v & 0xFFFF0000FFFF0000LL) >> 16) |
466 ((*v & 0x0000FFFF0000FFFFLL) << 16);
470 case TNG_BYTE_SWAP_64: /* Byte swap */
471 *v = ((*v & 0xFF00FF00FF00FF00LL) >> 8) |
472 ((*v & 0x00FF00FF00FF00FFLL) << 8);
476 case TNG_BIG_ENDIAN_64: /* Already correct */
485 * @brief This function swaps the byte order of a 32 bit numerical variable
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 */
502 case TNG_BYTE_PAIR_SWAP_32: /* byte pair swapped big endian to little endian */
503 *v = ((*v & 0xFF00FF00) >> 8) |
504 ((*v & 0x00FF00FF) << 8);
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 */
522 * @brief This function swaps the byte order of a 64 bit numerical variable
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 */
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);
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);
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);
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 */
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,
596 const char hash_mode,
597 md5_state_t *md5_state,
600 char temp[TNG_MAX_STR_LEN], *temp_alloc;
605 c = fgetc(tng_data->input_file);
609 /* Clear file error flag and return -1 if EOF is read.*/
610 clearerr(tng_data->input_file);
616 temp[count++] = (char) c;
618 } while ((temp[count-1] != '\0') && (count < TNG_MAX_STR_LEN));
620 temp_alloc = (char *)realloc(*str, count);
623 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n", __FILE__, line_nr);
630 strncpy(*str, temp, count);
632 if(hash_mode == TNG_USE_HASH)
634 md5_append(md5_state, (md5_byte_t *)*str, count);
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,
652 const char hash_mode,
653 md5_state_t *md5_state,
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);
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,
691 const char hash_mode,
692 md5_state_t *md5_state,
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);
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",
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",
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,
746 const char hash_mode,
747 md5_state_t *md5_state,
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",
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);
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",
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);
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);
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);
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
832 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
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;
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);
849 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
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__);
858 return(TNG_CRITICAL);
860 md5_append(md5_state, (md5_byte_t *)temp_data,
861 start_pos + block->block_contents_size - curr_file_pos);
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
874 static tng_function_status tng_input_file_init(const tng_trajectory_t tng_data)
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",
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);
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
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",
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);
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
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));
949 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n", __FILE__, __LINE__);
950 return(TNG_CRITICAL);
956 /* Reset the md5_hash */
957 memset(block->md5_hash, '\0', TNG_MD5_HASH_LEN);
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;
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
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;
984 /* fprintf(stderr, "TNG library: Destroying block\n"); */
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;
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)
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)
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
1054 if(tng_data->endianness_32 == TNG_LITTLE_ENDIAN_32)
1056 tng_data->input_endianness_swap_func_32 = 0;
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;
1069 tng_data->input_endianness_swap_func_64 =
1070 &tng_swap_byte_order_little_endian_64;
1073 /* File is big endian */
1076 /* If the architecture endianness is big endian no byte swap
1077 * will be needed. Otherwise use the functions to swap to big
1079 if(tng_data->endianness_32 == TNG_BIG_ENDIAN_32)
1081 tng_data->input_endianness_swap_func_32 = 0;
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;
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,
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)
1153 // if(!block->header_contents)
1155 // fprintf(stderr, "TNG library: No contents to write. %s: %d\n", __FILE__, __LINE__);
1156 // return(TNG_FAILURE);
1158 // if(fwrite(block->header_contents, block->header_contents_size, 1,
1159 // tng_data->output_file) != 1)
1161 // fprintf(stderr, "TNG library: Could not write all header data. %s: %d\n",
1162 // __FILE__, __LINE__);
1163 // return(TNG_CRITICAL);
1166 // if(!block->block_contents)
1168 // fprintf(stderr, "TNG library: No block data to write. %s: %d\n",
1169 // __FILE__, __LINE__);
1170 // return(TNG_FAILURE);
1172 // if(fwrite(block->block_contents, block->block_contents_size, 1,
1173 // tng_data->output_file) != 1)
1175 // fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n",
1176 // __FILE__, __LINE__);
1177 // return(TNG_CRITICAL);
1179 // return(TNG_SUCCESS);
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
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),
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,
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,
1300 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1301 __FILE__, __LINE__);
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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);
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,
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;
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);
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;
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);
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__);
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__);
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;
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;
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);
1839 return(TNG_SUCCESS);
1842 static tng_function_status tng_length_of_current_frame_set_contents_get
1843 (const tng_trajectory_t tng_data,
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;
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)
1878 stat = tng_block_header_read(tng_data, block);
1879 if(block->id == TNG_TRAJECTORY_FRAME_SET)
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
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
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;
1920 return(TNG_SUCCESS);
1923 stat = tng_file_pos_of_subsequent_trajectory_block_get(tng_data, &traj_start_pos);
1924 if(stat != TNG_SUCCESS)
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);
1963 stat = tng_frame_set_complete_migrate(tng_data, traj_start_pos,
1964 frame_set_length, tng_data->input_file_len,
1966 if(stat != TNG_SUCCESS)
1968 tng_block_destroy(&block);
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,
1988 /* If the string is unallocated allocate memory for just string
1992 block->name = (char *)malloc(1);
1995 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
1996 __FILE__, __LINE__);
1997 return(TNG_CRITICAL);
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) +
2008 sizeof(block->block_version) +
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) !=
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,
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,
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
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,
2201 last_program_name_len = tng_min_size(strlen(tng_data->last_program_name) + 1,
2203 first_user_name_len = tng_min_size(strlen(tng_data->first_user_name) + 1,
2205 last_user_name_len = tng_min_size(strlen(tng_data->last_user_name) + 1,
2207 first_computer_name_len = tng_min_size(strlen(tng_data->first_computer_name) + 1,
2209 last_computer_name_len = tng_min_size(strlen(tng_data->last_computer_name) + 1,
2211 first_pgp_signature_len = tng_min_size(strlen(tng_data->first_pgp_signature) + 1,
2213 last_pgp_signature_len = tng_min_size(strlen(tng_data->last_pgp_signature) + 1,
2215 forcefield_name_len = tng_min_size(strlen(tng_data->forcefield_name) + 1,
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)
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__);
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;
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);
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) !=
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__,
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,
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,
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,
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,
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,
2784 tng_molecule_t molecule;
2786 tng_residue_t residue;
2792 for(i = 0; i < tng_data->n_molecules; i++)
2794 molecule = &tng_data->molecules[i];
2797 molecule->name = (char *)malloc(1);
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);
2815 chain->name = (char *)malloc(1);
2818 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
2819 __FILE__, __LINE__);
2820 return(TNG_CRITICAL);
2824 *len += tng_min_size(strlen(chain->name) + 1, TNG_MAX_STR_LEN);
2826 *len += sizeof(chain->n_residues);
2831 residue = molecule->residues;
2832 for(j = 0; j < molecule->n_residues; j++)
2834 *len += sizeof(residue->id);
2838 residue->name = (char *)malloc(1);
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);
2854 atom = molecule->atoms;
2855 for(j = 0; j < molecule->n_atoms; j++)
2857 *len += sizeof(atom->id);
2860 atom->name = (char *)malloc(1);
2863 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
2864 __FILE__, __LINE__);
2865 return(TNG_CRITICAL);
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);
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;
2927 tng_residue_t residue;
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];
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],
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;
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;
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;
3125 tng_chain_data_read(tng_data, chain, hash_mode, &md5_state);
3129 chain->residues = molecule->residues;
3130 residue = chain->residues;
3134 chain->residues = residue;
3137 /* Read the residues of the chain */
3138 for(k=0; k<chain->n_residues; k++)
3140 residue->chain = chain;
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;
3153 atom->atom_type = 0;
3155 tng_atom_data_read(tng_data,atom, hash_mode, &md5_state);
3166 if(molecule->n_residues > 0)
3168 for(k=0; k<molecule->n_residues; k++)
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);
3191 for(l=0; l<molecule->n_atoms; l++)
3196 atom->atom_type = 0;
3198 tng_atom_data_read(tng_data, atom, hash_mode, &md5_state);
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;
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);
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__);
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)
3304 int64_t i, j, k, l, header_file_pos, curr_file_pos;
3305 tng_molecule_t molecule;
3307 tng_residue_t residue;
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);
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) !=
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],
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);
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);
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);
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);
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__,
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,
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],
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);
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__);
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)
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);
3756 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
3757 __FILE__, __LINE__);
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) !=
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],
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__,
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,
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);
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 *
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],
3984 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3986 return(TNG_CRITICAL);
3990 /* Otherwise the data can be read all at once */
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__);
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;
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);
4074 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
4075 __FILE__, __LINE__);
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) !=
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],
4128 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
4130 return(TNG_CRITICAL);
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__,
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;
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);
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;
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);
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,
4233 int64_t algo_find_n_frames = -1;
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];
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,
4300 dest = tng_compress_pos((double *)*data, (int)n_particles,
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)
4324 algo_find_n_frames = 5;
4328 algo_find_n_frames = n_frames;
4331 /* If the algorithm parameters are -1 they will be determined during the
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,
4352 if(algo_find_n_frames < n_frames)
4355 dest = tng_compress_pos_float((float *)*data, (int)n_particles,
4358 0, tng_data->compress_algo_pos,
4364 dest = tng_compress_pos((double *)*data, (int)n_particles,
4365 (int)algo_find_n_frames,
4371 if(algo_find_n_frames < n_frames)
4374 dest = tng_compress_pos((double *)*data, (int)n_particles,
4377 tng_data->compress_algo_pos,
4384 if(type == TNG_FLOAT_DATA)
4386 dest = tng_compress_pos_float((float *)*data, (int)n_particles,
4389 tng_data->compress_algo_pos, &compressed_len);
4393 dest = tng_compress_pos((double *)*data, (int)n_particles,
4396 tng_data->compress_algo_pos,
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];
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,
4441 dest = tng_compress_vel((double *)*data, (int)n_particles,
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)
4465 algo_find_n_frames = 5;
4469 algo_find_n_frames = n_frames;
4472 /* If the algorithm parameters are -1 they will be determined during the
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,
4492 if(algo_find_n_frames < n_frames)
4495 dest = tng_compress_vel_float((float *)*data, (int)n_particles,
4498 0, tng_data->compress_algo_vel,
4504 dest = tng_compress_vel((double *)*data, (int)n_particles,
4505 (int)algo_find_n_frames,
4510 if(algo_find_n_frames < n_frames)
4513 dest = tng_compress_vel((double *)*data, (int)n_particles,
4516 0, tng_data->compress_algo_vel,
4523 if(type == TNG_FLOAT_DATA)
4525 dest = tng_compress_vel_float((float *)*data, (int)n_particles,
4534 dest = tng_compress_vel((double *)*data, (int)n_particles,
4545 fprintf(stderr, "TNG library: Can only compress positions and velocities using TNG-MF1 algorithms.\n");
4546 return(TNG_FAILURE);
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,
4567 const int64_t uncompressed_len)
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"
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);
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);
4602 *data = (char *)f_dest;
4606 d_dest = (double *)malloc(uncompressed_len);
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);
4617 *data = (char *)d_dest;
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,
4634 uLongf stat, max_len;
4637 max_len = compressBound(len);
4638 dest = (Bytef *)malloc(max_len);
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)
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);
4666 *data = (char *)dest;
4668 return(TNG_SUCCESS);
4671 static tng_function_status tng_gzip_uncompress(const tng_trajectory_t tng_data,
4673 const int64_t compressed_len,
4674 const int64_t uncompressed_len)
4679 uLongf new_len = uncompressed_len;
4681 dest = (Bytef *)malloc(uncompressed_len);
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,
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__,
4709 return(TNG_FAILURE);
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
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
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,
4736 const int64_t stride_length,
4737 const int64_t n_particles,
4738 const int64_t n_values_per_frame)
4741 int64_t i, j, k, size, frame_alloc;
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 **) *
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;
4806 switch(data->datatype)
4809 size = sizeof(int64_t);
4811 case TNG_FLOAT_DATA:
4812 size = sizeof(float);
4814 case TNG_DOUBLE_DATA:
4816 size = sizeof(double);
4819 values = (void ***)realloc(data->values,
4820 size * frame_alloc *
4821 n_particles * n_values_per_frame);
4824 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
4825 __FILE__, __LINE__);
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,
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;
4852 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
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)
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)
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,
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;
4904 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
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)
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)
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)
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,
4965 char ***first_dim_values, **second_dim_values;
4970 return(TNG_SUCCESS);
4973 switch(data->datatype)
4979 size = sizeof(int64_t);
4981 case TNG_FLOAT_DATA:
4982 size = sizeof(float);
4984 case TNG_DOUBLE_DATA:
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;
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;
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;
5046 *len += size * frame_step * n_particles * data->n_values_per_frame;
5049 return(TNG_SUCCESS);
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;
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);
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;
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);
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);
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
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,
5120 const int64_t stride_length,
5121 const int64_t n_values_per_frame)
5124 int64_t i, j, size, frame_alloc;
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;
5178 switch(data->datatype)
5181 size = sizeof(int64_t);
5183 case TNG_FLOAT_DATA:
5184 size = sizeof(float);
5186 case TNG_DOUBLE_DATA:
5188 size = sizeof(double);
5191 values = (void **)realloc(data->values,
5192 size * frame_alloc *
5193 n_values_per_frame);
5196 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
5197 __FILE__, __LINE__);
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
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,
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;
5255 char ***first_dim_values, **second_dim_values;
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);*/
5271 size = sizeof(int64_t);
5273 case TNG_FLOAT_DATA:
5274 size = sizeof(float);
5276 case TNG_DOUBLE_DATA:
5278 size = sizeof(double);
5283 is_particle_data = TNG_TRUE;
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__,
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);
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;
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);
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];
5342 data = &tng_data->non_tr_particle_data[tng_data->
5343 n_particle_data_blocks - 1];
5348 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5350 data = &frame_set->tr_data[frame_set->n_data_blocks - 1];
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;
5372 /* FIXME: Memory leak from strings. */
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 &&
5382 frame_set->n_frames == n_frames ||
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;
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. */
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);
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;
5441 case TNG_XTC_COMPRESSION:
5442 fprintf(stderr, "TNG library: XTC compression not implemented yet.\n");
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__);
5452 return(TNG_CRITICAL);
5454 /* fprintf(stderr, "TNG library: After TNG uncompression: %" PRId64 "\n", block->block_contents_size);*/
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__,
5464 return(TNG_CRITICAL);
5466 /* fprintf(stderr, "TNG library: After compression: %" PRId64 "\n", block->block_contents_size); */
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,
5483 tot_n_particles, n_values);
5487 stat = tng_allocate_data_mem(tng_data, data, n_frames, stride_length,
5490 if(stat != TNG_SUCCESS)
5492 fprintf(stderr, "TNG library: Cannot allocate memory for data. %s: %d\n",
5493 __FILE__, __LINE__);
5495 return(TNG_CRITICAL);
5499 data->first_frame_with_data = first_frame_with_data;
5501 if(datatype == TNG_CHAR_DATA)
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;
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,
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__);
5529 return(TNG_CRITICAL);
5531 strncpy(second_dim_values[k], contents+offset, len);
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,
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__);
5555 return(TNG_CRITICAL);
5557 strncpy(data->strings[0][i][j], contents+offset, len);
5565 if(is_particle_data)
5567 memcpy((char *)data->values + n_frames_div * size * n_values *
5568 num_first_particle, contents, full_data_len);
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)
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))
5589 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5590 __FILE__, __LINE__);
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))
5605 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5606 __FILE__, __LINE__);
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;
5649 tng_function_status stat;
5650 char temp, *temp_name, ***first_dim_values, **second_dim_values, *contents;
5652 tng_trajectory_frame_set_t frame_set =
5653 &tng_data->current_trajectory_frame_set;
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;
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);
5691 data = &tng_data->non_tr_particle_data[block_index];
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);
5712 data = &tng_data->non_tr_data[block_index];
5717 switch(data->datatype)
5723 size = sizeof(int64_t);
5725 case TNG_FLOAT_DATA:
5726 size = sizeof(float);
5728 case TNG_DOUBLE_DATA:
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);
5740 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
5741 __FILE__, __LINE__);
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
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;
5791 num_first_particle = 0;
5792 if(tng_data->var_num_atoms_flag)
5794 n_particles = frame_set->n_particles;
5798 n_particles = tng_data->n_particles;
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;
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);
5826 if(tng_data_block_len_calculate(tng_data, data, TNG_FALSE, n_frames,
5827 frame_step, stride_length, 0,
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)
5875 if(tng_file_output_numerical(tng_data, &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)
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;
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);
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);
5988 if(data->dependency & TNG_PARTICLE_DEPENDENT)
5990 full_data_len = size * frame_step * n_particles * data->n_values_per_frame;
5994 full_data_len = size * frame_step * data->n_values_per_frame;
5996 contents = (char *)malloc(full_data_len);
5999 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
6000 __FILE__, __LINE__);
6001 return(TNG_CRITICAL);
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))
6024 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6025 __FILE__, __LINE__);
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))
6044 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6045 __FILE__, __LINE__);
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))
6060 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6061 __FILE__, __LINE__);
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))
6077 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6078 __FILE__, __LINE__);
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))
6097 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6098 __FILE__, __LINE__);
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;
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,
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,
6150 if(stat != TNG_SUCCESS)
6152 fprintf(stderr, "TNG library: Could not write gzipped block data. %s: %d\n", __FILE__,
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); */
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__,
6182 return(TNG_CRITICAL);
6184 if(hash_mode == TNG_USE_HASH)
6186 md5_append(&md5_state, (md5_byte_t *)contents, block_data_len);
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__,
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
6225 * @param num_first_particle is set to the number of the first particle with data written
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,
6241 int64_t *first_frame_with_data,
6242 int64_t *stride_length,
6244 int64_t *num_first_particle,
6245 int64_t *block_n_particles,
6247 const char hash_mode,
6248 md5_state_t *md5_state)
6250 if(tng_file_input_numerical(tng_data, 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,
6276 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6278 return(TNG_CRITICAL);
6281 if(tng_file_input_numerical(tng_data, 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);
6302 if(*dependency & TNG_FRAME_DEPENDENT)
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);
6326 *first_frame_with_data = tng_data->current_trajectory_frame_set.first_frame;
6328 *n_frames = tng_data->current_trajectory_frame_set.n_frames;
6333 *first_frame_with_data = 0;
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);
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;
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,
6404 &dependency, &sparse_data,
6405 &n_values, &codec_id,
6406 &first_frame_with_data,
6407 &stride_length, &n_frames,
6408 &num_first_particle,
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,
6426 first_frame_with_data,
6429 codec_id, multiplier,
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__);
6451 /* Seek to the end of the block */
6452 fseeko(tng_data->input_file, start_pos + block->block_contents_size, SEEK_SET);
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!!!
6469 // static tng_function_status tng_frame_set_align(tng_trajectory_t tng_data)
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)
6480 // return(TNG_SUCCESS);
6483 // if(tng_data->current_trajectory_frame_set_output_file_pos !=
6484 // tng_data->last_trajectory_frame_set_output_file_pos)
6488 // if(tng_output_file_init(tng_data) != TNG_SUCCESS)
6490 // fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
6491 // __FILE__, __LINE__);
6492 // return(TNG_CRITICAL);
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)
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);
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,
6520 // while(pos < output_file_len)
6522 // if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
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);
6530 // pos += block->header_contents_size + block->block_contents_size;
6531 // fseeko(tng_data->output_file, pos, SEEK_SET);
6534 // return(TNG_SUCCESS);
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
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)
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)
6636 // free(block->name);
6641 // block->name = (char *)malloc(len);
6644 // fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
6645 // __FILE__, __LINE__);
6646 // return(TNG_CRITICAL);
6650 // strncpy(block->name, new_name, len);
6652 // return(TNG_SUCCESS);
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)
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,
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)
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)
6712 atom->name = (char *)malloc(len);
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,
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)
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)
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)
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
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)
6829 int64_t i, res_cnt = 0;
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);
6842 * @brief Update atoms->residue pointers (after new memory for
6843 * molecule->residues has been allocated).
6844 * @param tng_data The trajectory container containing the molecule.
6845 * @param mol The molecule that contains the chains that need to be
6847 * @returns TNG_SUCCESS (0) if successful.
6849 static tng_function_status tng_molecule_atoms_residue_pointers_update
6850 (const tng_trajectory_t tng_data,
6851 const tng_molecule_t mol)
6854 tng_residue_t residue;
6855 int64_t i, j, atom_offset = 0;
6858 for(i = 0; i < mol->n_residues; i++)
6860 residue = &mol->residues[i];
6861 for(j = 0; j < residue->n_atoms; j++)
6863 atom = &mol->atoms[j + atom_offset];
6864 atom->residue = residue;
6866 atom_offset += residue->n_atoms;
6868 return(TNG_SUCCESS);
6871 tng_function_status DECLSPECDLLEXPORT tng_version_major
6872 (const tng_trajectory_t tng_data,
6877 *version = TNG_VERSION_MAJOR;
6879 return(TNG_SUCCESS);
6882 tng_function_status DECLSPECDLLEXPORT tng_version_minor
6883 (const tng_trajectory_t tng_data,
6888 *version = TNG_VERSION_MINOR;
6890 return(TNG_SUCCESS);
6893 tng_function_status DECLSPECDLLEXPORT tng_version_patchlevel
6894 (const tng_trajectory_t tng_data,
6899 *patch_level = TNG_VERSION_PATCHLEVEL;
6901 return(TNG_SUCCESS);
6904 tng_function_status DECLSPECDLLEXPORT tng_version
6905 (const tng_trajectory_t tng_data,
6910 TNG_ASSERT(version, "TNG library: version must not be a NULL pointer");
6912 TNG_SNPRINTF(version, max_len, "%s", TNG_VERSION);
6914 return(TNG_SUCCESS);
6917 tng_function_status DECLSPECDLLEXPORT tng_molecule_add
6918 (const tng_trajectory_t tng_data,
6920 tng_molecule_t *molecule)
6924 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
6925 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
6927 /* Set ID to the ID of the last molecule + 1 */
6928 if(tng_data->n_molecules)
6930 id = tng_data->molecules[tng_data->n_molecules-1].id + 1;
6937 return(tng_molecule_w_id_add(tng_data, name, id, molecule));
6940 tng_function_status DECLSPECDLLEXPORT tng_molecule_w_id_add
6941 (const tng_trajectory_t tng_data,
6944 tng_molecule_t *molecule)
6946 tng_molecule_t new_molecules;
6947 int64_t *new_molecule_cnt_list;
6948 tng_function_status stat = TNG_SUCCESS;
6950 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
6951 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
6953 new_molecules = (tng_molecule_t)realloc(tng_data->molecules,
6954 sizeof(struct tng_molecule) *
6955 (tng_data->n_molecules + 1));
6959 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
6960 __FILE__, __LINE__);
6961 free(tng_data->molecules);
6962 tng_data->molecules = 0;
6963 return(TNG_CRITICAL);
6966 new_molecule_cnt_list = (int64_t *)realloc(tng_data->molecule_cnt_list,
6968 (tng_data->n_molecules + 1));
6970 if(!new_molecule_cnt_list)
6972 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
6973 __FILE__, __LINE__);
6974 free(tng_data->molecule_cnt_list);
6975 tng_data->molecule_cnt_list = 0;
6976 free(new_molecules);
6977 return(TNG_CRITICAL);
6980 tng_data->molecules = new_molecules;
6981 tng_data->molecule_cnt_list = new_molecule_cnt_list;
6983 *molecule = &new_molecules[tng_data->n_molecules];
6985 tng_molecule_init(tng_data, *molecule);
6986 tng_molecule_name_set(tng_data, *molecule, name);
6988 /* FIXME: Should this be a function argument instead? */
6989 tng_data->molecule_cnt_list[tng_data->n_molecules] = 0;
6991 (*molecule)->id = id;
6993 tng_data->n_molecules++;
6998 tng_function_status DECLSPECDLLEXPORT tng_molecule_existing_add
6999 (const tng_trajectory_t tng_data,
7000 tng_molecule_t *molecule_p)
7002 int64_t *new_molecule_cnt_list, id;
7003 tng_molecule_t new_molecules, molecule;
7005 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7007 /* Set ID to the ID of the last molecule + 1 */
7008 if(tng_data->n_molecules)
7010 id = tng_data->molecules[tng_data->n_molecules-1].id + 1;
7017 new_molecules = (tng_molecule_t)realloc(tng_data->molecules,
7018 sizeof(struct tng_molecule) *
7019 (tng_data->n_molecules + 1));
7023 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
7024 __FILE__, __LINE__);
7025 free(tng_data->molecules);
7026 tng_data->molecules = 0;
7027 return(TNG_CRITICAL);
7030 new_molecule_cnt_list = (int64_t *)realloc(tng_data->molecule_cnt_list,
7032 (tng_data->n_molecules + 1));
7034 if(!new_molecule_cnt_list)
7036 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
7037 __FILE__, __LINE__);
7038 free(tng_data->molecule_cnt_list);
7039 tng_data->molecule_cnt_list = 0;
7040 free(new_molecules);
7041 return(TNG_CRITICAL);
7044 molecule = *molecule_p;
7046 tng_data->molecules = new_molecules;
7047 tng_data->molecule_cnt_list = new_molecule_cnt_list;
7049 new_molecules[tng_data->n_molecules] = *molecule;
7051 tng_data->molecule_cnt_list[tng_data->n_molecules] = 0;
7055 molecule = &new_molecules[tng_data->n_molecules];
7057 *molecule_p = molecule;
7061 tng_data->n_molecules++;
7063 return(TNG_SUCCESS);
7066 tng_function_status tng_molecule_name_get(const tng_trajectory_t tng_data,
7067 const tng_molecule_t molecule,
7072 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
7073 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
7075 strncpy(name, molecule->name, max_len - 1);
7076 name[max_len - 1] = 0;
7078 if(strlen(molecule->name) > (unsigned int)max_len - 1)
7080 return(TNG_FAILURE);
7082 return(TNG_SUCCESS);
7085 tng_function_status DECLSPECDLLEXPORT tng_molecule_name_set
7086 (const tng_trajectory_t tng_data,
7087 const tng_molecule_t molecule,
7088 const char *new_name)
7093 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7094 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
7096 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
7098 /* If the currently stored string length is not enough to store the new
7099 * string it is freed and reallocated. */
7100 if(molecule->name && strlen(molecule->name) < len)
7102 free(molecule->name);
7107 molecule->name = (char *)malloc(len);
7110 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
7111 __FILE__, __LINE__);
7112 return(TNG_CRITICAL);
7116 strncpy(molecule->name, new_name, len);
7118 return(TNG_SUCCESS);
7121 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_get
7122 (const tng_trajectory_t tng_data,
7123 const tng_molecule_t molecule,
7126 int64_t i, index = -1;
7128 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7129 TNG_ASSERT(cnt, "TNG library: cnt must not be a NULL pointer.");
7131 for(i = 0; i < tng_data->n_molecules; i++)
7133 if(&tng_data->molecules[i] == molecule)
7141 return(TNG_FAILURE);
7143 *cnt = tng_data->molecule_cnt_list[index];
7145 return(TNG_SUCCESS);
7148 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_set
7149 (const tng_trajectory_t tng_data,
7150 const tng_molecule_t molecule,
7153 int64_t i, old_cnt, index = -1;
7155 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7157 for(i = 0; i < tng_data->n_molecules; i++)
7159 if(&tng_data->molecules[i] == molecule)
7167 fprintf(stderr, "TNG library: Could not find molecule in TNG trajectory. %s: %d\n",
7168 __FILE__, __LINE__);
7169 return(TNG_FAILURE);
7171 if(tng_data->var_num_atoms_flag == TNG_CONSTANT_N_ATOMS)
7173 old_cnt = tng_data->molecule_cnt_list[index];
7174 tng_data->molecule_cnt_list[index] = cnt;
7176 tng_data->n_particles += (cnt-old_cnt) *
7177 tng_data->molecules[index].n_atoms;
7181 old_cnt = tng_data->current_trajectory_frame_set.molecule_cnt_list[index];
7182 tng_data->current_trajectory_frame_set.molecule_cnt_list[index] = cnt;
7184 tng_data->current_trajectory_frame_set.n_particles += (cnt-old_cnt) *
7185 tng_data->molecules[index].n_atoms;
7188 return(TNG_SUCCESS);
7191 tng_function_status DECLSPECDLLEXPORT tng_molecule_find
7192 (const tng_trajectory_t tng_data,
7195 tng_molecule_t *molecule)
7197 int64_t i, n_molecules;
7199 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7200 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7201 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
7203 n_molecules = tng_data->n_molecules;
7205 for(i = n_molecules - 1; i >= 0; i--)
7207 *molecule = &tng_data->molecules[i];
7208 if(name[0] == 0 || strcmp(name, (*molecule)->name) == 0)
7210 if(nr == -1 || nr == (*molecule)->id)
7212 return(TNG_SUCCESS);
7219 return(TNG_FAILURE);
7222 tng_function_status DECLSPECDLLEXPORT tng_molecule_of_index_get
7223 (const tng_trajectory_t tng_data,
7224 const int64_t index,
7225 tng_molecule_t *molecule)
7227 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7228 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
7230 if(index >= tng_data->n_molecules)
7233 return(TNG_FAILURE);
7235 *molecule = &tng_data->molecules[index];
7236 return(TNG_SUCCESS);
7239 tng_function_status DECLSPECDLLEXPORT tng_molecule_system_copy(const tng_trajectory_t tng_data_src,
7240 const tng_trajectory_t tng_data_dest)
7242 tng_molecule_t molecule, molecule_temp;
7243 tng_chain_t chain, chain_temp;
7244 tng_residue_t residue, residue_temp;
7245 tng_atom_t atom, atom_temp;
7246 tng_bond_t bond_temp;
7247 tng_function_status stat;
7248 int64_t i, j, k, l, *list_temp;
7250 TNG_ASSERT(tng_data_src, "TNG library: Trajectory container not properly setup.");
7251 TNG_ASSERT(tng_data_dest, "TNG library: Trajectory container not properly setup.");
7253 for(i = 0; i < tng_data_dest->n_molecules; i++)
7255 molecule = &tng_data_dest->molecules[i];
7256 tng_molecule_destroy(tng_data_dest, molecule);
7259 tng_data_dest->n_molecules = 0;
7260 tng_data_dest->n_particles = 0;
7262 molecule_temp = (tng_molecule_t)realloc(tng_data_dest->molecules,
7263 sizeof(struct tng_molecule) * tng_data_src->n_molecules);
7266 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
7267 __FILE__, __LINE__);
7268 free(tng_data_dest->molecules);
7269 tng_data_dest->molecules = 0;
7270 return(TNG_CRITICAL);
7272 list_temp = (int64_t *)realloc(tng_data_dest->molecule_cnt_list,
7273 sizeof(int64_t) * tng_data_src->n_molecules);
7276 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
7277 __FILE__, __LINE__);
7278 free(tng_data_dest->molecule_cnt_list);
7279 tng_data_dest->molecule_cnt_list = 0;
7280 free(molecule_temp);
7281 return(TNG_CRITICAL);
7284 tng_data_dest->molecules = molecule_temp;
7285 tng_data_dest->molecule_cnt_list = list_temp;
7287 for(i = 0; i < tng_data_src->n_molecules; i++)
7289 molecule = &tng_data_src->molecules[i];
7290 stat = tng_molecule_w_id_add(tng_data_dest, molecule->name, molecule->id,
7292 if(stat != TNG_SUCCESS)
7294 fprintf(stderr, "TNG library: Cannot create new molecule to make a copy. %s: %d\n",
7295 __FILE__, __LINE__);
7298 molecule_temp->quaternary_str = molecule->quaternary_str;
7299 for(j = 0; j < molecule->n_chains; j++)
7301 chain = &molecule->chains[j];
7302 stat = tng_molecule_chain_w_id_add(tng_data_dest, molecule_temp,
7303 chain->name, chain->id,
7305 if(stat != TNG_SUCCESS)
7307 fprintf(stderr, "TNG library: Cannot create new chain to make a copy. %s: %d\n",
7308 __FILE__, __LINE__);
7311 for(k = 0; k < chain->n_residues; k++)
7313 residue = &chain->residues[k];
7314 stat = tng_chain_residue_w_id_add(tng_data_dest, chain_temp,
7315 residue->name, residue->id,
7317 if(stat != TNG_SUCCESS)
7319 fprintf(stderr, "TNG library: Cannot create new residue to make a copy. %s: %d\n",
7320 __FILE__, __LINE__);
7323 for(l = 0; l < residue->n_atoms; l++)
7325 atom = &molecule->atoms[residue->atoms_offset + l];
7326 stat = tng_residue_atom_w_id_add(tng_data_dest, residue_temp,
7327 atom->name, atom->atom_type,
7328 atom->id, &atom_temp);
7329 if(stat != TNG_SUCCESS)
7331 fprintf(stderr, "TNG library: Cannot create new atom to make a copy. %s: %d\n",
7332 __FILE__, __LINE__);
7338 molecule_temp->n_bonds = molecule->n_bonds;
7339 if(molecule->n_bonds > 0)
7341 bond_temp = (tng_bond_t)realloc(molecule_temp->bonds, sizeof(struct tng_bond) *
7345 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
7346 __FILE__, __LINE__);
7347 free(molecule_temp->bonds);
7348 molecule_temp->n_bonds = 0;
7349 return(TNG_CRITICAL);
7351 molecule_temp->bonds = bond_temp;
7352 for(j = 0; j < molecule->n_bonds; j++)
7354 molecule_temp->bonds[j] = molecule->bonds[j];
7357 stat = tng_molecule_cnt_set(tng_data_dest, molecule_temp,
7358 tng_data_src->molecule_cnt_list[i]);
7359 if(stat != TNG_SUCCESS)
7361 fprintf(stderr, "TNG library: Cannot set molecule count. %s: %d.\n",
7362 __FILE__, __LINE__);
7366 return(TNG_SUCCESS);
7369 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_chains_get
7370 (const tng_trajectory_t tng_data,
7371 const tng_molecule_t molecule,
7375 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
7376 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
7378 *n = molecule->n_chains;
7380 return(TNG_SUCCESS);
7383 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_of_index_get
7384 (const tng_trajectory_t tng_data,
7385 const tng_molecule_t molecule,
7386 const int64_t index,
7390 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
7391 TNG_ASSERT(chain, "TNG library: chain must not be a NULL pointer.");
7393 if(index >= molecule->n_chains)
7396 return(TNG_FAILURE);
7398 *chain = &molecule->chains[index];
7399 return(TNG_SUCCESS);
7402 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_residues_get
7403 (const tng_trajectory_t tng_data,
7404 const tng_molecule_t molecule,
7408 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
7409 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
7411 *n = molecule->n_residues;
7413 return(TNG_SUCCESS);
7416 tng_function_status DECLSPECDLLEXPORT tng_molecule_residue_of_index_get
7417 (const tng_trajectory_t tng_data,
7418 const tng_molecule_t molecule,
7419 const int64_t index,
7420 tng_residue_t *residue)
7423 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
7424 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
7426 if(index >= molecule->n_residues)
7429 return(TNG_FAILURE);
7431 *residue = &molecule->residues[index];
7432 return(TNG_SUCCESS);
7435 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_atoms_get
7436 (const tng_trajectory_t tng_data,
7437 const tng_molecule_t molecule,
7441 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
7442 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
7444 *n = molecule->n_atoms;
7446 return(TNG_SUCCESS);
7449 tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_of_index_get
7450 (const tng_trajectory_t tng_data,
7451 const tng_molecule_t molecule,
7452 const int64_t index,
7456 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
7457 TNG_ASSERT(atom, "TNG library: atom must not be a NULL pointer.");
7459 if(index >= molecule->n_atoms)
7462 return(TNG_FAILURE);
7464 *atom = &molecule->atoms[index];
7465 return(TNG_SUCCESS);
7468 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_find
7469 (const tng_trajectory_t tng_data,
7470 const tng_molecule_t molecule,
7475 int64_t i, n_chains;
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 n_chains = molecule->n_chains;
7483 for(i = n_chains - 1; i >= 0; i--)
7485 *chain = &molecule->chains[i];
7486 if(name[0] == 0 || strcmp(name, (*chain)->name) == 0)
7488 if(nr == -1 || nr == (*chain)->id)
7490 return(TNG_SUCCESS);
7497 return(TNG_FAILURE);
7500 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_add
7501 (const tng_trajectory_t tng_data,
7502 const tng_molecule_t molecule,
7508 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7509 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7511 /* Set ID to the ID of the last chain + 1 */
7512 if(molecule->n_chains)
7514 id = molecule->chains[molecule->n_chains-1].id + 1;
7521 return(tng_molecule_chain_w_id_add(tng_data, molecule, name,
7525 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_w_id_add
7526 (const tng_trajectory_t tng_data,
7527 const tng_molecule_t molecule,
7532 tng_chain_t new_chains;
7533 tng_function_status stat = TNG_SUCCESS;
7535 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7536 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7538 new_chains = (tng_chain_t)realloc(molecule->chains,
7539 sizeof(struct tng_chain) *
7540 (molecule->n_chains + 1));
7544 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
7545 __FILE__, __LINE__);
7546 free(molecule->chains);
7547 molecule->chains = 0;
7548 return(TNG_CRITICAL);
7551 molecule->chains = new_chains;
7553 *chain = &new_chains[molecule->n_chains];
7556 tng_chain_name_set(tng_data, *chain, name);
7558 (*chain)->molecule = molecule;
7559 (*chain)->n_residues = 0;
7561 molecule->n_chains++;
7568 tng_function_status DECLSPECDLLEXPORT tng_molecule_bond_add
7569 (const tng_trajectory_t tng_data,
7570 const tng_molecule_t molecule,
7571 const int64_t from_atom_id,
7572 const int64_t to_atom_id,
7575 tng_bond_t new_bonds;
7578 new_bonds = (tng_bond_t)realloc(molecule->bonds,
7579 sizeof(struct tng_bond) *
7580 (molecule->n_bonds + 1));
7584 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
7585 __FILE__, __LINE__);
7587 free(molecule->bonds);
7588 molecule->bonds = 0;
7589 return(TNG_CRITICAL);
7592 molecule->bonds = new_bonds;
7594 *bond = &new_bonds[molecule->n_bonds];
7596 (*bond)->from_atom_id = from_atom_id;
7597 (*bond)->to_atom_id = to_atom_id;
7599 molecule->n_bonds++;
7601 return(TNG_SUCCESS);
7604 tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_find
7605 (const tng_trajectory_t tng_data,
7606 const tng_molecule_t molecule,
7614 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7616 n_atoms = molecule->n_atoms;
7618 for(i = n_atoms - 1; i >= 0; i--)
7620 *atom = &molecule->atoms[i];
7621 if(name[0] == 0 || strcmp(name, (*atom)->name) == 0)
7623 if(id == -1 || id == (*atom)->id)
7625 return(TNG_SUCCESS);
7632 return(TNG_FAILURE);
7635 tng_function_status tng_chain_name_get(const tng_trajectory_t tng_data,
7636 const tng_chain_t chain,
7641 TNG_ASSERT(chain, "TNG library: chain must not be NULL");
7642 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
7644 strncpy(name, chain->name, max_len - 1);
7645 name[max_len - 1] = 0;
7647 if(strlen(chain->name) > (unsigned int)max_len - 1)
7649 return(TNG_FAILURE);
7651 return(TNG_SUCCESS);
7654 tng_function_status DECLSPECDLLEXPORT tng_chain_name_set
7655 (const tng_trajectory_t tng_data,
7656 const tng_chain_t chain,
7657 const char *new_name)
7662 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
7664 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
7666 /* If the currently stored string length is not enough to store the new
7667 * string it is freed and reallocated. */
7668 if(chain->name && strlen(chain->name) < len)
7675 chain->name = (char *)malloc(len);
7678 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
7679 __FILE__, __LINE__);
7680 return(TNG_CRITICAL);
7684 strncpy(chain->name, new_name, len);
7686 return(TNG_SUCCESS);
7689 tng_function_status DECLSPECDLLEXPORT tng_chain_num_residues_get
7690 (const tng_trajectory_t tng_data,
7691 const tng_chain_t chain,
7695 TNG_ASSERT(chain, "TNG library: chain must not be NULL");
7696 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
7698 *n = chain->n_residues;
7700 return(TNG_SUCCESS);
7703 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_of_index_get
7704 (const tng_trajectory_t tng_data,
7705 const tng_chain_t chain,
7706 const int64_t index,
7707 tng_residue_t *residue)
7710 TNG_ASSERT(chain, "TNG library: chain must not be a NULL pointer.");
7711 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
7713 if(index >= chain->n_residues)
7716 return(TNG_FAILURE);
7718 *residue = &chain->residues[index];
7719 return(TNG_SUCCESS);
7722 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_find
7723 (const tng_trajectory_t tng_data,
7724 const tng_chain_t chain,
7727 tng_residue_t *residue)
7729 int64_t i, n_residues;
7732 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7734 n_residues = chain->n_residues;
7736 for(i = n_residues - 1; i >= 0; i--)
7738 *residue = &chain->residues[i];
7739 if(name[0] == 0 || strcmp(name, (*residue)->name) == 0)
7741 if(id == -1 || id == (*residue)->id)
7743 return(TNG_SUCCESS);
7750 return(TNG_FAILURE);
7753 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_add
7754 (const tng_trajectory_t tng_data,
7755 const tng_chain_t chain,
7757 tng_residue_t *residue)
7761 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7762 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7764 /* Set ID to the ID of the last residue + 1 */
7765 if(chain->n_residues)
7767 id = chain->residues[chain->n_residues-1].id + 1;
7774 return(tng_chain_residue_w_id_add(tng_data, chain, name,
7778 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_w_id_add
7779 (const tng_trajectory_t tng_data,
7780 const tng_chain_t chain,
7783 tng_residue_t *residue)
7786 tng_residue_t new_residues, temp_residue, last_residue;
7787 tng_molecule_t molecule = chain->molecule;
7788 tng_function_status stat = TNG_SUCCESS;
7790 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7791 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7793 if(chain->n_residues)
7795 curr_index = chain->residues - molecule->residues;
7802 new_residues = (tng_residue_t)realloc(molecule->residues,
7803 sizeof(struct tng_residue) *
7804 (molecule->n_residues + 1));
7808 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
7809 __FILE__, __LINE__);
7810 free(molecule->residues);
7811 molecule->residues = 0;
7812 return(TNG_CRITICAL);
7815 molecule->residues = new_residues;
7817 if(curr_index != -1)
7819 chain->residues = new_residues + curr_index;
7820 if(molecule->n_residues)
7822 last_residue = &new_residues[molecule->n_residues - 1];
7824 temp_residue = chain->residues + (chain->n_residues - 1);
7825 /* Make space in list of residues to add the new residues together with the other
7826 * residues of this chain */
7827 if(temp_residue != last_residue)
7830 memmove(temp_residue + 1, temp_residue,
7831 last_residue - temp_residue);
7837 curr_index = molecule->n_residues;
7840 *residue = &molecule->residues[curr_index + chain->n_residues];
7842 tng_molecule_chains_residue_pointers_update(tng_data, molecule);
7843 tng_molecule_atoms_residue_pointers_update(tng_data, molecule);
7845 (*residue)->name = 0;
7846 tng_residue_name_set(tng_data, *residue, name);
7848 (*residue)->chain = chain;
7849 (*residue)->n_atoms = 0;
7850 (*residue)->atoms_offset = 0;
7852 chain->n_residues++;
7853 molecule->n_residues++;
7855 (*residue)->id = id;
7860 tng_function_status tng_residue_name_get(const tng_trajectory_t tng_data,
7861 const tng_residue_t residue,
7866 TNG_ASSERT(residue, "TNG library: residue must not be NULL");
7867 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
7869 strncpy(name, residue->name, max_len - 1);
7870 name[max_len - 1] = 0;
7872 if(strlen(residue->name) > (unsigned int)max_len - 1)
7874 return(TNG_FAILURE);
7876 return(TNG_SUCCESS);
7879 tng_function_status DECLSPECDLLEXPORT tng_residue_name_set(const tng_trajectory_t tng_data,
7880 const tng_residue_t residue,
7881 const char *new_name)
7886 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7887 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
7889 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
7891 /* If the currently stored string length is not enough to store the new
7892 * string it is freed and reallocated. */
7893 if(residue->name && strlen(residue->name) < len)
7895 free(residue->name);
7900 residue->name = (char *)malloc(len);
7903 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
7904 __FILE__, __LINE__);
7905 return(TNG_CRITICAL);
7909 strncpy(residue->name, new_name, len);
7911 return(TNG_SUCCESS);
7914 tng_function_status DECLSPECDLLEXPORT tng_residue_num_atoms_get
7915 (const tng_trajectory_t tng_data,
7916 const tng_residue_t residue,
7920 TNG_ASSERT(residue, "TNG library: residue must not be NULL");
7921 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
7923 *n = residue->n_atoms;
7925 return(TNG_SUCCESS);
7928 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_of_index_get
7929 (const tng_trajectory_t tng_data,
7930 const tng_residue_t residue,
7931 const int64_t index,
7935 tng_molecule_t molecule;
7938 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
7939 TNG_ASSERT(atom, "TNG library: atom must not be a NULL pointer.");
7941 if(index >= residue->n_atoms)
7944 return(TNG_FAILURE);
7946 chain = residue->chain;
7947 molecule = chain->molecule;
7949 if(index + residue->atoms_offset >= molecule->n_atoms)
7952 return(TNG_FAILURE);
7955 *atom = &molecule->atoms[residue->atoms_offset + index];
7956 return(TNG_SUCCESS);
7959 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_add
7960 (const tng_trajectory_t tng_data,
7961 const tng_residue_t residue,
7962 const char *atom_name,
7963 const char *atom_type,
7968 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7969 TNG_ASSERT(atom_name, "TNG library: atom_name must not be a NULL pointer.");
7970 TNG_ASSERT(atom_type, "TNG library: atom_type must not be a NULL pointer.");
7972 /* Set ID to the ID of the last atom + 1 */
7973 if(residue->chain->molecule->n_atoms)
7975 id = residue->chain->molecule->atoms[residue->chain->molecule->n_atoms-1].id + 1;
7982 return(tng_residue_atom_w_id_add(tng_data, residue, atom_name, atom_type,
7986 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_w_id_add
7987 (const tng_trajectory_t tng_data,
7988 const tng_residue_t residue,
7989 const char *atom_name,
7990 const char *atom_type,
7994 tng_atom_t new_atoms;
7995 tng_molecule_t molecule = residue->chain->molecule;
7996 tng_function_status stat = TNG_SUCCESS;
7998 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7999 TNG_ASSERT(atom_name, "TNG library: atom_name must not be a NULL pointer.");
8000 TNG_ASSERT(atom_type, "TNG library: atom_type must not be a NULL pointer.");
8002 if(!residue->n_atoms)
8004 residue->atoms_offset = molecule->n_atoms;
8007 new_atoms = (tng_atom_t)realloc(molecule->atoms,
8008 sizeof(struct tng_atom) *
8009 (molecule->n_atoms + 1));
8013 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
8014 __FILE__, __LINE__);
8015 free(molecule->atoms);
8016 molecule->atoms = 0;
8017 return(TNG_CRITICAL);
8020 molecule->atoms = new_atoms;
8022 *atom = &new_atoms[molecule->n_atoms];
8024 tng_atom_init(*atom);
8025 tng_atom_name_set(tng_data, *atom, atom_name);
8026 tng_atom_type_set(tng_data, *atom, atom_type);
8028 (*atom)->residue = residue;
8031 molecule->n_atoms++;
8038 tng_function_status DECLSPECDLLEXPORT tng_molecule_alloc(const tng_trajectory_t tng_data,
8039 tng_molecule_t *molecule_p)
8041 *molecule_p = (tng_molecule_t)malloc(sizeof(struct tng_molecule));
8044 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
8045 __FILE__, __LINE__);
8046 return(TNG_CRITICAL);
8049 tng_molecule_init(tng_data, *molecule_p);
8051 return(TNG_SUCCESS);
8054 tng_function_status DECLSPECDLLEXPORT tng_molecule_free(const tng_trajectory_t tng_data,
8055 tng_molecule_t *molecule_p)
8059 return(TNG_SUCCESS);
8062 tng_molecule_destroy(tng_data, *molecule_p);
8067 return(TNG_SUCCESS);
8070 tng_function_status DECLSPECDLLEXPORT tng_molecule_init(const tng_trajectory_t tng_data,
8071 const tng_molecule_t molecule)
8074 molecule->quaternary_str = 1;
8076 molecule->n_chains = 0;
8077 molecule->chains = 0;
8078 molecule->n_residues = 0;
8079 molecule->residues = 0;
8080 molecule->n_atoms = 0;
8081 molecule->atoms = 0;
8082 molecule->n_bonds = 0;
8083 molecule->bonds = 0;
8085 return(TNG_SUCCESS);
8088 tng_function_status DECLSPECDLLEXPORT tng_molecule_destroy(const tng_trajectory_t tng_data,
8089 const tng_molecule_t molecule)
8096 free(molecule->name);
8100 if(molecule->chains)
8102 for(i = 0; i < molecule->n_chains; i++)
8104 if(molecule->chains[i].name)
8106 free(molecule->chains[i].name);
8107 molecule->chains[i].name = 0;
8110 free(molecule->chains);
8111 molecule->chains = 0;
8113 molecule->n_chains = 0;
8115 if(molecule->residues)
8117 for(i = 0; i < molecule->n_residues; i++)
8119 if(molecule->residues[i].name)
8121 free(molecule->residues[i].name);
8122 molecule->residues[i].name = 0;
8125 free(molecule->residues);
8126 molecule->residues = 0;
8128 molecule->n_residues = 0;
8132 for(i = 0; i < molecule->n_atoms; i++)
8134 tng_atom_destroy(&molecule->atoms[i]);
8136 free(molecule->atoms);
8137 molecule->atoms = 0;
8139 molecule->n_atoms = 0;
8143 free(molecule->bonds);
8144 molecule->bonds = 0;
8146 molecule->n_bonds = 0;
8148 return(TNG_SUCCESS);
8151 tng_function_status DECLSPECDLLEXPORT tng_molecule_name_of_particle_nr_get
8152 (const tng_trajectory_t tng_data,
8157 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8159 tng_bool found = TNG_FALSE;
8161 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8162 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8164 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8166 if(!molecule_cnt_list)
8168 return(TNG_FAILURE);
8171 for(i = 0; i < tng_data->n_molecules; i++)
8173 mol = &tng_data->molecules[i];
8174 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8176 cnt += mol->n_atoms * molecule_cnt_list[i];
8184 return(TNG_FAILURE);
8187 strncpy(name, mol->name, max_len - 1);
8188 name[max_len - 1] = 0;
8190 if(strlen(mol->name) > (unsigned int)max_len - 1)
8192 return(TNG_FAILURE);
8194 return(TNG_SUCCESS);
8197 tng_function_status DECLSPECDLLEXPORT tng_molecule_id_of_particle_nr_get
8198 (const tng_trajectory_t tng_data,
8202 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8204 tng_bool found = TNG_FALSE;
8206 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8207 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
8209 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8211 if(!molecule_cnt_list)
8213 return(TNG_FAILURE);
8216 for(i = 0; i < tng_data->n_molecules; i++)
8218 mol = &tng_data->molecules[i];
8219 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8221 cnt += mol->n_atoms * molecule_cnt_list[i];
8229 return(TNG_FAILURE);
8234 return(TNG_SUCCESS);
8237 tng_function_status DECLSPECDLLEXPORT tng_molsystem_bonds_get
8238 (const tng_trajectory_t tng_data,
8240 int64_t **from_atoms,
8243 int64_t atom_cnt = 0, cnt, mol_cnt, i, j, k;
8244 int64_t from_atom, to_atom, *molecule_cnt_list = 0;
8248 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8249 TNG_ASSERT(n_bonds, "TNG library: n_bonds must not be a NULL pointer.");
8250 TNG_ASSERT(from_atoms, "TNG library: from_atoms must not be a NULL pointer.");
8251 TNG_ASSERT(to_atoms, "TNG library: to_atoms must not be a NULL pointer.");
8253 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8255 if(!molecule_cnt_list)
8257 return(TNG_FAILURE);
8261 /* First count the total number of bonds to allocate memory */
8262 for(i = 0; i < tng_data->n_molecules; i++)
8264 mol = &tng_data->molecules[i];
8265 mol_cnt = molecule_cnt_list[i];
8266 *n_bonds += mol_cnt * mol->n_bonds;
8270 return(TNG_SUCCESS);
8273 *from_atoms = (int64_t *)malloc(sizeof(int64_t) * (*n_bonds));
8276 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
8277 __FILE__, __LINE__);
8278 return(TNG_CRITICAL);
8280 *to_atoms = (int64_t *)malloc(sizeof(int64_t) * (*n_bonds));
8283 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
8284 __FILE__, __LINE__);
8287 return(TNG_CRITICAL);
8291 for(i = 0; i < tng_data->n_molecules; i++)
8293 mol = &tng_data->molecules[i];
8294 mol_cnt = molecule_cnt_list[i];
8295 for(j = 0; j < mol_cnt; j++)
8297 for(k = 0; k < mol->n_bonds; k++)
8299 bond = &mol->bonds[k];
8300 from_atom = atom_cnt + bond->from_atom_id;
8301 to_atom = atom_cnt + bond->to_atom_id;
8302 (*from_atoms)[cnt] = from_atom;
8303 (*to_atoms)[cnt++] = to_atom;
8305 atom_cnt += mol->n_atoms;
8309 return(TNG_SUCCESS);
8312 tng_function_status DECLSPECDLLEXPORT tng_chain_name_of_particle_nr_get
8313 (const tng_trajectory_t tng_data,
8318 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8321 tng_bool found = TNG_FALSE;
8323 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8324 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8326 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8328 if(!molecule_cnt_list)
8330 return(TNG_FAILURE);
8333 for(i = 0; i < tng_data->n_molecules; i++)
8335 mol = &tng_data->molecules[i];
8336 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8338 cnt += mol->n_atoms * molecule_cnt_list[i];
8341 atom = &mol->atoms[nr % mol->n_atoms];
8347 return(TNG_FAILURE);
8349 if(!atom->residue || !atom->residue->chain)
8351 return(TNG_FAILURE);
8354 strncpy(name, atom->residue->chain->name, max_len - 1);
8355 name[max_len - 1] = 0;
8357 if(strlen(atom->residue->chain->name) > (unsigned int)max_len - 1)
8359 return(TNG_FAILURE);
8361 return(TNG_SUCCESS);
8364 tng_function_status DECLSPECDLLEXPORT tng_residue_name_of_particle_nr_get
8365 (const tng_trajectory_t tng_data,
8370 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8373 tng_bool found = TNG_FALSE;
8375 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8376 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8378 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8380 if(!molecule_cnt_list)
8382 return(TNG_FAILURE);
8385 for(i = 0; i < tng_data->n_molecules; i++)
8387 mol = &tng_data->molecules[i];
8388 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8390 cnt += mol->n_atoms * molecule_cnt_list[i];
8393 atom = &mol->atoms[nr % mol->n_atoms];
8399 return(TNG_FAILURE);
8403 return(TNG_FAILURE);
8406 strncpy(name, atom->residue->name, max_len - 1);
8407 name[max_len - 1] = 0;
8409 if(strlen(atom->residue->name) > (unsigned int)max_len - 1)
8411 return(TNG_FAILURE);
8413 return(TNG_SUCCESS);
8416 tng_function_status DECLSPECDLLEXPORT tng_residue_id_of_particle_nr_get
8417 (const tng_trajectory_t tng_data,
8421 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8424 tng_bool found = TNG_FALSE;
8426 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8427 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
8429 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8431 if(!molecule_cnt_list)
8433 return(TNG_FAILURE);
8436 for(i = 0; i < tng_data->n_molecules; i++)
8438 mol = &tng_data->molecules[i];
8439 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8441 cnt += mol->n_atoms * molecule_cnt_list[i];
8444 atom = &mol->atoms[nr % mol->n_atoms];
8450 return(TNG_FAILURE);
8454 return(TNG_FAILURE);
8457 *id = atom->residue->id;
8459 return(TNG_SUCCESS);
8462 tng_function_status DECLSPECDLLEXPORT tng_global_residue_id_of_particle_nr_get
8463 (const tng_trajectory_t tng_data,
8467 int64_t cnt = 0, i, offset = 0, *molecule_cnt_list = 0;
8470 tng_bool found = TNG_FALSE;
8472 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8473 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
8475 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8477 if(!molecule_cnt_list)
8479 return(TNG_FAILURE);
8482 for(i = 0; i < tng_data->n_molecules; i++)
8484 mol = &tng_data->molecules[i];
8485 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8487 cnt += mol->n_atoms * molecule_cnt_list[i];
8488 offset += mol->n_residues * molecule_cnt_list[i];
8491 atom = &mol->atoms[nr % mol->n_atoms];
8497 return(TNG_FAILURE);
8501 return(TNG_FAILURE);
8504 offset += mol->n_residues * ((nr - cnt) / mol->n_atoms);
8506 *id = atom->residue->id + offset;
8508 return(TNG_SUCCESS);
8511 tng_function_status DECLSPECDLLEXPORT tng_atom_name_of_particle_nr_get
8512 (const tng_trajectory_t tng_data,
8517 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8520 tng_bool found = TNG_FALSE;
8522 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8523 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8525 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8527 if(!molecule_cnt_list)
8529 return(TNG_FAILURE);
8532 for(i = 0; i < tng_data->n_molecules; i++)
8534 mol = &tng_data->molecules[i];
8535 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8537 cnt += mol->n_atoms * molecule_cnt_list[i];
8540 atom = &mol->atoms[nr % mol->n_atoms];
8546 return(TNG_FAILURE);
8549 strncpy(name, atom->name, max_len - 1);
8550 name[max_len - 1] = 0;
8552 if(strlen(atom->name) > (unsigned int)max_len - 1)
8554 return(TNG_FAILURE);
8556 return(TNG_SUCCESS);
8559 tng_function_status tng_atom_type_of_particle_nr_get
8560 (const tng_trajectory_t tng_data,
8565 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8568 tng_bool found = TNG_FALSE;
8570 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8571 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
8573 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8575 if(!molecule_cnt_list)
8577 return(TNG_FAILURE);
8580 for(i = 0; i < tng_data->n_molecules; i++)
8582 mol = &tng_data->molecules[i];
8583 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8585 cnt += mol->n_atoms * molecule_cnt_list[i];
8588 atom = &mol->atoms[nr % mol->n_atoms];
8594 return(TNG_FAILURE);
8597 strncpy(type, atom->atom_type, max_len - 1);
8598 type[max_len - 1] = 0;
8600 if(strlen(atom->atom_type) > (unsigned int)max_len - 1)
8602 return(TNG_FAILURE);
8604 return(TNG_SUCCESS);
8607 tng_function_status DECLSPECDLLEXPORT tng_particle_mapping_add
8608 (const tng_trajectory_t tng_data,
8609 const int64_t num_first_particle,
8610 const int64_t n_particles,
8611 const int64_t *mapping_table)
8614 tng_particle_mapping_t mapping;
8615 tng_trajectory_frame_set_t frame_set;
8617 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8619 frame_set = &tng_data->current_trajectory_frame_set;
8621 /* Sanity check of the particle ranges. Split into multiple if
8622 * statements for improved readability */
8623 for(i = 0; i < frame_set->n_mapping_blocks; i++)
8625 mapping = &frame_set->mappings[i];
8626 if(num_first_particle >= mapping->num_first_particle &&
8627 num_first_particle < mapping->num_first_particle +
8628 mapping->n_particles)
8630 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
8631 return(TNG_FAILURE);
8633 if(num_first_particle + n_particles >=
8634 mapping->num_first_particle &&
8635 num_first_particle + n_particles <
8636 mapping->num_first_particle + mapping->n_particles)
8638 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
8639 return(TNG_FAILURE);
8641 if(mapping->num_first_particle >= num_first_particle &&
8642 mapping->num_first_particle < num_first_particle +
8645 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
8646 return(TNG_FAILURE);
8648 if(mapping->num_first_particle + mapping->n_particles >
8649 num_first_particle &&
8650 mapping->num_first_particle + mapping->n_particles <
8651 num_first_particle + n_particles)
8653 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
8654 return(TNG_FAILURE);
8658 frame_set->n_mapping_blocks++;
8660 mapping = (tng_particle_mapping_t)realloc(frame_set->mappings, sizeof(struct tng_particle_mapping) *
8661 frame_set->n_mapping_blocks);
8665 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
8666 __FILE__, __LINE__);
8667 free(frame_set->mappings);
8668 frame_set->mappings = 0;
8669 return(TNG_CRITICAL);
8671 frame_set->mappings = mapping;
8673 frame_set->mappings[frame_set->n_mapping_blocks - 1].num_first_particle = num_first_particle;
8674 frame_set->mappings[frame_set->n_mapping_blocks - 1].n_particles = n_particles;
8676 frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers = (int64_t *)malloc(sizeof(int64_t) * n_particles);
8677 if(!frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers)
8679 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
8680 __FILE__, __LINE__);
8681 return(TNG_CRITICAL);
8684 for(i=0; i<n_particles; i++)
8686 frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers[i] = mapping_table[i];
8689 return(TNG_SUCCESS);
8692 tng_function_status DECLSPECDLLEXPORT tng_frame_set_particle_mapping_free(const tng_trajectory_t tng_data)
8694 tng_trajectory_frame_set_t frame_set;
8695 tng_particle_mapping_t mapping;
8698 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8700 frame_set = &tng_data->current_trajectory_frame_set;
8702 if(frame_set->n_mapping_blocks && frame_set->mappings)
8704 for(i = 0; i < frame_set->n_mapping_blocks; i++)
8706 mapping = &frame_set->mappings[i];
8707 if(mapping->real_particle_numbers)
8709 free(mapping->real_particle_numbers);
8710 mapping->real_particle_numbers = 0;
8713 free(frame_set->mappings);
8714 frame_set->mappings = 0;
8715 frame_set->n_mapping_blocks = 0;
8718 return(TNG_SUCCESS);
8721 tng_function_status DECLSPECDLLEXPORT tng_trajectory_init(tng_trajectory_t *tng_data_p)
8724 tng_trajectory_frame_set_t frame_set;
8725 tng_trajectory_t tng_data;
8727 *tng_data_p = (tng_trajectory_t)malloc(sizeof(struct tng_trajectory));
8730 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
8731 __FILE__, __LINE__);
8732 return(TNG_CRITICAL);
8735 tng_data = *tng_data_p;
8737 frame_set = &tng_data->current_trajectory_frame_set;
8739 tng_data->input_file_path = 0;
8740 tng_data->input_file = 0;
8741 tng_data->input_file_len = 0;
8742 tng_data->output_file_path = 0;
8743 tng_data->output_file = 0;
8745 tng_data->first_program_name = 0;
8746 tng_data->first_user_name = 0;
8747 tng_data->first_computer_name = 0;
8748 tng_data->first_pgp_signature = 0;
8749 tng_data->last_program_name = 0;
8750 tng_data->last_user_name = 0;
8751 tng_data->last_computer_name = 0;
8752 tng_data->last_pgp_signature = 0;
8753 tng_data->forcefield_name = 0;
8758 fprintf(stderr, "TNG library: Cannot get time. %s: %d\n", __FILE__, __LINE__);
8762 tng_data->time = seconds;
8765 tng_data->var_num_atoms_flag = TNG_CONSTANT_N_ATOMS;
8766 tng_data->first_trajectory_frame_set_input_file_pos = -1;
8767 tng_data->last_trajectory_frame_set_input_file_pos = -1;
8768 tng_data->current_trajectory_frame_set_input_file_pos = -1;
8769 tng_data->first_trajectory_frame_set_output_file_pos = -1;
8770 tng_data->last_trajectory_frame_set_output_file_pos = -1;
8771 tng_data->current_trajectory_frame_set_output_file_pos = -1;
8772 tng_data->frame_set_n_frames = 100;
8773 tng_data->n_trajectory_frame_sets = 0;
8774 tng_data->medium_stride_length = 100;
8775 tng_data->long_stride_length = 10000;
8777 tng_data->time_per_frame = -1;
8779 tng_data->n_particle_data_blocks = 0;
8780 tng_data->n_data_blocks = 0;
8782 tng_data->non_tr_particle_data = 0;
8783 tng_data->non_tr_data = 0;
8785 tng_data->compress_algo_pos = 0;
8786 tng_data->compress_algo_vel = 0;
8787 tng_data->compression_precision = 1000;
8788 tng_data->distance_unit_exponential = -9;
8790 frame_set->first_frame = -1;
8791 frame_set->n_mapping_blocks = 0;
8792 frame_set->mappings = 0;
8793 frame_set->molecule_cnt_list = 0;
8795 frame_set->n_particle_data_blocks = 0;
8796 frame_set->n_data_blocks = 0;
8798 frame_set->tr_particle_data = 0;
8799 frame_set->tr_data = 0;
8801 frame_set->n_written_frames = 0;
8802 frame_set->n_unwritten_frames = 0;
8804 frame_set->next_frame_set_file_pos = -1;
8805 frame_set->prev_frame_set_file_pos = -1;
8806 frame_set->medium_stride_next_frame_set_file_pos = -1;
8807 frame_set->medium_stride_prev_frame_set_file_pos = -1;
8808 frame_set->long_stride_next_frame_set_file_pos = -1;
8809 frame_set->long_stride_prev_frame_set_file_pos = -1;
8811 frame_set->first_frame_time = -1;
8813 tng_data->n_molecules = 0;
8814 tng_data->molecules = 0;
8815 tng_data->molecule_cnt_list = 0;
8816 tng_data->n_particles = 0;
8819 /* Check the endianness of the computer */
8820 static int32_t endianness_32 = 0x01234567;
8822 if ( *(const unsigned char*)&endianness_32 == 0x01 )
8824 tng_data->endianness_32 = TNG_BIG_ENDIAN_32;
8828 else if( *(const unsigned char*)&endianness_32 == 0x67 )
8830 tng_data->endianness_32 = TNG_LITTLE_ENDIAN_32;
8835 else if ( *(const unsigned char*)&endianness_32 == 0x45 )
8837 tng_data->endianness_32 = TNG_BYTE_PAIR_SWAP_32;
8841 static int64_t endianness_64 = 0x0123456789ABCDEFLL;
8842 /* 0x0123456789ABCDEF */
8843 if ( *(const unsigned char*)&endianness_64 == 0x01 )
8845 tng_data->endianness_64 = TNG_BIG_ENDIAN_64;
8848 /* 0xEFCDAB8967452301 */
8849 else if ( *(const unsigned char*)&endianness_64 == 0xEF )
8851 tng_data->endianness_64 = TNG_LITTLE_ENDIAN_64;
8854 /* 0x89ABCDEF01234567 */
8855 else if ( *(const unsigned char*)&endianness_64 == 0x89 )
8857 tng_data->endianness_64 = TNG_QUAD_SWAP_64;
8860 /* 0x45670123CDEF89AB */
8861 else if ( *(const unsigned char*)&endianness_64 == 0x45 )
8863 tng_data->endianness_64 = TNG_BYTE_PAIR_SWAP_64;
8866 /* 0x23016745AB89EFCD */
8867 else if ( *(const unsigned char*)&endianness_64 == 0x23 )
8869 tng_data->endianness_64 = TNG_BYTE_SWAP_64;
8873 /* By default do not swap the byte order, i.e. keep the byte order of the
8874 * architecture. The input file endianness will be set when reading the
8875 * header. The output endianness can be changed - before the file is
8877 tng_data->input_endianness_swap_func_32 = 0;
8878 tng_data->input_endianness_swap_func_64 = 0;
8879 tng_data->output_endianness_swap_func_32 = 0;
8880 tng_data->output_endianness_swap_func_64 = 0;
8882 tng_data->current_trajectory_frame_set.next_frame_set_file_pos = -1;
8883 tng_data->current_trajectory_frame_set.prev_frame_set_file_pos = -1;
8884 tng_data->current_trajectory_frame_set.n_frames = 0;
8886 return(TNG_SUCCESS);
8889 tng_function_status DECLSPECDLLEXPORT tng_trajectory_destroy(tng_trajectory_t *tng_data_p)
8892 int64_t n_particles, n_values_per_frame;
8893 tng_trajectory_t tng_data = *tng_data_p;
8894 tng_trajectory_frame_set_t frame_set;
8898 return(TNG_SUCCESS);
8901 frame_set = &tng_data->current_trajectory_frame_set;
8903 if(tng_data->input_file)
8905 if(tng_data->output_file == tng_data->input_file)
8907 tng_frame_set_finalize(tng_data, TNG_USE_HASH);
8908 tng_data->output_file = 0;
8910 fclose(tng_data->input_file);
8911 tng_data->input_file = 0;
8914 if(tng_data->input_file_path)
8916 free(tng_data->input_file_path);
8917 tng_data->input_file_path = 0;
8920 if(tng_data->output_file)
8922 /* FIXME: Do not always write the hash */
8923 tng_frame_set_finalize(tng_data, TNG_USE_HASH);
8924 fclose(tng_data->output_file);
8925 tng_data->output_file = 0;
8928 if(tng_data->output_file_path)
8930 free(tng_data->output_file_path);
8931 tng_data->output_file_path = 0;
8934 if(tng_data->first_program_name)
8936 free(tng_data->first_program_name);
8937 tng_data->first_program_name = 0;
8940 if(tng_data->last_program_name)
8942 free(tng_data->last_program_name);
8943 tng_data->last_program_name = 0;
8946 if(tng_data->first_user_name)
8948 free(tng_data->first_user_name);
8949 tng_data->first_user_name = 0;
8952 if(tng_data->last_user_name)
8954 free(tng_data->last_user_name);
8955 tng_data->last_user_name = 0;
8958 if(tng_data->first_computer_name)
8960 free(tng_data->first_computer_name);
8961 tng_data->first_computer_name = 0;
8964 if(tng_data->last_computer_name)
8966 free(tng_data->last_computer_name);
8967 tng_data->last_computer_name = 0;
8970 if(tng_data->first_pgp_signature)
8972 free(tng_data->first_pgp_signature);
8973 tng_data->first_pgp_signature = 0;
8976 if(tng_data->last_pgp_signature)
8978 free(tng_data->last_pgp_signature);
8979 tng_data->last_pgp_signature = 0;
8982 if(tng_data->forcefield_name)
8984 free(tng_data->forcefield_name);
8985 tng_data->forcefield_name = 0;
8988 tng_frame_set_particle_mapping_free(tng_data);
8990 if(frame_set->molecule_cnt_list)
8992 free(frame_set->molecule_cnt_list);
8993 frame_set->molecule_cnt_list = 0;
8996 if(tng_data->var_num_atoms_flag)
8998 n_particles = frame_set->n_particles;
9002 n_particles = tng_data->n_particles;
9005 if(tng_data->non_tr_particle_data)
9007 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
9009 if(tng_data->non_tr_particle_data[i].values)
9011 free(tng_data->non_tr_particle_data[i].values);
9012 tng_data->non_tr_particle_data[i].values = 0;
9015 if(tng_data->non_tr_particle_data[i].strings)
9017 n_values_per_frame = tng_data->non_tr_particle_data[i].
9019 if(tng_data->non_tr_particle_data[i].strings[0])
9021 for(j = 0; j < n_particles; j++)
9023 if(tng_data->non_tr_particle_data[i].strings[0][j])
9025 for(k = 0; k < n_values_per_frame; k++)
9027 if(tng_data->non_tr_particle_data[i].
9030 free(tng_data->non_tr_particle_data[i].
9032 tng_data->non_tr_particle_data[i].
9033 strings[0][j][k] = 0;
9036 free(tng_data->non_tr_particle_data[i].
9038 tng_data->non_tr_particle_data[i].strings[0][j] = 0;
9041 free(tng_data->non_tr_particle_data[i].strings[0]);
9042 tng_data->non_tr_particle_data[i].strings[0] = 0;
9044 free(tng_data->non_tr_particle_data[i].strings);
9045 tng_data->non_tr_particle_data[i].strings = 0;
9048 if(tng_data->non_tr_particle_data[i].block_name)
9050 free(tng_data->non_tr_particle_data[i].block_name);
9051 tng_data->non_tr_particle_data[i].block_name = 0;
9054 free(tng_data->non_tr_particle_data);
9055 tng_data->non_tr_particle_data = 0;
9058 if(tng_data->non_tr_data)
9060 for(i = 0; i < tng_data->n_data_blocks; i++)
9062 if(tng_data->non_tr_data[i].values)
9064 free(tng_data->non_tr_data[i].values);
9065 tng_data->non_tr_data[i].values = 0;
9068 if(tng_data->non_tr_data[i].strings)
9070 n_values_per_frame = tng_data->non_tr_data[i].
9072 if(tng_data->non_tr_data[i].strings[0][0])
9074 for(j = 0; j < n_values_per_frame; j++)
9076 if(tng_data->non_tr_data[i].strings[0][0][j])
9078 free(tng_data->non_tr_data[i].strings[0][0][j]);
9079 tng_data->non_tr_data[i].strings[0][0][j] = 0;
9082 free(tng_data->non_tr_data[i].strings[0][0]);
9083 tng_data->non_tr_data[i].strings[0][0] = 0;
9085 free(tng_data->non_tr_data[i].strings[0]);
9086 tng_data->non_tr_data[i].strings[0] = 0;
9087 free(tng_data->non_tr_data[i].strings);
9088 tng_data->non_tr_data[i].strings = 0;
9091 if(tng_data->non_tr_data[i].block_name)
9093 free(tng_data->non_tr_data[i].block_name);
9094 tng_data->non_tr_data[i].block_name = 0;
9097 free(tng_data->non_tr_data);
9098 tng_data->non_tr_data = 0;
9101 tng_data->n_particle_data_blocks = 0;
9102 tng_data->n_data_blocks = 0;
9104 if(tng_data->compress_algo_pos)
9106 free(tng_data->compress_algo_pos);
9107 tng_data->compress_algo_pos = 0;
9109 if(tng_data->compress_algo_vel)
9111 free(tng_data->compress_algo_vel);
9112 tng_data->compress_algo_vel = 0;
9115 if(frame_set->tr_particle_data)
9117 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
9119 if(frame_set->tr_particle_data[i].values)
9121 free(frame_set->tr_particle_data[i].values);
9122 frame_set->tr_particle_data[i].values = 0;
9125 if(frame_set->tr_particle_data[i].strings)
9127 n_values_per_frame = frame_set->tr_particle_data[i].
9129 for(j = 0; j < frame_set->tr_particle_data[i].n_frames; j++)
9131 if(frame_set->tr_particle_data[i].strings[j])
9133 for(k = 0; k < n_particles; k++)
9135 if(frame_set->tr_particle_data[i].
9138 for(l = 0; l < n_values_per_frame; l++)
9140 if(frame_set->tr_particle_data[i].
9143 free(frame_set->tr_particle_data[i].
9145 frame_set->tr_particle_data[i].
9146 strings[j][k][l] = 0;
9149 free(frame_set->tr_particle_data[i].
9151 frame_set->tr_particle_data[i].
9155 free(frame_set->tr_particle_data[i].strings[j]);
9156 frame_set->tr_particle_data[i].strings[j] = 0;
9159 free(frame_set->tr_particle_data[i].strings);
9160 frame_set->tr_particle_data[i].strings = 0;
9163 if(frame_set->tr_particle_data[i].block_name)
9165 free(frame_set->tr_particle_data[i].block_name);
9166 frame_set->tr_particle_data[i].block_name = 0;
9169 free(frame_set->tr_particle_data);
9170 frame_set->tr_particle_data = 0;
9173 if(frame_set->tr_data)
9175 for(i = 0; i < frame_set->n_data_blocks; i++)
9177 if(frame_set->tr_data[i].values)
9179 free(frame_set->tr_data[i].values);
9180 frame_set->tr_data[i].values = 0;
9183 if(frame_set->tr_data[i].strings)
9185 n_values_per_frame = frame_set->tr_data[i].
9187 for(j = 0; j < frame_set->tr_data[i].n_frames; j++)
9189 if(frame_set->tr_data[i].strings[j])
9191 for(k = 0; k < n_values_per_frame; k++)
9193 if(frame_set->tr_data[i].strings[j][k])
9195 free(frame_set->tr_data[i].strings[j][k]);
9196 frame_set->tr_data[i].strings[j][k] = 0;
9199 free(frame_set->tr_data[i].strings[j]);
9200 frame_set->tr_data[i].strings[j] = 0;
9203 free(frame_set->tr_data[i].strings);
9204 frame_set->tr_data[i].strings = 0;
9207 if(frame_set->tr_data[i].block_name)
9209 free(frame_set->tr_data[i].block_name);
9210 frame_set->tr_data[i].block_name = 0;
9213 free(frame_set->tr_data);
9214 frame_set->tr_data = 0;
9217 frame_set->n_particle_data_blocks = 0;
9218 frame_set->n_data_blocks = 0;
9220 if(tng_data->molecules)
9222 for(i = 0; i < tng_data->n_molecules; i++)
9224 tng_molecule_destroy(tng_data, &tng_data->molecules[i]);
9226 free(tng_data->molecules);
9227 tng_data->molecules = 0;
9228 tng_data->n_molecules = 0;
9230 if(tng_data->molecule_cnt_list)
9232 free(tng_data->molecule_cnt_list);
9233 tng_data->molecule_cnt_list = 0;
9239 return(TNG_SUCCESS);
9242 tng_function_status DECLSPECDLLEXPORT tng_trajectory_init_from_src
9243 (const tng_trajectory_t src,
9244 tng_trajectory_t *dest_p)
9246 tng_trajectory_frame_set_t frame_set;
9247 tng_trajectory_t dest;
9249 TNG_ASSERT(src != 0, "TNG library: Source trajectory must not be NULL.");
9251 *dest_p = (tng_trajectory_t)malloc(sizeof(struct tng_trajectory));
9254 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
9255 __FILE__, __LINE__);
9256 return(TNG_CRITICAL);
9261 frame_set = &dest->current_trajectory_frame_set;
9263 if(src->input_file_path)
9265 dest->input_file_path = (char *)malloc(strlen(src->input_file_path) + 1);
9266 if(!dest->input_file_path)
9268 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
9269 __FILE__, __LINE__);
9270 return(TNG_CRITICAL);
9272 strcpy(dest->input_file_path, src->input_file_path);
9273 dest->input_file_len = src->input_file_len;
9277 dest->input_file_path = 0;
9279 dest->input_file = 0;
9280 if(src->output_file_path)
9282 dest->output_file_path = (char *)malloc(strlen(src->output_file_path) + 1);
9283 if(!dest->output_file_path)
9285 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
9286 __FILE__, __LINE__);
9287 return(TNG_CRITICAL);
9289 strcpy(dest->output_file_path, src->output_file_path);
9293 dest->output_file_path = 0;
9295 dest->output_file = 0;
9297 dest->first_program_name = 0;
9298 dest->first_user_name = 0;
9299 dest->first_computer_name = 0;
9300 dest->first_pgp_signature = 0;
9301 dest->last_program_name = 0;
9302 dest->last_user_name = 0;
9303 dest->last_computer_name = 0;
9304 dest->last_pgp_signature = 0;
9305 dest->forcefield_name = 0;
9307 dest->var_num_atoms_flag = src->var_num_atoms_flag;
9308 dest->first_trajectory_frame_set_input_file_pos =
9309 src->first_trajectory_frame_set_input_file_pos;
9310 dest->last_trajectory_frame_set_input_file_pos =
9311 src->last_trajectory_frame_set_input_file_pos;
9312 dest->current_trajectory_frame_set_input_file_pos =
9313 src->current_trajectory_frame_set_input_file_pos;
9314 dest->first_trajectory_frame_set_output_file_pos =
9315 src->first_trajectory_frame_set_output_file_pos;
9316 dest->last_trajectory_frame_set_output_file_pos =
9317 src->last_trajectory_frame_set_output_file_pos;
9318 dest->current_trajectory_frame_set_output_file_pos =
9319 src->current_trajectory_frame_set_output_file_pos;
9320 dest->frame_set_n_frames = src->frame_set_n_frames;
9321 dest->n_trajectory_frame_sets = src->n_trajectory_frame_sets;
9322 dest->medium_stride_length = src->medium_stride_length;
9323 dest->long_stride_length = src->long_stride_length;
9325 dest->time_per_frame = src->time_per_frame;
9327 /* Currently the non trajectory data blocks are not copied since it
9328 * can lead to problems when freeing memory in a parallel block. */
9329 dest->n_particle_data_blocks = 0;
9330 dest->n_data_blocks = 0;
9331 dest->non_tr_particle_data = 0;
9332 dest->non_tr_data = 0;
9334 dest->compress_algo_pos = 0;
9335 dest->compress_algo_vel = 0;
9336 dest->distance_unit_exponential = -9;
9337 dest->compression_precision = 1000;
9339 frame_set->n_mapping_blocks = 0;
9340 frame_set->mappings = 0;
9341 frame_set->molecule_cnt_list = 0;
9343 frame_set->n_particle_data_blocks = 0;
9344 frame_set->n_data_blocks = 0;
9346 frame_set->tr_particle_data = 0;
9347 frame_set->tr_data = 0;
9349 frame_set->n_written_frames = 0;
9350 frame_set->n_unwritten_frames = 0;
9352 frame_set->next_frame_set_file_pos = -1;
9353 frame_set->prev_frame_set_file_pos = -1;
9354 frame_set->medium_stride_next_frame_set_file_pos = -1;
9355 frame_set->medium_stride_prev_frame_set_file_pos = -1;
9356 frame_set->long_stride_next_frame_set_file_pos = -1;
9357 frame_set->long_stride_prev_frame_set_file_pos = -1;
9358 frame_set->first_frame = -1;
9360 dest->n_molecules = 0;
9361 dest->molecules = 0;
9362 dest->molecule_cnt_list = 0;
9363 dest->n_particles = src->n_particles;
9365 dest->endianness_32 = src->endianness_32;
9366 dest->endianness_64 = src->endianness_64;
9367 dest->input_endianness_swap_func_32 = src->input_endianness_swap_func_32;
9368 dest->input_endianness_swap_func_64 = src->input_endianness_swap_func_64;
9369 dest->output_endianness_swap_func_32 = src->output_endianness_swap_func_32;
9370 dest->output_endianness_swap_func_64 = src->output_endianness_swap_func_64;
9372 dest->current_trajectory_frame_set.next_frame_set_file_pos = -1;
9373 dest->current_trajectory_frame_set.prev_frame_set_file_pos = -1;
9374 dest->current_trajectory_frame_set.n_frames = 0;
9376 return(TNG_SUCCESS);
9379 tng_function_status DECLSPECDLLEXPORT tng_input_file_get
9380 (const tng_trajectory_t tng_data,
9384 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9385 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
9387 strncpy(file_name, tng_data->input_file_path, max_len - 1);
9388 file_name[max_len - 1] = 0;
9390 if(strlen(tng_data->input_file_path) > (unsigned int)max_len - 1)
9392 return(TNG_FAILURE);
9394 return(TNG_SUCCESS);
9397 tng_function_status DECLSPECDLLEXPORT tng_input_file_set
9398 (const tng_trajectory_t tng_data,
9399 const char *file_name)
9404 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9405 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
9408 if(tng_data->input_file_path && strcmp(tng_data->input_file_path,
9411 return(TNG_SUCCESS);
9414 if(tng_data->input_file)
9416 fclose(tng_data->input_file);
9419 len = tng_min_size(strlen(file_name) + 1, TNG_MAX_STR_LEN);
9420 temp = (char *)realloc(tng_data->input_file_path, len);
9423 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
9424 __FILE__, __LINE__);
9425 free(tng_data->input_file_path);
9426 tng_data->input_file_path = 0;
9427 return(TNG_CRITICAL);
9429 tng_data->input_file_path = temp;
9431 strncpy(tng_data->input_file_path, file_name, len);
9433 return(tng_input_file_init(tng_data));
9436 tng_function_status tng_output_file_get
9437 (const tng_trajectory_t tng_data,
9441 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9442 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
9444 strncpy(file_name, tng_data->output_file_path, max_len - 1);
9445 file_name[max_len - 1] = 0;
9447 if(strlen(tng_data->output_file_path) > (unsigned int)max_len - 1)
9449 return(TNG_FAILURE);
9451 return(TNG_SUCCESS);
9454 tng_function_status DECLSPECDLLEXPORT tng_output_file_set
9455 (const tng_trajectory_t tng_data,
9456 const char *file_name)
9461 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9462 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
9464 if(tng_data->output_file_path &&
9465 strcmp(tng_data->output_file_path, file_name) == 0)
9467 return(TNG_SUCCESS);
9470 if(tng_data->output_file)
9472 fclose(tng_data->output_file);
9475 len = tng_min_size(strlen(file_name) + 1, TNG_MAX_STR_LEN);
9476 temp = (char *)realloc(tng_data->output_file_path, len);
9479 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
9480 __FILE__, __LINE__);
9481 free(tng_data->output_file_path);
9482 tng_data->output_file_path = 0;
9483 return(TNG_CRITICAL);
9485 tng_data->output_file_path = temp;
9487 strncpy(tng_data->output_file_path, file_name, len);
9489 return(tng_output_file_init(tng_data));
9492 tng_function_status DECLSPECDLLEXPORT tng_output_append_file_set
9493 (const tng_trajectory_t tng_data,
9494 const char *file_name)
9499 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9500 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
9502 if(tng_data->output_file_path &&
9503 strcmp(tng_data->output_file_path, file_name) == 0)
9505 return(TNG_SUCCESS);
9508 if(tng_data->output_file)
9510 fclose(tng_data->output_file);
9513 len = tng_min_size(strlen(file_name) + 1, TNG_MAX_STR_LEN);
9514 temp = (char *)realloc(tng_data->output_file_path, len);
9517 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
9518 __FILE__, __LINE__);
9519 free(tng_data->output_file_path);
9520 tng_data->output_file_path = 0;
9521 return(TNG_CRITICAL);
9523 tng_data->output_file_path = temp;
9525 strncpy(tng_data->output_file_path, file_name, len);
9527 tng_data->output_file = fopen(tng_data->output_file_path, "rb+");
9528 if(!tng_data->output_file)
9530 fprintf(stderr, "TNG library: Cannot open file %s. %s: %d\n",
9531 tng_data->output_file_path, __FILE__, __LINE__);
9532 return(TNG_CRITICAL);
9534 tng_data->input_file = tng_data->output_file;
9536 return(TNG_SUCCESS);
9539 tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_get
9540 (const tng_trajectory_t tng_data, tng_file_endianness *endianness)
9542 tng_endianness_32 end_32;
9543 tng_endianness_64 end_64;
9545 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9546 TNG_ASSERT(endianness, "TNG library: endianness must not be a NULL pointer");
9548 if(tng_data->output_endianness_swap_func_32)
9550 /* If other endianness variants are added they must be added here as well */
9551 if(tng_data->output_endianness_swap_func_32 ==
9552 &tng_swap_byte_order_big_endian_32)
9554 end_32 = TNG_BIG_ENDIAN_32;
9556 else if(tng_data->output_endianness_swap_func_32 ==
9557 &tng_swap_byte_order_little_endian_32)
9559 end_32 = TNG_LITTLE_ENDIAN_32;
9563 return(TNG_FAILURE);
9568 end_32 = (tng_endianness_32)tng_data->endianness_32;
9571 if(tng_data->output_endianness_swap_func_64)
9573 /* If other endianness variants are added they must be added here as well */
9574 if(tng_data->output_endianness_swap_func_64 ==
9575 &tng_swap_byte_order_big_endian_64)
9577 end_64 = TNG_BIG_ENDIAN_64;
9579 else if(tng_data->output_endianness_swap_func_64 ==
9580 &tng_swap_byte_order_little_endian_64)
9582 end_64 = TNG_LITTLE_ENDIAN_64;
9586 return(TNG_FAILURE);
9591 end_64 = (tng_endianness_64)tng_data->endianness_64;
9594 if((int)end_32 != (int)end_64)
9596 return(TNG_FAILURE);
9599 if(end_32 == TNG_LITTLE_ENDIAN_32)
9601 *endianness = TNG_LITTLE_ENDIAN;
9604 else if(end_32 == TNG_BIG_ENDIAN_32)
9606 *endianness = TNG_BIG_ENDIAN;
9610 return(TNG_FAILURE);
9613 return(TNG_SUCCESS);
9616 tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_set
9617 (const tng_trajectory_t tng_data,
9618 const tng_file_endianness endianness)
9620 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9622 /* Tne endianness cannot be changed if the data has already been written
9623 * to the output file. */
9624 if(ftello(tng_data->output_file) > 0)
9626 return(TNG_FAILURE);
9629 if(endianness == TNG_BIG_ENDIAN)
9631 if(tng_data->endianness_32 == TNG_BIG_ENDIAN_32)
9633 tng_data->output_endianness_swap_func_32 = 0;
9637 tng_data->output_endianness_swap_func_32 =
9638 &tng_swap_byte_order_big_endian_32;
9640 if(tng_data->endianness_64 == TNG_BIG_ENDIAN_64)
9642 tng_data->output_endianness_swap_func_64 = 0;
9646 tng_data->output_endianness_swap_func_64 =
9647 &tng_swap_byte_order_big_endian_64;
9649 return(TNG_SUCCESS);
9651 else if(endianness == TNG_LITTLE_ENDIAN)
9653 if(tng_data->endianness_32 == TNG_LITTLE_ENDIAN_32)
9655 tng_data->output_endianness_swap_func_32 = 0;
9659 tng_data->output_endianness_swap_func_32 =
9660 &tng_swap_byte_order_little_endian_32;
9662 if(tng_data->endianness_64 == TNG_LITTLE_ENDIAN_64)
9664 tng_data->output_endianness_swap_func_64 = 0;
9668 tng_data->output_endianness_swap_func_64 =
9669 &tng_swap_byte_order_little_endian_64;
9671 return(TNG_SUCCESS);
9674 /* If the specified endianness is neither big nor little endian return a
9676 return(TNG_FAILURE);
9679 tng_function_status DECLSPECDLLEXPORT tng_first_program_name_get
9680 (const tng_trajectory_t tng_data,
9684 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9685 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
9687 strncpy(name, tng_data->first_program_name, max_len - 1);
9688 name[max_len - 1] = 0;
9690 if(strlen(tng_data->first_program_name) > (unsigned int)max_len - 1)
9692 return(TNG_FAILURE);
9694 return(TNG_SUCCESS);
9697 tng_function_status DECLSPECDLLEXPORT tng_first_program_name_set
9698 (const tng_trajectory_t tng_data,
9699 const char *new_name)
9703 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9704 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
9706 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
9708 if(tng_data->first_program_name && strlen(tng_data->first_program_name) < len)
9710 free(tng_data->first_program_name);
9711 tng_data->first_program_name = 0;
9713 if(!tng_data->first_program_name)
9715 tng_data->first_program_name = (char *)malloc(len);
9716 if(!tng_data->first_program_name)
9718 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
9719 __FILE__, __LINE__);
9720 return(TNG_CRITICAL);
9724 strncpy(tng_data->first_program_name, new_name, len);
9726 return(TNG_SUCCESS);
9729 tng_function_status DECLSPECDLLEXPORT tng_last_program_name_get
9730 (const tng_trajectory_t tng_data,
9731 char *name, const int max_len)
9733 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9734 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
9736 strncpy(name, tng_data->last_program_name, max_len - 1);
9737 name[max_len - 1] = 0;
9739 if(strlen(tng_data->last_program_name) > (unsigned int)max_len - 1)
9741 return(TNG_FAILURE);
9743 return(TNG_SUCCESS);
9746 tng_function_status DECLSPECDLLEXPORT tng_last_program_name_set
9747 (const tng_trajectory_t tng_data,
9748 const char *new_name)
9752 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9753 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
9755 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
9757 if(tng_data->last_program_name && strlen(tng_data->last_program_name) < len)
9759 free(tng_data->last_program_name);
9760 tng_data->last_program_name = 0;
9762 if(!tng_data->last_program_name)
9764 tng_data->last_program_name = (char *)malloc(len);
9765 if(!tng_data->last_program_name)
9767 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
9768 __FILE__, __LINE__);
9769 return(TNG_CRITICAL);
9773 strncpy(tng_data->last_program_name, new_name, len);
9775 return(TNG_SUCCESS);
9778 tng_function_status DECLSPECDLLEXPORT tng_first_user_name_get
9779 (const tng_trajectory_t tng_data,
9780 char *name, const int max_len)
9782 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9783 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
9785 strncpy(name, tng_data->first_user_name, max_len - 1);
9786 name[max_len - 1] = 0;
9788 if(strlen(tng_data->first_user_name) > (unsigned int)max_len - 1)
9790 return(TNG_FAILURE);
9792 return(TNG_SUCCESS);
9795 tng_function_status DECLSPECDLLEXPORT tng_first_user_name_set
9796 (const tng_trajectory_t tng_data,
9797 const char *new_name)
9801 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9802 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
9804 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
9806 /* If the currently stored string length is not enough to store the new
9807 * string it is freed and reallocated. */
9808 if(tng_data->first_user_name && strlen(tng_data->first_user_name) < len)
9810 free(tng_data->first_user_name);
9811 tng_data->first_user_name = 0;
9813 if(!tng_data->first_user_name)
9815 tng_data->first_user_name = (char *)malloc(len);
9816 if(!tng_data->first_user_name)
9818 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
9819 __FILE__, __LINE__);
9820 return(TNG_CRITICAL);
9824 strncpy(tng_data->first_user_name, new_name, len);
9826 return(TNG_SUCCESS);
9829 tng_function_status DECLSPECDLLEXPORT tng_last_user_name_get
9830 (const tng_trajectory_t tng_data,
9831 char *name, const int max_len)
9833 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9834 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
9836 strncpy(name, tng_data->last_user_name, max_len - 1);
9837 name[max_len - 1] = 0;
9839 if(strlen(tng_data->last_user_name) > (unsigned int)max_len - 1)
9841 return(TNG_FAILURE);
9843 return(TNG_SUCCESS);
9846 tng_function_status DECLSPECDLLEXPORT tng_last_user_name_set
9847 (const tng_trajectory_t tng_data,
9848 const char *new_name)
9852 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9853 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
9855 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
9857 /* If the currently stored string length is not enough to store the new
9858 * string it is freed and reallocated. */
9859 if(tng_data->last_user_name && strlen(tng_data->last_user_name) < len)
9861 free(tng_data->last_user_name);
9862 tng_data->last_user_name = 0;
9864 if(!tng_data->last_user_name)
9866 tng_data->last_user_name = (char *)malloc(len);
9867 if(!tng_data->last_user_name)
9869 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
9870 __FILE__, __LINE__);
9871 return(TNG_CRITICAL);
9875 strncpy(tng_data->last_user_name, new_name, len);
9877 return(TNG_SUCCESS);
9880 tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_get
9881 (const tng_trajectory_t tng_data,
9882 char *name, const int max_len)
9884 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9885 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
9887 strncpy(name, tng_data->first_computer_name, max_len - 1);
9888 name[max_len - 1] = 0;
9890 if(strlen(tng_data->first_computer_name) > (unsigned int)max_len - 1)
9892 return(TNG_FAILURE);
9894 return(TNG_SUCCESS);
9897 tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_set
9898 (const tng_trajectory_t tng_data,
9899 const char *new_name)
9903 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9904 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
9906 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
9908 /* If the currently stored string length is not enough to store the new
9909 * string it is freed and reallocated. */
9910 if(tng_data->first_computer_name && strlen(tng_data->first_computer_name) < len)
9912 free(tng_data->first_computer_name);
9913 tng_data->first_computer_name = 0;
9915 if(!tng_data->first_computer_name)
9917 tng_data->first_computer_name = (char *)malloc(len);
9918 if(!tng_data->first_computer_name)
9920 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
9921 __FILE__, __LINE__);
9922 return(TNG_CRITICAL);
9926 strncpy(tng_data->first_computer_name, new_name, len);
9928 return(TNG_SUCCESS);
9931 tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_get
9932 (const tng_trajectory_t tng_data,
9933 char *name, const int max_len)
9935 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9936 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
9938 strncpy(name, tng_data->last_computer_name, max_len - 1);
9939 name[max_len - 1] = 0;
9941 if(strlen(tng_data->last_computer_name) > (unsigned int)max_len - 1)
9943 return(TNG_FAILURE);
9945 return(TNG_SUCCESS);
9948 tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_set
9949 (const tng_trajectory_t tng_data,
9950 const char *new_name)
9954 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9955 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
9957 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
9959 /* If the currently stored string length is not enough to store the new
9960 * string it is freed and reallocated. */
9961 if(tng_data->last_computer_name && strlen(tng_data->last_computer_name) <
9964 free(tng_data->last_computer_name);
9965 tng_data->last_computer_name = 0;
9967 if(!tng_data->last_computer_name)
9969 tng_data->last_computer_name = (char *)malloc(len);
9970 if(!tng_data->last_computer_name)
9972 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
9973 __FILE__, __LINE__);
9974 return(TNG_CRITICAL);
9978 strncpy(tng_data->last_computer_name, new_name, len);
9980 return(TNG_SUCCESS);
9983 tng_function_status DECLSPECDLLEXPORT tng_first_signature_get
9984 (const tng_trajectory_t tng_data,
9985 char *signature, const int max_len)
9987 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9988 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
9990 strncpy(signature, tng_data->first_pgp_signature, max_len - 1);
9991 signature[max_len - 1] = 0;
9993 if(strlen(tng_data->first_pgp_signature) > (unsigned int)max_len - 1)
9995 return(TNG_FAILURE);
9997 return(TNG_SUCCESS);
10000 tng_function_status DECLSPECDLLEXPORT tng_first_signature_set
10001 (const tng_trajectory_t tng_data,
10002 const char *signature)
10006 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10007 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
10009 len = tng_min_size(strlen(signature) + 1, TNG_MAX_STR_LEN);
10011 /* If the currently stored string length is not enough to store the new
10012 * string it is freed and reallocated. */
10013 if(tng_data->first_pgp_signature && strlen(tng_data->first_pgp_signature) <
10016 free(tng_data->first_pgp_signature);
10017 tng_data->first_pgp_signature = 0;
10019 if(!tng_data->first_pgp_signature)
10021 tng_data->first_pgp_signature = (char *)malloc(len);
10022 if(!tng_data->first_pgp_signature)
10024 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
10025 __FILE__, __LINE__);
10026 return(TNG_CRITICAL);
10030 strncpy(tng_data->first_pgp_signature, signature, len);
10032 return(TNG_SUCCESS);
10035 tng_function_status DECLSPECDLLEXPORT tng_last_signature_get
10036 (const tng_trajectory_t tng_data,
10037 char *signature, const int max_len)
10039 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10040 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
10042 strncpy(signature, tng_data->last_pgp_signature, max_len - 1);
10043 signature[max_len - 1] = 0;
10045 if(strlen(tng_data->last_pgp_signature) > (unsigned int)max_len - 1)
10047 return(TNG_FAILURE);
10049 return(TNG_SUCCESS);
10052 tng_function_status DECLSPECDLLEXPORT tng_last_signature_set
10053 (const tng_trajectory_t tng_data,
10054 const char *signature)
10058 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10059 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
10061 len = tng_min_size(strlen(signature) + 1, TNG_MAX_STR_LEN);
10063 /* If the currently stored string length is not enough to store the new
10064 * string it is freed and reallocated. */
10065 if(tng_data->last_pgp_signature && strlen(tng_data->last_pgp_signature) <
10068 free(tng_data->last_pgp_signature);
10069 tng_data->last_pgp_signature = 0;
10071 if(!tng_data->last_pgp_signature)
10073 tng_data->last_pgp_signature = (char *)malloc(len);
10074 if(!tng_data->last_pgp_signature)
10076 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
10077 __FILE__, __LINE__);
10078 return(TNG_CRITICAL);
10082 strncpy(tng_data->last_pgp_signature, signature, len);
10084 return(TNG_SUCCESS);
10087 tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_get
10088 (const tng_trajectory_t tng_data,
10089 char *name, const int max_len)
10091 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10092 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10094 strncpy(name, tng_data->forcefield_name, max_len - 1);
10095 name[max_len - 1] = 0;
10097 if(strlen(tng_data->forcefield_name) > (unsigned int)max_len - 1)
10099 return(TNG_FAILURE);
10101 return(TNG_SUCCESS);
10104 tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_set
10105 (const tng_trajectory_t tng_data,
10106 const char *new_name)
10110 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10111 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10113 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
10115 /* If the currently stored string length is not enough to store the new
10116 * string it is freed and reallocated. */
10117 if(tng_data->forcefield_name && strlen(tng_data->forcefield_name) < len)
10119 free(tng_data->forcefield_name);
10120 tng_data->forcefield_name = 0;
10122 if(!tng_data->forcefield_name)
10124 tng_data->forcefield_name = (char *)malloc(len);
10125 if(!tng_data->forcefield_name)
10127 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
10128 __FILE__, __LINE__);
10129 return(TNG_CRITICAL);
10133 strncpy(tng_data->forcefield_name, new_name, len);
10135 return(TNG_SUCCESS);
10138 tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_get
10139 (const tng_trajectory_t tng_data,
10142 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10143 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
10145 *len = tng_data->medium_stride_length;
10147 return(TNG_SUCCESS);
10150 tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_set
10151 (const tng_trajectory_t tng_data,
10154 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10156 if(len >= tng_data->long_stride_length)
10158 return(TNG_FAILURE);
10160 tng_data->medium_stride_length = len;
10162 return(TNG_SUCCESS);
10165 tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_get
10166 (const tng_trajectory_t tng_data,
10169 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10170 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
10172 *len = tng_data->long_stride_length;
10174 return(TNG_SUCCESS);
10177 tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_set
10178 (const tng_trajectory_t tng_data,
10181 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10183 if(len <= tng_data->medium_stride_length)
10185 return(TNG_FAILURE);
10187 tng_data->long_stride_length = len;
10189 return(TNG_SUCCESS);
10192 tng_function_status DECLSPECDLLEXPORT tng_time_per_frame_get
10193 (const tng_trajectory_t tng_data,
10196 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10197 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
10199 *time = tng_data->time_per_frame;
10201 return(TNG_SUCCESS);
10204 tng_function_status DECLSPECDLLEXPORT tng_time_per_frame_set
10205 (const tng_trajectory_t tng_data,
10208 tng_trajectory_frame_set_t frame_set;
10210 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10211 TNG_ASSERT(time >= 0, "TNG library: The time per frame must be >= 0.");
10213 if(fabs(time - tng_data->time_per_frame) < 0.00001)
10215 return(TNG_SUCCESS);
10218 frame_set = &tng_data->current_trajectory_frame_set;
10220 /* If the current frame set is not finished write it to disk before
10221 changing time per frame. */
10222 if(tng_data->time_per_frame > 0 && frame_set->n_unwritten_frames > 0)
10224 frame_set->n_frames = frame_set->n_unwritten_frames;
10225 tng_frame_set_write(tng_data, TNG_USE_HASH);
10227 tng_data->time_per_frame = time;
10229 return(TNG_SUCCESS);
10232 tng_function_status DECLSPECDLLEXPORT tng_input_file_len_get
10233 (const tng_trajectory_t tng_data,
10236 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10237 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
10239 *len = tng_data->input_file_len;
10241 return(TNG_SUCCESS);
10244 tng_function_status DECLSPECDLLEXPORT tng_num_frames_get
10245 (const tng_trajectory_t tng_data,
10248 tng_gen_block_t block;
10249 tng_function_status stat;
10250 int64_t file_pos, last_file_pos, first_frame, n_frames;
10252 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10253 TNG_ASSERT(tng_data->input_file, "TNG library: An input file must be open to find the next frame set");
10254 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10256 file_pos = ftello(tng_data->input_file);
10257 last_file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
10259 if(last_file_pos <= 0)
10261 return(TNG_FAILURE);
10264 tng_block_init(&block);
10265 fseeko(tng_data->input_file,
10268 /* Read block headers first to see that a frame set block is found. */
10269 stat = tng_block_header_read(tng_data, block);
10270 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10272 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n", last_file_pos,
10273 __FILE__, __LINE__);
10274 tng_block_destroy(&block);
10275 return(TNG_FAILURE);
10277 tng_block_destroy(&block);
10279 if(tng_file_input_numerical(tng_data, &first_frame,
10280 sizeof(first_frame),
10281 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
10283 return(TNG_CRITICAL);
10286 if(tng_file_input_numerical(tng_data, &n_frames,
10288 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
10290 return(TNG_CRITICAL);
10293 fseeko(tng_data->input_file, file_pos, SEEK_SET);
10295 *n = first_frame + n_frames;
10297 return(TNG_SUCCESS);
10300 tng_function_status DECLSPECDLLEXPORT tng_compression_precision_get
10301 (const tng_trajectory_t tng_data,
10304 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10306 *precision = tng_data->compression_precision;
10308 return(TNG_SUCCESS);
10311 tng_function_status DECLSPECDLLEXPORT tng_compression_precision_set
10312 (const tng_trajectory_t tng_data,
10313 const double precision)
10315 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10317 tng_data->compression_precision = precision;
10319 return(TNG_SUCCESS);
10322 tng_function_status DECLSPECDLLEXPORT tng_implicit_num_particles_set
10323 (const tng_trajectory_t tng_data,
10326 tng_molecule_t mol;
10330 tng_function_status stat;
10331 int64_t diff, n_mod, n_impl;
10333 TNG_ASSERT(n >= 0, "TNG library: The requested number of particles must be >= 0");
10335 diff = n - tng_data->n_particles;
10337 stat = tng_molecule_find(tng_data, "TNG_IMPLICIT_MOL", -1, &mol);
10338 if(stat == TNG_SUCCESS)
10340 if(tng_molecule_cnt_get(tng_data, mol, &n_impl) != TNG_SUCCESS)
10342 fprintf(stderr, "TNG library: Cannot get the number of implicit molecules. %s: %d\n",
10343 __FILE__, __LINE__);
10344 return(TNG_FAILURE);
10346 diff -= n_impl * mol->n_atoms;
10351 if(stat == TNG_SUCCESS)
10353 stat = tng_molecule_cnt_set(tng_data, mol, 0);
10356 return(TNG_SUCCESS);
10360 fprintf(stderr, "TNG library: Already more actual particles than requested implicit ");
10361 fprintf(stderr, "particle count.\n");
10362 fprintf(stderr, "TNG library: Cannot set implicit particle count. %s: %d\n",
10363 __FILE__, __LINE__);
10364 /* FIXME: Should we set the count of all other molecules to 0 and add
10365 * implicit molecules? */
10366 return(TNG_FAILURE);
10368 if(stat != TNG_SUCCESS)
10370 stat = tng_molecule_add(tng_data,
10371 "TNG_IMPLICIT_MOL",
10373 if(stat != TNG_SUCCESS)
10377 stat = tng_molecule_chain_add(tng_data, mol, "", &chain);
10378 if(stat != TNG_SUCCESS)
10382 stat = tng_chain_residue_add(tng_data, chain, "", &res);
10383 if(stat != TNG_SUCCESS)
10387 stat = tng_residue_atom_add(tng_data, res, "", "", &atom);
10388 if(stat != TNG_SUCCESS)
10395 if(mol->n_atoms > 1)
10397 n_mod = diff % mol->n_atoms;
10400 fprintf(stderr, "TNG library: Number of atoms in implicit molecule ");
10401 fprintf(stderr, "not compatible with requested implicit particle cnt.\n");
10402 fprintf(stderr, "TNG library: Cannot set implicit particle count. %s: %d\n",
10403 __FILE__, __LINE__);
10404 return(TNG_FAILURE);
10406 diff /= mol->n_atoms;
10409 stat = tng_molecule_cnt_set(tng_data, mol, diff);
10414 tng_function_status DECLSPECDLLEXPORT tng_num_particles_get
10415 (const tng_trajectory_t tng_data,
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 if(tng_data->var_num_atoms_flag == TNG_CONSTANT_N_ATOMS)
10423 *n = tng_data->n_particles;
10427 *n = tng_data->current_trajectory_frame_set.n_particles;
10430 return(TNG_SUCCESS);
10433 tng_function_status DECLSPECDLLEXPORT tng_num_particles_variable_get
10434 (const tng_trajectory_t tng_data,
10437 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10438 TNG_ASSERT(variable, "TNG library: variable must not be a NULL pointer");
10440 *variable = tng_data->var_num_atoms_flag;
10442 return(TNG_SUCCESS);
10445 tng_function_status DECLSPECDLLEXPORT tng_num_molecule_types_get
10446 (const tng_trajectory_t tng_data,
10449 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10450 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10452 *n = tng_data->n_molecules;
10454 return(TNG_SUCCESS);
10457 tng_function_status DECLSPECDLLEXPORT tng_num_molecules_get
10458 (const tng_trajectory_t tng_data,
10461 int64_t *cnt_list = 0, cnt = 0, i;
10463 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10464 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10466 tng_molecule_cnt_list_get(tng_data, &cnt_list);
10470 return(TNG_FAILURE);
10473 for(i = 0; i < tng_data->n_molecules; i++)
10475 cnt += cnt_list[i];
10480 return(TNG_SUCCESS);
10483 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_list_get
10484 (const tng_trajectory_t tng_data,
10485 int64_t **mol_cnt_list)
10487 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10489 if(tng_data->var_num_atoms_flag)
10491 *mol_cnt_list = tng_data->current_trajectory_frame_set.
10496 *mol_cnt_list = tng_data->molecule_cnt_list;
10498 if(*mol_cnt_list == 0)
10500 return(TNG_FAILURE);
10502 return(TNG_SUCCESS);
10505 tng_function_status DECLSPECDLLEXPORT tng_distance_unit_exponential_get
10506 (const tng_trajectory_t tng_data,
10509 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10510 TNG_ASSERT(exp, "TNG library: exp must not be a NULL pointer");
10512 *exp = tng_data->distance_unit_exponential;
10514 return(TNG_SUCCESS);
10517 tng_function_status DECLSPECDLLEXPORT tng_distance_unit_exponential_set
10518 (const tng_trajectory_t tng_data,
10521 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10523 tng_data->distance_unit_exponential = exp;
10525 return(TNG_SUCCESS);
10528 tng_function_status DECLSPECDLLEXPORT tng_num_frames_per_frame_set_get
10529 (const tng_trajectory_t tng_data,
10532 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10533 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10535 *n = tng_data->frame_set_n_frames;
10537 return(TNG_SUCCESS);
10540 tng_function_status DECLSPECDLLEXPORT tng_num_frames_per_frame_set_set
10541 (const tng_trajectory_t tng_data,
10544 tng_trajectory_frame_set_t frame_set;
10545 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10547 tng_data->frame_set_n_frames = n;
10548 frame_set = &tng_data->current_trajectory_frame_set;
10551 frame_set->n_frames = n;
10554 return(TNG_SUCCESS);
10557 tng_function_status DECLSPECDLLEXPORT tng_num_frame_sets_get
10558 (const tng_trajectory_t tng_data,
10561 int64_t long_stride_length, medium_stride_length;
10562 int64_t file_pos, orig_frame_set_file_pos;
10563 tng_trajectory_frame_set_t frame_set;
10564 struct tng_trajectory_frame_set orig_frame_set;
10565 tng_gen_block_t block;
10566 tng_function_status stat;
10569 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10570 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10572 orig_frame_set = tng_data->current_trajectory_frame_set;
10574 frame_set = &tng_data->current_trajectory_frame_set;
10576 orig_frame_set_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
10577 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
10581 *n = tng_data->n_trajectory_frame_sets = cnt;
10582 return(TNG_SUCCESS);
10585 tng_block_init(&block);
10586 fseeko(tng_data->input_file,
10589 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
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", file_pos,
10595 __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);
10609 long_stride_length = tng_data->long_stride_length;
10610 medium_stride_length = tng_data->medium_stride_length;
10612 /* Take long steps forward until a long step forward would be too long or
10613 * the last frame set is found */
10614 file_pos = frame_set->long_stride_next_frame_set_file_pos;
10615 while(file_pos > 0)
10619 cnt += long_stride_length;
10620 fseeko(tng_data->input_file, file_pos, 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->long_stride_next_frame_set_file_pos;
10641 /* Take medium steps forward until a medium step forward would be too long
10642 * or the last frame set is found */
10643 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
10644 while(file_pos > 0)
10648 cnt += medium_stride_length;
10649 fseeko(tng_data->input_file,
10652 /* Read block headers first to see what block is found. */
10653 stat = tng_block_header_read(tng_data, block);
10654 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10656 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
10657 file_pos, __FILE__, __LINE__);
10658 tng_block_destroy(&block);
10659 return(TNG_CRITICAL);
10662 if(tng_block_read_next(tng_data, block,
10663 TNG_SKIP_HASH) != TNG_SUCCESS)
10665 tng_block_destroy(&block);
10666 return(TNG_CRITICAL);
10669 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
10672 /* Take one step forward until the last frame set is found */
10673 file_pos = frame_set->next_frame_set_file_pos;
10674 while(file_pos > 0)
10679 fseeko(tng_data->input_file,
10682 /* Read block headers first to see what block is found. */
10683 stat = tng_block_header_read(tng_data, block);
10684 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10686 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
10687 file_pos, __FILE__, __LINE__);
10688 tng_block_destroy(&block);
10689 return(TNG_CRITICAL);
10692 if(tng_block_read_next(tng_data, block,
10693 TNG_SKIP_HASH) != TNG_SUCCESS)
10695 tng_block_destroy(&block);
10696 return(TNG_CRITICAL);
10699 file_pos = frame_set->next_frame_set_file_pos;
10702 tng_block_destroy(&block);
10704 *n = tng_data->n_trajectory_frame_sets = cnt;
10706 *frame_set = orig_frame_set;
10707 /* The mapping block in the original frame set has been freed when reading
10708 * other frame sets. */
10709 frame_set->mappings = 0;
10710 frame_set->n_mapping_blocks = 0;
10712 fseeko(tng_data->input_file,
10713 tng_data->first_trajectory_frame_set_input_file_pos,
10716 tng_data->current_trajectory_frame_set_input_file_pos = orig_frame_set_file_pos;
10718 return(TNG_SUCCESS);
10721 tng_function_status DECLSPECDLLEXPORT tng_current_frame_set_get
10722 (const tng_trajectory_t tng_data,
10723 tng_trajectory_frame_set_t *frame_set_p)
10725 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10727 *frame_set_p = &tng_data->current_trajectory_frame_set;
10729 return(TNG_SUCCESS);
10732 tng_function_status DECLSPECDLLEXPORT tng_frame_set_nr_find
10733 (const tng_trajectory_t tng_data,
10736 int64_t long_stride_length, medium_stride_length;
10737 int64_t file_pos, curr_nr = 0, n_frame_sets;
10738 tng_trajectory_frame_set_t frame_set;
10739 tng_gen_block_t block;
10740 tng_function_status stat;
10742 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10743 TNG_ASSERT(nr >= 0, "The frame set number (nr) must be >= 0");
10745 frame_set = &tng_data->current_trajectory_frame_set;
10747 stat = tng_num_frame_sets_get(tng_data, &n_frame_sets);
10749 if(stat != TNG_SUCCESS)
10754 if(nr >= n_frame_sets)
10756 return(TNG_FAILURE);
10759 long_stride_length = tng_data->long_stride_length;
10760 medium_stride_length = tng_data->medium_stride_length;
10762 /* FIXME: The frame set number of the current frame set is not stored */
10764 if(nr < n_frame_sets - 1 - nr)
10766 /* Start from the beginning */
10767 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
10771 /* Start from the end */
10772 file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
10773 curr_nr = n_frame_sets - 1;
10777 return(TNG_FAILURE);
10780 tng_block_init(&block);
10781 fseeko(tng_data->input_file,
10784 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
10785 /* Read block headers first to see what block is found. */
10786 stat = tng_block_header_read(tng_data, block);
10787 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10789 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n", file_pos,
10790 __FILE__, __LINE__);
10791 tng_block_destroy(&block);
10792 return(TNG_CRITICAL);
10795 if(tng_block_read_next(tng_data, block,
10796 TNG_SKIP_HASH) != TNG_SUCCESS)
10798 tng_block_destroy(&block);
10799 return(TNG_CRITICAL);
10804 tng_block_destroy(&block);
10805 return(TNG_SUCCESS);
10808 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
10810 /* Take long steps forward until a long step forward would be too long or
10811 * the right frame set is found */
10812 while(file_pos > 0 && curr_nr + long_stride_length <= nr)
10814 file_pos = frame_set->long_stride_next_frame_set_file_pos;
10817 curr_nr += long_stride_length;
10818 fseeko(tng_data->input_file, file_pos, SEEK_SET);
10819 /* Read block headers first to see what block is found. */
10820 stat = tng_block_header_read(tng_data, block);
10821 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10823 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
10824 file_pos, __FILE__, __LINE__);
10825 tng_block_destroy(&block);
10826 return(TNG_CRITICAL);
10829 if(tng_block_read_next(tng_data, block,
10830 TNG_SKIP_HASH) != TNG_SUCCESS)
10832 tng_block_destroy(&block);
10833 return(TNG_CRITICAL);
10837 tng_block_destroy(&block);
10838 return(TNG_SUCCESS);
10843 /* Take medium steps forward until a medium step forward would be too long
10844 * or the right frame set is found */
10845 while(file_pos > 0 && curr_nr + medium_stride_length <= nr)
10847 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
10850 curr_nr += medium_stride_length;
10851 fseeko(tng_data->input_file,
10854 /* Read block headers first to see what block is found. */
10855 stat = tng_block_header_read(tng_data, block);
10856 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10858 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
10859 file_pos, __FILE__, __LINE__);
10860 tng_block_destroy(&block);
10861 return(TNG_CRITICAL);
10864 if(tng_block_read_next(tng_data, block,
10865 TNG_SKIP_HASH) != TNG_SUCCESS)
10867 tng_block_destroy(&block);
10868 return(TNG_CRITICAL);
10872 tng_block_destroy(&block);
10873 return(TNG_SUCCESS);
10878 /* Take one step forward until the right frame set is found */
10879 while(file_pos > 0 && curr_nr < nr)
10881 file_pos = frame_set->next_frame_set_file_pos;
10886 fseeko(tng_data->input_file,
10889 /* Read block headers first to see what block is found. */
10890 stat = tng_block_header_read(tng_data, block);
10891 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10893 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
10894 file_pos, __FILE__, __LINE__);
10895 tng_block_destroy(&block);
10896 return(TNG_CRITICAL);
10899 if(tng_block_read_next(tng_data, block,
10900 TNG_SKIP_HASH) != TNG_SUCCESS)
10902 tng_block_destroy(&block);
10903 return(TNG_CRITICAL);
10907 tng_block_destroy(&block);
10908 return(TNG_SUCCESS);
10913 /* Take long steps backward until a long step backward would be too long
10914 * or the right frame set is found */
10915 while(file_pos > 0 && curr_nr - long_stride_length >= nr)
10917 file_pos = frame_set->long_stride_prev_frame_set_file_pos;
10920 curr_nr -= long_stride_length;
10921 fseeko(tng_data->input_file,
10924 /* Read block headers first to see what block is found. */
10925 stat = tng_block_header_read(tng_data, block);
10926 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10928 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
10929 file_pos, __FILE__, __LINE__);
10930 tng_block_destroy(&block);
10931 return(TNG_CRITICAL);
10934 if(tng_block_read_next(tng_data, block,
10935 TNG_SKIP_HASH) != TNG_SUCCESS)
10937 tng_block_destroy(&block);
10938 return(TNG_CRITICAL);
10942 tng_block_destroy(&block);
10943 return(TNG_SUCCESS);
10948 /* Take medium steps backward until a medium step backward would be too long
10949 * or the right frame set is found */
10950 while(file_pos > 0 && curr_nr - medium_stride_length >= nr)
10952 file_pos = frame_set->medium_stride_prev_frame_set_file_pos;
10955 curr_nr -= medium_stride_length;
10956 fseeko(tng_data->input_file,
10959 /* Read block headers first to see what block is found. */
10960 stat = tng_block_header_read(tng_data, block);
10961 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10963 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
10964 file_pos, __FILE__, __LINE__);
10965 tng_block_destroy(&block);
10966 return(TNG_CRITICAL);
10969 if(tng_block_read_next(tng_data, block,
10970 TNG_SKIP_HASH) != TNG_SUCCESS)
10972 tng_block_destroy(&block);
10973 return(TNG_CRITICAL);
10977 tng_block_destroy(&block);
10978 return(TNG_SUCCESS);
10983 /* Take one step backward until the right frame set is found */
10984 while(file_pos > 0 && curr_nr > nr)
10986 file_pos = frame_set->prev_frame_set_file_pos;
10990 fseeko(tng_data->input_file,
10993 /* Read block headers first to see what block is found. */
10994 stat = tng_block_header_read(tng_data, block);
10995 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10997 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
10998 file_pos, __FILE__, __LINE__);
10999 tng_block_destroy(&block);
11000 return(TNG_CRITICAL);
11003 if(tng_block_read_next(tng_data, block,
11004 TNG_SKIP_HASH) != TNG_SUCCESS)
11006 tng_block_destroy(&block);
11007 return(TNG_CRITICAL);
11011 tng_block_destroy(&block);
11012 return(TNG_SUCCESS);
11017 /* If for some reason the current frame set is not yet found,
11018 * take one step forward until the right frame set is found */
11019 while(file_pos > 0 && curr_nr < nr)
11021 file_pos = frame_set->next_frame_set_file_pos;
11025 fseeko(tng_data->input_file,
11028 /* Read block headers first to see what block is found. */
11029 stat = tng_block_header_read(tng_data, block);
11030 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11032 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
11033 file_pos, __FILE__, __LINE__);
11034 tng_block_destroy(&block);
11035 return(TNG_CRITICAL);
11038 if(tng_block_read_next(tng_data, block,
11039 TNG_SKIP_HASH) != TNG_SUCCESS)
11041 tng_block_destroy(&block);
11042 return(TNG_CRITICAL);
11046 tng_block_destroy(&block);
11047 return(TNG_SUCCESS);
11052 tng_block_destroy(&block);
11053 return(TNG_FAILURE);
11056 tng_function_status DECLSPECDLLEXPORT tng_frame_set_of_frame_find
11057 (const tng_trajectory_t tng_data,
11058 const int64_t frame)
11060 int64_t first_frame, last_frame, n_frames_per_frame_set;
11061 int64_t long_stride_length, medium_stride_length;
11062 int64_t file_pos, temp_frame, n_frames;
11063 tng_trajectory_frame_set_t frame_set;
11064 tng_gen_block_t block;
11065 tng_function_status stat;
11067 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11068 TNG_ASSERT(frame >= 0, "TNG library: frame must be >= 0.");
11070 frame_set = &tng_data->current_trajectory_frame_set;
11072 tng_block_init(&block);
11074 if(tng_data->current_trajectory_frame_set_input_file_pos < 0)
11076 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
11077 fseeko(tng_data->input_file,
11080 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
11081 /* Read block headers first to see what block is found. */
11082 stat = tng_block_header_read(tng_data, block);
11083 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11085 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
11086 file_pos, __FILE__, __LINE__);
11087 tng_block_destroy(&block);
11088 return(TNG_CRITICAL);
11091 if(tng_block_read_next(tng_data, block,
11092 TNG_SKIP_HASH) != TNG_SUCCESS)
11094 tng_block_destroy(&block);
11095 return(TNG_CRITICAL);
11099 first_frame = tng_max_i64(frame_set->first_frame, 0);
11100 last_frame = first_frame + frame_set->n_frames - 1;
11101 /* Is this the right frame set? */
11102 if(first_frame <= frame && frame <= last_frame)
11104 tng_block_destroy(&block);
11105 return(TNG_SUCCESS);
11108 n_frames_per_frame_set = tng_data->frame_set_n_frames;
11109 long_stride_length = tng_data->long_stride_length;
11110 medium_stride_length = tng_data->medium_stride_length;
11112 if(tng_first_frame_nr_of_next_frame_set_get(tng_data, &temp_frame) ==
11115 if(temp_frame - first_frame > n_frames_per_frame_set)
11117 n_frames_per_frame_set = temp_frame - first_frame;
11121 tng_num_frames_get(tng_data, &n_frames);
11123 if(frame >= n_frames)
11125 tng_block_destroy(&block);
11126 return(TNG_FAILURE);
11129 if(first_frame - frame >= frame ||
11130 frame - last_frame >
11131 tng_data->n_trajectory_frame_sets * n_frames_per_frame_set - frame)
11133 /* Start from the beginning */
11134 if(first_frame - frame >= frame)
11136 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
11140 tng_block_destroy(&block);
11141 return(TNG_FAILURE);
11144 /* Start from the end */
11145 else if(frame - first_frame > (n_frames - 1) - frame)
11147 file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
11149 /* If the last frame set position is not set start from the current
11150 * frame set, since it will be closer than the first frame set. */
11152 /* Start from current */
11155 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
11160 fseeko(tng_data->input_file,
11163 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
11164 /* Read block headers first to see what block is found. */
11165 stat = tng_block_header_read(tng_data, block);
11166 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11168 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
11169 file_pos, __FILE__, __LINE__);
11170 tng_block_destroy(&block);
11171 return(TNG_CRITICAL);
11174 if(tng_block_read_next(tng_data, block,
11175 TNG_SKIP_HASH) != TNG_SUCCESS)
11177 tng_block_destroy(&block);
11178 return(TNG_CRITICAL);
11183 first_frame = tng_max_i64(frame_set->first_frame, 0);
11184 last_frame = first_frame + frame_set->n_frames - 1;
11186 if(frame >= first_frame && frame <= last_frame)
11188 tng_block_destroy(&block);
11189 return(TNG_SUCCESS);
11192 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
11194 /* Take long steps forward until a long step forward would be too long or
11195 * the right frame set is found */
11196 while(file_pos > 0 && first_frame + long_stride_length *
11197 n_frames_per_frame_set <= frame)
11199 file_pos = frame_set->long_stride_next_frame_set_file_pos;
11202 fseeko(tng_data->input_file, file_pos, SEEK_SET);
11203 /* Read block headers first to see what block is found. */
11204 stat = tng_block_header_read(tng_data, block);
11205 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11207 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
11208 file_pos, __FILE__, __LINE__);
11209 tng_block_destroy(&block);
11210 return(TNG_CRITICAL);
11213 if(tng_block_read_next(tng_data, block,
11214 TNG_SKIP_HASH) != TNG_SUCCESS)
11216 tng_block_destroy(&block);
11217 return(TNG_CRITICAL);
11220 first_frame = tng_max_i64(frame_set->first_frame, 0);
11221 last_frame = first_frame + frame_set->n_frames - 1;
11222 if(frame >= first_frame && frame <= last_frame)
11224 tng_block_destroy(&block);
11225 return(TNG_SUCCESS);
11229 /* Take medium steps forward until a medium step forward would be too long
11230 * or the right frame set is found */
11231 while(file_pos > 0 && first_frame + medium_stride_length *
11232 n_frames_per_frame_set <= frame)
11234 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
11237 fseeko(tng_data->input_file,
11240 /* Read block headers first to see what block is found. */
11241 stat = tng_block_header_read(tng_data, block);
11242 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11244 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
11245 file_pos, __FILE__, __LINE__);
11246 tng_block_destroy(&block);
11247 return(TNG_CRITICAL);
11250 if(tng_block_read_next(tng_data, block,
11251 TNG_SKIP_HASH) != TNG_SUCCESS)
11253 tng_block_destroy(&block);
11254 return(TNG_CRITICAL);
11257 first_frame = tng_max_i64(frame_set->first_frame, 0);
11258 last_frame = first_frame + frame_set->n_frames - 1;
11259 if(frame >= first_frame && frame <= last_frame)
11261 tng_block_destroy(&block);
11262 return(TNG_SUCCESS);
11266 /* Take one step forward until the right frame set is found */
11267 while(file_pos > 0 && first_frame < frame && last_frame < frame)
11269 file_pos = frame_set->next_frame_set_file_pos;
11272 fseeko(tng_data->input_file,
11275 /* Read block headers first to see what block is found. */
11276 stat = tng_block_header_read(tng_data, block);
11277 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11279 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
11280 file_pos, __FILE__, __LINE__);
11281 tng_block_destroy(&block);
11282 return(TNG_CRITICAL);
11285 if(tng_block_read_next(tng_data, block,
11286 TNG_SKIP_HASH) != TNG_SUCCESS)
11288 tng_block_destroy(&block);
11289 return(TNG_CRITICAL);
11292 first_frame = tng_max_i64(frame_set->first_frame, 0);
11293 last_frame = first_frame + frame_set->n_frames - 1;
11294 if(frame >= first_frame && frame <= last_frame)
11296 tng_block_destroy(&block);
11297 return(TNG_SUCCESS);
11301 /* Take long steps backward until a long step backward would be too long
11302 * or the right frame set is found */
11303 while(file_pos > 0 && first_frame - long_stride_length *
11304 n_frames_per_frame_set >= frame)
11306 file_pos = frame_set->long_stride_prev_frame_set_file_pos;
11309 fseeko(tng_data->input_file,
11312 /* Read block headers first to see what block is found. */
11313 stat = tng_block_header_read(tng_data, block);
11314 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11316 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
11317 file_pos, __FILE__, __LINE__);
11318 tng_block_destroy(&block);
11319 return(TNG_CRITICAL);
11322 if(tng_block_read_next(tng_data, block,
11323 TNG_SKIP_HASH) != TNG_SUCCESS)
11325 tng_block_destroy(&block);
11326 return(TNG_CRITICAL);
11329 first_frame = tng_max_i64(frame_set->first_frame, 0);
11330 last_frame = first_frame + frame_set->n_frames - 1;
11331 if(frame >= first_frame && frame <= last_frame)
11333 tng_block_destroy(&block);
11334 return(TNG_SUCCESS);
11338 /* Take medium steps backward until a medium step backward would be too long
11339 * or the right frame set is found */
11340 while(file_pos > 0 && first_frame - medium_stride_length *
11341 n_frames_per_frame_set >= frame)
11343 file_pos = frame_set->medium_stride_prev_frame_set_file_pos;
11346 fseeko(tng_data->input_file,
11349 /* Read block headers first to see what block is found. */
11350 stat = tng_block_header_read(tng_data, block);
11351 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11353 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
11354 file_pos, __FILE__, __LINE__);
11355 tng_block_destroy(&block);
11356 return(TNG_CRITICAL);
11359 if(tng_block_read_next(tng_data, block,
11360 TNG_SKIP_HASH) != TNG_SUCCESS)
11362 tng_block_destroy(&block);
11363 return(TNG_CRITICAL);
11366 first_frame = tng_max_i64(frame_set->first_frame, 0);
11367 last_frame = first_frame + frame_set->n_frames - 1;
11368 if(frame >= first_frame && frame <= last_frame)
11370 tng_block_destroy(&block);
11371 return(TNG_SUCCESS);
11375 /* Take one step backward until the right frame set is found */
11376 while(file_pos > 0 && first_frame > frame && last_frame > frame)
11378 file_pos = frame_set->prev_frame_set_file_pos;
11381 fseeko(tng_data->input_file,
11384 /* Read block headers first to see what block is found. */
11385 stat = tng_block_header_read(tng_data, block);
11386 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11388 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
11389 file_pos, __FILE__, __LINE__);
11390 tng_block_destroy(&block);
11391 return(TNG_CRITICAL);
11394 if(tng_block_read_next(tng_data, block,
11395 TNG_SKIP_HASH) != TNG_SUCCESS)
11397 tng_block_destroy(&block);
11398 return(TNG_CRITICAL);
11401 first_frame = tng_max_i64(frame_set->first_frame, 0);
11402 last_frame = first_frame + frame_set->n_frames - 1;
11403 if(frame >= first_frame && frame <= last_frame)
11405 tng_block_destroy(&block);
11406 return(TNG_SUCCESS);
11410 /* If for some reason the current frame set is not yet found,
11411 * take one step forward until the right frame set is found */
11412 while(file_pos > 0 && first_frame < frame && last_frame < frame)
11414 file_pos = frame_set->next_frame_set_file_pos;
11417 fseeko(tng_data->input_file,
11420 /* Read block headers first to see what block is found. */
11421 stat = tng_block_header_read(tng_data, block);
11422 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11424 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
11425 file_pos, __FILE__, __LINE__);
11426 tng_block_destroy(&block);
11427 return(TNG_CRITICAL);
11430 if(tng_block_read_next(tng_data, block,
11431 TNG_SKIP_HASH) != TNG_SUCCESS)
11433 tng_block_destroy(&block);
11434 return(TNG_CRITICAL);
11437 first_frame = tng_max_i64(frame_set->first_frame, 0);
11438 last_frame = first_frame + frame_set->n_frames - 1;
11439 if(frame >= first_frame && frame <= last_frame)
11441 tng_block_destroy(&block);
11442 return(TNG_SUCCESS);
11446 tng_block_destroy(&block);
11447 return(TNG_FAILURE);
11450 tng_function_status DECLSPECDLLEXPORT tng_frame_set_next_frame_set_file_pos_get
11451 (const tng_trajectory_t tng_data,
11452 const tng_trajectory_frame_set_t frame_set,
11457 TNG_ASSERT(frame_set, "TNG library: frame_set not initialised before accessing data.");
11458 TNG_ASSERT(pos, "TNG library: pos must not be a NULL pointer");
11460 *pos = frame_set->next_frame_set_file_pos;
11462 return(TNG_SUCCESS);
11465 tng_function_status DECLSPECDLLEXPORT tng_frame_set_prev_frame_set_file_pos_get
11466 (const tng_trajectory_t tng_data,
11467 const tng_trajectory_frame_set_t frame_set,
11472 TNG_ASSERT(frame_set, "TNG library: frame_set not initialised before accessing data.");
11473 TNG_ASSERT(pos, "TNG library: pos must not be a NULL pointer");
11475 *pos = frame_set->prev_frame_set_file_pos;
11477 return(TNG_SUCCESS);
11480 tng_function_status DECLSPECDLLEXPORT tng_frame_set_frame_range_get
11481 (const tng_trajectory_t tng_data,
11482 const tng_trajectory_frame_set_t frame_set,
11483 int64_t *first_frame,
11484 int64_t *last_frame)
11488 TNG_ASSERT(first_frame, "TNG library: first_frame must not be a NULL pointer");
11489 TNG_ASSERT(last_frame, "TNG library: last_frame must not be a NULL pointer");
11490 TNG_ASSERT(frame_set, "TNG library: frame_set must not be a NULL pointer");
11492 *first_frame = frame_set->first_frame;
11493 *last_frame = *first_frame + frame_set->n_frames - 1;
11495 return(TNG_SUCCESS);
11499 * @brief Translate from the particle numbering used in a frame set to the real
11500 * particle numbering - used in the molecule description.
11501 * @param frame_set is the frame_set containing the mappings to use.
11502 * @param local is the index number of the atom in this frame set
11503 * @param real is set to the index of the atom in the molecular system.
11504 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the mapping
11507 static TNG_INLINE tng_function_status tng_particle_mapping_get_real_particle
11508 (const tng_trajectory_frame_set_t frame_set,
11509 const int64_t local,
11512 int64_t i, n_blocks = frame_set->n_mapping_blocks, first;
11513 tng_particle_mapping_t mapping;
11517 return(TNG_SUCCESS);
11519 for(i = 0; i < n_blocks; i++)
11521 mapping = &frame_set->mappings[i];
11522 first = mapping->num_first_particle;
11523 if(local < first ||
11524 local >= first + mapping->n_particles)
11528 *real = mapping->real_particle_numbers[local-first];
11529 return(TNG_SUCCESS);
11532 return(TNG_FAILURE);
11536 * @brief Translate from the real particle numbering to the particle numbering
11537 * used in a frame set.
11538 * @param frame_set is the frame_set containing the mappings to use.
11539 * @param real is the index number of the atom in the molecular system.
11540 * @param local is set to the index of the atom in this frame set.
11541 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the mapping
11544 /*static TNG_INLINE tng_function_status tng_particle_mapping_get_local_particle
11545 (const tng_trajectory_frame_set_t frame_set,
11546 const int64_t real,
11549 int64_t i, j, n_blocks = frame_set->n_mapping_blocks;
11550 tng_particle_mapping_t mapping;
11554 return(TNG_SUCCESS);
11556 for(i = 0; i < n_blocks; i++)
11558 mapping = &frame_set->mappings[i];
11559 for(j = mapping->n_particles; j--;)
11561 if(mapping->real_particle_numbers[j] == real)
11564 return(TNG_SUCCESS);
11568 return(TNG_FAILURE);
11572 static tng_function_status tng_file_headers_len_get
11573 (const tng_trajectory_t tng_data,
11577 tng_gen_block_t block;
11579 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11581 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
11583 return(TNG_CRITICAL);
11588 orig_pos = ftello(tng_data->input_file);
11590 fseeko(tng_data->input_file, 0, SEEK_SET);
11592 tng_block_init(&block);
11593 /* Read through the headers of non-trajectory blocks (they come before the
11594 * trajectory blocks in the file) */
11595 while (*len < tng_data->input_file_len &&
11596 tng_block_header_read(tng_data, block) != TNG_CRITICAL &&
11598 block->id != TNG_TRAJECTORY_FRAME_SET)
11600 *len += block->header_contents_size + block->block_contents_size;
11601 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
11604 fseeko(tng_data->input_file, orig_pos, SEEK_SET);
11606 tng_block_destroy(&block);
11608 return(TNG_SUCCESS);
11611 tng_function_status DECLSPECDLLEXPORT tng_file_headers_read
11612 (const tng_trajectory_t tng_data,
11613 const char hash_mode)
11615 int64_t prev_pos = 0;
11616 tng_gen_block_t block;
11618 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11620 tng_data->n_trajectory_frame_sets = 0;
11622 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
11624 return(TNG_CRITICAL);
11627 fseeko(tng_data->input_file, 0, SEEK_SET);
11629 tng_block_init(&block);
11630 /* Non trajectory blocks (they come before the trajectory
11631 * blocks in the file) */
11632 while (prev_pos < tng_data->input_file_len &&
11633 tng_block_header_read(tng_data, block) != TNG_CRITICAL &&
11635 block->id != TNG_TRAJECTORY_FRAME_SET)
11637 tng_block_read_next(tng_data, block, hash_mode);
11638 prev_pos = ftello(tng_data->input_file);
11641 /* Go back if a trajectory block was encountered */
11642 if(block->id == TNG_TRAJECTORY_FRAME_SET)
11644 fseeko(tng_data->input_file, prev_pos, SEEK_SET);
11647 tng_block_destroy(&block);
11649 return(TNG_SUCCESS);
11652 tng_function_status DECLSPECDLLEXPORT tng_file_headers_write
11653 (const tng_trajectory_t tng_data,
11654 const char hash_mode)
11657 int64_t len, orig_len, tot_len = 0, data_start_pos, temp_pos = -1;
11658 tng_function_status stat;
11659 tng_gen_block_t block;
11661 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11663 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
11665 return(TNG_CRITICAL);
11668 if(tng_data->n_trajectory_frame_sets > 0)
11670 stat = tng_file_headers_len_get(tng_data, &orig_len);
11671 if(stat != TNG_SUCCESS)
11676 tng_block_init(&block);
11677 block->name = (char *)malloc(TNG_MAX_STR_LEN);
11680 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
11681 __FILE__, __LINE__);
11682 tng_block_destroy(&block);
11683 return(TNG_CRITICAL);
11685 strcpy(block->name, "GENERAL INFO");
11686 tng_block_header_len_calculate(tng_data, block, &len);
11688 tng_general_info_block_len_calculate(tng_data, &len);
11690 strcpy(block->name, "MOLECULES");
11691 tng_block_header_len_calculate(tng_data, block, &len);
11693 tng_molecules_block_len_calculate(tng_data, &len);
11696 for(i = 0; i < tng_data->n_data_blocks; i++)
11698 strcpy(block->name, tng_data->non_tr_data[i].block_name);
11699 tng_block_header_len_calculate(tng_data, block, &len);
11701 tng_data_block_len_calculate(tng_data,
11702 (tng_data_t)&tng_data->non_tr_data[i],
11703 TNG_FALSE, 1, 1, 1, 0, 1,
11708 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
11710 strcpy(block->name, tng_data->non_tr_particle_data[i].block_name);
11711 tng_block_header_len_calculate(tng_data, block, &len);
11713 tng_data_block_len_calculate(tng_data,
11714 &tng_data->non_tr_particle_data[i],
11715 TNG_TRUE, 1, 1, 1, 0,
11716 tng_data->n_particles,
11721 tng_block_destroy(&block);
11723 if(tot_len > orig_len)
11725 tng_migrate_data_in_file(tng_data, orig_len+1, tot_len - orig_len, hash_mode);
11726 tng_data->last_trajectory_frame_set_input_file_pos = tng_data->last_trajectory_frame_set_output_file_pos;
11729 stat = tng_reread_frame_set_at_file_pos(tng_data, tng_data->last_trajectory_frame_set_input_file_pos);
11730 if(stat == TNG_CRITICAL)
11732 fprintf(stderr, "TNG library: Cannot read frame set. %s: %d\n",
11733 __FILE__, __LINE__);
11734 return(TNG_CRITICAL);
11737 /* In order to write non-trajectory data the current_trajectory_frame_set_output_file_pos
11738 * must temporarily be reset */
11739 temp_pos = tng_data->current_trajectory_frame_set_output_file_pos;
11740 tng_data->current_trajectory_frame_set_output_file_pos = -1;
11743 if(tng_general_info_block_write(tng_data, hash_mode)
11746 fprintf(stderr, "TNG library: Error writing general info block of file %s. %s: %d\n",
11747 tng_data->input_file_path, __FILE__, __LINE__);
11748 return(TNG_CRITICAL);
11751 if(tng_molecules_block_write(tng_data, hash_mode)
11754 fprintf(stderr, "TNG library: Error writing atom names block of file %s. %s: %d\n",
11755 tng_data->input_file_path, __FILE__, __LINE__);
11756 return(TNG_CRITICAL);
11759 /* FIXME: Currently writing non-trajectory data blocks here.
11760 * Should perhaps be moved. */
11761 tng_block_init(&block);
11762 for(i = 0; i < tng_data->n_data_blocks; i++)
11764 block->id = tng_data->non_tr_data[i].block_id;
11765 tng_data_block_write(tng_data, block,
11766 i, TNG_FALSE, 0, hash_mode);
11769 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
11771 block->id = tng_data->non_tr_particle_data[i].block_id;
11772 tng_data_block_write(tng_data, block,
11773 i, TNG_TRUE, 0, hash_mode);
11776 tng_block_destroy(&block);
11778 /* Continue writing at the end of the file. */
11779 fseeko(tng_data->output_file, 0, SEEK_END);
11782 tng_data->current_trajectory_frame_set_output_file_pos = temp_pos;
11785 return(TNG_SUCCESS);
11788 tng_function_status DECLSPECDLLEXPORT tng_block_read_next
11789 (const tng_trajectory_t tng_data,
11790 const tng_gen_block_t block,
11791 const char hash_mode)
11793 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11794 TNG_ASSERT(block, "TNG library: block must be initialised and must not be a NULL pointer.");
11798 case TNG_TRAJECTORY_FRAME_SET:
11799 return(tng_frame_set_block_read(tng_data, block, hash_mode));
11800 case TNG_PARTICLE_MAPPING:
11801 return(tng_trajectory_mapping_block_read(tng_data, block, hash_mode));
11802 case TNG_GENERAL_INFO:
11803 return(tng_general_info_block_read(tng_data, block, hash_mode));
11804 case TNG_MOLECULES:
11805 return(tng_molecules_block_read(tng_data, block, hash_mode));
11807 if(block->id >= TNG_TRAJ_BOX_SHAPE)
11809 return(tng_data_block_contents_read(tng_data, block, hash_mode));
11813 /* Skip to the next block */
11814 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
11815 return(TNG_FAILURE);
11820 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read
11821 (const tng_trajectory_t tng_data,
11822 const char hash_mode)
11825 tng_gen_block_t block;
11826 tng_function_status stat;
11828 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11830 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
11832 return(TNG_CRITICAL);
11835 file_pos = ftello(tng_data->input_file);
11837 tng_block_init(&block);
11839 /* Read block headers first to see what block is found. */
11840 stat = tng_block_header_read(tng_data, block);
11841 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET ||
11844 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
11845 file_pos, __FILE__, __LINE__);
11846 tng_block_destroy(&block);
11847 return(TNG_CRITICAL);
11850 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
11852 if(tng_block_read_next(tng_data, block,
11853 hash_mode) == TNG_SUCCESS)
11855 tng_data->n_trajectory_frame_sets++;
11856 file_pos = ftello(tng_data->input_file);
11857 /* Read all blocks until next frame set block */
11858 stat = tng_block_header_read(tng_data, block);
11859 while(file_pos < tng_data->input_file_len &&
11860 stat != TNG_CRITICAL &&
11861 block->id != TNG_TRAJECTORY_FRAME_SET &&
11864 stat = tng_block_read_next(tng_data, block,
11866 if(stat != TNG_CRITICAL)
11868 file_pos = ftello(tng_data->input_file);
11869 if(file_pos < tng_data->input_file_len)
11871 stat = tng_block_header_read(tng_data, block);
11875 if(stat == TNG_CRITICAL)
11877 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
11878 file_pos, __FILE__, __LINE__);
11879 tng_block_destroy(&block);
11883 if(block->id == TNG_TRAJECTORY_FRAME_SET)
11885 fseeko(tng_data->input_file, file_pos, SEEK_SET);
11889 tng_block_destroy(&block);
11891 return(TNG_SUCCESS);
11895 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_current_only_data_from_block_id
11896 (const tng_trajectory_t tng_data,
11897 const char hash_mode,
11898 const int64_t block_id)
11901 tng_gen_block_t block;
11902 tng_function_status stat;
11903 int found_flag = 1;
11905 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11907 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
11909 return(TNG_CRITICAL);
11912 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
11916 /* No current frame set. This means that the first frame set must be
11919 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
11924 fseeko(tng_data->input_file,
11930 return(TNG_FAILURE);
11933 tng_block_init(&block);
11935 /* Read block headers first to see what block is found. */
11936 stat = tng_block_header_read(tng_data, block);
11937 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11939 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
11940 file_pos, __FILE__, __LINE__);
11941 tng_block_destroy(&block);
11942 return(TNG_CRITICAL);
11944 /* If the current frame set had already been read skip its block contents */
11947 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
11949 /* Otherwise read the frame set block */
11952 stat = tng_block_read_next(tng_data, block,
11954 if(stat != TNG_SUCCESS)
11956 fprintf(stderr, "TNG library: Cannot read frame set block. %s: %d\n", __FILE__, __LINE__);
11957 tng_block_destroy(&block);
11961 file_pos = ftello(tng_data->input_file);
11965 /* Read only blocks of the requested ID
11966 * until next frame set block */
11967 stat = tng_block_header_read(tng_data, block);
11968 while(file_pos < tng_data->input_file_len &&
11969 stat != TNG_CRITICAL &&
11970 block->id != TNG_TRAJECTORY_FRAME_SET &&
11973 if(block->id == block_id)
11975 stat = tng_block_read_next(tng_data, block,
11977 if(stat != TNG_CRITICAL)
11979 file_pos = ftello(tng_data->input_file);
11981 if(file_pos < tng_data->input_file_len)
11983 stat = tng_block_header_read(tng_data, block);
11989 file_pos += block->block_contents_size + block->header_contents_size;
11990 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
11991 if(file_pos < tng_data->input_file_len)
11993 stat = tng_block_header_read(tng_data, block);
11997 if(stat == TNG_CRITICAL)
11999 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
12000 file_pos, __FILE__, __LINE__);
12001 tng_block_destroy(&block);
12005 if(block->id == TNG_TRAJECTORY_FRAME_SET)
12007 fseeko(tng_data->input_file, file_pos, SEEK_SET);
12010 tng_block_destroy(&block);
12014 return(TNG_SUCCESS);
12018 return(TNG_FAILURE);
12022 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next
12023 (const tng_trajectory_t tng_data,
12024 const char hash_mode)
12028 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12030 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12032 return(TNG_CRITICAL);
12035 file_pos = tng_data->current_trajectory_frame_set.next_frame_set_file_pos;
12037 if(file_pos < 0 && tng_data->current_trajectory_frame_set_input_file_pos <= 0)
12039 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
12044 fseeko(tng_data->input_file,
12050 return(TNG_FAILURE);
12053 return(tng_frame_set_read(tng_data, hash_mode));
12056 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next_only_data_from_block_id
12057 (const tng_trajectory_t tng_data,
12058 const char hash_mode,
12059 const int64_t block_id)
12062 tng_gen_block_t block;
12063 tng_function_status stat;
12065 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12067 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12069 return(TNG_CRITICAL);
12072 file_pos = tng_data->current_trajectory_frame_set.next_frame_set_file_pos;
12074 if(file_pos < 0 && tng_data->current_trajectory_frame_set_input_file_pos <= 0)
12076 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
12081 fseeko(tng_data->input_file,
12087 return(TNG_FAILURE);
12090 tng_block_init(&block);
12092 /* Read block headers first to see what block is found. */
12093 stat = tng_block_header_read(tng_data, block);
12094 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12096 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
12097 file_pos, __FILE__, __LINE__);
12098 tng_block_destroy(&block);
12099 return(TNG_CRITICAL);
12102 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
12104 if(tng_block_read_next(tng_data, block,
12105 hash_mode) == TNG_SUCCESS)
12107 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, hash_mode, block_id);
12110 tng_block_destroy(&block);
12115 tng_function_status tng_frame_set_write
12116 (const tng_trajectory_t tng_data,
12117 const char hash_mode)
12120 tng_gen_block_t block;
12121 tng_trajectory_frame_set_t frame_set;
12122 tng_function_status stat;
12124 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12126 frame_set = &tng_data->current_trajectory_frame_set;
12128 if(frame_set->n_written_frames == frame_set->n_frames)
12130 return(TNG_SUCCESS);
12133 tng_data->current_trajectory_frame_set_output_file_pos =
12134 ftello(tng_data->output_file);
12135 tng_data->last_trajectory_frame_set_output_file_pos =
12136 tng_data->current_trajectory_frame_set_output_file_pos;
12138 if(tng_data->current_trajectory_frame_set_output_file_pos <= 0)
12140 return(TNG_FAILURE);
12143 if(tng_data->first_trajectory_frame_set_output_file_pos == -1)
12145 tng_data->first_trajectory_frame_set_output_file_pos =
12146 tng_data->current_trajectory_frame_set_output_file_pos;
12149 tng_block_init(&block);
12151 if(tng_frame_set_block_write(tng_data, block, hash_mode) != TNG_SUCCESS)
12153 tng_block_destroy(&block);
12154 return(TNG_FAILURE);
12157 /* Write non-particle data blocks */
12158 for(i = 0; i<frame_set->n_data_blocks; i++)
12160 block->id = frame_set->tr_data[i].block_id;
12161 tng_data_block_write(tng_data, block, i, TNG_FALSE, 0, hash_mode);
12163 /* Write the mapping blocks and particle data blocks*/
12164 if(frame_set->n_mapping_blocks)
12166 for(i = 0; i < frame_set->n_mapping_blocks; i++)
12168 block->id = TNG_PARTICLE_MAPPING;
12169 if(frame_set->mappings[i].n_particles > 0)
12171 tng_trajectory_mapping_block_write(tng_data, block, i, hash_mode);
12172 for(j = 0; j<frame_set->n_particle_data_blocks; j++)
12174 block->id = frame_set->tr_particle_data[j].block_id;
12175 tng_data_block_write(tng_data, block,
12176 j, TNG_TRUE, &frame_set->mappings[i],
12184 for(i = 0; i<frame_set->n_particle_data_blocks; i++)
12186 block->id = frame_set->tr_particle_data[i].block_id;
12187 tng_data_block_write(tng_data, block,
12188 i, TNG_TRUE, 0, hash_mode);
12193 /* Update pointers in the general info block */
12194 stat = tng_header_pointers_update(tng_data, hash_mode);
12196 if(stat == TNG_SUCCESS)
12198 stat = tng_frame_set_pointers_update(tng_data, hash_mode);
12201 tng_block_destroy(&block);
12203 frame_set->n_unwritten_frames = 0;
12205 fflush(tng_data->output_file);
12210 tng_function_status DECLSPECDLLEXPORT tng_frame_set_premature_write
12211 (const tng_trajectory_t tng_data,
12212 const char hash_mode)
12214 tng_trajectory_frame_set_t frame_set;
12216 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12218 frame_set = &tng_data->current_trajectory_frame_set;
12220 if(frame_set->n_unwritten_frames == 0)
12222 return(TNG_SUCCESS);
12224 frame_set->n_frames = frame_set->n_unwritten_frames;
12226 return(tng_frame_set_write(tng_data, hash_mode));
12229 tng_function_status DECLSPECDLLEXPORT tng_frame_set_new
12230 (const tng_trajectory_t tng_data,
12231 const int64_t first_frame,
12232 const int64_t n_frames)
12234 tng_gen_block_t block;
12235 tng_trajectory_frame_set_t frame_set;
12236 FILE *temp = tng_data->input_file;
12237 int64_t curr_file_pos;
12239 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12240 TNG_ASSERT(first_frame >= 0, "TNG library: first_frame must be >= 0.");
12241 TNG_ASSERT(n_frames >= 0, "TNG library: n_frames must be >= 0.");
12243 frame_set = &tng_data->current_trajectory_frame_set;
12245 curr_file_pos = ftello(tng_data->output_file);
12247 if(curr_file_pos <= 10)
12249 tng_file_headers_write(tng_data, TNG_USE_HASH);
12252 /* Set pointer to previous frame set to the one that was loaded
12254 * FIXME: This is a bit risky. If they are not added in order
12255 * it will be wrong. */
12256 if(tng_data->n_trajectory_frame_sets)
12258 frame_set->prev_frame_set_file_pos =
12259 tng_data->last_trajectory_frame_set_output_file_pos;
12262 frame_set->next_frame_set_file_pos = -1;
12264 tng_data->current_trajectory_frame_set_output_file_pos =
12265 ftello(tng_data->output_file);
12267 tng_data->n_trajectory_frame_sets++;
12269 /* Set the medium range pointers */
12270 if(tng_data->n_trajectory_frame_sets == tng_data->medium_stride_length + 1)
12272 frame_set->medium_stride_prev_frame_set_file_pos =
12273 tng_data->first_trajectory_frame_set_output_file_pos;
12275 else if(tng_data->n_trajectory_frame_sets > tng_data->medium_stride_length + 1)
12277 /* FIXME: Currently only working if the previous frame set has its
12278 * medium stride pointer already set. This might need some fixing. */
12279 if(frame_set->medium_stride_prev_frame_set_file_pos != -1 &&
12280 frame_set->medium_stride_prev_frame_set_file_pos != 0)
12282 tng_block_init(&block);
12283 tng_data->input_file = tng_data->output_file;
12285 curr_file_pos = ftello(tng_data->output_file);
12286 fseeko(tng_data->output_file,
12287 frame_set->medium_stride_prev_frame_set_file_pos,
12290 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
12292 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
12293 __FILE__, __LINE__);
12294 tng_data->input_file = temp;
12295 tng_block_destroy(&block);
12296 return(TNG_CRITICAL);
12299 /* Read the next frame set from the previous frame set and one
12300 * medium stride step back */
12301 fseeko(tng_data->output_file, block->block_contents_size - (6 *
12302 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
12303 if(fread(&frame_set->medium_stride_prev_frame_set_file_pos,
12304 sizeof(frame_set->medium_stride_prev_frame_set_file_pos),
12305 1, tng_data->output_file) == 0)
12307 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
12308 tng_data->input_file = temp;
12309 tng_block_destroy(&block);
12310 return(TNG_CRITICAL);
12313 if(tng_data->input_endianness_swap_func_64)
12315 if(tng_data->input_endianness_swap_func_64(tng_data,
12316 (uint64_t *)&frame_set->medium_stride_prev_frame_set_file_pos)
12319 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
12320 __FILE__, __LINE__);
12324 tng_block_destroy(&block);
12326 /* Set the long range pointers */
12327 if(tng_data->n_trajectory_frame_sets == tng_data->long_stride_length + 1)
12329 frame_set->long_stride_prev_frame_set_file_pos =
12330 tng_data->first_trajectory_frame_set_output_file_pos;
12332 else if(tng_data->n_trajectory_frame_sets > tng_data->medium_stride_length + 1)
12334 /* FIXME: Currently only working if the previous frame set has its
12335 * long stride pointer already set. This might need some fixing. */
12336 if(frame_set->long_stride_prev_frame_set_file_pos != -1 &&
12337 frame_set->long_stride_prev_frame_set_file_pos != 0)
12339 tng_block_init(&block);
12340 tng_data->input_file = tng_data->output_file;
12342 fseeko(tng_data->output_file,
12343 frame_set->long_stride_prev_frame_set_file_pos,
12346 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
12348 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
12349 __FILE__, __LINE__);
12350 tng_data->input_file = temp;
12351 tng_block_destroy(&block);
12352 return(TNG_CRITICAL);
12355 /* Read the next frame set from the previous frame set and one
12356 * long stride step back */
12357 fseeko(tng_data->output_file, block->block_contents_size - (6 *
12358 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
12360 tng_block_destroy(&block);
12362 if(fread(&frame_set->long_stride_prev_frame_set_file_pos,
12363 sizeof(frame_set->long_stride_prev_frame_set_file_pos),
12364 1, tng_data->output_file) == 0)
12366 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
12367 tng_data->input_file = temp;
12368 return(TNG_CRITICAL);
12371 if(tng_data->input_endianness_swap_func_64)
12373 if(tng_data->input_endianness_swap_func_64(tng_data,
12374 (uint64_t *)&frame_set->long_stride_prev_frame_set_file_pos)
12377 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
12378 __FILE__, __LINE__);
12385 tng_data->input_file = temp;
12386 fseeko(tng_data->output_file, curr_file_pos, SEEK_SET);
12390 frame_set->first_frame = first_frame;
12391 frame_set->n_frames = n_frames;
12392 frame_set->n_written_frames = 0;
12393 frame_set->n_unwritten_frames = 0;
12394 frame_set->first_frame_time = -1;
12396 if(tng_data->first_trajectory_frame_set_output_file_pos == -1 ||
12397 tng_data->first_trajectory_frame_set_output_file_pos == 0)
12399 tng_data->first_trajectory_frame_set_output_file_pos =
12400 tng_data->current_trajectory_frame_set_output_file_pos;
12402 /* FIXME: Should check the frame number instead of the file_pos,
12403 * in case frame sets are not in order */
12404 if(tng_data->last_trajectory_frame_set_output_file_pos == -1 ||
12405 tng_data->last_trajectory_frame_set_output_file_pos == 0 ||
12406 tng_data->last_trajectory_frame_set_output_file_pos <
12407 tng_data->current_trajectory_frame_set_output_file_pos)
12409 tng_data->last_trajectory_frame_set_output_file_pos =
12410 tng_data->current_trajectory_frame_set_output_file_pos;
12413 return(TNG_SUCCESS);
12416 tng_function_status DECLSPECDLLEXPORT tng_frame_set_with_time_new
12417 (const tng_trajectory_t tng_data,
12418 const int64_t first_frame,
12419 const int64_t n_frames,
12420 const double first_frame_time)
12422 tng_function_status stat;
12424 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12425 TNG_ASSERT(first_frame >= 0, "TNG library: first_frame must be >= 0.");
12426 TNG_ASSERT(n_frames >= 0, "TNG library: n_frames must be >= 0.");
12427 TNG_ASSERT(first_frame_time >= 0, "TNG library: first_frame_time must be >= 0.");
12430 stat = tng_frame_set_new(tng_data, first_frame, n_frames);
12431 if(stat != TNG_SUCCESS)
12435 stat = tng_frame_set_first_frame_time_set(tng_data, first_frame_time);
12440 tng_function_status DECLSPECDLLEXPORT tng_frame_set_first_frame_time_set
12441 (const tng_trajectory_t tng_data,
12442 const double first_frame_time)
12444 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12445 TNG_ASSERT(first_frame_time >= 0, "TNG library: first_frame_time must be >= 0.");
12447 tng_data->current_trajectory_frame_set.first_frame_time = first_frame_time;
12449 return(TNG_SUCCESS);
12452 tng_function_status DECLSPECDLLEXPORT tng_first_frame_nr_of_next_frame_set_get
12453 (const tng_trajectory_t tng_data,
12456 int64_t file_pos, next_frame_set_file_pos;
12457 tng_gen_block_t block;
12458 tng_function_status stat;
12460 tng_trajectory_frame_set_t frame_set;
12462 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12463 TNG_ASSERT(tng_data->input_file, "TNG library: An input file must be open to find the next frame set");
12464 TNG_ASSERT(frame, "TNG library: frame must not be a NULL pointer");
12466 file_pos = ftello(tng_data->input_file);
12468 if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
12470 next_frame_set_file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
12474 frame_set = &tng_data->current_trajectory_frame_set;
12475 next_frame_set_file_pos = frame_set->next_frame_set_file_pos;
12478 if(next_frame_set_file_pos <= 0)
12480 return(TNG_FAILURE);
12483 fseeko(tng_data->input_file, next_frame_set_file_pos, SEEK_SET);
12484 /* Read block headers first to see that a frame set block is found. */
12485 tng_block_init(&block);
12486 stat = tng_block_header_read(tng_data, block);
12487 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12489 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
12490 file_pos, __FILE__, __LINE__);
12491 return(TNG_CRITICAL);
12493 /* if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
12495 tng_block_read_next(tng_data, block, TNG_USE_HASH);
12497 tng_block_destroy(&block);
12499 if(fread(frame, sizeof(int64_t), 1, tng_data->input_file) == 0)
12501 fprintf(stderr, "TNG library: Cannot read first frame of next frame set. %s: %d\n",
12502 __FILE__, __LINE__);
12503 return(TNG_CRITICAL);
12505 fseeko(tng_data->input_file, file_pos, SEEK_SET);
12507 return(TNG_SUCCESS);
12510 static tng_function_status tng_gen_data_block_add
12511 (const tng_trajectory_t tng_data,
12513 const tng_bool is_particle_data,
12514 const char *block_name,
12515 const char datatype,
12516 const char block_type_flag,
12518 const int64_t n_values_per_frame,
12519 int64_t stride_length,
12520 const int64_t num_first_particle,
12521 const int64_t n_particles,
12522 const int64_t codec_id,
12527 int64_t tot_n_particles, n_frames_div;
12528 char ***first_dim_values, **second_dim_values;
12529 tng_trajectory_frame_set_t frame_set;
12531 char *new_data_c = (char *)new_data;
12532 tng_function_status stat;
12534 frame_set = &tng_data->current_trajectory_frame_set;
12536 if(stride_length <= 0)
12541 if(is_particle_data)
12543 stat = tng_particle_data_find(tng_data, id, &data);
12547 stat = tng_data_find(tng_data, id, &data);
12549 /* If the block does not exist, create it */
12550 if(stat != TNG_SUCCESS)
12552 if(is_particle_data)
12554 stat = tng_particle_data_block_create(tng_data, block_type_flag);
12558 stat = tng_data_block_create(tng_data, block_type_flag);
12561 if(stat != TNG_SUCCESS)
12563 fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
12564 __FILE__, __LINE__);
12565 return(TNG_CRITICAL);
12567 if(is_particle_data)
12569 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
12571 data = &frame_set->tr_particle_data[frame_set->
12572 n_particle_data_blocks - 1];
12576 data = &tng_data->non_tr_particle_data[tng_data->
12577 n_particle_data_blocks - 1];
12582 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
12584 data = &frame_set->tr_data[frame_set->n_data_blocks - 1];
12588 data = &tng_data->non_tr_data[tng_data->n_data_blocks - 1];
12591 data->block_id = id;
12593 len = tng_min_size(strlen(block_name) + 1, TNG_MAX_STR_LEN);
12594 data->block_name = (char *)malloc(len);
12595 if(!data->block_name)
12597 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
12598 __FILE__, __LINE__);
12599 return(TNG_CRITICAL);
12601 strncpy(data->block_name, block_name, len);
12604 /* FIXME: Memory leak from strings. */
12606 data->last_retrieved_frame = -1;
12609 data->datatype = datatype;
12610 data->stride_length = tng_max_i64(stride_length, 1);
12611 data->n_values_per_frame = n_values_per_frame;
12612 data->n_frames = n_frames;
12613 if(is_particle_data)
12615 data->dependency = TNG_PARTICLE_DEPENDENT;
12619 data->dependency = 0;
12621 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
12623 frame_set->n_frames == n_frames ||
12624 stride_length > 1))
12626 data->dependency += TNG_FRAME_DEPENDENT;
12628 data->codec_id = codec_id;
12629 data->compression_multiplier = 1.0;
12630 /* FIXME: This can cause problems. */
12631 data->first_frame_with_data = frame_set->first_frame;
12633 if(is_particle_data)
12635 if(block_type_flag == TNG_TRAJECTORY_BLOCK && tng_data->var_num_atoms_flag)
12637 tot_n_particles = frame_set->n_particles;
12641 tot_n_particles = tng_data->n_particles;
12644 /* This is just to keep the compiler happy - avoid it considering tot_n_particles
12645 * uninitialized. */
12648 tot_n_particles = 0;
12651 /* If data values are supplied add that data to the data block. */
12654 /* Allocate memory */
12655 if(is_particle_data)
12657 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
12658 stride_length, tot_n_particles,
12659 n_values_per_frame);
12663 stat = tng_allocate_data_mem(tng_data, data, n_frames, stride_length,
12664 n_values_per_frame);
12666 if(stat != TNG_SUCCESS)
12668 fprintf(stderr, "TNG library: Cannot allocate particle data memory. %s: %d\n",
12669 __FILE__, __LINE__);
12670 return(TNG_CRITICAL);
12673 if(n_frames > frame_set->n_unwritten_frames)
12675 frame_set->n_unwritten_frames = n_frames;
12678 n_frames_div = (n_frames % stride_length) ?
12679 n_frames / stride_length + 1:
12680 n_frames / stride_length;
12682 if(datatype == TNG_CHAR_DATA)
12684 if(is_particle_data)
12686 for(i = 0; i < n_frames_div; i++)
12688 first_dim_values = data->strings[i];
12689 for(j = num_first_particle; j < num_first_particle + n_particles;
12692 second_dim_values = first_dim_values[j];
12693 for(k = 0; k < n_values_per_frame; k++)
12695 len = tng_min_size(strlen(new_data_c) + 1,
12697 if(second_dim_values[k])
12699 free(second_dim_values[k]);
12701 second_dim_values[k] = (char *)malloc(len);
12702 if(!second_dim_values[k])
12704 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
12705 __FILE__, __LINE__);
12706 return(TNG_CRITICAL);
12708 strncpy(second_dim_values[k],
12717 for(i = 0; i < n_frames_div; i++)
12719 second_dim_values = data->strings[0][i];
12720 for(j = 0; j < n_values_per_frame; j++)
12722 len = tng_min_size(strlen(new_data_c) + 1,
12724 if(second_dim_values[j])
12726 free(second_dim_values[j]);
12728 second_dim_values[j] = (char *)malloc(len);
12729 if(!second_dim_values[j])
12731 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
12732 __FILE__, __LINE__);
12733 return(TNG_CRITICAL);
12735 strncpy(second_dim_values[j],
12747 size = sizeof(int64_t);
12749 case TNG_FLOAT_DATA:
12750 size = sizeof(float);
12752 case TNG_DOUBLE_DATA:
12754 size = sizeof(double);
12757 if(is_particle_data)
12759 memcpy(data->values, new_data, size * n_frames_div *
12760 n_particles * n_values_per_frame);
12764 memcpy(data->values, new_data, size * n_frames_div *
12765 n_values_per_frame);
12770 return(TNG_SUCCESS);
12773 tng_function_status DECLSPECDLLEXPORT tng_data_block_add
12774 (const tng_trajectory_t tng_data,
12776 const char *block_name,
12777 const char datatype,
12778 const char block_type_flag,
12780 const int64_t n_values_per_frame,
12781 int64_t stride_length,
12782 const int64_t codec_id,
12785 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12786 TNG_ASSERT(block_name, "TNG library: block_name must not be a NULL pointer.");
12787 TNG_ASSERT(n_values_per_frame > 0, "TNG library: n_values_per_frame must be a positive integer.");
12789 return(tng_gen_data_block_add(tng_data, id, TNG_FALSE, block_name, datatype,
12790 block_type_flag, n_frames, n_values_per_frame,
12791 stride_length, 0, 0, codec_id, new_data));
12794 tng_function_status DECLSPECDLLEXPORT tng_particle_data_block_add
12795 (const tng_trajectory_t tng_data,
12797 const char *block_name,
12798 const char datatype,
12799 const char block_type_flag,
12801 const int64_t n_values_per_frame,
12802 int64_t stride_length,
12803 const int64_t num_first_particle,
12804 const int64_t n_particles,
12805 const int64_t codec_id,
12808 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12809 TNG_ASSERT(block_name, "TNG library: block_name mustnot be a NULL pointer.");
12810 TNG_ASSERT(n_values_per_frame > 0, "TNG library: n_values_per_frame must be a positive integer.");
12811 TNG_ASSERT(num_first_particle >= 0, "TNG library: num_first_particle must be >= 0.");
12812 TNG_ASSERT(n_particles >= 0, "TNG library: n_particles must be >= 0.");
12814 return(tng_gen_data_block_add(tng_data, id, TNG_TRUE, block_name, datatype,
12815 block_type_flag, n_frames, n_values_per_frame,
12816 stride_length, num_first_particle, n_particles,
12817 codec_id, new_data));
12820 tng_function_status DECLSPECDLLEXPORT tng_data_block_name_get
12821 (const tng_trajectory_t tng_data,
12822 const int64_t block_id,
12827 tng_trajectory_frame_set_t frame_set;
12828 tng_function_status stat;
12830 int block_type = -1;
12832 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12833 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
12835 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
12837 data = &tng_data->non_tr_particle_data[i];
12838 if(data->block_id == block_id)
12840 strncpy(name, data->block_name, max_len);
12841 name[max_len - 1] = '\0';
12842 return(TNG_SUCCESS);
12845 for(i = 0; i < tng_data->n_data_blocks; i++)
12847 data = &tng_data->non_tr_data[i];
12848 if(data->block_id == block_id)
12850 strncpy(name, data->block_name, max_len);
12851 name[max_len - 1] = '\0';
12852 return(TNG_SUCCESS);
12856 frame_set = &tng_data->current_trajectory_frame_set;
12858 stat = tng_particle_data_find(tng_data, block_id, &data);
12859 if(stat == TNG_SUCCESS)
12861 block_type = TNG_PARTICLE_BLOCK_DATA;
12865 stat = tng_data_find(tng_data, block_id, &data);
12866 if(stat == TNG_SUCCESS)
12868 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
12872 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
12873 if(stat != TNG_SUCCESS)
12877 stat = tng_particle_data_find(tng_data, block_id, &data);
12878 if(stat == TNG_SUCCESS)
12880 block_type = TNG_PARTICLE_BLOCK_DATA;
12884 stat = tng_data_find(tng_data, block_id, &data);
12885 if(stat == TNG_SUCCESS)
12887 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
12892 if(block_type == TNG_PARTICLE_BLOCK_DATA)
12894 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
12896 data = &frame_set->tr_particle_data[i];
12897 if(data->block_id == block_id)
12899 strncpy(name, data->block_name, max_len);
12900 name[max_len - 1] = '\0';
12901 return(TNG_SUCCESS);
12905 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
12907 for(i = 0; i < frame_set->n_data_blocks; i++)
12909 data = &frame_set->tr_data[i];
12910 if(data->block_id == block_id)
12912 strncpy(name, data->block_name, max_len);
12913 name[max_len - 1] = '\0';
12914 return(TNG_SUCCESS);
12919 return(TNG_FAILURE);
12922 tng_function_status DECLSPECDLLEXPORT tng_data_block_dependency_get
12923 (const tng_trajectory_t tng_data,
12924 const int64_t block_id,
12925 int *block_dependency)
12928 tng_function_status stat;
12931 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12932 TNG_ASSERT(block_dependency, "TNG library: block_dependency must not be a NULL pointer.");
12934 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
12936 data = &tng_data->non_tr_particle_data[i];
12937 if(data->block_id == block_id)
12939 *block_dependency = TNG_PARTICLE_DEPENDENT;
12940 return(TNG_SUCCESS);
12943 for(i = 0; i < tng_data->n_data_blocks; i++)
12945 data = &tng_data->non_tr_data[i];
12946 if(data->block_id == block_id)
12948 *block_dependency = 0;
12949 return(TNG_SUCCESS);
12953 stat = tng_particle_data_find(tng_data, block_id, &data);
12954 if(stat == TNG_SUCCESS)
12956 *block_dependency = TNG_PARTICLE_DEPENDENT + TNG_FRAME_DEPENDENT;
12957 return(TNG_SUCCESS);
12961 stat = tng_data_find(tng_data, block_id, &data);
12962 if(stat == TNG_SUCCESS)
12964 *block_dependency = TNG_FRAME_DEPENDENT;
12965 return(TNG_SUCCESS);
12969 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
12970 if(stat != TNG_SUCCESS)
12974 stat = tng_particle_data_find(tng_data, block_id, &data);
12975 if(stat == TNG_SUCCESS)
12977 *block_dependency = TNG_PARTICLE_DEPENDENT + TNG_FRAME_DEPENDENT;
12978 return(TNG_SUCCESS);
12982 stat = tng_data_find(tng_data, block_id, &data);
12983 if(stat == TNG_SUCCESS)
12985 *block_dependency = TNG_FRAME_DEPENDENT;
12986 return(TNG_SUCCESS);
12992 return(TNG_FAILURE);
12995 tng_function_status DECLSPECDLLEXPORT tng_data_block_num_values_per_frame_get
12996 (const tng_trajectory_t tng_data,
12997 const int64_t block_id,
12998 int64_t *n_values_per_frame)
13001 tng_function_status stat;
13004 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13005 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
13007 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
13009 data = &tng_data->non_tr_particle_data[i];
13010 if(data->block_id == block_id)
13012 *n_values_per_frame = data->n_values_per_frame;
13013 return(TNG_SUCCESS);
13016 for(i = 0; i < tng_data->n_data_blocks; i++)
13018 data = &tng_data->non_tr_data[i];
13019 if(data->block_id == block_id)
13021 *n_values_per_frame = data->n_values_per_frame;
13022 return(TNG_SUCCESS);
13026 stat = tng_particle_data_find(tng_data, block_id, &data);
13027 if(stat == TNG_SUCCESS)
13029 *n_values_per_frame = data->n_values_per_frame;
13030 return(TNG_SUCCESS);
13034 stat = tng_data_find(tng_data, block_id, &data);
13035 if(stat == TNG_SUCCESS)
13037 *n_values_per_frame = data->n_values_per_frame;
13038 return(TNG_SUCCESS);
13042 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
13043 if(stat != TNG_SUCCESS)
13047 stat = tng_particle_data_find(tng_data, block_id, &data);
13048 if(stat == TNG_SUCCESS)
13050 *n_values_per_frame = data->n_values_per_frame;
13051 return(TNG_SUCCESS);
13055 stat = tng_data_find(tng_data, block_id, &data);
13056 if(stat == TNG_SUCCESS)
13058 *n_values_per_frame = data->n_values_per_frame;
13059 return(TNG_SUCCESS);
13065 return(TNG_FAILURE);
13068 tng_function_status DECLSPECDLLEXPORT tng_frame_set_n_frames_of_data_block_get
13069 (const tng_trajectory_t tng_data,
13070 const int64_t block_id,
13073 tng_gen_block_t block;
13074 tng_function_status stat;
13075 char datatype, dependency, sparse_data;
13076 int64_t n_values, codec_id, first_frame_with_data, stride_length, curr_n_frames;
13077 int64_t num_first_particle, block_n_particles;
13079 md5_state_t md5_state;
13080 int found = TNG_FALSE;
13082 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13084 tng_block_init(&block);
13086 stat = tng_block_header_read(tng_data, block);
13087 /* If the block header could not be read the reading position might not have been
13088 * at the start of a block. Try again from the file position of the current frame
13090 if(stat != TNG_SUCCESS)
13092 fseeko(tng_data->input_file, tng_data->current_trajectory_frame_set_input_file_pos, SEEK_SET);
13093 stat = tng_block_header_read(tng_data, block);
13094 if(stat != TNG_SUCCESS)
13096 tng_block_destroy(&block);
13100 if(block->id == TNG_TRAJECTORY_FRAME_SET)
13102 stat = tng_block_read_next(tng_data, block, TNG_SKIP_HASH);
13103 if(stat != TNG_SUCCESS)
13105 tng_block_destroy(&block);
13108 stat = tng_block_header_read(tng_data, block);
13110 while(stat == TNG_SUCCESS && block->id != TNG_TRAJECTORY_FRAME_SET && found == TNG_FALSE)
13112 if(block->id == block_id)
13114 stat = tng_data_block_meta_information_read(tng_data, &datatype,
13115 &dependency, &sparse_data,
13116 &n_values, &codec_id,
13117 &first_frame_with_data,
13118 &stride_length, &curr_n_frames,
13119 &num_first_particle,
13120 &block_n_particles,
13121 &multiplier, TNG_SKIP_HASH,
13123 if(stat == TNG_SUCCESS)
13130 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
13131 stat = tng_block_header_read(tng_data, block);
13134 if(found == TNG_TRUE)
13136 *n_frames = (tng_data->current_trajectory_frame_set.n_frames -
13137 (tng_data->current_trajectory_frame_set.first_frame - first_frame_with_data)) / stride_length;
13139 else if(stat == TNG_SUCCESS)
13144 tng_block_destroy(&block);
13149 static tng_function_status tng_frame_gen_data_write
13150 (const tng_trajectory_t tng_data,
13151 const int64_t frame_nr,
13152 const int64_t block_id,
13153 const tng_bool is_particle_data,
13154 const int64_t val_first_particle,
13155 const int64_t val_n_particles,
13156 const void *values,
13157 const char hash_mode)
13159 int64_t header_pos, file_pos, tot_n_particles;
13160 int64_t output_file_len, n_values_per_frame, size, contents_size;
13161 int64_t header_size, temp_first, temp_last;
13162 int64_t mapping_block_end_pos, num_first_particle, block_n_particles;
13163 int64_t i, last_frame, temp_current, write_n_particles;
13164 tng_gen_block_t block;
13165 tng_trajectory_frame_set_t frame_set;
13166 FILE *temp = tng_data->input_file;
13167 struct tng_data data;
13168 tng_function_status stat;
13169 tng_particle_mapping_t mapping;
13170 char dependency, sparse_data, datatype;
13173 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
13175 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
13176 __FILE__, __LINE__);
13177 return(TNG_CRITICAL);
13180 temp_first = tng_data->first_trajectory_frame_set_input_file_pos;
13181 temp_last = tng_data->last_trajectory_frame_set_input_file_pos;
13182 temp_current = tng_data->current_trajectory_frame_set_input_file_pos;
13183 tng_data->first_trajectory_frame_set_input_file_pos =
13184 tng_data->first_trajectory_frame_set_output_file_pos;
13185 tng_data->last_trajectory_frame_set_input_file_pos =
13186 tng_data->last_trajectory_frame_set_output_file_pos;
13187 tng_data->current_trajectory_frame_set_input_file_pos =
13188 tng_data->current_trajectory_frame_set_output_file_pos;
13190 tng_data->input_file = tng_data->output_file;
13192 stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
13194 frame_set = &tng_data->current_trajectory_frame_set;
13196 if(stat != TNG_SUCCESS)
13198 last_frame = frame_set->first_frame +
13199 frame_set->n_frames - 1;
13200 /* If the wanted frame would be in the frame set after the last
13201 * frame set create a new frame set. */
13202 if(stat == TNG_FAILURE &&
13203 last_frame < frame_nr)
13204 /* (last_frame < frame_nr &&
13205 tng_data->current_trajectory_frame_set.first_frame +
13206 tng_data->frame_set_n_frames >= frame_nr))*/
13208 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
13210 last_frame = frame_nr - 1;
13212 tng_frame_set_new(tng_data,
13214 tng_data->frame_set_n_frames);
13215 file_pos = ftello(tng_data->output_file);
13216 fseeko(tng_data->output_file, 0, SEEK_END);
13217 output_file_len = ftello(tng_data->output_file);
13218 fseeko(tng_data->output_file, file_pos, SEEK_SET);
13220 /* Read mapping blocks from the last frame set */
13221 tng_block_init(&block);
13223 stat = tng_block_header_read(tng_data, block);
13224 while(file_pos < output_file_len &&
13225 stat != TNG_CRITICAL &&
13226 block->id != TNG_TRAJECTORY_FRAME_SET &&
13229 if(block->id == TNG_PARTICLE_MAPPING)
13231 tng_trajectory_mapping_block_read(tng_data, block,
13236 fseeko(tng_data->output_file, block->block_contents_size,
13239 file_pos = ftello(tng_data->output_file);
13240 if(file_pos < output_file_len)
13242 stat = tng_block_header_read(tng_data, block);
13246 tng_block_destroy(&block);
13247 /* Write the frame set to disk */
13248 if(tng_frame_set_write(tng_data, hash_mode) != TNG_SUCCESS)
13250 fprintf(stderr, "TNG library: Error writing frame set. %s: %d\n", __FILE__, __LINE__);
13251 return(TNG_CRITICAL);
13256 tng_data->input_file = temp;
13257 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13258 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13259 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13264 tng_block_init(&block);
13266 file_pos = tng_data->current_trajectory_frame_set_output_file_pos;
13268 fseeko(tng_data->output_file, 0, SEEK_END);
13269 output_file_len = ftello(tng_data->output_file);
13270 fseeko(tng_data->output_file, file_pos, SEEK_SET);
13272 /* Read past the frame set block first */
13273 stat = tng_block_header_read(tng_data, block);
13274 if(stat == TNG_CRITICAL)
13276 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
13277 file_pos, __FILE__, __LINE__);
13278 tng_block_destroy(&block);
13279 tng_data->input_file = temp;
13281 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13282 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13283 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13286 fseeko(tng_data->output_file, block->block_contents_size,
13289 if(is_particle_data == TNG_TRUE)
13291 if(tng_data->var_num_atoms_flag)
13293 tot_n_particles = frame_set->n_particles;
13297 tot_n_particles = tng_data->n_particles;
13300 if(val_n_particles < tot_n_particles)
13302 mapping_block_end_pos = -1;
13303 /* Read all mapping blocks to find the right place to put the data */
13304 stat = tng_block_header_read(tng_data, block);
13305 while(file_pos < output_file_len &&
13306 stat != TNG_CRITICAL &&
13307 block->id != TNG_TRAJECTORY_FRAME_SET &&
13310 if(block->id == TNG_PARTICLE_MAPPING)
13312 tng_trajectory_mapping_block_read(tng_data, block, hash_mode);
13316 fseeko(tng_data->output_file, block->block_contents_size,
13319 file_pos = ftello(tng_data->output_file);
13320 if(block->id == TNG_PARTICLE_MAPPING)
13322 mapping = &frame_set->mappings[frame_set->n_mapping_blocks - 1];
13323 if(val_first_particle >= mapping->num_first_particle &&
13324 val_first_particle < mapping->num_first_particle +
13325 mapping->n_particles &&
13326 val_first_particle + val_n_particles <=
13327 mapping->num_first_particle + mapping->n_particles)
13329 mapping_block_end_pos = file_pos;
13332 if(file_pos < output_file_len)
13334 stat = tng_block_header_read(tng_data, block);
13337 if(stat == TNG_CRITICAL)
13339 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
13340 file_pos, __FILE__, __LINE__);
13341 tng_block_destroy(&block);
13342 tng_data->input_file = temp;
13344 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13345 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13346 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13349 if(mapping_block_end_pos < 0)
13351 tng_block_destroy(&block);
13352 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(TNG_FAILURE);
13359 fseeko(tng_data->output_file, mapping_block_end_pos, SEEK_SET);
13363 /* Read all block headers until next frame set block or
13364 * until the wanted block id is found */
13365 stat = tng_block_header_read(tng_data, block);
13366 while(file_pos < output_file_len &&
13367 stat != TNG_CRITICAL &&
13368 block->id != block_id &&
13369 (is_particle_data != TNG_TRUE || block->id != TNG_PARTICLE_MAPPING) &&
13370 block->id != TNG_TRAJECTORY_FRAME_SET &&
13373 fseeko(tng_data->output_file, block->block_contents_size, SEEK_CUR);
13374 file_pos = ftello(tng_data->output_file);
13375 if(file_pos < output_file_len)
13377 stat = tng_block_header_read(tng_data, block);
13380 if(stat == TNG_CRITICAL)
13382 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
13383 file_pos, __FILE__, __LINE__);
13384 tng_block_destroy(&block);
13385 tng_data->input_file = temp;
13386 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13387 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13388 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13392 contents_size = block->block_contents_size;
13393 header_size = block->header_contents_size;
13395 header_pos = ftello(tng_data->output_file) - header_size;
13396 frame_set = &tng_data->current_trajectory_frame_set;
13398 if(tng_file_input_numerical(tng_data, &datatype,
13400 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13402 tng_block_destroy(&block);
13403 return(TNG_CRITICAL);
13405 if(tng_file_input_numerical(tng_data, &dependency,
13406 sizeof(dependency),
13407 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13409 tng_block_destroy(&block);
13410 return(TNG_CRITICAL);
13412 data.datatype = datatype;
13414 if(!(dependency & TNG_FRAME_DEPENDENT) ||
13415 (is_particle_data == TNG_FALSE && dependency & TNG_PARTICLE_DEPENDENT) ||
13416 (is_particle_data == TNG_TRUE && !(dependency & TNG_PARTICLE_DEPENDENT)))
13418 tng_block_destroy(&block);
13419 tng_data->input_file = temp;
13421 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13422 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13423 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13424 return(TNG_FAILURE);
13427 if(tng_file_input_numerical(tng_data, &sparse_data,
13428 sizeof(sparse_data),
13429 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13431 tng_block_destroy(&block);
13432 return(TNG_CRITICAL);
13435 if(tng_file_input_numerical(tng_data, &data.n_values_per_frame,
13436 sizeof(data.n_values_per_frame),
13437 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13439 tng_block_destroy(&block);
13440 return(TNG_CRITICAL);
13443 if(tng_file_input_numerical(tng_data, &data.codec_id,
13444 sizeof(data.codec_id),
13445 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13447 tng_block_destroy(&block);
13448 return(TNG_CRITICAL);
13451 if(data.codec_id != TNG_UNCOMPRESSED)
13453 if(tng_file_input_numerical(tng_data, &data.compression_multiplier,
13454 sizeof(data.compression_multiplier),
13455 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13457 tng_block_destroy(&block);
13458 return(TNG_CRITICAL);
13463 data.compression_multiplier = 1;
13468 if(tng_file_input_numerical(tng_data, &data.first_frame_with_data,
13469 sizeof(data.first_frame_with_data),
13470 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13472 tng_block_destroy(&block);
13473 return(TNG_CRITICAL);
13476 if(tng_file_input_numerical(tng_data, &data.stride_length,
13477 sizeof(data.stride_length),
13478 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13480 tng_block_destroy(&block);
13481 return(TNG_CRITICAL);
13486 data.first_frame_with_data = 0;
13487 data.stride_length = 1;
13489 data.n_frames = tng_data->current_trajectory_frame_set.n_frames;
13491 if(is_particle_data == TNG_TRUE)
13493 if(tng_file_input_numerical(tng_data, &num_first_particle,
13494 sizeof(num_first_particle),
13495 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13497 tng_block_destroy(&block);
13498 return(TNG_CRITICAL);
13501 if(tng_file_input_numerical(tng_data, &block_n_particles,
13502 sizeof(block_n_particles),
13503 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13505 tng_block_destroy(&block);
13506 return(TNG_CRITICAL);
13510 tng_data->input_file = temp;
13512 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13513 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13514 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13516 switch(data.datatype)
13518 case(TNG_INT_DATA):
13519 size = sizeof(int64_t);
13521 case(TNG_FLOAT_DATA):
13522 size = sizeof(float);
13524 case(TNG_DOUBLE_DATA):
13525 size = sizeof(double);
13528 fprintf(stderr, "TNG library: Cannot calculate writing locations. %s: %d.\n", __FILE__,
13530 tng_block_destroy(&block);
13531 return(TNG_FAILURE);
13534 n_values_per_frame = data.n_values_per_frame;
13536 file_pos = (frame_nr - tng_max_i64(frame_set->first_frame,
13537 data.first_frame_with_data)) /
13538 data.stride_length;
13539 if(is_particle_data == TNG_TRUE)
13541 file_pos *= block_n_particles * size * n_values_per_frame;
13545 file_pos *= size * n_values_per_frame;
13548 if(file_pos > contents_size)
13550 fprintf(stderr, "TNG library: Attempting to write outside the block. %s: %d\n", __FILE__,
13552 tng_block_destroy(&block);
13553 return(TNG_FAILURE);
13556 fseeko(tng_data->output_file, file_pos, SEEK_CUR);
13558 if(is_particle_data == TNG_TRUE)
13560 write_n_particles = val_n_particles;
13564 write_n_particles = 1;
13567 /* If the endianness is not big endian the data needs to be swapped */
13568 if((data.datatype == TNG_INT_DATA ||
13569 data.datatype == TNG_DOUBLE_DATA) &&
13570 tng_data->output_endianness_swap_func_64)
13572 copy = (char *)malloc(write_n_particles * n_values_per_frame * size);
13573 memcpy(copy, values, write_n_particles * n_values_per_frame * size);
13574 for(i = 0; i < write_n_particles * n_values_per_frame; i++)
13576 if(tng_data->output_endianness_swap_func_64(tng_data,
13577 (uint64_t *) copy+i)
13580 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13581 __FILE__, __LINE__);
13584 fwrite(copy, write_n_particles * n_values_per_frame, size,
13585 tng_data->output_file);
13588 else if(data.datatype == TNG_FLOAT_DATA &&
13589 tng_data->output_endianness_swap_func_32)
13591 copy = (char *)malloc(write_n_particles * n_values_per_frame * size);
13592 memcpy(copy, values, write_n_particles * n_values_per_frame * size);
13593 for(i = 0; i < write_n_particles * n_values_per_frame; i++)
13595 if(tng_data->output_endianness_swap_func_32(tng_data,
13596 (uint32_t *) copy+i)
13599 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13600 __FILE__, __LINE__);
13603 fwrite(copy, write_n_particles * n_values_per_frame, size,
13604 tng_data->output_file);
13610 fwrite(values, write_n_particles * n_values_per_frame, size, tng_data->output_file);
13613 fflush(tng_data->output_file);
13615 /* Update the number of written frames in the frame set. */
13616 if(frame_nr - frame_set->first_frame + 1 > frame_set->n_written_frames)
13618 frame_set->n_written_frames = frame_nr - frame_set->first_frame + 1;
13621 /* If the last frame has been written update the hash */
13622 if(hash_mode == TNG_USE_HASH && (frame_nr + data.stride_length -
13623 data.first_frame_with_data) >=
13624 frame_set->n_frames)
13626 tng_md5_hash_update(tng_data, block, header_pos, header_pos +
13630 tng_block_destroy(&block);
13632 return(TNG_SUCCESS);
13635 tng_function_status DECLSPECDLLEXPORT tng_frame_data_write
13636 (const tng_trajectory_t tng_data,
13637 const int64_t frame_nr,
13638 const int64_t block_id,
13639 const void *values,
13640 const char hash_mode)
13642 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13643 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
13644 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer.");
13646 /* This is now just calling the generic data writing function. This
13647 * function must keep its signature to let the API be backwards
13649 return(tng_frame_gen_data_write(tng_data, frame_nr, block_id,
13650 TNG_FALSE, 0, 0, values, hash_mode));
13653 tng_function_status DECLSPECDLLEXPORT tng_frame_particle_data_write
13654 (const tng_trajectory_t tng_data,
13655 const int64_t frame_nr,
13656 const int64_t block_id,
13657 const int64_t val_first_particle,
13658 const int64_t val_n_particles,
13659 const void *values,
13660 const char hash_mode)
13662 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13663 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
13664 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer.");
13665 TNG_ASSERT(val_first_particle >= 0, "TNG library: val_first_particle must be >= 0.");
13666 TNG_ASSERT(val_n_particles >= 0, "TNG library: val_n_particles must be >= 0.");
13668 /* This is now just calling the generic data writing function. This
13669 * function must keep its signature to let the API be backwards
13671 return(tng_frame_gen_data_write(tng_data, frame_nr, block_id,
13672 TNG_TRUE, val_first_particle, val_n_particles,
13673 values, hash_mode));
13676 static tng_function_status tng_data_values_alloc
13677 (const tng_trajectory_t tng_data,
13678 union data_values ***values,
13679 const int64_t n_frames,
13680 const int64_t n_values_per_frame,
13684 tng_function_status stat;
13686 if(n_frames <= 0 || n_values_per_frame <= 0)
13688 return(TNG_FAILURE);
13693 stat = tng_data_values_free(tng_data, *values, n_frames,
13694 n_values_per_frame,
13696 if(stat != TNG_SUCCESS)
13698 fprintf(stderr, "TNG library: Cannot free particle data values. %s: %d\n",
13699 __FILE__, __LINE__);
13703 *values = (union data_values **)malloc(sizeof(union data_values *) * n_frames);
13706 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
13707 __FILE__, __LINE__);
13708 return(TNG_CRITICAL);
13712 for(i = 0; i < n_frames; i++)
13714 (*values)[i] = (union data_values *)malloc(sizeof(union data_values) *
13715 n_values_per_frame);
13718 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
13719 __FILE__, __LINE__);
13722 return(TNG_CRITICAL);
13725 return(TNG_SUCCESS);
13728 /* FIXME: This needs ***values */
13729 tng_function_status DECLSPECDLLEXPORT tng_data_values_free
13730 (const tng_trajectory_t tng_data,
13731 union data_values **values,
13732 const int64_t n_frames,
13733 const int64_t n_values_per_frame,
13741 for(i = 0; i < n_frames; i++)
13745 if(type == TNG_CHAR_DATA)
13747 for(j = 0; j < n_values_per_frame; j++)
13751 free(values[i][j].c);
13752 values[i][j].c = 0;
13764 return(TNG_SUCCESS);
13767 static tng_function_status tng_particle_data_values_alloc
13768 (const tng_trajectory_t tng_data,
13769 union data_values ****values,
13770 const int64_t n_frames,
13771 const int64_t n_particles,
13772 const int64_t n_values_per_frame,
13776 tng_function_status stat;
13778 if(n_particles == 0 || n_values_per_frame == 0)
13780 return(TNG_FAILURE);
13785 stat = tng_particle_data_values_free(tng_data, *values, n_frames,
13786 n_particles, n_values_per_frame,
13788 if(stat != TNG_SUCCESS)
13790 fprintf(stderr, "TNG library: Cannot free particle data values. %s: %d\n",
13791 __FILE__, __LINE__);
13795 *values = (union data_values ***)malloc(sizeof(union data_values **) * n_frames);
13798 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
13799 __FILE__, __LINE__);
13800 return(TNG_CRITICAL);
13804 for(i = 0; i < n_frames; i++)
13806 (*values)[i] = (union data_values **)malloc(sizeof(union data_values *) *
13810 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
13811 __FILE__, __LINE__);
13814 return(TNG_CRITICAL);
13816 for(j = 0; j < n_particles; j++)
13818 (*values)[i][j] = (union data_values *)malloc(sizeof(union data_values) *
13819 n_values_per_frame);
13820 if(!(*values)[i][j])
13822 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
13823 __FILE__, __LINE__);
13824 tng_particle_data_values_free(tng_data, *values, n_frames,
13825 n_particles, n_values_per_frame,
13828 return(TNG_CRITICAL);
13832 return(TNG_SUCCESS);
13835 /* FIXME: This needs ****values */
13836 tng_function_status DECLSPECDLLEXPORT tng_particle_data_values_free
13837 (const tng_trajectory_t tng_data,
13838 union data_values ***values,
13839 const int64_t n_frames,
13840 const int64_t n_particles,
13841 const int64_t n_values_per_frame,
13849 for(i = 0; i < n_frames; i++)
13853 for(j = 0; j < n_particles; j++)
13855 if(type == TNG_CHAR_DATA)
13857 for(k = 0; k < n_values_per_frame; k++)
13859 if(values[i][j][k].c)
13861 free(values[i][j][k].c);
13862 values[i][j][k].c = 0;
13866 free(values[i][j]);
13877 return(TNG_SUCCESS);
13880 static tng_function_status tng_gen_data_get
13881 (const tng_trajectory_t tng_data,
13882 const int64_t block_id,
13883 const tng_bool is_particle_data,
13884 union data_values ****values,
13886 int64_t *n_particles,
13887 int64_t *n_values_per_frame,
13890 int64_t i, j, k, mapping, file_pos, i_step, block_index;
13894 tng_trajectory_frame_set_t frame_set;
13895 tng_gen_block_t block;
13896 char block_type_flag;
13897 tng_function_status stat;
13899 frame_set = &tng_data->current_trajectory_frame_set;
13904 if(is_particle_data == TNG_TRUE)
13906 stat = tng_particle_data_find(tng_data, block_id, &data);
13910 stat = tng_data_find(tng_data, block_id, &data);
13913 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
13915 block_type_flag = TNG_TRAJECTORY_BLOCK;
13919 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
13922 if(stat != TNG_SUCCESS)
13924 tng_block_init(&block);
13925 file_pos = ftello(tng_data->input_file);
13926 /* Read all blocks until next frame set block */
13927 stat = tng_block_header_read(tng_data, block);
13928 while(file_pos < tng_data->input_file_len &&
13929 stat != TNG_CRITICAL &&
13930 block->id != TNG_TRAJECTORY_FRAME_SET &&
13933 /* Use hash by default */
13934 stat = tng_block_read_next(tng_data, block,
13936 if(stat != TNG_CRITICAL)
13938 file_pos = ftello(tng_data->input_file);
13939 if(file_pos < tng_data->input_file_len)
13941 stat = tng_block_header_read(tng_data, block);
13945 tng_block_destroy(&block);
13946 if(stat == TNG_CRITICAL)
13948 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
13949 file_pos, __FILE__, __LINE__);
13953 if(is_particle_data == TNG_TRUE)
13955 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
13957 data = &frame_set->tr_particle_data[i];
13958 if(data->block_id == block_id)
13961 block_type_flag = TNG_TRAJECTORY_BLOCK;
13968 for(i = 0; i < frame_set->n_data_blocks; i++)
13970 data = &frame_set->tr_data[i];
13971 if(data->block_id == block_id)
13978 if(block_index < 0)
13980 return(TNG_FAILURE);
13984 if(is_particle_data == TNG_TRUE)
13986 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
13987 tng_data->var_num_atoms_flag)
13989 *n_particles = frame_set->n_particles;
13993 *n_particles = tng_data->n_particles;
13997 *n_frames = tng_max_i64(1, data->n_frames);
13998 *n_values_per_frame = data->n_values_per_frame;
13999 *type = data->datatype;
14001 if(is_particle_data == TNG_TRUE)
14005 if(tng_particle_data_values_alloc(tng_data, values, *n_frames,
14006 *n_particles, *n_values_per_frame,
14007 *type) != TNG_SUCCESS)
14009 return(TNG_CRITICAL);
14013 i_step = (*n_particles) * (*n_values_per_frame);
14015 /* It's not very elegant to reuse so much of the code in the different case
14016 * statements, but it's unnecessarily slow to have the switch-case block
14017 * inside the for loops. */
14020 case TNG_CHAR_DATA:
14021 for(i = 0; i < *n_frames; i++)
14023 for(j = 0; j < *n_particles; j++)
14025 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14026 for(k = 0; k < *n_values_per_frame; k++)
14028 len = strlen(data->strings[i][j][k]) + 1;
14029 (*values)[i][mapping][k].c = (char *)malloc(len);
14030 strncpy((*values)[i][mapping][k].c,
14031 data->strings[i][j][k], len);
14037 size = sizeof(int);
14038 for(i = 0; i < *n_frames; i++)
14040 for(j = 0; j < *n_particles; j++)
14042 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14043 for(k = 0; k < *n_values_per_frame; k++)
14045 (*values)[i][mapping][k].i = *(int *)
14046 ((char *)data->values + size *
14048 (*n_values_per_frame) + k));
14053 case TNG_FLOAT_DATA:
14054 size = sizeof(float);
14055 for(i = 0; i < *n_frames; i++)
14057 for(j = 0; j < *n_particles; j++)
14059 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14060 for(k = 0; k < *n_values_per_frame; k++)
14062 (*values)[i][mapping][k].f = *(float *)
14063 ((char *)data->values + size *
14065 (*n_values_per_frame) + k));
14070 case TNG_DOUBLE_DATA:
14072 size = sizeof(double);
14073 for(i = 0; i < *n_frames; i++)
14075 for(j = 0; j < *n_particles; j++)
14077 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14078 for(k = 0; k < *n_values_per_frame; k++)
14080 (*values)[i][mapping][k].d = *(double *)
14081 ((char *)data->values + size *
14083 (*n_values_per_frame) + k));
14091 if(*(values[0]) == 0)
14093 if(tng_data_values_alloc(tng_data, values[0], *n_frames,
14094 *n_values_per_frame,
14095 *type) != TNG_SUCCESS)
14097 return(TNG_CRITICAL);
14102 case TNG_CHAR_DATA:
14103 for(i = 0; i < *n_frames; i++)
14105 for(j = 0; j < *n_values_per_frame; j++)
14107 len = strlen(data->strings[0][i][j]) + 1;
14108 (*values)[0][i][j].c = (char *)malloc(len);
14109 strncpy((*values)[0][i][j].c, data->strings[0][i][j], len);
14114 size = sizeof(int);
14115 for(i = 0; i < *n_frames; i++)
14117 for(j = 0; j < *n_values_per_frame; j++)
14119 (*values)[0][i][j].i = *(int *)((char *)data->values + size *
14120 (i*(*n_values_per_frame) + j));
14124 case TNG_FLOAT_DATA:
14125 size = sizeof(float);
14126 for(i = 0; i < *n_frames; i++)
14128 for(j = 0; j < *n_values_per_frame; j++)
14130 (*values)[0][i][j].f = *(float *)((char *)data->values + size *
14131 (i*(*n_values_per_frame) + j));
14135 case TNG_DOUBLE_DATA:
14137 size = sizeof(double);
14138 for(i = 0; i < *n_frames; i++)
14140 for(j = 0; j < *n_values_per_frame; j++)
14142 (*values)[0][i][j].d = *(double *)((char *)data->values + size *
14143 (i*(*n_values_per_frame) + j));
14149 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
14151 return(TNG_SUCCESS);
14154 tng_function_status DECLSPECDLLEXPORT tng_data_get
14155 (const tng_trajectory_t tng_data,
14156 const int64_t block_id,
14157 union data_values ***values,
14159 int64_t *n_values_per_frame,
14162 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14163 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
14164 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
14165 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
14167 return(tng_gen_data_get(tng_data, block_id, TNG_FALSE, &values, n_frames, 0,
14168 n_values_per_frame, type));
14171 static tng_function_status tng_gen_data_vector_get
14172 (const tng_trajectory_t tng_data,
14173 const int64_t block_id,
14174 const tng_bool is_particle_data,
14177 int64_t *stride_length,
14178 int64_t *n_particles,
14179 int64_t *n_values_per_frame,
14182 int64_t i, j, mapping, file_pos, i_step, full_data_len, n_frames_div;
14183 int64_t block_index;
14186 tng_trajectory_frame_set_t frame_set;
14187 tng_gen_block_t block;
14189 char block_type_flag;
14190 tng_function_status stat;
14192 frame_set = &tng_data->current_trajectory_frame_set;
14197 if(is_particle_data == TNG_TRUE)
14199 stat = tng_particle_data_find(tng_data, block_id, &data);
14203 stat = tng_data_find(tng_data, block_id, &data);
14206 if(stat != TNG_SUCCESS)
14208 tng_block_init(&block);
14209 file_pos = ftello(tng_data->input_file);
14210 /* Read all blocks until next frame set block */
14211 stat = tng_block_header_read(tng_data, block);
14212 while(file_pos < tng_data->input_file_len &&
14213 stat != TNG_CRITICAL &&
14214 block->id != TNG_TRAJECTORY_FRAME_SET &&
14217 /* Use hash by default */
14218 stat = tng_block_read_next(tng_data, block,
14220 if(stat != TNG_CRITICAL)
14222 file_pos = ftello(tng_data->input_file);
14223 if(file_pos < tng_data->input_file_len)
14225 stat = tng_block_header_read(tng_data, block);
14229 tng_block_destroy(&block);
14230 if(stat == TNG_CRITICAL)
14232 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
14233 file_pos, __FILE__, __LINE__);
14237 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
14239 data = &frame_set->tr_particle_data[i];
14240 if(data->block_id == block_id)
14246 if(block_index < 0)
14248 return(TNG_FAILURE);
14252 if(is_particle_data == TNG_TRUE)
14254 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
14256 block_type_flag = TNG_TRAJECTORY_BLOCK;
14260 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
14263 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
14264 tng_data->var_num_atoms_flag)
14266 *n_particles = frame_set->n_particles;
14270 *n_particles = tng_data->n_particles;
14274 *type = data->datatype;
14278 case TNG_CHAR_DATA:
14279 return(TNG_FAILURE);
14281 size = sizeof(int64_t);
14283 case TNG_FLOAT_DATA:
14284 size = sizeof(float);
14286 case TNG_DOUBLE_DATA:
14288 size = sizeof(double);
14291 *n_frames = tng_max_i64(1, data->n_frames);
14292 *n_values_per_frame = data->n_values_per_frame;
14293 *stride_length = data->stride_length;
14295 n_frames_div = (*n_frames % *stride_length) ?
14296 *n_frames / *stride_length + 1:
14297 *n_frames / *stride_length;
14299 full_data_len = n_frames_div * size *
14300 (*n_values_per_frame);
14301 if(is_particle_data == TNG_TRUE)
14303 full_data_len *= (*n_particles);
14306 temp = (char *)realloc(*values, full_data_len);
14309 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
14310 __FILE__, __LINE__);
14313 return(TNG_CRITICAL);
14318 if(is_particle_data != TNG_TRUE || frame_set->n_mapping_blocks <= 0)
14320 memcpy(*values, data->values, full_data_len);
14324 i_step = (*n_particles) * (*n_values_per_frame);
14325 for(i = 0; i < *n_frames; i++)
14327 for(j = 0; j < *n_particles; j++)
14329 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14330 memcpy(((char *)*values) + size * (i * i_step + mapping *
14331 (*n_values_per_frame)),
14332 (char *)data->values + size *
14333 (i * i_step + j * (*n_values_per_frame)),
14334 size * (*n_values_per_frame));
14339 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
14341 return(TNG_SUCCESS);
14344 tng_function_status DECLSPECDLLEXPORT tng_data_vector_get
14345 (const tng_trajectory_t tng_data,
14346 const int64_t block_id,
14349 int64_t *stride_length,
14350 int64_t *n_values_per_frame,
14353 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14354 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
14355 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
14356 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
14357 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
14359 return(tng_gen_data_vector_get(tng_data, block_id, TNG_FALSE, values,
14360 n_frames, stride_length, 0, n_values_per_frame,
14364 static tng_function_status tng_gen_data_interval_get
14365 (const tng_trajectory_t tng_data,
14366 const int64_t block_id,
14367 const tng_bool is_particle_data,
14368 const int64_t start_frame_nr,
14369 const int64_t end_frame_nr,
14370 const char hash_mode,
14371 union data_values ****values,
14372 int64_t *n_particles,
14373 int64_t *n_values_per_frame,
14376 int64_t i, j, k, mapping, n_frames, file_pos, current_frame_pos, i_step;
14377 int64_t first_frame, block_index;
14381 tng_trajectory_frame_set_t frame_set;
14382 tng_gen_block_t block;
14383 char block_type_flag;
14384 tng_function_status stat;
14388 frame_set = &tng_data->current_trajectory_frame_set;
14389 first_frame = frame_set->first_frame;
14391 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
14392 if(stat != TNG_SUCCESS)
14397 /* Do not re-read the frame set. */
14398 if((is_particle_data == TNG_TRUE &&
14399 (first_frame != frame_set->first_frame ||
14400 frame_set->n_particle_data_blocks <= 0)) ||
14401 (is_particle_data == TNG_FALSE &&
14402 (first_frame != frame_set->first_frame ||
14403 frame_set->n_data_blocks <= 0)))
14405 tng_block_init(&block);
14406 file_pos = ftello(tng_data->input_file);
14407 /* Read all blocks until next frame set block */
14408 stat = tng_block_header_read(tng_data, block);
14409 while(file_pos < tng_data->input_file_len &&
14410 stat != TNG_CRITICAL &&
14411 block->id != TNG_TRAJECTORY_FRAME_SET &&
14414 stat = tng_block_read_next(tng_data, block,
14416 if(stat != TNG_CRITICAL)
14418 file_pos = ftello(tng_data->input_file);
14419 if(file_pos < tng_data->input_file_len)
14421 stat = tng_block_header_read(tng_data, block);
14425 tng_block_destroy(&block);
14426 if(stat == TNG_CRITICAL)
14428 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
14429 file_pos, __FILE__, __LINE__);
14434 /* See if there is already a data block of this ID.
14435 * Start checking the last read frame set */
14436 if(is_particle_data == TNG_TRUE)
14438 for(i = frame_set->n_particle_data_blocks; i-- ;)
14440 data = &frame_set->tr_particle_data[i];
14441 if(data->block_id == block_id)
14444 block_type_flag = TNG_TRAJECTORY_BLOCK;
14451 for(i = 0; i < frame_set->n_data_blocks; i++)
14453 data = &frame_set->tr_data[i];
14454 if(data->block_id == block_id)
14462 if(block_index < 0)
14464 fprintf(stderr, "TNG library: Could not find particle data block with id %" PRId64 ". %s: %d\n",
14465 block_id, __FILE__, __LINE__);
14466 return(TNG_FAILURE);
14469 if(is_particle_data == TNG_TRUE)
14471 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
14472 tng_data->var_num_atoms_flag)
14474 *n_particles = frame_set->n_particles;
14478 *n_particles = tng_data->n_particles;
14482 n_frames = end_frame_nr - start_frame_nr + 1;
14483 *n_values_per_frame = data->n_values_per_frame;
14484 *type = data->datatype;
14488 if(is_particle_data == TNG_TRUE)
14490 if(tng_particle_data_values_alloc(tng_data, values, n_frames,
14491 *n_particles, *n_values_per_frame,
14492 *type) != TNG_SUCCESS)
14494 return(TNG_CRITICAL);
14499 if(tng_data_values_alloc(tng_data, *values, n_frames,
14500 *n_values_per_frame,
14501 *type) != TNG_SUCCESS)
14503 return(TNG_CRITICAL);
14508 current_frame_pos = start_frame_nr - frame_set->first_frame;
14510 if(is_particle_data == TNG_TRUE)
14512 i_step = (*n_particles) * (*n_values_per_frame);
14516 i_step = (*n_values_per_frame);
14518 /* It's not very elegant to reuse so much of the code in the different case
14519 * statements, but it's unnecessarily slow to have the switch-case block
14520 * inside the for loops. */
14523 case TNG_CHAR_DATA:
14524 for(i=0; i<n_frames; i++)
14526 if(current_frame_pos == frame_set->n_frames)
14528 stat = tng_frame_set_read_next(tng_data, hash_mode);
14529 if(stat != TNG_SUCCESS)
14533 current_frame_pos = 0;
14535 if(is_particle_data == TNG_TRUE)
14537 for(j = 0; j < *n_particles; j++)
14539 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14540 for(k = 0; k < *n_values_per_frame; k++)
14542 len = strlen(data->strings[current_frame_pos][j][k]) + 1;
14543 (*values)[i][mapping][k].c = (char *)malloc(len);
14544 strncpy((*values)[i][mapping][k].c, data->strings[current_frame_pos][j][k], len);
14550 for(j = 0; j < *n_values_per_frame; j++)
14552 len = strlen(data->strings[0][current_frame_pos][j]) + 1;
14553 (*values)[0][i][j].c = (char *)malloc(len);
14554 strncpy((*values)[0][i][j].c, data->strings[0][current_frame_pos][j], len);
14557 current_frame_pos++;
14561 size = sizeof(int);
14562 for(i=0; i<n_frames; i++)
14564 if(current_frame_pos == frame_set->n_frames)
14566 stat = tng_frame_set_read_next(tng_data, hash_mode);
14567 if(stat != TNG_SUCCESS)
14571 current_frame_pos = 0;
14573 if(is_particle_data == TNG_TRUE)
14575 for(j = 0; j < *n_particles; j++)
14577 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14578 for(k = 0; k < *n_values_per_frame; k++)
14580 (*values)[i][mapping][k].i = *(int *)
14581 ((char *)data->values + size *
14582 (current_frame_pos *
14584 (*n_values_per_frame) + k));
14587 current_frame_pos++;
14591 for(j = 0; j < *n_values_per_frame; j++)
14593 (*values)[0][i][j].i = *(int *)((char *)data->values + size *
14594 (current_frame_pos *
14600 case TNG_FLOAT_DATA:
14601 size = sizeof(float);
14602 for(i=0; i<n_frames; i++)
14604 if(current_frame_pos == frame_set->n_frames)
14606 stat = tng_frame_set_read_next(tng_data, hash_mode);
14607 if(stat != TNG_SUCCESS)
14611 current_frame_pos = 0;
14613 if(is_particle_data == TNG_TRUE)
14615 for(j=0; j<*n_particles; j++)
14617 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14618 for(k=0; k<*n_values_per_frame; k++)
14620 (*values)[i][mapping][k].f = *(float *)
14621 ((char *)data->values + size *
14622 (current_frame_pos *
14624 (*n_values_per_frame) + k));
14630 for(j = 0; j < *n_values_per_frame; j++)
14632 (*values)[0][i][j].f = *(float *)((char *)data->values + size *
14633 (current_frame_pos *
14637 current_frame_pos++;
14640 case TNG_DOUBLE_DATA:
14642 size = sizeof(double);
14643 for(i=0; i<n_frames; i++)
14645 if(current_frame_pos == frame_set->n_frames)
14647 stat = tng_frame_set_read_next(tng_data, hash_mode);
14648 if(stat != TNG_SUCCESS)
14652 current_frame_pos = 0;
14654 if(is_particle_data == TNG_TRUE)
14656 for(j=0; j<*n_particles; j++)
14658 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14659 for(k=0; k<*n_values_per_frame; k++)
14661 (*values)[i][mapping][k].d = *(double *)
14662 ((char *)data->values + size *
14663 (current_frame_pos *
14665 (*n_values_per_frame) + k));
14671 for(j = 0; j < *n_values_per_frame; j++)
14673 (*values)[0][i][j].d = *(double *)((char *)data->values + size *
14674 (current_frame_pos *
14678 current_frame_pos++;
14682 data->last_retrieved_frame = end_frame_nr;
14684 return(TNG_SUCCESS);
14687 tng_function_status DECLSPECDLLEXPORT tng_data_interval_get
14688 (const tng_trajectory_t tng_data,
14689 const int64_t block_id,
14690 const int64_t start_frame_nr,
14691 const int64_t end_frame_nr,
14692 const char hash_mode,
14693 union data_values ***values,
14694 int64_t *n_values_per_frame,
14697 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14698 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
14699 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
14700 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
14702 return(tng_gen_data_interval_get(tng_data, block_id, TNG_FALSE, start_frame_nr,
14703 end_frame_nr, hash_mode, &values, 0,
14704 n_values_per_frame, type));
14707 static tng_function_status tng_gen_data_vector_interval_get
14708 (const tng_trajectory_t tng_data,
14709 const int64_t block_id,
14710 const tng_bool is_particle_data,
14711 const int64_t start_frame_nr,
14712 const int64_t end_frame_nr,
14713 const char hash_mode,
14715 int64_t *n_particles,
14716 int64_t *stride_length,
14717 int64_t *n_values_per_frame,
14720 int64_t n_frames, tot_n_frames, n_frames_div, n_frames_div_2, first_frame;
14721 int64_t file_pos, current_frame_pos, last_frame_pos, full_data_len, frame_size;
14723 tng_trajectory_frame_set_t frame_set;
14725 tng_gen_block_t block;
14726 void *current_values = 0, *temp;
14727 tng_function_status stat;
14729 frame_set = &tng_data->current_trajectory_frame_set;
14730 first_frame = frame_set->first_frame;
14732 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
14733 if(stat != TNG_SUCCESS)
14738 /* Do not re-read the frame set and only need the requested block + particle mapping blocks. */
14739 /* TODO: Test that blocks are read correctly now that now all of them are read at the same time. */
14740 if(is_particle_data == TNG_TRUE)
14742 stat = tng_particle_data_find(tng_data, block_id, &data);
14746 stat = tng_data_find(tng_data, block_id, &data);
14749 if(first_frame != frame_set->first_frame ||
14750 stat != TNG_SUCCESS)
14752 tng_block_init(&block);
14753 if(stat != TNG_SUCCESS)
14755 fseeko(tng_data->input_file,
14756 tng_data->current_trajectory_frame_set_input_file_pos,
14758 stat = tng_block_header_read(tng_data, block);
14759 if(stat != TNG_SUCCESS)
14761 fprintf(stderr, "TNG library: Cannot read block header. %s: %d\n",
14762 __FILE__, __LINE__);
14766 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
14768 file_pos = ftello(tng_data->input_file);
14769 /* Read until next frame set block */
14770 stat = tng_block_header_read(tng_data, block);
14771 while(file_pos < tng_data->input_file_len &&
14772 stat != TNG_CRITICAL &&
14773 block->id != TNG_TRAJECTORY_FRAME_SET &&
14776 if(block->id == block_id || block->id == TNG_PARTICLE_MAPPING)
14778 stat = tng_block_read_next(tng_data, block,
14780 if(stat != TNG_CRITICAL)
14782 file_pos = ftello(tng_data->input_file);
14783 if(file_pos < tng_data->input_file_len)
14785 stat = tng_block_header_read(tng_data, block);
14791 file_pos += block->block_contents_size + block->header_contents_size;
14792 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
14793 if(file_pos < tng_data->input_file_len)
14795 stat = tng_block_header_read(tng_data, block);
14799 tng_block_destroy(&block);
14800 if(stat == TNG_CRITICAL)
14802 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
14803 file_pos, __FILE__, __LINE__);
14807 if(is_particle_data == TNG_TRUE)
14809 stat = tng_particle_data_find(tng_data, block_id, &data);
14813 stat = tng_data_find(tng_data, block_id, &data);
14815 if(stat != TNG_SUCCESS)
14820 stat = tng_gen_data_vector_get(tng_data, block_id, is_particle_data,
14821 ¤t_values, &n_frames, stride_length,
14822 n_particles, n_values_per_frame, type);
14824 if(stat != TNG_SUCCESS || (is_particle_data && *n_particles == 0))
14828 free(current_values);
14833 if(n_frames == 1 && n_frames < frame_set->n_frames)
14839 tot_n_frames = end_frame_nr - start_frame_nr + 1;
14844 case TNG_CHAR_DATA:
14845 return(TNG_FAILURE);
14847 size = sizeof(int64_t);
14849 case TNG_FLOAT_DATA:
14850 size = sizeof(float);
14852 case TNG_DOUBLE_DATA:
14854 size = sizeof(double);
14857 n_frames_div = (tot_n_frames % *stride_length) ?
14858 tot_n_frames / *stride_length + 1:
14859 tot_n_frames / *stride_length;
14861 full_data_len = n_frames_div * size * (*n_values_per_frame);
14862 if(is_particle_data)
14864 full_data_len *= (*n_particles);
14867 temp = (char *)realloc(*values, full_data_len);
14870 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
14871 __FILE__, __LINE__);
14874 return(TNG_CRITICAL);
14879 if( n_frames == 1 && n_frames < frame_set->n_frames)
14881 if(is_particle_data)
14883 memcpy(*values, current_values, size * (*n_particles) *
14884 (*n_values_per_frame));
14888 memcpy(*values, current_values, size * (*n_values_per_frame));
14893 current_frame_pos = start_frame_nr - frame_set->first_frame;
14895 frame_size = size * (*n_values_per_frame);
14896 if(is_particle_data)
14898 frame_size *= (*n_particles);
14901 last_frame_pos = tng_min_i64(n_frames,
14902 end_frame_nr - start_frame_nr);
14904 n_frames_div = current_frame_pos / *stride_length;
14905 n_frames_div_2 = (last_frame_pos % *stride_length) ?
14906 last_frame_pos / *stride_length + 1:
14907 last_frame_pos / *stride_length;
14908 n_frames_div_2 = tng_max_i64(1, n_frames_div_2 + 1);
14910 memcpy(*values, (char *)current_values + n_frames_div * frame_size,
14911 n_frames_div_2 * frame_size);
14913 current_frame_pos += n_frames - current_frame_pos;
14915 while(current_frame_pos <= end_frame_nr - start_frame_nr)
14917 stat = tng_frame_set_read_next(tng_data, hash_mode);
14918 if(stat != TNG_SUCCESS)
14922 free(current_values);
14929 stat = tng_gen_data_vector_get(tng_data, block_id, is_particle_data,
14930 ¤t_values, &n_frames,
14931 stride_length, n_particles,
14932 n_values_per_frame, type);
14934 if(stat != TNG_SUCCESS)
14938 free(current_values);
14945 last_frame_pos = tng_min_i64(n_frames,
14946 end_frame_nr - current_frame_pos);
14948 n_frames_div = current_frame_pos / *stride_length;
14949 n_frames_div_2 = (last_frame_pos % *stride_length) ?
14950 last_frame_pos / *stride_length + 1:
14951 last_frame_pos / *stride_length;
14952 n_frames_div_2 = tng_max_i64(1, n_frames_div_2);
14954 memcpy(((char *)*values) + n_frames_div * frame_size,
14956 n_frames_div_2 * frame_size);
14958 current_frame_pos += n_frames;
14964 free(current_values);
14967 data->last_retrieved_frame = end_frame_nr;
14969 return(TNG_SUCCESS);
14973 tng_function_status DECLSPECDLLEXPORT tng_data_vector_interval_get
14974 (const tng_trajectory_t tng_data,
14975 const int64_t block_id,
14976 const int64_t start_frame_nr,
14977 const int64_t end_frame_nr,
14978 const char hash_mode,
14980 int64_t *stride_length,
14981 int64_t *n_values_per_frame,
14984 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14985 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than the end_frame_nr.");
14986 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
14987 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
14988 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
14990 return(tng_gen_data_vector_interval_get(tng_data, block_id, TNG_FALSE,
14991 start_frame_nr, end_frame_nr,
14992 hash_mode, values, 0, stride_length,
14993 n_values_per_frame, type));
14996 tng_function_status DECLSPECDLLEXPORT tng_particle_data_get
14997 (const tng_trajectory_t tng_data,
14998 const int64_t block_id,
14999 union data_values ****values,
15001 int64_t *n_particles,
15002 int64_t *n_values_per_frame,
15005 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15006 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
15007 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
15008 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15009 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15011 return(tng_gen_data_get(tng_data, block_id, TNG_TRUE, values, n_frames, n_particles,
15012 n_values_per_frame, type));
15015 tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_get
15016 (const tng_trajectory_t tng_data,
15017 const int64_t block_id,
15020 int64_t *stride_length,
15021 int64_t *n_particles,
15022 int64_t *n_values_per_frame,
15025 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15026 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
15027 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
15028 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15029 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15031 return(tng_gen_data_vector_get(tng_data, block_id, TNG_TRUE, values,
15032 n_frames, stride_length, n_particles,
15033 n_values_per_frame, type));
15036 tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
15037 (const tng_trajectory_t tng_data,
15038 const int64_t block_id,
15039 const int64_t start_frame_nr,
15040 const int64_t end_frame_nr,
15041 const char hash_mode,
15042 union data_values ****values,
15043 int64_t *n_particles,
15044 int64_t *n_values_per_frame,
15047 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15048 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
15049 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
15050 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15051 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15053 return(tng_gen_data_interval_get(tng_data, block_id, TNG_TRUE, start_frame_nr,
15054 end_frame_nr, hash_mode, values, n_particles,
15055 n_values_per_frame, type));
15058 tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_interval_get
15059 (const tng_trajectory_t tng_data,
15060 const int64_t block_id,
15061 const int64_t start_frame_nr,
15062 const int64_t end_frame_nr,
15063 const char hash_mode,
15065 int64_t *n_particles,
15066 int64_t *stride_length,
15067 int64_t *n_values_per_frame,
15070 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15071 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
15072 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
15073 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
15074 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15075 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15077 return(tng_gen_data_vector_interval_get(tng_data, block_id, TNG_TRUE,
15078 start_frame_nr, end_frame_nr,
15079 hash_mode, values, n_particles,
15080 stride_length, n_values_per_frame,
15084 tng_function_status DECLSPECDLLEXPORT tng_data_get_stride_length
15085 (const tng_trajectory_t tng_data,
15086 const int64_t block_id,
15088 int64_t *stride_length)
15090 tng_function_status stat;
15092 int64_t orig_file_pos, file_pos;
15093 int is_particle_data;
15095 if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
15102 stat = tng_frame_set_of_frame_find(tng_data, frame);
15103 if(stat != TNG_SUCCESS)
15108 orig_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
15109 stat = tng_data_find(tng_data, block_id, &data);
15110 if(stat != TNG_SUCCESS)
15112 stat = tng_particle_data_find(tng_data, block_id, &data);
15113 if(stat != TNG_SUCCESS)
15115 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15116 /* If no specific frame was required read until this data block is found */
15119 file_pos = ftello(tng_data->input_file);
15120 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
15122 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15123 file_pos = ftello(tng_data->input_file);
15126 if(stat != TNG_SUCCESS)
15128 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
15132 stat = tng_data_find(tng_data, block_id, &data);
15133 if(stat != TNG_SUCCESS)
15135 stat = tng_particle_data_find(tng_data, block_id, &data);
15136 if(stat != TNG_SUCCESS)
15138 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
15144 is_particle_data = 1;
15149 is_particle_data = 0;
15154 is_particle_data = 1;
15159 is_particle_data = 0;
15161 if(is_particle_data)
15163 *stride_length = data->stride_length;
15167 *stride_length = data->stride_length;
15169 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
15171 return(TNG_SUCCESS);
15174 tng_function_status DECLSPECDLLEXPORT tng_time_get_str
15175 (const tng_trajectory_t tng_data,
15178 struct tm *time_data;
15182 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15183 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
15185 secs = tng_data->time;
15187 time_data = localtime(&secs); /* Returns a statically allocated variable. */
15188 retval = TNG_SNPRINTF(time, TNG_MAX_DATE_STR_LEN,
15189 "%4d-%02d-%02d %02d:%02d:%02d",
15190 time_data->tm_year+1900, time_data->tm_mon+1, time_data->tm_mday,
15191 time_data->tm_hour, time_data->tm_min, time_data->tm_sec);
15193 /* handle return value (also) to quiet a -Wformat-truncation warning */
15194 return( (retval < 0) ? TNG_SUCCESS : TNG_FAILURE );
15198 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_open
15199 (const char *filename,
15201 tng_trajectory_t *tng_data_p)
15203 tng_function_status stat;
15205 TNG_ASSERT(filename, "TNG library: filename must not be a NULL pointer.");
15207 if(mode != 'r' && mode != 'w' && mode != 'a')
15209 return(TNG_FAILURE);
15212 if(tng_trajectory_init(tng_data_p) != TNG_SUCCESS)
15214 tng_trajectory_destroy(tng_data_p);
15215 return(TNG_CRITICAL);
15220 stat = tng_output_file_set(*tng_data_p, filename);
15223 tng_input_file_set(*tng_data_p, filename);
15225 /* Read the file headers */
15226 tng_file_headers_read(*tng_data_p, TNG_USE_HASH);
15228 stat = tng_num_frame_sets_get(*tng_data_p, &(*tng_data_p)->n_trajectory_frame_sets);
15230 if(stat != TNG_SUCCESS)
15237 if((*tng_data_p)->output_file)
15239 fclose((*tng_data_p)->output_file);
15241 (*tng_data_p)->output_file = (*tng_data_p)->input_file;
15242 fseeko((*tng_data_p)->input_file,
15243 (*tng_data_p)->last_trajectory_frame_set_input_file_pos,
15246 stat = tng_frame_set_read(*tng_data_p, TNG_USE_HASH);
15247 if(stat != TNG_SUCCESS)
15249 fprintf(stderr, "TNG library: Cannot read frame set and related blocks. %s: %d\n",
15250 __FILE__, __LINE__);
15252 (*tng_data_p)->output_file = 0;
15254 (*tng_data_p)->first_trajectory_frame_set_output_file_pos =
15255 (*tng_data_p)->first_trajectory_frame_set_input_file_pos;
15256 (*tng_data_p)->last_trajectory_frame_set_output_file_pos =
15257 (*tng_data_p)->last_trajectory_frame_set_input_file_pos;
15258 (*tng_data_p)->current_trajectory_frame_set_output_file_pos =
15259 (*tng_data_p)->current_trajectory_frame_set_input_file_pos;
15260 if((*tng_data_p)->input_file)
15262 fclose((*tng_data_p)->input_file);
15263 (*tng_data_p)->input_file = 0;
15265 if((*tng_data_p)->input_file_path)
15267 free((*tng_data_p)->input_file_path);
15268 (*tng_data_p)->input_file_path = 0;
15270 tng_output_append_file_set(*tng_data_p, filename);
15272 fseeko((*tng_data_p)->output_file, 0, SEEK_END);
15274 (*tng_data_p)->output_endianness_swap_func_32 = (*tng_data_p)->input_endianness_swap_func_32;
15275 (*tng_data_p)->output_endianness_swap_func_64 = (*tng_data_p)->input_endianness_swap_func_64;
15281 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_close
15282 (tng_trajectory_t *tng_data_p)
15284 tng_trajectory_frame_set_t frame_set;
15286 if(tng_data_p == 0)
15288 fprintf(stderr, "TNG library: Empty pointer to trajectory when attempting to close. %s: %d\n",
15289 __FILE__, __LINE__);
15290 return(TNG_FAILURE);
15293 if(*tng_data_p == 0)
15295 return(TNG_SUCCESS);
15298 frame_set = &(*tng_data_p)->current_trajectory_frame_set;
15300 if(frame_set->n_unwritten_frames > 0)
15302 frame_set->n_frames = frame_set->n_unwritten_frames;
15303 tng_frame_set_write(*tng_data_p, TNG_USE_HASH);
15306 return(tng_trajectory_destroy(tng_data_p));
15309 tng_function_status DECLSPECDLLEXPORT tng_util_time_of_frame_get
15310 (const tng_trajectory_t tng_data,
15311 const int64_t frame_nr,
15314 int64_t first_frame;
15315 tng_trajectory_frame_set_t frame_set;
15316 tng_function_status stat;
15318 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15319 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
15321 stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
15322 if(stat != TNG_SUCCESS)
15324 fprintf(stderr, "TNG library: Cannot find frame nr %" PRId64 ". %s: %d\n",
15325 frame_nr, __FILE__, __LINE__);
15329 frame_set = &tng_data->current_trajectory_frame_set;
15330 first_frame = frame_set->first_frame;
15332 if(tng_data->time_per_frame <= 0)
15334 return(TNG_FAILURE);
15337 *time = frame_set->first_frame_time + (tng_data->time_per_frame * (frame_nr - first_frame));
15339 return(TNG_SUCCESS);
15343 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecules_get
15344 (const tng_trajectory_t tng_data,
15346 int64_t **molecule_cnt_list,
15347 tng_molecule_t *mols)
15349 tng_trajectory_frame_set_t frame_set;
15351 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15352 TNG_ASSERT(n_mols, "TNG library: n_mols must not be a NULL pointer.");
15354 *n_mols = tng_data->n_molecules;
15356 frame_set = &tng_data->current_trajectory_frame_set;
15357 if(tng_data->var_num_atoms_flag && frame_set && frame_set->molecule_cnt_list)
15359 *molecule_cnt_list = frame_set->molecule_cnt_list;
15363 *molecule_cnt_list = tng_data->molecule_cnt_list;
15366 *mols = tng_data->molecules;
15368 return(TNG_SUCCESS);
15372 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecule_add
15373 (const tng_trajectory_t tng_data,
15376 tng_molecule_t *mol)
15378 tng_function_status stat;
15380 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
15381 TNG_ASSERT(cnt>=0, "TNG library: cnt must be >= 0");
15383 stat = tng_molecule_add(tng_data, name, mol);
15384 if(stat != TNG_SUCCESS)
15388 stat = tng_molecule_cnt_set(tng_data, *mol, cnt);
15393 tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_get
15394 (const tng_trajectory_t tng_data,
15395 const tng_molecule_t mol,
15396 int64_t *n_particles,
15401 char ***chain_names,
15402 int64_t **chain_ids)
15410 *n_particles = mol->n_atoms;
15412 *names = (char **)malloc(sizeof(char *) * *n_particles);
15413 *types = (char **)malloc(sizeof(char *) * *n_particles);
15414 *res_names = (char **)malloc(sizeof(char *) * *n_particles);
15415 *chain_names = (char **)malloc(sizeof(char *) * *n_particles);
15416 *res_ids = (int64_t *)malloc(sizeof(int64_t) * *n_particles);
15417 *chain_ids = (int64_t *)malloc(sizeof(int64_t) * *n_particles);
15419 for(i = 0; i < *n_particles; i++)
15421 atom = &mol->atoms[i];
15422 res = atom->residue;
15423 chain = res->chain;
15424 (*names)[i] = (char *)malloc(strlen(atom->name));
15425 strcpy(*names[i], atom->name);
15426 (*types)[i] = (char *)malloc(strlen(atom->atom_type));
15427 strcpy(*types[i], atom->atom_type);
15428 (*res_names)[i] = (char *)malloc(strlen(res->name));
15429 strcpy(*res_names[i], res->name);
15430 (*chain_names)[i] = (char *)malloc(strlen(chain->name));
15431 strcpy(*chain_names[i], chain->name);
15432 (*res_ids)[i] = res->id;
15433 (*chain_ids)[i] = chain->id;
15436 return(TNG_SUCCESS);
15439 tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_set
15440 (const tng_trajectory_t tng_data,
15441 const tng_molecule_t mol,
15442 const int64_t n_particles,
15443 const char **names,
15444 const char **types,
15445 const char **res_names,
15446 const int64_t *res_ids,
15447 const char **chain_names,
15448 const int64_t *chain_ids)
15452 tng_residue_t residue;
15454 tng_function_status stat;
15456 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15457 TNG_ASSERT(names, "TNG library: names must not be a NULL pointer");
15458 TNG_ASSERT(types, "TNG library: types must not be a NULL pointer");
15459 TNG_ASSERT(res_names, "TNG library: res_names must not be a NULL pointer");
15460 TNG_ASSERT(res_ids, "TNG library: res_ids must not be a NULL pointer");
15461 TNG_ASSERT(chain_names, "TNG library: chain_names must not be a NULL pointer");
15462 TNG_ASSERT(chain_ids, "TNG library: chain_ids must not be a NULL pointer");
15464 for(i = 0; i < n_particles; i++)
15466 if(tng_molecule_chain_find(tng_data, mol, chain_names[i], chain_ids[i],
15467 &chain) == TNG_FAILURE)
15469 stat = tng_molecule_chain_add(tng_data, mol, chain_names[i],
15471 if(stat != TNG_SUCCESS)
15476 if(tng_chain_residue_find(tng_data, chain, res_names[i], res_ids[i],
15477 &residue) == TNG_FAILURE)
15479 stat = tng_chain_residue_add(tng_data, chain, res_names[i],
15481 if(stat != TNG_SUCCESS)
15486 stat = tng_residue_atom_add(tng_data, residue, names[i], types[i], &atom);
15487 if(stat != TNG_SUCCESS)
15492 return(TNG_SUCCESS);
15495 tng_function_status DECLSPECDLLEXPORT tng_util_pos_read
15496 (const tng_trajectory_t tng_data,
15497 float **positions, int64_t *stride_length)
15499 int64_t n_frames, n_particles, n_values_per_frame;
15501 tng_function_status stat;
15503 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15504 TNG_ASSERT(positions, "TNG library: positions 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)
15513 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_POSITIONS,
15514 0, n_frames - 1, TNG_USE_HASH,
15515 (void **)positions,
15518 &n_values_per_frame,
15521 if(stat == TNG_SUCCESS && type != TNG_FLOAT_DATA)
15523 return(TNG_FAILURE);
15529 tng_function_status DECLSPECDLLEXPORT tng_util_vel_read
15530 (const tng_trajectory_t tng_data,
15531 float **velocities, int64_t *stride_length)
15533 int64_t n_frames, n_particles, n_values_per_frame;
15535 tng_function_status stat;
15537 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15538 TNG_ASSERT(velocities, "TNG library: velocities 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)
15547 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_VELOCITIES,
15548 0, n_frames - 1, TNG_USE_HASH,
15549 (void **)velocities,
15552 &n_values_per_frame,
15555 if(stat == TNG_SUCCESS && type != TNG_FLOAT_DATA)
15557 return(TNG_FAILURE);
15563 tng_function_status DECLSPECDLLEXPORT tng_util_force_read
15564 (const tng_trajectory_t tng_data,
15565 float **forces, int64_t *stride_length)
15567 int64_t n_frames, n_particles, n_values_per_frame;
15569 tng_function_status stat;
15571 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15572 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
15573 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
15575 stat = tng_num_frames_get(tng_data, &n_frames);
15576 if(stat != TNG_SUCCESS)
15581 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_FORCES,
15582 0, n_frames - 1, TNG_USE_HASH,
15586 &n_values_per_frame,
15589 if(stat == TNG_SUCCESS && type != TNG_FLOAT_DATA)
15591 return(TNG_FAILURE);
15597 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read
15598 (const tng_trajectory_t tng_data,
15600 int64_t *stride_length)
15602 int64_t n_frames, n_values_per_frame;
15604 tng_function_status stat;
15606 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15607 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
15608 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
15610 stat = tng_num_frames_get(tng_data, &n_frames);
15611 if(stat != TNG_SUCCESS)
15616 stat = tng_data_vector_interval_get(tng_data, TNG_TRAJ_BOX_SHAPE,
15617 0, n_frames - 1, TNG_USE_HASH,
15618 (void **)box_shape,
15620 &n_values_per_frame,
15623 if(stat == TNG_SUCCESS && type != TNG_FLOAT_DATA)
15625 return(TNG_FAILURE);
15631 tng_function_status DECLSPECDLLEXPORT tng_util_particle_data_next_frame_read
15632 (const tng_trajectory_t tng_data,
15633 const int64_t block_id,
15636 int64_t *retrieved_frame_number,
15637 double *retrieved_time)
15639 tng_trajectory_frame_set_t frame_set;
15640 tng_data_t data = 0;
15641 tng_function_status stat;
15643 int64_t i, full_data_len, n_particles;
15647 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15648 TNG_ASSERT(values, "TNG library: The pointer to the values array must not be a NULL pointer");
15649 TNG_ASSERT(data_type, "TNG library: The pointer to the data type of the returned data must not be a NULL pointer");
15650 TNG_ASSERT(retrieved_frame_number, "TNG library: The pointer to the frame number of the returned data must not be a NULL pointer");
15651 TNG_ASSERT(retrieved_time, "TNG library: The pointer to the time of the returned data must not be a NULL pointer");
15653 frame_set = &tng_data->current_trajectory_frame_set;
15655 stat = tng_particle_data_find(tng_data, block_id, &data);
15656 if(stat != TNG_SUCCESS)
15658 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15659 file_pos = ftello(tng_data->input_file);
15660 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
15662 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15663 file_pos = ftello(tng_data->input_file);
15665 if(stat != TNG_SUCCESS)
15669 stat = tng_particle_data_find(tng_data, block_id, &data);
15670 if(stat != TNG_SUCCESS)
15675 if(data->last_retrieved_frame < 0)
15677 fseeko(tng_data->input_file,
15678 tng_data->first_trajectory_frame_set_input_file_pos,
15680 stat = tng_frame_set_read(tng_data, TNG_USE_HASH);
15681 if(stat != TNG_SUCCESS)
15685 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15686 if(stat != TNG_SUCCESS)
15691 i = data->first_frame_with_data;
15695 if(data->n_frames == 1 && frame_set->n_frames == 1)
15697 i = data->last_retrieved_frame + 1;
15701 i = data->last_retrieved_frame + data->stride_length;
15703 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
15705 stat = tng_frame_set_of_frame_find(tng_data, i);
15706 if(stat != TNG_SUCCESS)
15708 /* If the frame set search found the frame set after the starting
15709 * frame set there is a gap in the frame sets. So, even if the frame
15710 * was not found the next frame with data is still in the found
15712 if(stat == TNG_CRITICAL)
15716 if(frame_set->first_frame + frame_set->n_frames - 1 < i)
15718 return(TNG_FAILURE);
15720 i = frame_set->first_frame;
15723 if(data->last_retrieved_frame < frame_set->first_frame)
15725 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15726 if(stat != TNG_SUCCESS)
15732 data->last_retrieved_frame = i;
15733 *retrieved_frame_number = i;
15734 if(frame_set->first_frame_time >= 0 && tng_data->time_per_frame >= 0)
15736 *retrieved_time = frame_set->first_frame_time +
15737 (i - frame_set->first_frame) *
15738 tng_data->time_per_frame;
15742 *retrieved_time = 0;
15745 if(data->stride_length > 1)
15747 i = (i - data->first_frame_with_data) / data->stride_length;
15751 i = (i - frame_set->first_frame);
15754 tng_num_particles_get(tng_data, &n_particles);
15756 *data_type = data->datatype;
15760 case TNG_CHAR_DATA:
15761 return(TNG_FAILURE);
15763 size = sizeof(int64_t);
15765 case TNG_FLOAT_DATA:
15766 size = sizeof(float);
15768 case TNG_DOUBLE_DATA:
15770 size = sizeof(double);
15773 full_data_len = size * n_particles * data->n_values_per_frame;
15775 // fprintf(stderr, "TNG library: TEMP: i = %" PRId64 ", full_data_len = %" PRId64 ", size = %d, n_particles = %" PRId64 ", n_values_per_frame = %" PRId64 "\n",
15776 // i, full_data_len, size, n_particles, data->n_values_per_frame);
15778 temp = (char *)realloc(*values, full_data_len);
15781 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
15782 __FILE__, __LINE__);
15785 return(TNG_CRITICAL);
15790 memcpy(*values, (char *)data->values + i * full_data_len, full_data_len);
15792 return(TNG_SUCCESS);
15795 tng_function_status DECLSPECDLLEXPORT tng_util_non_particle_data_next_frame_read
15796 (const tng_trajectory_t tng_data,
15797 const int64_t block_id,
15800 int64_t *retrieved_frame_number,
15801 double *retrieved_time)
15803 tng_trajectory_frame_set_t frame_set;
15804 tng_data_t data = 0;
15805 tng_function_status stat;
15807 int64_t i, full_data_len;
15811 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15812 TNG_ASSERT(values, "TNG library: The pointer to the values array must not be a NULL pointer");
15813 TNG_ASSERT(data_type, "TNG library: The pointer to the data type of the returned data must not be a NULL pointer");
15814 TNG_ASSERT(retrieved_frame_number, "TNG library: The pointer to the frame number of the returned data must not be a NULL pointer");
15815 TNG_ASSERT(retrieved_time, "TNG library: The pointer to the time of the returned data must not be a NULL pointer");
15817 frame_set = &tng_data->current_trajectory_frame_set;
15819 stat = tng_data_find(tng_data, block_id, &data);
15820 if(stat != TNG_SUCCESS)
15822 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15823 file_pos = ftello(tng_data->input_file);
15824 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
15826 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15827 file_pos = ftello(tng_data->input_file);
15829 if(stat != TNG_SUCCESS)
15833 stat = tng_data_find(tng_data, block_id, &data);
15834 if(stat != TNG_SUCCESS)
15839 if(data->last_retrieved_frame < 0)
15841 fseeko(tng_data->input_file,
15842 tng_data->first_trajectory_frame_set_input_file_pos,
15844 stat = tng_frame_set_read(tng_data, TNG_USE_HASH);
15845 if(stat != TNG_SUCCESS)
15849 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15850 if(stat != TNG_SUCCESS)
15855 i = data->first_frame_with_data;
15859 if(data->n_frames == 1 && frame_set->n_frames == 1)
15861 i = data->last_retrieved_frame + 1;
15865 i = data->last_retrieved_frame + data->stride_length;
15867 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
15869 stat = tng_frame_set_of_frame_find(tng_data, i);
15870 if(stat != TNG_SUCCESS)
15872 /* If the frame set search found the frame set after the starting
15873 * frame set there is a gap in the frame sets. So, even if the frame
15874 * was not found the next frame with data is still in the found
15876 if(stat == TNG_CRITICAL)
15880 if(frame_set->first_frame + frame_set->n_frames - 1 < i)
15882 return(TNG_FAILURE);
15884 i = frame_set->first_frame;
15887 if(data->last_retrieved_frame < frame_set->first_frame)
15889 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15890 if(stat != TNG_SUCCESS)
15896 data->last_retrieved_frame = i;
15897 *retrieved_frame_number = i;
15898 if(frame_set->first_frame_time >= 0 && tng_data->time_per_frame >= 0)
15900 *retrieved_time = frame_set->first_frame_time +
15901 (i - frame_set->first_frame) *
15902 tng_data->time_per_frame;
15906 *retrieved_time = 0;
15909 if(data->stride_length > 1)
15911 i = (i - data->first_frame_with_data) / data->stride_length;
15915 i = (i - frame_set->first_frame);
15918 *data_type = data->datatype;
15922 case TNG_CHAR_DATA:
15923 return(TNG_FAILURE);
15925 size = sizeof(int64_t);
15927 case TNG_FLOAT_DATA:
15928 size = sizeof(float);
15930 case TNG_DOUBLE_DATA:
15932 size = sizeof(double);
15935 full_data_len = size * data->n_values_per_frame;
15937 temp = (char *)realloc(*values, full_data_len);
15940 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
15941 __FILE__, __LINE__);
15944 return(TNG_CRITICAL);
15949 memcpy(*values, (char *)data->values + i * full_data_len, full_data_len);
15951 return(TNG_SUCCESS);
15954 tng_function_status DECLSPECDLLEXPORT tng_util_pos_read_range
15955 (const tng_trajectory_t tng_data,
15956 const int64_t first_frame,
15957 const int64_t last_frame,
15959 int64_t *stride_length)
15961 int64_t n_particles, n_values_per_frame;
15963 tng_function_status stat;
15965 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15966 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
15967 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
15968 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
15970 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_POSITIONS,
15971 first_frame, last_frame,
15973 (void **)positions,
15976 &n_values_per_frame,
15979 if(stat == TNG_SUCCESS && type != TNG_FLOAT_DATA)
15981 return(TNG_FAILURE);
15987 tng_function_status DECLSPECDLLEXPORT tng_util_vel_read_range
15988 (const tng_trajectory_t tng_data,
15989 const int64_t first_frame,
15990 const int64_t last_frame,
15991 float **velocities,
15992 int64_t *stride_length)
15994 int64_t n_particles, n_values_per_frame;
15996 tng_function_status stat;
15998 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15999 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
16000 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
16001 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
16003 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_VELOCITIES,
16004 first_frame, last_frame,
16006 (void **)velocities,
16009 &n_values_per_frame,
16012 if(stat == TNG_SUCCESS && type != TNG_FLOAT_DATA)
16014 return(TNG_FAILURE);
16020 tng_function_status DECLSPECDLLEXPORT tng_util_force_read_range
16021 (const tng_trajectory_t tng_data,
16022 const int64_t first_frame,
16023 const int64_t last_frame,
16025 int64_t *stride_length)
16027 int64_t n_particles, n_values_per_frame;
16029 tng_function_status stat;
16031 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16032 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
16033 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
16034 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
16036 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_FORCES,
16037 first_frame, last_frame,
16042 &n_values_per_frame,
16045 if(stat == TNG_SUCCESS && type != TNG_FLOAT_DATA)
16047 return(TNG_FAILURE);
16053 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read_range
16054 (const tng_trajectory_t tng_data,
16055 const int64_t first_frame,
16056 const int64_t last_frame,
16058 int64_t *stride_length)
16060 int64_t n_values_per_frame;
16062 tng_function_status stat;
16064 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16065 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
16066 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
16067 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
16069 stat = tng_data_vector_interval_get(tng_data, TNG_TRAJ_BOX_SHAPE,
16070 first_frame, last_frame,
16072 (void **)box_shape,
16074 &n_values_per_frame,
16077 if(stat == TNG_SUCCESS && type != TNG_FLOAT_DATA)
16079 return(TNG_FAILURE);
16085 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_set
16086 (const tng_trajectory_t tng_data,
16088 const int64_t n_values_per_frame,
16089 const int64_t block_id,
16090 const char *block_name,
16091 const char particle_dependency,
16092 const char compression)
16094 tng_trajectory_frame_set_t frame_set;
16096 int64_t n_particles, n_frames;
16097 tng_function_status stat;
16099 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16100 TNG_ASSERT(i >= 0, "TNG library: i (writing interval) must be >= 0.");
16104 fprintf(stderr, "TNG library: Cannot set writing frequency to %" PRId64 ". %s: %d\n",
16105 i, __FILE__, __LINE__);
16106 return(TNG_FAILURE);
16109 frame_set = &tng_data->current_trajectory_frame_set;
16111 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
16113 n_frames = tng_data->frame_set_n_frames;
16115 stat = tng_frame_set_new(tng_data, 0, n_frames);
16116 if(stat != TNG_SUCCESS)
16118 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
16125 n_frames = frame_set->n_frames;
16128 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
16130 tng_num_particles_get(tng_data, &n_particles);
16131 if(n_particles <= 0)
16133 return(TNG_FAILURE);
16136 if(tng_particle_data_find(tng_data, block_id, &data)
16139 stat = tng_particle_data_block_add(tng_data, block_id,
16142 TNG_TRAJECTORY_BLOCK,
16143 n_frames, n_values_per_frame, i,
16146 if(stat != TNG_SUCCESS)
16148 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16149 __FILE__, __LINE__);
16152 data = &frame_set->tr_particle_data[frame_set->
16153 n_particle_data_blocks - 1];
16154 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
16156 n_values_per_frame);
16157 if(stat != TNG_SUCCESS)
16159 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16160 __FILE__, __LINE__);
16166 if(data->stride_length != i)
16168 data->stride_length = i;
16169 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
16171 n_values_per_frame);
16172 if(stat != TNG_SUCCESS)
16174 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16175 __FILE__, __LINE__);
16183 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
16185 stat = tng_data_block_add(tng_data, block_id, block_name,
16186 TNG_FLOAT_DATA, TNG_TRAJECTORY_BLOCK,
16187 n_frames, n_values_per_frame,
16188 i, compression, 0);
16189 if(stat != TNG_SUCCESS)
16191 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16192 __FILE__, __LINE__);
16195 data = &frame_set->tr_data[frame_set->
16196 n_data_blocks - 1];
16197 stat = tng_allocate_data_mem(tng_data, data, n_frames,
16198 i, n_values_per_frame);
16199 if(stat != TNG_SUCCESS)
16201 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16202 __FILE__, __LINE__);
16208 if(data->stride_length != i)
16210 data->stride_length = i;
16211 stat = tng_allocate_data_mem(tng_data, data, n_frames,
16212 i, n_values_per_frame);
16213 if(stat != TNG_SUCCESS)
16215 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16216 __FILE__, __LINE__);
16223 return(TNG_SUCCESS);
16226 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_double_set
16227 (const tng_trajectory_t tng_data,
16229 const int64_t n_values_per_frame,
16230 const int64_t block_id,
16231 const char *block_name,
16232 const char particle_dependency,
16233 const char compression)
16235 tng_trajectory_frame_set_t frame_set;
16237 int64_t n_particles, n_frames;
16238 tng_function_status stat;
16240 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16241 TNG_ASSERT(i >= 0, "TNG library: i (writing interval) must be >= 0.");
16245 fprintf(stderr, "TNG library: Cannot set writing frequency to %" PRId64 ". %s: %d\n",
16246 i, __FILE__, __LINE__);
16247 return(TNG_FAILURE);
16250 frame_set = &tng_data->current_trajectory_frame_set;
16252 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
16254 n_frames = tng_data->frame_set_n_frames;
16256 stat = tng_frame_set_new(tng_data, 0, n_frames);
16257 if(stat != TNG_SUCCESS)
16259 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
16266 n_frames = frame_set->n_frames;
16269 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
16271 tng_num_particles_get(tng_data, &n_particles);
16273 if(n_particles <= 0)
16275 return(TNG_FAILURE);
16278 if(tng_particle_data_find(tng_data, block_id, &data)
16281 stat = tng_particle_data_block_add(tng_data, block_id,
16284 TNG_TRAJECTORY_BLOCK,
16285 n_frames, n_values_per_frame, i,
16288 if(stat != TNG_SUCCESS)
16290 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16291 __FILE__, __LINE__);
16294 data = &frame_set->tr_particle_data[frame_set->
16295 n_particle_data_blocks - 1];
16296 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
16298 n_values_per_frame);
16299 if(stat != TNG_SUCCESS)
16301 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16302 __FILE__, __LINE__);
16308 data->stride_length = i;
16313 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
16315 stat = tng_data_block_add(tng_data, block_id, block_name,
16316 TNG_DOUBLE_DATA, TNG_TRAJECTORY_BLOCK,
16317 n_frames, n_values_per_frame,
16318 i, compression, 0);
16319 if(stat != TNG_SUCCESS)
16321 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16322 __FILE__, __LINE__);
16325 data = &frame_set->tr_data[frame_set->
16326 n_data_blocks - 1];
16327 stat = tng_allocate_data_mem(tng_data, data, n_frames,
16328 i, n_values_per_frame);
16329 if(stat != TNG_SUCCESS)
16331 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16332 __FILE__, __LINE__);
16338 data->stride_length = i;
16342 return(TNG_SUCCESS);
16345 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_frequency_set
16346 (const tng_trajectory_t tng_data,
16348 const int64_t n_values_per_frame,
16349 const int64_t block_id,
16350 const char *block_name,
16351 const char particle_dependency,
16352 const char compression)
16354 fprintf(stderr, "TNG library: Using obsolete function tng_util_generic_write_frequency_set(). "
16355 "See documentation. %s: %d", __FILE__, __LINE__);
16356 return(tng_util_generic_write_interval_set(tng_data, i, n_values_per_frame,
16357 block_id, block_name,
16358 particle_dependency,
16361 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_set
16362 (const tng_trajectory_t tng_data,
16365 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16366 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
16368 return(tng_util_generic_write_interval_set(tng_data, i, 3,
16369 TNG_TRAJ_POSITIONS,
16371 TNG_PARTICLE_BLOCK_DATA,
16372 TNG_TNG_COMPRESSION));
16375 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_double_set
16376 (const tng_trajectory_t tng_data,
16379 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16380 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
16382 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
16383 TNG_TRAJ_POSITIONS,
16385 TNG_PARTICLE_BLOCK_DATA,
16386 TNG_TNG_COMPRESSION));
16389 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_frequency_set
16390 (const tng_trajectory_t tng_data,
16393 fprintf(stderr, "TNG library: Using obsolete function tng_util_pos_write_frequency_set(). "
16394 "See documentation. %s: %d", __FILE__, __LINE__);
16395 return(tng_util_pos_write_interval_set(tng_data, i));
16398 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_set
16399 (const tng_trajectory_t tng_data,
16402 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16403 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
16405 return(tng_util_generic_write_interval_set(tng_data, i, 3,
16406 TNG_TRAJ_VELOCITIES,
16408 TNG_PARTICLE_BLOCK_DATA,
16409 TNG_TNG_COMPRESSION));
16412 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_double_set
16413 (const tng_trajectory_t tng_data,
16416 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16417 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
16419 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
16420 TNG_TRAJ_VELOCITIES,
16422 TNG_PARTICLE_BLOCK_DATA,
16423 TNG_TNG_COMPRESSION));
16426 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_frequency_set
16427 (const tng_trajectory_t tng_data,
16430 fprintf(stderr, "TNG library: Using obsolete function tng_util_vel_write_frequency_set(). "
16431 "See documentation. %s: %d", __FILE__, __LINE__);
16432 return(tng_util_vel_write_interval_set(tng_data, i));
16435 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_set
16436 (const tng_trajectory_t tng_data,
16439 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16440 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
16442 return(tng_util_generic_write_interval_set(tng_data, i, 3,
16445 TNG_PARTICLE_BLOCK_DATA,
16446 TNG_GZIP_COMPRESSION));
16449 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_double_set
16450 (const tng_trajectory_t tng_data,
16453 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16454 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
16456 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
16459 TNG_PARTICLE_BLOCK_DATA,
16460 TNG_GZIP_COMPRESSION));
16463 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_frequency_set
16464 (const tng_trajectory_t tng_data,
16467 fprintf(stderr, "TNG library: Using obsolete function tng_util_force_write_frequency_set(). "
16468 "See documentation. %s: %d", __FILE__, __LINE__);
16469 return(tng_util_force_write_interval_set(tng_data, i));
16472 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_set
16473 (const tng_trajectory_t tng_data,
16476 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16477 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
16479 return(tng_util_generic_write_interval_set(tng_data, i, 9,
16480 TNG_TRAJ_BOX_SHAPE,
16482 TNG_NON_PARTICLE_BLOCK_DATA,
16483 TNG_GZIP_COMPRESSION));
16486 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_double_set
16487 (const tng_trajectory_t tng_data,
16490 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16491 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
16493 return(tng_util_generic_write_interval_double_set(tng_data, i, 9,
16494 TNG_TRAJ_BOX_SHAPE,
16496 TNG_NON_PARTICLE_BLOCK_DATA,
16497 TNG_GZIP_COMPRESSION));
16500 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_frequency_set
16501 (const tng_trajectory_t tng_data,
16504 fprintf(stderr, "TNG library: Using obsolete function tng_util_box_shape_write_frequency_set(). "
16505 "See documentation. %s: %d", __FILE__, __LINE__);
16506 return(tng_util_box_shape_write_interval_set(tng_data, i));
16509 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write
16510 (const tng_trajectory_t tng_data,
16511 const int64_t frame_nr,
16512 const float *values,
16513 const int64_t n_values_per_frame,
16514 const int64_t block_id,
16515 const char *block_name,
16516 const char particle_dependency,
16517 const char compression)
16519 tng_trajectory_frame_set_t frame_set;
16521 int64_t n_particles = 0, n_frames, stride_length = 100, frame_pos;
16522 int64_t last_frame;
16523 int is_first_frame_flag = 0;
16524 char block_type_flag;
16525 tng_function_status stat;
16527 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16528 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
16530 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
16532 tng_num_particles_get(tng_data, &n_particles);
16533 TNG_ASSERT(n_particles > 0, "TNG library: There must be particles in the system to write particle data.");
16538 return(TNG_FAILURE);
16541 frame_set = &tng_data->current_trajectory_frame_set;
16545 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
16546 n_frames = stride_length = 1;
16550 block_type_flag = TNG_TRAJECTORY_BLOCK;
16552 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
16554 stat = tng_frame_set_new(tng_data, 0, tng_data->frame_set_n_frames);
16555 if(stat != TNG_SUCCESS)
16557 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
16562 last_frame = frame_set->first_frame +
16563 frame_set->n_frames - 1;
16564 if(frame_nr > last_frame)
16566 stat = tng_frame_set_write(tng_data, TNG_USE_HASH);
16567 if(stat != TNG_SUCCESS)
16569 fprintf(stderr, "TNG library: Cannot write frame set. %s: %d\n", __FILE__,
16573 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
16575 last_frame = frame_nr - 1;
16577 stat = tng_frame_set_new(tng_data, last_frame + 1,
16578 tng_data->frame_set_n_frames);
16579 if(stat != TNG_SUCCESS)
16581 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
16586 if(frame_set->n_unwritten_frames == 0)
16588 is_first_frame_flag = 1;
16590 frame_set->n_unwritten_frames = frame_nr -
16591 frame_set->first_frame + 1;
16593 n_frames = frame_set->n_frames;
16596 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
16598 if(tng_particle_data_find(tng_data, block_id, &data)
16601 stat = tng_particle_data_block_add(tng_data, block_id,
16605 n_frames, n_values_per_frame,
16609 if(stat != TNG_SUCCESS)
16611 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16612 __FILE__, __LINE__);
16615 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16617 data = &frame_set->tr_particle_data[frame_set->
16618 n_particle_data_blocks - 1];
16622 data = &tng_data->non_tr_particle_data[tng_data->
16623 n_particle_data_blocks - 1];
16625 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
16626 stride_length, n_particles,
16627 n_values_per_frame);
16628 if(stat != TNG_SUCCESS)
16630 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16631 __FILE__, __LINE__);
16635 /* FIXME: Here we must be able to handle modified n_particles as well. */
16636 else if(n_frames > data->n_frames)
16638 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
16639 data->stride_length, n_particles,
16640 n_values_per_frame);
16641 if(stat != TNG_SUCCESS)
16643 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16644 __FILE__, __LINE__);
16649 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16651 stride_length = data->stride_length;
16653 if(is_first_frame_flag || data->first_frame_with_data < frame_set->first_frame)
16655 data->first_frame_with_data = frame_nr;
16660 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
16663 memcpy((char *)data->values + sizeof(float) * frame_pos * n_particles *
16664 n_values_per_frame, values, sizeof(float) *
16665 n_particles * n_values_per_frame);
16669 memcpy(data->values, values, sizeof(float) * n_particles *
16670 n_values_per_frame);
16675 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
16677 stat = tng_data_block_add(tng_data, block_id, block_name,
16678 TNG_FLOAT_DATA, block_type_flag,
16679 n_frames, n_values_per_frame,
16680 stride_length, compression, 0);
16681 if(stat != TNG_SUCCESS)
16683 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16684 __FILE__, __LINE__);
16687 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16689 data = &frame_set->tr_data[frame_set->
16690 n_data_blocks - 1];
16694 data = &tng_data->non_tr_data[tng_data->
16695 n_data_blocks - 1];
16697 stat = tng_allocate_data_mem(tng_data, data, n_frames,
16698 stride_length, n_values_per_frame);
16699 if(stat != TNG_SUCCESS)
16701 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16702 __FILE__, __LINE__);
16706 /* FIXME: Here we must be able to handle modified n_particles as well. */
16707 else if(n_frames > data->n_frames)
16709 stat = tng_allocate_data_mem(tng_data, data, n_frames,
16710 data->stride_length, n_values_per_frame);
16711 if(stat != TNG_SUCCESS)
16713 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16714 __FILE__, __LINE__);
16719 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16721 stride_length = data->stride_length;
16723 if(is_first_frame_flag || data->first_frame_with_data < frame_set->first_frame)
16725 data->first_frame_with_data = frame_nr;
16730 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
16733 memcpy((char *)data->values + sizeof(float) * frame_pos *
16734 n_values_per_frame, values, sizeof(float) *
16735 n_values_per_frame);
16739 memcpy(data->values, values, sizeof(float) * n_values_per_frame);
16743 return(TNG_SUCCESS);
16746 tng_function_status DECLSPECDLLEXPORT tng_util_generic_double_write
16747 (const tng_trajectory_t tng_data,
16748 const int64_t frame_nr,
16749 const double *values,
16750 const int64_t n_values_per_frame,
16751 const int64_t block_id,
16752 const char *block_name,
16753 const char particle_dependency,
16754 const char compression)
16756 tng_trajectory_frame_set_t frame_set;
16758 int64_t n_particles = 0, n_frames, stride_length = 100, frame_pos;
16759 int64_t last_frame;
16760 int is_first_frame_flag = 0;
16761 char block_type_flag;
16762 tng_function_status stat;
16764 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16765 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
16767 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
16769 tng_num_particles_get(tng_data, &n_particles);
16770 TNG_ASSERT(n_particles > 0, "TNG library: There must be particles in the system to write particle data.");
16775 return(TNG_FAILURE);
16778 frame_set = &tng_data->current_trajectory_frame_set;
16782 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
16783 n_frames = stride_length = 1;
16787 block_type_flag = TNG_TRAJECTORY_BLOCK;
16789 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
16791 stat = tng_frame_set_new(tng_data, 0, tng_data->frame_set_n_frames);
16792 if(stat != TNG_SUCCESS)
16794 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
16799 last_frame = frame_set->first_frame +
16800 frame_set->n_frames - 1;
16801 if(frame_nr > last_frame)
16803 stat = tng_frame_set_write(tng_data, TNG_USE_HASH);
16804 if(stat != TNG_SUCCESS)
16806 fprintf(stderr, "TNG library: Cannot write frame set. %s: %d\n", __FILE__,
16810 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
16812 last_frame = frame_nr - 1;
16814 stat = tng_frame_set_new(tng_data, last_frame + 1,
16815 tng_data->frame_set_n_frames);
16816 if(stat != TNG_SUCCESS)
16818 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
16823 if(frame_set->n_unwritten_frames == 0)
16825 is_first_frame_flag = 1;
16827 frame_set->n_unwritten_frames = frame_nr -
16828 frame_set->first_frame + 1;
16830 n_frames = frame_set->n_frames;
16834 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
16836 if(tng_particle_data_find(tng_data, block_id, &data)
16839 stat = tng_particle_data_block_add(tng_data, block_id,
16843 n_frames, n_values_per_frame,
16847 if(stat != TNG_SUCCESS)
16849 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16850 __FILE__, __LINE__);
16853 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16855 data = &frame_set->tr_particle_data[frame_set->
16856 n_particle_data_blocks - 1];
16860 data = &tng_data->non_tr_particle_data[tng_data->
16861 n_particle_data_blocks - 1];
16863 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
16864 stride_length, n_particles,
16865 n_values_per_frame);
16866 if(stat != TNG_SUCCESS)
16868 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16869 __FILE__, __LINE__);
16873 /* FIXME: Here we must be able to handle modified n_particles as well. */
16874 else if(n_frames > data->n_frames)
16876 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
16877 data->stride_length, n_particles,
16878 n_values_per_frame);
16879 if(stat != TNG_SUCCESS)
16881 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16882 __FILE__, __LINE__);
16887 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16889 stride_length = data->stride_length;
16891 if(is_first_frame_flag || data->first_frame_with_data < frame_set->first_frame)
16893 data->first_frame_with_data = frame_nr;
16898 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
16901 memcpy((char *)data->values + sizeof(double) * frame_pos * n_particles *
16902 n_values_per_frame, values, sizeof(double) *
16903 n_particles * n_values_per_frame);
16907 memcpy(data->values, values, sizeof(double) * n_particles *
16908 n_values_per_frame);
16913 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
16915 stat = tng_data_block_add(tng_data, block_id, block_name,
16916 TNG_DOUBLE_DATA, block_type_flag,
16917 n_frames, n_values_per_frame,
16918 stride_length, compression, 0);
16919 if(stat != TNG_SUCCESS)
16921 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16922 __FILE__, __LINE__);
16925 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16927 data = &frame_set->tr_data[frame_set->
16928 n_data_blocks - 1];
16932 data = &tng_data->non_tr_data[tng_data->
16933 n_data_blocks - 1];
16935 stat = tng_allocate_data_mem(tng_data, data, n_frames,
16936 stride_length, n_values_per_frame);
16937 if(stat != TNG_SUCCESS)
16939 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16940 __FILE__, __LINE__);
16944 /* FIXME: Here we must be able to handle modified n_particles as well. */
16945 else if(n_frames > data->n_frames)
16947 stat = tng_allocate_data_mem(tng_data, data, n_frames,
16948 data->stride_length, n_values_per_frame);
16949 if(stat != TNG_SUCCESS)
16951 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16952 __FILE__, __LINE__);
16957 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16959 stride_length = data->stride_length;
16961 if(is_first_frame_flag || data->first_frame_with_data < frame_set->first_frame)
16963 data->first_frame_with_data = frame_nr;
16968 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
16971 memcpy((char *)data->values + sizeof(double) * frame_pos *
16972 n_values_per_frame, values, sizeof(double) *
16973 n_values_per_frame);
16977 memcpy(data->values, values, sizeof(double) * n_values_per_frame);
16981 return(TNG_SUCCESS);
16984 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write
16985 (const tng_trajectory_t tng_data,
16986 const int64_t frame_nr,
16987 const float *positions)
16989 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16990 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
16992 return(tng_util_generic_write(tng_data, frame_nr, positions, 3,
16993 TNG_TRAJ_POSITIONS, "POSITIONS",
16994 TNG_PARTICLE_BLOCK_DATA,
16995 TNG_TNG_COMPRESSION));
16998 tng_function_status DECLSPECDLLEXPORT tng_util_pos_double_write
16999 (const tng_trajectory_t tng_data,
17000 const int64_t frame_nr,
17001 const double *positions)
17003 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17004 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
17006 return(tng_util_generic_double_write(tng_data, frame_nr, positions, 3,
17007 TNG_TRAJ_POSITIONS, "POSITIONS",
17008 TNG_PARTICLE_BLOCK_DATA,
17009 TNG_TNG_COMPRESSION));
17012 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write
17013 (const tng_trajectory_t tng_data,
17014 const int64_t frame_nr,
17015 const float *velocities)
17017 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17018 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
17020 return(tng_util_generic_write(tng_data, frame_nr, velocities, 3,
17021 TNG_TRAJ_VELOCITIES, "VELOCITIES",
17022 TNG_PARTICLE_BLOCK_DATA,
17023 TNG_TNG_COMPRESSION));
17026 tng_function_status DECLSPECDLLEXPORT tng_util_vel_double_write
17027 (const tng_trajectory_t tng_data,
17028 const int64_t frame_nr,
17029 const double *velocities)
17031 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17032 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
17034 return(tng_util_generic_double_write(tng_data, frame_nr, velocities, 3,
17035 TNG_TRAJ_VELOCITIES, "VELOCITIES",
17036 TNG_PARTICLE_BLOCK_DATA,
17037 TNG_TNG_COMPRESSION));
17040 tng_function_status DECLSPECDLLEXPORT tng_util_force_write
17041 (const tng_trajectory_t tng_data,
17042 const int64_t frame_nr,
17043 const float *forces)
17045 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17046 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17048 return(tng_util_generic_write(tng_data, frame_nr, forces, 3,
17049 TNG_TRAJ_FORCES, "FORCES",
17050 TNG_PARTICLE_BLOCK_DATA,
17051 TNG_GZIP_COMPRESSION));
17054 tng_function_status DECLSPECDLLEXPORT tng_util_force_double_write
17055 (const tng_trajectory_t tng_data,
17056 const int64_t frame_nr,
17057 const double *forces)
17059 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17060 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17062 return(tng_util_generic_double_write(tng_data, frame_nr, forces, 3,
17063 TNG_TRAJ_FORCES, "FORCES",
17064 TNG_PARTICLE_BLOCK_DATA,
17065 TNG_GZIP_COMPRESSION));
17068 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write
17069 (const tng_trajectory_t tng_data,
17070 const int64_t frame_nr,
17071 const float *box_shape)
17073 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17074 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17076 return(tng_util_generic_write(tng_data, frame_nr, box_shape, 9,
17077 TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
17078 TNG_NON_PARTICLE_BLOCK_DATA,
17079 TNG_GZIP_COMPRESSION));
17082 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_double_write
17083 (const tng_trajectory_t tng_data,
17084 const int64_t frame_nr,
17085 const double *box_shape)
17087 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17088 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17090 return(tng_util_generic_double_write(tng_data, frame_nr, box_shape, 9,
17091 TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
17092 TNG_NON_PARTICLE_BLOCK_DATA,
17093 TNG_GZIP_COMPRESSION));
17096 tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_write
17097 (const tng_trajectory_t tng_data,
17098 const int64_t frame_nr,
17100 const float *values,
17101 const int64_t n_values_per_frame,
17102 const int64_t block_id,
17103 const char *block_name,
17104 const char particle_dependency,
17105 const char compression)
17107 tng_trajectory_frame_set_t frame_set;
17108 tng_function_status stat;
17110 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17111 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17112 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17113 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
17115 stat = tng_util_generic_write(tng_data, frame_nr, values, n_values_per_frame,
17116 block_id, block_name,
17117 particle_dependency,
17120 if(stat != TNG_SUCCESS)
17125 frame_set = &tng_data->current_trajectory_frame_set;
17127 /* first_frame_time is -1 when it is not yet set. */
17128 if(frame_set->first_frame_time < -0.1)
17130 if(frame_nr > frame_set->first_frame)
17132 stat = tng_frame_set_first_frame_time_set(tng_data,
17135 frame_set->first_frame) *
17136 tng_data->time_per_frame);
17140 stat = tng_frame_set_first_frame_time_set(tng_data, time);
17146 tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_double_write
17147 (const tng_trajectory_t tng_data,
17148 const int64_t frame_nr,
17150 const double *values,
17151 const int64_t n_values_per_frame,
17152 const int64_t block_id,
17153 const char *block_name,
17154 const char particle_dependency,
17155 const char compression)
17157 tng_trajectory_frame_set_t frame_set;
17158 tng_function_status stat;
17160 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17161 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17162 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17163 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
17165 stat = tng_util_generic_double_write(tng_data, frame_nr, values, n_values_per_frame,
17166 block_id, block_name,
17167 particle_dependency,
17170 if(stat != TNG_SUCCESS)
17175 frame_set = &tng_data->current_trajectory_frame_set;
17177 /* first_frame_time is -1 when it is not yet set. */
17178 if(frame_set->first_frame_time < -0.1)
17180 if(frame_nr > frame_set->first_frame)
17182 stat = tng_frame_set_first_frame_time_set(tng_data,
17185 frame_set->first_frame) *
17186 tng_data->time_per_frame);
17190 stat = tng_frame_set_first_frame_time_set(tng_data, time);
17196 tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_write
17197 (const tng_trajectory_t tng_data,
17198 const int64_t frame_nr,
17200 const float *positions)
17202 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17203 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17204 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17205 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
17207 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, positions,
17208 3, TNG_TRAJ_POSITIONS, "POSITIONS",
17209 TNG_PARTICLE_BLOCK_DATA,
17210 TNG_TNG_COMPRESSION));
17213 tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_double_write
17214 (const tng_trajectory_t tng_data,
17215 const int64_t frame_nr,
17217 const double *positions)
17219 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17220 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17221 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17222 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
17224 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
17226 TNG_TRAJ_POSITIONS,
17228 TNG_PARTICLE_BLOCK_DATA,
17229 TNG_TNG_COMPRESSION));
17232 tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_write
17233 (const tng_trajectory_t tng_data,
17234 const int64_t frame_nr,
17236 const float *velocities)
17238 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17239 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17240 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17241 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
17243 return(tng_util_generic_with_time_write(tng_data, frame_nr, time,
17245 TNG_TRAJ_VELOCITIES,
17247 TNG_PARTICLE_BLOCK_DATA,
17248 TNG_TNG_COMPRESSION));
17251 tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_double_write
17252 (const tng_trajectory_t tng_data,
17253 const int64_t frame_nr,
17255 const double *velocities)
17257 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17258 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17259 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17260 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
17262 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
17264 TNG_TRAJ_VELOCITIES,
17266 TNG_PARTICLE_BLOCK_DATA,
17267 TNG_TNG_COMPRESSION));
17270 tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_write
17271 (const tng_trajectory_t tng_data,
17272 const int64_t frame_nr,
17274 const float *forces)
17276 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17277 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17278 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17279 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17281 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, forces,
17282 3, TNG_TRAJ_FORCES, "FORCES",
17283 TNG_PARTICLE_BLOCK_DATA,
17284 TNG_GZIP_COMPRESSION));
17287 tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_double_write
17288 (const tng_trajectory_t tng_data,
17289 const int64_t frame_nr,
17291 const double *forces)
17293 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17294 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17295 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17296 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17298 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
17300 TNG_TRAJ_FORCES, "FORCES",
17301 TNG_PARTICLE_BLOCK_DATA,
17302 TNG_GZIP_COMPRESSION));
17305 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_write
17306 (const tng_trajectory_t tng_data,
17307 const int64_t frame_nr,
17309 const float *box_shape)
17311 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17312 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17313 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17314 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17316 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, box_shape,
17317 9, TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
17318 TNG_NON_PARTICLE_BLOCK_DATA,
17319 TNG_GZIP_COMPRESSION));
17322 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_double_write
17323 (const tng_trajectory_t tng_data,
17324 const int64_t frame_nr,
17326 const double *box_shape)
17328 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17329 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17330 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17331 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17333 return(tng_util_generic_with_time_double_write(tng_data, frame_nr,
17334 time, box_shape, 9,
17335 TNG_TRAJ_BOX_SHAPE,
17337 TNG_NON_PARTICLE_BLOCK_DATA,
17338 TNG_GZIP_COMPRESSION));
17341 tng_function_status DECLSPECDLLEXPORT tng_util_frame_current_compression_get
17342 (const tng_trajectory_t tng_data,
17343 const int64_t block_id,
17347 tng_trajectory_frame_set_t frame_set;
17348 tng_data_t data = 0;
17349 tng_function_status stat;
17351 int block_type = -1;
17353 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17354 TNG_ASSERT(codec_id, "TNG library: The pointer to the returned codec id must not be a NULL pointer.");
17355 TNG_ASSERT(factor, "TNG library: The pointer to the returned multiplication factor must not be a NULL pointer.");
17357 frame_set = &tng_data->current_trajectory_frame_set;
17359 stat = tng_particle_data_find(tng_data, block_id, &data);
17360 if(stat == TNG_SUCCESS)
17362 block_type = TNG_PARTICLE_BLOCK_DATA;
17366 stat = tng_data_find(tng_data, block_id, &data);
17367 if(stat == TNG_SUCCESS)
17369 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
17373 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17374 if(stat != TNG_SUCCESS)
17378 stat = tng_particle_data_find(tng_data, block_id, &data);
17379 if(stat == TNG_SUCCESS)
17381 block_type = TNG_PARTICLE_BLOCK_DATA;
17385 stat = tng_data_find(tng_data, block_id, &data);
17386 if(stat == TNG_SUCCESS)
17388 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
17397 if(block_type == TNG_PARTICLE_BLOCK_DATA)
17399 if(data->last_retrieved_frame < 0)
17401 i = data->first_frame_with_data;
17405 i = data->last_retrieved_frame;
17408 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
17410 if(data->last_retrieved_frame < 0)
17412 i = data->first_frame_with_data;
17416 i = data->last_retrieved_frame;
17421 return(TNG_FAILURE);
17423 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
17425 stat = tng_frame_set_of_frame_find(tng_data, i);
17426 if(stat != TNG_SUCCESS)
17430 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17431 if(stat != TNG_SUCCESS)
17433 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
17434 __FILE__, __LINE__);
17438 if(block_type == TNG_PARTICLE_BLOCK_DATA)
17440 *codec_id = data->codec_id;
17441 *factor = data->compression_multiplier;
17443 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
17445 *codec_id = data->codec_id;
17446 *factor = data->compression_multiplier;
17448 return(TNG_SUCCESS);
17451 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_next_frame_present_data_blocks_find
17452 (const tng_trajectory_t tng_data,
17453 int64_t current_frame,
17454 const int64_t n_requested_data_block_ids,
17455 const int64_t *requested_data_block_ids,
17456 int64_t *next_frame,
17457 int64_t *n_data_blocks_in_next_frame,
17458 int64_t **data_block_ids_in_next_frame)
17460 tng_trajectory_frame_set_t frame_set;
17461 tng_function_status stat;
17463 tng_gen_block_t block;
17464 int64_t i, j, block_id, *temp;
17465 int64_t data_frame, frame_diff, min_diff;
17466 int64_t size, frame_set_file_pos;
17467 int found, read_all = 0;
17470 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17471 TNG_ASSERT(next_frame, "TNG library: The pointer to the next frame must not be NULL.");
17472 TNG_ASSERT(n_data_blocks_in_next_frame, "TNG library: The pointer to n_data_blocks_in_next_frame must not be NULL.");
17473 TNG_ASSERT(data_block_ids_in_next_frame, "TNG library: The pointer to the list of data block IDs must not be NULL.");
17475 if(n_requested_data_block_ids)
17477 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.");
17478 size = sizeof(int64_t) * n_requested_data_block_ids;
17479 temp = (int64_t *)realloc(*data_block_ids_in_next_frame, size);
17482 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
17483 __FILE__, __LINE__);
17484 free(*data_block_ids_in_next_frame);
17485 *data_block_ids_in_next_frame = 0;
17486 return(TNG_CRITICAL);
17488 *data_block_ids_in_next_frame = temp;
17491 frame_set = &tng_data->current_trajectory_frame_set;
17493 current_frame += 1;
17495 if(current_frame < frame_set->first_frame ||
17496 current_frame >= frame_set->first_frame + frame_set->n_frames)
17498 frame_set_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
17499 stat = tng_frame_set_of_frame_find(tng_data, current_frame);
17500 if(stat != TNG_SUCCESS)
17502 /* If the frame set search found the frame set after the starting
17503 * frame set there is a gap in the frame sets. So, even if the frame
17504 * was not found the next frame with data is still in the found
17506 if(stat == TNG_CRITICAL || frame_set->prev_frame_set_file_pos !=
17507 frame_set_file_pos)
17511 current_frame = frame_set->first_frame;
17515 /* Check for data blocks only if they have not already been found. */
17516 if(frame_set->n_particle_data_blocks <= 0 && frame_set->n_data_blocks <= 0)
17518 file_pos = ftello(tng_data->input_file);
17519 if(file_pos < tng_data->input_file_len)
17521 tng_block_init(&block);
17522 stat = tng_block_header_read(tng_data, block);
17523 while(file_pos < tng_data->input_file_len &&
17524 stat != TNG_CRITICAL &&
17525 block->id != TNG_TRAJECTORY_FRAME_SET &&
17528 stat = tng_block_read_next(tng_data, block,
17530 if(stat != TNG_CRITICAL)
17532 file_pos = ftello(tng_data->input_file);
17533 if(file_pos < tng_data->input_file_len)
17535 stat = tng_block_header_read(tng_data, block);
17539 tng_block_destroy(&block);
17540 if(stat == TNG_CRITICAL)
17542 fprintf(stderr, "TNG library: Cannot read block header at pos %" PRId64 ". %s: %d\n",
17543 file_pos, __FILE__, __LINE__);
17552 *n_data_blocks_in_next_frame = 0;
17554 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
17556 data = &frame_set->tr_particle_data[i];
17557 block_id = data->block_id;
17559 if(n_requested_data_block_ids > 0)
17562 for(j = 0; j < n_requested_data_block_ids; j++)
17564 if(block_id == requested_data_block_ids[j])
17576 if(!read_all && (data->last_retrieved_frame < frame_set->first_frame ||
17577 data->last_retrieved_frame >=
17578 frame_set->first_frame + frame_set->n_frames))
17580 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data,
17581 TNG_USE_HASH, block_id);
17582 if(stat == TNG_CRITICAL)
17584 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
17585 __FILE__, __LINE__);
17588 if(stat == TNG_FAILURE)
17593 if(frame_set->first_frame != current_frame &&
17594 data->last_retrieved_frame >= 0)
17596 data_frame = data->last_retrieved_frame + data->stride_length;
17600 data_frame = data->first_frame_with_data;
17602 frame_diff = data_frame - current_frame;
17607 if(min_diff == -1 || frame_diff <= min_diff)
17609 if(frame_diff < min_diff)
17611 *n_data_blocks_in_next_frame = 1;
17615 *n_data_blocks_in_next_frame += 1;
17617 if(n_requested_data_block_ids <= 0)
17619 size = sizeof(int64_t) * (*n_data_blocks_in_next_frame);
17620 temp = (int64_t *)realloc(*data_block_ids_in_next_frame, size);
17623 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
17624 __FILE__, __LINE__);
17625 free(*data_block_ids_in_next_frame);
17626 *data_block_ids_in_next_frame = 0;
17627 return(TNG_CRITICAL);
17629 *data_block_ids_in_next_frame = temp;
17633 TNG_ASSERT(*n_data_blocks_in_next_frame <= n_requested_data_block_ids, "TNG library: Array of data block IDs out of bounds");
17635 (*data_block_ids_in_next_frame)[(*n_data_blocks_in_next_frame) - 1] = block_id;
17637 min_diff = frame_diff;
17640 for(i = 0; i < frame_set->n_data_blocks; i++)
17642 data = &frame_set->tr_data[i];
17643 block_id = data->block_id;
17645 if(n_requested_data_block_ids > 0)
17648 for(j = 0; j < n_requested_data_block_ids; j++)
17650 if(block_id == requested_data_block_ids[j])
17662 if(!read_all && (data->last_retrieved_frame < frame_set->first_frame ||
17663 data->last_retrieved_frame >=
17664 frame_set->first_frame + frame_set->n_frames))
17666 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data,
17667 TNG_USE_HASH, block_id);
17668 if(stat == TNG_CRITICAL)
17670 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
17671 __FILE__, __LINE__);
17674 if(stat == TNG_FAILURE)
17679 if(frame_set->first_frame != current_frame &&
17680 data->last_retrieved_frame >= 0)
17682 data_frame = data->last_retrieved_frame + data->stride_length;
17686 data_frame = data->first_frame_with_data;
17688 frame_diff = data_frame - current_frame;
17693 if(min_diff == -1 || frame_diff <= min_diff)
17695 if(frame_diff < min_diff)
17697 *n_data_blocks_in_next_frame = 1;
17701 *n_data_blocks_in_next_frame += 1;
17703 if(n_requested_data_block_ids <= 0)
17705 size = sizeof(int64_t) * (*n_data_blocks_in_next_frame);
17706 temp = (int64_t *)realloc(*data_block_ids_in_next_frame, size);
17709 fprintf(stderr, "TNG library: Cannot allocate memory. %s: %d\n",
17710 __FILE__, __LINE__);
17711 free(*data_block_ids_in_next_frame);
17712 *data_block_ids_in_next_frame = 0;
17713 return(TNG_CRITICAL);
17715 *data_block_ids_in_next_frame = temp;
17719 TNG_ASSERT(*n_data_blocks_in_next_frame <= n_requested_data_block_ids, "TNG library: Array of data block IDs out of bounds");
17721 (*data_block_ids_in_next_frame)[(*n_data_blocks_in_next_frame) - 1] = block_id;
17723 min_diff = frame_diff;
17728 return(TNG_FAILURE);
17730 *next_frame = current_frame + min_diff;
17732 return(TNG_SUCCESS);
17736 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_all_data_block_types_get
17737 (const tng_trajectory_t tng_data,
17738 int64_t *n_data_blocks,
17739 int64_t **data_block_ids,
17740 char ***data_block_names,
17741 int64_t **stride_lengths,
17742 int64_t **n_values_per_frame,
17743 char **block_types,
17744 char **dependencies,
17745 char **compressions)
17747 tng_gen_block_t block;
17748 int64_t orig_file_pos, file_pos;
17750 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17751 TNG_ASSERT(n_data_blocks, "TNG library: The pointer to n_data_blocks must not be NULL.");
17752 TNG_ASSERT(data_block_ids, "TNG library: The pointer to the list of data block IDs must not be NULL.");
17753 TNG_ASSERT(data_block_names, "TNG library: The pointer to the list of data block names must not be NULL.");
17754 TNG_ASSERT(stride_lengths, "TNG library: The pointer to the list of stride lengths must not be NULL.");
17756 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
17758 return(TNG_CRITICAL);
17761 orig_file_pos = ftello(tng_data->input_file);
17763 fseeko(tng_data->input_file, 0, SEEK_SET);
17766 *n_data_blocks = 0;
17768 tng_block_init(&block);
17770 while(file_pos < tng_data->input_file_len &&
17771 tng_block_header_read(tng_data, block) != TNG_CRITICAL)
17773 if(block->id > TNG_TRAJECTORY_FRAME_SET)
17777 file_pos += (block->block_contents_size + block->header_contents_size);
17778 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
17781 fseeko(tng_data->input_file, orig_file_pos, SEEK_SET);
17783 return(TNG_SUCCESS);
17786 tng_function_status DECLSPECDLLEXPORT tng_util_prepare_append_after_frame
17787 (const tng_trajectory_t tng_data,
17788 const int64_t prev_frame)
17790 tng_function_status stat;
17791 FILE *temp = tng_data->input_file;
17793 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17794 TNG_ASSERT(prev_frame >= 0, "TNG library: The previous frame must not be negative.");
17796 tng_data->input_file = tng_data->output_file;
17798 stat = tng_frame_set_of_frame_find(tng_data, prev_frame);
17799 if(stat != TNG_SUCCESS)
17804 tng_data->current_trajectory_frame_set_output_file_pos =
17805 tng_data->current_trajectory_frame_set_input_file_pos;
17807 tng_data->input_file = temp;
17809 return(TNG_SUCCESS);
17812 tng_function_status DECLSPECDLLEXPORT tng_util_num_frames_with_data_of_block_id_get
17813 (const tng_trajectory_t tng_data,
17814 const int64_t block_id,
17817 int64_t curr_file_pos, first_frame_set_file_pos, curr_n_frames;
17818 tng_function_status stat;
17820 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17824 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
17826 return(TNG_CRITICAL);
17829 first_frame_set_file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
17830 curr_file_pos = ftello(tng_data->input_file);
17831 fseeko(tng_data->input_file, first_frame_set_file_pos, SEEK_SET);
17833 stat = tng_frame_set_n_frames_of_data_block_get(tng_data, block_id, &curr_n_frames);
17835 while(stat == TNG_SUCCESS && tng_data->current_trajectory_frame_set.next_frame_set_file_pos != -1)
17837 *n_frames += curr_n_frames;
17838 fseeko(tng_data->input_file,
17839 tng_data->current_trajectory_frame_set.next_frame_set_file_pos,
17841 stat = tng_frame_set_n_frames_of_data_block_get(tng_data, block_id, &curr_n_frames);
17843 if(stat == TNG_SUCCESS)
17845 *n_frames += curr_n_frames;
17847 fseeko(tng_data->input_file, curr_file_pos, SEEK_SET);
17848 if(stat == TNG_CRITICAL)
17850 return(TNG_CRITICAL);
17852 return(TNG_SUCCESS);