1 /* This code is part of the tng binary trajectory format.
3 * Written by Magnus Lundborg
4 * Copyright (c) 2012-2015, 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
36 #include "compression/tng_compress.h"
37 #include "tng/version.h"
39 #if defined( _WIN32 ) || defined( _WIN64 )
41 #define fseeko _fseeki64
45 #define ftello ftello64
47 #define ftello _ftelli64
53 /** One of the atoms of the bond */
55 /** The other atom of the bond */
60 /** The residue containing this atom */
61 tng_residue_t residue;
62 /** A unique (per molecule) ID number of the atom */
64 /** The atom_type (depending on the forcefield) */
66 /** The name of the atom */
71 /** The chain containing this residue */
73 /** A unique (per chain) ID number of the residue */
75 /** The name of the residue */
77 /** The number of atoms in the residue */
79 /** A list of atoms in the residue */
84 /** The molecule containing this chain */
85 tng_molecule_t molecule;
86 /** A unique (per molecule) ID number of the chain */
88 /** The name of the chain */
90 /** The number of residues in the chain */
92 /** A list of residues in the chain */
93 tng_residue_t residues;
97 /** A unique ID number of the molecule */
99 /** Quaternary structure of the molecule.
104 int64_t quaternary_str;
105 /** The number of chains in the molecule */
107 /** The number of residues in the molecule */
109 /** The number of atoms in the molecule */
111 /** The number of bonds in the molecule. If the bonds are not specified this
114 /** The name of the molecule */
116 /** A list of chains in the molecule */
118 /** A list of residues in the molecule */
119 tng_residue_t residues;
120 /** A list of the atoms in the molecule */
122 /** A list of the bonds in the molecule */
126 struct tng_gen_block {
127 /** The size of the block header in bytes */
128 int64_t header_contents_size;
129 /** The size of the block contents in bytes */
130 int64_t block_contents_size;
131 /** The ID of the block to determine its type */
133 /** The MD5 hash of the block to verify integrity */
134 char md5_hash[TNG_MD5_HASH_LEN];
135 /** The name of the block */
137 /** The library version used to write the block */
138 int64_t block_version;
139 int64_t alt_hash_type;
140 int64_t alt_hash_len;
142 int64_t signature_type;
143 int64_t signature_len;
145 /** The full block header contents */
146 char *header_contents;
147 /** The full block contents */
148 char *block_contents;
151 struct tng_particle_mapping {
152 /** The index number of the first particle in this mapping block */
153 int64_t num_first_particle;
154 /** The number of particles list in this mapping block */
156 /** the mapping of index numbers to the real particle numbers in the
157 * trajectory. real_particle_numbers[0] is the real particle number
158 * (as it is numbered in the molecular system) of the first particle
159 * in the data blocks covered by this particle mapping block */
160 int64_t *real_particle_numbers;
163 struct tng_trajectory_frame_set {
164 /** The number of different particle mapping blocks present. */
165 int64_t n_mapping_blocks;
166 /** The atom mappings of this frame set */
167 struct tng_particle_mapping *mappings;
168 /** The first frame of this frame set */
170 /** The number of frames in this frame set */
172 /** The number of written frames in this frame set (used when writing one
173 * frame at a time). */
174 int64_t n_written_frames;
175 /** The number of frames not yet written to file in this frame set
176 * (used from the utility functions to finish the writing properly. */
177 int64_t n_unwritten_frames;
180 /** A list of the number of each molecule type - only used when using
181 * variable number of atoms */
182 int64_t *molecule_cnt_list;
183 /** The number of particles/atoms - only used when using variable number
186 /** The file position of the next frame set */
187 int64_t next_frame_set_file_pos;
188 /** The file position of the previous frame set */
189 int64_t prev_frame_set_file_pos;
190 /** The file position of the frame set one long stride step ahead */
191 int64_t medium_stride_next_frame_set_file_pos;
192 /** The file position of the frame set one long stride step behind */
193 int64_t medium_stride_prev_frame_set_file_pos;
194 /** The file position of the frame set one long stride step ahead */
195 int64_t long_stride_next_frame_set_file_pos;
196 /** The file position of the frame set one long stride step behind */
197 int64_t long_stride_prev_frame_set_file_pos;
198 /** Time stamp (in seconds) of first frame in frame set */
199 double first_frame_time;
201 /* The data blocks in a frame set are trajectory data blocks */
202 /** The number of trajectory data blocks of particle dependent data */
203 int n_particle_data_blocks;
204 /** A list of data blocks containing particle dependent data */
205 struct tng_data *tr_particle_data;
206 /** The number of trajectory data blocks independent of particles */
208 /** A list of data blocks containing particle indepdendent data */
209 struct tng_data *tr_data;
212 /* FIXME: Should there be a pointer to a tng_gen_block from each data block? */
214 /** The block ID of the data block containing this particle data.
215 * This is used to determine the kind of data that is stored */
217 /** The name of the data block. This is used to determine the kind of
218 * data that is stored */
220 /** The type of data stored. */
222 /** A flag to indicate if this data block contains frame and/or particle dependent
225 /** The frame number of the first data value */
226 int64_t first_frame_with_data;
227 /** The number of frames in this frame set */
229 /** The number of values stored per frame */
230 int64_t n_values_per_frame;
231 /** The number of frames between each data point - e.g. when
232 * storing sparse data. */
233 int64_t stride_length;
234 /** ID of the CODEC used for compression 0 == no compression. */
236 /** If reading one frame at a time this is the last read frame */
237 int64_t last_retrieved_frame;
238 /** The multiplier used for getting integer values for compression */
239 double compression_multiplier;
240 /** A 1-dimensional array of values of length
241 * [sizeof (datatype)] * n_frames * n_particles * n_values_per_frame */
243 /** If storing character data store it in a 3-dimensional array */
248 struct tng_trajectory {
249 /** The path of the input trajectory file */
250 char *input_file_path;
251 /** A handle to the input file */
253 /** The length of the input file */
254 int64_t input_file_len;
255 /** The path of the output trajectory file */
256 char *output_file_path;
257 /** A handle to the output file */
259 /** Function to swap 32 bit values to and from the endianness of the
261 tng_function_status (*input_endianness_swap_func_32)(const tng_trajectory_t, int32_t *);
262 /** Function to swap 64 bit values to and from the endianness of the
264 tng_function_status (*input_endianness_swap_func_64)(const tng_trajectory_t, int64_t *);
265 /** Function to swap 32 bit values to and from the endianness of the
267 tng_function_status (*output_endianness_swap_func_32)(const tng_trajectory_t, int32_t *);
268 /** Function to swap 64 bit values to and from the endianness of the
270 tng_function_status (*output_endianness_swap_func_64)(const tng_trajectory_t, int64_t *);
271 /** The endianness of 32 bit values of the current computer */
273 /** The endianness of 64 bit values of the current computer */
276 /** The name of the program producing this trajectory */
277 char *first_program_name;
278 /** The forcefield used in the simulations */
279 char *forcefield_name;
280 /** The name of the user running the simulations */
281 char *first_user_name;
282 /** The name of the computer on which the simulations were performed */
283 char *first_computer_name;
284 /** The PGP signature of the user creating the file. */
285 char *first_pgp_signature;
286 /** The name of the program used when making last modifications to the
288 char *last_program_name;
289 /** The name of the user making the last modifications to the file */
290 char *last_user_name;
291 /** The name of the computer on which the last modifications were made */
292 char *last_computer_name;
293 /** The PGP signature of the user making the last modifications to the
295 char *last_pgp_signature;
296 /** The time (n seconds since 1970) when the file was created */
298 /** The exponential of the value of the distance unit used. The default
299 * distance unit is nm (1e-9), i.e. distance_unit_exponential = -9. If
300 * the measurements are in Ã… the distance_unit_exponential = -10. */
301 int64_t distance_unit_exponential;
303 /** A flag indicating if the number of atoms can vary throughout the
304 * simulation, e.g. using a grand canonical ensemble */
305 char var_num_atoms_flag;
306 /** The number of frames in a frame set. It is allowed to have frame sets
307 * with fewer frames, but this will help searching for specific frames */
308 int64_t frame_set_n_frames;
309 /** The number of frame sets in a medium stride step */
310 int64_t medium_stride_length;
311 /** The number of frame sets in a long stride step */
312 int64_t long_stride_length;
313 /** The current (can change from one frame set to another) time length
314 * (in seconds) of one frame */
315 double time_per_frame;
317 /** The number of different kinds of molecules in the trajectory */
319 /** A list of molecules in the trajectory */
320 tng_molecule_t molecules;
321 /** A list of the count of each molecule - if using variable number of
322 * particles this will be specified in each frame set */
323 int64_t *molecule_cnt_list;
324 /** The total number of particles/atoms. If using variable number of
325 * particles this will be specified in each frame set */
328 /** The pos in the src file of the first frame set */
329 int64_t first_trajectory_frame_set_input_file_pos;
330 /** The pos in the dest file of the first frame set */
331 int64_t first_trajectory_frame_set_output_file_pos;
332 /** The pos in the src file of the last frame set */
333 int64_t last_trajectory_frame_set_input_file_pos;
334 /** The pos in the dest file of the last frame set */
335 int64_t last_trajectory_frame_set_output_file_pos;
336 /** The currently active frame set */
337 struct tng_trajectory_frame_set current_trajectory_frame_set;
338 /** The pos in the src file of the current frame set */
339 int64_t current_trajectory_frame_set_input_file_pos;
340 /** The pos in the dest file of the current frame set */
341 int64_t current_trajectory_frame_set_output_file_pos;
342 /** The number of frame sets in the trajectory N.B. Not saved in file and
343 * cannot be trusted to be up-to-date */
344 int64_t n_trajectory_frame_sets;
346 /* These data blocks are non-trajectory data blocks */
347 /** The number of non-frame dependent particle dependent data blocks */
348 int n_particle_data_blocks;
349 /** A list of data blocks containing particle dependent data */
350 struct tng_data *non_tr_particle_data;
352 /** The number of frame and particle independent data blocks */
354 /** A list of frame and particle indepdendent data blocks */
355 struct tng_data *non_tr_data;
357 /** TNG compression algorithm for compressing positions */
358 int *compress_algo_pos;
359 /** TNG compression algorithm for compressing velocities */
360 int *compress_algo_vel;
361 /** The precision used for lossy compression */
362 double compression_precision;
366 #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)
368 #endif /* win32... */
369 #endif /* not defined USE_WINDOWS */
372 #define TNG_INLINE __inline
373 #define TNG_SNPRINTF _snprintf
375 #define TNG_INLINE inline
376 #define TNG_SNPRINTF snprintf
379 static TNG_INLINE size_t tng_min_size(const size_t a, const size_t b)
381 return (a < b ? a : b);
384 static TNG_INLINE int64_t tng_min_i64(const int64_t a, const int64_t b)
386 return (a < b ? a : b);
389 static TNG_INLINE int64_t tng_max_i64(const int64_t a, const int64_t b)
391 return (a > b ? a : b);
395 * @brief This function swaps the byte order of a 32 bit numerical variable
397 * @param tng_data is a trajectory data container.
398 * @param v is a pointer to a 32 bit numerical value (float or integer).
399 * @details The function does not only work with integer, but e.g. floats need casting.
400 * If the byte order is already big endian no change is needed.
401 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
402 * byte order is not recognised.
404 static tng_function_status tng_swap_byte_order_big_endian_32
405 (const tng_trajectory_t tng_data, int32_t *v)
407 switch(tng_data->endianness_32)
409 case TNG_LITTLE_ENDIAN_32: /* Byte order is reversed. */
410 *v = ((*v & 0xFF000000) >> 24) | /* Move first byte to end */
411 ((*v & 0x00FF0000) >> 8) | /* Move 2nd byte to pos 3 */
412 ((*v & 0x0000FF00) << 8) | /* Move 3rd byte to pos 2 */
413 ((*v & 0x000000FF) << 24); /* Move last byte to first */
417 case TNG_BYTE_PAIR_SWAP_32: /* byte pair swap */
418 *v = ((*v & 0xFFFF0000) >> 16) |
419 ((*v & 0x0000FFFF) << 16);
423 case TNG_BIG_ENDIAN_32: /* Already correct */
432 * @brief This function swaps the byte order of a 64 bit numerical variable
434 * @param tng_data is a trajectory data container.
435 * @param v is a pointer to a 64 bit numerical value (double or integer).
436 * @details The function does not only work with integer, but e.g. floats need casting.
437 * The byte order swapping routine can convert four different byte
438 * orders to big endian.
439 * If the byte order is already big endian no change is needed.
440 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
441 * byte order is not recognised.
443 static tng_function_status tng_swap_byte_order_big_endian_64
444 (const tng_trajectory_t tng_data, int64_t *v)
446 switch(tng_data->endianness_64)
448 case TNG_LITTLE_ENDIAN_64: /* Byte order is reversed. */
449 *v = ((*v & 0xFF00000000000000LL) >> 56) | /* Move first byte to end */
450 ((*v & 0x00FF000000000000LL) >> 40) | /* Move 2nd byte to pos 7 */
451 ((*v & 0x0000FF0000000000LL) >> 24) | /* Move 3rd byte to pos 6 */
452 ((*v & 0x000000FF00000000LL) >> 8 ) | /* Move 4th byte to pos 5 */
453 ((*v & 0x00000000FF000000LL) << 8 ) | /* Move 5th byte to pos 4 */
454 ((*v & 0x0000000000FF0000LL) << 24) | /* Move 6th byte to pos 3 */
455 ((*v & 0x000000000000FF00LL) << 40) | /* Move 7th byte to pos 2 */
456 ((*v & 0x00000000000000FFLL) << 56); /* Move last byte to first */
460 case TNG_QUAD_SWAP_64: /* Byte quad swap */
461 *v = ((*v & 0xFFFFFFFF00000000LL) >> 32) |
462 ((*v & 0x00000000FFFFFFFFLL) << 32);
466 case TNG_BYTE_PAIR_SWAP_64: /* Byte pair swap */
467 *v = ((*v & 0xFFFF0000FFFF0000LL) >> 16) |
468 ((*v & 0x0000FFFF0000FFFFLL) << 16);
472 case TNG_BYTE_SWAP_64: /* Byte swap */
473 *v = ((*v & 0xFF00FF00FF00FF00LL) >> 8) |
474 ((*v & 0x00FF00FF00FF00FFLL) << 8);
478 case TNG_BIG_ENDIAN_64: /* Already correct */
487 * @brief This function swaps the byte order of a 32 bit numerical variable
489 * @param tng_data is a trajectory data container.
490 * @param v is a pointer to a 32 bit numerical value (float or integer).
491 * @details The function does not only work with integer, but e.g. floats need casting.
492 * If the byte order is already little endian no change is needed.
493 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
494 * byte order is not recognised.
496 static tng_function_status tng_swap_byte_order_little_endian_32
497 (const tng_trajectory_t tng_data, int32_t *v)
499 switch(tng_data->endianness_32)
501 case TNG_LITTLE_ENDIAN_32: /* Already correct */
504 case TNG_BYTE_PAIR_SWAP_32: /* byte pair swapped big endian to little endian */
505 *v = ((*v & 0xFF00FF00) >> 8) |
506 ((*v & 0x00FF00FF) << 8);
510 case TNG_BIG_ENDIAN_32: /* Byte order is reversed. */
511 *v = ((*v & 0xFF000000) >> 24) | /* Move first byte to end */
512 ((*v & 0x00FF0000) >> 8) | /* Move 2nd byte to pos 3 */
513 ((*v & 0x0000FF00) << 8) | /* Move 3rd byte to pos 2 */
514 ((*v & 0x000000FF) << 24); /* Move last byte to first */
524 * @brief This function swaps the byte order of a 64 bit numerical variable
526 * @param tng_data is a trajectory data container.
527 * @param v is a pointer to a 64 bit numerical value (double or integer).
528 * @details The function does not only work with integer, but e.g. floats need casting.
529 * The byte order swapping routine can convert four different byte
530 * orders to little endian.
531 * If the byte order is already little endian no change is needed.
532 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the current
533 * byte order is not recognised.
535 static tng_function_status tng_swap_byte_order_little_endian_64
536 (const tng_trajectory_t tng_data, int64_t *v)
538 switch(tng_data->endianness_64)
540 case TNG_LITTLE_ENDIAN_64: /* Already correct */
543 case TNG_QUAD_SWAP_64: /* Byte quad swapped big endian to little endian */
544 *v = ((*v & 0xFF000000FF000000LL) >> 24) |
545 ((*v & 0x00FF000000FF0000LL) >> 8) |
546 ((*v & 0x0000FF000000FF00LL) << 8) |
547 ((*v & 0x000000FF000000FFLL) << 24);
551 case TNG_BYTE_PAIR_SWAP_64: /* Byte pair swapped big endian to little endian */
552 *v = ((*v & 0xFF00FF0000000000LL) >> 40) |
553 ((*v & 0x00FF00FF00000000LL) >> 24) |
554 ((*v & 0x00000000FF00FF00LL) << 24) |
555 ((*v & 0x0000000000FF00FFLL) << 40);
559 case TNG_BYTE_SWAP_64: /* Byte swapped big endian to little endian */
560 *v = ((*v & 0xFFFF000000000000LL) >> 48) |
561 ((*v & 0x0000FFFF00000000LL) >> 16) |
562 ((*v & 0x00000000FFFF0000LL) << 16) |
563 ((*v & 0x000000000000FFFFLL) << 48);
567 case TNG_BIG_ENDIAN_64: /* Byte order is reversed. */
568 *v = ((*v & 0xFF00000000000000LL) >> 56) | /* Move first byte to end */
569 ((*v & 0x00FF000000000000LL) >> 40) | /* Move 2nd byte to pos 7 */
570 ((*v & 0x0000FF0000000000LL) >> 24) | /* Move 3rd byte to pos 6 */
571 ((*v & 0x000000FF00000000LL) >> 8 ) | /* Move 4th byte to pos 5 */
572 ((*v & 0x00000000FF000000LL) << 8 ) | /* Move 5th byte to pos 4 */
573 ((*v & 0x0000000000FF0000LL) << 24) | /* Move 6th byte to pos 3 */
574 ((*v & 0x000000000000FF00LL) << 40) | /* Move 7th byte to pos 2 */
575 ((*v & 0x00000000000000FFLL) << 56); /* Move last byte to first */
585 * @brief Read a NULL terminated string from a file.
586 * @param tng_data is a trajectory data container
587 * @param str is a pointer to the character string that will
588 * contain the read string. *str is reallocated in the function
589 * and must be NULL or pointing at already allocated memory.
590 * @param hash_mode is an option to decide whether to use the md5 hash or not.
591 * @param md5_state is a pointer to the current md5 storage, which will be
592 * appended with str if hash_mode == TNG_USE_HASH.
593 * @param line_nr is the line number where this function was called, to be
594 * able to give more useful error messages.
596 static tng_function_status tng_freadstr(const tng_trajectory_t tng_data,
598 const char hash_mode,
599 md5_state_t *md5_state,
602 char temp[TNG_MAX_STR_LEN], *temp_alloc;
607 c = fgetc(tng_data->input_file);
611 /* Clear file error flag and return -1 if EOF is read.*/
612 clearerr(tng_data->input_file);
618 temp[count++] = (char) c;
620 } while ((temp[count-1] != '\0') && (count < TNG_MAX_STR_LEN));
622 temp_alloc = realloc(*str, count);
625 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", count,
633 strncpy(*str, temp, count);
635 if(hash_mode == TNG_USE_HASH)
637 md5_append(md5_state, (md5_byte_t *)*str, count);
644 * @brief Write a NULL terminated string to a file.
645 * @param tng_data is a trajectory data container
646 * @param str is a pointer to the character string should be written.
647 * @param hash_mode is an option to decide whether to use the md5 hash or not.
648 * @param md5_state is a pointer to the current md5 storage, which will be
649 * appended with str if hash_mode == TNG_USE_HASH.
650 * @param line_nr is the line number where this function was called, to be
651 * able to give more useful error messages.
653 static TNG_INLINE tng_function_status tng_fwritestr(tng_trajectory_t tng_data,
655 const char hash_mode,
656 md5_state_t *md5_state,
661 len = tng_min_size(strlen(str) + 1, TNG_MAX_STR_LEN);
663 if(fwrite(str, len, 1, tng_data->output_file) != 1)
665 fprintf(stderr, "TNG library: Could not write block data. %s: %d\n", __FILE__, line_nr);
666 return(TNG_CRITICAL);
669 if(hash_mode == TNG_USE_HASH)
671 md5_append(md5_state, (md5_byte_t *)str, len);
678 * @brief Read a numerical value from file.
679 * The byte order will be swapped if need be.
680 * @param tng_data is a trajectory data container
681 * @param dest is a pointer to where to store the read data.
682 * @param len is the length (in bytes) of the numerical data type. Should
683 * be 8 for 64 bit, 4 for 32 bit or 1 for a single byte flag.
684 * @param hash_mode is an option to decide whether to use the md5 hash or not.
685 * @param md5_state is a pointer to the current md5 storage, which will be
686 * appended with str if hash_mode == TNG_USE_HASH.
687 * @param line_nr is the line number where this function was called, to be
688 * able to give more useful error messages.
690 static TNG_INLINE tng_function_status tng_file_input_numerical
691 (const tng_trajectory_t tng_data,
694 const char hash_mode,
695 md5_state_t *md5_state,
698 if(fread(dest, len, 1, tng_data->input_file) == 0)
700 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, line_nr);
701 return(TNG_CRITICAL);
703 if(hash_mode == TNG_USE_HASH)
705 md5_append(md5_state, (md5_byte_t *)dest, len);
710 if(tng_data->input_endianness_swap_func_64 &&
711 tng_data->input_endianness_swap_func_64(tng_data, dest) != TNG_SUCCESS)
713 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
718 if(tng_data->input_endianness_swap_func_32 &&
719 tng_data->input_endianness_swap_func_32(tng_data, dest) != TNG_SUCCESS)
721 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
733 * @brief Write a numerical value to file.
734 * The byte order will be swapped if need be.
735 * @param tng_data is a trajectory data container
736 * @param src is a pointer to the data to write.
737 * @param len is the length (in bytes) of the numerical data type. Should
738 * be 8 for 64 bit, 4 for 32 bit or 1 for a single byte flag.
739 * @param hash_mode is an option to decide whether to use the md5 hash or not.
740 * @param md5_state is a pointer to the current md5 storage, which will be
741 * appended with str if hash_mode == TNG_USE_HASH.
742 * @param line_nr is the line number where this function was called, to be
743 * able to give more useful error messages.
745 static TNG_INLINE tng_function_status tng_file_output_numerical
746 (const tng_trajectory_t tng_data,
749 const char hash_mode,
750 md5_state_t *md5_state,
759 temp_i64 = *((int64_t *)src);
760 if(tng_data->output_endianness_swap_func_64 &&
761 tng_data->output_endianness_swap_func_64(tng_data, &temp_i64) != TNG_SUCCESS)
763 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
766 if(fwrite(&temp_i64, len, 1, tng_data->output_file) != 1)
768 fprintf(stderr, "TNG library: Could not write data. %s: %d\n", __FILE__, line_nr);
769 return(TNG_CRITICAL);
771 if(hash_mode == TNG_USE_HASH)
773 md5_append(md5_state, (md5_byte_t *)&temp_i64, len);
777 temp_i32 = *((int32_t *)src);
778 if(tng_data->output_endianness_swap_func_32 &&
779 tng_data->output_endianness_swap_func_32(tng_data, &temp_i32) != TNG_SUCCESS)
781 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
784 if(fwrite(&temp_i32, len, 1, tng_data->output_file) != 1)
786 fprintf(stderr, "TNG library: Could not write data. %s: %d\n", __FILE__, line_nr);
787 return(TNG_CRITICAL);
789 if(hash_mode == TNG_USE_HASH)
791 md5_append(md5_state, (md5_byte_t *)&temp_i32, len);
795 if(fwrite(src, len, 1, tng_data->output_file) != 1)
797 fprintf(stderr, "TNG library: Could not write data. %s: %d\n", __FILE__, line_nr);
798 return(TNG_CRITICAL);
800 if(hash_mode == TNG_USE_HASH)
802 md5_append(md5_state, (md5_byte_t *)src, len);
811 * @brief Generate the md5 hash of a block.
812 * The hash is created based on the actual block contents.
813 * @param block is a general block container.
814 * @return TNG_SUCCESS (0) if successful.
816 static tng_function_status tng_block_md5_hash_generate(const tng_gen_block_t block)
818 md5_state_t md5_state;
820 md5_init(&md5_state);
821 md5_append(&md5_state, (md5_byte_t *)block->block_contents,
822 (int)block->block_contents_size);
823 md5_finish(&md5_state, (md5_byte_t *)block->md5_hash);
829 * @brief If there is data left in the block read that to append that to the MD5 hash.
830 * @param tng_data is a trajectory data container.
831 * @param block is the data block that is being read.
832 * @param start_pos is the file position where the block started.
833 * @param md5_state is the md5 to which the md5 of the remaining block
835 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
838 static tng_function_status tng_md5_remaining_append(const tng_trajectory_t tng_data,
839 const tng_gen_block_t block,
840 const int64_t start_pos,
841 md5_state_t *md5_state)
843 int64_t curr_file_pos;
846 curr_file_pos = ftello(tng_data->input_file);
847 if(curr_file_pos < start_pos + block->block_contents_size)
849 temp_data = malloc(start_pos + block->block_contents_size - curr_file_pos);
852 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
853 start_pos + block->block_contents_size - curr_file_pos, __FILE__, __LINE__);
854 return(TNG_CRITICAL);
856 if(fread(temp_data, start_pos + block->block_contents_size - curr_file_pos,
857 1, tng_data->input_file) == 0)
859 fprintf(stderr, "TNG library: Cannot read remaining part of block to generate MD5 sum. %s: %d\n", __FILE__, __LINE__);
861 return(TNG_CRITICAL);
863 md5_append(md5_state, (md5_byte_t *)temp_data,
864 start_pos + block->block_contents_size - curr_file_pos);
872 * @brief Open the input file if it is not already opened.
873 * @param tng_data is a trajectory data container.
874 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
877 static tng_function_status tng_input_file_init(const tng_trajectory_t tng_data)
881 if(!tng_data->input_file)
883 if(!tng_data->input_file_path)
885 fprintf(stderr, "TNG library: No file specified for reading. %s: %d\n",
887 return(TNG_CRITICAL);
889 tng_data->input_file = fopen(tng_data->input_file_path, "rb");
890 if(!tng_data->input_file)
892 fprintf(stderr, "TNG library: Cannot open file %s. %s: %d\n",
893 tng_data->input_file_path, __FILE__, __LINE__);
894 return(TNG_CRITICAL);
898 if(!tng_data->input_file_len)
900 file_pos = ftello(tng_data->input_file);
901 fseeko(tng_data->input_file, 0, SEEK_END);
902 tng_data->input_file_len = ftello(tng_data->input_file);
903 fseeko(tng_data->input_file, file_pos, SEEK_SET);
910 * @brief Open the output file if it is not already opened
911 * @param tng_data is a trajectory data container.
912 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
915 static tng_function_status tng_output_file_init(const tng_trajectory_t tng_data)
917 if(!tng_data->output_file)
919 if(!tng_data->output_file_path)
921 fprintf(stderr, "TNG library: No file specified for writing. %s: %d\n",
923 return(TNG_CRITICAL);
926 tng_data->output_file = fopen(tng_data->output_file_path, "wb+");
928 if(!tng_data->output_file)
930 fprintf(stderr, "TNG library: Cannot open file %s. %s: %d\n",
931 tng_data->output_file_path, __FILE__, __LINE__);
932 return(TNG_CRITICAL);
939 * @brief Setup a file block container.
940 * @param block_p a pointer to memory to initialise as a file block container.
941 * @details Memory is allocated during initialisation.
942 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
945 static tng_function_status tng_block_init(struct tng_gen_block **block_p)
947 tng_gen_block_t block;
949 *block_p = malloc(sizeof(struct tng_gen_block));
952 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
953 sizeof(struct tng_gen_block), __FILE__, __LINE__);
954 return(TNG_CRITICAL);
960 /* Reset the md5_hash */
961 memset(block->md5_hash, '\0', TNG_MD5_HASH_LEN);
963 block->block_version = TNG_API_VERSION;
964 block->header_contents = 0;
965 block->header_contents_size = 0;
966 block->block_contents = 0;
967 block->block_contents_size = 0;
973 * @brief Clean up a file block container.
974 * @param block_p a pointer to the file block container to destroy.
975 * @details All allocated memory in the data structure is freed, as well as
977 * @return TNG_SUCCESS (0) if successful.
979 static tng_function_status tng_block_destroy(struct tng_gen_block **block_p)
981 tng_gen_block_t block = *block_p;
988 /* fprintf(stderr, "TNG library: Destroying block\n"); */
994 if(block->header_contents)
996 free(block->header_contents);
997 block->header_contents = 0;
999 if(block->block_contents)
1001 free(block->block_contents);
1002 block->block_contents = 0;
1008 return(TNG_SUCCESS);
1012 * @brief Read the header of a data block, regardless of its type
1013 * @param tng_data is a trajectory data container.
1014 * @param block is a general block container.
1015 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE(1) if a minor
1016 * error has occured (not able to read the header size, thus skipping
1017 * the block) or TNG_CRITICAL (2) if a major error has occured.
1019 static tng_function_status tng_block_header_read
1020 (const tng_trajectory_t tng_data, const tng_gen_block_t block)
1024 TNG_ASSERT(block != 0, "TNG library: Trying to read to uninitialized block (NULL pointer).");
1026 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
1028 return(TNG_CRITICAL);
1031 start_pos = ftello(tng_data->input_file);
1033 /* First read the header size to be able to read the whole header. */
1034 if(fread(&block->header_contents_size, sizeof(block->header_contents_size),
1035 1, tng_data->input_file) == 0)
1037 fprintf(stderr, "TNG library: Cannot read header size. %s: %d\n",
1038 __FILE__, __LINE__);
1039 return(TNG_CRITICAL);
1042 if(block->header_contents_size == 0)
1045 return(TNG_FAILURE);
1048 /* If this was the size of the general info block check the endianness */
1049 if(ftello(tng_data->input_file) < 9)
1051 /* File is little endian */
1052 if ( *((const char*)&block->header_contents_size) != 0x00 &&
1053 *((const char*)(&block->header_contents_size) + 7) == 0x00)
1055 /* If the architecture endianness is little endian no byte swap
1056 * will be needed. Otherwise use the functions to swap to little
1058 if(tng_data->endianness_32 == TNG_LITTLE_ENDIAN_32)
1060 tng_data->input_endianness_swap_func_32 = 0;
1064 tng_data->input_endianness_swap_func_32 =
1065 &tng_swap_byte_order_little_endian_32;
1067 if(tng_data->endianness_64 == TNG_LITTLE_ENDIAN_64)
1069 tng_data->input_endianness_swap_func_64 = 0;
1073 tng_data->input_endianness_swap_func_64 =
1074 &tng_swap_byte_order_little_endian_64;
1077 /* File is big endian */
1080 /* If the architecture endianness is big endian no byte swap
1081 * will be needed. Otherwise use the functions to swap to big
1083 if(tng_data->endianness_32 == TNG_BIG_ENDIAN_32)
1085 tng_data->input_endianness_swap_func_32 = 0;
1089 tng_data->input_endianness_swap_func_32 =
1090 &tng_swap_byte_order_big_endian_32;
1092 if(tng_data->endianness_64 == TNG_BIG_ENDIAN_64)
1094 tng_data->input_endianness_swap_func_64 = 0;
1098 tng_data->input_endianness_swap_func_64 =
1099 &tng_swap_byte_order_big_endian_64;
1104 if(tng_data->input_endianness_swap_func_64 &&
1105 tng_data->input_endianness_swap_func_64(tng_data, &block->header_contents_size) != TNG_SUCCESS)
1107 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1108 __FILE__, __LINE__);
1111 if(tng_file_input_numerical(tng_data, &block->block_contents_size,
1112 sizeof(block->block_contents_size),
1113 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
1115 return(TNG_CRITICAL);
1118 if(tng_file_input_numerical(tng_data, &block->id,
1120 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
1122 return(TNG_CRITICAL);
1125 if(fread(block->md5_hash, TNG_MD5_HASH_LEN, 1, tng_data->input_file) == 0)
1127 fprintf(stderr, "TNG library: Cannot read block header. %s: %d\n", __FILE__, __LINE__);
1128 return(TNG_CRITICAL);
1131 tng_freadstr(tng_data, &block->name, TNG_SKIP_HASH, 0, __LINE__);
1133 if(tng_file_input_numerical(tng_data, &block->block_version,
1134 sizeof(block->block_version),
1135 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
1137 return(TNG_CRITICAL);
1140 fseeko(tng_data->input_file, start_pos + block->header_contents_size, SEEK_SET);
1142 return(TNG_SUCCESS);
1146 * @brief Write a whole block, both header and contents, regardless of it type
1147 * @param tng_data is a trajectory data container.
1148 * @param block is a general block container.
1149 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if a minor error
1150 * has occurred or TNG_CRITICAL (2) if a major error has occured.
1152 /* Disabled until it is used.*/
1154 // static tng_function_status tng_block_verbatim_write(tng_trajectory_t tng_data,
1155 // tng_gen_block_t block)
1157 // if(!block->header_contents)
1159 // fprintf(stderr, "TNG library: No contents to write. %s: %d\n", __FILE__, __LINE__);
1160 // return(TNG_FAILURE);
1162 // if(fwrite(block->header_contents, block->header_contents_size, 1,
1163 // tng_data->output_file) != 1)
1165 // fprintf(stderr, "TNG library: Could not write all header data. %s: %d\n",
1166 // __FILE__, __LINE__);
1167 // return(TNG_CRITICAL);
1170 // if(!block->block_contents)
1172 // fprintf(stderr, "TNG library: No block data to write. %s: %d\n",
1173 // __FILE__, __LINE__);
1174 // return(TNG_FAILURE);
1176 // if(fwrite(block->block_contents, block->block_contents_size, 1,
1177 // tng_data->output_file) != 1)
1179 // fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n",
1180 // __FILE__, __LINE__);
1181 // return(TNG_CRITICAL);
1183 // return(TNG_SUCCESS);
1188 * @brief Update the md5 hash of a block already written to the file
1189 * @param tng_data is a trajectory data container.
1190 * @param block is the block, of which to update the md5 hash.
1191 * @param header_start_pos is the file position where the block header starts.
1192 * @param contents_start_pos is the file position where the block contents
1194 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
1195 * error has occured.
1197 static tng_function_status tng_md5_hash_update(const tng_trajectory_t tng_data,
1198 const tng_gen_block_t block,
1199 const int64_t header_start_pos,
1200 const int64_t contents_start_pos)
1202 if(block->block_contents)
1204 free(block->block_contents);
1207 block->block_contents = malloc(block->block_contents_size);
1208 if(!block->block_contents)
1210 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
1211 block->block_contents_size, __FILE__, __LINE__);
1212 return(TNG_CRITICAL);
1215 fseeko(tng_data->output_file, contents_start_pos, SEEK_SET);
1216 if(fread(block->block_contents, block->block_contents_size, 1,
1217 tng_data->output_file) == 0)
1219 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
1220 return(TNG_CRITICAL);
1223 tng_block_md5_hash_generate(block);
1225 fseeko(tng_data->output_file, header_start_pos + 3 * sizeof(int64_t),
1227 fwrite(block->md5_hash, TNG_MD5_HASH_LEN, 1, tng_data->output_file);
1229 return(TNG_SUCCESS);
1233 * @brief Update the frame set pointers in the file header (general info block),
1234 * already written to disk
1235 * @param tng_data is a trajectory data container.
1236 * @param hash_mode specifies whether to update the block md5 hash when
1237 * updating the pointers.
1238 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
1239 * error has occured.
1241 static tng_function_status tng_header_pointers_update
1242 (const tng_trajectory_t tng_data, const char hash_mode)
1244 tng_gen_block_t block;
1245 FILE *temp = tng_data->input_file;
1246 int64_t output_file_pos, pos, contents_start_pos;
1248 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
1250 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
1251 __FILE__, __LINE__);
1252 return(TNG_CRITICAL);
1255 tng_data->input_file = tng_data->output_file;
1257 tng_block_init(&block);
1259 output_file_pos = ftello(tng_data->output_file);
1260 fseeko(tng_data->output_file, 0, SEEK_SET);
1262 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1264 fprintf(stderr, "TNG library: Cannot read general info header. %s: %d\n",
1265 __FILE__, __LINE__);
1266 tng_data->input_file = temp;
1267 tng_block_destroy(&block);
1268 return(TNG_CRITICAL);
1271 contents_start_pos = ftello(tng_data->output_file);
1273 fseeko(tng_data->output_file, block->block_contents_size - 5 *
1274 sizeof(int64_t), SEEK_CUR);
1276 tng_data->input_file = temp;
1278 pos = tng_data->first_trajectory_frame_set_output_file_pos;
1280 if(tng_data->input_endianness_swap_func_64)
1282 if(tng_data->input_endianness_swap_func_64(tng_data,
1286 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1287 __FILE__, __LINE__);
1291 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1293 tng_block_destroy(&block);
1294 return(TNG_CRITICAL);
1297 pos = tng_data->last_trajectory_frame_set_output_file_pos;
1299 if(tng_data->input_endianness_swap_func_64)
1301 if(tng_data->input_endianness_swap_func_64(tng_data,
1305 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1306 __FILE__, __LINE__);
1311 sizeof(int64_t), 1, tng_data->output_file) != 1)
1313 tng_block_destroy(&block);
1314 return(TNG_CRITICAL);
1317 if(hash_mode == TNG_USE_HASH)
1319 tng_md5_hash_update(tng_data, block, 0, contents_start_pos);
1322 tng_block_destroy(&block);
1324 fseeko(tng_data->output_file, output_file_pos, SEEK_SET);
1326 return(TNG_SUCCESS);
1330 * @brief Update the frame set pointers in the current frame set block, already
1331 * written to disk. It also updates the pointers of the blocks pointing to
1332 * the current frame set block.
1333 * @param tng_data is a trajectory data container.
1334 * @param hash_mode specifies whether to update the block md5 hash when
1335 * updating the pointers.
1336 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
1337 * error has occured.
1339 static tng_function_status tng_frame_set_pointers_update
1340 (const tng_trajectory_t tng_data, const char hash_mode)
1342 tng_gen_block_t block;
1343 tng_trajectory_frame_set_t frame_set;
1344 FILE *temp = tng_data->input_file;
1345 int64_t pos, output_file_pos, contents_start_pos;
1347 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
1349 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
1350 __FILE__, __LINE__);
1351 return(TNG_CRITICAL);
1354 tng_block_init(&block);
1355 output_file_pos = ftello(tng_data->output_file);
1357 tng_data->input_file = tng_data->output_file;
1359 frame_set = &tng_data->current_trajectory_frame_set;
1361 pos = tng_data->current_trajectory_frame_set_output_file_pos;
1363 /* Update next frame set */
1364 if(frame_set->next_frame_set_file_pos > 0)
1366 fseeko(tng_data->output_file, frame_set->next_frame_set_file_pos, SEEK_SET);
1368 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1370 fprintf(stderr, "TNG library: Cannot read frame header. %s: %d\n",
1371 __FILE__, __LINE__);
1372 tng_data->input_file = temp;
1373 tng_block_destroy(&block);
1374 return(TNG_CRITICAL);
1377 contents_start_pos = ftello(tng_data->output_file);
1379 fseeko(tng_data->output_file, block->block_contents_size - (5 *
1380 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
1382 if(tng_data->input_endianness_swap_func_64)
1384 if(tng_data->input_endianness_swap_func_64(tng_data,
1388 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1389 __FILE__, __LINE__);
1393 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1395 tng_data->input_file = temp;
1396 tng_block_destroy(&block);
1397 return(TNG_CRITICAL);
1400 if(hash_mode == TNG_USE_HASH)
1402 tng_md5_hash_update(tng_data, block, frame_set->next_frame_set_file_pos,
1403 contents_start_pos);
1406 /* Update previous frame set */
1407 if(frame_set->prev_frame_set_file_pos > 0)
1409 fseeko(tng_data->output_file, frame_set->prev_frame_set_file_pos,
1412 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1414 fprintf(stderr, "TNG library: Cannot read frame header. %s: %d\n",
1415 __FILE__, __LINE__);
1416 tng_data->input_file = temp;
1417 tng_block_destroy(&block);
1418 return(TNG_CRITICAL);
1421 contents_start_pos = ftello(tng_data->output_file);
1423 fseeko(tng_data->output_file, block->block_contents_size - (6 *
1424 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
1426 if(tng_data->input_endianness_swap_func_64)
1428 if(tng_data->input_endianness_swap_func_64(tng_data,
1432 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1433 __FILE__, __LINE__);
1437 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1439 tng_data->input_file = temp;
1440 tng_block_destroy(&block);
1441 return(TNG_CRITICAL);
1444 if(hash_mode == TNG_USE_HASH)
1446 tng_md5_hash_update(tng_data, block, frame_set->prev_frame_set_file_pos,
1447 contents_start_pos);
1451 /* Update the frame set one medium stride step after */
1452 if(frame_set->medium_stride_next_frame_set_file_pos > 0)
1454 fseeko(tng_data->output_file,
1455 frame_set->medium_stride_next_frame_set_file_pos,
1458 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1460 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
1461 __FILE__, __LINE__);
1462 tng_data->input_file = temp;
1463 tng_block_destroy(&block);
1464 return(TNG_CRITICAL);
1467 contents_start_pos = ftello(tng_data->output_file);
1469 fseeko(tng_data->output_file, block->block_contents_size - (3 *
1470 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
1472 if(tng_data->input_endianness_swap_func_64)
1474 if(tng_data->input_endianness_swap_func_64(tng_data,
1478 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1479 __FILE__, __LINE__);
1483 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1485 tng_data->input_file = temp;
1486 tng_block_destroy(&block);
1487 return(TNG_CRITICAL);
1490 if(hash_mode == TNG_USE_HASH)
1492 tng_md5_hash_update(tng_data, block,
1493 frame_set->medium_stride_next_frame_set_file_pos,
1494 contents_start_pos);
1497 /* Update the frame set one medium stride step before */
1498 if(frame_set->medium_stride_prev_frame_set_file_pos > 0)
1500 fseeko(tng_data->output_file,
1501 frame_set->medium_stride_prev_frame_set_file_pos,
1504 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1506 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
1507 __FILE__, __LINE__);
1508 tng_data->input_file = temp;
1509 tng_block_destroy(&block);
1510 return(TNG_CRITICAL);
1513 contents_start_pos = ftello(tng_data->output_file);
1515 fseeko(tng_data->output_file, block->block_contents_size - (4 *
1516 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
1518 if(tng_data->input_endianness_swap_func_64)
1520 if(tng_data->input_endianness_swap_func_64(tng_data,
1524 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1525 __FILE__, __LINE__);
1529 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1531 tng_data->input_file = temp;
1532 tng_block_destroy(&block);
1533 return(TNG_CRITICAL);
1536 if(hash_mode == TNG_USE_HASH)
1538 tng_md5_hash_update(tng_data, block,
1539 frame_set->medium_stride_prev_frame_set_file_pos,
1540 contents_start_pos);
1544 /* Update the frame set one long stride step after */
1545 if(frame_set->long_stride_next_frame_set_file_pos > 0)
1547 fseeko(tng_data->output_file,
1548 frame_set->long_stride_next_frame_set_file_pos,
1551 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1553 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
1554 __FILE__, __LINE__);
1555 tng_data->input_file = temp;
1556 tng_block_destroy(&block);
1557 return(TNG_CRITICAL);
1560 contents_start_pos = ftello(tng_data->output_file);
1562 fseeko(tng_data->output_file, block->block_contents_size - (1 *
1563 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
1565 if(tng_data->input_endianness_swap_func_64)
1567 if(tng_data->input_endianness_swap_func_64(tng_data,
1571 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1572 __FILE__, __LINE__);
1576 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1578 tng_data->input_file = temp;
1579 tng_block_destroy(&block);
1580 return(TNG_CRITICAL);
1583 if(hash_mode == TNG_USE_HASH)
1585 tng_md5_hash_update(tng_data, block,
1586 frame_set->long_stride_next_frame_set_file_pos,
1587 contents_start_pos);
1590 /* Update the frame set one long stride step before */
1591 if(frame_set->long_stride_prev_frame_set_file_pos > 0)
1593 fseeko(tng_data->output_file,
1594 frame_set->long_stride_prev_frame_set_file_pos,
1597 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
1599 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
1600 __FILE__, __LINE__);
1601 tng_data->input_file = temp;
1602 tng_block_destroy(&block);
1603 return(TNG_CRITICAL);
1606 contents_start_pos = ftello(tng_data->output_file);
1608 fseeko(tng_data->output_file, block->block_contents_size - (2 *
1609 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
1611 if(tng_data->input_endianness_swap_func_64)
1613 if(tng_data->input_endianness_swap_func_64(tng_data,
1617 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
1618 __FILE__, __LINE__);
1622 if(fwrite(&pos, sizeof(int64_t), 1, tng_data->output_file) != 1)
1624 tng_data->input_file = temp;
1625 tng_block_destroy(&block);
1626 return(TNG_CRITICAL);
1629 if(hash_mode == TNG_USE_HASH)
1631 tng_md5_hash_update(tng_data, block,
1632 frame_set->long_stride_prev_frame_set_file_pos,
1633 contents_start_pos);
1637 fseeko(tng_data->output_file, output_file_pos, SEEK_SET);
1639 tng_data->input_file = temp;
1641 tng_block_destroy(&block);
1643 return(TNG_SUCCESS);
1646 static tng_function_status tng_reread_frame_set_at_file_pos
1647 (const tng_trajectory_t tng_data,
1650 tng_gen_block_t block;
1651 tng_function_status stat;
1653 tng_block_init(&block);
1655 fseeko(tng_data->input_file, pos, SEEK_SET);
1658 stat = tng_block_header_read(tng_data, block);
1659 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
1661 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", pos,
1662 __FILE__, __LINE__);
1663 tng_block_destroy(&block);
1664 return(TNG_FAILURE);
1667 if(tng_block_read_next(tng_data, block,
1668 TNG_SKIP_HASH) != TNG_SUCCESS)
1670 tng_block_destroy(&block);
1671 return(TNG_CRITICAL);
1675 tng_block_destroy(&block);
1677 return(TNG_SUCCESS);
1680 static tng_function_status tng_file_pos_of_subsequent_trajectory_block_get
1681 (const tng_trajectory_t tng_data,
1684 int64_t orig_pos, curr_frame_set_pos;
1685 tng_gen_block_t block;
1686 tng_function_status stat;
1687 tng_trajectory_frame_set_t frame_set =
1688 &tng_data->current_trajectory_frame_set;
1690 orig_pos = ftello(tng_data->input_file);
1691 curr_frame_set_pos = tng_data->current_trajectory_frame_set_input_file_pos;
1693 *pos = tng_data->first_trajectory_frame_set_input_file_pos;
1697 return(TNG_SUCCESS);
1700 fseeko(tng_data->input_file, *pos, SEEK_SET);
1702 tng_block_init(&block);
1703 /* Read block headers first to see that a frame set block is found. */
1704 stat = tng_block_header_read(tng_data, block);
1705 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
1707 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", *pos,
1708 __FILE__, __LINE__);
1709 tng_block_destroy(&block);
1710 return(TNG_FAILURE);
1713 if(tng_block_read_next(tng_data, block,
1714 TNG_SKIP_HASH) != TNG_SUCCESS)
1716 tng_block_destroy(&block);
1717 return(TNG_CRITICAL);
1720 /* Read all frame set blocks (not the blocks between them) */
1721 while(frame_set->next_frame_set_file_pos > 0)
1723 fseeko(tng_data->input_file, frame_set->next_frame_set_file_pos, SEEK_SET);
1724 stat = tng_block_header_read(tng_data, block);
1725 if(stat == TNG_CRITICAL)
1727 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", *pos,
1728 __FILE__, __LINE__);
1729 tng_block_destroy(&block);
1730 return(TNG_CRITICAL);
1732 if(stat != TNG_SUCCESS || block->id != TNG_TRAJECTORY_FRAME_SET)
1734 return(TNG_FAILURE);
1737 stat = tng_block_read_next(tng_data, block, TNG_SKIP_HASH);
1738 if(stat != TNG_SUCCESS)
1740 tng_block_destroy(&block);
1743 /* Update *pos if this is the earliest frame set so far (after orig_pos) */
1744 if(tng_data->current_trajectory_frame_set_input_file_pos < *pos &&
1745 tng_data->current_trajectory_frame_set_input_file_pos > orig_pos)
1747 *pos = tng_data->current_trajectory_frame_set_input_file_pos;
1751 /* Re-read the frame set that used to be the current one */
1752 tng_reread_frame_set_at_file_pos(tng_data, curr_frame_set_pos);
1754 fseeko(tng_data->input_file, orig_pos, SEEK_SET);
1756 tng_block_destroy(&block);
1758 return(TNG_SUCCESS);
1762 * @brief Migrate a whole frame set from one position in the file to another.
1763 * @param tng_data is a trajectory data container.
1764 * @param block_start_pos is the starting position in the file of the frame set.
1765 * @param block_len is the length of the whole frame set (including all data blocks etc).
1766 * @param new_pos is the new position in the file of the frame set.
1767 * @param hash_mode is an option to decide whether to generate/update the relevant md5 hashes.
1769 static tng_function_status tng_frame_set_complete_migrate
1770 (const tng_trajectory_t tng_data,
1771 const int64_t block_start_pos,
1772 const int64_t block_len,
1773 const int64_t new_pos,
1774 const char hash_mode)
1776 tng_bool updated = TNG_FALSE;
1780 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
1782 return(TNG_CRITICAL);
1785 fseeko(tng_data->input_file, block_start_pos, SEEK_SET);
1787 contents = malloc(block_len);
1790 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
1791 block_len, __FILE__, __LINE__);
1792 return(TNG_CRITICAL);
1795 if(fread(contents, block_len, 1, tng_data->input_file) == 0)
1797 fprintf(stderr, "TNG library: Cannot read data from file when migrating data. %s: %d\n",
1798 __FILE__, __LINE__);
1800 return(TNG_CRITICAL);
1802 fseeko(tng_data->output_file, new_pos, SEEK_SET);
1804 if(fwrite(contents, block_len, 1, tng_data->output_file) != 1)
1806 fprintf(stderr, "TNG library: Could not write data to file when migrating data. %s: %d\n",
1807 __FILE__, __LINE__);
1809 return(TNG_CRITICAL);
1812 tng_data->current_trajectory_frame_set_output_file_pos = new_pos;
1814 tng_frame_set_pointers_update(tng_data, hash_mode);
1816 /* Update the general info block if needed */
1817 if(block_start_pos == tng_data->first_trajectory_frame_set_output_file_pos)
1819 tng_data->first_trajectory_frame_set_output_file_pos = new_pos;
1822 if(block_start_pos == tng_data->last_trajectory_frame_set_output_file_pos)
1824 tng_data->last_trajectory_frame_set_output_file_pos = new_pos;
1829 tng_header_pointers_update(tng_data, hash_mode);
1832 /* Fill the block with NULL to avoid confusion. */
1833 memset(contents, '\0', block_len);
1834 fseeko(tng_data->output_file, block_start_pos, SEEK_SET);
1836 /* FIXME: casting block_len to size_t is dangerous */
1837 fwrite(contents, 1, block_len, tng_data->output_file);
1841 return(TNG_SUCCESS);
1844 static tng_function_status tng_length_of_current_frame_set_contents_get
1845 (const tng_trajectory_t tng_data,
1848 int64_t orig_pos, pos, curr_frame_set_pos;
1849 tng_gen_block_t block;
1850 tng_function_status stat;
1852 orig_pos = ftello(tng_data->input_file);
1853 curr_frame_set_pos = pos = tng_data->current_trajectory_frame_set_input_file_pos;
1857 fseeko(tng_data->input_file, curr_frame_set_pos, SEEK_SET);
1859 tng_block_init(&block);
1860 /* Read block headers first to see that a frame set block is found. */
1861 stat = tng_block_header_read(tng_data, block);
1862 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
1864 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
1865 curr_frame_set_pos, __FILE__, __LINE__);
1866 tng_block_destroy(&block);
1867 return(TNG_FAILURE);
1870 /* Read the headers of all blocks in the frame set (not the actual contents of them) */
1871 while(stat == TNG_SUCCESS)
1873 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
1874 *len += block->header_contents_size + block->block_contents_size;
1875 pos += block->header_contents_size + block->block_contents_size;
1876 if(pos >= tng_data->input_file_len)
1880 stat = tng_block_header_read(tng_data, block);
1881 if(block->id == TNG_TRAJECTORY_FRAME_SET)
1887 /* Re-read the frame set that used to be the current one */
1888 tng_reread_frame_set_at_file_pos(tng_data, curr_frame_set_pos);
1890 fseeko(tng_data->input_file, orig_pos, SEEK_SET);
1892 tng_block_destroy(&block);
1894 return(TNG_SUCCESS);
1898 * @brief Migrate blocks in the file to make room for new data in a block. This
1899 * is required e.g. when adding data to a block or extending strings in a
1901 * @param tng_data is a trajectory data container.
1902 * @param start_pos is the position from which to start moving data, usually
1903 * the byte after the end of the block to which data was added.
1904 * @param offset is the number of bytes that were inserted.
1905 * @param hash_mode is an option to decide whether to generate/update the relevant md5 hashes.
1906 * @details Trajectory blocks (frame sets and their related blocks) are moved
1907 * to the end of the file (if needed) in order to make room for non-trajectory
1910 static tng_function_status tng_migrate_data_in_file
1911 (const tng_trajectory_t tng_data,
1912 const int64_t start_pos,
1913 const int64_t offset,
1914 const char hash_mode)
1916 int64_t traj_start_pos, empty_space, orig_file_pos, frame_set_length;
1917 tng_gen_block_t block;
1918 tng_function_status stat;
1922 return(TNG_SUCCESS);
1925 stat = tng_file_pos_of_subsequent_trajectory_block_get(tng_data, &traj_start_pos);
1926 if(stat != TNG_SUCCESS)
1931 tng_data->current_trajectory_frame_set_input_file_pos = traj_start_pos;
1933 empty_space = traj_start_pos - (start_pos - 1);
1935 if(empty_space >= offset)
1937 return(TNG_SUCCESS);
1940 orig_file_pos = ftello(tng_data->input_file);
1941 tng_block_init(&block);
1943 while(empty_space < offset)
1945 fseeko(tng_data->input_file, traj_start_pos, SEEK_SET);
1946 stat = tng_block_header_read(tng_data, block);
1947 if(stat == TNG_CRITICAL)
1949 fprintf(stderr, "TNG library: Cannot read block header. %s: %d\n",
1950 __FILE__, __LINE__);
1951 tng_block_destroy(&block);
1952 return(TNG_CRITICAL);
1954 if(stat != TNG_SUCCESS || block->id != TNG_TRAJECTORY_FRAME_SET)
1956 tng_block_destroy(&block);
1957 return(TNG_FAILURE);
1959 stat = tng_length_of_current_frame_set_contents_get(tng_data, &frame_set_length);
1960 if(stat != TNG_SUCCESS)
1962 tng_block_destroy(&block);
1965 stat = tng_frame_set_complete_migrate(tng_data, traj_start_pos,
1966 frame_set_length, tng_data->input_file_len,
1968 if(stat != TNG_SUCCESS)
1970 tng_block_destroy(&block);
1974 empty_space += frame_set_length;
1976 fseeko(tng_data->input_file, orig_file_pos, SEEK_SET);
1977 tng_block_destroy(&block);
1979 return(TNG_SUCCESS);
1982 static tng_function_status tng_block_header_len_calculate
1983 (const tng_trajectory_t tng_data,
1984 const tng_gen_block_t block,
1990 /* If the string is unallocated allocate memory for just string
1994 block->name = malloc(1);
1997 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
1998 __FILE__, __LINE__);
1999 return(TNG_CRITICAL);
2004 name_len = tng_min_size(strlen(block->name) + 1, TNG_MAX_STR_LEN);
2006 /* Calculate the size of the header to write */
2007 *len = sizeof(block->header_contents_size) +
2008 sizeof(block->block_contents_size) +
2010 sizeof(block->block_version) +
2014 return (TNG_SUCCESS);
2018 * @brief Write the header of a data block, regardless of its type
2019 * @param tng_data is a trajectory data container.
2020 * @param block is a general block container.
2021 * @param hash_mode is an option to decide whether to use the md5 hash or not.
2022 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
2023 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
2024 * error has occured.
2026 static tng_function_status tng_block_header_write
2027 (const tng_trajectory_t tng_data,
2028 const tng_gen_block_t block)
2030 TNG_ASSERT(block != 0, "TNG library: Trying to write uninitialized block (NULL pointer).");
2032 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
2034 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
2035 __FILE__, __LINE__);
2036 return(TNG_CRITICAL);
2039 if(tng_block_header_len_calculate(tng_data, block, &block->header_contents_size) !=
2042 fprintf(stderr, "TNG library: Cannot calculate length of block header. %s: %d\n",
2043 __FILE__, __LINE__);
2044 return(TNG_CRITICAL);
2047 if(tng_file_output_numerical(tng_data, &block->header_contents_size,
2048 sizeof(block->header_contents_size),
2049 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
2051 return(TNG_CRITICAL);
2054 if(tng_file_output_numerical(tng_data, &block->block_contents_size,
2055 sizeof(block->block_contents_size),
2056 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
2058 return(TNG_CRITICAL);
2061 if(tng_file_output_numerical(tng_data, &block->id,
2063 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
2065 return(TNG_CRITICAL);
2068 if(fwrite(block->md5_hash, TNG_MD5_HASH_LEN, 1, tng_data->output_file) != 1)
2070 fprintf(stderr, "TNG library: Could not write header data. %s: %d\n", __FILE__, __LINE__);
2071 return(TNG_CRITICAL);
2074 if(tng_fwritestr(tng_data, block->name, TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
2076 return(TNG_CRITICAL);
2079 if(tng_file_output_numerical(tng_data, &block->block_version,
2080 sizeof(block->block_version),
2081 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
2083 return(TNG_CRITICAL);
2086 return(TNG_SUCCESS);
2089 static tng_function_status tng_general_info_block_len_calculate
2090 (const tng_trajectory_t tng_data,
2093 size_t first_program_name_len, first_user_name_len;
2094 size_t first_computer_name_len, first_pgp_signature_len;
2095 size_t last_program_name_len, last_user_name_len;
2096 size_t last_computer_name_len, last_pgp_signature_len;
2097 size_t forcefield_name_len;
2099 /* If the strings are unallocated allocate memory for just string
2101 if(!tng_data->first_program_name)
2103 tng_data->first_program_name = malloc(1);
2104 if(!tng_data->first_program_name)
2106 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2107 __FILE__, __LINE__);
2108 return(TNG_CRITICAL);
2110 tng_data->first_program_name[0] = 0;
2112 if(!tng_data->last_program_name)
2114 tng_data->last_program_name = malloc(1);
2115 if(!tng_data->last_program_name)
2117 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2118 __FILE__, __LINE__);
2119 return(TNG_CRITICAL);
2121 tng_data->last_program_name[0] = 0;
2123 if(!tng_data->first_user_name)
2125 tng_data->first_user_name = malloc(1);
2126 if(!tng_data->first_user_name)
2128 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2129 __FILE__, __LINE__);
2130 return(TNG_CRITICAL);
2132 tng_data->first_user_name[0] = 0;
2134 if(!tng_data->last_user_name)
2136 tng_data->last_user_name = malloc(1);
2137 if(!tng_data->last_user_name)
2139 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2140 __FILE__, __LINE__);
2141 return(TNG_CRITICAL);
2143 tng_data->last_user_name[0] = 0;
2145 if(!tng_data->first_computer_name)
2147 tng_data->first_computer_name = malloc(1);
2148 if(!tng_data->first_computer_name)
2150 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2151 __FILE__, __LINE__);
2152 return(TNG_CRITICAL);
2154 tng_data->first_computer_name[0] = 0;
2156 if(!tng_data->last_computer_name)
2158 tng_data->last_computer_name = malloc(1);
2159 if(!tng_data->last_computer_name)
2161 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2162 __FILE__, __LINE__);
2163 return(TNG_CRITICAL);
2165 tng_data->last_computer_name[0] = 0;
2167 if(!tng_data->first_pgp_signature)
2169 tng_data->first_pgp_signature = malloc(1);
2170 if(!tng_data->first_pgp_signature)
2172 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2173 __FILE__, __LINE__);
2174 return(TNG_CRITICAL);
2176 tng_data->first_pgp_signature[0] = 0;
2178 if(!tng_data->last_pgp_signature)
2180 tng_data->last_pgp_signature = malloc(1);
2181 if(!tng_data->last_pgp_signature)
2183 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2184 __FILE__, __LINE__);
2185 return(TNG_CRITICAL);
2187 tng_data->last_pgp_signature[0] = 0;
2189 if(!tng_data->forcefield_name)
2191 tng_data->forcefield_name = malloc(1);
2192 if(!tng_data->forcefield_name)
2194 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2195 __FILE__, __LINE__);
2196 return(TNG_CRITICAL);
2198 tng_data->forcefield_name[0] = 0;
2201 first_program_name_len = tng_min_size(strlen(tng_data->first_program_name) + 1,
2203 last_program_name_len = tng_min_size(strlen(tng_data->last_program_name) + 1,
2205 first_user_name_len = tng_min_size(strlen(tng_data->first_user_name) + 1,
2207 last_user_name_len = tng_min_size(strlen(tng_data->last_user_name) + 1,
2209 first_computer_name_len = tng_min_size(strlen(tng_data->first_computer_name) + 1,
2211 last_computer_name_len = tng_min_size(strlen(tng_data->last_computer_name) + 1,
2213 first_pgp_signature_len = tng_min_size(strlen(tng_data->first_pgp_signature) + 1,
2215 last_pgp_signature_len = tng_min_size(strlen(tng_data->last_pgp_signature) + 1,
2217 forcefield_name_len = tng_min_size(strlen(tng_data->forcefield_name) + 1,
2220 *len = sizeof(tng_data->time) +
2221 sizeof(tng_data->var_num_atoms_flag) +
2222 sizeof(tng_data->frame_set_n_frames) +
2223 sizeof(tng_data->first_trajectory_frame_set_input_file_pos) +
2224 sizeof(tng_data->last_trajectory_frame_set_input_file_pos) +
2225 sizeof(tng_data->medium_stride_length) +
2226 sizeof(tng_data->long_stride_length) +
2227 sizeof(tng_data->distance_unit_exponential) +
2228 first_program_name_len +
2229 last_program_name_len +
2230 first_user_name_len +
2231 last_user_name_len +
2232 first_computer_name_len +
2233 last_computer_name_len +
2234 first_pgp_signature_len +
2235 last_pgp_signature_len +
2236 forcefield_name_len;
2238 return(TNG_SUCCESS);
2242 * @brief Read a general info block. This is the first block of a TNG file.
2243 * Populate the fields in tng_data.
2244 * @param tng_data is a trajectory data container.
2245 * @param block is a general block container.
2246 * @param hash_mode is an option to decide whether to use the md5 hash or not.
2247 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
2248 * compared to the md5 hash of the read contents to ensure valid data.
2249 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
2250 * error has occured.
2252 static tng_function_status tng_general_info_block_read
2253 (const tng_trajectory_t tng_data,
2254 const tng_gen_block_t block,
2255 const char hash_mode)
2258 char hash[TNG_MD5_HASH_LEN];
2259 md5_state_t md5_state;
2261 TNG_ASSERT(block != 0, "TNG library: Trying to read data to an uninitialized block (NULL pointer)");
2263 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
2265 return(TNG_CRITICAL);
2268 start_pos = ftello(tng_data->input_file);
2270 if(hash_mode == TNG_USE_HASH)
2272 md5_init(&md5_state);
2275 tng_freadstr(tng_data, &tng_data->first_program_name, hash_mode, &md5_state, __LINE__);
2277 tng_freadstr(tng_data, &tng_data->last_program_name, hash_mode, &md5_state, __LINE__);
2279 tng_freadstr(tng_data, &tng_data->first_user_name, hash_mode, &md5_state, __LINE__);
2281 tng_freadstr(tng_data, &tng_data->last_user_name, hash_mode, &md5_state, __LINE__);
2283 tng_freadstr(tng_data, &tng_data->first_computer_name, hash_mode, &md5_state, __LINE__);
2285 tng_freadstr(tng_data, &tng_data->last_computer_name, hash_mode, &md5_state, __LINE__);
2287 tng_freadstr(tng_data, &tng_data->first_pgp_signature, hash_mode, &md5_state, __LINE__);
2289 tng_freadstr(tng_data, &tng_data->last_pgp_signature, hash_mode, &md5_state, __LINE__);
2291 tng_freadstr(tng_data, &tng_data->forcefield_name, hash_mode, &md5_state, __LINE__);
2293 if(tng_file_input_numerical(tng_data, &tng_data->time, sizeof(tng_data->time),
2294 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2296 return(TNG_CRITICAL);
2300 if(tng_file_input_numerical(tng_data, &tng_data->var_num_atoms_flag,
2301 sizeof(tng_data->var_num_atoms_flag),
2302 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2304 return(TNG_CRITICAL);
2307 if(tng_file_input_numerical(tng_data, &tng_data->frame_set_n_frames,
2308 sizeof(tng_data->frame_set_n_frames),
2309 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2311 return(TNG_CRITICAL);
2314 if(tng_file_input_numerical(tng_data,
2315 &tng_data->first_trajectory_frame_set_input_file_pos,
2316 sizeof(tng_data->first_trajectory_frame_set_input_file_pos),
2317 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2319 return(TNG_CRITICAL);
2322 tng_data->current_trajectory_frame_set.next_frame_set_file_pos =
2323 tng_data->first_trajectory_frame_set_input_file_pos;
2325 if(tng_file_input_numerical(tng_data,
2326 &tng_data->last_trajectory_frame_set_input_file_pos,
2327 sizeof(tng_data->last_trajectory_frame_set_input_file_pos),
2328 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2330 return(TNG_CRITICAL);
2333 if(tng_file_input_numerical(tng_data,
2334 &tng_data->medium_stride_length,
2335 sizeof(tng_data->medium_stride_length),
2336 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2338 return(TNG_CRITICAL);
2341 if(tng_file_input_numerical(tng_data,
2342 &tng_data->long_stride_length,
2343 sizeof(tng_data->long_stride_length),
2344 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2346 return(TNG_CRITICAL);
2349 if(block->block_version >= 3)
2351 if(tng_file_input_numerical(tng_data,
2352 &tng_data->distance_unit_exponential,
2353 sizeof(tng_data->distance_unit_exponential),
2354 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2356 return(TNG_CRITICAL);
2360 if(hash_mode == TNG_USE_HASH)
2362 /* If there is data left in the block that the current version of the library
2363 * cannot interpret still read that to generate the MD5 hash. */
2364 tng_md5_remaining_append(tng_data, block, start_pos, &md5_state);
2366 md5_finish(&md5_state, (md5_byte_t *)hash);
2367 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)
2369 if(strncmp(block->md5_hash, hash, TNG_MD5_HASH_LEN) != 0)
2371 fprintf(stderr, "TNG library: General info block contents corrupt. Hashes do not match. "
2372 "%s: %d\n", __FILE__, __LINE__);
2378 /* Seek to the end of the block */
2379 fseeko(tng_data->input_file, start_pos + block->block_contents_size, SEEK_SET);
2382 return(TNG_SUCCESS);
2386 * @brief Write a general info block. This is the first block of a TNG file.
2387 * @param tng_data is a trajectory data container.
2388 * @param hash_mode is an option to decide whether to use the md5 hash or not.
2389 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
2390 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
2391 * error has occured.
2393 static tng_function_status tng_general_info_block_write
2394 (const tng_trajectory_t tng_data,
2395 const char hash_mode)
2397 int64_t header_file_pos, curr_file_pos;
2399 tng_gen_block_t block;
2400 md5_state_t md5_state;
2402 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
2404 return(TNG_CRITICAL);
2407 fseeko(tng_data->output_file, 0, SEEK_SET);
2409 tng_block_init(&block);
2411 name_len = strlen("GENERAL INFO");
2413 block->name = malloc(name_len + 1);
2416 fprintf(stderr, "TNG library: Cannot allocate memory (%u bytes). %s: %d\n",
2417 (unsigned int)(name_len+1), __FILE__, __LINE__);
2418 tng_block_destroy(&block);
2419 return(TNG_CRITICAL);
2422 strcpy(block->name, "GENERAL INFO");
2423 block->id = TNG_GENERAL_INFO;
2425 if(tng_general_info_block_len_calculate(tng_data, &block->block_contents_size) !=
2428 fprintf(stderr, "TNG library: Cannot calculate length of general info block. %s: %d\n",
2429 __FILE__, __LINE__);
2430 tng_block_destroy(&block);
2431 return(TNG_CRITICAL);
2434 header_file_pos = 0;
2436 if(tng_block_header_write(tng_data, block) != TNG_SUCCESS)
2438 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
2439 tng_data->output_file_path, __FILE__, __LINE__);
2440 tng_block_destroy(&block);
2441 return(TNG_CRITICAL);
2444 if(hash_mode == TNG_USE_HASH)
2446 md5_init(&md5_state);
2449 if(tng_fwritestr(tng_data, tng_data->first_program_name,
2450 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2452 return(TNG_CRITICAL);
2455 if(tng_fwritestr(tng_data, tng_data->last_program_name,
2456 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2458 return(TNG_CRITICAL);
2461 if(tng_fwritestr(tng_data, tng_data->first_user_name,
2462 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2464 return(TNG_CRITICAL);
2467 if(tng_fwritestr(tng_data, tng_data->last_user_name,
2468 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2470 return(TNG_CRITICAL);
2473 if(tng_fwritestr(tng_data, tng_data->first_computer_name,
2474 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2476 return(TNG_CRITICAL);
2479 if(tng_fwritestr(tng_data, tng_data->last_computer_name,
2480 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2482 return(TNG_CRITICAL);
2485 if(tng_fwritestr(tng_data, tng_data->first_pgp_signature,
2486 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2488 return(TNG_CRITICAL);
2491 if(tng_fwritestr(tng_data, tng_data->last_pgp_signature,
2492 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2494 return(TNG_CRITICAL);
2497 if(tng_fwritestr(tng_data, tng_data->forcefield_name,
2498 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2500 return(TNG_CRITICAL);
2504 if(tng_file_output_numerical(tng_data, &tng_data->time, sizeof(tng_data->time),
2505 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2507 return(TNG_CRITICAL);
2510 if(tng_file_output_numerical(tng_data, &tng_data->var_num_atoms_flag,
2511 sizeof(tng_data->var_num_atoms_flag),
2512 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2514 return(TNG_CRITICAL);
2517 if(tng_file_output_numerical(tng_data, &tng_data->frame_set_n_frames,
2518 sizeof(tng_data->frame_set_n_frames),
2519 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2521 return(TNG_CRITICAL);
2524 if(tng_file_output_numerical(tng_data, &tng_data->first_trajectory_frame_set_output_file_pos,
2525 sizeof(tng_data->first_trajectory_frame_set_output_file_pos),
2526 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2528 return(TNG_CRITICAL);
2531 if(tng_file_output_numerical(tng_data, &tng_data->last_trajectory_frame_set_output_file_pos,
2532 sizeof(tng_data->last_trajectory_frame_set_output_file_pos),
2533 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2535 return(TNG_CRITICAL);
2538 if(tng_file_output_numerical(tng_data, &tng_data->medium_stride_length,
2539 sizeof(tng_data->medium_stride_length),
2540 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2542 return(TNG_CRITICAL);
2545 if(tng_file_output_numerical(tng_data, &tng_data->long_stride_length,
2546 sizeof(tng_data->long_stride_length),
2547 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2549 return(TNG_CRITICAL);
2552 if(tng_file_output_numerical(tng_data, &tng_data->distance_unit_exponential,
2553 sizeof(tng_data->distance_unit_exponential),
2554 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2556 return(TNG_CRITICAL);
2558 if(hash_mode == TNG_USE_HASH)
2560 md5_finish(&md5_state, (md5_byte_t *)block->md5_hash);
2561 curr_file_pos = ftello(tng_data->output_file);
2562 fseeko(tng_data->output_file, header_file_pos +
2563 3 * sizeof(int64_t), SEEK_SET);
2564 if(fwrite(block->md5_hash, TNG_MD5_HASH_LEN, 1, tng_data->output_file) != 1)
2566 fprintf(stderr, "TNG library: Could not write MD5 hash. %s: %d\n", __FILE__,
2568 return(TNG_CRITICAL);
2570 fseeko(tng_data->output_file, curr_file_pos, SEEK_SET);
2573 tng_block_destroy(&block);
2575 return(TNG_SUCCESS);
2579 * @brief Read the chain data of a molecules block.
2580 * @param tng_data is a trajectory data container.
2581 * @param chain is the chain data container.
2582 * @param hash_mode is an option to decide whether to generate/update the relevant md5 hashes.
2583 * @param md5_state is a pointer to the current md5 storage, which will be updated appropriately
2584 * if hash_mode == TNG_USE_HASH.
2585 * @return TNG_SUCCESS(0) is successful.
2587 static tng_function_status tng_chain_data_read(const tng_trajectory_t tng_data,
2588 const tng_chain_t chain,
2589 const char hash_mode,
2590 md5_state_t *md5_state)
2592 if(tng_file_input_numerical(tng_data, &chain->id,
2594 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
2596 return(TNG_CRITICAL);
2599 tng_freadstr(tng_data, &chain->name, hash_mode, md5_state, __LINE__);
2601 if(tng_file_input_numerical(tng_data, &chain->n_residues,
2602 sizeof(chain->n_residues),
2603 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
2605 return(TNG_CRITICAL);
2608 return(TNG_SUCCESS);
2612 * @brief Write the chain data of a molecules block.
2613 * @param tng_data is a trajectory data container.
2614 * @param chain is the chain data container.
2615 * @param hash_mode is an option to decide whether to generate/update the relevant md5 hashes.
2616 * @param md5_state is a pointer to the current md5 storage, which will be updated appropriately
2617 * if hash_mode == TNG_USE_HASH.
2618 * @return TNG_SUCCESS(0) is successful.
2620 static tng_function_status tng_chain_data_write(const tng_trajectory_t tng_data,
2621 const tng_chain_t chain,
2622 const char hash_mode,
2623 md5_state_t *md5_state)
2625 if(tng_file_output_numerical(tng_data, &chain->id,
2627 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
2629 return(TNG_CRITICAL);
2632 if(tng_fwritestr(tng_data, chain->name, hash_mode,
2633 md5_state, __LINE__) == TNG_CRITICAL)
2635 return(TNG_CRITICAL);
2638 if(tng_file_output_numerical(tng_data, &chain->n_residues,
2639 sizeof(chain->n_residues),
2640 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
2642 return(TNG_CRITICAL);
2645 return(TNG_SUCCESS);
2649 * @brief Read the residue data of a molecules block.
2650 * @param tng_data is a trajectory data container.
2651 * @param residue is the residue data container.
2652 * @param hash_mode is an option to decide whether to generate/update the relevant md5 hashes.
2653 * @param md5_state is a pointer to the current md5 storage, which will be updated appropriately
2654 * if hash_mode == TNG_USE_HASH.
2655 * @return TNG_SUCCESS(0) is successful.
2657 static tng_function_status tng_residue_data_read(const tng_trajectory_t tng_data,
2658 const tng_residue_t residue,
2659 const char hash_mode,
2660 md5_state_t *md5_state)
2662 if(tng_file_input_numerical(tng_data, &residue->id,
2663 sizeof(residue->id),
2664 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
2666 return(TNG_CRITICAL);
2669 tng_freadstr(tng_data, &residue->name, hash_mode, md5_state, __LINE__);
2671 if(tng_file_input_numerical(tng_data, &residue->n_atoms,
2672 sizeof(residue->n_atoms),
2673 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
2675 return(TNG_CRITICAL);
2678 return(TNG_SUCCESS);
2682 * @brief Write the residue data of a molecules block.
2683 * @param tng_data is a trajectory data container.
2684 * @param residue is the residue data container.
2685 * @param hash_mode is an option to decide whether to generate/update the relevant md5 hashes.
2686 * @param md5_state is a pointer to the current md5 storage, which will be updated appropriately
2687 * if hash_mode == TNG_USE_HASH.
2688 * @return TNG_SUCCESS(0) is successful.
2690 static tng_function_status tng_residue_data_write(const tng_trajectory_t tng_data,
2691 const tng_residue_t residue,
2692 const char hash_mode,
2693 md5_state_t *md5_state)
2695 if(tng_file_output_numerical(tng_data, &residue->id,
2696 sizeof(residue->id),
2697 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
2699 return(TNG_CRITICAL);
2702 if(tng_fwritestr(tng_data, residue->name, hash_mode,
2703 md5_state, __LINE__) == TNG_CRITICAL)
2705 return(TNG_CRITICAL);
2708 if(tng_file_output_numerical(tng_data, &residue->n_atoms,
2709 sizeof(residue->n_atoms),
2710 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
2712 return(TNG_CRITICAL);
2715 return(TNG_SUCCESS);
2719 * @brief Read the atom data of a molecules block.
2720 * @param tng_data is a trajectory data container.
2721 * @param atom is the atom data container.
2722 * @param hash_mode is an option to decide whether to generate/update the relevant md5 hashes.
2723 * @param md5_state is a pointer to the current md5 storage, which will be updated appropriately
2724 * if hash_mode == TNG_USE_HASH.
2725 * @return TNG_SUCCESS(0) is successful.
2727 static tng_function_status tng_atom_data_read(const tng_trajectory_t tng_data,
2728 const tng_atom_t atom,
2729 const char hash_mode,
2730 md5_state_t *md5_state)
2732 if(tng_file_input_numerical(tng_data, &atom->id,
2734 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
2736 return(TNG_CRITICAL);
2739 tng_freadstr(tng_data, &atom->name, hash_mode, md5_state, __LINE__);
2741 tng_freadstr(tng_data, &atom->atom_type, hash_mode, md5_state, __LINE__);
2743 return(TNG_SUCCESS);
2747 * @brief Write the atom data of a molecules block.
2748 * @param tng_data is a trajectory data container.
2749 * @param atom is the atom data container.
2750 * @param hash_mode is an option to decide whether to generate/update the relevant md5 hashes.
2751 * @param md5_state is a pointer to the current md5 storage, which will be updated appropriately
2752 * if hash_mode == TNG_USE_HASH.
2753 * @return TNG_SUCCESS(0) is successful.
2755 static tng_function_status tng_atom_data_write(const tng_trajectory_t tng_data,
2756 const tng_atom_t atom,
2757 const char hash_mode,
2758 md5_state_t *md5_state)
2760 if(tng_file_output_numerical(tng_data, &atom->id,
2762 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
2764 return(TNG_CRITICAL);
2767 if(tng_fwritestr(tng_data, atom->name, hash_mode,
2768 md5_state, __LINE__) == TNG_CRITICAL)
2770 return(TNG_CRITICAL);
2773 if(tng_fwritestr(tng_data, atom->atom_type, hash_mode,
2774 md5_state, __LINE__) == TNG_CRITICAL)
2776 return(TNG_CRITICAL);
2779 return(TNG_SUCCESS);
2782 static tng_function_status tng_molecules_block_len_calculate
2783 (const tng_trajectory_t tng_data,
2787 tng_molecule_t molecule;
2789 tng_residue_t residue;
2795 for(i = 0; i < tng_data->n_molecules; i++)
2797 molecule = &tng_data->molecules[i];
2800 molecule->name = malloc(1);
2803 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2804 __FILE__, __LINE__);
2805 return(TNG_CRITICAL);
2807 molecule->name[0] = 0;
2809 *len += tng_min_size(strlen(molecule->name) + 1, TNG_MAX_STR_LEN);
2811 chain = molecule->chains;
2812 for(j = 0; j < molecule->n_chains; j++)
2814 *len += sizeof(chain->id);
2818 chain->name = malloc(1);
2821 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2822 __FILE__, __LINE__);
2823 return(TNG_CRITICAL);
2827 *len += tng_min_size(strlen(chain->name) + 1, TNG_MAX_STR_LEN);
2829 *len += sizeof(chain->n_residues);
2834 residue = molecule->residues;
2835 for(j = 0; j < molecule->n_residues; j++)
2837 *len += sizeof(residue->id);
2841 residue->name = malloc(1);
2844 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2845 __FILE__, __LINE__);
2846 return(TNG_CRITICAL);
2848 residue->name[0] = 0;
2850 *len += tng_min_size(strlen(residue->name) + 1, TNG_MAX_STR_LEN);
2852 *len += sizeof(residue->n_atoms);
2857 atom = molecule->atoms;
2858 for(j = 0; j < molecule->n_atoms; j++)
2860 *len += sizeof(atom->id);
2863 atom->name = malloc(1);
2866 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2867 __FILE__, __LINE__);
2868 return(TNG_CRITICAL);
2872 *len += tng_min_size(strlen(atom->name) + 1, TNG_MAX_STR_LEN);
2874 if(!atom->atom_type)
2876 atom->atom_type = malloc(1);
2877 if(!atom->atom_type)
2879 fprintf(stderr, "TNG library: Cannot allocate memory (1 byte). %s: %d\n",
2880 __FILE__, __LINE__);
2881 return(TNG_CRITICAL);
2883 atom->atom_type[0] = 0;
2885 *len += tng_min_size(strlen(atom->atom_type) + 1, TNG_MAX_STR_LEN);
2890 for(j = 0; j < molecule->n_bonds; j++)
2892 *len += sizeof(bond->from_atom_id) + sizeof(bond->to_atom_id);
2895 *len += sizeof(tng_data->n_molecules) +
2896 (sizeof(molecule->id) +
2897 sizeof(molecule->quaternary_str) +
2898 sizeof(molecule->n_chains) +
2899 sizeof(molecule->n_residues) +
2900 sizeof(molecule->n_atoms) +
2901 sizeof(molecule->n_bonds)) *
2902 tng_data->n_molecules;
2904 if(!tng_data->var_num_atoms_flag)
2906 *len += tng_data->n_molecules * sizeof(int64_t);
2909 return(TNG_SUCCESS);
2913 * @brief Read a molecules block. Contains chain, residue and atom data
2914 * @param tng_data is a trajectory data container.
2915 * @param block is a general block container.
2916 * @param hash_mode is an option to decide whether to use the md5 hash or not.
2917 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
2918 * compared to the md5 hash of the read contents to ensure valid data.
2919 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
2920 * error has occured.
2922 static tng_function_status tng_molecules_block_read
2923 (const tng_trajectory_t tng_data,
2924 const tng_gen_block_t block,
2925 const char hash_mode)
2927 int64_t start_pos, i, j, k, l;
2928 tng_molecule_t molecule;
2930 tng_residue_t residue;
2933 char hash[TNG_MD5_HASH_LEN];
2934 md5_state_t md5_state;
2936 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
2938 return(TNG_CRITICAL);
2941 start_pos = ftello(tng_data->input_file);
2943 /* FIXME: Does not check if the size of the contents matches the expected
2944 * size or if the contents can be read. */
2946 if(tng_data->molecules)
2948 for(i=0; i<tng_data->n_molecules; i++)
2950 tng_molecule_destroy(tng_data, &tng_data->molecules[i]);
2952 free(tng_data->molecules);
2953 tng_data->molecules = 0;
2954 tng_data->n_molecules = 0;
2957 if(hash_mode == TNG_USE_HASH)
2959 md5_init(&md5_state);
2962 if(tng_file_input_numerical(tng_data, &tng_data->n_molecules,
2963 sizeof(tng_data->n_molecules),
2964 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
2966 return(TNG_CRITICAL);
2969 if(tng_data->molecules)
2971 free(tng_data->molecules);
2974 tng_data->n_particles = 0;
2976 tng_data->molecules = malloc(tng_data->n_molecules *
2977 sizeof(struct tng_molecule));
2978 if(!tng_data->molecules)
2980 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
2981 tng_data->n_molecules * sizeof(struct tng_molecule),
2982 __FILE__, __LINE__);
2983 return(TNG_CRITICAL);
2986 if(!tng_data->var_num_atoms_flag)
2988 if(tng_data->molecule_cnt_list)
2990 free(tng_data->molecule_cnt_list);
2992 tng_data->molecule_cnt_list = malloc(sizeof(int64_t) *
2993 tng_data->n_molecules);
2994 if(!tng_data->molecule_cnt_list)
2996 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
2997 tng_data->n_molecules * sizeof(struct tng_molecule),
2998 __FILE__, __LINE__);
2999 return(TNG_CRITICAL);
3003 /* Read each molecule from file */
3004 for(i=0; i < tng_data->n_molecules; i++)
3006 molecule = &tng_data->molecules[i];
3010 if(tng_file_input_numerical(tng_data, &molecule->id,
3011 sizeof(molecule->id),
3012 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3014 return(TNG_CRITICAL);
3017 /* fprintf(stderr, "TNG library: Read id: %"PRId64" offset: %d\n", molecule->id, offset);*/
3018 tng_freadstr(tng_data, &molecule->name, hash_mode, &md5_state, __LINE__);
3020 if(tng_file_input_numerical(tng_data, &molecule->quaternary_str,
3021 sizeof(molecule->quaternary_str),
3022 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3024 return(TNG_CRITICAL);
3027 if(!tng_data->var_num_atoms_flag)
3029 if(tng_file_input_numerical(tng_data, &tng_data->molecule_cnt_list[i],
3031 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3033 return(TNG_CRITICAL);
3037 if(tng_file_input_numerical(tng_data, &molecule->n_chains,
3038 sizeof(molecule->n_chains),
3039 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3041 return(TNG_CRITICAL);
3044 if(tng_file_input_numerical(tng_data, &molecule->n_residues,
3045 sizeof(molecule->n_residues),
3046 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3048 return(TNG_CRITICAL);
3051 if(tng_file_input_numerical(tng_data, &molecule->n_atoms,
3052 sizeof(molecule->n_atoms),
3053 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3055 return(TNG_CRITICAL);
3058 tng_data->n_particles += molecule->n_atoms *
3059 tng_data->molecule_cnt_list[i];
3061 if(molecule->n_chains > 0)
3063 molecule->chains = malloc(molecule->n_chains *
3064 sizeof(struct tng_chain));
3065 if(!molecule->chains)
3067 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
3068 molecule->n_chains * sizeof(struct tng_chain),
3069 __FILE__, __LINE__);
3070 return(TNG_CRITICAL);
3073 chain = molecule->chains;
3080 if(molecule->n_residues > 0)
3082 molecule->residues = malloc(molecule->n_residues *
3083 sizeof(struct tng_residue));
3084 if(!molecule->residues)
3086 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
3087 molecule->n_residues * sizeof(struct tng_residue),
3088 __FILE__, __LINE__);
3089 if(molecule->chains)
3091 free(molecule->chains);
3092 molecule->chains = 0;
3094 return(TNG_CRITICAL);
3097 residue = molecule->residues;
3104 molecule->atoms = malloc(molecule->n_atoms *
3105 sizeof(struct tng_atom));
3106 if(!molecule->atoms)
3108 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
3109 molecule->n_atoms * sizeof(struct tng_atom),
3110 __FILE__, __LINE__);
3111 if(molecule->chains)
3113 free(molecule->chains);
3114 molecule->chains = 0;
3116 if(molecule->residues)
3118 free(molecule->residues);
3119 molecule->residues = 0;
3121 return(TNG_CRITICAL);
3124 atom = molecule->atoms;
3126 if(molecule->n_chains > 0)
3128 /* Read the chains of the molecule */
3129 for(j=0; j<molecule->n_chains; j++)
3131 chain->molecule = molecule;
3135 tng_chain_data_read(tng_data, chain, hash_mode, &md5_state);
3139 chain->residues = molecule->residues;
3140 residue = chain->residues;
3144 chain->residues = residue;
3147 /* Read the residues of the chain */
3148 for(k=0; k<chain->n_residues; k++)
3150 residue->chain = chain;
3154 tng_residue_data_read(tng_data, residue, hash_mode, &md5_state);
3156 residue->atoms_offset = atom - molecule->atoms;
3157 /* Read the atoms of the residue */
3158 for(l=0; l<residue->n_atoms; l++)
3160 atom->residue = residue;
3163 atom->atom_type = 0;
3165 tng_atom_data_read(tng_data,atom, hash_mode, &md5_state);
3176 if(molecule->n_residues > 0)
3178 for(k=0; k<molecule->n_residues; k++)
3184 tng_residue_data_read(tng_data, residue, hash_mode, &md5_state);
3186 residue->atoms_offset = atom - molecule->atoms;
3187 /* Read the atoms of the residue */
3188 for(l=0; l<residue->n_atoms; l++)
3190 atom->residue = residue;
3192 tng_atom_data_read(tng_data, atom, hash_mode, &md5_state);
3201 for(l=0; l<molecule->n_atoms; l++)
3206 atom->atom_type = 0;
3208 tng_atom_data_read(tng_data, atom, hash_mode, &md5_state);
3215 if(tng_file_input_numerical(tng_data, &molecule->n_bonds,
3216 sizeof(molecule->n_bonds),
3217 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3219 return(TNG_CRITICAL);
3222 if(molecule->n_bonds > 0)
3224 tng_data->molecules[i].bonds = malloc(molecule->n_bonds *
3225 sizeof(struct tng_bond));
3226 if(!molecule->bonds)
3228 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
3229 molecule->n_bonds * sizeof(struct tng_bond),
3230 __FILE__, __LINE__);
3231 if(molecule->chains)
3233 free(molecule->chains);
3234 molecule->chains = 0;
3236 if(molecule->residues)
3238 free(molecule->residues);
3239 molecule->residues = 0;
3243 free(molecule->atoms);
3244 molecule->atoms = 0;
3246 return(TNG_CRITICAL);
3249 bond = molecule->bonds;
3251 for(j=0; j<molecule->n_bonds; j++)
3253 if(tng_file_input_numerical(tng_data, &bond->from_atom_id,
3254 sizeof(bond->from_atom_id),
3255 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3257 return(TNG_CRITICAL);
3260 if(tng_file_input_numerical(tng_data, &bond->to_atom_id,
3261 sizeof(bond->to_atom_id),
3262 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3264 return(TNG_CRITICAL);
3272 molecule->bonds = 0;
3276 if(hash_mode == TNG_USE_HASH)
3278 /* If there is data left in the block that the current version of the library
3279 * cannot interpret still read that to generate the MD5 hash. */
3280 tng_md5_remaining_append(tng_data, block, start_pos, &md5_state);
3282 md5_finish(&md5_state, (md5_byte_t *)hash);
3283 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)
3285 if(strncmp(block->md5_hash, hash, TNG_MD5_HASH_LEN) != 0)
3287 fprintf(stderr, "TNG library: Molecules block contents corrupt. Hashes do not match. "
3288 "%s: %d\n", __FILE__, __LINE__);
3295 /* Seek to the end of the block */
3296 fseeko(tng_data->input_file, start_pos + block->block_contents_size, SEEK_SET);
3299 return(TNG_SUCCESS);
3303 * @brief Write a molecules block.
3304 * @param tng_data is a trajectory data container.
3305 * @param hash_mode is an option to decide whether to use the md5 hash or not.
3306 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
3307 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
3308 * error has occured.
3310 static tng_function_status tng_molecules_block_write
3311 (const tng_trajectory_t tng_data,
3312 const char hash_mode)
3315 int64_t i, j, k, l, header_file_pos, curr_file_pos;
3316 tng_molecule_t molecule;
3318 tng_residue_t residue;
3321 tng_gen_block_t block;
3322 md5_state_t md5_state;
3324 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
3326 return(TNG_CRITICAL);
3329 tng_block_init(&block);
3331 name_len = (unsigned int)strlen("MOLECULES");
3333 block->name = malloc(name_len + 1);
3336 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
3337 name_len+1, __FILE__, __LINE__);
3338 tng_block_destroy(&block);
3339 return(TNG_CRITICAL);
3342 strcpy(block->name, "MOLECULES");
3343 block->id = TNG_MOLECULES;
3345 if(tng_molecules_block_len_calculate(tng_data, &block->block_contents_size) !=
3348 fprintf(stderr, "TNG library: Cannot calculate length of molecules block. %s: %d\n",
3349 __FILE__, __LINE__);
3350 tng_block_destroy(&block);
3351 return(TNG_CRITICAL);
3354 header_file_pos = ftello(tng_data->output_file);
3356 if(tng_block_header_write(tng_data, block) != TNG_SUCCESS)
3358 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
3359 tng_data->output_file_path, __FILE__, __LINE__);
3360 tng_block_destroy(&block);
3361 return(TNG_CRITICAL);
3364 if(hash_mode == TNG_USE_HASH)
3366 md5_init(&md5_state);
3369 if(tng_file_output_numerical(tng_data, &tng_data->n_molecules,
3370 sizeof(tng_data->n_molecules),
3371 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3373 return(TNG_CRITICAL);
3376 for(i = 0; i < tng_data->n_molecules; i++)
3378 molecule = &tng_data->molecules[i];
3380 if(tng_file_output_numerical(tng_data, &molecule->id,
3381 sizeof(molecule->id),
3382 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3384 return(TNG_CRITICAL);
3387 if(tng_fwritestr(tng_data, molecule->name, hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3389 return(TNG_CRITICAL);
3392 if(tng_file_output_numerical(tng_data, &molecule->quaternary_str,
3393 sizeof(molecule->quaternary_str),
3394 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3396 return(TNG_CRITICAL);
3399 if(!tng_data->var_num_atoms_flag)
3401 if(tng_file_output_numerical(tng_data, &tng_data->molecule_cnt_list[i],
3403 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3405 return(TNG_CRITICAL);
3409 if(tng_file_output_numerical(tng_data, &molecule->n_chains,
3410 sizeof(molecule->n_chains),
3411 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3413 return(TNG_CRITICAL);
3416 if(tng_file_output_numerical(tng_data, &molecule->n_residues,
3417 sizeof(molecule->n_residues),
3418 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3420 return(TNG_CRITICAL);
3423 if(tng_file_output_numerical(tng_data, &molecule->n_atoms,
3424 sizeof(molecule->n_atoms),
3425 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3427 return(TNG_CRITICAL);
3430 if(molecule->n_chains > 0)
3432 chain = molecule->chains;
3433 for(j = 0; j < molecule->n_chains; j++)
3435 tng_chain_data_write(tng_data, chain, hash_mode, &md5_state);
3437 residue = chain->residues;
3438 for(k = 0; k < chain->n_residues; k++)
3440 tng_residue_data_write(tng_data, residue, hash_mode, &md5_state);
3442 atom = molecule->atoms + residue->atoms_offset;
3443 for(l = 0; l < residue->n_atoms; l++)
3445 tng_atom_data_write(tng_data, atom, hash_mode, &md5_state);
3456 if(molecule->n_residues > 0)
3458 residue = molecule->residues;
3459 for(k = 0; k < molecule->n_residues; k++)
3461 tng_residue_data_write(tng_data, residue, hash_mode, &md5_state);
3463 atom = molecule->atoms + residue->atoms_offset;
3464 for(l = 0; l < residue->n_atoms; l++)
3466 tng_atom_data_write(tng_data, atom, hash_mode, &md5_state);
3475 atom = molecule->atoms;
3476 for(l = 0; l < molecule->n_atoms; l++)
3478 tng_atom_data_write(tng_data, atom, hash_mode, &md5_state);
3485 if(tng_file_output_numerical(tng_data, &molecule->n_bonds,
3486 sizeof(molecule->n_bonds),
3487 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3489 return(TNG_CRITICAL);
3492 bond = molecule->bonds;
3493 for(j = 0; j < molecule->n_bonds; j++)
3495 if(tng_file_output_numerical(tng_data, &bond->from_atom_id,
3496 sizeof(bond->from_atom_id),
3497 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3499 return(TNG_CRITICAL);
3502 if(tng_file_output_numerical(tng_data, &bond->to_atom_id,
3503 sizeof(bond->to_atom_id),
3504 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3506 return(TNG_CRITICAL);
3512 if(hash_mode == TNG_USE_HASH)
3514 md5_finish(&md5_state, (md5_byte_t *)block->md5_hash);
3515 curr_file_pos = ftello(tng_data->output_file);
3516 fseeko(tng_data->output_file, header_file_pos +
3517 3 * sizeof(int64_t), SEEK_SET);
3518 if(fwrite(block->md5_hash, TNG_MD5_HASH_LEN, 1, tng_data->output_file) != 1)
3520 fprintf(stderr, "TNG library: Could not write MD5 hash. %s: %d\n", __FILE__,
3522 return(TNG_CRITICAL);
3524 fseeko(tng_data->output_file, curr_file_pos, SEEK_SET);
3527 tng_block_destroy(&block);
3529 return(TNG_SUCCESS);
3532 static tng_function_status tng_frame_set_block_len_calculate
3533 (const tng_trajectory_t tng_data,
3536 *len = sizeof(int64_t) * 8;
3537 *len += sizeof(double) * 2;
3539 if(tng_data->var_num_atoms_flag)
3541 *len += sizeof(int64_t) * tng_data->n_molecules;
3543 return(TNG_SUCCESS);
3547 * @brief Read a frame set block. Update tng_data->current_trajectory_frame_set
3548 * @param tng_data is a trajectory data container.
3549 * @param block is a general block container.
3550 * @param hash_mode is an option to decide whether to use the md5 hash or not.
3551 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
3552 * compared to the md5 hash of the read contents to ensure valid data.
3553 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
3554 * error has occured.
3556 static tng_function_status tng_frame_set_block_read
3557 (tng_trajectory_t tng_data,
3558 tng_gen_block_t block,
3559 const char hash_mode)
3561 int64_t file_pos, start_pos, i, prev_n_particles;
3562 tng_trajectory_frame_set_t frame_set =
3563 &tng_data->current_trajectory_frame_set;
3564 char hash[TNG_MD5_HASH_LEN];
3565 md5_state_t md5_state;
3567 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
3569 return(TNG_CRITICAL);
3572 start_pos = ftello(tng_data->input_file);
3574 /* FIXME: Does not check if the size of the contents matches the expected
3575 * size or if the contents can be read. */
3577 file_pos = start_pos - block->header_contents_size;
3579 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
3581 tng_frame_set_particle_mapping_free(tng_data);
3583 if(hash_mode == TNG_USE_HASH)
3585 md5_init(&md5_state);
3587 if(tng_file_input_numerical(tng_data, &frame_set->first_frame,
3588 sizeof(frame_set->first_frame),
3589 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3591 return(TNG_CRITICAL);
3594 if(tng_file_input_numerical(tng_data, &frame_set->n_frames,
3595 sizeof(frame_set->n_frames),
3596 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3598 return(TNG_CRITICAL);
3601 if(tng_data->var_num_atoms_flag)
3603 prev_n_particles = frame_set->n_particles;
3604 frame_set->n_particles = 0;
3605 /* If the list of molecule counts has already been created assume that
3606 * it is of correct size. */
3607 if(!frame_set->molecule_cnt_list)
3609 frame_set->molecule_cnt_list =
3610 malloc(sizeof(int64_t) * tng_data->n_molecules);
3612 if(!frame_set->molecule_cnt_list)
3614 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
3615 sizeof(int64_t) * tng_data->n_molecules,
3616 __FILE__, __LINE__);
3617 return(TNG_CRITICAL);
3620 for(i = 0; i < tng_data->n_molecules; i++)
3622 if(tng_file_input_numerical(tng_data, &frame_set->molecule_cnt_list[i],
3624 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3626 return(TNG_CRITICAL);
3629 frame_set->n_particles += tng_data->molecules[i].n_atoms *
3630 frame_set->molecule_cnt_list[i];
3632 if(prev_n_particles && frame_set->n_particles != prev_n_particles)
3634 /* FIXME: Particle dependent data memory management */
3638 if(tng_file_input_numerical(tng_data, &frame_set->next_frame_set_file_pos,
3639 sizeof(frame_set->next_frame_set_file_pos),
3640 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3642 return(TNG_CRITICAL);
3645 if(tng_file_input_numerical(tng_data, &frame_set->prev_frame_set_file_pos,
3646 sizeof(frame_set->prev_frame_set_file_pos),
3647 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3649 return(TNG_CRITICAL);
3652 if(tng_file_input_numerical(tng_data, &frame_set->medium_stride_next_frame_set_file_pos,
3653 sizeof(frame_set->medium_stride_next_frame_set_file_pos),
3654 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3656 return(TNG_CRITICAL);
3659 if(tng_file_input_numerical(tng_data, &frame_set->medium_stride_prev_frame_set_file_pos,
3660 sizeof(frame_set->medium_stride_prev_frame_set_file_pos),
3661 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3663 return(TNG_CRITICAL);
3666 if(tng_file_input_numerical(tng_data, &frame_set->long_stride_next_frame_set_file_pos,
3667 sizeof(frame_set->long_stride_next_frame_set_file_pos),
3668 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3670 return(TNG_CRITICAL);
3673 if(tng_file_input_numerical(tng_data, &frame_set->long_stride_prev_frame_set_file_pos,
3674 sizeof(frame_set->long_stride_prev_frame_set_file_pos),
3675 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3677 return(TNG_CRITICAL);
3680 if(block->block_version >= 3)
3682 if(tng_file_input_numerical(tng_data, &frame_set->first_frame_time,
3683 sizeof(frame_set->first_frame_time),
3684 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3686 return(TNG_CRITICAL);
3689 if(tng_file_input_numerical(tng_data, &tng_data->time_per_frame,
3690 sizeof(tng_data->time_per_frame),
3691 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3693 return(TNG_CRITICAL);
3698 frame_set->first_frame_time = -1;
3699 tng_data->time_per_frame = -1;
3702 if(hash_mode == TNG_USE_HASH)
3704 /* If there is data left in the block that the current version of the library
3705 * cannot interpret still read that to generate the MD5 hash. */
3706 tng_md5_remaining_append(tng_data, block, start_pos, &md5_state);
3708 md5_finish(&md5_state, (md5_byte_t *)hash);
3709 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)
3711 if(strncmp(block->md5_hash, hash, TNG_MD5_HASH_LEN) != 0)
3713 fprintf(stderr, "TNG library: Frame set block contents corrupt (first frame %"PRId64"). Hashes do not match. "
3714 "%s: %d\n", frame_set->first_frame, __FILE__, __LINE__);
3720 /* Seek to the end of the block */
3721 fseeko(tng_data->input_file, start_pos + block->block_contents_size, SEEK_SET);
3724 /* If the output file and the input files are the same the number of
3725 * frames in the file are the same number as has just been read.
3726 * This is updated here to later on see if there have been new frames
3727 * added and thereby the frame set needs to be rewritten. */
3728 if(tng_data->output_file == tng_data->input_file)
3730 frame_set->n_written_frames = frame_set->n_frames;
3733 return(TNG_SUCCESS);
3737 * @brief Write tng_data->current_trajectory_frame_set to file
3738 * @param tng_data is a trajectory data container.
3739 * @param block is a general block container.
3740 * @param hash_mode is an option to decide whether to use the md5 hash or not.
3741 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
3742 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
3743 * error has occured.
3745 static tng_function_status tng_frame_set_block_write
3746 (const tng_trajectory_t tng_data,
3747 const tng_gen_block_t block,
3748 const char hash_mode)
3751 int64_t i, header_file_pos, curr_file_pos;
3752 unsigned int name_len;
3753 tng_trajectory_frame_set_t frame_set =
3754 &tng_data->current_trajectory_frame_set;
3755 md5_state_t md5_state;
3757 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
3759 return(TNG_CRITICAL);
3762 name_len = (unsigned int)strlen("TRAJECTORY FRAME SET");
3764 if(!block->name || strlen(block->name) < name_len)
3766 temp_name = realloc(block->name, name_len + 1);
3769 fprintf(stderr, "TNG library: Cannot allocate memory (%u bytes). %s: %d\n",
3770 name_len+1, __FILE__, __LINE__);
3773 return(TNG_CRITICAL);
3775 block->name = temp_name;
3777 strcpy(block->name, "TRAJECTORY FRAME SET");
3778 block->id = TNG_TRAJECTORY_FRAME_SET;
3780 if(tng_frame_set_block_len_calculate(tng_data, &block->block_contents_size) !=
3783 fprintf(stderr, "TNG library: Cannot calculate length of frame set block. %s: %d\n",
3784 __FILE__, __LINE__);
3785 return(TNG_CRITICAL);
3788 header_file_pos = ftello(tng_data->output_file);
3790 if(tng_block_header_write(tng_data, block) != TNG_SUCCESS)
3792 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
3793 tng_data->output_file_path, __FILE__, __LINE__);
3794 return(TNG_CRITICAL);
3797 if(hash_mode == TNG_USE_HASH)
3799 md5_init(&md5_state);
3801 if(tng_file_output_numerical(tng_data, &frame_set->first_frame,
3802 sizeof(frame_set->first_frame),
3803 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3805 return(TNG_CRITICAL);
3808 if(tng_file_output_numerical(tng_data, &frame_set->n_frames,
3809 sizeof(frame_set->n_frames),
3810 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3812 return(TNG_CRITICAL);
3815 if(tng_data->var_num_atoms_flag)
3817 for(i = 0; i < tng_data->n_molecules; i++)
3819 if(tng_file_output_numerical(tng_data, &frame_set->molecule_cnt_list[i],
3821 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3823 return(TNG_CRITICAL);
3828 if(tng_file_output_numerical(tng_data, &frame_set->next_frame_set_file_pos,
3829 sizeof(frame_set->next_frame_set_file_pos),
3830 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3832 return(TNG_CRITICAL);
3835 if(tng_file_output_numerical(tng_data, &frame_set->prev_frame_set_file_pos,
3836 sizeof(frame_set->prev_frame_set_file_pos),
3837 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3839 return(TNG_CRITICAL);
3842 if(tng_file_output_numerical(tng_data, &frame_set->medium_stride_next_frame_set_file_pos,
3843 sizeof(frame_set->medium_stride_next_frame_set_file_pos),
3844 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3846 return(TNG_CRITICAL);
3849 if(tng_file_output_numerical(tng_data, &frame_set->medium_stride_prev_frame_set_file_pos,
3850 sizeof(frame_set->medium_stride_prev_frame_set_file_pos),
3851 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3853 return(TNG_CRITICAL);
3856 if(tng_file_output_numerical(tng_data, &frame_set->long_stride_next_frame_set_file_pos,
3857 sizeof(frame_set->long_stride_next_frame_set_file_pos),
3858 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3860 return(TNG_CRITICAL);
3863 if(tng_file_output_numerical(tng_data, &frame_set->long_stride_prev_frame_set_file_pos,
3864 sizeof(frame_set->long_stride_prev_frame_set_file_pos),
3865 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3867 return(TNG_CRITICAL);
3870 if(tng_file_output_numerical(tng_data, &frame_set->first_frame_time,
3871 sizeof(frame_set->first_frame_time),
3872 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3874 return(TNG_CRITICAL);
3877 if(tng_file_output_numerical(tng_data, &tng_data->time_per_frame,
3878 sizeof(tng_data->time_per_frame),
3879 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3881 return(TNG_CRITICAL);
3883 if(hash_mode == TNG_USE_HASH)
3885 md5_finish(&md5_state, (md5_byte_t *)block->md5_hash);
3886 curr_file_pos = ftello(tng_data->output_file);
3887 fseeko(tng_data->output_file, header_file_pos +
3888 3 * sizeof(int64_t), SEEK_SET);
3889 if(fwrite(block->md5_hash, TNG_MD5_HASH_LEN, 1, tng_data->output_file) != 1)
3891 fprintf(stderr, "TNG library: Could not write MD5 hash. %s: %d\n", __FILE__,
3893 return(TNG_CRITICAL);
3895 fseeko(tng_data->output_file, curr_file_pos, SEEK_SET);
3898 return(TNG_SUCCESS);
3901 static tng_function_status tng_trajectory_mapping_block_len_calculate
3902 (const tng_trajectory_t tng_data,
3903 const int64_t n_particles,
3907 *len = sizeof(int64_t) * (2 + n_particles);
3909 return(TNG_SUCCESS);
3913 * @brief Read an atom mappings block (translating between real atom indexes and how
3914 * the atom info is written in this frame set).
3915 * @param tng_data is a trajectory data container.
3916 * @param block is a general block container.
3917 * @param hash_mode is an option to decide whether to use the md5 hash or not.
3918 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
3919 * compared to the md5 hash of the read contents to ensure valid data.
3920 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
3921 * error has occured.
3923 static tng_function_status tng_trajectory_mapping_block_read
3924 (const tng_trajectory_t tng_data,
3925 const tng_gen_block_t block,
3926 const char hash_mode)
3928 int64_t start_pos, i;
3929 tng_trajectory_frame_set_t frame_set =
3930 &tng_data->current_trajectory_frame_set;
3931 tng_particle_mapping_t mapping, mappings;
3932 char hash[TNG_MD5_HASH_LEN];
3933 md5_state_t md5_state;
3935 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
3937 return(TNG_CRITICAL);
3940 start_pos = ftello(tng_data->input_file);
3942 /* FIXME: Does not check if the size of the contents matches the expected
3943 * size or if the contents can be read. */
3945 frame_set->n_mapping_blocks++;
3946 mappings = realloc(frame_set->mappings,
3947 sizeof(struct tng_particle_mapping) *
3948 frame_set->n_mapping_blocks);
3951 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
3952 block->block_contents_size, __FILE__, __LINE__);
3953 free(frame_set->mappings);
3954 frame_set->mappings = 0;
3955 return(TNG_CRITICAL);
3957 frame_set->mappings = mappings;
3958 mapping = &mappings[frame_set->n_mapping_blocks - 1];
3961 if(hash_mode == TNG_USE_HASH)
3963 md5_init(&md5_state);
3966 if(tng_file_input_numerical(tng_data, &mapping->num_first_particle,
3967 sizeof(mapping->num_first_particle),
3968 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3970 return(TNG_CRITICAL);
3973 if(tng_file_input_numerical(tng_data, &mapping->n_particles,
3974 sizeof(mapping->n_particles),
3975 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3977 return(TNG_CRITICAL);
3980 mapping->real_particle_numbers = malloc(mapping->n_particles *
3982 if(!mapping->real_particle_numbers)
3984 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
3985 mapping->n_particles * sizeof(int64_t), __FILE__, __LINE__);
3986 return(TNG_CRITICAL);
3989 /* If the byte order needs to be swapped the data must be read one value at
3990 * a time and swapped */
3991 if(tng_data->input_endianness_swap_func_64)
3993 for(i = 0; i < mapping->n_particles; i++)
3995 if(tng_file_input_numerical(tng_data, &mapping->real_particle_numbers[i],
3997 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
3999 return(TNG_CRITICAL);
4003 /* Otherwise the data can be read all at once */
4006 if(fread(mapping->real_particle_numbers, mapping->n_particles * sizeof(int64_t),
4007 1, tng_data->input_file) == 0)
4009 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
4010 return(TNG_CRITICAL);
4012 if(hash_mode == TNG_USE_HASH)
4014 md5_append(&md5_state, (md5_byte_t *)mapping->real_particle_numbers, mapping->n_particles * sizeof(int64_t));
4018 if(hash_mode == TNG_USE_HASH)
4020 /* If there is data left in the block that the current version of the library
4021 * cannot interpret still read that to generate the MD5 hash. */
4022 tng_md5_remaining_append(tng_data, block, start_pos, &md5_state);
4024 md5_finish(&md5_state, (md5_byte_t *)hash);
4025 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)
4027 if(strncmp(block->md5_hash, hash, TNG_MD5_HASH_LEN) != 0)
4029 fprintf(stderr, "TNG library: Particle mapping block contents corrupt. Hashes do not match. "
4030 "%s: %d\n", __FILE__, __LINE__);
4036 /* Seek to the end of the block */
4037 fseeko(tng_data->input_file, start_pos + block->block_contents_size, SEEK_SET);
4040 return(TNG_SUCCESS);
4044 * @brief Write the atom mappings of the current trajectory frame set
4045 * @param tng_data is a trajectory data container.
4046 * @param block is a general block container.
4047 * @param mapping_block_nr is the index of the mapping block to write.
4048 * @param hash_mode is an option to decide whether to use the md5 hash or not.
4049 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
4050 * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if a minor error
4051 * has occurred or TNG_CRITICAL (2) if a major error has occured.
4053 static tng_function_status tng_trajectory_mapping_block_write
4054 (const tng_trajectory_t tng_data,
4055 const tng_gen_block_t block,
4056 const int mapping_block_nr,
4057 const char hash_mode)
4059 int64_t header_file_pos, curr_file_pos;
4062 unsigned int name_len;
4063 md5_state_t md5_state;
4064 tng_particle_mapping_t mapping =
4065 &tng_data->current_trajectory_frame_set.mappings[mapping_block_nr];
4067 if(mapping_block_nr >=
4068 tng_data->current_trajectory_frame_set.n_mapping_blocks)
4070 fprintf(stderr, "TNG library: Mapping block index out of bounds. %s: %d\n",
4071 __FILE__, __LINE__);
4072 return(TNG_FAILURE);
4075 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
4077 return(TNG_CRITICAL);
4080 name_len = (unsigned int)strlen("PARTICLE MAPPING");
4082 if(!block->name || strlen(block->name) < name_len)
4084 temp_name = realloc(block->name, name_len + 1);
4087 fprintf(stderr, "TNG library: Cannot allocate memory (%u bytes). %s: %d\n",
4088 name_len+1, __FILE__, __LINE__);
4091 return(TNG_CRITICAL);
4093 block->name = temp_name;
4095 strcpy(block->name, "PARTICLE MAPPING");
4096 block->id = TNG_PARTICLE_MAPPING;
4098 if(tng_trajectory_mapping_block_len_calculate(tng_data,
4099 mapping->n_particles,
4100 &block->block_contents_size) !=
4103 fprintf(stderr, "TNG library: Cannot calculate length of atom mapping block. %s: %d\n",
4104 __FILE__, __LINE__);
4105 return(TNG_CRITICAL);
4108 header_file_pos = ftello(tng_data->output_file);
4110 if(tng_block_header_write(tng_data, block) != TNG_SUCCESS)
4112 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
4113 tng_data->output_file_path, __FILE__, __LINE__);
4114 return(TNG_CRITICAL);
4117 if(hash_mode == TNG_USE_HASH)
4119 md5_init(&md5_state);
4121 if(tng_file_output_numerical(tng_data, &mapping->num_first_particle,
4122 sizeof(mapping->num_first_particle),
4123 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
4125 return(TNG_CRITICAL);
4128 if(tng_file_output_numerical(tng_data, &mapping->n_particles,
4129 sizeof(mapping->n_particles),
4130 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
4132 return(TNG_CRITICAL);
4135 if(tng_data->output_endianness_swap_func_64)
4137 for(i = 0; i < mapping->n_particles; i++)
4139 if(tng_file_output_numerical(tng_data, &mapping->real_particle_numbers[i],
4141 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
4143 return(TNG_CRITICAL);
4149 if(fwrite(mapping->real_particle_numbers,
4150 mapping->n_particles * sizeof(int64_t),
4151 1, tng_data->output_file) != 1)
4153 fprintf(stderr, "TNG library: Could not write block data. %s: %d\n", __FILE__, __LINE__);
4154 return(TNG_CRITICAL);
4156 if(hash_mode == TNG_USE_HASH)
4158 md5_append(&md5_state, (md5_byte_t *)mapping->real_particle_numbers,
4159 mapping->n_particles * sizeof(int64_t));
4163 if(hash_mode == TNG_USE_HASH)
4165 md5_finish(&md5_state, (md5_byte_t *)block->md5_hash);
4166 curr_file_pos = ftello(tng_data->output_file);
4167 fseeko(tng_data->output_file, header_file_pos +
4168 3 * sizeof(int64_t), SEEK_SET);
4169 if(fwrite(block->md5_hash, TNG_MD5_HASH_LEN, 1, tng_data->output_file) != 1)
4171 fprintf(stderr, "TNG library: Could not write MD5 hash. %s: %d\n", __FILE__,
4173 return(TNG_CRITICAL);
4175 fseeko(tng_data->output_file, curr_file_pos, SEEK_SET);
4178 return(TNG_SUCCESS);
4182 * @brief Prepare a block for storing particle data
4183 * @param tng_data is a trajectory data container.
4184 * @param block_type_flag specifies if this is a trajectory block or a
4185 * non-trajectory block. (TNG_TRAJECTORY_BLOCK or TNG_NON_TRAJECTORY_BLOCK)
4186 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
4187 * error has occured.
4189 static tng_function_status tng_particle_data_block_create
4190 (const tng_trajectory_t tng_data,
4191 const char block_type_flag)
4193 tng_trajectory_frame_set_t frame_set =
4194 &tng_data->current_trajectory_frame_set;
4198 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
4200 frame_set->n_particle_data_blocks++;
4201 data = realloc(frame_set->tr_particle_data,
4202 sizeof(struct tng_data) *
4203 frame_set->n_particle_data_blocks);
4206 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
4207 sizeof(struct tng_data) *
4208 frame_set->n_particle_data_blocks,
4209 __FILE__, __LINE__);
4210 free(frame_set->tr_particle_data);
4211 frame_set->tr_particle_data = 0;
4212 return(TNG_CRITICAL);
4214 frame_set->tr_particle_data = data;
4218 tng_data->n_particle_data_blocks++;
4219 data = realloc(tng_data->non_tr_particle_data,
4220 sizeof(struct tng_data) *
4221 tng_data->n_particle_data_blocks);
4224 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
4225 sizeof(struct tng_data) *
4226 tng_data->n_particle_data_blocks,
4227 __FILE__, __LINE__);
4228 free(tng_data->non_tr_particle_data);
4229 tng_data->non_tr_particle_data = 0;
4230 return(TNG_CRITICAL);
4232 tng_data->non_tr_particle_data = data;
4235 return(TNG_SUCCESS);
4238 static tng_function_status tng_compress(const tng_trajectory_t tng_data,
4239 const tng_gen_block_t block,
4240 const int64_t n_frames,
4241 const int64_t n_particles,
4250 int64_t algo_find_n_frames = -1;
4254 if(block->id != TNG_TRAJ_POSITIONS &&
4255 block->id != TNG_TRAJ_VELOCITIES)
4257 fprintf(stderr, "TNG library: Can only compress positions and velocities with the "
4258 "TNG method. %s: %d\n", __FILE__, __LINE__);
4259 return(TNG_FAILURE);
4261 if(type != TNG_FLOAT_DATA && type != TNG_DOUBLE_DATA)
4263 fprintf(stderr, "TNG library: Data type not supported. %s: %d\n", __FILE__, __LINE__);
4264 return(TNG_FAILURE);
4267 if(n_frames <= 0 || n_particles <= 0)
4269 fprintf(stderr, "TNG library: Missing frames or particles. Cannot compress data "
4270 "with the TNG method. %s: %d\n", __FILE__, __LINE__);
4271 return(TNG_FAILURE);
4274 f_precision = 1/(float)tng_data->compression_precision;
4275 d_precision = 1/tng_data->compression_precision;
4277 if(block->id == TNG_TRAJ_POSITIONS)
4279 /* If there is only one frame in this frame set and there might be more
4280 * do not store the algorithm as the compression algorithm, but find
4281 * the best one without storing it */
4282 if(n_frames == 1 && tng_data->frame_set_n_frames > 1)
4284 nalgo = tng_compress_nalgo();
4285 alt_algo = malloc(nalgo * sizeof *tng_data->compress_algo_pos);
4287 /* If we have already determined the initial coding and
4288 * initial coding parameter do not determine them again. */
4289 if(tng_data->compress_algo_pos)
4291 alt_algo[0] = tng_data->compress_algo_pos[0];
4292 alt_algo[1] = tng_data->compress_algo_pos[1];
4293 alt_algo[2] = tng_data->compress_algo_pos[2];
4294 alt_algo[3] = tng_data->compress_algo_pos[3];
4304 /* If the initial coding and initial coding parameter are -1
4305 * they will be determined in tng_compress_pos/_float/. */
4306 if(type == TNG_FLOAT_DATA)
4308 dest = tng_compress_pos_float((float *)*data, (int)n_particles,
4317 dest = tng_compress_pos((double *)*data, (int)n_particles,
4323 /* If there had been no algorithm determined before keep the initial coding
4324 * and initial coding parameter so that they won't have to be determined again. */
4325 if(!tng_data->compress_algo_pos)
4327 nalgo = tng_compress_nalgo();
4328 tng_data->compress_algo_pos=malloc(nalgo *
4329 sizeof *tng_data->compress_algo_pos);
4330 tng_data->compress_algo_pos[0] = alt_algo[0];
4331 tng_data->compress_algo_pos[1] = alt_algo[1];
4332 tng_data->compress_algo_pos[2] = -1;
4333 tng_data->compress_algo_pos[3] = -1;
4336 else if(!tng_data->compress_algo_pos || tng_data->compress_algo_pos[2] == -1 ||
4337 tng_data->compress_algo_pos[2] == -1)
4341 algo_find_n_frames = 5;
4345 algo_find_n_frames = n_frames;
4348 /* If the algorithm parameters are -1 they will be determined during the
4350 if(!tng_data->compress_algo_pos)
4352 nalgo = tng_compress_nalgo();
4353 tng_data->compress_algo_pos=malloc(nalgo *
4354 sizeof *tng_data->compress_algo_pos);
4355 tng_data->compress_algo_pos[0] = -1;
4356 tng_data->compress_algo_pos[1] = -1;
4357 tng_data->compress_algo_pos[2] = -1;
4358 tng_data->compress_algo_pos[3] = -1;
4360 if(type == TNG_FLOAT_DATA)
4362 dest = tng_compress_pos_float((float *)*data, (int)n_particles,
4363 (int)algo_find_n_frames,
4369 if(algo_find_n_frames < n_frames)
4372 dest = tng_compress_pos_float((float *)*data, (int)n_particles,
4375 0, tng_data->compress_algo_pos,
4381 dest = tng_compress_pos((double *)*data, (int)n_particles,
4382 (int)algo_find_n_frames,
4388 if(algo_find_n_frames < n_frames)
4391 dest = tng_compress_pos((double *)*data, (int)n_particles,
4394 tng_data->compress_algo_pos,
4401 if(type == TNG_FLOAT_DATA)
4403 dest = tng_compress_pos_float((float *)*data, (int)n_particles,
4406 tng_data->compress_algo_pos, &compressed_len);
4410 dest = tng_compress_pos((double *)*data, (int)n_particles,
4413 tng_data->compress_algo_pos,
4418 else if(block->id == TNG_TRAJ_VELOCITIES)
4420 /* If there is only one frame in this frame set and there might be more
4421 * do not store the algorithm as the compression algorithm, but find
4422 * the best one without storing it */
4423 if(n_frames == 1 && tng_data->frame_set_n_frames > 1)
4425 nalgo = tng_compress_nalgo();
4426 alt_algo=malloc(nalgo * sizeof *tng_data->compress_algo_vel);
4428 /* If we have already determined the initial coding and
4429 * initial coding parameter do not determine them again. */
4430 if(tng_data->compress_algo_vel)
4432 alt_algo[0] = tng_data->compress_algo_vel[0];
4433 alt_algo[1] = tng_data->compress_algo_vel[1];
4434 alt_algo[2] = tng_data->compress_algo_vel[2];
4435 alt_algo[3] = tng_data->compress_algo_vel[3];
4445 /* If the initial coding and initial coding parameter are -1
4446 * they will be determined in tng_compress_pos/_float/. */
4447 if(type == TNG_FLOAT_DATA)
4449 dest = tng_compress_vel_float((float *)*data, (int)n_particles,
4458 dest = tng_compress_vel((double *)*data, (int)n_particles,
4464 /* If there had been no algorithm determined before keep the initial coding
4465 * and initial coding parameter so that they won't have to be determined again. */
4466 if(!tng_data->compress_algo_vel)
4468 nalgo = tng_compress_nalgo();
4469 tng_data->compress_algo_vel=malloc(nalgo *
4470 sizeof *tng_data->compress_algo_vel);
4471 tng_data->compress_algo_vel[0] = alt_algo[0];
4472 tng_data->compress_algo_vel[1] = alt_algo[1];
4473 tng_data->compress_algo_vel[2] = -1;
4474 tng_data->compress_algo_vel[3] = -1;
4477 else if(!tng_data->compress_algo_vel || tng_data->compress_algo_vel[2] == -1 ||
4478 tng_data->compress_algo_vel[2] == -1)
4482 algo_find_n_frames = 5;
4486 algo_find_n_frames = n_frames;
4489 /* If the algorithm parameters are -1 they will be determined during the
4491 if(!tng_data->compress_algo_vel)
4493 nalgo = tng_compress_nalgo();
4494 tng_data->compress_algo_vel=malloc(nalgo *
4495 sizeof *tng_data->compress_algo_vel);
4496 tng_data->compress_algo_vel[0] = -1;
4497 tng_data->compress_algo_vel[1] = -1;
4498 tng_data->compress_algo_vel[2] = -1;
4499 tng_data->compress_algo_vel[3] = -1;
4501 if(type == TNG_FLOAT_DATA)
4503 dest = tng_compress_vel_float((float *)*data, (int)n_particles,
4504 (int)algo_find_n_frames,
4509 if(algo_find_n_frames < n_frames)
4512 dest = tng_compress_vel_float((float *)*data, (int)n_particles,
4515 0, tng_data->compress_algo_vel,
4521 dest = tng_compress_vel((double *)*data, (int)n_particles,
4522 (int)algo_find_n_frames,
4527 if(algo_find_n_frames < n_frames)
4530 dest = tng_compress_vel((double *)*data, (int)n_particles,
4533 0, tng_data->compress_algo_vel,
4540 if(type == TNG_FLOAT_DATA)
4542 dest = tng_compress_vel_float((float *)*data, (int)n_particles,
4551 dest = tng_compress_vel((double *)*data, (int)n_particles,
4562 fprintf(stderr, "TNG library: Can only compress positions and velocities using TNG-MF1 algorithms.\n");
4563 return(TNG_FAILURE);
4573 *data = (char *)dest;
4575 *new_len = compressed_len;
4577 return(TNG_SUCCESS);
4580 static tng_function_status tng_uncompress(const tng_trajectory_t tng_data,
4581 const tng_gen_block_t block,
4584 const int64_t uncompressed_len)
4591 TNG_ASSERT(uncompressed_len, "TNG library: The full length of the uncompressed data must be > 0.");
4593 if(block->id != TNG_TRAJ_POSITIONS &&
4594 block->id != TNG_TRAJ_VELOCITIES)
4596 fprintf(stderr, "TNG library: Can only uncompress positions and velocities with the"
4598 return(TNG_FAILURE);
4600 if(type != TNG_FLOAT_DATA && type != TNG_DOUBLE_DATA)
4602 fprintf(stderr, "TNG library: Data type not supported.\n");
4603 return(TNG_FAILURE);
4606 if(type == TNG_FLOAT_DATA)
4608 f_dest = malloc(uncompressed_len);
4611 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4612 uncompressed_len, __FILE__, __LINE__);
4613 return(TNG_CRITICAL);
4615 result = tng_compress_uncompress_float(*data, f_dest);
4619 *data = (char *)f_dest;
4623 d_dest = malloc(uncompressed_len);
4626 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4627 uncompressed_len, __FILE__, __LINE__);
4628 return(TNG_CRITICAL);
4630 result = tng_compress_uncompress(*data, d_dest);
4634 *data = (char *)d_dest;
4639 fprintf(stderr, "TNG library: Cannot uncompress TNG compressed block.\n");
4640 return(TNG_FAILURE);
4643 return(TNG_SUCCESS);
4647 static tng_function_status tng_gzip_compress(const tng_trajectory_t tng_data,
4648 char **data, const int64_t len,
4652 uLongf stat, max_len;
4655 max_len = compressBound(len);
4656 dest = malloc(max_len);
4659 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
4660 max_len, __FILE__, __LINE__);
4661 return(TNG_CRITICAL);
4664 stat = compress(dest, &max_len, (Bytef *)*data, len);
4665 if(stat != (unsigned long)Z_OK)
4668 if(stat == (unsigned long)Z_MEM_ERROR)
4670 fprintf(stderr, "TNG library: Not enough memory. ");
4672 else if(stat == (unsigned long)Z_BUF_ERROR)
4674 fprintf(stderr, "TNG library: Destination buffer too small. ");
4676 fprintf(stderr, "TNG library: Error gzipping data. %s: %d\n", __FILE__, __LINE__);
4677 return(TNG_FAILURE);
4684 *data = (char *)dest;
4686 return(TNG_SUCCESS);
4689 static tng_function_status tng_gzip_uncompress(const tng_trajectory_t tng_data,
4691 const int64_t compressed_len,
4692 const int64_t uncompressed_len)
4697 uLongf new_len = uncompressed_len;
4699 dest = malloc(uncompressed_len);
4702 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4703 uncompressed_len, __FILE__, __LINE__);
4704 return(TNG_CRITICAL);
4707 stat = uncompress(dest, &new_len, (Bytef *) *data,
4713 if(stat == (unsigned long)Z_MEM_ERROR)
4715 fprintf(stderr, "TNG library: Not enough memory. ");
4717 else if(stat == (unsigned long)Z_BUF_ERROR)
4719 fprintf(stderr, "TNG library: Destination buffer too small. ");
4721 else if(stat == (unsigned long)Z_DATA_ERROR)
4723 fprintf(stderr, "TNG library: Data corrupt. ");
4725 fprintf(stderr, "TNG library: Error uncompressing gzipped data. %s: %d\n", __FILE__,
4727 return(TNG_FAILURE);
4732 *data = (char *)dest;
4734 return(TNG_SUCCESS);
4739 * @brief Allocate memory for storing particle data.
4740 * The allocated block will be refered to by data->values.
4741 * @param tng_data is a trajectory data container.
4742 * @param data is the data struct, which will contain the allocated memory in
4744 * @param n_frames is the number of frames of data to store.
4745 * @param n_particles is the number of particles with data.
4746 * @param n_values_per_frame is the number of data values per particle and
4748 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
4749 * error has occured.
4751 static tng_function_status tng_allocate_particle_data_mem
4752 (const tng_trajectory_t tng_data,
4753 const tng_data_t data,
4755 const int64_t stride_length,
4756 const int64_t n_particles,
4757 const int64_t n_values_per_frame)
4760 int64_t i, j, k, size, frame_alloc;
4763 if(n_particles == 0 || n_values_per_frame == 0)
4765 return(TNG_FAILURE);
4768 if(data->strings && data->datatype == TNG_CHAR_DATA)
4770 for(i = 0; i < data->n_frames; i++)
4772 for(j = 0; j < n_particles; j++)
4774 for(k = 0; k < data->n_values_per_frame; k++)
4776 if(data->strings[i][j][k])
4778 free(data->strings[i][j][k]);
4781 free(data->strings[i][j]);
4783 free(data->strings[i]);
4785 free(data->strings);
4787 data->n_frames = n_frames;
4788 n_frames = tng_max_i64(1, n_frames);
4789 data->stride_length = tng_max_i64(1, stride_length);
4790 data->n_values_per_frame = n_values_per_frame;
4791 frame_alloc = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
4793 if(data->datatype == TNG_CHAR_DATA)
4795 data->strings = malloc(sizeof(char ***) * frame_alloc);
4796 for(i = 0; i < frame_alloc; i++)
4798 data->strings[i] = malloc(sizeof(char **) *
4800 if(!data->strings[i])
4802 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
4803 sizeof(union data_values *) * n_particles,
4804 __FILE__, __LINE__);
4805 return(TNG_CRITICAL);
4807 for(j = 0; j < n_particles; j++)
4809 data->strings[i][j] = malloc(sizeof(char *) *
4810 n_values_per_frame);
4811 if(!data->strings[i][j])
4813 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
4814 sizeof(union data_values) * n_values_per_frame,
4815 __FILE__, __LINE__);
4816 return(TNG_CRITICAL);
4818 for(k = 0; k < n_values_per_frame; k++)
4820 data->strings[i][j][k] = 0;
4827 switch(data->datatype)
4830 size = sizeof(int64_t);
4832 case TNG_FLOAT_DATA:
4833 size = sizeof(float);
4835 case TNG_DOUBLE_DATA:
4837 size = sizeof(double);
4840 values = realloc(data->values,
4841 size * frame_alloc *
4842 n_particles * n_values_per_frame);
4845 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
4846 size * frame_alloc *
4847 n_particles * n_values_per_frame,
4848 __FILE__, __LINE__);
4851 return(TNG_CRITICAL);
4853 data->values = values;
4855 return(TNG_SUCCESS);
4858 static tng_function_status tng_particle_data_find
4859 (const tng_trajectory_t tng_data,
4863 int64_t block_index, i;
4864 tng_trajectory_frame_set_t frame_set = &tng_data->
4865 current_trajectory_frame_set;
4866 char block_type_flag;
4868 if(tng_data->current_trajectory_frame_set_input_file_pos > 0 ||
4869 tng_data->current_trajectory_frame_set_output_file_pos > 0)
4871 block_type_flag = TNG_TRAJECTORY_BLOCK;
4875 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
4879 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
4881 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
4883 *data = &frame_set->tr_particle_data[i];
4884 if((*data)->block_id == id)
4893 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
4895 *data = &tng_data->non_tr_particle_data[i];
4896 if((*data)->block_id == id)
4903 if(block_index == -1)
4905 return(TNG_FAILURE);
4907 return(TNG_SUCCESS);
4910 static tng_function_status tng_data_find
4911 (const tng_trajectory_t tng_data,
4915 int64_t block_index, i;
4916 tng_trajectory_frame_set_t frame_set = &tng_data->
4917 current_trajectory_frame_set;
4918 char block_type_flag;
4920 if(tng_data->current_trajectory_frame_set_input_file_pos > 0 ||
4921 tng_data->current_trajectory_frame_set_output_file_pos > 0)
4923 block_type_flag = TNG_TRAJECTORY_BLOCK;
4927 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
4931 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
4933 for(i = 0; i < frame_set->n_data_blocks; i++)
4935 *data = &frame_set->tr_data[i];
4936 if((*data)->block_id == id)
4942 if(block_index == -1)
4944 for(i = 0; i < tng_data->n_data_blocks; i++)
4946 *data = &tng_data->non_tr_data[i];
4947 if((*data)->block_id == id)
4957 for(i = 0; i < tng_data->n_data_blocks; i++)
4959 *data = &tng_data->non_tr_data[i];
4960 if((*data)->block_id == id)
4967 if(block_index == -1)
4969 return(TNG_FAILURE);
4971 return(TNG_SUCCESS);
4974 static tng_function_status tng_data_block_len_calculate
4975 (const tng_trajectory_t tng_data,
4976 const tng_data_t data,
4977 const tng_bool is_particle_data,
4978 const int64_t n_frames,
4979 const int64_t frame_step,
4980 const int64_t stride_length,
4981 const int64_t num_first_particle,
4982 const int64_t n_particles,
4983 int64_t *data_start_pos,
4988 char ***first_dim_values, **second_dim_values;
4993 return(TNG_SUCCESS);
4996 switch(data->datatype)
5002 size = sizeof(int64_t);
5004 case TNG_FLOAT_DATA:
5005 size = sizeof(float);
5007 case TNG_DOUBLE_DATA:
5009 size = sizeof(double);
5012 *len = sizeof(char) * 2 + sizeof(data->n_values_per_frame) +
5013 sizeof(data->codec_id);
5014 if(is_particle_data)
5016 *len += sizeof(num_first_particle) + sizeof(n_particles);
5019 if(stride_length > 1)
5021 *len += sizeof(data->first_frame_with_data) +
5022 sizeof(data->stride_length);
5025 if(data->codec_id != TNG_UNCOMPRESSED)
5027 *len += sizeof(data->compression_multiplier);
5030 if(data->dependency & TNG_FRAME_DEPENDENT)
5032 *len += sizeof(char);
5035 *data_start_pos = *len;
5037 if(data->datatype == TNG_CHAR_DATA)
5039 if(is_particle_data)
5041 for(i = 0; i < n_frames; i++)
5043 first_dim_values = data->strings[i];
5044 for(j = num_first_particle; j < num_first_particle + n_particles;
5047 second_dim_values = first_dim_values[j];
5048 for(k = 0; k < data->n_values_per_frame; k++)
5050 *len += strlen(second_dim_values[k]) + 1;
5057 for(i = 0; i < n_frames; i++)
5059 second_dim_values = data->strings[0][i];
5060 for(j = 0; j < data->n_values_per_frame; j++)
5062 *len += strlen(second_dim_values[j]) + 1;
5069 *len += size * frame_step * n_particles * data->n_values_per_frame;
5072 return(TNG_SUCCESS);
5077 * @brief Create a non-particle data block
5078 * @param tng_data is a trajectory data container.
5079 * @param block_type_flag specifies if this is a trajectory block or a
5080 * non-trajectory block. (TNG_TRAJECTORY_BLOCK or TNG_NON_TRAJECTORY_BLOCK)
5081 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5082 * error has occured.
5084 static tng_function_status tng_data_block_create
5085 (const tng_trajectory_t tng_data,
5086 const char block_type_flag)
5088 tng_trajectory_frame_set_t frame_set =
5089 &tng_data->current_trajectory_frame_set;
5093 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5095 frame_set->n_data_blocks++;
5096 data = realloc(frame_set->tr_data, sizeof(struct tng_data) *
5097 frame_set->n_data_blocks);
5100 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
5101 sizeof(struct tng_data) * frame_set->n_data_blocks,
5102 __FILE__, __LINE__);
5103 free(frame_set->tr_data);
5104 frame_set->tr_data = 0;
5105 return(TNG_CRITICAL);
5107 frame_set->tr_data = data;
5111 tng_data->n_data_blocks++;
5112 data = realloc(tng_data->non_tr_data, sizeof(struct tng_data) *
5113 tng_data->n_data_blocks);
5116 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
5117 sizeof(struct tng_data) * tng_data->n_data_blocks,
5118 __FILE__, __LINE__);
5119 free(tng_data->non_tr_data);
5120 tng_data->non_tr_data = 0;
5121 return(TNG_CRITICAL);
5123 tng_data->non_tr_data = data;
5126 return(TNG_SUCCESS);
5131 * @brief Allocate memory for storing non-particle data.
5132 * The allocated block will be refered to by data->values.
5133 * @param tng_data is a trajectory data container.
5134 * @param data is the data struct, which will contain the allocated memory in
5136 * @param n_frames is the number of frames of data to store.
5137 * @param n_values_per_frame is the number of data values per frame.
5138 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5139 * error has occured.
5141 static tng_function_status tng_allocate_data_mem
5142 (const tng_trajectory_t tng_data,
5143 const tng_data_t data,
5145 const int64_t stride_length,
5146 const int64_t n_values_per_frame)
5149 int64_t i, j, size, frame_alloc;
5152 if(n_values_per_frame == 0)
5154 return(TNG_FAILURE);
5157 if(data->strings && data->datatype == TNG_CHAR_DATA)
5159 for(i = 0; i < data->n_frames; i++)
5161 for(j = 0; j < data->n_values_per_frame; j++)
5163 if(data->strings[0][i][j])
5165 free(data->strings[0][i][j]);
5166 data->strings[0][i][j] = 0;
5169 free(data->strings[0][i]);
5170 data->strings[0][i] = 0;
5172 free(data->strings[0]);
5173 data->strings[0] = 0;
5174 free(data->strings);
5176 data->n_frames = n_frames;
5177 data->stride_length = tng_max_i64(1, stride_length);
5178 n_frames = tng_max_i64(1, n_frames);
5179 data->n_values_per_frame = n_values_per_frame;
5180 frame_alloc = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
5182 if(data->datatype == TNG_CHAR_DATA)
5184 data->strings = malloc(sizeof(char ***));
5185 data->strings[0] = malloc(sizeof(char **) * frame_alloc);
5186 for(i = 0; i < frame_alloc; i++)
5188 data->strings[0][i] = malloc(sizeof(char *) * n_values_per_frame);
5189 if(!data->strings[0][i])
5191 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5193 __FILE__, __LINE__);
5194 return(TNG_CRITICAL);
5196 for(j = 0; j < n_values_per_frame; j++)
5198 data->strings[0][i][j] = 0;
5204 switch(data->datatype)
5207 size = sizeof(int64_t);
5209 case TNG_FLOAT_DATA:
5210 size = sizeof(float);
5212 case TNG_DOUBLE_DATA:
5214 size = sizeof(double);
5217 values = realloc(data->values,
5218 size * frame_alloc *
5219 n_values_per_frame);
5222 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5223 size * frame_alloc *
5225 __FILE__, __LINE__);
5228 return(TNG_CRITICAL);
5230 data->values = values;
5233 return(TNG_SUCCESS);
5237 * @brief Read the values of a data block
5238 * @param tng_data is a trajectory data container.
5239 * @param block is the block to store the data (should already contain
5240 * the block headers and the block contents).
5241 * @param block_data_len is the length of the data contents of the block.
5242 * @param datatype is the type of data of the data block (char, int, float or
5244 * @param num_first_particle is the number of the first particle in the data
5245 * block. This should be the same as in the corresponding particle mapping
5246 * block. Only used if reading particle dependent data.
5247 * @param n_particles is the number of particles in the data block. This should
5248 * be the same as in the corresponding particle mapping block. Only used if
5249 * reading particle dependent data.
5250 * @param first_frame_with_data is the frame number of the first frame with data
5251 * in this data block.
5252 * @param stride_length is the number of frames between each data entry.
5253 * @param n_frames is the number of frames in this data block.
5254 * @param n_values is the number of values per frame stored in this data block.
5255 * @param codec_id is the ID of the codec to compress the data.
5256 * @param multiplier is the multiplication factor applied to each data value
5257 * before compression. This factor is applied since some compression algorithms
5258 * work only on integers.
5259 * @param hash_mode is an option to decide whether to generate/update the relevant md5 hashes.
5260 * @param md5_state is a pointer to the current md5 storage, which will be updated appropriately
5261 * if hash_mode == TNG_USE_HASH.
5262 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5263 * error has occured.
5265 static tng_function_status tng_data_read(const tng_trajectory_t tng_data,
5266 const tng_gen_block_t block,
5267 const int64_t block_data_len,
5268 const char datatype,
5269 const int64_t num_first_particle,
5270 const int64_t n_particles,
5271 const int64_t first_frame_with_data,
5272 const int64_t stride_length,
5274 const int64_t n_values,
5275 const int64_t codec_id,
5276 const double multiplier,
5277 const char hash_mode,
5278 md5_state_t *md5_state)
5280 int64_t i, j, k, tot_n_particles, n_frames_div, offset;
5281 int64_t full_data_len;
5283 char ***first_dim_values, **second_dim_values;
5285 tng_trajectory_frame_set_t frame_set =
5286 &tng_data->current_trajectory_frame_set;
5287 char block_type_flag, *contents;
5288 tng_bool is_particle_data;
5289 tng_function_status stat;
5291 /* fprintf(stderr, "TNG library: %s\n", block->name);*/
5293 /* This must be caught early to avoid creating a data block if not necessary. */
5295 if(codec_id == TNG_GZIP_COMPRESSION)
5297 fprintf(stderr, "TNG library: Cannot uncompress data block. %s: %d\n", __FILE__,
5299 return(TNG_FAILURE);
5309 size = sizeof(int64_t);
5311 case TNG_FLOAT_DATA:
5312 size = sizeof(float);
5314 case TNG_DOUBLE_DATA:
5316 size = sizeof(double);
5321 is_particle_data = TNG_TRUE;
5325 if(codec_id == TNG_XTC_COMPRESSION || codec_id == TNG_TNG_COMPRESSION)
5327 fprintf(stderr, "TNG library: Cannot uncompress data block. %s: %d\n", __FILE__,
5329 return(TNG_FAILURE);
5331 is_particle_data = TNG_FALSE;
5334 if(is_particle_data == TNG_TRUE)
5336 stat = tng_particle_data_find(tng_data, block->id, &data);
5340 stat = tng_data_find(tng_data, block->id, &data);
5343 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
5345 block_type_flag = TNG_TRAJECTORY_BLOCK;
5349 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5352 /* If the block does not exist, create it */
5353 if(stat != TNG_SUCCESS)
5355 if(is_particle_data == TNG_TRUE)
5357 stat = tng_particle_data_block_create(tng_data, block_type_flag);
5361 stat = tng_data_block_create(tng_data, block_type_flag);
5364 if(stat != TNG_SUCCESS)
5366 fprintf(stderr, "TNG library: Cannot create data block. %s: %d\n",
5367 __FILE__, __LINE__);
5368 return(TNG_CRITICAL);
5371 if(is_particle_data == TNG_TRUE)
5373 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5375 data = &frame_set->tr_particle_data[frame_set->
5376 n_particle_data_blocks - 1];
5380 data = &tng_data->non_tr_particle_data[tng_data->
5381 n_particle_data_blocks - 1];
5386 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5388 data = &frame_set->tr_data[frame_set->n_data_blocks - 1];
5392 data = &tng_data->non_tr_data[tng_data->n_data_blocks - 1];
5396 data->block_id = block->id;
5398 data->block_name = malloc(strlen(block->name) + 1);
5399 if(!data->block_name)
5401 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n",
5402 (unsigned int)strlen(block->name)+1, __FILE__, __LINE__);
5403 return(TNG_CRITICAL);
5405 strcpy(data->block_name, block->name);
5407 data->datatype = datatype;
5410 /* FIXME: Memory leak from strings. */
5413 data->dependency = 0;
5414 if(is_particle_data == TNG_TRUE)
5416 data->dependency += TNG_PARTICLE_DEPENDENT;
5418 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
5420 frame_set->n_frames == n_frames ||
5423 data->dependency += TNG_FRAME_DEPENDENT;
5425 data->codec_id = codec_id;
5426 data->compression_multiplier = multiplier;
5427 data->last_retrieved_frame = -1;
5430 if(is_particle_data == TNG_TRUE)
5432 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
5433 tng_data->var_num_atoms_flag)
5435 tot_n_particles = frame_set->n_particles;
5439 tot_n_particles = tng_data->n_particles;
5442 /* If there are no particles in this data block, still set tot_n_particles = 1
5443 * to calculate block lengths etc properly. */
5446 tot_n_particles = 1;
5449 n_frames_div = (n_frames % stride_length) ? n_frames / stride_length + 1 : n_frames / stride_length;
5451 contents = malloc(block_data_len);
5454 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
5455 block_data_len, __FILE__, __LINE__);
5456 return(TNG_CRITICAL);
5459 if(fread(contents, block_data_len, 1, tng_data->input_file) == 0)
5461 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
5462 return(TNG_CRITICAL);
5465 if(hash_mode == TNG_USE_HASH)
5467 md5_append(md5_state, (md5_byte_t *)contents, block_data_len);
5470 if(codec_id != TNG_UNCOMPRESSED)
5472 full_data_len = n_frames_div * size * n_values;
5473 if(is_particle_data == TNG_TRUE)
5475 full_data_len *= n_particles;
5479 case TNG_XTC_COMPRESSION:
5480 fprintf(stderr, "TNG library: XTC compression not implemented yet.\n");
5482 case TNG_TNG_COMPRESSION:
5483 /* fprintf(stderr, "TNG library: Before TNG uncompression: %"PRId64"\n", block->block_contents_size);*/
5484 if(tng_uncompress(tng_data, block, datatype,
5485 &contents, full_data_len) != TNG_SUCCESS)
5487 fprintf(stderr, "TNG library: Could not read tng compressed block data. %s: %d\n",
5488 __FILE__, __LINE__);
5490 return(TNG_CRITICAL);
5492 /* fprintf(stderr, "TNG library: After TNG uncompression: %"PRId64"\n", block->block_contents_size);*/
5495 case TNG_GZIP_COMPRESSION:
5496 /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size); */
5497 if(tng_gzip_uncompress(tng_data, &contents,
5498 block_data_len, full_data_len) != TNG_SUCCESS)
5500 fprintf(stderr, "TNG library: Could not read gzipped block data. %s: %d\n", __FILE__,
5503 return(TNG_CRITICAL);
5505 /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size); */
5512 full_data_len = block_data_len;
5515 /* Allocate memory */
5516 if(!data->values || data->n_frames != n_frames ||
5517 data->n_values_per_frame != n_values)
5519 if(is_particle_data == TNG_TRUE)
5521 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
5523 tot_n_particles, n_values);
5527 stat = tng_allocate_data_mem(tng_data, data, n_frames, stride_length,
5530 if(stat != TNG_SUCCESS)
5532 fprintf(stderr, "TNG library: Cannot allocate memory for data. %s: %d\n",
5533 __FILE__, __LINE__);
5535 return(TNG_CRITICAL);
5539 data->first_frame_with_data = first_frame_with_data;
5541 if(datatype == TNG_CHAR_DATA)
5544 /* Strings are stores slightly differently if the data block contains particle
5545 * data (frames * particles * n_values) or not (frames * n_values). */
5546 if(is_particle_data == TNG_TRUE)
5548 for(i = 0; i < n_frames_div; i++)
5550 first_dim_values = data->strings[i];
5551 for(j = num_first_particle; j < num_first_particle + n_particles;
5554 second_dim_values = first_dim_values[j];
5555 for(k = 0; k < n_values; k++)
5557 len = tng_min_size(strlen(contents+offset) + 1,
5559 if(second_dim_values[k])
5561 free(second_dim_values[k]);
5563 second_dim_values[k] = malloc(len);
5564 if(!second_dim_values[k])
5566 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
5567 len, __FILE__, __LINE__);
5569 return(TNG_CRITICAL);
5571 strncpy(second_dim_values[k], contents+offset, len);
5579 for(i = 0; i < n_frames_div; i++)
5581 for(j = 0; j < n_values; j++)
5583 len = tng_min_size(strlen(contents+offset) + 1,
5585 if(data->strings[0][i][j])
5587 free(data->strings[0][i][j]);
5589 data->strings[0][i][j] = malloc(len);
5590 if(!data->strings[0][i][j])
5592 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
5593 len, __FILE__, __LINE__);
5595 return(TNG_CRITICAL);
5597 strncpy(data->strings[0][i][j], contents+offset, len);
5605 if(is_particle_data)
5607 memcpy((char *)data->values + n_frames_div * size * n_values *
5608 num_first_particle, contents, full_data_len);
5612 memcpy(data->values, contents, full_data_len);
5616 case TNG_FLOAT_DATA:
5617 if(tng_data->input_endianness_swap_func_32)
5619 for(i = 0; i < full_data_len; i+=size)
5621 if(tng_data->input_endianness_swap_func_32(tng_data,
5622 (int32_t *)((char *)data->values + i))
5625 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5626 __FILE__, __LINE__);
5632 case TNG_DOUBLE_DATA:
5633 if(tng_data->input_endianness_swap_func_64)
5635 for(i = 0; i < full_data_len; i+=size)
5637 if(tng_data->input_endianness_swap_func_64(tng_data,
5638 (int64_t *)((char *)data->values + i))
5641 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5642 __FILE__, __LINE__);
5654 return(TNG_SUCCESS);
5658 * @brief Write a data block (particle or non-particle data)
5659 * @param tng_data is a trajectory data container.
5660 * @param block is the block to store the data (should already contain
5661 * the block headers and the block contents).
5662 * @param block_index is the index number of the data block in the frame set.
5663 * @param is_particle_data is a flag to specify if the data to write is
5664 * particle dependent or not.
5665 * @param mapping is the particle mapping that is relevant for the data block.
5666 * Only relevant if writing particle dependent data.
5667 * @param hash_mode is an option to decide whether to use the md5 hash or not.
5668 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
5669 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5670 * error has occured.
5672 static tng_function_status tng_data_block_write(const tng_trajectory_t tng_data,
5673 const tng_gen_block_t block,
5674 const int64_t block_index,
5675 const tng_bool is_particle_data,
5676 const tng_particle_mapping_t mapping,
5677 const char hash_mode)
5679 int64_t n_particles, num_first_particle, n_frames, stride_length;
5680 int64_t full_data_len, block_data_len, frame_step, data_start_pos;
5681 int64_t i, j, k, curr_file_pos, header_file_pos;
5684 tng_function_status stat;
5685 char temp, *temp_name, ***first_dim_values, **second_dim_values, *contents;
5687 tng_trajectory_frame_set_t frame_set =
5688 &tng_data->current_trajectory_frame_set;
5690 char block_type_flag;
5691 md5_state_t md5_state;
5693 /* If we have already started writing frame sets it is too late to write
5694 * non-trajectory data blocks */
5695 if(tng_data->current_trajectory_frame_set_output_file_pos > 0)
5697 block_type_flag = TNG_TRAJECTORY_BLOCK;
5701 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5704 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
5706 return(TNG_CRITICAL);
5709 if(is_particle_data == TNG_TRUE)
5711 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5713 data = &frame_set->tr_particle_data[block_index];
5715 /* If this data block has not had any data added in this frame set
5716 * do not write it. */
5717 if(data->first_frame_with_data < frame_set->first_frame)
5719 return(TNG_SUCCESS);
5722 stride_length = tng_max_i64(1, data->stride_length);
5726 data = &tng_data->non_tr_particle_data[block_index];
5732 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5734 data = &frame_set->tr_data[block_index];
5736 /* If this data block has not had any data added in this frame set
5737 * do not write it. */
5738 if(data->first_frame_with_data < frame_set->first_frame)
5740 return(TNG_SUCCESS);
5743 stride_length = tng_max_i64(1, data->stride_length);
5747 data = &tng_data->non_tr_data[block_index];
5752 switch(data->datatype)
5758 size = sizeof(int64_t);
5760 case TNG_FLOAT_DATA:
5761 size = sizeof(float);
5763 case TNG_DOUBLE_DATA:
5765 size = sizeof(double);
5768 len = strlen(data->block_name) + 1;
5770 if(!block->name || strlen(block->name) < len)
5772 temp_name = realloc(block->name, len);
5775 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n", len+1,
5776 __FILE__, __LINE__);
5779 return(TNG_CRITICAL);
5781 block->name = temp_name;
5783 strncpy(block->name, data->block_name, len);
5784 block->id = data->block_id;
5786 /* If writing frame independent data data->n_frames is 0, but n_frames
5787 is used for the loop writing the data (and reserving memory) and needs
5789 n_frames = tng_max_i64(1, data->n_frames);
5791 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5793 /* If the frame set is finished before writing the full number of frames
5794 make sure the data block is not longer than the frame set. */
5795 n_frames = tng_min_i64(n_frames, frame_set->n_frames);
5797 n_frames -= (data->first_frame_with_data - frame_set->first_frame);
5800 frame_step = (n_frames % stride_length) ? n_frames / stride_length + 1:
5801 n_frames / stride_length;
5803 /* TNG compression will use compression precision to get integers from
5804 * floating point data. The compression multiplier stores that information
5805 * to be able to return the precision of the compressed data. */
5806 if(data->codec_id == TNG_TNG_COMPRESSION)
5808 data->compression_multiplier = tng_data->compression_precision;
5810 /* Uncompressed data blocks do not use compression multipliers at all.
5811 * GZip compression does not need it either. */
5812 else if(data->codec_id == TNG_UNCOMPRESSED || data->codec_id == TNG_GZIP_COMPRESSION)
5814 data->compression_multiplier = 1.0;
5817 if(data->dependency & TNG_PARTICLE_DEPENDENT)
5819 if(mapping && mapping->n_particles != 0)
5821 n_particles = mapping->n_particles;
5822 num_first_particle = mapping->num_first_particle;
5826 num_first_particle = 0;
5827 if(tng_data->var_num_atoms_flag)
5829 n_particles = frame_set->n_particles;
5833 n_particles = tng_data->n_particles;
5838 if(data->dependency & TNG_PARTICLE_DEPENDENT)
5840 if(tng_data_block_len_calculate(tng_data, data, TNG_TRUE, n_frames,
5841 frame_step, stride_length, num_first_particle,
5842 n_particles, &data_start_pos,
5843 &block->block_contents_size) != TNG_SUCCESS)
5845 fprintf(stderr, "TNG library: Cannot calculate length of particle data block. %s: %d\n",
5846 __FILE__, __LINE__);
5847 return(TNG_CRITICAL);
5852 if(tng_data_block_len_calculate(tng_data, data, TNG_FALSE, n_frames,
5853 frame_step, stride_length, 0,
5855 &block->block_contents_size) != TNG_SUCCESS)
5857 fprintf(stderr, "TNG library: Cannot calculate length of non-particle data block. %s: %d\n",
5858 __FILE__, __LINE__);
5859 return(TNG_CRITICAL);
5863 header_file_pos = ftello(tng_data->output_file);
5865 if(tng_block_header_write(tng_data, block) != TNG_SUCCESS)
5867 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
5868 tng_data->output_file_path, __FILE__, __LINE__);
5869 return(TNG_CRITICAL);
5872 if(hash_mode == TNG_USE_HASH)
5874 md5_init(&md5_state);
5877 if(tng_file_output_numerical(tng_data, &data->datatype,
5878 sizeof(data->datatype),
5879 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5881 return(TNG_CRITICAL);
5884 if(tng_file_output_numerical(tng_data, &data->dependency,
5885 sizeof(data->dependency),
5886 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5888 return(TNG_CRITICAL);
5891 if(data->dependency & TNG_FRAME_DEPENDENT)
5893 if(stride_length > 1)
5901 if(tng_file_output_numerical(tng_data, &temp,
5903 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5905 return(TNG_CRITICAL);
5909 if(tng_file_output_numerical(tng_data, &data->n_values_per_frame,
5910 sizeof(data->n_values_per_frame),
5911 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5913 return(TNG_CRITICAL);
5916 if(tng_file_output_numerical(tng_data, &data->codec_id,
5917 sizeof(data->codec_id),
5918 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5920 return(TNG_CRITICAL);
5923 if(data->codec_id != TNG_UNCOMPRESSED)
5925 if(tng_file_output_numerical(tng_data, &data->compression_multiplier,
5926 sizeof(data->compression_multiplier),
5927 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5929 return(TNG_CRITICAL);
5933 if(data->n_frames > 0 && stride_length > 1)
5935 /* FIXME: first_frame_with_data is not reliably set */
5936 if(data->first_frame_with_data == 0)
5938 data->first_frame_with_data = frame_set->first_frame;
5940 if(tng_file_output_numerical(tng_data, &data->first_frame_with_data,
5941 sizeof(data->first_frame_with_data),
5942 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5944 return(TNG_CRITICAL);
5947 if(tng_file_output_numerical(tng_data, &stride_length,
5948 sizeof(stride_length),
5949 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5951 return(TNG_CRITICAL);
5955 if(data->dependency & TNG_PARTICLE_DEPENDENT)
5957 if(tng_file_output_numerical(tng_data, &num_first_particle,
5958 sizeof(num_first_particle),
5959 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5961 return(TNG_CRITICAL);
5964 if(tng_file_output_numerical(tng_data, &n_particles,
5965 sizeof(n_particles),
5966 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5968 return(TNG_CRITICAL);
5972 if(data->datatype == TNG_CHAR_DATA)
5976 if(data->dependency & TNG_PARTICLE_DEPENDENT)
5978 for(i = 0; i < frame_step; i++)
5980 first_dim_values = data->strings[i];
5981 for(j = num_first_particle; j < num_first_particle + n_particles;
5984 second_dim_values = first_dim_values[j];
5985 for(k = 0; k < data->n_values_per_frame; k++)
5987 if(tng_fwritestr(tng_data, second_dim_values[k],
5988 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5990 return(TNG_CRITICAL);
5998 for(i = 0; i < frame_step; i++)
6000 for(j = 0; j < data->n_values_per_frame; j++)
6002 if(tng_fwritestr(tng_data, data->strings[0][i][j],
6003 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
6005 return(TNG_CRITICAL);
6014 if(data->dependency & TNG_PARTICLE_DEPENDENT)
6016 full_data_len = size * frame_step * n_particles * data->n_values_per_frame;
6020 full_data_len = size * frame_step * data->n_values_per_frame;
6022 contents = malloc(full_data_len);
6025 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
6026 full_data_len, __FILE__, __LINE__);
6027 return(TNG_CRITICAL);
6032 memcpy(contents, data->values, full_data_len);
6033 switch(data->datatype)
6035 case TNG_FLOAT_DATA:
6036 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
6037 data->codec_id == TNG_TNG_COMPRESSION)
6039 if(tng_data->output_endianness_swap_func_32)
6041 for(i = 0; i < full_data_len; i+=size)
6043 if(tng_data->output_endianness_swap_func_32(tng_data,
6044 (int32_t *)(contents + i))
6047 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6048 __FILE__, __LINE__);
6055 multiplier = data->compression_multiplier;
6056 if(fabs(multiplier - 1.0) > 0.00001 ||
6057 tng_data->output_endianness_swap_func_32)
6059 for(i = 0; full_data_len; i+=size)
6061 *(float *)(contents + i) *= (float)multiplier;
6062 if(tng_data->output_endianness_swap_func_32 &&
6063 tng_data->output_endianness_swap_func_32(tng_data,
6064 (int32_t *)(contents + i))
6067 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6068 __FILE__, __LINE__);
6075 if(tng_data->output_endianness_swap_func_64)
6077 for(i = 0; i < full_data_len; i+=size)
6079 if(tng_data->output_endianness_swap_func_64(tng_data,
6080 (int64_t *)(contents + i))
6083 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6084 __FILE__, __LINE__);
6089 case TNG_DOUBLE_DATA:
6090 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
6091 data->codec_id == TNG_TNG_COMPRESSION)
6093 if(tng_data->output_endianness_swap_func_64)
6095 for(i = 0; i < full_data_len; i+=size)
6097 if(tng_data->output_endianness_swap_func_64(tng_data,
6098 (int64_t *)(contents + i))
6101 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6102 __FILE__, __LINE__);
6109 multiplier = data->compression_multiplier;
6110 if(fabs(multiplier - 1.0) > 0.00001 ||
6111 tng_data->output_endianness_swap_func_64)
6113 for(i = 0; i < full_data_len; i+=size)
6115 *(double *)(contents + i) *= multiplier;
6116 if(tng_data->output_endianness_swap_func_64 &&
6117 tng_data->output_endianness_swap_func_64(tng_data,
6118 (int64_t *)(contents + i))
6121 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6122 __FILE__, __LINE__);
6134 memset(contents, 0, full_data_len);
6137 block_data_len = full_data_len;
6139 switch(data->codec_id)
6141 case TNG_XTC_COMPRESSION:
6142 fprintf(stderr, "TNG library: XTC compression not implemented yet.\n");
6143 data->codec_id = TNG_UNCOMPRESSED;
6145 case TNG_TNG_COMPRESSION:
6146 stat = tng_compress(tng_data, block, frame_step,
6147 n_particles, data->datatype,
6148 &contents, &block_data_len);
6149 if(stat != TNG_SUCCESS)
6151 fprintf(stderr, "TNG library: Could not write tng compressed block data. %s: %d\n",
6152 __FILE__, __LINE__);
6153 if(stat == TNG_CRITICAL)
6155 return(TNG_CRITICAL);
6157 /* Set the data again, but with no compression (to write only
6158 * the relevant data) */
6159 data->codec_id = TNG_UNCOMPRESSED;
6160 stat = tng_data_block_write(tng_data, block,
6161 block_index, is_particle_data, mapping,
6168 case TNG_GZIP_COMPRESSION:
6169 /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size); */
6170 stat = tng_gzip_compress(tng_data,
6174 if(stat != TNG_SUCCESS)
6176 fprintf(stderr, "TNG library: Could not write gzipped block data. %s: %d\n", __FILE__,
6178 if(stat == TNG_CRITICAL)
6180 return(TNG_CRITICAL);
6182 data->codec_id = TNG_UNCOMPRESSED;
6184 /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size); */
6188 if(block_data_len != full_data_len)
6190 block->block_contents_size -= full_data_len - block_data_len;
6192 curr_file_pos = ftello(tng_data->output_file);
6193 fseeko(tng_data->output_file, header_file_pos + sizeof(block->header_contents_size), SEEK_SET);
6195 if(tng_file_output_numerical(tng_data, &block->block_contents_size,
6196 sizeof(block->block_contents_size),
6197 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
6199 return(TNG_CRITICAL);
6201 fseeko(tng_data->output_file, curr_file_pos, SEEK_SET);
6203 if(fwrite(contents, block_data_len, 1, tng_data->output_file) != 1)
6205 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__,
6207 return(TNG_CRITICAL);
6209 if(hash_mode == TNG_USE_HASH)
6211 md5_append(&md5_state, (md5_byte_t *)contents, block_data_len);
6217 if(hash_mode == TNG_USE_HASH)
6219 md5_finish(&md5_state, (md5_byte_t *)block->md5_hash);
6220 curr_file_pos = ftello(tng_data->output_file);
6221 fseeko(tng_data->output_file, header_file_pos +
6222 3 * sizeof(int64_t), SEEK_SET);
6223 if(fwrite(block->md5_hash, TNG_MD5_HASH_LEN, 1, tng_data->output_file) != 1)
6225 fprintf(stderr, "TNG library: Could not write MD5 hash. %s: %d\n", __FILE__,
6227 return(TNG_CRITICAL);
6229 fseeko(tng_data->output_file, curr_file_pos, SEEK_SET);
6232 frame_set->n_written_frames += frame_set->n_unwritten_frames;
6233 frame_set->n_unwritten_frames = 0;
6235 return(TNG_SUCCESS);
6239 * @brief Read the meta information of a data block (particle or non-particle data).
6240 * @param tng_data is a trajectory data container.
6241 * @param datatype is set to the datatype of the data block.
6242 * @param dependency is set to the dependency (particle and/or frame dependent)
6243 * @param sparse_data is set to TRUE if data is not written every frame.
6244 * @param n_values is set to the number of values per frame of the data.
6245 * @param codec_id is set to the ID of the codec used to compress the data.
6246 * @param first_frame_with_data is set to the first frame with data (only relevant if
6247 * sparse_data == TRUE).
6248 * @param stride_length is set to the writing interval of the data (1 if sparse_data
6250 * @param num_first_particle is set to the number of the first particle with data written
6252 * @param block_n_particles is set to the number of particles in this data block.
6253 * @param multiplier is set to the compression multiplier.
6254 * @param hash_mode specifies whether to check if the hash matches the contents or not.
6255 * @param md5_state is the md5 hash of the block (only used if hash_mode == TNG_USE_HASH).
6256 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6257 * error has occured.
6259 static tng_function_status tng_data_block_meta_information_read
6260 (const tng_trajectory_t tng_data,
6266 int64_t *first_frame_with_data,
6267 int64_t *stride_length,
6269 int64_t *num_first_particle,
6270 int64_t *block_n_particles,
6272 const char hash_mode,
6273 md5_state_t *md5_state)
6275 if(tng_file_input_numerical(tng_data, datatype,
6277 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6279 return(TNG_CRITICAL);
6282 if(tng_file_input_numerical(tng_data, dependency,
6283 sizeof(*dependency),
6284 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6286 return(TNG_CRITICAL);
6289 if(*dependency & TNG_FRAME_DEPENDENT)
6291 if(tng_file_input_numerical(tng_data, sparse_data,
6292 sizeof(*sparse_data),
6293 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6295 return(TNG_CRITICAL);
6299 if(tng_file_input_numerical(tng_data, n_values,
6301 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6303 return(TNG_CRITICAL);
6306 if(tng_file_input_numerical(tng_data, codec_id,
6308 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6310 return(TNG_CRITICAL);
6313 if(*codec_id != TNG_UNCOMPRESSED)
6315 if(tng_file_input_numerical(tng_data, multiplier,
6316 sizeof(*multiplier),
6317 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6319 return(TNG_CRITICAL);
6327 if(*dependency & TNG_FRAME_DEPENDENT)
6331 if(tng_file_input_numerical(tng_data, first_frame_with_data,
6332 sizeof(*first_frame_with_data),
6333 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6335 return(TNG_CRITICAL);
6338 if(tng_file_input_numerical(tng_data, stride_length,
6339 sizeof(*stride_length),
6340 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6342 return(TNG_CRITICAL);
6345 *n_frames = tng_data->current_trajectory_frame_set.n_frames -
6346 (*first_frame_with_data -
6347 tng_data->current_trajectory_frame_set.first_frame);
6351 *first_frame_with_data = tng_data->current_trajectory_frame_set.first_frame;
6353 *n_frames = tng_data->current_trajectory_frame_set.n_frames;
6358 *first_frame_with_data = 0;
6363 if (*dependency & TNG_PARTICLE_DEPENDENT)
6365 if(tng_file_input_numerical(tng_data, num_first_particle,
6366 sizeof(*num_first_particle),
6367 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6369 return(TNG_CRITICAL);
6372 if(tng_file_input_numerical(tng_data, block_n_particles,
6373 sizeof(*block_n_particles),
6374 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6376 return(TNG_CRITICAL);
6381 *num_first_particle = -1;
6382 *block_n_particles = 0;
6385 return(TNG_SUCCESS);
6389 * @brief Read the contents of a data block (particle or non-particle data).
6390 * @param tng_data is a trajectory data container.
6391 * @param block is the block to store the data (should already contain
6392 * the block headers).
6393 * @param hash_mode is an option to decide whether to use the md5 hash or not.
6394 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
6395 * compared to the md5 hash of the read contents to ensure valid data.
6396 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6397 * error has occured.
6399 static tng_function_status tng_data_block_contents_read
6400 (const tng_trajectory_t tng_data,
6401 const tng_gen_block_t block,
6402 const char hash_mode)
6404 int64_t start_pos, n_values, codec_id, n_frames, first_frame_with_data;
6405 int64_t remaining_len, stride_length, block_n_particles, num_first_particle;
6407 char datatype, dependency, sparse_data;
6408 tng_function_status stat = TNG_SUCCESS;
6409 char hash[TNG_MD5_HASH_LEN];
6410 md5_state_t md5_state;
6412 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
6414 return(TNG_CRITICAL);
6417 start_pos = ftello(tng_data->input_file);
6419 if(hash_mode == TNG_USE_HASH)
6421 md5_init(&md5_state);
6424 /* FIXME: Does not check if the size of the contents matches the expected
6425 * size or if the contents can be read. */
6427 if(tng_data_block_meta_information_read(tng_data,
6429 &dependency, &sparse_data,
6430 &n_values, &codec_id,
6431 &first_frame_with_data,
6432 &stride_length, &n_frames,
6433 &num_first_particle,
6437 &md5_state) == TNG_CRITICAL)
6439 fprintf(stderr, "TNG library: Cannot read data block (%s) meta information. %s: %d\n",
6440 block->name, __FILE__, __LINE__);
6441 return(TNG_CRITICAL);
6444 remaining_len = block->block_contents_size - (ftello(tng_data->input_file) - start_pos);
6446 stat = tng_data_read(tng_data, block,
6451 first_frame_with_data,
6454 codec_id, multiplier,
6458 if(hash_mode == TNG_USE_HASH)
6460 /* If there is data left in the block that the current version of the library
6461 * cannot interpret still read that to generate the MD5 hash. */
6462 tng_md5_remaining_append(tng_data, block, start_pos, &md5_state);
6464 md5_finish(&md5_state, (md5_byte_t *)hash);
6465 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)
6467 if(strncmp(block->md5_hash, hash, TNG_MD5_HASH_LEN) != 0)
6469 fprintf(stderr, "TNG library: Data block contents corrupt (%s). Hashes do not match. "
6470 "%s: %d\n", block->name, __FILE__, __LINE__);
6476 /* Seek to the end of the block */
6477 fseeko(tng_data->input_file, start_pos + block->block_contents_size, SEEK_SET);
6484 // ** Move the blocks in a frame set so that there is no unused space between
6485 // * them. This can only be done on the last frame set in the file and should
6486 // * be done e.g. if the last frame set in the file has fewer frames than
6487 // * default or after compressing data blocks in a frame set.
6488 // * @param tng_data is a trajectory data container.
6489 // * @details the current_trajectory_frame_set is the one that will be modified.
6490 // * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the frame set
6491 // * cannot be aligned or TNG_CRITICAL (2) if a major error has occured.
6492 // * FIXME: This function is not finished!!!
6494 // static tng_function_status tng_frame_set_align(tng_trajectory_t tng_data)
6496 // tng_gen_block_t block;
6497 // tng_trajectory_frame_set_t frame_set;
6498 // FILE *temp = tng_data->input_file;
6499 // int64_t pos, contents_start_pos, output_file_len;
6501 // frame_set = &tng_data->current_trajectory_frame_set;
6503 // if(frame_set->n_written_frames == frame_set->n_frames)
6505 // return(TNG_SUCCESS);
6508 // if(tng_data->current_trajectory_frame_set_output_file_pos !=
6509 // tng_data->last_trajectory_frame_set_output_file_pos)
6513 // if(tng_output_file_init(tng_data) != TNG_SUCCESS)
6515 // fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
6516 // __FILE__, __LINE__);
6517 // return(TNG_CRITICAL);
6520 // tng_block_init(&block);
6521 // // output_file_pos = ftello(tng_data->output_file);
6523 // tng_data->input_file = tng_data->output_file;
6525 // pos = tng_data->current_trajectory_frame_set_output_file_pos;
6527 // fseeko(tng_data->output_file, pos, SEEK_SET);
6528 // if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
6530 // fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
6531 // __FILE__, __LINE__);
6532 // tng_data->input_file = temp;
6533 // tng_block_destroy(&block);
6534 // return(TNG_CRITICAL);
6537 // contents_start_pos = ftello(tng_data->output_file);
6539 // fseeko(tng_data->output_file, 0, SEEK_END);
6540 // output_file_len = ftello(tng_data->output_file);
6541 // pos = contents_start_pos + block->block_contents_size;
6542 // fseeko(tng_data->output_file, pos,
6545 // while(pos < output_file_len)
6547 // if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
6549 // fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", pos,
6550 // __FILE__, __LINE__);
6551 // tng_data->input_file = temp;
6552 // tng_block_destroy(&block);
6553 // return(TNG_CRITICAL);
6555 // pos += block->header_contents_size + block->block_contents_size;
6556 // fseeko(tng_data->output_file, pos, SEEK_SET);
6559 // return(TNG_SUCCESS);
6563 * @brief Finish writing the current frame set. Update the number of frames
6564 * and the hashes of the frame set and all its data blocks (if hash_mode
6566 * @param tng_data is a trajectory data container.
6567 * @param hash_mode specifies whether to update the block md5 hash when
6568 * updating the pointers.
6569 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6570 * error has occured.
6572 static tng_function_status tng_frame_set_finalize
6573 (const tng_trajectory_t tng_data,
6574 const char hash_mode)
6576 tng_gen_block_t block;
6577 tng_trajectory_frame_set_t frame_set;
6578 FILE *temp = tng_data->input_file;
6579 int64_t pos, curr_file_pos;
6581 frame_set = &tng_data->current_trajectory_frame_set;
6583 if(frame_set->n_written_frames == frame_set->n_frames)
6585 return(TNG_SUCCESS);
6588 frame_set->n_written_frames = frame_set->n_frames;
6590 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
6592 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
6593 __FILE__, __LINE__);
6594 return(TNG_CRITICAL);
6597 tng_block_init(&block);
6598 /* output_file_pos = ftello(tng_data->output_file); */
6600 tng_data->input_file = tng_data->output_file;
6602 curr_file_pos = ftello(tng_data->output_file);
6604 pos = tng_data->current_trajectory_frame_set_output_file_pos;
6606 fseeko(tng_data->output_file, pos, SEEK_SET);
6608 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
6610 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
6611 __FILE__, __LINE__);
6612 tng_data->input_file = temp;
6613 tng_block_destroy(&block);
6614 return(TNG_CRITICAL);
6617 // contents_start_pos = ftello(tng_data->output_file);
6619 fseeko(tng_data->output_file, sizeof(frame_set->first_frame), SEEK_CUR);
6620 if(fwrite(&frame_set->n_frames, sizeof(frame_set->n_frames),
6621 1, tng_data->output_file) != 1)
6623 tng_data->input_file = temp;
6624 tng_block_destroy(&block);
6625 return(TNG_CRITICAL);
6628 if(hash_mode == TNG_USE_HASH)
6630 tng_md5_hash_update(tng_data, block, pos,
6631 pos + block->header_contents_size);
6634 fseeko(tng_data->output_file, curr_file_pos, SEEK_SET);
6636 tng_data->input_file = temp;
6637 tng_block_destroy(&block);
6638 return(TNG_SUCCESS);
6642 // ** Sets the name of a file contents block
6643 // * @param tng_data is a trajectory data container.
6644 // * @param block is the block, of which to change names.
6645 // * @param new_name is the new name of the block.
6646 // * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6647 // * error has occured.
6649 // static tng_function_status tng_block_name_set(tng_trajectory_t tng_data,
6650 // tng_gen_block_t block,
6651 // const char *new_name)
6655 // len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
6657 // * If the currently stored string length is not enough to store the new
6658 // * string it is freed and reallocated. *
6659 // if(block->name && strlen(block->name) < len)
6661 // free(block->name);
6666 // block->name = malloc(len);
6669 // fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
6670 // __FILE__, __LINE__);
6671 // return(TNG_CRITICAL);
6675 // strncpy(block->name, new_name, len);
6677 // return(TNG_SUCCESS);
6681 tng_function_status tng_atom_residue_get(const tng_trajectory_t tng_data,
6682 const tng_atom_t atom,
6683 tng_residue_t *residue)
6687 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
6689 *residue = atom->residue;
6691 return(TNG_SUCCESS);
6694 tng_function_status tng_atom_name_get(const tng_trajectory_t tng_data,
6695 const tng_atom_t atom,
6700 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
6701 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
6703 strncpy(name, atom->name, max_len - 1);
6704 name[max_len - 1] = 0;
6706 if(strlen(atom->name) > (unsigned int)max_len - 1)
6708 return(TNG_FAILURE);
6710 return(TNG_SUCCESS);
6713 tng_function_status tng_atom_name_set(const tng_trajectory_t tng_data,
6714 const tng_atom_t atom,
6715 const char *new_name)
6720 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
6721 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
6723 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
6725 /* If the currently stored string length is not enough to store the new
6726 * string it is freed and reallocated. */
6727 if(atom->name && strlen(atom->name) < len)
6734 atom->name = malloc(len);
6737 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
6738 __FILE__, __LINE__);
6739 return(TNG_CRITICAL);
6743 strncpy(atom->name, new_name, len);
6745 return(TNG_SUCCESS);
6748 tng_function_status tng_atom_type_get(const tng_trajectory_t tng_data,
6749 const tng_atom_t atom,
6754 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
6755 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer");
6757 strncpy(type, atom->atom_type, max_len - 1);
6758 type[max_len - 1] = 0;
6760 if(strlen(atom->atom_type) > (unsigned int)max_len - 1)
6762 return(TNG_FAILURE);
6764 return(TNG_SUCCESS);
6767 tng_function_status tng_atom_type_set(const tng_trajectory_t tng_data,
6768 const tng_atom_t atom,
6769 const char *new_type)
6774 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
6775 TNG_ASSERT(new_type, "TNG library: new_type must not be a NULL pointer.");
6777 len = tng_min_size(strlen(new_type) + 1, TNG_MAX_STR_LEN);
6779 /* If the currently stored string length is not enough to store the new
6780 * string it is freed and reallocated. */
6781 if(atom->atom_type && strlen(atom->atom_type) < len)
6783 free(atom->atom_type);
6784 atom->atom_type = 0;
6786 if(!atom->atom_type)
6788 atom->atom_type = malloc(len);
6789 if(!atom->atom_type)
6791 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
6792 __FILE__, __LINE__);
6793 return(TNG_CRITICAL);
6797 strncpy(atom->atom_type, new_type, len);
6799 return(TNG_SUCCESS);
6803 * @brief Initialise an atom struct
6804 * @param atom is the atom to initialise.
6805 * @return TNG_SUCCESS (0) if successful.
6807 static tng_function_status tng_atom_init(const tng_atom_t atom)
6810 atom->atom_type = 0;
6812 return(TNG_SUCCESS);
6816 * @brief Free the memory in an atom struct
6817 * @param atom is the atom to destroy.
6818 * @return TNG_SUCCESS (0) if successful.
6820 static tng_function_status tng_atom_destroy(const tng_atom_t atom)
6829 free(atom->atom_type);
6830 atom->atom_type = 0;
6833 return(TNG_SUCCESS);
6836 tng_function_status DECLSPECDLLEXPORT tng_version_major
6837 (const tng_trajectory_t tng_data,
6842 *version = TNG_VERSION_MAJOR;
6844 return(TNG_SUCCESS);
6847 tng_function_status DECLSPECDLLEXPORT tng_version_minor
6848 (const tng_trajectory_t tng_data,
6853 *version = TNG_VERSION_MINOR;
6855 return(TNG_SUCCESS);
6858 tng_function_status DECLSPECDLLEXPORT tng_version_patchlevel
6859 (const tng_trajectory_t tng_data,
6864 *patch_level = TNG_VERSION_PATCHLEVEL;
6866 return(TNG_SUCCESS);
6869 tng_function_status DECLSPECDLLEXPORT tng_version
6870 (const tng_trajectory_t tng_data,
6875 TNG_ASSERT(version, "TNG library: version must not be a NULL pointer");
6877 TNG_SNPRINTF(version, max_len, "%s", TNG_VERSION);
6879 return(TNG_SUCCESS);
6882 tng_function_status DECLSPECDLLEXPORT tng_molecule_add
6883 (const tng_trajectory_t tng_data,
6885 tng_molecule_t *molecule)
6889 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
6890 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
6892 /* Set ID to the ID of the last molecule + 1 */
6893 if(tng_data->n_molecules)
6895 id = tng_data->molecules[tng_data->n_molecules-1].id + 1;
6902 return(tng_molecule_w_id_add(tng_data, name, id, molecule));
6905 tng_function_status DECLSPECDLLEXPORT tng_molecule_w_id_add
6906 (const tng_trajectory_t tng_data,
6909 tng_molecule_t *molecule)
6911 tng_molecule_t new_molecules;
6912 int64_t *new_molecule_cnt_list;
6913 tng_function_status stat = TNG_SUCCESS;
6915 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
6916 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
6918 new_molecules = realloc(tng_data->molecules,
6919 sizeof(struct tng_molecule) *
6920 (tng_data->n_molecules + 1));
6924 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
6925 sizeof(struct tng_molecule) * (tng_data->n_molecules + 1),
6926 __FILE__, __LINE__);
6927 free(tng_data->molecules);
6928 tng_data->molecules = 0;
6929 return(TNG_CRITICAL);
6932 new_molecule_cnt_list = realloc(tng_data->molecule_cnt_list,
6934 (tng_data->n_molecules + 1));
6936 if(!new_molecule_cnt_list)
6938 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
6939 sizeof(int64_t) * (tng_data->n_molecules + 1),
6940 __FILE__, __LINE__);
6941 free(tng_data->molecule_cnt_list);
6942 tng_data->molecule_cnt_list = 0;
6943 free(new_molecules);
6944 return(TNG_CRITICAL);
6947 tng_data->molecules = new_molecules;
6948 tng_data->molecule_cnt_list = new_molecule_cnt_list;
6950 *molecule = &new_molecules[tng_data->n_molecules];
6952 tng_molecule_init(tng_data, *molecule);
6953 tng_molecule_name_set(tng_data, *molecule, name);
6955 /* FIXME: Should this be a function argument instead? */
6956 tng_data->molecule_cnt_list[tng_data->n_molecules] = 0;
6958 (*molecule)->id = id;
6960 tng_data->n_molecules++;
6965 tng_function_status DECLSPECDLLEXPORT tng_molecule_existing_add
6966 (const tng_trajectory_t tng_data,
6967 tng_molecule_t *molecule_p)
6969 int64_t *new_molecule_cnt_list, id;
6970 tng_molecule_t new_molecules, molecule;
6972 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
6974 /* Set ID to the ID of the last molecule + 1 */
6975 if(tng_data->n_molecules)
6977 id = tng_data->molecules[tng_data->n_molecules-1].id + 1;
6984 new_molecules = realloc(tng_data->molecules,
6985 sizeof(struct tng_molecule) *
6986 (tng_data->n_molecules + 1));
6990 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
6991 sizeof(struct tng_molecule) * (tng_data->n_molecules + 1),
6992 __FILE__, __LINE__);
6993 free(tng_data->molecules);
6994 tng_data->molecules = 0;
6995 return(TNG_CRITICAL);
6998 new_molecule_cnt_list = realloc(tng_data->molecule_cnt_list,
7000 (tng_data->n_molecules + 1));
7002 if(!new_molecule_cnt_list)
7004 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
7005 sizeof(int64_t) * (tng_data->n_molecules + 1),
7006 __FILE__, __LINE__);
7007 free(tng_data->molecule_cnt_list);
7008 tng_data->molecule_cnt_list = 0;
7009 free(new_molecules);
7010 return(TNG_CRITICAL);
7013 molecule = *molecule_p;
7015 tng_data->molecules = new_molecules;
7016 tng_data->molecule_cnt_list = new_molecule_cnt_list;
7018 new_molecules[tng_data->n_molecules] = *molecule;
7020 tng_data->molecule_cnt_list[tng_data->n_molecules] = 0;
7024 molecule = &new_molecules[tng_data->n_molecules];
7026 *molecule_p = molecule;
7030 tng_data->n_molecules++;
7032 return(TNG_SUCCESS);
7035 tng_function_status tng_molecule_name_get(const tng_trajectory_t tng_data,
7036 const tng_molecule_t molecule,
7041 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
7042 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
7044 strncpy(name, molecule->name, max_len - 1);
7045 name[max_len - 1] = 0;
7047 if(strlen(molecule->name) > (unsigned int)max_len - 1)
7049 return(TNG_FAILURE);
7051 return(TNG_SUCCESS);
7054 tng_function_status DECLSPECDLLEXPORT tng_molecule_name_set
7055 (const tng_trajectory_t tng_data,
7056 const tng_molecule_t molecule,
7057 const char *new_name)
7062 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7063 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
7065 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
7067 /* If the currently stored string length is not enough to store the new
7068 * string it is freed and reallocated. */
7069 if(molecule->name && strlen(molecule->name) < len)
7071 free(molecule->name);
7076 molecule->name = malloc(len);
7079 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
7080 __FILE__, __LINE__);
7081 return(TNG_CRITICAL);
7085 strncpy(molecule->name, new_name, len);
7087 return(TNG_SUCCESS);
7090 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_get
7091 (const tng_trajectory_t tng_data,
7092 const tng_molecule_t molecule,
7095 int64_t i, index = -1;
7097 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7098 TNG_ASSERT(cnt, "TNG library: cnt must not be a NULL pointer.");
7100 for(i = 0; i < tng_data->n_molecules; i++)
7102 if(&tng_data->molecules[i] == molecule)
7110 return(TNG_FAILURE);
7112 *cnt = tng_data->molecule_cnt_list[index];
7114 return(TNG_SUCCESS);
7117 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_set
7118 (const tng_trajectory_t tng_data,
7119 const tng_molecule_t molecule,
7122 int64_t i, old_cnt, index = -1;
7124 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7126 for(i = 0; i < tng_data->n_molecules; i++)
7128 if(&tng_data->molecules[i] == molecule)
7136 fprintf(stderr, "TNG library: Could not find molecule in TNG trajectory. %s: %d\n",
7137 __FILE__, __LINE__);
7138 return(TNG_FAILURE);
7140 if(tng_data->var_num_atoms_flag == TNG_CONSTANT_N_ATOMS)
7142 old_cnt = tng_data->molecule_cnt_list[index];
7143 tng_data->molecule_cnt_list[index] = cnt;
7145 tng_data->n_particles += (cnt-old_cnt) *
7146 tng_data->molecules[index].n_atoms;
7150 old_cnt = tng_data->current_trajectory_frame_set.molecule_cnt_list[index];
7151 tng_data->current_trajectory_frame_set.molecule_cnt_list[index] = cnt;
7153 tng_data->current_trajectory_frame_set.n_particles += (cnt-old_cnt) *
7154 tng_data->molecules[index].n_atoms;
7157 return(TNG_SUCCESS);
7160 tng_function_status DECLSPECDLLEXPORT tng_molecule_find
7161 (const tng_trajectory_t tng_data,
7164 tng_molecule_t *molecule)
7166 int64_t i, n_molecules;
7168 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7169 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7170 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
7172 n_molecules = tng_data->n_molecules;
7174 for(i = n_molecules - 1; i >= 0; i--)
7176 *molecule = &tng_data->molecules[i];
7177 if(name[0] == 0 || strcmp(name, (*molecule)->name) == 0)
7179 if(nr == -1 || nr == (*molecule)->id)
7181 return(TNG_SUCCESS);
7188 return(TNG_FAILURE);
7191 tng_function_status DECLSPECDLLEXPORT tng_molecule_of_index_get
7192 (const tng_trajectory_t tng_data,
7193 const int64_t index,
7194 tng_molecule_t *molecule)
7196 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7197 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
7199 if(index >= tng_data->n_molecules)
7202 return(TNG_FAILURE);
7204 *molecule = &tng_data->molecules[index];
7205 return(TNG_SUCCESS);
7208 tng_function_status DECLSPECDLLEXPORT tng_molecule_system_copy(const tng_trajectory_t tng_data_src,
7209 const tng_trajectory_t tng_data_dest)
7211 tng_molecule_t molecule, molecule_temp;
7212 tng_chain_t chain, chain_temp;
7213 tng_residue_t residue, residue_temp;
7214 tng_atom_t atom, atom_temp;
7215 tng_bond_t bond_temp;
7216 tng_function_status stat;
7217 int64_t i, j, k, l, *list_temp;
7219 TNG_ASSERT(tng_data_src, "TNG library: Trajectory container not properly setup.");
7220 TNG_ASSERT(tng_data_dest, "TNG library: Trajectory container not properly setup.");
7222 for(i = 0; i < tng_data_dest->n_molecules; i++)
7224 molecule = &tng_data_dest->molecules[i];
7225 tng_molecule_destroy(tng_data_dest, molecule);
7228 tng_data_dest->n_molecules = 0;
7229 tng_data_dest->n_particles = 0;
7231 molecule_temp = realloc(tng_data_dest->molecules,
7232 sizeof(struct tng_molecule) * tng_data_src->n_molecules);
7235 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
7236 sizeof(struct tng_molecule) * tng_data_src->n_molecules,
7237 __FILE__, __LINE__);
7238 free(tng_data_dest->molecules);
7239 tng_data_dest->molecules = 0;
7240 return(TNG_CRITICAL);
7242 list_temp = realloc(tng_data_dest->molecule_cnt_list,
7243 sizeof(int64_t) * tng_data_src->n_molecules);
7246 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
7247 sizeof(int64_t) * tng_data_src->n_molecules,
7248 __FILE__, __LINE__);
7249 free(tng_data_dest->molecule_cnt_list);
7250 tng_data_dest->molecule_cnt_list = 0;
7251 free(molecule_temp);
7252 return(TNG_CRITICAL);
7255 tng_data_dest->molecules = molecule_temp;
7256 tng_data_dest->molecule_cnt_list = list_temp;
7258 for(i = 0; i < tng_data_src->n_molecules; i++)
7260 molecule = &tng_data_src->molecules[i];
7261 stat = tng_molecule_w_id_add(tng_data_dest, molecule->name, molecule->id,
7263 if(stat != TNG_SUCCESS)
7265 fprintf(stderr, "TNG library: Cannot create new molecule to make a copy. %s: %d\n",
7266 __FILE__, __LINE__);
7269 molecule_temp->quaternary_str = molecule->quaternary_str;
7270 for(j = 0; j < molecule->n_chains; j++)
7272 chain = &molecule->chains[j];
7273 stat = tng_molecule_chain_w_id_add(tng_data_dest, molecule_temp,
7274 chain->name, chain->id,
7276 if(stat != TNG_SUCCESS)
7278 fprintf(stderr, "TNG library: Cannot create new chain to make a copy. %s: %d\n",
7279 __FILE__, __LINE__);
7282 for(k = 0; k < chain->n_residues; k++)
7284 residue = &chain->residues[k];
7285 stat = tng_chain_residue_w_id_add(tng_data_dest, chain_temp,
7286 residue->name, residue->id,
7288 if(stat != TNG_SUCCESS)
7290 fprintf(stderr, "TNG library: Cannot create new residue to make a copy. %s: %d\n",
7291 __FILE__, __LINE__);
7294 for(l = 0; l < residue->n_atoms; l++)
7296 atom = &molecule->atoms[residue->atoms_offset + l];
7297 stat = tng_residue_atom_w_id_add(tng_data_dest, residue_temp,
7298 atom->name, atom->atom_type,
7299 atom->id, &atom_temp);
7300 if(stat != TNG_SUCCESS)
7302 fprintf(stderr, "TNG library: Cannot create new atom to make a copy. %s: %d\n",
7303 __FILE__, __LINE__);
7309 molecule_temp->n_bonds = molecule->n_bonds;
7310 if(molecule->n_bonds > 0)
7312 bond_temp = realloc(molecule_temp->bonds, sizeof(struct tng_bond) *
7316 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
7317 sizeof(struct tng_bond) * molecule->n_bonds,
7318 __FILE__, __LINE__);
7319 free(molecule_temp->bonds);
7320 molecule_temp->n_bonds = 0;
7321 return(TNG_CRITICAL);
7323 molecule_temp->bonds = bond_temp;
7324 for(j = 0; j < molecule->n_bonds; j++)
7326 molecule_temp->bonds[j] = molecule->bonds[j];
7329 stat = tng_molecule_cnt_set(tng_data_dest, molecule_temp,
7330 tng_data_src->molecule_cnt_list[i]);
7331 if(stat != TNG_SUCCESS)
7333 fprintf(stderr, "TNG library: Cannot set molecule count. %s: %d.\n",
7334 __FILE__, __LINE__);
7338 return(TNG_SUCCESS);
7341 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_chains_get
7342 (const tng_trajectory_t tng_data,
7343 const tng_molecule_t molecule,
7347 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
7348 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
7350 *n = molecule->n_chains;
7352 return(TNG_SUCCESS);
7355 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_of_index_get
7356 (const tng_trajectory_t tng_data,
7357 const tng_molecule_t molecule,
7358 const int64_t index,
7362 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
7363 TNG_ASSERT(chain, "TNG library: chain must not be a NULL pointer.");
7365 if(index >= molecule->n_chains)
7368 return(TNG_FAILURE);
7370 *chain = &molecule->chains[index];
7371 return(TNG_SUCCESS);
7374 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_residues_get
7375 (const tng_trajectory_t tng_data,
7376 const tng_molecule_t molecule,
7380 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
7381 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
7383 *n = molecule->n_residues;
7385 return(TNG_SUCCESS);
7388 tng_function_status DECLSPECDLLEXPORT tng_molecule_residue_of_index_get
7389 (const tng_trajectory_t tng_data,
7390 const tng_molecule_t molecule,
7391 const int64_t index,
7392 tng_residue_t *residue)
7395 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
7396 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
7398 if(index >= molecule->n_residues)
7401 return(TNG_FAILURE);
7403 *residue = &molecule->residues[index];
7404 return(TNG_SUCCESS);
7407 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_atoms_get
7408 (const tng_trajectory_t tng_data,
7409 const tng_molecule_t molecule,
7413 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
7414 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
7416 *n = molecule->n_atoms;
7418 return(TNG_SUCCESS);
7421 tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_of_index_get
7422 (const tng_trajectory_t tng_data,
7423 const tng_molecule_t molecule,
7424 const int64_t index,
7428 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
7429 TNG_ASSERT(atom, "TNG library: atom must not be a NULL pointer.");
7431 if(index >= molecule->n_atoms)
7434 return(TNG_FAILURE);
7436 *atom = &molecule->atoms[index];
7437 return(TNG_SUCCESS);
7440 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_find
7441 (const tng_trajectory_t tng_data,
7442 const tng_molecule_t molecule,
7447 int64_t i, n_chains;
7450 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7451 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7453 n_chains = molecule->n_chains;
7455 for(i = n_chains - 1; i >= 0; i--)
7457 *chain = &molecule->chains[i];
7458 if(name[0] == 0 || strcmp(name, (*chain)->name) == 0)
7460 if(nr == -1 || nr == (*chain)->id)
7462 return(TNG_SUCCESS);
7469 return(TNG_FAILURE);
7472 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_add
7473 (const tng_trajectory_t tng_data,
7474 const tng_molecule_t molecule,
7480 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7481 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7483 /* Set ID to the ID of the last chain + 1 */
7484 if(molecule->n_chains)
7486 id = molecule->chains[molecule->n_chains-1].id + 1;
7493 return(tng_molecule_chain_w_id_add(tng_data, molecule, name,
7497 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_w_id_add
7498 (const tng_trajectory_t tng_data,
7499 const tng_molecule_t molecule,
7504 tng_chain_t new_chains;
7505 tng_function_status stat = TNG_SUCCESS;
7507 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7508 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7510 new_chains = realloc(molecule->chains,
7511 sizeof(struct tng_chain) *
7512 (molecule->n_chains + 1));
7516 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
7517 sizeof(struct tng_chain) * (molecule->n_chains + 1),
7518 __FILE__, __LINE__);
7519 free(molecule->chains);
7520 molecule->chains = 0;
7521 return(TNG_CRITICAL);
7524 molecule->chains = new_chains;
7526 *chain = &new_chains[molecule->n_chains];
7529 tng_chain_name_set(tng_data, *chain, name);
7531 (*chain)->molecule = molecule;
7532 (*chain)->n_residues = 0;
7534 molecule->n_chains++;
7541 tng_function_status DECLSPECDLLEXPORT tng_molecule_bond_add
7542 (const tng_trajectory_t tng_data,
7543 const tng_molecule_t molecule,
7544 const int64_t from_atom_id,
7545 const int64_t to_atom_id,
7548 tng_bond_t new_bonds;
7551 new_bonds = realloc(molecule->bonds,
7552 sizeof(struct tng_bond) *
7553 (molecule->n_bonds + 1));
7557 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
7558 sizeof(struct tng_bond) * (molecule->n_bonds + 1),
7559 __FILE__, __LINE__);
7561 free(molecule->bonds);
7562 molecule->bonds = 0;
7563 return(TNG_CRITICAL);
7566 molecule->bonds = new_bonds;
7568 *bond = &new_bonds[molecule->n_bonds];
7570 (*bond)->from_atom_id = from_atom_id;
7571 (*bond)->to_atom_id = to_atom_id;
7573 molecule->n_bonds++;
7575 return(TNG_SUCCESS);
7578 tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_find
7579 (const tng_trajectory_t tng_data,
7580 const tng_molecule_t molecule,
7588 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7590 n_atoms = molecule->n_atoms;
7592 for(i = n_atoms - 1; i >= 0; i--)
7594 *atom = &molecule->atoms[i];
7595 if(name[0] == 0 || strcmp(name, (*atom)->name) == 0)
7597 if(id == -1 || id == (*atom)->id)
7599 return(TNG_SUCCESS);
7606 return(TNG_FAILURE);
7609 tng_function_status tng_chain_name_get(const tng_trajectory_t tng_data,
7610 const tng_chain_t chain,
7615 TNG_ASSERT(chain, "TNG library: chain must not be NULL");
7616 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
7618 strncpy(name, chain->name, max_len - 1);
7619 name[max_len - 1] = 0;
7621 if(strlen(chain->name) > (unsigned int)max_len - 1)
7623 return(TNG_FAILURE);
7625 return(TNG_SUCCESS);
7628 tng_function_status DECLSPECDLLEXPORT tng_chain_name_set
7629 (const tng_trajectory_t tng_data,
7630 const tng_chain_t chain,
7631 const char *new_name)
7636 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
7638 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
7640 /* If the currently stored string length is not enough to store the new
7641 * string it is freed and reallocated. */
7642 if(chain->name && strlen(chain->name) < len)
7649 chain->name = malloc(len);
7652 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
7653 __FILE__, __LINE__);
7654 return(TNG_CRITICAL);
7658 strncpy(chain->name, new_name, len);
7660 return(TNG_SUCCESS);
7663 tng_function_status DECLSPECDLLEXPORT tng_chain_num_residues_get
7664 (const tng_trajectory_t tng_data,
7665 const tng_chain_t chain,
7669 TNG_ASSERT(chain, "TNG library: chain must not be NULL");
7670 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
7672 *n = chain->n_residues;
7674 return(TNG_SUCCESS);
7677 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_of_index_get
7678 (const tng_trajectory_t tng_data,
7679 const tng_chain_t chain,
7680 const int64_t index,
7681 tng_residue_t *residue)
7684 TNG_ASSERT(chain, "TNG library: chain must not be a NULL pointer.");
7685 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
7687 if(index >= chain->n_residues)
7690 return(TNG_FAILURE);
7692 *residue = &chain->residues[index];
7693 return(TNG_SUCCESS);
7696 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_find
7697 (const tng_trajectory_t tng_data,
7698 const tng_chain_t chain,
7701 tng_residue_t *residue)
7703 int64_t i, n_residues;
7706 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7708 n_residues = chain->n_residues;
7710 for(i = n_residues - 1; i >= 0; i--)
7712 *residue = &chain->residues[i];
7713 if(name[0] == 0 || strcmp(name, (*residue)->name) == 0)
7715 if(id == -1 || id == (*residue)->id)
7717 return(TNG_SUCCESS);
7724 return(TNG_FAILURE);
7727 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_add
7728 (const tng_trajectory_t tng_data,
7729 const tng_chain_t chain,
7731 tng_residue_t *residue)
7735 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7736 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7738 /* Set ID to the ID of the last residue + 1 */
7739 if(chain->n_residues)
7741 id = chain->residues[chain->n_residues-1].id + 1;
7748 return(tng_chain_residue_w_id_add(tng_data, chain, name,
7752 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_w_id_add
7753 (const tng_trajectory_t tng_data,
7754 const tng_chain_t chain,
7757 tng_residue_t *residue)
7760 tng_residue_t new_residues, temp_residue, last_residue;
7761 tng_molecule_t molecule = chain->molecule;
7762 tng_function_status stat = TNG_SUCCESS;
7764 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7765 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7767 if(chain->n_residues)
7769 curr_index = chain->residues - molecule->residues;
7776 new_residues = realloc(molecule->residues,
7777 sizeof(struct tng_residue) *
7778 (molecule->n_residues + 1));
7782 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
7783 sizeof(struct tng_residue) * (molecule->n_residues + 1),
7784 __FILE__, __LINE__);
7785 free(molecule->residues);
7786 molecule->residues = 0;
7787 return(TNG_CRITICAL);
7790 molecule->residues = new_residues;
7792 if(curr_index != -1)
7794 chain->residues = new_residues + curr_index;
7795 if(molecule->n_residues)
7797 last_residue = &new_residues[molecule->n_residues - 1];
7799 temp_residue = chain->residues + (chain->n_residues - 1);
7800 /* Make space in list of residues to add the new residues together with the other
7801 * residues of this chain */
7802 if(temp_residue != last_residue)
7805 memmove(temp_residue + 1, temp_residue,
7806 last_residue - temp_residue);
7812 curr_index = molecule->n_residues;
7815 *residue = &molecule->residues[curr_index + chain->n_residues];
7817 if(!chain->n_residues)
7819 chain->residues = *residue;
7823 chain->residues = &molecule->residues[curr_index];
7826 (*residue)->name = 0;
7827 tng_residue_name_set(tng_data, *residue, name);
7829 (*residue)->chain = chain;
7830 (*residue)->n_atoms = 0;
7831 (*residue)->atoms_offset = 0;
7833 chain->n_residues++;
7834 molecule->n_residues++;
7836 (*residue)->id = id;
7841 tng_function_status tng_residue_name_get(const tng_trajectory_t tng_data,
7842 const tng_residue_t residue,
7847 TNG_ASSERT(residue, "TNG library: residue must not be NULL");
7848 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
7850 strncpy(name, residue->name, max_len - 1);
7851 name[max_len - 1] = 0;
7853 if(strlen(residue->name) > (unsigned int)max_len - 1)
7855 return(TNG_FAILURE);
7857 return(TNG_SUCCESS);
7860 tng_function_status DECLSPECDLLEXPORT tng_residue_name_set(const tng_trajectory_t tng_data,
7861 const tng_residue_t residue,
7862 const char *new_name)
7867 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7868 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
7870 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
7872 /* If the currently stored string length is not enough to store the new
7873 * string it is freed and reallocated. */
7874 if(residue->name && strlen(residue->name) < len)
7876 free(residue->name);
7881 residue->name = malloc(len);
7884 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
7885 __FILE__, __LINE__);
7886 return(TNG_CRITICAL);
7890 strncpy(residue->name, new_name, len);
7892 return(TNG_SUCCESS);
7895 tng_function_status DECLSPECDLLEXPORT tng_residue_num_atoms_get
7896 (const tng_trajectory_t tng_data,
7897 const tng_residue_t residue,
7901 TNG_ASSERT(residue, "TNG library: residue must not be NULL");
7902 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
7904 *n = residue->n_atoms;
7906 return(TNG_SUCCESS);
7909 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_of_index_get
7910 (const tng_trajectory_t tng_data,
7911 const tng_residue_t residue,
7912 const int64_t index,
7916 tng_molecule_t molecule;
7919 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
7920 TNG_ASSERT(atom, "TNG library: atom must not be a NULL pointer.");
7922 if(index >= residue->n_atoms)
7925 return(TNG_FAILURE);
7927 chain = residue->chain;
7928 molecule = chain->molecule;
7930 if(index + residue->atoms_offset >= molecule->n_atoms)
7933 return(TNG_FAILURE);
7936 *atom = &molecule->atoms[residue->atoms_offset + index];
7937 return(TNG_SUCCESS);
7940 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_add
7941 (const tng_trajectory_t tng_data,
7942 const tng_residue_t residue,
7943 const char *atom_name,
7944 const char *atom_type,
7949 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7950 TNG_ASSERT(atom_name, "TNG library: atom_name must not be a NULL pointer.");
7951 TNG_ASSERT(atom_type, "TNG library: atom_type must not be a NULL pointer.");
7953 /* Set ID to the ID of the last atom + 1 */
7954 if(residue->chain->molecule->n_atoms)
7956 id = residue->chain->molecule->atoms[residue->chain->molecule->n_atoms-1].id + 1;
7963 return(tng_residue_atom_w_id_add(tng_data, residue, atom_name, atom_type,
7967 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_w_id_add
7968 (const tng_trajectory_t tng_data,
7969 const tng_residue_t residue,
7970 const char *atom_name,
7971 const char *atom_type,
7975 tng_atom_t new_atoms;
7976 tng_molecule_t molecule = residue->chain->molecule;
7977 tng_function_status stat = TNG_SUCCESS;
7979 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7980 TNG_ASSERT(atom_name, "TNG library: atom_name must not be a NULL pointer.");
7981 TNG_ASSERT(atom_type, "TNG library: atom_type must not be a NULL pointer.");
7983 if(!residue->n_atoms)
7985 residue->atoms_offset = molecule->n_atoms;
7988 new_atoms = realloc(molecule->atoms,
7989 sizeof(struct tng_atom) *
7990 (molecule->n_atoms + 1));
7994 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
7995 sizeof(struct tng_atom) * (molecule->n_atoms + 1),
7996 __FILE__, __LINE__);
7997 free(molecule->atoms);
7998 molecule->atoms = 0;
7999 return(TNG_CRITICAL);
8002 molecule->atoms = new_atoms;
8004 *atom = &new_atoms[molecule->n_atoms];
8006 tng_atom_init(*atom);
8007 tng_atom_name_set(tng_data, *atom, atom_name);
8008 tng_atom_type_set(tng_data, *atom, atom_type);
8010 (*atom)->residue = residue;
8013 molecule->n_atoms++;
8020 tng_function_status DECLSPECDLLEXPORT tng_molecule_alloc(const tng_trajectory_t tng_data,
8021 tng_molecule_t *molecule_p)
8023 *molecule_p = malloc(sizeof(struct tng_molecule));
8026 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
8027 sizeof(struct tng_molecule), __FILE__, __LINE__);
8028 return(TNG_CRITICAL);
8031 tng_molecule_init(tng_data, *molecule_p);
8033 return(TNG_SUCCESS);
8036 tng_function_status DECLSPECDLLEXPORT tng_molecule_free(const tng_trajectory_t tng_data,
8037 tng_molecule_t *molecule_p)
8041 return(TNG_SUCCESS);
8044 tng_molecule_destroy(tng_data, *molecule_p);
8049 return(TNG_SUCCESS);
8052 tng_function_status DECLSPECDLLEXPORT tng_molecule_init(const tng_trajectory_t tng_data,
8053 const tng_molecule_t molecule)
8056 molecule->quaternary_str = 1;
8058 molecule->n_chains = 0;
8059 molecule->chains = 0;
8060 molecule->n_residues = 0;
8061 molecule->residues = 0;
8062 molecule->n_atoms = 0;
8063 molecule->atoms = 0;
8064 molecule->n_bonds = 0;
8065 molecule->bonds = 0;
8067 return(TNG_SUCCESS);
8070 tng_function_status DECLSPECDLLEXPORT tng_molecule_destroy(const tng_trajectory_t tng_data,
8071 const tng_molecule_t molecule)
8078 free(molecule->name);
8082 if(molecule->chains)
8084 for(i = 0; i < molecule->n_chains; i++)
8086 if(molecule->chains[i].name)
8088 free(molecule->chains[i].name);
8089 molecule->chains[i].name = 0;
8092 free(molecule->chains);
8093 molecule->chains = 0;
8095 molecule->n_chains = 0;
8097 if(molecule->residues)
8099 for(i = 0; i < molecule->n_residues; i++)
8101 if(molecule->residues[i].name)
8103 free(molecule->residues[i].name);
8104 molecule->residues[i].name = 0;
8107 free(molecule->residues);
8108 molecule->residues = 0;
8110 molecule->n_residues = 0;
8114 for(i = 0; i < molecule->n_atoms; i++)
8116 tng_atom_destroy(&molecule->atoms[i]);
8118 free(molecule->atoms);
8119 molecule->atoms = 0;
8121 molecule->n_atoms = 0;
8125 free(molecule->bonds);
8126 molecule->bonds = 0;
8128 molecule->n_bonds = 0;
8130 return(TNG_SUCCESS);
8133 tng_function_status DECLSPECDLLEXPORT tng_molecule_name_of_particle_nr_get
8134 (const tng_trajectory_t tng_data,
8139 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8141 tng_bool found = TNG_FALSE;
8143 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8144 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8146 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8148 if(!molecule_cnt_list)
8150 return(TNG_FAILURE);
8153 for(i = 0; i < tng_data->n_molecules; i++)
8155 mol = &tng_data->molecules[i];
8156 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8158 cnt += mol->n_atoms * molecule_cnt_list[i];
8166 return(TNG_FAILURE);
8169 strncpy(name, mol->name, max_len - 1);
8170 name[max_len - 1] = 0;
8172 if(strlen(mol->name) > (unsigned int)max_len - 1)
8174 return(TNG_FAILURE);
8176 return(TNG_SUCCESS);
8179 tng_function_status DECLSPECDLLEXPORT tng_molecule_id_of_particle_nr_get
8180 (const tng_trajectory_t tng_data,
8184 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8186 tng_bool found = TNG_FALSE;
8188 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8189 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
8191 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8193 if(!molecule_cnt_list)
8195 return(TNG_FAILURE);
8198 for(i = 0; i < tng_data->n_molecules; i++)
8200 mol = &tng_data->molecules[i];
8201 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8203 cnt += mol->n_atoms * molecule_cnt_list[i];
8211 return(TNG_FAILURE);
8216 return(TNG_SUCCESS);
8219 tng_function_status DECLSPECDLLEXPORT tng_molsystem_bonds_get
8220 (const tng_trajectory_t tng_data,
8222 int64_t **from_atoms,
8225 int64_t atom_cnt = 0, cnt, mol_cnt, i, j, k;
8226 int64_t from_atom, to_atom, *molecule_cnt_list = 0;
8230 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8231 TNG_ASSERT(n_bonds, "TNG library: n_bonds must not be a NULL pointer.");
8232 TNG_ASSERT(from_atoms, "TNG library: from_atoms must not be a NULL pointer.");
8233 TNG_ASSERT(to_atoms, "TNG library: to_atoms must not be a NULL pointer.");
8235 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8237 if(!molecule_cnt_list)
8239 return(TNG_FAILURE);
8243 /* First count the total number of bonds to allocate memory */
8244 for(i = 0; i < tng_data->n_molecules; i++)
8246 mol = &tng_data->molecules[i];
8247 mol_cnt = molecule_cnt_list[i];
8248 *n_bonds += mol_cnt * mol->n_bonds;
8252 return(TNG_SUCCESS);
8255 *from_atoms = malloc(sizeof(int64_t) * (*n_bonds));
8258 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
8259 sizeof(int64_t) * (*n_bonds), __FILE__, __LINE__);
8260 return(TNG_CRITICAL);
8262 *to_atoms = malloc(sizeof(int64_t) * (*n_bonds));
8265 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
8266 sizeof(int64_t) * (*n_bonds), __FILE__, __LINE__);
8269 return(TNG_CRITICAL);
8273 for(i = 0; i < tng_data->n_molecules; i++)
8275 mol = &tng_data->molecules[i];
8276 mol_cnt = molecule_cnt_list[i];
8277 for(j = 0; j < mol_cnt; j++)
8279 for(k = 0; k < mol->n_bonds; k++)
8281 bond = &mol->bonds[k];
8282 from_atom = atom_cnt + bond->from_atom_id;
8283 to_atom = atom_cnt + bond->to_atom_id;
8284 (*from_atoms)[cnt] = from_atom;
8285 (*to_atoms)[cnt++] = to_atom;
8287 atom_cnt += mol->n_atoms;
8291 return(TNG_SUCCESS);
8294 tng_function_status DECLSPECDLLEXPORT tng_chain_name_of_particle_nr_get
8295 (const tng_trajectory_t tng_data,
8300 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8303 tng_bool found = TNG_FALSE;
8305 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8306 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8308 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8310 if(!molecule_cnt_list)
8312 return(TNG_FAILURE);
8315 for(i = 0; i < tng_data->n_molecules; i++)
8317 mol = &tng_data->molecules[i];
8318 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8320 cnt += mol->n_atoms * molecule_cnt_list[i];
8323 atom = &mol->atoms[nr % mol->n_atoms];
8329 return(TNG_FAILURE);
8331 if(!atom->residue || !atom->residue->chain)
8333 return(TNG_FAILURE);
8336 strncpy(name, atom->residue->chain->name, max_len - 1);
8337 name[max_len - 1] = 0;
8339 if(strlen(atom->residue->chain->name) > (unsigned int)max_len - 1)
8341 return(TNG_FAILURE);
8343 return(TNG_SUCCESS);
8346 tng_function_status DECLSPECDLLEXPORT tng_residue_name_of_particle_nr_get
8347 (const tng_trajectory_t tng_data,
8352 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8355 tng_bool found = TNG_FALSE;
8357 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8358 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8360 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8362 if(!molecule_cnt_list)
8364 return(TNG_FAILURE);
8367 for(i = 0; i < tng_data->n_molecules; i++)
8369 mol = &tng_data->molecules[i];
8370 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8372 cnt += mol->n_atoms * molecule_cnt_list[i];
8375 atom = &mol->atoms[nr % mol->n_atoms];
8381 return(TNG_FAILURE);
8385 return(TNG_FAILURE);
8388 strncpy(name, atom->residue->name, max_len - 1);
8389 name[max_len - 1] = 0;
8391 if(strlen(atom->residue->name) > (unsigned int)max_len - 1)
8393 return(TNG_FAILURE);
8395 return(TNG_SUCCESS);
8398 tng_function_status DECLSPECDLLEXPORT tng_residue_id_of_particle_nr_get
8399 (const tng_trajectory_t tng_data,
8403 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8406 tng_bool found = TNG_FALSE;
8408 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8409 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
8411 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8413 if(!molecule_cnt_list)
8415 return(TNG_FAILURE);
8418 for(i = 0; i < tng_data->n_molecules; i++)
8420 mol = &tng_data->molecules[i];
8421 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8423 cnt += mol->n_atoms * molecule_cnt_list[i];
8426 atom = &mol->atoms[nr % mol->n_atoms];
8432 return(TNG_FAILURE);
8436 return(TNG_FAILURE);
8439 *id = atom->residue->id;
8441 return(TNG_SUCCESS);
8444 tng_function_status DECLSPECDLLEXPORT tng_global_residue_id_of_particle_nr_get
8445 (const tng_trajectory_t tng_data,
8449 int64_t cnt = 0, i, offset = 0, *molecule_cnt_list = 0;
8452 tng_bool found = TNG_FALSE;
8454 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8455 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
8457 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8459 if(!molecule_cnt_list)
8461 return(TNG_FAILURE);
8464 for(i = 0; i < tng_data->n_molecules; i++)
8466 mol = &tng_data->molecules[i];
8467 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8469 cnt += mol->n_atoms * molecule_cnt_list[i];
8470 offset += mol->n_residues * molecule_cnt_list[i];
8473 atom = &mol->atoms[nr % mol->n_atoms];
8479 return(TNG_FAILURE);
8483 return(TNG_FAILURE);
8486 offset += mol->n_residues * ((nr - cnt) / mol->n_atoms);
8488 *id = atom->residue->id + offset;
8490 return(TNG_SUCCESS);
8493 tng_function_status DECLSPECDLLEXPORT tng_atom_name_of_particle_nr_get
8494 (const tng_trajectory_t tng_data,
8499 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8502 tng_bool found = TNG_FALSE;
8504 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8505 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8507 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8509 if(!molecule_cnt_list)
8511 return(TNG_FAILURE);
8514 for(i = 0; i < tng_data->n_molecules; i++)
8516 mol = &tng_data->molecules[i];
8517 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8519 cnt += mol->n_atoms * molecule_cnt_list[i];
8522 atom = &mol->atoms[nr % mol->n_atoms];
8528 return(TNG_FAILURE);
8531 strncpy(name, atom->name, max_len - 1);
8532 name[max_len - 1] = 0;
8534 if(strlen(atom->name) > (unsigned int)max_len - 1)
8536 return(TNG_FAILURE);
8538 return(TNG_SUCCESS);
8541 tng_function_status tng_atom_type_of_particle_nr_get
8542 (const tng_trajectory_t tng_data,
8547 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8550 tng_bool found = TNG_FALSE;
8552 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8553 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
8555 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8557 if(!molecule_cnt_list)
8559 return(TNG_FAILURE);
8562 for(i = 0; i < tng_data->n_molecules; i++)
8564 mol = &tng_data->molecules[i];
8565 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8567 cnt += mol->n_atoms * molecule_cnt_list[i];
8570 atom = &mol->atoms[nr % mol->n_atoms];
8576 return(TNG_FAILURE);
8579 strncpy(type, atom->atom_type, max_len - 1);
8580 type[max_len - 1] = 0;
8582 if(strlen(atom->atom_type) > (unsigned int)max_len - 1)
8584 return(TNG_FAILURE);
8586 return(TNG_SUCCESS);
8589 tng_function_status DECLSPECDLLEXPORT tng_particle_mapping_add
8590 (const tng_trajectory_t tng_data,
8591 const int64_t num_first_particle,
8592 const int64_t n_particles,
8593 const int64_t *mapping_table)
8596 tng_particle_mapping_t mapping;
8597 tng_trajectory_frame_set_t frame_set;
8599 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8601 frame_set = &tng_data->current_trajectory_frame_set;
8603 /* Sanity check of the particle ranges. Split into multiple if
8604 * statements for improved readability */
8605 for(i = 0; i < frame_set->n_mapping_blocks; i++)
8607 mapping = &frame_set->mappings[i];
8608 if(num_first_particle >= mapping->num_first_particle &&
8609 num_first_particle < mapping->num_first_particle +
8610 mapping->n_particles)
8612 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
8613 return(TNG_FAILURE);
8615 if(num_first_particle + n_particles >=
8616 mapping->num_first_particle &&
8617 num_first_particle + n_particles <
8618 mapping->num_first_particle + mapping->n_particles)
8620 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
8621 return(TNG_FAILURE);
8623 if(mapping->num_first_particle >= num_first_particle &&
8624 mapping->num_first_particle < num_first_particle +
8627 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
8628 return(TNG_FAILURE);
8630 if(mapping->num_first_particle + mapping->n_particles >
8631 num_first_particle &&
8632 mapping->num_first_particle + mapping->n_particles <
8633 num_first_particle + n_particles)
8635 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
8636 return(TNG_FAILURE);
8640 frame_set->n_mapping_blocks++;
8642 mapping = realloc(frame_set->mappings, sizeof(struct tng_particle_mapping) *
8643 frame_set->n_mapping_blocks);
8647 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
8648 sizeof(struct tng_particle_mapping)*frame_set->n_mapping_blocks,
8649 __FILE__, __LINE__);
8650 free(frame_set->mappings);
8651 frame_set->mappings = 0;
8652 return(TNG_CRITICAL);
8654 frame_set->mappings = mapping;
8656 frame_set->mappings[frame_set->n_mapping_blocks - 1].num_first_particle = num_first_particle;
8657 frame_set->mappings[frame_set->n_mapping_blocks - 1].n_particles = n_particles;
8659 frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers = malloc(sizeof(int64_t) * n_particles);
8660 if(!frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers)
8662 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
8663 sizeof(int64_t) * n_particles, __FILE__, __LINE__);
8664 return(TNG_CRITICAL);
8667 for(i=0; i<n_particles; i++)
8669 frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers[i] = mapping_table[i];
8672 return(TNG_SUCCESS);
8675 tng_function_status DECLSPECDLLEXPORT tng_frame_set_particle_mapping_free(const tng_trajectory_t tng_data)
8677 tng_trajectory_frame_set_t frame_set;
8678 tng_particle_mapping_t mapping;
8681 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8683 frame_set = &tng_data->current_trajectory_frame_set;
8685 if(frame_set->n_mapping_blocks && frame_set->mappings)
8687 for(i = 0; i < frame_set->n_mapping_blocks; i++)
8689 mapping = &frame_set->mappings[i];
8690 if(mapping->real_particle_numbers)
8692 free(mapping->real_particle_numbers);
8693 mapping->real_particle_numbers = 0;
8696 free(frame_set->mappings);
8697 frame_set->mappings = 0;
8698 frame_set->n_mapping_blocks = 0;
8701 return(TNG_SUCCESS);
8704 tng_function_status DECLSPECDLLEXPORT tng_trajectory_init(tng_trajectory_t *tng_data_p)
8707 tng_trajectory_frame_set_t frame_set;
8708 tng_trajectory_t tng_data;
8710 *tng_data_p = malloc(sizeof(struct tng_trajectory));
8713 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
8714 sizeof(struct tng_trajectory), __FILE__, __LINE__);
8715 return(TNG_CRITICAL);
8718 tng_data = *tng_data_p;
8720 frame_set = &tng_data->current_trajectory_frame_set;
8722 tng_data->input_file_path = 0;
8723 tng_data->input_file = 0;
8724 tng_data->input_file_len = 0;
8725 tng_data->output_file_path = 0;
8726 tng_data->output_file = 0;
8728 tng_data->first_program_name = 0;
8729 tng_data->first_user_name = 0;
8730 tng_data->first_computer_name = 0;
8731 tng_data->first_pgp_signature = 0;
8732 tng_data->last_program_name = 0;
8733 tng_data->last_user_name = 0;
8734 tng_data->last_computer_name = 0;
8735 tng_data->last_pgp_signature = 0;
8736 tng_data->forcefield_name = 0;
8741 fprintf(stderr, "TNG library: Cannot get time. %s: %d\n", __FILE__, __LINE__);
8745 tng_data->time = seconds;
8748 tng_data->var_num_atoms_flag = TNG_CONSTANT_N_ATOMS;
8749 tng_data->first_trajectory_frame_set_input_file_pos = -1;
8750 tng_data->last_trajectory_frame_set_input_file_pos = -1;
8751 tng_data->current_trajectory_frame_set_input_file_pos = -1;
8752 tng_data->first_trajectory_frame_set_output_file_pos = -1;
8753 tng_data->last_trajectory_frame_set_output_file_pos = -1;
8754 tng_data->current_trajectory_frame_set_output_file_pos = -1;
8755 tng_data->frame_set_n_frames = 100;
8756 tng_data->n_trajectory_frame_sets = 0;
8757 tng_data->medium_stride_length = 100;
8758 tng_data->long_stride_length = 10000;
8760 tng_data->time_per_frame = -1;
8762 tng_data->n_particle_data_blocks = 0;
8763 tng_data->n_data_blocks = 0;
8765 tng_data->non_tr_particle_data = 0;
8766 tng_data->non_tr_data = 0;
8768 tng_data->compress_algo_pos = 0;
8769 tng_data->compress_algo_vel = 0;
8770 tng_data->compression_precision = 1000;
8771 tng_data->distance_unit_exponential = -9;
8773 frame_set->first_frame = -1;
8774 frame_set->n_mapping_blocks = 0;
8775 frame_set->mappings = 0;
8776 frame_set->molecule_cnt_list = 0;
8778 frame_set->n_particle_data_blocks = 0;
8779 frame_set->n_data_blocks = 0;
8781 frame_set->tr_particle_data = 0;
8782 frame_set->tr_data = 0;
8784 frame_set->n_written_frames = 0;
8785 frame_set->n_unwritten_frames = 0;
8787 frame_set->next_frame_set_file_pos = -1;
8788 frame_set->prev_frame_set_file_pos = -1;
8789 frame_set->medium_stride_next_frame_set_file_pos = -1;
8790 frame_set->medium_stride_prev_frame_set_file_pos = -1;
8791 frame_set->long_stride_next_frame_set_file_pos = -1;
8792 frame_set->long_stride_prev_frame_set_file_pos = -1;
8794 frame_set->first_frame_time = -1;
8796 tng_data->n_molecules = 0;
8797 tng_data->molecules = 0;
8798 tng_data->molecule_cnt_list = 0;
8799 tng_data->n_particles = 0;
8802 /* Check the endianness of the computer */
8803 static int32_t endianness_32 = 0x01234567;
8805 if ( *(const unsigned char*)&endianness_32 == 0x01 )
8807 tng_data->endianness_32 = TNG_BIG_ENDIAN_32;
8811 else if( *(const unsigned char*)&endianness_32 == 0x67 )
8813 tng_data->endianness_32 = TNG_LITTLE_ENDIAN_32;
8818 else if ( *(const unsigned char*)&endianness_32 == 0x45 )
8820 tng_data->endianness_32 = TNG_BYTE_PAIR_SWAP_32;
8824 static int64_t endianness_64 = 0x0123456789ABCDEFLL;
8825 /* 0x0123456789ABCDEF */
8826 if ( *(const unsigned char*)&endianness_64 == 0x01 )
8828 tng_data->endianness_64 = TNG_BIG_ENDIAN_64;
8831 /* 0xEFCDAB8967452301 */
8832 else if ( *(const unsigned char*)&endianness_64 == 0xEF )
8834 tng_data->endianness_64 = TNG_LITTLE_ENDIAN_64;
8837 /* 0x89ABCDEF01234567 */
8838 else if ( *(const unsigned char*)&endianness_64 == 0x89 )
8840 tng_data->endianness_64 = TNG_QUAD_SWAP_64;
8843 /* 0x45670123CDEF89AB */
8844 else if ( *(const unsigned char*)&endianness_64 == 0x45 )
8846 tng_data->endianness_64 = TNG_BYTE_PAIR_SWAP_64;
8849 /* 0x23016745AB89EFCD */
8850 else if ( *(const unsigned char*)&endianness_64 == 0x23 )
8852 tng_data->endianness_64 = TNG_BYTE_SWAP_64;
8856 /* By default do not swap the byte order, i.e. keep the byte order of the
8857 * architecture. The input file endianness will be set when reading the
8858 * header. The output endianness can be changed - before the file is
8860 tng_data->input_endianness_swap_func_32 = 0;
8861 tng_data->input_endianness_swap_func_64 = 0;
8862 tng_data->output_endianness_swap_func_32 = 0;
8863 tng_data->output_endianness_swap_func_64 = 0;
8865 tng_data->current_trajectory_frame_set.next_frame_set_file_pos = -1;
8866 tng_data->current_trajectory_frame_set.prev_frame_set_file_pos = -1;
8867 tng_data->current_trajectory_frame_set.n_frames = 0;
8869 return(TNG_SUCCESS);
8872 tng_function_status DECLSPECDLLEXPORT tng_trajectory_destroy(tng_trajectory_t *tng_data_p)
8875 int64_t n_particles, n_values_per_frame;
8876 tng_trajectory_t tng_data = *tng_data_p;
8877 tng_trajectory_frame_set_t frame_set;
8881 return(TNG_SUCCESS);
8884 frame_set = &tng_data->current_trajectory_frame_set;
8886 if(tng_data->input_file)
8888 if(tng_data->output_file == tng_data->input_file)
8890 tng_frame_set_finalize(tng_data, TNG_USE_HASH);
8891 tng_data->output_file = 0;
8893 fclose(tng_data->input_file);
8894 tng_data->input_file = 0;
8897 if(tng_data->input_file_path)
8899 free(tng_data->input_file_path);
8900 tng_data->input_file_path = 0;
8903 if(tng_data->output_file)
8905 /* FIXME: Do not always write the hash */
8906 tng_frame_set_finalize(tng_data, TNG_USE_HASH);
8907 fclose(tng_data->output_file);
8908 tng_data->output_file = 0;
8911 if(tng_data->output_file_path)
8913 free(tng_data->output_file_path);
8914 tng_data->output_file_path = 0;
8917 if(tng_data->first_program_name)
8919 free(tng_data->first_program_name);
8920 tng_data->first_program_name = 0;
8923 if(tng_data->last_program_name)
8925 free(tng_data->last_program_name);
8926 tng_data->last_program_name = 0;
8929 if(tng_data->first_user_name)
8931 free(tng_data->first_user_name);
8932 tng_data->first_user_name = 0;
8935 if(tng_data->last_user_name)
8937 free(tng_data->last_user_name);
8938 tng_data->last_user_name = 0;
8941 if(tng_data->first_computer_name)
8943 free(tng_data->first_computer_name);
8944 tng_data->first_computer_name = 0;
8947 if(tng_data->last_computer_name)
8949 free(tng_data->last_computer_name);
8950 tng_data->last_computer_name = 0;
8953 if(tng_data->first_pgp_signature)
8955 free(tng_data->first_pgp_signature);
8956 tng_data->first_pgp_signature = 0;
8959 if(tng_data->last_pgp_signature)
8961 free(tng_data->last_pgp_signature);
8962 tng_data->last_pgp_signature = 0;
8965 if(tng_data->forcefield_name)
8967 free(tng_data->forcefield_name);
8968 tng_data->forcefield_name = 0;
8971 tng_frame_set_particle_mapping_free(tng_data);
8973 if(frame_set->molecule_cnt_list)
8975 free(frame_set->molecule_cnt_list);
8976 frame_set->molecule_cnt_list = 0;
8979 if(tng_data->var_num_atoms_flag)
8981 n_particles = frame_set->n_particles;
8985 n_particles = tng_data->n_particles;
8988 if(tng_data->non_tr_particle_data)
8990 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
8992 if(tng_data->non_tr_particle_data[i].values)
8994 free(tng_data->non_tr_particle_data[i].values);
8995 tng_data->non_tr_particle_data[i].values = 0;
8998 if(tng_data->non_tr_particle_data[i].strings)
9000 n_values_per_frame = tng_data->non_tr_particle_data[i].
9002 if(tng_data->non_tr_particle_data[i].strings[0])
9004 for(j = 0; j < n_particles; j++)
9006 if(tng_data->non_tr_particle_data[i].strings[0][j])
9008 for(k = 0; k < n_values_per_frame; k++)
9010 if(tng_data->non_tr_particle_data[i].
9013 free(tng_data->non_tr_particle_data[i].
9015 tng_data->non_tr_particle_data[i].
9016 strings[0][j][k] = 0;
9019 free(tng_data->non_tr_particle_data[i].
9021 tng_data->non_tr_particle_data[i].strings[0][j] = 0;
9024 free(tng_data->non_tr_particle_data[i].strings[0]);
9025 tng_data->non_tr_particle_data[i].strings[0] = 0;
9027 free(tng_data->non_tr_particle_data[i].strings);
9028 tng_data->non_tr_particle_data[i].strings = 0;
9031 if(tng_data->non_tr_particle_data[i].block_name)
9033 free(tng_data->non_tr_particle_data[i].block_name);
9034 tng_data->non_tr_particle_data[i].block_name = 0;
9037 free(tng_data->non_tr_particle_data);
9038 tng_data->non_tr_particle_data = 0;
9041 if(tng_data->non_tr_data)
9043 for(i = 0; i < tng_data->n_data_blocks; i++)
9045 if(tng_data->non_tr_data[i].values)
9047 free(tng_data->non_tr_data[i].values);
9048 tng_data->non_tr_data[i].values = 0;
9051 if(tng_data->non_tr_data[i].strings)
9053 n_values_per_frame = tng_data->non_tr_data[i].
9055 if(tng_data->non_tr_data[i].strings[0][0])
9057 for(j = 0; j < n_values_per_frame; j++)
9059 if(tng_data->non_tr_data[i].strings[0][0][j])
9061 free(tng_data->non_tr_data[i].strings[0][0][j]);
9062 tng_data->non_tr_data[i].strings[0][0][j] = 0;
9065 free(tng_data->non_tr_data[i].strings[0][0]);
9066 tng_data->non_tr_data[i].strings[0][0] = 0;
9068 free(tng_data->non_tr_data[i].strings[0]);
9069 tng_data->non_tr_data[i].strings[0] = 0;
9070 free(tng_data->non_tr_data[i].strings);
9071 tng_data->non_tr_data[i].strings = 0;
9074 if(tng_data->non_tr_data[i].block_name)
9076 free(tng_data->non_tr_data[i].block_name);
9077 tng_data->non_tr_data[i].block_name = 0;
9080 free(tng_data->non_tr_data);
9081 tng_data->non_tr_data = 0;
9084 tng_data->n_particle_data_blocks = 0;
9085 tng_data->n_data_blocks = 0;
9087 if(tng_data->compress_algo_pos)
9089 free(tng_data->compress_algo_pos);
9090 tng_data->compress_algo_pos = 0;
9092 if(tng_data->compress_algo_vel)
9094 free(tng_data->compress_algo_vel);
9095 tng_data->compress_algo_vel = 0;
9098 if(frame_set->tr_particle_data)
9100 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
9102 if(frame_set->tr_particle_data[i].values)
9104 free(frame_set->tr_particle_data[i].values);
9105 frame_set->tr_particle_data[i].values = 0;
9108 if(frame_set->tr_particle_data[i].strings)
9110 n_values_per_frame = frame_set->tr_particle_data[i].
9112 for(j = 0; j < frame_set->tr_particle_data[i].n_frames; j++)
9114 if(frame_set->tr_particle_data[i].strings[j])
9116 for(k = 0; k < n_particles; k++)
9118 if(frame_set->tr_particle_data[i].
9121 for(l = 0; l < n_values_per_frame; l++)
9123 if(frame_set->tr_particle_data[i].
9126 free(frame_set->tr_particle_data[i].
9128 frame_set->tr_particle_data[i].
9129 strings[j][k][l] = 0;
9132 free(frame_set->tr_particle_data[i].
9134 frame_set->tr_particle_data[i].
9138 free(frame_set->tr_particle_data[i].strings[j]);
9139 frame_set->tr_particle_data[i].strings[j] = 0;
9142 free(frame_set->tr_particle_data[i].strings);
9143 frame_set->tr_particle_data[i].strings = 0;
9146 if(frame_set->tr_particle_data[i].block_name)
9148 free(frame_set->tr_particle_data[i].block_name);
9149 frame_set->tr_particle_data[i].block_name = 0;
9152 free(frame_set->tr_particle_data);
9153 frame_set->tr_particle_data = 0;
9156 if(frame_set->tr_data)
9158 for(i = 0; i < frame_set->n_data_blocks; i++)
9160 if(frame_set->tr_data[i].values)
9162 free(frame_set->tr_data[i].values);
9163 frame_set->tr_data[i].values = 0;
9166 if(frame_set->tr_data[i].strings)
9168 n_values_per_frame = frame_set->tr_data[i].
9170 for(j = 0; j < frame_set->tr_data[i].n_frames; j++)
9172 if(frame_set->tr_data[i].strings[j])
9174 for(k = 0; k < n_values_per_frame; k++)
9176 if(frame_set->tr_data[i].strings[j][k])
9178 free(frame_set->tr_data[i].strings[j][k]);
9179 frame_set->tr_data[i].strings[j][k] = 0;
9182 free(frame_set->tr_data[i].strings[j]);
9183 frame_set->tr_data[i].strings[j] = 0;
9186 free(frame_set->tr_data[i].strings);
9187 frame_set->tr_data[i].strings = 0;
9190 if(frame_set->tr_data[i].block_name)
9192 free(frame_set->tr_data[i].block_name);
9193 frame_set->tr_data[i].block_name = 0;
9196 free(frame_set->tr_data);
9197 frame_set->tr_data = 0;
9200 frame_set->n_particle_data_blocks = 0;
9201 frame_set->n_data_blocks = 0;
9203 if(tng_data->molecules)
9205 for(i = 0; i < tng_data->n_molecules; i++)
9207 tng_molecule_destroy(tng_data, &tng_data->molecules[i]);
9209 free(tng_data->molecules);
9210 tng_data->molecules = 0;
9211 tng_data->n_molecules = 0;
9213 if(tng_data->molecule_cnt_list)
9215 free(tng_data->molecule_cnt_list);
9216 tng_data->molecule_cnt_list = 0;
9222 return(TNG_SUCCESS);
9225 tng_function_status DECLSPECDLLEXPORT tng_trajectory_init_from_src
9226 (const tng_trajectory_t src,
9227 tng_trajectory_t *dest_p)
9229 tng_trajectory_frame_set_t frame_set;
9230 tng_trajectory_t dest;
9232 TNG_ASSERT(src != 0, "TNG library: Source trajectory must not be NULL.");
9234 *dest_p = malloc(sizeof(struct tng_trajectory));
9237 fprintf(stderr, "TNG library: Cannot allocate memory (%lu bytes). %s: %d\n",
9238 sizeof(struct tng_trajectory), __FILE__, __LINE__);
9239 return(TNG_CRITICAL);
9244 frame_set = &dest->current_trajectory_frame_set;
9246 if(src->input_file_path)
9248 dest->input_file_path = malloc(strlen(src->input_file_path) + 1);
9249 if(!dest->input_file_path)
9251 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n",
9252 (unsigned int)strlen(src->input_file_path) + 1, __FILE__, __LINE__);
9253 return(TNG_CRITICAL);
9255 strcpy(dest->input_file_path, src->input_file_path);
9256 dest->input_file_len = src->input_file_len;
9260 dest->input_file_path = 0;
9262 dest->input_file = 0;
9263 if(src->output_file_path)
9265 dest->output_file_path = malloc(strlen(src->output_file_path) + 1);
9266 if(!dest->output_file_path)
9268 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n",
9269 (unsigned int)strlen(src->output_file_path) + 1, __FILE__, __LINE__);
9270 return(TNG_CRITICAL);
9272 strcpy(dest->output_file_path, src->output_file_path);
9276 dest->output_file_path = 0;
9278 dest->output_file = 0;
9280 dest->first_program_name = 0;
9281 dest->first_user_name = 0;
9282 dest->first_computer_name = 0;
9283 dest->first_pgp_signature = 0;
9284 dest->last_program_name = 0;
9285 dest->last_user_name = 0;
9286 dest->last_computer_name = 0;
9287 dest->last_pgp_signature = 0;
9288 dest->forcefield_name = 0;
9290 dest->var_num_atoms_flag = src->var_num_atoms_flag;
9291 dest->first_trajectory_frame_set_input_file_pos =
9292 src->first_trajectory_frame_set_input_file_pos;
9293 dest->last_trajectory_frame_set_input_file_pos =
9294 src->last_trajectory_frame_set_input_file_pos;
9295 dest->current_trajectory_frame_set_input_file_pos =
9296 src->current_trajectory_frame_set_input_file_pos;
9297 dest->first_trajectory_frame_set_output_file_pos =
9298 src->first_trajectory_frame_set_output_file_pos;
9299 dest->last_trajectory_frame_set_output_file_pos =
9300 src->last_trajectory_frame_set_output_file_pos;
9301 dest->current_trajectory_frame_set_output_file_pos =
9302 src->current_trajectory_frame_set_output_file_pos;
9303 dest->frame_set_n_frames = src->frame_set_n_frames;
9304 dest->n_trajectory_frame_sets = src->n_trajectory_frame_sets;
9305 dest->medium_stride_length = src->medium_stride_length;
9306 dest->long_stride_length = src->long_stride_length;
9308 dest->time_per_frame = src->time_per_frame;
9310 /* Currently the non trajectory data blocks are not copied since it
9311 * can lead to problems when freeing memory in a parallel block. */
9312 dest->n_particle_data_blocks = 0;
9313 dest->n_data_blocks = 0;
9314 dest->non_tr_particle_data = 0;
9315 dest->non_tr_data = 0;
9317 dest->compress_algo_pos = 0;
9318 dest->compress_algo_vel = 0;
9319 dest->distance_unit_exponential = -9;
9320 dest->compression_precision = 1000;
9322 frame_set->n_mapping_blocks = 0;
9323 frame_set->mappings = 0;
9324 frame_set->molecule_cnt_list = 0;
9326 frame_set->n_particle_data_blocks = 0;
9327 frame_set->n_data_blocks = 0;
9329 frame_set->tr_particle_data = 0;
9330 frame_set->tr_data = 0;
9332 frame_set->n_written_frames = 0;
9333 frame_set->n_unwritten_frames = 0;
9335 frame_set->next_frame_set_file_pos = -1;
9336 frame_set->prev_frame_set_file_pos = -1;
9337 frame_set->medium_stride_next_frame_set_file_pos = -1;
9338 frame_set->medium_stride_prev_frame_set_file_pos = -1;
9339 frame_set->long_stride_next_frame_set_file_pos = -1;
9340 frame_set->long_stride_prev_frame_set_file_pos = -1;
9341 frame_set->first_frame = -1;
9343 dest->n_molecules = 0;
9344 dest->molecules = 0;
9345 dest->molecule_cnt_list = 0;
9346 dest->n_particles = src->n_particles;
9348 dest->endianness_32 = src->endianness_32;
9349 dest->endianness_64 = src->endianness_64;
9350 dest->input_endianness_swap_func_32 = src->input_endianness_swap_func_32;
9351 dest->input_endianness_swap_func_64 = src->input_endianness_swap_func_64;
9352 dest->output_endianness_swap_func_32 = src->output_endianness_swap_func_32;
9353 dest->output_endianness_swap_func_64 = src->output_endianness_swap_func_64;
9355 dest->current_trajectory_frame_set.next_frame_set_file_pos = -1;
9356 dest->current_trajectory_frame_set.prev_frame_set_file_pos = -1;
9357 dest->current_trajectory_frame_set.n_frames = 0;
9359 return(TNG_SUCCESS);
9362 tng_function_status DECLSPECDLLEXPORT tng_input_file_get
9363 (const tng_trajectory_t tng_data,
9367 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9368 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
9370 strncpy(file_name, tng_data->input_file_path, max_len - 1);
9371 file_name[max_len - 1] = 0;
9373 if(strlen(tng_data->input_file_path) > (unsigned int)max_len - 1)
9375 return(TNG_FAILURE);
9377 return(TNG_SUCCESS);
9380 tng_function_status DECLSPECDLLEXPORT tng_input_file_set
9381 (const tng_trajectory_t tng_data,
9382 const char *file_name)
9387 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9388 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
9391 if(tng_data->input_file_path && strcmp(tng_data->input_file_path,
9394 return(TNG_SUCCESS);
9397 if(tng_data->input_file)
9399 fclose(tng_data->input_file);
9402 len = tng_min_size(strlen(file_name) + 1, TNG_MAX_STR_LEN);
9403 temp = realloc(tng_data->input_file_path, len);
9406 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
9407 __FILE__, __LINE__);
9408 free(tng_data->input_file_path);
9409 tng_data->input_file_path = 0;
9410 return(TNG_CRITICAL);
9412 tng_data->input_file_path = temp;
9414 strncpy(tng_data->input_file_path, file_name, len);
9416 return(tng_input_file_init(tng_data));
9419 tng_function_status tng_output_file_get
9420 (const tng_trajectory_t tng_data,
9424 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9425 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
9427 strncpy(file_name, tng_data->output_file_path, max_len - 1);
9428 file_name[max_len - 1] = 0;
9430 if(strlen(tng_data->output_file_path) > (unsigned int)max_len - 1)
9432 return(TNG_FAILURE);
9434 return(TNG_SUCCESS);
9437 tng_function_status DECLSPECDLLEXPORT tng_output_file_set
9438 (const tng_trajectory_t tng_data,
9439 const char *file_name)
9444 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9445 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
9447 if(tng_data->output_file_path &&
9448 strcmp(tng_data->output_file_path, file_name) == 0)
9450 return(TNG_SUCCESS);
9453 if(tng_data->output_file)
9455 fclose(tng_data->output_file);
9458 len = tng_min_size(strlen(file_name) + 1, TNG_MAX_STR_LEN);
9459 temp = realloc(tng_data->output_file_path, len);
9462 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
9463 __FILE__, __LINE__);
9464 free(tng_data->output_file_path);
9465 tng_data->output_file_path = 0;
9466 return(TNG_CRITICAL);
9468 tng_data->output_file_path = temp;
9470 strncpy(tng_data->output_file_path, file_name, len);
9472 return(tng_output_file_init(tng_data));
9475 tng_function_status DECLSPECDLLEXPORT tng_output_append_file_set
9476 (const tng_trajectory_t tng_data,
9477 const char *file_name)
9482 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9483 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
9485 if(tng_data->output_file_path &&
9486 strcmp(tng_data->output_file_path, file_name) == 0)
9488 return(TNG_SUCCESS);
9491 if(tng_data->output_file)
9493 fclose(tng_data->output_file);
9496 len = tng_min_size(strlen(file_name) + 1, TNG_MAX_STR_LEN);
9497 temp = realloc(tng_data->output_file_path, len);
9500 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
9501 __FILE__, __LINE__);
9502 free(tng_data->output_file_path);
9503 tng_data->output_file_path = 0;
9504 return(TNG_CRITICAL);
9506 tng_data->output_file_path = temp;
9508 strncpy(tng_data->output_file_path, file_name, len);
9510 tng_data->output_file = fopen(tng_data->output_file_path, "rb+");
9511 if(!tng_data->output_file)
9513 fprintf(stderr, "TNG library: Cannot open file %s. %s: %d\n",
9514 tng_data->output_file_path, __FILE__, __LINE__);
9515 return(TNG_CRITICAL);
9517 tng_data->input_file = tng_data->output_file;
9519 return(TNG_SUCCESS);
9522 tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_get
9523 (const tng_trajectory_t tng_data, tng_file_endianness *endianness)
9525 tng_endianness_32 end_32;
9526 tng_endianness_64 end_64;
9528 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9529 TNG_ASSERT(endianness, "TNG library: endianness must not be a NULL pointer");
9531 if(tng_data->output_endianness_swap_func_32)
9533 /* If other endianness variants are added they must be added here as well */
9534 if(tng_data->output_endianness_swap_func_32 ==
9535 &tng_swap_byte_order_big_endian_32)
9537 end_32 = TNG_BIG_ENDIAN_32;
9539 else if(tng_data->output_endianness_swap_func_32 ==
9540 &tng_swap_byte_order_little_endian_32)
9542 end_32 = TNG_LITTLE_ENDIAN_32;
9546 return(TNG_FAILURE);
9551 end_32 = (tng_endianness_32)tng_data->endianness_32;
9554 if(tng_data->output_endianness_swap_func_64)
9556 /* If other endianness variants are added they must be added here as well */
9557 if(tng_data->output_endianness_swap_func_64 ==
9558 &tng_swap_byte_order_big_endian_64)
9560 end_64 = TNG_BIG_ENDIAN_64;
9562 else if(tng_data->output_endianness_swap_func_64 ==
9563 &tng_swap_byte_order_little_endian_64)
9565 end_64 = TNG_LITTLE_ENDIAN_64;
9569 return(TNG_FAILURE);
9574 end_64 = (tng_endianness_64)tng_data->endianness_64;
9577 if((int)end_32 != (int)end_64)
9579 return(TNG_FAILURE);
9582 if(end_32 == TNG_LITTLE_ENDIAN_32)
9584 *endianness = TNG_LITTLE_ENDIAN;
9587 else if(end_32 == TNG_BIG_ENDIAN_32)
9589 *endianness = TNG_BIG_ENDIAN;
9593 return(TNG_FAILURE);
9596 return(TNG_SUCCESS);
9599 tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_set
9600 (const tng_trajectory_t tng_data,
9601 const tng_file_endianness endianness)
9603 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9605 /* Tne endianness cannot be changed if the data has already been written
9606 * to the output file. */
9607 if(ftello(tng_data->output_file) > 0)
9609 return(TNG_FAILURE);
9612 if(endianness == TNG_BIG_ENDIAN)
9614 if(tng_data->endianness_32 == TNG_BIG_ENDIAN_32)
9616 tng_data->output_endianness_swap_func_32 = 0;
9620 tng_data->output_endianness_swap_func_32 =
9621 &tng_swap_byte_order_big_endian_32;
9623 if(tng_data->endianness_64 == TNG_BIG_ENDIAN_64)
9625 tng_data->output_endianness_swap_func_64 = 0;
9629 tng_data->output_endianness_swap_func_64 =
9630 &tng_swap_byte_order_big_endian_64;
9632 return(TNG_SUCCESS);
9634 else if(endianness == TNG_LITTLE_ENDIAN)
9636 if(tng_data->endianness_32 == TNG_LITTLE_ENDIAN_32)
9638 tng_data->output_endianness_swap_func_32 = 0;
9642 tng_data->output_endianness_swap_func_32 =
9643 &tng_swap_byte_order_little_endian_32;
9645 if(tng_data->endianness_64 == TNG_LITTLE_ENDIAN_64)
9647 tng_data->output_endianness_swap_func_64 = 0;
9651 tng_data->output_endianness_swap_func_64 =
9652 &tng_swap_byte_order_little_endian_64;
9654 return(TNG_SUCCESS);
9657 /* If the specified endianness is neither big nor little endian return a
9659 return(TNG_FAILURE);
9662 tng_function_status DECLSPECDLLEXPORT tng_first_program_name_get
9663 (const tng_trajectory_t tng_data,
9667 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9668 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
9670 strncpy(name, tng_data->first_program_name, max_len - 1);
9671 name[max_len - 1] = 0;
9673 if(strlen(tng_data->first_program_name) > (unsigned int)max_len - 1)
9675 return(TNG_FAILURE);
9677 return(TNG_SUCCESS);
9680 tng_function_status DECLSPECDLLEXPORT tng_first_program_name_set
9681 (const tng_trajectory_t tng_data,
9682 const char *new_name)
9686 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9687 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
9689 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
9691 if(tng_data->first_program_name && strlen(tng_data->first_program_name) < len)
9693 free(tng_data->first_program_name);
9694 tng_data->first_program_name = 0;
9696 if(!tng_data->first_program_name)
9698 tng_data->first_program_name = malloc(len);
9699 if(!tng_data->first_program_name)
9701 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
9702 __FILE__, __LINE__);
9703 return(TNG_CRITICAL);
9707 strncpy(tng_data->first_program_name, new_name, len);
9709 return(TNG_SUCCESS);
9712 tng_function_status DECLSPECDLLEXPORT tng_last_program_name_get
9713 (const tng_trajectory_t tng_data,
9714 char *name, const int max_len)
9716 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9717 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
9719 strncpy(name, tng_data->last_program_name, max_len - 1);
9720 name[max_len - 1] = 0;
9722 if(strlen(tng_data->last_program_name) > (unsigned int)max_len - 1)
9724 return(TNG_FAILURE);
9726 return(TNG_SUCCESS);
9729 tng_function_status DECLSPECDLLEXPORT tng_last_program_name_set
9730 (const tng_trajectory_t tng_data,
9731 const char *new_name)
9735 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9736 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
9738 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
9740 if(tng_data->last_program_name && strlen(tng_data->last_program_name) < len)
9742 free(tng_data->last_program_name);
9743 tng_data->last_program_name = 0;
9745 if(!tng_data->last_program_name)
9747 tng_data->last_program_name = malloc(len);
9748 if(!tng_data->last_program_name)
9750 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
9751 __FILE__, __LINE__);
9752 return(TNG_CRITICAL);
9756 strncpy(tng_data->last_program_name, new_name, len);
9758 return(TNG_SUCCESS);
9761 tng_function_status DECLSPECDLLEXPORT tng_first_user_name_get
9762 (const tng_trajectory_t tng_data,
9763 char *name, const int max_len)
9765 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9766 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
9768 strncpy(name, tng_data->first_user_name, max_len - 1);
9769 name[max_len - 1] = 0;
9771 if(strlen(tng_data->first_user_name) > (unsigned int)max_len - 1)
9773 return(TNG_FAILURE);
9775 return(TNG_SUCCESS);
9778 tng_function_status DECLSPECDLLEXPORT tng_first_user_name_set
9779 (const tng_trajectory_t tng_data,
9780 const char *new_name)
9784 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9785 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
9787 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
9789 /* If the currently stored string length is not enough to store the new
9790 * string it is freed and reallocated. */
9791 if(tng_data->first_user_name && strlen(tng_data->first_user_name) < len)
9793 free(tng_data->first_user_name);
9794 tng_data->first_user_name = 0;
9796 if(!tng_data->first_user_name)
9798 tng_data->first_user_name = malloc(len);
9799 if(!tng_data->first_user_name)
9801 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
9802 __FILE__, __LINE__);
9803 return(TNG_CRITICAL);
9807 strncpy(tng_data->first_user_name, new_name, len);
9809 return(TNG_SUCCESS);
9812 tng_function_status DECLSPECDLLEXPORT tng_last_user_name_get
9813 (const tng_trajectory_t tng_data,
9814 char *name, const int max_len)
9816 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9817 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
9819 strncpy(name, tng_data->last_user_name, max_len - 1);
9820 name[max_len - 1] = 0;
9822 if(strlen(tng_data->last_user_name) > (unsigned int)max_len - 1)
9824 return(TNG_FAILURE);
9826 return(TNG_SUCCESS);
9829 tng_function_status DECLSPECDLLEXPORT tng_last_user_name_set
9830 (const tng_trajectory_t tng_data,
9831 const char *new_name)
9835 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9836 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
9838 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
9840 /* If the currently stored string length is not enough to store the new
9841 * string it is freed and reallocated. */
9842 if(tng_data->last_user_name && strlen(tng_data->last_user_name) < len)
9844 free(tng_data->last_user_name);
9845 tng_data->last_user_name = 0;
9847 if(!tng_data->last_user_name)
9849 tng_data->last_user_name = malloc(len);
9850 if(!tng_data->last_user_name)
9852 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
9853 __FILE__, __LINE__);
9854 return(TNG_CRITICAL);
9858 strncpy(tng_data->last_user_name, new_name, len);
9860 return(TNG_SUCCESS);
9863 tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_get
9864 (const tng_trajectory_t tng_data,
9865 char *name, const int max_len)
9867 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9868 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
9870 strncpy(name, tng_data->first_computer_name, max_len - 1);
9871 name[max_len - 1] = 0;
9873 if(strlen(tng_data->first_computer_name) > (unsigned int)max_len - 1)
9875 return(TNG_FAILURE);
9877 return(TNG_SUCCESS);
9880 tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_set
9881 (const tng_trajectory_t tng_data,
9882 const char *new_name)
9886 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9887 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
9889 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
9891 /* If the currently stored string length is not enough to store the new
9892 * string it is freed and reallocated. */
9893 if(tng_data->first_computer_name && strlen(tng_data->first_computer_name) < len)
9895 free(tng_data->first_computer_name);
9896 tng_data->first_computer_name = 0;
9898 if(!tng_data->first_computer_name)
9900 tng_data->first_computer_name = malloc(len);
9901 if(!tng_data->first_computer_name)
9903 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
9904 __FILE__, __LINE__);
9905 return(TNG_CRITICAL);
9909 strncpy(tng_data->first_computer_name, new_name, len);
9911 return(TNG_SUCCESS);
9914 tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_get
9915 (const tng_trajectory_t tng_data,
9916 char *name, const int max_len)
9918 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9919 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
9921 strncpy(name, tng_data->last_computer_name, max_len - 1);
9922 name[max_len - 1] = 0;
9924 if(strlen(tng_data->last_computer_name) > (unsigned int)max_len - 1)
9926 return(TNG_FAILURE);
9928 return(TNG_SUCCESS);
9931 tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_set
9932 (const tng_trajectory_t tng_data,
9933 const char *new_name)
9937 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9938 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
9940 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
9942 /* If the currently stored string length is not enough to store the new
9943 * string it is freed and reallocated. */
9944 if(tng_data->last_computer_name && strlen(tng_data->last_computer_name) <
9947 free(tng_data->last_computer_name);
9948 tng_data->last_computer_name = 0;
9950 if(!tng_data->last_computer_name)
9952 tng_data->last_computer_name = malloc(len);
9953 if(!tng_data->last_computer_name)
9955 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
9956 __FILE__, __LINE__);
9957 return(TNG_CRITICAL);
9961 strncpy(tng_data->last_computer_name, new_name, len);
9963 return(TNG_SUCCESS);
9966 tng_function_status DECLSPECDLLEXPORT tng_first_signature_get
9967 (const tng_trajectory_t tng_data,
9968 char *signature, const int max_len)
9970 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9971 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
9973 strncpy(signature, tng_data->first_pgp_signature, max_len - 1);
9974 signature[max_len - 1] = 0;
9976 if(strlen(tng_data->first_pgp_signature) > (unsigned int)max_len - 1)
9978 return(TNG_FAILURE);
9980 return(TNG_SUCCESS);
9983 tng_function_status DECLSPECDLLEXPORT tng_first_signature_set
9984 (const tng_trajectory_t tng_data,
9985 const char *signature)
9989 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9990 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
9992 len = tng_min_size(strlen(signature) + 1, TNG_MAX_STR_LEN);
9994 /* If the currently stored string length is not enough to store the new
9995 * string it is freed and reallocated. */
9996 if(tng_data->first_pgp_signature && strlen(tng_data->first_pgp_signature) <
9999 free(tng_data->first_pgp_signature);
10000 tng_data->first_pgp_signature = 0;
10002 if(!tng_data->first_pgp_signature)
10004 tng_data->first_pgp_signature = malloc(len);
10005 if(!tng_data->first_pgp_signature)
10007 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10008 __FILE__, __LINE__);
10009 return(TNG_CRITICAL);
10013 strncpy(tng_data->first_pgp_signature, signature, len);
10015 return(TNG_SUCCESS);
10018 tng_function_status DECLSPECDLLEXPORT tng_last_signature_get
10019 (const tng_trajectory_t tng_data,
10020 char *signature, const int max_len)
10022 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10023 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
10025 strncpy(signature, tng_data->last_pgp_signature, max_len - 1);
10026 signature[max_len - 1] = 0;
10028 if(strlen(tng_data->last_pgp_signature) > (unsigned int)max_len - 1)
10030 return(TNG_FAILURE);
10032 return(TNG_SUCCESS);
10035 tng_function_status DECLSPECDLLEXPORT tng_last_signature_set
10036 (const tng_trajectory_t tng_data,
10037 const char *signature)
10041 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10042 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
10044 len = tng_min_size(strlen(signature) + 1, TNG_MAX_STR_LEN);
10046 /* If the currently stored string length is not enough to store the new
10047 * string it is freed and reallocated. */
10048 if(tng_data->last_pgp_signature && strlen(tng_data->last_pgp_signature) <
10051 free(tng_data->last_pgp_signature);
10052 tng_data->last_pgp_signature = 0;
10054 if(!tng_data->last_pgp_signature)
10056 tng_data->last_pgp_signature = malloc(len);
10057 if(!tng_data->last_pgp_signature)
10059 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10060 __FILE__, __LINE__);
10061 return(TNG_CRITICAL);
10065 strncpy(tng_data->last_pgp_signature, signature, len);
10067 return(TNG_SUCCESS);
10070 tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_get
10071 (const tng_trajectory_t tng_data,
10072 char *name, const int max_len)
10074 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10075 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10077 strncpy(name, tng_data->forcefield_name, max_len - 1);
10078 name[max_len - 1] = 0;
10080 if(strlen(tng_data->forcefield_name) > (unsigned int)max_len - 1)
10082 return(TNG_FAILURE);
10084 return(TNG_SUCCESS);
10087 tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_set
10088 (const tng_trajectory_t tng_data,
10089 const char *new_name)
10093 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10094 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10096 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
10098 /* If the currently stored string length is not enough to store the new
10099 * string it is freed and reallocated. */
10100 if(tng_data->forcefield_name && strlen(tng_data->forcefield_name) < len)
10102 free(tng_data->forcefield_name);
10103 tng_data->forcefield_name = 0;
10105 if(!tng_data->forcefield_name)
10107 tng_data->forcefield_name = malloc(len);
10108 if(!tng_data->forcefield_name)
10110 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10111 __FILE__, __LINE__);
10112 return(TNG_CRITICAL);
10116 strncpy(tng_data->forcefield_name, new_name, len);
10118 return(TNG_SUCCESS);
10121 tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_get
10122 (const tng_trajectory_t tng_data,
10125 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10126 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
10128 *len = tng_data->medium_stride_length;
10130 return(TNG_SUCCESS);
10133 tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_set
10134 (const tng_trajectory_t tng_data,
10137 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10139 if(len >= tng_data->long_stride_length)
10141 return(TNG_FAILURE);
10143 tng_data->medium_stride_length = len;
10145 return(TNG_SUCCESS);
10148 tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_get
10149 (const tng_trajectory_t tng_data,
10152 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10153 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
10155 *len = tng_data->long_stride_length;
10157 return(TNG_SUCCESS);
10160 tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_set
10161 (const tng_trajectory_t tng_data,
10164 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10166 if(len <= tng_data->medium_stride_length)
10168 return(TNG_FAILURE);
10170 tng_data->long_stride_length = len;
10172 return(TNG_SUCCESS);
10175 tng_function_status DECLSPECDLLEXPORT tng_time_per_frame_get
10176 (const tng_trajectory_t tng_data,
10179 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10180 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
10182 *time = tng_data->time_per_frame;
10184 return(TNG_SUCCESS);
10187 tng_function_status DECLSPECDLLEXPORT tng_time_per_frame_set
10188 (const tng_trajectory_t tng_data,
10191 tng_trajectory_frame_set_t frame_set;
10193 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10194 TNG_ASSERT(time >= 0, "TNG library: The time per frame must be >= 0.");
10196 if(fabs(time - tng_data->time_per_frame) < 0.00001)
10198 return(TNG_SUCCESS);
10201 frame_set = &tng_data->current_trajectory_frame_set;
10203 /* If the current frame set is not finished write it to disk before
10204 changing time per frame. */
10205 if(tng_data->time_per_frame > 0 && frame_set->n_unwritten_frames > 0)
10207 frame_set->n_frames = frame_set->n_unwritten_frames;
10208 tng_frame_set_write(tng_data, TNG_USE_HASH);
10210 tng_data->time_per_frame = time;
10212 return(TNG_SUCCESS);
10215 tng_function_status DECLSPECDLLEXPORT tng_input_file_len_get
10216 (const tng_trajectory_t tng_data,
10219 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10220 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
10222 *len = tng_data->input_file_len;
10224 return(TNG_SUCCESS);
10227 tng_function_status DECLSPECDLLEXPORT tng_num_frames_get
10228 (const tng_trajectory_t tng_data,
10231 tng_gen_block_t block;
10232 tng_function_status stat;
10233 int64_t file_pos, last_file_pos, first_frame, n_frames;
10235 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10236 TNG_ASSERT(tng_data->input_file, "TNG library: An input file must be open to find the next frame set");
10237 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10239 file_pos = ftello(tng_data->input_file);
10240 last_file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
10242 if(last_file_pos <= 0)
10244 return(TNG_FAILURE);
10247 tng_block_init(&block);
10248 fseeko(tng_data->input_file,
10251 /* Read block headers first to see that a frame set block is found. */
10252 stat = tng_block_header_read(tng_data, block);
10253 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10255 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", last_file_pos,
10256 __FILE__, __LINE__);
10257 tng_block_destroy(&block);
10258 return(TNG_FAILURE);
10260 tng_block_destroy(&block);
10262 if(tng_file_input_numerical(tng_data, &first_frame,
10263 sizeof(first_frame),
10264 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
10266 return(TNG_CRITICAL);
10269 if(tng_file_input_numerical(tng_data, &n_frames,
10271 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
10273 return(TNG_CRITICAL);
10276 fseeko(tng_data->input_file, file_pos, SEEK_SET);
10278 *n = first_frame + n_frames;
10280 return(TNG_SUCCESS);
10283 tng_function_status DECLSPECDLLEXPORT tng_compression_precision_get
10284 (const tng_trajectory_t tng_data,
10287 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10289 *precision = tng_data->compression_precision;
10291 return(TNG_SUCCESS);
10294 tng_function_status DECLSPECDLLEXPORT tng_compression_precision_set
10295 (const tng_trajectory_t tng_data,
10296 const double precision)
10298 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10300 tng_data->compression_precision = precision;
10302 return(TNG_SUCCESS);
10305 tng_function_status DECLSPECDLLEXPORT tng_implicit_num_particles_set
10306 (const tng_trajectory_t tng_data,
10309 tng_molecule_t mol;
10313 tng_function_status stat;
10314 int64_t diff, n_mod, n_impl;
10316 TNG_ASSERT(n >= 0, "TNG library: The number of molecules must be >= 0");
10318 diff = n - tng_data->n_particles;
10320 stat = tng_molecule_find(tng_data, "TNG_IMPLICIT_MOL", -1, &mol);
10321 if(stat == TNG_SUCCESS)
10323 if(tng_molecule_cnt_get(tng_data, mol, &n_impl) != TNG_SUCCESS)
10325 fprintf(stderr, "TNG library: Cannot get the number of implicit molecules. %s: %d\n",
10326 __FILE__, __LINE__);
10327 return(TNG_FAILURE);
10329 diff -= n_impl * mol->n_atoms;
10334 if(stat == TNG_SUCCESS)
10336 stat = tng_molecule_cnt_set(tng_data, mol, 0);
10339 return(TNG_SUCCESS);
10343 fprintf(stderr, "TNG library: Already more actual particles than requested implicit ");
10344 fprintf(stderr, "particle count.\n");
10345 fprintf(stderr, "TNG library: Cannot set implicit particle count. %s: %d\n",
10346 __FILE__, __LINE__);
10347 /* FIXME: Should we set the count of all other molecules to 0 and add
10348 * implicit molecules? */
10349 return(TNG_FAILURE);
10351 if(stat != TNG_SUCCESS)
10353 stat = tng_molecule_add(tng_data,
10354 "TNG_IMPLICIT_MOL",
10356 if(stat != TNG_SUCCESS)
10360 stat = tng_molecule_chain_add(tng_data, mol, "", &chain);
10361 if(stat != TNG_SUCCESS)
10365 stat = tng_chain_residue_add(tng_data, chain, "", &res);
10366 if(stat != TNG_SUCCESS)
10370 stat = tng_residue_atom_add(tng_data, res, "", "", &atom);
10371 if(stat != TNG_SUCCESS)
10378 if(mol->n_atoms > 1)
10380 n_mod = diff % mol->n_atoms;
10383 fprintf(stderr, "TNG library: Number of atoms in implicit molecule ");
10384 fprintf(stderr, "not compatible with requested implicit particle cnt.\n");
10385 fprintf(stderr, "TNG library: Cannot set implicit particle count. %s: %d\n",
10386 __FILE__, __LINE__);
10387 return(TNG_FAILURE);
10389 diff /= mol->n_atoms;
10392 stat = tng_molecule_cnt_set(tng_data, mol, diff);
10397 tng_function_status DECLSPECDLLEXPORT tng_num_particles_get
10398 (const tng_trajectory_t tng_data,
10401 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10402 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10404 if(tng_data->var_num_atoms_flag == TNG_CONSTANT_N_ATOMS)
10406 *n = tng_data->n_particles;
10410 *n = tng_data->current_trajectory_frame_set.n_particles;
10413 return(TNG_SUCCESS);
10416 tng_function_status DECLSPECDLLEXPORT tng_num_particles_variable_get
10417 (const tng_trajectory_t tng_data,
10420 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10421 TNG_ASSERT(variable, "TNG library: variable must not be a NULL pointer");
10423 *variable = tng_data->var_num_atoms_flag;
10425 return(TNG_SUCCESS);
10428 tng_function_status DECLSPECDLLEXPORT tng_num_molecule_types_get
10429 (const tng_trajectory_t tng_data,
10432 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10433 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10435 *n = tng_data->n_molecules;
10437 return(TNG_SUCCESS);
10440 tng_function_status DECLSPECDLLEXPORT tng_num_molecules_get
10441 (const tng_trajectory_t tng_data,
10444 int64_t *cnt_list = 0, cnt = 0, i;
10446 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10447 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10449 tng_molecule_cnt_list_get(tng_data, &cnt_list);
10453 return(TNG_FAILURE);
10456 for(i = 0; i < tng_data->n_molecules; i++)
10458 cnt += cnt_list[i];
10463 return(TNG_SUCCESS);
10466 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_list_get
10467 (const tng_trajectory_t tng_data,
10468 int64_t **mol_cnt_list)
10470 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10472 if(tng_data->var_num_atoms_flag)
10474 *mol_cnt_list = tng_data->current_trajectory_frame_set.
10479 *mol_cnt_list = tng_data->molecule_cnt_list;
10481 if(*mol_cnt_list == 0)
10483 return(TNG_FAILURE);
10485 return(TNG_SUCCESS);
10488 tng_function_status DECLSPECDLLEXPORT tng_distance_unit_exponential_get
10489 (const tng_trajectory_t tng_data,
10492 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10493 TNG_ASSERT(exp, "TNG library: exp must not be a NULL pointer");
10495 *exp = tng_data->distance_unit_exponential;
10497 return(TNG_SUCCESS);
10500 tng_function_status DECLSPECDLLEXPORT tng_distance_unit_exponential_set
10501 (const tng_trajectory_t tng_data,
10504 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10506 tng_data->distance_unit_exponential = exp;
10508 return(TNG_SUCCESS);
10511 tng_function_status DECLSPECDLLEXPORT tng_num_frames_per_frame_set_get
10512 (const tng_trajectory_t tng_data,
10515 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10516 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10518 *n = tng_data->frame_set_n_frames;
10520 return(TNG_SUCCESS);
10523 tng_function_status DECLSPECDLLEXPORT tng_num_frames_per_frame_set_set
10524 (const tng_trajectory_t tng_data,
10527 tng_trajectory_frame_set_t frame_set;
10528 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10530 tng_data->frame_set_n_frames = n;
10531 frame_set = &tng_data->current_trajectory_frame_set;
10534 frame_set->n_frames = n;
10537 return(TNG_SUCCESS);
10540 tng_function_status DECLSPECDLLEXPORT tng_num_frame_sets_get
10541 (const tng_trajectory_t tng_data,
10544 int64_t long_stride_length, medium_stride_length;
10545 int64_t file_pos, orig_frame_set_file_pos;
10546 tng_trajectory_frame_set_t frame_set;
10547 struct tng_trajectory_frame_set orig_frame_set;
10548 tng_gen_block_t block;
10549 tng_function_status stat;
10552 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10553 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10555 orig_frame_set = tng_data->current_trajectory_frame_set;
10557 frame_set = &tng_data->current_trajectory_frame_set;
10559 orig_frame_set_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
10560 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
10564 *n = tng_data->n_trajectory_frame_sets = cnt;
10565 return(TNG_SUCCESS);
10568 tng_block_init(&block);
10569 fseeko(tng_data->input_file,
10572 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
10573 /* Read block headers first to see what block is found. */
10574 stat = tng_block_header_read(tng_data, block);
10575 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10577 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", file_pos,
10578 __FILE__, __LINE__);
10579 tng_block_destroy(&block);
10580 return(TNG_CRITICAL);
10583 if(tng_block_read_next(tng_data, block,
10584 TNG_SKIP_HASH) != TNG_SUCCESS)
10586 tng_block_destroy(&block);
10587 return(TNG_CRITICAL);
10592 long_stride_length = tng_data->long_stride_length;
10593 medium_stride_length = tng_data->medium_stride_length;
10595 /* Take long steps forward until a long step forward would be too long or
10596 * the last frame set is found */
10597 file_pos = frame_set->long_stride_next_frame_set_file_pos;
10598 while(file_pos > 0)
10602 cnt += long_stride_length;
10603 fseeko(tng_data->input_file, file_pos, SEEK_SET);
10604 /* Read block headers first to see what block is found. */
10605 stat = tng_block_header_read(tng_data, block);
10606 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10608 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
10609 file_pos, __FILE__, __LINE__);
10610 tng_block_destroy(&block);
10611 return(TNG_CRITICAL);
10614 if(tng_block_read_next(tng_data, block,
10615 TNG_SKIP_HASH) != TNG_SUCCESS)
10617 tng_block_destroy(&block);
10618 return(TNG_CRITICAL);
10621 file_pos = frame_set->long_stride_next_frame_set_file_pos;
10624 /* Take medium steps forward until a medium step forward would be too long
10625 * or the last frame set is found */
10626 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
10627 while(file_pos > 0)
10631 cnt += medium_stride_length;
10632 fseeko(tng_data->input_file,
10635 /* Read block headers first to see what block is found. */
10636 stat = tng_block_header_read(tng_data, block);
10637 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10639 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
10640 file_pos, __FILE__, __LINE__);
10641 tng_block_destroy(&block);
10642 return(TNG_CRITICAL);
10645 if(tng_block_read_next(tng_data, block,
10646 TNG_SKIP_HASH) != TNG_SUCCESS)
10648 tng_block_destroy(&block);
10649 return(TNG_CRITICAL);
10652 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
10655 /* Take one step forward until the last frame set is found */
10656 file_pos = frame_set->next_frame_set_file_pos;
10657 while(file_pos > 0)
10662 fseeko(tng_data->input_file,
10665 /* Read block headers first to see what block is found. */
10666 stat = tng_block_header_read(tng_data, block);
10667 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10669 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
10670 file_pos, __FILE__, __LINE__);
10671 tng_block_destroy(&block);
10672 return(TNG_CRITICAL);
10675 if(tng_block_read_next(tng_data, block,
10676 TNG_SKIP_HASH) != TNG_SUCCESS)
10678 tng_block_destroy(&block);
10679 return(TNG_CRITICAL);
10682 file_pos = frame_set->next_frame_set_file_pos;
10685 tng_block_destroy(&block);
10687 *n = tng_data->n_trajectory_frame_sets = cnt;
10689 *frame_set = orig_frame_set;
10690 /* The mapping block in the original frame set has been freed when reading
10691 * other frame sets. */
10692 frame_set->mappings = 0;
10693 frame_set->n_mapping_blocks = 0;
10695 fseeko(tng_data->input_file,
10696 tng_data->first_trajectory_frame_set_input_file_pos,
10699 tng_data->current_trajectory_frame_set_input_file_pos = orig_frame_set_file_pos;
10701 return(TNG_SUCCESS);
10704 tng_function_status DECLSPECDLLEXPORT tng_current_frame_set_get
10705 (const tng_trajectory_t tng_data,
10706 tng_trajectory_frame_set_t *frame_set_p)
10708 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10710 *frame_set_p = &tng_data->current_trajectory_frame_set;
10712 return(TNG_SUCCESS);
10715 tng_function_status DECLSPECDLLEXPORT tng_frame_set_nr_find
10716 (const tng_trajectory_t tng_data,
10719 int64_t long_stride_length, medium_stride_length;
10720 int64_t file_pos, curr_nr = 0, n_frame_sets;
10721 tng_trajectory_frame_set_t frame_set;
10722 tng_gen_block_t block;
10723 tng_function_status stat;
10725 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10726 TNG_ASSERT(nr >= 0, "The frame set number (nr) must be >= 0");
10728 frame_set = &tng_data->current_trajectory_frame_set;
10730 stat = tng_num_frame_sets_get(tng_data, &n_frame_sets);
10732 if(stat != TNG_SUCCESS)
10737 if(nr >= n_frame_sets)
10739 return(TNG_FAILURE);
10742 long_stride_length = tng_data->long_stride_length;
10743 medium_stride_length = tng_data->medium_stride_length;
10745 /* FIXME: The frame set number of the current frame set is not stored */
10747 if(nr < n_frame_sets - 1 - nr)
10749 /* Start from the beginning */
10750 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
10754 /* Start from the end */
10755 file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
10756 curr_nr = n_frame_sets - 1;
10760 return(TNG_FAILURE);
10763 tng_block_init(&block);
10764 fseeko(tng_data->input_file,
10767 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
10768 /* Read block headers first to see what block is found. */
10769 stat = tng_block_header_read(tng_data, block);
10770 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10772 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", file_pos,
10773 __FILE__, __LINE__);
10774 tng_block_destroy(&block);
10775 return(TNG_CRITICAL);
10778 if(tng_block_read_next(tng_data, block,
10779 TNG_SKIP_HASH) != TNG_SUCCESS)
10781 tng_block_destroy(&block);
10782 return(TNG_CRITICAL);
10787 tng_block_destroy(&block);
10788 return(TNG_SUCCESS);
10791 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
10793 /* Take long steps forward until a long step forward would be too long or
10794 * the right frame set is found */
10795 while(file_pos > 0 && curr_nr + long_stride_length <= nr)
10797 file_pos = frame_set->long_stride_next_frame_set_file_pos;
10800 curr_nr += long_stride_length;
10801 fseeko(tng_data->input_file, file_pos, SEEK_SET);
10802 /* Read block headers first to see what block is found. */
10803 stat = tng_block_header_read(tng_data, block);
10804 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10806 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
10807 file_pos, __FILE__, __LINE__);
10808 tng_block_destroy(&block);
10809 return(TNG_CRITICAL);
10812 if(tng_block_read_next(tng_data, block,
10813 TNG_SKIP_HASH) != TNG_SUCCESS)
10815 tng_block_destroy(&block);
10816 return(TNG_CRITICAL);
10820 tng_block_destroy(&block);
10821 return(TNG_SUCCESS);
10826 /* Take medium steps forward until a medium step forward would be too long
10827 * or the right frame set is found */
10828 while(file_pos > 0 && curr_nr + medium_stride_length <= nr)
10830 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
10833 curr_nr += medium_stride_length;
10834 fseeko(tng_data->input_file,
10837 /* Read block headers first to see what block is found. */
10838 stat = tng_block_header_read(tng_data, block);
10839 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10841 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
10842 file_pos, __FILE__, __LINE__);
10843 tng_block_destroy(&block);
10844 return(TNG_CRITICAL);
10847 if(tng_block_read_next(tng_data, block,
10848 TNG_SKIP_HASH) != TNG_SUCCESS)
10850 tng_block_destroy(&block);
10851 return(TNG_CRITICAL);
10855 tng_block_destroy(&block);
10856 return(TNG_SUCCESS);
10861 /* Take one step forward until the right frame set is found */
10862 while(file_pos > 0 && curr_nr < nr)
10864 file_pos = frame_set->next_frame_set_file_pos;
10869 fseeko(tng_data->input_file,
10872 /* Read block headers first to see what block is found. */
10873 stat = tng_block_header_read(tng_data, block);
10874 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10876 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
10877 file_pos, __FILE__, __LINE__);
10878 tng_block_destroy(&block);
10879 return(TNG_CRITICAL);
10882 if(tng_block_read_next(tng_data, block,
10883 TNG_SKIP_HASH) != TNG_SUCCESS)
10885 tng_block_destroy(&block);
10886 return(TNG_CRITICAL);
10890 tng_block_destroy(&block);
10891 return(TNG_SUCCESS);
10896 /* Take long steps backward until a long step backward would be too long
10897 * or the right frame set is found */
10898 while(file_pos > 0 && curr_nr - long_stride_length >= nr)
10900 file_pos = frame_set->long_stride_prev_frame_set_file_pos;
10903 curr_nr -= long_stride_length;
10904 fseeko(tng_data->input_file,
10907 /* Read block headers first to see what block is found. */
10908 stat = tng_block_header_read(tng_data, block);
10909 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10911 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
10912 file_pos, __FILE__, __LINE__);
10913 tng_block_destroy(&block);
10914 return(TNG_CRITICAL);
10917 if(tng_block_read_next(tng_data, block,
10918 TNG_SKIP_HASH) != TNG_SUCCESS)
10920 tng_block_destroy(&block);
10921 return(TNG_CRITICAL);
10925 tng_block_destroy(&block);
10926 return(TNG_SUCCESS);
10931 /* Take medium steps backward until a medium step backward would be too long
10932 * or the right frame set is found */
10933 while(file_pos > 0 && curr_nr - medium_stride_length >= nr)
10935 file_pos = frame_set->medium_stride_prev_frame_set_file_pos;
10938 curr_nr -= medium_stride_length;
10939 fseeko(tng_data->input_file,
10942 /* Read block headers first to see what block is found. */
10943 stat = tng_block_header_read(tng_data, block);
10944 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10946 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
10947 file_pos, __FILE__, __LINE__);
10948 tng_block_destroy(&block);
10949 return(TNG_CRITICAL);
10952 if(tng_block_read_next(tng_data, block,
10953 TNG_SKIP_HASH) != TNG_SUCCESS)
10955 tng_block_destroy(&block);
10956 return(TNG_CRITICAL);
10960 tng_block_destroy(&block);
10961 return(TNG_SUCCESS);
10966 /* Take one step backward until the right frame set is found */
10967 while(file_pos > 0 && curr_nr > nr)
10969 file_pos = frame_set->prev_frame_set_file_pos;
10973 fseeko(tng_data->input_file,
10976 /* Read block headers first to see what block is found. */
10977 stat = tng_block_header_read(tng_data, block);
10978 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10980 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
10981 file_pos, __FILE__, __LINE__);
10982 tng_block_destroy(&block);
10983 return(TNG_CRITICAL);
10986 if(tng_block_read_next(tng_data, block,
10987 TNG_SKIP_HASH) != TNG_SUCCESS)
10989 tng_block_destroy(&block);
10990 return(TNG_CRITICAL);
10994 tng_block_destroy(&block);
10995 return(TNG_SUCCESS);
11000 /* If for some reason the current frame set is not yet found,
11001 * take one step forward until the right frame set is found */
11002 while(file_pos > 0 && curr_nr < nr)
11004 file_pos = frame_set->next_frame_set_file_pos;
11008 fseeko(tng_data->input_file,
11011 /* Read block headers first to see what block is found. */
11012 stat = tng_block_header_read(tng_data, block);
11013 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11015 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11016 file_pos, __FILE__, __LINE__);
11017 tng_block_destroy(&block);
11018 return(TNG_CRITICAL);
11021 if(tng_block_read_next(tng_data, block,
11022 TNG_SKIP_HASH) != TNG_SUCCESS)
11024 tng_block_destroy(&block);
11025 return(TNG_CRITICAL);
11029 tng_block_destroy(&block);
11030 return(TNG_SUCCESS);
11035 tng_block_destroy(&block);
11036 return(TNG_FAILURE);
11039 tng_function_status DECLSPECDLLEXPORT tng_frame_set_of_frame_find
11040 (const tng_trajectory_t tng_data,
11041 const int64_t frame)
11043 int64_t first_frame, last_frame, n_frames_per_frame_set;
11044 int64_t long_stride_length, medium_stride_length;
11045 int64_t file_pos, temp_frame, n_frames;
11046 tng_trajectory_frame_set_t frame_set;
11047 tng_gen_block_t block;
11048 tng_function_status stat;
11050 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11051 TNG_ASSERT(frame >= 0, "TNG library: frame must be >= 0.");
11053 frame_set = &tng_data->current_trajectory_frame_set;
11055 tng_block_init(&block);
11057 if(tng_data->current_trajectory_frame_set_input_file_pos < 0)
11059 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
11060 fseeko(tng_data->input_file,
11063 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
11064 /* Read block headers first to see what block is found. */
11065 stat = tng_block_header_read(tng_data, block);
11066 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11068 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11069 file_pos, __FILE__, __LINE__);
11070 tng_block_destroy(&block);
11071 return(TNG_CRITICAL);
11074 if(tng_block_read_next(tng_data, block,
11075 TNG_SKIP_HASH) != TNG_SUCCESS)
11077 tng_block_destroy(&block);
11078 return(TNG_CRITICAL);
11082 first_frame = tng_max_i64(frame_set->first_frame, 0);
11083 last_frame = first_frame + frame_set->n_frames - 1;
11084 /* Is this the right frame set? */
11085 if(first_frame <= frame && frame <= last_frame)
11087 tng_block_destroy(&block);
11088 return(TNG_SUCCESS);
11091 n_frames_per_frame_set = tng_data->frame_set_n_frames;
11092 long_stride_length = tng_data->long_stride_length;
11093 medium_stride_length = tng_data->medium_stride_length;
11095 if(tng_first_frame_nr_of_next_frame_set_get(tng_data, &temp_frame) ==
11098 if(temp_frame - first_frame > n_frames_per_frame_set)
11100 n_frames_per_frame_set = temp_frame - first_frame;
11104 tng_num_frames_get(tng_data, &n_frames);
11106 if(frame >= n_frames)
11108 tng_block_destroy(&block);
11109 return(TNG_FAILURE);
11112 if(first_frame - frame >= frame ||
11113 frame - last_frame >
11114 tng_data->n_trajectory_frame_sets * n_frames_per_frame_set - frame)
11116 /* Start from the beginning */
11117 if(first_frame - frame >= frame)
11119 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
11123 tng_block_destroy(&block);
11124 return(TNG_FAILURE);
11127 /* Start from the end */
11128 else if(frame - first_frame > (n_frames - 1) - frame)
11130 file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
11132 /* If the last frame set position is not set start from the current
11133 * frame set, since it will be closer than the first frame set. */
11135 /* Start from current */
11138 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
11143 fseeko(tng_data->input_file,
11146 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
11147 /* Read block headers first to see what block is found. */
11148 stat = tng_block_header_read(tng_data, block);
11149 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11151 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11152 file_pos, __FILE__, __LINE__);
11153 tng_block_destroy(&block);
11154 return(TNG_CRITICAL);
11157 if(tng_block_read_next(tng_data, block,
11158 TNG_SKIP_HASH) != TNG_SUCCESS)
11160 tng_block_destroy(&block);
11161 return(TNG_CRITICAL);
11166 first_frame = tng_max_i64(frame_set->first_frame, 0);
11167 last_frame = first_frame + frame_set->n_frames - 1;
11169 if(frame >= first_frame && frame <= last_frame)
11171 tng_block_destroy(&block);
11172 return(TNG_SUCCESS);
11175 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
11177 /* Take long steps forward until a long step forward would be too long or
11178 * the right frame set is found */
11179 while(file_pos > 0 && first_frame + long_stride_length *
11180 n_frames_per_frame_set <= frame)
11182 file_pos = frame_set->long_stride_next_frame_set_file_pos;
11185 fseeko(tng_data->input_file, file_pos, SEEK_SET);
11186 /* Read block headers first to see what block is found. */
11187 stat = tng_block_header_read(tng_data, block);
11188 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11190 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11191 file_pos, __FILE__, __LINE__);
11192 tng_block_destroy(&block);
11193 return(TNG_CRITICAL);
11196 if(tng_block_read_next(tng_data, block,
11197 TNG_SKIP_HASH) != TNG_SUCCESS)
11199 tng_block_destroy(&block);
11200 return(TNG_CRITICAL);
11203 first_frame = tng_max_i64(frame_set->first_frame, 0);
11204 last_frame = first_frame + frame_set->n_frames - 1;
11205 if(frame >= first_frame && frame <= last_frame)
11207 tng_block_destroy(&block);
11208 return(TNG_SUCCESS);
11212 /* Take medium steps forward until a medium step forward would be too long
11213 * or the right frame set is found */
11214 while(file_pos > 0 && first_frame + medium_stride_length *
11215 n_frames_per_frame_set <= frame)
11217 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
11220 fseeko(tng_data->input_file,
11223 /* Read block headers first to see what block is found. */
11224 stat = tng_block_header_read(tng_data, block);
11225 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11227 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11228 file_pos, __FILE__, __LINE__);
11229 tng_block_destroy(&block);
11230 return(TNG_CRITICAL);
11233 if(tng_block_read_next(tng_data, block,
11234 TNG_SKIP_HASH) != TNG_SUCCESS)
11236 tng_block_destroy(&block);
11237 return(TNG_CRITICAL);
11240 first_frame = tng_max_i64(frame_set->first_frame, 0);
11241 last_frame = first_frame + frame_set->n_frames - 1;
11242 if(frame >= first_frame && frame <= last_frame)
11244 tng_block_destroy(&block);
11245 return(TNG_SUCCESS);
11249 /* Take one step forward until the right frame set is found */
11250 while(file_pos > 0 && first_frame < frame && last_frame < frame)
11252 file_pos = frame_set->next_frame_set_file_pos;
11255 fseeko(tng_data->input_file,
11258 /* Read block headers first to see what block is found. */
11259 stat = tng_block_header_read(tng_data, block);
11260 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11262 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11263 file_pos, __FILE__, __LINE__);
11264 tng_block_destroy(&block);
11265 return(TNG_CRITICAL);
11268 if(tng_block_read_next(tng_data, block,
11269 TNG_SKIP_HASH) != TNG_SUCCESS)
11271 tng_block_destroy(&block);
11272 return(TNG_CRITICAL);
11275 first_frame = tng_max_i64(frame_set->first_frame, 0);
11276 last_frame = first_frame + frame_set->n_frames - 1;
11277 if(frame >= first_frame && frame <= last_frame)
11279 tng_block_destroy(&block);
11280 return(TNG_SUCCESS);
11284 /* Take long steps backward until a long step backward would be too long
11285 * or the right frame set is found */
11286 while(file_pos > 0 && first_frame - long_stride_length *
11287 n_frames_per_frame_set >= frame)
11289 file_pos = frame_set->long_stride_prev_frame_set_file_pos;
11292 fseeko(tng_data->input_file,
11295 /* Read block headers first to see what block is found. */
11296 stat = tng_block_header_read(tng_data, block);
11297 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11299 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11300 file_pos, __FILE__, __LINE__);
11301 tng_block_destroy(&block);
11302 return(TNG_CRITICAL);
11305 if(tng_block_read_next(tng_data, block,
11306 TNG_SKIP_HASH) != TNG_SUCCESS)
11308 tng_block_destroy(&block);
11309 return(TNG_CRITICAL);
11312 first_frame = tng_max_i64(frame_set->first_frame, 0);
11313 last_frame = first_frame + frame_set->n_frames - 1;
11314 if(frame >= first_frame && frame <= last_frame)
11316 tng_block_destroy(&block);
11317 return(TNG_SUCCESS);
11321 /* Take medium steps backward until a medium step backward would be too long
11322 * or the right frame set is found */
11323 while(file_pos > 0 && first_frame - medium_stride_length *
11324 n_frames_per_frame_set >= frame)
11326 file_pos = frame_set->medium_stride_prev_frame_set_file_pos;
11329 fseeko(tng_data->input_file,
11332 /* Read block headers first to see what block is found. */
11333 stat = tng_block_header_read(tng_data, block);
11334 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11336 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11337 file_pos, __FILE__, __LINE__);
11338 tng_block_destroy(&block);
11339 return(TNG_CRITICAL);
11342 if(tng_block_read_next(tng_data, block,
11343 TNG_SKIP_HASH) != TNG_SUCCESS)
11345 tng_block_destroy(&block);
11346 return(TNG_CRITICAL);
11349 first_frame = tng_max_i64(frame_set->first_frame, 0);
11350 last_frame = first_frame + frame_set->n_frames - 1;
11351 if(frame >= first_frame && frame <= last_frame)
11353 tng_block_destroy(&block);
11354 return(TNG_SUCCESS);
11358 /* Take one step backward until the right frame set is found */
11359 while(file_pos > 0 && first_frame > frame && last_frame > frame)
11361 file_pos = frame_set->prev_frame_set_file_pos;
11364 fseeko(tng_data->input_file,
11367 /* Read block headers first to see what block is found. */
11368 stat = tng_block_header_read(tng_data, block);
11369 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11371 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11372 file_pos, __FILE__, __LINE__);
11373 tng_block_destroy(&block);
11374 return(TNG_CRITICAL);
11377 if(tng_block_read_next(tng_data, block,
11378 TNG_SKIP_HASH) != TNG_SUCCESS)
11380 tng_block_destroy(&block);
11381 return(TNG_CRITICAL);
11384 first_frame = tng_max_i64(frame_set->first_frame, 0);
11385 last_frame = first_frame + frame_set->n_frames - 1;
11386 if(frame >= first_frame && frame <= last_frame)
11388 tng_block_destroy(&block);
11389 return(TNG_SUCCESS);
11393 /* If for some reason the current frame set is not yet found,
11394 * take one step forward until the right frame set is found */
11395 while(file_pos > 0 && first_frame < frame && last_frame < frame)
11397 file_pos = frame_set->next_frame_set_file_pos;
11400 fseeko(tng_data->input_file,
11403 /* Read block headers first to see what block is found. */
11404 stat = tng_block_header_read(tng_data, block);
11405 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11407 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11408 file_pos, __FILE__, __LINE__);
11409 tng_block_destroy(&block);
11410 return(TNG_CRITICAL);
11413 if(tng_block_read_next(tng_data, block,
11414 TNG_SKIP_HASH) != TNG_SUCCESS)
11416 tng_block_destroy(&block);
11417 return(TNG_CRITICAL);
11420 first_frame = tng_max_i64(frame_set->first_frame, 0);
11421 last_frame = first_frame + frame_set->n_frames - 1;
11422 if(frame >= first_frame && frame <= last_frame)
11424 tng_block_destroy(&block);
11425 return(TNG_SUCCESS);
11429 tng_block_destroy(&block);
11430 return(TNG_FAILURE);
11433 tng_function_status DECLSPECDLLEXPORT tng_frame_set_next_frame_set_file_pos_get
11434 (const tng_trajectory_t tng_data,
11435 const tng_trajectory_frame_set_t frame_set,
11440 TNG_ASSERT(frame_set, "TNG library: frame_set not initialised before accessing data.");
11441 TNG_ASSERT(pos, "TNG library: pos must not be a NULL pointer");
11443 *pos = frame_set->next_frame_set_file_pos;
11445 return(TNG_SUCCESS);
11448 tng_function_status DECLSPECDLLEXPORT tng_frame_set_prev_frame_set_file_pos_get
11449 (const tng_trajectory_t tng_data,
11450 const tng_trajectory_frame_set_t frame_set,
11455 TNG_ASSERT(frame_set, "TNG library: frame_set not initialised before accessing data.");
11456 TNG_ASSERT(pos, "TNG library: pos must not be a NULL pointer");
11458 *pos = frame_set->prev_frame_set_file_pos;
11460 return(TNG_SUCCESS);
11463 tng_function_status DECLSPECDLLEXPORT tng_frame_set_frame_range_get
11464 (const tng_trajectory_t tng_data,
11465 const tng_trajectory_frame_set_t frame_set,
11466 int64_t *first_frame,
11467 int64_t *last_frame)
11471 TNG_ASSERT(first_frame, "TNG library: first_frame must not be a NULL pointer");
11472 TNG_ASSERT(last_frame, "TNG library: last_frame must not be a NULL pointer");
11473 TNG_ASSERT(frame_set, "TNG library: frame_set must not be a NULL pointer");
11475 *first_frame = frame_set->first_frame;
11476 *last_frame = *first_frame + frame_set->n_frames - 1;
11478 return(TNG_SUCCESS);
11482 * @brief Translate from the particle numbering used in a frame set to the real
11483 * particle numbering - used in the molecule description.
11484 * @param frame_set is the frame_set containing the mappings to use.
11485 * @param local is the index number of the atom in this frame set
11486 * @param real is set to the index of the atom in the molecular system.
11487 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the mapping
11490 static TNG_INLINE tng_function_status tng_particle_mapping_get_real_particle
11491 (const tng_trajectory_frame_set_t frame_set,
11492 const int64_t local,
11495 int64_t i, n_blocks = frame_set->n_mapping_blocks, first;
11496 tng_particle_mapping_t mapping;
11500 return(TNG_SUCCESS);
11502 for(i = 0; i < n_blocks; i++)
11504 mapping = &frame_set->mappings[i];
11505 first = mapping->num_first_particle;
11506 if(local < first ||
11507 local >= first + mapping->n_particles)
11511 *real = mapping->real_particle_numbers[local-first];
11512 return(TNG_SUCCESS);
11515 return(TNG_FAILURE);
11519 * @brief Translate from the real particle numbering to the particle numbering
11520 * used in a frame set.
11521 * @param frame_set is the frame_set containing the mappings to use.
11522 * @param real is the index number of the atom in the molecular system.
11523 * @param local is set to the index of the atom in this frame set.
11524 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the mapping
11527 /*static TNG_INLINE tng_function_status tng_particle_mapping_get_local_particle
11528 (const tng_trajectory_frame_set_t frame_set,
11529 const int64_t real,
11532 int64_t i, j, n_blocks = frame_set->n_mapping_blocks;
11533 tng_particle_mapping_t mapping;
11537 return(TNG_SUCCESS);
11539 for(i = 0; i < n_blocks; i++)
11541 mapping = &frame_set->mappings[i];
11542 for(j = mapping->n_particles; j--;)
11544 if(mapping->real_particle_numbers[j] == real)
11547 return(TNG_SUCCESS);
11551 return(TNG_FAILURE);
11555 static tng_function_status tng_file_headers_len_get
11556 (const tng_trajectory_t tng_data,
11560 tng_gen_block_t block;
11562 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11564 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
11566 return(TNG_CRITICAL);
11571 orig_pos = ftello(tng_data->input_file);
11573 fseeko(tng_data->input_file, 0, SEEK_SET);
11575 tng_block_init(&block);
11576 /* Read through the headers of non-trajectory blocks (they come before the
11577 * trajectory blocks in the file) */
11578 while (*len < tng_data->input_file_len &&
11579 tng_block_header_read(tng_data, block) != TNG_CRITICAL &&
11581 block->id != TNG_TRAJECTORY_FRAME_SET)
11583 *len += block->header_contents_size + block->block_contents_size;
11584 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
11587 fseeko(tng_data->input_file, orig_pos, SEEK_SET);
11589 tng_block_destroy(&block);
11591 return(TNG_SUCCESS);
11594 tng_function_status DECLSPECDLLEXPORT tng_file_headers_read
11595 (const tng_trajectory_t tng_data,
11596 const char hash_mode)
11598 int64_t prev_pos = 0;
11599 tng_gen_block_t block;
11601 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11603 tng_data->n_trajectory_frame_sets = 0;
11605 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
11607 return(TNG_CRITICAL);
11610 fseeko(tng_data->input_file, 0, SEEK_SET);
11612 tng_block_init(&block);
11613 /* Non trajectory blocks (they come before the trajectory
11614 * blocks in the file) */
11615 while (prev_pos < tng_data->input_file_len &&
11616 tng_block_header_read(tng_data, block) != TNG_CRITICAL &&
11618 block->id != TNG_TRAJECTORY_FRAME_SET)
11620 tng_block_read_next(tng_data, block, hash_mode);
11621 prev_pos = ftello(tng_data->input_file);
11624 /* Go back if a trajectory block was encountered */
11625 if(block->id == TNG_TRAJECTORY_FRAME_SET)
11627 fseeko(tng_data->input_file, prev_pos, SEEK_SET);
11630 tng_block_destroy(&block);
11632 return(TNG_SUCCESS);
11635 tng_function_status DECLSPECDLLEXPORT tng_file_headers_write
11636 (const tng_trajectory_t tng_data,
11637 const char hash_mode)
11640 int64_t len, orig_len, tot_len = 0, data_start_pos, temp_pos = -1;
11641 tng_function_status stat;
11642 tng_gen_block_t block;
11644 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11646 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
11648 return(TNG_CRITICAL);
11651 if(tng_data->n_trajectory_frame_sets > 0)
11653 stat = tng_file_headers_len_get(tng_data, &orig_len);
11654 if(stat != TNG_SUCCESS)
11659 tng_block_init(&block);
11660 block->name = malloc(TNG_MAX_STR_LEN);
11663 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
11664 TNG_MAX_STR_LEN, __FILE__, __LINE__);
11665 tng_block_destroy(&block);
11666 return(TNG_CRITICAL);
11668 strcpy(block->name, "GENERAL INFO");
11669 tng_block_header_len_calculate(tng_data, block, &len);
11671 tng_general_info_block_len_calculate(tng_data, &len);
11673 strcpy(block->name, "MOLECULES");
11674 tng_block_header_len_calculate(tng_data, block, &len);
11676 tng_molecules_block_len_calculate(tng_data, &len);
11679 for(i = 0; i < tng_data->n_data_blocks; i++)
11681 strcpy(block->name, tng_data->non_tr_data[i].block_name);
11682 tng_block_header_len_calculate(tng_data, block, &len);
11684 tng_data_block_len_calculate(tng_data,
11685 (tng_data_t)&tng_data->non_tr_data[i],
11686 TNG_FALSE, 1, 1, 1, 0, 1,
11691 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
11693 strcpy(block->name, tng_data->non_tr_particle_data[i].block_name);
11694 tng_block_header_len_calculate(tng_data, block, &len);
11696 tng_data_block_len_calculate(tng_data,
11697 &tng_data->non_tr_particle_data[i],
11698 TNG_TRUE, 1, 1, 1, 0,
11699 tng_data->n_particles,
11704 tng_block_destroy(&block);
11706 if(tot_len > orig_len)
11708 tng_migrate_data_in_file(tng_data, orig_len+1, tot_len - orig_len, hash_mode);
11711 stat = tng_reread_frame_set_at_file_pos(tng_data, tng_data->last_trajectory_frame_set_input_file_pos);
11712 if(stat == TNG_CRITICAL)
11714 fprintf(stderr, "TNG library: Cannot read frame set. %s: %d\n",
11715 __FILE__, __LINE__);
11716 return(TNG_CRITICAL);
11719 /* In order to write non-trajectory data the current_trajectory_frame_set_output_file_pos
11720 * must temporarily be reset */
11721 temp_pos = tng_data->current_trajectory_frame_set_output_file_pos;
11722 tng_data->current_trajectory_frame_set_output_file_pos = -1;
11725 if(tng_general_info_block_write(tng_data, hash_mode)
11728 fprintf(stderr, "TNG library: Error writing general info block of file %s. %s: %d\n",
11729 tng_data->input_file_path, __FILE__, __LINE__);
11730 return(TNG_CRITICAL);
11733 if(tng_molecules_block_write(tng_data, hash_mode)
11736 fprintf(stderr, "TNG library: Error writing atom names block of file %s. %s: %d\n",
11737 tng_data->input_file_path, __FILE__, __LINE__);
11738 return(TNG_CRITICAL);
11741 /* FIXME: Currently writing non-trajectory data blocks here.
11742 * Should perhaps be moved. */
11743 tng_block_init(&block);
11744 for(i = 0; i < tng_data->n_data_blocks; i++)
11746 block->id = tng_data->non_tr_data[i].block_id;
11747 tng_data_block_write(tng_data, block,
11748 i, TNG_FALSE, 0, hash_mode);
11751 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
11753 block->id = tng_data->non_tr_particle_data[i].block_id;
11754 tng_data_block_write(tng_data, block,
11755 i, TNG_TRUE, 0, hash_mode);
11758 tng_block_destroy(&block);
11760 /* Continue writing at the end of the file. */
11761 fseeko(tng_data->output_file, 0, SEEK_END);
11764 tng_data->current_trajectory_frame_set_output_file_pos = temp_pos;
11767 return(TNG_SUCCESS);
11770 tng_function_status DECLSPECDLLEXPORT tng_block_read_next
11771 (const tng_trajectory_t tng_data,
11772 const tng_gen_block_t block,
11773 const char hash_mode)
11775 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11776 TNG_ASSERT(block, "TNG library: block must be initialised and must not be a NULL pointer.");
11780 case TNG_TRAJECTORY_FRAME_SET:
11781 return(tng_frame_set_block_read(tng_data, block, hash_mode));
11782 case TNG_PARTICLE_MAPPING:
11783 return(tng_trajectory_mapping_block_read(tng_data, block, hash_mode));
11784 case TNG_GENERAL_INFO:
11785 return(tng_general_info_block_read(tng_data, block, hash_mode));
11786 case TNG_MOLECULES:
11787 return(tng_molecules_block_read(tng_data, block, hash_mode));
11789 if(block->id >= TNG_TRAJ_BOX_SHAPE)
11791 return(tng_data_block_contents_read(tng_data, block, hash_mode));
11795 /* Skip to the next block */
11796 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
11797 return(TNG_FAILURE);
11802 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read
11803 (const tng_trajectory_t tng_data,
11804 const char hash_mode)
11807 tng_gen_block_t block;
11808 tng_function_status stat;
11810 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11812 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
11814 return(TNG_CRITICAL);
11817 file_pos = ftello(tng_data->input_file);
11819 tng_block_init(&block);
11821 /* Read block headers first to see what block is found. */
11822 stat = tng_block_header_read(tng_data, block);
11823 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET ||
11826 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11827 file_pos, __FILE__, __LINE__);
11828 tng_block_destroy(&block);
11829 return(TNG_CRITICAL);
11832 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
11834 if(tng_block_read_next(tng_data, block,
11835 hash_mode) == TNG_SUCCESS)
11837 tng_data->n_trajectory_frame_sets++;
11838 file_pos = ftello(tng_data->input_file);
11839 /* Read all blocks until next frame set block */
11840 stat = tng_block_header_read(tng_data, block);
11841 while(file_pos < tng_data->input_file_len &&
11842 stat != TNG_CRITICAL &&
11843 block->id != TNG_TRAJECTORY_FRAME_SET &&
11846 stat = tng_block_read_next(tng_data, block,
11848 if(stat != TNG_CRITICAL)
11850 file_pos = ftello(tng_data->input_file);
11851 if(file_pos < tng_data->input_file_len)
11853 stat = tng_block_header_read(tng_data, block);
11857 if(stat == TNG_CRITICAL)
11859 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11860 file_pos, __FILE__, __LINE__);
11861 tng_block_destroy(&block);
11865 if(block->id == TNG_TRAJECTORY_FRAME_SET)
11867 fseeko(tng_data->input_file, file_pos, SEEK_SET);
11871 tng_block_destroy(&block);
11873 return(TNG_SUCCESS);
11877 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_current_only_data_from_block_id
11878 (const tng_trajectory_t tng_data,
11879 const char hash_mode,
11880 const int64_t block_id)
11883 tng_gen_block_t block;
11884 tng_function_status stat;
11885 int found_flag = 1;
11887 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11889 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
11891 return(TNG_CRITICAL);
11894 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
11898 /* No current frame set. This means that the first frame set must be
11901 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
11906 fseeko(tng_data->input_file,
11912 return(TNG_FAILURE);
11915 tng_block_init(&block);
11917 /* Read block headers first to see what block is found. */
11918 stat = tng_block_header_read(tng_data, block);
11919 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11921 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11922 file_pos, __FILE__, __LINE__);
11923 tng_block_destroy(&block);
11924 return(TNG_CRITICAL);
11926 /* If the current frame set had already been read skip its block contents */
11929 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
11931 /* Otherwise read the frame set block */
11934 stat = tng_block_read_next(tng_data, block,
11936 if(stat != TNG_SUCCESS)
11938 fprintf(stderr, "TNG library: Cannot read frame set block. %s: %d\n", __FILE__, __LINE__);
11939 tng_block_destroy(&block);
11943 file_pos = ftello(tng_data->input_file);
11947 /* Read only blocks of the requested ID
11948 * until next frame set block */
11949 stat = tng_block_header_read(tng_data, block);
11950 while(file_pos < tng_data->input_file_len &&
11951 stat != TNG_CRITICAL &&
11952 block->id != TNG_TRAJECTORY_FRAME_SET &&
11955 if(block->id == block_id)
11957 stat = tng_block_read_next(tng_data, block,
11959 if(stat != TNG_CRITICAL)
11961 file_pos = ftello(tng_data->input_file);
11963 if(file_pos < tng_data->input_file_len)
11965 stat = tng_block_header_read(tng_data, block);
11971 file_pos += block->block_contents_size + block->header_contents_size;
11972 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
11973 if(file_pos < tng_data->input_file_len)
11975 stat = tng_block_header_read(tng_data, block);
11979 if(stat == TNG_CRITICAL)
11981 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11982 file_pos, __FILE__, __LINE__);
11983 tng_block_destroy(&block);
11987 if(block->id == TNG_TRAJECTORY_FRAME_SET)
11989 fseeko(tng_data->input_file, file_pos, SEEK_SET);
11992 tng_block_destroy(&block);
11996 return(TNG_SUCCESS);
12000 return(TNG_FAILURE);
12004 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next
12005 (const tng_trajectory_t tng_data,
12006 const char hash_mode)
12010 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12012 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12014 return(TNG_CRITICAL);
12017 file_pos = tng_data->current_trajectory_frame_set.next_frame_set_file_pos;
12019 if(file_pos < 0 && tng_data->current_trajectory_frame_set_input_file_pos <= 0)
12021 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
12026 fseeko(tng_data->input_file,
12032 return(TNG_FAILURE);
12035 return(tng_frame_set_read(tng_data, hash_mode));
12038 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next_only_data_from_block_id
12039 (const tng_trajectory_t tng_data,
12040 const char hash_mode,
12041 const int64_t block_id)
12044 tng_gen_block_t block;
12045 tng_function_status stat;
12047 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12049 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12051 return(TNG_CRITICAL);
12054 file_pos = tng_data->current_trajectory_frame_set.next_frame_set_file_pos;
12056 if(file_pos < 0 && tng_data->current_trajectory_frame_set_input_file_pos <= 0)
12058 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
12063 fseeko(tng_data->input_file,
12069 return(TNG_FAILURE);
12072 tng_block_init(&block);
12074 /* Read block headers first to see what block is found. */
12075 stat = tng_block_header_read(tng_data, block);
12076 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12078 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12079 file_pos, __FILE__, __LINE__);
12080 tng_block_destroy(&block);
12081 return(TNG_CRITICAL);
12084 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
12086 if(tng_block_read_next(tng_data, block,
12087 hash_mode) == TNG_SUCCESS)
12089 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, hash_mode, block_id);
12092 tng_block_destroy(&block);
12097 tng_function_status tng_frame_set_write
12098 (const tng_trajectory_t tng_data,
12099 const char hash_mode)
12102 tng_gen_block_t block;
12103 tng_trajectory_frame_set_t frame_set;
12104 tng_function_status stat;
12106 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12108 frame_set = &tng_data->current_trajectory_frame_set;
12110 if(frame_set->n_written_frames == frame_set->n_frames)
12112 return(TNG_SUCCESS);
12115 tng_data->current_trajectory_frame_set_output_file_pos =
12116 ftello(tng_data->output_file);
12117 tng_data->last_trajectory_frame_set_output_file_pos =
12118 tng_data->current_trajectory_frame_set_output_file_pos;
12120 if(tng_data->current_trajectory_frame_set_output_file_pos <= 0)
12122 return(TNG_FAILURE);
12125 if(tng_data->first_trajectory_frame_set_output_file_pos == -1)
12127 tng_data->first_trajectory_frame_set_output_file_pos =
12128 tng_data->current_trajectory_frame_set_output_file_pos;
12131 tng_block_init(&block);
12133 if(tng_frame_set_block_write(tng_data, block, hash_mode) != TNG_SUCCESS)
12135 tng_block_destroy(&block);
12136 return(TNG_FAILURE);
12139 /* Write non-particle data blocks */
12140 for(i = 0; i<frame_set->n_data_blocks; i++)
12142 block->id = frame_set->tr_data[i].block_id;
12143 tng_data_block_write(tng_data, block, i, TNG_FALSE, 0, hash_mode);
12145 /* Write the mapping blocks and particle data blocks*/
12146 if(frame_set->n_mapping_blocks)
12148 for(i = 0; i < frame_set->n_mapping_blocks; i++)
12150 block->id = TNG_PARTICLE_MAPPING;
12151 if(frame_set->mappings[i].n_particles > 0)
12153 tng_trajectory_mapping_block_write(tng_data, block, i, hash_mode);
12154 for(j = 0; j<frame_set->n_particle_data_blocks; j++)
12156 block->id = frame_set->tr_particle_data[j].block_id;
12157 tng_data_block_write(tng_data, block,
12158 j, TNG_TRUE, &frame_set->mappings[i],
12166 for(i = 0; i<frame_set->n_particle_data_blocks; i++)
12168 block->id = frame_set->tr_particle_data[i].block_id;
12169 tng_data_block_write(tng_data, block,
12170 i, TNG_TRUE, 0, hash_mode);
12175 /* Update pointers in the general info block */
12176 stat = tng_header_pointers_update(tng_data, hash_mode);
12178 if(stat == TNG_SUCCESS)
12180 stat = tng_frame_set_pointers_update(tng_data, hash_mode);
12183 tng_block_destroy(&block);
12185 frame_set->n_unwritten_frames = 0;
12187 fflush(tng_data->output_file);
12192 tng_function_status DECLSPECDLLEXPORT tng_frame_set_premature_write
12193 (const tng_trajectory_t tng_data,
12194 const char hash_mode)
12196 tng_trajectory_frame_set_t frame_set;
12198 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12200 frame_set = &tng_data->current_trajectory_frame_set;
12202 if(frame_set->n_unwritten_frames == 0)
12204 return(TNG_SUCCESS);
12206 frame_set->n_frames = frame_set->n_unwritten_frames;
12208 return(tng_frame_set_write(tng_data, hash_mode));
12211 tng_function_status DECLSPECDLLEXPORT tng_frame_set_new
12212 (const tng_trajectory_t tng_data,
12213 const int64_t first_frame,
12214 const int64_t n_frames)
12216 tng_gen_block_t block;
12217 tng_trajectory_frame_set_t frame_set;
12218 FILE *temp = tng_data->input_file;
12219 int64_t curr_file_pos;
12221 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12222 TNG_ASSERT(first_frame >= 0, "TNG library: first_frame must be >= 0.");
12223 TNG_ASSERT(n_frames >= 0, "TNG library: n_frames must be >= 0.");
12225 frame_set = &tng_data->current_trajectory_frame_set;
12227 curr_file_pos = ftello(tng_data->output_file);
12229 if(curr_file_pos <= 10)
12231 tng_file_headers_write(tng_data, TNG_USE_HASH);
12234 /* Set pointer to previous frame set to the one that was loaded
12236 * FIXME: This is a bit risky. If they are not added in order
12237 * it will be wrong. */
12238 if(tng_data->n_trajectory_frame_sets)
12240 frame_set->prev_frame_set_file_pos =
12241 tng_data->last_trajectory_frame_set_output_file_pos;
12244 frame_set->next_frame_set_file_pos = -1;
12246 tng_data->current_trajectory_frame_set_output_file_pos =
12247 ftello(tng_data->output_file);
12249 tng_data->n_trajectory_frame_sets++;
12251 /* Set the medium range pointers */
12252 if(tng_data->n_trajectory_frame_sets == tng_data->medium_stride_length + 1)
12254 frame_set->medium_stride_prev_frame_set_file_pos =
12255 tng_data->first_trajectory_frame_set_output_file_pos;
12257 else if(tng_data->n_trajectory_frame_sets > tng_data->medium_stride_length + 1)
12259 /* FIXME: Currently only working if the previous frame set has its
12260 * medium stride pointer already set. This might need some fixing. */
12261 if(frame_set->medium_stride_prev_frame_set_file_pos != -1 &&
12262 frame_set->medium_stride_prev_frame_set_file_pos != 0)
12264 tng_block_init(&block);
12265 tng_data->input_file = tng_data->output_file;
12267 curr_file_pos = ftello(tng_data->output_file);
12268 fseeko(tng_data->output_file,
12269 frame_set->medium_stride_prev_frame_set_file_pos,
12272 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
12274 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
12275 __FILE__, __LINE__);
12276 tng_data->input_file = temp;
12277 tng_block_destroy(&block);
12278 return(TNG_CRITICAL);
12281 /* Read the next frame set from the previous frame set and one
12282 * medium stride step back */
12283 fseeko(tng_data->output_file, block->block_contents_size - (6 *
12284 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
12285 if(fread(&frame_set->medium_stride_prev_frame_set_file_pos,
12286 sizeof(frame_set->medium_stride_prev_frame_set_file_pos),
12287 1, tng_data->output_file) == 0)
12289 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
12290 tng_data->input_file = temp;
12291 tng_block_destroy(&block);
12292 return(TNG_CRITICAL);
12295 if(tng_data->input_endianness_swap_func_64)
12297 if(tng_data->input_endianness_swap_func_64(tng_data,
12298 &frame_set->medium_stride_prev_frame_set_file_pos)
12301 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
12302 __FILE__, __LINE__);
12306 tng_block_destroy(&block);
12308 /* Set the long range pointers */
12309 if(tng_data->n_trajectory_frame_sets == tng_data->long_stride_length + 1)
12311 frame_set->long_stride_prev_frame_set_file_pos =
12312 tng_data->first_trajectory_frame_set_output_file_pos;
12314 else if(tng_data->n_trajectory_frame_sets > tng_data->medium_stride_length + 1)
12316 /* FIXME: Currently only working if the previous frame set has its
12317 * long stride pointer already set. This might need some fixing. */
12318 if(frame_set->long_stride_prev_frame_set_file_pos != -1 &&
12319 frame_set->long_stride_prev_frame_set_file_pos != 0)
12321 tng_block_init(&block);
12322 tng_data->input_file = tng_data->output_file;
12324 fseeko(tng_data->output_file,
12325 frame_set->long_stride_prev_frame_set_file_pos,
12328 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
12330 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
12331 __FILE__, __LINE__);
12332 tng_data->input_file = temp;
12333 tng_block_destroy(&block);
12334 return(TNG_CRITICAL);
12337 /* Read the next frame set from the previous frame set and one
12338 * long stride step back */
12339 fseeko(tng_data->output_file, block->block_contents_size - (6 *
12340 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
12342 tng_block_destroy(&block);
12344 if(fread(&frame_set->long_stride_prev_frame_set_file_pos,
12345 sizeof(frame_set->long_stride_prev_frame_set_file_pos),
12346 1, tng_data->output_file) == 0)
12348 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
12349 tng_data->input_file = temp;
12350 return(TNG_CRITICAL);
12353 if(tng_data->input_endianness_swap_func_64)
12355 if(tng_data->input_endianness_swap_func_64(tng_data,
12356 &frame_set->long_stride_prev_frame_set_file_pos)
12359 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
12360 __FILE__, __LINE__);
12367 tng_data->input_file = temp;
12368 fseeko(tng_data->output_file, curr_file_pos, SEEK_SET);
12372 frame_set->first_frame = first_frame;
12373 frame_set->n_frames = n_frames;
12374 frame_set->n_written_frames = 0;
12375 frame_set->n_unwritten_frames = 0;
12376 frame_set->first_frame_time = -1;
12378 if(tng_data->first_trajectory_frame_set_output_file_pos == -1 ||
12379 tng_data->first_trajectory_frame_set_output_file_pos == 0)
12381 tng_data->first_trajectory_frame_set_output_file_pos =
12382 tng_data->current_trajectory_frame_set_output_file_pos;
12384 /* FIXME: Should check the frame number instead of the file_pos,
12385 * in case frame sets are not in order */
12386 if(tng_data->last_trajectory_frame_set_output_file_pos == -1 ||
12387 tng_data->last_trajectory_frame_set_output_file_pos == 0 ||
12388 tng_data->last_trajectory_frame_set_output_file_pos <
12389 tng_data->current_trajectory_frame_set_output_file_pos)
12391 tng_data->last_trajectory_frame_set_output_file_pos =
12392 tng_data->current_trajectory_frame_set_output_file_pos;
12395 return(TNG_SUCCESS);
12398 tng_function_status DECLSPECDLLEXPORT tng_frame_set_with_time_new
12399 (const tng_trajectory_t tng_data,
12400 const int64_t first_frame,
12401 const int64_t n_frames,
12402 const double first_frame_time)
12404 tng_function_status stat;
12406 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12407 TNG_ASSERT(first_frame >= 0, "TNG library: first_frame must be >= 0.");
12408 TNG_ASSERT(n_frames >= 0, "TNG library: n_frames must be >= 0.");
12409 TNG_ASSERT(first_frame_time >= 0, "TNG library: first_frame_time must be >= 0.");
12412 stat = tng_frame_set_new(tng_data, first_frame, n_frames);
12413 if(stat != TNG_SUCCESS)
12417 stat = tng_frame_set_first_frame_time_set(tng_data, first_frame_time);
12422 tng_function_status DECLSPECDLLEXPORT tng_frame_set_first_frame_time_set
12423 (const tng_trajectory_t tng_data,
12424 const double first_frame_time)
12426 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12427 TNG_ASSERT(first_frame_time >= 0, "TNG library: first_frame_time must be >= 0.");
12429 tng_data->current_trajectory_frame_set.first_frame_time = first_frame_time;
12431 return(TNG_SUCCESS);
12434 tng_function_status DECLSPECDLLEXPORT tng_first_frame_nr_of_next_frame_set_get
12435 (const tng_trajectory_t tng_data,
12438 int64_t file_pos, next_frame_set_file_pos;
12439 tng_gen_block_t block;
12440 tng_function_status stat;
12442 tng_trajectory_frame_set_t frame_set;
12444 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12445 TNG_ASSERT(tng_data->input_file, "TNG library: An input file must be open to find the next frame set");
12446 TNG_ASSERT(frame, "TNG library: frame must not be a NULL pointer");
12448 file_pos = ftello(tng_data->input_file);
12450 if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
12452 next_frame_set_file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
12456 frame_set = &tng_data->current_trajectory_frame_set;
12457 next_frame_set_file_pos = frame_set->next_frame_set_file_pos;
12460 if(next_frame_set_file_pos <= 0)
12462 return(TNG_FAILURE);
12465 fseeko(tng_data->input_file, next_frame_set_file_pos, SEEK_SET);
12466 /* Read block headers first to see that a frame set block is found. */
12467 tng_block_init(&block);
12468 stat = tng_block_header_read(tng_data, block);
12469 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12471 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12472 file_pos, __FILE__, __LINE__);
12473 return(TNG_CRITICAL);
12475 /* if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
12477 tng_block_read_next(tng_data, block, TNG_USE_HASH);
12479 tng_block_destroy(&block);
12481 if(fread(frame, sizeof(int64_t), 1, tng_data->input_file) == 0)
12483 fprintf(stderr, "TNG library: Cannot read first frame of next frame set. %s: %d\n",
12484 __FILE__, __LINE__);
12485 return(TNG_CRITICAL);
12487 fseeko(tng_data->input_file, file_pos, SEEK_SET);
12489 return(TNG_SUCCESS);
12492 static tng_function_status tng_gen_data_block_add
12493 (const tng_trajectory_t tng_data,
12495 const tng_bool is_particle_data,
12496 const char *block_name,
12497 const char datatype,
12498 const char block_type_flag,
12500 const int64_t n_values_per_frame,
12501 int64_t stride_length,
12502 const int64_t num_first_particle,
12503 const int64_t n_particles,
12504 const int64_t codec_id,
12509 int64_t tot_n_particles, n_frames_div;
12510 char ***first_dim_values, **second_dim_values;
12511 tng_trajectory_frame_set_t frame_set;
12513 char *new_data_c=new_data;
12514 tng_function_status stat;
12516 frame_set = &tng_data->current_trajectory_frame_set;
12518 if(stride_length <= 0)
12523 if(is_particle_data)
12525 stat = tng_particle_data_find(tng_data, id, &data);
12529 stat = tng_data_find(tng_data, id, &data);
12531 /* If the block does not exist, create it */
12532 if(stat != TNG_SUCCESS)
12534 if(is_particle_data)
12536 stat = tng_particle_data_block_create(tng_data, block_type_flag);
12540 stat = tng_data_block_create(tng_data, block_type_flag);
12543 if(stat != TNG_SUCCESS)
12545 fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
12546 __FILE__, __LINE__);
12547 return(TNG_CRITICAL);
12549 if(is_particle_data)
12551 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
12553 data = &frame_set->tr_particle_data[frame_set->
12554 n_particle_data_blocks - 1];
12558 data = &tng_data->non_tr_particle_data[tng_data->
12559 n_particle_data_blocks - 1];
12564 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
12566 data = &frame_set->tr_data[frame_set->n_data_blocks - 1];
12570 data = &tng_data->non_tr_data[tng_data->n_data_blocks - 1];
12573 data->block_id = id;
12575 data->block_name = malloc(strlen(block_name) + 1);
12576 if(!data->block_name)
12578 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n",
12579 (unsigned int)strlen(block_name)+1, __FILE__, __LINE__);
12580 return(TNG_CRITICAL);
12582 strncpy(data->block_name, block_name, strlen(block_name) + 1);
12585 /* FIXME: Memory leak from strings. */
12587 data->last_retrieved_frame = -1;
12590 data->datatype = datatype;
12591 data->stride_length = tng_max_i64(stride_length, 1);
12592 data->n_values_per_frame = n_values_per_frame;
12593 data->n_frames = n_frames;
12594 if(is_particle_data)
12596 data->dependency = TNG_PARTICLE_DEPENDENT;
12600 data->dependency = 0;
12602 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
12604 frame_set->n_frames == n_frames ||
12605 stride_length > 1))
12607 data->dependency += TNG_FRAME_DEPENDENT;
12609 data->codec_id = codec_id;
12610 data->compression_multiplier = 1.0;
12611 /* FIXME: This can cause problems. */
12612 data->first_frame_with_data = frame_set->first_frame;
12614 if(is_particle_data)
12616 if(block_type_flag == TNG_TRAJECTORY_BLOCK && tng_data->var_num_atoms_flag)
12618 tot_n_particles = frame_set->n_particles;
12622 tot_n_particles = tng_data->n_particles;
12625 /* This is just to keep the compiler happy - avoid it considering tot_n_particles
12626 * uninitialized. */
12629 tot_n_particles = 0;
12632 /* If data values are supplied add that data to the data block. */
12635 /* Allocate memory */
12636 if(is_particle_data)
12638 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
12639 stride_length, tot_n_particles,
12640 n_values_per_frame);
12644 stat = tng_allocate_data_mem(tng_data, data, n_frames, stride_length,
12645 n_values_per_frame);
12647 if(stat != TNG_SUCCESS)
12649 fprintf(stderr, "TNG library: Cannot allocate particle data memory. %s: %d\n",
12650 __FILE__, __LINE__);
12651 return(TNG_CRITICAL);
12654 if(n_frames > frame_set->n_unwritten_frames)
12656 frame_set->n_unwritten_frames = n_frames;
12659 n_frames_div = (n_frames % stride_length) ?
12660 n_frames / stride_length + 1:
12661 n_frames / stride_length;
12663 if(datatype == TNG_CHAR_DATA)
12665 if(is_particle_data)
12667 for(i = 0; i < n_frames_div; i++)
12669 first_dim_values = data->strings[i];
12670 for(j = num_first_particle; j < num_first_particle + n_particles;
12673 second_dim_values = first_dim_values[j];
12674 for(k = 0; k < n_values_per_frame; k++)
12676 len = tng_min_size(strlen(new_data_c) + 1,
12678 if(second_dim_values[k])
12680 free(second_dim_values[k]);
12682 second_dim_values[k] = malloc(len);
12683 if(!second_dim_values[k])
12685 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
12686 len, __FILE__, __LINE__);
12687 return(TNG_CRITICAL);
12689 strncpy(second_dim_values[k],
12698 for(i = 0; i < n_frames_div; i++)
12700 second_dim_values = data->strings[0][i];
12701 for(j = 0; j < n_values_per_frame; j++)
12703 len = tng_min_size(strlen(new_data_c) + 1,
12705 if(second_dim_values[j])
12707 free(second_dim_values[j]);
12709 second_dim_values[j] = malloc(len);
12710 if(!second_dim_values[j])
12712 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
12713 len, __FILE__, __LINE__);
12714 return(TNG_CRITICAL);
12716 strncpy(second_dim_values[j],
12728 size = sizeof(int64_t);
12730 case TNG_FLOAT_DATA:
12731 size = sizeof(float);
12733 case TNG_DOUBLE_DATA:
12735 size = sizeof(double);
12738 if(is_particle_data)
12740 memcpy(data->values, new_data, size * n_frames_div *
12741 n_particles * n_values_per_frame);
12745 memcpy(data->values, new_data, size * n_frames_div *
12746 n_values_per_frame);
12751 return(TNG_SUCCESS);
12754 tng_function_status DECLSPECDLLEXPORT tng_data_block_add
12755 (const tng_trajectory_t tng_data,
12757 const char *block_name,
12758 const char datatype,
12759 const char block_type_flag,
12761 const int64_t n_values_per_frame,
12762 int64_t stride_length,
12763 const int64_t codec_id,
12766 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12767 TNG_ASSERT(block_name, "TNG library: block_name must not be a NULL pointer.");
12768 TNG_ASSERT(n_values_per_frame > 0, "TNG library: n_values_per_frame must be a positive integer.");
12770 return(tng_gen_data_block_add(tng_data, id, TNG_FALSE, block_name, datatype,
12771 block_type_flag, n_frames, n_values_per_frame,
12772 stride_length, 0, 0, codec_id, new_data));
12775 tng_function_status DECLSPECDLLEXPORT tng_particle_data_block_add
12776 (const tng_trajectory_t tng_data,
12778 const char *block_name,
12779 const char datatype,
12780 const char block_type_flag,
12782 const int64_t n_values_per_frame,
12783 int64_t stride_length,
12784 const int64_t num_first_particle,
12785 const int64_t n_particles,
12786 const int64_t codec_id,
12789 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12790 TNG_ASSERT(block_name, "TNG library: block_name mustnot be a NULL pointer.");
12791 TNG_ASSERT(n_values_per_frame > 0, "TNG library: n_values_per_frame must be a positive integer.");
12792 TNG_ASSERT(num_first_particle >= 0, "TNG library: num_first_particle must be >= 0.");
12793 TNG_ASSERT(n_particles >= 0, "TNG library: n_particles must be >= 0.");
12795 return(tng_gen_data_block_add(tng_data, id, TNG_TRUE, block_name, datatype,
12796 block_type_flag, n_frames, n_values_per_frame,
12797 stride_length, num_first_particle, n_particles,
12798 codec_id, new_data));
12801 tng_function_status DECLSPECDLLEXPORT tng_data_block_name_get
12802 (const tng_trajectory_t tng_data,
12803 const int64_t block_id,
12808 tng_trajectory_frame_set_t frame_set;
12809 tng_function_status stat;
12811 int block_type = -1;
12813 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12814 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
12816 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
12818 data = &tng_data->non_tr_particle_data[i];
12819 if(data->block_id == block_id)
12821 strncpy(name, data->block_name, max_len);
12822 name[max_len - 1] = '\0';
12823 return(TNG_SUCCESS);
12826 for(i = 0; i < tng_data->n_data_blocks; i++)
12828 data = &tng_data->non_tr_data[i];
12829 if(data->block_id == block_id)
12831 strncpy(name, data->block_name, max_len);
12832 name[max_len - 1] = '\0';
12833 return(TNG_SUCCESS);
12837 frame_set = &tng_data->current_trajectory_frame_set;
12839 stat = tng_particle_data_find(tng_data, block_id, &data);
12840 if(stat == TNG_SUCCESS)
12842 block_type = TNG_PARTICLE_BLOCK_DATA;
12846 stat = tng_data_find(tng_data, block_id, &data);
12847 if(stat == TNG_SUCCESS)
12849 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
12853 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
12854 if(stat != TNG_SUCCESS)
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;
12873 if(block_type == TNG_PARTICLE_BLOCK_DATA)
12875 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
12877 data = &frame_set->tr_particle_data[i];
12878 if(data->block_id == block_id)
12880 strncpy(name, data->block_name, max_len);
12881 name[max_len - 1] = '\0';
12882 return(TNG_SUCCESS);
12886 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
12888 for(i = 0; i < frame_set->n_data_blocks; i++)
12890 data = &frame_set->tr_data[i];
12891 if(data->block_id == block_id)
12893 strncpy(name, data->block_name, max_len);
12894 name[max_len - 1] = '\0';
12895 return(TNG_SUCCESS);
12900 return(TNG_FAILURE);
12903 tng_function_status DECLSPECDLLEXPORT tng_data_block_dependency_get
12904 (const tng_trajectory_t tng_data,
12905 const int64_t block_id,
12906 int *block_dependency)
12909 tng_function_status stat;
12912 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12913 TNG_ASSERT(block_dependency, "TNG library: block_dependency must not be a NULL pointer.");
12915 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
12917 data = &tng_data->non_tr_particle_data[i];
12918 if(data->block_id == block_id)
12920 *block_dependency = TNG_PARTICLE_DEPENDENT;
12921 return(TNG_SUCCESS);
12924 for(i = 0; i < tng_data->n_data_blocks; i++)
12926 data = &tng_data->non_tr_data[i];
12927 if(data->block_id == block_id)
12929 *block_dependency = 0;
12930 return(TNG_SUCCESS);
12934 stat = tng_particle_data_find(tng_data, block_id, &data);
12935 if(stat == TNG_SUCCESS)
12937 *block_dependency = TNG_PARTICLE_DEPENDENT + TNG_FRAME_DEPENDENT;
12938 return(TNG_SUCCESS);
12942 stat = tng_data_find(tng_data, block_id, &data);
12943 if(stat == TNG_SUCCESS)
12945 *block_dependency = TNG_FRAME_DEPENDENT;
12946 return(TNG_SUCCESS);
12950 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
12951 if(stat != TNG_SUCCESS)
12955 stat = tng_particle_data_find(tng_data, block_id, &data);
12956 if(stat == TNG_SUCCESS)
12958 *block_dependency = TNG_PARTICLE_DEPENDENT + TNG_FRAME_DEPENDENT;
12959 return(TNG_SUCCESS);
12963 stat = tng_data_find(tng_data, block_id, &data);
12964 if(stat == TNG_SUCCESS)
12966 *block_dependency = TNG_FRAME_DEPENDENT;
12967 return(TNG_SUCCESS);
12973 return(TNG_FAILURE);
12976 tng_function_status DECLSPECDLLEXPORT tng_data_block_num_values_per_frame_get
12977 (const tng_trajectory_t tng_data,
12978 const int64_t block_id,
12979 int64_t *n_values_per_frame)
12982 tng_function_status stat;
12985 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12986 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
12988 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
12990 data = &tng_data->non_tr_particle_data[i];
12991 if(data->block_id == block_id)
12993 *n_values_per_frame = data->n_values_per_frame;
12994 return(TNG_SUCCESS);
12997 for(i = 0; i < tng_data->n_data_blocks; i++)
12999 data = &tng_data->non_tr_data[i];
13000 if(data->block_id == block_id)
13002 *n_values_per_frame = data->n_values_per_frame;
13003 return(TNG_SUCCESS);
13007 stat = tng_particle_data_find(tng_data, block_id, &data);
13008 if(stat == TNG_SUCCESS)
13010 *n_values_per_frame = data->n_values_per_frame;
13011 return(TNG_SUCCESS);
13015 stat = tng_data_find(tng_data, block_id, &data);
13016 if(stat == TNG_SUCCESS)
13018 *n_values_per_frame = data->n_values_per_frame;
13019 return(TNG_SUCCESS);
13023 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
13024 if(stat != TNG_SUCCESS)
13028 stat = tng_particle_data_find(tng_data, block_id, &data);
13029 if(stat == TNG_SUCCESS)
13031 *n_values_per_frame = data->n_values_per_frame;
13032 return(TNG_SUCCESS);
13036 stat = tng_data_find(tng_data, block_id, &data);
13037 if(stat == TNG_SUCCESS)
13039 *n_values_per_frame = data->n_values_per_frame;
13040 return(TNG_SUCCESS);
13046 return(TNG_FAILURE);
13049 tng_function_status DECLSPECDLLEXPORT tng_frame_set_n_frames_of_data_block_get
13050 (const tng_trajectory_t tng_data,
13051 const int64_t block_id,
13054 tng_gen_block_t block;
13055 tng_function_status stat;
13056 char datatype, dependency, sparse_data;
13057 int64_t n_values, codec_id, first_frame_with_data, stride_length, curr_n_frames;
13058 int64_t num_first_particle, block_n_particles;
13060 md5_state_t md5_state;
13061 int found = TNG_FALSE;
13063 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13065 tng_block_init(&block);
13067 stat = tng_block_header_read(tng_data, block);
13068 /* If the block header could not be read the reading position might not have been
13069 * at the start of a block. Try again from the file position of the current frame
13071 if(stat != TNG_SUCCESS)
13073 fseeko(tng_data->input_file, tng_data->current_trajectory_frame_set_input_file_pos, SEEK_SET);
13074 stat = tng_block_header_read(tng_data, block);
13075 if(stat != TNG_SUCCESS)
13077 tng_block_destroy(&block);
13081 if(block->id == TNG_TRAJECTORY_FRAME_SET)
13083 stat = tng_block_read_next(tng_data, block, TNG_SKIP_HASH);
13084 if(stat != TNG_SUCCESS)
13086 tng_block_destroy(&block);
13089 stat = tng_block_header_read(tng_data, block);
13091 while(stat == TNG_SUCCESS && block->id != TNG_TRAJECTORY_FRAME_SET && found == TNG_FALSE)
13093 if(block->id == block_id)
13095 stat = tng_data_block_meta_information_read(tng_data, &datatype,
13096 &dependency, &sparse_data,
13097 &n_values, &codec_id,
13098 &first_frame_with_data,
13099 &stride_length, &curr_n_frames,
13100 &num_first_particle,
13101 &block_n_particles,
13102 &multiplier, TNG_SKIP_HASH,
13104 if(stat == TNG_SUCCESS)
13111 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
13112 stat = tng_block_header_read(tng_data, block);
13115 if(found == TNG_TRUE)
13117 *n_frames = (tng_data->current_trajectory_frame_set.n_frames -
13118 (tng_data->current_trajectory_frame_set.first_frame - first_frame_with_data)) / stride_length;
13120 else if(stat == TNG_SUCCESS)
13125 tng_block_destroy(&block);
13130 static tng_function_status tng_frame_gen_data_write
13131 (const tng_trajectory_t tng_data,
13132 const int64_t frame_nr,
13133 const int64_t block_id,
13134 const tng_bool is_particle_data,
13135 const int64_t val_first_particle,
13136 const int64_t val_n_particles,
13137 const void *values,
13138 const char hash_mode)
13140 int64_t header_pos, file_pos, tot_n_particles;
13141 int64_t output_file_len, n_values_per_frame, size, contents_size;
13142 int64_t header_size, temp_first, temp_last;
13143 int64_t mapping_block_end_pos, num_first_particle, block_n_particles;
13144 int64_t i, last_frame, temp_current, write_n_particles;
13145 tng_gen_block_t block;
13146 tng_trajectory_frame_set_t frame_set;
13147 FILE *temp = tng_data->input_file;
13148 struct tng_data data;
13149 tng_function_status stat;
13150 tng_particle_mapping_t mapping;
13151 char dependency, sparse_data, datatype;
13154 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
13156 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
13157 __FILE__, __LINE__);
13158 return(TNG_CRITICAL);
13161 temp_first = tng_data->first_trajectory_frame_set_input_file_pos;
13162 temp_last = tng_data->last_trajectory_frame_set_input_file_pos;
13163 temp_current = tng_data->current_trajectory_frame_set_input_file_pos;
13164 tng_data->first_trajectory_frame_set_input_file_pos =
13165 tng_data->first_trajectory_frame_set_output_file_pos;
13166 tng_data->last_trajectory_frame_set_input_file_pos =
13167 tng_data->last_trajectory_frame_set_output_file_pos;
13168 tng_data->current_trajectory_frame_set_input_file_pos =
13169 tng_data->current_trajectory_frame_set_output_file_pos;
13171 tng_data->input_file = tng_data->output_file;
13173 stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
13175 frame_set = &tng_data->current_trajectory_frame_set;
13177 if(stat != TNG_SUCCESS)
13179 last_frame = frame_set->first_frame +
13180 frame_set->n_frames - 1;
13181 /* If the wanted frame would be in the frame set after the last
13182 * frame set create a new frame set. */
13183 if(stat == TNG_FAILURE &&
13184 last_frame < frame_nr)
13185 /* (last_frame < frame_nr &&
13186 tng_data->current_trajectory_frame_set.first_frame +
13187 tng_data->frame_set_n_frames >= frame_nr))*/
13189 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
13191 last_frame = frame_nr - 1;
13193 tng_frame_set_new(tng_data,
13195 tng_data->frame_set_n_frames);
13196 file_pos = ftello(tng_data->output_file);
13197 fseeko(tng_data->output_file, 0, SEEK_END);
13198 output_file_len = ftello(tng_data->output_file);
13199 fseeko(tng_data->output_file, file_pos, SEEK_SET);
13201 /* Read mapping blocks from the last frame set */
13202 tng_block_init(&block);
13204 stat = tng_block_header_read(tng_data, block);
13205 while(file_pos < output_file_len &&
13206 stat != TNG_CRITICAL &&
13207 block->id != TNG_TRAJECTORY_FRAME_SET &&
13210 if(block->id == TNG_PARTICLE_MAPPING)
13212 tng_trajectory_mapping_block_read(tng_data, block,
13217 fseeko(tng_data->output_file, block->block_contents_size,
13220 file_pos = ftello(tng_data->output_file);
13221 if(file_pos < output_file_len)
13223 stat = tng_block_header_read(tng_data, block);
13227 tng_block_destroy(&block);
13228 /* Write the frame set to disk */
13229 if(tng_frame_set_write(tng_data, hash_mode) != TNG_SUCCESS)
13231 fprintf(stderr, "TNG library: Error writing frame set. %s: %d\n", __FILE__, __LINE__);
13232 return(TNG_CRITICAL);
13237 tng_data->input_file = temp;
13238 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13239 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13240 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13245 tng_block_init(&block);
13247 file_pos = tng_data->current_trajectory_frame_set_output_file_pos;
13249 fseeko(tng_data->output_file, 0, SEEK_END);
13250 output_file_len = ftello(tng_data->output_file);
13251 fseeko(tng_data->output_file, file_pos, SEEK_SET);
13253 /* Read past the frame set block first */
13254 stat = tng_block_header_read(tng_data, block);
13255 if(stat == TNG_CRITICAL)
13257 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
13258 file_pos, __FILE__, __LINE__);
13259 tng_block_destroy(&block);
13260 tng_data->input_file = temp;
13262 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13263 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13264 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13267 fseeko(tng_data->output_file, block->block_contents_size,
13270 if(is_particle_data == TNG_TRUE)
13272 if(tng_data->var_num_atoms_flag)
13274 tot_n_particles = frame_set->n_particles;
13278 tot_n_particles = tng_data->n_particles;
13281 if(val_n_particles < tot_n_particles)
13283 mapping_block_end_pos = -1;
13284 /* Read all mapping blocks to find the right place to put the data */
13285 stat = tng_block_header_read(tng_data, block);
13286 while(file_pos < output_file_len &&
13287 stat != TNG_CRITICAL &&
13288 block->id != TNG_TRAJECTORY_FRAME_SET &&
13291 if(block->id == TNG_PARTICLE_MAPPING)
13293 tng_trajectory_mapping_block_read(tng_data, block, hash_mode);
13297 fseeko(tng_data->output_file, block->block_contents_size,
13300 file_pos = ftello(tng_data->output_file);
13301 if(block->id == TNG_PARTICLE_MAPPING)
13303 mapping = &frame_set->mappings[frame_set->n_mapping_blocks - 1];
13304 if(val_first_particle >= mapping->num_first_particle &&
13305 val_first_particle < mapping->num_first_particle +
13306 mapping->n_particles &&
13307 val_first_particle + val_n_particles <=
13308 mapping->num_first_particle + mapping->n_particles)
13310 mapping_block_end_pos = file_pos;
13313 if(file_pos < output_file_len)
13315 stat = tng_block_header_read(tng_data, block);
13318 if(stat == TNG_CRITICAL)
13320 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
13321 file_pos, __FILE__, __LINE__);
13322 tng_block_destroy(&block);
13323 tng_data->input_file = temp;
13325 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13326 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13327 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13330 if(mapping_block_end_pos < 0)
13332 tng_block_destroy(&block);
13333 tng_data->input_file = temp;
13335 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13336 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13337 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13338 return(TNG_FAILURE);
13340 fseeko(tng_data->output_file, mapping_block_end_pos, SEEK_SET);
13344 /* Read all block headers until next frame set block or
13345 * until the wanted block id is found */
13346 stat = tng_block_header_read(tng_data, block);
13347 while(file_pos < output_file_len &&
13348 stat != TNG_CRITICAL &&
13349 block->id != block_id &&
13350 (is_particle_data != TNG_TRUE || block->id != TNG_PARTICLE_MAPPING) &&
13351 block->id != TNG_TRAJECTORY_FRAME_SET &&
13354 fseeko(tng_data->output_file, block->block_contents_size, SEEK_CUR);
13355 file_pos = ftello(tng_data->output_file);
13356 if(file_pos < output_file_len)
13358 stat = tng_block_header_read(tng_data, block);
13361 if(stat == TNG_CRITICAL)
13363 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
13364 file_pos, __FILE__, __LINE__);
13365 tng_block_destroy(&block);
13366 tng_data->input_file = temp;
13367 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13368 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13369 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13373 contents_size = block->block_contents_size;
13374 header_size = block->header_contents_size;
13376 header_pos = ftello(tng_data->output_file) - header_size;
13377 frame_set = &tng_data->current_trajectory_frame_set;
13379 if(tng_file_input_numerical(tng_data, &datatype,
13381 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13383 tng_block_destroy(&block);
13384 return(TNG_CRITICAL);
13386 if(tng_file_input_numerical(tng_data, &dependency,
13387 sizeof(dependency),
13388 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13390 tng_block_destroy(&block);
13391 return(TNG_CRITICAL);
13393 data.datatype = datatype;
13395 if(!(dependency & TNG_FRAME_DEPENDENT) ||
13396 (is_particle_data == TNG_FALSE && dependency & TNG_PARTICLE_DEPENDENT) ||
13397 (is_particle_data == TNG_TRUE && !(dependency & TNG_PARTICLE_DEPENDENT)))
13399 tng_block_destroy(&block);
13400 tng_data->input_file = temp;
13402 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13403 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13404 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13405 return(TNG_FAILURE);
13408 if(tng_file_input_numerical(tng_data, &sparse_data,
13409 sizeof(sparse_data),
13410 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13412 tng_block_destroy(&block);
13413 return(TNG_CRITICAL);
13416 if(tng_file_input_numerical(tng_data, &data.n_values_per_frame,
13417 sizeof(data.n_values_per_frame),
13418 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13420 tng_block_destroy(&block);
13421 return(TNG_CRITICAL);
13424 if(tng_file_input_numerical(tng_data, &data.codec_id,
13425 sizeof(data.codec_id),
13426 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13428 tng_block_destroy(&block);
13429 return(TNG_CRITICAL);
13432 if(data.codec_id != TNG_UNCOMPRESSED)
13434 if(tng_file_input_numerical(tng_data, &data.compression_multiplier,
13435 sizeof(data.compression_multiplier),
13436 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13438 tng_block_destroy(&block);
13439 return(TNG_CRITICAL);
13444 data.compression_multiplier = 1;
13449 if(tng_file_input_numerical(tng_data, &data.first_frame_with_data,
13450 sizeof(data.first_frame_with_data),
13451 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13453 tng_block_destroy(&block);
13454 return(TNG_CRITICAL);
13457 if(tng_file_input_numerical(tng_data, &data.stride_length,
13458 sizeof(data.stride_length),
13459 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13461 tng_block_destroy(&block);
13462 return(TNG_CRITICAL);
13467 data.first_frame_with_data = 0;
13468 data.stride_length = 1;
13470 data.n_frames = tng_data->current_trajectory_frame_set.n_frames;
13472 if(is_particle_data == TNG_TRUE)
13474 if(tng_file_input_numerical(tng_data, &num_first_particle,
13475 sizeof(num_first_particle),
13476 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13478 tng_block_destroy(&block);
13479 return(TNG_CRITICAL);
13482 if(tng_file_input_numerical(tng_data, &block_n_particles,
13483 sizeof(block_n_particles),
13484 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13486 tng_block_destroy(&block);
13487 return(TNG_CRITICAL);
13491 tng_data->input_file = temp;
13493 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13494 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13495 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13497 switch(data.datatype)
13499 case(TNG_INT_DATA):
13500 size = sizeof(int64_t);
13502 case(TNG_FLOAT_DATA):
13503 size = sizeof(float);
13505 case(TNG_DOUBLE_DATA):
13506 size = sizeof(double);
13509 fprintf(stderr, "TNG library: Cannot calculate writing locations. %s: %d.\n", __FILE__,
13511 tng_block_destroy(&block);
13512 return(TNG_FAILURE);
13515 n_values_per_frame = data.n_values_per_frame;
13517 file_pos = (frame_nr - tng_max_i64(frame_set->first_frame,
13518 data.first_frame_with_data)) /
13519 data.stride_length;
13520 if(is_particle_data == TNG_TRUE)
13522 file_pos *= block_n_particles * size * n_values_per_frame;
13526 file_pos *= size * n_values_per_frame;
13529 if(file_pos > contents_size)
13531 fprintf(stderr, "TNG library: Attempting to write outside the block. %s: %d\n", __FILE__,
13533 tng_block_destroy(&block);
13534 return(TNG_FAILURE);
13537 fseeko(tng_data->output_file, file_pos, SEEK_CUR);
13539 if(is_particle_data == TNG_TRUE)
13541 write_n_particles = val_n_particles;
13545 write_n_particles = 1;
13548 /* If the endianness is not big endian the data needs to be swapped */
13549 if((data.datatype == TNG_INT_DATA ||
13550 data.datatype == TNG_DOUBLE_DATA) &&
13551 tng_data->output_endianness_swap_func_64)
13553 copy = malloc(write_n_particles * n_values_per_frame * size);
13554 memcpy(copy, values, write_n_particles * n_values_per_frame * size);
13555 for(i = 0; i < write_n_particles * n_values_per_frame; i++)
13557 if(tng_data->output_endianness_swap_func_64(tng_data,
13558 (int64_t *) copy+i)
13561 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13562 __FILE__, __LINE__);
13565 fwrite(copy, write_n_particles * n_values_per_frame, size,
13566 tng_data->output_file);
13569 else if(data.datatype == TNG_FLOAT_DATA &&
13570 tng_data->output_endianness_swap_func_32)
13572 copy = 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_32(tng_data,
13577 (int32_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);
13591 fwrite(values, write_n_particles * n_values_per_frame, size, tng_data->output_file);
13594 fflush(tng_data->output_file);
13596 /* Update the number of written frames in the frame set. */
13597 if(frame_nr - frame_set->first_frame + 1 > frame_set->n_written_frames)
13599 frame_set->n_written_frames = frame_nr - frame_set->first_frame + 1;
13602 /* If the last frame has been written update the hash */
13603 if(hash_mode == TNG_USE_HASH && (frame_nr + data.stride_length -
13604 data.first_frame_with_data) >=
13605 frame_set->n_frames)
13607 tng_md5_hash_update(tng_data, block, header_pos, header_pos +
13611 tng_block_destroy(&block);
13613 return(TNG_SUCCESS);
13616 tng_function_status DECLSPECDLLEXPORT tng_frame_data_write
13617 (const tng_trajectory_t tng_data,
13618 const int64_t frame_nr,
13619 const int64_t block_id,
13620 const void *values,
13621 const char hash_mode)
13623 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13624 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
13625 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer.");
13627 /* This is now just calling the generic data writing function. This
13628 * function must keep its signature to let the API be backwards
13630 return(tng_frame_gen_data_write(tng_data, frame_nr, block_id,
13631 TNG_FALSE, 0, 0, values, hash_mode));
13634 tng_function_status DECLSPECDLLEXPORT tng_frame_particle_data_write
13635 (const tng_trajectory_t tng_data,
13636 const int64_t frame_nr,
13637 const int64_t block_id,
13638 const int64_t val_first_particle,
13639 const int64_t val_n_particles,
13640 const void *values,
13641 const char hash_mode)
13643 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13644 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
13645 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer.");
13646 TNG_ASSERT(val_first_particle >= 0, "TNG library: val_first_particle must be >= 0.");
13647 TNG_ASSERT(val_n_particles >= 0, "TNG library: val_n_particles must be >= 0.");
13649 /* This is now just calling the generic data writing function. This
13650 * function must keep its signature to let the API be backwards
13652 return(tng_frame_gen_data_write(tng_data, frame_nr, block_id,
13653 TNG_TRUE, val_first_particle, val_n_particles,
13654 values, hash_mode));
13657 static tng_function_status tng_data_values_alloc
13658 (const tng_trajectory_t tng_data,
13659 union data_values ***values,
13660 const int64_t n_frames,
13661 const int64_t n_values_per_frame,
13665 tng_function_status stat;
13667 if(n_frames <= 0 || n_values_per_frame <= 0)
13669 return(TNG_FAILURE);
13674 stat = tng_data_values_free(tng_data, *values, n_frames,
13675 n_values_per_frame,
13677 if(stat != TNG_SUCCESS)
13679 fprintf(stderr, "TNG library: Cannot free particle data values. %s: %d\n",
13680 __FILE__, __LINE__);
13684 *values = malloc(sizeof(union data_values *) * n_frames);
13687 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
13688 sizeof(union data_values **) * n_frames,
13689 __FILE__, __LINE__);
13690 return(TNG_CRITICAL);
13694 for(i = 0; i < n_frames; i++)
13696 (*values)[i] = malloc(sizeof(union data_values) *
13697 n_values_per_frame);
13700 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
13701 sizeof(union data_values) * n_values_per_frame,
13702 __FILE__, __LINE__);
13705 return(TNG_CRITICAL);
13708 return(TNG_SUCCESS);
13711 /* FIXME: This needs ***values */
13712 tng_function_status DECLSPECDLLEXPORT tng_data_values_free
13713 (const tng_trajectory_t tng_data,
13714 union data_values **values,
13715 const int64_t n_frames,
13716 const int64_t n_values_per_frame,
13724 for(i = 0; i < n_frames; i++)
13728 if(type == TNG_CHAR_DATA)
13730 for(j = 0; j < n_values_per_frame; j++)
13734 free(values[i][j].c);
13735 values[i][j].c = 0;
13747 return(TNG_SUCCESS);
13750 static tng_function_status tng_particle_data_values_alloc
13751 (const tng_trajectory_t tng_data,
13752 union data_values ****values,
13753 const int64_t n_frames,
13754 const int64_t n_particles,
13755 const int64_t n_values_per_frame,
13759 tng_function_status stat;
13761 if(n_particles == 0 || n_values_per_frame == 0)
13763 return(TNG_FAILURE);
13768 stat = tng_particle_data_values_free(tng_data, *values, n_frames,
13769 n_particles, n_values_per_frame,
13771 if(stat != TNG_SUCCESS)
13773 fprintf(stderr, "TNG library: Cannot free particle data values. %s: %d\n",
13774 __FILE__, __LINE__);
13778 *values = malloc(sizeof(union data_values **) * n_frames);
13781 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
13782 sizeof(union data_values **) * n_frames,
13783 __FILE__, __LINE__);
13784 return(TNG_CRITICAL);
13788 for(i = 0; i < n_frames; i++)
13790 (*values)[i] = malloc(sizeof(union data_values *) *
13794 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
13795 sizeof(union data_values *) * n_particles,
13796 __FILE__, __LINE__);
13799 return(TNG_CRITICAL);
13801 for(j = 0; j < n_particles; j++)
13803 (*values)[i][j] = malloc(sizeof(union data_values) *
13804 n_values_per_frame);
13805 if(!(*values)[i][j])
13807 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
13808 sizeof(union data_values *) * n_particles,
13809 __FILE__, __LINE__);
13810 tng_particle_data_values_free(tng_data, *values, n_frames,
13811 n_particles, n_values_per_frame,
13814 return(TNG_CRITICAL);
13818 return(TNG_SUCCESS);
13821 /* FIXME: This needs ****values */
13822 tng_function_status DECLSPECDLLEXPORT tng_particle_data_values_free
13823 (const tng_trajectory_t tng_data,
13824 union data_values ***values,
13825 const int64_t n_frames,
13826 const int64_t n_particles,
13827 const int64_t n_values_per_frame,
13835 for(i = 0; i < n_frames; i++)
13839 for(j = 0; j < n_particles; j++)
13841 if(type == TNG_CHAR_DATA)
13843 for(k = 0; k < n_values_per_frame; k++)
13845 if(values[i][j][k].c)
13847 free(values[i][j][k].c);
13848 values[i][j][k].c = 0;
13852 free(values[i][j]);
13863 return(TNG_SUCCESS);
13866 static tng_function_status tng_gen_data_get
13867 (const tng_trajectory_t tng_data,
13868 const int64_t block_id,
13869 const tng_bool is_particle_data,
13870 union data_values ****values,
13872 int64_t *n_particles,
13873 int64_t *n_values_per_frame,
13876 int64_t i, j, k, mapping, file_pos, i_step, block_index;
13880 tng_trajectory_frame_set_t frame_set;
13881 tng_gen_block_t block;
13882 char block_type_flag;
13883 tng_function_status stat;
13885 frame_set = &tng_data->current_trajectory_frame_set;
13890 if(is_particle_data == TNG_TRUE)
13892 stat = tng_particle_data_find(tng_data, block_id, &data);
13896 stat = tng_data_find(tng_data, block_id, &data);
13899 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
13901 block_type_flag = TNG_TRAJECTORY_BLOCK;
13905 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
13908 if(stat != TNG_SUCCESS)
13910 tng_block_init(&block);
13911 file_pos = ftello(tng_data->input_file);
13912 /* Read all blocks until next frame set block */
13913 stat = tng_block_header_read(tng_data, block);
13914 while(file_pos < tng_data->input_file_len &&
13915 stat != TNG_CRITICAL &&
13916 block->id != TNG_TRAJECTORY_FRAME_SET &&
13919 /* Use hash by default */
13920 stat = tng_block_read_next(tng_data, block,
13922 if(stat != TNG_CRITICAL)
13924 file_pos = ftello(tng_data->input_file);
13925 if(file_pos < tng_data->input_file_len)
13927 stat = tng_block_header_read(tng_data, block);
13931 tng_block_destroy(&block);
13932 if(stat == TNG_CRITICAL)
13934 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
13935 file_pos, __FILE__, __LINE__);
13939 if(is_particle_data == TNG_TRUE)
13941 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
13943 data = &frame_set->tr_particle_data[i];
13944 if(data->block_id == block_id)
13947 block_type_flag = TNG_TRAJECTORY_BLOCK;
13954 for(i = 0; i < frame_set->n_data_blocks; i++)
13956 data = &frame_set->tr_data[i];
13957 if(data->block_id == block_id)
13964 if(block_index < 0)
13966 return(TNG_FAILURE);
13970 if(is_particle_data == TNG_TRUE)
13972 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
13973 tng_data->var_num_atoms_flag)
13975 *n_particles = frame_set->n_particles;
13979 *n_particles = tng_data->n_particles;
13983 *n_frames = tng_max_i64(1, data->n_frames);
13984 *n_values_per_frame = data->n_values_per_frame;
13985 *type = data->datatype;
13987 if(is_particle_data == TNG_TRUE)
13991 if(tng_particle_data_values_alloc(tng_data, values, *n_frames,
13992 *n_particles, *n_values_per_frame,
13993 *type) != TNG_SUCCESS)
13995 return(TNG_CRITICAL);
13999 i_step = (*n_particles) * (*n_values_per_frame);
14001 /* It's not very elegant to reuse so much of the code in the different case
14002 * statements, but it's unnecessarily slow to have the switch-case block
14003 * inside the for loops. */
14006 case TNG_CHAR_DATA:
14007 for(i = 0; i < *n_frames; i++)
14009 for(j = 0; j < *n_particles; j++)
14011 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14012 for(k = 0; k < *n_values_per_frame; k++)
14014 len = strlen(data->strings[i][j][k]) + 1;
14015 (*values)[i][mapping][k].c = malloc(len);
14016 strncpy((*values)[i][mapping][k].c,
14017 data->strings[i][j][k], len);
14023 size = sizeof(int);
14024 for(i = 0; i < *n_frames; i++)
14026 for(j = 0; j < *n_particles; j++)
14028 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14029 for(k = 0; k < *n_values_per_frame; k++)
14031 (*values)[i][mapping][k].i = *(int *)
14032 ((char *)data->values + size *
14034 (*n_values_per_frame) + k));
14039 case TNG_FLOAT_DATA:
14040 size = sizeof(float);
14041 for(i = 0; i < *n_frames; i++)
14043 for(j = 0; j < *n_particles; j++)
14045 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14046 for(k = 0; k < *n_values_per_frame; k++)
14048 (*values)[i][mapping][k].f = *(float *)
14049 ((char *)data->values + size *
14051 (*n_values_per_frame) + k));
14056 case TNG_DOUBLE_DATA:
14058 size = sizeof(double);
14059 for(i = 0; i < *n_frames; i++)
14061 for(j = 0; j < *n_particles; j++)
14063 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14064 for(k = 0; k < *n_values_per_frame; k++)
14066 (*values)[i][mapping][k].d = *(double *)
14067 ((char *)data->values + size *
14069 (*n_values_per_frame) + k));
14077 if(*(values[0]) == 0)
14079 if(tng_data_values_alloc(tng_data, values[0], *n_frames,
14080 *n_values_per_frame,
14081 *type) != TNG_SUCCESS)
14083 return(TNG_CRITICAL);
14088 case TNG_CHAR_DATA:
14089 for(i = 0; i < *n_frames; i++)
14091 for(j = 0; j < *n_values_per_frame; j++)
14093 len = strlen(data->strings[0][i][j]) + 1;
14094 (*values)[0][i][j].c = malloc(len);
14095 strncpy((*values)[0][i][j].c, data->strings[0][i][j], len);
14100 size = sizeof(int);
14101 for(i = 0; i < *n_frames; i++)
14103 for(j = 0; j < *n_values_per_frame; j++)
14105 (*values)[0][i][j].i = *(int *)((char *)data->values + size *
14106 (i*(*n_values_per_frame) + j));
14110 case TNG_FLOAT_DATA:
14111 size = sizeof(float);
14112 for(i = 0; i < *n_frames; i++)
14114 for(j = 0; j < *n_values_per_frame; j++)
14116 (*values)[0][i][j].f = *(float *)((char *)data->values + size *
14117 (i*(*n_values_per_frame) + j));
14121 case TNG_DOUBLE_DATA:
14123 size = sizeof(double);
14124 for(i = 0; i < *n_frames; i++)
14126 for(j = 0; j < *n_values_per_frame; j++)
14128 (*values)[0][i][j].d = *(double *)((char *)data->values + size *
14129 (i*(*n_values_per_frame) + j));
14135 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
14137 return(TNG_SUCCESS);
14140 tng_function_status DECLSPECDLLEXPORT tng_data_get
14141 (const tng_trajectory_t tng_data,
14142 const int64_t block_id,
14143 union data_values ***values,
14145 int64_t *n_values_per_frame,
14148 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14149 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
14150 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
14151 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
14153 return(tng_gen_data_get(tng_data, block_id, TNG_FALSE, &values, n_frames, 0,
14154 n_values_per_frame, type));
14157 static tng_function_status tng_gen_data_vector_get
14158 (const tng_trajectory_t tng_data,
14159 const int64_t block_id,
14160 const tng_bool is_particle_data,
14163 int64_t *stride_length,
14164 int64_t *n_particles,
14165 int64_t *n_values_per_frame,
14168 int64_t i, j, mapping, file_pos, i_step, full_data_len, n_frames_div;
14169 int64_t block_index;
14172 tng_trajectory_frame_set_t frame_set;
14173 tng_gen_block_t block;
14175 char block_type_flag;
14176 tng_function_status stat;
14178 frame_set = &tng_data->current_trajectory_frame_set;
14183 if(is_particle_data == TNG_TRUE)
14185 stat = tng_particle_data_find(tng_data, block_id, &data);
14189 stat = tng_data_find(tng_data, block_id, &data);
14192 if(stat != TNG_SUCCESS)
14194 tng_block_init(&block);
14195 file_pos = ftello(tng_data->input_file);
14196 /* Read all blocks until next frame set block */
14197 stat = tng_block_header_read(tng_data, block);
14198 while(file_pos < tng_data->input_file_len &&
14199 stat != TNG_CRITICAL &&
14200 block->id != TNG_TRAJECTORY_FRAME_SET &&
14203 /* Use hash by default */
14204 stat = tng_block_read_next(tng_data, block,
14206 if(stat != TNG_CRITICAL)
14208 file_pos = ftello(tng_data->input_file);
14209 if(file_pos < tng_data->input_file_len)
14211 stat = tng_block_header_read(tng_data, block);
14215 tng_block_destroy(&block);
14216 if(stat == TNG_CRITICAL)
14218 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14219 file_pos, __FILE__, __LINE__);
14223 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
14225 data = &frame_set->tr_particle_data[i];
14226 if(data->block_id == block_id)
14232 if(block_index < 0)
14234 return(TNG_FAILURE);
14238 if(is_particle_data == TNG_TRUE)
14240 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
14242 block_type_flag = TNG_TRAJECTORY_BLOCK;
14246 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
14249 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
14250 tng_data->var_num_atoms_flag)
14252 *n_particles = frame_set->n_particles;
14256 *n_particles = tng_data->n_particles;
14260 *type = data->datatype;
14264 case TNG_CHAR_DATA:
14265 return(TNG_FAILURE);
14267 size = sizeof(int64_t);
14269 case TNG_FLOAT_DATA:
14270 size = sizeof(float);
14272 case TNG_DOUBLE_DATA:
14274 size = sizeof(double);
14277 *n_frames = tng_max_i64(1, data->n_frames);
14278 *n_values_per_frame = data->n_values_per_frame;
14279 *stride_length = data->stride_length;
14281 n_frames_div = (*n_frames % *stride_length) ?
14282 *n_frames / *stride_length + 1:
14283 *n_frames / *stride_length;
14285 full_data_len = n_frames_div * size *
14286 (*n_values_per_frame);
14287 if(is_particle_data == TNG_TRUE)
14289 full_data_len *= (*n_particles);
14292 temp = realloc(*values, full_data_len);
14295 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
14296 full_data_len, __FILE__, __LINE__);
14299 return(TNG_CRITICAL);
14304 if(is_particle_data != TNG_TRUE || frame_set->n_mapping_blocks <= 0)
14306 memcpy(*values, data->values, full_data_len);
14310 i_step = (*n_particles) * (*n_values_per_frame);
14311 for(i = 0; i < *n_frames; i++)
14313 for(j = 0; j < *n_particles; j++)
14315 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14316 memcpy(((char *)*values) + size * (i * i_step + mapping *
14317 (*n_values_per_frame)),
14318 (char *)data->values + size *
14319 (i * i_step + j * (*n_values_per_frame)),
14320 size * (*n_values_per_frame));
14325 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
14327 return(TNG_SUCCESS);
14330 tng_function_status DECLSPECDLLEXPORT tng_data_vector_get
14331 (const tng_trajectory_t tng_data,
14332 const int64_t block_id,
14335 int64_t *stride_length,
14336 int64_t *n_values_per_frame,
14339 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14340 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
14341 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
14342 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
14343 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
14345 return(tng_gen_data_vector_get(tng_data, block_id, TNG_FALSE, values,
14346 n_frames, stride_length, 0, n_values_per_frame,
14350 static tng_function_status tng_gen_data_interval_get
14351 (const tng_trajectory_t tng_data,
14352 const int64_t block_id,
14353 const tng_bool is_particle_data,
14354 const int64_t start_frame_nr,
14355 const int64_t end_frame_nr,
14356 const char hash_mode,
14357 union data_values ****values,
14358 int64_t *n_particles,
14359 int64_t *n_values_per_frame,
14362 int64_t i, j, k, mapping, n_frames, file_pos, current_frame_pos, i_step;
14363 int64_t first_frame, block_index;
14367 tng_trajectory_frame_set_t frame_set;
14368 tng_gen_block_t block;
14369 char block_type_flag;
14370 tng_function_status stat;
14374 frame_set = &tng_data->current_trajectory_frame_set;
14375 first_frame = frame_set->first_frame;
14377 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
14378 if(stat != TNG_SUCCESS)
14383 /* Do not re-read the frame set. */
14384 if((is_particle_data == TNG_TRUE &&
14385 (first_frame != frame_set->first_frame ||
14386 frame_set->n_particle_data_blocks <= 0)) ||
14387 (is_particle_data == TNG_FALSE &&
14388 (first_frame != frame_set->first_frame ||
14389 frame_set->n_data_blocks <= 0)))
14391 tng_block_init(&block);
14392 file_pos = ftello(tng_data->input_file);
14393 /* Read all blocks until next frame set block */
14394 stat = tng_block_header_read(tng_data, block);
14395 while(file_pos < tng_data->input_file_len &&
14396 stat != TNG_CRITICAL &&
14397 block->id != TNG_TRAJECTORY_FRAME_SET &&
14400 stat = tng_block_read_next(tng_data, block,
14402 if(stat != TNG_CRITICAL)
14404 file_pos = ftello(tng_data->input_file);
14405 if(file_pos < tng_data->input_file_len)
14407 stat = tng_block_header_read(tng_data, block);
14411 tng_block_destroy(&block);
14412 if(stat == TNG_CRITICAL)
14414 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14415 file_pos, __FILE__, __LINE__);
14420 /* See if there is already a data block of this ID.
14421 * Start checking the last read frame set */
14422 if(is_particle_data == TNG_TRUE)
14424 for(i = frame_set->n_particle_data_blocks; i-- ;)
14426 data = &frame_set->tr_particle_data[i];
14427 if(data->block_id == block_id)
14430 block_type_flag = TNG_TRAJECTORY_BLOCK;
14437 for(i = 0; i < frame_set->n_data_blocks; i++)
14439 data = &frame_set->tr_data[i];
14440 if(data->block_id == block_id)
14448 if(block_index < 0)
14450 fprintf(stderr, "TNG library: Could not find particle data block with id %"PRId64". %s: %d\n",
14451 block_id, __FILE__, __LINE__);
14452 return(TNG_FAILURE);
14455 if(is_particle_data == TNG_TRUE)
14457 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
14458 tng_data->var_num_atoms_flag)
14460 *n_particles = frame_set->n_particles;
14464 *n_particles = tng_data->n_particles;
14468 n_frames = end_frame_nr - start_frame_nr + 1;
14469 *n_values_per_frame = data->n_values_per_frame;
14470 *type = data->datatype;
14474 if(is_particle_data == TNG_TRUE)
14476 if(tng_particle_data_values_alloc(tng_data, values, n_frames,
14477 *n_particles, *n_values_per_frame,
14478 *type) != TNG_SUCCESS)
14480 return(TNG_CRITICAL);
14485 if(tng_data_values_alloc(tng_data, *values, n_frames,
14486 *n_values_per_frame,
14487 *type) != TNG_SUCCESS)
14489 return(TNG_CRITICAL);
14494 current_frame_pos = start_frame_nr - frame_set->first_frame;
14496 if(is_particle_data == TNG_TRUE)
14498 i_step = (*n_particles) * (*n_values_per_frame);
14502 i_step = (*n_values_per_frame);
14504 /* It's not very elegant to reuse so much of the code in the different case
14505 * statements, but it's unnecessarily slow to have the switch-case block
14506 * inside the for loops. */
14509 case TNG_CHAR_DATA:
14510 for(i=0; i<n_frames; i++)
14512 if(current_frame_pos == frame_set->n_frames)
14514 stat = tng_frame_set_read_next(tng_data, hash_mode);
14515 if(stat != TNG_SUCCESS)
14519 current_frame_pos = 0;
14521 if(is_particle_data == TNG_TRUE)
14523 for(j = 0; j < *n_particles; j++)
14525 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14526 for(k = 0; k < *n_values_per_frame; k++)
14528 len = strlen(data->strings[current_frame_pos][j][k]) + 1;
14529 (*values)[i][mapping][k].c = malloc(len);
14530 strncpy((*values)[i][mapping][k].c, data->strings[current_frame_pos][j][k], len);
14536 for(j = 0; j < *n_values_per_frame; j++)
14538 len = strlen(data->strings[0][current_frame_pos][j]) + 1;
14539 (*values)[0][i][j].c = malloc(len);
14540 strncpy((*values)[0][i][j].c, data->strings[0][current_frame_pos][j], len);
14543 current_frame_pos++;
14547 size = sizeof(int);
14548 for(i=0; i<n_frames; i++)
14550 if(current_frame_pos == frame_set->n_frames)
14552 stat = tng_frame_set_read_next(tng_data, hash_mode);
14553 if(stat != TNG_SUCCESS)
14557 current_frame_pos = 0;
14559 if(is_particle_data == TNG_TRUE)
14561 for(j = 0; j < *n_particles; j++)
14563 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14564 for(k = 0; k < *n_values_per_frame; k++)
14566 (*values)[i][mapping][k].i = *(int *)
14567 ((char *)data->values + size *
14568 (current_frame_pos *
14570 (*n_values_per_frame) + k));
14573 current_frame_pos++;
14577 for(j = 0; j < *n_values_per_frame; j++)
14579 (*values)[0][i][j].i = *(int *)((char *)data->values + size *
14580 (current_frame_pos *
14586 case TNG_FLOAT_DATA:
14587 size = sizeof(float);
14588 for(i=0; i<n_frames; i++)
14590 if(current_frame_pos == frame_set->n_frames)
14592 stat = tng_frame_set_read_next(tng_data, hash_mode);
14593 if(stat != TNG_SUCCESS)
14597 current_frame_pos = 0;
14599 if(is_particle_data == TNG_TRUE)
14601 for(j=0; j<*n_particles; j++)
14603 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14604 for(k=0; k<*n_values_per_frame; k++)
14606 (*values)[i][mapping][k].f = *(float *)
14607 ((char *)data->values + size *
14608 (current_frame_pos *
14610 (*n_values_per_frame) + k));
14616 for(j = 0; j < *n_values_per_frame; j++)
14618 (*values)[0][i][j].f = *(float *)((char *)data->values + size *
14619 (current_frame_pos *
14623 current_frame_pos++;
14626 case TNG_DOUBLE_DATA:
14628 size = sizeof(double);
14629 for(i=0; i<n_frames; i++)
14631 if(current_frame_pos == frame_set->n_frames)
14633 stat = tng_frame_set_read_next(tng_data, hash_mode);
14634 if(stat != TNG_SUCCESS)
14638 current_frame_pos = 0;
14640 if(is_particle_data == TNG_TRUE)
14642 for(j=0; j<*n_particles; j++)
14644 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14645 for(k=0; k<*n_values_per_frame; k++)
14647 (*values)[i][mapping][k].d = *(double *)
14648 ((char *)data->values + size *
14649 (current_frame_pos *
14651 (*n_values_per_frame) + k));
14657 for(j = 0; j < *n_values_per_frame; j++)
14659 (*values)[0][i][j].d = *(double *)((char *)data->values + size *
14660 (current_frame_pos *
14664 current_frame_pos++;
14668 data->last_retrieved_frame = end_frame_nr;
14670 return(TNG_SUCCESS);
14673 tng_function_status DECLSPECDLLEXPORT tng_data_interval_get
14674 (const tng_trajectory_t tng_data,
14675 const int64_t block_id,
14676 const int64_t start_frame_nr,
14677 const int64_t end_frame_nr,
14678 const char hash_mode,
14679 union data_values ***values,
14680 int64_t *n_values_per_frame,
14683 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14684 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
14685 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
14686 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
14688 return(tng_gen_data_interval_get(tng_data, block_id, TNG_FALSE, start_frame_nr,
14689 end_frame_nr, hash_mode, &values, 0,
14690 n_values_per_frame, type));
14693 static tng_function_status tng_gen_data_vector_interval_get
14694 (const tng_trajectory_t tng_data,
14695 const int64_t block_id,
14696 const tng_bool is_particle_data,
14697 const int64_t start_frame_nr,
14698 const int64_t end_frame_nr,
14699 const char hash_mode,
14701 int64_t *n_particles,
14702 int64_t *stride_length,
14703 int64_t *n_values_per_frame,
14706 int64_t n_frames, tot_n_frames, n_frames_div, n_frames_div_2, first_frame;
14707 int64_t file_pos, current_frame_pos, last_frame_pos, full_data_len, frame_size;
14709 tng_trajectory_frame_set_t frame_set;
14711 tng_gen_block_t block;
14712 void *current_values = 0, *temp;
14713 tng_function_status stat;
14715 frame_set = &tng_data->current_trajectory_frame_set;
14716 first_frame = frame_set->first_frame;
14718 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
14719 if(stat != TNG_SUCCESS)
14724 /* Do not re-read the frame set and only need the requested block + particle mapping blocks. */
14725 /* TODO: Test that blocks are read correctly now that now all of them are read at the same time. */
14726 if(is_particle_data == TNG_TRUE)
14728 stat = tng_particle_data_find(tng_data, block_id, &data);
14732 stat = tng_data_find(tng_data, block_id, &data);
14735 if(first_frame != frame_set->first_frame ||
14736 stat != TNG_SUCCESS)
14738 tng_block_init(&block);
14739 if(stat != TNG_SUCCESS)
14741 fseeko(tng_data->input_file,
14742 tng_data->current_trajectory_frame_set_input_file_pos,
14744 stat = tng_block_header_read(tng_data, block);
14745 if(stat != TNG_SUCCESS)
14747 fprintf(stderr, "TNG library: Cannot read block header. %s: %d\n",
14748 __FILE__, __LINE__);
14752 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
14754 file_pos = ftello(tng_data->input_file);
14755 /* Read until next frame set block */
14756 stat = tng_block_header_read(tng_data, block);
14757 while(file_pos < tng_data->input_file_len &&
14758 stat != TNG_CRITICAL &&
14759 block->id != TNG_TRAJECTORY_FRAME_SET &&
14762 if(block->id == block_id || block->id == TNG_PARTICLE_MAPPING)
14764 stat = tng_block_read_next(tng_data, block,
14766 if(stat != TNG_CRITICAL)
14768 file_pos = ftello(tng_data->input_file);
14769 if(file_pos < tng_data->input_file_len)
14771 stat = tng_block_header_read(tng_data, block);
14777 file_pos += block->block_contents_size + block->header_contents_size;
14778 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
14779 if(file_pos < tng_data->input_file_len)
14781 stat = tng_block_header_read(tng_data, block);
14785 tng_block_destroy(&block);
14786 if(stat == TNG_CRITICAL)
14788 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14789 file_pos, __FILE__, __LINE__);
14793 if(is_particle_data == TNG_TRUE)
14795 stat = tng_particle_data_find(tng_data, block_id, &data);
14799 stat = tng_data_find(tng_data, block_id, &data);
14801 if(stat != TNG_SUCCESS)
14806 stat = tng_gen_data_vector_get(tng_data, block_id, is_particle_data,
14807 ¤t_values, &n_frames, stride_length,
14808 n_particles, n_values_per_frame, type);
14810 if(stat != TNG_SUCCESS || (is_particle_data && *n_particles == 0))
14814 free(current_values);
14819 if(n_frames == 1 && n_frames < frame_set->n_frames)
14825 tot_n_frames = end_frame_nr - start_frame_nr + 1;
14830 case TNG_CHAR_DATA:
14831 return(TNG_FAILURE);
14833 size = sizeof(int64_t);
14835 case TNG_FLOAT_DATA:
14836 size = sizeof(float);
14838 case TNG_DOUBLE_DATA:
14840 size = sizeof(double);
14843 n_frames_div = (tot_n_frames % *stride_length) ?
14844 tot_n_frames / *stride_length + 1:
14845 tot_n_frames / *stride_length;
14847 full_data_len = n_frames_div * size * (*n_values_per_frame);
14848 if(is_particle_data)
14850 full_data_len *= (*n_particles);
14853 temp = realloc(*values, full_data_len);
14856 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
14857 full_data_len, __FILE__, __LINE__);
14860 return(TNG_CRITICAL);
14865 if( n_frames == 1 && n_frames < frame_set->n_frames)
14867 if(is_particle_data)
14869 memcpy(*values, current_values, size * (*n_particles) *
14870 (*n_values_per_frame));
14874 memcpy(*values, current_values, size * (*n_values_per_frame));
14879 current_frame_pos = start_frame_nr - frame_set->first_frame;
14881 frame_size = size * (*n_values_per_frame);
14882 if(is_particle_data)
14884 frame_size *= (*n_particles);
14887 last_frame_pos = tng_min_i64(n_frames,
14888 end_frame_nr - start_frame_nr);
14890 n_frames_div = current_frame_pos / *stride_length;
14891 n_frames_div_2 = (last_frame_pos % *stride_length) ?
14892 last_frame_pos / *stride_length + 1:
14893 last_frame_pos / *stride_length;
14894 n_frames_div_2 = tng_max_i64(1, n_frames_div_2 + 1);
14896 memcpy(*values, (char *)current_values + n_frames_div * frame_size,
14897 n_frames_div_2 * frame_size);
14899 current_frame_pos += n_frames - current_frame_pos;
14901 while(current_frame_pos <= end_frame_nr - start_frame_nr)
14903 stat = tng_frame_set_read_next(tng_data, hash_mode);
14904 if(stat != TNG_SUCCESS)
14908 free(current_values);
14915 stat = tng_gen_data_vector_get(tng_data, block_id, is_particle_data,
14916 ¤t_values, &n_frames,
14917 stride_length, n_particles,
14918 n_values_per_frame, type);
14920 if(stat != TNG_SUCCESS)
14924 free(current_values);
14931 last_frame_pos = tng_min_i64(n_frames,
14932 end_frame_nr - current_frame_pos);
14934 n_frames_div = current_frame_pos / *stride_length;
14935 n_frames_div_2 = (last_frame_pos % *stride_length) ?
14936 last_frame_pos / *stride_length + 1:
14937 last_frame_pos / *stride_length;
14938 n_frames_div_2 = tng_max_i64(1, n_frames_div_2);
14940 memcpy(((char *)*values) + n_frames_div * frame_size,
14942 n_frames_div_2 * frame_size);
14944 current_frame_pos += n_frames;
14950 free(current_values);
14953 data->last_retrieved_frame = end_frame_nr;
14955 return(TNG_SUCCESS);
14959 tng_function_status DECLSPECDLLEXPORT tng_data_vector_interval_get
14960 (const tng_trajectory_t tng_data,
14961 const int64_t block_id,
14962 const int64_t start_frame_nr,
14963 const int64_t end_frame_nr,
14964 const char hash_mode,
14966 int64_t *stride_length,
14967 int64_t *n_values_per_frame,
14970 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14971 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than the end_frame_nr.");
14972 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
14973 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
14974 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
14976 return(tng_gen_data_vector_interval_get(tng_data, block_id, TNG_FALSE,
14977 start_frame_nr, end_frame_nr,
14978 hash_mode, values, 0, stride_length,
14979 n_values_per_frame, type));
14982 tng_function_status DECLSPECDLLEXPORT tng_particle_data_get
14983 (const tng_trajectory_t tng_data,
14984 const int64_t block_id,
14985 union data_values ****values,
14987 int64_t *n_particles,
14988 int64_t *n_values_per_frame,
14991 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14992 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
14993 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
14994 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
14995 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
14997 return(tng_gen_data_get(tng_data, block_id, TNG_TRUE, values, n_frames, n_particles,
14998 n_values_per_frame, type));
15001 tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_get
15002 (const tng_trajectory_t tng_data,
15003 const int64_t block_id,
15006 int64_t *stride_length,
15007 int64_t *n_particles,
15008 int64_t *n_values_per_frame,
15011 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15012 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
15013 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
15014 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15015 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15017 return(tng_gen_data_vector_get(tng_data, block_id, TNG_TRUE, values,
15018 n_frames, stride_length, n_particles,
15019 n_values_per_frame, type));
15022 tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
15023 (const tng_trajectory_t tng_data,
15024 const int64_t block_id,
15025 const int64_t start_frame_nr,
15026 const int64_t end_frame_nr,
15027 const char hash_mode,
15028 union data_values ****values,
15029 int64_t *n_particles,
15030 int64_t *n_values_per_frame,
15033 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15034 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
15035 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
15036 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15037 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15039 return(tng_gen_data_interval_get(tng_data, block_id, TNG_TRUE, start_frame_nr,
15040 end_frame_nr, hash_mode, values, n_particles,
15041 n_values_per_frame, type));
15044 tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_interval_get
15045 (const tng_trajectory_t tng_data,
15046 const int64_t block_id,
15047 const int64_t start_frame_nr,
15048 const int64_t end_frame_nr,
15049 const char hash_mode,
15051 int64_t *n_particles,
15052 int64_t *stride_length,
15053 int64_t *n_values_per_frame,
15056 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15057 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
15058 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
15059 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
15060 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15061 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15063 return(tng_gen_data_vector_interval_get(tng_data, block_id, TNG_TRUE,
15064 start_frame_nr, end_frame_nr,
15065 hash_mode, values, n_particles,
15066 stride_length, n_values_per_frame,
15070 tng_function_status DECLSPECDLLEXPORT tng_data_get_stride_length
15071 (const tng_trajectory_t tng_data,
15072 const int64_t block_id,
15074 int64_t *stride_length)
15076 tng_function_status stat;
15078 int64_t orig_file_pos, file_pos;
15079 int is_particle_data;
15081 if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
15088 stat = tng_frame_set_of_frame_find(tng_data, frame);
15089 if(stat != TNG_SUCCESS)
15094 orig_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
15095 stat = tng_data_find(tng_data, block_id, &data);
15096 if(stat != TNG_SUCCESS)
15098 stat = tng_particle_data_find(tng_data, block_id, &data);
15099 if(stat != TNG_SUCCESS)
15101 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15102 /* If no specific frame was required read until this data block is found */
15105 file_pos = ftello(tng_data->input_file);
15106 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
15108 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15109 file_pos = ftello(tng_data->input_file);
15112 if(stat != TNG_SUCCESS)
15114 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
15118 stat = tng_data_find(tng_data, block_id, &data);
15119 if(stat != TNG_SUCCESS)
15121 stat = tng_particle_data_find(tng_data, block_id, &data);
15122 if(stat != TNG_SUCCESS)
15124 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
15130 is_particle_data = 1;
15135 is_particle_data = 0;
15140 is_particle_data = 1;
15145 is_particle_data = 0;
15147 if(is_particle_data)
15149 *stride_length = data->stride_length;
15153 *stride_length = data->stride_length;
15155 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
15157 return(TNG_SUCCESS);
15160 tng_function_status DECLSPECDLLEXPORT tng_time_get_str
15161 (const tng_trajectory_t tng_data,
15164 struct tm *time_data;
15167 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15168 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
15170 secs = tng_data->time;
15172 time_data = localtime(&secs); /* Returns a statically allocated variable. */
15173 TNG_SNPRINTF(time, TNG_MAX_DATE_STR_LEN,
15174 "%4d-%02d-%02d %02d:%02d:%02d",
15175 time_data->tm_year+1900, time_data->tm_mon+1, time_data->tm_mday,
15176 time_data->tm_hour, time_data->tm_min, time_data->tm_sec);
15178 return(TNG_SUCCESS);
15182 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_open
15183 (const char *filename,
15185 tng_trajectory_t *tng_data_p)
15187 tng_function_status stat;
15189 TNG_ASSERT(filename, "TNG library: filename must not be a NULL pointer.");
15191 if(mode != 'r' && mode != 'w' && mode != 'a')
15193 return(TNG_FAILURE);
15196 if(tng_trajectory_init(tng_data_p) != TNG_SUCCESS)
15198 tng_trajectory_destroy(tng_data_p);
15199 return(TNG_CRITICAL);
15202 if(mode == 'r' || mode == 'a')
15204 tng_input_file_set(*tng_data_p, filename);
15206 /* Read the file headers */
15207 tng_file_headers_read(*tng_data_p, TNG_USE_HASH);
15209 stat = tng_num_frame_sets_get(*tng_data_p, &(*tng_data_p)->n_trajectory_frame_sets);
15211 if(stat != TNG_SUCCESS)
15219 stat = tng_output_file_set(*tng_data_p, filename);
15221 else if(mode == 'a')
15223 if((*tng_data_p)->output_file)
15225 fclose((*tng_data_p)->output_file);
15227 (*tng_data_p)->output_file = (*tng_data_p)->input_file;
15228 fseeko((*tng_data_p)->input_file,
15229 (*tng_data_p)->last_trajectory_frame_set_input_file_pos,
15232 stat = tng_frame_set_read(*tng_data_p, TNG_USE_HASH);
15233 if(stat != TNG_SUCCESS)
15235 fprintf(stderr, "TNG library: Cannot read frame set and related blocks. %s: %d\n",
15236 __FILE__, __LINE__);
15238 (*tng_data_p)->output_file = 0;
15240 (*tng_data_p)->first_trajectory_frame_set_output_file_pos =
15241 (*tng_data_p)->first_trajectory_frame_set_input_file_pos;
15242 (*tng_data_p)->last_trajectory_frame_set_output_file_pos =
15243 (*tng_data_p)->last_trajectory_frame_set_input_file_pos;
15244 (*tng_data_p)->current_trajectory_frame_set_output_file_pos =
15245 (*tng_data_p)->current_trajectory_frame_set_input_file_pos;
15246 if((*tng_data_p)->input_file)
15248 fclose((*tng_data_p)->input_file);
15249 (*tng_data_p)->input_file = 0;
15251 if((*tng_data_p)->input_file_path)
15253 free((*tng_data_p)->input_file_path);
15254 (*tng_data_p)->input_file_path = 0;
15256 tng_output_append_file_set(*tng_data_p, filename);
15258 fseeko((*tng_data_p)->output_file, 0, SEEK_END);
15264 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_close
15265 (tng_trajectory_t *tng_data_p)
15267 tng_trajectory_frame_set_t frame_set;
15269 if(tng_data_p == 0)
15271 fprintf(stderr, "TNG library: Empty pointer to trajectory when attempting to close. %s: %d\n",
15272 __FILE__, __LINE__);
15273 return(TNG_FAILURE);
15276 if(*tng_data_p == 0)
15278 return(TNG_SUCCESS);
15281 frame_set = &(*tng_data_p)->current_trajectory_frame_set;
15283 if(frame_set->n_unwritten_frames > 0)
15285 frame_set->n_frames = frame_set->n_unwritten_frames;
15286 tng_frame_set_write(*tng_data_p, TNG_USE_HASH);
15289 return(tng_trajectory_destroy(tng_data_p));
15292 tng_function_status DECLSPECDLLEXPORT tng_util_time_of_frame_get
15293 (const tng_trajectory_t tng_data,
15294 const int64_t frame_nr,
15297 int64_t first_frame;
15298 tng_trajectory_frame_set_t frame_set;
15299 tng_function_status stat;
15301 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15302 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
15304 stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
15305 if(stat != TNG_SUCCESS)
15307 fprintf(stderr, "TNG library: Cannot find frame nr %"PRId64". %s: %d\n",
15308 frame_nr, __FILE__, __LINE__);
15312 frame_set = &tng_data->current_trajectory_frame_set;
15313 first_frame = frame_set->first_frame;
15315 if(tng_data->time_per_frame <= 0)
15317 return(TNG_FAILURE);
15320 *time = frame_set->first_frame_time + (tng_data->time_per_frame * (frame_nr - first_frame));
15322 return(TNG_SUCCESS);
15326 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecules_get
15327 (const tng_trajectory_t tng_data,
15329 int64_t **molecule_cnt_list,
15330 tng_molecule_t *mols)
15332 tng_trajectory_frame_set_t frame_set;
15334 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15335 TNG_ASSERT(n_mols, "TNG library: n_mols must not be a NULL pointer.");
15337 *n_mols = tng_data->n_molecules;
15339 frame_set = &tng_data->current_trajectory_frame_set;
15340 if(tng_data->var_num_atoms_flag && frame_set && frame_set->molecule_cnt_list)
15342 *molecule_cnt_list = frame_set->molecule_cnt_list;
15346 *molecule_cnt_list = tng_data->molecule_cnt_list;
15349 *mols = tng_data->molecules;
15351 return(TNG_SUCCESS);
15355 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecule_add
15356 (const tng_trajectory_t tng_data,
15359 tng_molecule_t *mol)
15361 tng_function_status stat;
15363 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
15364 TNG_ASSERT(cnt>=0, "TNG library: cnt must be >= 0");
15366 stat = tng_molecule_add(tng_data, name, mol);
15367 if(stat != TNG_SUCCESS)
15371 stat = tng_molecule_cnt_set(tng_data, *mol, cnt);
15376 tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_get
15377 (const tng_trajectory_t tng_data,
15378 const tng_molecule_t mol,
15379 int64_t *n_particles,
15384 char ***chain_names,
15385 int64_t **chain_ids)
15393 *n_particles = mol->n_atoms;
15395 *names = malloc(sizeof(char *) * *n_particles);
15396 *types = malloc(sizeof(char *) * *n_particles);
15397 *res_names = malloc(sizeof(char *) * *n_particles);
15398 *chain_names = malloc(sizeof(char *) * *n_particles);
15399 *res_ids = malloc(sizeof(int64_t) * *n_particles);
15400 *chain_ids = malloc(sizeof(int64_t) * *n_particles);
15402 for(i = 0; i < *n_particles; i++)
15404 atom = &mol->atoms[i];
15405 res = atom->residue;
15406 chain = res->chain;
15407 (*names)[i] = malloc(strlen(atom->name));
15408 strcpy(*names[i], atom->name);
15409 (*types)[i] = malloc(strlen(atom->atom_type));
15410 strcpy(*types[i], atom->atom_type);
15411 (*res_names)[i] = malloc(strlen(res->name));
15412 strcpy(*res_names[i], res->name);
15413 (*chain_names)[i] = malloc(strlen(chain->name));
15414 strcpy(*chain_names[i], chain->name);
15415 (*res_ids)[i] = res->id;
15416 (*chain_ids)[i] = chain->id;
15419 return(TNG_SUCCESS);
15422 tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_set
15423 (const tng_trajectory_t tng_data,
15424 const tng_molecule_t mol,
15425 const int64_t n_particles,
15426 const char **names,
15427 const char **types,
15428 const char **res_names,
15429 const int64_t *res_ids,
15430 const char **chain_names,
15431 const int64_t *chain_ids)
15435 tng_residue_t residue;
15437 tng_function_status stat;
15439 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15440 TNG_ASSERT(names, "TNG library: names must not be a NULL pointer");
15441 TNG_ASSERT(types, "TNG library: types must not be a NULL pointer");
15442 TNG_ASSERT(res_names, "TNG library: res_names must not be a NULL pointer");
15443 TNG_ASSERT(res_ids, "TNG library: res_ids must not be a NULL pointer");
15444 TNG_ASSERT(chain_names, "TNG library: chain_names must not be a NULL pointer");
15445 TNG_ASSERT(chain_ids, "TNG library: chain_ids must not be a NULL pointer");
15447 for(i = 0; i < n_particles; i++)
15449 if(tng_molecule_chain_find(tng_data, mol, chain_names[i], chain_ids[i],
15450 &chain) == TNG_FAILURE)
15452 stat = tng_molecule_chain_add(tng_data, mol, chain_names[i],
15454 if(stat != TNG_SUCCESS)
15459 if(tng_chain_residue_find(tng_data, chain, res_names[i], res_ids[i],
15460 &residue) == TNG_FAILURE)
15462 stat = tng_chain_residue_add(tng_data, chain, res_names[i],
15464 if(stat != TNG_SUCCESS)
15469 stat = tng_residue_atom_add(tng_data, residue, names[i], types[i], &atom);
15470 if(stat != TNG_SUCCESS)
15475 return(TNG_SUCCESS);
15478 tng_function_status DECLSPECDLLEXPORT tng_util_pos_read
15479 (const tng_trajectory_t tng_data,
15480 float **positions, int64_t *stride_length)
15482 int64_t n_frames, n_particles, n_values_per_frame;
15484 tng_function_status stat;
15486 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15487 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
15488 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
15490 stat = tng_num_frames_get(tng_data, &n_frames);
15491 if(stat != TNG_SUCCESS)
15496 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_POSITIONS,
15497 0, n_frames - 1, TNG_USE_HASH,
15498 (void **)positions,
15501 &n_values_per_frame,
15507 tng_function_status DECLSPECDLLEXPORT tng_util_vel_read
15508 (const tng_trajectory_t tng_data,
15509 float **velocities, int64_t *stride_length)
15511 int64_t n_frames, n_particles, n_values_per_frame;
15513 tng_function_status stat;
15515 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15516 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
15517 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
15519 stat = tng_num_frames_get(tng_data, &n_frames);
15520 if(stat != TNG_SUCCESS)
15525 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_VELOCITIES,
15526 0, n_frames - 1, TNG_USE_HASH,
15527 (void **)velocities,
15530 &n_values_per_frame,
15536 tng_function_status DECLSPECDLLEXPORT tng_util_force_read
15537 (const tng_trajectory_t tng_data,
15538 float **forces, int64_t *stride_length)
15540 int64_t n_frames, n_particles, n_values_per_frame;
15542 tng_function_status stat;
15544 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15545 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
15546 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
15548 stat = tng_num_frames_get(tng_data, &n_frames);
15549 if(stat != TNG_SUCCESS)
15554 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_FORCES,
15555 0, n_frames - 1, TNG_USE_HASH,
15559 &n_values_per_frame,
15565 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read
15566 (const tng_trajectory_t tng_data,
15568 int64_t *stride_length)
15570 int64_t n_frames, n_values_per_frame;
15572 tng_function_status stat;
15574 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15575 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
15576 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
15578 stat = tng_num_frames_get(tng_data, &n_frames);
15579 if(stat != TNG_SUCCESS)
15584 stat = tng_data_vector_interval_get(tng_data, TNG_TRAJ_BOX_SHAPE,
15585 0, n_frames - 1, TNG_USE_HASH,
15586 (void **)box_shape,
15588 &n_values_per_frame,
15594 tng_function_status DECLSPECDLLEXPORT tng_util_particle_data_next_frame_read
15595 (const tng_trajectory_t tng_data,
15596 const int64_t block_id,
15599 int64_t *retrieved_frame_number,
15600 double *retrieved_time)
15602 tng_trajectory_frame_set_t frame_set;
15603 tng_data_t data = 0;
15604 tng_function_status stat;
15606 int64_t i, full_data_len, n_particles;
15610 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15611 TNG_ASSERT(values, "TNG library: The pointer to the values array must not be a NULL pointer");
15612 TNG_ASSERT(data_type, "TNG library: The pointer to the data type of the returned data must not be a NULL pointer");
15613 TNG_ASSERT(retrieved_frame_number, "TNG library: The pointer to the frame number of the returned data must not be a NULL pointer");
15614 TNG_ASSERT(retrieved_time, "TNG library: The pointer to the time of the returned data must not be a NULL pointer");
15616 frame_set = &tng_data->current_trajectory_frame_set;
15618 stat = tng_particle_data_find(tng_data, block_id, &data);
15619 if(stat != TNG_SUCCESS)
15621 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15622 file_pos = ftello(tng_data->input_file);
15623 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
15625 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15626 file_pos = ftello(tng_data->input_file);
15628 if(stat != TNG_SUCCESS)
15632 stat = tng_particle_data_find(tng_data, block_id, &data);
15633 if(stat != TNG_SUCCESS)
15638 if(data->last_retrieved_frame < 0)
15640 fseeko(tng_data->input_file,
15641 tng_data->first_trajectory_frame_set_input_file_pos,
15643 stat = tng_frame_set_read(tng_data, TNG_USE_HASH);
15644 if(stat != TNG_SUCCESS)
15648 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15649 if(stat != TNG_SUCCESS)
15654 i = data->first_frame_with_data;
15658 if(data->n_frames == 1 && frame_set->n_frames == 1)
15660 i = data->last_retrieved_frame + 1;
15664 i = data->last_retrieved_frame + data->stride_length;
15666 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
15668 stat = tng_frame_set_of_frame_find(tng_data, i);
15669 if(stat != TNG_SUCCESS)
15671 /* If the frame set search found the frame set after the starting
15672 * frame set there is a gap in the frame sets. So, even if the frame
15673 * was not found the next frame with data is still in the found
15675 if(stat == TNG_CRITICAL)
15679 if(frame_set->first_frame + frame_set->n_frames - 1 < i)
15681 return(TNG_FAILURE);
15683 i = frame_set->first_frame;
15686 if(data->last_retrieved_frame < frame_set->first_frame)
15688 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15689 if(stat != TNG_SUCCESS)
15695 data->last_retrieved_frame = i;
15696 *retrieved_frame_number = i;
15697 if(frame_set->first_frame_time >= 0 && tng_data->time_per_frame >= 0)
15699 *retrieved_time = frame_set->first_frame_time +
15700 (i - frame_set->first_frame) *
15701 tng_data->time_per_frame;
15705 *retrieved_time = 0;
15708 if(data->stride_length > 1)
15710 i = (i - data->first_frame_with_data) / data->stride_length;
15714 i = (i - frame_set->first_frame);
15717 tng_num_particles_get(tng_data, &n_particles);
15719 *data_type = data->datatype;
15723 case TNG_CHAR_DATA:
15724 return(TNG_FAILURE);
15726 size = sizeof(int64_t);
15728 case TNG_FLOAT_DATA:
15729 size = sizeof(float);
15731 case TNG_DOUBLE_DATA:
15733 size = sizeof(double);
15736 full_data_len = size * n_particles * data->n_values_per_frame;
15738 // fprintf(stderr, "TNG library: TEMP: i = %"PRId64", full_data_len = %"PRId64", size = %d, n_particles = %"PRId64", n_values_per_frame = %"PRId64"\n",
15739 // i, full_data_len, size, n_particles, data->n_values_per_frame);
15741 temp = realloc(*values, full_data_len);
15744 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15745 full_data_len, __FILE__, __LINE__);
15748 return(TNG_CRITICAL);
15753 memcpy(*values, (char *)data->values + i * full_data_len, full_data_len);
15755 return(TNG_SUCCESS);
15758 tng_function_status DECLSPECDLLEXPORT tng_util_non_particle_data_next_frame_read
15759 (const tng_trajectory_t tng_data,
15760 const int64_t block_id,
15763 int64_t *retrieved_frame_number,
15764 double *retrieved_time)
15766 tng_trajectory_frame_set_t frame_set;
15767 tng_data_t data = 0;
15768 tng_function_status stat;
15770 int64_t i, full_data_len;
15774 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15775 TNG_ASSERT(values, "TNG library: The pointer to the values array must not be a NULL pointer");
15776 TNG_ASSERT(data_type, "TNG library: The pointer to the data type of the returned data must not be a NULL pointer");
15777 TNG_ASSERT(retrieved_frame_number, "TNG library: The pointer to the frame number of the returned data must not be a NULL pointer");
15778 TNG_ASSERT(retrieved_time, "TNG library: The pointer to the time of the returned data must not be a NULL pointer");
15780 frame_set = &tng_data->current_trajectory_frame_set;
15782 stat = tng_data_find(tng_data, block_id, &data);
15783 if(stat != TNG_SUCCESS)
15785 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15786 file_pos = ftello(tng_data->input_file);
15787 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
15789 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15790 file_pos = ftello(tng_data->input_file);
15792 if(stat != TNG_SUCCESS)
15796 stat = tng_data_find(tng_data, block_id, &data);
15797 if(stat != TNG_SUCCESS)
15802 if(data->last_retrieved_frame < 0)
15804 fseeko(tng_data->input_file,
15805 tng_data->first_trajectory_frame_set_input_file_pos,
15807 stat = tng_frame_set_read(tng_data, TNG_USE_HASH);
15808 if(stat != TNG_SUCCESS)
15812 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15813 if(stat != TNG_SUCCESS)
15818 i = data->first_frame_with_data;
15822 if(data->n_frames == 1 && frame_set->n_frames == 1)
15824 i = data->last_retrieved_frame + 1;
15828 i = data->last_retrieved_frame + data->stride_length;
15830 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
15832 stat = tng_frame_set_of_frame_find(tng_data, i);
15833 if(stat != TNG_SUCCESS)
15835 /* If the frame set search found the frame set after the starting
15836 * frame set there is a gap in the frame sets. So, even if the frame
15837 * was not found the next frame with data is still in the found
15839 if(stat == TNG_CRITICAL)
15843 if(frame_set->first_frame + frame_set->n_frames - 1 < i)
15845 return(TNG_FAILURE);
15847 i = frame_set->first_frame;
15850 if(data->last_retrieved_frame < frame_set->first_frame)
15852 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15853 if(stat != TNG_SUCCESS)
15859 data->last_retrieved_frame = i;
15860 *retrieved_frame_number = i;
15861 if(frame_set->first_frame_time >= 0 && tng_data->time_per_frame >= 0)
15863 *retrieved_time = frame_set->first_frame_time +
15864 (i - frame_set->first_frame) *
15865 tng_data->time_per_frame;
15869 *retrieved_time = 0;
15872 if(data->stride_length > 1)
15874 i = (i - data->first_frame_with_data) / data->stride_length;
15878 i = (i - frame_set->first_frame);
15881 *data_type = data->datatype;
15885 case TNG_CHAR_DATA:
15886 return(TNG_FAILURE);
15888 size = sizeof(int64_t);
15890 case TNG_FLOAT_DATA:
15891 size = sizeof(float);
15893 case TNG_DOUBLE_DATA:
15895 size = sizeof(double);
15898 full_data_len = size * data->n_values_per_frame;
15900 temp = realloc(*values, full_data_len);
15903 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15904 full_data_len, __FILE__, __LINE__);
15907 return(TNG_CRITICAL);
15912 memcpy(*values, (char *)data->values + i * full_data_len, full_data_len);
15914 return(TNG_SUCCESS);
15917 tng_function_status DECLSPECDLLEXPORT tng_util_pos_read_range
15918 (const tng_trajectory_t tng_data,
15919 const int64_t first_frame,
15920 const int64_t last_frame,
15922 int64_t *stride_length)
15924 int64_t n_particles, n_values_per_frame;
15926 tng_function_status stat;
15928 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15929 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
15930 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
15931 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
15933 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_POSITIONS,
15934 first_frame, last_frame,
15936 (void **)positions,
15939 &n_values_per_frame,
15942 if(stat == TNG_SUCCESS && type != TNG_FLOAT_DATA)
15944 return(TNG_FAILURE);
15950 tng_function_status DECLSPECDLLEXPORT tng_util_vel_read_range
15951 (const tng_trajectory_t tng_data,
15952 const int64_t first_frame,
15953 const int64_t last_frame,
15954 float **velocities,
15955 int64_t *stride_length)
15957 int64_t n_particles, n_values_per_frame;
15959 tng_function_status stat;
15961 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15962 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
15963 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
15964 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
15966 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_VELOCITIES,
15967 first_frame, last_frame,
15969 (void **)velocities,
15972 &n_values_per_frame,
15975 if(stat == TNG_SUCCESS && type != TNG_FLOAT_DATA)
15977 return(TNG_FAILURE);
15983 tng_function_status DECLSPECDLLEXPORT tng_util_force_read_range
15984 (const tng_trajectory_t tng_data,
15985 const int64_t first_frame,
15986 const int64_t last_frame,
15988 int64_t *stride_length)
15990 int64_t n_particles, n_values_per_frame;
15992 tng_function_status stat;
15994 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15995 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
15996 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
15997 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
15999 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_FORCES,
16000 first_frame, last_frame,
16005 &n_values_per_frame,
16008 if(stat == TNG_SUCCESS && type != TNG_FLOAT_DATA)
16010 return(TNG_FAILURE);
16016 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read_range
16017 (const tng_trajectory_t tng_data,
16018 const int64_t first_frame,
16019 const int64_t last_frame,
16021 int64_t *stride_length)
16023 int64_t n_values_per_frame;
16025 tng_function_status stat;
16027 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16028 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
16029 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
16030 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
16032 stat = tng_data_vector_interval_get(tng_data, TNG_TRAJ_BOX_SHAPE,
16033 first_frame, last_frame,
16035 (void **)box_shape,
16037 &n_values_per_frame,
16040 if(stat == TNG_SUCCESS && type != TNG_FLOAT_DATA)
16042 return(TNG_FAILURE);
16048 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_set
16049 (const tng_trajectory_t tng_data,
16051 const int64_t n_values_per_frame,
16052 const int64_t block_id,
16053 const char *block_name,
16054 const char particle_dependency,
16055 const char compression)
16057 tng_trajectory_frame_set_t frame_set;
16059 int64_t n_particles, n_frames;
16060 tng_function_status stat;
16062 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16063 TNG_ASSERT(i >= 0, "TNG library: i (writing interval) must be >= 0.");
16067 fprintf(stderr, "TNG library: Cannot set writing frequency to %"PRId64". %s: %d\n",
16068 i, __FILE__, __LINE__);
16069 return(TNG_FAILURE);
16072 frame_set = &tng_data->current_trajectory_frame_set;
16074 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
16076 n_frames = tng_data->frame_set_n_frames;
16078 stat = tng_frame_set_new(tng_data, 0, n_frames);
16079 if(stat != TNG_SUCCESS)
16081 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
16088 n_frames = frame_set->n_frames;
16091 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
16093 tng_num_particles_get(tng_data, &n_particles);
16094 if(n_particles <= 0)
16096 return(TNG_FAILURE);
16099 if(tng_particle_data_find(tng_data, block_id, &data)
16102 stat = tng_particle_data_block_add(tng_data, block_id,
16105 TNG_TRAJECTORY_BLOCK,
16106 n_frames, n_values_per_frame, i,
16109 if(stat != TNG_SUCCESS)
16111 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16112 __FILE__, __LINE__);
16115 data = &frame_set->tr_particle_data[frame_set->
16116 n_particle_data_blocks - 1];
16117 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
16119 n_values_per_frame);
16120 if(stat != TNG_SUCCESS)
16122 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16123 __FILE__, __LINE__);
16129 if(data->stride_length != i)
16131 data->stride_length = i;
16132 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
16134 n_values_per_frame);
16135 if(stat != TNG_SUCCESS)
16137 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16138 __FILE__, __LINE__);
16146 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
16148 stat = tng_data_block_add(tng_data, block_id, block_name,
16149 TNG_FLOAT_DATA, TNG_TRAJECTORY_BLOCK,
16150 n_frames, n_values_per_frame,
16151 i, compression, 0);
16152 if(stat != TNG_SUCCESS)
16154 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16155 __FILE__, __LINE__);
16158 data = &frame_set->tr_data[frame_set->
16159 n_data_blocks - 1];
16160 stat = tng_allocate_data_mem(tng_data, data, n_frames,
16161 i, n_values_per_frame);
16162 if(stat != TNG_SUCCESS)
16164 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16165 __FILE__, __LINE__);
16171 if(data->stride_length != i)
16173 data->stride_length = i;
16174 stat = tng_allocate_data_mem(tng_data, data, n_frames,
16175 i, n_values_per_frame);
16176 if(stat != TNG_SUCCESS)
16178 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16179 __FILE__, __LINE__);
16186 return(TNG_SUCCESS);
16189 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_double_set
16190 (const tng_trajectory_t tng_data,
16192 const int64_t n_values_per_frame,
16193 const int64_t block_id,
16194 const char *block_name,
16195 const char particle_dependency,
16196 const char compression)
16198 tng_trajectory_frame_set_t frame_set;
16200 int64_t n_particles, n_frames;
16201 tng_function_status stat;
16203 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16204 TNG_ASSERT(i >= 0, "TNG library: i (writing interval) must be >= 0.");
16208 fprintf(stderr, "TNG library: Cannot set writing frequency to %"PRId64". %s: %d\n",
16209 i, __FILE__, __LINE__);
16210 return(TNG_FAILURE);
16213 frame_set = &tng_data->current_trajectory_frame_set;
16215 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
16217 n_frames = tng_data->frame_set_n_frames;
16219 stat = tng_frame_set_new(tng_data, 0, n_frames);
16220 if(stat != TNG_SUCCESS)
16222 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
16229 n_frames = frame_set->n_frames;
16232 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
16234 tng_num_particles_get(tng_data, &n_particles);
16236 if(n_particles <= 0)
16238 return(TNG_FAILURE);
16241 if(tng_particle_data_find(tng_data, block_id, &data)
16244 stat = tng_particle_data_block_add(tng_data, block_id,
16247 TNG_TRAJECTORY_BLOCK,
16248 n_frames, n_values_per_frame, i,
16251 if(stat != TNG_SUCCESS)
16253 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16254 __FILE__, __LINE__);
16257 data = &frame_set->tr_particle_data[frame_set->
16258 n_particle_data_blocks - 1];
16259 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
16261 n_values_per_frame);
16262 if(stat != TNG_SUCCESS)
16264 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16265 __FILE__, __LINE__);
16271 data->stride_length = i;
16276 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
16278 stat = tng_data_block_add(tng_data, block_id, block_name,
16279 TNG_DOUBLE_DATA, TNG_TRAJECTORY_BLOCK,
16280 n_frames, n_values_per_frame,
16281 i, compression, 0);
16282 if(stat != TNG_SUCCESS)
16284 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16285 __FILE__, __LINE__);
16288 data = &frame_set->tr_data[frame_set->
16289 n_data_blocks - 1];
16290 stat = tng_allocate_data_mem(tng_data, data, n_frames,
16291 i, n_values_per_frame);
16292 if(stat != TNG_SUCCESS)
16294 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16295 __FILE__, __LINE__);
16301 data->stride_length = i;
16305 return(TNG_SUCCESS);
16308 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_frequency_set
16309 (const tng_trajectory_t tng_data,
16311 const int64_t n_values_per_frame,
16312 const int64_t block_id,
16313 const char *block_name,
16314 const char particle_dependency,
16315 const char compression)
16317 fprintf(stderr, "TNG library: Using obsolete function tng_util_generic_write_frequency_set(). "
16318 "See documentation. %s: %d", __FILE__, __LINE__);
16319 return(tng_util_generic_write_interval_set(tng_data, i, n_values_per_frame,
16320 block_id, block_name,
16321 particle_dependency,
16324 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_set
16325 (const tng_trajectory_t tng_data,
16328 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16329 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
16331 return(tng_util_generic_write_interval_set(tng_data, i, 3,
16332 TNG_TRAJ_POSITIONS,
16334 TNG_PARTICLE_BLOCK_DATA,
16335 TNG_TNG_COMPRESSION));
16338 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_double_set
16339 (const tng_trajectory_t tng_data,
16342 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16343 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
16345 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
16346 TNG_TRAJ_POSITIONS,
16348 TNG_PARTICLE_BLOCK_DATA,
16349 TNG_TNG_COMPRESSION));
16352 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_frequency_set
16353 (const tng_trajectory_t tng_data,
16356 fprintf(stderr, "TNG library: Using obsolete function tng_util_pos_write_frequency_set(). "
16357 "See documentation. %s: %d", __FILE__, __LINE__);
16358 return(tng_util_pos_write_interval_set(tng_data, i));
16361 tng_function_status DECLSPECDLLEXPORT tng_util_vel_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_VELOCITIES,
16371 TNG_PARTICLE_BLOCK_DATA,
16372 TNG_TNG_COMPRESSION));
16375 tng_function_status DECLSPECDLLEXPORT tng_util_vel_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_VELOCITIES,
16385 TNG_PARTICLE_BLOCK_DATA,
16386 TNG_TNG_COMPRESSION));
16389 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_frequency_set
16390 (const tng_trajectory_t tng_data,
16393 fprintf(stderr, "TNG library: Using obsolete function tng_util_vel_write_frequency_set(). "
16394 "See documentation. %s: %d", __FILE__, __LINE__);
16395 return(tng_util_vel_write_interval_set(tng_data, i));
16398 tng_function_status DECLSPECDLLEXPORT tng_util_force_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,
16408 TNG_PARTICLE_BLOCK_DATA,
16409 TNG_GZIP_COMPRESSION));
16412 tng_function_status DECLSPECDLLEXPORT tng_util_force_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,
16422 TNG_PARTICLE_BLOCK_DATA,
16423 TNG_GZIP_COMPRESSION));
16426 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_frequency_set
16427 (const tng_trajectory_t tng_data,
16430 fprintf(stderr, "TNG library: Using obsolete function tng_util_force_write_frequency_set(). "
16431 "See documentation. %s: %d", __FILE__, __LINE__);
16432 return(tng_util_force_write_interval_set(tng_data, i));
16435 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_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, 9,
16443 TNG_TRAJ_BOX_SHAPE,
16445 TNG_NON_PARTICLE_BLOCK_DATA,
16446 TNG_GZIP_COMPRESSION));
16449 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_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, 9,
16457 TNG_TRAJ_BOX_SHAPE,
16459 TNG_NON_PARTICLE_BLOCK_DATA,
16460 TNG_GZIP_COMPRESSION));
16463 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_frequency_set
16464 (const tng_trajectory_t tng_data,
16467 fprintf(stderr, "TNG library: Using obsolete function tng_util_box_shape_write_frequency_set(). "
16468 "See documentation. %s: %d", __FILE__, __LINE__);
16469 return(tng_util_box_shape_write_interval_set(tng_data, i));
16472 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write
16473 (const tng_trajectory_t tng_data,
16474 const int64_t frame_nr,
16475 const float *values,
16476 const int64_t n_values_per_frame,
16477 const int64_t block_id,
16478 const char *block_name,
16479 const char particle_dependency,
16480 const char compression)
16482 tng_trajectory_frame_set_t frame_set;
16484 int64_t n_particles = 0, n_frames, stride_length = 100, frame_pos;
16485 int64_t last_frame;
16486 int is_first_frame_flag = 0;
16487 char block_type_flag;
16488 tng_function_status stat;
16490 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16491 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
16493 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
16495 tng_num_particles_get(tng_data, &n_particles);
16496 TNG_ASSERT(n_particles > 0, "TNG library: There must be particles in the system to write particle data.");
16501 return(TNG_FAILURE);
16504 frame_set = &tng_data->current_trajectory_frame_set;
16508 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
16509 n_frames = stride_length = 1;
16513 block_type_flag = TNG_TRAJECTORY_BLOCK;
16515 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
16517 stat = tng_frame_set_new(tng_data, 0, tng_data->frame_set_n_frames);
16518 if(stat != TNG_SUCCESS)
16520 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
16525 last_frame = frame_set->first_frame +
16526 frame_set->n_frames - 1;
16527 if(frame_nr > last_frame)
16529 stat = tng_frame_set_write(tng_data, TNG_USE_HASH);
16530 if(stat != TNG_SUCCESS)
16532 fprintf(stderr, "TNG library: Cannot write frame set. %s: %d\n", __FILE__,
16536 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
16538 last_frame = frame_nr - 1;
16540 stat = tng_frame_set_new(tng_data, last_frame + 1,
16541 tng_data->frame_set_n_frames);
16542 if(stat != TNG_SUCCESS)
16544 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
16549 if(frame_set->n_unwritten_frames == 0)
16551 is_first_frame_flag = 1;
16553 frame_set->n_unwritten_frames = frame_nr -
16554 frame_set->first_frame + 1;
16556 n_frames = frame_set->n_frames;
16559 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
16561 if(tng_particle_data_find(tng_data, block_id, &data)
16564 stat = tng_particle_data_block_add(tng_data, block_id,
16568 n_frames, n_values_per_frame,
16572 if(stat != TNG_SUCCESS)
16574 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16575 __FILE__, __LINE__);
16578 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16580 data = &frame_set->tr_particle_data[frame_set->
16581 n_particle_data_blocks - 1];
16585 data = &tng_data->non_tr_particle_data[tng_data->
16586 n_particle_data_blocks - 1];
16588 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
16589 stride_length, n_particles,
16590 n_values_per_frame);
16591 if(stat != TNG_SUCCESS)
16593 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16594 __FILE__, __LINE__);
16598 /* FIXME: Here we must be able to handle modified n_particles as well. */
16599 else if(n_frames > data->n_frames)
16601 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
16602 data->stride_length, n_particles,
16603 n_values_per_frame);
16604 if(stat != TNG_SUCCESS)
16606 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16607 __FILE__, __LINE__);
16612 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16614 stride_length = data->stride_length;
16616 if(is_first_frame_flag || data->first_frame_with_data < frame_set->first_frame)
16618 data->first_frame_with_data = frame_nr;
16623 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
16626 memcpy((char *)data->values + sizeof(float) * frame_pos * n_particles *
16627 n_values_per_frame, values, sizeof(float) *
16628 n_particles * n_values_per_frame);
16632 memcpy(data->values, values, sizeof(float) * n_particles *
16633 n_values_per_frame);
16638 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
16640 stat = tng_data_block_add(tng_data, block_id, block_name,
16641 TNG_FLOAT_DATA, block_type_flag,
16642 n_frames, n_values_per_frame,
16643 stride_length, compression, 0);
16644 if(stat != TNG_SUCCESS)
16646 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16647 __FILE__, __LINE__);
16650 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16652 data = &frame_set->tr_data[frame_set->
16653 n_data_blocks - 1];
16657 data = &tng_data->non_tr_data[tng_data->
16658 n_data_blocks - 1];
16660 stat = tng_allocate_data_mem(tng_data, data, n_frames,
16661 stride_length, n_values_per_frame);
16662 if(stat != TNG_SUCCESS)
16664 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16665 __FILE__, __LINE__);
16669 /* FIXME: Here we must be able to handle modified n_particles as well. */
16670 else if(n_frames > data->n_frames)
16672 stat = tng_allocate_data_mem(tng_data, data, n_frames,
16673 data->stride_length, n_values_per_frame);
16674 if(stat != TNG_SUCCESS)
16676 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16677 __FILE__, __LINE__);
16682 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16684 stride_length = data->stride_length;
16686 if(is_first_frame_flag || data->first_frame_with_data < frame_set->first_frame)
16688 data->first_frame_with_data = frame_nr;
16693 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
16696 memcpy((char *)data->values + sizeof(float) * frame_pos *
16697 n_values_per_frame, values, sizeof(float) *
16698 n_values_per_frame);
16702 memcpy(data->values, values, sizeof(float) * n_values_per_frame);
16706 return(TNG_SUCCESS);
16709 tng_function_status DECLSPECDLLEXPORT tng_util_generic_double_write
16710 (const tng_trajectory_t tng_data,
16711 const int64_t frame_nr,
16712 const double *values,
16713 const int64_t n_values_per_frame,
16714 const int64_t block_id,
16715 const char *block_name,
16716 const char particle_dependency,
16717 const char compression)
16719 tng_trajectory_frame_set_t frame_set;
16721 int64_t n_particles = 0, n_frames, stride_length = 100, frame_pos;
16722 int64_t last_frame;
16723 int is_first_frame_flag = 0;
16724 char block_type_flag;
16725 tng_function_status stat;
16727 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16728 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
16730 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
16732 tng_num_particles_get(tng_data, &n_particles);
16733 TNG_ASSERT(n_particles > 0, "TNG library: There must be particles in the system to write particle data.");
16738 return(TNG_FAILURE);
16741 frame_set = &tng_data->current_trajectory_frame_set;
16745 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
16746 n_frames = stride_length = 1;
16750 block_type_flag = TNG_TRAJECTORY_BLOCK;
16752 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
16754 stat = tng_frame_set_new(tng_data, 0, tng_data->frame_set_n_frames);
16755 if(stat != TNG_SUCCESS)
16757 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
16762 last_frame = frame_set->first_frame +
16763 frame_set->n_frames - 1;
16764 if(frame_nr > last_frame)
16766 stat = tng_frame_set_write(tng_data, TNG_USE_HASH);
16767 if(stat != TNG_SUCCESS)
16769 fprintf(stderr, "TNG library: Cannot write frame set. %s: %d\n", __FILE__,
16773 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
16775 last_frame = frame_nr - 1;
16777 stat = tng_frame_set_new(tng_data, last_frame + 1,
16778 tng_data->frame_set_n_frames);
16779 if(stat != TNG_SUCCESS)
16781 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
16786 if(frame_set->n_unwritten_frames == 0)
16788 is_first_frame_flag = 1;
16790 frame_set->n_unwritten_frames = frame_nr -
16791 frame_set->first_frame + 1;
16793 n_frames = frame_set->n_frames;
16797 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
16799 if(tng_particle_data_find(tng_data, block_id, &data)
16802 stat = tng_particle_data_block_add(tng_data, block_id,
16806 n_frames, n_values_per_frame,
16810 if(stat != TNG_SUCCESS)
16812 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16813 __FILE__, __LINE__);
16816 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16818 data = &frame_set->tr_particle_data[frame_set->
16819 n_particle_data_blocks - 1];
16823 data = &tng_data->non_tr_particle_data[tng_data->
16824 n_particle_data_blocks - 1];
16826 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
16827 stride_length, n_particles,
16828 n_values_per_frame);
16829 if(stat != TNG_SUCCESS)
16831 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16832 __FILE__, __LINE__);
16836 /* FIXME: Here we must be able to handle modified n_particles as well. */
16837 else if(n_frames > data->n_frames)
16839 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
16840 data->stride_length, n_particles,
16841 n_values_per_frame);
16842 if(stat != TNG_SUCCESS)
16844 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16845 __FILE__, __LINE__);
16850 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16852 stride_length = data->stride_length;
16854 if(is_first_frame_flag || data->first_frame_with_data < frame_set->first_frame)
16856 data->first_frame_with_data = frame_nr;
16861 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
16864 memcpy((char *)data->values + sizeof(double) * frame_pos * n_particles *
16865 n_values_per_frame, values, sizeof(double) *
16866 n_particles * n_values_per_frame);
16870 memcpy(data->values, values, sizeof(double) * n_particles *
16871 n_values_per_frame);
16876 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
16878 stat = tng_data_block_add(tng_data, block_id, block_name,
16879 TNG_DOUBLE_DATA, block_type_flag,
16880 n_frames, n_values_per_frame,
16881 stride_length, compression, 0);
16882 if(stat != TNG_SUCCESS)
16884 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16885 __FILE__, __LINE__);
16888 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16890 data = &frame_set->tr_data[frame_set->
16891 n_data_blocks - 1];
16895 data = &tng_data->non_tr_data[tng_data->
16896 n_data_blocks - 1];
16898 stat = tng_allocate_data_mem(tng_data, data, n_frames,
16899 stride_length, n_values_per_frame);
16900 if(stat != TNG_SUCCESS)
16902 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16903 __FILE__, __LINE__);
16907 /* FIXME: Here we must be able to handle modified n_particles as well. */
16908 else if(n_frames > data->n_frames)
16910 stat = tng_allocate_data_mem(tng_data, data, n_frames,
16911 data->stride_length, n_values_per_frame);
16912 if(stat != TNG_SUCCESS)
16914 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16915 __FILE__, __LINE__);
16920 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16922 stride_length = data->stride_length;
16924 if(is_first_frame_flag || data->first_frame_with_data < frame_set->first_frame)
16926 data->first_frame_with_data = frame_nr;
16931 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
16934 memcpy((char *)data->values + sizeof(double) * frame_pos *
16935 n_values_per_frame, values, sizeof(double) *
16936 n_values_per_frame);
16940 memcpy(data->values, values, sizeof(double) * n_values_per_frame);
16944 return(TNG_SUCCESS);
16947 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write
16948 (const tng_trajectory_t tng_data,
16949 const int64_t frame_nr,
16950 const float *positions)
16952 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16953 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
16955 return(tng_util_generic_write(tng_data, frame_nr, positions, 3,
16956 TNG_TRAJ_POSITIONS, "POSITIONS",
16957 TNG_PARTICLE_BLOCK_DATA,
16958 TNG_TNG_COMPRESSION));
16961 tng_function_status DECLSPECDLLEXPORT tng_util_pos_double_write
16962 (const tng_trajectory_t tng_data,
16963 const int64_t frame_nr,
16964 const double *positions)
16966 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16967 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
16969 return(tng_util_generic_double_write(tng_data, frame_nr, positions, 3,
16970 TNG_TRAJ_POSITIONS, "POSITIONS",
16971 TNG_PARTICLE_BLOCK_DATA,
16972 TNG_TNG_COMPRESSION));
16975 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write
16976 (const tng_trajectory_t tng_data,
16977 const int64_t frame_nr,
16978 const float *velocities)
16980 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16981 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
16983 return(tng_util_generic_write(tng_data, frame_nr, velocities, 3,
16984 TNG_TRAJ_VELOCITIES, "VELOCITIES",
16985 TNG_PARTICLE_BLOCK_DATA,
16986 TNG_TNG_COMPRESSION));
16989 tng_function_status DECLSPECDLLEXPORT tng_util_vel_double_write
16990 (const tng_trajectory_t tng_data,
16991 const int64_t frame_nr,
16992 const double *velocities)
16994 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16995 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
16997 return(tng_util_generic_double_write(tng_data, frame_nr, velocities, 3,
16998 TNG_TRAJ_VELOCITIES, "VELOCITIES",
16999 TNG_PARTICLE_BLOCK_DATA,
17000 TNG_TNG_COMPRESSION));
17003 tng_function_status DECLSPECDLLEXPORT tng_util_force_write
17004 (const tng_trajectory_t tng_data,
17005 const int64_t frame_nr,
17006 const float *forces)
17008 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17009 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17011 return(tng_util_generic_write(tng_data, frame_nr, forces, 3,
17012 TNG_TRAJ_FORCES, "FORCES",
17013 TNG_PARTICLE_BLOCK_DATA,
17014 TNG_GZIP_COMPRESSION));
17017 tng_function_status DECLSPECDLLEXPORT tng_util_force_double_write
17018 (const tng_trajectory_t tng_data,
17019 const int64_t frame_nr,
17020 const double *forces)
17022 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17023 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17025 return(tng_util_generic_double_write(tng_data, frame_nr, forces, 3,
17026 TNG_TRAJ_FORCES, "FORCES",
17027 TNG_PARTICLE_BLOCK_DATA,
17028 TNG_GZIP_COMPRESSION));
17031 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write
17032 (const tng_trajectory_t tng_data,
17033 const int64_t frame_nr,
17034 const float *box_shape)
17036 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17037 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17039 return(tng_util_generic_write(tng_data, frame_nr, box_shape, 9,
17040 TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
17041 TNG_NON_PARTICLE_BLOCK_DATA,
17042 TNG_GZIP_COMPRESSION));
17045 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_double_write
17046 (const tng_trajectory_t tng_data,
17047 const int64_t frame_nr,
17048 const double *box_shape)
17050 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17051 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17053 return(tng_util_generic_double_write(tng_data, frame_nr, box_shape, 9,
17054 TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
17055 TNG_NON_PARTICLE_BLOCK_DATA,
17056 TNG_GZIP_COMPRESSION));
17059 tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_write
17060 (const tng_trajectory_t tng_data,
17061 const int64_t frame_nr,
17063 const float *values,
17064 const int64_t n_values_per_frame,
17065 const int64_t block_id,
17066 const char *block_name,
17067 const char particle_dependency,
17068 const char compression)
17070 tng_trajectory_frame_set_t frame_set;
17071 tng_function_status stat;
17073 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17074 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17075 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17076 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
17078 stat = tng_util_generic_write(tng_data, frame_nr, values, n_values_per_frame,
17079 block_id, block_name,
17080 particle_dependency,
17083 if(stat != TNG_SUCCESS)
17088 frame_set = &tng_data->current_trajectory_frame_set;
17090 /* first_frame_time is -1 when it is not yet set. */
17091 if(frame_set->first_frame_time < -0.1)
17093 if(frame_nr > frame_set->first_frame)
17095 stat = tng_frame_set_first_frame_time_set(tng_data,
17098 frame_set->first_frame) *
17099 tng_data->time_per_frame);
17103 stat = tng_frame_set_first_frame_time_set(tng_data, time);
17109 tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_double_write
17110 (const tng_trajectory_t tng_data,
17111 const int64_t frame_nr,
17113 const double *values,
17114 const int64_t n_values_per_frame,
17115 const int64_t block_id,
17116 const char *block_name,
17117 const char particle_dependency,
17118 const char compression)
17120 tng_trajectory_frame_set_t frame_set;
17121 tng_function_status stat;
17123 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17124 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17125 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17126 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
17128 stat = tng_util_generic_double_write(tng_data, frame_nr, values, n_values_per_frame,
17129 block_id, block_name,
17130 particle_dependency,
17133 if(stat != TNG_SUCCESS)
17138 frame_set = &tng_data->current_trajectory_frame_set;
17140 /* first_frame_time is -1 when it is not yet set. */
17141 if(frame_set->first_frame_time < -0.1)
17143 if(frame_nr > frame_set->first_frame)
17145 stat = tng_frame_set_first_frame_time_set(tng_data,
17148 frame_set->first_frame) *
17149 tng_data->time_per_frame);
17153 stat = tng_frame_set_first_frame_time_set(tng_data, time);
17159 tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_write
17160 (const tng_trajectory_t tng_data,
17161 const int64_t frame_nr,
17163 const float *positions)
17165 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17166 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17167 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17168 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
17170 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, positions,
17171 3, TNG_TRAJ_POSITIONS, "POSITIONS",
17172 TNG_PARTICLE_BLOCK_DATA,
17173 TNG_TNG_COMPRESSION));
17176 tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_double_write
17177 (const tng_trajectory_t tng_data,
17178 const int64_t frame_nr,
17180 const double *positions)
17182 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17183 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17184 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17185 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
17187 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
17189 TNG_TRAJ_POSITIONS,
17191 TNG_PARTICLE_BLOCK_DATA,
17192 TNG_TNG_COMPRESSION));
17195 tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_write
17196 (const tng_trajectory_t tng_data,
17197 const int64_t frame_nr,
17199 const float *velocities)
17201 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17202 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17203 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17204 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
17206 return(tng_util_generic_with_time_write(tng_data, frame_nr, time,
17208 TNG_TRAJ_VELOCITIES,
17210 TNG_PARTICLE_BLOCK_DATA,
17211 TNG_TNG_COMPRESSION));
17214 tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_double_write
17215 (const tng_trajectory_t tng_data,
17216 const int64_t frame_nr,
17218 const double *velocities)
17220 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17221 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17222 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17223 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
17225 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
17227 TNG_TRAJ_VELOCITIES,
17229 TNG_PARTICLE_BLOCK_DATA,
17230 TNG_TNG_COMPRESSION));
17233 tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_write
17234 (const tng_trajectory_t tng_data,
17235 const int64_t frame_nr,
17237 const float *forces)
17239 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17240 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17241 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17242 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17244 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, forces,
17245 3, TNG_TRAJ_FORCES, "FORCES",
17246 TNG_PARTICLE_BLOCK_DATA,
17247 TNG_GZIP_COMPRESSION));
17250 tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_double_write
17251 (const tng_trajectory_t tng_data,
17252 const int64_t frame_nr,
17254 const double *forces)
17256 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17257 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17258 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17259 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17261 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
17263 TNG_TRAJ_FORCES, "FORCES",
17264 TNG_PARTICLE_BLOCK_DATA,
17265 TNG_GZIP_COMPRESSION));
17268 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_write
17269 (const tng_trajectory_t tng_data,
17270 const int64_t frame_nr,
17272 const float *box_shape)
17274 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17275 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17276 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17277 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17279 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, box_shape,
17280 9, TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
17281 TNG_NON_PARTICLE_BLOCK_DATA,
17282 TNG_GZIP_COMPRESSION));
17285 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_double_write
17286 (const tng_trajectory_t tng_data,
17287 const int64_t frame_nr,
17289 const double *box_shape)
17291 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17292 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17293 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17294 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17296 return(tng_util_generic_with_time_double_write(tng_data, frame_nr,
17297 time, box_shape, 9,
17298 TNG_TRAJ_BOX_SHAPE,
17300 TNG_NON_PARTICLE_BLOCK_DATA,
17301 TNG_GZIP_COMPRESSION));
17304 tng_function_status DECLSPECDLLEXPORT tng_util_frame_current_compression_get
17305 (const tng_trajectory_t tng_data,
17306 const int64_t block_id,
17310 tng_trajectory_frame_set_t frame_set;
17311 tng_data_t data = 0;
17312 tng_function_status stat;
17314 int block_type = -1;
17316 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17317 TNG_ASSERT(codec_id, "TNG library: The pointer to the returned codec id must not be a NULL pointer.");
17318 TNG_ASSERT(factor, "TNG library: The pointer to the returned multiplication factor must not be a NULL pointer.");
17320 frame_set = &tng_data->current_trajectory_frame_set;
17322 stat = tng_particle_data_find(tng_data, block_id, &data);
17323 if(stat == TNG_SUCCESS)
17325 block_type = TNG_PARTICLE_BLOCK_DATA;
17329 stat = tng_data_find(tng_data, block_id, &data);
17330 if(stat == TNG_SUCCESS)
17332 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
17336 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17337 if(stat != TNG_SUCCESS)
17341 stat = tng_particle_data_find(tng_data, block_id, &data);
17342 if(stat == TNG_SUCCESS)
17344 block_type = TNG_PARTICLE_BLOCK_DATA;
17348 stat = tng_data_find(tng_data, block_id, &data);
17349 if(stat == TNG_SUCCESS)
17351 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
17360 if(block_type == TNG_PARTICLE_BLOCK_DATA)
17362 if(data->last_retrieved_frame < 0)
17364 i = data->first_frame_with_data;
17368 i = data->last_retrieved_frame;
17371 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
17373 if(data->last_retrieved_frame < 0)
17375 i = data->first_frame_with_data;
17379 i = data->last_retrieved_frame;
17384 return(TNG_FAILURE);
17386 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
17388 stat = tng_frame_set_of_frame_find(tng_data, i);
17389 if(stat != TNG_SUCCESS)
17393 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17394 if(stat != TNG_SUCCESS)
17396 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
17397 __FILE__, __LINE__);
17401 if(block_type == TNG_PARTICLE_BLOCK_DATA)
17403 *codec_id = data->codec_id;
17404 *factor = data->compression_multiplier;
17406 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
17408 *codec_id = data->codec_id;
17409 *factor = data->compression_multiplier;
17411 return(TNG_SUCCESS);
17414 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_next_frame_present_data_blocks_find
17415 (const tng_trajectory_t tng_data,
17416 int64_t current_frame,
17417 const int64_t n_requested_data_block_ids,
17418 const int64_t *requested_data_block_ids,
17419 int64_t *next_frame,
17420 int64_t *n_data_blocks_in_next_frame,
17421 int64_t **data_block_ids_in_next_frame)
17423 tng_trajectory_frame_set_t frame_set;
17424 tng_function_status stat;
17426 tng_gen_block_t block;
17427 int64_t i, j, block_id, *temp;
17428 int64_t data_frame, frame_diff, min_diff;
17429 int64_t size, frame_set_file_pos;
17430 int found, read_all = 0;
17433 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17434 TNG_ASSERT(next_frame, "TNG library: The pointer to the next frame must not be NULL.");
17435 TNG_ASSERT(n_data_blocks_in_next_frame, "TNG library: The pointer to n_data_blocks_in_next_frame must not be NULL.");
17436 TNG_ASSERT(data_block_ids_in_next_frame, "TNG library: The pointer to the list of data block IDs must not be NULL.");
17438 if(n_requested_data_block_ids)
17440 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.");
17441 size = sizeof(int64_t) * n_requested_data_block_ids;
17442 temp = realloc(*data_block_ids_in_next_frame, size);
17445 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
17446 sizeof(int64_t) * (*n_data_blocks_in_next_frame),
17447 __FILE__, __LINE__);
17448 free(*data_block_ids_in_next_frame);
17449 *data_block_ids_in_next_frame = 0;
17450 return(TNG_CRITICAL);
17452 *data_block_ids_in_next_frame = temp;
17455 frame_set = &tng_data->current_trajectory_frame_set;
17457 current_frame += 1;
17459 if(current_frame < frame_set->first_frame ||
17460 current_frame >= frame_set->first_frame + frame_set->n_frames)
17462 frame_set_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
17463 stat = tng_frame_set_of_frame_find(tng_data, current_frame);
17464 if(stat != TNG_SUCCESS)
17466 /* If the frame set search found the frame set after the starting
17467 * frame set there is a gap in the frame sets. So, even if the frame
17468 * was not found the next frame with data is still in the found
17470 if(stat == TNG_CRITICAL || frame_set->prev_frame_set_file_pos !=
17471 frame_set_file_pos)
17475 current_frame = frame_set->first_frame;
17479 /* Check for data blocks only if they have not already been found. */
17480 if(frame_set->n_particle_data_blocks <= 0 && frame_set->n_data_blocks <= 0)
17482 file_pos = ftello(tng_data->input_file);
17483 if(file_pos < tng_data->input_file_len)
17485 tng_block_init(&block);
17486 stat = tng_block_header_read(tng_data, block);
17487 while(file_pos < tng_data->input_file_len &&
17488 stat != TNG_CRITICAL &&
17489 block->id != TNG_TRAJECTORY_FRAME_SET &&
17492 stat = tng_block_read_next(tng_data, block,
17494 if(stat != TNG_CRITICAL)
17496 file_pos = ftello(tng_data->input_file);
17497 if(file_pos < tng_data->input_file_len)
17499 stat = tng_block_header_read(tng_data, block);
17503 tng_block_destroy(&block);
17504 if(stat == TNG_CRITICAL)
17506 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
17507 file_pos, __FILE__, __LINE__);
17516 *n_data_blocks_in_next_frame = 0;
17518 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
17520 data = &frame_set->tr_particle_data[i];
17521 block_id = data->block_id;
17523 if(n_requested_data_block_ids > 0)
17526 for(j = 0; j < n_requested_data_block_ids; j++)
17528 if(block_id == requested_data_block_ids[j])
17540 if(!read_all && (data->last_retrieved_frame < frame_set->first_frame ||
17541 data->last_retrieved_frame >=
17542 frame_set->first_frame + frame_set->n_frames))
17544 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data,
17545 TNG_USE_HASH, block_id);
17546 if(stat == TNG_CRITICAL)
17548 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
17549 __FILE__, __LINE__);
17552 if(stat == TNG_FAILURE)
17557 if(frame_set->first_frame != current_frame &&
17558 data->last_retrieved_frame >= 0)
17560 data_frame = data->last_retrieved_frame + data->stride_length;
17564 data_frame = data->first_frame_with_data;
17566 frame_diff = data_frame - current_frame;
17571 if(min_diff == -1 || frame_diff <= min_diff)
17573 if(frame_diff < min_diff)
17575 *n_data_blocks_in_next_frame = 1;
17579 *n_data_blocks_in_next_frame += 1;
17581 if(n_requested_data_block_ids <= 0)
17583 size = sizeof(int64_t) * (*n_data_blocks_in_next_frame);
17584 temp = realloc(*data_block_ids_in_next_frame, size);
17587 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
17588 sizeof(int64_t) * (*n_data_blocks_in_next_frame),
17589 __FILE__, __LINE__);
17590 free(*data_block_ids_in_next_frame);
17591 *data_block_ids_in_next_frame = 0;
17592 return(TNG_CRITICAL);
17594 *data_block_ids_in_next_frame = temp;
17598 TNG_ASSERT(*n_data_blocks_in_next_frame <= n_requested_data_block_ids, "TNG library: Array of data block IDs out of bounds");
17600 (*data_block_ids_in_next_frame)[(*n_data_blocks_in_next_frame) - 1] = block_id;
17602 min_diff = frame_diff;
17605 for(i = 0; i < frame_set->n_data_blocks; i++)
17607 data = &frame_set->tr_data[i];
17608 block_id = data->block_id;
17610 if(n_requested_data_block_ids > 0)
17613 for(j = 0; j < n_requested_data_block_ids; j++)
17615 if(block_id == requested_data_block_ids[j])
17627 if(!read_all && (data->last_retrieved_frame < frame_set->first_frame ||
17628 data->last_retrieved_frame >=
17629 frame_set->first_frame + frame_set->n_frames))
17631 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data,
17632 TNG_USE_HASH, block_id);
17633 if(stat == TNG_CRITICAL)
17635 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
17636 __FILE__, __LINE__);
17639 if(stat == TNG_FAILURE)
17644 if(frame_set->first_frame != current_frame &&
17645 data->last_retrieved_frame >= 0)
17647 data_frame = data->last_retrieved_frame + data->stride_length;
17651 data_frame = data->first_frame_with_data;
17653 frame_diff = data_frame - current_frame;
17658 if(min_diff == -1 || frame_diff <= min_diff)
17660 if(frame_diff < min_diff)
17662 *n_data_blocks_in_next_frame = 1;
17666 *n_data_blocks_in_next_frame += 1;
17668 if(n_requested_data_block_ids <= 0)
17670 size = sizeof(int64_t) * (*n_data_blocks_in_next_frame);
17671 temp = realloc(*data_block_ids_in_next_frame, size);
17674 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
17675 sizeof(int64_t) * (*n_data_blocks_in_next_frame),
17676 __FILE__, __LINE__);
17677 free(*data_block_ids_in_next_frame);
17678 *data_block_ids_in_next_frame = 0;
17679 return(TNG_CRITICAL);
17681 *data_block_ids_in_next_frame = temp;
17685 TNG_ASSERT(*n_data_blocks_in_next_frame <= n_requested_data_block_ids, "TNG library: Array of data block IDs out of bounds");
17687 (*data_block_ids_in_next_frame)[(*n_data_blocks_in_next_frame) - 1] = block_id;
17689 min_diff = frame_diff;
17694 return(TNG_FAILURE);
17696 *next_frame = current_frame + min_diff;
17698 return(TNG_SUCCESS);
17702 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_all_data_block_types_get
17703 (const tng_trajectory_t tng_data,
17704 int64_t *n_data_blocks,
17705 int64_t **data_block_ids,
17706 char ***data_block_names,
17707 int64_t **stride_lengths,
17708 int64_t **n_values_per_frame,
17709 char **block_types,
17710 char **dependencies,
17711 char **compressions)
17713 tng_gen_block_t block;
17714 int64_t orig_file_pos, file_pos;
17716 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17717 TNG_ASSERT(n_data_blocks, "TNG library: The pointer to n_data_blocks must not be NULL.");
17718 TNG_ASSERT(data_block_ids, "TNG library: The pointer to the list of data block IDs must not be NULL.");
17719 TNG_ASSERT(data_block_names, "TNG library: The pointer to the list of data block names must not be NULL.");
17720 TNG_ASSERT(stride_lengths, "TNG library: The pointer to the list of stride lengths must not be NULL.");
17722 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
17724 return(TNG_CRITICAL);
17727 orig_file_pos = ftello(tng_data->input_file);
17729 fseeko(tng_data->input_file, 0, SEEK_SET);
17732 *n_data_blocks = 0;
17734 tng_block_init(&block);
17736 while(file_pos < tng_data->input_file_len &&
17737 tng_block_header_read(tng_data, block) != TNG_CRITICAL)
17739 if(block->id > TNG_TRAJECTORY_FRAME_SET)
17743 file_pos += (block->block_contents_size + block->header_contents_size);
17744 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
17747 fseeko(tng_data->input_file, orig_file_pos, SEEK_SET);
17749 return(TNG_SUCCESS);
17752 tng_function_status DECLSPECDLLEXPORT tng_util_prepare_append_after_frame
17753 (const tng_trajectory_t tng_data,
17754 const int64_t prev_frame)
17756 tng_function_status stat;
17757 FILE *temp = tng_data->input_file;
17759 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17760 TNG_ASSERT(prev_frame >= 0, "TNG library: The previous frame must not be negative.");
17762 tng_data->input_file = tng_data->output_file;
17764 stat = tng_frame_set_of_frame_find(tng_data, prev_frame);
17765 if(stat != TNG_SUCCESS)
17770 tng_data->current_trajectory_frame_set_output_file_pos =
17771 tng_data->current_trajectory_frame_set_input_file_pos;
17773 tng_data->input_file = temp;
17775 return(TNG_SUCCESS);
17778 tng_function_status DECLSPECDLLEXPORT tng_util_num_frames_with_data_of_block_id_get
17779 (const tng_trajectory_t tng_data,
17780 const int64_t block_id,
17783 int64_t curr_file_pos, first_frame_set_file_pos, curr_n_frames;
17784 tng_function_status stat;
17786 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17790 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
17792 return(TNG_CRITICAL);
17795 first_frame_set_file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
17796 curr_file_pos = ftello(tng_data->input_file);
17797 fseeko(tng_data->input_file, first_frame_set_file_pos, SEEK_SET);
17799 stat = tng_frame_set_n_frames_of_data_block_get(tng_data, block_id, &curr_n_frames);
17801 while(stat == TNG_SUCCESS && tng_data->current_trajectory_frame_set.next_frame_set_file_pos != -1)
17803 *n_frames += curr_n_frames;
17804 fseeko(tng_data->input_file,
17805 tng_data->current_trajectory_frame_set.next_frame_set_file_pos,
17807 stat = tng_frame_set_n_frames_of_data_block_get(tng_data, block_id, &curr_n_frames);
17809 if(stat == TNG_SUCCESS)
17811 *n_frames += curr_n_frames;
17813 fseeko(tng_data->input_file, curr_file_pos, SEEK_SET);
17814 if(stat == TNG_CRITICAL)
17816 return(TNG_CRITICAL);
17818 return(TNG_SUCCESS);