CamiTK Community Edition issueshttps://gricad-gitlab.univ-grenoble-alpes.fr/CamiTK/CamiTK/-/issues2023-10-29T13:49:12+01:00https://gricad-gitlab.univ-grenoble-alpes.fr/CamiTK/CamiTK/-/issues/169add dbus connection2023-10-29T13:49:12+01:00Emmanuel Promayonadd dbus connection## About you
CamiTK dev
## Product
CamiTK Core / Application
## Overview
Issue #168 was not detected during configure/make/test as it is not possible to set a test where an application that starts a user interaction loop would be ru...## About you
CamiTK dev
## Product
CamiTK Core / Application
## Overview
Issue #168 was not detected during configure/make/test as it is not possible to set a test where an application that starts a user interaction loop would be run and stopped automatically after a while. For example, in the case of `camitk-fancy` that would have allowed for a simple start and exit. In the presence of a bug similar to #168, the test would then have failed.
A possible way of offering extended testing for application would be to add the possibility for any CamiTK application to listen to dbus messages.
- it would then be possible to send message from outside the application (e.g. a shell, a test script or program...) such as "run action `Quit`".
- it would also add the **great** advantage of opening a whole lot of testing and automation. For instance by sending message analog to state in the action state machine (e.g. by sending XML/json message containing the action to apply and its parameter).
## Relevant logs and/or screenshots
### Adding dbus message support in CamiTK::Application
For instance by using:
```cpp
QDBusConnection::sessionBus().connect(QString(), QString(), "camitk.action", "apply", this, SLOT(applyActionFromDBus(QString)));
...
void Application::applyActionFromDBus(const QString &message) {
if(message=="...") {
...
}
}
```
### From the test application
```cpp
QProcess myProcess;
myProcess.start("camitk-fancy", "");
if (!myProcess.waitForStarted())
return false;
QDBusMessage msg = QDBusMessage::createSignal("/", "camitk.action", "apply");
message="Quit"
QDBusConnection::sessionBus().send(msg);
if (!myProcess.waitForFinished())
return false;
```
**Note**
DBus is supported on Linux desktops by default. A [windows port exists](https://www.freedesktop.org/wiki/Software/dbus/#download) but this need further checks.
### dbus not allowed by default
For security reason, the default behaviour should be _not_ to listen to DBus, and flag `--dbus` should be added to the arguments to enable the feature in the application.
### See also
[KDE doc for creating dbus interface](https://develop.kde.org/docs/features/d-bus/creating_dbus_interfaces/)
---https://gricad-gitlab.univ-grenoble-alpes.fr/CamiTK/CamiTK/-/issues/152MHA/MHD orientation convention combined with rotation/translation2023-07-28T14:58:20+02:00Manik BhattacharjeeMHA/MHD orientation convention combined with rotation/translation## About you
CamiTK developer
## Overview
This issue is a follow-up of issue #66
When loading and writing MHA/MHD files, geometrical transformations are applied in this order:
- transform to RAI convention
- rotation
- translation
Unf...## About you
CamiTK developer
## Overview
This issue is a follow-up of issue #66
When loading and writing MHA/MHD files, geometrical transformations are applied in this order:
- transform to RAI convention
- rotation
- translation
Unfortunately it means that we apply the rotation and translation specified in the header after changing the convention to RAI (CamiTK convention). But those rotation and translation were probably defined in the convention specified in the header file (e.g. RSA). In that case it means we apply the rotation and translation to the wrong axes.
## Steps to Reproduce
Need sample files in conventions other than RAI to be able to test this.
Finding out which software (3D Slicer ?) uses a different convention to compare how the transform is read/saved in another convention would be useful.
## Actual VS Expected Result
- The transform matrix loaded in a RSA file is saved in an RAI file with the exact same values, even though the axes are not the same
- Loading an image in RSA convention with a translation of (0,1,2) should be saved in RAI with a different translation (1 for axis S-I, 2 for axis A-P)
## Interpretation & Possible fixes
MHA/MHD MetaImage file format specs are not very precise on this issue. But I believe that rotation and translation are defined according to the specified orientation convention, and not an arbitrary one (RAI for CamiTK).
[A thread from 3D slicer](https://discourse.slicer.org/t/bug-when-reading-mha-file-with-anatomicalorientation/7038/7) about how ITK does not use this information correctly and how VTK should manage the issue:
It refers to a [merge request to solve it in VTK that was not merged](https://gitlab.kitware.com/vtk/vtk/-/merge_requests/5656) because it breaks a lot of tests, but the discussion is interesting. [In ITK, it was decided to ignore cases where ITK reader fails](https://github.com/InsightSoftwareConsortium/ITK/issues/1017) because they focus on other image formats.
After reading this we should take our own decision in how to interact with this format.
I suggest:
- read the orientation
- consider the image is encoded in that orientation
- consider the matrix is expressed in the specified orientation and use it accordingly
For the write part, multiple choices:
- we save in any orientation we want (e.g. RAI, current way), specify it in the header, and write the matrix accordingly. The most logical way !
- we save in LPS (used by ITK and other software for MetaImage format), increasing compatibility with other software. We specify the orientation and the matrix in LPS. This would be ok but, there is a problem: it seems that most software just ignore orientation when they read, but use the matrix in their own orientation without adapting it (e.g. 3D Slicer loads the image as LPS, converts to RAS, and considers the matrix as being in RAS...)
## CamiTK Version
CamiTK 5.1.dev.develop.c3d59664
---
**please do not remove anything below this line**Manik BhattacharjeeManik Bhattacharjeehttps://gricad-gitlab.univ-grenoble-alpes.fr/CamiTK/CamiTK/-/issues/137Unix file separator "/" is used explicitely in some file handling code of the...2023-05-31T12:15:49+02:00Manik BhattacharjeeUnix file separator "/" is used explicitely in some file handling code of the SDK instead of a portable value such as QDir::separator()## About you
CamiTK developper
## Overview
While reading code in libraries/core/viewer/RendererWidget.cpp I found a line of code which assumes that file path are using the unix separator '/'.
```c++
QString filePrefix = QFileInfo(filen...## About you
CamiTK developper
## Overview
While reading code in libraries/core/viewer/RendererWidget.cpp I found a line of code which assumes that file path are using the unix separator '/'.
```c++
QString filePrefix = QFileInfo(filename).absolutePath() + "/" + QFileInfo(filename).baseName();
```
The same type of separator use is found at multiple places in the SDK:
```bash
$ grep -n --include "*.cpp" --include "*.h" '"/"' * -R
```
```c++
actions/application/file/SaveAsAction.cpp:178: QFileDialog saveFileDialog(nullptr, tr("Save File As..."), QFileInfo(compfileName).dir().canonicalPath() + "/" + suggestedName, test);
actions/application/file/SaveAsAction.cpp:183: QString filename = QFileDialog::getSaveFileName(nullptr, tr("Save File As..."), QFileInfo(compfileName).dir().canonicalPath() + "/" + suggestedName, test);
applications/actionstatemachine/SaveActionState.cpp:107: (*outIt)->setFileName(saveDirName + "/" + compName + ".mha");
applications/actionstatemachine/SaveActionState.cpp:109: (*compIt)->setFileName(compDir + "/" + compName + compExt);
applications/actionstatemachine/SaveActionState.cpp:114: (*logStream) << compDir + "/" + compName + compExt << "' type='" << compType << "'/>" << Qt::endl;
applications/testcomponents/main.cpp:190: comp->setFileName(outputDirectory + "/" + inputComponent.fileName());
applications/wizard/GeneratingCEPState.cpp:105: QString outputFileName = dir.absolutePath() + "/" + cepDirName + "/libraries/" + libraryName + "/" + shortFileName;
components/vtkimage/VtkImageComponentExtension.cpp:251: QString filePattern = fileInfo.absoluteDir().absolutePath() + "/" + fileInfo.baseName();
components/off/OffExtension.cpp:71: QString baseFilename = QFileInfo(component->getFileName()).absolutePath() + "/" + QFileInfo(component->getFileName()).completeBaseName();
components/obj/ObjExtension.cpp:68: QString baseFilename = QFileInfo(component->getFileName()).absolutePath() + "/" + QFileInfo(component->getFileName()).completeBaseName();
libraries/core/viewer/RendererWidget.cpp:572: QString filePrefix = QFileInfo(filename).absolutePath() + "/" + QFileInfo(filename).baseName();
libraries/core/utils/CamiTKLogger.cpp:158: QFile::rename(fileToMove.absoluteFilePath(), logFileDirectory.path() + "/" + logFileName);
libraries/core/utils/CamiTKLogger.cpp:162: logFile = new QFile(logFileDirectory.path() + "/" + logFileName);
libraries/core/ExtensionManager.cpp:322: QString privateLibToLoad = Core::getGlobalInstallDir() + "/" + QString(Core::libDir) + "/" + QString(Core::shortVersion) + "/" + libname.cap(1);
libraries/core/ExtensionManager.cpp:328: privateLibToLoad = Core::getGlobalInstallDir() + "/" + QString(Core::libDir) + "/" + QString(Core::shortVersion) + "/" + libname.cap(1);
libraries/core/ExtensionManager.cpp:367: // add one cdUp() for each "/" inside Core::libDir (to take into account any multiarch configuration that
libraries/core/ExtensionManager.cpp:576: appFilePath.replace("/", "\\");
libraries/core/ExtensionManager.cpp:717: if (potentialPath.cd(potentialLibDir + "/" + QString(Core::shortVersion))) {
libraries/core/Core.cpp:314: QStringList installDirectories = getInstallDirectories(QString(Core::libDir) + "/" + QString(Core::shortVersion) + "/" + extensionType);
libraries/core/Core.cpp:318: QStringList libInstallDirectories = getInstallDirectories("lib/" + QString(Core::shortVersion) + "/" + extensionType, false);
libraries/cepgenerator/CepGenerator.cpp:95: devDirectoryName = devDirectoryName + "/";
libraries/cepgenerator/ComponentExtensionGenerator.cpp:309: QString testFileName = currentDirectory.absolutePath() + "/" + "empty." + suffix;
```
Same with '/':
```cpp
libraries/core/ExtensionManager.cpp:369: for (int i = 0; i < QString(Core::libDir).count(QLatin1Char('/')); i++) {
components/vtkmesh/VtkMeshUtil.cpp:230: size_t nbegin = vtkFileName.find_last_of('/');
```
Outside the SDK, tutorials and modeling also contain instances of the same problem:
```cpp
modeling/libraries/mml/monitoring/MonitoringManager.cpp:565: if (mmlIn->simulatorFile().get()[0] != '/') {
modeling/libraries/mml/monitoring/AnsysSimulator.cpp:48: if (workingDir[workingDir.length() - 1] != '/') {
modeling/libraries/mml/monitoring/ArtiSynthSimulator.cpp:44: if (workingDir[workingDir.length() - 1] != '/') {
modeling/applications/pmltools/obj2pml/obj2pml.cpp:111: unsigned int slash = buff.find('/');
modeling/actions/mml/GenerateModel.cpp:86: QString baseFilename = QFileInfo(originalFilename).absolutePath() + "/" + QFileInfo(originalFilename).completeBaseName();
modeling/libraries/mml/monitoring/MonitoringManager.cpp:53: size_t slashPlace = mmlPath.find_last_of("/");
modeling/libraries/mml/monitoring/MonitoringManager.cpp:97: QString guessPMLFilename = QFileInfo(fi).absolutePath() + "/" + QFileInfo(fi).baseName() + ".pml";
modeling/libraries/mml/monitoring/SofaSimulator.cpp:80: QString scnFileName = mmlFileInfo.absolutePath() + "/" + mmlFileInfo.baseName() + ".scn";
modeling/libraries/mml/monitoring/SofaSimulator.cpp:88: scnFileName = QDir::tempPath() + "/" + mmlFileInfo.baseName() + ".scn";
modeling/libraries/mml/monitoring/SofaSimulator.cpp:92: QString mshFileName = QDir::tempPath() + "/" + QFileInfo(monitoringManager->getPmlFileName().c_str()).baseName() + ".msh";
modeling/libraries/mml/monitoring/SofaWidget.cpp:87: size_t slashPlace = scnFileTemp.find_last_of("/");
modeling/libraries/mml/monitoring/AnsysSimulator.cpp:49: workingDir = workingDir + "/";
modeling/libraries/mml/monitoring/ArtiSynthSimulator.cpp:45: workingDir = workingDir + "/";
modeling/libraries/mml/monitoring/Reference.cpp:82: size_t slashPlace = refpath.find_last_of("/");
modeling/components/mmlcomponent/MMLComponent.cpp:61: file = QDir::tempPath() + "/" + QFileInfo(fi).baseName() + ".mml";
modeling/applications/pmltools/extractCells/extractCells.cpp:147: extracted = new StructuralComponent(pm, c1 + "/" + c2 + " extracted");
modeling/applications/pmltools/extractCells/extractCells.cpp:172: cout << '\r' << (i + 1) << "/" << ok;
modeling/applications/pmltools/extractCells/extractCells.cpp:192: pm->setName(pm->getName() + " " + c1 + "/" + c2 + " Extracted");
```
```cpp
tutorials/components/mixed/MixedComponent.cpp:41: QString mhaFile = QFileInfo(file).absolutePath() + "/" + filename.c_str();
tutorials/components/mixed/MixedComponent.cpp:43: QString vtkFile = QFileInfo(file).absolutePath() + "/" + filename.c_str();
tutorials/applications/fancy/FancyMainWindow.cpp:221: ui.slideValue->setText(QString("%1").arg((currentSliceId + 1), 3) + "/" + QString("%1").arg(maxSliceId, 3));
tutorials/applications/nogui/main.cpp:85: QString outputFileName = QDir::currentPath() + "/" + QFileInfo(image->getFileName()).completeBaseName() + "-output." + QFileInfo(image->getFileName()).suffix(
```
## Actual VS Expected Result
As CamiTK is multiplaform, the code should not assume that the path separator is the '/' char.
Using Qt Resources might be an exception to this, so each line of code should be checked manually before replacing '/' by QDir::separator().
## Interpretation & Possible fixes
Replacing '/' char with QDir::separator() when building file paths.
## CamiTK Version
CamiTK 5.1.dev.develop.f3f104d8
---
**please do not remove anything below this line**Manik BhattacharjeeManik Bhattacharjeehttps://gricad-gitlab.univ-grenoble-alpes.fr/CamiTK/CamiTK/-/issues/65Unexpected image behaviors in Viewers2024-03-29T18:33:30+01:00Emmanuel PromayonUnexpected image behaviors in Viewers## About you
Bug filed on Bugzilla by @jaffarda on 2016-04-22
## Overview:
> when looking at an image in 2D viewer (axial for exemple)
> - pb1/ border voxels are only half-sized (both in 2D and in 3D)
> - pb2/ border...## About you
Bug filed on Bugzilla by @jaffarda on 2016-04-22
## Overview:
> when looking at an image in 2D viewer (axial for exemple)
> - pb1/ border voxels are only half-sized (both in 2D and in 3D)
> - pb2/ border box does not adjust to displayed image
> - pb3/ picking is not possible a all places inside pixels
> - pb4/ picking is possible outside the image
> - pb5/ picking actor (crossing bars are not always visible)
> attached images are very small in number of voxels for a better view
> provided:
> - testImage.bmp (the expected visble result)
> - testData.raw (raw file for 2D images)
> - testData3D.raw (raw file for 3D image)
> - test1.mhd ( image 5x5x1 black & white grid, spacing 10x10x1)
> - test2.mhd ( image 5x5x1 black & white grid, spacing 1x1x1)
> - test_3D.mhd ( image 5x5x5 black & white grid, spacing 1x1x1)
[testImages.zip](/uploads/dbdae0b5992f6f646f9f890d03bd277e/testImages.zip)
## Steps to Reproduce
> - step 1/ Load test1.mhd in camitk
> - step 2/ click on centralViewer and press I (to toogle off image interpolation)
> - step 3/ open axial viewer (ctrl + 2)
> - step 4/ Pick a point (ctrl + click) close to the middle of a pixel
> - step 5/ Pick a point (ctrl + click) close to the border of a pixel
> - step 6/ Pick a point (ctrl + click) close to the middle of a pixel but on the outside of the displayed image
> - step 7/ Load test2.mhd, open axial viewer, toogle off interpolation
> - step 8/ Pick a point (ctrl + click) close to the middle of a pixel
## Actual VS Expected Result
> - at step 2/ we see pb1 all the pixels are not the same size but they should
> - at step 3/ we see pb1 all the pixels are not the same size but they should
> - at step 3/ we see pb2 the border does not match the image but should
> - at step 5/ we see pb3 picking works close to centre of pixel but nowhere else
> picking should be available everwhere
> - at step 6/ we see pb4 it is possible to pick a point outside the image,
> it should not
> - at step 8/ we see pb5 when picking works (see with pb3) the actor (small lines) are not visible, it should
## Relevant logs and/or screenshots:
See [testImages.zip](/uploads/dbdae0b5992f6f646f9f890d03bd277e/testImages.zip)
## Interpretation & Possible fixes:
> - pb1/ maybe miss set of dimensions?
> - pb2/ probably linked to pb1 the boxing seems to be the good size if pixels were correctly displayed
> - pb3/ maybe bad use of pixel size?
> - pb4/ probably linked to pb1 the selection box should be in pixel if pb1
> - pb5/ no ideas
## CamiTK Version:
Filed for CamiTK 3.6, but confirmed still on 4.1.develop