Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion src/Model/NiftiToRtstructConverter.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ def nifti_to_rtstruct_conversion(nifti_path: str, dicom_path: str, output_path:
try:
for img_path in nifti_files_list:
_process_nifti_file(str(img_path), dicom_img, rtstruct, segment_name_map)
rtstruct.save(rtss_path)
rtstruct.save(str(rtss_path))
return True
except Exception as e:
logger.error(f"Conversion failed: {type(e).__name__}: {e}")
Expand Down
2 changes: 1 addition & 1 deletion src/Model/VTKEngine.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ def cleanup_old_dicom_temp_dirs(temp_root=None):

# ------------------------------ VTK Processing Engine ------------------------------

WINDOW_DEFAULT = 390
WINDOW_DEFAULT = 400
LEVEL_DEFAULT = 40

class VTKEngine:
Expand Down
37 changes: 15 additions & 22 deletions src/Model/Windowing.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,22 @@ def windowing_model(text, init):
"""
patient_dict_container = PatientDictContainer()


# Use custom window/level for manual fusion overlays (init[3])
#TODO This is just a patch. Need to figure out why VTK doesnt work with default dicom windowing
if init[3]:
# You can use a custom dictionary here, or load from MovingDictContainer
moving_dict_container = MovingDictContainer()
dict_windowing_moving = moving_dict_container.get("dict_windowing_moving")
if dict_windowing_moving and text in dict_windowing_moving:
windowing_limits = dict_windowing_moving[text]
else:
# Fallback to a hardcoded set or the fixed image's presets
custom_presets = {
"Normal": [390, 40], # Soft tissue, covers -160 to 240 HU
"Lung": [1600, -600], # Lung, covers -1400 to 200 HU
"Bone": [2000, 300], # Bone, covers -700 to 1300 HU
"Brain": [80, 40], # Brain, covers 0 to 80 HU
"Soft Tissue": [440, 40], # Alias for Normal
"Head and Neck": [275, 40], # Covers -147.5 to 227.5 HU
}
windowing_limits = custom_presets.get(text, [400, 40])
custom_presets = {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is essentially a fixed dictionary, unless it's being updated elsewhere.
And for these hardcoded settings, it is a fixed dictionary:
WINDOW_LEVEL_PRESETS = { "LUNG": [1600, -600], ...}
DEFAULT_PRESET = WINDOW_LEVEL_PRESETS["NORMAL"]
And then just do the lookup
windowing_limits = WINDOW_LEVEL_PRESETS.get(text, DEFAULT_PRESET)

"Normal": [400, 40], # Normal levels (typical soft tissue window)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is Normal supposed to be the same as Soft Tissue or not? [400,40] != [440,40]
If it's not supposed to be the same thing, then explain why Normal is almost the same but not quite.

"Lung": [1600, -600], # Lung, covers -1400 to 200 HU
"Bone": [2000, 300], # Bone, covers -700 to 1300 HU
"Brain": [80, 40], # Brain, covers 0 to 80 HU
"Soft Tissue": [440, 40], # Soft tissue, covers -180 to 260 HU (muscle, fat, organs)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the window is the difference between the two HU values (upper - lower).
And the window centre in HU is (upper+lower)/2.
It might be better to have a dictionary of HOUNSFIELD_UPPER_LOWER_BOUNDS so the physics is clear regarding what is going on, and then calculate (in to a constant dictionary) for CUSTOM_PRESETS from that.

"Head and Neck": [275, 40], # Covers -147.5 to 227.5 HU
}
windowing_limits = custom_presets.get(text, [400, 40])
else:
windowing_limits = patient_dict_container.get("dict_windowing")[text]

# Set window and level to the new values
window = windowing_limits[0]
level = windowing_limits[1]

Expand Down Expand Up @@ -110,12 +103,14 @@ def windowing_model_direct(window, level, init, fixed_image_array=None):
'windowing_slider' in globals()
and windowing_slider is not None
and hasattr(windowing_slider, "fusion_views")
and windowing_slider.fusion_views is not None
and windowing_slider.fusion_views
):
for view in windowing_slider.fusion_views:
if hasattr(view, "vtk_engine") and view.vtk_engine is not None:

view.vtk_engine.set_window_level(float(window), float(level))
if hasattr(view, "update_color_overlay"):

view.update_color_overlay()
# Also call the fusion window/level callback if present (ensures views update)
if hasattr(windowing_slider, "fusion_window_level_callback") and callable(
Expand Down Expand Up @@ -146,7 +141,5 @@ def set_windowing_slider(slider, fusion_views=None):
global windowing_slider
windowing_slider = slider

if fusion_views is not None:
windowing_slider.fusion_views = fusion_views
elif hasattr(windowing_slider, "fusion_views"):
windowing_slider.fusion_views = None
windowing_slider.fusion_views = fusion_views if fusion_views is not None else []

2 changes: 1 addition & 1 deletion src/View/mainpage/WindowingSlider.py
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ def mouse_release(self, event):

# Apply the window/level changes using the model
with wait_cursor():
windowing_model_direct(level, window, send)
windowing_model_direct(window, level, send)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd need to see the history of this to understand why this is being reversed in terms of window/level.
This seems very risky, and may imply that the verification testing is not including adequate regression testing.

Copy link
Collaborator Author

@Nowhere4Nothing Nowhere4Nothing Oct 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in a previous PR
#386
i mistook you thinking u said swap them so i did. I should of asked you to clarify. My bad

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in a previous PR #386 i mistook you thinking u said swap them so i did. I should of asked you to clarify

OK. "Almost looks like" should be interpreted as "go investigate and trace to the bottom to make sure that these are being passed in correctly".


# Update fusion overlays if present
try:
Expand Down
Loading