Find frames with certain data blocks
First of all, thank you very much for maintaining a standalone library for the TNG format. This makes using the format in other projects much easier.
However, I believe there is an issue with the tng_util_trajectory_next_frame_present_data_blocks_find
function. Let's assume one has this file '1aki.tng' with 6 frames stored in the file. I now want to know the actual MD steps corresponding to the frames to further extract information like positions.
Consider the following example:
Minimal C example
#include <tng/tng_io.h>
#include <stdio.h>
int main() {
tng_trajectory_t handle_;
tng_util_trajectory_open("1aki.tng", 'r', &handle_);
int64_t current_frame = -1;
int64_t next_frame = 0;
int64_t unused = 0;
int64_t* buffer = NULL;
tng_function_status status = TNG_SUCCESS;
while (1) {
int64_t block_ids[] = {TNG_TRAJ_POSITIONS};
status = tng_util_trajectory_next_frame_present_data_blocks_find(
handle_, current_frame, 1, block_ids, &next_frame, &unused, &buffer
);
if (status == TNG_SUCCESS) {
current_frame = next_frame;
printf("%d\n", current_frame);
} else if (status == TNG_FAILURE) {
// We found the end of the file
printf("TNG_FAILURE\n");
break;
} else {
printf("TNG_CRITICAL\n");
}
}
free(buffer);
tng_util_trajectory_close(&handle_);
}
For convenience to build and run main.c
:
#!/bin/bash
if [ ! -d "tng" ]; then
git clone https://gitlab.com/gromacs/tng.git
fi
cd tng && mkdir -p build && cd build
echo "Building..."
cmake ..
make
echo -e "Done.\n--------------------"
cd ../..
gcc main.c -I./tng/include/ -L./tng/build/lib/ -ltng_io
LD_LIBRARY_PATH=./tng/build/lib/ ./a.out
Running this with latest master d71bb99c I get the following output:
0
TNG_FAILURE
So the first frame at MD step 0 is discovered but not the rest.
After looking at tng_io.c
I think that the update of data->last_retrieved_frame
is missing. My understanding is that this value is used to advance through the data but if it's never updated one cant get further than the first frame.
This seems to be fixed by updating the last retrieved frame when looping over frame_set->n_particle_data_blocks
(and frame_set->n_data_blocks
too I suppose):
diff --git a/src/lib/tng_io.c b/src/lib/tng_io.c
index eaedb79..bb83a32 100644
--- a/src/lib/tng_io.c
+++ b/src/lib/tng_io.c
@@ -16457,6 +16457,7 @@ tng_function_status DECLSPECDLLEXPORT
min_diff = frame_diff;
}
+ data->last_retrieved_frame = data_frame;
}
for (i = 0; i < frame_set->n_data_blocks; i++)
{
@@ -16541,6 +16542,7 @@ tng_function_status DECLSPECDLLEXPORT
min_diff = frame_diff;
}
+ data->last_retrieved_frame = data_frame;
}
if (min_diff < 0)
{
Using this patch (git apply <changes.patch>
) one gets the following correct output from the test program:
0
10
20
30
40
50
TNG_FAILURE
If it makes things easier for you and someone has the time to review the changes, I can open a PR and deal with the code details.