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);
5616 case TNG_FLOAT_DATA:
5617 if(tng_data->input_endianness_swap_func_32)
5619 for(i = 0; i < full_data_len; i+=size)
5621 if(tng_data->input_endianness_swap_func_32(tng_data,
5622 (int32_t *)((char *)data->values + i))
5625 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5626 __FILE__, __LINE__);
5632 case TNG_DOUBLE_DATA:
5633 if(tng_data->input_endianness_swap_func_64)
5635 for(i = 0; i < full_data_len; i+=size)
5637 if(tng_data->input_endianness_swap_func_64(tng_data,
5638 (int64_t *)((char *)data->values + i))
5641 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
5642 __FILE__, __LINE__);
5654 return(TNG_SUCCESS);
5658 * @brief Write a data block (particle or non-particle data)
5659 * @param tng_data is a trajectory data container.
5660 * @param block is the block to store the data (should already contain
5661 * the block headers and the block contents).
5662 * @param block_index is the index number of the data block in the frame set.
5663 * @param is_particle_data is a flag to specify if the data to write is
5664 * particle dependent or not.
5665 * @param mapping is the particle mapping that is relevant for the data block.
5666 * Only relevant if writing particle dependent data.
5667 * @param hash_mode is an option to decide whether to use the md5 hash or not.
5668 * If hash_mode == TNG_USE_HASH an md5 hash will be generated and written.
5669 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
5670 * error has occured.
5672 static tng_function_status tng_data_block_write(const tng_trajectory_t tng_data,
5673 const tng_gen_block_t block,
5674 const int64_t block_index,
5675 const tng_bool is_particle_data,
5676 const tng_particle_mapping_t mapping,
5677 const char hash_mode)
5679 int64_t n_particles, num_first_particle, n_frames, stride_length;
5680 int64_t full_data_len, block_data_len, frame_step, data_start_pos;
5681 int64_t i, j, k, curr_file_pos, header_file_pos;
5684 tng_function_status stat;
5685 char temp, *temp_name, ***first_dim_values, **second_dim_values, *contents;
5687 tng_trajectory_frame_set_t frame_set =
5688 &tng_data->current_trajectory_frame_set;
5690 char block_type_flag;
5691 md5_state_t md5_state;
5693 /* If we have already started writing frame sets it is too late to write
5694 * non-trajectory data blocks */
5695 if(tng_data->current_trajectory_frame_set_output_file_pos > 0)
5697 block_type_flag = TNG_TRAJECTORY_BLOCK;
5701 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
5704 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
5706 return(TNG_CRITICAL);
5709 if(is_particle_data == TNG_TRUE)
5711 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5713 data = &frame_set->tr_particle_data[block_index];
5715 /* If this data block has not had any data added in this frame set
5716 * do not write it. */
5717 if(data->first_frame_with_data < frame_set->first_frame)
5719 return(TNG_SUCCESS);
5722 stride_length = tng_max_i64(1, data->stride_length);
5726 data = &tng_data->non_tr_particle_data[block_index];
5732 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5734 data = &frame_set->tr_data[block_index];
5736 /* If this data block has not had any data added in this frame set
5737 * do not write it. */
5738 if(data->first_frame_with_data < frame_set->first_frame)
5740 return(TNG_SUCCESS);
5743 stride_length = tng_max_i64(1, data->stride_length);
5747 data = &tng_data->non_tr_data[block_index];
5752 switch(data->datatype)
5758 size = sizeof(int64_t);
5760 case TNG_FLOAT_DATA:
5761 size = sizeof(float);
5763 case TNG_DOUBLE_DATA:
5765 size = sizeof(double);
5768 len = strlen(data->block_name) + 1;
5770 if(!block->name || strlen(block->name) < len)
5772 temp_name = realloc(block->name, len);
5775 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIuPTR" bytes). %s: %d\n", len+1,
5776 __FILE__, __LINE__);
5779 return(TNG_CRITICAL);
5781 block->name = temp_name;
5783 strncpy(block->name, data->block_name, len);
5784 block->id = data->block_id;
5786 /* If writing frame independent data data->n_frames is 0, but n_frames
5787 is used for the loop writing the data (and reserving memory) and needs
5789 n_frames = tng_max_i64(1, data->n_frames);
5791 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
5793 /* If the frame set is finished before writing the full number of frames
5794 make sure the data block is not longer than the frame set. */
5795 n_frames = tng_min_i64(n_frames, frame_set->n_frames);
5797 n_frames -= (data->first_frame_with_data - frame_set->first_frame);
5800 frame_step = (n_frames % stride_length) ? n_frames / stride_length + 1:
5801 n_frames / stride_length;
5803 /* TNG compression will use compression precision to get integers from
5804 * floating point data. The compression multiplier stores that information
5805 * to be able to return the precision of the compressed data. */
5806 if(data->codec_id == TNG_TNG_COMPRESSION)
5808 data->compression_multiplier = tng_data->compression_precision;
5810 /* Uncompressed data blocks do not use compression multipliers at all.
5811 * GZip compression does not need it either. */
5812 else if(data->codec_id == TNG_UNCOMPRESSED || data->codec_id == TNG_GZIP_COMPRESSION)
5814 data->compression_multiplier = 1.0;
5817 if(data->dependency & TNG_PARTICLE_DEPENDENT)
5819 if(mapping && mapping->n_particles != 0)
5821 n_particles = mapping->n_particles;
5822 num_first_particle = mapping->num_first_particle;
5826 num_first_particle = 0;
5827 if(tng_data->var_num_atoms_flag)
5829 n_particles = frame_set->n_particles;
5833 n_particles = tng_data->n_particles;
5838 if(data->dependency & TNG_PARTICLE_DEPENDENT)
5840 if(tng_data_block_len_calculate(tng_data, data, TNG_TRUE, n_frames,
5841 frame_step, stride_length, num_first_particle,
5842 n_particles, &data_start_pos,
5843 &block->block_contents_size) != TNG_SUCCESS)
5845 fprintf(stderr, "TNG library: Cannot calculate length of particle data block. %s: %d\n",
5846 __FILE__, __LINE__);
5847 return(TNG_CRITICAL);
5852 if(tng_data_block_len_calculate(tng_data, data, TNG_FALSE, n_frames,
5853 frame_step, stride_length, 0,
5855 &block->block_contents_size) != TNG_SUCCESS)
5857 fprintf(stderr, "TNG library: Cannot calculate length of non-particle data block. %s: %d\n",
5858 __FILE__, __LINE__);
5859 return(TNG_CRITICAL);
5863 header_file_pos = ftello(tng_data->output_file);
5865 if(tng_block_header_write(tng_data, block) != TNG_SUCCESS)
5867 fprintf(stderr, "TNG library: Cannot write header of file %s. %s: %d\n",
5868 tng_data->output_file_path, __FILE__, __LINE__);
5869 return(TNG_CRITICAL);
5872 if(hash_mode == TNG_USE_HASH)
5874 md5_init(&md5_state);
5877 if(tng_file_output_numerical(tng_data, &data->datatype,
5878 sizeof(data->datatype),
5879 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5881 return(TNG_CRITICAL);
5884 if(tng_file_output_numerical(tng_data, &data->dependency,
5885 sizeof(data->dependency),
5886 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5888 return(TNG_CRITICAL);
5891 if(data->dependency & TNG_FRAME_DEPENDENT)
5893 if(stride_length > 1)
5901 if(tng_file_output_numerical(tng_data, &temp,
5903 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5905 return(TNG_CRITICAL);
5909 if(tng_file_output_numerical(tng_data, &data->n_values_per_frame,
5910 sizeof(data->n_values_per_frame),
5911 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5913 return(TNG_CRITICAL);
5916 if(tng_file_output_numerical(tng_data, &data->codec_id,
5917 sizeof(data->codec_id),
5918 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5920 return(TNG_CRITICAL);
5923 if(data->codec_id != TNG_UNCOMPRESSED)
5925 if(tng_file_output_numerical(tng_data, &data->compression_multiplier,
5926 sizeof(data->compression_multiplier),
5927 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5929 return(TNG_CRITICAL);
5933 if(data->n_frames > 0 && stride_length > 1)
5935 /* FIXME: first_frame_with_data is not reliably set */
5936 if(data->first_frame_with_data == 0)
5938 data->first_frame_with_data = frame_set->first_frame;
5940 if(tng_file_output_numerical(tng_data, &data->first_frame_with_data,
5941 sizeof(data->first_frame_with_data),
5942 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5944 return(TNG_CRITICAL);
5947 if(tng_file_output_numerical(tng_data, &stride_length,
5948 sizeof(stride_length),
5949 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5951 return(TNG_CRITICAL);
5955 if(data->dependency & TNG_PARTICLE_DEPENDENT)
5957 if(tng_file_output_numerical(tng_data, &num_first_particle,
5958 sizeof(num_first_particle),
5959 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5961 return(TNG_CRITICAL);
5964 if(tng_file_output_numerical(tng_data, &n_particles,
5965 sizeof(n_particles),
5966 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5968 return(TNG_CRITICAL);
5972 if(data->datatype == TNG_CHAR_DATA)
5976 if(data->dependency & TNG_PARTICLE_DEPENDENT)
5978 for(i = 0; i < frame_step; i++)
5980 first_dim_values = data->strings[i];
5981 for(j = num_first_particle; j < num_first_particle + n_particles;
5984 second_dim_values = first_dim_values[j];
5985 for(k = 0; k < data->n_values_per_frame; k++)
5987 if(tng_fwritestr(tng_data, second_dim_values[k],
5988 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
5990 return(TNG_CRITICAL);
5998 for(i = 0; i < frame_step; i++)
6000 for(j = 0; j < data->n_values_per_frame; j++)
6002 if(tng_fwritestr(tng_data, data->strings[0][i][j],
6003 hash_mode, &md5_state, __LINE__) == TNG_CRITICAL)
6005 return(TNG_CRITICAL);
6014 if(data->dependency & TNG_PARTICLE_DEPENDENT)
6016 full_data_len = size * frame_step * n_particles * data->n_values_per_frame;
6020 full_data_len = size * frame_step * data->n_values_per_frame;
6022 contents = malloc(full_data_len);
6025 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
6026 full_data_len, __FILE__, __LINE__);
6027 return(TNG_CRITICAL);
6032 memcpy(contents, data->values, full_data_len);
6033 switch(data->datatype)
6035 case TNG_FLOAT_DATA:
6036 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
6037 data->codec_id == TNG_TNG_COMPRESSION)
6039 if(tng_data->output_endianness_swap_func_32)
6041 for(i = 0; i < full_data_len; i+=size)
6043 if(tng_data->output_endianness_swap_func_32(tng_data,
6044 (int32_t *)(contents + i))
6047 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6048 __FILE__, __LINE__);
6055 multiplier = data->compression_multiplier;
6056 if(fabs(multiplier - 1.0) > 0.00001 ||
6057 tng_data->output_endianness_swap_func_32)
6059 for(i = 0; full_data_len; i+=size)
6061 *(float *)(contents + i) *= (float)multiplier;
6062 if(tng_data->output_endianness_swap_func_32 &&
6063 tng_data->output_endianness_swap_func_32(tng_data,
6064 (int32_t *)(contents + i))
6067 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6068 __FILE__, __LINE__);
6075 if(tng_data->output_endianness_swap_func_64)
6077 for(i = 0; i < full_data_len; i+=size)
6079 if(tng_data->output_endianness_swap_func_64(tng_data,
6080 (int64_t *)(contents + i))
6083 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6084 __FILE__, __LINE__);
6089 case TNG_DOUBLE_DATA:
6090 if(data->codec_id == TNG_UNCOMPRESSED || data-> codec_id == TNG_GZIP_COMPRESSION ||
6091 data->codec_id == TNG_TNG_COMPRESSION)
6093 if(tng_data->output_endianness_swap_func_64)
6095 for(i = 0; i < full_data_len; i+=size)
6097 if(tng_data->output_endianness_swap_func_64(tng_data,
6098 (int64_t *)(contents + i))
6101 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6102 __FILE__, __LINE__);
6109 multiplier = data->compression_multiplier;
6110 if(fabs(multiplier - 1.0) > 0.00001 ||
6111 tng_data->output_endianness_swap_func_64)
6113 for(i = 0; i < full_data_len; i+=size)
6115 *(double *)(contents + i) *= multiplier;
6116 if(tng_data->output_endianness_swap_func_64 &&
6117 tng_data->output_endianness_swap_func_64(tng_data,
6118 (int64_t *)(contents + i))
6121 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
6122 __FILE__, __LINE__);
6134 memset(contents, 0, full_data_len);
6137 block_data_len = full_data_len;
6139 switch(data->codec_id)
6141 case TNG_XTC_COMPRESSION:
6142 fprintf(stderr, "TNG library: XTC compression not implemented yet.\n");
6143 data->codec_id = TNG_UNCOMPRESSED;
6145 case TNG_TNG_COMPRESSION:
6146 stat = tng_compress(tng_data, block, frame_step,
6147 n_particles, data->datatype,
6148 &contents, &block_data_len);
6149 if(stat != TNG_SUCCESS)
6151 fprintf(stderr, "TNG library: Could not write tng compressed block data. %s: %d\n",
6152 __FILE__, __LINE__);
6153 if(stat == TNG_CRITICAL)
6155 return(TNG_CRITICAL);
6157 /* Set the data again, but with no compression (to write only
6158 * the relevant data) */
6159 data->codec_id = TNG_UNCOMPRESSED;
6160 stat = tng_data_block_write(tng_data, block,
6161 block_index, is_particle_data, mapping,
6168 case TNG_GZIP_COMPRESSION:
6169 /* fprintf(stderr, "TNG library: Before compression: %"PRId64"\n", block->block_contents_size); */
6170 stat = tng_gzip_compress(tng_data,
6174 if(stat != TNG_SUCCESS)
6176 fprintf(stderr, "TNG library: Could not write gzipped block data. %s: %d\n", __FILE__,
6178 if(stat == TNG_CRITICAL)
6180 return(TNG_CRITICAL);
6182 data->codec_id = TNG_UNCOMPRESSED;
6184 /* fprintf(stderr, "TNG library: After compression: %"PRId64"\n", block->block_contents_size); */
6188 if(block_data_len != full_data_len)
6190 block->block_contents_size -= full_data_len - block_data_len;
6192 curr_file_pos = ftello(tng_data->output_file);
6193 fseeko(tng_data->output_file, header_file_pos + sizeof(block->header_contents_size), SEEK_SET);
6195 if(tng_file_output_numerical(tng_data, &block->block_contents_size,
6196 sizeof(block->block_contents_size),
6197 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
6199 return(TNG_CRITICAL);
6201 fseeko(tng_data->output_file, curr_file_pos, SEEK_SET);
6203 if(fwrite(contents, block_data_len, 1, tng_data->output_file) != 1)
6205 fprintf(stderr, "TNG library: Could not write all block data. %s: %d\n", __FILE__,
6207 return(TNG_CRITICAL);
6209 if(hash_mode == TNG_USE_HASH)
6211 md5_append(&md5_state, (md5_byte_t *)contents, block_data_len);
6217 if(hash_mode == TNG_USE_HASH)
6219 md5_finish(&md5_state, (md5_byte_t *)block->md5_hash);
6220 curr_file_pos = ftello(tng_data->output_file);
6221 fseeko(tng_data->output_file, header_file_pos +
6222 3 * sizeof(int64_t), SEEK_SET);
6223 if(fwrite(block->md5_hash, TNG_MD5_HASH_LEN, 1, tng_data->output_file) != 1)
6225 fprintf(stderr, "TNG library: Could not write MD5 hash. %s: %d\n", __FILE__,
6227 return(TNG_CRITICAL);
6229 fseeko(tng_data->output_file, curr_file_pos, SEEK_SET);
6232 frame_set->n_written_frames += frame_set->n_unwritten_frames;
6233 frame_set->n_unwritten_frames = 0;
6235 return(TNG_SUCCESS);
6239 * @brief Read the meta information of a data block (particle or non-particle data).
6240 * @param tng_data is a trajectory data container.
6241 * @param datatype is set to the datatype of the data block.
6242 * @param dependency is set to the dependency (particle and/or frame dependent)
6243 * @param sparse_data is set to TRUE if data is not written every frame.
6244 * @param n_values is set to the number of values per frame of the data.
6245 * @param codec_id is set to the ID of the codec used to compress the data.
6246 * @param first_frame_with_data is set to the first frame with data (only relevant if
6247 * sparse_data == TRUE).
6248 * @param stride_length is set to the writing interval of the data (1 if sparse_data
6250 * @param num_first_particle is set to the number of the first particle with data written
6252 * @param block_n_particles is set to the number of particles in this data block.
6253 * @param multiplier is set to the compression multiplier.
6254 * @param hash_mode specifies whether to check if the hash matches the contents or not.
6255 * @param md5_state is the md5 hash of the block (only used if hash_mode == TNG_USE_HASH).
6256 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6257 * error has occured.
6259 static tng_function_status tng_data_block_meta_information_read
6260 (const tng_trajectory_t tng_data,
6266 int64_t *first_frame_with_data,
6267 int64_t *stride_length,
6269 int64_t *num_first_particle,
6270 int64_t *block_n_particles,
6272 const char hash_mode,
6273 md5_state_t *md5_state)
6275 if(tng_file_input_numerical(tng_data, datatype,
6277 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6279 return(TNG_CRITICAL);
6282 if(tng_file_input_numerical(tng_data, dependency,
6283 sizeof(*dependency),
6284 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6286 return(TNG_CRITICAL);
6289 if(*dependency & TNG_FRAME_DEPENDENT)
6291 if(tng_file_input_numerical(tng_data, sparse_data,
6292 sizeof(*sparse_data),
6293 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6295 return(TNG_CRITICAL);
6299 if(tng_file_input_numerical(tng_data, n_values,
6301 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6303 return(TNG_CRITICAL);
6306 if(tng_file_input_numerical(tng_data, codec_id,
6308 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6310 return(TNG_CRITICAL);
6313 if(*codec_id != TNG_UNCOMPRESSED)
6315 if(tng_file_input_numerical(tng_data, multiplier,
6316 sizeof(*multiplier),
6317 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6319 return(TNG_CRITICAL);
6327 if(*dependency & TNG_FRAME_DEPENDENT)
6331 if(tng_file_input_numerical(tng_data, first_frame_with_data,
6332 sizeof(*first_frame_with_data),
6333 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6335 return(TNG_CRITICAL);
6338 if(tng_file_input_numerical(tng_data, stride_length,
6339 sizeof(*stride_length),
6340 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6342 return(TNG_CRITICAL);
6345 *n_frames = tng_data->current_trajectory_frame_set.n_frames -
6346 (*first_frame_with_data -
6347 tng_data->current_trajectory_frame_set.first_frame);
6351 *first_frame_with_data = tng_data->current_trajectory_frame_set.first_frame;
6353 *n_frames = tng_data->current_trajectory_frame_set.n_frames;
6358 *first_frame_with_data = 0;
6363 if (*dependency & TNG_PARTICLE_DEPENDENT)
6365 if(tng_file_input_numerical(tng_data, num_first_particle,
6366 sizeof(*num_first_particle),
6367 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6369 return(TNG_CRITICAL);
6372 if(tng_file_input_numerical(tng_data, block_n_particles,
6373 sizeof(*block_n_particles),
6374 hash_mode, md5_state, __LINE__) == TNG_CRITICAL)
6376 return(TNG_CRITICAL);
6381 *num_first_particle = -1;
6382 *block_n_particles = 0;
6385 return(TNG_SUCCESS);
6389 * @brief Read the contents of a data block (particle or non-particle data).
6390 * @param tng_data is a trajectory data container.
6391 * @param block is the block to store the data (should already contain
6392 * the block headers).
6393 * @param hash_mode is an option to decide whether to use the md5 hash or not.
6394 * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be
6395 * compared to the md5 hash of the read contents to ensure valid data.
6396 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6397 * error has occured.
6399 static tng_function_status tng_data_block_contents_read
6400 (const tng_trajectory_t tng_data,
6401 const tng_gen_block_t block,
6402 const char hash_mode)
6404 int64_t start_pos, n_values, codec_id, n_frames, first_frame_with_data;
6405 int64_t remaining_len, stride_length, block_n_particles, num_first_particle;
6407 char datatype, dependency, sparse_data;
6408 tng_function_status stat = TNG_SUCCESS;
6409 char hash[TNG_MD5_HASH_LEN];
6410 md5_state_t md5_state;
6412 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
6414 return(TNG_CRITICAL);
6417 start_pos = ftello(tng_data->input_file);
6419 if(hash_mode == TNG_USE_HASH)
6421 md5_init(&md5_state);
6424 /* FIXME: Does not check if the size of the contents matches the expected
6425 * size or if the contents can be read. */
6427 if(tng_data_block_meta_information_read(tng_data,
6429 &dependency, &sparse_data,
6430 &n_values, &codec_id,
6431 &first_frame_with_data,
6432 &stride_length, &n_frames,
6433 &num_first_particle,
6437 &md5_state) == TNG_CRITICAL)
6439 fprintf(stderr, "TNG library: Cannot read data block (%s) meta information. %s: %d\n",
6440 block->name, __FILE__, __LINE__);
6441 return(TNG_CRITICAL);
6444 remaining_len = block->block_contents_size - (ftello(tng_data->input_file) - start_pos);
6446 stat = tng_data_read(tng_data, block,
6451 first_frame_with_data,
6454 codec_id, multiplier,
6458 if(hash_mode == TNG_USE_HASH)
6460 /* If there is data left in the block that the current version of the library
6461 * cannot interpret still read that to generate the MD5 hash. */
6462 tng_md5_remaining_append(tng_data, block, start_pos, &md5_state);
6464 md5_finish(&md5_state, (md5_byte_t *)hash);
6465 if(strncmp(block->md5_hash, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", TNG_MD5_HASH_LEN) != 0)
6467 if(strncmp(block->md5_hash, hash, TNG_MD5_HASH_LEN) != 0)
6469 fprintf(stderr, "TNG library: Data block contents corrupt (%s). Hashes do not match. "
6470 "%s: %d\n", block->name, __FILE__, __LINE__);
6476 /* Seek to the end of the block */
6477 fseeko(tng_data->input_file, start_pos + block->block_contents_size, SEEK_SET);
6484 // ** Move the blocks in a frame set so that there is no unused space between
6485 // * them. This can only be done on the last frame set in the file and should
6486 // * be done e.g. if the last frame set in the file has fewer frames than
6487 // * default or after compressing data blocks in a frame set.
6488 // * @param tng_data is a trajectory data container.
6489 // * @details the current_trajectory_frame_set is the one that will be modified.
6490 // * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if the frame set
6491 // * cannot be aligned or TNG_CRITICAL (2) if a major error has occured.
6492 // * FIXME: This function is not finished!!!
6494 // static tng_function_status tng_frame_set_align(tng_trajectory_t tng_data)
6496 // tng_gen_block_t block;
6497 // tng_trajectory_frame_set_t frame_set;
6498 // FILE *temp = tng_data->input_file;
6499 // int64_t pos, contents_start_pos, output_file_len;
6501 // frame_set = &tng_data->current_trajectory_frame_set;
6503 // if(frame_set->n_written_frames == frame_set->n_frames)
6505 // return(TNG_SUCCESS);
6508 // if(tng_data->current_trajectory_frame_set_output_file_pos !=
6509 // tng_data->last_trajectory_frame_set_output_file_pos)
6513 // if(tng_output_file_init(tng_data) != TNG_SUCCESS)
6515 // fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
6516 // __FILE__, __LINE__);
6517 // return(TNG_CRITICAL);
6520 // tng_block_init(&block);
6521 // // output_file_pos = ftello(tng_data->output_file);
6523 // tng_data->input_file = tng_data->output_file;
6525 // pos = tng_data->current_trajectory_frame_set_output_file_pos;
6527 // fseeko(tng_data->output_file, pos, SEEK_SET);
6528 // if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
6530 // fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
6531 // __FILE__, __LINE__);
6532 // tng_data->input_file = temp;
6533 // tng_block_destroy(&block);
6534 // return(TNG_CRITICAL);
6537 // contents_start_pos = ftello(tng_data->output_file);
6539 // fseeko(tng_data->output_file, 0, SEEK_END);
6540 // output_file_len = ftello(tng_data->output_file);
6541 // pos = contents_start_pos + block->block_contents_size;
6542 // fseeko(tng_data->output_file, pos,
6545 // while(pos < output_file_len)
6547 // if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
6549 // fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", pos,
6550 // __FILE__, __LINE__);
6551 // tng_data->input_file = temp;
6552 // tng_block_destroy(&block);
6553 // return(TNG_CRITICAL);
6555 // pos += block->header_contents_size + block->block_contents_size;
6556 // fseeko(tng_data->output_file, pos, SEEK_SET);
6559 // return(TNG_SUCCESS);
6563 * @brief Finish writing the current frame set. Update the number of frames
6564 * and the hashes of the frame set and all its data blocks (if hash_mode
6566 * @param tng_data is a trajectory data container.
6567 * @param hash_mode specifies whether to update the block md5 hash when
6568 * updating the pointers.
6569 * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6570 * error has occured.
6572 static tng_function_status tng_frame_set_finalize
6573 (const tng_trajectory_t tng_data,
6574 const char hash_mode)
6576 tng_gen_block_t block;
6577 tng_trajectory_frame_set_t frame_set;
6578 FILE *temp = tng_data->input_file;
6579 int64_t pos, curr_file_pos;
6581 frame_set = &tng_data->current_trajectory_frame_set;
6583 if(frame_set->n_written_frames == frame_set->n_frames)
6585 return(TNG_SUCCESS);
6588 frame_set->n_written_frames = frame_set->n_frames;
6590 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
6592 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
6593 __FILE__, __LINE__);
6594 return(TNG_CRITICAL);
6597 tng_block_init(&block);
6598 /* output_file_pos = ftello(tng_data->output_file); */
6600 tng_data->input_file = tng_data->output_file;
6602 curr_file_pos = ftello(tng_data->output_file);
6604 pos = tng_data->current_trajectory_frame_set_output_file_pos;
6606 fseeko(tng_data->output_file, pos, SEEK_SET);
6608 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
6610 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
6611 __FILE__, __LINE__);
6612 tng_data->input_file = temp;
6613 tng_block_destroy(&block);
6614 return(TNG_CRITICAL);
6617 // contents_start_pos = ftello(tng_data->output_file);
6619 fseeko(tng_data->output_file, sizeof(frame_set->first_frame), SEEK_CUR);
6620 if(fwrite(&frame_set->n_frames, sizeof(frame_set->n_frames),
6621 1, tng_data->output_file) != 1)
6623 tng_data->input_file = temp;
6624 tng_block_destroy(&block);
6625 return(TNG_CRITICAL);
6628 if(hash_mode == TNG_USE_HASH)
6630 tng_md5_hash_update(tng_data, block, pos,
6631 pos + block->header_contents_size);
6634 fseeko(tng_data->output_file, curr_file_pos, SEEK_SET);
6636 tng_data->input_file = temp;
6637 tng_block_destroy(&block);
6638 return(TNG_SUCCESS);
6642 // ** Sets the name of a file contents block
6643 // * @param tng_data is a trajectory data container.
6644 // * @param block is the block, of which to change names.
6645 // * @param new_name is the new name of the block.
6646 // * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major
6647 // * error has occured.
6649 // static tng_function_status tng_block_name_set(tng_trajectory_t tng_data,
6650 // tng_gen_block_t block,
6651 // const char *new_name)
6655 // len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
6657 // * If the currently stored string length is not enough to store the new
6658 // * string it is freed and reallocated. *
6659 // if(block->name && strlen(block->name) < len)
6661 // free(block->name);
6666 // block->name = malloc(len);
6669 // fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
6670 // __FILE__, __LINE__);
6671 // return(TNG_CRITICAL);
6675 // strncpy(block->name, new_name, len);
6677 // return(TNG_SUCCESS);
6681 tng_function_status DECLSPECDLLEXPORT tng_atom_residue_get
6682 (const tng_trajectory_t tng_data,
6683 const tng_atom_t atom,
6684 tng_residue_t *residue)
6688 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
6690 *residue = atom->residue;
6692 return(TNG_SUCCESS);
6695 tng_function_status DECLSPECDLLEXPORT tng_atom_name_get
6696 (const tng_trajectory_t tng_data,
6697 const tng_atom_t atom,
6702 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
6703 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
6705 strncpy(name, atom->name, max_len - 1);
6706 name[max_len - 1] = 0;
6708 if(strlen(atom->name) > (unsigned int)max_len - 1)
6710 return(TNG_FAILURE);
6712 return(TNG_SUCCESS);
6715 tng_function_status DECLSPECDLLEXPORT tng_atom_name_set
6716 (const tng_trajectory_t tng_data,
6717 const tng_atom_t atom,
6718 const char *new_name)
6723 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
6724 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
6726 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
6728 /* If the currently stored string length is not enough to store the new
6729 * string it is freed and reallocated. */
6730 if(atom->name && strlen(atom->name) < len)
6737 atom->name = malloc(len);
6740 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
6741 __FILE__, __LINE__);
6742 return(TNG_CRITICAL);
6746 strncpy(atom->name, new_name, len);
6748 return(TNG_SUCCESS);
6751 tng_function_status DECLSPECDLLEXPORT tng_atom_type_get
6752 (const tng_trajectory_t tng_data,
6753 const tng_atom_t atom,
6758 TNG_ASSERT(atom, "TNG library: atom must not be NULL");
6759 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer");
6761 strncpy(type, atom->atom_type, max_len - 1);
6762 type[max_len - 1] = 0;
6764 if(strlen(atom->atom_type) > (unsigned int)max_len - 1)
6766 return(TNG_FAILURE);
6768 return(TNG_SUCCESS);
6771 tng_function_status DECLSPECDLLEXPORT tng_atom_type_set
6772 (const tng_trajectory_t tng_data,
6773 const tng_atom_t atom,
6774 const char *new_type)
6779 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
6780 TNG_ASSERT(new_type, "TNG library: new_type must not be a NULL pointer.");
6782 len = tng_min_size(strlen(new_type) + 1, TNG_MAX_STR_LEN);
6784 /* If the currently stored string length is not enough to store the new
6785 * string it is freed and reallocated. */
6786 if(atom->atom_type && strlen(atom->atom_type) < len)
6788 free(atom->atom_type);
6789 atom->atom_type = 0;
6791 if(!atom->atom_type)
6793 atom->atom_type = malloc(len);
6794 if(!atom->atom_type)
6796 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
6797 __FILE__, __LINE__);
6798 return(TNG_CRITICAL);
6802 strncpy(atom->atom_type, new_type, len);
6804 return(TNG_SUCCESS);
6808 * @brief Initialise an atom struct
6809 * @param atom is the atom to initialise.
6810 * @return TNG_SUCCESS (0) if successful.
6812 static tng_function_status tng_atom_init(const tng_atom_t atom)
6815 atom->atom_type = 0;
6817 return(TNG_SUCCESS);
6821 * @brief Free the memory in an atom struct
6822 * @param atom is the atom to destroy.
6823 * @return TNG_SUCCESS (0) if successful.
6825 static tng_function_status tng_atom_destroy(const tng_atom_t atom)
6834 free(atom->atom_type);
6835 atom->atom_type = 0;
6838 return(TNG_SUCCESS);
6842 * @brief Update chain->residue pointers (after new memory for
6843 * molecule->residues has been allocated).
6844 * @param tng_data The trajectory container containing the molecule.
6845 * @param mol The molecule that contains the chains that need to be
6847 * @returns TNG_SUCCESS (0) if successful.
6849 static tng_function_status tng_molecule_chains_residue_pointers_update
6850 (const tng_trajectory_t tng_data,
6851 const tng_molecule_t mol)
6854 int64_t i, res_cnt = 0;
6857 for(i = 0; i < mol->n_chains; i++)
6859 chain = &mol->chains[i];
6860 chain->residues = mol->residues + res_cnt;
6861 res_cnt += chain->n_residues;
6863 return(TNG_SUCCESS);
6866 tng_function_status DECLSPECDLLEXPORT tng_version_major
6867 (const tng_trajectory_t tng_data,
6872 *version = TNG_VERSION_MAJOR;
6874 return(TNG_SUCCESS);
6877 tng_function_status DECLSPECDLLEXPORT tng_version_minor
6878 (const tng_trajectory_t tng_data,
6883 *version = TNG_VERSION_MINOR;
6885 return(TNG_SUCCESS);
6888 tng_function_status DECLSPECDLLEXPORT tng_version_patchlevel
6889 (const tng_trajectory_t tng_data,
6894 *patch_level = TNG_VERSION_PATCHLEVEL;
6896 return(TNG_SUCCESS);
6899 tng_function_status DECLSPECDLLEXPORT tng_version
6900 (const tng_trajectory_t tng_data,
6905 TNG_ASSERT(version, "TNG library: version must not be a NULL pointer");
6907 TNG_SNPRINTF(version, max_len, "%s", TNG_VERSION);
6909 return(TNG_SUCCESS);
6912 tng_function_status DECLSPECDLLEXPORT tng_molecule_add
6913 (const tng_trajectory_t tng_data,
6915 tng_molecule_t *molecule)
6919 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
6920 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
6922 /* Set ID to the ID of the last molecule + 1 */
6923 if(tng_data->n_molecules)
6925 id = tng_data->molecules[tng_data->n_molecules-1].id + 1;
6932 return(tng_molecule_w_id_add(tng_data, name, id, molecule));
6935 tng_function_status DECLSPECDLLEXPORT tng_molecule_w_id_add
6936 (const tng_trajectory_t tng_data,
6939 tng_molecule_t *molecule)
6941 tng_molecule_t new_molecules;
6942 int64_t *new_molecule_cnt_list;
6943 tng_function_status stat = TNG_SUCCESS;
6945 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
6946 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
6948 new_molecules = realloc(tng_data->molecules,
6949 sizeof(struct tng_molecule) *
6950 (tng_data->n_molecules + 1));
6954 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
6955 sizeof(struct tng_molecule) * (tng_data->n_molecules + 1),
6956 __FILE__, __LINE__);
6957 free(tng_data->molecules);
6958 tng_data->molecules = 0;
6959 return(TNG_CRITICAL);
6962 new_molecule_cnt_list = realloc(tng_data->molecule_cnt_list,
6964 (tng_data->n_molecules + 1));
6966 if(!new_molecule_cnt_list)
6968 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
6969 sizeof(int64_t) * (tng_data->n_molecules + 1),
6970 __FILE__, __LINE__);
6971 free(tng_data->molecule_cnt_list);
6972 tng_data->molecule_cnt_list = 0;
6973 free(new_molecules);
6974 return(TNG_CRITICAL);
6977 tng_data->molecules = new_molecules;
6978 tng_data->molecule_cnt_list = new_molecule_cnt_list;
6980 *molecule = &new_molecules[tng_data->n_molecules];
6982 tng_molecule_init(tng_data, *molecule);
6983 tng_molecule_name_set(tng_data, *molecule, name);
6985 /* FIXME: Should this be a function argument instead? */
6986 tng_data->molecule_cnt_list[tng_data->n_molecules] = 0;
6988 (*molecule)->id = id;
6990 tng_data->n_molecules++;
6995 tng_function_status DECLSPECDLLEXPORT tng_molecule_existing_add
6996 (const tng_trajectory_t tng_data,
6997 tng_molecule_t *molecule_p)
6999 int64_t *new_molecule_cnt_list, id;
7000 tng_molecule_t new_molecules, molecule;
7002 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7004 /* Set ID to the ID of the last molecule + 1 */
7005 if(tng_data->n_molecules)
7007 id = tng_data->molecules[tng_data->n_molecules-1].id + 1;
7014 new_molecules = realloc(tng_data->molecules,
7015 sizeof(struct tng_molecule) *
7016 (tng_data->n_molecules + 1));
7020 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
7021 sizeof(struct tng_molecule) * (tng_data->n_molecules + 1),
7022 __FILE__, __LINE__);
7023 free(tng_data->molecules);
7024 tng_data->molecules = 0;
7025 return(TNG_CRITICAL);
7028 new_molecule_cnt_list = realloc(tng_data->molecule_cnt_list,
7030 (tng_data->n_molecules + 1));
7032 if(!new_molecule_cnt_list)
7034 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
7035 sizeof(int64_t) * (tng_data->n_molecules + 1),
7036 __FILE__, __LINE__);
7037 free(tng_data->molecule_cnt_list);
7038 tng_data->molecule_cnt_list = 0;
7039 free(new_molecules);
7040 return(TNG_CRITICAL);
7043 molecule = *molecule_p;
7045 tng_data->molecules = new_molecules;
7046 tng_data->molecule_cnt_list = new_molecule_cnt_list;
7048 new_molecules[tng_data->n_molecules] = *molecule;
7050 tng_data->molecule_cnt_list[tng_data->n_molecules] = 0;
7054 molecule = &new_molecules[tng_data->n_molecules];
7056 *molecule_p = molecule;
7060 tng_data->n_molecules++;
7062 return(TNG_SUCCESS);
7065 tng_function_status tng_molecule_name_get(const tng_trajectory_t tng_data,
7066 const tng_molecule_t molecule,
7071 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
7072 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
7074 strncpy(name, molecule->name, max_len - 1);
7075 name[max_len - 1] = 0;
7077 if(strlen(molecule->name) > (unsigned int)max_len - 1)
7079 return(TNG_FAILURE);
7081 return(TNG_SUCCESS);
7084 tng_function_status DECLSPECDLLEXPORT tng_molecule_name_set
7085 (const tng_trajectory_t tng_data,
7086 const tng_molecule_t molecule,
7087 const char *new_name)
7092 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7093 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
7095 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
7097 /* If the currently stored string length is not enough to store the new
7098 * string it is freed and reallocated. */
7099 if(molecule->name && strlen(molecule->name) < len)
7101 free(molecule->name);
7106 molecule->name = malloc(len);
7109 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
7110 __FILE__, __LINE__);
7111 return(TNG_CRITICAL);
7115 strncpy(molecule->name, new_name, len);
7117 return(TNG_SUCCESS);
7120 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_get
7121 (const tng_trajectory_t tng_data,
7122 const tng_molecule_t molecule,
7125 int64_t i, index = -1;
7127 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7128 TNG_ASSERT(cnt, "TNG library: cnt must not be a NULL pointer.");
7130 for(i = 0; i < tng_data->n_molecules; i++)
7132 if(&tng_data->molecules[i] == molecule)
7140 return(TNG_FAILURE);
7142 *cnt = tng_data->molecule_cnt_list[index];
7144 return(TNG_SUCCESS);
7147 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_set
7148 (const tng_trajectory_t tng_data,
7149 const tng_molecule_t molecule,
7152 int64_t i, old_cnt, index = -1;
7154 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7156 for(i = 0; i < tng_data->n_molecules; i++)
7158 if(&tng_data->molecules[i] == molecule)
7166 fprintf(stderr, "TNG library: Could not find molecule in TNG trajectory. %s: %d\n",
7167 __FILE__, __LINE__);
7168 return(TNG_FAILURE);
7170 if(tng_data->var_num_atoms_flag == TNG_CONSTANT_N_ATOMS)
7172 old_cnt = tng_data->molecule_cnt_list[index];
7173 tng_data->molecule_cnt_list[index] = cnt;
7175 tng_data->n_particles += (cnt-old_cnt) *
7176 tng_data->molecules[index].n_atoms;
7180 old_cnt = tng_data->current_trajectory_frame_set.molecule_cnt_list[index];
7181 tng_data->current_trajectory_frame_set.molecule_cnt_list[index] = cnt;
7183 tng_data->current_trajectory_frame_set.n_particles += (cnt-old_cnt) *
7184 tng_data->molecules[index].n_atoms;
7187 return(TNG_SUCCESS);
7190 tng_function_status DECLSPECDLLEXPORT tng_molecule_find
7191 (const tng_trajectory_t tng_data,
7194 tng_molecule_t *molecule)
7196 int64_t i, n_molecules;
7198 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7199 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7200 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
7202 n_molecules = tng_data->n_molecules;
7204 for(i = n_molecules - 1; i >= 0; i--)
7206 *molecule = &tng_data->molecules[i];
7207 if(name[0] == 0 || strcmp(name, (*molecule)->name) == 0)
7209 if(nr == -1 || nr == (*molecule)->id)
7211 return(TNG_SUCCESS);
7218 return(TNG_FAILURE);
7221 tng_function_status DECLSPECDLLEXPORT tng_molecule_of_index_get
7222 (const tng_trajectory_t tng_data,
7223 const int64_t index,
7224 tng_molecule_t *molecule)
7226 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7227 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
7229 if(index >= tng_data->n_molecules)
7232 return(TNG_FAILURE);
7234 *molecule = &tng_data->molecules[index];
7235 return(TNG_SUCCESS);
7238 tng_function_status DECLSPECDLLEXPORT tng_molecule_system_copy(const tng_trajectory_t tng_data_src,
7239 const tng_trajectory_t tng_data_dest)
7241 tng_molecule_t molecule, molecule_temp;
7242 tng_chain_t chain, chain_temp;
7243 tng_residue_t residue, residue_temp;
7244 tng_atom_t atom, atom_temp;
7245 tng_bond_t bond_temp;
7246 tng_function_status stat;
7247 int64_t i, j, k, l, *list_temp;
7249 TNG_ASSERT(tng_data_src, "TNG library: Trajectory container not properly setup.");
7250 TNG_ASSERT(tng_data_dest, "TNG library: Trajectory container not properly setup.");
7252 for(i = 0; i < tng_data_dest->n_molecules; i++)
7254 molecule = &tng_data_dest->molecules[i];
7255 tng_molecule_destroy(tng_data_dest, molecule);
7258 tng_data_dest->n_molecules = 0;
7259 tng_data_dest->n_particles = 0;
7261 molecule_temp = realloc(tng_data_dest->molecules,
7262 sizeof(struct tng_molecule) * tng_data_src->n_molecules);
7265 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
7266 sizeof(struct tng_molecule) * tng_data_src->n_molecules,
7267 __FILE__, __LINE__);
7268 free(tng_data_dest->molecules);
7269 tng_data_dest->molecules = 0;
7270 return(TNG_CRITICAL);
7272 list_temp = realloc(tng_data_dest->molecule_cnt_list,
7273 sizeof(int64_t) * tng_data_src->n_molecules);
7276 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
7277 sizeof(int64_t) * tng_data_src->n_molecules,
7278 __FILE__, __LINE__);
7279 free(tng_data_dest->molecule_cnt_list);
7280 tng_data_dest->molecule_cnt_list = 0;
7281 free(molecule_temp);
7282 return(TNG_CRITICAL);
7285 tng_data_dest->molecules = molecule_temp;
7286 tng_data_dest->molecule_cnt_list = list_temp;
7288 for(i = 0; i < tng_data_src->n_molecules; i++)
7290 molecule = &tng_data_src->molecules[i];
7291 stat = tng_molecule_w_id_add(tng_data_dest, molecule->name, molecule->id,
7293 if(stat != TNG_SUCCESS)
7295 fprintf(stderr, "TNG library: Cannot create new molecule to make a copy. %s: %d\n",
7296 __FILE__, __LINE__);
7299 molecule_temp->quaternary_str = molecule->quaternary_str;
7300 for(j = 0; j < molecule->n_chains; j++)
7302 chain = &molecule->chains[j];
7303 stat = tng_molecule_chain_w_id_add(tng_data_dest, molecule_temp,
7304 chain->name, chain->id,
7306 if(stat != TNG_SUCCESS)
7308 fprintf(stderr, "TNG library: Cannot create new chain to make a copy. %s: %d\n",
7309 __FILE__, __LINE__);
7312 for(k = 0; k < chain->n_residues; k++)
7314 residue = &chain->residues[k];
7315 stat = tng_chain_residue_w_id_add(tng_data_dest, chain_temp,
7316 residue->name, residue->id,
7318 if(stat != TNG_SUCCESS)
7320 fprintf(stderr, "TNG library: Cannot create new residue to make a copy. %s: %d\n",
7321 __FILE__, __LINE__);
7324 for(l = 0; l < residue->n_atoms; l++)
7326 atom = &molecule->atoms[residue->atoms_offset + l];
7327 stat = tng_residue_atom_w_id_add(tng_data_dest, residue_temp,
7328 atom->name, atom->atom_type,
7329 atom->id, &atom_temp);
7330 if(stat != TNG_SUCCESS)
7332 fprintf(stderr, "TNG library: Cannot create new atom to make a copy. %s: %d\n",
7333 __FILE__, __LINE__);
7339 molecule_temp->n_bonds = molecule->n_bonds;
7340 if(molecule->n_bonds > 0)
7342 bond_temp = realloc(molecule_temp->bonds, sizeof(struct tng_bond) *
7346 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
7347 sizeof(struct tng_bond) * molecule->n_bonds,
7348 __FILE__, __LINE__);
7349 free(molecule_temp->bonds);
7350 molecule_temp->n_bonds = 0;
7351 return(TNG_CRITICAL);
7353 molecule_temp->bonds = bond_temp;
7354 for(j = 0; j < molecule->n_bonds; j++)
7356 molecule_temp->bonds[j] = molecule->bonds[j];
7359 stat = tng_molecule_cnt_set(tng_data_dest, molecule_temp,
7360 tng_data_src->molecule_cnt_list[i]);
7361 if(stat != TNG_SUCCESS)
7363 fprintf(stderr, "TNG library: Cannot set molecule count. %s: %d.\n",
7364 __FILE__, __LINE__);
7368 return(TNG_SUCCESS);
7371 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_chains_get
7372 (const tng_trajectory_t tng_data,
7373 const tng_molecule_t molecule,
7377 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
7378 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
7380 *n = molecule->n_chains;
7382 return(TNG_SUCCESS);
7385 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_of_index_get
7386 (const tng_trajectory_t tng_data,
7387 const tng_molecule_t molecule,
7388 const int64_t index,
7392 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
7393 TNG_ASSERT(chain, "TNG library: chain must not be a NULL pointer.");
7395 if(index >= molecule->n_chains)
7398 return(TNG_FAILURE);
7400 *chain = &molecule->chains[index];
7401 return(TNG_SUCCESS);
7404 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_residues_get
7405 (const tng_trajectory_t tng_data,
7406 const tng_molecule_t molecule,
7410 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
7411 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
7413 *n = molecule->n_residues;
7415 return(TNG_SUCCESS);
7418 tng_function_status DECLSPECDLLEXPORT tng_molecule_residue_of_index_get
7419 (const tng_trajectory_t tng_data,
7420 const tng_molecule_t molecule,
7421 const int64_t index,
7422 tng_residue_t *residue)
7425 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
7426 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
7428 if(index >= molecule->n_residues)
7431 return(TNG_FAILURE);
7433 *residue = &molecule->residues[index];
7434 return(TNG_SUCCESS);
7437 tng_function_status DECLSPECDLLEXPORT tng_molecule_num_atoms_get
7438 (const tng_trajectory_t tng_data,
7439 const tng_molecule_t molecule,
7443 TNG_ASSERT(molecule, "TNG library: molecule must not be NULL");
7444 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
7446 *n = molecule->n_atoms;
7448 return(TNG_SUCCESS);
7451 tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_of_index_get
7452 (const tng_trajectory_t tng_data,
7453 const tng_molecule_t molecule,
7454 const int64_t index,
7458 TNG_ASSERT(molecule, "TNG library: molecule must not be a NULL pointer.");
7459 TNG_ASSERT(atom, "TNG library: atom must not be a NULL pointer.");
7461 if(index >= molecule->n_atoms)
7464 return(TNG_FAILURE);
7466 *atom = &molecule->atoms[index];
7467 return(TNG_SUCCESS);
7470 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_find
7471 (const tng_trajectory_t tng_data,
7472 const tng_molecule_t molecule,
7477 int64_t i, n_chains;
7480 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7481 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7483 n_chains = molecule->n_chains;
7485 for(i = n_chains - 1; i >= 0; i--)
7487 *chain = &molecule->chains[i];
7488 if(name[0] == 0 || strcmp(name, (*chain)->name) == 0)
7490 if(nr == -1 || nr == (*chain)->id)
7492 return(TNG_SUCCESS);
7499 return(TNG_FAILURE);
7502 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_add
7503 (const tng_trajectory_t tng_data,
7504 const tng_molecule_t molecule,
7510 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7511 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7513 /* Set ID to the ID of the last chain + 1 */
7514 if(molecule->n_chains)
7516 id = molecule->chains[molecule->n_chains-1].id + 1;
7523 return(tng_molecule_chain_w_id_add(tng_data, molecule, name,
7527 tng_function_status DECLSPECDLLEXPORT tng_molecule_chain_w_id_add
7528 (const tng_trajectory_t tng_data,
7529 const tng_molecule_t molecule,
7534 tng_chain_t new_chains;
7535 tng_function_status stat = TNG_SUCCESS;
7537 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7538 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7540 new_chains = realloc(molecule->chains,
7541 sizeof(struct tng_chain) *
7542 (molecule->n_chains + 1));
7546 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
7547 sizeof(struct tng_chain) * (molecule->n_chains + 1),
7548 __FILE__, __LINE__);
7549 free(molecule->chains);
7550 molecule->chains = 0;
7551 return(TNG_CRITICAL);
7554 molecule->chains = new_chains;
7556 *chain = &new_chains[molecule->n_chains];
7559 tng_chain_name_set(tng_data, *chain, name);
7561 (*chain)->molecule = molecule;
7562 (*chain)->n_residues = 0;
7564 molecule->n_chains++;
7571 tng_function_status DECLSPECDLLEXPORT tng_molecule_bond_add
7572 (const tng_trajectory_t tng_data,
7573 const tng_molecule_t molecule,
7574 const int64_t from_atom_id,
7575 const int64_t to_atom_id,
7578 tng_bond_t new_bonds;
7581 new_bonds = realloc(molecule->bonds,
7582 sizeof(struct tng_bond) *
7583 (molecule->n_bonds + 1));
7587 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
7588 sizeof(struct tng_bond) * (molecule->n_bonds + 1),
7589 __FILE__, __LINE__);
7591 free(molecule->bonds);
7592 molecule->bonds = 0;
7593 return(TNG_CRITICAL);
7596 molecule->bonds = new_bonds;
7598 *bond = &new_bonds[molecule->n_bonds];
7600 (*bond)->from_atom_id = from_atom_id;
7601 (*bond)->to_atom_id = to_atom_id;
7603 molecule->n_bonds++;
7605 return(TNG_SUCCESS);
7608 tng_function_status DECLSPECDLLEXPORT tng_molecule_atom_find
7609 (const tng_trajectory_t tng_data,
7610 const tng_molecule_t molecule,
7618 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7620 n_atoms = molecule->n_atoms;
7622 for(i = n_atoms - 1; i >= 0; i--)
7624 *atom = &molecule->atoms[i];
7625 if(name[0] == 0 || strcmp(name, (*atom)->name) == 0)
7627 if(id == -1 || id == (*atom)->id)
7629 return(TNG_SUCCESS);
7636 return(TNG_FAILURE);
7639 tng_function_status tng_chain_name_get(const tng_trajectory_t tng_data,
7640 const tng_chain_t chain,
7645 TNG_ASSERT(chain, "TNG library: chain must not be NULL");
7646 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
7648 strncpy(name, chain->name, max_len - 1);
7649 name[max_len - 1] = 0;
7651 if(strlen(chain->name) > (unsigned int)max_len - 1)
7653 return(TNG_FAILURE);
7655 return(TNG_SUCCESS);
7658 tng_function_status DECLSPECDLLEXPORT tng_chain_name_set
7659 (const tng_trajectory_t tng_data,
7660 const tng_chain_t chain,
7661 const char *new_name)
7666 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer.");
7668 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
7670 /* If the currently stored string length is not enough to store the new
7671 * string it is freed and reallocated. */
7672 if(chain->name && strlen(chain->name) < len)
7679 chain->name = malloc(len);
7682 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
7683 __FILE__, __LINE__);
7684 return(TNG_CRITICAL);
7688 strncpy(chain->name, new_name, len);
7690 return(TNG_SUCCESS);
7693 tng_function_status DECLSPECDLLEXPORT tng_chain_num_residues_get
7694 (const tng_trajectory_t tng_data,
7695 const tng_chain_t chain,
7699 TNG_ASSERT(chain, "TNG library: chain must not be NULL");
7700 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
7702 *n = chain->n_residues;
7704 return(TNG_SUCCESS);
7707 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_of_index_get
7708 (const tng_trajectory_t tng_data,
7709 const tng_chain_t chain,
7710 const int64_t index,
7711 tng_residue_t *residue)
7714 TNG_ASSERT(chain, "TNG library: chain must not be a NULL pointer.");
7715 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
7717 if(index >= chain->n_residues)
7720 return(TNG_FAILURE);
7722 *residue = &chain->residues[index];
7723 return(TNG_SUCCESS);
7726 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_find
7727 (const tng_trajectory_t tng_data,
7728 const tng_chain_t chain,
7731 tng_residue_t *residue)
7733 int64_t i, n_residues;
7736 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7738 n_residues = chain->n_residues;
7740 for(i = n_residues - 1; i >= 0; i--)
7742 *residue = &chain->residues[i];
7743 if(name[0] == 0 || strcmp(name, (*residue)->name) == 0)
7745 if(id == -1 || id == (*residue)->id)
7747 return(TNG_SUCCESS);
7754 return(TNG_FAILURE);
7757 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_add
7758 (const tng_trajectory_t tng_data,
7759 const tng_chain_t chain,
7761 tng_residue_t *residue)
7765 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7766 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7768 /* Set ID to the ID of the last residue + 1 */
7769 if(chain->n_residues)
7771 id = chain->residues[chain->n_residues-1].id + 1;
7778 return(tng_chain_residue_w_id_add(tng_data, chain, name,
7782 tng_function_status DECLSPECDLLEXPORT tng_chain_residue_w_id_add
7783 (const tng_trajectory_t tng_data,
7784 const tng_chain_t chain,
7787 tng_residue_t *residue)
7790 tng_residue_t new_residues, temp_residue, last_residue;
7791 tng_molecule_t molecule = chain->molecule;
7792 tng_function_status stat = TNG_SUCCESS;
7794 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7795 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
7797 if(chain->n_residues)
7799 curr_index = chain->residues - molecule->residues;
7806 new_residues = realloc(molecule->residues,
7807 sizeof(struct tng_residue) *
7808 (molecule->n_residues + 1));
7812 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
7813 sizeof(struct tng_residue) * (molecule->n_residues + 1),
7814 __FILE__, __LINE__);
7815 free(molecule->residues);
7816 molecule->residues = 0;
7817 return(TNG_CRITICAL);
7820 molecule->residues = new_residues;
7822 if(curr_index != -1)
7824 chain->residues = new_residues + curr_index;
7825 if(molecule->n_residues)
7827 last_residue = &new_residues[molecule->n_residues - 1];
7829 temp_residue = chain->residues + (chain->n_residues - 1);
7830 /* Make space in list of residues to add the new residues together with the other
7831 * residues of this chain */
7832 if(temp_residue != last_residue)
7835 memmove(temp_residue + 1, temp_residue,
7836 last_residue - temp_residue);
7842 curr_index = molecule->n_residues;
7845 *residue = &molecule->residues[curr_index + chain->n_residues];
7847 tng_molecule_chains_residue_pointers_update(tng_data, molecule);
7849 (*residue)->name = 0;
7850 tng_residue_name_set(tng_data, *residue, name);
7852 (*residue)->chain = chain;
7853 (*residue)->n_atoms = 0;
7854 (*residue)->atoms_offset = 0;
7856 chain->n_residues++;
7857 molecule->n_residues++;
7859 (*residue)->id = id;
7864 tng_function_status tng_residue_name_get(const tng_trajectory_t tng_data,
7865 const tng_residue_t residue,
7870 TNG_ASSERT(residue, "TNG library: residue must not be NULL");
7871 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
7873 strncpy(name, residue->name, max_len - 1);
7874 name[max_len - 1] = 0;
7876 if(strlen(residue->name) > (unsigned int)max_len - 1)
7878 return(TNG_FAILURE);
7880 return(TNG_SUCCESS);
7883 tng_function_status DECLSPECDLLEXPORT tng_residue_name_set(const tng_trajectory_t tng_data,
7884 const tng_residue_t residue,
7885 const char *new_name)
7890 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7891 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
7893 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
7895 /* If the currently stored string length is not enough to store the new
7896 * string it is freed and reallocated. */
7897 if(residue->name && strlen(residue->name) < len)
7899 free(residue->name);
7904 residue->name = malloc(len);
7907 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
7908 __FILE__, __LINE__);
7909 return(TNG_CRITICAL);
7913 strncpy(residue->name, new_name, len);
7915 return(TNG_SUCCESS);
7918 tng_function_status DECLSPECDLLEXPORT tng_residue_num_atoms_get
7919 (const tng_trajectory_t tng_data,
7920 const tng_residue_t residue,
7924 TNG_ASSERT(residue, "TNG library: residue must not be NULL");
7925 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
7927 *n = residue->n_atoms;
7929 return(TNG_SUCCESS);
7932 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_of_index_get
7933 (const tng_trajectory_t tng_data,
7934 const tng_residue_t residue,
7935 const int64_t index,
7939 tng_molecule_t molecule;
7942 TNG_ASSERT(residue, "TNG library: residue must not be a NULL pointer.");
7943 TNG_ASSERT(atom, "TNG library: atom must not be a NULL pointer.");
7945 if(index >= residue->n_atoms)
7948 return(TNG_FAILURE);
7950 chain = residue->chain;
7951 molecule = chain->molecule;
7953 if(index + residue->atoms_offset >= molecule->n_atoms)
7956 return(TNG_FAILURE);
7959 *atom = &molecule->atoms[residue->atoms_offset + index];
7960 return(TNG_SUCCESS);
7963 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_add
7964 (const tng_trajectory_t tng_data,
7965 const tng_residue_t residue,
7966 const char *atom_name,
7967 const char *atom_type,
7972 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
7973 TNG_ASSERT(atom_name, "TNG library: atom_name must not be a NULL pointer.");
7974 TNG_ASSERT(atom_type, "TNG library: atom_type must not be a NULL pointer.");
7976 /* Set ID to the ID of the last atom + 1 */
7977 if(residue->chain->molecule->n_atoms)
7979 id = residue->chain->molecule->atoms[residue->chain->molecule->n_atoms-1].id + 1;
7986 return(tng_residue_atom_w_id_add(tng_data, residue, atom_name, atom_type,
7990 tng_function_status DECLSPECDLLEXPORT tng_residue_atom_w_id_add
7991 (const tng_trajectory_t tng_data,
7992 const tng_residue_t residue,
7993 const char *atom_name,
7994 const char *atom_type,
7998 tng_atom_t new_atoms;
7999 tng_molecule_t molecule = residue->chain->molecule;
8000 tng_function_status stat = TNG_SUCCESS;
8002 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8003 TNG_ASSERT(atom_name, "TNG library: atom_name must not be a NULL pointer.");
8004 TNG_ASSERT(atom_type, "TNG library: atom_type must not be a NULL pointer.");
8006 if(!residue->n_atoms)
8008 residue->atoms_offset = molecule->n_atoms;
8011 new_atoms = realloc(molecule->atoms,
8012 sizeof(struct tng_atom) *
8013 (molecule->n_atoms + 1));
8017 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
8018 sizeof(struct tng_atom) * (molecule->n_atoms + 1),
8019 __FILE__, __LINE__);
8020 free(molecule->atoms);
8021 molecule->atoms = 0;
8022 return(TNG_CRITICAL);
8025 molecule->atoms = new_atoms;
8027 *atom = &new_atoms[molecule->n_atoms];
8029 tng_atom_init(*atom);
8030 tng_atom_name_set(tng_data, *atom, atom_name);
8031 tng_atom_type_set(tng_data, *atom, atom_type);
8033 (*atom)->residue = residue;
8036 molecule->n_atoms++;
8043 tng_function_status DECLSPECDLLEXPORT tng_molecule_alloc(const tng_trajectory_t tng_data,
8044 tng_molecule_t *molecule_p)
8046 *molecule_p = malloc(sizeof(struct tng_molecule));
8049 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIuPTR" bytes). %s: %d\n",
8050 sizeof(struct tng_molecule), __FILE__, __LINE__);
8051 return(TNG_CRITICAL);
8054 tng_molecule_init(tng_data, *molecule_p);
8056 return(TNG_SUCCESS);
8059 tng_function_status DECLSPECDLLEXPORT tng_molecule_free(const tng_trajectory_t tng_data,
8060 tng_molecule_t *molecule_p)
8064 return(TNG_SUCCESS);
8067 tng_molecule_destroy(tng_data, *molecule_p);
8072 return(TNG_SUCCESS);
8075 tng_function_status DECLSPECDLLEXPORT tng_molecule_init(const tng_trajectory_t tng_data,
8076 const tng_molecule_t molecule)
8079 molecule->quaternary_str = 1;
8081 molecule->n_chains = 0;
8082 molecule->chains = 0;
8083 molecule->n_residues = 0;
8084 molecule->residues = 0;
8085 molecule->n_atoms = 0;
8086 molecule->atoms = 0;
8087 molecule->n_bonds = 0;
8088 molecule->bonds = 0;
8090 return(TNG_SUCCESS);
8093 tng_function_status DECLSPECDLLEXPORT tng_molecule_destroy(const tng_trajectory_t tng_data,
8094 const tng_molecule_t molecule)
8101 free(molecule->name);
8105 if(molecule->chains)
8107 for(i = 0; i < molecule->n_chains; i++)
8109 if(molecule->chains[i].name)
8111 free(molecule->chains[i].name);
8112 molecule->chains[i].name = 0;
8115 free(molecule->chains);
8116 molecule->chains = 0;
8118 molecule->n_chains = 0;
8120 if(molecule->residues)
8122 for(i = 0; i < molecule->n_residues; i++)
8124 if(molecule->residues[i].name)
8126 free(molecule->residues[i].name);
8127 molecule->residues[i].name = 0;
8130 free(molecule->residues);
8131 molecule->residues = 0;
8133 molecule->n_residues = 0;
8137 for(i = 0; i < molecule->n_atoms; i++)
8139 tng_atom_destroy(&molecule->atoms[i]);
8141 free(molecule->atoms);
8142 molecule->atoms = 0;
8144 molecule->n_atoms = 0;
8148 free(molecule->bonds);
8149 molecule->bonds = 0;
8151 molecule->n_bonds = 0;
8153 return(TNG_SUCCESS);
8156 tng_function_status DECLSPECDLLEXPORT tng_molecule_name_of_particle_nr_get
8157 (const tng_trajectory_t tng_data,
8162 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8164 tng_bool found = TNG_FALSE;
8166 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8167 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8169 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8171 if(!molecule_cnt_list)
8173 return(TNG_FAILURE);
8176 for(i = 0; i < tng_data->n_molecules; i++)
8178 mol = &tng_data->molecules[i];
8179 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8181 cnt += mol->n_atoms * molecule_cnt_list[i];
8189 return(TNG_FAILURE);
8192 strncpy(name, mol->name, max_len - 1);
8193 name[max_len - 1] = 0;
8195 if(strlen(mol->name) > (unsigned int)max_len - 1)
8197 return(TNG_FAILURE);
8199 return(TNG_SUCCESS);
8202 tng_function_status DECLSPECDLLEXPORT tng_molecule_id_of_particle_nr_get
8203 (const tng_trajectory_t tng_data,
8207 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8209 tng_bool found = TNG_FALSE;
8211 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8212 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
8214 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8216 if(!molecule_cnt_list)
8218 return(TNG_FAILURE);
8221 for(i = 0; i < tng_data->n_molecules; i++)
8223 mol = &tng_data->molecules[i];
8224 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8226 cnt += mol->n_atoms * molecule_cnt_list[i];
8234 return(TNG_FAILURE);
8239 return(TNG_SUCCESS);
8242 tng_function_status DECLSPECDLLEXPORT tng_molsystem_bonds_get
8243 (const tng_trajectory_t tng_data,
8245 int64_t **from_atoms,
8248 int64_t atom_cnt = 0, cnt, mol_cnt, i, j, k;
8249 int64_t from_atom, to_atom, *molecule_cnt_list = 0;
8253 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8254 TNG_ASSERT(n_bonds, "TNG library: n_bonds must not be a NULL pointer.");
8255 TNG_ASSERT(from_atoms, "TNG library: from_atoms must not be a NULL pointer.");
8256 TNG_ASSERT(to_atoms, "TNG library: to_atoms must not be a NULL pointer.");
8258 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8260 if(!molecule_cnt_list)
8262 return(TNG_FAILURE);
8266 /* First count the total number of bonds to allocate memory */
8267 for(i = 0; i < tng_data->n_molecules; i++)
8269 mol = &tng_data->molecules[i];
8270 mol_cnt = molecule_cnt_list[i];
8271 *n_bonds += mol_cnt * mol->n_bonds;
8275 return(TNG_SUCCESS);
8278 *from_atoms = malloc(sizeof(int64_t) * (*n_bonds));
8281 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
8282 sizeof(int64_t) * (*n_bonds), __FILE__, __LINE__);
8283 return(TNG_CRITICAL);
8285 *to_atoms = malloc(sizeof(int64_t) * (*n_bonds));
8288 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
8289 sizeof(int64_t) * (*n_bonds), __FILE__, __LINE__);
8292 return(TNG_CRITICAL);
8296 for(i = 0; i < tng_data->n_molecules; i++)
8298 mol = &tng_data->molecules[i];
8299 mol_cnt = molecule_cnt_list[i];
8300 for(j = 0; j < mol_cnt; j++)
8302 for(k = 0; k < mol->n_bonds; k++)
8304 bond = &mol->bonds[k];
8305 from_atom = atom_cnt + bond->from_atom_id;
8306 to_atom = atom_cnt + bond->to_atom_id;
8307 (*from_atoms)[cnt] = from_atom;
8308 (*to_atoms)[cnt++] = to_atom;
8310 atom_cnt += mol->n_atoms;
8314 return(TNG_SUCCESS);
8317 tng_function_status DECLSPECDLLEXPORT tng_chain_name_of_particle_nr_get
8318 (const tng_trajectory_t tng_data,
8323 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8326 tng_bool found = TNG_FALSE;
8328 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8329 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8331 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8333 if(!molecule_cnt_list)
8335 return(TNG_FAILURE);
8338 for(i = 0; i < tng_data->n_molecules; i++)
8340 mol = &tng_data->molecules[i];
8341 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8343 cnt += mol->n_atoms * molecule_cnt_list[i];
8346 atom = &mol->atoms[nr % mol->n_atoms];
8352 return(TNG_FAILURE);
8354 if(!atom->residue || !atom->residue->chain)
8356 return(TNG_FAILURE);
8359 strncpy(name, atom->residue->chain->name, max_len - 1);
8360 name[max_len - 1] = 0;
8362 if(strlen(atom->residue->chain->name) > (unsigned int)max_len - 1)
8364 return(TNG_FAILURE);
8366 return(TNG_SUCCESS);
8369 tng_function_status DECLSPECDLLEXPORT tng_residue_name_of_particle_nr_get
8370 (const tng_trajectory_t tng_data,
8375 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8378 tng_bool found = TNG_FALSE;
8380 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8381 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8383 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8385 if(!molecule_cnt_list)
8387 return(TNG_FAILURE);
8390 for(i = 0; i < tng_data->n_molecules; i++)
8392 mol = &tng_data->molecules[i];
8393 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8395 cnt += mol->n_atoms * molecule_cnt_list[i];
8398 atom = &mol->atoms[nr % mol->n_atoms];
8404 return(TNG_FAILURE);
8408 return(TNG_FAILURE);
8411 strncpy(name, atom->residue->name, max_len - 1);
8412 name[max_len - 1] = 0;
8414 if(strlen(atom->residue->name) > (unsigned int)max_len - 1)
8416 return(TNG_FAILURE);
8418 return(TNG_SUCCESS);
8421 tng_function_status DECLSPECDLLEXPORT tng_residue_id_of_particle_nr_get
8422 (const tng_trajectory_t tng_data,
8426 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8429 tng_bool found = TNG_FALSE;
8431 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8432 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
8434 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8436 if(!molecule_cnt_list)
8438 return(TNG_FAILURE);
8441 for(i = 0; i < tng_data->n_molecules; i++)
8443 mol = &tng_data->molecules[i];
8444 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8446 cnt += mol->n_atoms * molecule_cnt_list[i];
8449 atom = &mol->atoms[nr % mol->n_atoms];
8455 return(TNG_FAILURE);
8459 return(TNG_FAILURE);
8462 *id = atom->residue->id;
8464 return(TNG_SUCCESS);
8467 tng_function_status DECLSPECDLLEXPORT tng_global_residue_id_of_particle_nr_get
8468 (const tng_trajectory_t tng_data,
8472 int64_t cnt = 0, i, offset = 0, *molecule_cnt_list = 0;
8475 tng_bool found = TNG_FALSE;
8477 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8478 TNG_ASSERT(id, "TNG library: id must not be a NULL pointer.");
8480 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8482 if(!molecule_cnt_list)
8484 return(TNG_FAILURE);
8487 for(i = 0; i < tng_data->n_molecules; i++)
8489 mol = &tng_data->molecules[i];
8490 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8492 cnt += mol->n_atoms * molecule_cnt_list[i];
8493 offset += mol->n_residues * molecule_cnt_list[i];
8496 atom = &mol->atoms[nr % mol->n_atoms];
8502 return(TNG_FAILURE);
8506 return(TNG_FAILURE);
8509 offset += mol->n_residues * ((nr - cnt) / mol->n_atoms);
8511 *id = atom->residue->id + offset;
8513 return(TNG_SUCCESS);
8516 tng_function_status DECLSPECDLLEXPORT tng_atom_name_of_particle_nr_get
8517 (const tng_trajectory_t tng_data,
8522 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8525 tng_bool found = TNG_FALSE;
8527 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8528 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
8530 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8532 if(!molecule_cnt_list)
8534 return(TNG_FAILURE);
8537 for(i = 0; i < tng_data->n_molecules; i++)
8539 mol = &tng_data->molecules[i];
8540 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8542 cnt += mol->n_atoms * molecule_cnt_list[i];
8545 atom = &mol->atoms[nr % mol->n_atoms];
8551 return(TNG_FAILURE);
8554 strncpy(name, atom->name, max_len - 1);
8555 name[max_len - 1] = 0;
8557 if(strlen(atom->name) > (unsigned int)max_len - 1)
8559 return(TNG_FAILURE);
8561 return(TNG_SUCCESS);
8564 tng_function_status tng_atom_type_of_particle_nr_get
8565 (const tng_trajectory_t tng_data,
8570 int64_t cnt = 0, i, *molecule_cnt_list = 0;
8573 tng_bool found = TNG_FALSE;
8575 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8576 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
8578 tng_molecule_cnt_list_get(tng_data, &molecule_cnt_list);
8580 if(!molecule_cnt_list)
8582 return(TNG_FAILURE);
8585 for(i = 0; i < tng_data->n_molecules; i++)
8587 mol = &tng_data->molecules[i];
8588 if(cnt + mol->n_atoms * molecule_cnt_list[i] - 1 < nr)
8590 cnt += mol->n_atoms * molecule_cnt_list[i];
8593 atom = &mol->atoms[nr % mol->n_atoms];
8599 return(TNG_FAILURE);
8602 strncpy(type, atom->atom_type, max_len - 1);
8603 type[max_len - 1] = 0;
8605 if(strlen(atom->atom_type) > (unsigned int)max_len - 1)
8607 return(TNG_FAILURE);
8609 return(TNG_SUCCESS);
8612 tng_function_status DECLSPECDLLEXPORT tng_particle_mapping_add
8613 (const tng_trajectory_t tng_data,
8614 const int64_t num_first_particle,
8615 const int64_t n_particles,
8616 const int64_t *mapping_table)
8619 tng_particle_mapping_t mapping;
8620 tng_trajectory_frame_set_t frame_set;
8622 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8624 frame_set = &tng_data->current_trajectory_frame_set;
8626 /* Sanity check of the particle ranges. Split into multiple if
8627 * statements for improved readability */
8628 for(i = 0; i < frame_set->n_mapping_blocks; i++)
8630 mapping = &frame_set->mappings[i];
8631 if(num_first_particle >= mapping->num_first_particle &&
8632 num_first_particle < mapping->num_first_particle +
8633 mapping->n_particles)
8635 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
8636 return(TNG_FAILURE);
8638 if(num_first_particle + n_particles >=
8639 mapping->num_first_particle &&
8640 num_first_particle + n_particles <
8641 mapping->num_first_particle + mapping->n_particles)
8643 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
8644 return(TNG_FAILURE);
8646 if(mapping->num_first_particle >= num_first_particle &&
8647 mapping->num_first_particle < num_first_particle +
8650 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
8651 return(TNG_FAILURE);
8653 if(mapping->num_first_particle + mapping->n_particles >
8654 num_first_particle &&
8655 mapping->num_first_particle + mapping->n_particles <
8656 num_first_particle + n_particles)
8658 fprintf(stderr, "TNG library: Particle mapping overlap. %s: %d\n", __FILE__, __LINE__);
8659 return(TNG_FAILURE);
8663 frame_set->n_mapping_blocks++;
8665 mapping = realloc(frame_set->mappings, sizeof(struct tng_particle_mapping) *
8666 frame_set->n_mapping_blocks);
8670 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
8671 sizeof(struct tng_particle_mapping)*frame_set->n_mapping_blocks,
8672 __FILE__, __LINE__);
8673 free(frame_set->mappings);
8674 frame_set->mappings = 0;
8675 return(TNG_CRITICAL);
8677 frame_set->mappings = mapping;
8679 frame_set->mappings[frame_set->n_mapping_blocks - 1].num_first_particle = num_first_particle;
8680 frame_set->mappings[frame_set->n_mapping_blocks - 1].n_particles = n_particles;
8682 frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers = malloc(sizeof(int64_t) * n_particles);
8683 if(!frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers)
8685 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
8686 sizeof(int64_t) * n_particles, __FILE__, __LINE__);
8687 return(TNG_CRITICAL);
8690 for(i=0; i<n_particles; i++)
8692 frame_set->mappings[frame_set->n_mapping_blocks - 1].real_particle_numbers[i] = mapping_table[i];
8695 return(TNG_SUCCESS);
8698 tng_function_status DECLSPECDLLEXPORT tng_frame_set_particle_mapping_free(const tng_trajectory_t tng_data)
8700 tng_trajectory_frame_set_t frame_set;
8701 tng_particle_mapping_t mapping;
8704 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
8706 frame_set = &tng_data->current_trajectory_frame_set;
8708 if(frame_set->n_mapping_blocks && frame_set->mappings)
8710 for(i = 0; i < frame_set->n_mapping_blocks; i++)
8712 mapping = &frame_set->mappings[i];
8713 if(mapping->real_particle_numbers)
8715 free(mapping->real_particle_numbers);
8716 mapping->real_particle_numbers = 0;
8719 free(frame_set->mappings);
8720 frame_set->mappings = 0;
8721 frame_set->n_mapping_blocks = 0;
8724 return(TNG_SUCCESS);
8727 tng_function_status DECLSPECDLLEXPORT tng_trajectory_init(tng_trajectory_t *tng_data_p)
8730 tng_trajectory_frame_set_t frame_set;
8731 tng_trajectory_t tng_data;
8733 *tng_data_p = malloc(sizeof(struct tng_trajectory));
8736 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIuPTR" bytes). %s: %d\n",
8737 sizeof(struct tng_trajectory), __FILE__, __LINE__);
8738 return(TNG_CRITICAL);
8741 tng_data = *tng_data_p;
8743 frame_set = &tng_data->current_trajectory_frame_set;
8745 tng_data->input_file_path = 0;
8746 tng_data->input_file = 0;
8747 tng_data->input_file_len = 0;
8748 tng_data->output_file_path = 0;
8749 tng_data->output_file = 0;
8751 tng_data->first_program_name = 0;
8752 tng_data->first_user_name = 0;
8753 tng_data->first_computer_name = 0;
8754 tng_data->first_pgp_signature = 0;
8755 tng_data->last_program_name = 0;
8756 tng_data->last_user_name = 0;
8757 tng_data->last_computer_name = 0;
8758 tng_data->last_pgp_signature = 0;
8759 tng_data->forcefield_name = 0;
8764 fprintf(stderr, "TNG library: Cannot get time. %s: %d\n", __FILE__, __LINE__);
8768 tng_data->time = seconds;
8771 tng_data->var_num_atoms_flag = TNG_CONSTANT_N_ATOMS;
8772 tng_data->first_trajectory_frame_set_input_file_pos = -1;
8773 tng_data->last_trajectory_frame_set_input_file_pos = -1;
8774 tng_data->current_trajectory_frame_set_input_file_pos = -1;
8775 tng_data->first_trajectory_frame_set_output_file_pos = -1;
8776 tng_data->last_trajectory_frame_set_output_file_pos = -1;
8777 tng_data->current_trajectory_frame_set_output_file_pos = -1;
8778 tng_data->frame_set_n_frames = 100;
8779 tng_data->n_trajectory_frame_sets = 0;
8780 tng_data->medium_stride_length = 100;
8781 tng_data->long_stride_length = 10000;
8783 tng_data->time_per_frame = -1;
8785 tng_data->n_particle_data_blocks = 0;
8786 tng_data->n_data_blocks = 0;
8788 tng_data->non_tr_particle_data = 0;
8789 tng_data->non_tr_data = 0;
8791 tng_data->compress_algo_pos = 0;
8792 tng_data->compress_algo_vel = 0;
8793 tng_data->compression_precision = 1000;
8794 tng_data->distance_unit_exponential = -9;
8796 frame_set->first_frame = -1;
8797 frame_set->n_mapping_blocks = 0;
8798 frame_set->mappings = 0;
8799 frame_set->molecule_cnt_list = 0;
8801 frame_set->n_particle_data_blocks = 0;
8802 frame_set->n_data_blocks = 0;
8804 frame_set->tr_particle_data = 0;
8805 frame_set->tr_data = 0;
8807 frame_set->n_written_frames = 0;
8808 frame_set->n_unwritten_frames = 0;
8810 frame_set->next_frame_set_file_pos = -1;
8811 frame_set->prev_frame_set_file_pos = -1;
8812 frame_set->medium_stride_next_frame_set_file_pos = -1;
8813 frame_set->medium_stride_prev_frame_set_file_pos = -1;
8814 frame_set->long_stride_next_frame_set_file_pos = -1;
8815 frame_set->long_stride_prev_frame_set_file_pos = -1;
8817 frame_set->first_frame_time = -1;
8819 tng_data->n_molecules = 0;
8820 tng_data->molecules = 0;
8821 tng_data->molecule_cnt_list = 0;
8822 tng_data->n_particles = 0;
8825 /* Check the endianness of the computer */
8826 static int32_t endianness_32 = 0x01234567;
8828 if ( *(const unsigned char*)&endianness_32 == 0x01 )
8830 tng_data->endianness_32 = TNG_BIG_ENDIAN_32;
8834 else if( *(const unsigned char*)&endianness_32 == 0x67 )
8836 tng_data->endianness_32 = TNG_LITTLE_ENDIAN_32;
8841 else if ( *(const unsigned char*)&endianness_32 == 0x45 )
8843 tng_data->endianness_32 = TNG_BYTE_PAIR_SWAP_32;
8847 static int64_t endianness_64 = 0x0123456789ABCDEFLL;
8848 /* 0x0123456789ABCDEF */
8849 if ( *(const unsigned char*)&endianness_64 == 0x01 )
8851 tng_data->endianness_64 = TNG_BIG_ENDIAN_64;
8854 /* 0xEFCDAB8967452301 */
8855 else if ( *(const unsigned char*)&endianness_64 == 0xEF )
8857 tng_data->endianness_64 = TNG_LITTLE_ENDIAN_64;
8860 /* 0x89ABCDEF01234567 */
8861 else if ( *(const unsigned char*)&endianness_64 == 0x89 )
8863 tng_data->endianness_64 = TNG_QUAD_SWAP_64;
8866 /* 0x45670123CDEF89AB */
8867 else if ( *(const unsigned char*)&endianness_64 == 0x45 )
8869 tng_data->endianness_64 = TNG_BYTE_PAIR_SWAP_64;
8872 /* 0x23016745AB89EFCD */
8873 else if ( *(const unsigned char*)&endianness_64 == 0x23 )
8875 tng_data->endianness_64 = TNG_BYTE_SWAP_64;
8879 /* By default do not swap the byte order, i.e. keep the byte order of the
8880 * architecture. The input file endianness will be set when reading the
8881 * header. The output endianness can be changed - before the file is
8883 tng_data->input_endianness_swap_func_32 = 0;
8884 tng_data->input_endianness_swap_func_64 = 0;
8885 tng_data->output_endianness_swap_func_32 = 0;
8886 tng_data->output_endianness_swap_func_64 = 0;
8888 tng_data->current_trajectory_frame_set.next_frame_set_file_pos = -1;
8889 tng_data->current_trajectory_frame_set.prev_frame_set_file_pos = -1;
8890 tng_data->current_trajectory_frame_set.n_frames = 0;
8892 return(TNG_SUCCESS);
8895 tng_function_status DECLSPECDLLEXPORT tng_trajectory_destroy(tng_trajectory_t *tng_data_p)
8898 int64_t n_particles, n_values_per_frame;
8899 tng_trajectory_t tng_data = *tng_data_p;
8900 tng_trajectory_frame_set_t frame_set;
8904 return(TNG_SUCCESS);
8907 frame_set = &tng_data->current_trajectory_frame_set;
8909 if(tng_data->input_file)
8911 if(tng_data->output_file == tng_data->input_file)
8913 tng_frame_set_finalize(tng_data, TNG_USE_HASH);
8914 tng_data->output_file = 0;
8916 fclose(tng_data->input_file);
8917 tng_data->input_file = 0;
8920 if(tng_data->input_file_path)
8922 free(tng_data->input_file_path);
8923 tng_data->input_file_path = 0;
8926 if(tng_data->output_file)
8928 /* FIXME: Do not always write the hash */
8929 tng_frame_set_finalize(tng_data, TNG_USE_HASH);
8930 fclose(tng_data->output_file);
8931 tng_data->output_file = 0;
8934 if(tng_data->output_file_path)
8936 free(tng_data->output_file_path);
8937 tng_data->output_file_path = 0;
8940 if(tng_data->first_program_name)
8942 free(tng_data->first_program_name);
8943 tng_data->first_program_name = 0;
8946 if(tng_data->last_program_name)
8948 free(tng_data->last_program_name);
8949 tng_data->last_program_name = 0;
8952 if(tng_data->first_user_name)
8954 free(tng_data->first_user_name);
8955 tng_data->first_user_name = 0;
8958 if(tng_data->last_user_name)
8960 free(tng_data->last_user_name);
8961 tng_data->last_user_name = 0;
8964 if(tng_data->first_computer_name)
8966 free(tng_data->first_computer_name);
8967 tng_data->first_computer_name = 0;
8970 if(tng_data->last_computer_name)
8972 free(tng_data->last_computer_name);
8973 tng_data->last_computer_name = 0;
8976 if(tng_data->first_pgp_signature)
8978 free(tng_data->first_pgp_signature);
8979 tng_data->first_pgp_signature = 0;
8982 if(tng_data->last_pgp_signature)
8984 free(tng_data->last_pgp_signature);
8985 tng_data->last_pgp_signature = 0;
8988 if(tng_data->forcefield_name)
8990 free(tng_data->forcefield_name);
8991 tng_data->forcefield_name = 0;
8994 tng_frame_set_particle_mapping_free(tng_data);
8996 if(frame_set->molecule_cnt_list)
8998 free(frame_set->molecule_cnt_list);
8999 frame_set->molecule_cnt_list = 0;
9002 if(tng_data->var_num_atoms_flag)
9004 n_particles = frame_set->n_particles;
9008 n_particles = tng_data->n_particles;
9011 if(tng_data->non_tr_particle_data)
9013 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
9015 if(tng_data->non_tr_particle_data[i].values)
9017 free(tng_data->non_tr_particle_data[i].values);
9018 tng_data->non_tr_particle_data[i].values = 0;
9021 if(tng_data->non_tr_particle_data[i].strings)
9023 n_values_per_frame = tng_data->non_tr_particle_data[i].
9025 if(tng_data->non_tr_particle_data[i].strings[0])
9027 for(j = 0; j < n_particles; j++)
9029 if(tng_data->non_tr_particle_data[i].strings[0][j])
9031 for(k = 0; k < n_values_per_frame; k++)
9033 if(tng_data->non_tr_particle_data[i].
9036 free(tng_data->non_tr_particle_data[i].
9038 tng_data->non_tr_particle_data[i].
9039 strings[0][j][k] = 0;
9042 free(tng_data->non_tr_particle_data[i].
9044 tng_data->non_tr_particle_data[i].strings[0][j] = 0;
9047 free(tng_data->non_tr_particle_data[i].strings[0]);
9048 tng_data->non_tr_particle_data[i].strings[0] = 0;
9050 free(tng_data->non_tr_particle_data[i].strings);
9051 tng_data->non_tr_particle_data[i].strings = 0;
9054 if(tng_data->non_tr_particle_data[i].block_name)
9056 free(tng_data->non_tr_particle_data[i].block_name);
9057 tng_data->non_tr_particle_data[i].block_name = 0;
9060 free(tng_data->non_tr_particle_data);
9061 tng_data->non_tr_particle_data = 0;
9064 if(tng_data->non_tr_data)
9066 for(i = 0; i < tng_data->n_data_blocks; i++)
9068 if(tng_data->non_tr_data[i].values)
9070 free(tng_data->non_tr_data[i].values);
9071 tng_data->non_tr_data[i].values = 0;
9074 if(tng_data->non_tr_data[i].strings)
9076 n_values_per_frame = tng_data->non_tr_data[i].
9078 if(tng_data->non_tr_data[i].strings[0][0])
9080 for(j = 0; j < n_values_per_frame; j++)
9082 if(tng_data->non_tr_data[i].strings[0][0][j])
9084 free(tng_data->non_tr_data[i].strings[0][0][j]);
9085 tng_data->non_tr_data[i].strings[0][0][j] = 0;
9088 free(tng_data->non_tr_data[i].strings[0][0]);
9089 tng_data->non_tr_data[i].strings[0][0] = 0;
9091 free(tng_data->non_tr_data[i].strings[0]);
9092 tng_data->non_tr_data[i].strings[0] = 0;
9093 free(tng_data->non_tr_data[i].strings);
9094 tng_data->non_tr_data[i].strings = 0;
9097 if(tng_data->non_tr_data[i].block_name)
9099 free(tng_data->non_tr_data[i].block_name);
9100 tng_data->non_tr_data[i].block_name = 0;
9103 free(tng_data->non_tr_data);
9104 tng_data->non_tr_data = 0;
9107 tng_data->n_particle_data_blocks = 0;
9108 tng_data->n_data_blocks = 0;
9110 if(tng_data->compress_algo_pos)
9112 free(tng_data->compress_algo_pos);
9113 tng_data->compress_algo_pos = 0;
9115 if(tng_data->compress_algo_vel)
9117 free(tng_data->compress_algo_vel);
9118 tng_data->compress_algo_vel = 0;
9121 if(frame_set->tr_particle_data)
9123 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
9125 if(frame_set->tr_particle_data[i].values)
9127 free(frame_set->tr_particle_data[i].values);
9128 frame_set->tr_particle_data[i].values = 0;
9131 if(frame_set->tr_particle_data[i].strings)
9133 n_values_per_frame = frame_set->tr_particle_data[i].
9135 for(j = 0; j < frame_set->tr_particle_data[i].n_frames; j++)
9137 if(frame_set->tr_particle_data[i].strings[j])
9139 for(k = 0; k < n_particles; k++)
9141 if(frame_set->tr_particle_data[i].
9144 for(l = 0; l < n_values_per_frame; l++)
9146 if(frame_set->tr_particle_data[i].
9149 free(frame_set->tr_particle_data[i].
9151 frame_set->tr_particle_data[i].
9152 strings[j][k][l] = 0;
9155 free(frame_set->tr_particle_data[i].
9157 frame_set->tr_particle_data[i].
9161 free(frame_set->tr_particle_data[i].strings[j]);
9162 frame_set->tr_particle_data[i].strings[j] = 0;
9165 free(frame_set->tr_particle_data[i].strings);
9166 frame_set->tr_particle_data[i].strings = 0;
9169 if(frame_set->tr_particle_data[i].block_name)
9171 free(frame_set->tr_particle_data[i].block_name);
9172 frame_set->tr_particle_data[i].block_name = 0;
9175 free(frame_set->tr_particle_data);
9176 frame_set->tr_particle_data = 0;
9179 if(frame_set->tr_data)
9181 for(i = 0; i < frame_set->n_data_blocks; i++)
9183 if(frame_set->tr_data[i].values)
9185 free(frame_set->tr_data[i].values);
9186 frame_set->tr_data[i].values = 0;
9189 if(frame_set->tr_data[i].strings)
9191 n_values_per_frame = frame_set->tr_data[i].
9193 for(j = 0; j < frame_set->tr_data[i].n_frames; j++)
9195 if(frame_set->tr_data[i].strings[j])
9197 for(k = 0; k < n_values_per_frame; k++)
9199 if(frame_set->tr_data[i].strings[j][k])
9201 free(frame_set->tr_data[i].strings[j][k]);
9202 frame_set->tr_data[i].strings[j][k] = 0;
9205 free(frame_set->tr_data[i].strings[j]);
9206 frame_set->tr_data[i].strings[j] = 0;
9209 free(frame_set->tr_data[i].strings);
9210 frame_set->tr_data[i].strings = 0;
9213 if(frame_set->tr_data[i].block_name)
9215 free(frame_set->tr_data[i].block_name);
9216 frame_set->tr_data[i].block_name = 0;
9219 free(frame_set->tr_data);
9220 frame_set->tr_data = 0;
9223 frame_set->n_particle_data_blocks = 0;
9224 frame_set->n_data_blocks = 0;
9226 if(tng_data->molecules)
9228 for(i = 0; i < tng_data->n_molecules; i++)
9230 tng_molecule_destroy(tng_data, &tng_data->molecules[i]);
9232 free(tng_data->molecules);
9233 tng_data->molecules = 0;
9234 tng_data->n_molecules = 0;
9236 if(tng_data->molecule_cnt_list)
9238 free(tng_data->molecule_cnt_list);
9239 tng_data->molecule_cnt_list = 0;
9245 return(TNG_SUCCESS);
9248 tng_function_status DECLSPECDLLEXPORT tng_trajectory_init_from_src
9249 (const tng_trajectory_t src,
9250 tng_trajectory_t *dest_p)
9252 tng_trajectory_frame_set_t frame_set;
9253 tng_trajectory_t dest;
9255 TNG_ASSERT(src != 0, "TNG library: Source trajectory must not be NULL.");
9257 *dest_p = malloc(sizeof(struct tng_trajectory));
9260 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIuPTR" bytes). %s: %d\n",
9261 sizeof(struct tng_trajectory), __FILE__, __LINE__);
9262 return(TNG_CRITICAL);
9267 frame_set = &dest->current_trajectory_frame_set;
9269 if(src->input_file_path)
9271 dest->input_file_path = malloc(strlen(src->input_file_path) + 1);
9272 if(!dest->input_file_path)
9274 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n",
9275 (unsigned int)strlen(src->input_file_path) + 1, __FILE__, __LINE__);
9276 return(TNG_CRITICAL);
9278 strcpy(dest->input_file_path, src->input_file_path);
9279 dest->input_file_len = src->input_file_len;
9283 dest->input_file_path = 0;
9285 dest->input_file = 0;
9286 if(src->output_file_path)
9288 dest->output_file_path = malloc(strlen(src->output_file_path) + 1);
9289 if(!dest->output_file_path)
9291 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n",
9292 (unsigned int)strlen(src->output_file_path) + 1, __FILE__, __LINE__);
9293 return(TNG_CRITICAL);
9295 strcpy(dest->output_file_path, src->output_file_path);
9299 dest->output_file_path = 0;
9301 dest->output_file = 0;
9303 dest->first_program_name = 0;
9304 dest->first_user_name = 0;
9305 dest->first_computer_name = 0;
9306 dest->first_pgp_signature = 0;
9307 dest->last_program_name = 0;
9308 dest->last_user_name = 0;
9309 dest->last_computer_name = 0;
9310 dest->last_pgp_signature = 0;
9311 dest->forcefield_name = 0;
9313 dest->var_num_atoms_flag = src->var_num_atoms_flag;
9314 dest->first_trajectory_frame_set_input_file_pos =
9315 src->first_trajectory_frame_set_input_file_pos;
9316 dest->last_trajectory_frame_set_input_file_pos =
9317 src->last_trajectory_frame_set_input_file_pos;
9318 dest->current_trajectory_frame_set_input_file_pos =
9319 src->current_trajectory_frame_set_input_file_pos;
9320 dest->first_trajectory_frame_set_output_file_pos =
9321 src->first_trajectory_frame_set_output_file_pos;
9322 dest->last_trajectory_frame_set_output_file_pos =
9323 src->last_trajectory_frame_set_output_file_pos;
9324 dest->current_trajectory_frame_set_output_file_pos =
9325 src->current_trajectory_frame_set_output_file_pos;
9326 dest->frame_set_n_frames = src->frame_set_n_frames;
9327 dest->n_trajectory_frame_sets = src->n_trajectory_frame_sets;
9328 dest->medium_stride_length = src->medium_stride_length;
9329 dest->long_stride_length = src->long_stride_length;
9331 dest->time_per_frame = src->time_per_frame;
9333 /* Currently the non trajectory data blocks are not copied since it
9334 * can lead to problems when freeing memory in a parallel block. */
9335 dest->n_particle_data_blocks = 0;
9336 dest->n_data_blocks = 0;
9337 dest->non_tr_particle_data = 0;
9338 dest->non_tr_data = 0;
9340 dest->compress_algo_pos = 0;
9341 dest->compress_algo_vel = 0;
9342 dest->distance_unit_exponential = -9;
9343 dest->compression_precision = 1000;
9345 frame_set->n_mapping_blocks = 0;
9346 frame_set->mappings = 0;
9347 frame_set->molecule_cnt_list = 0;
9349 frame_set->n_particle_data_blocks = 0;
9350 frame_set->n_data_blocks = 0;
9352 frame_set->tr_particle_data = 0;
9353 frame_set->tr_data = 0;
9355 frame_set->n_written_frames = 0;
9356 frame_set->n_unwritten_frames = 0;
9358 frame_set->next_frame_set_file_pos = -1;
9359 frame_set->prev_frame_set_file_pos = -1;
9360 frame_set->medium_stride_next_frame_set_file_pos = -1;
9361 frame_set->medium_stride_prev_frame_set_file_pos = -1;
9362 frame_set->long_stride_next_frame_set_file_pos = -1;
9363 frame_set->long_stride_prev_frame_set_file_pos = -1;
9364 frame_set->first_frame = -1;
9366 dest->n_molecules = 0;
9367 dest->molecules = 0;
9368 dest->molecule_cnt_list = 0;
9369 dest->n_particles = src->n_particles;
9371 dest->endianness_32 = src->endianness_32;
9372 dest->endianness_64 = src->endianness_64;
9373 dest->input_endianness_swap_func_32 = src->input_endianness_swap_func_32;
9374 dest->input_endianness_swap_func_64 = src->input_endianness_swap_func_64;
9375 dest->output_endianness_swap_func_32 = src->output_endianness_swap_func_32;
9376 dest->output_endianness_swap_func_64 = src->output_endianness_swap_func_64;
9378 dest->current_trajectory_frame_set.next_frame_set_file_pos = -1;
9379 dest->current_trajectory_frame_set.prev_frame_set_file_pos = -1;
9380 dest->current_trajectory_frame_set.n_frames = 0;
9382 return(TNG_SUCCESS);
9385 tng_function_status DECLSPECDLLEXPORT tng_input_file_get
9386 (const tng_trajectory_t tng_data,
9390 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9391 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
9393 strncpy(file_name, tng_data->input_file_path, max_len - 1);
9394 file_name[max_len - 1] = 0;
9396 if(strlen(tng_data->input_file_path) > (unsigned int)max_len - 1)
9398 return(TNG_FAILURE);
9400 return(TNG_SUCCESS);
9403 tng_function_status DECLSPECDLLEXPORT tng_input_file_set
9404 (const tng_trajectory_t tng_data,
9405 const char *file_name)
9410 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9411 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
9414 if(tng_data->input_file_path && strcmp(tng_data->input_file_path,
9417 return(TNG_SUCCESS);
9420 if(tng_data->input_file)
9422 fclose(tng_data->input_file);
9425 len = tng_min_size(strlen(file_name) + 1, TNG_MAX_STR_LEN);
9426 temp = realloc(tng_data->input_file_path, len);
9429 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
9430 __FILE__, __LINE__);
9431 free(tng_data->input_file_path);
9432 tng_data->input_file_path = 0;
9433 return(TNG_CRITICAL);
9435 tng_data->input_file_path = temp;
9437 strncpy(tng_data->input_file_path, file_name, len);
9439 return(tng_input_file_init(tng_data));
9442 tng_function_status tng_output_file_get
9443 (const tng_trajectory_t tng_data,
9447 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9448 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
9450 strncpy(file_name, tng_data->output_file_path, max_len - 1);
9451 file_name[max_len - 1] = 0;
9453 if(strlen(tng_data->output_file_path) > (unsigned int)max_len - 1)
9455 return(TNG_FAILURE);
9457 return(TNG_SUCCESS);
9460 tng_function_status DECLSPECDLLEXPORT tng_output_file_set
9461 (const tng_trajectory_t tng_data,
9462 const char *file_name)
9467 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9468 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
9470 if(tng_data->output_file_path &&
9471 strcmp(tng_data->output_file_path, file_name) == 0)
9473 return(TNG_SUCCESS);
9476 if(tng_data->output_file)
9478 fclose(tng_data->output_file);
9481 len = tng_min_size(strlen(file_name) + 1, TNG_MAX_STR_LEN);
9482 temp = realloc(tng_data->output_file_path, len);
9485 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
9486 __FILE__, __LINE__);
9487 free(tng_data->output_file_path);
9488 tng_data->output_file_path = 0;
9489 return(TNG_CRITICAL);
9491 tng_data->output_file_path = temp;
9493 strncpy(tng_data->output_file_path, file_name, len);
9495 return(tng_output_file_init(tng_data));
9498 tng_function_status DECLSPECDLLEXPORT tng_output_append_file_set
9499 (const tng_trajectory_t tng_data,
9500 const char *file_name)
9505 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9506 TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer");
9508 if(tng_data->output_file_path &&
9509 strcmp(tng_data->output_file_path, file_name) == 0)
9511 return(TNG_SUCCESS);
9514 if(tng_data->output_file)
9516 fclose(tng_data->output_file);
9519 len = tng_min_size(strlen(file_name) + 1, TNG_MAX_STR_LEN);
9520 temp = realloc(tng_data->output_file_path, len);
9523 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len,
9524 __FILE__, __LINE__);
9525 free(tng_data->output_file_path);
9526 tng_data->output_file_path = 0;
9527 return(TNG_CRITICAL);
9529 tng_data->output_file_path = temp;
9531 strncpy(tng_data->output_file_path, file_name, len);
9533 tng_data->output_file = fopen(tng_data->output_file_path, "rb+");
9534 if(!tng_data->output_file)
9536 fprintf(stderr, "TNG library: Cannot open file %s. %s: %d\n",
9537 tng_data->output_file_path, __FILE__, __LINE__);
9538 return(TNG_CRITICAL);
9540 tng_data->input_file = tng_data->output_file;
9542 return(TNG_SUCCESS);
9545 tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_get
9546 (const tng_trajectory_t tng_data, tng_file_endianness *endianness)
9548 tng_endianness_32 end_32;
9549 tng_endianness_64 end_64;
9551 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9552 TNG_ASSERT(endianness, "TNG library: endianness must not be a NULL pointer");
9554 if(tng_data->output_endianness_swap_func_32)
9556 /* If other endianness variants are added they must be added here as well */
9557 if(tng_data->output_endianness_swap_func_32 ==
9558 &tng_swap_byte_order_big_endian_32)
9560 end_32 = TNG_BIG_ENDIAN_32;
9562 else if(tng_data->output_endianness_swap_func_32 ==
9563 &tng_swap_byte_order_little_endian_32)
9565 end_32 = TNG_LITTLE_ENDIAN_32;
9569 return(TNG_FAILURE);
9574 end_32 = (tng_endianness_32)tng_data->endianness_32;
9577 if(tng_data->output_endianness_swap_func_64)
9579 /* If other endianness variants are added they must be added here as well */
9580 if(tng_data->output_endianness_swap_func_64 ==
9581 &tng_swap_byte_order_big_endian_64)
9583 end_64 = TNG_BIG_ENDIAN_64;
9585 else if(tng_data->output_endianness_swap_func_64 ==
9586 &tng_swap_byte_order_little_endian_64)
9588 end_64 = TNG_LITTLE_ENDIAN_64;
9592 return(TNG_FAILURE);
9597 end_64 = (tng_endianness_64)tng_data->endianness_64;
9600 if((int)end_32 != (int)end_64)
9602 return(TNG_FAILURE);
9605 if(end_32 == TNG_LITTLE_ENDIAN_32)
9607 *endianness = TNG_LITTLE_ENDIAN;
9610 else if(end_32 == TNG_BIG_ENDIAN_32)
9612 *endianness = TNG_BIG_ENDIAN;
9616 return(TNG_FAILURE);
9619 return(TNG_SUCCESS);
9622 tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_set
9623 (const tng_trajectory_t tng_data,
9624 const tng_file_endianness endianness)
9626 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9628 /* Tne endianness cannot be changed if the data has already been written
9629 * to the output file. */
9630 if(ftello(tng_data->output_file) > 0)
9632 return(TNG_FAILURE);
9635 if(endianness == TNG_BIG_ENDIAN)
9637 if(tng_data->endianness_32 == TNG_BIG_ENDIAN_32)
9639 tng_data->output_endianness_swap_func_32 = 0;
9643 tng_data->output_endianness_swap_func_32 =
9644 &tng_swap_byte_order_big_endian_32;
9646 if(tng_data->endianness_64 == TNG_BIG_ENDIAN_64)
9648 tng_data->output_endianness_swap_func_64 = 0;
9652 tng_data->output_endianness_swap_func_64 =
9653 &tng_swap_byte_order_big_endian_64;
9655 return(TNG_SUCCESS);
9657 else if(endianness == TNG_LITTLE_ENDIAN)
9659 if(tng_data->endianness_32 == TNG_LITTLE_ENDIAN_32)
9661 tng_data->output_endianness_swap_func_32 = 0;
9665 tng_data->output_endianness_swap_func_32 =
9666 &tng_swap_byte_order_little_endian_32;
9668 if(tng_data->endianness_64 == TNG_LITTLE_ENDIAN_64)
9670 tng_data->output_endianness_swap_func_64 = 0;
9674 tng_data->output_endianness_swap_func_64 =
9675 &tng_swap_byte_order_little_endian_64;
9677 return(TNG_SUCCESS);
9680 /* If the specified endianness is neither big nor little endian return a
9682 return(TNG_FAILURE);
9685 tng_function_status DECLSPECDLLEXPORT tng_first_program_name_get
9686 (const tng_trajectory_t tng_data,
9690 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9691 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
9693 strncpy(name, tng_data->first_program_name, max_len - 1);
9694 name[max_len - 1] = 0;
9696 if(strlen(tng_data->first_program_name) > (unsigned int)max_len - 1)
9698 return(TNG_FAILURE);
9700 return(TNG_SUCCESS);
9703 tng_function_status DECLSPECDLLEXPORT tng_first_program_name_set
9704 (const tng_trajectory_t tng_data,
9705 const char *new_name)
9709 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9710 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
9712 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
9714 if(tng_data->first_program_name && strlen(tng_data->first_program_name) < len)
9716 free(tng_data->first_program_name);
9717 tng_data->first_program_name = 0;
9719 if(!tng_data->first_program_name)
9721 tng_data->first_program_name = malloc(len);
9722 if(!tng_data->first_program_name)
9724 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
9725 __FILE__, __LINE__);
9726 return(TNG_CRITICAL);
9730 strncpy(tng_data->first_program_name, new_name, len);
9732 return(TNG_SUCCESS);
9735 tng_function_status DECLSPECDLLEXPORT tng_last_program_name_get
9736 (const tng_trajectory_t tng_data,
9737 char *name, const int max_len)
9739 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9740 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
9742 strncpy(name, tng_data->last_program_name, max_len - 1);
9743 name[max_len - 1] = 0;
9745 if(strlen(tng_data->last_program_name) > (unsigned int)max_len - 1)
9747 return(TNG_FAILURE);
9749 return(TNG_SUCCESS);
9752 tng_function_status DECLSPECDLLEXPORT tng_last_program_name_set
9753 (const tng_trajectory_t tng_data,
9754 const char *new_name)
9758 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9759 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
9761 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
9763 if(tng_data->last_program_name && strlen(tng_data->last_program_name) < len)
9765 free(tng_data->last_program_name);
9766 tng_data->last_program_name = 0;
9768 if(!tng_data->last_program_name)
9770 tng_data->last_program_name = malloc(len);
9771 if(!tng_data->last_program_name)
9773 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
9774 __FILE__, __LINE__);
9775 return(TNG_CRITICAL);
9779 strncpy(tng_data->last_program_name, new_name, len);
9781 return(TNG_SUCCESS);
9784 tng_function_status DECLSPECDLLEXPORT tng_first_user_name_get
9785 (const tng_trajectory_t tng_data,
9786 char *name, const int max_len)
9788 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9789 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
9791 strncpy(name, tng_data->first_user_name, max_len - 1);
9792 name[max_len - 1] = 0;
9794 if(strlen(tng_data->first_user_name) > (unsigned int)max_len - 1)
9796 return(TNG_FAILURE);
9798 return(TNG_SUCCESS);
9801 tng_function_status DECLSPECDLLEXPORT tng_first_user_name_set
9802 (const tng_trajectory_t tng_data,
9803 const char *new_name)
9807 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9808 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
9810 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
9812 /* If the currently stored string length is not enough to store the new
9813 * string it is freed and reallocated. */
9814 if(tng_data->first_user_name && strlen(tng_data->first_user_name) < len)
9816 free(tng_data->first_user_name);
9817 tng_data->first_user_name = 0;
9819 if(!tng_data->first_user_name)
9821 tng_data->first_user_name = malloc(len);
9822 if(!tng_data->first_user_name)
9824 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
9825 __FILE__, __LINE__);
9826 return(TNG_CRITICAL);
9830 strncpy(tng_data->first_user_name, new_name, len);
9832 return(TNG_SUCCESS);
9835 tng_function_status DECLSPECDLLEXPORT tng_last_user_name_get
9836 (const tng_trajectory_t tng_data,
9837 char *name, const int max_len)
9839 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9840 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
9842 strncpy(name, tng_data->last_user_name, max_len - 1);
9843 name[max_len - 1] = 0;
9845 if(strlen(tng_data->last_user_name) > (unsigned int)max_len - 1)
9847 return(TNG_FAILURE);
9849 return(TNG_SUCCESS);
9852 tng_function_status DECLSPECDLLEXPORT tng_last_user_name_set
9853 (const tng_trajectory_t tng_data,
9854 const char *new_name)
9858 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9859 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
9861 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
9863 /* If the currently stored string length is not enough to store the new
9864 * string it is freed and reallocated. */
9865 if(tng_data->last_user_name && strlen(tng_data->last_user_name) < len)
9867 free(tng_data->last_user_name);
9868 tng_data->last_user_name = 0;
9870 if(!tng_data->last_user_name)
9872 tng_data->last_user_name = malloc(len);
9873 if(!tng_data->last_user_name)
9875 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
9876 __FILE__, __LINE__);
9877 return(TNG_CRITICAL);
9881 strncpy(tng_data->last_user_name, new_name, len);
9883 return(TNG_SUCCESS);
9886 tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_get
9887 (const tng_trajectory_t tng_data,
9888 char *name, const int max_len)
9890 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9891 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
9893 strncpy(name, tng_data->first_computer_name, max_len - 1);
9894 name[max_len - 1] = 0;
9896 if(strlen(tng_data->first_computer_name) > (unsigned int)max_len - 1)
9898 return(TNG_FAILURE);
9900 return(TNG_SUCCESS);
9903 tng_function_status DECLSPECDLLEXPORT tng_first_computer_name_set
9904 (const tng_trajectory_t tng_data,
9905 const char *new_name)
9909 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9910 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
9912 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
9914 /* If the currently stored string length is not enough to store the new
9915 * string it is freed and reallocated. */
9916 if(tng_data->first_computer_name && strlen(tng_data->first_computer_name) < len)
9918 free(tng_data->first_computer_name);
9919 tng_data->first_computer_name = 0;
9921 if(!tng_data->first_computer_name)
9923 tng_data->first_computer_name = malloc(len);
9924 if(!tng_data->first_computer_name)
9926 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
9927 __FILE__, __LINE__);
9928 return(TNG_CRITICAL);
9932 strncpy(tng_data->first_computer_name, new_name, len);
9934 return(TNG_SUCCESS);
9937 tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_get
9938 (const tng_trajectory_t tng_data,
9939 char *name, const int max_len)
9941 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9942 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
9944 strncpy(name, tng_data->last_computer_name, max_len - 1);
9945 name[max_len - 1] = 0;
9947 if(strlen(tng_data->last_computer_name) > (unsigned int)max_len - 1)
9949 return(TNG_FAILURE);
9951 return(TNG_SUCCESS);
9954 tng_function_status DECLSPECDLLEXPORT tng_last_computer_name_set
9955 (const tng_trajectory_t tng_data,
9956 const char *new_name)
9960 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9961 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
9963 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
9965 /* If the currently stored string length is not enough to store the new
9966 * string it is freed and reallocated. */
9967 if(tng_data->last_computer_name && strlen(tng_data->last_computer_name) <
9970 free(tng_data->last_computer_name);
9971 tng_data->last_computer_name = 0;
9973 if(!tng_data->last_computer_name)
9975 tng_data->last_computer_name = malloc(len);
9976 if(!tng_data->last_computer_name)
9978 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
9979 __FILE__, __LINE__);
9980 return(TNG_CRITICAL);
9984 strncpy(tng_data->last_computer_name, new_name, len);
9986 return(TNG_SUCCESS);
9989 tng_function_status DECLSPECDLLEXPORT tng_first_signature_get
9990 (const tng_trajectory_t tng_data,
9991 char *signature, const int max_len)
9993 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
9994 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
9996 strncpy(signature, tng_data->first_pgp_signature, max_len - 1);
9997 signature[max_len - 1] = 0;
9999 if(strlen(tng_data->first_pgp_signature) > (unsigned int)max_len - 1)
10001 return(TNG_FAILURE);
10003 return(TNG_SUCCESS);
10006 tng_function_status DECLSPECDLLEXPORT tng_first_signature_set
10007 (const tng_trajectory_t tng_data,
10008 const char *signature)
10012 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10013 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
10015 len = tng_min_size(strlen(signature) + 1, TNG_MAX_STR_LEN);
10017 /* If the currently stored string length is not enough to store the new
10018 * string it is freed and reallocated. */
10019 if(tng_data->first_pgp_signature && strlen(tng_data->first_pgp_signature) <
10022 free(tng_data->first_pgp_signature);
10023 tng_data->first_pgp_signature = 0;
10025 if(!tng_data->first_pgp_signature)
10027 tng_data->first_pgp_signature = malloc(len);
10028 if(!tng_data->first_pgp_signature)
10030 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10031 __FILE__, __LINE__);
10032 return(TNG_CRITICAL);
10036 strncpy(tng_data->first_pgp_signature, signature, len);
10038 return(TNG_SUCCESS);
10041 tng_function_status DECLSPECDLLEXPORT tng_last_signature_get
10042 (const tng_trajectory_t tng_data,
10043 char *signature, const int max_len)
10045 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10046 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
10048 strncpy(signature, tng_data->last_pgp_signature, max_len - 1);
10049 signature[max_len - 1] = 0;
10051 if(strlen(tng_data->last_pgp_signature) > (unsigned int)max_len - 1)
10053 return(TNG_FAILURE);
10055 return(TNG_SUCCESS);
10058 tng_function_status DECLSPECDLLEXPORT tng_last_signature_set
10059 (const tng_trajectory_t tng_data,
10060 const char *signature)
10064 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10065 TNG_ASSERT(signature, "TNG library: signature must not be a NULL pointer");
10067 len = tng_min_size(strlen(signature) + 1, TNG_MAX_STR_LEN);
10069 /* If the currently stored string length is not enough to store the new
10070 * string it is freed and reallocated. */
10071 if(tng_data->last_pgp_signature && strlen(tng_data->last_pgp_signature) <
10074 free(tng_data->last_pgp_signature);
10075 tng_data->last_pgp_signature = 0;
10077 if(!tng_data->last_pgp_signature)
10079 tng_data->last_pgp_signature = malloc(len);
10080 if(!tng_data->last_pgp_signature)
10082 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10083 __FILE__, __LINE__);
10084 return(TNG_CRITICAL);
10088 strncpy(tng_data->last_pgp_signature, signature, len);
10090 return(TNG_SUCCESS);
10093 tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_get
10094 (const tng_trajectory_t tng_data,
10095 char *name, const int max_len)
10097 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10098 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
10100 strncpy(name, tng_data->forcefield_name, max_len - 1);
10101 name[max_len - 1] = 0;
10103 if(strlen(tng_data->forcefield_name) > (unsigned int)max_len - 1)
10105 return(TNG_FAILURE);
10107 return(TNG_SUCCESS);
10110 tng_function_status DECLSPECDLLEXPORT tng_forcefield_name_set
10111 (const tng_trajectory_t tng_data,
10112 const char *new_name)
10116 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10117 TNG_ASSERT(new_name, "TNG library: new_name must not be a NULL pointer");
10119 len = tng_min_size(strlen(new_name) + 1, TNG_MAX_STR_LEN);
10121 /* If the currently stored string length is not enough to store the new
10122 * string it is freed and reallocated. */
10123 if(tng_data->forcefield_name && strlen(tng_data->forcefield_name) < len)
10125 free(tng_data->forcefield_name);
10126 tng_data->forcefield_name = 0;
10128 if(!tng_data->forcefield_name)
10130 tng_data->forcefield_name = malloc(len);
10131 if(!tng_data->forcefield_name)
10133 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n", len,
10134 __FILE__, __LINE__);
10135 return(TNG_CRITICAL);
10139 strncpy(tng_data->forcefield_name, new_name, len);
10141 return(TNG_SUCCESS);
10144 tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_get
10145 (const tng_trajectory_t tng_data,
10148 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10149 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
10151 *len = tng_data->medium_stride_length;
10153 return(TNG_SUCCESS);
10156 tng_function_status DECLSPECDLLEXPORT tng_medium_stride_length_set
10157 (const tng_trajectory_t tng_data,
10160 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10162 if(len >= tng_data->long_stride_length)
10164 return(TNG_FAILURE);
10166 tng_data->medium_stride_length = len;
10168 return(TNG_SUCCESS);
10171 tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_get
10172 (const tng_trajectory_t tng_data,
10175 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10176 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
10178 *len = tng_data->long_stride_length;
10180 return(TNG_SUCCESS);
10183 tng_function_status DECLSPECDLLEXPORT tng_long_stride_length_set
10184 (const tng_trajectory_t tng_data,
10187 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10189 if(len <= tng_data->medium_stride_length)
10191 return(TNG_FAILURE);
10193 tng_data->long_stride_length = len;
10195 return(TNG_SUCCESS);
10198 tng_function_status DECLSPECDLLEXPORT tng_time_per_frame_get
10199 (const tng_trajectory_t tng_data,
10202 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10203 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
10205 *time = tng_data->time_per_frame;
10207 return(TNG_SUCCESS);
10210 tng_function_status DECLSPECDLLEXPORT tng_time_per_frame_set
10211 (const tng_trajectory_t tng_data,
10214 tng_trajectory_frame_set_t frame_set;
10216 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10217 TNG_ASSERT(time >= 0, "TNG library: The time per frame must be >= 0.");
10219 if(fabs(time - tng_data->time_per_frame) < 0.00001)
10221 return(TNG_SUCCESS);
10224 frame_set = &tng_data->current_trajectory_frame_set;
10226 /* If the current frame set is not finished write it to disk before
10227 changing time per frame. */
10228 if(tng_data->time_per_frame > 0 && frame_set->n_unwritten_frames > 0)
10230 frame_set->n_frames = frame_set->n_unwritten_frames;
10231 tng_frame_set_write(tng_data, TNG_USE_HASH);
10233 tng_data->time_per_frame = time;
10235 return(TNG_SUCCESS);
10238 tng_function_status DECLSPECDLLEXPORT tng_input_file_len_get
10239 (const tng_trajectory_t tng_data,
10242 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10243 TNG_ASSERT(len, "TNG library: len must not be a NULL pointer");
10245 *len = tng_data->input_file_len;
10247 return(TNG_SUCCESS);
10250 tng_function_status DECLSPECDLLEXPORT tng_num_frames_get
10251 (const tng_trajectory_t tng_data,
10254 tng_gen_block_t block;
10255 tng_function_status stat;
10256 int64_t file_pos, last_file_pos, first_frame, n_frames;
10258 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10259 TNG_ASSERT(tng_data->input_file, "TNG library: An input file must be open to find the next frame set");
10260 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10262 file_pos = ftello(tng_data->input_file);
10263 last_file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
10265 if(last_file_pos <= 0)
10267 return(TNG_FAILURE);
10270 tng_block_init(&block);
10271 fseeko(tng_data->input_file,
10274 /* Read block headers first to see that a frame set block is found. */
10275 stat = tng_block_header_read(tng_data, block);
10276 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10278 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", last_file_pos,
10279 __FILE__, __LINE__);
10280 tng_block_destroy(&block);
10281 return(TNG_FAILURE);
10283 tng_block_destroy(&block);
10285 if(tng_file_input_numerical(tng_data, &first_frame,
10286 sizeof(first_frame),
10287 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
10289 return(TNG_CRITICAL);
10292 if(tng_file_input_numerical(tng_data, &n_frames,
10294 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
10296 return(TNG_CRITICAL);
10299 fseeko(tng_data->input_file, file_pos, SEEK_SET);
10301 *n = first_frame + n_frames;
10303 return(TNG_SUCCESS);
10306 tng_function_status DECLSPECDLLEXPORT tng_compression_precision_get
10307 (const tng_trajectory_t tng_data,
10310 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10312 *precision = tng_data->compression_precision;
10314 return(TNG_SUCCESS);
10317 tng_function_status DECLSPECDLLEXPORT tng_compression_precision_set
10318 (const tng_trajectory_t tng_data,
10319 const double precision)
10321 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10323 tng_data->compression_precision = precision;
10325 return(TNG_SUCCESS);
10328 tng_function_status DECLSPECDLLEXPORT tng_implicit_num_particles_set
10329 (const tng_trajectory_t tng_data,
10332 tng_molecule_t mol;
10336 tng_function_status stat;
10337 int64_t diff, n_mod, n_impl;
10339 TNG_ASSERT(n >= 0, "TNG library: The requested number of particles must be >= 0");
10341 diff = n - tng_data->n_particles;
10343 stat = tng_molecule_find(tng_data, "TNG_IMPLICIT_MOL", -1, &mol);
10344 if(stat == TNG_SUCCESS)
10346 if(tng_molecule_cnt_get(tng_data, mol, &n_impl) != TNG_SUCCESS)
10348 fprintf(stderr, "TNG library: Cannot get the number of implicit molecules. %s: %d\n",
10349 __FILE__, __LINE__);
10350 return(TNG_FAILURE);
10352 diff -= n_impl * mol->n_atoms;
10357 if(stat == TNG_SUCCESS)
10359 stat = tng_molecule_cnt_set(tng_data, mol, 0);
10362 return(TNG_SUCCESS);
10366 fprintf(stderr, "TNG library: Already more actual particles than requested implicit ");
10367 fprintf(stderr, "particle count.\n");
10368 fprintf(stderr, "TNG library: Cannot set implicit particle count. %s: %d\n",
10369 __FILE__, __LINE__);
10370 /* FIXME: Should we set the count of all other molecules to 0 and add
10371 * implicit molecules? */
10372 return(TNG_FAILURE);
10374 if(stat != TNG_SUCCESS)
10376 stat = tng_molecule_add(tng_data,
10377 "TNG_IMPLICIT_MOL",
10379 if(stat != TNG_SUCCESS)
10383 stat = tng_molecule_chain_add(tng_data, mol, "", &chain);
10384 if(stat != TNG_SUCCESS)
10388 stat = tng_chain_residue_add(tng_data, chain, "", &res);
10389 if(stat != TNG_SUCCESS)
10393 stat = tng_residue_atom_add(tng_data, res, "", "", &atom);
10394 if(stat != TNG_SUCCESS)
10401 if(mol->n_atoms > 1)
10403 n_mod = diff % mol->n_atoms;
10406 fprintf(stderr, "TNG library: Number of atoms in implicit molecule ");
10407 fprintf(stderr, "not compatible with requested implicit particle cnt.\n");
10408 fprintf(stderr, "TNG library: Cannot set implicit particle count. %s: %d\n",
10409 __FILE__, __LINE__);
10410 return(TNG_FAILURE);
10412 diff /= mol->n_atoms;
10415 stat = tng_molecule_cnt_set(tng_data, mol, diff);
10420 tng_function_status DECLSPECDLLEXPORT tng_num_particles_get
10421 (const tng_trajectory_t tng_data,
10424 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10425 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10427 if(tng_data->var_num_atoms_flag == TNG_CONSTANT_N_ATOMS)
10429 *n = tng_data->n_particles;
10433 *n = tng_data->current_trajectory_frame_set.n_particles;
10436 return(TNG_SUCCESS);
10439 tng_function_status DECLSPECDLLEXPORT tng_num_particles_variable_get
10440 (const tng_trajectory_t tng_data,
10443 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10444 TNG_ASSERT(variable, "TNG library: variable must not be a NULL pointer");
10446 *variable = tng_data->var_num_atoms_flag;
10448 return(TNG_SUCCESS);
10451 tng_function_status DECLSPECDLLEXPORT tng_num_molecule_types_get
10452 (const tng_trajectory_t tng_data,
10455 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10456 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10458 *n = tng_data->n_molecules;
10460 return(TNG_SUCCESS);
10463 tng_function_status DECLSPECDLLEXPORT tng_num_molecules_get
10464 (const tng_trajectory_t tng_data,
10467 int64_t *cnt_list = 0, cnt = 0, i;
10469 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10470 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10472 tng_molecule_cnt_list_get(tng_data, &cnt_list);
10476 return(TNG_FAILURE);
10479 for(i = 0; i < tng_data->n_molecules; i++)
10481 cnt += cnt_list[i];
10486 return(TNG_SUCCESS);
10489 tng_function_status DECLSPECDLLEXPORT tng_molecule_cnt_list_get
10490 (const tng_trajectory_t tng_data,
10491 int64_t **mol_cnt_list)
10493 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10495 if(tng_data->var_num_atoms_flag)
10497 *mol_cnt_list = tng_data->current_trajectory_frame_set.
10502 *mol_cnt_list = tng_data->molecule_cnt_list;
10504 if(*mol_cnt_list == 0)
10506 return(TNG_FAILURE);
10508 return(TNG_SUCCESS);
10511 tng_function_status DECLSPECDLLEXPORT tng_distance_unit_exponential_get
10512 (const tng_trajectory_t tng_data,
10515 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10516 TNG_ASSERT(exp, "TNG library: exp must not be a NULL pointer");
10518 *exp = tng_data->distance_unit_exponential;
10520 return(TNG_SUCCESS);
10523 tng_function_status DECLSPECDLLEXPORT tng_distance_unit_exponential_set
10524 (const tng_trajectory_t tng_data,
10527 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10529 tng_data->distance_unit_exponential = exp;
10531 return(TNG_SUCCESS);
10534 tng_function_status DECLSPECDLLEXPORT tng_num_frames_per_frame_set_get
10535 (const tng_trajectory_t tng_data,
10538 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10539 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10541 *n = tng_data->frame_set_n_frames;
10543 return(TNG_SUCCESS);
10546 tng_function_status DECLSPECDLLEXPORT tng_num_frames_per_frame_set_set
10547 (const tng_trajectory_t tng_data,
10550 tng_trajectory_frame_set_t frame_set;
10551 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10553 tng_data->frame_set_n_frames = n;
10554 frame_set = &tng_data->current_trajectory_frame_set;
10557 frame_set->n_frames = n;
10560 return(TNG_SUCCESS);
10563 tng_function_status DECLSPECDLLEXPORT tng_num_frame_sets_get
10564 (const tng_trajectory_t tng_data,
10567 int64_t long_stride_length, medium_stride_length;
10568 int64_t file_pos, orig_frame_set_file_pos;
10569 tng_trajectory_frame_set_t frame_set;
10570 struct tng_trajectory_frame_set orig_frame_set;
10571 tng_gen_block_t block;
10572 tng_function_status stat;
10575 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10576 TNG_ASSERT(n, "TNG library: n must not be a NULL pointer");
10578 orig_frame_set = tng_data->current_trajectory_frame_set;
10580 frame_set = &tng_data->current_trajectory_frame_set;
10582 orig_frame_set_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
10583 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
10587 *n = tng_data->n_trajectory_frame_sets = cnt;
10588 return(TNG_SUCCESS);
10591 tng_block_init(&block);
10592 fseeko(tng_data->input_file,
10595 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
10596 /* Read block headers first to see what block is found. */
10597 stat = tng_block_header_read(tng_data, block);
10598 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10600 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", file_pos,
10601 __FILE__, __LINE__);
10602 tng_block_destroy(&block);
10603 return(TNG_CRITICAL);
10606 if(tng_block_read_next(tng_data, block,
10607 TNG_SKIP_HASH) != TNG_SUCCESS)
10609 tng_block_destroy(&block);
10610 return(TNG_CRITICAL);
10615 long_stride_length = tng_data->long_stride_length;
10616 medium_stride_length = tng_data->medium_stride_length;
10618 /* Take long steps forward until a long step forward would be too long or
10619 * the last frame set is found */
10620 file_pos = frame_set->long_stride_next_frame_set_file_pos;
10621 while(file_pos > 0)
10625 cnt += long_stride_length;
10626 fseeko(tng_data->input_file, file_pos, SEEK_SET);
10627 /* Read block headers first to see what block is found. */
10628 stat = tng_block_header_read(tng_data, block);
10629 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10631 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
10632 file_pos, __FILE__, __LINE__);
10633 tng_block_destroy(&block);
10634 return(TNG_CRITICAL);
10637 if(tng_block_read_next(tng_data, block,
10638 TNG_SKIP_HASH) != TNG_SUCCESS)
10640 tng_block_destroy(&block);
10641 return(TNG_CRITICAL);
10644 file_pos = frame_set->long_stride_next_frame_set_file_pos;
10647 /* Take medium steps forward until a medium step forward would be too long
10648 * or the last frame set is found */
10649 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
10650 while(file_pos > 0)
10654 cnt += medium_stride_length;
10655 fseeko(tng_data->input_file,
10658 /* Read block headers first to see what block is found. */
10659 stat = tng_block_header_read(tng_data, block);
10660 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10662 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
10663 file_pos, __FILE__, __LINE__);
10664 tng_block_destroy(&block);
10665 return(TNG_CRITICAL);
10668 if(tng_block_read_next(tng_data, block,
10669 TNG_SKIP_HASH) != TNG_SUCCESS)
10671 tng_block_destroy(&block);
10672 return(TNG_CRITICAL);
10675 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
10678 /* Take one step forward until the last frame set is found */
10679 file_pos = frame_set->next_frame_set_file_pos;
10680 while(file_pos > 0)
10685 fseeko(tng_data->input_file,
10688 /* Read block headers first to see what block is found. */
10689 stat = tng_block_header_read(tng_data, block);
10690 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10692 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
10693 file_pos, __FILE__, __LINE__);
10694 tng_block_destroy(&block);
10695 return(TNG_CRITICAL);
10698 if(tng_block_read_next(tng_data, block,
10699 TNG_SKIP_HASH) != TNG_SUCCESS)
10701 tng_block_destroy(&block);
10702 return(TNG_CRITICAL);
10705 file_pos = frame_set->next_frame_set_file_pos;
10708 tng_block_destroy(&block);
10710 *n = tng_data->n_trajectory_frame_sets = cnt;
10712 *frame_set = orig_frame_set;
10713 /* The mapping block in the original frame set has been freed when reading
10714 * other frame sets. */
10715 frame_set->mappings = 0;
10716 frame_set->n_mapping_blocks = 0;
10718 fseeko(tng_data->input_file,
10719 tng_data->first_trajectory_frame_set_input_file_pos,
10722 tng_data->current_trajectory_frame_set_input_file_pos = orig_frame_set_file_pos;
10724 return(TNG_SUCCESS);
10727 tng_function_status DECLSPECDLLEXPORT tng_current_frame_set_get
10728 (const tng_trajectory_t tng_data,
10729 tng_trajectory_frame_set_t *frame_set_p)
10731 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10733 *frame_set_p = &tng_data->current_trajectory_frame_set;
10735 return(TNG_SUCCESS);
10738 tng_function_status DECLSPECDLLEXPORT tng_frame_set_nr_find
10739 (const tng_trajectory_t tng_data,
10742 int64_t long_stride_length, medium_stride_length;
10743 int64_t file_pos, curr_nr = 0, n_frame_sets;
10744 tng_trajectory_frame_set_t frame_set;
10745 tng_gen_block_t block;
10746 tng_function_status stat;
10748 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
10749 TNG_ASSERT(nr >= 0, "The frame set number (nr) must be >= 0");
10751 frame_set = &tng_data->current_trajectory_frame_set;
10753 stat = tng_num_frame_sets_get(tng_data, &n_frame_sets);
10755 if(stat != TNG_SUCCESS)
10760 if(nr >= n_frame_sets)
10762 return(TNG_FAILURE);
10765 long_stride_length = tng_data->long_stride_length;
10766 medium_stride_length = tng_data->medium_stride_length;
10768 /* FIXME: The frame set number of the current frame set is not stored */
10770 if(nr < n_frame_sets - 1 - nr)
10772 /* Start from the beginning */
10773 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
10777 /* Start from the end */
10778 file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
10779 curr_nr = n_frame_sets - 1;
10783 return(TNG_FAILURE);
10786 tng_block_init(&block);
10787 fseeko(tng_data->input_file,
10790 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
10791 /* Read block headers first to see what block is found. */
10792 stat = tng_block_header_read(tng_data, block);
10793 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10795 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", file_pos,
10796 __FILE__, __LINE__);
10797 tng_block_destroy(&block);
10798 return(TNG_CRITICAL);
10801 if(tng_block_read_next(tng_data, block,
10802 TNG_SKIP_HASH) != TNG_SUCCESS)
10804 tng_block_destroy(&block);
10805 return(TNG_CRITICAL);
10810 tng_block_destroy(&block);
10811 return(TNG_SUCCESS);
10814 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
10816 /* Take long steps forward until a long step forward would be too long or
10817 * the right frame set is found */
10818 while(file_pos > 0 && curr_nr + long_stride_length <= nr)
10820 file_pos = frame_set->long_stride_next_frame_set_file_pos;
10823 curr_nr += long_stride_length;
10824 fseeko(tng_data->input_file, file_pos, SEEK_SET);
10825 /* Read block headers first to see what block is found. */
10826 stat = tng_block_header_read(tng_data, block);
10827 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10829 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
10830 file_pos, __FILE__, __LINE__);
10831 tng_block_destroy(&block);
10832 return(TNG_CRITICAL);
10835 if(tng_block_read_next(tng_data, block,
10836 TNG_SKIP_HASH) != TNG_SUCCESS)
10838 tng_block_destroy(&block);
10839 return(TNG_CRITICAL);
10843 tng_block_destroy(&block);
10844 return(TNG_SUCCESS);
10849 /* Take medium steps forward until a medium step forward would be too long
10850 * or the right frame set is found */
10851 while(file_pos > 0 && curr_nr + medium_stride_length <= nr)
10853 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
10856 curr_nr += medium_stride_length;
10857 fseeko(tng_data->input_file,
10860 /* Read block headers first to see what block is found. */
10861 stat = tng_block_header_read(tng_data, block);
10862 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10864 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
10865 file_pos, __FILE__, __LINE__);
10866 tng_block_destroy(&block);
10867 return(TNG_CRITICAL);
10870 if(tng_block_read_next(tng_data, block,
10871 TNG_SKIP_HASH) != TNG_SUCCESS)
10873 tng_block_destroy(&block);
10874 return(TNG_CRITICAL);
10878 tng_block_destroy(&block);
10879 return(TNG_SUCCESS);
10884 /* Take one step forward until the right frame set is found */
10885 while(file_pos > 0 && curr_nr < nr)
10887 file_pos = frame_set->next_frame_set_file_pos;
10892 fseeko(tng_data->input_file,
10895 /* Read block headers first to see what block is found. */
10896 stat = tng_block_header_read(tng_data, block);
10897 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10899 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
10900 file_pos, __FILE__, __LINE__);
10901 tng_block_destroy(&block);
10902 return(TNG_CRITICAL);
10905 if(tng_block_read_next(tng_data, block,
10906 TNG_SKIP_HASH) != TNG_SUCCESS)
10908 tng_block_destroy(&block);
10909 return(TNG_CRITICAL);
10913 tng_block_destroy(&block);
10914 return(TNG_SUCCESS);
10919 /* Take long steps backward until a long step backward would be too long
10920 * or the right frame set is found */
10921 while(file_pos > 0 && curr_nr - long_stride_length >= nr)
10923 file_pos = frame_set->long_stride_prev_frame_set_file_pos;
10926 curr_nr -= long_stride_length;
10927 fseeko(tng_data->input_file,
10930 /* Read block headers first to see what block is found. */
10931 stat = tng_block_header_read(tng_data, block);
10932 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10934 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
10935 file_pos, __FILE__, __LINE__);
10936 tng_block_destroy(&block);
10937 return(TNG_CRITICAL);
10940 if(tng_block_read_next(tng_data, block,
10941 TNG_SKIP_HASH) != TNG_SUCCESS)
10943 tng_block_destroy(&block);
10944 return(TNG_CRITICAL);
10948 tng_block_destroy(&block);
10949 return(TNG_SUCCESS);
10954 /* Take medium steps backward until a medium step backward would be too long
10955 * or the right frame set is found */
10956 while(file_pos > 0 && curr_nr - medium_stride_length >= nr)
10958 file_pos = frame_set->medium_stride_prev_frame_set_file_pos;
10961 curr_nr -= medium_stride_length;
10962 fseeko(tng_data->input_file,
10965 /* Read block headers first to see what block is found. */
10966 stat = tng_block_header_read(tng_data, block);
10967 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
10969 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
10970 file_pos, __FILE__, __LINE__);
10971 tng_block_destroy(&block);
10972 return(TNG_CRITICAL);
10975 if(tng_block_read_next(tng_data, block,
10976 TNG_SKIP_HASH) != TNG_SUCCESS)
10978 tng_block_destroy(&block);
10979 return(TNG_CRITICAL);
10983 tng_block_destroy(&block);
10984 return(TNG_SUCCESS);
10989 /* Take one step backward until the right frame set is found */
10990 while(file_pos > 0 && curr_nr > nr)
10992 file_pos = frame_set->prev_frame_set_file_pos;
10996 fseeko(tng_data->input_file,
10999 /* Read block headers first to see what block is found. */
11000 stat = tng_block_header_read(tng_data, block);
11001 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11003 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11004 file_pos, __FILE__, __LINE__);
11005 tng_block_destroy(&block);
11006 return(TNG_CRITICAL);
11009 if(tng_block_read_next(tng_data, block,
11010 TNG_SKIP_HASH) != TNG_SUCCESS)
11012 tng_block_destroy(&block);
11013 return(TNG_CRITICAL);
11017 tng_block_destroy(&block);
11018 return(TNG_SUCCESS);
11023 /* If for some reason the current frame set is not yet found,
11024 * take one step forward until the right frame set is found */
11025 while(file_pos > 0 && curr_nr < nr)
11027 file_pos = frame_set->next_frame_set_file_pos;
11031 fseeko(tng_data->input_file,
11034 /* Read block headers first to see what block is found. */
11035 stat = tng_block_header_read(tng_data, block);
11036 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11038 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11039 file_pos, __FILE__, __LINE__);
11040 tng_block_destroy(&block);
11041 return(TNG_CRITICAL);
11044 if(tng_block_read_next(tng_data, block,
11045 TNG_SKIP_HASH) != TNG_SUCCESS)
11047 tng_block_destroy(&block);
11048 return(TNG_CRITICAL);
11052 tng_block_destroy(&block);
11053 return(TNG_SUCCESS);
11058 tng_block_destroy(&block);
11059 return(TNG_FAILURE);
11062 tng_function_status DECLSPECDLLEXPORT tng_frame_set_of_frame_find
11063 (const tng_trajectory_t tng_data,
11064 const int64_t frame)
11066 int64_t first_frame, last_frame, n_frames_per_frame_set;
11067 int64_t long_stride_length, medium_stride_length;
11068 int64_t file_pos, temp_frame, n_frames;
11069 tng_trajectory_frame_set_t frame_set;
11070 tng_gen_block_t block;
11071 tng_function_status stat;
11073 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11074 TNG_ASSERT(frame >= 0, "TNG library: frame must be >= 0.");
11076 frame_set = &tng_data->current_trajectory_frame_set;
11078 tng_block_init(&block);
11080 if(tng_data->current_trajectory_frame_set_input_file_pos < 0)
11082 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
11083 fseeko(tng_data->input_file,
11086 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
11087 /* Read block headers first to see what block is found. */
11088 stat = tng_block_header_read(tng_data, block);
11089 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11091 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11092 file_pos, __FILE__, __LINE__);
11093 tng_block_destroy(&block);
11094 return(TNG_CRITICAL);
11097 if(tng_block_read_next(tng_data, block,
11098 TNG_SKIP_HASH) != TNG_SUCCESS)
11100 tng_block_destroy(&block);
11101 return(TNG_CRITICAL);
11105 first_frame = tng_max_i64(frame_set->first_frame, 0);
11106 last_frame = first_frame + frame_set->n_frames - 1;
11107 /* Is this the right frame set? */
11108 if(first_frame <= frame && frame <= last_frame)
11110 tng_block_destroy(&block);
11111 return(TNG_SUCCESS);
11114 n_frames_per_frame_set = tng_data->frame_set_n_frames;
11115 long_stride_length = tng_data->long_stride_length;
11116 medium_stride_length = tng_data->medium_stride_length;
11118 if(tng_first_frame_nr_of_next_frame_set_get(tng_data, &temp_frame) ==
11121 if(temp_frame - first_frame > n_frames_per_frame_set)
11123 n_frames_per_frame_set = temp_frame - first_frame;
11127 tng_num_frames_get(tng_data, &n_frames);
11129 if(frame >= n_frames)
11131 tng_block_destroy(&block);
11132 return(TNG_FAILURE);
11135 if(first_frame - frame >= frame ||
11136 frame - last_frame >
11137 tng_data->n_trajectory_frame_sets * n_frames_per_frame_set - frame)
11139 /* Start from the beginning */
11140 if(first_frame - frame >= frame)
11142 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
11146 tng_block_destroy(&block);
11147 return(TNG_FAILURE);
11150 /* Start from the end */
11151 else if(frame - first_frame > (n_frames - 1) - frame)
11153 file_pos = tng_data->last_trajectory_frame_set_input_file_pos;
11155 /* If the last frame set position is not set start from the current
11156 * frame set, since it will be closer than the first frame set. */
11158 /* Start from current */
11161 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
11166 fseeko(tng_data->input_file,
11169 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
11170 /* Read block headers first to see what block is found. */
11171 stat = tng_block_header_read(tng_data, block);
11172 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11174 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11175 file_pos, __FILE__, __LINE__);
11176 tng_block_destroy(&block);
11177 return(TNG_CRITICAL);
11180 if(tng_block_read_next(tng_data, block,
11181 TNG_SKIP_HASH) != TNG_SUCCESS)
11183 tng_block_destroy(&block);
11184 return(TNG_CRITICAL);
11189 first_frame = tng_max_i64(frame_set->first_frame, 0);
11190 last_frame = first_frame + frame_set->n_frames - 1;
11192 if(frame >= first_frame && frame <= last_frame)
11194 tng_block_destroy(&block);
11195 return(TNG_SUCCESS);
11198 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
11200 /* Take long steps forward until a long step forward would be too long or
11201 * the right frame set is found */
11202 while(file_pos > 0 && first_frame + long_stride_length *
11203 n_frames_per_frame_set <= frame)
11205 file_pos = frame_set->long_stride_next_frame_set_file_pos;
11208 fseeko(tng_data->input_file, file_pos, SEEK_SET);
11209 /* Read block headers first to see what block is found. */
11210 stat = tng_block_header_read(tng_data, block);
11211 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11213 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11214 file_pos, __FILE__, __LINE__);
11215 tng_block_destroy(&block);
11216 return(TNG_CRITICAL);
11219 if(tng_block_read_next(tng_data, block,
11220 TNG_SKIP_HASH) != TNG_SUCCESS)
11222 tng_block_destroy(&block);
11223 return(TNG_CRITICAL);
11226 first_frame = tng_max_i64(frame_set->first_frame, 0);
11227 last_frame = first_frame + frame_set->n_frames - 1;
11228 if(frame >= first_frame && frame <= last_frame)
11230 tng_block_destroy(&block);
11231 return(TNG_SUCCESS);
11235 /* Take medium steps forward until a medium step forward would be too long
11236 * or the right frame set is found */
11237 while(file_pos > 0 && first_frame + medium_stride_length *
11238 n_frames_per_frame_set <= frame)
11240 file_pos = frame_set->medium_stride_next_frame_set_file_pos;
11243 fseeko(tng_data->input_file,
11246 /* Read block headers first to see what block is found. */
11247 stat = tng_block_header_read(tng_data, block);
11248 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11250 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11251 file_pos, __FILE__, __LINE__);
11252 tng_block_destroy(&block);
11253 return(TNG_CRITICAL);
11256 if(tng_block_read_next(tng_data, block,
11257 TNG_SKIP_HASH) != TNG_SUCCESS)
11259 tng_block_destroy(&block);
11260 return(TNG_CRITICAL);
11263 first_frame = tng_max_i64(frame_set->first_frame, 0);
11264 last_frame = first_frame + frame_set->n_frames - 1;
11265 if(frame >= first_frame && frame <= last_frame)
11267 tng_block_destroy(&block);
11268 return(TNG_SUCCESS);
11272 /* Take one step forward until the right frame set is found */
11273 while(file_pos > 0 && first_frame < frame && last_frame < frame)
11275 file_pos = frame_set->next_frame_set_file_pos;
11278 fseeko(tng_data->input_file,
11281 /* Read block headers first to see what block is found. */
11282 stat = tng_block_header_read(tng_data, block);
11283 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11285 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11286 file_pos, __FILE__, __LINE__);
11287 tng_block_destroy(&block);
11288 return(TNG_CRITICAL);
11291 if(tng_block_read_next(tng_data, block,
11292 TNG_SKIP_HASH) != TNG_SUCCESS)
11294 tng_block_destroy(&block);
11295 return(TNG_CRITICAL);
11298 first_frame = tng_max_i64(frame_set->first_frame, 0);
11299 last_frame = first_frame + frame_set->n_frames - 1;
11300 if(frame >= first_frame && frame <= last_frame)
11302 tng_block_destroy(&block);
11303 return(TNG_SUCCESS);
11307 /* Take long steps backward until a long step backward would be too long
11308 * or the right frame set is found */
11309 while(file_pos > 0 && first_frame - long_stride_length *
11310 n_frames_per_frame_set >= frame)
11312 file_pos = frame_set->long_stride_prev_frame_set_file_pos;
11315 fseeko(tng_data->input_file,
11318 /* Read block headers first to see what block is found. */
11319 stat = tng_block_header_read(tng_data, block);
11320 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11322 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11323 file_pos, __FILE__, __LINE__);
11324 tng_block_destroy(&block);
11325 return(TNG_CRITICAL);
11328 if(tng_block_read_next(tng_data, block,
11329 TNG_SKIP_HASH) != TNG_SUCCESS)
11331 tng_block_destroy(&block);
11332 return(TNG_CRITICAL);
11335 first_frame = tng_max_i64(frame_set->first_frame, 0);
11336 last_frame = first_frame + frame_set->n_frames - 1;
11337 if(frame >= first_frame && frame <= last_frame)
11339 tng_block_destroy(&block);
11340 return(TNG_SUCCESS);
11344 /* Take medium steps backward until a medium step backward would be too long
11345 * or the right frame set is found */
11346 while(file_pos > 0 && first_frame - medium_stride_length *
11347 n_frames_per_frame_set >= frame)
11349 file_pos = frame_set->medium_stride_prev_frame_set_file_pos;
11352 fseeko(tng_data->input_file,
11355 /* Read block headers first to see what block is found. */
11356 stat = tng_block_header_read(tng_data, block);
11357 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11359 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11360 file_pos, __FILE__, __LINE__);
11361 tng_block_destroy(&block);
11362 return(TNG_CRITICAL);
11365 if(tng_block_read_next(tng_data, block,
11366 TNG_SKIP_HASH) != TNG_SUCCESS)
11368 tng_block_destroy(&block);
11369 return(TNG_CRITICAL);
11372 first_frame = tng_max_i64(frame_set->first_frame, 0);
11373 last_frame = first_frame + frame_set->n_frames - 1;
11374 if(frame >= first_frame && frame <= last_frame)
11376 tng_block_destroy(&block);
11377 return(TNG_SUCCESS);
11381 /* Take one step backward until the right frame set is found */
11382 while(file_pos > 0 && first_frame > frame && last_frame > frame)
11384 file_pos = frame_set->prev_frame_set_file_pos;
11387 fseeko(tng_data->input_file,
11390 /* Read block headers first to see what block is found. */
11391 stat = tng_block_header_read(tng_data, block);
11392 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11394 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11395 file_pos, __FILE__, __LINE__);
11396 tng_block_destroy(&block);
11397 return(TNG_CRITICAL);
11400 if(tng_block_read_next(tng_data, block,
11401 TNG_SKIP_HASH) != TNG_SUCCESS)
11403 tng_block_destroy(&block);
11404 return(TNG_CRITICAL);
11407 first_frame = tng_max_i64(frame_set->first_frame, 0);
11408 last_frame = first_frame + frame_set->n_frames - 1;
11409 if(frame >= first_frame && frame <= last_frame)
11411 tng_block_destroy(&block);
11412 return(TNG_SUCCESS);
11416 /* If for some reason the current frame set is not yet found,
11417 * take one step forward until the right frame set is found */
11418 while(file_pos > 0 && first_frame < frame && last_frame < frame)
11420 file_pos = frame_set->next_frame_set_file_pos;
11423 fseeko(tng_data->input_file,
11426 /* Read block headers first to see what block is found. */
11427 stat = tng_block_header_read(tng_data, block);
11428 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11430 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11431 file_pos, __FILE__, __LINE__);
11432 tng_block_destroy(&block);
11433 return(TNG_CRITICAL);
11436 if(tng_block_read_next(tng_data, block,
11437 TNG_SKIP_HASH) != TNG_SUCCESS)
11439 tng_block_destroy(&block);
11440 return(TNG_CRITICAL);
11443 first_frame = tng_max_i64(frame_set->first_frame, 0);
11444 last_frame = first_frame + frame_set->n_frames - 1;
11445 if(frame >= first_frame && frame <= last_frame)
11447 tng_block_destroy(&block);
11448 return(TNG_SUCCESS);
11452 tng_block_destroy(&block);
11453 return(TNG_FAILURE);
11456 tng_function_status DECLSPECDLLEXPORT tng_frame_set_next_frame_set_file_pos_get
11457 (const tng_trajectory_t tng_data,
11458 const tng_trajectory_frame_set_t frame_set,
11463 TNG_ASSERT(frame_set, "TNG library: frame_set not initialised before accessing data.");
11464 TNG_ASSERT(pos, "TNG library: pos must not be a NULL pointer");
11466 *pos = frame_set->next_frame_set_file_pos;
11468 return(TNG_SUCCESS);
11471 tng_function_status DECLSPECDLLEXPORT tng_frame_set_prev_frame_set_file_pos_get
11472 (const tng_trajectory_t tng_data,
11473 const tng_trajectory_frame_set_t frame_set,
11478 TNG_ASSERT(frame_set, "TNG library: frame_set not initialised before accessing data.");
11479 TNG_ASSERT(pos, "TNG library: pos must not be a NULL pointer");
11481 *pos = frame_set->prev_frame_set_file_pos;
11483 return(TNG_SUCCESS);
11486 tng_function_status DECLSPECDLLEXPORT tng_frame_set_frame_range_get
11487 (const tng_trajectory_t tng_data,
11488 const tng_trajectory_frame_set_t frame_set,
11489 int64_t *first_frame,
11490 int64_t *last_frame)
11494 TNG_ASSERT(first_frame, "TNG library: first_frame must not be a NULL pointer");
11495 TNG_ASSERT(last_frame, "TNG library: last_frame must not be a NULL pointer");
11496 TNG_ASSERT(frame_set, "TNG library: frame_set must not be a NULL pointer");
11498 *first_frame = frame_set->first_frame;
11499 *last_frame = *first_frame + frame_set->n_frames - 1;
11501 return(TNG_SUCCESS);
11505 * @brief Translate from the particle numbering used in a frame set to the real
11506 * particle numbering - used in the molecule description.
11507 * @param frame_set is the frame_set containing the mappings to use.
11508 * @param local is the index number of the atom in this frame set
11509 * @param real is set to the index of the atom in the molecular system.
11510 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the mapping
11513 static TNG_INLINE tng_function_status tng_particle_mapping_get_real_particle
11514 (const tng_trajectory_frame_set_t frame_set,
11515 const int64_t local,
11518 int64_t i, n_blocks = frame_set->n_mapping_blocks, first;
11519 tng_particle_mapping_t mapping;
11523 return(TNG_SUCCESS);
11525 for(i = 0; i < n_blocks; i++)
11527 mapping = &frame_set->mappings[i];
11528 first = mapping->num_first_particle;
11529 if(local < first ||
11530 local >= first + mapping->n_particles)
11534 *real = mapping->real_particle_numbers[local-first];
11535 return(TNG_SUCCESS);
11538 return(TNG_FAILURE);
11542 * @brief Translate from the real particle numbering to the particle numbering
11543 * used in a frame set.
11544 * @param frame_set is the frame_set containing the mappings to use.
11545 * @param real is the index number of the atom in the molecular system.
11546 * @param local is set to the index of the atom in this frame set.
11547 * @return TNG_SUCCESS (0) if successful or TNG_FAILURE (1) if the mapping
11550 /*static TNG_INLINE tng_function_status tng_particle_mapping_get_local_particle
11551 (const tng_trajectory_frame_set_t frame_set,
11552 const int64_t real,
11555 int64_t i, j, n_blocks = frame_set->n_mapping_blocks;
11556 tng_particle_mapping_t mapping;
11560 return(TNG_SUCCESS);
11562 for(i = 0; i < n_blocks; i++)
11564 mapping = &frame_set->mappings[i];
11565 for(j = mapping->n_particles; j--;)
11567 if(mapping->real_particle_numbers[j] == real)
11570 return(TNG_SUCCESS);
11574 return(TNG_FAILURE);
11578 static tng_function_status tng_file_headers_len_get
11579 (const tng_trajectory_t tng_data,
11583 tng_gen_block_t block;
11585 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11587 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
11589 return(TNG_CRITICAL);
11594 orig_pos = ftello(tng_data->input_file);
11596 fseeko(tng_data->input_file, 0, SEEK_SET);
11598 tng_block_init(&block);
11599 /* Read through the headers of non-trajectory blocks (they come before the
11600 * trajectory blocks in the file) */
11601 while (*len < tng_data->input_file_len &&
11602 tng_block_header_read(tng_data, block) != TNG_CRITICAL &&
11604 block->id != TNG_TRAJECTORY_FRAME_SET)
11606 *len += block->header_contents_size + block->block_contents_size;
11607 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
11610 fseeko(tng_data->input_file, orig_pos, SEEK_SET);
11612 tng_block_destroy(&block);
11614 return(TNG_SUCCESS);
11617 tng_function_status DECLSPECDLLEXPORT tng_file_headers_read
11618 (const tng_trajectory_t tng_data,
11619 const char hash_mode)
11621 int64_t prev_pos = 0;
11622 tng_gen_block_t block;
11624 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11626 tng_data->n_trajectory_frame_sets = 0;
11628 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
11630 return(TNG_CRITICAL);
11633 fseeko(tng_data->input_file, 0, SEEK_SET);
11635 tng_block_init(&block);
11636 /* Non trajectory blocks (they come before the trajectory
11637 * blocks in the file) */
11638 while (prev_pos < tng_data->input_file_len &&
11639 tng_block_header_read(tng_data, block) != TNG_CRITICAL &&
11641 block->id != TNG_TRAJECTORY_FRAME_SET)
11643 tng_block_read_next(tng_data, block, hash_mode);
11644 prev_pos = ftello(tng_data->input_file);
11647 /* Go back if a trajectory block was encountered */
11648 if(block->id == TNG_TRAJECTORY_FRAME_SET)
11650 fseeko(tng_data->input_file, prev_pos, SEEK_SET);
11653 tng_block_destroy(&block);
11655 return(TNG_SUCCESS);
11658 tng_function_status DECLSPECDLLEXPORT tng_file_headers_write
11659 (const tng_trajectory_t tng_data,
11660 const char hash_mode)
11663 int64_t len, orig_len, tot_len = 0, data_start_pos, temp_pos = -1;
11664 tng_function_status stat;
11665 tng_gen_block_t block;
11667 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11669 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
11671 return(TNG_CRITICAL);
11674 if(tng_data->n_trajectory_frame_sets > 0)
11676 stat = tng_file_headers_len_get(tng_data, &orig_len);
11677 if(stat != TNG_SUCCESS)
11682 tng_block_init(&block);
11683 block->name = malloc(TNG_MAX_STR_LEN);
11686 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
11687 TNG_MAX_STR_LEN, __FILE__, __LINE__);
11688 tng_block_destroy(&block);
11689 return(TNG_CRITICAL);
11691 strcpy(block->name, "GENERAL INFO");
11692 tng_block_header_len_calculate(tng_data, block, &len);
11694 tng_general_info_block_len_calculate(tng_data, &len);
11696 strcpy(block->name, "MOLECULES");
11697 tng_block_header_len_calculate(tng_data, block, &len);
11699 tng_molecules_block_len_calculate(tng_data, &len);
11702 for(i = 0; i < tng_data->n_data_blocks; i++)
11704 strcpy(block->name, tng_data->non_tr_data[i].block_name);
11705 tng_block_header_len_calculate(tng_data, block, &len);
11707 tng_data_block_len_calculate(tng_data,
11708 (tng_data_t)&tng_data->non_tr_data[i],
11709 TNG_FALSE, 1, 1, 1, 0, 1,
11714 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
11716 strcpy(block->name, tng_data->non_tr_particle_data[i].block_name);
11717 tng_block_header_len_calculate(tng_data, block, &len);
11719 tng_data_block_len_calculate(tng_data,
11720 &tng_data->non_tr_particle_data[i],
11721 TNG_TRUE, 1, 1, 1, 0,
11722 tng_data->n_particles,
11727 tng_block_destroy(&block);
11729 if(tot_len > orig_len)
11731 tng_migrate_data_in_file(tng_data, orig_len+1, tot_len - orig_len, hash_mode);
11734 stat = tng_reread_frame_set_at_file_pos(tng_data, tng_data->last_trajectory_frame_set_input_file_pos);
11735 if(stat == TNG_CRITICAL)
11737 fprintf(stderr, "TNG library: Cannot read frame set. %s: %d\n",
11738 __FILE__, __LINE__);
11739 return(TNG_CRITICAL);
11742 /* In order to write non-trajectory data the current_trajectory_frame_set_output_file_pos
11743 * must temporarily be reset */
11744 temp_pos = tng_data->current_trajectory_frame_set_output_file_pos;
11745 tng_data->current_trajectory_frame_set_output_file_pos = -1;
11748 if(tng_general_info_block_write(tng_data, hash_mode)
11751 fprintf(stderr, "TNG library: Error writing general info block of file %s. %s: %d\n",
11752 tng_data->input_file_path, __FILE__, __LINE__);
11753 return(TNG_CRITICAL);
11756 if(tng_molecules_block_write(tng_data, hash_mode)
11759 fprintf(stderr, "TNG library: Error writing atom names block of file %s. %s: %d\n",
11760 tng_data->input_file_path, __FILE__, __LINE__);
11761 return(TNG_CRITICAL);
11764 /* FIXME: Currently writing non-trajectory data blocks here.
11765 * Should perhaps be moved. */
11766 tng_block_init(&block);
11767 for(i = 0; i < tng_data->n_data_blocks; i++)
11769 block->id = tng_data->non_tr_data[i].block_id;
11770 tng_data_block_write(tng_data, block,
11771 i, TNG_FALSE, 0, hash_mode);
11774 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
11776 block->id = tng_data->non_tr_particle_data[i].block_id;
11777 tng_data_block_write(tng_data, block,
11778 i, TNG_TRUE, 0, hash_mode);
11781 tng_block_destroy(&block);
11783 /* Continue writing at the end of the file. */
11784 fseeko(tng_data->output_file, 0, SEEK_END);
11787 tng_data->current_trajectory_frame_set_output_file_pos = temp_pos;
11790 return(TNG_SUCCESS);
11793 tng_function_status DECLSPECDLLEXPORT tng_block_read_next
11794 (const tng_trajectory_t tng_data,
11795 const tng_gen_block_t block,
11796 const char hash_mode)
11798 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11799 TNG_ASSERT(block, "TNG library: block must be initialised and must not be a NULL pointer.");
11803 case TNG_TRAJECTORY_FRAME_SET:
11804 return(tng_frame_set_block_read(tng_data, block, hash_mode));
11805 case TNG_PARTICLE_MAPPING:
11806 return(tng_trajectory_mapping_block_read(tng_data, block, hash_mode));
11807 case TNG_GENERAL_INFO:
11808 return(tng_general_info_block_read(tng_data, block, hash_mode));
11809 case TNG_MOLECULES:
11810 return(tng_molecules_block_read(tng_data, block, hash_mode));
11812 if(block->id >= TNG_TRAJ_BOX_SHAPE)
11814 return(tng_data_block_contents_read(tng_data, block, hash_mode));
11818 /* Skip to the next block */
11819 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
11820 return(TNG_FAILURE);
11825 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read
11826 (const tng_trajectory_t tng_data,
11827 const char hash_mode)
11830 tng_gen_block_t block;
11831 tng_function_status stat;
11833 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11835 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
11837 return(TNG_CRITICAL);
11840 file_pos = ftello(tng_data->input_file);
11842 tng_block_init(&block);
11844 /* Read block headers first to see what block is found. */
11845 stat = tng_block_header_read(tng_data, block);
11846 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET ||
11849 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11850 file_pos, __FILE__, __LINE__);
11851 tng_block_destroy(&block);
11852 return(TNG_CRITICAL);
11855 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
11857 if(tng_block_read_next(tng_data, block,
11858 hash_mode) == TNG_SUCCESS)
11860 tng_data->n_trajectory_frame_sets++;
11861 file_pos = ftello(tng_data->input_file);
11862 /* Read all blocks until next frame set block */
11863 stat = tng_block_header_read(tng_data, block);
11864 while(file_pos < tng_data->input_file_len &&
11865 stat != TNG_CRITICAL &&
11866 block->id != TNG_TRAJECTORY_FRAME_SET &&
11869 stat = tng_block_read_next(tng_data, block,
11871 if(stat != TNG_CRITICAL)
11873 file_pos = ftello(tng_data->input_file);
11874 if(file_pos < tng_data->input_file_len)
11876 stat = tng_block_header_read(tng_data, block);
11880 if(stat == TNG_CRITICAL)
11882 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11883 file_pos, __FILE__, __LINE__);
11884 tng_block_destroy(&block);
11888 if(block->id == TNG_TRAJECTORY_FRAME_SET)
11890 fseeko(tng_data->input_file, file_pos, SEEK_SET);
11894 tng_block_destroy(&block);
11896 return(TNG_SUCCESS);
11900 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_current_only_data_from_block_id
11901 (const tng_trajectory_t tng_data,
11902 const char hash_mode,
11903 const int64_t block_id)
11906 tng_gen_block_t block;
11907 tng_function_status stat;
11908 int found_flag = 1;
11910 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
11912 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
11914 return(TNG_CRITICAL);
11917 file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
11921 /* No current frame set. This means that the first frame set must be
11924 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
11929 fseeko(tng_data->input_file,
11935 return(TNG_FAILURE);
11938 tng_block_init(&block);
11940 /* Read block headers first to see what block is found. */
11941 stat = tng_block_header_read(tng_data, block);
11942 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
11944 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
11945 file_pos, __FILE__, __LINE__);
11946 tng_block_destroy(&block);
11947 return(TNG_CRITICAL);
11949 /* If the current frame set had already been read skip its block contents */
11952 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
11954 /* Otherwise read the frame set block */
11957 stat = tng_block_read_next(tng_data, block,
11959 if(stat != TNG_SUCCESS)
11961 fprintf(stderr, "TNG library: Cannot read frame set block. %s: %d\n", __FILE__, __LINE__);
11962 tng_block_destroy(&block);
11966 file_pos = ftello(tng_data->input_file);
11970 /* Read only blocks of the requested ID
11971 * until next frame set block */
11972 stat = tng_block_header_read(tng_data, block);
11973 while(file_pos < tng_data->input_file_len &&
11974 stat != TNG_CRITICAL &&
11975 block->id != TNG_TRAJECTORY_FRAME_SET &&
11978 if(block->id == block_id)
11980 stat = tng_block_read_next(tng_data, block,
11982 if(stat != TNG_CRITICAL)
11984 file_pos = ftello(tng_data->input_file);
11986 if(file_pos < tng_data->input_file_len)
11988 stat = tng_block_header_read(tng_data, block);
11994 file_pos += block->block_contents_size + block->header_contents_size;
11995 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
11996 if(file_pos < tng_data->input_file_len)
11998 stat = tng_block_header_read(tng_data, block);
12002 if(stat == TNG_CRITICAL)
12004 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12005 file_pos, __FILE__, __LINE__);
12006 tng_block_destroy(&block);
12010 if(block->id == TNG_TRAJECTORY_FRAME_SET)
12012 fseeko(tng_data->input_file, file_pos, SEEK_SET);
12015 tng_block_destroy(&block);
12019 return(TNG_SUCCESS);
12023 return(TNG_FAILURE);
12027 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next
12028 (const tng_trajectory_t tng_data,
12029 const char hash_mode)
12033 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12035 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12037 return(TNG_CRITICAL);
12040 file_pos = tng_data->current_trajectory_frame_set.next_frame_set_file_pos;
12042 if(file_pos < 0 && tng_data->current_trajectory_frame_set_input_file_pos <= 0)
12044 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
12049 fseeko(tng_data->input_file,
12055 return(TNG_FAILURE);
12058 return(tng_frame_set_read(tng_data, hash_mode));
12061 tng_function_status DECLSPECDLLEXPORT tng_frame_set_read_next_only_data_from_block_id
12062 (const tng_trajectory_t tng_data,
12063 const char hash_mode,
12064 const int64_t block_id)
12067 tng_gen_block_t block;
12068 tng_function_status stat;
12070 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12072 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
12074 return(TNG_CRITICAL);
12077 file_pos = tng_data->current_trajectory_frame_set.next_frame_set_file_pos;
12079 if(file_pos < 0 && tng_data->current_trajectory_frame_set_input_file_pos <= 0)
12081 file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
12086 fseeko(tng_data->input_file,
12092 return(TNG_FAILURE);
12095 tng_block_init(&block);
12097 /* Read block headers first to see what block is found. */
12098 stat = tng_block_header_read(tng_data, block);
12099 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12101 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12102 file_pos, __FILE__, __LINE__);
12103 tng_block_destroy(&block);
12104 return(TNG_CRITICAL);
12107 tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
12109 if(tng_block_read_next(tng_data, block,
12110 hash_mode) == TNG_SUCCESS)
12112 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, hash_mode, block_id);
12115 tng_block_destroy(&block);
12120 tng_function_status tng_frame_set_write
12121 (const tng_trajectory_t tng_data,
12122 const char hash_mode)
12125 tng_gen_block_t block;
12126 tng_trajectory_frame_set_t frame_set;
12127 tng_function_status stat;
12129 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12131 frame_set = &tng_data->current_trajectory_frame_set;
12133 if(frame_set->n_written_frames == frame_set->n_frames)
12135 return(TNG_SUCCESS);
12138 tng_data->current_trajectory_frame_set_output_file_pos =
12139 ftello(tng_data->output_file);
12140 tng_data->last_trajectory_frame_set_output_file_pos =
12141 tng_data->current_trajectory_frame_set_output_file_pos;
12143 if(tng_data->current_trajectory_frame_set_output_file_pos <= 0)
12145 return(TNG_FAILURE);
12148 if(tng_data->first_trajectory_frame_set_output_file_pos == -1)
12150 tng_data->first_trajectory_frame_set_output_file_pos =
12151 tng_data->current_trajectory_frame_set_output_file_pos;
12154 tng_block_init(&block);
12156 if(tng_frame_set_block_write(tng_data, block, hash_mode) != TNG_SUCCESS)
12158 tng_block_destroy(&block);
12159 return(TNG_FAILURE);
12162 /* Write non-particle data blocks */
12163 for(i = 0; i<frame_set->n_data_blocks; i++)
12165 block->id = frame_set->tr_data[i].block_id;
12166 tng_data_block_write(tng_data, block, i, TNG_FALSE, 0, hash_mode);
12168 /* Write the mapping blocks and particle data blocks*/
12169 if(frame_set->n_mapping_blocks)
12171 for(i = 0; i < frame_set->n_mapping_blocks; i++)
12173 block->id = TNG_PARTICLE_MAPPING;
12174 if(frame_set->mappings[i].n_particles > 0)
12176 tng_trajectory_mapping_block_write(tng_data, block, i, hash_mode);
12177 for(j = 0; j<frame_set->n_particle_data_blocks; j++)
12179 block->id = frame_set->tr_particle_data[j].block_id;
12180 tng_data_block_write(tng_data, block,
12181 j, TNG_TRUE, &frame_set->mappings[i],
12189 for(i = 0; i<frame_set->n_particle_data_blocks; i++)
12191 block->id = frame_set->tr_particle_data[i].block_id;
12192 tng_data_block_write(tng_data, block,
12193 i, TNG_TRUE, 0, hash_mode);
12198 /* Update pointers in the general info block */
12199 stat = tng_header_pointers_update(tng_data, hash_mode);
12201 if(stat == TNG_SUCCESS)
12203 stat = tng_frame_set_pointers_update(tng_data, hash_mode);
12206 tng_block_destroy(&block);
12208 frame_set->n_unwritten_frames = 0;
12210 fflush(tng_data->output_file);
12215 tng_function_status DECLSPECDLLEXPORT tng_frame_set_premature_write
12216 (const tng_trajectory_t tng_data,
12217 const char hash_mode)
12219 tng_trajectory_frame_set_t frame_set;
12221 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12223 frame_set = &tng_data->current_trajectory_frame_set;
12225 if(frame_set->n_unwritten_frames == 0)
12227 return(TNG_SUCCESS);
12229 frame_set->n_frames = frame_set->n_unwritten_frames;
12231 return(tng_frame_set_write(tng_data, hash_mode));
12234 tng_function_status DECLSPECDLLEXPORT tng_frame_set_new
12235 (const tng_trajectory_t tng_data,
12236 const int64_t first_frame,
12237 const int64_t n_frames)
12239 tng_gen_block_t block;
12240 tng_trajectory_frame_set_t frame_set;
12241 FILE *temp = tng_data->input_file;
12242 int64_t curr_file_pos;
12244 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12245 TNG_ASSERT(first_frame >= 0, "TNG library: first_frame must be >= 0.");
12246 TNG_ASSERT(n_frames >= 0, "TNG library: n_frames must be >= 0.");
12248 frame_set = &tng_data->current_trajectory_frame_set;
12250 curr_file_pos = ftello(tng_data->output_file);
12252 if(curr_file_pos <= 10)
12254 tng_file_headers_write(tng_data, TNG_USE_HASH);
12257 /* Set pointer to previous frame set to the one that was loaded
12259 * FIXME: This is a bit risky. If they are not added in order
12260 * it will be wrong. */
12261 if(tng_data->n_trajectory_frame_sets)
12263 frame_set->prev_frame_set_file_pos =
12264 tng_data->last_trajectory_frame_set_output_file_pos;
12267 frame_set->next_frame_set_file_pos = -1;
12269 tng_data->current_trajectory_frame_set_output_file_pos =
12270 ftello(tng_data->output_file);
12272 tng_data->n_trajectory_frame_sets++;
12274 /* Set the medium range pointers */
12275 if(tng_data->n_trajectory_frame_sets == tng_data->medium_stride_length + 1)
12277 frame_set->medium_stride_prev_frame_set_file_pos =
12278 tng_data->first_trajectory_frame_set_output_file_pos;
12280 else if(tng_data->n_trajectory_frame_sets > tng_data->medium_stride_length + 1)
12282 /* FIXME: Currently only working if the previous frame set has its
12283 * medium stride pointer already set. This might need some fixing. */
12284 if(frame_set->medium_stride_prev_frame_set_file_pos != -1 &&
12285 frame_set->medium_stride_prev_frame_set_file_pos != 0)
12287 tng_block_init(&block);
12288 tng_data->input_file = tng_data->output_file;
12290 curr_file_pos = ftello(tng_data->output_file);
12291 fseeko(tng_data->output_file,
12292 frame_set->medium_stride_prev_frame_set_file_pos,
12295 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
12297 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
12298 __FILE__, __LINE__);
12299 tng_data->input_file = temp;
12300 tng_block_destroy(&block);
12301 return(TNG_CRITICAL);
12304 /* Read the next frame set from the previous frame set and one
12305 * medium stride step back */
12306 fseeko(tng_data->output_file, block->block_contents_size - (6 *
12307 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
12308 if(fread(&frame_set->medium_stride_prev_frame_set_file_pos,
12309 sizeof(frame_set->medium_stride_prev_frame_set_file_pos),
12310 1, tng_data->output_file) == 0)
12312 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
12313 tng_data->input_file = temp;
12314 tng_block_destroy(&block);
12315 return(TNG_CRITICAL);
12318 if(tng_data->input_endianness_swap_func_64)
12320 if(tng_data->input_endianness_swap_func_64(tng_data,
12321 &frame_set->medium_stride_prev_frame_set_file_pos)
12324 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
12325 __FILE__, __LINE__);
12329 tng_block_destroy(&block);
12331 /* Set the long range pointers */
12332 if(tng_data->n_trajectory_frame_sets == tng_data->long_stride_length + 1)
12334 frame_set->long_stride_prev_frame_set_file_pos =
12335 tng_data->first_trajectory_frame_set_output_file_pos;
12337 else if(tng_data->n_trajectory_frame_sets > tng_data->medium_stride_length + 1)
12339 /* FIXME: Currently only working if the previous frame set has its
12340 * long stride pointer already set. This might need some fixing. */
12341 if(frame_set->long_stride_prev_frame_set_file_pos != -1 &&
12342 frame_set->long_stride_prev_frame_set_file_pos != 0)
12344 tng_block_init(&block);
12345 tng_data->input_file = tng_data->output_file;
12347 fseeko(tng_data->output_file,
12348 frame_set->long_stride_prev_frame_set_file_pos,
12351 if(tng_block_header_read(tng_data, block) != TNG_SUCCESS)
12353 fprintf(stderr, "TNG library: Cannot read frame set header. %s: %d\n",
12354 __FILE__, __LINE__);
12355 tng_data->input_file = temp;
12356 tng_block_destroy(&block);
12357 return(TNG_CRITICAL);
12360 /* Read the next frame set from the previous frame set and one
12361 * long stride step back */
12362 fseeko(tng_data->output_file, block->block_contents_size - (6 *
12363 sizeof(int64_t) + 2 * sizeof(double)), SEEK_CUR);
12365 tng_block_destroy(&block);
12367 if(fread(&frame_set->long_stride_prev_frame_set_file_pos,
12368 sizeof(frame_set->long_stride_prev_frame_set_file_pos),
12369 1, tng_data->output_file) == 0)
12371 fprintf(stderr, "TNG library: Cannot read block. %s: %d\n", __FILE__, __LINE__);
12372 tng_data->input_file = temp;
12373 return(TNG_CRITICAL);
12376 if(tng_data->input_endianness_swap_func_64)
12378 if(tng_data->input_endianness_swap_func_64(tng_data,
12379 &frame_set->long_stride_prev_frame_set_file_pos)
12382 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
12383 __FILE__, __LINE__);
12390 tng_data->input_file = temp;
12391 fseeko(tng_data->output_file, curr_file_pos, SEEK_SET);
12395 frame_set->first_frame = first_frame;
12396 frame_set->n_frames = n_frames;
12397 frame_set->n_written_frames = 0;
12398 frame_set->n_unwritten_frames = 0;
12399 frame_set->first_frame_time = -1;
12401 if(tng_data->first_trajectory_frame_set_output_file_pos == -1 ||
12402 tng_data->first_trajectory_frame_set_output_file_pos == 0)
12404 tng_data->first_trajectory_frame_set_output_file_pos =
12405 tng_data->current_trajectory_frame_set_output_file_pos;
12407 /* FIXME: Should check the frame number instead of the file_pos,
12408 * in case frame sets are not in order */
12409 if(tng_data->last_trajectory_frame_set_output_file_pos == -1 ||
12410 tng_data->last_trajectory_frame_set_output_file_pos == 0 ||
12411 tng_data->last_trajectory_frame_set_output_file_pos <
12412 tng_data->current_trajectory_frame_set_output_file_pos)
12414 tng_data->last_trajectory_frame_set_output_file_pos =
12415 tng_data->current_trajectory_frame_set_output_file_pos;
12418 return(TNG_SUCCESS);
12421 tng_function_status DECLSPECDLLEXPORT tng_frame_set_with_time_new
12422 (const tng_trajectory_t tng_data,
12423 const int64_t first_frame,
12424 const int64_t n_frames,
12425 const double first_frame_time)
12427 tng_function_status stat;
12429 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12430 TNG_ASSERT(first_frame >= 0, "TNG library: first_frame must be >= 0.");
12431 TNG_ASSERT(n_frames >= 0, "TNG library: n_frames must be >= 0.");
12432 TNG_ASSERT(first_frame_time >= 0, "TNG library: first_frame_time must be >= 0.");
12435 stat = tng_frame_set_new(tng_data, first_frame, n_frames);
12436 if(stat != TNG_SUCCESS)
12440 stat = tng_frame_set_first_frame_time_set(tng_data, first_frame_time);
12445 tng_function_status DECLSPECDLLEXPORT tng_frame_set_first_frame_time_set
12446 (const tng_trajectory_t tng_data,
12447 const double first_frame_time)
12449 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12450 TNG_ASSERT(first_frame_time >= 0, "TNG library: first_frame_time must be >= 0.");
12452 tng_data->current_trajectory_frame_set.first_frame_time = first_frame_time;
12454 return(TNG_SUCCESS);
12457 tng_function_status DECLSPECDLLEXPORT tng_first_frame_nr_of_next_frame_set_get
12458 (const tng_trajectory_t tng_data,
12461 int64_t file_pos, next_frame_set_file_pos;
12462 tng_gen_block_t block;
12463 tng_function_status stat;
12465 tng_trajectory_frame_set_t frame_set;
12467 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12468 TNG_ASSERT(tng_data->input_file, "TNG library: An input file must be open to find the next frame set");
12469 TNG_ASSERT(frame, "TNG library: frame must not be a NULL pointer");
12471 file_pos = ftello(tng_data->input_file);
12473 if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
12475 next_frame_set_file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
12479 frame_set = &tng_data->current_trajectory_frame_set;
12480 next_frame_set_file_pos = frame_set->next_frame_set_file_pos;
12483 if(next_frame_set_file_pos <= 0)
12485 return(TNG_FAILURE);
12488 fseeko(tng_data->input_file, next_frame_set_file_pos, SEEK_SET);
12489 /* Read block headers first to see that a frame set block is found. */
12490 tng_block_init(&block);
12491 stat = tng_block_header_read(tng_data, block);
12492 if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
12494 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
12495 file_pos, __FILE__, __LINE__);
12496 return(TNG_CRITICAL);
12498 /* if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
12500 tng_block_read_next(tng_data, block, TNG_USE_HASH);
12502 tng_block_destroy(&block);
12504 if(fread(frame, sizeof(int64_t), 1, tng_data->input_file) == 0)
12506 fprintf(stderr, "TNG library: Cannot read first frame of next frame set. %s: %d\n",
12507 __FILE__, __LINE__);
12508 return(TNG_CRITICAL);
12510 fseeko(tng_data->input_file, file_pos, SEEK_SET);
12512 return(TNG_SUCCESS);
12515 static tng_function_status tng_gen_data_block_add
12516 (const tng_trajectory_t tng_data,
12518 const tng_bool is_particle_data,
12519 const char *block_name,
12520 const char datatype,
12521 const char block_type_flag,
12523 const int64_t n_values_per_frame,
12524 int64_t stride_length,
12525 const int64_t num_first_particle,
12526 const int64_t n_particles,
12527 const int64_t codec_id,
12532 int64_t tot_n_particles, n_frames_div;
12533 char ***first_dim_values, **second_dim_values;
12534 tng_trajectory_frame_set_t frame_set;
12536 char *new_data_c=new_data;
12537 tng_function_status stat;
12539 frame_set = &tng_data->current_trajectory_frame_set;
12541 if(stride_length <= 0)
12546 if(is_particle_data)
12548 stat = tng_particle_data_find(tng_data, id, &data);
12552 stat = tng_data_find(tng_data, id, &data);
12554 /* If the block does not exist, create it */
12555 if(stat != TNG_SUCCESS)
12557 if(is_particle_data)
12559 stat = tng_particle_data_block_create(tng_data, block_type_flag);
12563 stat = tng_data_block_create(tng_data, block_type_flag);
12566 if(stat != TNG_SUCCESS)
12568 fprintf(stderr, "TNG library: Cannot create particle data block. %s: %d\n",
12569 __FILE__, __LINE__);
12570 return(TNG_CRITICAL);
12572 if(is_particle_data)
12574 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
12576 data = &frame_set->tr_particle_data[frame_set->
12577 n_particle_data_blocks - 1];
12581 data = &tng_data->non_tr_particle_data[tng_data->
12582 n_particle_data_blocks - 1];
12587 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
12589 data = &frame_set->tr_data[frame_set->n_data_blocks - 1];
12593 data = &tng_data->non_tr_data[tng_data->n_data_blocks - 1];
12596 data->block_id = id;
12598 data->block_name = malloc(strlen(block_name) + 1);
12599 if(!data->block_name)
12601 fprintf(stderr, "TNG library: Cannot allocate memory (%ud bytes). %s: %d\n",
12602 (unsigned int)strlen(block_name)+1, __FILE__, __LINE__);
12603 return(TNG_CRITICAL);
12605 strncpy(data->block_name, block_name, strlen(block_name) + 1);
12608 /* FIXME: Memory leak from strings. */
12610 data->last_retrieved_frame = -1;
12613 data->datatype = datatype;
12614 data->stride_length = tng_max_i64(stride_length, 1);
12615 data->n_values_per_frame = n_values_per_frame;
12616 data->n_frames = n_frames;
12617 if(is_particle_data)
12619 data->dependency = TNG_PARTICLE_DEPENDENT;
12623 data->dependency = 0;
12625 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
12627 frame_set->n_frames == n_frames ||
12628 stride_length > 1))
12630 data->dependency += TNG_FRAME_DEPENDENT;
12632 data->codec_id = codec_id;
12633 data->compression_multiplier = 1.0;
12634 /* FIXME: This can cause problems. */
12635 data->first_frame_with_data = frame_set->first_frame;
12637 if(is_particle_data)
12639 if(block_type_flag == TNG_TRAJECTORY_BLOCK && tng_data->var_num_atoms_flag)
12641 tot_n_particles = frame_set->n_particles;
12645 tot_n_particles = tng_data->n_particles;
12648 /* This is just to keep the compiler happy - avoid it considering tot_n_particles
12649 * uninitialized. */
12652 tot_n_particles = 0;
12655 /* If data values are supplied add that data to the data block. */
12658 /* Allocate memory */
12659 if(is_particle_data)
12661 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
12662 stride_length, tot_n_particles,
12663 n_values_per_frame);
12667 stat = tng_allocate_data_mem(tng_data, data, n_frames, stride_length,
12668 n_values_per_frame);
12670 if(stat != TNG_SUCCESS)
12672 fprintf(stderr, "TNG library: Cannot allocate particle data memory. %s: %d\n",
12673 __FILE__, __LINE__);
12674 return(TNG_CRITICAL);
12677 if(n_frames > frame_set->n_unwritten_frames)
12679 frame_set->n_unwritten_frames = n_frames;
12682 n_frames_div = (n_frames % stride_length) ?
12683 n_frames / stride_length + 1:
12684 n_frames / stride_length;
12686 if(datatype == TNG_CHAR_DATA)
12688 if(is_particle_data)
12690 for(i = 0; i < n_frames_div; i++)
12692 first_dim_values = data->strings[i];
12693 for(j = num_first_particle; j < num_first_particle + n_particles;
12696 second_dim_values = first_dim_values[j];
12697 for(k = 0; k < n_values_per_frame; k++)
12699 len = tng_min_size(strlen(new_data_c) + 1,
12701 if(second_dim_values[k])
12703 free(second_dim_values[k]);
12705 second_dim_values[k] = malloc(len);
12706 if(!second_dim_values[k])
12708 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
12709 len, __FILE__, __LINE__);
12710 return(TNG_CRITICAL);
12712 strncpy(second_dim_values[k],
12721 for(i = 0; i < n_frames_div; i++)
12723 second_dim_values = data->strings[0][i];
12724 for(j = 0; j < n_values_per_frame; j++)
12726 len = tng_min_size(strlen(new_data_c) + 1,
12728 if(second_dim_values[j])
12730 free(second_dim_values[j]);
12732 second_dim_values[j] = malloc(len);
12733 if(!second_dim_values[j])
12735 fprintf(stderr, "TNG library: Cannot allocate memory (%d bytes). %s: %d\n",
12736 len, __FILE__, __LINE__);
12737 return(TNG_CRITICAL);
12739 strncpy(second_dim_values[j],
12751 size = sizeof(int64_t);
12753 case TNG_FLOAT_DATA:
12754 size = sizeof(float);
12756 case TNG_DOUBLE_DATA:
12758 size = sizeof(double);
12761 if(is_particle_data)
12763 memcpy(data->values, new_data, size * n_frames_div *
12764 n_particles * n_values_per_frame);
12768 memcpy(data->values, new_data, size * n_frames_div *
12769 n_values_per_frame);
12774 return(TNG_SUCCESS);
12777 tng_function_status DECLSPECDLLEXPORT tng_data_block_add
12778 (const tng_trajectory_t tng_data,
12780 const char *block_name,
12781 const char datatype,
12782 const char block_type_flag,
12784 const int64_t n_values_per_frame,
12785 int64_t stride_length,
12786 const int64_t codec_id,
12789 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12790 TNG_ASSERT(block_name, "TNG library: block_name must not be a NULL pointer.");
12791 TNG_ASSERT(n_values_per_frame > 0, "TNG library: n_values_per_frame must be a positive integer.");
12793 return(tng_gen_data_block_add(tng_data, id, TNG_FALSE, block_name, datatype,
12794 block_type_flag, n_frames, n_values_per_frame,
12795 stride_length, 0, 0, codec_id, new_data));
12798 tng_function_status DECLSPECDLLEXPORT tng_particle_data_block_add
12799 (const tng_trajectory_t tng_data,
12801 const char *block_name,
12802 const char datatype,
12803 const char block_type_flag,
12805 const int64_t n_values_per_frame,
12806 int64_t stride_length,
12807 const int64_t num_first_particle,
12808 const int64_t n_particles,
12809 const int64_t codec_id,
12812 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12813 TNG_ASSERT(block_name, "TNG library: block_name mustnot be a NULL pointer.");
12814 TNG_ASSERT(n_values_per_frame > 0, "TNG library: n_values_per_frame must be a positive integer.");
12815 TNG_ASSERT(num_first_particle >= 0, "TNG library: num_first_particle must be >= 0.");
12816 TNG_ASSERT(n_particles >= 0, "TNG library: n_particles must be >= 0.");
12818 return(tng_gen_data_block_add(tng_data, id, TNG_TRUE, block_name, datatype,
12819 block_type_flag, n_frames, n_values_per_frame,
12820 stride_length, num_first_particle, n_particles,
12821 codec_id, new_data));
12824 tng_function_status DECLSPECDLLEXPORT tng_data_block_name_get
12825 (const tng_trajectory_t tng_data,
12826 const int64_t block_id,
12831 tng_trajectory_frame_set_t frame_set;
12832 tng_function_status stat;
12834 int block_type = -1;
12836 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12837 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer.");
12839 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
12841 data = &tng_data->non_tr_particle_data[i];
12842 if(data->block_id == block_id)
12844 strncpy(name, data->block_name, max_len);
12845 name[max_len - 1] = '\0';
12846 return(TNG_SUCCESS);
12849 for(i = 0; i < tng_data->n_data_blocks; i++)
12851 data = &tng_data->non_tr_data[i];
12852 if(data->block_id == block_id)
12854 strncpy(name, data->block_name, max_len);
12855 name[max_len - 1] = '\0';
12856 return(TNG_SUCCESS);
12860 frame_set = &tng_data->current_trajectory_frame_set;
12862 stat = tng_particle_data_find(tng_data, block_id, &data);
12863 if(stat == TNG_SUCCESS)
12865 block_type = TNG_PARTICLE_BLOCK_DATA;
12869 stat = tng_data_find(tng_data, block_id, &data);
12870 if(stat == TNG_SUCCESS)
12872 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
12876 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
12877 if(stat != TNG_SUCCESS)
12881 stat = tng_particle_data_find(tng_data, block_id, &data);
12882 if(stat == TNG_SUCCESS)
12884 block_type = TNG_PARTICLE_BLOCK_DATA;
12888 stat = tng_data_find(tng_data, block_id, &data);
12889 if(stat == TNG_SUCCESS)
12891 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
12896 if(block_type == TNG_PARTICLE_BLOCK_DATA)
12898 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
12900 data = &frame_set->tr_particle_data[i];
12901 if(data->block_id == block_id)
12903 strncpy(name, data->block_name, max_len);
12904 name[max_len - 1] = '\0';
12905 return(TNG_SUCCESS);
12909 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
12911 for(i = 0; i < frame_set->n_data_blocks; i++)
12913 data = &frame_set->tr_data[i];
12914 if(data->block_id == block_id)
12916 strncpy(name, data->block_name, max_len);
12917 name[max_len - 1] = '\0';
12918 return(TNG_SUCCESS);
12923 return(TNG_FAILURE);
12926 tng_function_status DECLSPECDLLEXPORT tng_data_block_dependency_get
12927 (const tng_trajectory_t tng_data,
12928 const int64_t block_id,
12929 int *block_dependency)
12932 tng_function_status stat;
12935 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
12936 TNG_ASSERT(block_dependency, "TNG library: block_dependency must not be a NULL pointer.");
12938 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
12940 data = &tng_data->non_tr_particle_data[i];
12941 if(data->block_id == block_id)
12943 *block_dependency = TNG_PARTICLE_DEPENDENT;
12944 return(TNG_SUCCESS);
12947 for(i = 0; i < tng_data->n_data_blocks; i++)
12949 data = &tng_data->non_tr_data[i];
12950 if(data->block_id == block_id)
12952 *block_dependency = 0;
12953 return(TNG_SUCCESS);
12957 stat = tng_particle_data_find(tng_data, block_id, &data);
12958 if(stat == TNG_SUCCESS)
12960 *block_dependency = TNG_PARTICLE_DEPENDENT + TNG_FRAME_DEPENDENT;
12961 return(TNG_SUCCESS);
12965 stat = tng_data_find(tng_data, block_id, &data);
12966 if(stat == TNG_SUCCESS)
12968 *block_dependency = TNG_FRAME_DEPENDENT;
12969 return(TNG_SUCCESS);
12973 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
12974 if(stat != TNG_SUCCESS)
12978 stat = tng_particle_data_find(tng_data, block_id, &data);
12979 if(stat == TNG_SUCCESS)
12981 *block_dependency = TNG_PARTICLE_DEPENDENT + TNG_FRAME_DEPENDENT;
12982 return(TNG_SUCCESS);
12986 stat = tng_data_find(tng_data, block_id, &data);
12987 if(stat == TNG_SUCCESS)
12989 *block_dependency = TNG_FRAME_DEPENDENT;
12990 return(TNG_SUCCESS);
12996 return(TNG_FAILURE);
12999 tng_function_status DECLSPECDLLEXPORT tng_data_block_num_values_per_frame_get
13000 (const tng_trajectory_t tng_data,
13001 const int64_t block_id,
13002 int64_t *n_values_per_frame)
13005 tng_function_status stat;
13008 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13009 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
13011 for(i = 0; i < tng_data->n_particle_data_blocks; i++)
13013 data = &tng_data->non_tr_particle_data[i];
13014 if(data->block_id == block_id)
13016 *n_values_per_frame = data->n_values_per_frame;
13017 return(TNG_SUCCESS);
13020 for(i = 0; i < tng_data->n_data_blocks; i++)
13022 data = &tng_data->non_tr_data[i];
13023 if(data->block_id == block_id)
13025 *n_values_per_frame = data->n_values_per_frame;
13026 return(TNG_SUCCESS);
13030 stat = tng_particle_data_find(tng_data, block_id, &data);
13031 if(stat == TNG_SUCCESS)
13033 *n_values_per_frame = data->n_values_per_frame;
13034 return(TNG_SUCCESS);
13038 stat = tng_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_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
13047 if(stat != TNG_SUCCESS)
13051 stat = tng_particle_data_find(tng_data, block_id, &data);
13052 if(stat == TNG_SUCCESS)
13054 *n_values_per_frame = data->n_values_per_frame;
13055 return(TNG_SUCCESS);
13059 stat = tng_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);
13069 return(TNG_FAILURE);
13072 tng_function_status DECLSPECDLLEXPORT tng_frame_set_n_frames_of_data_block_get
13073 (const tng_trajectory_t tng_data,
13074 const int64_t block_id,
13077 tng_gen_block_t block;
13078 tng_function_status stat;
13079 char datatype, dependency, sparse_data;
13080 int64_t n_values, codec_id, first_frame_with_data, stride_length, curr_n_frames;
13081 int64_t num_first_particle, block_n_particles;
13083 md5_state_t md5_state;
13084 int found = TNG_FALSE;
13086 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13088 tng_block_init(&block);
13090 stat = tng_block_header_read(tng_data, block);
13091 /* If the block header could not be read the reading position might not have been
13092 * at the start of a block. Try again from the file position of the current frame
13094 if(stat != TNG_SUCCESS)
13096 fseeko(tng_data->input_file, tng_data->current_trajectory_frame_set_input_file_pos, SEEK_SET);
13097 stat = tng_block_header_read(tng_data, block);
13098 if(stat != TNG_SUCCESS)
13100 tng_block_destroy(&block);
13104 if(block->id == TNG_TRAJECTORY_FRAME_SET)
13106 stat = tng_block_read_next(tng_data, block, TNG_SKIP_HASH);
13107 if(stat != TNG_SUCCESS)
13109 tng_block_destroy(&block);
13112 stat = tng_block_header_read(tng_data, block);
13114 while(stat == TNG_SUCCESS && block->id != TNG_TRAJECTORY_FRAME_SET && found == TNG_FALSE)
13116 if(block->id == block_id)
13118 stat = tng_data_block_meta_information_read(tng_data, &datatype,
13119 &dependency, &sparse_data,
13120 &n_values, &codec_id,
13121 &first_frame_with_data,
13122 &stride_length, &curr_n_frames,
13123 &num_first_particle,
13124 &block_n_particles,
13125 &multiplier, TNG_SKIP_HASH,
13127 if(stat == TNG_SUCCESS)
13134 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
13135 stat = tng_block_header_read(tng_data, block);
13138 if(found == TNG_TRUE)
13140 *n_frames = (tng_data->current_trajectory_frame_set.n_frames -
13141 (tng_data->current_trajectory_frame_set.first_frame - first_frame_with_data)) / stride_length;
13143 else if(stat == TNG_SUCCESS)
13148 tng_block_destroy(&block);
13153 static tng_function_status tng_frame_gen_data_write
13154 (const tng_trajectory_t tng_data,
13155 const int64_t frame_nr,
13156 const int64_t block_id,
13157 const tng_bool is_particle_data,
13158 const int64_t val_first_particle,
13159 const int64_t val_n_particles,
13160 const void *values,
13161 const char hash_mode)
13163 int64_t header_pos, file_pos, tot_n_particles;
13164 int64_t output_file_len, n_values_per_frame, size, contents_size;
13165 int64_t header_size, temp_first, temp_last;
13166 int64_t mapping_block_end_pos, num_first_particle, block_n_particles;
13167 int64_t i, last_frame, temp_current, write_n_particles;
13168 tng_gen_block_t block;
13169 tng_trajectory_frame_set_t frame_set;
13170 FILE *temp = tng_data->input_file;
13171 struct tng_data data;
13172 tng_function_status stat;
13173 tng_particle_mapping_t mapping;
13174 char dependency, sparse_data, datatype;
13177 if(tng_output_file_init(tng_data) != TNG_SUCCESS)
13179 fprintf(stderr, "TNG library: Cannot initialise destination file. %s: %d\n",
13180 __FILE__, __LINE__);
13181 return(TNG_CRITICAL);
13184 temp_first = tng_data->first_trajectory_frame_set_input_file_pos;
13185 temp_last = tng_data->last_trajectory_frame_set_input_file_pos;
13186 temp_current = tng_data->current_trajectory_frame_set_input_file_pos;
13187 tng_data->first_trajectory_frame_set_input_file_pos =
13188 tng_data->first_trajectory_frame_set_output_file_pos;
13189 tng_data->last_trajectory_frame_set_input_file_pos =
13190 tng_data->last_trajectory_frame_set_output_file_pos;
13191 tng_data->current_trajectory_frame_set_input_file_pos =
13192 tng_data->current_trajectory_frame_set_output_file_pos;
13194 tng_data->input_file = tng_data->output_file;
13196 stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
13198 frame_set = &tng_data->current_trajectory_frame_set;
13200 if(stat != TNG_SUCCESS)
13202 last_frame = frame_set->first_frame +
13203 frame_set->n_frames - 1;
13204 /* If the wanted frame would be in the frame set after the last
13205 * frame set create a new frame set. */
13206 if(stat == TNG_FAILURE &&
13207 last_frame < frame_nr)
13208 /* (last_frame < frame_nr &&
13209 tng_data->current_trajectory_frame_set.first_frame +
13210 tng_data->frame_set_n_frames >= frame_nr))*/
13212 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
13214 last_frame = frame_nr - 1;
13216 tng_frame_set_new(tng_data,
13218 tng_data->frame_set_n_frames);
13219 file_pos = ftello(tng_data->output_file);
13220 fseeko(tng_data->output_file, 0, SEEK_END);
13221 output_file_len = ftello(tng_data->output_file);
13222 fseeko(tng_data->output_file, file_pos, SEEK_SET);
13224 /* Read mapping blocks from the last frame set */
13225 tng_block_init(&block);
13227 stat = tng_block_header_read(tng_data, block);
13228 while(file_pos < output_file_len &&
13229 stat != TNG_CRITICAL &&
13230 block->id != TNG_TRAJECTORY_FRAME_SET &&
13233 if(block->id == TNG_PARTICLE_MAPPING)
13235 tng_trajectory_mapping_block_read(tng_data, block,
13240 fseeko(tng_data->output_file, block->block_contents_size,
13243 file_pos = ftello(tng_data->output_file);
13244 if(file_pos < output_file_len)
13246 stat = tng_block_header_read(tng_data, block);
13250 tng_block_destroy(&block);
13251 /* Write the frame set to disk */
13252 if(tng_frame_set_write(tng_data, hash_mode) != TNG_SUCCESS)
13254 fprintf(stderr, "TNG library: Error writing frame set. %s: %d\n", __FILE__, __LINE__);
13255 return(TNG_CRITICAL);
13260 tng_data->input_file = temp;
13261 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13262 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13263 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13268 tng_block_init(&block);
13270 file_pos = tng_data->current_trajectory_frame_set_output_file_pos;
13272 fseeko(tng_data->output_file, 0, SEEK_END);
13273 output_file_len = ftello(tng_data->output_file);
13274 fseeko(tng_data->output_file, file_pos, SEEK_SET);
13276 /* Read past the frame set block first */
13277 stat = tng_block_header_read(tng_data, block);
13278 if(stat == TNG_CRITICAL)
13280 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
13281 file_pos, __FILE__, __LINE__);
13282 tng_block_destroy(&block);
13283 tng_data->input_file = temp;
13285 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13286 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13287 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13290 fseeko(tng_data->output_file, block->block_contents_size,
13293 if(is_particle_data == TNG_TRUE)
13295 if(tng_data->var_num_atoms_flag)
13297 tot_n_particles = frame_set->n_particles;
13301 tot_n_particles = tng_data->n_particles;
13304 if(val_n_particles < tot_n_particles)
13306 mapping_block_end_pos = -1;
13307 /* Read all mapping blocks to find the right place to put the data */
13308 stat = tng_block_header_read(tng_data, block);
13309 while(file_pos < output_file_len &&
13310 stat != TNG_CRITICAL &&
13311 block->id != TNG_TRAJECTORY_FRAME_SET &&
13314 if(block->id == TNG_PARTICLE_MAPPING)
13316 tng_trajectory_mapping_block_read(tng_data, block, hash_mode);
13320 fseeko(tng_data->output_file, block->block_contents_size,
13323 file_pos = ftello(tng_data->output_file);
13324 if(block->id == TNG_PARTICLE_MAPPING)
13326 mapping = &frame_set->mappings[frame_set->n_mapping_blocks - 1];
13327 if(val_first_particle >= mapping->num_first_particle &&
13328 val_first_particle < mapping->num_first_particle +
13329 mapping->n_particles &&
13330 val_first_particle + val_n_particles <=
13331 mapping->num_first_particle + mapping->n_particles)
13333 mapping_block_end_pos = file_pos;
13336 if(file_pos < output_file_len)
13338 stat = tng_block_header_read(tng_data, block);
13341 if(stat == TNG_CRITICAL)
13343 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
13344 file_pos, __FILE__, __LINE__);
13345 tng_block_destroy(&block);
13346 tng_data->input_file = temp;
13348 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13349 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13350 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13353 if(mapping_block_end_pos < 0)
13355 tng_block_destroy(&block);
13356 tng_data->input_file = temp;
13358 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13359 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13360 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13361 return(TNG_FAILURE);
13363 fseeko(tng_data->output_file, mapping_block_end_pos, SEEK_SET);
13367 /* Read all block headers until next frame set block or
13368 * until the wanted block id is found */
13369 stat = tng_block_header_read(tng_data, block);
13370 while(file_pos < output_file_len &&
13371 stat != TNG_CRITICAL &&
13372 block->id != block_id &&
13373 (is_particle_data != TNG_TRUE || block->id != TNG_PARTICLE_MAPPING) &&
13374 block->id != TNG_TRAJECTORY_FRAME_SET &&
13377 fseeko(tng_data->output_file, block->block_contents_size, SEEK_CUR);
13378 file_pos = ftello(tng_data->output_file);
13379 if(file_pos < output_file_len)
13381 stat = tng_block_header_read(tng_data, block);
13384 if(stat == TNG_CRITICAL)
13386 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
13387 file_pos, __FILE__, __LINE__);
13388 tng_block_destroy(&block);
13389 tng_data->input_file = temp;
13390 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13391 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13392 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13396 contents_size = block->block_contents_size;
13397 header_size = block->header_contents_size;
13399 header_pos = ftello(tng_data->output_file) - header_size;
13400 frame_set = &tng_data->current_trajectory_frame_set;
13402 if(tng_file_input_numerical(tng_data, &datatype,
13404 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13406 tng_block_destroy(&block);
13407 return(TNG_CRITICAL);
13409 if(tng_file_input_numerical(tng_data, &dependency,
13410 sizeof(dependency),
13411 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13413 tng_block_destroy(&block);
13414 return(TNG_CRITICAL);
13416 data.datatype = datatype;
13418 if(!(dependency & TNG_FRAME_DEPENDENT) ||
13419 (is_particle_data == TNG_FALSE && dependency & TNG_PARTICLE_DEPENDENT) ||
13420 (is_particle_data == TNG_TRUE && !(dependency & TNG_PARTICLE_DEPENDENT)))
13422 tng_block_destroy(&block);
13423 tng_data->input_file = temp;
13425 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13426 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13427 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13428 return(TNG_FAILURE);
13431 if(tng_file_input_numerical(tng_data, &sparse_data,
13432 sizeof(sparse_data),
13433 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13435 tng_block_destroy(&block);
13436 return(TNG_CRITICAL);
13439 if(tng_file_input_numerical(tng_data, &data.n_values_per_frame,
13440 sizeof(data.n_values_per_frame),
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.codec_id,
13448 sizeof(data.codec_id),
13449 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13451 tng_block_destroy(&block);
13452 return(TNG_CRITICAL);
13455 if(data.codec_id != TNG_UNCOMPRESSED)
13457 if(tng_file_input_numerical(tng_data, &data.compression_multiplier,
13458 sizeof(data.compression_multiplier),
13459 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13461 tng_block_destroy(&block);
13462 return(TNG_CRITICAL);
13467 data.compression_multiplier = 1;
13472 if(tng_file_input_numerical(tng_data, &data.first_frame_with_data,
13473 sizeof(data.first_frame_with_data),
13474 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13476 tng_block_destroy(&block);
13477 return(TNG_CRITICAL);
13480 if(tng_file_input_numerical(tng_data, &data.stride_length,
13481 sizeof(data.stride_length),
13482 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13484 tng_block_destroy(&block);
13485 return(TNG_CRITICAL);
13490 data.first_frame_with_data = 0;
13491 data.stride_length = 1;
13493 data.n_frames = tng_data->current_trajectory_frame_set.n_frames;
13495 if(is_particle_data == TNG_TRUE)
13497 if(tng_file_input_numerical(tng_data, &num_first_particle,
13498 sizeof(num_first_particle),
13499 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13501 tng_block_destroy(&block);
13502 return(TNG_CRITICAL);
13505 if(tng_file_input_numerical(tng_data, &block_n_particles,
13506 sizeof(block_n_particles),
13507 TNG_SKIP_HASH, 0, __LINE__) == TNG_CRITICAL)
13509 tng_block_destroy(&block);
13510 return(TNG_CRITICAL);
13514 tng_data->input_file = temp;
13516 tng_data->first_trajectory_frame_set_input_file_pos = temp_first;
13517 tng_data->last_trajectory_frame_set_input_file_pos = temp_last;
13518 tng_data->current_trajectory_frame_set_input_file_pos = temp_current;
13520 switch(data.datatype)
13522 case(TNG_INT_DATA):
13523 size = sizeof(int64_t);
13525 case(TNG_FLOAT_DATA):
13526 size = sizeof(float);
13528 case(TNG_DOUBLE_DATA):
13529 size = sizeof(double);
13532 fprintf(stderr, "TNG library: Cannot calculate writing locations. %s: %d.\n", __FILE__,
13534 tng_block_destroy(&block);
13535 return(TNG_FAILURE);
13538 n_values_per_frame = data.n_values_per_frame;
13540 file_pos = (frame_nr - tng_max_i64(frame_set->first_frame,
13541 data.first_frame_with_data)) /
13542 data.stride_length;
13543 if(is_particle_data == TNG_TRUE)
13545 file_pos *= block_n_particles * size * n_values_per_frame;
13549 file_pos *= size * n_values_per_frame;
13552 if(file_pos > contents_size)
13554 fprintf(stderr, "TNG library: Attempting to write outside the block. %s: %d\n", __FILE__,
13556 tng_block_destroy(&block);
13557 return(TNG_FAILURE);
13560 fseeko(tng_data->output_file, file_pos, SEEK_CUR);
13562 if(is_particle_data == TNG_TRUE)
13564 write_n_particles = val_n_particles;
13568 write_n_particles = 1;
13571 /* If the endianness is not big endian the data needs to be swapped */
13572 if((data.datatype == TNG_INT_DATA ||
13573 data.datatype == TNG_DOUBLE_DATA) &&
13574 tng_data->output_endianness_swap_func_64)
13576 copy = malloc(write_n_particles * n_values_per_frame * size);
13577 memcpy(copy, values, write_n_particles * n_values_per_frame * size);
13578 for(i = 0; i < write_n_particles * n_values_per_frame; i++)
13580 if(tng_data->output_endianness_swap_func_64(tng_data,
13581 (int64_t *) copy+i)
13584 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13585 __FILE__, __LINE__);
13588 fwrite(copy, write_n_particles * n_values_per_frame, size,
13589 tng_data->output_file);
13592 else if(data.datatype == TNG_FLOAT_DATA &&
13593 tng_data->output_endianness_swap_func_32)
13595 copy = malloc(write_n_particles * n_values_per_frame * size);
13596 memcpy(copy, values, write_n_particles * n_values_per_frame * size);
13597 for(i = 0; i < write_n_particles * n_values_per_frame; i++)
13599 if(tng_data->output_endianness_swap_func_32(tng_data,
13600 (int32_t *) copy+i)
13603 fprintf(stderr, "TNG library: Cannot swap byte order. %s: %d\n",
13604 __FILE__, __LINE__);
13607 fwrite(copy, write_n_particles * n_values_per_frame, size,
13608 tng_data->output_file);
13614 fwrite(values, write_n_particles * n_values_per_frame, size, tng_data->output_file);
13617 fflush(tng_data->output_file);
13619 /* Update the number of written frames in the frame set. */
13620 if(frame_nr - frame_set->first_frame + 1 > frame_set->n_written_frames)
13622 frame_set->n_written_frames = frame_nr - frame_set->first_frame + 1;
13625 /* If the last frame has been written update the hash */
13626 if(hash_mode == TNG_USE_HASH && (frame_nr + data.stride_length -
13627 data.first_frame_with_data) >=
13628 frame_set->n_frames)
13630 tng_md5_hash_update(tng_data, block, header_pos, header_pos +
13634 tng_block_destroy(&block);
13636 return(TNG_SUCCESS);
13639 tng_function_status DECLSPECDLLEXPORT tng_frame_data_write
13640 (const tng_trajectory_t tng_data,
13641 const int64_t frame_nr,
13642 const int64_t block_id,
13643 const void *values,
13644 const char hash_mode)
13646 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13647 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
13648 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer.");
13650 /* This is now just calling the generic data writing function. This
13651 * function must keep its signature to let the API be backwards
13653 return(tng_frame_gen_data_write(tng_data, frame_nr, block_id,
13654 TNG_FALSE, 0, 0, values, hash_mode));
13657 tng_function_status DECLSPECDLLEXPORT tng_frame_particle_data_write
13658 (const tng_trajectory_t tng_data,
13659 const int64_t frame_nr,
13660 const int64_t block_id,
13661 const int64_t val_first_particle,
13662 const int64_t val_n_particles,
13663 const void *values,
13664 const char hash_mode)
13666 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
13667 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
13668 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer.");
13669 TNG_ASSERT(val_first_particle >= 0, "TNG library: val_first_particle must be >= 0.");
13670 TNG_ASSERT(val_n_particles >= 0, "TNG library: val_n_particles must be >= 0.");
13672 /* This is now just calling the generic data writing function. This
13673 * function must keep its signature to let the API be backwards
13675 return(tng_frame_gen_data_write(tng_data, frame_nr, block_id,
13676 TNG_TRUE, val_first_particle, val_n_particles,
13677 values, hash_mode));
13680 static tng_function_status tng_data_values_alloc
13681 (const tng_trajectory_t tng_data,
13682 union data_values ***values,
13683 const int64_t n_frames,
13684 const int64_t n_values_per_frame,
13688 tng_function_status stat;
13690 if(n_frames <= 0 || n_values_per_frame <= 0)
13692 return(TNG_FAILURE);
13697 stat = tng_data_values_free(tng_data, *values, n_frames,
13698 n_values_per_frame,
13700 if(stat != TNG_SUCCESS)
13702 fprintf(stderr, "TNG library: Cannot free particle data values. %s: %d\n",
13703 __FILE__, __LINE__);
13707 *values = malloc(sizeof(union data_values *) * n_frames);
13710 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
13711 sizeof(union data_values **) * n_frames,
13712 __FILE__, __LINE__);
13713 return(TNG_CRITICAL);
13717 for(i = 0; i < n_frames; i++)
13719 (*values)[i] = malloc(sizeof(union data_values) *
13720 n_values_per_frame);
13723 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
13724 sizeof(union data_values) * n_values_per_frame,
13725 __FILE__, __LINE__);
13728 return(TNG_CRITICAL);
13731 return(TNG_SUCCESS);
13734 /* FIXME: This needs ***values */
13735 tng_function_status DECLSPECDLLEXPORT tng_data_values_free
13736 (const tng_trajectory_t tng_data,
13737 union data_values **values,
13738 const int64_t n_frames,
13739 const int64_t n_values_per_frame,
13747 for(i = 0; i < n_frames; i++)
13751 if(type == TNG_CHAR_DATA)
13753 for(j = 0; j < n_values_per_frame; j++)
13757 free(values[i][j].c);
13758 values[i][j].c = 0;
13770 return(TNG_SUCCESS);
13773 static tng_function_status tng_particle_data_values_alloc
13774 (const tng_trajectory_t tng_data,
13775 union data_values ****values,
13776 const int64_t n_frames,
13777 const int64_t n_particles,
13778 const int64_t n_values_per_frame,
13782 tng_function_status stat;
13784 if(n_particles == 0 || n_values_per_frame == 0)
13786 return(TNG_FAILURE);
13791 stat = tng_particle_data_values_free(tng_data, *values, n_frames,
13792 n_particles, n_values_per_frame,
13794 if(stat != TNG_SUCCESS)
13796 fprintf(stderr, "TNG library: Cannot free particle data values. %s: %d\n",
13797 __FILE__, __LINE__);
13801 *values = malloc(sizeof(union data_values **) * n_frames);
13804 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
13805 sizeof(union data_values **) * n_frames,
13806 __FILE__, __LINE__);
13807 return(TNG_CRITICAL);
13811 for(i = 0; i < n_frames; i++)
13813 (*values)[i] = malloc(sizeof(union data_values *) *
13817 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
13818 sizeof(union data_values *) * n_particles,
13819 __FILE__, __LINE__);
13822 return(TNG_CRITICAL);
13824 for(j = 0; j < n_particles; j++)
13826 (*values)[i][j] = malloc(sizeof(union data_values) *
13827 n_values_per_frame);
13828 if(!(*values)[i][j])
13830 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
13831 sizeof(union data_values *) * n_particles,
13832 __FILE__, __LINE__);
13833 tng_particle_data_values_free(tng_data, *values, n_frames,
13834 n_particles, n_values_per_frame,
13837 return(TNG_CRITICAL);
13841 return(TNG_SUCCESS);
13844 /* FIXME: This needs ****values */
13845 tng_function_status DECLSPECDLLEXPORT tng_particle_data_values_free
13846 (const tng_trajectory_t tng_data,
13847 union data_values ***values,
13848 const int64_t n_frames,
13849 const int64_t n_particles,
13850 const int64_t n_values_per_frame,
13858 for(i = 0; i < n_frames; i++)
13862 for(j = 0; j < n_particles; j++)
13864 if(type == TNG_CHAR_DATA)
13866 for(k = 0; k < n_values_per_frame; k++)
13868 if(values[i][j][k].c)
13870 free(values[i][j][k].c);
13871 values[i][j][k].c = 0;
13875 free(values[i][j]);
13886 return(TNG_SUCCESS);
13889 static tng_function_status tng_gen_data_get
13890 (const tng_trajectory_t tng_data,
13891 const int64_t block_id,
13892 const tng_bool is_particle_data,
13893 union data_values ****values,
13895 int64_t *n_particles,
13896 int64_t *n_values_per_frame,
13899 int64_t i, j, k, mapping, file_pos, i_step, block_index;
13903 tng_trajectory_frame_set_t frame_set;
13904 tng_gen_block_t block;
13905 char block_type_flag;
13906 tng_function_status stat;
13908 frame_set = &tng_data->current_trajectory_frame_set;
13913 if(is_particle_data == TNG_TRUE)
13915 stat = tng_particle_data_find(tng_data, block_id, &data);
13919 stat = tng_data_find(tng_data, block_id, &data);
13922 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
13924 block_type_flag = TNG_TRAJECTORY_BLOCK;
13928 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
13931 if(stat != TNG_SUCCESS)
13933 tng_block_init(&block);
13934 file_pos = ftello(tng_data->input_file);
13935 /* Read all blocks until next frame set block */
13936 stat = tng_block_header_read(tng_data, block);
13937 while(file_pos < tng_data->input_file_len &&
13938 stat != TNG_CRITICAL &&
13939 block->id != TNG_TRAJECTORY_FRAME_SET &&
13942 /* Use hash by default */
13943 stat = tng_block_read_next(tng_data, block,
13945 if(stat != TNG_CRITICAL)
13947 file_pos = ftello(tng_data->input_file);
13948 if(file_pos < tng_data->input_file_len)
13950 stat = tng_block_header_read(tng_data, block);
13954 tng_block_destroy(&block);
13955 if(stat == TNG_CRITICAL)
13957 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
13958 file_pos, __FILE__, __LINE__);
13962 if(is_particle_data == TNG_TRUE)
13964 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
13966 data = &frame_set->tr_particle_data[i];
13967 if(data->block_id == block_id)
13970 block_type_flag = TNG_TRAJECTORY_BLOCK;
13977 for(i = 0; i < frame_set->n_data_blocks; i++)
13979 data = &frame_set->tr_data[i];
13980 if(data->block_id == block_id)
13987 if(block_index < 0)
13989 return(TNG_FAILURE);
13993 if(is_particle_data == TNG_TRUE)
13995 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
13996 tng_data->var_num_atoms_flag)
13998 *n_particles = frame_set->n_particles;
14002 *n_particles = tng_data->n_particles;
14006 *n_frames = tng_max_i64(1, data->n_frames);
14007 *n_values_per_frame = data->n_values_per_frame;
14008 *type = data->datatype;
14010 if(is_particle_data == TNG_TRUE)
14014 if(tng_particle_data_values_alloc(tng_data, values, *n_frames,
14015 *n_particles, *n_values_per_frame,
14016 *type) != TNG_SUCCESS)
14018 return(TNG_CRITICAL);
14022 i_step = (*n_particles) * (*n_values_per_frame);
14024 /* It's not very elegant to reuse so much of the code in the different case
14025 * statements, but it's unnecessarily slow to have the switch-case block
14026 * inside the for loops. */
14029 case TNG_CHAR_DATA:
14030 for(i = 0; i < *n_frames; i++)
14032 for(j = 0; j < *n_particles; j++)
14034 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14035 for(k = 0; k < *n_values_per_frame; k++)
14037 len = strlen(data->strings[i][j][k]) + 1;
14038 (*values)[i][mapping][k].c = malloc(len);
14039 strncpy((*values)[i][mapping][k].c,
14040 data->strings[i][j][k], len);
14046 size = sizeof(int);
14047 for(i = 0; i < *n_frames; i++)
14049 for(j = 0; j < *n_particles; j++)
14051 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14052 for(k = 0; k < *n_values_per_frame; k++)
14054 (*values)[i][mapping][k].i = *(int *)
14055 ((char *)data->values + size *
14057 (*n_values_per_frame) + k));
14062 case TNG_FLOAT_DATA:
14063 size = sizeof(float);
14064 for(i = 0; i < *n_frames; i++)
14066 for(j = 0; j < *n_particles; j++)
14068 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14069 for(k = 0; k < *n_values_per_frame; k++)
14071 (*values)[i][mapping][k].f = *(float *)
14072 ((char *)data->values + size *
14074 (*n_values_per_frame) + k));
14079 case TNG_DOUBLE_DATA:
14081 size = sizeof(double);
14082 for(i = 0; i < *n_frames; i++)
14084 for(j = 0; j < *n_particles; j++)
14086 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14087 for(k = 0; k < *n_values_per_frame; k++)
14089 (*values)[i][mapping][k].d = *(double *)
14090 ((char *)data->values + size *
14092 (*n_values_per_frame) + k));
14100 if(*(values[0]) == 0)
14102 if(tng_data_values_alloc(tng_data, values[0], *n_frames,
14103 *n_values_per_frame,
14104 *type) != TNG_SUCCESS)
14106 return(TNG_CRITICAL);
14111 case TNG_CHAR_DATA:
14112 for(i = 0; i < *n_frames; i++)
14114 for(j = 0; j < *n_values_per_frame; j++)
14116 len = strlen(data->strings[0][i][j]) + 1;
14117 (*values)[0][i][j].c = malloc(len);
14118 strncpy((*values)[0][i][j].c, data->strings[0][i][j], len);
14123 size = sizeof(int);
14124 for(i = 0; i < *n_frames; i++)
14126 for(j = 0; j < *n_values_per_frame; j++)
14128 (*values)[0][i][j].i = *(int *)((char *)data->values + size *
14129 (i*(*n_values_per_frame) + j));
14133 case TNG_FLOAT_DATA:
14134 size = sizeof(float);
14135 for(i = 0; i < *n_frames; i++)
14137 for(j = 0; j < *n_values_per_frame; j++)
14139 (*values)[0][i][j].f = *(float *)((char *)data->values + size *
14140 (i*(*n_values_per_frame) + j));
14144 case TNG_DOUBLE_DATA:
14146 size = sizeof(double);
14147 for(i = 0; i < *n_frames; i++)
14149 for(j = 0; j < *n_values_per_frame; j++)
14151 (*values)[0][i][j].d = *(double *)((char *)data->values + size *
14152 (i*(*n_values_per_frame) + j));
14158 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
14160 return(TNG_SUCCESS);
14163 tng_function_status DECLSPECDLLEXPORT tng_data_get
14164 (const tng_trajectory_t tng_data,
14165 const int64_t block_id,
14166 union data_values ***values,
14168 int64_t *n_values_per_frame,
14171 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14172 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
14173 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
14174 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
14176 return(tng_gen_data_get(tng_data, block_id, TNG_FALSE, &values, n_frames, 0,
14177 n_values_per_frame, type));
14180 static tng_function_status tng_gen_data_vector_get
14181 (const tng_trajectory_t tng_data,
14182 const int64_t block_id,
14183 const tng_bool is_particle_data,
14186 int64_t *stride_length,
14187 int64_t *n_particles,
14188 int64_t *n_values_per_frame,
14191 int64_t i, j, mapping, file_pos, i_step, full_data_len, n_frames_div;
14192 int64_t block_index;
14195 tng_trajectory_frame_set_t frame_set;
14196 tng_gen_block_t block;
14198 char block_type_flag;
14199 tng_function_status stat;
14201 frame_set = &tng_data->current_trajectory_frame_set;
14206 if(is_particle_data == TNG_TRUE)
14208 stat = tng_particle_data_find(tng_data, block_id, &data);
14212 stat = tng_data_find(tng_data, block_id, &data);
14215 if(stat != TNG_SUCCESS)
14217 tng_block_init(&block);
14218 file_pos = ftello(tng_data->input_file);
14219 /* Read all blocks until next frame set block */
14220 stat = tng_block_header_read(tng_data, block);
14221 while(file_pos < tng_data->input_file_len &&
14222 stat != TNG_CRITICAL &&
14223 block->id != TNG_TRAJECTORY_FRAME_SET &&
14226 /* Use hash by default */
14227 stat = tng_block_read_next(tng_data, block,
14229 if(stat != TNG_CRITICAL)
14231 file_pos = ftello(tng_data->input_file);
14232 if(file_pos < tng_data->input_file_len)
14234 stat = tng_block_header_read(tng_data, block);
14238 tng_block_destroy(&block);
14239 if(stat == TNG_CRITICAL)
14241 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14242 file_pos, __FILE__, __LINE__);
14246 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
14248 data = &frame_set->tr_particle_data[i];
14249 if(data->block_id == block_id)
14255 if(block_index < 0)
14257 return(TNG_FAILURE);
14261 if(is_particle_data == TNG_TRUE)
14263 if(tng_data->current_trajectory_frame_set_input_file_pos > 0)
14265 block_type_flag = TNG_TRAJECTORY_BLOCK;
14269 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
14272 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
14273 tng_data->var_num_atoms_flag)
14275 *n_particles = frame_set->n_particles;
14279 *n_particles = tng_data->n_particles;
14283 *type = data->datatype;
14287 case TNG_CHAR_DATA:
14288 return(TNG_FAILURE);
14290 size = sizeof(int64_t);
14292 case TNG_FLOAT_DATA:
14293 size = sizeof(float);
14295 case TNG_DOUBLE_DATA:
14297 size = sizeof(double);
14300 *n_frames = tng_max_i64(1, data->n_frames);
14301 *n_values_per_frame = data->n_values_per_frame;
14302 *stride_length = data->stride_length;
14304 n_frames_div = (*n_frames % *stride_length) ?
14305 *n_frames / *stride_length + 1:
14306 *n_frames / *stride_length;
14308 full_data_len = n_frames_div * size *
14309 (*n_values_per_frame);
14310 if(is_particle_data == TNG_TRUE)
14312 full_data_len *= (*n_particles);
14315 temp = realloc(*values, full_data_len);
14318 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
14319 full_data_len, __FILE__, __LINE__);
14322 return(TNG_CRITICAL);
14327 if(is_particle_data != TNG_TRUE || frame_set->n_mapping_blocks <= 0)
14329 memcpy(*values, data->values, full_data_len);
14333 i_step = (*n_particles) * (*n_values_per_frame);
14334 for(i = 0; i < *n_frames; i++)
14336 for(j = 0; j < *n_particles; j++)
14338 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14339 memcpy(((char *)*values) + size * (i * i_step + mapping *
14340 (*n_values_per_frame)),
14341 (char *)data->values + size *
14342 (i * i_step + j * (*n_values_per_frame)),
14343 size * (*n_values_per_frame));
14348 data->last_retrieved_frame = frame_set->first_frame + data->n_frames - 1;
14350 return(TNG_SUCCESS);
14353 tng_function_status DECLSPECDLLEXPORT tng_data_vector_get
14354 (const tng_trajectory_t tng_data,
14355 const int64_t block_id,
14358 int64_t *stride_length,
14359 int64_t *n_values_per_frame,
14362 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14363 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
14364 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
14365 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
14366 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
14368 return(tng_gen_data_vector_get(tng_data, block_id, TNG_FALSE, values,
14369 n_frames, stride_length, 0, n_values_per_frame,
14373 static tng_function_status tng_gen_data_interval_get
14374 (const tng_trajectory_t tng_data,
14375 const int64_t block_id,
14376 const tng_bool is_particle_data,
14377 const int64_t start_frame_nr,
14378 const int64_t end_frame_nr,
14379 const char hash_mode,
14380 union data_values ****values,
14381 int64_t *n_particles,
14382 int64_t *n_values_per_frame,
14385 int64_t i, j, k, mapping, n_frames, file_pos, current_frame_pos, i_step;
14386 int64_t first_frame, block_index;
14390 tng_trajectory_frame_set_t frame_set;
14391 tng_gen_block_t block;
14392 char block_type_flag;
14393 tng_function_status stat;
14397 frame_set = &tng_data->current_trajectory_frame_set;
14398 first_frame = frame_set->first_frame;
14400 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
14401 if(stat != TNG_SUCCESS)
14406 /* Do not re-read the frame set. */
14407 if((is_particle_data == TNG_TRUE &&
14408 (first_frame != frame_set->first_frame ||
14409 frame_set->n_particle_data_blocks <= 0)) ||
14410 (is_particle_data == TNG_FALSE &&
14411 (first_frame != frame_set->first_frame ||
14412 frame_set->n_data_blocks <= 0)))
14414 tng_block_init(&block);
14415 file_pos = ftello(tng_data->input_file);
14416 /* Read all blocks until next frame set block */
14417 stat = tng_block_header_read(tng_data, block);
14418 while(file_pos < tng_data->input_file_len &&
14419 stat != TNG_CRITICAL &&
14420 block->id != TNG_TRAJECTORY_FRAME_SET &&
14423 stat = tng_block_read_next(tng_data, block,
14425 if(stat != TNG_CRITICAL)
14427 file_pos = ftello(tng_data->input_file);
14428 if(file_pos < tng_data->input_file_len)
14430 stat = tng_block_header_read(tng_data, block);
14434 tng_block_destroy(&block);
14435 if(stat == TNG_CRITICAL)
14437 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14438 file_pos, __FILE__, __LINE__);
14443 /* See if there is already a data block of this ID.
14444 * Start checking the last read frame set */
14445 if(is_particle_data == TNG_TRUE)
14447 for(i = frame_set->n_particle_data_blocks; i-- ;)
14449 data = &frame_set->tr_particle_data[i];
14450 if(data->block_id == block_id)
14453 block_type_flag = TNG_TRAJECTORY_BLOCK;
14460 for(i = 0; i < frame_set->n_data_blocks; i++)
14462 data = &frame_set->tr_data[i];
14463 if(data->block_id == block_id)
14471 if(block_index < 0)
14473 fprintf(stderr, "TNG library: Could not find particle data block with id %"PRId64". %s: %d\n",
14474 block_id, __FILE__, __LINE__);
14475 return(TNG_FAILURE);
14478 if(is_particle_data == TNG_TRUE)
14480 if(block_type_flag == TNG_TRAJECTORY_BLOCK &&
14481 tng_data->var_num_atoms_flag)
14483 *n_particles = frame_set->n_particles;
14487 *n_particles = tng_data->n_particles;
14491 n_frames = end_frame_nr - start_frame_nr + 1;
14492 *n_values_per_frame = data->n_values_per_frame;
14493 *type = data->datatype;
14497 if(is_particle_data == TNG_TRUE)
14499 if(tng_particle_data_values_alloc(tng_data, values, n_frames,
14500 *n_particles, *n_values_per_frame,
14501 *type) != TNG_SUCCESS)
14503 return(TNG_CRITICAL);
14508 if(tng_data_values_alloc(tng_data, *values, n_frames,
14509 *n_values_per_frame,
14510 *type) != TNG_SUCCESS)
14512 return(TNG_CRITICAL);
14517 current_frame_pos = start_frame_nr - frame_set->first_frame;
14519 if(is_particle_data == TNG_TRUE)
14521 i_step = (*n_particles) * (*n_values_per_frame);
14525 i_step = (*n_values_per_frame);
14527 /* It's not very elegant to reuse so much of the code in the different case
14528 * statements, but it's unnecessarily slow to have the switch-case block
14529 * inside the for loops. */
14532 case TNG_CHAR_DATA:
14533 for(i=0; i<n_frames; i++)
14535 if(current_frame_pos == frame_set->n_frames)
14537 stat = tng_frame_set_read_next(tng_data, hash_mode);
14538 if(stat != TNG_SUCCESS)
14542 current_frame_pos = 0;
14544 if(is_particle_data == TNG_TRUE)
14546 for(j = 0; j < *n_particles; j++)
14548 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14549 for(k = 0; k < *n_values_per_frame; k++)
14551 len = strlen(data->strings[current_frame_pos][j][k]) + 1;
14552 (*values)[i][mapping][k].c = malloc(len);
14553 strncpy((*values)[i][mapping][k].c, data->strings[current_frame_pos][j][k], len);
14559 for(j = 0; j < *n_values_per_frame; j++)
14561 len = strlen(data->strings[0][current_frame_pos][j]) + 1;
14562 (*values)[0][i][j].c = malloc(len);
14563 strncpy((*values)[0][i][j].c, data->strings[0][current_frame_pos][j], len);
14566 current_frame_pos++;
14570 size = sizeof(int);
14571 for(i=0; i<n_frames; i++)
14573 if(current_frame_pos == frame_set->n_frames)
14575 stat = tng_frame_set_read_next(tng_data, hash_mode);
14576 if(stat != TNG_SUCCESS)
14580 current_frame_pos = 0;
14582 if(is_particle_data == TNG_TRUE)
14584 for(j = 0; j < *n_particles; j++)
14586 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14587 for(k = 0; k < *n_values_per_frame; k++)
14589 (*values)[i][mapping][k].i = *(int *)
14590 ((char *)data->values + size *
14591 (current_frame_pos *
14593 (*n_values_per_frame) + k));
14596 current_frame_pos++;
14600 for(j = 0; j < *n_values_per_frame; j++)
14602 (*values)[0][i][j].i = *(int *)((char *)data->values + size *
14603 (current_frame_pos *
14609 case TNG_FLOAT_DATA:
14610 size = sizeof(float);
14611 for(i=0; i<n_frames; i++)
14613 if(current_frame_pos == frame_set->n_frames)
14615 stat = tng_frame_set_read_next(tng_data, hash_mode);
14616 if(stat != TNG_SUCCESS)
14620 current_frame_pos = 0;
14622 if(is_particle_data == TNG_TRUE)
14624 for(j=0; j<*n_particles; j++)
14626 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14627 for(k=0; k<*n_values_per_frame; k++)
14629 (*values)[i][mapping][k].f = *(float *)
14630 ((char *)data->values + size *
14631 (current_frame_pos *
14633 (*n_values_per_frame) + k));
14639 for(j = 0; j < *n_values_per_frame; j++)
14641 (*values)[0][i][j].f = *(float *)((char *)data->values + size *
14642 (current_frame_pos *
14646 current_frame_pos++;
14649 case TNG_DOUBLE_DATA:
14651 size = sizeof(double);
14652 for(i=0; i<n_frames; i++)
14654 if(current_frame_pos == frame_set->n_frames)
14656 stat = tng_frame_set_read_next(tng_data, hash_mode);
14657 if(stat != TNG_SUCCESS)
14661 current_frame_pos = 0;
14663 if(is_particle_data == TNG_TRUE)
14665 for(j=0; j<*n_particles; j++)
14667 tng_particle_mapping_get_real_particle(frame_set, j, &mapping);
14668 for(k=0; k<*n_values_per_frame; k++)
14670 (*values)[i][mapping][k].d = *(double *)
14671 ((char *)data->values + size *
14672 (current_frame_pos *
14674 (*n_values_per_frame) + k));
14680 for(j = 0; j < *n_values_per_frame; j++)
14682 (*values)[0][i][j].d = *(double *)((char *)data->values + size *
14683 (current_frame_pos *
14687 current_frame_pos++;
14691 data->last_retrieved_frame = end_frame_nr;
14693 return(TNG_SUCCESS);
14696 tng_function_status DECLSPECDLLEXPORT tng_data_interval_get
14697 (const tng_trajectory_t tng_data,
14698 const int64_t block_id,
14699 const int64_t start_frame_nr,
14700 const int64_t end_frame_nr,
14701 const char hash_mode,
14702 union data_values ***values,
14703 int64_t *n_values_per_frame,
14706 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14707 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
14708 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
14709 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
14711 return(tng_gen_data_interval_get(tng_data, block_id, TNG_FALSE, start_frame_nr,
14712 end_frame_nr, hash_mode, &values, 0,
14713 n_values_per_frame, type));
14716 static tng_function_status tng_gen_data_vector_interval_get
14717 (const tng_trajectory_t tng_data,
14718 const int64_t block_id,
14719 const tng_bool is_particle_data,
14720 const int64_t start_frame_nr,
14721 const int64_t end_frame_nr,
14722 const char hash_mode,
14724 int64_t *n_particles,
14725 int64_t *stride_length,
14726 int64_t *n_values_per_frame,
14729 int64_t n_frames, tot_n_frames, n_frames_div, n_frames_div_2, first_frame;
14730 int64_t file_pos, current_frame_pos, last_frame_pos, full_data_len, frame_size;
14732 tng_trajectory_frame_set_t frame_set;
14734 tng_gen_block_t block;
14735 void *current_values = 0, *temp;
14736 tng_function_status stat;
14738 frame_set = &tng_data->current_trajectory_frame_set;
14739 first_frame = frame_set->first_frame;
14741 stat = tng_frame_set_of_frame_find(tng_data, start_frame_nr);
14742 if(stat != TNG_SUCCESS)
14747 /* Do not re-read the frame set and only need the requested block + particle mapping blocks. */
14748 /* TODO: Test that blocks are read correctly now that now all of them are read at the same time. */
14749 if(is_particle_data == TNG_TRUE)
14751 stat = tng_particle_data_find(tng_data, block_id, &data);
14755 stat = tng_data_find(tng_data, block_id, &data);
14758 if(first_frame != frame_set->first_frame ||
14759 stat != TNG_SUCCESS)
14761 tng_block_init(&block);
14762 if(stat != TNG_SUCCESS)
14764 fseeko(tng_data->input_file,
14765 tng_data->current_trajectory_frame_set_input_file_pos,
14767 stat = tng_block_header_read(tng_data, block);
14768 if(stat != TNG_SUCCESS)
14770 fprintf(stderr, "TNG library: Cannot read block header. %s: %d\n",
14771 __FILE__, __LINE__);
14775 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
14777 file_pos = ftello(tng_data->input_file);
14778 /* Read until next frame set block */
14779 stat = tng_block_header_read(tng_data, block);
14780 while(file_pos < tng_data->input_file_len &&
14781 stat != TNG_CRITICAL &&
14782 block->id != TNG_TRAJECTORY_FRAME_SET &&
14785 if(block->id == block_id || block->id == TNG_PARTICLE_MAPPING)
14787 stat = tng_block_read_next(tng_data, block,
14789 if(stat != TNG_CRITICAL)
14791 file_pos = ftello(tng_data->input_file);
14792 if(file_pos < tng_data->input_file_len)
14794 stat = tng_block_header_read(tng_data, block);
14800 file_pos += block->block_contents_size + block->header_contents_size;
14801 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
14802 if(file_pos < tng_data->input_file_len)
14804 stat = tng_block_header_read(tng_data, block);
14808 tng_block_destroy(&block);
14809 if(stat == TNG_CRITICAL)
14811 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
14812 file_pos, __FILE__, __LINE__);
14816 if(is_particle_data == TNG_TRUE)
14818 stat = tng_particle_data_find(tng_data, block_id, &data);
14822 stat = tng_data_find(tng_data, block_id, &data);
14824 if(stat != TNG_SUCCESS)
14829 stat = tng_gen_data_vector_get(tng_data, block_id, is_particle_data,
14830 ¤t_values, &n_frames, stride_length,
14831 n_particles, n_values_per_frame, type);
14833 if(stat != TNG_SUCCESS || (is_particle_data && *n_particles == 0))
14837 free(current_values);
14842 if(n_frames == 1 && n_frames < frame_set->n_frames)
14848 tot_n_frames = end_frame_nr - start_frame_nr + 1;
14853 case TNG_CHAR_DATA:
14854 return(TNG_FAILURE);
14856 size = sizeof(int64_t);
14858 case TNG_FLOAT_DATA:
14859 size = sizeof(float);
14861 case TNG_DOUBLE_DATA:
14863 size = sizeof(double);
14866 n_frames_div = (tot_n_frames % *stride_length) ?
14867 tot_n_frames / *stride_length + 1:
14868 tot_n_frames / *stride_length;
14870 full_data_len = n_frames_div * size * (*n_values_per_frame);
14871 if(is_particle_data)
14873 full_data_len *= (*n_particles);
14876 temp = realloc(*values, full_data_len);
14879 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
14880 full_data_len, __FILE__, __LINE__);
14883 return(TNG_CRITICAL);
14888 if( n_frames == 1 && n_frames < frame_set->n_frames)
14890 if(is_particle_data)
14892 memcpy(*values, current_values, size * (*n_particles) *
14893 (*n_values_per_frame));
14897 memcpy(*values, current_values, size * (*n_values_per_frame));
14902 current_frame_pos = start_frame_nr - frame_set->first_frame;
14904 frame_size = size * (*n_values_per_frame);
14905 if(is_particle_data)
14907 frame_size *= (*n_particles);
14910 last_frame_pos = tng_min_i64(n_frames,
14911 end_frame_nr - start_frame_nr);
14913 n_frames_div = current_frame_pos / *stride_length;
14914 n_frames_div_2 = (last_frame_pos % *stride_length) ?
14915 last_frame_pos / *stride_length + 1:
14916 last_frame_pos / *stride_length;
14917 n_frames_div_2 = tng_max_i64(1, n_frames_div_2 + 1);
14919 memcpy(*values, (char *)current_values + n_frames_div * frame_size,
14920 n_frames_div_2 * frame_size);
14922 current_frame_pos += n_frames - current_frame_pos;
14924 while(current_frame_pos <= end_frame_nr - start_frame_nr)
14926 stat = tng_frame_set_read_next(tng_data, hash_mode);
14927 if(stat != TNG_SUCCESS)
14931 free(current_values);
14938 stat = tng_gen_data_vector_get(tng_data, block_id, is_particle_data,
14939 ¤t_values, &n_frames,
14940 stride_length, n_particles,
14941 n_values_per_frame, type);
14943 if(stat != TNG_SUCCESS)
14947 free(current_values);
14954 last_frame_pos = tng_min_i64(n_frames,
14955 end_frame_nr - current_frame_pos);
14957 n_frames_div = current_frame_pos / *stride_length;
14958 n_frames_div_2 = (last_frame_pos % *stride_length) ?
14959 last_frame_pos / *stride_length + 1:
14960 last_frame_pos / *stride_length;
14961 n_frames_div_2 = tng_max_i64(1, n_frames_div_2);
14963 memcpy(((char *)*values) + n_frames_div * frame_size,
14965 n_frames_div_2 * frame_size);
14967 current_frame_pos += n_frames;
14973 free(current_values);
14976 data->last_retrieved_frame = end_frame_nr;
14978 return(TNG_SUCCESS);
14982 tng_function_status DECLSPECDLLEXPORT tng_data_vector_interval_get
14983 (const tng_trajectory_t tng_data,
14984 const int64_t block_id,
14985 const int64_t start_frame_nr,
14986 const int64_t end_frame_nr,
14987 const char hash_mode,
14989 int64_t *stride_length,
14990 int64_t *n_values_per_frame,
14993 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
14994 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than the end_frame_nr.");
14995 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
14996 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
14997 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
14999 return(tng_gen_data_vector_interval_get(tng_data, block_id, TNG_FALSE,
15000 start_frame_nr, end_frame_nr,
15001 hash_mode, values, 0, stride_length,
15002 n_values_per_frame, type));
15005 tng_function_status DECLSPECDLLEXPORT tng_particle_data_get
15006 (const tng_trajectory_t tng_data,
15007 const int64_t block_id,
15008 union data_values ****values,
15010 int64_t *n_particles,
15011 int64_t *n_values_per_frame,
15014 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15015 TNG_ASSERT(n_frames, "TNG library: n_frames must not be a NULL pointer.");
15016 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
15017 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15018 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15020 return(tng_gen_data_get(tng_data, block_id, TNG_TRUE, values, n_frames, n_particles,
15021 n_values_per_frame, type));
15024 tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_get
15025 (const tng_trajectory_t tng_data,
15026 const int64_t block_id,
15029 int64_t *stride_length,
15030 int64_t *n_particles,
15031 int64_t *n_values_per_frame,
15034 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15035 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
15036 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
15037 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15038 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15040 return(tng_gen_data_vector_get(tng_data, block_id, TNG_TRUE, values,
15041 n_frames, stride_length, n_particles,
15042 n_values_per_frame, type));
15045 tng_function_status DECLSPECDLLEXPORT tng_particle_data_interval_get
15046 (const tng_trajectory_t tng_data,
15047 const int64_t block_id,
15048 const int64_t start_frame_nr,
15049 const int64_t end_frame_nr,
15050 const char hash_mode,
15051 union data_values ****values,
15052 int64_t *n_particles,
15053 int64_t *n_values_per_frame,
15056 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15057 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
15058 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
15059 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15060 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15062 return(tng_gen_data_interval_get(tng_data, block_id, TNG_TRUE, start_frame_nr,
15063 end_frame_nr, hash_mode, values, n_particles,
15064 n_values_per_frame, type));
15067 tng_function_status DECLSPECDLLEXPORT tng_particle_data_vector_interval_get
15068 (const tng_trajectory_t tng_data,
15069 const int64_t block_id,
15070 const int64_t start_frame_nr,
15071 const int64_t end_frame_nr,
15072 const char hash_mode,
15074 int64_t *n_particles,
15075 int64_t *stride_length,
15076 int64_t *n_values_per_frame,
15079 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15080 TNG_ASSERT(start_frame_nr <= end_frame_nr, "TNG library: start_frame_nr must not be higher than tne end_frame_nr.");
15081 TNG_ASSERT(n_particles, "TNG library: n_particles must not be a NULL pointer.");
15082 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer.");
15083 TNG_ASSERT(n_values_per_frame, "TNG library: n_values_per_frame must not be a NULL pointer.");
15084 TNG_ASSERT(type, "TNG library: type must not be a NULL pointer.");
15086 return(tng_gen_data_vector_interval_get(tng_data, block_id, TNG_TRUE,
15087 start_frame_nr, end_frame_nr,
15088 hash_mode, values, n_particles,
15089 stride_length, n_values_per_frame,
15093 tng_function_status DECLSPECDLLEXPORT tng_data_get_stride_length
15094 (const tng_trajectory_t tng_data,
15095 const int64_t block_id,
15097 int64_t *stride_length)
15099 tng_function_status stat;
15101 int64_t orig_file_pos, file_pos;
15102 int is_particle_data;
15104 if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
15111 stat = tng_frame_set_of_frame_find(tng_data, frame);
15112 if(stat != TNG_SUCCESS)
15117 orig_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
15118 stat = tng_data_find(tng_data, block_id, &data);
15119 if(stat != TNG_SUCCESS)
15121 stat = tng_particle_data_find(tng_data, block_id, &data);
15122 if(stat != TNG_SUCCESS)
15124 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15125 /* If no specific frame was required read until this data block is found */
15128 file_pos = ftello(tng_data->input_file);
15129 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
15131 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15132 file_pos = ftello(tng_data->input_file);
15135 if(stat != TNG_SUCCESS)
15137 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
15141 stat = tng_data_find(tng_data, block_id, &data);
15142 if(stat != TNG_SUCCESS)
15144 stat = tng_particle_data_find(tng_data, block_id, &data);
15145 if(stat != TNG_SUCCESS)
15147 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
15153 is_particle_data = 1;
15158 is_particle_data = 0;
15163 is_particle_data = 1;
15168 is_particle_data = 0;
15170 if(is_particle_data)
15172 *stride_length = data->stride_length;
15176 *stride_length = data->stride_length;
15178 tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
15180 return(TNG_SUCCESS);
15183 tng_function_status DECLSPECDLLEXPORT tng_time_get_str
15184 (const tng_trajectory_t tng_data,
15187 struct tm *time_data;
15190 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15191 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
15193 secs = tng_data->time;
15195 time_data = localtime(&secs); /* Returns a statically allocated variable. */
15196 TNG_SNPRINTF(time, TNG_MAX_DATE_STR_LEN,
15197 "%4d-%02d-%02d %02d:%02d:%02d",
15198 time_data->tm_year+1900, time_data->tm_mon+1, time_data->tm_mday,
15199 time_data->tm_hour, time_data->tm_min, time_data->tm_sec);
15201 return(TNG_SUCCESS);
15205 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_open
15206 (const char *filename,
15208 tng_trajectory_t *tng_data_p)
15210 tng_function_status stat;
15212 TNG_ASSERT(filename, "TNG library: filename must not be a NULL pointer.");
15214 if(mode != 'r' && mode != 'w' && mode != 'a')
15216 return(TNG_FAILURE);
15219 if(tng_trajectory_init(tng_data_p) != TNG_SUCCESS)
15221 tng_trajectory_destroy(tng_data_p);
15222 return(TNG_CRITICAL);
15225 if(mode == 'r' || mode == 'a')
15227 tng_input_file_set(*tng_data_p, filename);
15229 /* Read the file headers */
15230 tng_file_headers_read(*tng_data_p, TNG_USE_HASH);
15232 stat = tng_num_frame_sets_get(*tng_data_p, &(*tng_data_p)->n_trajectory_frame_sets);
15234 if(stat != TNG_SUCCESS)
15242 stat = tng_output_file_set(*tng_data_p, filename);
15244 else if(mode == 'a')
15246 if((*tng_data_p)->output_file)
15248 fclose((*tng_data_p)->output_file);
15250 (*tng_data_p)->output_file = (*tng_data_p)->input_file;
15251 fseeko((*tng_data_p)->input_file,
15252 (*tng_data_p)->last_trajectory_frame_set_input_file_pos,
15255 stat = tng_frame_set_read(*tng_data_p, TNG_USE_HASH);
15256 if(stat != TNG_SUCCESS)
15258 fprintf(stderr, "TNG library: Cannot read frame set and related blocks. %s: %d\n",
15259 __FILE__, __LINE__);
15261 (*tng_data_p)->output_file = 0;
15263 (*tng_data_p)->first_trajectory_frame_set_output_file_pos =
15264 (*tng_data_p)->first_trajectory_frame_set_input_file_pos;
15265 (*tng_data_p)->last_trajectory_frame_set_output_file_pos =
15266 (*tng_data_p)->last_trajectory_frame_set_input_file_pos;
15267 (*tng_data_p)->current_trajectory_frame_set_output_file_pos =
15268 (*tng_data_p)->current_trajectory_frame_set_input_file_pos;
15269 if((*tng_data_p)->input_file)
15271 fclose((*tng_data_p)->input_file);
15272 (*tng_data_p)->input_file = 0;
15274 if((*tng_data_p)->input_file_path)
15276 free((*tng_data_p)->input_file_path);
15277 (*tng_data_p)->input_file_path = 0;
15279 tng_output_append_file_set(*tng_data_p, filename);
15281 fseeko((*tng_data_p)->output_file, 0, SEEK_END);
15287 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_close
15288 (tng_trajectory_t *tng_data_p)
15290 tng_trajectory_frame_set_t frame_set;
15292 if(tng_data_p == 0)
15294 fprintf(stderr, "TNG library: Empty pointer to trajectory when attempting to close. %s: %d\n",
15295 __FILE__, __LINE__);
15296 return(TNG_FAILURE);
15299 if(*tng_data_p == 0)
15301 return(TNG_SUCCESS);
15304 frame_set = &(*tng_data_p)->current_trajectory_frame_set;
15306 if(frame_set->n_unwritten_frames > 0)
15308 frame_set->n_frames = frame_set->n_unwritten_frames;
15309 tng_frame_set_write(*tng_data_p, TNG_USE_HASH);
15312 return(tng_trajectory_destroy(tng_data_p));
15315 tng_function_status DECLSPECDLLEXPORT tng_util_time_of_frame_get
15316 (const tng_trajectory_t tng_data,
15317 const int64_t frame_nr,
15320 int64_t first_frame;
15321 tng_trajectory_frame_set_t frame_set;
15322 tng_function_status stat;
15324 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15325 TNG_ASSERT(time, "TNG library: time must not be a NULL pointer");
15327 stat = tng_frame_set_of_frame_find(tng_data, frame_nr);
15328 if(stat != TNG_SUCCESS)
15330 fprintf(stderr, "TNG library: Cannot find frame nr %"PRId64". %s: %d\n",
15331 frame_nr, __FILE__, __LINE__);
15335 frame_set = &tng_data->current_trajectory_frame_set;
15336 first_frame = frame_set->first_frame;
15338 if(tng_data->time_per_frame <= 0)
15340 return(TNG_FAILURE);
15343 *time = frame_set->first_frame_time + (tng_data->time_per_frame * (frame_nr - first_frame));
15345 return(TNG_SUCCESS);
15349 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecules_get
15350 (const tng_trajectory_t tng_data,
15352 int64_t **molecule_cnt_list,
15353 tng_molecule_t *mols)
15355 tng_trajectory_frame_set_t frame_set;
15357 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15358 TNG_ASSERT(n_mols, "TNG library: n_mols must not be a NULL pointer.");
15360 *n_mols = tng_data->n_molecules;
15362 frame_set = &tng_data->current_trajectory_frame_set;
15363 if(tng_data->var_num_atoms_flag && frame_set && frame_set->molecule_cnt_list)
15365 *molecule_cnt_list = frame_set->molecule_cnt_list;
15369 *molecule_cnt_list = tng_data->molecule_cnt_list;
15372 *mols = tng_data->molecules;
15374 return(TNG_SUCCESS);
15378 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_molecule_add
15379 (const tng_trajectory_t tng_data,
15382 tng_molecule_t *mol)
15384 tng_function_status stat;
15386 TNG_ASSERT(name, "TNG library: name must not be a NULL pointer");
15387 TNG_ASSERT(cnt>=0, "TNG library: cnt must be >= 0");
15389 stat = tng_molecule_add(tng_data, name, mol);
15390 if(stat != TNG_SUCCESS)
15394 stat = tng_molecule_cnt_set(tng_data, *mol, cnt);
15399 tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_get
15400 (const tng_trajectory_t tng_data,
15401 const tng_molecule_t mol,
15402 int64_t *n_particles,
15407 char ***chain_names,
15408 int64_t **chain_ids)
15416 *n_particles = mol->n_atoms;
15418 *names = malloc(sizeof(char *) * *n_particles);
15419 *types = malloc(sizeof(char *) * *n_particles);
15420 *res_names = malloc(sizeof(char *) * *n_particles);
15421 *chain_names = malloc(sizeof(char *) * *n_particles);
15422 *res_ids = malloc(sizeof(int64_t) * *n_particles);
15423 *chain_ids = malloc(sizeof(int64_t) * *n_particles);
15425 for(i = 0; i < *n_particles; i++)
15427 atom = &mol->atoms[i];
15428 res = atom->residue;
15429 chain = res->chain;
15430 (*names)[i] = malloc(strlen(atom->name));
15431 strcpy(*names[i], atom->name);
15432 (*types)[i] = malloc(strlen(atom->atom_type));
15433 strcpy(*types[i], atom->atom_type);
15434 (*res_names)[i] = malloc(strlen(res->name));
15435 strcpy(*res_names[i], res->name);
15436 (*chain_names)[i] = malloc(strlen(chain->name));
15437 strcpy(*chain_names[i], chain->name);
15438 (*res_ids)[i] = res->id;
15439 (*chain_ids)[i] = chain->id;
15442 return(TNG_SUCCESS);
15445 tng_function_status DECLSPECDLLEXPORT tng_util_molecule_particles_set
15446 (const tng_trajectory_t tng_data,
15447 const tng_molecule_t mol,
15448 const int64_t n_particles,
15449 const char **names,
15450 const char **types,
15451 const char **res_names,
15452 const int64_t *res_ids,
15453 const char **chain_names,
15454 const int64_t *chain_ids)
15458 tng_residue_t residue;
15460 tng_function_status stat;
15462 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15463 TNG_ASSERT(names, "TNG library: names must not be a NULL pointer");
15464 TNG_ASSERT(types, "TNG library: types must not be a NULL pointer");
15465 TNG_ASSERT(res_names, "TNG library: res_names must not be a NULL pointer");
15466 TNG_ASSERT(res_ids, "TNG library: res_ids must not be a NULL pointer");
15467 TNG_ASSERT(chain_names, "TNG library: chain_names must not be a NULL pointer");
15468 TNG_ASSERT(chain_ids, "TNG library: chain_ids must not be a NULL pointer");
15470 for(i = 0; i < n_particles; i++)
15472 if(tng_molecule_chain_find(tng_data, mol, chain_names[i], chain_ids[i],
15473 &chain) == TNG_FAILURE)
15475 stat = tng_molecule_chain_add(tng_data, mol, chain_names[i],
15477 if(stat != TNG_SUCCESS)
15482 if(tng_chain_residue_find(tng_data, chain, res_names[i], res_ids[i],
15483 &residue) == TNG_FAILURE)
15485 stat = tng_chain_residue_add(tng_data, chain, res_names[i],
15487 if(stat != TNG_SUCCESS)
15492 stat = tng_residue_atom_add(tng_data, residue, names[i], types[i], &atom);
15493 if(stat != TNG_SUCCESS)
15498 return(TNG_SUCCESS);
15501 tng_function_status DECLSPECDLLEXPORT tng_util_pos_read
15502 (const tng_trajectory_t tng_data,
15503 float **positions, int64_t *stride_length)
15505 int64_t n_frames, n_particles, n_values_per_frame;
15507 tng_function_status stat;
15509 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15510 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
15511 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
15513 stat = tng_num_frames_get(tng_data, &n_frames);
15514 if(stat != TNG_SUCCESS)
15519 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_POSITIONS,
15520 0, n_frames - 1, TNG_USE_HASH,
15521 (void **)positions,
15524 &n_values_per_frame,
15530 tng_function_status DECLSPECDLLEXPORT tng_util_vel_read
15531 (const tng_trajectory_t tng_data,
15532 float **velocities, int64_t *stride_length)
15534 int64_t n_frames, n_particles, n_values_per_frame;
15536 tng_function_status stat;
15538 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15539 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
15540 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
15542 stat = tng_num_frames_get(tng_data, &n_frames);
15543 if(stat != TNG_SUCCESS)
15548 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_VELOCITIES,
15549 0, n_frames - 1, TNG_USE_HASH,
15550 (void **)velocities,
15553 &n_values_per_frame,
15559 tng_function_status DECLSPECDLLEXPORT tng_util_force_read
15560 (const tng_trajectory_t tng_data,
15561 float **forces, int64_t *stride_length)
15563 int64_t n_frames, n_particles, n_values_per_frame;
15565 tng_function_status stat;
15567 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15568 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
15569 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
15571 stat = tng_num_frames_get(tng_data, &n_frames);
15572 if(stat != TNG_SUCCESS)
15577 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_FORCES,
15578 0, n_frames - 1, TNG_USE_HASH,
15582 &n_values_per_frame,
15588 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read
15589 (const tng_trajectory_t tng_data,
15591 int64_t *stride_length)
15593 int64_t n_frames, n_values_per_frame;
15595 tng_function_status stat;
15597 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15598 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
15599 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
15601 stat = tng_num_frames_get(tng_data, &n_frames);
15602 if(stat != TNG_SUCCESS)
15607 stat = tng_data_vector_interval_get(tng_data, TNG_TRAJ_BOX_SHAPE,
15608 0, n_frames - 1, TNG_USE_HASH,
15609 (void **)box_shape,
15611 &n_values_per_frame,
15617 tng_function_status DECLSPECDLLEXPORT tng_util_particle_data_next_frame_read
15618 (const tng_trajectory_t tng_data,
15619 const int64_t block_id,
15622 int64_t *retrieved_frame_number,
15623 double *retrieved_time)
15625 tng_trajectory_frame_set_t frame_set;
15626 tng_data_t data = 0;
15627 tng_function_status stat;
15629 int64_t i, full_data_len, n_particles;
15633 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15634 TNG_ASSERT(values, "TNG library: The pointer to the values array must not be a NULL pointer");
15635 TNG_ASSERT(data_type, "TNG library: The pointer to the data type of the returned data must not be a NULL pointer");
15636 TNG_ASSERT(retrieved_frame_number, "TNG library: The pointer to the frame number of the returned data must not be a NULL pointer");
15637 TNG_ASSERT(retrieved_time, "TNG library: The pointer to the time of the returned data must not be a NULL pointer");
15639 frame_set = &tng_data->current_trajectory_frame_set;
15641 stat = tng_particle_data_find(tng_data, block_id, &data);
15642 if(stat != TNG_SUCCESS)
15644 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15645 file_pos = ftello(tng_data->input_file);
15646 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
15648 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15649 file_pos = ftello(tng_data->input_file);
15651 if(stat != TNG_SUCCESS)
15655 stat = tng_particle_data_find(tng_data, block_id, &data);
15656 if(stat != TNG_SUCCESS)
15661 if(data->last_retrieved_frame < 0)
15663 fseeko(tng_data->input_file,
15664 tng_data->first_trajectory_frame_set_input_file_pos,
15666 stat = tng_frame_set_read(tng_data, TNG_USE_HASH);
15667 if(stat != TNG_SUCCESS)
15671 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15672 if(stat != TNG_SUCCESS)
15677 i = data->first_frame_with_data;
15681 if(data->n_frames == 1 && frame_set->n_frames == 1)
15683 i = data->last_retrieved_frame + 1;
15687 i = data->last_retrieved_frame + data->stride_length;
15689 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
15691 stat = tng_frame_set_of_frame_find(tng_data, i);
15692 if(stat != TNG_SUCCESS)
15694 /* If the frame set search found the frame set after the starting
15695 * frame set there is a gap in the frame sets. So, even if the frame
15696 * was not found the next frame with data is still in the found
15698 if(stat == TNG_CRITICAL)
15702 if(frame_set->first_frame + frame_set->n_frames - 1 < i)
15704 return(TNG_FAILURE);
15706 i = frame_set->first_frame;
15709 if(data->last_retrieved_frame < frame_set->first_frame)
15711 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15712 if(stat != TNG_SUCCESS)
15718 data->last_retrieved_frame = i;
15719 *retrieved_frame_number = i;
15720 if(frame_set->first_frame_time >= 0 && tng_data->time_per_frame >= 0)
15722 *retrieved_time = frame_set->first_frame_time +
15723 (i - frame_set->first_frame) *
15724 tng_data->time_per_frame;
15728 *retrieved_time = 0;
15731 if(data->stride_length > 1)
15733 i = (i - data->first_frame_with_data) / data->stride_length;
15737 i = (i - frame_set->first_frame);
15740 tng_num_particles_get(tng_data, &n_particles);
15742 *data_type = data->datatype;
15746 case TNG_CHAR_DATA:
15747 return(TNG_FAILURE);
15749 size = sizeof(int64_t);
15751 case TNG_FLOAT_DATA:
15752 size = sizeof(float);
15754 case TNG_DOUBLE_DATA:
15756 size = sizeof(double);
15759 full_data_len = size * n_particles * data->n_values_per_frame;
15761 // fprintf(stderr, "TNG library: TEMP: i = %"PRId64", full_data_len = %"PRId64", size = %d, n_particles = %"PRId64", n_values_per_frame = %"PRId64"\n",
15762 // i, full_data_len, size, n_particles, data->n_values_per_frame);
15764 temp = realloc(*values, full_data_len);
15767 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15768 full_data_len, __FILE__, __LINE__);
15771 return(TNG_CRITICAL);
15776 memcpy(*values, (char *)data->values + i * full_data_len, full_data_len);
15778 return(TNG_SUCCESS);
15781 tng_function_status DECLSPECDLLEXPORT tng_util_non_particle_data_next_frame_read
15782 (const tng_trajectory_t tng_data,
15783 const int64_t block_id,
15786 int64_t *retrieved_frame_number,
15787 double *retrieved_time)
15789 tng_trajectory_frame_set_t frame_set;
15790 tng_data_t data = 0;
15791 tng_function_status stat;
15793 int64_t i, full_data_len;
15797 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15798 TNG_ASSERT(values, "TNG library: The pointer to the values array must not be a NULL pointer");
15799 TNG_ASSERT(data_type, "TNG library: The pointer to the data type of the returned data must not be a NULL pointer");
15800 TNG_ASSERT(retrieved_frame_number, "TNG library: The pointer to the frame number of the returned data must not be a NULL pointer");
15801 TNG_ASSERT(retrieved_time, "TNG library: The pointer to the time of the returned data must not be a NULL pointer");
15803 frame_set = &tng_data->current_trajectory_frame_set;
15805 stat = tng_data_find(tng_data, block_id, &data);
15806 if(stat != TNG_SUCCESS)
15808 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15809 file_pos = ftello(tng_data->input_file);
15810 while(stat != TNG_SUCCESS && file_pos < tng_data->input_file_len)
15812 stat = tng_frame_set_read_next_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15813 file_pos = ftello(tng_data->input_file);
15815 if(stat != TNG_SUCCESS)
15819 stat = tng_data_find(tng_data, block_id, &data);
15820 if(stat != TNG_SUCCESS)
15825 if(data->last_retrieved_frame < 0)
15827 fseeko(tng_data->input_file,
15828 tng_data->first_trajectory_frame_set_input_file_pos,
15830 stat = tng_frame_set_read(tng_data, TNG_USE_HASH);
15831 if(stat != TNG_SUCCESS)
15835 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15836 if(stat != TNG_SUCCESS)
15841 i = data->first_frame_with_data;
15845 if(data->n_frames == 1 && frame_set->n_frames == 1)
15847 i = data->last_retrieved_frame + 1;
15851 i = data->last_retrieved_frame + data->stride_length;
15853 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
15855 stat = tng_frame_set_of_frame_find(tng_data, i);
15856 if(stat != TNG_SUCCESS)
15858 /* If the frame set search found the frame set after the starting
15859 * frame set there is a gap in the frame sets. So, even if the frame
15860 * was not found the next frame with data is still in the found
15862 if(stat == TNG_CRITICAL)
15866 if(frame_set->first_frame + frame_set->n_frames - 1 < i)
15868 return(TNG_FAILURE);
15870 i = frame_set->first_frame;
15873 if(data->last_retrieved_frame < frame_set->first_frame)
15875 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
15876 if(stat != TNG_SUCCESS)
15882 data->last_retrieved_frame = i;
15883 *retrieved_frame_number = i;
15884 if(frame_set->first_frame_time >= 0 && tng_data->time_per_frame >= 0)
15886 *retrieved_time = frame_set->first_frame_time +
15887 (i - frame_set->first_frame) *
15888 tng_data->time_per_frame;
15892 *retrieved_time = 0;
15895 if(data->stride_length > 1)
15897 i = (i - data->first_frame_with_data) / data->stride_length;
15901 i = (i - frame_set->first_frame);
15904 *data_type = data->datatype;
15908 case TNG_CHAR_DATA:
15909 return(TNG_FAILURE);
15911 size = sizeof(int64_t);
15913 case TNG_FLOAT_DATA:
15914 size = sizeof(float);
15916 case TNG_DOUBLE_DATA:
15918 size = sizeof(double);
15921 full_data_len = size * data->n_values_per_frame;
15923 temp = realloc(*values, full_data_len);
15926 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRId64" bytes). %s: %d\n",
15927 full_data_len, __FILE__, __LINE__);
15930 return(TNG_CRITICAL);
15935 memcpy(*values, (char *)data->values + i * full_data_len, full_data_len);
15937 return(TNG_SUCCESS);
15940 tng_function_status DECLSPECDLLEXPORT tng_util_pos_read_range
15941 (const tng_trajectory_t tng_data,
15942 const int64_t first_frame,
15943 const int64_t last_frame,
15945 int64_t *stride_length)
15947 int64_t n_particles, n_values_per_frame;
15949 tng_function_status stat;
15951 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15952 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
15953 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
15954 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
15956 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_POSITIONS,
15957 first_frame, last_frame,
15959 (void **)positions,
15962 &n_values_per_frame,
15965 if(stat == TNG_SUCCESS && type != TNG_FLOAT_DATA)
15967 return(TNG_FAILURE);
15973 tng_function_status DECLSPECDLLEXPORT tng_util_vel_read_range
15974 (const tng_trajectory_t tng_data,
15975 const int64_t first_frame,
15976 const int64_t last_frame,
15977 float **velocities,
15978 int64_t *stride_length)
15980 int64_t n_particles, n_values_per_frame;
15982 tng_function_status stat;
15984 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
15985 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
15986 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
15987 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
15989 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_VELOCITIES,
15990 first_frame, last_frame,
15992 (void **)velocities,
15995 &n_values_per_frame,
15998 if(stat == TNG_SUCCESS && type != TNG_FLOAT_DATA)
16000 return(TNG_FAILURE);
16006 tng_function_status DECLSPECDLLEXPORT tng_util_force_read_range
16007 (const tng_trajectory_t tng_data,
16008 const int64_t first_frame,
16009 const int64_t last_frame,
16011 int64_t *stride_length)
16013 int64_t n_particles, n_values_per_frame;
16015 tng_function_status stat;
16017 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16018 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
16019 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
16020 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
16022 stat = tng_particle_data_vector_interval_get(tng_data, TNG_TRAJ_FORCES,
16023 first_frame, last_frame,
16028 &n_values_per_frame,
16031 if(stat == TNG_SUCCESS && type != TNG_FLOAT_DATA)
16033 return(TNG_FAILURE);
16039 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_read_range
16040 (const tng_trajectory_t tng_data,
16041 const int64_t first_frame,
16042 const int64_t last_frame,
16044 int64_t *stride_length)
16046 int64_t n_values_per_frame;
16048 tng_function_status stat;
16050 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16051 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
16052 TNG_ASSERT(first_frame <= last_frame, "TNG library: first_frame must be lower or equal to last_frame.");
16053 TNG_ASSERT(stride_length, "TNG library: stride_length must not be a NULL pointer");
16055 stat = tng_data_vector_interval_get(tng_data, TNG_TRAJ_BOX_SHAPE,
16056 first_frame, last_frame,
16058 (void **)box_shape,
16060 &n_values_per_frame,
16063 if(stat == TNG_SUCCESS && type != TNG_FLOAT_DATA)
16065 return(TNG_FAILURE);
16071 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_set
16072 (const tng_trajectory_t tng_data,
16074 const int64_t n_values_per_frame,
16075 const int64_t block_id,
16076 const char *block_name,
16077 const char particle_dependency,
16078 const char compression)
16080 tng_trajectory_frame_set_t frame_set;
16082 int64_t n_particles, n_frames;
16083 tng_function_status stat;
16085 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16086 TNG_ASSERT(i >= 0, "TNG library: i (writing interval) must be >= 0.");
16090 fprintf(stderr, "TNG library: Cannot set writing frequency to %"PRId64". %s: %d\n",
16091 i, __FILE__, __LINE__);
16092 return(TNG_FAILURE);
16095 frame_set = &tng_data->current_trajectory_frame_set;
16097 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
16099 n_frames = tng_data->frame_set_n_frames;
16101 stat = tng_frame_set_new(tng_data, 0, n_frames);
16102 if(stat != TNG_SUCCESS)
16104 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
16111 n_frames = frame_set->n_frames;
16114 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
16116 tng_num_particles_get(tng_data, &n_particles);
16117 if(n_particles <= 0)
16119 return(TNG_FAILURE);
16122 if(tng_particle_data_find(tng_data, block_id, &data)
16125 stat = tng_particle_data_block_add(tng_data, block_id,
16128 TNG_TRAJECTORY_BLOCK,
16129 n_frames, n_values_per_frame, i,
16132 if(stat != TNG_SUCCESS)
16134 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16135 __FILE__, __LINE__);
16138 data = &frame_set->tr_particle_data[frame_set->
16139 n_particle_data_blocks - 1];
16140 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
16142 n_values_per_frame);
16143 if(stat != TNG_SUCCESS)
16145 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16146 __FILE__, __LINE__);
16152 if(data->stride_length != i)
16154 data->stride_length = i;
16155 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
16157 n_values_per_frame);
16158 if(stat != TNG_SUCCESS)
16160 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16161 __FILE__, __LINE__);
16169 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
16171 stat = tng_data_block_add(tng_data, block_id, block_name,
16172 TNG_FLOAT_DATA, TNG_TRAJECTORY_BLOCK,
16173 n_frames, n_values_per_frame,
16174 i, compression, 0);
16175 if(stat != TNG_SUCCESS)
16177 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16178 __FILE__, __LINE__);
16181 data = &frame_set->tr_data[frame_set->
16182 n_data_blocks - 1];
16183 stat = tng_allocate_data_mem(tng_data, data, n_frames,
16184 i, n_values_per_frame);
16185 if(stat != TNG_SUCCESS)
16187 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16188 __FILE__, __LINE__);
16194 if(data->stride_length != i)
16196 data->stride_length = i;
16197 stat = tng_allocate_data_mem(tng_data, data, n_frames,
16198 i, n_values_per_frame);
16199 if(stat != TNG_SUCCESS)
16201 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16202 __FILE__, __LINE__);
16209 return(TNG_SUCCESS);
16212 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_interval_double_set
16213 (const tng_trajectory_t tng_data,
16215 const int64_t n_values_per_frame,
16216 const int64_t block_id,
16217 const char *block_name,
16218 const char particle_dependency,
16219 const char compression)
16221 tng_trajectory_frame_set_t frame_set;
16223 int64_t n_particles, n_frames;
16224 tng_function_status stat;
16226 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16227 TNG_ASSERT(i >= 0, "TNG library: i (writing interval) must be >= 0.");
16231 fprintf(stderr, "TNG library: Cannot set writing frequency to %"PRId64". %s: %d\n",
16232 i, __FILE__, __LINE__);
16233 return(TNG_FAILURE);
16236 frame_set = &tng_data->current_trajectory_frame_set;
16238 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
16240 n_frames = tng_data->frame_set_n_frames;
16242 stat = tng_frame_set_new(tng_data, 0, n_frames);
16243 if(stat != TNG_SUCCESS)
16245 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
16252 n_frames = frame_set->n_frames;
16255 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
16257 tng_num_particles_get(tng_data, &n_particles);
16259 if(n_particles <= 0)
16261 return(TNG_FAILURE);
16264 if(tng_particle_data_find(tng_data, block_id, &data)
16267 stat = tng_particle_data_block_add(tng_data, block_id,
16270 TNG_TRAJECTORY_BLOCK,
16271 n_frames, n_values_per_frame, i,
16274 if(stat != TNG_SUCCESS)
16276 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16277 __FILE__, __LINE__);
16280 data = &frame_set->tr_particle_data[frame_set->
16281 n_particle_data_blocks - 1];
16282 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
16284 n_values_per_frame);
16285 if(stat != TNG_SUCCESS)
16287 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16288 __FILE__, __LINE__);
16294 data->stride_length = i;
16299 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
16301 stat = tng_data_block_add(tng_data, block_id, block_name,
16302 TNG_DOUBLE_DATA, TNG_TRAJECTORY_BLOCK,
16303 n_frames, n_values_per_frame,
16304 i, compression, 0);
16305 if(stat != TNG_SUCCESS)
16307 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16308 __FILE__, __LINE__);
16311 data = &frame_set->tr_data[frame_set->
16312 n_data_blocks - 1];
16313 stat = tng_allocate_data_mem(tng_data, data, n_frames,
16314 i, n_values_per_frame);
16315 if(stat != TNG_SUCCESS)
16317 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16318 __FILE__, __LINE__);
16324 data->stride_length = i;
16328 return(TNG_SUCCESS);
16331 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write_frequency_set
16332 (const tng_trajectory_t tng_data,
16334 const int64_t n_values_per_frame,
16335 const int64_t block_id,
16336 const char *block_name,
16337 const char particle_dependency,
16338 const char compression)
16340 fprintf(stderr, "TNG library: Using obsolete function tng_util_generic_write_frequency_set(). "
16341 "See documentation. %s: %d", __FILE__, __LINE__);
16342 return(tng_util_generic_write_interval_set(tng_data, i, n_values_per_frame,
16343 block_id, block_name,
16344 particle_dependency,
16347 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_set
16348 (const tng_trajectory_t tng_data,
16351 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16352 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
16354 return(tng_util_generic_write_interval_set(tng_data, i, 3,
16355 TNG_TRAJ_POSITIONS,
16357 TNG_PARTICLE_BLOCK_DATA,
16358 TNG_TNG_COMPRESSION));
16361 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_interval_double_set
16362 (const tng_trajectory_t tng_data,
16365 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16366 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
16368 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
16369 TNG_TRAJ_POSITIONS,
16371 TNG_PARTICLE_BLOCK_DATA,
16372 TNG_TNG_COMPRESSION));
16375 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write_frequency_set
16376 (const tng_trajectory_t tng_data,
16379 fprintf(stderr, "TNG library: Using obsolete function tng_util_pos_write_frequency_set(). "
16380 "See documentation. %s: %d", __FILE__, __LINE__);
16381 return(tng_util_pos_write_interval_set(tng_data, i));
16384 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_set
16385 (const tng_trajectory_t tng_data,
16388 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16389 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
16391 return(tng_util_generic_write_interval_set(tng_data, i, 3,
16392 TNG_TRAJ_VELOCITIES,
16394 TNG_PARTICLE_BLOCK_DATA,
16395 TNG_TNG_COMPRESSION));
16398 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_interval_double_set
16399 (const tng_trajectory_t tng_data,
16402 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16403 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
16405 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
16406 TNG_TRAJ_VELOCITIES,
16408 TNG_PARTICLE_BLOCK_DATA,
16409 TNG_TNG_COMPRESSION));
16412 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write_frequency_set
16413 (const tng_trajectory_t tng_data,
16416 fprintf(stderr, "TNG library: Using obsolete function tng_util_vel_write_frequency_set(). "
16417 "See documentation. %s: %d", __FILE__, __LINE__);
16418 return(tng_util_vel_write_interval_set(tng_data, i));
16421 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_set
16422 (const tng_trajectory_t tng_data,
16425 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16426 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
16428 return(tng_util_generic_write_interval_set(tng_data, i, 3,
16431 TNG_PARTICLE_BLOCK_DATA,
16432 TNG_GZIP_COMPRESSION));
16435 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_interval_double_set
16436 (const tng_trajectory_t tng_data,
16439 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16440 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
16442 return(tng_util_generic_write_interval_double_set(tng_data, i, 3,
16445 TNG_PARTICLE_BLOCK_DATA,
16446 TNG_GZIP_COMPRESSION));
16449 tng_function_status DECLSPECDLLEXPORT tng_util_force_write_frequency_set
16450 (const tng_trajectory_t tng_data,
16453 fprintf(stderr, "TNG library: Using obsolete function tng_util_force_write_frequency_set(). "
16454 "See documentation. %s: %d", __FILE__, __LINE__);
16455 return(tng_util_force_write_interval_set(tng_data, i));
16458 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_set
16459 (const tng_trajectory_t tng_data,
16462 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16463 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
16465 return(tng_util_generic_write_interval_set(tng_data, i, 9,
16466 TNG_TRAJ_BOX_SHAPE,
16468 TNG_NON_PARTICLE_BLOCK_DATA,
16469 TNG_GZIP_COMPRESSION));
16472 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_interval_double_set
16473 (const tng_trajectory_t tng_data,
16476 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16477 TNG_ASSERT(i > 0, "TNG library: i (writing interval) must be >= 0.");
16479 return(tng_util_generic_write_interval_double_set(tng_data, i, 9,
16480 TNG_TRAJ_BOX_SHAPE,
16482 TNG_NON_PARTICLE_BLOCK_DATA,
16483 TNG_GZIP_COMPRESSION));
16486 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write_frequency_set
16487 (const tng_trajectory_t tng_data,
16490 fprintf(stderr, "TNG library: Using obsolete function tng_util_box_shape_write_frequency_set(). "
16491 "See documentation. %s: %d", __FILE__, __LINE__);
16492 return(tng_util_box_shape_write_interval_set(tng_data, i));
16495 tng_function_status DECLSPECDLLEXPORT tng_util_generic_write
16496 (const tng_trajectory_t tng_data,
16497 const int64_t frame_nr,
16498 const float *values,
16499 const int64_t n_values_per_frame,
16500 const int64_t block_id,
16501 const char *block_name,
16502 const char particle_dependency,
16503 const char compression)
16505 tng_trajectory_frame_set_t frame_set;
16507 int64_t n_particles = 0, n_frames, stride_length = 100, frame_pos;
16508 int64_t last_frame;
16509 int is_first_frame_flag = 0;
16510 char block_type_flag;
16511 tng_function_status stat;
16513 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16514 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
16516 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
16518 tng_num_particles_get(tng_data, &n_particles);
16519 TNG_ASSERT(n_particles > 0, "TNG library: There must be particles in the system to write particle data.");
16524 return(TNG_FAILURE);
16527 frame_set = &tng_data->current_trajectory_frame_set;
16531 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
16532 n_frames = stride_length = 1;
16536 block_type_flag = TNG_TRAJECTORY_BLOCK;
16538 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
16540 stat = tng_frame_set_new(tng_data, 0, tng_data->frame_set_n_frames);
16541 if(stat != TNG_SUCCESS)
16543 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
16548 last_frame = frame_set->first_frame +
16549 frame_set->n_frames - 1;
16550 if(frame_nr > last_frame)
16552 stat = tng_frame_set_write(tng_data, TNG_USE_HASH);
16553 if(stat != TNG_SUCCESS)
16555 fprintf(stderr, "TNG library: Cannot write frame set. %s: %d\n", __FILE__,
16559 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
16561 last_frame = frame_nr - 1;
16563 stat = tng_frame_set_new(tng_data, last_frame + 1,
16564 tng_data->frame_set_n_frames);
16565 if(stat != TNG_SUCCESS)
16567 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
16572 if(frame_set->n_unwritten_frames == 0)
16574 is_first_frame_flag = 1;
16576 frame_set->n_unwritten_frames = frame_nr -
16577 frame_set->first_frame + 1;
16579 n_frames = frame_set->n_frames;
16582 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
16584 if(tng_particle_data_find(tng_data, block_id, &data)
16587 stat = tng_particle_data_block_add(tng_data, block_id,
16591 n_frames, n_values_per_frame,
16595 if(stat != TNG_SUCCESS)
16597 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16598 __FILE__, __LINE__);
16601 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16603 data = &frame_set->tr_particle_data[frame_set->
16604 n_particle_data_blocks - 1];
16608 data = &tng_data->non_tr_particle_data[tng_data->
16609 n_particle_data_blocks - 1];
16611 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
16612 stride_length, n_particles,
16613 n_values_per_frame);
16614 if(stat != TNG_SUCCESS)
16616 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16617 __FILE__, __LINE__);
16621 /* FIXME: Here we must be able to handle modified n_particles as well. */
16622 else if(n_frames > data->n_frames)
16624 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
16625 data->stride_length, n_particles,
16626 n_values_per_frame);
16627 if(stat != TNG_SUCCESS)
16629 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16630 __FILE__, __LINE__);
16635 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16637 stride_length = data->stride_length;
16639 if(is_first_frame_flag || data->first_frame_with_data < frame_set->first_frame)
16641 data->first_frame_with_data = frame_nr;
16646 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
16649 memcpy((char *)data->values + sizeof(float) * frame_pos * n_particles *
16650 n_values_per_frame, values, sizeof(float) *
16651 n_particles * n_values_per_frame);
16655 memcpy(data->values, values, sizeof(float) * n_particles *
16656 n_values_per_frame);
16661 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
16663 stat = tng_data_block_add(tng_data, block_id, block_name,
16664 TNG_FLOAT_DATA, block_type_flag,
16665 n_frames, n_values_per_frame,
16666 stride_length, compression, 0);
16667 if(stat != TNG_SUCCESS)
16669 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16670 __FILE__, __LINE__);
16673 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16675 data = &frame_set->tr_data[frame_set->
16676 n_data_blocks - 1];
16680 data = &tng_data->non_tr_data[tng_data->
16681 n_data_blocks - 1];
16683 stat = tng_allocate_data_mem(tng_data, data, n_frames,
16684 stride_length, n_values_per_frame);
16685 if(stat != TNG_SUCCESS)
16687 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16688 __FILE__, __LINE__);
16692 /* FIXME: Here we must be able to handle modified n_particles as well. */
16693 else if(n_frames > data->n_frames)
16695 stat = tng_allocate_data_mem(tng_data, data, n_frames,
16696 data->stride_length, n_values_per_frame);
16697 if(stat != TNG_SUCCESS)
16699 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16700 __FILE__, __LINE__);
16705 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16707 stride_length = data->stride_length;
16709 if(is_first_frame_flag || data->first_frame_with_data < frame_set->first_frame)
16711 data->first_frame_with_data = frame_nr;
16716 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
16719 memcpy((char *)data->values + sizeof(float) * frame_pos *
16720 n_values_per_frame, values, sizeof(float) *
16721 n_values_per_frame);
16725 memcpy(data->values, values, sizeof(float) * n_values_per_frame);
16729 return(TNG_SUCCESS);
16732 tng_function_status DECLSPECDLLEXPORT tng_util_generic_double_write
16733 (const tng_trajectory_t tng_data,
16734 const int64_t frame_nr,
16735 const double *values,
16736 const int64_t n_values_per_frame,
16737 const int64_t block_id,
16738 const char *block_name,
16739 const char particle_dependency,
16740 const char compression)
16742 tng_trajectory_frame_set_t frame_set;
16744 int64_t n_particles = 0, n_frames, stride_length = 100, frame_pos;
16745 int64_t last_frame;
16746 int is_first_frame_flag = 0;
16747 char block_type_flag;
16748 tng_function_status stat;
16750 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16751 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
16753 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
16755 tng_num_particles_get(tng_data, &n_particles);
16756 TNG_ASSERT(n_particles > 0, "TNG library: There must be particles in the system to write particle data.");
16761 return(TNG_FAILURE);
16764 frame_set = &tng_data->current_trajectory_frame_set;
16768 block_type_flag = TNG_NON_TRAJECTORY_BLOCK;
16769 n_frames = stride_length = 1;
16773 block_type_flag = TNG_TRAJECTORY_BLOCK;
16775 if(!frame_set || tng_data->n_trajectory_frame_sets <= 0)
16777 stat = tng_frame_set_new(tng_data, 0, tng_data->frame_set_n_frames);
16778 if(stat != TNG_SUCCESS)
16780 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
16785 last_frame = frame_set->first_frame +
16786 frame_set->n_frames - 1;
16787 if(frame_nr > last_frame)
16789 stat = tng_frame_set_write(tng_data, TNG_USE_HASH);
16790 if(stat != TNG_SUCCESS)
16792 fprintf(stderr, "TNG library: Cannot write frame set. %s: %d\n", __FILE__,
16796 if(last_frame + tng_data->frame_set_n_frames < frame_nr)
16798 last_frame = frame_nr - 1;
16800 stat = tng_frame_set_new(tng_data, last_frame + 1,
16801 tng_data->frame_set_n_frames);
16802 if(stat != TNG_SUCCESS)
16804 fprintf(stderr, "TNG library: Cannot create frame set. %s: %d\n", __FILE__,
16809 if(frame_set->n_unwritten_frames == 0)
16811 is_first_frame_flag = 1;
16813 frame_set->n_unwritten_frames = frame_nr -
16814 frame_set->first_frame + 1;
16816 n_frames = frame_set->n_frames;
16820 if(particle_dependency == TNG_PARTICLE_BLOCK_DATA)
16822 if(tng_particle_data_find(tng_data, block_id, &data)
16825 stat = tng_particle_data_block_add(tng_data, block_id,
16829 n_frames, n_values_per_frame,
16833 if(stat != TNG_SUCCESS)
16835 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16836 __FILE__, __LINE__);
16839 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16841 data = &frame_set->tr_particle_data[frame_set->
16842 n_particle_data_blocks - 1];
16846 data = &tng_data->non_tr_particle_data[tng_data->
16847 n_particle_data_blocks - 1];
16849 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
16850 stride_length, n_particles,
16851 n_values_per_frame);
16852 if(stat != TNG_SUCCESS)
16854 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16855 __FILE__, __LINE__);
16859 /* FIXME: Here we must be able to handle modified n_particles as well. */
16860 else if(n_frames > data->n_frames)
16862 stat = tng_allocate_particle_data_mem(tng_data, data, n_frames,
16863 data->stride_length, n_particles,
16864 n_values_per_frame);
16865 if(stat != TNG_SUCCESS)
16867 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16868 __FILE__, __LINE__);
16873 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16875 stride_length = data->stride_length;
16877 if(is_first_frame_flag || data->first_frame_with_data < frame_set->first_frame)
16879 data->first_frame_with_data = frame_nr;
16884 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
16887 memcpy((char *)data->values + sizeof(double) * frame_pos * n_particles *
16888 n_values_per_frame, values, sizeof(double) *
16889 n_particles * n_values_per_frame);
16893 memcpy(data->values, values, sizeof(double) * n_particles *
16894 n_values_per_frame);
16899 if(tng_data_find(tng_data, block_id, &data) != TNG_SUCCESS)
16901 stat = tng_data_block_add(tng_data, block_id, block_name,
16902 TNG_DOUBLE_DATA, block_type_flag,
16903 n_frames, n_values_per_frame,
16904 stride_length, compression, 0);
16905 if(stat != TNG_SUCCESS)
16907 fprintf(stderr, "TNG library: Error %s adding data block. %s: %d\n", block_name,
16908 __FILE__, __LINE__);
16911 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16913 data = &frame_set->tr_data[frame_set->
16914 n_data_blocks - 1];
16918 data = &tng_data->non_tr_data[tng_data->
16919 n_data_blocks - 1];
16921 stat = tng_allocate_data_mem(tng_data, data, n_frames,
16922 stride_length, n_values_per_frame);
16923 if(stat != TNG_SUCCESS)
16925 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16926 __FILE__, __LINE__);
16930 /* FIXME: Here we must be able to handle modified n_particles as well. */
16931 else if(n_frames > data->n_frames)
16933 stat = tng_allocate_data_mem(tng_data, data, n_frames,
16934 data->stride_length, n_values_per_frame);
16935 if(stat != TNG_SUCCESS)
16937 fprintf(stderr, "TNG library: Error allocating particle data memory. %s: %d\n",
16938 __FILE__, __LINE__);
16943 if(block_type_flag == TNG_TRAJECTORY_BLOCK)
16945 stride_length = data->stride_length;
16947 if(is_first_frame_flag || data->first_frame_with_data < frame_set->first_frame)
16949 data->first_frame_with_data = frame_nr;
16954 frame_pos = (frame_nr - frame_set->first_frame) / stride_length;
16957 memcpy((char *)data->values + sizeof(double) * frame_pos *
16958 n_values_per_frame, values, sizeof(double) *
16959 n_values_per_frame);
16963 memcpy(data->values, values, sizeof(double) * n_values_per_frame);
16967 return(TNG_SUCCESS);
16970 tng_function_status DECLSPECDLLEXPORT tng_util_pos_write
16971 (const tng_trajectory_t tng_data,
16972 const int64_t frame_nr,
16973 const float *positions)
16975 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16976 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
16978 return(tng_util_generic_write(tng_data, frame_nr, positions, 3,
16979 TNG_TRAJ_POSITIONS, "POSITIONS",
16980 TNG_PARTICLE_BLOCK_DATA,
16981 TNG_TNG_COMPRESSION));
16984 tng_function_status DECLSPECDLLEXPORT tng_util_pos_double_write
16985 (const tng_trajectory_t tng_data,
16986 const int64_t frame_nr,
16987 const double *positions)
16989 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
16990 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
16992 return(tng_util_generic_double_write(tng_data, frame_nr, positions, 3,
16993 TNG_TRAJ_POSITIONS, "POSITIONS",
16994 TNG_PARTICLE_BLOCK_DATA,
16995 TNG_TNG_COMPRESSION));
16998 tng_function_status DECLSPECDLLEXPORT tng_util_vel_write
16999 (const tng_trajectory_t tng_data,
17000 const int64_t frame_nr,
17001 const float *velocities)
17003 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17004 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
17006 return(tng_util_generic_write(tng_data, frame_nr, velocities, 3,
17007 TNG_TRAJ_VELOCITIES, "VELOCITIES",
17008 TNG_PARTICLE_BLOCK_DATA,
17009 TNG_TNG_COMPRESSION));
17012 tng_function_status DECLSPECDLLEXPORT tng_util_vel_double_write
17013 (const tng_trajectory_t tng_data,
17014 const int64_t frame_nr,
17015 const double *velocities)
17017 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17018 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
17020 return(tng_util_generic_double_write(tng_data, frame_nr, velocities, 3,
17021 TNG_TRAJ_VELOCITIES, "VELOCITIES",
17022 TNG_PARTICLE_BLOCK_DATA,
17023 TNG_TNG_COMPRESSION));
17026 tng_function_status DECLSPECDLLEXPORT tng_util_force_write
17027 (const tng_trajectory_t tng_data,
17028 const int64_t frame_nr,
17029 const float *forces)
17031 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17032 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17034 return(tng_util_generic_write(tng_data, frame_nr, forces, 3,
17035 TNG_TRAJ_FORCES, "FORCES",
17036 TNG_PARTICLE_BLOCK_DATA,
17037 TNG_GZIP_COMPRESSION));
17040 tng_function_status DECLSPECDLLEXPORT tng_util_force_double_write
17041 (const tng_trajectory_t tng_data,
17042 const int64_t frame_nr,
17043 const double *forces)
17045 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17046 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17048 return(tng_util_generic_double_write(tng_data, frame_nr, forces, 3,
17049 TNG_TRAJ_FORCES, "FORCES",
17050 TNG_PARTICLE_BLOCK_DATA,
17051 TNG_GZIP_COMPRESSION));
17054 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_write
17055 (const tng_trajectory_t tng_data,
17056 const int64_t frame_nr,
17057 const float *box_shape)
17059 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17060 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17062 return(tng_util_generic_write(tng_data, frame_nr, box_shape, 9,
17063 TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
17064 TNG_NON_PARTICLE_BLOCK_DATA,
17065 TNG_GZIP_COMPRESSION));
17068 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_double_write
17069 (const tng_trajectory_t tng_data,
17070 const int64_t frame_nr,
17071 const double *box_shape)
17073 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17074 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17076 return(tng_util_generic_double_write(tng_data, frame_nr, box_shape, 9,
17077 TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
17078 TNG_NON_PARTICLE_BLOCK_DATA,
17079 TNG_GZIP_COMPRESSION));
17082 tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_write
17083 (const tng_trajectory_t tng_data,
17084 const int64_t frame_nr,
17086 const float *values,
17087 const int64_t n_values_per_frame,
17088 const int64_t block_id,
17089 const char *block_name,
17090 const char particle_dependency,
17091 const char compression)
17093 tng_trajectory_frame_set_t frame_set;
17094 tng_function_status stat;
17096 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17097 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17098 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17099 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
17101 stat = tng_util_generic_write(tng_data, frame_nr, values, n_values_per_frame,
17102 block_id, block_name,
17103 particle_dependency,
17106 if(stat != TNG_SUCCESS)
17111 frame_set = &tng_data->current_trajectory_frame_set;
17113 /* first_frame_time is -1 when it is not yet set. */
17114 if(frame_set->first_frame_time < -0.1)
17116 if(frame_nr > frame_set->first_frame)
17118 stat = tng_frame_set_first_frame_time_set(tng_data,
17121 frame_set->first_frame) *
17122 tng_data->time_per_frame);
17126 stat = tng_frame_set_first_frame_time_set(tng_data, time);
17132 tng_function_status DECLSPECDLLEXPORT tng_util_generic_with_time_double_write
17133 (const tng_trajectory_t tng_data,
17134 const int64_t frame_nr,
17136 const double *values,
17137 const int64_t n_values_per_frame,
17138 const int64_t block_id,
17139 const char *block_name,
17140 const char particle_dependency,
17141 const char compression)
17143 tng_trajectory_frame_set_t frame_set;
17144 tng_function_status stat;
17146 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17147 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17148 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17149 TNG_ASSERT(values, "TNG library: values must not be a NULL pointer");
17151 stat = tng_util_generic_double_write(tng_data, frame_nr, values, n_values_per_frame,
17152 block_id, block_name,
17153 particle_dependency,
17156 if(stat != TNG_SUCCESS)
17161 frame_set = &tng_data->current_trajectory_frame_set;
17163 /* first_frame_time is -1 when it is not yet set. */
17164 if(frame_set->first_frame_time < -0.1)
17166 if(frame_nr > frame_set->first_frame)
17168 stat = tng_frame_set_first_frame_time_set(tng_data,
17171 frame_set->first_frame) *
17172 tng_data->time_per_frame);
17176 stat = tng_frame_set_first_frame_time_set(tng_data, time);
17182 tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_write
17183 (const tng_trajectory_t tng_data,
17184 const int64_t frame_nr,
17186 const float *positions)
17188 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17189 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17190 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17191 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
17193 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, positions,
17194 3, TNG_TRAJ_POSITIONS, "POSITIONS",
17195 TNG_PARTICLE_BLOCK_DATA,
17196 TNG_TNG_COMPRESSION));
17199 tng_function_status DECLSPECDLLEXPORT tng_util_pos_with_time_double_write
17200 (const tng_trajectory_t tng_data,
17201 const int64_t frame_nr,
17203 const double *positions)
17205 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17206 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17207 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17208 TNG_ASSERT(positions, "TNG library: positions must not be a NULL pointer");
17210 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
17212 TNG_TRAJ_POSITIONS,
17214 TNG_PARTICLE_BLOCK_DATA,
17215 TNG_TNG_COMPRESSION));
17218 tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_write
17219 (const tng_trajectory_t tng_data,
17220 const int64_t frame_nr,
17222 const float *velocities)
17224 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17225 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17226 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17227 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
17229 return(tng_util_generic_with_time_write(tng_data, frame_nr, time,
17231 TNG_TRAJ_VELOCITIES,
17233 TNG_PARTICLE_BLOCK_DATA,
17234 TNG_TNG_COMPRESSION));
17237 tng_function_status DECLSPECDLLEXPORT tng_util_vel_with_time_double_write
17238 (const tng_trajectory_t tng_data,
17239 const int64_t frame_nr,
17241 const double *velocities)
17243 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17244 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17245 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17246 TNG_ASSERT(velocities, "TNG library: velocities must not be a NULL pointer");
17248 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
17250 TNG_TRAJ_VELOCITIES,
17252 TNG_PARTICLE_BLOCK_DATA,
17253 TNG_TNG_COMPRESSION));
17256 tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_write
17257 (const tng_trajectory_t tng_data,
17258 const int64_t frame_nr,
17260 const float *forces)
17262 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17263 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17264 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17265 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17267 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, forces,
17268 3, TNG_TRAJ_FORCES, "FORCES",
17269 TNG_PARTICLE_BLOCK_DATA,
17270 TNG_GZIP_COMPRESSION));
17273 tng_function_status DECLSPECDLLEXPORT tng_util_force_with_time_double_write
17274 (const tng_trajectory_t tng_data,
17275 const int64_t frame_nr,
17277 const double *forces)
17279 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17280 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17281 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17282 TNG_ASSERT(forces, "TNG library: forces must not be a NULL pointer");
17284 return(tng_util_generic_with_time_double_write(tng_data, frame_nr, time,
17286 TNG_TRAJ_FORCES, "FORCES",
17287 TNG_PARTICLE_BLOCK_DATA,
17288 TNG_GZIP_COMPRESSION));
17291 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_write
17292 (const tng_trajectory_t tng_data,
17293 const int64_t frame_nr,
17295 const float *box_shape)
17297 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17298 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17299 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17300 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17302 return(tng_util_generic_with_time_write(tng_data, frame_nr, time, box_shape,
17303 9, TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
17304 TNG_NON_PARTICLE_BLOCK_DATA,
17305 TNG_GZIP_COMPRESSION));
17308 tng_function_status DECLSPECDLLEXPORT tng_util_box_shape_with_time_double_write
17309 (const tng_trajectory_t tng_data,
17310 const int64_t frame_nr,
17312 const double *box_shape)
17314 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17315 TNG_ASSERT(frame_nr >= 0, "TNG library: frame_nr must be >= 0.");
17316 TNG_ASSERT(time >= 0, "TNG library: time must be >= 0.");
17317 TNG_ASSERT(box_shape, "TNG library: box_shape must not be a NULL pointer");
17319 return(tng_util_generic_with_time_double_write(tng_data, frame_nr,
17320 time, box_shape, 9,
17321 TNG_TRAJ_BOX_SHAPE,
17323 TNG_NON_PARTICLE_BLOCK_DATA,
17324 TNG_GZIP_COMPRESSION));
17327 tng_function_status DECLSPECDLLEXPORT tng_util_frame_current_compression_get
17328 (const tng_trajectory_t tng_data,
17329 const int64_t block_id,
17333 tng_trajectory_frame_set_t frame_set;
17334 tng_data_t data = 0;
17335 tng_function_status stat;
17337 int block_type = -1;
17339 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17340 TNG_ASSERT(codec_id, "TNG library: The pointer to the returned codec id must not be a NULL pointer.");
17341 TNG_ASSERT(factor, "TNG library: The pointer to the returned multiplication factor must not be a NULL pointer.");
17343 frame_set = &tng_data->current_trajectory_frame_set;
17345 stat = tng_particle_data_find(tng_data, block_id, &data);
17346 if(stat == TNG_SUCCESS)
17348 block_type = TNG_PARTICLE_BLOCK_DATA;
17352 stat = tng_data_find(tng_data, block_id, &data);
17353 if(stat == TNG_SUCCESS)
17355 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
17359 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17360 if(stat != TNG_SUCCESS)
17364 stat = tng_particle_data_find(tng_data, block_id, &data);
17365 if(stat == TNG_SUCCESS)
17367 block_type = TNG_PARTICLE_BLOCK_DATA;
17371 stat = tng_data_find(tng_data, block_id, &data);
17372 if(stat == TNG_SUCCESS)
17374 block_type = TNG_NON_PARTICLE_BLOCK_DATA;
17383 if(block_type == TNG_PARTICLE_BLOCK_DATA)
17385 if(data->last_retrieved_frame < 0)
17387 i = data->first_frame_with_data;
17391 i = data->last_retrieved_frame;
17394 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
17396 if(data->last_retrieved_frame < 0)
17398 i = data->first_frame_with_data;
17402 i = data->last_retrieved_frame;
17407 return(TNG_FAILURE);
17409 if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
17411 stat = tng_frame_set_of_frame_find(tng_data, i);
17412 if(stat != TNG_SUCCESS)
17416 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data, TNG_USE_HASH, block_id);
17417 if(stat != TNG_SUCCESS)
17419 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
17420 __FILE__, __LINE__);
17424 if(block_type == TNG_PARTICLE_BLOCK_DATA)
17426 *codec_id = data->codec_id;
17427 *factor = data->compression_multiplier;
17429 else if(block_type == TNG_NON_PARTICLE_BLOCK_DATA)
17431 *codec_id = data->codec_id;
17432 *factor = data->compression_multiplier;
17434 return(TNG_SUCCESS);
17437 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_next_frame_present_data_blocks_find
17438 (const tng_trajectory_t tng_data,
17439 int64_t current_frame,
17440 const int64_t n_requested_data_block_ids,
17441 const int64_t *requested_data_block_ids,
17442 int64_t *next_frame,
17443 int64_t *n_data_blocks_in_next_frame,
17444 int64_t **data_block_ids_in_next_frame)
17446 tng_trajectory_frame_set_t frame_set;
17447 tng_function_status stat;
17449 tng_gen_block_t block;
17450 int64_t i, j, block_id, *temp;
17451 int64_t data_frame, frame_diff, min_diff;
17452 int64_t size, frame_set_file_pos;
17453 int found, read_all = 0;
17456 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17457 TNG_ASSERT(next_frame, "TNG library: The pointer to the next frame must not be NULL.");
17458 TNG_ASSERT(n_data_blocks_in_next_frame, "TNG library: The pointer to n_data_blocks_in_next_frame must not be NULL.");
17459 TNG_ASSERT(data_block_ids_in_next_frame, "TNG library: The pointer to the list of data block IDs must not be NULL.");
17461 if(n_requested_data_block_ids)
17463 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.");
17464 size = sizeof(int64_t) * n_requested_data_block_ids;
17465 temp = realloc(*data_block_ids_in_next_frame, size);
17468 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
17469 sizeof(int64_t) * (*n_data_blocks_in_next_frame),
17470 __FILE__, __LINE__);
17471 free(*data_block_ids_in_next_frame);
17472 *data_block_ids_in_next_frame = 0;
17473 return(TNG_CRITICAL);
17475 *data_block_ids_in_next_frame = temp;
17478 frame_set = &tng_data->current_trajectory_frame_set;
17480 current_frame += 1;
17482 if(current_frame < frame_set->first_frame ||
17483 current_frame >= frame_set->first_frame + frame_set->n_frames)
17485 frame_set_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
17486 stat = tng_frame_set_of_frame_find(tng_data, current_frame);
17487 if(stat != TNG_SUCCESS)
17489 /* If the frame set search found the frame set after the starting
17490 * frame set there is a gap in the frame sets. So, even if the frame
17491 * was not found the next frame with data is still in the found
17493 if(stat == TNG_CRITICAL || frame_set->prev_frame_set_file_pos !=
17494 frame_set_file_pos)
17498 current_frame = frame_set->first_frame;
17502 /* Check for data blocks only if they have not already been found. */
17503 if(frame_set->n_particle_data_blocks <= 0 && frame_set->n_data_blocks <= 0)
17505 file_pos = ftello(tng_data->input_file);
17506 if(file_pos < tng_data->input_file_len)
17508 tng_block_init(&block);
17509 stat = tng_block_header_read(tng_data, block);
17510 while(file_pos < tng_data->input_file_len &&
17511 stat != TNG_CRITICAL &&
17512 block->id != TNG_TRAJECTORY_FRAME_SET &&
17515 stat = tng_block_read_next(tng_data, block,
17517 if(stat != TNG_CRITICAL)
17519 file_pos = ftello(tng_data->input_file);
17520 if(file_pos < tng_data->input_file_len)
17522 stat = tng_block_header_read(tng_data, block);
17526 tng_block_destroy(&block);
17527 if(stat == TNG_CRITICAL)
17529 fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n",
17530 file_pos, __FILE__, __LINE__);
17539 *n_data_blocks_in_next_frame = 0;
17541 for(i = 0; i < frame_set->n_particle_data_blocks; i++)
17543 data = &frame_set->tr_particle_data[i];
17544 block_id = data->block_id;
17546 if(n_requested_data_block_ids > 0)
17549 for(j = 0; j < n_requested_data_block_ids; j++)
17551 if(block_id == requested_data_block_ids[j])
17563 if(!read_all && (data->last_retrieved_frame < frame_set->first_frame ||
17564 data->last_retrieved_frame >=
17565 frame_set->first_frame + frame_set->n_frames))
17567 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data,
17568 TNG_USE_HASH, block_id);
17569 if(stat == TNG_CRITICAL)
17571 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
17572 __FILE__, __LINE__);
17575 if(stat == TNG_FAILURE)
17580 if(frame_set->first_frame != current_frame &&
17581 data->last_retrieved_frame >= 0)
17583 data_frame = data->last_retrieved_frame + data->stride_length;
17587 data_frame = data->first_frame_with_data;
17589 frame_diff = data_frame - current_frame;
17594 if(min_diff == -1 || frame_diff <= min_diff)
17596 if(frame_diff < min_diff)
17598 *n_data_blocks_in_next_frame = 1;
17602 *n_data_blocks_in_next_frame += 1;
17604 if(n_requested_data_block_ids <= 0)
17606 size = sizeof(int64_t) * (*n_data_blocks_in_next_frame);
17607 temp = realloc(*data_block_ids_in_next_frame, size);
17610 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
17611 sizeof(int64_t) * (*n_data_blocks_in_next_frame),
17612 __FILE__, __LINE__);
17613 free(*data_block_ids_in_next_frame);
17614 *data_block_ids_in_next_frame = 0;
17615 return(TNG_CRITICAL);
17617 *data_block_ids_in_next_frame = temp;
17621 TNG_ASSERT(*n_data_blocks_in_next_frame <= n_requested_data_block_ids, "TNG library: Array of data block IDs out of bounds");
17623 (*data_block_ids_in_next_frame)[(*n_data_blocks_in_next_frame) - 1] = block_id;
17625 min_diff = frame_diff;
17628 for(i = 0; i < frame_set->n_data_blocks; i++)
17630 data = &frame_set->tr_data[i];
17631 block_id = data->block_id;
17633 if(n_requested_data_block_ids > 0)
17636 for(j = 0; j < n_requested_data_block_ids; j++)
17638 if(block_id == requested_data_block_ids[j])
17650 if(!read_all && (data->last_retrieved_frame < frame_set->first_frame ||
17651 data->last_retrieved_frame >=
17652 frame_set->first_frame + frame_set->n_frames))
17654 stat = tng_frame_set_read_current_only_data_from_block_id(tng_data,
17655 TNG_USE_HASH, block_id);
17656 if(stat == TNG_CRITICAL)
17658 fprintf(stderr, "TNG library: Cannot read data block of frame set. %s: %d\n",
17659 __FILE__, __LINE__);
17662 if(stat == TNG_FAILURE)
17667 if(frame_set->first_frame != current_frame &&
17668 data->last_retrieved_frame >= 0)
17670 data_frame = data->last_retrieved_frame + data->stride_length;
17674 data_frame = data->first_frame_with_data;
17676 frame_diff = data_frame - current_frame;
17681 if(min_diff == -1 || frame_diff <= min_diff)
17683 if(frame_diff < min_diff)
17685 *n_data_blocks_in_next_frame = 1;
17689 *n_data_blocks_in_next_frame += 1;
17691 if(n_requested_data_block_ids <= 0)
17693 size = sizeof(int64_t) * (*n_data_blocks_in_next_frame);
17694 temp = realloc(*data_block_ids_in_next_frame, size);
17697 fprintf(stderr, "TNG library: Cannot allocate memory (%"PRIu64" bytes). %s: %d\n",
17698 sizeof(int64_t) * (*n_data_blocks_in_next_frame),
17699 __FILE__, __LINE__);
17700 free(*data_block_ids_in_next_frame);
17701 *data_block_ids_in_next_frame = 0;
17702 return(TNG_CRITICAL);
17704 *data_block_ids_in_next_frame = temp;
17708 TNG_ASSERT(*n_data_blocks_in_next_frame <= n_requested_data_block_ids, "TNG library: Array of data block IDs out of bounds");
17710 (*data_block_ids_in_next_frame)[(*n_data_blocks_in_next_frame) - 1] = block_id;
17712 min_diff = frame_diff;
17717 return(TNG_FAILURE);
17719 *next_frame = current_frame + min_diff;
17721 return(TNG_SUCCESS);
17725 tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_all_data_block_types_get
17726 (const tng_trajectory_t tng_data,
17727 int64_t *n_data_blocks,
17728 int64_t **data_block_ids,
17729 char ***data_block_names,
17730 int64_t **stride_lengths,
17731 int64_t **n_values_per_frame,
17732 char **block_types,
17733 char **dependencies,
17734 char **compressions)
17736 tng_gen_block_t block;
17737 int64_t orig_file_pos, file_pos;
17739 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17740 TNG_ASSERT(n_data_blocks, "TNG library: The pointer to n_data_blocks must not be NULL.");
17741 TNG_ASSERT(data_block_ids, "TNG library: The pointer to the list of data block IDs must not be NULL.");
17742 TNG_ASSERT(data_block_names, "TNG library: The pointer to the list of data block names must not be NULL.");
17743 TNG_ASSERT(stride_lengths, "TNG library: The pointer to the list of stride lengths must not be NULL.");
17745 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
17747 return(TNG_CRITICAL);
17750 orig_file_pos = ftello(tng_data->input_file);
17752 fseeko(tng_data->input_file, 0, SEEK_SET);
17755 *n_data_blocks = 0;
17757 tng_block_init(&block);
17759 while(file_pos < tng_data->input_file_len &&
17760 tng_block_header_read(tng_data, block) != TNG_CRITICAL)
17762 if(block->id > TNG_TRAJECTORY_FRAME_SET)
17766 file_pos += (block->block_contents_size + block->header_contents_size);
17767 fseeko(tng_data->input_file, block->block_contents_size, SEEK_CUR);
17770 fseeko(tng_data->input_file, orig_file_pos, SEEK_SET);
17772 return(TNG_SUCCESS);
17775 tng_function_status DECLSPECDLLEXPORT tng_util_prepare_append_after_frame
17776 (const tng_trajectory_t tng_data,
17777 const int64_t prev_frame)
17779 tng_function_status stat;
17780 FILE *temp = tng_data->input_file;
17782 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17783 TNG_ASSERT(prev_frame >= 0, "TNG library: The previous frame must not be negative.");
17785 tng_data->input_file = tng_data->output_file;
17787 stat = tng_frame_set_of_frame_find(tng_data, prev_frame);
17788 if(stat != TNG_SUCCESS)
17793 tng_data->current_trajectory_frame_set_output_file_pos =
17794 tng_data->current_trajectory_frame_set_input_file_pos;
17796 tng_data->input_file = temp;
17798 return(TNG_SUCCESS);
17801 tng_function_status DECLSPECDLLEXPORT tng_util_num_frames_with_data_of_block_id_get
17802 (const tng_trajectory_t tng_data,
17803 const int64_t block_id,
17806 int64_t curr_file_pos, first_frame_set_file_pos, curr_n_frames;
17807 tng_function_status stat;
17809 TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup.");
17813 if(tng_input_file_init(tng_data) != TNG_SUCCESS)
17815 return(TNG_CRITICAL);
17818 first_frame_set_file_pos = tng_data->first_trajectory_frame_set_input_file_pos;
17819 curr_file_pos = ftello(tng_data->input_file);
17820 fseeko(tng_data->input_file, first_frame_set_file_pos, SEEK_SET);
17822 stat = tng_frame_set_n_frames_of_data_block_get(tng_data, block_id, &curr_n_frames);
17824 while(stat == TNG_SUCCESS && tng_data->current_trajectory_frame_set.next_frame_set_file_pos != -1)
17826 *n_frames += curr_n_frames;
17827 fseeko(tng_data->input_file,
17828 tng_data->current_trajectory_frame_set.next_frame_set_file_pos,
17830 stat = tng_frame_set_n_frames_of_data_block_get(tng_data, block_id, &curr_n_frames);
17832 if(stat == TNG_SUCCESS)
17834 *n_frames += curr_n_frames;
17836 fseeko(tng_data->input_file, curr_file_pos, SEEK_SET);
17837 if(stat == TNG_CRITICAL)
17839 return(TNG_CRITICAL);
17841 return(TNG_SUCCESS);