Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
e94b4ec
pyradiomics fix + docs update
akannan05 Dec 18, 2025
96a8aae
readme update for new repo link
HaseebGarfinkel Dec 18, 2025
3c1d857
Merge pull request #11 from QuantUS-OpenSource/docs-update
davidspector67 Dec 21, 2025
9cae10c
Add DICOM overlay foundation for RF ultrasound imaging
OmidChaghaneh Jan 8, 2026
c05d848
Reset to original state before DICOM overlay implementation
OmidChaghaneh Jan 8, 2026
402b54f
Implement complete DICOM overlay functionality for ROI drawing
OmidChaghaneh Jan 8, 2026
7c1c66a
Update submodule with DICOM overlay functionality
OmidChaghaneh Jan 8, 2026
fd1271f
Fix DICOM overlay control access error
OmidChaghaneh Jan 8, 2026
ad887dd
Create DICOM overlay controls programmatically to fix UI access issue
OmidChaghaneh Jan 8, 2026
0b913bc
Add fallback approach for DICOM overlay controls with UI file support
OmidChaghaneh Jan 8, 2026
9708164
Add manual DICOM file loading with transparent overlay
OmidChaghaneh Jan 8, 2026
dd5e944
Update QUS engine submodule
OmidChaghaneh Jan 8, 2026
45dbe63
Update QUS engine submodule with DICOM cropping
OmidChaghaneh Jan 8, 2026
bcf2714
config: update submodules to track main branch
OmidChaghaneh Jan 12, 2026
76ba2fb
chore: update dependencies including pydicom
OmidChaghaneh Jan 12, 2026
4308080
feat: migrate DICOM loading logic to application model
OmidChaghaneh Jan 12, 2026
96dd2fe
refactor: decouple ROI drawing UI and integrate application-level DIC…
OmidChaghaneh Jan 12, 2026
4689fe3
chore: update qus engine submodule to include B-mode analysis plugins
OmidChaghaneh Jan 12, 2026
4adadf6
refactor: integrate application model with view coordinators for unif…
OmidChaghaneh Jan 12, 2026
c112498
ui: modernize ROI drawing interface and add standard loading indicator
OmidChaghaneh Jan 12, 2026
1099846
feat: implement real-time DICOM overlay and brightness adjustment in …
OmidChaghaneh Jan 12, 2026
4ace72c
UI: make 'Load DICOM File' button text normal instead of bold
OmidChaghaneh Jan 13, 2026
0d2636e
Updated readme for windows users
HaseebGarfinkel Jan 18, 2026
ff88ced
Updated gui for qus to qus analysis on sidebar
HaseebGarfinkel Jan 18, 2026
81efdfe
Merge pull request #33 from QuantUS-OpenSource/17-change-RF-analysis-…
davidspector67 Jan 19, 2026
df5f563
Merge branch 'feature/Philips_Quality' into 3-nifti-file-scaling-and-…
OmidChaghaneh Jan 22, 2026
19be9e4
Merge feature/Philips_Quality and cleanup redundant logic in Images/
OmidChaghaneh Jan 22, 2026
987f4cf
Fix module path in options.py and uncomment functions in functions.py
OmidChaghaneh Jan 22, 2026
f89a85d
Fix CEUS import error and refactor image enhancement logic
OmidChaghaneh Jan 22, 2026
e6caaf5
Feature: add interactive enhancement sliders to 3D VOI drawing widget
OmidChaghaneh Jan 22, 2026
5a60511
Refactor: improve 3D stability of image enhancement by using global n…
OmidChaghaneh Jan 22, 2026
da0a2c7
Feature: add interactive Philips-style pseudocoloring to VOI drawer w…
OmidChaghaneh Jan 22, 2026
ef8c04b
feat: display NIfTI metadata on load
OmidChaghaneh Jan 23, 2026
77a6b1d
feat: add dynamic aspect ratio and width control in VOI menu
OmidChaghaneh Jan 23, 2026
96d4bf0
feat(ceus): add independent plane-specific width aspect ratio controls
OmidChaghaneh Jan 29, 2026
95965a9
removed saved _ui.py file
davidspector67 Feb 2, 2026
deeb2c4
enforced mvc architecture
davidspector67 Feb 2, 2026
6af15b7
Merge pull request #38 from QuantUS-OpenSource/13-display-the-origina…
OmidChaghaneh Feb 5, 2026
b1f7cec
feat: update FileSelectionWidget and ceus engine for single DICOM sel…
OmidChaghaneh Feb 9, 2026
985ca96
Feat: Add preprocessing interface to ApplicationModel and connect to …
OmidChaghaneh Feb 9, 2026
7826605
Refactor: Move image preprocessing to backend engine and remove redun…
OmidChaghaneh Feb 9, 2026
f63b4be
Refactor: Update DrawVOIWidget to use standardized backend preprocess…
OmidChaghaneh Feb 9, 2026
43ffb23
Chore: Update QUS submodule pointer state
OmidChaghaneh Feb 9, 2026
dc465fe
Fix frame slider synchronization and frame-based display in CEUS GUI
OmidChaghaneh Feb 9, 2026
8448005
Merge branch '48-urgent-philips-high-quality-data-loading' into 36-dc…
OmidChaghaneh Feb 12, 2026
7625585
Add compact enhancement controls and pseudo-colouring to CEUS ROI dra…
OmidChaghaneh Feb 12, 2026
bd67285
Update gitignore to include generated UI files
OmidChaghaneh Feb 13, 2026
a99fe96
fix(ceus): resolve freeze after loading NIfTI segmentation by connect…
OmidChaghaneh Feb 13, 2026
d3e6f9f
feat(ceus): connect analysis screen to application workflow
OmidChaghaneh Feb 13, 2026
3ce6e6c
fix(ceus): standardize imports and fix NameErrors in analysis widgets
OmidChaghaneh Feb 13, 2026
18c6469
feat(ceus): implement analysis discovery and background execution
OmidChaghaneh Feb 13, 2026
46df59b
feat(ceus): add missing analysis parameters widget
OmidChaghaneh Feb 13, 2026
984fb39
fix: update .gitignore to include UI files and add missing .ui and _u…
OmidChaghaneh Feb 18, 2026
a8ceaf9
Fix GUI loading of saved NIfTI VOI - update seg loading components
OmidChaghaneh Feb 20, 2026
922fc07
Update ceus submodule with image preprocessing changes
OmidChaghaneh Feb 20, 2026
90b9219
Fix orientation mismatch and vertical inversion in SegPreviewWidget
OmidChaghaneh Mar 18, 2026
19dbd0a
Fix Sagittal plane coordinate mapping and broadcast error in DrawVOIW…
OmidChaghaneh Mar 18, 2026
469635d
Fix spline interpolation crash by deduplicating points
OmidChaghaneh Mar 18, 2026
c91d149
Synchronize SegPreviewWidget orientation with DrawVOIWidget
OmidChaghaneh Mar 18, 2026
65cd7ec
Synchronize VOI rendering and interpolation display across drawing an…
OmidChaghaneh Mar 18, 2026
ea9d1b8
Standardize mask overlay transposition logic for bit-perfect Axial/Co…
OmidChaghaneh Mar 18, 2026
96373df
feat: add crosshair hover behavior to SegPreviewWidget
OmidChaghaneh Mar 20, 2026
e271857
UI: Add crosshair hover logic, adjustable VOI alpha, and fixed window…
OmidChaghaneh Mar 20, 2026
ac53ba8
Fix ValueError in ROI interpolation by stripping 4th dimension for py…
OmidChaghaneh Mar 24, 2026
0c6f4b9
chore: Update ceus backend submodule with analysis discovery fix
OmidChaghaneh Mar 31, 2026
2d50296
feat: Add 'Confirm & Review' button to manual segmentation UI
OmidChaghaneh Mar 31, 2026
84c9765
Merge main into feature branch and resolve conflicts
OmidChaghaneh Apr 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,4 @@ fixed_wheels/
.vscode/
.DS_Store
*.so
/**/*_ui.py
Visualization_Results/
33 changes: 22 additions & 11 deletions src/ceus/analysis_loading/analysis_loading_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@

from ..mvc.base_controller import BaseController
from .analysis_loading_view_coordinator import AnalysisLoadingViewCoordinator
from engines.ceus.src.data_objs import UltrasoundImage, CeusSeg
from engines.ceus.src.data_objs.image import UltrasoundImage
from engines.ceus.src.data_objs.seg import CeusSeg
from engines.ceus.src.time_series_analysis.curves.framework import CurvesAnalysis


Expand Down Expand Up @@ -64,20 +65,30 @@ def _connect_signals(self) -> None:
def _setup_analysis_options(self) -> None:
"""Setup available analysis types and functions in the view."""
analysis_types, analysis_functions = self._model.get_analysis_types()
print(f"DEBUG: Available analysis types: {list(analysis_types.keys())}")

# Automatically select "Paramap" as the analysis type
paramap_type = "paramap"
if paramap_type in analysis_types:
self._selected_analysis_type = paramap_type
if self._model.set_analysis_type(paramap_type):
# Get available functions for Paramap analysis
available_functions = self._model.get_analysis_functions(paramap_type)
# Automatically select the best available analysis type
# Prefer curves_paramap, then curves, or just the first available one
selected_type = None
for preferred in ["curves_paramap", "curves", "paramap"]:
if preferred in analysis_types:
selected_type = preferred
break

if not selected_type and analysis_types:
selected_type = list(analysis_types.keys())[0]

if selected_type:
self._selected_analysis_type = selected_type
if self._model.set_analysis_type(selected_type):
# Get available functions for selected analysis type
available_functions = self._model.get_analysis_functions(selected_type)
# Skip analysis type selection and go directly to function selection
self._view_coordinator.show_function_selection(available_functions)
else:
self._view_coordinator.show_error("Failed to set Paramap analysis type")
self._view_coordinator.show_error(f"Failed to set {selected_type} analysis type")
else:
self._view_coordinator.show_error("Paramap analysis type not available")
self._view_coordinator.show_error("No analysis types available")

def _on_user_action(self, action_name: str, action_data: Any) -> None:
"""
Expand All @@ -98,7 +109,7 @@ def _on_user_action(self, action_name: str, action_data: Any) -> None:
print(f"DEBUG: Controller received analysis_execution_started action")
print(f"DEBUG: action_data = {action_data}")
self._handle_analysis_execution(action_data)
elif action_name == "analysis_completed":
elif action_name == "analysis_loading_completed":
self._handle_analysis_completion(action_data)
else:
# Forward unknown actions to application controller
Expand Down
30 changes: 15 additions & 15 deletions src/ceus/analysis_loading/analysis_loading_view_coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@
from PyQt6.QtWidgets import QWidget, QStackedWidget
from PyQt6.QtCore import pyqtSignal

from quantus.gui.mvc.base_view import BaseViewMixin
from ..mvc.base_view import BaseViewMixin
from .views.analysis_function_selection_widget import AnalysisFunctionSelectionWidget
from quantus.gui.config_loading.views.analysis_params_widget import AnalysisParamsWidget
from .views.analysis_params_widget import AnalysisParamsWidget
from .views.analysis_execution_widget import AnalysisExecutionWidget
from quantus.data_objs import UltrasoundRfImage, BmodeSeg, RfAnalysisConfig
from quantus.analysis.paramap.framework import ParamapAnalysis
from engines.ceus.src.data_objs.image import UltrasoundImage
from engines.ceus.src.data_objs.seg import CeusSeg
from engines.ceus.src.time_series_analysis.curves.framework import CurvesAnalysis


class AnalysisLoadingViewCoordinator(QStackedWidget, BaseViewMixin):
Expand All @@ -40,19 +41,14 @@ class AnalysisLoadingViewCoordinator(QStackedWidget, BaseViewMixin):
# ============================================================================


def __init__(self, image_data: UltrasoundRfImage, seg_data: BmodeSeg, config_data: RfAnalysisConfig, parent: Optional[QWidget] = None):
def __init__(self, image_data: UltrasoundImage, seg_data: CeusSeg, config_data, parent: Optional[QWidget] = None):
super().__init__(parent)
self.__init_base_view__(parent)
self._image_data = image_data
self._seg_data = seg_data
self._config_data = config_data

print(f"DEBUG: AnalysisLoadingViewCoordinator - image_data = {image_data is not None}")
if image_data is not None:
print(f"DEBUG: AnalysisLoadingViewCoordinator - scan_name = {image_data.scan_name}")
print(f"DEBUG: AnalysisLoadingViewCoordinator - phantom_name = {image_data.phantom_name}")
else:
print(f"DEBUG: AnalysisLoadingViewCoordinator - image_data is None!")

# Widget instances
self._function_selection_widget: Optional[AnalysisFunctionSelectionWidget] = None
Expand All @@ -63,7 +59,7 @@ def __init__(self, image_data: UltrasoundRfImage, seg_data: BmodeSeg, config_dat
self._selected_analysis_type: Optional[str] = None
self._selected_functions: List[str] = []
self._analysis_params: dict = {}
self._analysis_data: Optional[ParamapAnalysis] = None
self._analysis_data: Optional[CurvesAnalysis] = None

# Note: Analysis type selection is now skipped - Paramap is automatically selected
# The controller will call show_function_selection directly
Expand Down Expand Up @@ -106,12 +102,16 @@ def show_error(self, error_message: str) -> None:
error_message: Error message to display
"""
current_widget: BaseViewMixin = self.currentWidget()
current_widget.show_error(error_message)
if current_widget:
current_widget.show_error(error_message)
else:
print(f"ERROR (no active widget): {error_message}")

def clear_error(self) -> None:
"""Clear error message in the current widget."""
current_widget: BaseViewMixin = self.currentWidget()
current_widget.clear_error()
if current_widget:
current_widget.clear_error()

# ============================================================================
# NAVIGATION METHODS - Methods to show different widgets
Expand Down Expand Up @@ -208,7 +208,7 @@ def show_analysis_execution(self, execution_summary: Dict) -> None:
self._execution_widget.clear_error()
print(f"DEBUG: show_analysis_execution completed - execution screen should be visible")

def show_analysis_results(self, analysis_data: ParamapAnalysis) -> None:
def show_analysis_results(self, analysis_data: CurvesAnalysis) -> None:
"""
Show analysis results in the execution widget.

Expand Down Expand Up @@ -260,7 +260,7 @@ def _on_execution_started(self, execution_data: dict) -> None:
self._emit_user_action("analysis_execution_started", execution_data)
print(f"DEBUG: user_action signal emitted")

def _on_analysis_confirmed(self, analysis_data: ParamapAnalysis) -> None:
def _on_analysis_confirmed(self, analysis_data: CurvesAnalysis) -> None:
"""
Handle analysis completion confirmation.

Expand Down
Loading