CamiTK Community Edition issueshttps://gricad-gitlab.univ-grenoble-alpes.fr/CamiTK/CamiTK/-/issues2018-06-13T10:43:51+02:00https://gricad-gitlab.univ-grenoble-alpes.fr/CamiTK/CamiTK/-/issues/30Easy action GUI/widget for specific properties2018-06-13T10:43:51+02:00Emmanuel PromayonEasy action GUI/widget for specific properties| | |
|--|--|
| **As a** | CEP developer |
| **I would like to** | easily add/easily manage specific high-level properties/parameters to my action |
| **So that** | my action source code is only focusing on the processing |
## Descript...| | |
|--|--|
| **As a** | CEP developer |
| **I would like to** | easily add/easily manage specific high-level properties/parameters to my action |
| **So that** | my action source code is only focusing on the processing |
## Description / Overview
This story is about having an easy way to declare and manage specific high level properties in actions.
In an `Action` derived class it should be easy to add properties (and automatically create their GUI) for the following:
- `QStringList` → dropdown list
- list of instanciated/available components (with possible restriction to components of a given type) → GUI = dropdown list
- list of `MedicalImageViewer` viewers → GUI = dropdown list
- button (name + icon + tristate or not + double state or not + slot to call) → GUI = `QPushButton` automatically added to the default `ActionWidget` that calls the slot.
Therefore it should be possible to directly write something like:
```cpp
// MyAction constructor
MyAction::MyAction(..) : .. {
...
QStringList myList;
myList << "A" << "B" << "C";
addParameters(new Property(tr("List of strings"), myList, ...);
Property *listOfComp = new Property(tr("Image 1", Property::LIST_OF_COMPONENT, ...);
listOfComp->setAttribute("componentName", "ImageComponent");
addParameters(listOfComp);
addParameters(new Property(tr("Viewer to show"), Property::LIST_OF_MEDICAL_VIEWERS, ...);
Property *pushMeProp = new Property(tr("Push Me"), SLOT(pushMeSlot()), ...);
pushMeProp->setAttribute("checkable",true);
pushMeProp->setAttribute("icon",QIcon(":/images/myIcon.png"));
addParameters(pushMeProp);
...
}
```
## Acceptance test
- [ ] there is a tutorial showing how to use these highlevel
- [ ] the Action and Property API documentation is updated
- [ ] the wizard allow for the creation of such properties
- [ ] the CEP generator is aware of these properties and there are new tests in the `cepgenerator/testing/cepgernerator-test.sh`
- [ ] any action in CamiTK CE that manages this type of high-level properties otherwise should use the new way
https://gricad-gitlab.univ-grenoble-alpes.fr/CamiTK/CamiTK/-/issues/36Interface Data2018-06-13T10:41:45+02:00Emmanuel PromayonInterface Data| | |
|--|--|
| **As a** | CEP developer |
| **I would like to** | add easily manipulate array of data (values, signals, vectors...) to any type of component (not MeshComponent nor ImageComponent) |
| **So that** | I can visualize/inter...| | |
|--|--|
| **As a** | CEP developer |
| **I would like to** | add easily manipulate array of data (values, signals, vectors...) to any type of component (not MeshComponent nor ImageComponent) |
| **So that** | I can visualize/interact data as colors on a mesh, as graph/curve |
| **Epic/Topics** | Interface Data |
## Description / Overview
The epic is called "Interface Data" or how to include 1D temporal signal in CamiTK.
This is a new facet for `Component` that enables storage, manipulation, visualization and interaction with/of array of data. The idea is to offer data abstraction and minimal default behaviour for signal and temporal values.
In the design stage, first check:
- Check the Pulse project to check how they store the signals
- Check the work done by Nico (see `incubator-local/respirm` CEP) in order to handle 1D signal and their representation using a dedicated viewer based on vtkChart library (and some action to process them). In particular check the viewer and the defined actions.
- Check open-source application that help manipulate data and display charts to deduce best practices
- Check for standard in signal processing data format and processing library (if any)
One idea would be to be able to use a python interface/shell/script in order to process the signal directly from a console...
## Hints
As for any creation of interface in CamiTK, this can be done following these steps:
- Create a new interface that add the management of a list of `vtkDataArray` in `Component`
- Create the corresponding helper class
- Create the corresponding viewer (using vtkChart and the possibility to add data as if it was a live physiological signal) and integrate it to camitk-imp
- Create another viewer to display data in a table/spreadsheet
- Take into account the fact that `MeshComponent` can project the data as colors
- move addPointData/addCellData in `InterfaceGeometry` or to the new `InterfaceData` interface (may be use an enum for `FREE`, `ATTACHED_TO_CELLS`, `ATTACHED_TO_POINTS` etc...
## Acceptance tests
- [ ] a new tutorial component that shows how to add/remove/show these data in the new viewer
- [ ] a new tutorial MeshComponent that shows how data can be displayed directly _on_ the mesh surface
- [ ] a new tutorial that shows generates random value based on a sinus function to show how update/acquisition can be done
## Track
/label ~"Track Technology Integration"https://gricad-gitlab.univ-grenoble-alpes.fr/CamiTK/CamiTK/-/issues/54Improved ActionWidget2024-03-25T18:04:17+01:00Emmanuel PromayonImproved ActionWidget| | |
|--|--|
| **As a** | CEP developer |
| **I would like to** | change just the parameters tab of the action widget (and have more space for my action widget) |
| **So that** | I can deliver the same user experience (doc and informati...| | |
|--|--|
| **As a** | CEP developer |
| **I would like to** | change just the parameters tab of the action widget (and have more space for my action widget) |
| **So that** | I can deliver the same user experience (doc and information about selected target) without reimplementing everything |
## Description / Overview
This story is about improving the `ActionWidget` API/usage:
- It should be possible to get/set only the `QFrame` parameters section of default `ActionWidget` (and hence modifying just the "Parameters" part of the widget, see below)
![Screenshot_20180612_143335](/uploads/a1d13000f8029b6b73afde7bd9a97818/Screenshot_20180612_143335.png)
- It should be possible to easily access the frame itself in order to restrict the space used in the GUI (for instance in the action state machine, as in the screenshot below, should we use all this space for description and targets that nobody really look at) ?
![Screenshot_20180612_143650](/uploads/98f907763249155e8ae9f1b4314b8aea/Screenshot_20180612_143650.png)
- The `Description` / `Targets` / `Parameters` section should take less space (use stacked widget like in the mockup below? Tab widget?)
![Screenshot_20180612_160056](/uploads/d513f0839e4f0acb48fc44db33e97027/Screenshot_20180612_160056.png)
![Screenshot_20180612_160109](/uploads/919244814c8295d69b31f7066f52253c/Screenshot_20180612_160109.png)
## Hints
- Add `set/getFrame()` to `ActionWidget`
- modify action state machine to use the `getFrame()` not the full default widget
- rewrite default widget to take less space
## Acceptance test
- [ ] a tutorial showing a demo
- [ ] asm for reconstruction improve the space for parameter interaction
- [ ] Action API doc updated to show this usagehttps://gricad-gitlab.univ-grenoble-alpes.fr/CamiTK/CamiTK/-/issues/59Auto center option in InteractiveViewer2018-06-15T18:17:15+02:00Emmanuel PromayonAuto center option in InteractiveViewer## About you
This is a feature request that summarizes two bugs submitted on the old bugzilla:
- "InteractiveViewer option for specifying whether the scene must be centered when a Component is added" submitted by Hadrien Oliveri on 2015...## About you
This is a feature request that summarizes two bugs submitted on the old bugzilla:
- "InteractiveViewer option for specifying whether the scene must be centered when a Component is added" submitted by Hadrien Oliveri on 2015-07-07
- "Impossible to scroll through a zoomed image without the image automatically de-zooming" submitted by Nikolai on 2015-01-16
## Product:
imp
## Overview:
### Hadrien's submission
> Hello everyone,
> I'm developping a surgery simulator, and I need to add Components during the simulation. By default, the scene is
> recentered by the InteractiveViewer each time a Component is added (which is quite annoying). I modified this locally in
> my sdk and it works well for my ad hoc needs.
>
> I would be great if recentering the scene by default could be specified in the Imp user preferences for example.
>
> Thank you
>
> -- Hadrien Oliveri
### Nikolai's submission
> Imp de-zooms automatically when it's not expected. In this case, the 2D medical viewer panes de-zoom when you try to scroll through the image's volume with the vertical slider.
>
>
> Steps to Reproduce:
> Open Imp. Open any 3D image. Zoom in on any of the 2D viewers using the scroll wheel of your mouse. Move the vertical slider to another image plane. You will see the viewer de-zoom automatically.
>
>
> The viewer should stay zoomed while scrolling with the sliders.
>
> -- Nikolai
## Interpretation & Possible fixes
Both problems can be solved by implementing a special "Auto Center" option for the `InteractiveViewer`s.
Auto center
- [ ] When a new component is loaded (default is yes)
- [ ] When a slice is changed (default is yes)
As well as a "Center" Icon on the toolbar or the slice viewer side bar.
Depends on #17 https://gricad-gitlab.univ-grenoble-alpes.fr/CamiTK/CamiTK/-/issues/65Unexpected image behaviors in Viewers2023-05-15T15:59:39+02: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.develophttps://gricad-gitlab.univ-grenoble-alpes.fr/CamiTK/CamiTK/-/issues/67Protocol file associated with the action state machine2018-07-09T15:39:29+02:00Emmanuel PromayonProtocol file associated with the action state machine## About you
CamiTK team member.
## Product
action state machine
## Overview
This is issue was created by splitting issue #57 originally submitted on bugzilla by Antoine Tacheau @tacheaua, 2017-09-11.
This issue is abo...## About you
CamiTK team member.
## Product
action state machine
## Overview
This is issue was created by splitting issue #57 originally submitted on bugzilla by Antoine Tacheau @tacheaua, 2017-09-11.
This issue is about providing an associated protocol file to enable double-click to start the action state machine from a desktop without using the command line.
> Currently, we need to open a terminal and type this kind of command to start asm:
>
> camitk-actionstatemachine -f <ProtocolFile> -o <LogFolder>
>
> Since Action State Machine can be used by 'basic user' to run new protocol, it would be easier if a launcher or an interface were available.
>
> ~~For instance:#~~
> ~~- a gui interface in order to select which protocol should be started~~
> ~~or~~
> a specific protocol file (only changing extension by .asm, .prot, .protocolASM ...) to be associated to asm executable. Thus, users only have to double click to start application
>
> -- Antoine Tacheau
## Hints
The best would probably be to :
- add another option to the command line `--protocol-file` (or something like that)
- parse the corresponding `.prot` file (or `.casm` of, as `.asm` extension is [already used a lot, especially for assembler](https://fileinfo.com/extension/asm) and the other suggestion is very looong!)
- a `.prot` can be a very simple file with
- first line: the filepath to the `.scxml`
- second line: filepath to the output directory
- add another page to the Qt Wizard describe above to ask the user if she/he wants to save a corresponding `.prot` for later reuse
- make sure that at file can be associated to the application (on windows reproduce what is done in camitk-imp: at first launch, ask the user if s⋅he wants `.prot` to be associated directly to the application).
- write a wiki documentation to show how to associate `.prot` files to the action state state machine for Windows, KDE and MacOS X
https://gricad-gitlab.univ-grenoble-alpes.fr/CamiTK/CamiTK/-/issues/72use setProperty with QString instead of char*2020-05-18T14:55:02+02:00Matthias Tummersuse setProperty with QString instead of char*| | |
|--|--|
| **As a** | CEP developer |
| **I would like** | a `setProperty` with `const QString name` instead of `const char * name` |
| **To** | improve camitk code consistency |
| **Epic/Topics** | Property setProperty QString char...| | |
|--|--|
| **As a** | CEP developer |
| **I would like** | a `setProperty` with `const QString name` instead of `const char * name` |
| **To** | improve camitk code consistency |
| **Epic/Topics** | Property setProperty QString char* |
## Description / Overview
I noticed that the `QObject::setProperty` method prototype demands a `const char *` type for the first argument whereas the `camitk::Property` constructor and the `getProperty` method use a `QString` type.
I think it might be a good idea to implement a method looking like
```cpp
//PropertyObject.h
virtual bool setProperty(const QString name, const QVariant &value);
```
```cpp
//PropertyObject.cpp
bool PropertyObject::setProperty(const QString name, const QVariant &value) {
if (propertiesMap.contains(name)) {
return setProperty(name.toStdString().c_str(), value);
}
else {
return false;
}
}
```
,
to be re-implemented in component and action.
(just like `getPropertyValue` (which I think should be re-implemented in component and action too (for the same reason)))
This would allow manipulating camitk properties only with QStrings and not with a mix of qstrings and char* types depending on the method being used.
## Acceptance tests
- **SetProperty works with QString**
One is able to set a property with the setProperty method using a QSting for the first argument
- **All uses of setProperty in CamiTK and CEPs are updated**
CamiTK and CEPs compile without errors regarding the setProperty method
## Track
One (or two) of:
## Misc
- Automatic subscription of issue creator:
**Do not forget to mark this issue as "confidential"** by checking the tick box below (if appropriate)https://gricad-gitlab.univ-grenoble-alpes.fr/CamiTK/CamiTK/-/issues/101viewer extension dependencies in wizard2023-06-02T16:49:24+02:00Maxime Calkaviewer extension dependencies in wizard## About you
Occasional CamiTK developer
## Product
Wizard
## Overview
Add in the dependencies of the extension the possibilities to link a viewer extension.
## Relevant logs and/or screenshots
Already implemented:
![image](/uploa...## About you
Occasional CamiTK developer
## Product
Wizard
## Overview
Add in the dependencies of the extension the possibilities to link a viewer extension.
## Relevant logs and/or screenshots
Already implemented:
![image](/uploads/d5dac9ba6884a5565013cbc41f370457/image.png)
Needed:
![image](/uploads/4c4851f8c2277b4c451ecd4129a12339/image.png)Maxime CalkaMaxime Calkahttps://gricad-gitlab.univ-grenoble-alpes.fr/CamiTK/CamiTK/-/issues/126Name conflict while including external lib using QT for a CEP action2023-02-23T18:05:42+01:00Erwan LecesneName conflict while including external lib using QT for a CEP actionThe CmakeLists is located **_../actions/MyAction/CmakeLists.txt_** . [Cmake_output.txt](/uploads/4dbc62aefa9a879f9065beb3a65c0061/Cmake_output.txt)[CmakeLists.txt](/uploads/5611751a71ec3746480b7bde59091bec/CmakeLists.txt)The CmakeLists is located **_../actions/MyAction/CmakeLists.txt_** . [Cmake_output.txt](/uploads/4dbc62aefa9a879f9065beb3a65c0061/Cmake_output.txt)[CmakeLists.txt](/uploads/5611751a71ec3746480b7bde59091bec/CmakeLists.txt)https://gricad-gitlab.univ-grenoble-alpes.fr/CamiTK/CamiTK/-/issues/132Option to highlight selected object by silhouette2023-04-21T19:56:41+02:00Manik BhattacharjeeOption to highlight selected object by silhouette## About you
CamiTK developer
## Product
Core in InteractiveViewer.
## Overview
In the main viewer, unselected elements are transparent, selected elements are not.
Add an option to show unselected elements as non-transparent, and selec...## About you
CamiTK developer
## Product
Core in InteractiveViewer.
## Overview
In the main viewer, unselected elements are transparent, selected elements are not.
Add an option to show unselected elements as non-transparent, and selected elements with an highlighted sihouette.
This is identical to [the VTK Silhouette example](https://kitware.github.io/vtk-examples/site/Cxx/Picking/HighlightWithSilhouette/)
---
**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/138Add support for RGBA color2023-06-05T17:16:25+02:00Manik BhattacharjeeAdd support for RGBA color## About you
CamiTK developer
## Product
MeshComponent
## Overview
MeshComponent can have associated data. If the display mode is COLOR, the data is read as RGB data.
If there is a 4th dimension (A for alpha transparency), this is no...## About you
CamiTK developer
## Product
MeshComponent
## Overview
MeshComponent can have associated data. If the display mode is COLOR, the data is read as RGB data.
If there is a 4th dimension (A for alpha transparency), this is not supported.
It should be checked whether data works if it is encoded as:
- double/float between 0 and 1,
- int 8/16/32 bits in their respective range
## Relevant logs and/or screenshots
Check commit d827e23daf036652c10657bd57f12d0819ba0891
In libraries/core/mesh/MeshComponent.cpp
`colorArrayToDisplay->SetTuple3(i, val[0], val[1], val[2]);`
should work when there are 4 values with setTuple4. Hopefully VTK would use that as RGBA.
---
**please do not remove anything below this line**Manik BhattacharjeeManik Bhattacharjeehttps://gricad-gitlab.univ-grenoble-alpes.fr/CamiTK/CamiTK/-/issues/139CamiTK does not read OBJ material file2023-06-05T17:22:36+02:00Manik BhattacharjeeCamiTK does not read OBJ material file## About you
CamiTK developer
## Product
sdk/obj/ObjComponent
## Overview
The OBJ file format can be associated with a .mtl file that store the material (RGBA color). This is ignored by CamiTK.
## Relevant logs and/or screenshots
V...## About you
CamiTK developer
## Product
sdk/obj/ObjComponent
## Overview
The OBJ file format can be associated with a .mtl file that store the material (RGBA color). This is ignored by CamiTK.
## Relevant logs and/or screenshots
VTK has two objects to read obj files: CamiTK should use VtkObjImporter (and not VtkObjReader) and use its support for mtl files.
A test object can be easily generated in Blender (standard cube + material exported as obj file).
---
**please do not remove anything below this line**Manik BhattacharjeeManik Bhattacharjeehttps://gricad-gitlab.univ-grenoble-alpes.fr/CamiTK/CamiTK/-/issues/140Better LUT editor, standard LUT should be provided as well2024-03-25T17:37:38+01:00Manik BhattacharjeeBetter LUT editor, standard LUT should be provided as well## About you
CamiTK developer
## Product
sdk/actions/image/imagelut
## Overview
The LUT editor only allows to choose one color (changing the first color does nothing) and go from black to that color.
There is no way to create a LUT t...## About you
CamiTK developer
## Product
sdk/actions/image/imagelut
## Overview
The LUT editor only allows to choose one color (changing the first color does nothing) and go from black to that color.
There is no way to create a LUT that goes from blue to yellow to red for example, and that should be possible.
We should also provide a list of "standard" LUTs, maybe taken from another opensource project (Brainvisa/Anatomist ?).
The same editor could be used for the 3D rendering widget as well if we can also set transparency (RGBA) of the reference values
Saving a user's custom LUTs would be useful too.
To avoid the UI being too complex,
- use one tab to select a palette and set window level and width (adapted to the range of the image type - e.g. 0-65535 for uint16 or -2B/+2B for int32, not 0-255 in all cases)
- use another tab to create a new palette
## Relevant logs and/or screenshots
BrainVisa/Anatomist palette system: https://brainvisa.info/anatomist-5.0/user_doc/anatomist_tutorial.html#modification-of-color-palette
---
**please do not remove anything below this line**Manik BhattacharjeeManik Bhattacharjeehttps://gricad-gitlab.univ-grenoble-alpes.fr/CamiTK/CamiTK/-/issues/141Add icon next to components to show/hide components in viewers2023-11-24T19:10:15+01:00Manik BhattacharjeeAdd icon next to components to show/hide components in viewers## About you
CamiTK developer
## Product
Main IMP interface - Component explorer
## Overview
In the list of components in camitk-imp, it would be useful to have an eye icon next to the component's name to click on to show or hide co...## About you
CamiTK developer
## Product
Main IMP interface - Component explorer
## Overview
In the list of components in camitk-imp, it would be useful to have an eye icon next to the component's name to click on to show or hide components in views.
As visibility depends on the view:
- should we add a ViewerExplorer in IMP that would allow to select views (adding or removing components from views before setting visibility,
- just show/hide on all views ?
- Allow drag and drop of a component into a viewer to make it visible in that viewer.
## Relevant logs and/or screenshots
Eye icons that are already present in CamiTK: sdk/libraries/core/resources/oxygen_icons/actions/layer-visible-on.png
---
**please do not remove anything below this line**Manik BhattacharjeeManik Bhattacharjeehttps://gricad-gitlab.univ-grenoble-alpes.fr/CamiTK/CamiTK/-/issues/142Toolbar for each viewer2023-06-14T08:19:10+02:00Manik BhattacharjeeToolbar for each viewer## About you
CamiTK developer
## Product
IMP UI and Viewers
## Overview
The main toolbar does not apply to all viewers, which is confusing, and does not allow buttons specific to a viewer (e.g. display mode).
Code structure is alread...## About you
CamiTK developer
## Product
IMP UI and Viewers
## Overview
The main toolbar does not apply to all viewers, which is confusing, and does not allow buttons specific to a viewer (e.g. display mode).
Code structure is already developed with viewer-specific toolbars in mind.
---
**please do not remove anything below this line**Manik BhattacharjeeManik Bhattacharjeehttps://gricad-gitlab.univ-grenoble-alpes.fr/CamiTK/CamiTK/-/issues/151Picking a point changes selected object and makes current Action disappear2024-03-25T17:54:17+01:00Manik BhattacharjeePicking a point changes selected object and makes current Action disappear## About you
CamiTK developper
## Overview
While creating a CEP, an action that uses multiple components was written and needs to get point coordinates from a click in a viewer.
When clicking on the point, if the image in the viewer is...## About you
CamiTK developper
## Overview
While creating a CEP, an action that uses multiple components was written and needs to get point coordinates from a click in a viewer.
When clicking on the point, if the image in the viewer is not the selected imageComponent, the picking action changes the selection. The action is then hidden because the selection changed.
## Steps to Reproduce
This is visible when using Meniscare CamiTK CEP and the ManualRegistration3D action.
Load two volumes (e.g. brain.mha and sinus-displaced.mha).
In the action, select one of the images, and Ctrl+Click on the image in a slice viewer.
Click on the "pick" button in the action to get the coordinates.
## Actual VS Expected Result
If the image shown in the viewer (the one "selected" in the Action widget) is not the selected component of CamiTK Application, the image is selected, and the action disappears because the component selection changed.
## Interpretation & Possible fixes
This is due to the [selectionChanged(comp)](https://gricad-gitlab.univ-grenoble-alpes.fr/CamiTK/CamiTK/-/blob/develop/sdk/libraries/core/viewer/InteractiveViewer.cpp#L2165) in InteractiveViewer. The same applies to other picking modes in the same InteractiveViewer::picked() function.
I think this is done to show in the PropertyExplorer the coordinates of the picked point when it is clicked (which needs the ImageComponent to be selected), and hiding the action is a side effect of that.
I see two ways to fix this problem:
- do not change the selected component when a point is picked, but that might break the behavior of displaying the picked coordinates in the "selection" tab of the PropertyExplorer
- A large change in CamiTK: separate completely the notion of selected components in the Application with the currently running Action. I mean that when an action is open on selected components, the fact that the selection changes in the application should not hide the action. The action should only be closed if the component disappears (closed) or the action is closed by the user. This means rethinking what an action can be, e.g. an action can be instantiated multiple times, and there should be an ActionExplorer that lists currently opened actions. In this way, we could run the same action twice with different parameters at the same time.
## CamiTK Version
CamiTK 5.1.dev.develop.f3f104d8
---
**please do not remove anything below this line**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/157Reference frames and transformations management2024-03-28T14:25:48+01:00Manik BhattacharjeeReference frames and transformations management| | |
|--|--|
| **As a** | CamiTK developer |
| **I would like to** | support and document reference frames, geometrical transformations and orientation conventions |
| **So that** | CamiTK can load, register and display volumes and mesh...| | |
|--|--|
| **As a** | CamiTK developer |
| **I would like to** | support and document reference frames, geometrical transformations and orientation conventions |
| **So that** | CamiTK can load, register and display volumes and meshes with explicit reference frames, transformations and anatomical orientations |
| **Epic/Topics** | Referential Management Epic |
## Current state overview
**Geometrical transformations in CamiTK are currently managed by**:
- Frames which are attached to all components
- A transformation from each frame to its parent Frame
- A World Frame
- A default orientation for volumes (RAI convention)
- Depending on the file format used (DICOM, MHD/MHA, Nifti...) the transformation to the parent frame may or may not be loaded/saved
- Depending on the file format, the anatomical orientation may be loaded/saved or not, and conversion to RAI may or may not work.
- There is no standard way to store a registration between two images so that CamiTK reloads it when the software loads images again
## Solutions
### 1. Documentation
- Document every detail of geometrical conventions using illustrations when needed to avoid confusion
- For DICOM, there is the position of the patient in the machine, the position of the image relative to the machine, and the convention of the order to save the pixels. [Illustrations are useful](https://dicom.nema.org/medical/Dicom/2016e/output/chtml/part03/sect_C.7.3.html#sect_C.7.3.1.1.2).
- Matrices may be stored in row-major (Nifti) or column-major order (MHA file format)
- For each image and mesh file format, detail how we read and write it (e.g. ITK and VTK do not read and write the same information in the header and do not assume the same conventions for MHA format). This should explain how CamiTK may differ with other software and why we took those decisions.
### 2. Main (core) changes
- Define a CamiTK unique ID : **CamiUID** so that each object has a unique ID, maybe associated with a name, a description and a type ?
- Define a **ReferenceFrame** class (mostly a CamiUID) so that every displayable component has an instance of it
- We have to keep the **anatomical orientation** information. It might be stored in the Referential object and specify which axes (if known) are Right/Left, Superior/Inferior, Anterior/Posterior. This information is transitive (e.g. if there is no large rotation (> 45°) or axes flipping, the anatomical orientation is the same between two reference frames linked by a transformation). It can be set to UNKNOWN (in which case a viewer should not display the anatomical directions).
- Define a **Transformation** class that has an origin and a destination (from/to) ReferenceFrame, a vtkTransform (by default a linear transform represented by a 4x4 matrix), and a CamiUID. Make it generic enough so that it could manage a 4th dimension (e.g. for a time offset between videos) and non-linear transformations
- The Frame interface should be updated
- A Referential and Transformation Manager should be included in CamiTK Application to manage the list of known reference frames and transformations
- In this manager, keep the source of referentials and transformations. E.g. if a Nifti file contains two transforms, the loaded nifti component, when saved, should save again both transforms. and not other transforms to other referentials. Or maybe this information should be stored in the Image Component itself (which transformations to save).
- A CamiTK world referential will exist by default, and components that are loaded without specific transformations to CamiTK will have an identity transform from their referential to CamiTKWorldReferential
- There is no reason to force an orientation convention in CamiTK (e.g. RAI for all volumes).
### 3. UI changes
- An explorer for referential and transformations should be provided, (like the Component explorer, the property explorer and so on). It should be able to display/edit transformations, to link referentials with new transformations (identity, loaded from file...).
- A color code for each referential will be displayed next to each component name, and next to each viewer name, and can be changed by clicking on it to choose another one
### 4. I/O ###
- Define a way to store metadata associated to files (e.g., keep the UID of the referential of a MHD file).
This is linked to a metadata format (see specific issue #158) that should be defined for all CamiTK-related data (such as the LUT settings associated to an image, a list of actions to run for a state machine, a scene description and so on). If possible, choose a human-readable format and try to be compatible with other software or norms, e.g. the JSON format used by [BIDS](https://bids.neuroimaging.io/) or in the metadata files of [Brainvisa](https://brainvisa.info). Maybe a .camitk file.
- test
### 5. Viewers
- Each viewer is attached to a reference frame (e.g. all coordinates of a selected point in the viewer are expressed in this referential), and a camera position and orientation.
- Slice viewers may use their reference frame orientation information to display R/L, A/P, I/S directions
- In viewer preferences, the user can set its own convention (Right displayed on the left, or right displayed on the right)
- When adding a volume to a SliceViewer, it should get its reference frame from it, use anatomical orientation information of the frame, and user preference to orient its camera transform (no need to have RAI/LAS or other convention forced on the volume).
- Viewers should be in charge of the way they want to display a volume (e.g. no Axial View Component, just a SliceViewer with a camera orientation that matches Axial, and a volume image).
- Medical Image Viewer should manage the slices displayed in the 3D view in relation to the slices displayed in the SliceViewers by itself (not using subcomponents)
- A common cursor between viewers can be achieved by following the transformation graph from one view's reference frame to another viewer's reference frame. We can display a 3D cross with its own reference frame, and moving the cursor means changing the transformation between this frame and the selected object's frame. This allows a 3D cursor in a SliceViewer to be displayed in a 3D viewer, rotated with the angle of the slice currently being clicked on.
## Acceptance tests
- [ ] [Documentation is clear and complete]
- [ ] [Reading an image, registering it with another, saving both, then closing the software and reading both again should load all referentials and transforms so that the images are still aligned]
- [ ] [Same test with an image and a mesh segmented from it]
- [ ] [Same test with two meshes registered then saved and loaded again]
- [ ] [3D cursor synchronized between views with different referentials]
- [ ] [Displaying a volume in a SliceViewer using a referential of another volume (should display "arbitrary" slices of the volume aligned with the slices of the other volume)]
- [ ] [Loading two volumes from the same MRI acquisition should show volumes aligned because of the common scanner-based reference]
- [ ] use QUuid as a map key in TransformationManager, not QString
- [ ] Cleanup the TransformationManager API (maybe too complete/complex)
- [ ] Better API Documentation
- [ ] Remove C++23 specific code (too early)
## Track
## Misc
- Automatic subscription of issue creator:
**If appropriate, do not forget to mark this issue as "confidential"** by checking the corresponding tick box belowManik BhattacharjeeManik Bhattacharjeehttps://gricad-gitlab.univ-grenoble-alpes.fr/CamiTK/CamiTK/-/issues/166Python bindings: Python CEP and scripting2023-10-13T18:11:11+02:00Manik BhattacharjeePython bindings: Python CEP and scripting## About you
CamiTK developers
## Product
CamiTK
## Overview
Allow Python CEP and Python scripting
---
**please do not remove anything below this line**## About you
CamiTK developers
## Product
CamiTK
## Overview
Allow Python CEP and Python scripting
---
**please do not remove anything below this line**Emmanuel PromayonEmmanuel Promayon