- Nov 22, 2024
-
-
Didier WECKMANN authored
Rename `enum sight::data::image::pixel_format` to `sight::data::image::pixel_format_t` to avoid ambiguities with ` sight::data::image::pixel_format()` It also makes VS Code happier.
-
- Nov 19, 2024
-
-
Flavien BRIDAULT authored
-
- Nov 15, 2024
-
-
Flavien BRIDAULT authored
- move the PACS configuration in a module so that it can be used in other apps - the image is now an input and not an inout in the `module::ui::qt::image::window_level` service - adjust the range of `module::ui::qt::image::window_level` depending on the image range - remove the static label in the color widget of `module::ui::qt::settings` - `sight::data::helper::medical_image::get_min_max()` now returns its values as a pair to avoid a wrong initialisation in the caller code. - fix mixed rendering with binary transparent objects
-
- Add unit tests - Fix wrong return type in matrix4::position() and matrix4::orientation()
-
- Nov 14, 2024
-
-
Flavien BRIDAULT authored
Auto-connections were correctly configured and honored only by the config manager, thus required, a XML configuration. This was annoying for unit-tests and overall, that was not the proper place to do it. This is now done directly in the service code itself.
-
Flavien BRIDAULT authored
The naming of the unit test target is used to deduce the name of the module to be tested, which is then auto loaded. This mechanism was broken for sub-repositories. It is now fixed, and if the naming of the target is not correct, an error is reported to the user.
-
- Nov 13, 2024
-
-
Didier WECKMANN authored
Fixed: - illegal access to deleted objects - memory leaks - visibility badly applied - desynchronization of ogre object and fiducials - race conditions on signal / slot handling - too many wrappers and clumsy code
-
- Nov 07, 2024
-
-
Marc SCHWEITZER authored
Allow to call slot="start" or slot="stop" within an update_sequence. This ensure to call start/stop in a specific order. Example: ```xml <sequence uid="toggle_dev_mode"> <service uid="video_grabber" slot="stop"/> <service uid="dummy_grabber" slot="start"/> </sequence> <sequence uid="toggle_prod_mode"> <service uid="dummy_grabber" slot="stop"/> <service uid="video_grabber" slot="start"/> </sequence> ```
-
- Nov 03, 2024
-
-
Flavien BRIDAULT authored
- use malloc policy for images shared with ITK - send signals when action property is set - init text of combo box when using keys/values - do not autoconnect map properties to avoid spurious warnings when the service is used in an update loop - model_series adaptor was accidentally unregistered while updating - jobs::observer should not allow to report done work when finished
-
- Oct 30, 2024
-
-
Marc SCHWEITZER authored
when the service is "disabled" the configured key-sequence is ignored. The classic behavior is kept with the "enabled" mode.
-
- Oct 21, 2024
-
-
Didier WECKMANN authored
- Only use fiducial data from source image_series, not intermediate point_list - Remove opencv "drawing" and only rely on ogre - Simplify / remove unneeded code
-
- Oct 18, 2024
-
-
Luis MENDOZA authored
- Tab widgets are now transparent and hand the noctura theme correctly - Toolboxes have now a configurable expand icon color - unify hove/pressed effects on buttons
-
- Oct 17, 2024
-
-
This uses the native `timeBeginPeriod` function to force timer precision on Windows to be around the millisecond, otherwise, we can't go down below 1/64s.
-
- Oct 16, 2024
-
-
Flavien BRIDAULT authored
Chaining service updates in Sight live applications has always been tough. To circumvent all related issues with event-based chaining, we introduce an explicit approach allowing to specify update sequence and execute them all at once. It used to be possible to specify which services to update **once** once after start: ```xml <update uid="service1"> <update uid="service2"> <update uid="service3"> ``` This section is now modified and allows specifying these single-shot updates, but also the ability to define an update loop: ```xml <start uid="update_loop"> <update> <service uid="service1"/> <service uid="service2"/> <sequence uid="update_loop" loop="true"> <service uid="service3" /> <service uid="service4" /> </sequence> </update> ``` In this example, `service1` and `service2` are updated once after start, while `service3` and `service4` are continuously updated. The sequence `update_loop`is identified with an uid, so it can be started and stopped like any other service. Doing this, the update sequence is not dependent on the updated() signal. This is much more robust because this means any other, maybe unwanted updates triggered from somewhere else do not affect the sequence. This new syntax also allows chaining update sequences between XML configurations. As the manner of UI registries and `wid`, it is possible to reserve a slot for another update sequence defined in another configuration: ```xml <!-- Main loop --> <update> <sequence uid="update_loop" loop="true"> <service uid="service1" /> <updater uid="sub_updater" /> <service uid="service2" slot="modify" /> </sequence> </update> <!-- In a sub-configuration, passing the parameter "sub_updater" --> <update> <sequence parent="${sub_updater}"> <service uid="..." /> <service uid="..." /> </sequence> </update> ``` Note that here the `uid` of the sequence is omitted because no interaction is required inside this XML. The sequence is played automatically by the root updater after `service1::update()` and `service2::modify` slots. It is also possible to execute services in parallel. Mixing sequences and parallel are allowed with the syntax: ```xml <!-- Main loop --> <update> <sequence uid="update_loop" loop="true"> <service uid="service1" /> <parallel> <service uid="service2" /> <updater uid="sub_updater" /> <sequence> <service uid="service3" /> <service uid="service4" /> </sequence> <parallel/> <service uid="service5" /> </sequence> </update> <!-- In a sub-configuration, passing the parameter "sub_updater" --> <update> <sequence parent="${sub_updater}"> <service uid="..." /> <service uid="..." /> </sequence> </update> ``` In this example, `service1`updates first, then `service2`, the whole update sequence in the sub-configuration, and the sequence of `service3` and `service4` are executed in parallel. When they are executed, whether or not they are on different workers, `service5` is executed. The solution proposed above could be sufficient. However, managing `sight::viz::scene3d::render` could become tedious. Correctly using auto-connections, and maintaining the list of all adaptors in the update can be tedious and error-prone. Developers usually expect that a single call to the \`update()\` of the renderer manages the update of the adaptors properly, which is the case in auto mode when we do interactive rendering, but not in manual mode, in "live" applications. To solve this, we introduced a generic update interface `sight::core::updater` that will be inherited by the adaptors. This interface allows to defer the update of the adaptor required by their data. In manual mode, the adaptors just flag which part of their update process they should process. When the update is actually called, they will really perform it and unflag it. The render only requires to interrogate the adaptors before rendering to know if they need to update or not. To sum up, updating a generic scene in manual mode is now much easier and not error-prone regarding synchronisation. For example, if we imagine an application reading a video, extracting a feature and then display it in overlay over the video, the update loop could look like: ```xml <!-- Main loop --> <update> <sequence uid="main_loop" loop="true"> <service uid="video_grabber_srv" /> <service uid="extract_position_srv" /> <service uid="compute_position_srv" /> <service uid="render_srv" /> <!-- Update all adaptors, only those required if their data have changed --> </sequence> </update> ```
-
- Oct 15, 2024
-
-
Luis MENDOZA authored
- new camera parser that uses either sight resources path or an absolute file system path to default the camera to video file playing - update ex_video_recorder to use that parser feat(test): unitary test of camera parser
-
Didier WECKMANN authored
Roughly 10X speedup, measured with a big xml "configuration": - Debug build: - Before: 419.446 ms - After: 42.868 ms. - Release build: - Before: 35.768 ms - After: 4.716 ms
-
- Oct 14, 2024
-
-
Several fixes were brought: 1. A Qt error was fixed when closing the chessboard window. This did not improve the situation but was needed anyway, 2. The board square size was unintentionally set to 0.5 instead of 20 in !1138. This was, I think, the cause of the increase in the occurrence of the test failure, yielding values of around 180 or > 400. 3. Sometimes, we still get cx=341 instead of 352. This might come from the input detection that slightly differs. We don't understand the reason, but since this is rather an issue of the test than an implementation error, we chose to increase the tolerance of the test to accept this value of 341.
-
- Oct 11, 2024
-
-
-
Removing a group from `fiducial::point` no longer resets the current group to the default value, unless we're removing the current group. This also fixes an annoying XML warning.
-
- Oct 01, 2024
-
-
- Sep 30, 2024
-
-
#### No separate `sight_log` process anymore Everything is self-contained in the current `sightrun` process. The logging is, by default in debug builds, in full synchronous mode, from end-to-end. In case of a crash, it is guaranteed to have everything sent to log to be readable back (with a possible, but improbable, loss of 16 bytes when encryption is used). However, since the full synchronous mode is blocking, there may be a significant performance hit, since the compression and the encryption are done in the same thread as the caller, which in turn, also block all other threads, if logging occurs during the writing. To overcome this, in release builds, I propose to use an asynchronous mode, which do the "real" writing in a separated thread (managed by boost::log). This is a bit less safe, but since RAII model is used, there is still a very good chance that everything is well written, even in case of fatal exception. And, to be honest, it was a bit the same level of safety with the previous separated process, as the stream communication between process was also buffered. >
⚠ zstd < 1.5 (for example, on ubuntu 22.04..) have a "flaw" that makes the block size to be "big", meaning we may loose a big chunk of data if interrupted (a block must be complete to be uncompressed). zstd >= 1.5 (like the one used in our VCPKG) ensure the "flush" command to complete a block, which is done on each log lines, ensuring we only "loose" the last lines. This explain why the associated unit test `crash_test` is somewhat "tolerant". > Of course we can discuss if we should be in asynchronous mode in release or always use the "safe" synchronous. #### No CMake `SIGHT_ENABLE_ENCRYPTED_LOG` anymore Log encryption is now enabled by `sightrun --encrypted-log` switch. However, the log will not be "really" encrypted, but only compressed, until a global password has been set, using, for example, the preferences dialog. See the `ex_acitivies` sample, especially the `CMakeLists.txt`, to learn how to ask a password from the user. As soon as the password is set or change and if the application has been started with `--encrypted-log` switch, a new log file "xxx.1.log.aes" will be created and the previous log "xxx.0.log.aes" will be relocated, recompressed and re-encrypted with the new password. #### No CMake `SIGHT_DEFAULT_PASSWORD` variable anymore SIGHT_DEFAULT_PASSWORD was used to pass a compile time "default" password, used to encrypt things without having to force the user to enter one. Even if the password was not stored in clear text in the binary, this was rather weak and confusing, so it has been removed. Consequently, there is no `password_keeper::has_default_password()` and `password_keeper::get_default_password()` have also been removed. #### spy_logger is no more only "global" You can now instantiate your own private logger using `spy_logger::make();`. The unit test `multiple_logger_test()` demonstrates the usage. You will not be able to use the sight macros (SIGHT_ERROR, ...) as they indeed use the global logger, but direct call to `spy_logger::error()`, `spy_logger::fatal()`, etc. The global spy_logger is now a global reference stored in `sight::core::log::g_logger`, available as soon as the `core` module is loaded. #### Archive_extractor now handles encrypted log A special extraction function `spy_logger::extract();` has been added, which is used in `sight::module::io::zip::extract` to manage our new log format. Since the logs are no more a plain zip file, and because we want to recover truncate files, third party tools like 7zip are no more able to decompress them. If there is only compression (empty password) used, then it should be readable by any tool that reads zstd compressed file. #### Unit tests improvement The logging tests have been rewritten and improved ...and fixed, as there were some race condition, left test materials, hang process, etc.. Almost 100% test coverage on the related files. #### General fixes and improvements - Now, we test the return values and error codes from OpenSSL encryption functions → yes, some "features" that were based on "bugs" were fixed. - Proper OpenSSL initialization, and error management - Split the spy_logger implementation in `libs\__\core\log\detail\spy_logger_impl.hxx` and `libs\__\core\log\detail\stream_sink.hxx`. The stream_sink.hxx implements a `boost/iostreams/stream` which can be used elsewhere to have an ostream with transparent zstd compression, with aes256 encryption. - Clang-tidy fixes on old files - proper guard for `#include <boost/iostreams/stream.hpp>` which generate a fatal warning on Windows - Some cleanup
-
- Sep 27, 2024
-
-
-
Flavien BRIDAULT authored
This allows Sight to build with DCMTK version >= 3.6.8. by removing the support of two deprecated DICOM transfer syntaxes: * `UID_RFC2557MIMEEncapsulationTransferSyntax` * `UID_XMLEncodingTransferSyntax`
-
Flavien BRIDAULT authored
The version of the application is now well generated in the `profile.xml` of each app. Thus, it is now safe to use: ```cpp const auto profile = sight::core::runtime::get_current_profile(); const software_version = profile->version(); ``` It is even recommended to use this instead of passing the APP_VERSION through the XML or by a C++ compiler macro.
-
- Sep 20, 2024
-
-
-
Flavien BRIDAULT authored
-
- Sep 19, 2024
-
-
* Enable admin requests in unit tests: useful for unit tests requiring specific devices * Add additional dicom fields to be used * Forward missing fields from image_series to the associated fiducials
-
- Sep 17, 2024
-
-
Flavien BRIDAULT authored
Services rely a lot on simple data such as algorithm parameters, using simple types such as numbers and strings. Manipulating these parameters always ends up requiring the same features: - initialization of the parameter in the XML configuration of the service, - dynamic update of the parameter through a slot, - persistence of the parameter during the runtime. To simplify the coding of these three features, we introduced the concept of service *properties*. For a complete description of this new exciting development feature, pleaser refer to https://sight.pages.ircad.fr/sight-doc/SAD/src/Properties.html
-
- Sep 02, 2024
-
-
Didier WECKMANN authored
Allow optimized debug
-
- Aug 20, 2024
-
-
Didier WECKMANN authored
Add functions to DICOM API in `series` to manage DICOM `SourceImageSequence` which allows making `DERIVED` image (ex: a reconstructed volume derived from US frames sequence): - `[s|g]et_image_type()`: Sets/gets the `ImageType` of the series. The `ImageType` is a `\` separated string with the following format: `[Pixel Data Characteristics:ORIGINAL|DERIVED], [Patient Examination Characteristics:PRIMARY|SECONDARY], [modality specific:xxx|yyy|...], [zzz], ...`: See ImageType (0008,0008) DICOM tag. The exact definition is modality dependent, but the two first elements ([ORIGINAL|DERIVED] and [PRIMARY|SECONDARY]) are fixed. This allows to set a reconstructed volume as `DERIVED` and the original frame sequence as `ORIGINAL` and, optionally, other attributes. - `[s|g]et_referenced_sop_class_uid()` and `[s|g]et_referenced_sop_instance_uid()`: Sets/gets the referenced series. Both are required for a valid DICOM. - Preliminary work to simplify the fiducials DICOM API: code factorization (more can be done like introducing high level fiducials functions in `has_fiducials`)
-
- Jul 23, 2024
-
-
- The usage of point_list has been removed. We now only use a vector of ogre elements and the associated ruler id. With this id, we can find the desired ruler in fiducials and modify or remove it. - The dashed line is now working correctly. - Rulers should always be displayed according to the current slice. This includes rulers that have spheres on 2 different slices. If the current slice is in between, we will also display these rulers. The part of the line that is behind the current slice is displayed as a dashed line. This allows us to manage the ruler display the same for both 2D and 3D contexts. - Now we are registering the color of the ruler. By doing this, the indications on the slider will match the color of the ruler. We are also handling cases where rulers are created without color and outside of the adaptor. We register the assigned color by the adaptor during updating(). - When we enter in interaction mode (activate_tool), we draw rulers with larger spheres. This makes it easier to grab the sphere when using a touch screen. - All deprecated services associated to old distance signals have been deleted.
-
- Jul 16, 2024
-
-
Didier WECKMANN authored
-
- Jul 13, 2024
-
-
Flavien BRIDAULT authored
-
Flavien BRIDAULT authored
-
- Jul 11, 2024
-
-
Flavien BRIDAULT authored
We can now pass objects as parameters without declaring them locally with `src=ref`: ```xml <extension implements="sight::app::extension::config"> <id>sight::module::config</id> <parameters> <object uid="image" type="sight::data::image" optional="true" /> <object uid="model" type="sight::data::model_series" /> </parameters> <config> ... </config> </extension> ```
-
- Jul 10, 2024
-
-
Alexandre ANCEL authored
-
- Jul 09, 2024
-
-
- Jul 08, 2024
-
-
Didier WECKMANN authored
* Recreate image position patient in all cases, even if unneeded
-
Alexandre ANCEL authored
-
- Jul 04, 2024
-
-
- Improve quality of life when using matrix4
-