dectris / documentation

A repository of documentation for DECTRIS products
5 stars 4 forks source link

API changes to stream2 CBOR parsing #1

Closed GDYendell closed 1 year ago

GDYendell commented 2 years ago

This ticket is for the outcomes of our meeting today.

There a couple of other things that aren't such a problem to maintain in a fork but would be nice to resolve if it doesn't cause you any problems.

Build Error
``` [build] cd /workspaces/eiger-detector/vscode_build/third_party/dectris/stream_v2/examples/third_party/compression && /bin/g++ -Dcompression_EXPORTS -I/workspaces/eiger-detector/vscode_build/include -I/workspaces/eiger-detector/data/include -I/workspaces/eiger-detector/data/common/include -I/workspaces/eiger-detector/data/third_party/dectris/stream_v2/examples/third_party/compression -I/workspaces/eiger-detector/data/third_party/dectris/stream_v2/examples/third_party/compression/third_party -g -fPIC -std=gnu++11 -o CMakeFiles/compression.dir/src/compression.c.o -c /workspaces/eiger-detector/data/third_party/dectris/stream_v2/examples/third_party/compression/src/compression.c [build] /workspaces/eiger-detector/data/third_party/dectris/stream_v2/examples/third_party/compression/src/compression.c:42:8: error: ‘_Bool’ does not name a type [build] static _Bool parse_header(const char** const src, [build] ^ [build] /workspaces/eiger-detector/data/third_party/dectris/stream_v2/examples/third_party/compression/src/compression.c:56:8: error: ‘_Bool’ does not name a type [build] static _Bool decompress_bslz4_block(char** const dst, [build] ^ [build] /workspaces/eiger-detector/data/third_party/dectris/stream_v2/examples/third_party/compression/src/compression.c: In function ‘size_t decompress_buffer_bslz4_hdf5(char*, size_t, const char*, size_t, size_t)’: [build] /workspaces/eiger-detector/data/third_party/dectris/stream_v2/examples/third_party/compression/src/compression.c:94:61: error: ‘parse_header’ was not declared in this scope [build] if (!parse_header(&src, src_end, &orig_size, &block_size)) [build] ^ [build] /workspaces/eiger-detector/data/third_party/dectris/stream_v2/examples/third_party/compression/src/compression.c:110:38: error: invalid conversion from ‘void*’ to ‘char*’ [-fpermissive] [build] char* tmp_buf = malloc(block_size); [build] ^ [build] /workspaces/eiger-detector/data/third_party/dectris/stream_v2/examples/third_party/compression/src/compression.c:122:46: error: ‘decompress_bslz4_block’ was not declared in this scope [build] elem_size)) [build] ^ [build] /workspaces/eiger-detector/data/third_party/dectris/stream_v2/examples/third_party/compression/src/compression.c:130:63: error: ‘decompress_bslz4_block’ was not declared in this scope [build] last_block_size, elem_size)) [build] ^ [build] /workspaces/eiger-detector/data/third_party/dectris/stream_v2/examples/third_party/compression/src/compression.c: At global scope: [build] /workspaces/eiger-detector/data/third_party/dectris/stream_v2/examples/third_party/compression/src/compression.c:147:8: error: ‘_Bool’ does not name a type [build] static _Bool decompress_lz4_block(char** const dst, [build] ^ [build] /workspaces/eiger-detector/data/third_party/dectris/stream_v2/examples/third_party/compression/src/compression.c: In function ‘size_t decompress_buffer_lz4_hdf5(char*, size_t, const char*, size_t)’: [build] /workspaces/eiger-detector/data/third_party/dectris/stream_v2/examples/third_party/compression/src/compression.c:178:61: error: ‘parse_header’ was not declared in this scope [build] if (!parse_header(&src, src_end, &orig_size, &block_size)) [build] ^ [build] /workspaces/eiger-detector/data/third_party/dectris/stream_v2/examples/third_party/compression/src/compression.c:197:66: error: ‘decompress_lz4_block’ was not declared in this scope [build] if (!decompress_lz4_block(&dst, &src, src_end, block_size)) [build] ^ [build] /workspaces/eiger-detector/data/third_party/dectris/stream_v2/examples/third_party/compression/src/compression.c:201:71: error: ‘decompress_lz4_block’ was not declared in this scope [build] if (!decompress_lz4_block(&dst, &src, src_end, last_block_size)) [build] ^ [build] gmake[2]: *** [third_party/dectris/stream_v2/examples/third_party/compression/CMakeFiles/compression.dir/src/compression.c.o] Error 1 [build] gmake[1]: *** [third_party/dectris/stream_v2/examples/third_party/compression/CMakeFiles/compression.dir/all] Error 2 ```

I think it should just use bool so that it works in C++? https://stackoverflow.com/a/3530061/6694972

kalcutter commented 2 years ago

@GDYendell A few comments to your issues.

Could you maybe provide a CMakeLists.txt that expresses how you want to build your software?

GDYendell commented 2 years ago

OK I have it building without changing it to SHARED and including the compression lib now. See here.

I can build my dynamic library against a stream2 lib that uses STATIC as long as I add the -fPIC compiler flag for stream2 and tinycbor. See here. Would this be an acceptable change?

Adding set(CMAKE_C_STANDARD 99) to my top level CMakeLists allows it to compile compression - for some reason the same command here does not work, I guess because it is not the top level. I would rather not have to do this as it could be restrictive to the rest of the project. It also works if I add the compile flag directly in the relevant places. See here and here. Is there a better way to do this? I feel like it should be possible to define it in the stream2 CMakeLists and have that apply to everything in the tree, but it does not seem to.

Maybe set_property(TARGET tgt PROPERTY CXX_STANDARD 11) would work? https://cmake.org/cmake/help/latest/prop_tgt/CXX_STANDARD.html

sdebionne commented 1 year ago

I second the need for compressed data access for two reasons:

Would you accept a PR that implements this?

kalcutter commented 1 year ago

@sdebionne First, let me start off by saying that this code was primarily intended only as an example. At the same time, it was written with considerable care, such that it could also be used verbatim as an unofficial library. Would you see it as a benefit if this was more of an official library? Or is the status quo also acceptable assuming it includes maintenance?

In general, we are open to PRs. However, in this case we are also considering adding a C++ example that includes the feature you request. Would C++ also be acceptable, or do you think C is more appropriate? How urgent do you need this feature?

sdebionne commented 1 year ago

Hi @kalcutter, I understand that this code is primarily an exemple, but if it can be turned into a officially supported library (with the help of the community) that would be even better for us.

C works for me, since C++17 is our target platform we are all for C++. But I guess it might make binding to other languages mode complicated. With C++ in mind, I would like to have more control on the memory management, either using memory_resource if memory has to be managed by the library, or using OutputRange if the memory is provided by the client (probably better).

How urgent do you need this feature?

Actually I was about to start coding it... Using the already compressed buffer chunk to write HDF5 file is a recurrent feature request on our side. We would still decompress the data to compute Region-Of-Interest statistics and other "const" operations.

What would be your timeframe for this C++ example?

kalcutter commented 1 year ago

Hi @sdebionne, Thanks for the input. So to solve the immediate issue, I think its best to update the current C example. I will look into this today and put the changes on a branch for feedback sometime this week.

kalcutter commented 1 year ago

Hi @sdebionne @GDYendell, I have pushed a new branch stream2-no-decompress that removes decompression from stream2.c. Please try to integrate these changes and give any feedback ASAP.

GDYendell commented 1 year ago

Thanks @kalcutter I will try too look at this soon.

Do you know if the frame capture data here is up to date / compatible with this latest stream.c logic?

kalcutter commented 1 year ago

@GDYendell That data is not compatible with the current examples. That is old incompatible data from the preview release.

kalcutter commented 1 year ago

Would it be helpful if I committed test data to this repository?

GDYendell commented 1 year ago

Would it be helpful if I committed test data to this repository?

Yeah that would be great!

kalcutter commented 1 year ago

I have pushed some test data to a new branch stream2-test_data. We may move it to another repository in the future since it's a bit large.

sdebionne commented 1 year ago

Thanks @kalcutter ! I had a quick look at the code and it sounds like it answers our needs perfectly. I'll give you more feedback once I have integrated it in our system.

GDYendell commented 1 year ago

Thanks @kalcutter! I think this works OK for me - even the user data :smile:.

I do still have to insert -fPIC to the stream2, cbor and bitshuffle CMakeLists to be able to compile it into a dynamic library (e.g.). Is there a way around this or will I have to maintain that in a fork?

A few comments / questions:

kalcutter commented 1 year ago

I will look into your -fPIC issue. Can you make a separate issue for that?

All documented fields are implemented and will be available on a running system. detector_serial_number and goniometer are documented and only missing from the test data. goniometer, specifically, is only present if goniometer parameters are configured, in my case they were not.

The other missing fields: images_per_trigger, number_of_triggers and roi_mode are currently not supported. We intentionally did not include every possible field from the SIMPLON API. Generally, we would like to avoid fields that are merely artifacts of the API and do not directly describe the data. However, additional fields may be added in the future if they make sense, pending feedback. Please open a separate issue for each unsupported field that you require explaining the use-case and we will consider it. As a workaround, you can always put any missing fields in user_data, however, the C example currently doesn't doesn't expose user_data. Please open an issue if you want to see user_data in the C API.

I included the threshold_2 and difference channels in the test data so you could know what to expect when they are enabled. Enabling these channels is optional. If they are not enabled, their data will not be present.

GDYendell commented 1 year ago

Added #3 for building shared libs.

... are currently not supported.

OK good to know. I will ask if we have a use case for those and take them out for now.

If they are not enabled, their data will not be present.

OK that's great. It is useful to have the test data with it included, as you say.

Also, I think it probably would be best to keep the test data separate from this repo as the size not ideal when cloning this repo as a submodule. Having it available and versioned against this library would be very useful. Although presumably it won't change much going forward.

kalcutter commented 1 year ago

Also, I think it probably would be best to keep the test data separate from this repo as the size not ideal when cloning this repo as a submodule. Having it available and versioned against this library would be very useful. Although presumably it won't change much going forward.

Yes I agree. I only put them here temporarily for convenience.

kalcutter commented 1 year ago

@sdebionne We would love your feedback too. :smiley:

sdebionne commented 1 year ago

I am on it 😁 !

sdebionne commented 1 year ago

Hi @kalcutter, sorry for the delay, I have just finished moving my code to your branch and I am happy with the changes! The only changes I would suggest are in the client code, so no big deal. Thank you again, I really appreciate your reactivity.

About the test data, I would also like to have in a different repo (this one would need to be cleaned with a tool like BFG Repo-Cleaner).

kalcutter commented 1 year ago

@sdebionne Great! Please give me your suggestions! What do you mean "client" code? example.c? client.py?

I have removed the test data branch. The data will no longer be fetched when checking out the repo. Why do you think additional cleaning is necessary?

sdebionne commented 1 year ago

By client code, I meant the example that consumes the "Stream2 C API".

I have removed the test data branch. The data will no longer be fetched when checking out the repo. Why do you think additional cleaning is necessary?

I would think that git removes not the commits but the branch ref only. Maybe they are orphan and cleanup after a while though.

kalcutter commented 1 year ago

By client code, I meant the example that consumes the "Stream2 C API".

@sdebionne Please send any suggestions. :-)

kalcutter commented 1 year ago

@sdebionne @GDYendell If the API is OK for both of you, I will apply the changes to the main branch. Any objections?

kalcutter commented 1 year ago

@sdebionne @GDYendell I have rebased these changes and applied them to main. Please reference the commit on main. I will delete the old branch next week.

kalcutter commented 1 year ago

@GDYendell Regarding stream2_parse_msg_header: I gave this some thought and I don't think it makes sense to implement in this repository. Is there any reason you can't just use tinycbor to parse the two fields that interest you (and stop early to avoid errors)?

GDYendell commented 1 year ago

@kalcutter I have actually re-implemented some things on my side to make it much easier to work with the full message, so I am happy to drop this request.

kalcutter commented 1 year ago

@GDYendell Great. Are there any points still open?

GDYendell commented 1 year ago

@kalcutter I don't think so. We will be rolling out the latest detector software across Eigers at DLS in the coming weeks so we will see how that goes, but it is working well with the simulator.

GDYendell commented 1 year ago

I included the threshold_2 and difference channels in the test data so you could know what to expect when they are enabled. Enabling these channels is optional. If they are not enabled, their data will not be present.

@kalcutter is there a config in the SIMPLON API to control which channels are sent?

kalcutter commented 1 year ago

@GDYendell you simply need to enable the thresholds/difference mode as described in the official documentation (search the document for "threshold/n/mode"): https://media.dectris.com/210607-DECTRIS-SIMPLON-API-Manual_EIGER2-chip-based_detectros.pdf

GDYendell commented 1 year ago

Ah perfect, I had not seen this latest manual - I will have a read through. Thanks!