diff options
author | Magnus Lundborg <lundborg.magnus@gmail.com> | 2012-12-20 10:37:54 (GMT) |
---|---|---|
committer | Magnus Lundborg <lundborg.magnus@gmail.com> | 2012-12-20 10:37:54 (GMT) |
commit | 6637159ac02cf4abe439a7ef1ee10f7e7b1a6054 (patch) | |
tree | a3357c994a2b17b08a852247f73e996fb6e330d0 | |
parent | 808823a7aaeb3e7a1f1610eef677d9ae81906ebc (diff) |
Functions for writing one frame of data at a time. N.B. Still not tested
-rw-r--r-- | src/lib/tng_io.c | 330 | ||||
-rw-r--r-- | src/lib/tng_io.h | 42 |
2 files changed, 335 insertions, 37 deletions
diff --git a/src/lib/tng_io.c b/src/lib/tng_io.c index 99dfa5e..6b67d35 100644 --- a/src/lib/tng_io.c +++ b/src/lib/tng_io.c @@ -191,7 +191,7 @@ struct tng_particle_data { char *block_name; /** The type of data stored. */ tng_data_type datatype; - /** The first frame number of the first data value */ + /** The frame number of the first data value */ int64_t first_frame_with_data; /** The number of frames in this frame set */ int64_t n_frames; @@ -7995,7 +7995,292 @@ tng_function_status tng_particle_data_block_add(tng_trajectory_t tng_data, return(TNG_SUCCESS); } - + +tng_function_status tng_frame_data_write(tng_trajectory_t tng_data, + const int64_t frame_nr, + const int64_t block_id, + const void *values, + const tng_hash_mode hash_mode) +{ + int64_t i, block_index, header_pos, file_pos; + int64_t output_file_len, n_values_per_frame, size, contents_size; + int64_t header_size; + tng_gen_block_t block; + tng_trajectory_frame_set_t frame_set; + FILE *temp = tng_data->input_file; + tng_non_particle_data_t data; + tng_function_status stat; + + if(tng_output_file_init(tng_data, FALSE) != TNG_SUCCESS) + { + printf("Cannot initialise destination file. %s: %d\n", + __FILE__, __LINE__); + return(TNG_CRITICAL); + } + + tng_data->input_file = tng_data->output_file; + + stat = tng_frame_set_find(tng_data, frame_nr); + + if(stat != TNG_SUCCESS) + { + return(stat); + } + + tng_data->input_file = temp; + + file_pos = ftell(tng_data->output_file); + + fseek(tng_data->output_file, 0, SEEK_END); + output_file_len = ftell(tng_data->output_file); + fseek(tng_data->output_file, file_pos, SEEK_SET); + + + tng_block_init(&block); + /* Read all block headers until next frame set block */ + stat = tng_block_header_read(tng_data, block); + while(file_pos < output_file_len && + stat != TNG_CRITICAL && + block->id != block_id && + block->id != TNG_TRAJECTORY_FRAME_SET) + { + fseek(tng_data->output_file, block->block_contents_size, SEEK_CUR); + file_pos = ftell(tng_data->output_file); + if(file_pos < output_file_len) + { + stat = tng_block_header_read(tng_data, block); + } + } + if(stat == TNG_CRITICAL) + { + tng_block_destroy(&block); + return(stat); + } + + contents_size = block->block_contents_size; + header_size = block->header_contents_size; + + header_pos = file_pos; + frame_set = &tng_data->current_trajectory_frame_set; + + block_index = -1; + /* See if there is already a data block of this ID. + * Start checking the last read frame set */ + for(i = frame_set->n_data_blocks; i--;) + { + data = &frame_set->tr_data[i]; + if(data->block_id == block_id) + { + block_index = i; + break; + } + } + + if(block_index < 0) + { + tng_block_destroy(&block); + return(TNG_FAILURE); + } + + switch(data->datatype) + { + case(TNG_INT_DATA): + size = sizeof(int64_t); + break; + case(TNG_FLOAT_DATA): + size = sizeof(float); + break; + case(TNG_DOUBLE_DATA): + size = sizeof(double); + break; + default: + printf("Cannot calculate writing locations. %s: %d.\n", __FILE__, + __LINE__); + tng_block_destroy(&block); + return(TNG_FAILURE); + } + + size *= data->n_values_per_frame; + + n_values_per_frame = data->n_values_per_frame; + + file_pos = (frame_nr - data->first_frame_with_data) * n_values_per_frame / + data->stride_length; + + if(file_pos > contents_size) + { + printf("Attempting to write outside the block. %s: %d\n", __FILE__, + __LINE__); + tng_block_destroy(&block); + return(TNG_FAILURE); + } + + fseek(tng_data->output_file, file_pos, SEEK_CUR); + + fwrite(values, n_values_per_frame, size, tng_data->output_file); + + /* If the last frame has been written update the hash */ + if(hash_mode == TNG_USE_HASH && (frame_nr + data->stride_length - + data->first_frame_with_data) / data->stride_length >= + frame_set->n_frames) + { + tng_md5_hash_update(tng_data, block, header_pos, header_pos + + header_size); + } + + tng_block_destroy(&block); + + return(TNG_SUCCESS); +} + +tng_function_status tng_frame_particle_data_write(tng_trajectory_t tng_data, + const int64_t frame_nr, + const int64_t block_id, + const void **values, + const tng_hash_mode hash_mode) +{ + int64_t i, block_index, header_pos, file_pos, n_particles; + int64_t output_file_len, n_values_per_frame, size, contents_size; + int64_t header_size; + tng_gen_block_t block; + tng_trajectory_frame_set_t frame_set; + FILE *temp = tng_data->input_file; + tng_particle_data_t data; + tng_function_status stat; + + if(tng_output_file_init(tng_data, FALSE) != TNG_SUCCESS) + { + printf("Cannot initialise destination file. %s: %d\n", + __FILE__, __LINE__); + return(TNG_CRITICAL); + } + + tng_data->input_file = tng_data->output_file; + + stat = tng_frame_set_find(tng_data, frame_nr); + + if(stat != TNG_SUCCESS) + { + return(stat); + } + + frame_set = &tng_data->current_trajectory_frame_set; + + tng_data->input_file = temp; + + file_pos = ftell(tng_data->output_file); + + fseek(tng_data->output_file, 0, SEEK_END); + output_file_len = ftell(tng_data->output_file); + fseek(tng_data->output_file, file_pos, SEEK_SET); + + tng_block_init(&block); + /* Read all block headers until next frame set block */ + stat = tng_block_header_read(tng_data, block); + while(file_pos < output_file_len && + stat != TNG_CRITICAL && + block->id != block_id && + block->id != TNG_TRAJECTORY_FRAME_SET) + { + fseek(tng_data->output_file, block->block_contents_size, SEEK_CUR); + file_pos = ftell(tng_data->output_file); + if(file_pos < output_file_len) + { + stat = tng_block_header_read(tng_data, block); + } + } + if(stat == TNG_CRITICAL) + { + tng_block_destroy(&block); + return(stat); + } + + contents_size = block->block_contents_size; + header_size = block->header_contents_size; + + header_pos = file_pos; + frame_set = &tng_data->current_trajectory_frame_set; + + block_index = -1; + /* See if there is already a data block of this ID. + * Start checking the last read frame set */ + for(i = frame_set->n_data_blocks; i--;) + { + data = &frame_set->tr_particle_data[i]; + if(data->block_id == block_id) + { + block_index = i; + break; + } + } + + if(block_index < 0) + { + tng_block_destroy(&block); + return(TNG_FAILURE); + } + + switch(data->datatype) + { + case(TNG_INT_DATA): + size = sizeof(int64_t); + break; + case(TNG_FLOAT_DATA): + size = sizeof(float); + break; + case(TNG_DOUBLE_DATA): + size = sizeof(double); + break; + default: + printf("Cannot calculate writing locations. %s: %d.\n", __FILE__, + __LINE__); + tng_block_destroy(&block); + return(TNG_FAILURE); + } + + size *= data->n_values_per_frame; + + if(tng_data->var_num_atoms_flag) + { + n_particles = frame_set->n_particles; + } + else + { + n_particles = tng_data->n_particles; + } + n_values_per_frame = data->n_values_per_frame; + + file_pos = (frame_nr - data->first_frame_with_data) / data->stride_length; + file_pos *= n_particles * n_values_per_frame; + + if(file_pos > contents_size) + { + printf("Attempting to write outside the block. %s: %d\n", __FILE__, + __LINE__); + tng_block_destroy(&block); + return(TNG_FAILURE); + } + + fseek(tng_data->output_file, file_pos, SEEK_CUR); + + for(i = 0; i < n_particles; i++) + { + fwrite(values[i], n_values_per_frame, size, tng_data->output_file); + } + + /* If the last frame has been written update the hash */ + if(hash_mode == TNG_USE_HASH && (frame_nr + data->stride_length - + data->first_frame_with_data) / data->stride_length >= + frame_set->n_frames) + { + tng_md5_hash_update(tng_data, block, header_pos, header_pos + + header_size); + } + + tng_block_destroy(&block); + return(TNG_SUCCESS); +} + tng_function_status tng_data_values_free(union data_values **values, const int64_t n_frames, const int64_t n_values_per_frame, @@ -8245,23 +8530,9 @@ tng_function_status tng_data_interval_get(tng_trajectory_t tng_data, if(block_index < 0) { - /* If the data block was not found in the frame set - * look for it in the non-trajectory data (in tng_data). */ - for(i = tng_data->n_data_blocks; i-- ;) - { - data = &tng_data->non_tr_data[i]; - if(data->block_id == block_id) - { - block_index = i; - break; - } - } - if(block_index < 0) - { - printf("Could not find non-particle data block with id %"PRId64". %s: %d\n", - block_id, __FILE__, __LINE__); - return(TNG_FAILURE); - } + printf("Could not find non-particle data block with id %"PRId64". %s: %d\n", + block_id, __FILE__, __LINE__); + return(TNG_FAILURE); } n_frames = end_frame_nr - start_frame_nr + 1; @@ -8601,24 +8872,9 @@ tng_function_status tng_particle_data_interval_get(tng_trajectory_t tng_data, if(block_index < 0) { - /* If the data block was not found in the frame set - * look for it in the non-trajectory data (in tng_data). */ - for(i = tng_data->n_particle_data_blocks; i-- ;) - { - data = &tng_data->non_tr_particle_data[i]; - if(data->block_id == block_id) - { - block_index = i; - block_type_flag = TNG_NON_TRAJECTORY_BLOCK; - break; - } - } - if(block_index < 0) - { - printf("Could not find particle data block with id %"PRId64". %s: %d\n", - block_id, __FILE__, __LINE__); - return(TNG_FAILURE); - } + printf("Could not find particle data block with id %"PRId64". %s: %d\n", + block_id, __FILE__, __LINE__); + return(TNG_FAILURE); } if(block_type_flag == TNG_TRAJECTORY_BLOCK && diff --git a/src/lib/tng_io.h b/src/lib/tng_io.h index d17ce85..9999f7c 100644 --- a/src/lib/tng_io.h +++ b/src/lib/tng_io.h @@ -814,6 +814,48 @@ tng_function_status tng_particle_data_block_add(tng_trajectory_t tng_data, const int64_t codec_id, void *new_data); +/** + * @brief Write data of one trajectory frame to the output_file of tng_data. + * @param tng_data is a trajectory data container. tng_data->output_file_path + * specifies which file to write to. If the file (output_file) is not open it + * will be opened. + * @param frame_nr is the index number of the frame to write. + * @param block_id is the ID of the data block to write the data to. + * @param data is an array of data to write. The length of the array should + * equal n_values_per_frame. + * @param hash_mode is an option to decide whether to use the md5 hash or not. + * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be + * compared to the md5 hash of the read contents to ensure valid data. + * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if a minor error + * has occurred or TNG_CRITICAL (2) if a major error has occured. + */ +tng_function_status tng_frame_data_write(tng_trajectory_t tng_data, + const int64_t frame_nr, + const int64_t block_id, + const void *data, + const tng_hash_mode hash_mode); + +/** + * @brief Write particle data of one trajectory frame to the output_file of + * tng_data. + * @param tng_data is a trajectory data container. tng_data->output_file_path + * specifies which file to write to. If the file (output_file) is not open it + * will be opened. + * @param frame_nr is the index number of the frame to write. + * @param block_id is the ID of the data block to write the data to. + * @param data is a 2D-array of data to write. The length of the array should + * equal n_particles * n_values_per_frame. + * @param hash_mode is an option to decide whether to use the md5 hash or not. + * If hash_mode == TNG_USE_HASH the written md5 hash in the file will be + * compared to the md5 hash of the read contents to ensure valid data. + * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if a minor error + * has occurred or TNG_CRITICAL (2) if a major error has occured. + */ +tng_function_status tng_frame_particle_data_write(tng_trajectory_t tng_data, + const int64_t frame_nr, + const int64_t block_id, + const void **data, + const tng_hash_mode hash_mode); /** * @brief Free data is an array of values (2D). |