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 (%"PRIuPTR" 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 (%"PRIuPTR" 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 (%"PRIuPTR" 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 (%"PRIuPTR" 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 (%"PRIuPTR" 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);
5614 /* Endianness is handled by the TNG compression library. TNG compressed blocks are always written
5615 * as little endian by the compression library. */
5616 if(codec_id != TNG_TNG_COMPRESSION)
5620 case TNG_FLOAT_DATA:
5621 if(tng_data->input_endianness_swap_func_32)
5623 for(i = 0; i < full_data_len; i+=size)
5625 if(tng_data->input_endianness_swap_func_32(tng_data,
5626 (int32_t *)((char *)data->values + i))
5629 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5630 __FILE__, __LINE__);
5636 case TNG_DOUBLE_DATA:
5637 if(tng_data->input_endianness_swap_func_64)
5639 for(i = 0; i < full_data_len; i+=size)
5641 if(tng_data->input_endianness_swap_func_64(tng_data,
5642 (int64_t *)((char *)data->values + i))
5645 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5646 __FILE__, __LINE__);
5659 return(TNG_SUCCESS);
5663 * @brief Write a data block (particle or non-particle data)
5664 * @param tng_data is a trajectory data container.
5665 * @param block is the block to store the data (should already contain
5666 * the block headers and the block contents).
5667 * @param block_index is the index number of the data block in the frame set.
5668 * @param is_particle_data is a flag to specify if the data to write is
5669 * particle dependent or not.
5670 * @param mapping is the particle mapping that is relevant for the data block.
5671 * Only relevant if writing particle dependent data.
5672 * @param hash_mode is an option to decide whether to use the md5 hash or not.
5673 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
5674 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5675 * error has occured.
5677 static tng_function_status tng_data_block_write(const tng_trajectory_t tng_data,
5678 const tng_gen_block_t block,
5679 const int64_t block_index,
5680 const tng_bool is_particle_data,
5681 const tng_particle_mapping_t mapping,
5682 const char hash_mode)
5684 int64_t n_particles, num_first_particle, n_frames, stride_length;
5685 int64_t full_data_len, block_data_len, frame_step, data_start_pos;
5686 int64_t i, j, k, curr_file_pos, header_file_pos;
5689 tng_function_status stat;
5690 char temp, *temp_name, ***first_dim_values, **second_dim_values, *contents;
5692 tng_trajectory_frame_set_t frame_set =
5693 &tng_data->current_trajectory_frame_set;
5695 char block_type_flag;
5696 md5_state_t md5_state;
5698 /* If we have already started writing frame sets it is too late to write
5699 * non-trajectory data blocks */
5700 if(tng_data->current_trajectory_frame_set_output_file_pos > 0)
5702 block_type_flag = TNG_TRAJECTORY_BLOCK;
5706 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5709 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
5711 return(TNG_CRITICAL);
5714 if(is_particle_data == TNG_TRUE)
5716 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5718 data = &frame_set->tr_particle_data[block_index];
5720 /* If this data block has not had any data added in this frame set
5721 * do not write it. */
5722 if(data->first_frame_with_data < frame_set->first_frame)
5724 return(TNG_SUCCESS);
5727 stride_length = tng_max_i64(1, data->stride_length);
5731 data = &tng_data->non_tr_particle_data[block_index];
5737 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5739 data = &frame_set->tr_data[block_index];
5741 /* If this data block has not had any data added in this frame set
5742 * do not write it. */
5743 if(data->first_frame_with_data < frame_set->first_frame)
5745 return(TNG_SUCCESS);
5748 stride_length = tng_max_i64(1, data->stride_length);
5752 data = &tng_data->non_tr_data[block_index];
5757 switch(data->datatype)
5763 size = sizeof(int64_t);
5765 case TNG_FLOAT_DATA:
5766 size = sizeof(float);
5768 case TNG_DOUBLE_DATA:
5770 size = sizeof(double);
5773 len = strlen(data->block_name) + 1;
5775 if(!block->name || strlen(block->name) < len)
5777 temp_name = realloc(block->name, len);
5780 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIuPTR" bytes). %s: %d\n", len+1,
5781 __FILE__, __LINE__);
5784 return(TNG_CRITICAL);
5786 block->name = temp_name;
5788 strncpy(block->name, data->block_name, len);
5789 block->id = data->block_id;
5791 /* If writing frame independent data data->n_frames is 0, but n_frames
5792 is used for the loop writing the data (and reserving memory) and needs
5794 n_frames = tng_max_i64(1, data->n_frames);
5796 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5798 /* If the frame set is finished before writing the full number of frames
5799 make sure the data block is not longer than the frame set. */
5800 n_frames = tng_min_i64(n_frames, frame_set->n_frames);
5802 n_frames -= (data->first_frame_with_data - frame_set->first_frame);
5805 frame_step = (n_frames % stride_length) ? n_frames / stride_length + 1:
5806 n_frames / stride_length;
5808 /* TNG compression will use compression precision to get integers from
5809 * floating point data. The compression multiplier stores that information
5810 * to be able to return the precision of the compressed data. */
5811 if(data->codec_id == TNG_TNG_COMPRESSION)
5813 data->compression_multiplier = tng_data->compression_precision;
5815 /* Uncompressed data blocks do not use compression multipliers at all.
5816 * GZip compression does not need it either. */
5817 else if(data->codec_id == TNG_UNCOMPRESSED || data->codec_id == TNG_GZIP_COMPRESSION)
5819 data->compression_multiplier = 1.0;
5822 if(data->dependency & TNG_PARTICLE_DEPENDENT)
5824 if(mapping && mapping->n_particles != 0)
5826 n_particles = mapping->n_particles;
5827 num_first_particle = mapping->num_first_particle;
5831 num_first_particle = 0;
5832 if(tng_data->var_num_atoms_flag)
5834 n_particles = frame_set->n_particles;
5838 n_particles = tng_data->n_particles;
5843 if(data->dependency & TNG_PARTICLE_DEPENDENT)
5845 if(tng_data_block_len_calculate(tng_data, data, TNG_TRUE, n_frames,
5846 frame_step, stride_length, num_first_particle,
5847 n_particles, &data_start_pos,
5848 &block->block_contents_size) != TNG_SUCCESS)
5850 fprintf(stderr, "TNG library: Cannot calculate length of particle data block. %s: %d\n",
5851 __FILE__, __LINE__);
5852 return(TNG_CRITICAL);
5857 if(tng_data_block_len_calculate(tng_data, data, TNG_FALSE, n_frames,
5858 frame_step, stride_length, 0,
5860 &block->block_contents_size) != TNG_SUCCESS)
5862 fprintf(stderr, "TNG library: Cannot calculate length of non-particle data block. %s: %d\n",
5863 __FILE__, __LINE__);
5864 return(TNG_CRITICAL);
5868 header_file_pos = ftello(tng_data->output_file);
5870 if(tng_block_header_write(tng_data, block) != TNG_SUCCESS)
5872 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
5873 tng_data->output_file_path, __FILE__, __LINE__);
5874 return(TNG_CRITICAL);
5877 if(hash_mode == TNG_USE_HASH)
5879 md5_init(&md5_state);
5882 if(tng_file_output_numerical(tng_data, &data->datatype,
5883 sizeof(data->datatype),
5884 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5886 return(TNG_CRITICAL);
5889 if(tng_file_output_numerical(tng_data, &data->dependency,
5890 sizeof(data->dependency),
5891 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5893 return(TNG_CRITICAL);
5896 if(data->dependency & TNG_FRAME_DEPENDENT)
5898 if(stride_length > 1)
5906 if(tng_file_output_numerical(tng_data, &temp,
5908 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5910 return(TNG_CRITICAL);
5914 if(tng_file_output_numerical(tng_data, &data->n_values_per_frame,
5915 sizeof(data->n_values_per_frame),
5916 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5918 return(TNG_CRITICAL);
5921 if(tng_file_output_numerical(tng_data, &data->codec_id,
5922 sizeof(data->codec_id),
5923 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5925 return(TNG_CRITICAL);
5928 if(data->codec_id != TNG_UNCOMPRESSED)
5930 if(tng_file_output_numerical(tng_data, &data->compression_multiplier,
5931 sizeof(data->compression_multiplier),
5932 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5934 return(TNG_CRITICAL);
5938 if(data->n_frames > 0 && stride_length > 1)
5940 /* FIXME: first_frame_with_data is not reliably set */
5941 if(data->first_frame_with_data == 0)
5943 data->first_frame_with_data = frame_set->first_frame;
5945 if(tng_file_output_numerical(tng_data, &data->first_frame_with_data,
5946 sizeof(data->first_frame_with_data),
5947 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5949 return(TNG_CRITICAL);
5952 if(tng_file_output_numerical(tng_data, &stride_length,
5953 sizeof(stride_length),
5954 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5956 return(TNG_CRITICAL);
5960 if(data->dependency & TNG_PARTICLE_DEPENDENT)
5962 if(tng_file_output_numerical(tng_data, &num_first_particle,
5963 sizeof(num_first_particle),
5964 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5966 return(TNG_CRITICAL);
5969 if(tng_file_output_numerical(tng_data, &n_particles,
5970 sizeof(n_particles),
5971 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5973 return(TNG_CRITICAL);
5977 if(data->datatype == TNG_CHAR_DATA)
5981 if(data->dependency & TNG_PARTICLE_DEPENDENT)
5983 for(i = 0; i < frame_step; i++)
5985 first_dim_values = data->strings[i];
5986 for(j = num_first_particle; j < num_first_particle + n_particles;
5989 second_dim_values = first_dim_values[j];
5990 for(k = 0; k < data->n_values_per_frame; k++)
5992 if(tng_fwritestr(tng_data, second_dim_values[k],
5993 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5995 return(TNG_CRITICAL);
6003 for(i = 0; i < frame_step; i++)
6005 for(j = 0; j < data->n_values_per_frame; j++)
6007 if(tng_fwritestr(tng_data, data->strings[0][i][j],
6008 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
6010 return(TNG_CRITICAL);
6019 if(data->dependency & TNG_PARTICLE_DEPENDENT)
6021 full_data_len = size * frame_step * n_particles * data->n_values_per_frame;
6025 full_data_len = size * frame_step * data->n_values_per_frame;
6027 contents = malloc(full_data_len);
6030 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
6031 full_data_len, __FILE__, __LINE__);
6032 return(TNG_CRITICAL);
6037 memcpy(contents, data->values, full_data_len);
6038 /* If writing TNG compressed data the endianness is taken into account by the compression
6039 * routines. TNG compressed data is always written as little endian. */
6040 if(data->codec_id != TNG_TNG_COMPRESSION)
6042 switch(data->datatype)
6044 case TNG_FLOAT_DATA:
6045 if(data->codec_id == TNG_UNCOMPRESSED || data->codec_id == TNG_GZIP_COMPRESSION)
6047 if(tng_data->output_endianness_swap_func_32)
6049 for(i = 0; i < full_data_len; i+=size)
6051 if(tng_data->output_endianness_swap_func_32(tng_data,
6052 (int32_t *)(contents + i))
6055 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6056 __FILE__, __LINE__);
6063 multiplier = data->compression_multiplier;
6064 if(fabs(multiplier - 1.0) > 0.00001 ||
6065 tng_data->output_endianness_swap_func_32)
6067 for(i = 0; full_data_len; i+=size)
6069 *(float *)(contents + i) *= (float)multiplier;
6070 if(tng_data->output_endianness_swap_func_32 &&
6071 tng_data->output_endianness_swap_func_32(tng_data,
6072 (int32_t *)(contents + i))
6075 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6076 __FILE__, __LINE__);
6083 if(tng_data->output_endianness_swap_func_64)
6085 for(i = 0; i < full_data_len; i+=size)
6087 if(tng_data->output_endianness_swap_func_64(tng_data,
6088 (int64_t *)(contents + i))
6091 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6092 __FILE__, __LINE__);
6097 case TNG_DOUBLE_DATA:
6098 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION)
6100 if(tng_data->output_endianness_swap_func_64)
6102 for(i = 0; i < full_data_len; i+=size)
6104 if(tng_data->output_endianness_swap_func_64(tng_data,
6105 (int64_t *)(contents + i))
6108 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6109 __FILE__, __LINE__);
6116 multiplier = data->compression_multiplier;
6117 if(fabs(multiplier - 1.0) > 0.00001 ||
6118 tng_data->output_endianness_swap_func_64)
6120 for(i = 0; i < full_data_len; i+=size)
6122 *(double *)(contents + i) *= multiplier;
6123 if(tng_data->output_endianness_swap_func_64 &&
6124 tng_data->output_endianness_swap_func_64(tng_data,
6125 (int64_t *)(contents + i))
6128 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6129 __FILE__, __LINE__);
6142 memset(contents, 0, full_data_len);
6145 block_data_len = full_data_len;
6147 switch(data->codec_id)
6149 case TNG_XTC_COMPRESSION:
6150 fprintf(stderr, "TNG library: XTC compression not implemented yet.\n");
6151 data->codec_id = TNG_UNCOMPRESSED;
6153 case TNG_TNG_COMPRESSION:
6154 stat = tng_compress(tng_data, block, frame_step,
6155 n_particles, data->datatype,
6156 &contents, &block_data_len);
6157 if(stat != TNG_SUCCESS)
6159 fprintf(stderr, "TNG library: Could not write TNG compressed block data. %s: %d\n",
6160 __FILE__, __LINE__);
6161 if(stat == TNG_CRITICAL)
6163 return(TNG_CRITICAL);
6165 /* Set the data again, but with no compression (to write only
6166 * the relevant data) */
6167 data->codec_id = TNG_UNCOMPRESSED;
6168 stat = tng_data_block_write(tng_data, block,
6169 block_index, is_particle_data, mapping,
6176 case TNG_GZIP_COMPRESSION:
6177 /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size); */
6178 stat = tng_gzip_compress(tng_data,
6182 if(stat != TNG_SUCCESS)
6184 fprintf(stderr, "TNG library: Could not write gzipped block data. %s: %d\n", __FILE__,
6186 if(stat == TNG_CRITICAL)
6188 return(TNG_CRITICAL);
6190 data->codec_id = TNG_UNCOMPRESSED;
6192 /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size); */
6196 if(block_data_len != full_data_len)
6198 block->block_contents_size -= full_data_len - block_data_len;
6200 curr_file_pos = ftello(tng_data->output_file);
6201 fseeko(tng_data->output_file, header_file_pos + sizeof(block->header_contents_size), SEEK_SET);
6203 if(tng_file_output_numerical(tng_data, &block->block_contents_size,
6204 sizeof(block->block_contents_size),
6205 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
6207 return(TNG_CRITICAL);
6209 fseeko(tng_data->output_file, curr_file_pos, SEEK_SET);
6211 if(fwrite(contents, block_data_len, 1, tng_data->output_file) != 1)
6213 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__,
6215 return(TNG_CRITICAL);
6217 if(hash_mode == TNG_USE_HASH)
6219 md5_append(&md5_state, (md5_byte_t *)contents, block_data_len);
6225 if(hash_mode == TNG_USE_HASH)
6227 md5_finish(&md5_state, (md5_byte_t *)block->md5_hash);
6228 curr_file_pos = ftello(tng_data->output_file);
6229 fseeko(tng_data->output_file, header_file_pos +
6230 3 * sizeof(int64_t), SEEK_SET);
6231 if(fwrite(block->md5_hash, TNG_MD5_HASH_LEN, 1, tng_data->output_file) != 1)
6233 fprintf(stderr, "TNG library: Could not write MD5 hash. %s: %d\n", __FILE__,
6235 return(TNG_CRITICAL);
6237 fseeko(tng_data->output_file, curr_file_pos, SEEK_SET);
6240 frame_set->n_written_frames += frame_set->n_unwritten_frames;
6241 frame_set->n_unwritten_frames = 0;
6243 return(TNG_SUCCESS);
6247 * @brief Read the meta information of a data block (particle or non-particle data).
6248 * @param tng_data is a trajectory data container.
6249 * @param datatype is set to the datatype of the data block.
6250 * @param dependency is set to the dependency (particle and/or frame dependent)
6251 * @param sparse_data is set to TRUE if data is not written every frame.
6252 * @param n_values is set to the number of values per frame of the data.
6253 * @param codec_id is set to the ID of the codec used to compress the data.
6254 * @param first_frame_with_data is set to the first frame with data (only relevant if
6255 * sparse_data == TRUE).
6256 * @param stride_length is set to the writing interval of the data (1 if sparse_data
6258 * @param num_first_particle is set to the number of the first particle with data written
6260 * @param block_n_particles is set to the number of particles in this data block.
6261 * @param multiplier is set to the compression multiplier.
6262 * @param hash_mode specifies whether to check if the hash matches the contents or not.
6263 * @param md5_state is the md5 hash of the block (only used if hash_mode == TNG_USE_HASH).
6264 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6265 * error has occured.
6267 static tng_function_status tng_data_block_meta_information_read
6268 (const tng_trajectory_t tng_data,
6274 int64_t *first_frame_with_data,
6275 int64_t *stride_length,
6277 int64_t *num_first_particle,
6278 int64_t *block_n_particles,
6280 const char hash_mode,
6281 md5_state_t *md5_state)
6283 if(tng_file_input_numerical(tng_data, datatype,
6285 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6287 return(TNG_CRITICAL);
6290 if(tng_file_input_numerical(tng_data, dependency,
6291 sizeof(*dependency),
6292 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6294 return(TNG_CRITICAL);
6297 if(*dependency & TNG_FRAME_DEPENDENT)
6299 if(tng_file_input_numerical(tng_data, sparse_data,
6300 sizeof(*sparse_data),
6301 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6303 return(TNG_CRITICAL);
6307 if(tng_file_input_numerical(tng_data, n_values,
6309 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6311 return(TNG_CRITICAL);
6314 if(tng_file_input_numerical(tng_data, codec_id,
6316 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6318 return(TNG_CRITICAL);
6321 if(*codec_id != TNG_UNCOMPRESSED)
6323 if(tng_file_input_numerical(tng_data, multiplier,
6324 sizeof(*multiplier),
6325 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6327 return(TNG_CRITICAL);
6335 if(*dependency & TNG_FRAME_DEPENDENT)
6339 if(tng_file_input_numerical(tng_data, first_frame_with_data,
6340 sizeof(*first_frame_with_data),
6341 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6343 return(TNG_CRITICAL);
6346 if(tng_file_input_numerical(tng_data, stride_length,
6347 sizeof(*stride_length),
6348 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6350 return(TNG_CRITICAL);
6353 *n_frames = tng_data->current_trajectory_frame_set.n_frames -
6354 (*first_frame_with_data -
6355 tng_data->current_trajectory_frame_set.first_frame);
6359 *first_frame_with_data = tng_data->current_trajectory_frame_set.first_frame;
6361 *n_frames = tng_data->current_trajectory_frame_set.n_frames;
6366 *first_frame_with_data = 0;
6371 if (*dependency & TNG_PARTICLE_DEPENDENT)
6373 if(tng_file_input_numerical(tng_data, num_first_particle,
6374 sizeof(*num_first_particle),
6375 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6377 return(TNG_CRITICAL);
6380 if(tng_file_input_numerical(tng_data, block_n_particles,
6381 sizeof(*block_n_particles),
6382 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6384 return(TNG_CRITICAL);
6389 *num_first_particle = -1;
6390 *block_n_particles = 0;
6393 return(TNG_SUCCESS);
6397 * @brief Read the contents of a data block (particle or non-particle data).
6398 * @param tng_data is a trajectory data container.
6399 * @param block is the block to store the data (should already contain
6400 * the block headers).
6401 * @param hash_mode is an option to decide whether to use the md5 hash or not.
6402 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
6403 * compared to the md5 hash of the read contents to ensure valid data.
6404 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6405 * error has occured.
6407 static tng_function_status tng_data_block_contents_read
6408 (const tng_trajectory_t tng_data,
6409 const tng_gen_block_t block,
6410 const char hash_mode)
6412 int64_t start_pos, n_values, codec_id, n_frames, first_frame_with_data;
6413 int64_t remaining_len, stride_length, block_n_particles, num_first_particle;
6415 char datatype, dependency, sparse_data;
6416 tng_function_status stat = TNG_SUCCESS;
6417 char hash[TNG_MD5_HASH_LEN];
6418 md5_state_t md5_state;
6420 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
6422 return(TNG_CRITICAL);
6425 start_pos = ftello(tng_data->input_file);
6427 if(hash_mode == TNG_USE_HASH)
6429 md5_init(&md5_state);
6432 /* FIXME: Does not check if the size of the contents matches the expected
6433 * size or if the contents can be read. */
6435 if(tng_data_block_meta_information_read(tng_data,
6437 &dependency, &sparse_data,
6438 &n_values, &codec_id,
6439 &first_frame_with_data,
6440 &stride_length, &n_frames,
6441 &num_first_particle,
6445 &md5_state) == TNG_CRITICAL)
6447 fprintf(stderr, "TNG library: Cannot read data block (%s) meta information. %s: %d\n",
6448 block->name, __FILE__, __LINE__);
6449 return(TNG_CRITICAL);
6452 remaining_len = block->block_contents_size - (ftello(tng_data->input_file) - start_pos);
6454 stat = tng_data_read(tng_data, block,
6459 first_frame_with_data,
6462 codec_id, multiplier,
6466 if(hash_mode == TNG_USE_HASH)
6468 /* If there is data left in the block that the current version of the library
6469 * cannot interpret still read that to generate the MD5 hash. */
6470 tng_md5_remaining_append(tng_data, block, start_pos, &md5_state);
6472 md5_finish(&md5_state, (md5_byte_t *)hash);
6473 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)
6475 if(strncmp(block->md5_hash, hash, TNG_MD5_HASH_LEN) != 0)
6477 fprintf(stderr, "TNG library: Data block contents corrupt (%s). Hashes do not match. "
6478 "%s: %d\n", block->name, __FILE__, __LINE__);
6484 /* Seek to the end of the block */
6485 fseeko(tng_data->input_file, start_pos + block->block_contents_size, SEEK_SET);
6492 // ** Move the blocks in a frame set so that there is no unused space between
6493 // * them. This can only be done on the last frame set in the file and should
6494 // * be done e.g. if the last frame set in the file has fewer frames than
6495 // * default or after compressing data blocks in a frame set.
6496 // * @param tng_data is a trajectory data container.
6497 // * @details the current_trajectory_frame_set is the one that will be modified.
6498 // * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the frame set
6499 // * cannot be aligned or TNG_CRITICAL (2) if a major error has occured.
6500 // * FIXME: This function is not finished!!!
6502 // static tng_function_status tng_frame_set_align(tng_trajectory_t tng_data)
6504 // tng_gen_block_t block;
6505 // tng_trajectory_frame_set_t frame_set;
6506 // FILE *temp = tng_data->input_file;
6507 // int64_t pos, contents_start_pos, output_file_len;
6509 // frame_set = &tng_data->current_trajectory_frame_set;
6511 // if(frame_set->n_written_frames == frame_set->n_frames)
6513 // return(TNG_SUCCESS);
6516 // if(tng_data->current_trajectory_frame_set_output_file_pos !=
6517 // tng_data->last_trajectory_frame_set_output_file_pos)
6521 // if(tng_output_file_init(tng_data) != TNG_SUCCESS)
6523 // fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
6524 // __FILE__, __LINE__);
6525 // return(TNG_CRITICAL);
6528 // tng_block_init(&block);
6529 // // output_file_pos = ftello(tng_data->output_file);
6531 // tng_data->input_file = tng_data->output_file;
6533 // pos = tng_data->current_trajectory_frame_set_output_file_pos;
6535 // fseeko(tng_data->output_file, pos, SEEK_SET);
6536 // if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
6538 // fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
6539 // __FILE__, __LINE__);
6540 // tng_data->input_file = temp;
6541 // tng_block_destroy(&block);
6542 // return(TNG_CRITICAL);
6545 // contents_start_pos = ftello(tng_data->output_file);
6547 // fseeko(tng_data->output_file, 0, SEEK_END);
6548 // output_file_len = ftello(tng_data->output_file);
6549 // pos = contents_start_pos + block->block_contents_size;
6550 // fseeko(tng_data->output_file, pos,
6553 // while(pos < output_file_len)
6555 // if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
6557 // fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", pos,
6558 // __FILE__, __LINE__);
6559 // tng_data->input_file = temp;
6560 // tng_block_destroy(&block);
6561 // return(TNG_CRITICAL);
6563 // pos += block->header_contents_size + block->block_contents_size;
6564 // fseeko(tng_data->output_file, pos, SEEK_SET);
6567 // return(TNG_SUCCESS);
6571 * @brief Finish writing the current frame set. Update the number of frames
6572 * and the hashes of the frame set and all its data blocks (if hash_mode
6574 * @param tng_data is a trajectory data container.
6575 * @param hash_mode specifies whether to update the block md5 hash when
6576 * updating the pointers.
6577 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6578 * error has occured.
6580 static tng_function_status tng_frame_set_finalize
6581 (const tng_trajectory_t tng_data,
6582 const char hash_mode)
6584 tng_gen_block_t block;
6585 tng_trajectory_frame_set_t frame_set;
6586 FILE *temp = tng_data->input_file;
6587 int64_t pos, curr_file_pos;
6589 frame_set = &tng_data->current_trajectory_frame_set;
6591 if(frame_set->n_written_frames == frame_set->n_frames)
6593 return(TNG_SUCCESS);
6596 frame_set->n_written_frames = frame_set->n_frames;
6598 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
6600 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
6601 __FILE__, __LINE__);
6602 return(TNG_CRITICAL);
6605 tng_block_init(&block);
6606 /* output_file_pos = ftello(tng_data->output_file); */
6608 tng_data->input_file = tng_data->output_file;
6610 curr_file_pos = ftello(tng_data->output_file);
6612 pos = tng_data->current_trajectory_frame_set_output_file_pos;
6614 fseeko(tng_data->output_file, pos, SEEK_SET);
6616 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
6618 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
6619 __FILE__, __LINE__);
6620 tng_data->input_file = temp;
6621 tng_block_destroy(&block);
6622 return(TNG_CRITICAL);
6625 // contents_start_pos = ftello(tng_data->output_file);
6627 fseeko(tng_data->output_file, sizeof(frame_set->first_frame), SEEK_CUR);
6628 if(fwrite(&frame_set->n_frames, sizeof(frame_set->n_frames),
6629 1, tng_data->output_file) != 1)
6631 tng_data->input_file = temp;
6632 tng_block_destroy(&block);
6633 return(TNG_CRITICAL);
6636 if(hash_mode == TNG_USE_HASH)
6638 tng_md5_hash_update(tng_data, block, pos,
6639 pos + block->header_contents_size);
6642 fseeko(tng_data->output_file, curr_file_pos, SEEK_SET);
6644 tng_data->input_file = temp;
6645 tng_block_destroy(&block);
6646 return(TNG_SUCCESS);
6650 // ** Sets the name of a file contents block
6651 // * @param tng_data is a trajectory data container.
6652 // * @param block is the block, of which to change names.
6653 // * @param new_name is the new name of the block.
6654 // * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6655 // * error has occured.
6657 // static tng_function_status tng_block_name_set(tng_trajectory_t tng_data,
6658 // tng_gen_block_t block,
6659 // const char *new_name)
6663 // len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
6665 // * If the currently stored string length is not enough to store the new
6666 // * string it is freed and reallocated. *
6667 // if(block->name && strlen(block->name) < len)
6669 // free(block->name);
6674 // block->name = malloc(len);
6677 // fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
6678 // __FILE__, __LINE__);
6679 // return(TNG_CRITICAL);
6683 // strncpy(block->name, new_name, len);
6685 // return(TNG_SUCCESS);
6689 tng_function_status DECLSPECDLLEXPORT tng_atom_residue_get
6690 (const tng_trajectory_t tng_data,
6691 const tng_atom_t atom,
6692 tng_residue_t *residue)
6696 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
6698 *residue = atom->residue;
6700 return(TNG_SUCCESS);
6703 tng_function_status DECLSPECDLLEXPORT tng_atom_name_get
6704 (const tng_trajectory_t tng_data,
6705 const tng_atom_t atom,
6710 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
6711 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
6713 strncpy(name, atom->name, max_len - 1);
6714 name[max_len - 1] = 0;
6716 if(strlen(atom->name) > (unsigned int)max_len - 1)
6718 return(TNG_FAILURE);
6720 return(TNG_SUCCESS);
6723 tng_function_status DECLSPECDLLEXPORT tng_atom_name_set
6724 (const tng_trajectory_t tng_data,
6725 const tng_atom_t atom,
6726 const char *new_name)
6731 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
6732 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
6734 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
6736 /* If the currently stored string length is not enough to store the new
6737 * string it is freed and reallocated. */
6738 if(atom->name && strlen(atom->name) < len)
6745 atom->name = malloc(len);
6748 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
6749 __FILE__, __LINE__);
6750 return(TNG_CRITICAL);
6754 strncpy(atom->name, new_name, len);
6756 return(TNG_SUCCESS);
6759 tng_function_status DECLSPECDLLEXPORT tng_atom_type_get
6760 (const tng_trajectory_t tng_data,
6761 const tng_atom_t atom,
6766 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
6767 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer");
6769 strncpy(type, atom->atom_type, max_len - 1);
6770 type[max_len - 1] = 0;
6772 if(strlen(atom->atom_type) > (unsigned int)max_len - 1)
6774 return(TNG_FAILURE);
6776 return(TNG_SUCCESS);
6779 tng_function_status DECLSPECDLLEXPORT tng_atom_type_set
6780 (const tng_trajectory_t tng_data,
6781 const tng_atom_t atom,
6782 const char *new_type)
6787 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
6788 TNG_ASSERT(new_type, "TNG library: new_type must not be a NULL pointer.");
6790 len = tng_min_size(strlen(new_type) + 1, TNG_MAX_STR_LEN);
6792 /* If the currently stored string length is not enough to store the new
6793 * string it is freed and reallocated. */
6794 if(atom->atom_type && strlen(atom->atom_type) < len)
6796 free(atom->atom_type);
6797 atom->atom_type = 0;
6799 if(!atom->atom_type)
6801 atom->atom_type = malloc(len);
6802 if(!atom->atom_type)
6804 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
6805 __FILE__, __LINE__);
6806 return(TNG_CRITICAL);
6810 strncpy(atom->atom_type, new_type, len);
6812 return(TNG_SUCCESS);
6816 * @brief Initialise an atom struct
6817 * @param atom is the atom to initialise.
6818 * @return TNG_SUCCESS (0) if successful.
6820 static tng_function_status tng_atom_init(const tng_atom_t atom)
6823 atom->atom_type = 0;
6825 return(TNG_SUCCESS);
6829 * @brief Free the memory in an atom struct
6830 * @param atom is the atom to destroy.
6831 * @return TNG_SUCCESS (0) if successful.
6833 static tng_function_status tng_atom_destroy(const tng_atom_t atom)
6842 free(atom->atom_type);
6843 atom->atom_type = 0;
6846 return(TNG_SUCCESS);
6850 * @brief Update chain->residue pointers (after new memory for
6851 * molecule->residues has been allocated).
6852 * @param tng_data The trajectory container containing the molecule.
6853 * @param mol The molecule that contains the chains that need to be
6855 * @returns TNG_SUCCESS (0) if successful.
6857 static tng_function_status tng_molecule_chains_residue_pointers_update
6858 (const tng_trajectory_t tng_data,
6859 const tng_molecule_t mol)
6862 int64_t i, res_cnt = 0;
6865 for(i = 0; i < mol->n_chains; i++)
6867 chain = &mol->chains[i];
6868 chain->residues = mol->residues + res_cnt;
6869 res_cnt += chain->n_residues;
6871 return(TNG_SUCCESS);
6874 tng_function_status DECLSPECDLLEXPORT tng_version_major
6875 (const tng_trajectory_t tng_data,
6880 *version = TNG_VERSION_MAJOR;
6882 return(TNG_SUCCESS);
6885 tng_function_status DECLSPECDLLEXPORT tng_version_minor
6886 (const tng_trajectory_t tng_data,
6891 *version = TNG_VERSION_MINOR;
6893 return(TNG_SUCCESS);
6896 tng_function_status DECLSPECDLLEXPORT tng_version_patchlevel
6897 (const tng_trajectory_t tng_data,
6902 *patch_level = TNG_VERSION_PATCHLEVEL;
6904 return(TNG_SUCCESS);
6907 tng_function_status DECLSPECDLLEXPORT tng_version
6908 (const tng_trajectory_t tng_data,
6913 TNG_ASSERT(version, "TNG library: version must not be a NULL pointer");
6915 TNG_SNPRINTF(version, max_len, "%s", TNG_VERSION);
6917 return(TNG_SUCCESS);
6920 tng_function_status DECLSPECDLLEXPORT tng_molecule_add
6921 (const tng_trajectory_t tng_data,
6923 tng_molecule_t *molecule)
6927 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
6928 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
6930 /* Set ID to the ID of the last molecule + 1 */
6931 if(tng_data->n_molecules)
6933 id = tng_data->molecules[tng_data->n_molecules-1].id + 1;
6940 return(tng_molecule_w_id_add(tng_data, name, id, molecule));
6943 tng_function_status DECLSPECDLLEXPORT tng_molecule_w_id_add
6944 (const tng_trajectory_t tng_data,
6947 tng_molecule_t *molecule)
6949 tng_molecule_t new_molecules;
6950 int64_t *new_molecule_cnt_list;
6951 tng_function_status stat = TNG_SUCCESS;
6953 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
6954 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
6956 new_molecules = realloc(tng_data->molecules,
6957 sizeof(struct tng_molecule) *
6958 (tng_data->n_molecules + 1));
6962 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
6963 sizeof(struct tng_molecule) * (tng_data->n_molecules + 1),
6964 __FILE__, __LINE__);
6965 free(tng_data->molecules);
6966 tng_data->molecules = 0;
6967 return(TNG_CRITICAL);
6970 new_molecule_cnt_list = realloc(tng_data->molecule_cnt_list,
6972 (tng_data->n_molecules + 1));
6974 if(!new_molecule_cnt_list)
6976 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
6977 sizeof(int64_t) * (tng_data->n_molecules + 1),
6978 __FILE__, __LINE__);
6979 free(tng_data->molecule_cnt_list);
6980 tng_data->molecule_cnt_list = 0;
6981 free(new_molecules);
6982 return(TNG_CRITICAL);
6985 tng_data->molecules = new_molecules;
6986 tng_data->molecule_cnt_list = new_molecule_cnt_list;
6988 *molecule = &new_molecules[tng_data->n_molecules];
6990 tng_molecule_init(tng_data, *molecule);
6991 tng_molecule_name_set(tng_data, *molecule, name);
6993 /* FIXME: Should this be a function argument instead? */
6994 tng_data->molecule_cnt_list[tng_data->n_molecules] = 0;
6996 (*molecule)->id = id;
6998 tng_data->n_molecules++;
7003 tng_function_status DECLSPECDLLEXPORT tng_molecule_existing_add
7004 (const tng_trajectory_t tng_data,
7005 tng_molecule_t *molecule_p)
7007 int64_t *new_molecule_cnt_list, id;
7008 tng_molecule_t new_molecules, molecule;
7010 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7012 /* Set ID to the ID of the last molecule + 1 */
7013 if(tng_data->n_molecules)
7015 id = tng_data->molecules[tng_data->n_molecules-1].id + 1;
7022 new_molecules = realloc(tng_data->molecules,
7023 sizeof(struct tng_molecule) *
7024 (tng_data->n_molecules + 1));
7028 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
7029 sizeof(struct tng_molecule) * (tng_data->n_molecules + 1),
7030 __FILE__, __LINE__);
7031 free(tng_data->molecules);
7032 tng_data->molecules = 0;
7033 return(TNG_CRITICAL);
7036 new_molecule_cnt_list = realloc(tng_data->molecule_cnt_list,
7038 (tng_data->n_molecules + 1));
7040 if(!new_molecule_cnt_list)
7042 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
7043 sizeof(int64_t) * (tng_data->n_molecules + 1),
7044 __FILE__, __LINE__);
7045 free(tng_data->molecule_cnt_list);
7046 tng_data->molecule_cnt_list = 0;
7047 free(new_molecules);
7048 return(TNG_CRITICAL);
7051 molecule = *molecule_p;
7053 tng_data->molecules = new_molecules;
7054 tng_data->molecule_cnt_list = new_molecule_cnt_list;
7056 new_molecules[tng_data->n_molecules] = *molecule;
7058 tng_data->molecule_cnt_list[tng_data->n_molecules] = 0;
7062 molecule = &new_molecules[tng_data->n_molecules];
7064 *molecule_p = molecule;
7068 tng_data->n_molecules++;
7070 return(TNG_SUCCESS);
7073 tng_function_status tng_molecule_name_get(const tng_trajectory_t tng_data,
7074 const tng_molecule_t molecule,
7079 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
7080 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
7082 strncpy(name, molecule->name, max_len - 1);
7083 name[max_len - 1] = 0;
7085 if(strlen(molecule->name) > (unsigned int)max_len - 1)
7087 return(TNG_FAILURE);
7089 return(TNG_SUCCESS);
7092 tng_function_status DECLSPECDLLEXPORT tng_molecule_name_set
7093 (const tng_trajectory_t tng_data,
7094 const tng_molecule_t molecule,
7095 const char *new_name)
7100 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7101 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
7103 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
7105 /* If the currently stored string length is not enough to store the new
7106 * string it is freed and reallocated. */
7107 if(molecule->name && strlen(molecule->name) < len)
7109 free(molecule->name);
7114 molecule->name = malloc(len);
7117 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
7118 __FILE__, __LINE__);
7119 return(TNG_CRITICAL);
7123 strncpy(molecule->name, new_name, len);
7125 return(TNG_SUCCESS);
7128 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_get
7129 (const tng_trajectory_t tng_data,
7130 const tng_molecule_t molecule,
7133 int64_t i, index = -1;
7135 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7136 TNG_ASSERT(cnt, "TNG library: cnt must not be a NULL pointer.");
7138 for(i = 0; i < tng_data->n_molecules; i++)
7140 if(&tng_data->molecules[i] == molecule)
7148 return(TNG_FAILURE);
7150 *cnt = tng_data->molecule_cnt_list[index];
7152 return(TNG_SUCCESS);
7155 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_set
7156 (const tng_trajectory_t tng_data,
7157 const tng_molecule_t molecule,
7160 int64_t i, old_cnt, index = -1;
7162 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7164 for(i = 0; i < tng_data->n_molecules; i++)
7166 if(&tng_data->molecules[i] == molecule)
7174 fprintf(stderr, "TNG library: Could not find molecule in TNG trajectory. %s: %d\n",
7175 __FILE__, __LINE__);
7176 return(TNG_FAILURE);
7178 if(tng_data->var_num_atoms_flag == TNG_CONSTANT_N_ATOMS)
7180 old_cnt = tng_data->molecule_cnt_list[index];
7181 tng_data->molecule_cnt_list[index] = cnt;
7183 tng_data->n_particles += (cnt-old_cnt) *
7184 tng_data->molecules[index].n_atoms;
7188 old_cnt = tng_data->current_trajectory_frame_set.molecule_cnt_list[index];
7189 tng_data->current_trajectory_frame_set.molecule_cnt_list[index] = cnt;
7191 tng_data->current_trajectory_frame_set.n_particles += (cnt-old_cnt) *
7192 tng_data->molecules[index].n_atoms;
7195 return(TNG_SUCCESS);
7198 tng_function_status DECLSPECDLLEXPORT tng_molecule_find
7199 (const tng_trajectory_t tng_data,
7202 tng_molecule_t *molecule)
7204 int64_t i, n_molecules;
7206 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7207 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7208 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
7210 n_molecules = tng_data->n_molecules;
7212 for(i = n_molecules - 1; i >= 0; i--)
7214 *molecule = &tng_data->molecules[i];
7215 if(name[0] == 0 || strcmp(name, (*molecule)->name) == 0)
7217 if(nr == -1 || nr == (*molecule)->id)
7219 return(TNG_SUCCESS);
7226 return(TNG_FAILURE);
7229 tng_function_status DECLSPECDLLEXPORT tng_molecule_of_index_get
7230 (const tng_trajectory_t tng_data,
7231 const int64_t index,
7232 tng_molecule_t *molecule)
7234 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7235 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
7237 if(index >= tng_data->n_molecules)
7240 return(TNG_FAILURE);
7242 *molecule = &tng_data->molecules[index];
7243 return(TNG_SUCCESS);
7246 tng_function_status DECLSPECDLLEXPORT tng_molecule_system_copy(const tng_trajectory_t tng_data_src,
7247 const tng_trajectory_t tng_data_dest)
7249 tng_molecule_t molecule, molecule_temp;
7250 tng_chain_t chain, chain_temp;
7251 tng_residue_t residue, residue_temp;
7252 tng_atom_t atom, atom_temp;
7253 tng_bond_t bond_temp;
7254 tng_function_status stat;
7255 int64_t i, j, k, l, *list_temp;
7257 TNG_ASSERT(tng_data_src, "TNG library: Trajectory container not properly setup.");
7258 TNG_ASSERT(tng_data_dest, "TNG library: Trajectory container not properly setup.");
7260 for(i = 0; i < tng_data_dest->n_molecules; i++)
7262 molecule = &tng_data_dest->molecules[i];
7263 tng_molecule_destroy(tng_data_dest, molecule);
7266 tng_data_dest->n_molecules = 0;
7267 tng_data_dest->n_particles = 0;
7269 molecule_temp = realloc(tng_data_dest->molecules,
7270 sizeof(struct tng_molecule) * tng_data_src->n_molecules);
7273 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
7274 sizeof(struct tng_molecule) * tng_data_src->n_molecules,
7275 __FILE__, __LINE__);
7276 free(tng_data_dest->molecules);
7277 tng_data_dest->molecules = 0;
7278 return(TNG_CRITICAL);
7280 list_temp = realloc(tng_data_dest->molecule_cnt_list,
7281 sizeof(int64_t) * tng_data_src->n_molecules);
7284 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
7285 sizeof(int64_t) * tng_data_src->n_molecules,
7286 __FILE__, __LINE__);
7287 free(tng_data_dest->molecule_cnt_list);
7288 tng_data_dest->molecule_cnt_list = 0;
7289 free(molecule_temp);
7290 return(TNG_CRITICAL);
7293 tng_data_dest->molecules = molecule_temp;
7294 tng_data_dest->molecule_cnt_list = list_temp;
7296 for(i = 0; i < tng_data_src->n_molecules; i++)
7298 molecule = &tng_data_src->molecules[i];
7299 stat = tng_molecule_w_id_add(tng_data_dest, molecule->name, molecule->id,
7301 if(stat != TNG_SUCCESS)
7303 fprintf(stderr, "TNG library: Cannot create new molecule to make a copy. %s: %d\n",
7304 __FILE__, __LINE__);
7307 molecule_temp->quaternary_str = molecule->quaternary_str;
7308 for(j = 0; j < molecule->n_chains; j++)
7310 chain = &molecule->chains[j];
7311 stat = tng_molecule_chain_w_id_add(tng_data_dest, molecule_temp,
7312 chain->name, chain->id,
7314 if(stat != TNG_SUCCESS)
7316 fprintf(stderr, "TNG library: Cannot create new chain to make a copy. %s: %d\n",
7317 __FILE__, __LINE__);
7320 for(k = 0; k < chain->n_residues; k++)
7322 residue = &chain->residues[k];
7323 stat = tng_chain_residue_w_id_add(tng_data_dest, chain_temp,
7324 residue->name, residue->id,
7326 if(stat != TNG_SUCCESS)
7328 fprintf(stderr, "TNG library: Cannot create new residue to make a copy. %s: %d\n",
7329 __FILE__, __LINE__);
7332 for(l = 0; l < residue->n_atoms; l++)
7334 atom = &molecule->atoms[residue->atoms_offset + l];
7335 stat = tng_residue_atom_w_id_add(tng_data_dest, residue_temp,
7336 atom->name, atom->atom_type,
7337 atom->id, &atom_temp);
7338 if(stat != TNG_SUCCESS)
7340 fprintf(stderr, "TNG library: Cannot create new atom to make a copy. %s: %d\n",
7341 __FILE__, __LINE__);
7347 molecule_temp->n_bonds = molecule->n_bonds;
7348 if(molecule->n_bonds > 0)
7350 bond_temp = realloc(molecule_temp->bonds, sizeof(struct tng_bond) *
7354 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
7355 sizeof(struct tng_bond) * molecule->n_bonds,
7356 __FILE__, __LINE__);
7357 free(molecule_temp->bonds);
7358 molecule_temp->n_bonds = 0;
7359 return(TNG_CRITICAL);
7361 molecule_temp->bonds = bond_temp;
7362 for(j = 0; j < molecule->n_bonds; j++)
7364 molecule_temp->bonds[j] = molecule->bonds[j];
7367 stat = tng_molecule_cnt_set(tng_data_dest, molecule_temp,
7368 tng_data_src->molecule_cnt_list[i]);
7369 if(stat != TNG_SUCCESS)
7371 fprintf(stderr, "TNG library: Cannot set molecule count. %s: %d.\n",
7372 __FILE__, __LINE__);
7376 return(TNG_SUCCESS);
7379 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_chains_get
7380 (const tng_trajectory_t tng_data,
7381 const tng_molecule_t molecule,
7385 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
7386 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
7388 *n = molecule->n_chains;
7390 return(TNG_SUCCESS);
7393 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_of_index_get
7394 (const tng_trajectory_t tng_data,
7395 const tng_molecule_t molecule,
7396 const int64_t index,
7400 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
7401 TNG_ASSERT(chain, "TNG library: chain must not be a NULL pointer.");
7403 if(index >= molecule->n_chains)
7406 return(TNG_FAILURE);
7408 *chain = &molecule->chains[index];
7409 return(TNG_SUCCESS);
7412 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_residues_get
7413 (const tng_trajectory_t tng_data,
7414 const tng_molecule_t molecule,
7418 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
7419 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
7421 *n = molecule->n_residues;
7423 return(TNG_SUCCESS);
7426 tng_function_status DECLSPECDLLEXPORT tng_molecule_residue_of_index_get
7427 (const tng_trajectory_t tng_data,
7428 const tng_molecule_t molecule,
7429 const int64_t index,
7430 tng_residue_t *residue)
7433 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
7434 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
7436 if(index >= molecule->n_residues)
7439 return(TNG_FAILURE);
7441 *residue = &molecule->residues[index];
7442 return(TNG_SUCCESS);
7445 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_atoms_get
7446 (const tng_trajectory_t tng_data,
7447 const tng_molecule_t molecule,
7451 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
7452 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
7454 *n = molecule->n_atoms;
7456 return(TNG_SUCCESS);
7459 tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_of_index_get
7460 (const tng_trajectory_t tng_data,
7461 const tng_molecule_t molecule,
7462 const int64_t index,
7466 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
7467 TNG_ASSERT(atom, "TNG library: atom must not be a NULL pointer.");
7469 if(index >= molecule->n_atoms)
7472 return(TNG_FAILURE);
7474 *atom = &molecule->atoms[index];
7475 return(TNG_SUCCESS);
7478 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_find
7479 (const tng_trajectory_t tng_data,
7480 const tng_molecule_t molecule,
7485 int64_t i, n_chains;
7488 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7489 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7491 n_chains = molecule->n_chains;
7493 for(i = n_chains - 1; i >= 0; i--)
7495 *chain = &molecule->chains[i];
7496 if(name[0] == 0 || strcmp(name, (*chain)->name) == 0)
7498 if(nr == -1 || nr == (*chain)->id)
7500 return(TNG_SUCCESS);
7507 return(TNG_FAILURE);
7510 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_add
7511 (const tng_trajectory_t tng_data,
7512 const tng_molecule_t molecule,
7518 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7519 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7521 /* Set ID to the ID of the last chain + 1 */
7522 if(molecule->n_chains)
7524 id = molecule->chains[molecule->n_chains-1].id + 1;
7531 return(tng_molecule_chain_w_id_add(tng_data, molecule, name,
7535 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_w_id_add
7536 (const tng_trajectory_t tng_data,
7537 const tng_molecule_t molecule,
7542 tng_chain_t new_chains;
7543 tng_function_status stat = TNG_SUCCESS;
7545 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7546 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7548 new_chains = realloc(molecule->chains,
7549 sizeof(struct tng_chain) *
7550 (molecule->n_chains + 1));
7554 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
7555 sizeof(struct tng_chain) * (molecule->n_chains + 1),
7556 __FILE__, __LINE__);
7557 free(molecule->chains);
7558 molecule->chains = 0;
7559 return(TNG_CRITICAL);
7562 molecule->chains = new_chains;
7564 *chain = &new_chains[molecule->n_chains];
7567 tng_chain_name_set(tng_data, *chain, name);
7569 (*chain)->molecule = molecule;
7570 (*chain)->n_residues = 0;
7572 molecule->n_chains++;
7579 tng_function_status DECLSPECDLLEXPORT tng_molecule_bond_add
7580 (const tng_trajectory_t tng_data,
7581 const tng_molecule_t molecule,
7582 const int64_t from_atom_id,
7583 const int64_t to_atom_id,
7586 tng_bond_t new_bonds;
7589 new_bonds = realloc(molecule->bonds,
7590 sizeof(struct tng_bond) *
7591 (molecule->n_bonds + 1));
7595 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
7596 sizeof(struct tng_bond) * (molecule->n_bonds + 1),
7597 __FILE__, __LINE__);
7599 free(molecule->bonds);
7600 molecule->bonds = 0;
7601 return(TNG_CRITICAL);
7604 molecule->bonds = new_bonds;
7606 *bond = &new_bonds[molecule->n_bonds];
7608 (*bond)->from_atom_id = from_atom_id;
7609 (*bond)->to_atom_id = to_atom_id;
7611 molecule->n_bonds++;
7613 return(TNG_SUCCESS);
7616 tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_find
7617 (const tng_trajectory_t tng_data,
7618 const tng_molecule_t molecule,
7626 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7628 n_atoms = molecule->n_atoms;
7630 for(i = n_atoms - 1; i >= 0; i--)
7632 *atom = &molecule->atoms[i];
7633 if(name[0] == 0 || strcmp(name, (*atom)->name) == 0)
7635 if(id == -1 || id == (*atom)->id)
7637 return(TNG_SUCCESS);
7644 return(TNG_FAILURE);
7647 tng_function_status tng_chain_name_get(const tng_trajectory_t tng_data,
7648 const tng_chain_t chain,
7653 TNG_ASSERT(chain, "TNG library: chain must not be NULL");
7654 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
7656 strncpy(name, chain->name, max_len - 1);
7657 name[max_len - 1] = 0;
7659 if(strlen(chain->name) > (unsigned int)max_len - 1)
7661 return(TNG_FAILURE);
7663 return(TNG_SUCCESS);
7666 tng_function_status DECLSPECDLLEXPORT tng_chain_name_set
7667 (const tng_trajectory_t tng_data,
7668 const tng_chain_t chain,
7669 const char *new_name)
7674 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
7676 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
7678 /* If the currently stored string length is not enough to store the new
7679 * string it is freed and reallocated. */
7680 if(chain->name && strlen(chain->name) < len)
7687 chain->name = malloc(len);
7690 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
7691 __FILE__, __LINE__);
7692 return(TNG_CRITICAL);
7696 strncpy(chain->name, new_name, len);
7698 return(TNG_SUCCESS);
7701 tng_function_status DECLSPECDLLEXPORT tng_chain_num_residues_get
7702 (const tng_trajectory_t tng_data,
7703 const tng_chain_t chain,
7707 TNG_ASSERT(chain, "TNG library: chain must not be NULL");
7708 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
7710 *n = chain->n_residues;
7712 return(TNG_SUCCESS);
7715 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_of_index_get
7716 (const tng_trajectory_t tng_data,
7717 const tng_chain_t chain,
7718 const int64_t index,
7719 tng_residue_t *residue)
7722 TNG_ASSERT(chain, "TNG library: chain must not be a NULL pointer.");
7723 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
7725 if(index >= chain->n_residues)
7728 return(TNG_FAILURE);
7730 *residue = &chain->residues[index];
7731 return(TNG_SUCCESS);
7734 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_find
7735 (const tng_trajectory_t tng_data,
7736 const tng_chain_t chain,
7739 tng_residue_t *residue)
7741 int64_t i, n_residues;
7744 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7746 n_residues = chain->n_residues;
7748 for(i = n_residues - 1; i >= 0; i--)
7750 *residue = &chain->residues[i];
7751 if(name[0] == 0 || strcmp(name, (*residue)->name) == 0)
7753 if(id == -1 || id == (*residue)->id)
7755 return(TNG_SUCCESS);
7762 return(TNG_FAILURE);
7765 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_add
7766 (const tng_trajectory_t tng_data,
7767 const tng_chain_t chain,
7769 tng_residue_t *residue)
7773 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7774 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7776 /* Set ID to the ID of the last residue + 1 */
7777 if(chain->n_residues)
7779 id = chain->residues[chain->n_residues-1].id + 1;
7786 return(tng_chain_residue_w_id_add(tng_data, chain, name,
7790 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_w_id_add
7791 (const tng_trajectory_t tng_data,
7792 const tng_chain_t chain,
7795 tng_residue_t *residue)
7798 tng_residue_t new_residues, temp_residue, last_residue;
7799 tng_molecule_t molecule = chain->molecule;
7800 tng_function_status stat = TNG_SUCCESS;
7802 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7803 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7805 if(chain->n_residues)
7807 curr_index = chain->residues - molecule->residues;
7814 new_residues = realloc(molecule->residues,
7815 sizeof(struct tng_residue) *
7816 (molecule->n_residues + 1));
7820 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
7821 sizeof(struct tng_residue) * (molecule->n_residues + 1),
7822 __FILE__, __LINE__);
7823 free(molecule->residues);
7824 molecule->residues = 0;
7825 return(TNG_CRITICAL);
7828 molecule->residues = new_residues;
7830 if(curr_index != -1)
7832 chain->residues = new_residues + curr_index;
7833 if(molecule->n_residues)
7835 last_residue = &new_residues[molecule->n_residues - 1];
7837 temp_residue = chain->residues + (chain->n_residues - 1);
7838 /* Make space in list of residues to add the new residues together with the other
7839 * residues of this chain */
7840 if(temp_residue != last_residue)
7843 memmove(temp_residue + 1, temp_residue,
7844 last_residue - temp_residue);
7850 curr_index = molecule->n_residues;
7853 *residue = &molecule->residues[curr_index + chain->n_residues];
7855 tng_molecule_chains_residue_pointers_update(tng_data, molecule);
7857 (*residue)->name = 0;
7858 tng_residue_name_set(tng_data, *residue, name);
7860 (*residue)->chain = chain;
7861 (*residue)->n_atoms = 0;
7862 (*residue)->atoms_offset = 0;
7864 chain->n_residues++;
7865 molecule->n_residues++;
7867 (*residue)->id = id;
7872 tng_function_status tng_residue_name_get(const tng_trajectory_t tng_data,
7873 const tng_residue_t residue,
7878 TNG_ASSERT(residue, "TNG library: residue must not be NULL");
7879 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
7881 strncpy(name, residue->name, max_len - 1);
7882 name[max_len - 1] = 0;
7884 if(strlen(residue->name) > (unsigned int)max_len - 1)
7886 return(TNG_FAILURE);
7888 return(TNG_SUCCESS);
7891 tng_function_status DECLSPECDLLEXPORT tng_residue_name_set(const tng_trajectory_t tng_data,
7892 const tng_residue_t residue,
7893 const char *new_name)
7898 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7899 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
7901 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
7903 /* If the currently stored string length is not enough to store the new
7904 * string it is freed and reallocated. */
7905 if(residue->name && strlen(residue->name) < len)
7907 free(residue->name);
7912 residue->name = malloc(len);
7915 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
7916 __FILE__, __LINE__);
7917 return(TNG_CRITICAL);
7921 strncpy(residue->name, new_name, len);
7923 return(TNG_SUCCESS);
7926 tng_function_status DECLSPECDLLEXPORT tng_residue_num_atoms_get
7927 (const tng_trajectory_t tng_data,
7928 const tng_residue_t residue,
7932 TNG_ASSERT(residue, "TNG library: residue must not be NULL");
7933 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
7935 *n = residue->n_atoms;
7937 return(TNG_SUCCESS);
7940 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_of_index_get
7941 (const tng_trajectory_t tng_data,
7942 const tng_residue_t residue,
7943 const int64_t index,
7947 tng_molecule_t molecule;
7950 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
7951 TNG_ASSERT(atom, "TNG library: atom must not be a NULL pointer.");
7953 if(index >= residue->n_atoms)
7956 return(TNG_FAILURE);
7958 chain = residue->chain;
7959 molecule = chain->molecule;
7961 if(index + residue->atoms_offset >= molecule->n_atoms)
7964 return(TNG_FAILURE);
7967 *atom = &molecule->atoms[residue->atoms_offset + index];
7968 return(TNG_SUCCESS);
7971 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_add
7972 (const tng_trajectory_t tng_data,
7973 const tng_residue_t residue,
7974 const char *atom_name,
7975 const char *atom_type,
7980 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7981 TNG_ASSERT(atom_name, "TNG library: atom_name must not be a NULL pointer.");
7982 TNG_ASSERT(atom_type, "TNG library: atom_type must not be a NULL pointer.");
7984 /* Set ID to the ID of the last atom + 1 */
7985 if(residue->chain->molecule->n_atoms)
7987 id = residue->chain->molecule->atoms[residue->chain->molecule->n_atoms-1].id + 1;
7994 return(tng_residue_atom_w_id_add(tng_data, residue, atom_name, atom_type,
7998 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_w_id_add
7999 (const tng_trajectory_t tng_data,
8000 const tng_residue_t residue,
8001 const char *atom_name,
8002 const char *atom_type,
8006 tng_atom_t new_atoms;
8007 tng_molecule_t molecule = residue->chain->molecule;
8008 tng_function_status stat = TNG_SUCCESS;
8010 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8011 TNG_ASSERT(atom_name, "TNG library: atom_name must not be a NULL pointer.");
8012 TNG_ASSERT(atom_type, "TNG library: atom_type must not be a NULL pointer.");
8014 if(!residue->n_atoms)
8016 residue->atoms_offset = molecule->n_atoms;
8019 new_atoms = realloc(molecule->atoms,
8020 sizeof(struct tng_atom) *
8021 (molecule->n_atoms + 1));
8025 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
8026 sizeof(struct tng_atom) * (molecule->n_atoms + 1),
8027 __FILE__, __LINE__);
8028 free(molecule->atoms);
8029 molecule->atoms = 0;
8030 return(TNG_CRITICAL);
8033 molecule->atoms = new_atoms;
8035 *atom = &new_atoms[molecule->n_atoms];
8037 tng_atom_init(*atom);
8038 tng_atom_name_set(tng_data, *atom, atom_name);
8039 tng_atom_type_set(tng_data, *atom, atom_type);
8041 (*atom)->residue = residue;
8044 molecule->n_atoms++;
8051 tng_function_status DECLSPECDLLEXPORT tng_molecule_alloc(const tng_trajectory_t tng_data,
8052 tng_molecule_t *molecule_p)
8054 *molecule_p = malloc(sizeof(struct tng_molecule));
8057 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIuPTR" bytes). %s: %d\n",
8058 sizeof(struct tng_molecule), __FILE__, __LINE__);
8059 return(TNG_CRITICAL);
8062 tng_molecule_init(tng_data, *molecule_p);
8064 return(TNG_SUCCESS);
8067 tng_function_status DECLSPECDLLEXPORT tng_molecule_free(const tng_trajectory_t tng_data,
8068 tng_molecule_t *molecule_p)
8072 return(TNG_SUCCESS);
8075 tng_molecule_destroy(tng_data, *molecule_p);
8080 return(TNG_SUCCESS);
8083 tng_function_status DECLSPECDLLEXPORT tng_molecule_init(const tng_trajectory_t tng_data,
8084 const tng_molecule_t molecule)
8087 molecule->quaternary_str = 1;
8089 molecule->n_chains = 0;
8090 molecule->chains = 0;
8091 molecule->n_residues = 0;
8092 molecule->residues = 0;
8093 molecule->n_atoms = 0;
8094 molecule->atoms = 0;
8095 molecule->n_bonds = 0;
8096 molecule->bonds = 0;
8098 return(TNG_SUCCESS);
8101 tng_function_status DECLSPECDLLEXPORT tng_molecule_destroy(const tng_trajectory_t tng_data,
8102 const tng_molecule_t molecule)
8109 free(molecule->name);
8113 if(molecule->chains)
8115 for(i = 0; i < molecule->n_chains; i++)
8117 if(molecule->chains[i].name)
8119 free(molecule->chains[i].name);
8120 molecule->chains[i].name = 0;
8123 free(molecule->chains);
8124 molecule->chains = 0;
8126 molecule->n_chains = 0;
8128 if(molecule->residues)
8130 for(i = 0; i < molecule->n_residues; i++)
8132 if(molecule->residues[i].name)
8134 free(molecule->residues[i].name);
8135 molecule->residues[i].name = 0;
8138 free(molecule->residues);
8139 molecule->residues = 0;
8141 molecule->n_residues = 0;
8145 for(i = 0; i < molecule->n_atoms; i++)
8147 tng_atom_destroy(&molecule->atoms[i]);
8149 free(molecule->atoms);
8150 molecule->atoms = 0;
8152 molecule->n_atoms = 0;
8156 free(molecule->bonds);
8157 molecule->bonds = 0;
8159 molecule->n_bonds = 0;
8161 return(TNG_SUCCESS);
8164 tng_function_status DECLSPECDLLEXPORT tng_molecule_name_of_particle_nr_get
8165 (const tng_trajectory_t tng_data,
8170 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8172 tng_bool found = TNG_FALSE;
8174 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8175 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8177 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8179 if(!molecule_cnt_list)
8181 return(TNG_FAILURE);
8184 for(i = 0; i < tng_data->n_molecules; i++)
8186 mol = &tng_data->molecules[i];
8187 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8189 cnt += mol->n_atoms * molecule_cnt_list[i];
8197 return(TNG_FAILURE);
8200 strncpy(name, mol->name, max_len - 1);
8201 name[max_len - 1] = 0;
8203 if(strlen(mol->name) > (unsigned int)max_len - 1)
8205 return(TNG_FAILURE);
8207 return(TNG_SUCCESS);
8210 tng_function_status DECLSPECDLLEXPORT tng_molecule_id_of_particle_nr_get
8211 (const tng_trajectory_t tng_data,
8215 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8217 tng_bool found = TNG_FALSE;
8219 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8220 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
8222 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8224 if(!molecule_cnt_list)
8226 return(TNG_FAILURE);
8229 for(i = 0; i < tng_data->n_molecules; i++)
8231 mol = &tng_data->molecules[i];
8232 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8234 cnt += mol->n_atoms * molecule_cnt_list[i];
8242 return(TNG_FAILURE);
8247 return(TNG_SUCCESS);
8250 tng_function_status DECLSPECDLLEXPORT tng_molsystem_bonds_get
8251 (const tng_trajectory_t tng_data,
8253 int64_t **from_atoms,
8256 int64_t atom_cnt = 0, cnt, mol_cnt, i, j, k;
8257 int64_t from_atom, to_atom, *molecule_cnt_list = 0;
8261 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8262 TNG_ASSERT(n_bonds, "TNG library: n_bonds must not be a NULL pointer.");
8263 TNG_ASSERT(from_atoms, "TNG library: from_atoms must not be a NULL pointer.");
8264 TNG_ASSERT(to_atoms, "TNG library: to_atoms must not be a NULL pointer.");
8266 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8268 if(!molecule_cnt_list)
8270 return(TNG_FAILURE);
8274 /* First count the total number of bonds to allocate memory */
8275 for(i = 0; i < tng_data->n_molecules; i++)
8277 mol = &tng_data->molecules[i];
8278 mol_cnt = molecule_cnt_list[i];
8279 *n_bonds += mol_cnt * mol->n_bonds;
8283 return(TNG_SUCCESS);
8286 *from_atoms = malloc(sizeof(int64_t) * (*n_bonds));
8289 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
8290 sizeof(int64_t) * (*n_bonds), __FILE__, __LINE__);
8291 return(TNG_CRITICAL);
8293 *to_atoms = malloc(sizeof(int64_t) * (*n_bonds));
8296 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
8297 sizeof(int64_t) * (*n_bonds), __FILE__, __LINE__);
8300 return(TNG_CRITICAL);
8304 for(i = 0; i < tng_data->n_molecules; i++)
8306 mol = &tng_data->molecules[i];
8307 mol_cnt = molecule_cnt_list[i];
8308 for(j = 0; j < mol_cnt; j++)
8310 for(k = 0; k < mol->n_bonds; k++)
8312 bond = &mol->bonds[k];
8313 from_atom = atom_cnt + bond->from_atom_id;
8314 to_atom = atom_cnt + bond->to_atom_id;
8315 (*from_atoms)[cnt] = from_atom;
8316 (*to_atoms)[cnt++] = to_atom;
8318 atom_cnt += mol->n_atoms;
8322 return(TNG_SUCCESS);
8325 tng_function_status DECLSPECDLLEXPORT tng_chain_name_of_particle_nr_get
8326 (const tng_trajectory_t tng_data,
8331 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8334 tng_bool found = TNG_FALSE;
8336 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8337 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8339 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8341 if(!molecule_cnt_list)
8343 return(TNG_FAILURE);
8346 for(i = 0; i < tng_data->n_molecules; i++)
8348 mol = &tng_data->molecules[i];
8349 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8351 cnt += mol->n_atoms * molecule_cnt_list[i];
8354 atom = &mol->atoms[nr % mol->n_atoms];
8360 return(TNG_FAILURE);
8362 if(!atom->residue || !atom->residue->chain)
8364 return(TNG_FAILURE);
8367 strncpy(name, atom->residue->chain->name, max_len - 1);
8368 name[max_len - 1] = 0;
8370 if(strlen(atom->residue->chain->name) > (unsigned int)max_len - 1)
8372 return(TNG_FAILURE);
8374 return(TNG_SUCCESS);
8377 tng_function_status DECLSPECDLLEXPORT tng_residue_name_of_particle_nr_get
8378 (const tng_trajectory_t tng_data,
8383 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8386 tng_bool found = TNG_FALSE;
8388 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8389 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8391 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8393 if(!molecule_cnt_list)
8395 return(TNG_FAILURE);
8398 for(i = 0; i < tng_data->n_molecules; i++)
8400 mol = &tng_data->molecules[i];
8401 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8403 cnt += mol->n_atoms * molecule_cnt_list[i];
8406 atom = &mol->atoms[nr % mol->n_atoms];
8412 return(TNG_FAILURE);
8416 return(TNG_FAILURE);
8419 strncpy(name, atom->residue->name, max_len - 1);
8420 name[max_len - 1] = 0;
8422 if(strlen(atom->residue->name) > (unsigned int)max_len - 1)
8424 return(TNG_FAILURE);
8426 return(TNG_SUCCESS);
8429 tng_function_status DECLSPECDLLEXPORT tng_residue_id_of_particle_nr_get
8430 (const tng_trajectory_t tng_data,
8434 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8437 tng_bool found = TNG_FALSE;
8439 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8440 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
8442 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8444 if(!molecule_cnt_list)
8446 return(TNG_FAILURE);
8449 for(i = 0; i < tng_data->n_molecules; i++)
8451 mol = &tng_data->molecules[i];
8452 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8454 cnt += mol->n_atoms * molecule_cnt_list[i];
8457 atom = &mol->atoms[nr % mol->n_atoms];
8463 return(TNG_FAILURE);
8467 return(TNG_FAILURE);
8470 *id = atom->residue->id;
8472 return(TNG_SUCCESS);
8475 tng_function_status DECLSPECDLLEXPORT tng_global_residue_id_of_particle_nr_get
8476 (const tng_trajectory_t tng_data,
8480 int64_t cnt = 0, i, offset = 0, *molecule_cnt_list = 0;
8483 tng_bool found = TNG_FALSE;
8485 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8486 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
8488 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8490 if(!molecule_cnt_list)
8492 return(TNG_FAILURE);
8495 for(i = 0; i < tng_data->n_molecules; i++)
8497 mol = &tng_data->molecules[i];
8498 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8500 cnt += mol->n_atoms * molecule_cnt_list[i];
8501 offset += mol->n_residues * molecule_cnt_list[i];
8504 atom = &mol->atoms[nr % mol->n_atoms];
8510 return(TNG_FAILURE);
8514 return(TNG_FAILURE);
8517 offset += mol->n_residues * ((nr - cnt) / mol->n_atoms);
8519 *id = atom->residue->id + offset;
8521 return(TNG_SUCCESS);
8524 tng_function_status DECLSPECDLLEXPORT tng_atom_name_of_particle_nr_get
8525 (const tng_trajectory_t tng_data,
8530 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8533 tng_bool found = TNG_FALSE;
8535 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8536 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8538 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8540 if(!molecule_cnt_list)
8542 return(TNG_FAILURE);
8545 for(i = 0; i < tng_data->n_molecules; i++)
8547 mol = &tng_data->molecules[i];
8548 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8550 cnt += mol->n_atoms * molecule_cnt_list[i];
8553 atom = &mol->atoms[nr % mol->n_atoms];
8559 return(TNG_FAILURE);
8562 strncpy(name, atom->name, max_len - 1);
8563 name[max_len - 1] = 0;
8565 if(strlen(atom->name) > (unsigned int)max_len - 1)
8567 return(TNG_FAILURE);
8569 return(TNG_SUCCESS);
8572 tng_function_status tng_atom_type_of_particle_nr_get
8573 (const tng_trajectory_t tng_data,
8578 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8581 tng_bool found = TNG_FALSE;
8583 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8584 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
8586 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8588 if(!molecule_cnt_list)
8590 return(TNG_FAILURE);
8593 for(i = 0; i < tng_data->n_molecules; i++)
8595 mol = &tng_data->molecules[i];
8596 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8598 cnt += mol->n_atoms * molecule_cnt_list[i];
8601 atom = &mol->atoms[nr % mol->n_atoms];
8607 return(TNG_FAILURE);
8610 strncpy(type, atom->atom_type, max_len - 1);
8611 type[max_len - 1] = 0;
8613 if(strlen(atom->atom_type) > (unsigned int)max_len - 1)
8615 return(TNG_FAILURE);
8617 return(TNG_SUCCESS);
8620 tng_function_status DECLSPECDLLEXPORT tng_particle_mapping_add
8621 (const tng_trajectory_t tng_data,
8622 const int64_t num_first_particle,
8623 const int64_t n_particles,
8624 const int64_t *mapping_table)
8627 tng_particle_mapping_t mapping;
8628 tng_trajectory_frame_set_t frame_set;
8630 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8632 frame_set = &tng_data->current_trajectory_frame_set;
8634 /* Sanity check of the particle ranges. Split into multiple if
8635 * statements for improved readability */
8636 for(i = 0; i < frame_set->n_mapping_blocks; i++)
8638 mapping = &frame_set->mappings[i];
8639 if(num_first_particle >= mapping->num_first_particle &&
8640 num_first_particle < mapping->num_first_particle +
8641 mapping->n_particles)
8643 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
8644 return(TNG_FAILURE);
8646 if(num_first_particle + n_particles >=
8647 mapping->num_first_particle &&
8648 num_first_particle + n_particles <
8649 mapping->num_first_particle + mapping->n_particles)
8651 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
8652 return(TNG_FAILURE);
8654 if(mapping->num_first_particle >= num_first_particle &&
8655 mapping->num_first_particle < num_first_particle +
8658 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
8659 return(TNG_FAILURE);
8661 if(mapping->num_first_particle + mapping->n_particles >
8662 num_first_particle &&
8663 mapping->num_first_particle + mapping->n_particles <
8664 num_first_particle + n_particles)
8666 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
8667 return(TNG_FAILURE);
8671 frame_set->n_mapping_blocks++;
8673 mapping = realloc(frame_set->mappings, sizeof(struct tng_particle_mapping) *
8674 frame_set->n_mapping_blocks);
8678 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
8679 sizeof(struct tng_particle_mapping)*frame_set->n_mapping_blocks,
8680 __FILE__, __LINE__);
8681 free(frame_set->mappings);
8682 frame_set->mappings = 0;
8683 return(TNG_CRITICAL);
8685 frame_set->mappings = mapping;
8687 frame_set->mappings[frame_set->n_mapping_blocks - 1].num_first_particle = num_first_particle;
8688 frame_set->mappings[frame_set->n_mapping_blocks - 1].n_particles = n_particles;
8690 frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers = malloc(sizeof(int64_t) * n_particles);
8691 if(!frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers)
8693 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
8694 sizeof(int64_t) * n_particles, __FILE__, __LINE__);
8695 return(TNG_CRITICAL);
8698 for(i=0; i<n_particles; i++)
8700 frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers[i] = mapping_table[i];
8703 return(TNG_SUCCESS);
8706 tng_function_status DECLSPECDLLEXPORT tng_frame_set_particle_mapping_free(const tng_trajectory_t tng_data)
8708 tng_trajectory_frame_set_t frame_set;
8709 tng_particle_mapping_t mapping;
8712 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8714 frame_set = &tng_data->current_trajectory_frame_set;
8716 if(frame_set->n_mapping_blocks && frame_set->mappings)
8718 for(i = 0; i < frame_set->n_mapping_blocks; i++)
8720 mapping = &frame_set->mappings[i];
8721 if(mapping->real_particle_numbers)
8723 free(mapping->real_particle_numbers);
8724 mapping->real_particle_numbers = 0;
8727 free(frame_set->mappings);
8728 frame_set->mappings = 0;
8729 frame_set->n_mapping_blocks = 0;
8732 return(TNG_SUCCESS);
8735 tng_function_status DECLSPECDLLEXPORT tng_trajectory_init(tng_trajectory_t *tng_data_p)
8738 tng_trajectory_frame_set_t frame_set;
8739 tng_trajectory_t tng_data;
8741 *tng_data_p = malloc(sizeof(struct tng_trajectory));
8744 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIuPTR" bytes). %s: %d\n",
8745 sizeof(struct tng_trajectory), __FILE__, __LINE__);
8746 return(TNG_CRITICAL);
8749 tng_data = *tng_data_p;
8751 frame_set = &tng_data->current_trajectory_frame_set;
8753 tng_data->input_file_path = 0;
8754 tng_data->input_file = 0;
8755 tng_data->input_file_len = 0;
8756 tng_data->output_file_path = 0;
8757 tng_data->output_file = 0;
8759 tng_data->first_program_name = 0;
8760 tng_data->first_user_name = 0;
8761 tng_data->first_computer_name = 0;
8762 tng_data->first_pgp_signature = 0;
8763 tng_data->last_program_name = 0;
8764 tng_data->last_user_name = 0;
8765 tng_data->last_computer_name = 0;
8766 tng_data->last_pgp_signature = 0;
8767 tng_data->forcefield_name = 0;
8772 fprintf(stderr, "TNG library: Cannot get time. %s: %d\n", __FILE__, __LINE__);
8776 tng_data->time = seconds;
8779 tng_data->var_num_atoms_flag = TNG_CONSTANT_N_ATOMS;
8780 tng_data->first_trajectory_frame_set_input_file_pos = -1;
8781 tng_data->last_trajectory_frame_set_input_file_pos = -1;
8782 tng_data->current_trajectory_frame_set_input_file_pos = -1;
8783 tng_data->first_trajectory_frame_set_output_file_pos = -1;
8784 tng_data->last_trajectory_frame_set_output_file_pos = -1;
8785 tng_data->current_trajectory_frame_set_output_file_pos = -1;
8786 tng_data->frame_set_n_frames = 100;
8787 tng_data->n_trajectory_frame_sets = 0;
8788 tng_data->medium_stride_length = 100;
8789 tng_data->long_stride_length = 10000;
8791 tng_data->time_per_frame = -1;
8793 tng_data->n_particle_data_blocks = 0;
8794 tng_data->n_data_blocks = 0;
8796 tng_data->non_tr_particle_data = 0;
8797 tng_data->non_tr_data = 0;
8799 tng_data->compress_algo_pos = 0;
8800 tng_data->compress_algo_vel = 0;
8801 tng_data->compression_precision = 1000;
8802 tng_data->distance_unit_exponential = -9;
8804 frame_set->first_frame = -1;
8805 frame_set->n_mapping_blocks = 0;
8806 frame_set->mappings = 0;
8807 frame_set->molecule_cnt_list = 0;
8809 frame_set->n_particle_data_blocks = 0;
8810 frame_set->n_data_blocks = 0;
8812 frame_set->tr_particle_data = 0;
8813 frame_set->tr_data = 0;
8815 frame_set->n_written_frames = 0;
8816 frame_set->n_unwritten_frames = 0;
8818 frame_set->next_frame_set_file_pos = -1;
8819 frame_set->prev_frame_set_file_pos = -1;
8820 frame_set->medium_stride_next_frame_set_file_pos = -1;
8821 frame_set->medium_stride_prev_frame_set_file_pos = -1;
8822 frame_set->long_stride_next_frame_set_file_pos = -1;
8823 frame_set->long_stride_prev_frame_set_file_pos = -1;
8825 frame_set->first_frame_time = -1;
8827 tng_data->n_molecules = 0;
8828 tng_data->molecules = 0;
8829 tng_data->molecule_cnt_list = 0;
8830 tng_data->n_particles = 0;
8833 /* Check the endianness of the computer */
8834 static int32_t endianness_32 = 0x01234567;
8836 if ( *(const unsigned char*)&endianness_32 == 0x01 )
8838 tng_data->endianness_32 = TNG_BIG_ENDIAN_32;
8842 else if( *(const unsigned char*)&endianness_32 == 0x67 )
8844 tng_data->endianness_32 = TNG_LITTLE_ENDIAN_32;
8849 else if ( *(const unsigned char*)&endianness_32 == 0x45 )
8851 tng_data->endianness_32 = TNG_BYTE_PAIR_SWAP_32;
8855 static int64_t endianness_64 = 0x0123456789ABCDEFLL;
8856 /* 0x0123456789ABCDEF */
8857 if ( *(const unsigned char*)&endianness_64 == 0x01 )
8859 tng_data->endianness_64 = TNG_BIG_ENDIAN_64;
8862 /* 0xEFCDAB8967452301 */
8863 else if ( *(const unsigned char*)&endianness_64 == 0xEF )
8865 tng_data->endianness_64 = TNG_LITTLE_ENDIAN_64;
8868 /* 0x89ABCDEF01234567 */
8869 else if ( *(const unsigned char*)&endianness_64 == 0x89 )
8871 tng_data->endianness_64 = TNG_QUAD_SWAP_64;
8874 /* 0x45670123CDEF89AB */
8875 else if ( *(const unsigned char*)&endianness_64 == 0x45 )
8877 tng_data->endianness_64 = TNG_BYTE_PAIR_SWAP_64;
8880 /* 0x23016745AB89EFCD */
8881 else if ( *(const unsigned char*)&endianness_64 == 0x23 )
8883 tng_data->endianness_64 = TNG_BYTE_SWAP_64;
8887 /* By default do not swap the byte order, i.e. keep the byte order of the
8888 * architecture. The input file endianness will be set when reading the
8889 * header. The output endianness can be changed - before the file is
8891 tng_data->input_endianness_swap_func_32 = 0;
8892 tng_data->input_endianness_swap_func_64 = 0;
8893 tng_data->output_endianness_swap_func_32 = 0;
8894 tng_data->output_endianness_swap_func_64 = 0;
8896 tng_data->current_trajectory_frame_set.next_frame_set_file_pos = -1;
8897 tng_data->current_trajectory_frame_set.prev_frame_set_file_pos = -1;
8898 tng_data->current_trajectory_frame_set.n_frames = 0;
8900 return(TNG_SUCCESS);
8903 tng_function_status DECLSPECDLLEXPORT tng_trajectory_destroy(tng_trajectory_t *tng_data_p)
8906 int64_t n_particles, n_values_per_frame;
8907 tng_trajectory_t tng_data = *tng_data_p;
8908 tng_trajectory_frame_set_t frame_set;
8912 return(TNG_SUCCESS);
8915 frame_set = &tng_data->current_trajectory_frame_set;
8917 if(tng_data->input_file)
8919 if(tng_data->output_file == tng_data->input_file)
8921 tng_frame_set_finalize(tng_data, TNG_USE_HASH);
8922 tng_data->output_file = 0;
8924 fclose(tng_data->input_file);
8925 tng_data->input_file = 0;
8928 if(tng_data->input_file_path)
8930 free(tng_data->input_file_path);
8931 tng_data->input_file_path = 0;
8934 if(tng_data->output_file)
8936 /* FIXME: Do not always write the hash */
8937 tng_frame_set_finalize(tng_data, TNG_USE_HASH);
8938 fclose(tng_data->output_file);
8939 tng_data->output_file = 0;
8942 if(tng_data->output_file_path)
8944 free(tng_data->output_file_path);
8945 tng_data->output_file_path = 0;
8948 if(tng_data->first_program_name)
8950 free(tng_data->first_program_name);
8951 tng_data->first_program_name = 0;
8954 if(tng_data->last_program_name)
8956 free(tng_data->last_program_name);
8957 tng_data->last_program_name = 0;
8960 if(tng_data->first_user_name)
8962 free(tng_data->first_user_name);
8963 tng_data->first_user_name = 0;
8966 if(tng_data->last_user_name)
8968 free(tng_data->last_user_name);
8969 tng_data->last_user_name = 0;
8972 if(tng_data->first_computer_name)
8974 free(tng_data->first_computer_name);
8975 tng_data->first_computer_name = 0;
8978 if(tng_data->last_computer_name)
8980 free(tng_data->last_computer_name);
8981 tng_data->last_computer_name = 0;
8984 if(tng_data->first_pgp_signature)
8986 free(tng_data->first_pgp_signature);
8987 tng_data->first_pgp_signature = 0;
8990 if(tng_data->last_pgp_signature)
8992 free(tng_data->last_pgp_signature);
8993 tng_data->last_pgp_signature = 0;
8996 if(tng_data->forcefield_name)
8998 free(tng_data->forcefield_name);
8999 tng_data->forcefield_name = 0;
9002 tng_frame_set_particle_mapping_free(tng_data);
9004 if(frame_set->molecule_cnt_list)
9006 free(frame_set->molecule_cnt_list);
9007 frame_set->molecule_cnt_list = 0;
9010 if(tng_data->var_num_atoms_flag)
9012 n_particles = frame_set->n_particles;
9016 n_particles = tng_data->n_particles;
9019 if(tng_data->non_tr_particle_data)
9021 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
9023 if(tng_data->non_tr_particle_data[i].values)
9025 free(tng_data->non_tr_particle_data[i].values);
9026 tng_data->non_tr_particle_data[i].values = 0;
9029 if(tng_data->non_tr_particle_data[i].strings)
9031 n_values_per_frame = tng_data->non_tr_particle_data[i].
9033 if(tng_data->non_tr_particle_data[i].strings[0])
9035 for(j = 0; j < n_particles; j++)
9037 if(tng_data->non_tr_particle_data[i].strings[0][j])
9039 for(k = 0; k < n_values_per_frame; k++)
9041 if(tng_data->non_tr_particle_data[i].
9044 free(tng_data->non_tr_particle_data[i].
9046 tng_data->non_tr_particle_data[i].
9047 strings[0][j][k] = 0;
9050 free(tng_data->non_tr_particle_data[i].
9052 tng_data->non_tr_particle_data[i].strings[0][j] = 0;
9055 free(tng_data->non_tr_particle_data[i].strings[0]);
9056 tng_data->non_tr_particle_data[i].strings[0] = 0;
9058 free(tng_data->non_tr_particle_data[i].strings);
9059 tng_data->non_tr_particle_data[i].strings = 0;
9062 if(tng_data->non_tr_particle_data[i].block_name)
9064 free(tng_data->non_tr_particle_data[i].block_name);
9065 tng_data->non_tr_particle_data[i].block_name = 0;
9068 free(tng_data->non_tr_particle_data);
9069 tng_data->non_tr_particle_data = 0;
9072 if(tng_data->non_tr_data)
9074 for(i = 0; i < tng_data->n_data_blocks; i++)
9076 if(tng_data->non_tr_data[i].values)
9078 free(tng_data->non_tr_data[i].values);
9079 tng_data->non_tr_data[i].values = 0;
9082 if(tng_data->non_tr_data[i].strings)
9084 n_values_per_frame = tng_data->non_tr_data[i].
9086 if(tng_data->non_tr_data[i].strings[0][0])
9088 for(j = 0; j < n_values_per_frame; j++)
9090 if(tng_data->non_tr_data[i].strings[0][0][j])
9092 free(tng_data->non_tr_data[i].strings[0][0][j]);
9093 tng_data->non_tr_data[i].strings[0][0][j] = 0;
9096 free(tng_data->non_tr_data[i].strings[0][0]);
9097 tng_data->non_tr_data[i].strings[0][0] = 0;
9099 free(tng_data->non_tr_data[i].strings[0]);
9100 tng_data->non_tr_data[i].strings[0] = 0;
9101 free(tng_data->non_tr_data[i].strings);
9102 tng_data->non_tr_data[i].strings = 0;
9105 if(tng_data->non_tr_data[i].block_name)
9107 free(tng_data->non_tr_data[i].block_name);
9108 tng_data->non_tr_data[i].block_name = 0;
9111 free(tng_data->non_tr_data);
9112 tng_data->non_tr_data = 0;
9115 tng_data->n_particle_data_blocks = 0;
9116 tng_data->n_data_blocks = 0;
9118 if(tng_data->compress_algo_pos)
9120 free(tng_data->compress_algo_pos);
9121 tng_data->compress_algo_pos = 0;
9123 if(tng_data->compress_algo_vel)
9125 free(tng_data->compress_algo_vel);
9126 tng_data->compress_algo_vel = 0;
9129 if(frame_set->tr_particle_data)
9131 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
9133 if(frame_set->tr_particle_data[i].values)
9135 free(frame_set->tr_particle_data[i].values);
9136 frame_set->tr_particle_data[i].values = 0;
9139 if(frame_set->tr_particle_data[i].strings)
9141 n_values_per_frame = frame_set->tr_particle_data[i].
9143 for(j = 0; j < frame_set->tr_particle_data[i].n_frames; j++)
9145 if(frame_set->tr_particle_data[i].strings[j])
9147 for(k = 0; k < n_particles; k++)
9149 if(frame_set->tr_particle_data[i].
9152 for(l = 0; l < n_values_per_frame; l++)
9154 if(frame_set->tr_particle_data[i].
9157 free(frame_set->tr_particle_data[i].
9159 frame_set->tr_particle_data[i].
9160 strings[j][k][l] = 0;
9163 free(frame_set->tr_particle_data[i].
9165 frame_set->tr_particle_data[i].
9169 free(frame_set->tr_particle_data[i].strings[j]);
9170 frame_set->tr_particle_data[i].strings[j] = 0;
9173 free(frame_set->tr_particle_data[i].strings);
9174 frame_set->tr_particle_data[i].strings = 0;
9177 if(frame_set->tr_particle_data[i].block_name)
9179 free(frame_set->tr_particle_data[i].block_name);
9180 frame_set->tr_particle_data[i].block_name = 0;
9183 free(frame_set->tr_particle_data);
9184 frame_set->tr_particle_data = 0;
9187 if(frame_set->tr_data)
9189 for(i = 0; i < frame_set->n_data_blocks; i++)
9191 if(frame_set->tr_data[i].values)
9193 free(frame_set->tr_data[i].values);
9194 frame_set->tr_data[i].values = 0;
9197 if(frame_set->tr_data[i].strings)
9199 n_values_per_frame = frame_set->tr_data[i].
9201 for(j = 0; j < frame_set->tr_data[i].n_frames; j++)
9203 if(frame_set->tr_data[i].strings[j])
9205 for(k = 0; k < n_values_per_frame; k++)
9207 if(frame_set->tr_data[i].strings[j][k])
9209 free(frame_set->tr_data[i].strings[j][k]);
9210 frame_set->tr_data[i].strings[j][k] = 0;
9213 free(frame_set->tr_data[i].strings[j]);
9214 frame_set->tr_data[i].strings[j] = 0;
9217 free(frame_set->tr_data[i].strings);
9218 frame_set->tr_data[i].strings = 0;
9221 if(frame_set->tr_data[i].block_name)
9223 free(frame_set->tr_data[i].block_name);
9224 frame_set->tr_data[i].block_name = 0;
9227 free(frame_set->tr_data);
9228 frame_set->tr_data = 0;
9231 frame_set->n_particle_data_blocks = 0;
9232 frame_set->n_data_blocks = 0;
9234 if(tng_data->molecules)
9236 for(i = 0; i < tng_data->n_molecules; i++)
9238 tng_molecule_destroy(tng_data, &tng_data->molecules[i]);
9240 free(tng_data->molecules);
9241 tng_data->molecules = 0;
9242 tng_data->n_molecules = 0;
9244 if(tng_data->molecule_cnt_list)
9246 free(tng_data->molecule_cnt_list);
9247 tng_data->molecule_cnt_list = 0;
9253 return(TNG_SUCCESS);
9256 tng_function_status DECLSPECDLLEXPORT tng_trajectory_init_from_src
9257 (const tng_trajectory_t src,
9258 tng_trajectory_t *dest_p)
9260 tng_trajectory_frame_set_t frame_set;
9261 tng_trajectory_t dest;
9263 TNG_ASSERT(src != 0, "TNG library: Source trajectory must not be NULL.");
9265 *dest_p = malloc(sizeof(struct tng_trajectory));
9268 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIuPTR" bytes). %s: %d\n",
9269 sizeof(struct tng_trajectory), __FILE__, __LINE__);
9270 return(TNG_CRITICAL);
9275 frame_set = &dest->current_trajectory_frame_set;
9277 if(src->input_file_path)
9279 dest->input_file_path = malloc(strlen(src->input_file_path) + 1);
9280 if(!dest->input_file_path)
9282 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n",
9283 (unsigned int)strlen(src->input_file_path) + 1, __FILE__, __LINE__);
9284 return(TNG_CRITICAL);
9286 strcpy(dest->input_file_path, src->input_file_path);
9287 dest->input_file_len = src->input_file_len;
9291 dest->input_file_path = 0;
9293 dest->input_file = 0;
9294 if(src->output_file_path)
9296 dest->output_file_path = malloc(strlen(src->output_file_path) + 1);
9297 if(!dest->output_file_path)
9299 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n",
9300 (unsigned int)strlen(src->output_file_path) + 1, __FILE__, __LINE__);
9301 return(TNG_CRITICAL);
9303 strcpy(dest->output_file_path, src->output_file_path);
9307 dest->output_file_path = 0;
9309 dest->output_file = 0;
9311 dest->first_program_name = 0;
9312 dest->first_user_name = 0;
9313 dest->first_computer_name = 0;
9314 dest->first_pgp_signature = 0;
9315 dest->last_program_name = 0;
9316 dest->last_user_name = 0;
9317 dest->last_computer_name = 0;
9318 dest->last_pgp_signature = 0;
9319 dest->forcefield_name = 0;
9321 dest->var_num_atoms_flag = src->var_num_atoms_flag;
9322 dest->first_trajectory_frame_set_input_file_pos =
9323 src->first_trajectory_frame_set_input_file_pos;
9324 dest->last_trajectory_frame_set_input_file_pos =
9325 src->last_trajectory_frame_set_input_file_pos;
9326 dest->current_trajectory_frame_set_input_file_pos =
9327 src->current_trajectory_frame_set_input_file_pos;
9328 dest->first_trajectory_frame_set_output_file_pos =
9329 src->first_trajectory_frame_set_output_file_pos;
9330 dest->last_trajectory_frame_set_output_file_pos =
9331 src->last_trajectory_frame_set_output_file_pos;
9332 dest->current_trajectory_frame_set_output_file_pos =
9333 src->current_trajectory_frame_set_output_file_pos;
9334 dest->frame_set_n_frames = src->frame_set_n_frames;
9335 dest->n_trajectory_frame_sets = src->n_trajectory_frame_sets;
9336 dest->medium_stride_length = src->medium_stride_length;
9337 dest->long_stride_length = src->long_stride_length;
9339 dest->time_per_frame = src->time_per_frame;
9341 /* Currently the non trajectory data blocks are not copied since it
9342 * can lead to problems when freeing memory in a parallel block. */
9343 dest->n_particle_data_blocks = 0;
9344 dest->n_data_blocks = 0;
9345 dest->non_tr_particle_data = 0;
9346 dest->non_tr_data = 0;
9348 dest->compress_algo_pos = 0;
9349 dest->compress_algo_vel = 0;
9350 dest->distance_unit_exponential = -9;
9351 dest->compression_precision = 1000;
9353 frame_set->n_mapping_blocks = 0;
9354 frame_set->mappings = 0;
9355 frame_set->molecule_cnt_list = 0;
9357 frame_set->n_particle_data_blocks = 0;
9358 frame_set->n_data_blocks = 0;
9360 frame_set->tr_particle_data = 0;
9361 frame_set->tr_data = 0;
9363 frame_set->n_written_frames = 0;
9364 frame_set->n_unwritten_frames = 0;
9366 frame_set->next_frame_set_file_pos = -1;
9367 frame_set->prev_frame_set_file_pos = -1;
9368 frame_set->medium_stride_next_frame_set_file_pos = -1;
9369 frame_set->medium_stride_prev_frame_set_file_pos = -1;
9370 frame_set->long_stride_next_frame_set_file_pos = -1;
9371 frame_set->long_stride_prev_frame_set_file_pos = -1;
9372 frame_set->first_frame = -1;
9374 dest->n_molecules = 0;
9375 dest->molecules = 0;
9376 dest->molecule_cnt_list = 0;
9377 dest->n_particles = src->n_particles;
9379 dest->endianness_32 = src->endianness_32;
9380 dest->endianness_64 = src->endianness_64;
9381 dest->input_endianness_swap_func_32 = src->input_endianness_swap_func_32;
9382 dest->input_endianness_swap_func_64 = src->input_endianness_swap_func_64;
9383 dest->output_endianness_swap_func_32 = src->output_endianness_swap_func_32;
9384 dest->output_endianness_swap_func_64 = src->output_endianness_swap_func_64;
9386 dest->current_trajectory_frame_set.next_frame_set_file_pos = -1;
9387 dest->current_trajectory_frame_set.prev_frame_set_file_pos = -1;
9388 dest->current_trajectory_frame_set.n_frames = 0;
9390 return(TNG_SUCCESS);
9393 tng_function_status DECLSPECDLLEXPORT tng_input_file_get
9394 (const tng_trajectory_t tng_data,
9398 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9399 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
9401 strncpy(file_name, tng_data->input_file_path, max_len - 1);
9402 file_name[max_len - 1] = 0;
9404 if(strlen(tng_data->input_file_path) > (unsigned int)max_len - 1)
9406 return(TNG_FAILURE);
9408 return(TNG_SUCCESS);
9411 tng_function_status DECLSPECDLLEXPORT tng_input_file_set
9412 (const tng_trajectory_t tng_data,
9413 const char *file_name)
9418 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9419 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
9422 if(tng_data->input_file_path && strcmp(tng_data->input_file_path,
9425 return(TNG_SUCCESS);
9428 if(tng_data->input_file)
9430 fclose(tng_data->input_file);
9433 len = tng_min_size(strlen(file_name) + 1, TNG_MAX_STR_LEN);
9434 temp = realloc(tng_data->input_file_path, len);
9437 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
9438 __FILE__, __LINE__);
9439 free(tng_data->input_file_path);
9440 tng_data->input_file_path = 0;
9441 return(TNG_CRITICAL);
9443 tng_data->input_file_path = temp;
9445 strncpy(tng_data->input_file_path, file_name, len);
9447 return(tng_input_file_init(tng_data));
9450 tng_function_status tng_output_file_get
9451 (const tng_trajectory_t tng_data,
9455 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9456 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
9458 strncpy(file_name, tng_data->output_file_path, max_len - 1);
9459 file_name[max_len - 1] = 0;
9461 if(strlen(tng_data->output_file_path) > (unsigned int)max_len - 1)
9463 return(TNG_FAILURE);
9465 return(TNG_SUCCESS);
9468 tng_function_status DECLSPECDLLEXPORT tng_output_file_set
9469 (const tng_trajectory_t tng_data,
9470 const char *file_name)
9475 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9476 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
9478 if(tng_data->output_file_path &&
9479 strcmp(tng_data->output_file_path, file_name) == 0)
9481 return(TNG_SUCCESS);
9484 if(tng_data->output_file)
9486 fclose(tng_data->output_file);
9489 len = tng_min_size(strlen(file_name) + 1, TNG_MAX_STR_LEN);
9490 temp = realloc(tng_data->output_file_path, len);
9493 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
9494 __FILE__, __LINE__);
9495 free(tng_data->output_file_path);
9496 tng_data->output_file_path = 0;
9497 return(TNG_CRITICAL);
9499 tng_data->output_file_path = temp;
9501 strncpy(tng_data->output_file_path, file_name, len);
9503 return(tng_output_file_init(tng_data));
9506 tng_function_status DECLSPECDLLEXPORT tng_output_append_file_set
9507 (const tng_trajectory_t tng_data,
9508 const char *file_name)
9513 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9514 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
9516 if(tng_data->output_file_path &&
9517 strcmp(tng_data->output_file_path, file_name) == 0)
9519 return(TNG_SUCCESS);
9522 if(tng_data->output_file)
9524 fclose(tng_data->output_file);
9527 len = tng_min_size(strlen(file_name) + 1, TNG_MAX_STR_LEN);
9528 temp = realloc(tng_data->output_file_path, len);
9531 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
9532 __FILE__, __LINE__);
9533 free(tng_data->output_file_path);
9534 tng_data->output_file_path = 0;
9535 return(TNG_CRITICAL);
9537 tng_data->output_file_path = temp;
9539 strncpy(tng_data->output_file_path, file_name, len);
9541 tng_data->output_file = fopen(tng_data->output_file_path, "rb+");
9542 if(!tng_data->output_file)
9544 fprintf(stderr, "TNG library: Cannot open file %s. %s: %d\n",
9545 tng_data->output_file_path, __FILE__, __LINE__);
9546 return(TNG_CRITICAL);
9548 tng_data->input_file = tng_data->output_file;
9550 return(TNG_SUCCESS);
9553 tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_get
9554 (const tng_trajectory_t tng_data, tng_file_endianness *endianness)
9556 tng_endianness_32 end_32;
9557 tng_endianness_64 end_64;
9559 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9560 TNG_ASSERT(endianness, "TNG library: endianness must not be a NULL pointer");
9562 if(tng_data->output_endianness_swap_func_32)
9564 /* If other endianness variants are added they must be added here as well */
9565 if(tng_data->output_endianness_swap_func_32 ==
9566 &tng_swap_byte_order_big_endian_32)
9568 end_32 = TNG_BIG_ENDIAN_32;
9570 else if(tng_data->output_endianness_swap_func_32 ==
9571 &tng_swap_byte_order_little_endian_32)
9573 end_32 = TNG_LITTLE_ENDIAN_32;
9577 return(TNG_FAILURE);
9582 end_32 = (tng_endianness_32)tng_data->endianness_32;
9585 if(tng_data->output_endianness_swap_func_64)
9587 /* If other endianness variants are added they must be added here as well */
9588 if(tng_data->output_endianness_swap_func_64 ==
9589 &tng_swap_byte_order_big_endian_64)
9591 end_64 = TNG_BIG_ENDIAN_64;
9593 else if(tng_data->output_endianness_swap_func_64 ==
9594 &tng_swap_byte_order_little_endian_64)
9596 end_64 = TNG_LITTLE_ENDIAN_64;
9600 return(TNG_FAILURE);
9605 end_64 = (tng_endianness_64)tng_data->endianness_64;
9608 if((int)end_32 != (int)end_64)
9610 return(TNG_FAILURE);
9613 if(end_32 == TNG_LITTLE_ENDIAN_32)
9615 *endianness = TNG_LITTLE_ENDIAN;
9618 else if(end_32 == TNG_BIG_ENDIAN_32)
9620 *endianness = TNG_BIG_ENDIAN;
9624 return(TNG_FAILURE);
9627 return(TNG_SUCCESS);
9630 tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_set
9631 (const tng_trajectory_t tng_data,
9632 const tng_file_endianness endianness)
9634 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9636 /* Tne endianness cannot be changed if the data has already been written
9637 * to the output file. */
9638 if(ftello(tng_data->output_file) > 0)
9640 return(TNG_FAILURE);
9643 if(endianness == TNG_BIG_ENDIAN)
9645 if(tng_data->endianness_32 == TNG_BIG_ENDIAN_32)
9647 tng_data->output_endianness_swap_func_32 = 0;
9651 tng_data->output_endianness_swap_func_32 =
9652 &tng_swap_byte_order_big_endian_32;
9654 if(tng_data->endianness_64 == TNG_BIG_ENDIAN_64)
9656 tng_data->output_endianness_swap_func_64 = 0;
9660 tng_data->output_endianness_swap_func_64 =
9661 &tng_swap_byte_order_big_endian_64;
9663 return(TNG_SUCCESS);
9665 else if(endianness == TNG_LITTLE_ENDIAN)
9667 if(tng_data->endianness_32 == TNG_LITTLE_ENDIAN_32)
9669 tng_data->output_endianness_swap_func_32 = 0;
9673 tng_data->output_endianness_swap_func_32 =
9674 &tng_swap_byte_order_little_endian_32;
9676 if(tng_data->endianness_64 == TNG_LITTLE_ENDIAN_64)
9678 tng_data->output_endianness_swap_func_64 = 0;
9682 tng_data->output_endianness_swap_func_64 =
9683 &tng_swap_byte_order_little_endian_64;
9685 return(TNG_SUCCESS);
9688 /* If the specified endianness is neither big nor little endian return a
9690 return(TNG_FAILURE);
9693 tng_function_status DECLSPECDLLEXPORT tng_first_program_name_get
9694 (const tng_trajectory_t tng_data,
9698 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9699 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
9701 strncpy(name, tng_data->first_program_name, max_len - 1);
9702 name[max_len - 1] = 0;
9704 if(strlen(tng_data->first_program_name) > (unsigned int)max_len - 1)
9706 return(TNG_FAILURE);
9708 return(TNG_SUCCESS);
9711 tng_function_status DECLSPECDLLEXPORT tng_first_program_name_set
9712 (const tng_trajectory_t tng_data,
9713 const char *new_name)
9717 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9718 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
9720 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
9722 if(tng_data->first_program_name && strlen(tng_data->first_program_name) < len)
9724 free(tng_data->first_program_name);
9725 tng_data->first_program_name = 0;
9727 if(!tng_data->first_program_name)
9729 tng_data->first_program_name = malloc(len);
9730 if(!tng_data->first_program_name)
9732 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
9733 __FILE__, __LINE__);
9734 return(TNG_CRITICAL);
9738 strncpy(tng_data->first_program_name, new_name, len);
9740 return(TNG_SUCCESS);
9743 tng_function_status DECLSPECDLLEXPORT tng_last_program_name_get
9744 (const tng_trajectory_t tng_data,
9745 char *name, const int max_len)
9747 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9748 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
9750 strncpy(name, tng_data->last_program_name, max_len - 1);
9751 name[max_len - 1] = 0;
9753 if(strlen(tng_data->last_program_name) > (unsigned int)max_len - 1)
9755 return(TNG_FAILURE);
9757 return(TNG_SUCCESS);
9760 tng_function_status DECLSPECDLLEXPORT tng_last_program_name_set
9761 (const tng_trajectory_t tng_data,
9762 const char *new_name)
9766 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9767 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
9769 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
9771 if(tng_data->last_program_name && strlen(tng_data->last_program_name) < len)
9773 free(tng_data->last_program_name);
9774 tng_data->last_program_name = 0;
9776 if(!tng_data->last_program_name)
9778 tng_data->last_program_name = malloc(len);
9779 if(!tng_data->last_program_name)
9781 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
9782 __FILE__, __LINE__);
9783 return(TNG_CRITICAL);
9787 strncpy(tng_data->last_program_name, new_name, len);
9789 return(TNG_SUCCESS);
9792 tng_function_status DECLSPECDLLEXPORT tng_first_user_name_get
9793 (const tng_trajectory_t tng_data,
9794 char *name, const int max_len)
9796 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9797 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
9799 strncpy(name, tng_data->first_user_name, max_len - 1);
9800 name[max_len - 1] = 0;
9802 if(strlen(tng_data->first_user_name) > (unsigned int)max_len - 1)
9804 return(TNG_FAILURE);
9806 return(TNG_SUCCESS);
9809 tng_function_status DECLSPECDLLEXPORT tng_first_user_name_set
9810 (const tng_trajectory_t tng_data,
9811 const char *new_name)
9815 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9816 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
9818 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
9820 /* If the currently stored string length is not enough to store the new
9821 * string it is freed and reallocated. */
9822 if(tng_data->first_user_name && strlen(tng_data->first_user_name) < len)
9824 free(tng_data->first_user_name);
9825 tng_data->first_user_name = 0;
9827 if(!tng_data->first_user_name)
9829 tng_data->first_user_name = malloc(len);
9830 if(!tng_data->first_user_name)
9832 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
9833 __FILE__, __LINE__);
9834 return(TNG_CRITICAL);
9838 strncpy(tng_data->first_user_name, new_name, len);
9840 return(TNG_SUCCESS);
9843 tng_function_status DECLSPECDLLEXPORT tng_last_user_name_get
9844 (const tng_trajectory_t tng_data,
9845 char *name, const int max_len)
9847 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9848 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
9850 strncpy(name, tng_data->last_user_name, max_len - 1);
9851 name[max_len - 1] = 0;
9853 if(strlen(tng_data->last_user_name) > (unsigned int)max_len - 1)
9855 return(TNG_FAILURE);
9857 return(TNG_SUCCESS);
9860 tng_function_status DECLSPECDLLEXPORT tng_last_user_name_set
9861 (const tng_trajectory_t tng_data,
9862 const char *new_name)
9866 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9867 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
9869 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
9871 /* If the currently stored string length is not enough to store the new
9872 * string it is freed and reallocated. */
9873 if(tng_data->last_user_name && strlen(tng_data->last_user_name) < len)
9875 free(tng_data->last_user_name);
9876 tng_data->last_user_name = 0;
9878 if(!tng_data->last_user_name)
9880 tng_data->last_user_name = malloc(len);
9881 if(!tng_data->last_user_name)
9883 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
9884 __FILE__, __LINE__);
9885 return(TNG_CRITICAL);
9889 strncpy(tng_data->last_user_name, new_name, len);
9891 return(TNG_SUCCESS);
9894 tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_get
9895 (const tng_trajectory_t tng_data,
9896 char *name, const int max_len)
9898 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9899 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
9901 strncpy(name, tng_data->first_computer_name, max_len - 1);
9902 name[max_len - 1] = 0;
9904 if(strlen(tng_data->first_computer_name) > (unsigned int)max_len - 1)
9906 return(TNG_FAILURE);
9908 return(TNG_SUCCESS);
9911 tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_set
9912 (const tng_trajectory_t tng_data,
9913 const char *new_name)
9917 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9918 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
9920 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
9922 /* If the currently stored string length is not enough to store the new
9923 * string it is freed and reallocated. */
9924 if(tng_data->first_computer_name && strlen(tng_data->first_computer_name) < len)
9926 free(tng_data->first_computer_name);
9927 tng_data->first_computer_name = 0;
9929 if(!tng_data->first_computer_name)
9931 tng_data->first_computer_name = malloc(len);
9932 if(!tng_data->first_computer_name)
9934 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
9935 __FILE__, __LINE__);
9936 return(TNG_CRITICAL);
9940 strncpy(tng_data->first_computer_name, new_name, len);
9942 return(TNG_SUCCESS);
9945 tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_get
9946 (const tng_trajectory_t tng_data,
9947 char *name, const int max_len)
9949 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9950 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
9952 strncpy(name, tng_data->last_computer_name, max_len - 1);
9953 name[max_len - 1] = 0;
9955 if(strlen(tng_data->last_computer_name) > (unsigned int)max_len - 1)
9957 return(TNG_FAILURE);
9959 return(TNG_SUCCESS);
9962 tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_set
9963 (const tng_trajectory_t tng_data,
9964 const char *new_name)
9968 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9969 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
9971 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
9973 /* If the currently stored string length is not enough to store the new
9974 * string it is freed and reallocated. */
9975 if(tng_data->last_computer_name && strlen(tng_data->last_computer_name) <
9978 free(tng_data->last_computer_name);
9979 tng_data->last_computer_name = 0;
9981 if(!tng_data->last_computer_name)
9983 tng_data->last_computer_name = malloc(len);
9984 if(!tng_data->last_computer_name)
9986 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
9987 __FILE__, __LINE__);
9988 return(TNG_CRITICAL);
9992 strncpy(tng_data->last_computer_name, new_name, len);
9994 return(TNG_SUCCESS);
9997 tng_function_status DECLSPECDLLEXPORT tng_first_signature_get
9998 (const tng_trajectory_t tng_data,
9999 char *signature, const int max_len)
10001 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10002 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
10004 strncpy(signature, tng_data->first_pgp_signature, max_len - 1);
10005 signature[max_len - 1] = 0;
10007 if(strlen(tng_data->first_pgp_signature) > (unsigned int)max_len - 1)
10009 return(TNG_FAILURE);
10011 return(TNG_SUCCESS);
10014 tng_function_status DECLSPECDLLEXPORT tng_first_signature_set
10015 (const tng_trajectory_t tng_data,
10016 const char *signature)
10020 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10021 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
10023 len = tng_min_size(strlen(signature) + 1, TNG_MAX_STR_LEN);
10025 /* If the currently stored string length is not enough to store the new
10026 * string it is freed and reallocated. */
10027 if(tng_data->first_pgp_signature && strlen(tng_data->first_pgp_signature) <
10030 free(tng_data->first_pgp_signature);
10031 tng_data->first_pgp_signature = 0;
10033 if(!tng_data->first_pgp_signature)
10035 tng_data->first_pgp_signature = malloc(len);
10036 if(!tng_data->first_pgp_signature)
10038 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10039 __FILE__, __LINE__);
10040 return(TNG_CRITICAL);
10044 strncpy(tng_data->first_pgp_signature, signature, len);
10046 return(TNG_SUCCESS);
10049 tng_function_status DECLSPECDLLEXPORT tng_last_signature_get
10050 (const tng_trajectory_t tng_data,
10051 char *signature, const int max_len)
10053 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10054 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
10056 strncpy(signature, tng_data->last_pgp_signature, max_len - 1);
10057 signature[max_len - 1] = 0;
10059 if(strlen(tng_data->last_pgp_signature) > (unsigned int)max_len - 1)
10061 return(TNG_FAILURE);
10063 return(TNG_SUCCESS);
10066 tng_function_status DECLSPECDLLEXPORT tng_last_signature_set
10067 (const tng_trajectory_t tng_data,
10068 const char *signature)
10072 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10073 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
10075 len = tng_min_size(strlen(signature) + 1, TNG_MAX_STR_LEN);
10077 /* If the currently stored string length is not enough to store the new
10078 * string it is freed and reallocated. */
10079 if(tng_data->last_pgp_signature && strlen(tng_data->last_pgp_signature) <
10082 free(tng_data->last_pgp_signature);
10083 tng_data->last_pgp_signature = 0;
10085 if(!tng_data->last_pgp_signature)
10087 tng_data->last_pgp_signature = malloc(len);
10088 if(!tng_data->last_pgp_signature)
10090 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10091 __FILE__, __LINE__);
10092 return(TNG_CRITICAL);
10096 strncpy(tng_data->last_pgp_signature, signature, len);
10098 return(TNG_SUCCESS);
10101 tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_get
10102 (const tng_trajectory_t tng_data,
10103 char *name, const int max_len)
10105 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10106 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10108 strncpy(name, tng_data->forcefield_name, max_len - 1);
10109 name[max_len - 1] = 0;
10111 if(strlen(tng_data->forcefield_name) > (unsigned int)max_len - 1)
10113 return(TNG_FAILURE);
10115 return(TNG_SUCCESS);
10118 tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_set
10119 (const tng_trajectory_t tng_data,
10120 const char *new_name)
10124 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10125 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10127 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
10129 /* If the currently stored string length is not enough to store the new
10130 * string it is freed and reallocated. */
10131 if(tng_data->forcefield_name && strlen(tng_data->forcefield_name) < len)
10133 free(tng_data->forcefield_name);
10134 tng_data->forcefield_name = 0;
10136 if(!tng_data->forcefield_name)
10138 tng_data->forcefield_name = malloc(len);
10139 if(!tng_data->forcefield_name)
10141 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10142 __FILE__, __LINE__);
10143 return(TNG_CRITICAL);
10147 strncpy(tng_data->forcefield_name, new_name, len);
10149 return(TNG_SUCCESS);
10152 tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_get
10153 (const tng_trajectory_t tng_data,
10156 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10157 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
10159 *len = tng_data->medium_stride_length;
10161 return(TNG_SUCCESS);
10164 tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_set
10165 (const tng_trajectory_t tng_data,
10168 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10170 if(len >= tng_data->long_stride_length)
10172 return(TNG_FAILURE);
10174 tng_data->medium_stride_length = len;
10176 return(TNG_SUCCESS);
10179 tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_get
10180 (const tng_trajectory_t tng_data,
10183 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10184 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
10186 *len = tng_data->long_stride_length;
10188 return(TNG_SUCCESS);
10191 tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_set
10192 (const tng_trajectory_t tng_data,
10195 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10197 if(len <= tng_data->medium_stride_length)
10199 return(TNG_FAILURE);
10201 tng_data->long_stride_length = len;
10203 return(TNG_SUCCESS);
10206 tng_function_status DECLSPECDLLEXPORT tng_time_per_frame_get
10207 (const tng_trajectory_t tng_data,
10210 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10211 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
10213 *time = tng_data->time_per_frame;
10215 return(TNG_SUCCESS);
10218 tng_function_status DECLSPECDLLEXPORT tng_time_per_frame_set
10219 (const tng_trajectory_t tng_data,
10222 tng_trajectory_frame_set_t frame_set;
10224 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10225 TNG_ASSERT(time >= 0, "TNG library: The time per frame must be >= 0.");
10227 if(fabs(time - tng_data->time_per_frame) < 0.00001)
10229 return(TNG_SUCCESS);
10232 frame_set = &tng_data->current_trajectory_frame_set;
10234 /* If the current frame set is not finished write it to disk before
10235 changing time per frame. */
10236 if(tng_data->time_per_frame > 0 && frame_set->n_unwritten_frames > 0)
10238 frame_set->n_frames = frame_set->n_unwritten_frames;
10239 tng_frame_set_write(tng_data, TNG_USE_HASH);
10241 tng_data->time_per_frame = time;
10243 return(TNG_SUCCESS);
10246 tng_function_status DECLSPECDLLEXPORT tng_input_file_len_get
10247 (const tng_trajectory_t tng_data,
10250 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10251 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
10253 *len = tng_data->input_file_len;
10255 return(TNG_SUCCESS);
10258 tng_function_status DECLSPECDLLEXPORT tng_num_frames_get
10259 (const tng_trajectory_t tng_data,
10262 tng_gen_block_t block;
10263 tng_function_status stat;
10264 int64_t file_pos, last_file_pos, first_frame, n_frames;
10266 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10267 TNG_ASSERT(tng_data->input_file, "TNG library: An input file must be open to find the next frame set");
10268 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10270 file_pos = ftello(tng_data->input_file);
10271 last_file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
10273 if(last_file_pos <= 0)
10275 return(TNG_FAILURE);
10278 tng_block_init(&block);
10279 fseeko(tng_data->input_file,
10282 /* Read block headers first to see that a frame set block is found. */
10283 stat = tng_block_header_read(tng_data, block);
10284 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10286 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", last_file_pos,
10287 __FILE__, __LINE__);
10288 tng_block_destroy(&block);
10289 return(TNG_FAILURE);
10291 tng_block_destroy(&block);
10293 if(tng_file_input_numerical(tng_data, &first_frame,
10294 sizeof(first_frame),
10295 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
10297 return(TNG_CRITICAL);
10300 if(tng_file_input_numerical(tng_data, &n_frames,
10302 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
10304 return(TNG_CRITICAL);
10307 fseeko(tng_data->input_file, file_pos, SEEK_SET);
10309 *n = first_frame + n_frames;
10311 return(TNG_SUCCESS);
10314 tng_function_status DECLSPECDLLEXPORT tng_compression_precision_get
10315 (const tng_trajectory_t tng_data,
10318 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10320 *precision = tng_data->compression_precision;
10322 return(TNG_SUCCESS);
10325 tng_function_status DECLSPECDLLEXPORT tng_compression_precision_set
10326 (const tng_trajectory_t tng_data,
10327 const double precision)
10329 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10331 tng_data->compression_precision = precision;
10333 return(TNG_SUCCESS);
10336 tng_function_status DECLSPECDLLEXPORT tng_implicit_num_particles_set
10337 (const tng_trajectory_t tng_data,
10340 tng_molecule_t mol;
10344 tng_function_status stat;
10345 int64_t diff, n_mod, n_impl;
10347 TNG_ASSERT(n >= 0, "TNG library: The requested number of particles must be >= 0");
10349 diff = n - tng_data->n_particles;
10351 stat = tng_molecule_find(tng_data, "TNG_IMPLICIT_MOL", -1, &mol);
10352 if(stat == TNG_SUCCESS)
10354 if(tng_molecule_cnt_get(tng_data, mol, &n_impl) != TNG_SUCCESS)
10356 fprintf(stderr, "TNG library: Cannot get the number of implicit molecules. %s: %d\n",
10357 __FILE__, __LINE__);
10358 return(TNG_FAILURE);
10360 diff -= n_impl * mol->n_atoms;
10365 if(stat == TNG_SUCCESS)
10367 stat = tng_molecule_cnt_set(tng_data, mol, 0);
10370 return(TNG_SUCCESS);
10374 fprintf(stderr, "TNG library: Already more actual particles than requested implicit ");
10375 fprintf(stderr, "particle count.\n");
10376 fprintf(stderr, "TNG library: Cannot set implicit particle count. %s: %d\n",
10377 __FILE__, __LINE__);
10378 /* FIXME: Should we set the count of all other molecules to 0 and add
10379 * implicit molecules? */
10380 return(TNG_FAILURE);
10382 if(stat != TNG_SUCCESS)
10384 stat = tng_molecule_add(tng_data,
10385 "TNG_IMPLICIT_MOL",
10387 if(stat != TNG_SUCCESS)
10391 stat = tng_molecule_chain_add(tng_data, mol, "", &chain);
10392 if(stat != TNG_SUCCESS)
10396 stat = tng_chain_residue_add(tng_data, chain, "", &res);
10397 if(stat != TNG_SUCCESS)
10401 stat = tng_residue_atom_add(tng_data, res, "", "", &atom);
10402 if(stat != TNG_SUCCESS)
10409 if(mol->n_atoms > 1)
10411 n_mod = diff % mol->n_atoms;
10414 fprintf(stderr, "TNG library: Number of atoms in implicit molecule ");
10415 fprintf(stderr, "not compatible with requested implicit particle cnt.\n");
10416 fprintf(stderr, "TNG library: Cannot set implicit particle count. %s: %d\n",
10417 __FILE__, __LINE__);
10418 return(TNG_FAILURE);
10420 diff /= mol->n_atoms;
10423 stat = tng_molecule_cnt_set(tng_data, mol, diff);
10428 tng_function_status DECLSPECDLLEXPORT tng_num_particles_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 if(tng_data->var_num_atoms_flag == TNG_CONSTANT_N_ATOMS)
10437 *n = tng_data->n_particles;
10441 *n = tng_data->current_trajectory_frame_set.n_particles;
10444 return(TNG_SUCCESS);
10447 tng_function_status DECLSPECDLLEXPORT tng_num_particles_variable_get
10448 (const tng_trajectory_t tng_data,
10451 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10452 TNG_ASSERT(variable, "TNG library: variable must not be a NULL pointer");
10454 *variable = tng_data->var_num_atoms_flag;
10456 return(TNG_SUCCESS);
10459 tng_function_status DECLSPECDLLEXPORT tng_num_molecule_types_get
10460 (const tng_trajectory_t tng_data,
10463 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10464 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10466 *n = tng_data->n_molecules;
10468 return(TNG_SUCCESS);
10471 tng_function_status DECLSPECDLLEXPORT tng_num_molecules_get
10472 (const tng_trajectory_t tng_data,
10475 int64_t *cnt_list = 0, cnt = 0, i;
10477 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10478 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10480 tng_molecule_cnt_list_get(tng_data, &cnt_list);
10484 return(TNG_FAILURE);
10487 for(i = 0; i < tng_data->n_molecules; i++)
10489 cnt += cnt_list[i];
10494 return(TNG_SUCCESS);
10497 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_list_get
10498 (const tng_trajectory_t tng_data,
10499 int64_t **mol_cnt_list)
10501 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10503 if(tng_data->var_num_atoms_flag)
10505 *mol_cnt_list = tng_data->current_trajectory_frame_set.
10510 *mol_cnt_list = tng_data->molecule_cnt_list;
10512 if(*mol_cnt_list == 0)
10514 return(TNG_FAILURE);
10516 return(TNG_SUCCESS);
10519 tng_function_status DECLSPECDLLEXPORT tng_distance_unit_exponential_get
10520 (const tng_trajectory_t tng_data,
10523 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10524 TNG_ASSERT(exp, "TNG library: exp must not be a NULL pointer");
10526 *exp = tng_data->distance_unit_exponential;
10528 return(TNG_SUCCESS);
10531 tng_function_status DECLSPECDLLEXPORT tng_distance_unit_exponential_set
10532 (const tng_trajectory_t tng_data,
10535 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10537 tng_data->distance_unit_exponential = exp;
10539 return(TNG_SUCCESS);
10542 tng_function_status DECLSPECDLLEXPORT tng_num_frames_per_frame_set_get
10543 (const tng_trajectory_t tng_data,
10546 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10547 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10549 *n = tng_data->frame_set_n_frames;
10551 return(TNG_SUCCESS);
10554 tng_function_status DECLSPECDLLEXPORT tng_num_frames_per_frame_set_set
10555 (const tng_trajectory_t tng_data,
10558 tng_trajectory_frame_set_t frame_set;
10559 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10561 tng_data->frame_set_n_frames = n;
10562 frame_set = &tng_data->current_trajectory_frame_set;
10565 frame_set->n_frames = n;
10568 return(TNG_SUCCESS);
10571 tng_function_status DECLSPECDLLEXPORT tng_num_frame_sets_get
10572 (const tng_trajectory_t tng_data,
10575 int64_t long_stride_length, medium_stride_length;
10576 int64_t file_pos, orig_frame_set_file_pos;
10577 tng_trajectory_frame_set_t frame_set;
10578 struct tng_trajectory_frame_set orig_frame_set;
10579 tng_gen_block_t block;
10580 tng_function_status stat;
10583 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10584 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10586 orig_frame_set = tng_data->current_trajectory_frame_set;
10588 frame_set = &tng_data->current_trajectory_frame_set;
10590 orig_frame_set_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
10591 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
10595 *n = tng_data->n_trajectory_frame_sets = cnt;
10596 return(TNG_SUCCESS);
10599 tng_block_init(&block);
10600 fseeko(tng_data->input_file,
10603 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
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", file_pos,
10609 __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);
10623 long_stride_length = tng_data->long_stride_length;
10624 medium_stride_length = tng_data->medium_stride_length;
10626 /* Take long steps forward until a long step forward would be too long or
10627 * the last frame set is found */
10628 file_pos = frame_set->long_stride_next_frame_set_file_pos;
10629 while(file_pos > 0)
10633 cnt += long_stride_length;
10634 fseeko(tng_data->input_file, file_pos, SEEK_SET);
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->long_stride_next_frame_set_file_pos;
10655 /* Take medium steps forward until a medium step forward would be too long
10656 * or the last frame set is found */
10657 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
10658 while(file_pos > 0)
10662 cnt += medium_stride_length;
10663 fseeko(tng_data->input_file,
10666 /* Read block headers first to see what block is found. */
10667 stat = tng_block_header_read(tng_data, block);
10668 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10670 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
10671 file_pos, __FILE__, __LINE__);
10672 tng_block_destroy(&block);
10673 return(TNG_CRITICAL);
10676 if(tng_block_read_next(tng_data, block,
10677 TNG_SKIP_HASH) != TNG_SUCCESS)
10679 tng_block_destroy(&block);
10680 return(TNG_CRITICAL);
10683 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
10686 /* Take one step forward until the last frame set is found */
10687 file_pos = frame_set->next_frame_set_file_pos;
10688 while(file_pos > 0)
10693 fseeko(tng_data->input_file,
10696 /* Read block headers first to see what block is found. */
10697 stat = tng_block_header_read(tng_data, block);
10698 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10700 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
10701 file_pos, __FILE__, __LINE__);
10702 tng_block_destroy(&block);
10703 return(TNG_CRITICAL);
10706 if(tng_block_read_next(tng_data, block,
10707 TNG_SKIP_HASH) != TNG_SUCCESS)
10709 tng_block_destroy(&block);
10710 return(TNG_CRITICAL);
10713 file_pos = frame_set->next_frame_set_file_pos;
10716 tng_block_destroy(&block);
10718 *n = tng_data->n_trajectory_frame_sets = cnt;
10720 *frame_set = orig_frame_set;
10721 /* The mapping block in the original frame set has been freed when reading
10722 * other frame sets. */
10723 frame_set->mappings = 0;
10724 frame_set->n_mapping_blocks = 0;
10726 fseeko(tng_data->input_file,
10727 tng_data->first_trajectory_frame_set_input_file_pos,
10730 tng_data->current_trajectory_frame_set_input_file_pos = orig_frame_set_file_pos;
10732 return(TNG_SUCCESS);
10735 tng_function_status DECLSPECDLLEXPORT tng_current_frame_set_get
10736 (const tng_trajectory_t tng_data,
10737 tng_trajectory_frame_set_t *frame_set_p)
10739 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10741 *frame_set_p = &tng_data->current_trajectory_frame_set;
10743 return(TNG_SUCCESS);
10746 tng_function_status DECLSPECDLLEXPORT tng_frame_set_nr_find
10747 (const tng_trajectory_t tng_data,
10750 int64_t long_stride_length, medium_stride_length;
10751 int64_t file_pos, curr_nr = 0, n_frame_sets;
10752 tng_trajectory_frame_set_t frame_set;
10753 tng_gen_block_t block;
10754 tng_function_status stat;
10756 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10757 TNG_ASSERT(nr >= 0, "The frame set number (nr) must be >= 0");
10759 frame_set = &tng_data->current_trajectory_frame_set;
10761 stat = tng_num_frame_sets_get(tng_data, &n_frame_sets);
10763 if(stat != TNG_SUCCESS)
10768 if(nr >= n_frame_sets)
10770 return(TNG_FAILURE);
10773 long_stride_length = tng_data->long_stride_length;
10774 medium_stride_length = tng_data->medium_stride_length;
10776 /* FIXME: The frame set number of the current frame set is not stored */
10778 if(nr < n_frame_sets - 1 - nr)
10780 /* Start from the beginning */
10781 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
10785 /* Start from the end */
10786 file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
10787 curr_nr = n_frame_sets - 1;
10791 return(TNG_FAILURE);
10794 tng_block_init(&block);
10795 fseeko(tng_data->input_file,
10798 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
10799 /* Read block headers first to see what block is found. */
10800 stat = tng_block_header_read(tng_data, block);
10801 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10803 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", file_pos,
10804 __FILE__, __LINE__);
10805 tng_block_destroy(&block);
10806 return(TNG_CRITICAL);
10809 if(tng_block_read_next(tng_data, block,
10810 TNG_SKIP_HASH) != TNG_SUCCESS)
10812 tng_block_destroy(&block);
10813 return(TNG_CRITICAL);
10818 tng_block_destroy(&block);
10819 return(TNG_SUCCESS);
10822 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
10824 /* Take long steps forward until a long step forward would be too long or
10825 * the right frame set is found */
10826 while(file_pos > 0 && curr_nr + long_stride_length <= nr)
10828 file_pos = frame_set->long_stride_next_frame_set_file_pos;
10831 curr_nr += long_stride_length;
10832 fseeko(tng_data->input_file, file_pos, SEEK_SET);
10833 /* Read block headers first to see what block is found. */
10834 stat = tng_block_header_read(tng_data, block);
10835 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10837 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
10838 file_pos, __FILE__, __LINE__);
10839 tng_block_destroy(&block);
10840 return(TNG_CRITICAL);
10843 if(tng_block_read_next(tng_data, block,
10844 TNG_SKIP_HASH) != TNG_SUCCESS)
10846 tng_block_destroy(&block);
10847 return(TNG_CRITICAL);
10851 tng_block_destroy(&block);
10852 return(TNG_SUCCESS);
10857 /* Take medium steps forward until a medium step forward would be too long
10858 * or the right frame set is found */
10859 while(file_pos > 0 && curr_nr + medium_stride_length <= nr)
10861 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
10864 curr_nr += medium_stride_length;
10865 fseeko(tng_data->input_file,
10868 /* Read block headers first to see what block is found. */
10869 stat = tng_block_header_read(tng_data, block);
10870 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10872 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
10873 file_pos, __FILE__, __LINE__);
10874 tng_block_destroy(&block);
10875 return(TNG_CRITICAL);
10878 if(tng_block_read_next(tng_data, block,
10879 TNG_SKIP_HASH) != TNG_SUCCESS)
10881 tng_block_destroy(&block);
10882 return(TNG_CRITICAL);
10886 tng_block_destroy(&block);
10887 return(TNG_SUCCESS);
10892 /* Take one step forward until the right frame set is found */
10893 while(file_pos > 0 && curr_nr < nr)
10895 file_pos = frame_set->next_frame_set_file_pos;
10900 fseeko(tng_data->input_file,
10903 /* Read block headers first to see what block is found. */
10904 stat = tng_block_header_read(tng_data, block);
10905 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10907 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
10908 file_pos, __FILE__, __LINE__);
10909 tng_block_destroy(&block);
10910 return(TNG_CRITICAL);
10913 if(tng_block_read_next(tng_data, block,
10914 TNG_SKIP_HASH) != TNG_SUCCESS)
10916 tng_block_destroy(&block);
10917 return(TNG_CRITICAL);
10921 tng_block_destroy(&block);
10922 return(TNG_SUCCESS);
10927 /* Take long steps backward until a long step backward would be too long
10928 * or the right frame set is found */
10929 while(file_pos > 0 && curr_nr - long_stride_length >= nr)
10931 file_pos = frame_set->long_stride_prev_frame_set_file_pos;
10934 curr_nr -= long_stride_length;
10935 fseeko(tng_data->input_file,
10938 /* Read block headers first to see what block is found. */
10939 stat = tng_block_header_read(tng_data, block);
10940 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10942 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
10943 file_pos, __FILE__, __LINE__);
10944 tng_block_destroy(&block);
10945 return(TNG_CRITICAL);
10948 if(tng_block_read_next(tng_data, block,
10949 TNG_SKIP_HASH) != TNG_SUCCESS)
10951 tng_block_destroy(&block);
10952 return(TNG_CRITICAL);
10956 tng_block_destroy(&block);
10957 return(TNG_SUCCESS);
10962 /* Take medium steps backward until a medium step backward would be too long
10963 * or the right frame set is found */
10964 while(file_pos > 0 && curr_nr - medium_stride_length >= nr)
10966 file_pos = frame_set->medium_stride_prev_frame_set_file_pos;
10969 curr_nr -= medium_stride_length;
10970 fseeko(tng_data->input_file,
10973 /* Read block headers first to see what block is found. */
10974 stat = tng_block_header_read(tng_data, block);
10975 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10977 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
10978 file_pos, __FILE__, __LINE__);
10979 tng_block_destroy(&block);
10980 return(TNG_CRITICAL);
10983 if(tng_block_read_next(tng_data, block,
10984 TNG_SKIP_HASH) != TNG_SUCCESS)
10986 tng_block_destroy(&block);
10987 return(TNG_CRITICAL);
10991 tng_block_destroy(&block);
10992 return(TNG_SUCCESS);
10997 /* Take one step backward until the right frame set is found */
10998 while(file_pos > 0 && curr_nr > nr)
11000 file_pos = frame_set->prev_frame_set_file_pos;
11004 fseeko(tng_data->input_file,
11007 /* Read block headers first to see what block is found. */
11008 stat = tng_block_header_read(tng_data, block);
11009 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11011 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11012 file_pos, __FILE__, __LINE__);
11013 tng_block_destroy(&block);
11014 return(TNG_CRITICAL);
11017 if(tng_block_read_next(tng_data, block,
11018 TNG_SKIP_HASH) != TNG_SUCCESS)
11020 tng_block_destroy(&block);
11021 return(TNG_CRITICAL);
11025 tng_block_destroy(&block);
11026 return(TNG_SUCCESS);
11031 /* If for some reason the current frame set is not yet found,
11032 * take one step forward until the right frame set is found */
11033 while(file_pos > 0 && curr_nr < nr)
11035 file_pos = frame_set->next_frame_set_file_pos;
11039 fseeko(tng_data->input_file,
11042 /* Read block headers first to see what block is found. */
11043 stat = tng_block_header_read(tng_data, block);
11044 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11046 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11047 file_pos, __FILE__, __LINE__);
11048 tng_block_destroy(&block);
11049 return(TNG_CRITICAL);
11052 if(tng_block_read_next(tng_data, block,
11053 TNG_SKIP_HASH) != TNG_SUCCESS)
11055 tng_block_destroy(&block);
11056 return(TNG_CRITICAL);
11060 tng_block_destroy(&block);
11061 return(TNG_SUCCESS);
11066 tng_block_destroy(&block);
11067 return(TNG_FAILURE);
11070 tng_function_status DECLSPECDLLEXPORT tng_frame_set_of_frame_find
11071 (const tng_trajectory_t tng_data,
11072 const int64_t frame)
11074 int64_t first_frame, last_frame, n_frames_per_frame_set;
11075 int64_t long_stride_length, medium_stride_length;
11076 int64_t file_pos, temp_frame, n_frames;
11077 tng_trajectory_frame_set_t frame_set;
11078 tng_gen_block_t block;
11079 tng_function_status stat;
11081 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11082 TNG_ASSERT(frame >= 0, "TNG library: frame must be >= 0.");
11084 frame_set = &tng_data->current_trajectory_frame_set;
11086 tng_block_init(&block);
11088 if(tng_data->current_trajectory_frame_set_input_file_pos < 0)
11090 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
11091 fseeko(tng_data->input_file,
11094 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
11095 /* Read block headers first to see what block is found. */
11096 stat = tng_block_header_read(tng_data, block);
11097 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11099 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11100 file_pos, __FILE__, __LINE__);
11101 tng_block_destroy(&block);
11102 return(TNG_CRITICAL);
11105 if(tng_block_read_next(tng_data, block,
11106 TNG_SKIP_HASH) != TNG_SUCCESS)
11108 tng_block_destroy(&block);
11109 return(TNG_CRITICAL);
11113 first_frame = tng_max_i64(frame_set->first_frame, 0);
11114 last_frame = first_frame + frame_set->n_frames - 1;
11115 /* Is this the right frame set? */
11116 if(first_frame <= frame && frame <= last_frame)
11118 tng_block_destroy(&block);
11119 return(TNG_SUCCESS);
11122 n_frames_per_frame_set = tng_data->frame_set_n_frames;
11123 long_stride_length = tng_data->long_stride_length;
11124 medium_stride_length = tng_data->medium_stride_length;
11126 if(tng_first_frame_nr_of_next_frame_set_get(tng_data, &temp_frame) ==
11129 if(temp_frame - first_frame > n_frames_per_frame_set)
11131 n_frames_per_frame_set = temp_frame - first_frame;
11135 tng_num_frames_get(tng_data, &n_frames);
11137 if(frame >= n_frames)
11139 tng_block_destroy(&block);
11140 return(TNG_FAILURE);
11143 if(first_frame - frame >= frame ||
11144 frame - last_frame >
11145 tng_data->n_trajectory_frame_sets * n_frames_per_frame_set - frame)
11147 /* Start from the beginning */
11148 if(first_frame - frame >= frame)
11150 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
11154 tng_block_destroy(&block);
11155 return(TNG_FAILURE);
11158 /* Start from the end */
11159 else if(frame - first_frame > (n_frames - 1) - frame)
11161 file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
11163 /* If the last frame set position is not set start from the current
11164 * frame set, since it will be closer than the first frame set. */
11166 /* Start from current */
11169 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
11174 fseeko(tng_data->input_file,
11177 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
11178 /* Read block headers first to see what block is found. */
11179 stat = tng_block_header_read(tng_data, block);
11180 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11182 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11183 file_pos, __FILE__, __LINE__);
11184 tng_block_destroy(&block);
11185 return(TNG_CRITICAL);
11188 if(tng_block_read_next(tng_data, block,
11189 TNG_SKIP_HASH) != TNG_SUCCESS)
11191 tng_block_destroy(&block);
11192 return(TNG_CRITICAL);
11197 first_frame = tng_max_i64(frame_set->first_frame, 0);
11198 last_frame = first_frame + frame_set->n_frames - 1;
11200 if(frame >= first_frame && frame <= last_frame)
11202 tng_block_destroy(&block);
11203 return(TNG_SUCCESS);
11206 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
11208 /* Take long steps forward until a long step forward would be too long or
11209 * the right frame set is found */
11210 while(file_pos > 0 && first_frame + long_stride_length *
11211 n_frames_per_frame_set <= frame)
11213 file_pos = frame_set->long_stride_next_frame_set_file_pos;
11216 fseeko(tng_data->input_file, file_pos, SEEK_SET);
11217 /* Read block headers first to see what block is found. */
11218 stat = tng_block_header_read(tng_data, block);
11219 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11221 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11222 file_pos, __FILE__, __LINE__);
11223 tng_block_destroy(&block);
11224 return(TNG_CRITICAL);
11227 if(tng_block_read_next(tng_data, block,
11228 TNG_SKIP_HASH) != TNG_SUCCESS)
11230 tng_block_destroy(&block);
11231 return(TNG_CRITICAL);
11234 first_frame = tng_max_i64(frame_set->first_frame, 0);
11235 last_frame = first_frame + frame_set->n_frames - 1;
11236 if(frame >= first_frame && frame <= last_frame)
11238 tng_block_destroy(&block);
11239 return(TNG_SUCCESS);
11243 /* Take medium steps forward until a medium step forward would be too long
11244 * or the right frame set is found */
11245 while(file_pos > 0 && first_frame + medium_stride_length *
11246 n_frames_per_frame_set <= frame)
11248 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
11251 fseeko(tng_data->input_file,
11254 /* Read block headers first to see what block is found. */
11255 stat = tng_block_header_read(tng_data, block);
11256 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11258 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11259 file_pos, __FILE__, __LINE__);
11260 tng_block_destroy(&block);
11261 return(TNG_CRITICAL);
11264 if(tng_block_read_next(tng_data, block,
11265 TNG_SKIP_HASH) != TNG_SUCCESS)
11267 tng_block_destroy(&block);
11268 return(TNG_CRITICAL);
11271 first_frame = tng_max_i64(frame_set->first_frame, 0);
11272 last_frame = first_frame + frame_set->n_frames - 1;
11273 if(frame >= first_frame && frame <= last_frame)
11275 tng_block_destroy(&block);
11276 return(TNG_SUCCESS);
11280 /* Take one step forward until the right frame set is found */
11281 while(file_pos > 0 && first_frame < frame && last_frame < frame)
11283 file_pos = frame_set->next_frame_set_file_pos;
11286 fseeko(tng_data->input_file,
11289 /* Read block headers first to see what block is found. */
11290 stat = tng_block_header_read(tng_data, block);
11291 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11293 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11294 file_pos, __FILE__, __LINE__);
11295 tng_block_destroy(&block);
11296 return(TNG_CRITICAL);
11299 if(tng_block_read_next(tng_data, block,
11300 TNG_SKIP_HASH) != TNG_SUCCESS)
11302 tng_block_destroy(&block);
11303 return(TNG_CRITICAL);
11306 first_frame = tng_max_i64(frame_set->first_frame, 0);
11307 last_frame = first_frame + frame_set->n_frames - 1;
11308 if(frame >= first_frame && frame <= last_frame)
11310 tng_block_destroy(&block);
11311 return(TNG_SUCCESS);
11315 /* Take long steps backward until a long step backward would be too long
11316 * or the right frame set is found */
11317 while(file_pos > 0 && first_frame - long_stride_length *
11318 n_frames_per_frame_set >= frame)
11320 file_pos = frame_set->long_stride_prev_frame_set_file_pos;
11323 fseeko(tng_data->input_file,
11326 /* Read block headers first to see what block is found. */
11327 stat = tng_block_header_read(tng_data, block);
11328 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11330 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11331 file_pos, __FILE__, __LINE__);
11332 tng_block_destroy(&block);
11333 return(TNG_CRITICAL);
11336 if(tng_block_read_next(tng_data, block,
11337 TNG_SKIP_HASH) != TNG_SUCCESS)
11339 tng_block_destroy(&block);
11340 return(TNG_CRITICAL);
11343 first_frame = tng_max_i64(frame_set->first_frame, 0);
11344 last_frame = first_frame + frame_set->n_frames - 1;
11345 if(frame >= first_frame && frame <= last_frame)
11347 tng_block_destroy(&block);
11348 return(TNG_SUCCESS);
11352 /* Take medium steps backward until a medium step backward would be too long
11353 * or the right frame set is found */
11354 while(file_pos > 0 && first_frame - medium_stride_length *
11355 n_frames_per_frame_set >= frame)
11357 file_pos = frame_set->medium_stride_prev_frame_set_file_pos;
11360 fseeko(tng_data->input_file,
11363 /* Read block headers first to see what block is found. */
11364 stat = tng_block_header_read(tng_data, block);
11365 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11367 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11368 file_pos, __FILE__, __LINE__);
11369 tng_block_destroy(&block);
11370 return(TNG_CRITICAL);
11373 if(tng_block_read_next(tng_data, block,
11374 TNG_SKIP_HASH) != TNG_SUCCESS)
11376 tng_block_destroy(&block);
11377 return(TNG_CRITICAL);
11380 first_frame = tng_max_i64(frame_set->first_frame, 0);
11381 last_frame = first_frame + frame_set->n_frames - 1;
11382 if(frame >= first_frame && frame <= last_frame)
11384 tng_block_destroy(&block);
11385 return(TNG_SUCCESS);
11389 /* Take one step backward until the right frame set is found */
11390 while(file_pos > 0 && first_frame > frame && last_frame > frame)
11392 file_pos = frame_set->prev_frame_set_file_pos;
11395 fseeko(tng_data->input_file,
11398 /* Read block headers first to see what block is found. */
11399 stat = tng_block_header_read(tng_data, block);
11400 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11402 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11403 file_pos, __FILE__, __LINE__);
11404 tng_block_destroy(&block);
11405 return(TNG_CRITICAL);
11408 if(tng_block_read_next(tng_data, block,
11409 TNG_SKIP_HASH) != TNG_SUCCESS)
11411 tng_block_destroy(&block);
11412 return(TNG_CRITICAL);
11415 first_frame = tng_max_i64(frame_set->first_frame, 0);
11416 last_frame = first_frame + frame_set->n_frames - 1;
11417 if(frame >= first_frame && frame <= last_frame)
11419 tng_block_destroy(&block);
11420 return(TNG_SUCCESS);
11424 /* If for some reason the current frame set is not yet found,
11425 * take one step forward until the right frame set is found */
11426 while(file_pos > 0 && first_frame < frame && last_frame < frame)
11428 file_pos = frame_set->next_frame_set_file_pos;
11431 fseeko(tng_data->input_file,
11434 /* Read block headers first to see what block is found. */
11435 stat = tng_block_header_read(tng_data, block);
11436 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11438 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11439 file_pos, __FILE__, __LINE__);
11440 tng_block_destroy(&block);
11441 return(TNG_CRITICAL);
11444 if(tng_block_read_next(tng_data, block,
11445 TNG_SKIP_HASH) != TNG_SUCCESS)
11447 tng_block_destroy(&block);
11448 return(TNG_CRITICAL);
11451 first_frame = tng_max_i64(frame_set->first_frame, 0);
11452 last_frame = first_frame + frame_set->n_frames - 1;
11453 if(frame >= first_frame && frame <= last_frame)
11455 tng_block_destroy(&block);
11456 return(TNG_SUCCESS);
11460 tng_block_destroy(&block);
11461 return(TNG_FAILURE);
11464 tng_function_status DECLSPECDLLEXPORT tng_frame_set_next_frame_set_file_pos_get
11465 (const tng_trajectory_t tng_data,
11466 const tng_trajectory_frame_set_t frame_set,
11471 TNG_ASSERT(frame_set, "TNG library: frame_set not initialised before accessing data.");
11472 TNG_ASSERT(pos, "TNG library: pos must not be a NULL pointer");
11474 *pos = frame_set->next_frame_set_file_pos;
11476 return(TNG_SUCCESS);
11479 tng_function_status DECLSPECDLLEXPORT tng_frame_set_prev_frame_set_file_pos_get
11480 (const tng_trajectory_t tng_data,
11481 const tng_trajectory_frame_set_t frame_set,
11486 TNG_ASSERT(frame_set, "TNG library: frame_set not initialised before accessing data.");
11487 TNG_ASSERT(pos, "TNG library: pos must not be a NULL pointer");
11489 *pos = frame_set->prev_frame_set_file_pos;
11491 return(TNG_SUCCESS);
11494 tng_function_status DECLSPECDLLEXPORT tng_frame_set_frame_range_get
11495 (const tng_trajectory_t tng_data,
11496 const tng_trajectory_frame_set_t frame_set,
11497 int64_t *first_frame,
11498 int64_t *last_frame)
11502 TNG_ASSERT(first_frame, "TNG library: first_frame must not be a NULL pointer");
11503 TNG_ASSERT(last_frame, "TNG library: last_frame must not be a NULL pointer");
11504 TNG_ASSERT(frame_set, "TNG library: frame_set must not be a NULL pointer");
11506 *first_frame = frame_set->first_frame;
11507 *last_frame = *first_frame + frame_set->n_frames - 1;
11509 return(TNG_SUCCESS);
11513 * @brief Translate from the particle numbering used in a frame set to the real
11514 * particle numbering - used in the molecule description.
11515 * @param frame_set is the frame_set containing the mappings to use.
11516 * @param local is the index number of the atom in this frame set
11517 * @param real is set to the index of the atom in the molecular system.
11518 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the mapping
11521 static TNG_INLINE tng_function_status tng_particle_mapping_get_real_particle
11522 (const tng_trajectory_frame_set_t frame_set,
11523 const int64_t local,
11526 int64_t i, n_blocks = frame_set->n_mapping_blocks, first;
11527 tng_particle_mapping_t mapping;
11531 return(TNG_SUCCESS);
11533 for(i = 0; i < n_blocks; i++)
11535 mapping = &frame_set->mappings[i];
11536 first = mapping->num_first_particle;
11537 if(local < first ||
11538 local >= first + mapping->n_particles)
11542 *real = mapping->real_particle_numbers[local-first];
11543 return(TNG_SUCCESS);
11546 return(TNG_FAILURE);
11550 * @brief Translate from the real particle numbering to the particle numbering
11551 * used in a frame set.
11552 * @param frame_set is the frame_set containing the mappings to use.
11553 * @param real is the index number of the atom in the molecular system.
11554 * @param local is set to the index of the atom in this frame set.
11555 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the mapping
11558 /*static TNG_INLINE tng_function_status tng_particle_mapping_get_local_particle
11559 (const tng_trajectory_frame_set_t frame_set,
11560 const int64_t real,
11563 int64_t i, j, n_blocks = frame_set->n_mapping_blocks;
11564 tng_particle_mapping_t mapping;
11568 return(TNG_SUCCESS);
11570 for(i = 0; i < n_blocks; i++)
11572 mapping = &frame_set->mappings[i];
11573 for(j = mapping->n_particles; j--;)
11575 if(mapping->real_particle_numbers[j] == real)
11578 return(TNG_SUCCESS);
11582 return(TNG_FAILURE);
11586 static tng_function_status tng_file_headers_len_get
11587 (const tng_trajectory_t tng_data,
11591 tng_gen_block_t block;
11593 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11595 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
11597 return(TNG_CRITICAL);
11602 orig_pos = ftello(tng_data->input_file);
11604 fseeko(tng_data->input_file, 0, SEEK_SET);
11606 tng_block_init(&block);
11607 /* Read through the headers of non-trajectory blocks (they come before the
11608 * trajectory blocks in the file) */
11609 while (*len < tng_data->input_file_len &&
11610 tng_block_header_read(tng_data, block) != TNG_CRITICAL &&
11612 block->id != TNG_TRAJECTORY_FRAME_SET)
11614 *len += block->header_contents_size + block->block_contents_size;
11615 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
11618 fseeko(tng_data->input_file, orig_pos, SEEK_SET);
11620 tng_block_destroy(&block);
11622 return(TNG_SUCCESS);
11625 tng_function_status DECLSPECDLLEXPORT tng_file_headers_read
11626 (const tng_trajectory_t tng_data,
11627 const char hash_mode)
11629 int64_t prev_pos = 0;
11630 tng_gen_block_t block;
11632 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11634 tng_data->n_trajectory_frame_sets = 0;
11636 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
11638 return(TNG_CRITICAL);
11641 fseeko(tng_data->input_file, 0, SEEK_SET);
11643 tng_block_init(&block);
11644 /* Non trajectory blocks (they come before the trajectory
11645 * blocks in the file) */
11646 while (prev_pos < tng_data->input_file_len &&
11647 tng_block_header_read(tng_data, block) != TNG_CRITICAL &&
11649 block->id != TNG_TRAJECTORY_FRAME_SET)
11651 tng_block_read_next(tng_data, block, hash_mode);
11652 prev_pos = ftello(tng_data->input_file);
11655 /* Go back if a trajectory block was encountered */
11656 if(block->id == TNG_TRAJECTORY_FRAME_SET)
11658 fseeko(tng_data->input_file, prev_pos, SEEK_SET);
11661 tng_block_destroy(&block);
11663 return(TNG_SUCCESS);
11666 tng_function_status DECLSPECDLLEXPORT tng_file_headers_write
11667 (const tng_trajectory_t tng_data,
11668 const char hash_mode)
11671 int64_t len, orig_len, tot_len = 0, data_start_pos, temp_pos = -1;
11672 tng_function_status stat;
11673 tng_gen_block_t block;
11675 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11677 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
11679 return(TNG_CRITICAL);
11682 if(tng_data->n_trajectory_frame_sets > 0)
11684 stat = tng_file_headers_len_get(tng_data, &orig_len);
11685 if(stat != TNG_SUCCESS)
11690 tng_block_init(&block);
11691 block->name = malloc(TNG_MAX_STR_LEN);
11694 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
11695 TNG_MAX_STR_LEN, __FILE__, __LINE__);
11696 tng_block_destroy(&block);
11697 return(TNG_CRITICAL);
11699 strcpy(block->name, "GENERAL INFO");
11700 tng_block_header_len_calculate(tng_data, block, &len);
11702 tng_general_info_block_len_calculate(tng_data, &len);
11704 strcpy(block->name, "MOLECULES");
11705 tng_block_header_len_calculate(tng_data, block, &len);
11707 tng_molecules_block_len_calculate(tng_data, &len);
11710 for(i = 0; i < tng_data->n_data_blocks; i++)
11712 strcpy(block->name, tng_data->non_tr_data[i].block_name);
11713 tng_block_header_len_calculate(tng_data, block, &len);
11715 tng_data_block_len_calculate(tng_data,
11716 (tng_data_t)&tng_data->non_tr_data[i],
11717 TNG_FALSE, 1, 1, 1, 0, 1,
11722 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
11724 strcpy(block->name, tng_data->non_tr_particle_data[i].block_name);
11725 tng_block_header_len_calculate(tng_data, block, &len);
11727 tng_data_block_len_calculate(tng_data,
11728 &tng_data->non_tr_particle_data[i],
11729 TNG_TRUE, 1, 1, 1, 0,
11730 tng_data->n_particles,
11735 tng_block_destroy(&block);
11737 if(tot_len > orig_len)
11739 tng_migrate_data_in_file(tng_data, orig_len+1, tot_len - orig_len, hash_mode);
11742 stat = tng_reread_frame_set_at_file_pos(tng_data, tng_data->last_trajectory_frame_set_input_file_pos);
11743 if(stat == TNG_CRITICAL)
11745 fprintf(stderr, "TNG library: Cannot read frame set. %s: %d\n",
11746 __FILE__, __LINE__);
11747 return(TNG_CRITICAL);
11750 /* In order to write non-trajectory data the current_trajectory_frame_set_output_file_pos
11751 * must temporarily be reset */
11752 temp_pos = tng_data->current_trajectory_frame_set_output_file_pos;
11753 tng_data->current_trajectory_frame_set_output_file_pos = -1;
11756 if(tng_general_info_block_write(tng_data, hash_mode)
11759 fprintf(stderr, "TNG library: Error writing general info block of file %s. %s: %d\n",
11760 tng_data->input_file_path, __FILE__, __LINE__);
11761 return(TNG_CRITICAL);
11764 if(tng_molecules_block_write(tng_data, hash_mode)
11767 fprintf(stderr, "TNG library: Error writing atom names block of file %s. %s: %d\n",
11768 tng_data->input_file_path, __FILE__, __LINE__);
11769 return(TNG_CRITICAL);
11772 /* FIXME: Currently writing non-trajectory data blocks here.
11773 * Should perhaps be moved. */
11774 tng_block_init(&block);
11775 for(i = 0; i < tng_data->n_data_blocks; i++)
11777 block->id = tng_data->non_tr_data[i].block_id;
11778 tng_data_block_write(tng_data, block,
11779 i, TNG_FALSE, 0, hash_mode);
11782 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
11784 block->id = tng_data->non_tr_particle_data[i].block_id;
11785 tng_data_block_write(tng_data, block,
11786 i, TNG_TRUE, 0, hash_mode);
11789 tng_block_destroy(&block);
11791 /* Continue writing at the end of the file. */
11792 fseeko(tng_data->output_file, 0, SEEK_END);
11795 tng_data->current_trajectory_frame_set_output_file_pos = temp_pos;
11798 return(TNG_SUCCESS);
11801 tng_function_status DECLSPECDLLEXPORT tng_block_read_next
11802 (const tng_trajectory_t tng_data,
11803 const tng_gen_block_t block,
11804 const char hash_mode)
11806 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11807 TNG_ASSERT(block, "TNG library: block must be initialised and must not be a NULL pointer.");
11811 case TNG_TRAJECTORY_FRAME_SET:
11812 return(tng_frame_set_block_read(tng_data, block, hash_mode));
11813 case TNG_PARTICLE_MAPPING:
11814 return(tng_trajectory_mapping_block_read(tng_data, block, hash_mode));
11815 case TNG_GENERAL_INFO:
11816 return(tng_general_info_block_read(tng_data, block, hash_mode));
11817 case TNG_MOLECULES:
11818 return(tng_molecules_block_read(tng_data, block, hash_mode));
11820 if(block->id >= TNG_TRAJ_BOX_SHAPE)
11822 return(tng_data_block_contents_read(tng_data, block, hash_mode));
11826 /* Skip to the next block */
11827 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
11828 return(TNG_FAILURE);
11833 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read
11834 (const tng_trajectory_t tng_data,
11835 const char hash_mode)
11838 tng_gen_block_t block;
11839 tng_function_status stat;
11841 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11843 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
11845 return(TNG_CRITICAL);
11848 file_pos = ftello(tng_data->input_file);
11850 tng_block_init(&block);
11852 /* Read block headers first to see what block is found. */
11853 stat = tng_block_header_read(tng_data, block);
11854 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET ||
11857 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11858 file_pos, __FILE__, __LINE__);
11859 tng_block_destroy(&block);
11860 return(TNG_CRITICAL);
11863 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
11865 if(tng_block_read_next(tng_data, block,
11866 hash_mode) == TNG_SUCCESS)
11868 tng_data->n_trajectory_frame_sets++;
11869 file_pos = ftello(tng_data->input_file);
11870 /* Read all blocks until next frame set block */
11871 stat = tng_block_header_read(tng_data, block);
11872 while(file_pos < tng_data->input_file_len &&
11873 stat != TNG_CRITICAL &&
11874 block->id != TNG_TRAJECTORY_FRAME_SET &&
11877 stat = tng_block_read_next(tng_data, block,
11879 if(stat != TNG_CRITICAL)
11881 file_pos = ftello(tng_data->input_file);
11882 if(file_pos < tng_data->input_file_len)
11884 stat = tng_block_header_read(tng_data, block);
11888 if(stat == TNG_CRITICAL)
11890 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11891 file_pos, __FILE__, __LINE__);
11892 tng_block_destroy(&block);
11896 if(block->id == TNG_TRAJECTORY_FRAME_SET)
11898 fseeko(tng_data->input_file, file_pos, SEEK_SET);
11902 tng_block_destroy(&block);
11904 return(TNG_SUCCESS);
11908 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_current_only_data_from_block_id
11909 (const tng_trajectory_t tng_data,
11910 const char hash_mode,
11911 const int64_t block_id)
11914 tng_gen_block_t block;
11915 tng_function_status stat;
11916 int found_flag = 1;
11918 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11920 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
11922 return(TNG_CRITICAL);
11925 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
11929 /* No current frame set. This means that the first frame set must be
11932 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
11937 fseeko(tng_data->input_file,
11943 return(TNG_FAILURE);
11946 tng_block_init(&block);
11948 /* Read block headers first to see what block is found. */
11949 stat = tng_block_header_read(tng_data, block);
11950 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11952 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11953 file_pos, __FILE__, __LINE__);
11954 tng_block_destroy(&block);
11955 return(TNG_CRITICAL);
11957 /* If the current frame set had already been read skip its block contents */
11960 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
11962 /* Otherwise read the frame set block */
11965 stat = tng_block_read_next(tng_data, block,
11967 if(stat != TNG_SUCCESS)
11969 fprintf(stderr, "TNG library: Cannot read frame set block. %s: %d\n", __FILE__, __LINE__);
11970 tng_block_destroy(&block);
11974 file_pos = ftello(tng_data->input_file);
11978 /* Read only blocks of the requested ID
11979 * until next frame set block */
11980 stat = tng_block_header_read(tng_data, block);
11981 while(file_pos < tng_data->input_file_len &&
11982 stat != TNG_CRITICAL &&
11983 block->id != TNG_TRAJECTORY_FRAME_SET &&
11986 if(block->id == block_id)
11988 stat = tng_block_read_next(tng_data, block,
11990 if(stat != TNG_CRITICAL)
11992 file_pos = ftello(tng_data->input_file);
11994 if(file_pos < tng_data->input_file_len)
11996 stat = tng_block_header_read(tng_data, block);
12002 file_pos += block->block_contents_size + block->header_contents_size;
12003 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
12004 if(file_pos < tng_data->input_file_len)
12006 stat = tng_block_header_read(tng_data, block);
12010 if(stat == TNG_CRITICAL)
12012 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12013 file_pos, __FILE__, __LINE__);
12014 tng_block_destroy(&block);
12018 if(block->id == TNG_TRAJECTORY_FRAME_SET)
12020 fseeko(tng_data->input_file, file_pos, SEEK_SET);
12023 tng_block_destroy(&block);
12027 return(TNG_SUCCESS);
12031 return(TNG_FAILURE);
12035 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next
12036 (const tng_trajectory_t tng_data,
12037 const char hash_mode)
12041 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12043 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12045 return(TNG_CRITICAL);
12048 file_pos = tng_data->current_trajectory_frame_set.next_frame_set_file_pos;
12050 if(file_pos < 0 && tng_data->current_trajectory_frame_set_input_file_pos <= 0)
12052 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
12057 fseeko(tng_data->input_file,
12063 return(TNG_FAILURE);
12066 return(tng_frame_set_read(tng_data, hash_mode));
12069 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next_only_data_from_block_id
12070 (const tng_trajectory_t tng_data,
12071 const char hash_mode,
12072 const int64_t block_id)
12075 tng_gen_block_t block;
12076 tng_function_status stat;
12078 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12080 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12082 return(TNG_CRITICAL);
12085 file_pos = tng_data->current_trajectory_frame_set.next_frame_set_file_pos;
12087 if(file_pos < 0 && tng_data->current_trajectory_frame_set_input_file_pos <= 0)
12089 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
12094 fseeko(tng_data->input_file,
12100 return(TNG_FAILURE);
12103 tng_block_init(&block);
12105 /* Read block headers first to see what block is found. */
12106 stat = tng_block_header_read(tng_data, block);
12107 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12109 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12110 file_pos, __FILE__, __LINE__);
12111 tng_block_destroy(&block);
12112 return(TNG_CRITICAL);
12115 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
12117 if(tng_block_read_next(tng_data, block,
12118 hash_mode) == TNG_SUCCESS)
12120 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, hash_mode, block_id);
12123 tng_block_destroy(&block);
12128 tng_function_status tng_frame_set_write
12129 (const tng_trajectory_t tng_data,
12130 const char hash_mode)
12133 tng_gen_block_t block;
12134 tng_trajectory_frame_set_t frame_set;
12135 tng_function_status stat;
12137 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12139 frame_set = &tng_data->current_trajectory_frame_set;
12141 if(frame_set->n_written_frames == frame_set->n_frames)
12143 return(TNG_SUCCESS);
12146 tng_data->current_trajectory_frame_set_output_file_pos =
12147 ftello(tng_data->output_file);
12148 tng_data->last_trajectory_frame_set_output_file_pos =
12149 tng_data->current_trajectory_frame_set_output_file_pos;
12151 if(tng_data->current_trajectory_frame_set_output_file_pos <= 0)
12153 return(TNG_FAILURE);
12156 if(tng_data->first_trajectory_frame_set_output_file_pos == -1)
12158 tng_data->first_trajectory_frame_set_output_file_pos =
12159 tng_data->current_trajectory_frame_set_output_file_pos;
12162 tng_block_init(&block);
12164 if(tng_frame_set_block_write(tng_data, block, hash_mode) != TNG_SUCCESS)
12166 tng_block_destroy(&block);
12167 return(TNG_FAILURE);
12170 /* Write non-particle data blocks */
12171 for(i = 0; i<frame_set->n_data_blocks; i++)
12173 block->id = frame_set->tr_data[i].block_id;
12174 tng_data_block_write(tng_data, block, i, TNG_FALSE, 0, hash_mode);
12176 /* Write the mapping blocks and particle data blocks*/
12177 if(frame_set->n_mapping_blocks)
12179 for(i = 0; i < frame_set->n_mapping_blocks; i++)
12181 block->id = TNG_PARTICLE_MAPPING;
12182 if(frame_set->mappings[i].n_particles > 0)
12184 tng_trajectory_mapping_block_write(tng_data, block, i, hash_mode);
12185 for(j = 0; j<frame_set->n_particle_data_blocks; j++)
12187 block->id = frame_set->tr_particle_data[j].block_id;
12188 tng_data_block_write(tng_data, block,
12189 j, TNG_TRUE, &frame_set->mappings[i],
12197 for(i = 0; i<frame_set->n_particle_data_blocks; i++)
12199 block->id = frame_set->tr_particle_data[i].block_id;
12200 tng_data_block_write(tng_data, block,
12201 i, TNG_TRUE, 0, hash_mode);
12206 /* Update pointers in the general info block */
12207 stat = tng_header_pointers_update(tng_data, hash_mode);
12209 if(stat == TNG_SUCCESS)
12211 stat = tng_frame_set_pointers_update(tng_data, hash_mode);
12214 tng_block_destroy(&block);
12216 frame_set->n_unwritten_frames = 0;
12218 fflush(tng_data->output_file);
12223 tng_function_status DECLSPECDLLEXPORT tng_frame_set_premature_write
12224 (const tng_trajectory_t tng_data,
12225 const char hash_mode)
12227 tng_trajectory_frame_set_t frame_set;
12229 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12231 frame_set = &tng_data->current_trajectory_frame_set;
12233 if(frame_set->n_unwritten_frames == 0)
12235 return(TNG_SUCCESS);
12237 frame_set->n_frames = frame_set->n_unwritten_frames;
12239 return(tng_frame_set_write(tng_data, hash_mode));
12242 tng_function_status DECLSPECDLLEXPORT tng_frame_set_new
12243 (const tng_trajectory_t tng_data,
12244 const int64_t first_frame,
12245 const int64_t n_frames)
12247 tng_gen_block_t block;
12248 tng_trajectory_frame_set_t frame_set;
12249 FILE *temp = tng_data->input_file;
12250 int64_t curr_file_pos;
12252 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12253 TNG_ASSERT(first_frame >= 0, "TNG library: first_frame must be >= 0.");
12254 TNG_ASSERT(n_frames >= 0, "TNG library: n_frames must be >= 0.");
12256 frame_set = &tng_data->current_trajectory_frame_set;
12258 curr_file_pos = ftello(tng_data->output_file);
12260 if(curr_file_pos <= 10)
12262 tng_file_headers_write(tng_data, TNG_USE_HASH);
12265 /* Set pointer to previous frame set to the one that was loaded
12267 * FIXME: This is a bit risky. If they are not added in order
12268 * it will be wrong. */
12269 if(tng_data->n_trajectory_frame_sets)
12271 frame_set->prev_frame_set_file_pos =
12272 tng_data->last_trajectory_frame_set_output_file_pos;
12275 frame_set->next_frame_set_file_pos = -1;
12277 tng_data->current_trajectory_frame_set_output_file_pos =
12278 ftello(tng_data->output_file);
12280 tng_data->n_trajectory_frame_sets++;
12282 /* Set the medium range pointers */
12283 if(tng_data->n_trajectory_frame_sets == tng_data->medium_stride_length + 1)
12285 frame_set->medium_stride_prev_frame_set_file_pos =
12286 tng_data->first_trajectory_frame_set_output_file_pos;
12288 else if(tng_data->n_trajectory_frame_sets > tng_data->medium_stride_length + 1)
12290 /* FIXME: Currently only working if the previous frame set has its
12291 * medium stride pointer already set. This might need some fixing. */
12292 if(frame_set->medium_stride_prev_frame_set_file_pos != -1 &&
12293 frame_set->medium_stride_prev_frame_set_file_pos != 0)
12295 tng_block_init(&block);
12296 tng_data->input_file = tng_data->output_file;
12298 curr_file_pos = ftello(tng_data->output_file);
12299 fseeko(tng_data->output_file,
12300 frame_set->medium_stride_prev_frame_set_file_pos,
12303 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
12305 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
12306 __FILE__, __LINE__);
12307 tng_data->input_file = temp;
12308 tng_block_destroy(&block);
12309 return(TNG_CRITICAL);
12312 /* Read the next frame set from the previous frame set and one
12313 * medium stride step back */
12314 fseeko(tng_data->output_file, block->block_contents_size - (6 *
12315 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
12316 if(fread(&frame_set->medium_stride_prev_frame_set_file_pos,
12317 sizeof(frame_set->medium_stride_prev_frame_set_file_pos),
12318 1, tng_data->output_file) == 0)
12320 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
12321 tng_data->input_file = temp;
12322 tng_block_destroy(&block);
12323 return(TNG_CRITICAL);
12326 if(tng_data->input_endianness_swap_func_64)
12328 if(tng_data->input_endianness_swap_func_64(tng_data,
12329 &frame_set->medium_stride_prev_frame_set_file_pos)
12332 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
12333 __FILE__, __LINE__);
12337 tng_block_destroy(&block);
12339 /* Set the long range pointers */
12340 if(tng_data->n_trajectory_frame_sets == tng_data->long_stride_length + 1)
12342 frame_set->long_stride_prev_frame_set_file_pos =
12343 tng_data->first_trajectory_frame_set_output_file_pos;
12345 else if(tng_data->n_trajectory_frame_sets > tng_data->medium_stride_length + 1)
12347 /* FIXME: Currently only working if the previous frame set has its
12348 * long stride pointer already set. This might need some fixing. */
12349 if(frame_set->long_stride_prev_frame_set_file_pos != -1 &&
12350 frame_set->long_stride_prev_frame_set_file_pos != 0)
12352 tng_block_init(&block);
12353 tng_data->input_file = tng_data->output_file;
12355 fseeko(tng_data->output_file,
12356 frame_set->long_stride_prev_frame_set_file_pos,
12359 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
12361 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
12362 __FILE__, __LINE__);
12363 tng_data->input_file = temp;
12364 tng_block_destroy(&block);
12365 return(TNG_CRITICAL);
12368 /* Read the next frame set from the previous frame set and one
12369 * long stride step back */
12370 fseeko(tng_data->output_file, block->block_contents_size - (6 *
12371 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
12373 tng_block_destroy(&block);
12375 if(fread(&frame_set->long_stride_prev_frame_set_file_pos,
12376 sizeof(frame_set->long_stride_prev_frame_set_file_pos),
12377 1, tng_data->output_file) == 0)
12379 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
12380 tng_data->input_file = temp;
12381 return(TNG_CRITICAL);
12384 if(tng_data->input_endianness_swap_func_64)
12386 if(tng_data->input_endianness_swap_func_64(tng_data,
12387 &frame_set->long_stride_prev_frame_set_file_pos)
12390 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
12391 __FILE__, __LINE__);
12398 tng_data->input_file = temp;
12399 fseeko(tng_data->output_file, curr_file_pos, SEEK_SET);
12403 frame_set->first_frame = first_frame;
12404 frame_set->n_frames = n_frames;
12405 frame_set->n_written_frames = 0;
12406 frame_set->n_unwritten_frames = 0;
12407 frame_set->first_frame_time = -1;
12409 if(tng_data->first_trajectory_frame_set_output_file_pos == -1 ||
12410 tng_data->first_trajectory_frame_set_output_file_pos == 0)
12412 tng_data->first_trajectory_frame_set_output_file_pos =
12413 tng_data->current_trajectory_frame_set_output_file_pos;
12415 /* FIXME: Should check the frame number instead of the file_pos,
12416 * in case frame sets are not in order */
12417 if(tng_data->last_trajectory_frame_set_output_file_pos == -1 ||
12418 tng_data->last_trajectory_frame_set_output_file_pos == 0 ||
12419 tng_data->last_trajectory_frame_set_output_file_pos <
12420 tng_data->current_trajectory_frame_set_output_file_pos)
12422 tng_data->last_trajectory_frame_set_output_file_pos =
12423 tng_data->current_trajectory_frame_set_output_file_pos;
12426 return(TNG_SUCCESS);
12429 tng_function_status DECLSPECDLLEXPORT tng_frame_set_with_time_new
12430 (const tng_trajectory_t tng_data,
12431 const int64_t first_frame,
12432 const int64_t n_frames,
12433 const double first_frame_time)
12435 tng_function_status stat;
12437 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12438 TNG_ASSERT(first_frame >= 0, "TNG library: first_frame must be >= 0.");
12439 TNG_ASSERT(n_frames >= 0, "TNG library: n_frames must be >= 0.");
12440 TNG_ASSERT(first_frame_time >= 0, "TNG library: first_frame_time must be >= 0.");
12443 stat = tng_frame_set_new(tng_data, first_frame, n_frames);
12444 if(stat != TNG_SUCCESS)
12448 stat = tng_frame_set_first_frame_time_set(tng_data, first_frame_time);
12453 tng_function_status DECLSPECDLLEXPORT tng_frame_set_first_frame_time_set
12454 (const tng_trajectory_t tng_data,
12455 const double first_frame_time)
12457 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12458 TNG_ASSERT(first_frame_time >= 0, "TNG library: first_frame_time must be >= 0.");
12460 tng_data->current_trajectory_frame_set.first_frame_time = first_frame_time;
12462 return(TNG_SUCCESS);
12465 tng_function_status DECLSPECDLLEXPORT tng_first_frame_nr_of_next_frame_set_get
12466 (const tng_trajectory_t tng_data,
12469 int64_t file_pos, next_frame_set_file_pos;
12470 tng_gen_block_t block;
12471 tng_function_status stat;
12473 tng_trajectory_frame_set_t frame_set;
12475 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12476 TNG_ASSERT(tng_data->input_file, "TNG library: An input file must be open to find the next frame set");
12477 TNG_ASSERT(frame, "TNG library: frame must not be a NULL pointer");
12479 file_pos = ftello(tng_data->input_file);
12481 if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
12483 next_frame_set_file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
12487 frame_set = &tng_data->current_trajectory_frame_set;
12488 next_frame_set_file_pos = frame_set->next_frame_set_file_pos;
12491 if(next_frame_set_file_pos <= 0)
12493 return(TNG_FAILURE);
12496 fseeko(tng_data->input_file, next_frame_set_file_pos, SEEK_SET);
12497 /* Read block headers first to see that a frame set block is found. */
12498 tng_block_init(&block);
12499 stat = tng_block_header_read(tng_data, block);
12500 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12502 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12503 file_pos, __FILE__, __LINE__);
12504 return(TNG_CRITICAL);
12506 /* if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
12508 tng_block_read_next(tng_data, block, TNG_USE_HASH);
12510 tng_block_destroy(&block);
12512 if(fread(frame, sizeof(int64_t), 1, tng_data->input_file) == 0)
12514 fprintf(stderr, "TNG library: Cannot read first frame of next frame set. %s: %d\n",
12515 __FILE__, __LINE__);
12516 return(TNG_CRITICAL);
12518 fseeko(tng_data->input_file, file_pos, SEEK_SET);
12520 return(TNG_SUCCESS);
12523 static tng_function_status tng_gen_data_block_add
12524 (const tng_trajectory_t tng_data,
12526 const tng_bool is_particle_data,
12527 const char *block_name,
12528 const char datatype,
12529 const char block_type_flag,
12531 const int64_t n_values_per_frame,
12532 int64_t stride_length,
12533 const int64_t num_first_particle,
12534 const int64_t n_particles,
12535 const int64_t codec_id,
12540 int64_t tot_n_particles, n_frames_div;
12541 char ***first_dim_values, **second_dim_values;
12542 tng_trajectory_frame_set_t frame_set;
12544 char *new_data_c=new_data;
12545 tng_function_status stat;
12547 frame_set = &tng_data->current_trajectory_frame_set;
12549 if(stride_length <= 0)
12554 if(is_particle_data)
12556 stat = tng_particle_data_find(tng_data, id, &data);
12560 stat = tng_data_find(tng_data, id, &data);
12562 /* If the block does not exist, create it */
12563 if(stat != TNG_SUCCESS)
12565 if(is_particle_data)
12567 stat = tng_particle_data_block_create(tng_data, block_type_flag);
12571 stat = tng_data_block_create(tng_data, block_type_flag);
12574 if(stat != TNG_SUCCESS)
12576 fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
12577 __FILE__, __LINE__);
12578 return(TNG_CRITICAL);
12580 if(is_particle_data)
12582 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
12584 data = &frame_set->tr_particle_data[frame_set->
12585 n_particle_data_blocks - 1];
12589 data = &tng_data->non_tr_particle_data[tng_data->
12590 n_particle_data_blocks - 1];
12595 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
12597 data = &frame_set->tr_data[frame_set->n_data_blocks - 1];
12601 data = &tng_data->non_tr_data[tng_data->n_data_blocks - 1];
12604 data->block_id = id;
12606 data->block_name = malloc(strlen(block_name) + 1);
12607 if(!data->block_name)
12609 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n",
12610 (unsigned int)strlen(block_name)+1, __FILE__, __LINE__);
12611 return(TNG_CRITICAL);
12613 strncpy(data->block_name, block_name, strlen(block_name) + 1);
12616 /* FIXME: Memory leak from strings. */
12618 data->last_retrieved_frame = -1;
12621 data->datatype = datatype;
12622 data->stride_length = tng_max_i64(stride_length, 1);
12623 data->n_values_per_frame = n_values_per_frame;
12624 data->n_frames = n_frames;
12625 if(is_particle_data)
12627 data->dependency = TNG_PARTICLE_DEPENDENT;
12631 data->dependency = 0;
12633 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
12635 frame_set->n_frames == n_frames ||
12636 stride_length > 1))
12638 data->dependency += TNG_FRAME_DEPENDENT;
12640 data->codec_id = codec_id;
12641 data->compression_multiplier = 1.0;
12642 /* FIXME: This can cause problems. */
12643 data->first_frame_with_data = frame_set->first_frame;
12645 if(is_particle_data)
12647 if(block_type_flag == TNG_TRAJECTORY_BLOCK && tng_data->var_num_atoms_flag)
12649 tot_n_particles = frame_set->n_particles;
12653 tot_n_particles = tng_data->n_particles;
12656 /* This is just to keep the compiler happy - avoid it considering tot_n_particles
12657 * uninitialized. */
12660 tot_n_particles = 0;
12663 /* If data values are supplied add that data to the data block. */
12666 /* Allocate memory */
12667 if(is_particle_data)
12669 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
12670 stride_length, tot_n_particles,
12671 n_values_per_frame);
12675 stat = tng_allocate_data_mem(tng_data, data, n_frames, stride_length,
12676 n_values_per_frame);
12678 if(stat != TNG_SUCCESS)
12680 fprintf(stderr, "TNG library: Cannot allocate particle data memory. %s: %d\n",
12681 __FILE__, __LINE__);
12682 return(TNG_CRITICAL);
12685 if(n_frames > frame_set->n_unwritten_frames)
12687 frame_set->n_unwritten_frames = n_frames;
12690 n_frames_div = (n_frames % stride_length) ?
12691 n_frames / stride_length + 1:
12692 n_frames / stride_length;
12694 if(datatype == TNG_CHAR_DATA)
12696 if(is_particle_data)
12698 for(i = 0; i < n_frames_div; i++)
12700 first_dim_values = data->strings[i];
12701 for(j = num_first_particle; j < num_first_particle + n_particles;
12704 second_dim_values = first_dim_values[j];
12705 for(k = 0; k < n_values_per_frame; k++)
12707 len = tng_min_size(strlen(new_data_c) + 1,
12709 if(second_dim_values[k])
12711 free(second_dim_values[k]);
12713 second_dim_values[k] = malloc(len);
12714 if(!second_dim_values[k])
12716 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
12717 len, __FILE__, __LINE__);
12718 return(TNG_CRITICAL);
12720 strncpy(second_dim_values[k],
12729 for(i = 0; i < n_frames_div; i++)
12731 second_dim_values = data->strings[0][i];
12732 for(j = 0; j < n_values_per_frame; j++)
12734 len = tng_min_size(strlen(new_data_c) + 1,
12736 if(second_dim_values[j])
12738 free(second_dim_values[j]);
12740 second_dim_values[j] = malloc(len);
12741 if(!second_dim_values[j])
12743 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
12744 len, __FILE__, __LINE__);
12745 return(TNG_CRITICAL);
12747 strncpy(second_dim_values[j],
12759 size = sizeof(int64_t);
12761 case TNG_FLOAT_DATA:
12762 size = sizeof(float);
12764 case TNG_DOUBLE_DATA:
12766 size = sizeof(double);
12769 if(is_particle_data)
12771 memcpy(data->values, new_data, size * n_frames_div *
12772 n_particles * n_values_per_frame);
12776 memcpy(data->values, new_data, size * n_frames_div *
12777 n_values_per_frame);
12782 return(TNG_SUCCESS);
12785 tng_function_status DECLSPECDLLEXPORT tng_data_block_add
12786 (const tng_trajectory_t tng_data,
12788 const char *block_name,
12789 const char datatype,
12790 const char block_type_flag,
12792 const int64_t n_values_per_frame,
12793 int64_t stride_length,
12794 const int64_t codec_id,
12797 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12798 TNG_ASSERT(block_name, "TNG library: block_name must not be a NULL pointer.");
12799 TNG_ASSERT(n_values_per_frame > 0, "TNG library: n_values_per_frame must be a positive integer.");
12801 return(tng_gen_data_block_add(tng_data, id, TNG_FALSE, block_name, datatype,
12802 block_type_flag, n_frames, n_values_per_frame,
12803 stride_length, 0, 0, codec_id, new_data));
12806 tng_function_status DECLSPECDLLEXPORT tng_particle_data_block_add
12807 (const tng_trajectory_t tng_data,
12809 const char *block_name,
12810 const char datatype,
12811 const char block_type_flag,
12813 const int64_t n_values_per_frame,
12814 int64_t stride_length,
12815 const int64_t num_first_particle,
12816 const int64_t n_particles,
12817 const int64_t codec_id,
12820 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12821 TNG_ASSERT(block_name, "TNG library: block_name mustnot be a NULL pointer.");
12822 TNG_ASSERT(n_values_per_frame > 0, "TNG library: n_values_per_frame must be a positive integer.");
12823 TNG_ASSERT(num_first_particle >= 0, "TNG library: num_first_particle must be >= 0.");
12824 TNG_ASSERT(n_particles >= 0, "TNG library: n_particles must be >= 0.");
12826 return(tng_gen_data_block_add(tng_data, id, TNG_TRUE, block_name, datatype,
12827 block_type_flag, n_frames, n_values_per_frame,
12828 stride_length, num_first_particle, n_particles,
12829 codec_id, new_data));
12832 tng_function_status DECLSPECDLLEXPORT tng_data_block_name_get
12833 (const tng_trajectory_t tng_data,
12834 const int64_t block_id,
12839 tng_trajectory_frame_set_t frame_set;
12840 tng_function_status stat;
12842 int block_type = -1;
12844 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12845 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
12847 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
12849 data = &tng_data->non_tr_particle_data[i];
12850 if(data->block_id == block_id)
12852 strncpy(name, data->block_name, max_len);
12853 name[max_len - 1] = '\0';
12854 return(TNG_SUCCESS);
12857 for(i = 0; i < tng_data->n_data_blocks; i++)
12859 data = &tng_data->non_tr_data[i];
12860 if(data->block_id == block_id)
12862 strncpy(name, data->block_name, max_len);
12863 name[max_len - 1] = '\0';
12864 return(TNG_SUCCESS);
12868 frame_set = &tng_data->current_trajectory_frame_set;
12870 stat = tng_particle_data_find(tng_data, block_id, &data);
12871 if(stat == TNG_SUCCESS)
12873 block_type = TNG_PARTICLE_BLOCK_DATA;
12877 stat = tng_data_find(tng_data, block_id, &data);
12878 if(stat == TNG_SUCCESS)
12880 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
12884 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
12885 if(stat != TNG_SUCCESS)
12889 stat = tng_particle_data_find(tng_data, block_id, &data);
12890 if(stat == TNG_SUCCESS)
12892 block_type = TNG_PARTICLE_BLOCK_DATA;
12896 stat = tng_data_find(tng_data, block_id, &data);
12897 if(stat == TNG_SUCCESS)
12899 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
12904 if(block_type == TNG_PARTICLE_BLOCK_DATA)
12906 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
12908 data = &frame_set->tr_particle_data[i];
12909 if(data->block_id == block_id)
12911 strncpy(name, data->block_name, max_len);
12912 name[max_len - 1] = '\0';
12913 return(TNG_SUCCESS);
12917 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
12919 for(i = 0; i < frame_set->n_data_blocks; i++)
12921 data = &frame_set->tr_data[i];
12922 if(data->block_id == block_id)
12924 strncpy(name, data->block_name, max_len);
12925 name[max_len - 1] = '\0';
12926 return(TNG_SUCCESS);
12931 return(TNG_FAILURE);
12934 tng_function_status DECLSPECDLLEXPORT tng_data_block_dependency_get
12935 (const tng_trajectory_t tng_data,
12936 const int64_t block_id,
12937 int *block_dependency)
12940 tng_function_status stat;
12943 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12944 TNG_ASSERT(block_dependency, "TNG library: block_dependency must not be a NULL pointer.");
12946 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
12948 data = &tng_data->non_tr_particle_data[i];
12949 if(data->block_id == block_id)
12951 *block_dependency = TNG_PARTICLE_DEPENDENT;
12952 return(TNG_SUCCESS);
12955 for(i = 0; i < tng_data->n_data_blocks; i++)
12957 data = &tng_data->non_tr_data[i];
12958 if(data->block_id == block_id)
12960 *block_dependency = 0;
12961 return(TNG_SUCCESS);
12965 stat = tng_particle_data_find(tng_data, block_id, &data);
12966 if(stat == TNG_SUCCESS)
12968 *block_dependency = TNG_PARTICLE_DEPENDENT + TNG_FRAME_DEPENDENT;
12969 return(TNG_SUCCESS);
12973 stat = tng_data_find(tng_data, block_id, &data);
12974 if(stat == TNG_SUCCESS)
12976 *block_dependency = TNG_FRAME_DEPENDENT;
12977 return(TNG_SUCCESS);
12981 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
12982 if(stat != TNG_SUCCESS)
12986 stat = tng_particle_data_find(tng_data, block_id, &data);
12987 if(stat == TNG_SUCCESS)
12989 *block_dependency = TNG_PARTICLE_DEPENDENT + TNG_FRAME_DEPENDENT;
12990 return(TNG_SUCCESS);
12994 stat = tng_data_find(tng_data, block_id, &data);
12995 if(stat == TNG_SUCCESS)
12997 *block_dependency = TNG_FRAME_DEPENDENT;
12998 return(TNG_SUCCESS);
13004 return(TNG_FAILURE);
13007 tng_function_status DECLSPECDLLEXPORT tng_data_block_num_values_per_frame_get
13008 (const tng_trajectory_t tng_data,
13009 const int64_t block_id,
13010 int64_t *n_values_per_frame)
13013 tng_function_status stat;
13016 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13017 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
13019 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
13021 data = &tng_data->non_tr_particle_data[i];
13022 if(data->block_id == block_id)
13024 *n_values_per_frame = data->n_values_per_frame;
13025 return(TNG_SUCCESS);
13028 for(i = 0; i < tng_data->n_data_blocks; i++)
13030 data = &tng_data->non_tr_data[i];
13031 if(data->block_id == block_id)
13033 *n_values_per_frame = data->n_values_per_frame;
13034 return(TNG_SUCCESS);
13038 stat = tng_particle_data_find(tng_data, block_id, &data);
13039 if(stat == TNG_SUCCESS)
13041 *n_values_per_frame = data->n_values_per_frame;
13042 return(TNG_SUCCESS);
13046 stat = tng_data_find(tng_data, block_id, &data);
13047 if(stat == TNG_SUCCESS)
13049 *n_values_per_frame = data->n_values_per_frame;
13050 return(TNG_SUCCESS);
13054 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
13055 if(stat != TNG_SUCCESS)
13059 stat = tng_particle_data_find(tng_data, block_id, &data);
13060 if(stat == TNG_SUCCESS)
13062 *n_values_per_frame = data->n_values_per_frame;
13063 return(TNG_SUCCESS);
13067 stat = tng_data_find(tng_data, block_id, &data);
13068 if(stat == TNG_SUCCESS)
13070 *n_values_per_frame = data->n_values_per_frame;
13071 return(TNG_SUCCESS);
13077 return(TNG_FAILURE);
13080 tng_function_status DECLSPECDLLEXPORT tng_frame_set_n_frames_of_data_block_get
13081 (const tng_trajectory_t tng_data,
13082 const int64_t block_id,
13085 tng_gen_block_t block;
13086 tng_function_status stat;
13087 char datatype, dependency, sparse_data;
13088 int64_t n_values, codec_id, first_frame_with_data, stride_length, curr_n_frames;
13089 int64_t num_first_particle, block_n_particles;
13091 md5_state_t md5_state;
13092 int found = TNG_FALSE;
13094 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13096 tng_block_init(&block);
13098 stat = tng_block_header_read(tng_data, block);
13099 /* If the block header could not be read the reading position might not have been
13100 * at the start of a block. Try again from the file position of the current frame
13102 if(stat != TNG_SUCCESS)
13104 fseeko(tng_data->input_file, tng_data->current_trajectory_frame_set_input_file_pos, SEEK_SET);
13105 stat = tng_block_header_read(tng_data, block);
13106 if(stat != TNG_SUCCESS)
13108 tng_block_destroy(&block);
13112 if(block->id == TNG_TRAJECTORY_FRAME_SET)
13114 stat = tng_block_read_next(tng_data, block, TNG_SKIP_HASH);
13115 if(stat != TNG_SUCCESS)
13117 tng_block_destroy(&block);
13120 stat = tng_block_header_read(tng_data, block);
13122 while(stat == TNG_SUCCESS && block->id != TNG_TRAJECTORY_FRAME_SET && found == TNG_FALSE)
13124 if(block->id == block_id)
13126 stat = tng_data_block_meta_information_read(tng_data, &datatype,
13127 &dependency, &sparse_data,
13128 &n_values, &codec_id,
13129 &first_frame_with_data,
13130 &stride_length, &curr_n_frames,
13131 &num_first_particle,
13132 &block_n_particles,
13133 &multiplier, TNG_SKIP_HASH,
13135 if(stat == TNG_SUCCESS)
13142 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
13143 stat = tng_block_header_read(tng_data, block);
13146 if(found == TNG_TRUE)
13148 *n_frames = (tng_data->current_trajectory_frame_set.n_frames -
13149 (tng_data->current_trajectory_frame_set.first_frame - first_frame_with_data)) / stride_length;
13151 else if(stat == TNG_SUCCESS)
13156 tng_block_destroy(&block);
13161 static tng_function_status tng_frame_gen_data_write
13162 (const tng_trajectory_t tng_data,
13163 const int64_t frame_nr,
13164 const int64_t block_id,
13165 const tng_bool is_particle_data,
13166 const int64_t val_first_particle,
13167 const int64_t val_n_particles,
13168 const void *values,
13169 const char hash_mode)
13171 int64_t header_pos, file_pos, tot_n_particles;
13172 int64_t output_file_len, n_values_per_frame, size, contents_size;
13173 int64_t header_size, temp_first, temp_last;
13174 int64_t mapping_block_end_pos, num_first_particle, block_n_particles;
13175 int64_t i, last_frame, temp_current, write_n_particles;
13176 tng_gen_block_t block;
13177 tng_trajectory_frame_set_t frame_set;
13178 FILE *temp = tng_data->input_file;
13179 struct tng_data data;
13180 tng_function_status stat;
13181 tng_particle_mapping_t mapping;
13182 char dependency, sparse_data, datatype;
13185 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
13187 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
13188 __FILE__, __LINE__);
13189 return(TNG_CRITICAL);
13192 temp_first = tng_data->first_trajectory_frame_set_input_file_pos;
13193 temp_last = tng_data->last_trajectory_frame_set_input_file_pos;
13194 temp_current = tng_data->current_trajectory_frame_set_input_file_pos;
13195 tng_data->first_trajectory_frame_set_input_file_pos =
13196 tng_data->first_trajectory_frame_set_output_file_pos;
13197 tng_data->last_trajectory_frame_set_input_file_pos =
13198 tng_data->last_trajectory_frame_set_output_file_pos;
13199 tng_data->current_trajectory_frame_set_input_file_pos =
13200 tng_data->current_trajectory_frame_set_output_file_pos;
13202 tng_data->input_file = tng_data->output_file;
13204 stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
13206 frame_set = &tng_data->current_trajectory_frame_set;
13208 if(stat != TNG_SUCCESS)
13210 last_frame = frame_set->first_frame +
13211 frame_set->n_frames - 1;
13212 /* If the wanted frame would be in the frame set after the last
13213 * frame set create a new frame set. */
13214 if(stat == TNG_FAILURE &&
13215 last_frame < frame_nr)
13216 /* (last_frame < frame_nr &&
13217 tng_data->current_trajectory_frame_set.first_frame +
13218 tng_data->frame_set_n_frames >= frame_nr))*/
13220 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
13222 last_frame = frame_nr - 1;
13224 tng_frame_set_new(tng_data,
13226 tng_data->frame_set_n_frames);
13227 file_pos = ftello(tng_data->output_file);
13228 fseeko(tng_data->output_file, 0, SEEK_END);
13229 output_file_len = ftello(tng_data->output_file);
13230 fseeko(tng_data->output_file, file_pos, SEEK_SET);
13232 /* Read mapping blocks from the last frame set */
13233 tng_block_init(&block);
13235 stat = tng_block_header_read(tng_data, block);
13236 while(file_pos < output_file_len &&
13237 stat != TNG_CRITICAL &&
13238 block->id != TNG_TRAJECTORY_FRAME_SET &&
13241 if(block->id == TNG_PARTICLE_MAPPING)
13243 tng_trajectory_mapping_block_read(tng_data, block,
13248 fseeko(tng_data->output_file, block->block_contents_size,
13251 file_pos = ftello(tng_data->output_file);
13252 if(file_pos < output_file_len)
13254 stat = tng_block_header_read(tng_data, block);
13258 tng_block_destroy(&block);
13259 /* Write the frame set to disk */
13260 if(tng_frame_set_write(tng_data, hash_mode) != TNG_SUCCESS)
13262 fprintf(stderr, "TNG library: Error writing frame set. %s: %d\n", __FILE__, __LINE__);
13263 return(TNG_CRITICAL);
13268 tng_data->input_file = temp;
13269 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13270 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13271 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13276 tng_block_init(&block);
13278 file_pos = tng_data->current_trajectory_frame_set_output_file_pos;
13280 fseeko(tng_data->output_file, 0, SEEK_END);
13281 output_file_len = ftello(tng_data->output_file);
13282 fseeko(tng_data->output_file, file_pos, SEEK_SET);
13284 /* Read past the frame set block first */
13285 stat = tng_block_header_read(tng_data, block);
13286 if(stat == TNG_CRITICAL)
13288 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
13289 file_pos, __FILE__, __LINE__);
13290 tng_block_destroy(&block);
13291 tng_data->input_file = temp;
13293 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13294 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13295 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13298 fseeko(tng_data->output_file, block->block_contents_size,
13301 if(is_particle_data == TNG_TRUE)
13303 if(tng_data->var_num_atoms_flag)
13305 tot_n_particles = frame_set->n_particles;
13309 tot_n_particles = tng_data->n_particles;
13312 if(val_n_particles < tot_n_particles)
13314 mapping_block_end_pos = -1;
13315 /* Read all mapping blocks to find the right place to put the data */
13316 stat = tng_block_header_read(tng_data, block);
13317 while(file_pos < output_file_len &&
13318 stat != TNG_CRITICAL &&
13319 block->id != TNG_TRAJECTORY_FRAME_SET &&
13322 if(block->id == TNG_PARTICLE_MAPPING)
13324 tng_trajectory_mapping_block_read(tng_data, block, hash_mode);
13328 fseeko(tng_data->output_file, block->block_contents_size,
13331 file_pos = ftello(tng_data->output_file);
13332 if(block->id == TNG_PARTICLE_MAPPING)
13334 mapping = &frame_set->mappings[frame_set->n_mapping_blocks - 1];
13335 if(val_first_particle >= mapping->num_first_particle &&
13336 val_first_particle < mapping->num_first_particle +
13337 mapping->n_particles &&
13338 val_first_particle + val_n_particles <=
13339 mapping->num_first_particle + mapping->n_particles)
13341 mapping_block_end_pos = file_pos;
13344 if(file_pos < output_file_len)
13346 stat = tng_block_header_read(tng_data, block);
13349 if(stat == TNG_CRITICAL)
13351 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
13352 file_pos, __FILE__, __LINE__);
13353 tng_block_destroy(&block);
13354 tng_data->input_file = temp;
13356 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13357 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13358 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13361 if(mapping_block_end_pos < 0)
13363 tng_block_destroy(&block);
13364 tng_data->input_file = temp;
13366 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13367 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13368 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13369 return(TNG_FAILURE);
13371 fseeko(tng_data->output_file, mapping_block_end_pos, SEEK_SET);
13375 /* Read all block headers until next frame set block or
13376 * until the wanted block id is found */
13377 stat = tng_block_header_read(tng_data, block);
13378 while(file_pos < output_file_len &&
13379 stat != TNG_CRITICAL &&
13380 block->id != block_id &&
13381 (is_particle_data != TNG_TRUE || block->id != TNG_PARTICLE_MAPPING) &&
13382 block->id != TNG_TRAJECTORY_FRAME_SET &&
13385 fseeko(tng_data->output_file, block->block_contents_size, SEEK_CUR);
13386 file_pos = ftello(tng_data->output_file);
13387 if(file_pos < output_file_len)
13389 stat = tng_block_header_read(tng_data, block);
13392 if(stat == TNG_CRITICAL)
13394 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
13395 file_pos, __FILE__, __LINE__);
13396 tng_block_destroy(&block);
13397 tng_data->input_file = temp;
13398 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13399 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13400 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13404 contents_size = block->block_contents_size;
13405 header_size = block->header_contents_size;
13407 header_pos = ftello(tng_data->output_file) - header_size;
13408 frame_set = &tng_data->current_trajectory_frame_set;
13410 if(tng_file_input_numerical(tng_data, &datatype,
13412 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13414 tng_block_destroy(&block);
13415 return(TNG_CRITICAL);
13417 if(tng_file_input_numerical(tng_data, &dependency,
13418 sizeof(dependency),
13419 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13421 tng_block_destroy(&block);
13422 return(TNG_CRITICAL);
13424 data.datatype = datatype;
13426 if(!(dependency & TNG_FRAME_DEPENDENT) ||
13427 (is_particle_data == TNG_FALSE && dependency & TNG_PARTICLE_DEPENDENT) ||
13428 (is_particle_data == TNG_TRUE && !(dependency & TNG_PARTICLE_DEPENDENT)))
13430 tng_block_destroy(&block);
13431 tng_data->input_file = temp;
13433 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13434 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13435 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13436 return(TNG_FAILURE);
13439 if(tng_file_input_numerical(tng_data, &sparse_data,
13440 sizeof(sparse_data),
13441 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13443 tng_block_destroy(&block);
13444 return(TNG_CRITICAL);
13447 if(tng_file_input_numerical(tng_data, &data.n_values_per_frame,
13448 sizeof(data.n_values_per_frame),
13449 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13451 tng_block_destroy(&block);
13452 return(TNG_CRITICAL);
13455 if(tng_file_input_numerical(tng_data, &data.codec_id,
13456 sizeof(data.codec_id),
13457 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13459 tng_block_destroy(&block);
13460 return(TNG_CRITICAL);
13463 if(data.codec_id != TNG_UNCOMPRESSED)
13465 if(tng_file_input_numerical(tng_data, &data.compression_multiplier,
13466 sizeof(data.compression_multiplier),
13467 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13469 tng_block_destroy(&block);
13470 return(TNG_CRITICAL);
13475 data.compression_multiplier = 1;
13480 if(tng_file_input_numerical(tng_data, &data.first_frame_with_data,
13481 sizeof(data.first_frame_with_data),
13482 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13484 tng_block_destroy(&block);
13485 return(TNG_CRITICAL);
13488 if(tng_file_input_numerical(tng_data, &data.stride_length,
13489 sizeof(data.stride_length),
13490 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13492 tng_block_destroy(&block);
13493 return(TNG_CRITICAL);
13498 data.first_frame_with_data = 0;
13499 data.stride_length = 1;
13501 data.n_frames = tng_data->current_trajectory_frame_set.n_frames;
13503 if(is_particle_data == TNG_TRUE)
13505 if(tng_file_input_numerical(tng_data, &num_first_particle,
13506 sizeof(num_first_particle),
13507 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13509 tng_block_destroy(&block);
13510 return(TNG_CRITICAL);
13513 if(tng_file_input_numerical(tng_data, &block_n_particles,
13514 sizeof(block_n_particles),
13515 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13517 tng_block_destroy(&block);
13518 return(TNG_CRITICAL);
13522 tng_data->input_file = temp;
13524 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13525 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13526 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13528 switch(data.datatype)
13530 case(TNG_INT_DATA):
13531 size = sizeof(int64_t);
13533 case(TNG_FLOAT_DATA):
13534 size = sizeof(float);
13536 case(TNG_DOUBLE_DATA):
13537 size = sizeof(double);
13540 fprintf(stderr, "TNG library: Cannot calculate writing locations. %s: %d.\n", __FILE__,
13542 tng_block_destroy(&block);
13543 return(TNG_FAILURE);
13546 n_values_per_frame = data.n_values_per_frame;
13548 file_pos = (frame_nr - tng_max_i64(frame_set->first_frame,
13549 data.first_frame_with_data)) /
13550 data.stride_length;
13551 if(is_particle_data == TNG_TRUE)
13553 file_pos *= block_n_particles * size * n_values_per_frame;
13557 file_pos *= size * n_values_per_frame;
13560 if(file_pos > contents_size)
13562 fprintf(stderr, "TNG library: Attempting to write outside the block. %s: %d\n", __FILE__,
13564 tng_block_destroy(&block);
13565 return(TNG_FAILURE);
13568 fseeko(tng_data->output_file, file_pos, SEEK_CUR);
13570 if(is_particle_data == TNG_TRUE)
13572 write_n_particles = val_n_particles;
13576 write_n_particles = 1;
13579 /* If the endianness is not big endian the data needs to be swapped */
13580 if((data.datatype == TNG_INT_DATA ||
13581 data.datatype == TNG_DOUBLE_DATA) &&
13582 tng_data->output_endianness_swap_func_64)
13584 copy = malloc(write_n_particles * n_values_per_frame * size);
13585 memcpy(copy, values, write_n_particles * n_values_per_frame * size);
13586 for(i = 0; i < write_n_particles * n_values_per_frame; i++)
13588 if(tng_data->output_endianness_swap_func_64(tng_data,
13589 (int64_t *) copy+i)
13592 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13593 __FILE__, __LINE__);
13596 fwrite(copy, write_n_particles * n_values_per_frame, size,
13597 tng_data->output_file);
13600 else if(data.datatype == TNG_FLOAT_DATA &&
13601 tng_data->output_endianness_swap_func_32)
13603 copy = malloc(write_n_particles * n_values_per_frame * size);
13604 memcpy(copy, values, write_n_particles * n_values_per_frame * size);
13605 for(i = 0; i < write_n_particles * n_values_per_frame; i++)
13607 if(tng_data->output_endianness_swap_func_32(tng_data,
13608 (int32_t *) copy+i)
13611 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13612 __FILE__, __LINE__);
13615 fwrite(copy, write_n_particles * n_values_per_frame, size,
13616 tng_data->output_file);
13622 fwrite(values, write_n_particles * n_values_per_frame, size, tng_data->output_file);
13625 fflush(tng_data->output_file);
13627 /* Update the number of written frames in the frame set. */
13628 if(frame_nr - frame_set->first_frame + 1 > frame_set->n_written_frames)
13630 frame_set->n_written_frames = frame_nr - frame_set->first_frame + 1;
13633 /* If the last frame has been written update the hash */
13634 if(hash_mode == TNG_USE_HASH && (frame_nr + data.stride_length -
13635 data.first_frame_with_data) >=
13636 frame_set->n_frames)
13638 tng_md5_hash_update(tng_data, block, header_pos, header_pos +
13642 tng_block_destroy(&block);
13644 return(TNG_SUCCESS);
13647 tng_function_status DECLSPECDLLEXPORT tng_frame_data_write
13648 (const tng_trajectory_t tng_data,
13649 const int64_t frame_nr,
13650 const int64_t block_id,
13651 const void *values,
13652 const char hash_mode)
13654 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13655 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
13656 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer.");
13658 /* This is now just calling the generic data writing function. This
13659 * function must keep its signature to let the API be backwards
13661 return(tng_frame_gen_data_write(tng_data, frame_nr, block_id,
13662 TNG_FALSE, 0, 0, values, hash_mode));
13665 tng_function_status DECLSPECDLLEXPORT tng_frame_particle_data_write
13666 (const tng_trajectory_t tng_data,
13667 const int64_t frame_nr,
13668 const int64_t block_id,
13669 const int64_t val_first_particle,
13670 const int64_t val_n_particles,
13671 const void *values,
13672 const char hash_mode)
13674 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13675 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
13676 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer.");
13677 TNG_ASSERT(val_first_particle >= 0, "TNG library: val_first_particle must be >= 0.");
13678 TNG_ASSERT(val_n_particles >= 0, "TNG library: val_n_particles must be >= 0.");
13680 /* This is now just calling the generic data writing function. This
13681 * function must keep its signature to let the API be backwards
13683 return(tng_frame_gen_data_write(tng_data, frame_nr, block_id,
13684 TNG_TRUE, val_first_particle, val_n_particles,
13685 values, hash_mode));
13688 static tng_function_status tng_data_values_alloc
13689 (const tng_trajectory_t tng_data,
13690 union data_values ***values,
13691 const int64_t n_frames,
13692 const int64_t n_values_per_frame,
13696 tng_function_status stat;
13698 if(n_frames <= 0 || n_values_per_frame <= 0)
13700 return(TNG_FAILURE);
13705 stat = tng_data_values_free(tng_data, *values, n_frames,
13706 n_values_per_frame,
13708 if(stat != TNG_SUCCESS)
13710 fprintf(stderr, "TNG library: Cannot free particle data values. %s: %d\n",
13711 __FILE__, __LINE__);
13715 *values = malloc(sizeof(union data_values *) * n_frames);
13718 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
13719 sizeof(union data_values **) * n_frames,
13720 __FILE__, __LINE__);
13721 return(TNG_CRITICAL);
13725 for(i = 0; i < n_frames; i++)
13727 (*values)[i] = malloc(sizeof(union data_values) *
13728 n_values_per_frame);
13731 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
13732 sizeof(union data_values) * n_values_per_frame,
13733 __FILE__, __LINE__);
13736 return(TNG_CRITICAL);
13739 return(TNG_SUCCESS);
13742 /* FIXME: This needs ***values */
13743 tng_function_status DECLSPECDLLEXPORT tng_data_values_free
13744 (const tng_trajectory_t tng_data,
13745 union data_values **values,
13746 const int64_t n_frames,
13747 const int64_t n_values_per_frame,
13755 for(i = 0; i < n_frames; i++)
13759 if(type == TNG_CHAR_DATA)
13761 for(j = 0; j < n_values_per_frame; j++)
13765 free(values[i][j].c);
13766 values[i][j].c = 0;
13778 return(TNG_SUCCESS);
13781 static tng_function_status tng_particle_data_values_alloc
13782 (const tng_trajectory_t tng_data,
13783 union data_values ****values,
13784 const int64_t n_frames,
13785 const int64_t n_particles,
13786 const int64_t n_values_per_frame,
13790 tng_function_status stat;
13792 if(n_particles == 0 || n_values_per_frame == 0)
13794 return(TNG_FAILURE);
13799 stat = tng_particle_data_values_free(tng_data, *values, n_frames,
13800 n_particles, n_values_per_frame,
13802 if(stat != TNG_SUCCESS)
13804 fprintf(stderr, "TNG library: Cannot free particle data values. %s: %d\n",
13805 __FILE__, __LINE__);
13809 *values = malloc(sizeof(union data_values **) * n_frames);
13812 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
13813 sizeof(union data_values **) * n_frames,
13814 __FILE__, __LINE__);
13815 return(TNG_CRITICAL);
13819 for(i = 0; i < n_frames; i++)
13821 (*values)[i] = malloc(sizeof(union data_values *) *
13825 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
13826 sizeof(union data_values *) * n_particles,
13827 __FILE__, __LINE__);
13830 return(TNG_CRITICAL);
13832 for(j = 0; j < n_particles; j++)
13834 (*values)[i][j] = malloc(sizeof(union data_values) *
13835 n_values_per_frame);
13836 if(!(*values)[i][j])
13838 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
13839 sizeof(union data_values *) * n_particles,
13840 __FILE__, __LINE__);
13841 tng_particle_data_values_free(tng_data, *values, n_frames,
13842 n_particles, n_values_per_frame,
13845 return(TNG_CRITICAL);
13849 return(TNG_SUCCESS);
13852 /* FIXME: This needs ****values */
13853 tng_function_status DECLSPECDLLEXPORT tng_particle_data_values_free
13854 (const tng_trajectory_t tng_data,
13855 union data_values ***values,
13856 const int64_t n_frames,
13857 const int64_t n_particles,
13858 const int64_t n_values_per_frame,
13866 for(i = 0; i < n_frames; i++)
13870 for(j = 0; j < n_particles; j++)
13872 if(type == TNG_CHAR_DATA)
13874 for(k = 0; k < n_values_per_frame; k++)
13876 if(values[i][j][k].c)
13878 free(values[i][j][k].c);
13879 values[i][j][k].c = 0;
13883 free(values[i][j]);
13894 return(TNG_SUCCESS);
13897 static tng_function_status tng_gen_data_get
13898 (const tng_trajectory_t tng_data,
13899 const int64_t block_id,
13900 const tng_bool is_particle_data,
13901 union data_values ****values,
13903 int64_t *n_particles,
13904 int64_t *n_values_per_frame,
13907 int64_t i, j, k, mapping, file_pos, i_step, block_index;
13911 tng_trajectory_frame_set_t frame_set;
13912 tng_gen_block_t block;
13913 char block_type_flag;
13914 tng_function_status stat;
13916 frame_set = &tng_data->current_trajectory_frame_set;
13921 if(is_particle_data == TNG_TRUE)
13923 stat = tng_particle_data_find(tng_data, block_id, &data);
13927 stat = tng_data_find(tng_data, block_id, &data);
13930 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
13932 block_type_flag = TNG_TRAJECTORY_BLOCK;
13936 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
13939 if(stat != TNG_SUCCESS)
13941 tng_block_init(&block);
13942 file_pos = ftello(tng_data->input_file);
13943 /* Read all blocks until next frame set block */
13944 stat = tng_block_header_read(tng_data, block);
13945 while(file_pos < tng_data->input_file_len &&
13946 stat != TNG_CRITICAL &&
13947 block->id != TNG_TRAJECTORY_FRAME_SET &&
13950 /* Use hash by default */
13951 stat = tng_block_read_next(tng_data, block,
13953 if(stat != TNG_CRITICAL)
13955 file_pos = ftello(tng_data->input_file);
13956 if(file_pos < tng_data->input_file_len)
13958 stat = tng_block_header_read(tng_data, block);
13962 tng_block_destroy(&block);
13963 if(stat == TNG_CRITICAL)
13965 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
13966 file_pos, __FILE__, __LINE__);
13970 if(is_particle_data == TNG_TRUE)
13972 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
13974 data = &frame_set->tr_particle_data[i];
13975 if(data->block_id == block_id)
13978 block_type_flag = TNG_TRAJECTORY_BLOCK;
13985 for(i = 0; i < frame_set->n_data_blocks; i++)
13987 data = &frame_set->tr_data[i];
13988 if(data->block_id == block_id)
13995 if(block_index < 0)
13997 return(TNG_FAILURE);
14001 if(is_particle_data == TNG_TRUE)
14003 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
14004 tng_data->var_num_atoms_flag)
14006 *n_particles = frame_set->n_particles;
14010 *n_particles = tng_data->n_particles;
14014 *n_frames = tng_max_i64(1, data->n_frames);
14015 *n_values_per_frame = data->n_values_per_frame;
14016 *type = data->datatype;
14018 if(is_particle_data == TNG_TRUE)
14022 if(tng_particle_data_values_alloc(tng_data, values, *n_frames,
14023 *n_particles, *n_values_per_frame,
14024 *type) != TNG_SUCCESS)
14026 return(TNG_CRITICAL);
14030 i_step = (*n_particles) * (*n_values_per_frame);
14032 /* It's not very elegant to reuse so much of the code in the different case
14033 * statements, but it's unnecessarily slow to have the switch-case block
14034 * inside the for loops. */
14037 case TNG_CHAR_DATA:
14038 for(i = 0; i < *n_frames; i++)
14040 for(j = 0; j < *n_particles; j++)
14042 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14043 for(k = 0; k < *n_values_per_frame; k++)
14045 len = strlen(data->strings[i][j][k]) + 1;
14046 (*values)[i][mapping][k].c = malloc(len);
14047 strncpy((*values)[i][mapping][k].c,
14048 data->strings[i][j][k], len);
14054 size = sizeof(int);
14055 for(i = 0; i < *n_frames; i++)
14057 for(j = 0; j < *n_particles; j++)
14059 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14060 for(k = 0; k < *n_values_per_frame; k++)
14062 (*values)[i][mapping][k].i = *(int *)
14063 ((char *)data->values + size *
14065 (*n_values_per_frame) + k));
14070 case TNG_FLOAT_DATA:
14071 size = sizeof(float);
14072 for(i = 0; i < *n_frames; i++)
14074 for(j = 0; j < *n_particles; j++)
14076 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14077 for(k = 0; k < *n_values_per_frame; k++)
14079 (*values)[i][mapping][k].f = *(float *)
14080 ((char *)data->values + size *
14082 (*n_values_per_frame) + k));
14087 case TNG_DOUBLE_DATA:
14089 size = sizeof(double);
14090 for(i = 0; i < *n_frames; i++)
14092 for(j = 0; j < *n_particles; j++)
14094 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14095 for(k = 0; k < *n_values_per_frame; k++)
14097 (*values)[i][mapping][k].d = *(double *)
14098 ((char *)data->values + size *
14100 (*n_values_per_frame) + k));
14108 if(*(values[0]) == 0)
14110 if(tng_data_values_alloc(tng_data, values[0], *n_frames,
14111 *n_values_per_frame,
14112 *type) != TNG_SUCCESS)
14114 return(TNG_CRITICAL);
14119 case TNG_CHAR_DATA:
14120 for(i = 0; i < *n_frames; i++)
14122 for(j = 0; j < *n_values_per_frame; j++)
14124 len = strlen(data->strings[0][i][j]) + 1;
14125 (*values)[0][i][j].c = malloc(len);
14126 strncpy((*values)[0][i][j].c, data->strings[0][i][j], len);
14131 size = sizeof(int);
14132 for(i = 0; i < *n_frames; i++)
14134 for(j = 0; j < *n_values_per_frame; j++)
14136 (*values)[0][i][j].i = *(int *)((char *)data->values + size *
14137 (i*(*n_values_per_frame) + j));
14141 case TNG_FLOAT_DATA:
14142 size = sizeof(float);
14143 for(i = 0; i < *n_frames; i++)
14145 for(j = 0; j < *n_values_per_frame; j++)
14147 (*values)[0][i][j].f = *(float *)((char *)data->values + size *
14148 (i*(*n_values_per_frame) + j));
14152 case TNG_DOUBLE_DATA:
14154 size = sizeof(double);
14155 for(i = 0; i < *n_frames; i++)
14157 for(j = 0; j < *n_values_per_frame; j++)
14159 (*values)[0][i][j].d = *(double *)((char *)data->values + size *
14160 (i*(*n_values_per_frame) + j));
14166 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
14168 return(TNG_SUCCESS);
14171 tng_function_status DECLSPECDLLEXPORT tng_data_get
14172 (const tng_trajectory_t tng_data,
14173 const int64_t block_id,
14174 union data_values ***values,
14176 int64_t *n_values_per_frame,
14179 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14180 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
14181 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
14182 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
14184 return(tng_gen_data_get(tng_data, block_id, TNG_FALSE, &values, n_frames, 0,
14185 n_values_per_frame, type));
14188 static tng_function_status tng_gen_data_vector_get
14189 (const tng_trajectory_t tng_data,
14190 const int64_t block_id,
14191 const tng_bool is_particle_data,
14194 int64_t *stride_length,
14195 int64_t *n_particles,
14196 int64_t *n_values_per_frame,
14199 int64_t i, j, mapping, file_pos, i_step, full_data_len, n_frames_div;
14200 int64_t block_index;
14203 tng_trajectory_frame_set_t frame_set;
14204 tng_gen_block_t block;
14206 char block_type_flag;
14207 tng_function_status stat;
14209 frame_set = &tng_data->current_trajectory_frame_set;
14214 if(is_particle_data == TNG_TRUE)
14216 stat = tng_particle_data_find(tng_data, block_id, &data);
14220 stat = tng_data_find(tng_data, block_id, &data);
14223 if(stat != TNG_SUCCESS)
14225 tng_block_init(&block);
14226 file_pos = ftello(tng_data->input_file);
14227 /* Read all blocks until next frame set block */
14228 stat = tng_block_header_read(tng_data, block);
14229 while(file_pos < tng_data->input_file_len &&
14230 stat != TNG_CRITICAL &&
14231 block->id != TNG_TRAJECTORY_FRAME_SET &&
14234 /* Use hash by default */
14235 stat = tng_block_read_next(tng_data, block,
14237 if(stat != TNG_CRITICAL)
14239 file_pos = ftello(tng_data->input_file);
14240 if(file_pos < tng_data->input_file_len)
14242 stat = tng_block_header_read(tng_data, block);
14246 tng_block_destroy(&block);
14247 if(stat == TNG_CRITICAL)
14249 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14250 file_pos, __FILE__, __LINE__);
14254 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
14256 data = &frame_set->tr_particle_data[i];
14257 if(data->block_id == block_id)
14263 if(block_index < 0)
14265 return(TNG_FAILURE);
14269 if(is_particle_data == TNG_TRUE)
14271 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
14273 block_type_flag = TNG_TRAJECTORY_BLOCK;
14277 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
14280 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
14281 tng_data->var_num_atoms_flag)
14283 *n_particles = frame_set->n_particles;
14287 *n_particles = tng_data->n_particles;
14291 *type = data->datatype;
14295 case TNG_CHAR_DATA:
14296 return(TNG_FAILURE);
14298 size = sizeof(int64_t);
14300 case TNG_FLOAT_DATA:
14301 size = sizeof(float);
14303 case TNG_DOUBLE_DATA:
14305 size = sizeof(double);
14308 *n_frames = tng_max_i64(1, data->n_frames);
14309 *n_values_per_frame = data->n_values_per_frame;
14310 *stride_length = data->stride_length;
14312 n_frames_div = (*n_frames % *stride_length) ?
14313 *n_frames / *stride_length + 1:
14314 *n_frames / *stride_length;
14316 full_data_len = n_frames_div * size *
14317 (*n_values_per_frame);
14318 if(is_particle_data == TNG_TRUE)
14320 full_data_len *= (*n_particles);
14323 temp = realloc(*values, full_data_len);
14326 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
14327 full_data_len, __FILE__, __LINE__);
14330 return(TNG_CRITICAL);
14335 if(is_particle_data != TNG_TRUE || frame_set->n_mapping_blocks <= 0)
14337 memcpy(*values, data->values, full_data_len);
14341 i_step = (*n_particles) * (*n_values_per_frame);
14342 for(i = 0; i < *n_frames; i++)
14344 for(j = 0; j < *n_particles; j++)
14346 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14347 memcpy(((char *)*values) + size * (i * i_step + mapping *
14348 (*n_values_per_frame)),
14349 (char *)data->values + size *
14350 (i * i_step + j * (*n_values_per_frame)),
14351 size * (*n_values_per_frame));
14356 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
14358 return(TNG_SUCCESS);
14361 tng_function_status DECLSPECDLLEXPORT tng_data_vector_get
14362 (const tng_trajectory_t tng_data,
14363 const int64_t block_id,
14366 int64_t *stride_length,
14367 int64_t *n_values_per_frame,
14370 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14371 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
14372 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
14373 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
14374 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
14376 return(tng_gen_data_vector_get(tng_data, block_id, TNG_FALSE, values,
14377 n_frames, stride_length, 0, n_values_per_frame,
14381 static tng_function_status tng_gen_data_interval_get
14382 (const tng_trajectory_t tng_data,
14383 const int64_t block_id,
14384 const tng_bool is_particle_data,
14385 const int64_t start_frame_nr,
14386 const int64_t end_frame_nr,
14387 const char hash_mode,
14388 union data_values ****values,
14389 int64_t *n_particles,
14390 int64_t *n_values_per_frame,
14393 int64_t i, j, k, mapping, n_frames, file_pos, current_frame_pos, i_step;
14394 int64_t first_frame, block_index;
14398 tng_trajectory_frame_set_t frame_set;
14399 tng_gen_block_t block;
14400 char block_type_flag;
14401 tng_function_status stat;
14405 frame_set = &tng_data->current_trajectory_frame_set;
14406 first_frame = frame_set->first_frame;
14408 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
14409 if(stat != TNG_SUCCESS)
14414 /* Do not re-read the frame set. */
14415 if((is_particle_data == TNG_TRUE &&
14416 (first_frame != frame_set->first_frame ||
14417 frame_set->n_particle_data_blocks <= 0)) ||
14418 (is_particle_data == TNG_FALSE &&
14419 (first_frame != frame_set->first_frame ||
14420 frame_set->n_data_blocks <= 0)))
14422 tng_block_init(&block);
14423 file_pos = ftello(tng_data->input_file);
14424 /* Read all blocks until next frame set block */
14425 stat = tng_block_header_read(tng_data, block);
14426 while(file_pos < tng_data->input_file_len &&
14427 stat != TNG_CRITICAL &&
14428 block->id != TNG_TRAJECTORY_FRAME_SET &&
14431 stat = tng_block_read_next(tng_data, block,
14433 if(stat != TNG_CRITICAL)
14435 file_pos = ftello(tng_data->input_file);
14436 if(file_pos < tng_data->input_file_len)
14438 stat = tng_block_header_read(tng_data, block);
14442 tng_block_destroy(&block);
14443 if(stat == TNG_CRITICAL)
14445 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14446 file_pos, __FILE__, __LINE__);
14451 /* See if there is already a data block of this ID.
14452 * Start checking the last read frame set */
14453 if(is_particle_data == TNG_TRUE)
14455 for(i = frame_set->n_particle_data_blocks; i-- ;)
14457 data = &frame_set->tr_particle_data[i];
14458 if(data->block_id == block_id)
14461 block_type_flag = TNG_TRAJECTORY_BLOCK;
14468 for(i = 0; i < frame_set->n_data_blocks; i++)
14470 data = &frame_set->tr_data[i];
14471 if(data->block_id == block_id)
14479 if(block_index < 0)
14481 fprintf(stderr, "TNG library: Could not find particle data block with id %"PRId64". %s: %d\n",
14482 block_id, __FILE__, __LINE__);
14483 return(TNG_FAILURE);
14486 if(is_particle_data == TNG_TRUE)
14488 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
14489 tng_data->var_num_atoms_flag)
14491 *n_particles = frame_set->n_particles;
14495 *n_particles = tng_data->n_particles;
14499 n_frames = end_frame_nr - start_frame_nr + 1;
14500 *n_values_per_frame = data->n_values_per_frame;
14501 *type = data->datatype;
14505 if(is_particle_data == TNG_TRUE)
14507 if(tng_particle_data_values_alloc(tng_data, values, n_frames,
14508 *n_particles, *n_values_per_frame,
14509 *type) != TNG_SUCCESS)
14511 return(TNG_CRITICAL);
14516 if(tng_data_values_alloc(tng_data, *values, n_frames,
14517 *n_values_per_frame,
14518 *type) != TNG_SUCCESS)
14520 return(TNG_CRITICAL);
14525 current_frame_pos = start_frame_nr - frame_set->first_frame;
14527 if(is_particle_data == TNG_TRUE)
14529 i_step = (*n_particles) * (*n_values_per_frame);
14533 i_step = (*n_values_per_frame);
14535 /* It's not very elegant to reuse so much of the code in the different case
14536 * statements, but it's unnecessarily slow to have the switch-case block
14537 * inside the for loops. */
14540 case TNG_CHAR_DATA:
14541 for(i=0; i<n_frames; i++)
14543 if(current_frame_pos == frame_set->n_frames)
14545 stat = tng_frame_set_read_next(tng_data, hash_mode);
14546 if(stat != TNG_SUCCESS)
14550 current_frame_pos = 0;
14552 if(is_particle_data == TNG_TRUE)
14554 for(j = 0; j < *n_particles; j++)
14556 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14557 for(k = 0; k < *n_values_per_frame; k++)
14559 len = strlen(data->strings[current_frame_pos][j][k]) + 1;
14560 (*values)[i][mapping][k].c = malloc(len);
14561 strncpy((*values)[i][mapping][k].c, data->strings[current_frame_pos][j][k], len);
14567 for(j = 0; j < *n_values_per_frame; j++)
14569 len = strlen(data->strings[0][current_frame_pos][j]) + 1;
14570 (*values)[0][i][j].c = malloc(len);
14571 strncpy((*values)[0][i][j].c, data->strings[0][current_frame_pos][j], len);
14574 current_frame_pos++;
14578 size = sizeof(int);
14579 for(i=0; i<n_frames; i++)
14581 if(current_frame_pos == frame_set->n_frames)
14583 stat = tng_frame_set_read_next(tng_data, hash_mode);
14584 if(stat != TNG_SUCCESS)
14588 current_frame_pos = 0;
14590 if(is_particle_data == TNG_TRUE)
14592 for(j = 0; j < *n_particles; j++)
14594 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14595 for(k = 0; k < *n_values_per_frame; k++)
14597 (*values)[i][mapping][k].i = *(int *)
14598 ((char *)data->values + size *
14599 (current_frame_pos *
14601 (*n_values_per_frame) + k));
14604 current_frame_pos++;
14608 for(j = 0; j < *n_values_per_frame; j++)
14610 (*values)[0][i][j].i = *(int *)((char *)data->values + size *
14611 (current_frame_pos *
14617 case TNG_FLOAT_DATA:
14618 size = sizeof(float);
14619 for(i=0; i<n_frames; i++)
14621 if(current_frame_pos == frame_set->n_frames)
14623 stat = tng_frame_set_read_next(tng_data, hash_mode);
14624 if(stat != TNG_SUCCESS)
14628 current_frame_pos = 0;
14630 if(is_particle_data == TNG_TRUE)
14632 for(j=0; j<*n_particles; j++)
14634 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14635 for(k=0; k<*n_values_per_frame; k++)
14637 (*values)[i][mapping][k].f = *(float *)
14638 ((char *)data->values + size *
14639 (current_frame_pos *
14641 (*n_values_per_frame) + k));
14647 for(j = 0; j < *n_values_per_frame; j++)
14649 (*values)[0][i][j].f = *(float *)((char *)data->values + size *
14650 (current_frame_pos *
14654 current_frame_pos++;
14657 case TNG_DOUBLE_DATA:
14659 size = sizeof(double);
14660 for(i=0; i<n_frames; i++)
14662 if(current_frame_pos == frame_set->n_frames)
14664 stat = tng_frame_set_read_next(tng_data, hash_mode);
14665 if(stat != TNG_SUCCESS)
14669 current_frame_pos = 0;
14671 if(is_particle_data == TNG_TRUE)
14673 for(j=0; j<*n_particles; j++)
14675 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14676 for(k=0; k<*n_values_per_frame; k++)
14678 (*values)[i][mapping][k].d = *(double *)
14679 ((char *)data->values + size *
14680 (current_frame_pos *
14682 (*n_values_per_frame) + k));
14688 for(j = 0; j < *n_values_per_frame; j++)
14690 (*values)[0][i][j].d = *(double *)((char *)data->values + size *
14691 (current_frame_pos *
14695 current_frame_pos++;
14699 data->last_retrieved_frame = end_frame_nr;
14701 return(TNG_SUCCESS);
14704 tng_function_status DECLSPECDLLEXPORT tng_data_interval_get
14705 (const tng_trajectory_t tng_data,
14706 const int64_t block_id,
14707 const int64_t start_frame_nr,
14708 const int64_t end_frame_nr,
14709 const char hash_mode,
14710 union data_values ***values,
14711 int64_t *n_values_per_frame,
14714 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14715 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
14716 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
14717 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
14719 return(tng_gen_data_interval_get(tng_data, block_id, TNG_FALSE, start_frame_nr,
14720 end_frame_nr, hash_mode, &values, 0,
14721 n_values_per_frame, type));
14724 static tng_function_status tng_gen_data_vector_interval_get
14725 (const tng_trajectory_t tng_data,
14726 const int64_t block_id,
14727 const tng_bool is_particle_data,
14728 const int64_t start_frame_nr,
14729 const int64_t end_frame_nr,
14730 const char hash_mode,
14732 int64_t *n_particles,
14733 int64_t *stride_length,
14734 int64_t *n_values_per_frame,
14737 int64_t n_frames, tot_n_frames, n_frames_div, n_frames_div_2, first_frame;
14738 int64_t file_pos, current_frame_pos, last_frame_pos, full_data_len, frame_size;
14740 tng_trajectory_frame_set_t frame_set;
14742 tng_gen_block_t block;
14743 void *current_values = 0, *temp;
14744 tng_function_status stat;
14746 frame_set = &tng_data->current_trajectory_frame_set;
14747 first_frame = frame_set->first_frame;
14749 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
14750 if(stat != TNG_SUCCESS)
14755 /* Do not re-read the frame set and only need the requested block + particle mapping blocks. */
14756 /* TODO: Test that blocks are read correctly now that now all of them are read at the same time. */
14757 if(is_particle_data == TNG_TRUE)
14759 stat = tng_particle_data_find(tng_data, block_id, &data);
14763 stat = tng_data_find(tng_data, block_id, &data);
14766 if(first_frame != frame_set->first_frame ||
14767 stat != TNG_SUCCESS)
14769 tng_block_init(&block);
14770 if(stat != TNG_SUCCESS)
14772 fseeko(tng_data->input_file,
14773 tng_data->current_trajectory_frame_set_input_file_pos,
14775 stat = tng_block_header_read(tng_data, block);
14776 if(stat != TNG_SUCCESS)
14778 fprintf(stderr, "TNG library: Cannot read block header. %s: %d\n",
14779 __FILE__, __LINE__);
14783 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
14785 file_pos = ftello(tng_data->input_file);
14786 /* Read until next frame set block */
14787 stat = tng_block_header_read(tng_data, block);
14788 while(file_pos < tng_data->input_file_len &&
14789 stat != TNG_CRITICAL &&
14790 block->id != TNG_TRAJECTORY_FRAME_SET &&
14793 if(block->id == block_id || block->id == TNG_PARTICLE_MAPPING)
14795 stat = tng_block_read_next(tng_data, block,
14797 if(stat != TNG_CRITICAL)
14799 file_pos = ftello(tng_data->input_file);
14800 if(file_pos < tng_data->input_file_len)
14802 stat = tng_block_header_read(tng_data, block);
14808 file_pos += block->block_contents_size + block->header_contents_size;
14809 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
14810 if(file_pos < tng_data->input_file_len)
14812 stat = tng_block_header_read(tng_data, block);
14816 tng_block_destroy(&block);
14817 if(stat == TNG_CRITICAL)
14819 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14820 file_pos, __FILE__, __LINE__);
14824 if(is_particle_data == TNG_TRUE)
14826 stat = tng_particle_data_find(tng_data, block_id, &data);
14830 stat = tng_data_find(tng_data, block_id, &data);
14832 if(stat != TNG_SUCCESS)
14837 stat = tng_gen_data_vector_get(tng_data, block_id, is_particle_data,
14838 ¤t_values, &n_frames, stride_length,
14839 n_particles, n_values_per_frame, type);
14841 if(stat != TNG_SUCCESS || (is_particle_data && *n_particles == 0))
14845 free(current_values);
14850 if(n_frames == 1 && n_frames < frame_set->n_frames)
14856 tot_n_frames = end_frame_nr - start_frame_nr + 1;
14861 case TNG_CHAR_DATA:
14862 return(TNG_FAILURE);
14864 size = sizeof(int64_t);
14866 case TNG_FLOAT_DATA:
14867 size = sizeof(float);
14869 case TNG_DOUBLE_DATA:
14871 size = sizeof(double);
14874 n_frames_div = (tot_n_frames % *stride_length) ?
14875 tot_n_frames / *stride_length + 1:
14876 tot_n_frames / *stride_length;
14878 full_data_len = n_frames_div * size * (*n_values_per_frame);
14879 if(is_particle_data)
14881 full_data_len *= (*n_particles);
14884 temp = realloc(*values, full_data_len);
14887 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
14888 full_data_len, __FILE__, __LINE__);
14891 return(TNG_CRITICAL);
14896 if( n_frames == 1 && n_frames < frame_set->n_frames)
14898 if(is_particle_data)
14900 memcpy(*values, current_values, size * (*n_particles) *
14901 (*n_values_per_frame));
14905 memcpy(*values, current_values, size * (*n_values_per_frame));
14910 current_frame_pos = start_frame_nr - frame_set->first_frame;
14912 frame_size = size * (*n_values_per_frame);
14913 if(is_particle_data)
14915 frame_size *= (*n_particles);
14918 last_frame_pos = tng_min_i64(n_frames,
14919 end_frame_nr - start_frame_nr);
14921 n_frames_div = current_frame_pos / *stride_length;
14922 n_frames_div_2 = (last_frame_pos % *stride_length) ?
14923 last_frame_pos / *stride_length + 1:
14924 last_frame_pos / *stride_length;
14925 n_frames_div_2 = tng_max_i64(1, n_frames_div_2 + 1);
14927 memcpy(*values, (char *)current_values + n_frames_div * frame_size,
14928 n_frames_div_2 * frame_size);
14930 current_frame_pos += n_frames - current_frame_pos;
14932 while(current_frame_pos <= end_frame_nr - start_frame_nr)
14934 stat = tng_frame_set_read_next(tng_data, hash_mode);
14935 if(stat != TNG_SUCCESS)
14939 free(current_values);
14946 stat = tng_gen_data_vector_get(tng_data, block_id, is_particle_data,
14947 ¤t_values, &n_frames,
14948 stride_length, n_particles,
14949 n_values_per_frame, type);
14951 if(stat != TNG_SUCCESS)
14955 free(current_values);
14962 last_frame_pos = tng_min_i64(n_frames,
14963 end_frame_nr - current_frame_pos);
14965 n_frames_div = current_frame_pos / *stride_length;
14966 n_frames_div_2 = (last_frame_pos % *stride_length) ?
14967 last_frame_pos / *stride_length + 1:
14968 last_frame_pos / *stride_length;
14969 n_frames_div_2 = tng_max_i64(1, n_frames_div_2);
14971 memcpy(((char *)*values) + n_frames_div * frame_size,
14973 n_frames_div_2 * frame_size);
14975 current_frame_pos += n_frames;
14981 free(current_values);
14984 data->last_retrieved_frame = end_frame_nr;
14986 return(TNG_SUCCESS);
14990 tng_function_status DECLSPECDLLEXPORT tng_data_vector_interval_get
14991 (const tng_trajectory_t tng_data,
14992 const int64_t block_id,
14993 const int64_t start_frame_nr,
14994 const int64_t end_frame_nr,
14995 const char hash_mode,
14997 int64_t *stride_length,
14998 int64_t *n_values_per_frame,
15001 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15002 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than the end_frame_nr.");
15003 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
15004 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15005 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15007 return(tng_gen_data_vector_interval_get(tng_data, block_id, TNG_FALSE,
15008 start_frame_nr, end_frame_nr,
15009 hash_mode, values, 0, stride_length,
15010 n_values_per_frame, type));
15013 tng_function_status DECLSPECDLLEXPORT tng_particle_data_get
15014 (const tng_trajectory_t tng_data,
15015 const int64_t block_id,
15016 union data_values ****values,
15018 int64_t *n_particles,
15019 int64_t *n_values_per_frame,
15022 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15023 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
15024 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
15025 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15026 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15028 return(tng_gen_data_get(tng_data, block_id, TNG_TRUE, values, n_frames, n_particles,
15029 n_values_per_frame, type));
15032 tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_get
15033 (const tng_trajectory_t tng_data,
15034 const int64_t block_id,
15037 int64_t *stride_length,
15038 int64_t *n_particles,
15039 int64_t *n_values_per_frame,
15042 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15043 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
15044 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
15045 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15046 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15048 return(tng_gen_data_vector_get(tng_data, block_id, TNG_TRUE, values,
15049 n_frames, stride_length, n_particles,
15050 n_values_per_frame, type));
15053 tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
15054 (const tng_trajectory_t tng_data,
15055 const int64_t block_id,
15056 const int64_t start_frame_nr,
15057 const int64_t end_frame_nr,
15058 const char hash_mode,
15059 union data_values ****values,
15060 int64_t *n_particles,
15061 int64_t *n_values_per_frame,
15064 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15065 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
15066 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
15067 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15068 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15070 return(tng_gen_data_interval_get(tng_data, block_id, TNG_TRUE, start_frame_nr,
15071 end_frame_nr, hash_mode, values, n_particles,
15072 n_values_per_frame, type));
15075 tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_interval_get
15076 (const tng_trajectory_t tng_data,
15077 const int64_t block_id,
15078 const int64_t start_frame_nr,
15079 const int64_t end_frame_nr,
15080 const char hash_mode,
15082 int64_t *n_particles,
15083 int64_t *stride_length,
15084 int64_t *n_values_per_frame,
15087 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15088 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
15089 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
15090 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
15091 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15092 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15094 return(tng_gen_data_vector_interval_get(tng_data, block_id, TNG_TRUE,
15095 start_frame_nr, end_frame_nr,
15096 hash_mode, values, n_particles,
15097 stride_length, n_values_per_frame,
15101 tng_function_status DECLSPECDLLEXPORT tng_data_get_stride_length
15102 (const tng_trajectory_t tng_data,
15103 const int64_t block_id,
15105 int64_t *stride_length)
15107 tng_function_status stat;
15109 int64_t orig_file_pos, file_pos;
15110 int is_particle_data;
15112 if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
15119 stat = tng_frame_set_of_frame_find(tng_data, frame);
15120 if(stat != TNG_SUCCESS)
15125 orig_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
15126 stat = tng_data_find(tng_data, block_id, &data);
15127 if(stat != TNG_SUCCESS)
15129 stat = tng_particle_data_find(tng_data, block_id, &data);
15130 if(stat != TNG_SUCCESS)
15132 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15133 /* If no specific frame was required read until this data block is found */
15136 file_pos = ftello(tng_data->input_file);
15137 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
15139 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15140 file_pos = ftello(tng_data->input_file);
15143 if(stat != TNG_SUCCESS)
15145 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
15149 stat = tng_data_find(tng_data, block_id, &data);
15150 if(stat != TNG_SUCCESS)
15152 stat = tng_particle_data_find(tng_data, block_id, &data);
15153 if(stat != TNG_SUCCESS)
15155 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
15161 is_particle_data = 1;
15166 is_particle_data = 0;
15171 is_particle_data = 1;
15176 is_particle_data = 0;
15178 if(is_particle_data)
15180 *stride_length = data->stride_length;
15184 *stride_length = data->stride_length;
15186 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
15188 return(TNG_SUCCESS);
15191 tng_function_status DECLSPECDLLEXPORT tng_time_get_str
15192 (const tng_trajectory_t tng_data,
15195 struct tm *time_data;
15198 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15199 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
15201 secs = tng_data->time;
15203 time_data = localtime(&secs); /* Returns a statically allocated variable. */
15204 TNG_SNPRINTF(time, TNG_MAX_DATE_STR_LEN,
15205 "%4d-%02d-%02d %02d:%02d:%02d",
15206 time_data->tm_year+1900, time_data->tm_mon+1, time_data->tm_mday,
15207 time_data->tm_hour, time_data->tm_min, time_data->tm_sec);
15209 return(TNG_SUCCESS);
15213 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_open
15214 (const char *filename,
15216 tng_trajectory_t *tng_data_p)
15218 tng_function_status stat;
15220 TNG_ASSERT(filename, "TNG library: filename must not be a NULL pointer.");
15222 if(mode != 'r' && mode != 'w' && mode != 'a')
15224 return(TNG_FAILURE);
15227 if(tng_trajectory_init(tng_data_p) != TNG_SUCCESS)
15229 tng_trajectory_destroy(tng_data_p);
15230 return(TNG_CRITICAL);
15235 stat = tng_output_file_set(*tng_data_p, filename);
15238 tng_input_file_set(*tng_data_p, filename);
15240 /* Read the file headers */
15241 tng_file_headers_read(*tng_data_p, TNG_USE_HASH);
15243 stat = tng_num_frame_sets_get(*tng_data_p, &(*tng_data_p)->n_trajectory_frame_sets);
15245 if(stat != TNG_SUCCESS)
15252 if((*tng_data_p)->output_file)
15254 fclose((*tng_data_p)->output_file);
15256 (*tng_data_p)->output_file = (*tng_data_p)->input_file;
15257 fseeko((*tng_data_p)->input_file,
15258 (*tng_data_p)->last_trajectory_frame_set_input_file_pos,
15261 stat = tng_frame_set_read(*tng_data_p, TNG_USE_HASH);
15262 if(stat != TNG_SUCCESS)
15264 fprintf(stderr, "TNG library: Cannot read frame set and related blocks. %s: %d\n",
15265 __FILE__, __LINE__);
15267 (*tng_data_p)->output_file = 0;
15269 (*tng_data_p)->first_trajectory_frame_set_output_file_pos =
15270 (*tng_data_p)->first_trajectory_frame_set_input_file_pos;
15271 (*tng_data_p)->last_trajectory_frame_set_output_file_pos =
15272 (*tng_data_p)->last_trajectory_frame_set_input_file_pos;
15273 (*tng_data_p)->current_trajectory_frame_set_output_file_pos =
15274 (*tng_data_p)->current_trajectory_frame_set_input_file_pos;
15275 if((*tng_data_p)->input_file)
15277 fclose((*tng_data_p)->input_file);
15278 (*tng_data_p)->input_file = 0;
15280 if((*tng_data_p)->input_file_path)
15282 free((*tng_data_p)->input_file_path);
15283 (*tng_data_p)->input_file_path = 0;
15285 tng_output_append_file_set(*tng_data_p, filename);
15287 fseeko((*tng_data_p)->output_file, 0, SEEK_END);
15293 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_close
15294 (tng_trajectory_t *tng_data_p)
15296 tng_trajectory_frame_set_t frame_set;
15298 if(tng_data_p == 0)
15300 fprintf(stderr, "TNG library: Empty pointer to trajectory when attempting to close. %s: %d\n",
15301 __FILE__, __LINE__);
15302 return(TNG_FAILURE);
15305 if(*tng_data_p == 0)
15307 return(TNG_SUCCESS);
15310 frame_set = &(*tng_data_p)->current_trajectory_frame_set;
15312 if(frame_set->n_unwritten_frames > 0)
15314 frame_set->n_frames = frame_set->n_unwritten_frames;
15315 tng_frame_set_write(*tng_data_p, TNG_USE_HASH);
15318 return(tng_trajectory_destroy(tng_data_p));
15321 tng_function_status DECLSPECDLLEXPORT tng_util_time_of_frame_get
15322 (const tng_trajectory_t tng_data,
15323 const int64_t frame_nr,
15326 int64_t first_frame;
15327 tng_trajectory_frame_set_t frame_set;
15328 tng_function_status stat;
15330 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15331 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
15333 stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
15334 if(stat != TNG_SUCCESS)
15336 fprintf(stderr, "TNG library: Cannot find frame nr %"PRId64". %s: %d\n",
15337 frame_nr, __FILE__, __LINE__);
15341 frame_set = &tng_data->current_trajectory_frame_set;
15342 first_frame = frame_set->first_frame;
15344 if(tng_data->time_per_frame <= 0)
15346 return(TNG_FAILURE);
15349 *time = frame_set->first_frame_time + (tng_data->time_per_frame * (frame_nr - first_frame));
15351 return(TNG_SUCCESS);
15355 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecules_get
15356 (const tng_trajectory_t tng_data,
15358 int64_t **molecule_cnt_list,
15359 tng_molecule_t *mols)
15361 tng_trajectory_frame_set_t frame_set;
15363 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15364 TNG_ASSERT(n_mols, "TNG library: n_mols must not be a NULL pointer.");
15366 *n_mols = tng_data->n_molecules;
15368 frame_set = &tng_data->current_trajectory_frame_set;
15369 if(tng_data->var_num_atoms_flag && frame_set && frame_set->molecule_cnt_list)
15371 *molecule_cnt_list = frame_set->molecule_cnt_list;
15375 *molecule_cnt_list = tng_data->molecule_cnt_list;
15378 *mols = tng_data->molecules;
15380 return(TNG_SUCCESS);
15384 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecule_add
15385 (const tng_trajectory_t tng_data,
15388 tng_molecule_t *mol)
15390 tng_function_status stat;
15392 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
15393 TNG_ASSERT(cnt>=0, "TNG library: cnt must be >= 0");
15395 stat = tng_molecule_add(tng_data, name, mol);
15396 if(stat != TNG_SUCCESS)
15400 stat = tng_molecule_cnt_set(tng_data, *mol, cnt);
15405 tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_get
15406 (const tng_trajectory_t tng_data,
15407 const tng_molecule_t mol,
15408 int64_t *n_particles,
15413 char ***chain_names,
15414 int64_t **chain_ids)
15422 *n_particles = mol->n_atoms;
15424 *names = malloc(sizeof(char *) * *n_particles);
15425 *types = malloc(sizeof(char *) * *n_particles);
15426 *res_names = malloc(sizeof(char *) * *n_particles);
15427 *chain_names = malloc(sizeof(char *) * *n_particles);
15428 *res_ids = malloc(sizeof(int64_t) * *n_particles);
15429 *chain_ids = malloc(sizeof(int64_t) * *n_particles);
15431 for(i = 0; i < *n_particles; i++)
15433 atom = &mol->atoms[i];
15434 res = atom->residue;
15435 chain = res->chain;
15436 (*names)[i] = malloc(strlen(atom->name));
15437 strcpy(*names[i], atom->name);
15438 (*types)[i] = malloc(strlen(atom->atom_type));
15439 strcpy(*types[i], atom->atom_type);
15440 (*res_names)[i] = malloc(strlen(res->name));
15441 strcpy(*res_names[i], res->name);
15442 (*chain_names)[i] = malloc(strlen(chain->name));
15443 strcpy(*chain_names[i], chain->name);
15444 (*res_ids)[i] = res->id;
15445 (*chain_ids)[i] = chain->id;
15448 return(TNG_SUCCESS);
15451 tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_set
15452 (const tng_trajectory_t tng_data,
15453 const tng_molecule_t mol,
15454 const int64_t n_particles,
15455 const char **names,
15456 const char **types,
15457 const char **res_names,
15458 const int64_t *res_ids,
15459 const char **chain_names,
15460 const int64_t *chain_ids)
15464 tng_residue_t residue;
15466 tng_function_status stat;
15468 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15469 TNG_ASSERT(names, "TNG library: names must not be a NULL pointer");
15470 TNG_ASSERT(types, "TNG library: types must not be a NULL pointer");
15471 TNG_ASSERT(res_names, "TNG library: res_names must not be a NULL pointer");
15472 TNG_ASSERT(res_ids, "TNG library: res_ids must not be a NULL pointer");
15473 TNG_ASSERT(chain_names, "TNG library: chain_names must not be a NULL pointer");
15474 TNG_ASSERT(chain_ids, "TNG library: chain_ids must not be a NULL pointer");
15476 for(i = 0; i < n_particles; i++)
15478 if(tng_molecule_chain_find(tng_data, mol, chain_names[i], chain_ids[i],
15479 &chain) == TNG_FAILURE)
15481 stat = tng_molecule_chain_add(tng_data, mol, chain_names[i],
15483 if(stat != TNG_SUCCESS)
15488 if(tng_chain_residue_find(tng_data, chain, res_names[i], res_ids[i],
15489 &residue) == TNG_FAILURE)
15491 stat = tng_chain_residue_add(tng_data, chain, res_names[i],
15493 if(stat != TNG_SUCCESS)
15498 stat = tng_residue_atom_add(tng_data, residue, names[i], types[i], &atom);
15499 if(stat != TNG_SUCCESS)
15504 return(TNG_SUCCESS);
15507 tng_function_status DECLSPECDLLEXPORT tng_util_pos_read
15508 (const tng_trajectory_t tng_data,
15509 float **positions, 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(positions, "TNG library: positions 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_POSITIONS,
15526 0, n_frames - 1, TNG_USE_HASH,
15527 (void **)positions,
15530 &n_values_per_frame,
15536 tng_function_status DECLSPECDLLEXPORT tng_util_vel_read
15537 (const tng_trajectory_t tng_data,
15538 float **velocities, 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(velocities, "TNG library: velocities 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_VELOCITIES,
15555 0, n_frames - 1, TNG_USE_HASH,
15556 (void **)velocities,
15559 &n_values_per_frame,
15565 tng_function_status DECLSPECDLLEXPORT tng_util_force_read
15566 (const tng_trajectory_t tng_data,
15567 float **forces, int64_t *stride_length)
15569 int64_t n_frames, n_particles, n_values_per_frame;
15571 tng_function_status stat;
15573 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15574 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
15575 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
15577 stat = tng_num_frames_get(tng_data, &n_frames);
15578 if(stat != TNG_SUCCESS)
15583 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_FORCES,
15584 0, n_frames - 1, TNG_USE_HASH,
15588 &n_values_per_frame,
15594 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read
15595 (const tng_trajectory_t tng_data,
15597 int64_t *stride_length)
15599 int64_t n_frames, n_values_per_frame;
15601 tng_function_status stat;
15603 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15604 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
15605 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
15607 stat = tng_num_frames_get(tng_data, &n_frames);
15608 if(stat != TNG_SUCCESS)
15613 stat = tng_data_vector_interval_get(tng_data, TNG_TRAJ_BOX_SHAPE,
15614 0, n_frames - 1, TNG_USE_HASH,
15615 (void **)box_shape,
15617 &n_values_per_frame,
15623 tng_function_status DECLSPECDLLEXPORT tng_util_particle_data_next_frame_read
15624 (const tng_trajectory_t tng_data,
15625 const int64_t block_id,
15628 int64_t *retrieved_frame_number,
15629 double *retrieved_time)
15631 tng_trajectory_frame_set_t frame_set;
15632 tng_data_t data = 0;
15633 tng_function_status stat;
15635 int64_t i, full_data_len, n_particles;
15639 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15640 TNG_ASSERT(values, "TNG library: The pointer to the values array must not be a NULL pointer");
15641 TNG_ASSERT(data_type, "TNG library: The pointer to the data type of the returned data must not be a NULL pointer");
15642 TNG_ASSERT(retrieved_frame_number, "TNG library: The pointer to the frame number of the returned data must not be a NULL pointer");
15643 TNG_ASSERT(retrieved_time, "TNG library: The pointer to the time of the returned data must not be a NULL pointer");
15645 frame_set = &tng_data->current_trajectory_frame_set;
15647 stat = tng_particle_data_find(tng_data, block_id, &data);
15648 if(stat != TNG_SUCCESS)
15650 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15651 file_pos = ftello(tng_data->input_file);
15652 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
15654 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15655 file_pos = ftello(tng_data->input_file);
15657 if(stat != TNG_SUCCESS)
15661 stat = tng_particle_data_find(tng_data, block_id, &data);
15662 if(stat != TNG_SUCCESS)
15667 if(data->last_retrieved_frame < 0)
15669 fseeko(tng_data->input_file,
15670 tng_data->first_trajectory_frame_set_input_file_pos,
15672 stat = tng_frame_set_read(tng_data, TNG_USE_HASH);
15673 if(stat != TNG_SUCCESS)
15677 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15678 if(stat != TNG_SUCCESS)
15683 i = data->first_frame_with_data;
15687 if(data->n_frames == 1 && frame_set->n_frames == 1)
15689 i = data->last_retrieved_frame + 1;
15693 i = data->last_retrieved_frame + data->stride_length;
15695 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
15697 stat = tng_frame_set_of_frame_find(tng_data, i);
15698 if(stat != TNG_SUCCESS)
15700 /* If the frame set search found the frame set after the starting
15701 * frame set there is a gap in the frame sets. So, even if the frame
15702 * was not found the next frame with data is still in the found
15704 if(stat == TNG_CRITICAL)
15708 if(frame_set->first_frame + frame_set->n_frames - 1 < i)
15710 return(TNG_FAILURE);
15712 i = frame_set->first_frame;
15715 if(data->last_retrieved_frame < frame_set->first_frame)
15717 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15718 if(stat != TNG_SUCCESS)
15724 data->last_retrieved_frame = i;
15725 *retrieved_frame_number = i;
15726 if(frame_set->first_frame_time >= 0 && tng_data->time_per_frame >= 0)
15728 *retrieved_time = frame_set->first_frame_time +
15729 (i - frame_set->first_frame) *
15730 tng_data->time_per_frame;
15734 *retrieved_time = 0;
15737 if(data->stride_length > 1)
15739 i = (i - data->first_frame_with_data) / data->stride_length;
15743 i = (i - frame_set->first_frame);
15746 tng_num_particles_get(tng_data, &n_particles);
15748 *data_type = data->datatype;
15752 case TNG_CHAR_DATA:
15753 return(TNG_FAILURE);
15755 size = sizeof(int64_t);
15757 case TNG_FLOAT_DATA:
15758 size = sizeof(float);
15760 case TNG_DOUBLE_DATA:
15762 size = sizeof(double);
15765 full_data_len = size * n_particles * data->n_values_per_frame;
15767 // fprintf(stderr, "TNG library: TEMP: i = %"PRId64", full_data_len = %"PRId64", size = %d, n_particles = %"PRId64", n_values_per_frame = %"PRId64"\n",
15768 // i, full_data_len, size, n_particles, data->n_values_per_frame);
15770 temp = realloc(*values, full_data_len);
15773 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15774 full_data_len, __FILE__, __LINE__);
15777 return(TNG_CRITICAL);
15782 memcpy(*values, (char *)data->values + i * full_data_len, full_data_len);
15784 return(TNG_SUCCESS);
15787 tng_function_status DECLSPECDLLEXPORT tng_util_non_particle_data_next_frame_read
15788 (const tng_trajectory_t tng_data,
15789 const int64_t block_id,
15792 int64_t *retrieved_frame_number,
15793 double *retrieved_time)
15795 tng_trajectory_frame_set_t frame_set;
15796 tng_data_t data = 0;
15797 tng_function_status stat;
15799 int64_t i, full_data_len;
15803 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15804 TNG_ASSERT(values, "TNG library: The pointer to the values array must not be a NULL pointer");
15805 TNG_ASSERT(data_type, "TNG library: The pointer to the data type of the returned data must not be a NULL pointer");
15806 TNG_ASSERT(retrieved_frame_number, "TNG library: The pointer to the frame number of the returned data must not be a NULL pointer");
15807 TNG_ASSERT(retrieved_time, "TNG library: The pointer to the time of the returned data must not be a NULL pointer");
15809 frame_set = &tng_data->current_trajectory_frame_set;
15811 stat = tng_data_find(tng_data, block_id, &data);
15812 if(stat != TNG_SUCCESS)
15814 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15815 file_pos = ftello(tng_data->input_file);
15816 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
15818 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15819 file_pos = ftello(tng_data->input_file);
15821 if(stat != TNG_SUCCESS)
15825 stat = tng_data_find(tng_data, block_id, &data);
15826 if(stat != TNG_SUCCESS)
15831 if(data->last_retrieved_frame < 0)
15833 fseeko(tng_data->input_file,
15834 tng_data->first_trajectory_frame_set_input_file_pos,
15836 stat = tng_frame_set_read(tng_data, TNG_USE_HASH);
15837 if(stat != TNG_SUCCESS)
15841 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15842 if(stat != TNG_SUCCESS)
15847 i = data->first_frame_with_data;
15851 if(data->n_frames == 1 && frame_set->n_frames == 1)
15853 i = data->last_retrieved_frame + 1;
15857 i = data->last_retrieved_frame + data->stride_length;
15859 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
15861 stat = tng_frame_set_of_frame_find(tng_data, i);
15862 if(stat != TNG_SUCCESS)
15864 /* If the frame set search found the frame set after the starting
15865 * frame set there is a gap in the frame sets. So, even if the frame
15866 * was not found the next frame with data is still in the found
15868 if(stat == TNG_CRITICAL)
15872 if(frame_set->first_frame + frame_set->n_frames - 1 < i)
15874 return(TNG_FAILURE);
15876 i = frame_set->first_frame;
15879 if(data->last_retrieved_frame < frame_set->first_frame)
15881 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15882 if(stat != TNG_SUCCESS)
15888 data->last_retrieved_frame = i;
15889 *retrieved_frame_number = i;
15890 if(frame_set->first_frame_time >= 0 && tng_data->time_per_frame >= 0)
15892 *retrieved_time = frame_set->first_frame_time +
15893 (i - frame_set->first_frame) *
15894 tng_data->time_per_frame;
15898 *retrieved_time = 0;
15901 if(data->stride_length > 1)
15903 i = (i - data->first_frame_with_data) / data->stride_length;
15907 i = (i - frame_set->first_frame);
15910 *data_type = data->datatype;
15914 case TNG_CHAR_DATA:
15915 return(TNG_FAILURE);
15917 size = sizeof(int64_t);
15919 case TNG_FLOAT_DATA:
15920 size = sizeof(float);
15922 case TNG_DOUBLE_DATA:
15924 size = sizeof(double);
15927 full_data_len = size * data->n_values_per_frame;
15929 temp = realloc(*values, full_data_len);
15932 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15933 full_data_len, __FILE__, __LINE__);
15936 return(TNG_CRITICAL);
15941 memcpy(*values, (char *)data->values + i * full_data_len, full_data_len);
15943 return(TNG_SUCCESS);
15946 tng_function_status DECLSPECDLLEXPORT tng_util_pos_read_range
15947 (const tng_trajectory_t tng_data,
15948 const int64_t first_frame,
15949 const int64_t last_frame,
15951 int64_t *stride_length)
15953 int64_t n_particles, n_values_per_frame;
15955 tng_function_status stat;
15957 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15958 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
15959 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
15960 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
15962 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_POSITIONS,
15963 first_frame, last_frame,
15965 (void **)positions,
15968 &n_values_per_frame,
15971 if(stat == TNG_SUCCESS && type != TNG_FLOAT_DATA)
15973 return(TNG_FAILURE);
15979 tng_function_status DECLSPECDLLEXPORT tng_util_vel_read_range
15980 (const tng_trajectory_t tng_data,
15981 const int64_t first_frame,
15982 const int64_t last_frame,
15983 float **velocities,
15984 int64_t *stride_length)
15986 int64_t n_particles, n_values_per_frame;
15988 tng_function_status stat;
15990 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15991 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
15992 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
15993 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
15995 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_VELOCITIES,
15996 first_frame, last_frame,
15998 (void **)velocities,
16001 &n_values_per_frame,
16004 if(stat == TNG_SUCCESS && type != TNG_FLOAT_DATA)
16006 return(TNG_FAILURE);
16012 tng_function_status DECLSPECDLLEXPORT tng_util_force_read_range
16013 (const tng_trajectory_t tng_data,
16014 const int64_t first_frame,
16015 const int64_t last_frame,
16017 int64_t *stride_length)
16019 int64_t n_particles, n_values_per_frame;
16021 tng_function_status stat;
16023 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16024 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
16025 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
16026 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
16028 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_FORCES,
16029 first_frame, last_frame,
16034 &n_values_per_frame,
16037 if(stat == TNG_SUCCESS && type != TNG_FLOAT_DATA)
16039 return(TNG_FAILURE);
16045 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read_range
16046 (const tng_trajectory_t tng_data,
16047 const int64_t first_frame,
16048 const int64_t last_frame,
16050 int64_t *stride_length)
16052 int64_t n_values_per_frame;
16054 tng_function_status stat;
16056 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16057 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
16058 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
16059 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
16061 stat = tng_data_vector_interval_get(tng_data, TNG_TRAJ_BOX_SHAPE,
16062 first_frame, last_frame,
16064 (void **)box_shape,
16066 &n_values_per_frame,
16069 if(stat == TNG_SUCCESS && type != TNG_FLOAT_DATA)
16071 return(TNG_FAILURE);
16077 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_set
16078 (const tng_trajectory_t tng_data,
16080 const int64_t n_values_per_frame,
16081 const int64_t block_id,
16082 const char *block_name,
16083 const char particle_dependency,
16084 const char compression)
16086 tng_trajectory_frame_set_t frame_set;
16088 int64_t n_particles, n_frames;
16089 tng_function_status stat;
16091 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16092 TNG_ASSERT(i >= 0, "TNG library: i (writing interval) must be >= 0.");
16096 fprintf(stderr, "TNG library: Cannot set writing frequency to %"PRId64". %s: %d\n",
16097 i, __FILE__, __LINE__);
16098 return(TNG_FAILURE);
16101 frame_set = &tng_data->current_trajectory_frame_set;
16103 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
16105 n_frames = tng_data->frame_set_n_frames;
16107 stat = tng_frame_set_new(tng_data, 0, n_frames);
16108 if(stat != TNG_SUCCESS)
16110 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
16117 n_frames = frame_set->n_frames;
16120 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
16122 tng_num_particles_get(tng_data, &n_particles);
16123 if(n_particles <= 0)
16125 return(TNG_FAILURE);
16128 if(tng_particle_data_find(tng_data, block_id, &data)
16131 stat = tng_particle_data_block_add(tng_data, block_id,
16134 TNG_TRAJECTORY_BLOCK,
16135 n_frames, n_values_per_frame, i,
16138 if(stat != TNG_SUCCESS)
16140 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16141 __FILE__, __LINE__);
16144 data = &frame_set->tr_particle_data[frame_set->
16145 n_particle_data_blocks - 1];
16146 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
16148 n_values_per_frame);
16149 if(stat != TNG_SUCCESS)
16151 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16152 __FILE__, __LINE__);
16158 if(data->stride_length != i)
16160 data->stride_length = i;
16161 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
16163 n_values_per_frame);
16164 if(stat != TNG_SUCCESS)
16166 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16167 __FILE__, __LINE__);
16175 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
16177 stat = tng_data_block_add(tng_data, block_id, block_name,
16178 TNG_FLOAT_DATA, TNG_TRAJECTORY_BLOCK,
16179 n_frames, n_values_per_frame,
16180 i, compression, 0);
16181 if(stat != TNG_SUCCESS)
16183 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16184 __FILE__, __LINE__);
16187 data = &frame_set->tr_data[frame_set->
16188 n_data_blocks - 1];
16189 stat = tng_allocate_data_mem(tng_data, data, n_frames,
16190 i, n_values_per_frame);
16191 if(stat != TNG_SUCCESS)
16193 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16194 __FILE__, __LINE__);
16200 if(data->stride_length != i)
16202 data->stride_length = i;
16203 stat = tng_allocate_data_mem(tng_data, data, n_frames,
16204 i, n_values_per_frame);
16205 if(stat != TNG_SUCCESS)
16207 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16208 __FILE__, __LINE__);
16215 return(TNG_SUCCESS);
16218 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_double_set
16219 (const tng_trajectory_t tng_data,
16221 const int64_t n_values_per_frame,
16222 const int64_t block_id,
16223 const char *block_name,
16224 const char particle_dependency,
16225 const char compression)
16227 tng_trajectory_frame_set_t frame_set;
16229 int64_t n_particles, n_frames;
16230 tng_function_status stat;
16232 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16233 TNG_ASSERT(i >= 0, "TNG library: i (writing interval) must be >= 0.");
16237 fprintf(stderr, "TNG library: Cannot set writing frequency to %"PRId64". %s: %d\n",
16238 i, __FILE__, __LINE__);
16239 return(TNG_FAILURE);
16242 frame_set = &tng_data->current_trajectory_frame_set;
16244 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
16246 n_frames = tng_data->frame_set_n_frames;
16248 stat = tng_frame_set_new(tng_data, 0, n_frames);
16249 if(stat != TNG_SUCCESS)
16251 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
16258 n_frames = frame_set->n_frames;
16261 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
16263 tng_num_particles_get(tng_data, &n_particles);
16265 if(n_particles <= 0)
16267 return(TNG_FAILURE);
16270 if(tng_particle_data_find(tng_data, block_id, &data)
16273 stat = tng_particle_data_block_add(tng_data, block_id,
16276 TNG_TRAJECTORY_BLOCK,
16277 n_frames, n_values_per_frame, i,
16280 if(stat != TNG_SUCCESS)
16282 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16283 __FILE__, __LINE__);
16286 data = &frame_set->tr_particle_data[frame_set->
16287 n_particle_data_blocks - 1];
16288 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
16290 n_values_per_frame);
16291 if(stat != TNG_SUCCESS)
16293 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16294 __FILE__, __LINE__);
16300 data->stride_length = i;
16305 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
16307 stat = tng_data_block_add(tng_data, block_id, block_name,
16308 TNG_DOUBLE_DATA, TNG_TRAJECTORY_BLOCK,
16309 n_frames, n_values_per_frame,
16310 i, compression, 0);
16311 if(stat != TNG_SUCCESS)
16313 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16314 __FILE__, __LINE__);
16317 data = &frame_set->tr_data[frame_set->
16318 n_data_blocks - 1];
16319 stat = tng_allocate_data_mem(tng_data, data, n_frames,
16320 i, n_values_per_frame);
16321 if(stat != TNG_SUCCESS)
16323 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16324 __FILE__, __LINE__);
16330 data->stride_length = i;
16334 return(TNG_SUCCESS);
16337 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_frequency_set
16338 (const tng_trajectory_t tng_data,
16340 const int64_t n_values_per_frame,
16341 const int64_t block_id,
16342 const char *block_name,
16343 const char particle_dependency,
16344 const char compression)
16346 fprintf(stderr, "TNG library: Using obsolete function tng_util_generic_write_frequency_set(). "
16347 "See documentation. %s: %d", __FILE__, __LINE__);
16348 return(tng_util_generic_write_interval_set(tng_data, i, n_values_per_frame,
16349 block_id, block_name,
16350 particle_dependency,
16353 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_set
16354 (const tng_trajectory_t tng_data,
16357 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16358 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
16360 return(tng_util_generic_write_interval_set(tng_data, i, 3,
16361 TNG_TRAJ_POSITIONS,
16363 TNG_PARTICLE_BLOCK_DATA,
16364 TNG_TNG_COMPRESSION));
16367 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_double_set
16368 (const tng_trajectory_t tng_data,
16371 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16372 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
16374 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
16375 TNG_TRAJ_POSITIONS,
16377 TNG_PARTICLE_BLOCK_DATA,
16378 TNG_TNG_COMPRESSION));
16381 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_frequency_set
16382 (const tng_trajectory_t tng_data,
16385 fprintf(stderr, "TNG library: Using obsolete function tng_util_pos_write_frequency_set(). "
16386 "See documentation. %s: %d", __FILE__, __LINE__);
16387 return(tng_util_pos_write_interval_set(tng_data, i));
16390 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_set
16391 (const tng_trajectory_t tng_data,
16394 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16395 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
16397 return(tng_util_generic_write_interval_set(tng_data, i, 3,
16398 TNG_TRAJ_VELOCITIES,
16400 TNG_PARTICLE_BLOCK_DATA,
16401 TNG_TNG_COMPRESSION));
16404 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_double_set
16405 (const tng_trajectory_t tng_data,
16408 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16409 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
16411 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
16412 TNG_TRAJ_VELOCITIES,
16414 TNG_PARTICLE_BLOCK_DATA,
16415 TNG_TNG_COMPRESSION));
16418 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_frequency_set
16419 (const tng_trajectory_t tng_data,
16422 fprintf(stderr, "TNG library: Using obsolete function tng_util_vel_write_frequency_set(). "
16423 "See documentation. %s: %d", __FILE__, __LINE__);
16424 return(tng_util_vel_write_interval_set(tng_data, i));
16427 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_set
16428 (const tng_trajectory_t tng_data,
16431 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16432 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
16434 return(tng_util_generic_write_interval_set(tng_data, i, 3,
16437 TNG_PARTICLE_BLOCK_DATA,
16438 TNG_GZIP_COMPRESSION));
16441 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_double_set
16442 (const tng_trajectory_t tng_data,
16445 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16446 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
16448 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
16451 TNG_PARTICLE_BLOCK_DATA,
16452 TNG_GZIP_COMPRESSION));
16455 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_frequency_set
16456 (const tng_trajectory_t tng_data,
16459 fprintf(stderr, "TNG library: Using obsolete function tng_util_force_write_frequency_set(). "
16460 "See documentation. %s: %d", __FILE__, __LINE__);
16461 return(tng_util_force_write_interval_set(tng_data, i));
16464 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_set
16465 (const tng_trajectory_t tng_data,
16468 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16469 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
16471 return(tng_util_generic_write_interval_set(tng_data, i, 9,
16472 TNG_TRAJ_BOX_SHAPE,
16474 TNG_NON_PARTICLE_BLOCK_DATA,
16475 TNG_GZIP_COMPRESSION));
16478 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_double_set
16479 (const tng_trajectory_t tng_data,
16482 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16483 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
16485 return(tng_util_generic_write_interval_double_set(tng_data, i, 9,
16486 TNG_TRAJ_BOX_SHAPE,
16488 TNG_NON_PARTICLE_BLOCK_DATA,
16489 TNG_GZIP_COMPRESSION));
16492 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_frequency_set
16493 (const tng_trajectory_t tng_data,
16496 fprintf(stderr, "TNG library: Using obsolete function tng_util_box_shape_write_frequency_set(). "
16497 "See documentation. %s: %d", __FILE__, __LINE__);
16498 return(tng_util_box_shape_write_interval_set(tng_data, i));
16501 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write
16502 (const tng_trajectory_t tng_data,
16503 const int64_t frame_nr,
16504 const float *values,
16505 const int64_t n_values_per_frame,
16506 const int64_t block_id,
16507 const char *block_name,
16508 const char particle_dependency,
16509 const char compression)
16511 tng_trajectory_frame_set_t frame_set;
16513 int64_t n_particles = 0, n_frames, stride_length = 100, frame_pos;
16514 int64_t last_frame;
16515 int is_first_frame_flag = 0;
16516 char block_type_flag;
16517 tng_function_status stat;
16519 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16520 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
16522 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
16524 tng_num_particles_get(tng_data, &n_particles);
16525 TNG_ASSERT(n_particles > 0, "TNG library: There must be particles in the system to write particle data.");
16530 return(TNG_FAILURE);
16533 frame_set = &tng_data->current_trajectory_frame_set;
16537 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
16538 n_frames = stride_length = 1;
16542 block_type_flag = TNG_TRAJECTORY_BLOCK;
16544 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
16546 stat = tng_frame_set_new(tng_data, 0, tng_data->frame_set_n_frames);
16547 if(stat != TNG_SUCCESS)
16549 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
16554 last_frame = frame_set->first_frame +
16555 frame_set->n_frames - 1;
16556 if(frame_nr > last_frame)
16558 stat = tng_frame_set_write(tng_data, TNG_USE_HASH);
16559 if(stat != TNG_SUCCESS)
16561 fprintf(stderr, "TNG library: Cannot write frame set. %s: %d\n", __FILE__,
16565 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
16567 last_frame = frame_nr - 1;
16569 stat = tng_frame_set_new(tng_data, last_frame + 1,
16570 tng_data->frame_set_n_frames);
16571 if(stat != TNG_SUCCESS)
16573 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
16578 if(frame_set->n_unwritten_frames == 0)
16580 is_first_frame_flag = 1;
16582 frame_set->n_unwritten_frames = frame_nr -
16583 frame_set->first_frame + 1;
16585 n_frames = frame_set->n_frames;
16588 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
16590 if(tng_particle_data_find(tng_data, block_id, &data)
16593 stat = tng_particle_data_block_add(tng_data, block_id,
16597 n_frames, n_values_per_frame,
16601 if(stat != TNG_SUCCESS)
16603 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16604 __FILE__, __LINE__);
16607 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16609 data = &frame_set->tr_particle_data[frame_set->
16610 n_particle_data_blocks - 1];
16614 data = &tng_data->non_tr_particle_data[tng_data->
16615 n_particle_data_blocks - 1];
16617 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
16618 stride_length, n_particles,
16619 n_values_per_frame);
16620 if(stat != TNG_SUCCESS)
16622 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16623 __FILE__, __LINE__);
16627 /* FIXME: Here we must be able to handle modified n_particles as well. */
16628 else if(n_frames > data->n_frames)
16630 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
16631 data->stride_length, n_particles,
16632 n_values_per_frame);
16633 if(stat != TNG_SUCCESS)
16635 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16636 __FILE__, __LINE__);
16641 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16643 stride_length = data->stride_length;
16645 if(is_first_frame_flag || data->first_frame_with_data < frame_set->first_frame)
16647 data->first_frame_with_data = frame_nr;
16652 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
16655 memcpy((char *)data->values + sizeof(float) * frame_pos * n_particles *
16656 n_values_per_frame, values, sizeof(float) *
16657 n_particles * n_values_per_frame);
16661 memcpy(data->values, values, sizeof(float) * n_particles *
16662 n_values_per_frame);
16667 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
16669 stat = tng_data_block_add(tng_data, block_id, block_name,
16670 TNG_FLOAT_DATA, block_type_flag,
16671 n_frames, n_values_per_frame,
16672 stride_length, compression, 0);
16673 if(stat != TNG_SUCCESS)
16675 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16676 __FILE__, __LINE__);
16679 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16681 data = &frame_set->tr_data[frame_set->
16682 n_data_blocks - 1];
16686 data = &tng_data->non_tr_data[tng_data->
16687 n_data_blocks - 1];
16689 stat = tng_allocate_data_mem(tng_data, data, n_frames,
16690 stride_length, n_values_per_frame);
16691 if(stat != TNG_SUCCESS)
16693 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16694 __FILE__, __LINE__);
16698 /* FIXME: Here we must be able to handle modified n_particles as well. */
16699 else if(n_frames > data->n_frames)
16701 stat = tng_allocate_data_mem(tng_data, data, n_frames,
16702 data->stride_length, n_values_per_frame);
16703 if(stat != TNG_SUCCESS)
16705 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16706 __FILE__, __LINE__);
16711 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16713 stride_length = data->stride_length;
16715 if(is_first_frame_flag || data->first_frame_with_data < frame_set->first_frame)
16717 data->first_frame_with_data = frame_nr;
16722 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
16725 memcpy((char *)data->values + sizeof(float) * frame_pos *
16726 n_values_per_frame, values, sizeof(float) *
16727 n_values_per_frame);
16731 memcpy(data->values, values, sizeof(float) * n_values_per_frame);
16735 return(TNG_SUCCESS);
16738 tng_function_status DECLSPECDLLEXPORT tng_util_generic_double_write
16739 (const tng_trajectory_t tng_data,
16740 const int64_t frame_nr,
16741 const double *values,
16742 const int64_t n_values_per_frame,
16743 const int64_t block_id,
16744 const char *block_name,
16745 const char particle_dependency,
16746 const char compression)
16748 tng_trajectory_frame_set_t frame_set;
16750 int64_t n_particles = 0, n_frames, stride_length = 100, frame_pos;
16751 int64_t last_frame;
16752 int is_first_frame_flag = 0;
16753 char block_type_flag;
16754 tng_function_status stat;
16756 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16757 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
16759 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
16761 tng_num_particles_get(tng_data, &n_particles);
16762 TNG_ASSERT(n_particles > 0, "TNG library: There must be particles in the system to write particle data.");
16767 return(TNG_FAILURE);
16770 frame_set = &tng_data->current_trajectory_frame_set;
16774 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
16775 n_frames = stride_length = 1;
16779 block_type_flag = TNG_TRAJECTORY_BLOCK;
16781 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
16783 stat = tng_frame_set_new(tng_data, 0, tng_data->frame_set_n_frames);
16784 if(stat != TNG_SUCCESS)
16786 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
16791 last_frame = frame_set->first_frame +
16792 frame_set->n_frames - 1;
16793 if(frame_nr > last_frame)
16795 stat = tng_frame_set_write(tng_data, TNG_USE_HASH);
16796 if(stat != TNG_SUCCESS)
16798 fprintf(stderr, "TNG library: Cannot write frame set. %s: %d\n", __FILE__,
16802 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
16804 last_frame = frame_nr - 1;
16806 stat = tng_frame_set_new(tng_data, last_frame + 1,
16807 tng_data->frame_set_n_frames);
16808 if(stat != TNG_SUCCESS)
16810 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
16815 if(frame_set->n_unwritten_frames == 0)
16817 is_first_frame_flag = 1;
16819 frame_set->n_unwritten_frames = frame_nr -
16820 frame_set->first_frame + 1;
16822 n_frames = frame_set->n_frames;
16826 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
16828 if(tng_particle_data_find(tng_data, block_id, &data)
16831 stat = tng_particle_data_block_add(tng_data, block_id,
16835 n_frames, n_values_per_frame,
16839 if(stat != TNG_SUCCESS)
16841 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16842 __FILE__, __LINE__);
16845 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16847 data = &frame_set->tr_particle_data[frame_set->
16848 n_particle_data_blocks - 1];
16852 data = &tng_data->non_tr_particle_data[tng_data->
16853 n_particle_data_blocks - 1];
16855 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
16856 stride_length, n_particles,
16857 n_values_per_frame);
16858 if(stat != TNG_SUCCESS)
16860 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16861 __FILE__, __LINE__);
16865 /* FIXME: Here we must be able to handle modified n_particles as well. */
16866 else if(n_frames > data->n_frames)
16868 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
16869 data->stride_length, n_particles,
16870 n_values_per_frame);
16871 if(stat != TNG_SUCCESS)
16873 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16874 __FILE__, __LINE__);
16879 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16881 stride_length = data->stride_length;
16883 if(is_first_frame_flag || data->first_frame_with_data < frame_set->first_frame)
16885 data->first_frame_with_data = frame_nr;
16890 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
16893 memcpy((char *)data->values + sizeof(double) * frame_pos * n_particles *
16894 n_values_per_frame, values, sizeof(double) *
16895 n_particles * n_values_per_frame);
16899 memcpy(data->values, values, sizeof(double) * n_particles *
16900 n_values_per_frame);
16905 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
16907 stat = tng_data_block_add(tng_data, block_id, block_name,
16908 TNG_DOUBLE_DATA, block_type_flag,
16909 n_frames, n_values_per_frame,
16910 stride_length, compression, 0);
16911 if(stat != TNG_SUCCESS)
16913 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16914 __FILE__, __LINE__);
16917 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16919 data = &frame_set->tr_data[frame_set->
16920 n_data_blocks - 1];
16924 data = &tng_data->non_tr_data[tng_data->
16925 n_data_blocks - 1];
16927 stat = tng_allocate_data_mem(tng_data, data, n_frames,
16928 stride_length, n_values_per_frame);
16929 if(stat != TNG_SUCCESS)
16931 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16932 __FILE__, __LINE__);
16936 /* FIXME: Here we must be able to handle modified n_particles as well. */
16937 else if(n_frames > data->n_frames)
16939 stat = tng_allocate_data_mem(tng_data, data, n_frames,
16940 data->stride_length, n_values_per_frame);
16941 if(stat != TNG_SUCCESS)
16943 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16944 __FILE__, __LINE__);
16949 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16951 stride_length = data->stride_length;
16953 if(is_first_frame_flag || data->first_frame_with_data < frame_set->first_frame)
16955 data->first_frame_with_data = frame_nr;
16960 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
16963 memcpy((char *)data->values + sizeof(double) * frame_pos *
16964 n_values_per_frame, values, sizeof(double) *
16965 n_values_per_frame);
16969 memcpy(data->values, values, sizeof(double) * n_values_per_frame);
16973 return(TNG_SUCCESS);
16976 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write
16977 (const tng_trajectory_t tng_data,
16978 const int64_t frame_nr,
16979 const float *positions)
16981 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16982 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
16984 return(tng_util_generic_write(tng_data, frame_nr, positions, 3,
16985 TNG_TRAJ_POSITIONS, "POSITIONS",
16986 TNG_PARTICLE_BLOCK_DATA,
16987 TNG_TNG_COMPRESSION));
16990 tng_function_status DECLSPECDLLEXPORT tng_util_pos_double_write
16991 (const tng_trajectory_t tng_data,
16992 const int64_t frame_nr,
16993 const double *positions)
16995 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16996 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
16998 return(tng_util_generic_double_write(tng_data, frame_nr, positions, 3,
16999 TNG_TRAJ_POSITIONS, "POSITIONS",
17000 TNG_PARTICLE_BLOCK_DATA,
17001 TNG_TNG_COMPRESSION));
17004 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write
17005 (const tng_trajectory_t tng_data,
17006 const int64_t frame_nr,
17007 const float *velocities)
17009 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17010 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
17012 return(tng_util_generic_write(tng_data, frame_nr, velocities, 3,
17013 TNG_TRAJ_VELOCITIES, "VELOCITIES",
17014 TNG_PARTICLE_BLOCK_DATA,
17015 TNG_TNG_COMPRESSION));
17018 tng_function_status DECLSPECDLLEXPORT tng_util_vel_double_write
17019 (const tng_trajectory_t tng_data,
17020 const int64_t frame_nr,
17021 const double *velocities)
17023 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17024 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
17026 return(tng_util_generic_double_write(tng_data, frame_nr, velocities, 3,
17027 TNG_TRAJ_VELOCITIES, "VELOCITIES",
17028 TNG_PARTICLE_BLOCK_DATA,
17029 TNG_TNG_COMPRESSION));
17032 tng_function_status DECLSPECDLLEXPORT tng_util_force_write
17033 (const tng_trajectory_t tng_data,
17034 const int64_t frame_nr,
17035 const float *forces)
17037 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17038 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17040 return(tng_util_generic_write(tng_data, frame_nr, forces, 3,
17041 TNG_TRAJ_FORCES, "FORCES",
17042 TNG_PARTICLE_BLOCK_DATA,
17043 TNG_GZIP_COMPRESSION));
17046 tng_function_status DECLSPECDLLEXPORT tng_util_force_double_write
17047 (const tng_trajectory_t tng_data,
17048 const int64_t frame_nr,
17049 const double *forces)
17051 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17052 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17054 return(tng_util_generic_double_write(tng_data, frame_nr, forces, 3,
17055 TNG_TRAJ_FORCES, "FORCES",
17056 TNG_PARTICLE_BLOCK_DATA,
17057 TNG_GZIP_COMPRESSION));
17060 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write
17061 (const tng_trajectory_t tng_data,
17062 const int64_t frame_nr,
17063 const float *box_shape)
17065 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17066 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17068 return(tng_util_generic_write(tng_data, frame_nr, box_shape, 9,
17069 TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
17070 TNG_NON_PARTICLE_BLOCK_DATA,
17071 TNG_GZIP_COMPRESSION));
17074 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_double_write
17075 (const tng_trajectory_t tng_data,
17076 const int64_t frame_nr,
17077 const double *box_shape)
17079 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17080 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17082 return(tng_util_generic_double_write(tng_data, frame_nr, box_shape, 9,
17083 TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
17084 TNG_NON_PARTICLE_BLOCK_DATA,
17085 TNG_GZIP_COMPRESSION));
17088 tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_write
17089 (const tng_trajectory_t tng_data,
17090 const int64_t frame_nr,
17092 const float *values,
17093 const int64_t n_values_per_frame,
17094 const int64_t block_id,
17095 const char *block_name,
17096 const char particle_dependency,
17097 const char compression)
17099 tng_trajectory_frame_set_t frame_set;
17100 tng_function_status stat;
17102 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17103 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17104 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17105 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
17107 stat = tng_util_generic_write(tng_data, frame_nr, values, n_values_per_frame,
17108 block_id, block_name,
17109 particle_dependency,
17112 if(stat != TNG_SUCCESS)
17117 frame_set = &tng_data->current_trajectory_frame_set;
17119 /* first_frame_time is -1 when it is not yet set. */
17120 if(frame_set->first_frame_time < -0.1)
17122 if(frame_nr > frame_set->first_frame)
17124 stat = tng_frame_set_first_frame_time_set(tng_data,
17127 frame_set->first_frame) *
17128 tng_data->time_per_frame);
17132 stat = tng_frame_set_first_frame_time_set(tng_data, time);
17138 tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_double_write
17139 (const tng_trajectory_t tng_data,
17140 const int64_t frame_nr,
17142 const double *values,
17143 const int64_t n_values_per_frame,
17144 const int64_t block_id,
17145 const char *block_name,
17146 const char particle_dependency,
17147 const char compression)
17149 tng_trajectory_frame_set_t frame_set;
17150 tng_function_status stat;
17152 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17153 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17154 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17155 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
17157 stat = tng_util_generic_double_write(tng_data, frame_nr, values, n_values_per_frame,
17158 block_id, block_name,
17159 particle_dependency,
17162 if(stat != TNG_SUCCESS)
17167 frame_set = &tng_data->current_trajectory_frame_set;
17169 /* first_frame_time is -1 when it is not yet set. */
17170 if(frame_set->first_frame_time < -0.1)
17172 if(frame_nr > frame_set->first_frame)
17174 stat = tng_frame_set_first_frame_time_set(tng_data,
17177 frame_set->first_frame) *
17178 tng_data->time_per_frame);
17182 stat = tng_frame_set_first_frame_time_set(tng_data, time);
17188 tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_write
17189 (const tng_trajectory_t tng_data,
17190 const int64_t frame_nr,
17192 const float *positions)
17194 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17195 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17196 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17197 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
17199 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, positions,
17200 3, TNG_TRAJ_POSITIONS, "POSITIONS",
17201 TNG_PARTICLE_BLOCK_DATA,
17202 TNG_TNG_COMPRESSION));
17205 tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_double_write
17206 (const tng_trajectory_t tng_data,
17207 const int64_t frame_nr,
17209 const double *positions)
17211 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17212 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17213 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17214 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
17216 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
17218 TNG_TRAJ_POSITIONS,
17220 TNG_PARTICLE_BLOCK_DATA,
17221 TNG_TNG_COMPRESSION));
17224 tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_write
17225 (const tng_trajectory_t tng_data,
17226 const int64_t frame_nr,
17228 const float *velocities)
17230 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17231 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17232 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17233 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
17235 return(tng_util_generic_with_time_write(tng_data, frame_nr, time,
17237 TNG_TRAJ_VELOCITIES,
17239 TNG_PARTICLE_BLOCK_DATA,
17240 TNG_TNG_COMPRESSION));
17243 tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_double_write
17244 (const tng_trajectory_t tng_data,
17245 const int64_t frame_nr,
17247 const double *velocities)
17249 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17250 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17251 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17252 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
17254 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
17256 TNG_TRAJ_VELOCITIES,
17258 TNG_PARTICLE_BLOCK_DATA,
17259 TNG_TNG_COMPRESSION));
17262 tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_write
17263 (const tng_trajectory_t tng_data,
17264 const int64_t frame_nr,
17266 const float *forces)
17268 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17269 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17270 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17271 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17273 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, forces,
17274 3, TNG_TRAJ_FORCES, "FORCES",
17275 TNG_PARTICLE_BLOCK_DATA,
17276 TNG_GZIP_COMPRESSION));
17279 tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_double_write
17280 (const tng_trajectory_t tng_data,
17281 const int64_t frame_nr,
17283 const double *forces)
17285 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17286 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17287 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17288 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17290 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
17292 TNG_TRAJ_FORCES, "FORCES",
17293 TNG_PARTICLE_BLOCK_DATA,
17294 TNG_GZIP_COMPRESSION));
17297 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_write
17298 (const tng_trajectory_t tng_data,
17299 const int64_t frame_nr,
17301 const float *box_shape)
17303 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17304 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17305 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17306 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17308 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, box_shape,
17309 9, TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
17310 TNG_NON_PARTICLE_BLOCK_DATA,
17311 TNG_GZIP_COMPRESSION));
17314 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_double_write
17315 (const tng_trajectory_t tng_data,
17316 const int64_t frame_nr,
17318 const double *box_shape)
17320 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17321 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17322 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17323 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17325 return(tng_util_generic_with_time_double_write(tng_data, frame_nr,
17326 time, box_shape, 9,
17327 TNG_TRAJ_BOX_SHAPE,
17329 TNG_NON_PARTICLE_BLOCK_DATA,
17330 TNG_GZIP_COMPRESSION));
17333 tng_function_status DECLSPECDLLEXPORT tng_util_frame_current_compression_get
17334 (const tng_trajectory_t tng_data,
17335 const int64_t block_id,
17339 tng_trajectory_frame_set_t frame_set;
17340 tng_data_t data = 0;
17341 tng_function_status stat;
17343 int block_type = -1;
17345 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17346 TNG_ASSERT(codec_id, "TNG library: The pointer to the returned codec id must not be a NULL pointer.");
17347 TNG_ASSERT(factor, "TNG library: The pointer to the returned multiplication factor must not be a NULL pointer.");
17349 frame_set = &tng_data->current_trajectory_frame_set;
17351 stat = tng_particle_data_find(tng_data, block_id, &data);
17352 if(stat == TNG_SUCCESS)
17354 block_type = TNG_PARTICLE_BLOCK_DATA;
17358 stat = tng_data_find(tng_data, block_id, &data);
17359 if(stat == TNG_SUCCESS)
17361 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
17365 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17366 if(stat != TNG_SUCCESS)
17370 stat = tng_particle_data_find(tng_data, block_id, &data);
17371 if(stat == TNG_SUCCESS)
17373 block_type = TNG_PARTICLE_BLOCK_DATA;
17377 stat = tng_data_find(tng_data, block_id, &data);
17378 if(stat == TNG_SUCCESS)
17380 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
17389 if(block_type == TNG_PARTICLE_BLOCK_DATA)
17391 if(data->last_retrieved_frame < 0)
17393 i = data->first_frame_with_data;
17397 i = data->last_retrieved_frame;
17400 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
17402 if(data->last_retrieved_frame < 0)
17404 i = data->first_frame_with_data;
17408 i = data->last_retrieved_frame;
17413 return(TNG_FAILURE);
17415 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
17417 stat = tng_frame_set_of_frame_find(tng_data, i);
17418 if(stat != TNG_SUCCESS)
17422 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17423 if(stat != TNG_SUCCESS)
17425 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
17426 __FILE__, __LINE__);
17430 if(block_type == TNG_PARTICLE_BLOCK_DATA)
17432 *codec_id = data->codec_id;
17433 *factor = data->compression_multiplier;
17435 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
17437 *codec_id = data->codec_id;
17438 *factor = data->compression_multiplier;
17440 return(TNG_SUCCESS);
17443 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_next_frame_present_data_blocks_find
17444 (const tng_trajectory_t tng_data,
17445 int64_t current_frame,
17446 const int64_t n_requested_data_block_ids,
17447 const int64_t *requested_data_block_ids,
17448 int64_t *next_frame,
17449 int64_t *n_data_blocks_in_next_frame,
17450 int64_t **data_block_ids_in_next_frame)
17452 tng_trajectory_frame_set_t frame_set;
17453 tng_function_status stat;
17455 tng_gen_block_t block;
17456 int64_t i, j, block_id, *temp;
17457 int64_t data_frame, frame_diff, min_diff;
17458 int64_t size, frame_set_file_pos;
17459 int found, read_all = 0;
17462 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17463 TNG_ASSERT(next_frame, "TNG library: The pointer to the next frame must not be NULL.");
17464 TNG_ASSERT(n_data_blocks_in_next_frame, "TNG library: The pointer to n_data_blocks_in_next_frame must not be NULL.");
17465 TNG_ASSERT(data_block_ids_in_next_frame, "TNG library: The pointer to the list of data block IDs must not be NULL.");
17467 if(n_requested_data_block_ids)
17469 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.");
17470 size = sizeof(int64_t) * n_requested_data_block_ids;
17471 temp = realloc(*data_block_ids_in_next_frame, size);
17474 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
17475 sizeof(int64_t) * (*n_data_blocks_in_next_frame),
17476 __FILE__, __LINE__);
17477 free(*data_block_ids_in_next_frame);
17478 *data_block_ids_in_next_frame = 0;
17479 return(TNG_CRITICAL);
17481 *data_block_ids_in_next_frame = temp;
17484 frame_set = &tng_data->current_trajectory_frame_set;
17486 current_frame += 1;
17488 if(current_frame < frame_set->first_frame ||
17489 current_frame >= frame_set->first_frame + frame_set->n_frames)
17491 frame_set_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
17492 stat = tng_frame_set_of_frame_find(tng_data, current_frame);
17493 if(stat != TNG_SUCCESS)
17495 /* If the frame set search found the frame set after the starting
17496 * frame set there is a gap in the frame sets. So, even if the frame
17497 * was not found the next frame with data is still in the found
17499 if(stat == TNG_CRITICAL || frame_set->prev_frame_set_file_pos !=
17500 frame_set_file_pos)
17504 current_frame = frame_set->first_frame;
17508 /* Check for data blocks only if they have not already been found. */
17509 if(frame_set->n_particle_data_blocks <= 0 && frame_set->n_data_blocks <= 0)
17511 file_pos = ftello(tng_data->input_file);
17512 if(file_pos < tng_data->input_file_len)
17514 tng_block_init(&block);
17515 stat = tng_block_header_read(tng_data, block);
17516 while(file_pos < tng_data->input_file_len &&
17517 stat != TNG_CRITICAL &&
17518 block->id != TNG_TRAJECTORY_FRAME_SET &&
17521 stat = tng_block_read_next(tng_data, block,
17523 if(stat != TNG_CRITICAL)
17525 file_pos = ftello(tng_data->input_file);
17526 if(file_pos < tng_data->input_file_len)
17528 stat = tng_block_header_read(tng_data, block);
17532 tng_block_destroy(&block);
17533 if(stat == TNG_CRITICAL)
17535 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
17536 file_pos, __FILE__, __LINE__);
17545 *n_data_blocks_in_next_frame = 0;
17547 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
17549 data = &frame_set->tr_particle_data[i];
17550 block_id = data->block_id;
17552 if(n_requested_data_block_ids > 0)
17555 for(j = 0; j < n_requested_data_block_ids; j++)
17557 if(block_id == requested_data_block_ids[j])
17569 if(!read_all && (data->last_retrieved_frame < frame_set->first_frame ||
17570 data->last_retrieved_frame >=
17571 frame_set->first_frame + frame_set->n_frames))
17573 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data,
17574 TNG_USE_HASH, block_id);
17575 if(stat == TNG_CRITICAL)
17577 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
17578 __FILE__, __LINE__);
17581 if(stat == TNG_FAILURE)
17586 if(frame_set->first_frame != current_frame &&
17587 data->last_retrieved_frame >= 0)
17589 data_frame = data->last_retrieved_frame + data->stride_length;
17593 data_frame = data->first_frame_with_data;
17595 frame_diff = data_frame - current_frame;
17600 if(min_diff == -1 || frame_diff <= min_diff)
17602 if(frame_diff < min_diff)
17604 *n_data_blocks_in_next_frame = 1;
17608 *n_data_blocks_in_next_frame += 1;
17610 if(n_requested_data_block_ids <= 0)
17612 size = sizeof(int64_t) * (*n_data_blocks_in_next_frame);
17613 temp = realloc(*data_block_ids_in_next_frame, size);
17616 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
17617 sizeof(int64_t) * (*n_data_blocks_in_next_frame),
17618 __FILE__, __LINE__);
17619 free(*data_block_ids_in_next_frame);
17620 *data_block_ids_in_next_frame = 0;
17621 return(TNG_CRITICAL);
17623 *data_block_ids_in_next_frame = temp;
17627 TNG_ASSERT(*n_data_blocks_in_next_frame <= n_requested_data_block_ids, "TNG library: Array of data block IDs out of bounds");
17629 (*data_block_ids_in_next_frame)[(*n_data_blocks_in_next_frame) - 1] = block_id;
17631 min_diff = frame_diff;
17634 for(i = 0; i < frame_set->n_data_blocks; i++)
17636 data = &frame_set->tr_data[i];
17637 block_id = data->block_id;
17639 if(n_requested_data_block_ids > 0)
17642 for(j = 0; j < n_requested_data_block_ids; j++)
17644 if(block_id == requested_data_block_ids[j])
17656 if(!read_all && (data->last_retrieved_frame < frame_set->first_frame ||
17657 data->last_retrieved_frame >=
17658 frame_set->first_frame + frame_set->n_frames))
17660 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data,
17661 TNG_USE_HASH, block_id);
17662 if(stat == TNG_CRITICAL)
17664 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
17665 __FILE__, __LINE__);
17668 if(stat == TNG_FAILURE)
17673 if(frame_set->first_frame != current_frame &&
17674 data->last_retrieved_frame >= 0)
17676 data_frame = data->last_retrieved_frame + data->stride_length;
17680 data_frame = data->first_frame_with_data;
17682 frame_diff = data_frame - current_frame;
17687 if(min_diff == -1 || frame_diff <= min_diff)
17689 if(frame_diff < min_diff)
17691 *n_data_blocks_in_next_frame = 1;
17695 *n_data_blocks_in_next_frame += 1;
17697 if(n_requested_data_block_ids <= 0)
17699 size = sizeof(int64_t) * (*n_data_blocks_in_next_frame);
17700 temp = realloc(*data_block_ids_in_next_frame, size);
17703 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
17704 sizeof(int64_t) * (*n_data_blocks_in_next_frame),
17705 __FILE__, __LINE__);
17706 free(*data_block_ids_in_next_frame);
17707 *data_block_ids_in_next_frame = 0;
17708 return(TNG_CRITICAL);
17710 *data_block_ids_in_next_frame = temp;
17714 TNG_ASSERT(*n_data_blocks_in_next_frame <= n_requested_data_block_ids, "TNG library: Array of data block IDs out of bounds");
17716 (*data_block_ids_in_next_frame)[(*n_data_blocks_in_next_frame) - 1] = block_id;
17718 min_diff = frame_diff;
17723 return(TNG_FAILURE);
17725 *next_frame = current_frame + min_diff;
17727 return(TNG_SUCCESS);
17731 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_all_data_block_types_get
17732 (const tng_trajectory_t tng_data,
17733 int64_t *n_data_blocks,
17734 int64_t **data_block_ids,
17735 char ***data_block_names,
17736 int64_t **stride_lengths,
17737 int64_t **n_values_per_frame,
17738 char **block_types,
17739 char **dependencies,
17740 char **compressions)
17742 tng_gen_block_t block;
17743 int64_t orig_file_pos, file_pos;
17745 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17746 TNG_ASSERT(n_data_blocks, "TNG library: The pointer to n_data_blocks must not be NULL.");
17747 TNG_ASSERT(data_block_ids, "TNG library: The pointer to the list of data block IDs must not be NULL.");
17748 TNG_ASSERT(data_block_names, "TNG library: The pointer to the list of data block names must not be NULL.");
17749 TNG_ASSERT(stride_lengths, "TNG library: The pointer to the list of stride lengths must not be NULL.");
17751 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
17753 return(TNG_CRITICAL);
17756 orig_file_pos = ftello(tng_data->input_file);
17758 fseeko(tng_data->input_file, 0, SEEK_SET);
17761 *n_data_blocks = 0;
17763 tng_block_init(&block);
17765 while(file_pos < tng_data->input_file_len &&
17766 tng_block_header_read(tng_data, block) != TNG_CRITICAL)
17768 if(block->id > TNG_TRAJECTORY_FRAME_SET)
17772 file_pos += (block->block_contents_size + block->header_contents_size);
17773 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
17776 fseeko(tng_data->input_file, orig_file_pos, SEEK_SET);
17778 return(TNG_SUCCESS);
17781 tng_function_status DECLSPECDLLEXPORT tng_util_prepare_append_after_frame
17782 (const tng_trajectory_t tng_data,
17783 const int64_t prev_frame)
17785 tng_function_status stat;
17786 FILE *temp = tng_data->input_file;
17788 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17789 TNG_ASSERT(prev_frame >= 0, "TNG library: The previous frame must not be negative.");
17791 tng_data->input_file = tng_data->output_file;
17793 stat = tng_frame_set_of_frame_find(tng_data, prev_frame);
17794 if(stat != TNG_SUCCESS)
17799 tng_data->current_trajectory_frame_set_output_file_pos =
17800 tng_data->current_trajectory_frame_set_input_file_pos;
17802 tng_data->input_file = temp;
17804 return(TNG_SUCCESS);
17807 tng_function_status DECLSPECDLLEXPORT tng_util_num_frames_with_data_of_block_id_get
17808 (const tng_trajectory_t tng_data,
17809 const int64_t block_id,
17812 int64_t curr_file_pos, first_frame_set_file_pos, curr_n_frames;
17813 tng_function_status stat;
17815 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17819 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
17821 return(TNG_CRITICAL);
17824 first_frame_set_file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
17825 curr_file_pos = ftello(tng_data->input_file);
17826 fseeko(tng_data->input_file, first_frame_set_file_pos, SEEK_SET);
17828 stat = tng_frame_set_n_frames_of_data_block_get(tng_data, block_id, &curr_n_frames);
17830 while(stat == TNG_SUCCESS && tng_data->current_trajectory_frame_set.next_frame_set_file_pos != -1)
17832 *n_frames += curr_n_frames;
17833 fseeko(tng_data->input_file,
17834 tng_data->current_trajectory_frame_set.next_frame_set_file_pos,
17836 stat = tng_frame_set_n_frames_of_data_block_get(tng_data, block_id, &curr_n_frames);
17838 if(stat == TNG_SUCCESS)
17840 *n_frames += curr_n_frames;
17842 fseeko(tng_data->input_file, curr_file_pos, SEEK_SET);
17843 if(stat == TNG_CRITICAL)
17845 return(TNG_CRITICAL);
17847 return(TNG_SUCCESS);