Skip to content

Commit

Permalink
Merge branch 'invesalius:master' into navigation-volume-maximize
Browse files Browse the repository at this point in the history
  • Loading branch information
Hafsa-shoaib989 authored Sep 27, 2024
2 parents ffd8aff + 8a97f49 commit 27cab37
Show file tree
Hide file tree
Showing 93 changed files with 928 additions and 2,913 deletions.
96 changes: 56 additions & 40 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@
# detalhes.
# -------------------------------------------------------------------------

from __future__ import print_function

import argparse
import multiprocessing
import os
Expand Down Expand Up @@ -53,11 +51,7 @@
os.environ["GDK_BACKEND"] = "x11"

import wx

try:
from wx.adv import SplashScreen
except ImportError:
from wx import SplashScreen
from wx.adv import SPLASH_CENTRE_ON_SCREEN, SPLASH_TIMEOUT, SplashScreen

# import wx.lib.agw.advancedsplash as agw
# if sys.platform.startswith('linux'):
Expand All @@ -66,6 +60,7 @@
# if sys.platform != 'darwin':
# _SplashScreen = wx.SplashScreen
import invesalius.gui.language_dialog as lang_dlg
import invesalius.gui.log as log
import invesalius.i18n as i18n
import invesalius.session as ses
import invesalius.utils as utils
Expand All @@ -78,13 +73,8 @@
# ------------------------------------------------------------------

if sys.platform in ("linux2", "linux", "win32"):
try:
tmp_var = wx.GetXDisplay
except AttributeError:
# A workaround to make InVesalius run with wxPython4 from Ubuntu 18.04
wx.GetXDisplay = lambda: None
else:
del tmp_var
if not hasattr(wx, "GetXDisplay"):
setattr(wx, "GetXDisplay", lambda: None)


session = ses.Session()
Expand All @@ -96,8 +86,6 @@
except FileNotFoundError:
pass

import invesalius.gui.log as log


class InVesalius(wx.App):
"""
Expand Down Expand Up @@ -203,7 +191,7 @@ def __init__(self):
icon_file = "splash_" + lang + ".png"

if hasattr(sys, "frozen") and (
sys.frozen == "windows_exe" or sys.frozen == "console_exe"
getattr(sys, "frozen") == "windows_exe" or getattr(sys, "frozen") == "console_exe"
):
abs_file_path = os.path.abspath(".." + os.sep)
path = abs_file_path
Expand All @@ -215,10 +203,7 @@ def __init__(self):

bmp = wx.Image(path).ConvertToBitmap()

try:
style = wx.adv.SPLASH_TIMEOUT | wx.adv.SPLASH_CENTRE_ON_SCREEN
except AttributeError:
style = wx.SPLASH_TIMEOUT | wx.SPLASH_CENTRE_ON_SCREEN
style = SPLASH_TIMEOUT | SPLASH_CENTRE_ON_SCREEN

SplashScreen.__init__(
self, bitmap=bmp, splashStyle=style, milliseconds=1500, id=-1, parent=None
Expand All @@ -232,7 +217,6 @@ def Startup(self):
# while splash is being shown
from invesalius.control import Controller
from invesalius.gui.frame import Frame
from invesalius.project import Project

self.main = Frame(None)
self.control = Controller(self.main)
Expand Down Expand Up @@ -289,14 +273,13 @@ def non_gui_startup(args):
_ = i18n.InstallLanguage(lang)

from invesalius.control import Controller
from invesalius.project import Project

session = ses.Session()
if not session.ReadConfig():
session.CreateConfig()
session.SetConfig("language", lang)

control = Controller(None)
_ = Controller(None)

use_cmd_optargs(args)

Expand Down Expand Up @@ -362,6 +345,8 @@ def parse_command_line():
help="Debug navigated TMS E-field computation",
)

parser.add_argument("--cranioplasty", help="Creates an AI-based cranioplasty implant.")

args = parser.parse_args()
return args

Expand All @@ -375,24 +360,31 @@ def use_cmd_optargs(args):
if args.save:
Publisher.sendMessage("Save project", filepath=os.path.abspath(args.save))
exit(0)

check_for_export(args)

if args.cranioplasty:
check_for_cranioplasty(args)
else:
check_for_export(args)
return True

elif args.import_folder:
Publisher.sendMessage("Import folder", folder=args.import_folder)
if args.save:
Publisher.sendMessage("Save project", filepath=os.path.abspath(args.save))
exit(0)
check_for_export(args)
if args.cranioplasty:
check_for_cranioplasty(args)
else:
check_for_export(args)

elif args.other_file:
Publisher.sendMessage("Open other files", filepath=args.other_file)
if args.save:
Publisher.sendMessage("Save project", filepath=os.path.abspath(args.save))
exit(0)
check_for_export(args)
if args.cranioplasty:
check_for_cranioplasty(args)
else:
check_for_export(args)

elif args.import_all:
import invesalius.reader.dicom_reader as dcm
Expand Down Expand Up @@ -425,6 +417,29 @@ def use_cmd_optargs(args):
return False


def check_for_cranioplasty(args):
import invesalius.constants as const
from invesalius.i18n import tr as _

if args.cranioplasty:
from invesalius.data import slice_
from invesalius.project import Project

# create cranium mask
Publisher.sendMessage("Update threshold limits", threshold_range=(226, 3071))
Publisher.sendMessage("Appy threshold all slices")

# create implant mask
Publisher.sendMessage("Create implant for cranioplasty")

path_ = args.export

# convert masks to surfaces and exports them.
Publisher.sendMessage(
"Export all surfaces separately", folder=path_, filetype=const.FILETYPE_STL
)


def sanitize(text):
text = str(text).strip().replace(" ", "_")
return re.sub(r"(?u)[^-\w.]", "", text)
Expand All @@ -441,9 +456,9 @@ def check_for_export(args, suffix="", remove_surfaces=False):

if suffix:
if args.export.endswith(".stl"):
path_ = "{}-{}.stl".format(args.export[:-4], suffix)
path_ = f"{args.export[:-4]}-{suffix}.stl"
else:
path_ = "{}-{}.stl".format(args.export, suffix)
path_ = f"{args.export}-{suffix}.stl"
else:
path_ = args.export

Expand All @@ -455,9 +470,9 @@ def check_for_export(args, suffix="", remove_surfaces=False):

for threshold_name, threshold_range in Project().presets.thresh_ct.items():
if isinstance(threshold_range[0], int):
path_ = "{}-{}-{}.stl".format(args.export_to_all, suffix, threshold_name)
path_ = f"{args.export_to_all}-{suffix}-{threshold_name}.stl"
export(path_, threshold_range, remove_surface=True)
except:
except Exception:
traceback.print_exc()
finally:
exit(0)
Expand All @@ -469,14 +484,15 @@ def check_for_export(args, suffix="", remove_surfaces=False):
export_filename = args.export_project
if suffix:
export_filename, ext = os.path.splitext(export_filename)
export_filename = "{}-{}{}".format(export_filename, suffix, ext)
export_filename = f"{export_filename}-{suffix}{ext}"

prj.export_project(export_filename, save_masks=args.save_masks)
print("Saved {}".format(export_filename))
print(f"Saved {export_filename}")


def export(path_, threshold_range, remove_surface=False):
import invesalius.constants as const
from invesalius.i18n import tr as _

Publisher.sendMessage("Set threshold values", threshold_range=threshold_range)

Expand Down Expand Up @@ -504,7 +520,7 @@ def print_events(topic=Publisher.AUTO_TOPIC, **msg_data):
"""
Print pubsub messages
"""
utils.debug("%s\n\tParameters: %s" % (topic, msg_data))
utils.debug(f"{topic}\n\tParameters: {msg_data}")


def init():
Expand All @@ -517,7 +533,7 @@ def init():
multiprocessing.freeze_support()

# Needed in win 32 exe
if hasattr(sys, "frozen") and sys.platform.startswith("win"):
if hasattr(sys, "frozen") and sys.platform == "win32":
# Click in the .inv3 file support
root = winreg.HKEY_CLASSES_ROOT
key = "InVesalius 3.1\InstallationDir"
Expand All @@ -532,9 +548,9 @@ def init():
if inv_paths.OLD_USER_INV_DIR.exists():
inv_paths.copy_old_files()

if hasattr(sys, "frozen") and sys.frozen == "windows_exe":
if hasattr(sys, "frozen") and getattr(sys, "frozen") == "windows_exe":
# Set system standard error output to file
path = inv_paths.USER_LOG_DIR.join("stderr.log")
path = inv_paths.USER_LOG_DIR.joinpath("stderr.log")
sys.stderr = open(path, "w")


Expand Down Expand Up @@ -586,7 +602,7 @@ def main(connection=None, remote_host=None):
if args.no_gui:
non_gui_startup(args)
else:
application = InVesalius(0)
application = InVesalius(False)
application.MainLoop()


Expand Down
4 changes: 2 additions & 2 deletions environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ channels:
- conda-forge
- bioconda
dependencies:
- python==3.11
- python==3.11.10
- cython==3.0.10
- pillow==10.3.0
- pypubsub==4.0.3
Expand All @@ -12,7 +12,6 @@ dependencies:
- numpy==1.26.4
- psutil==6.0.0
- pyserial==3.5
- pytorch==2.3.1
- requests==2.32.3
- scipy==1.14.0
- vtk==9.3.0
Expand All @@ -33,6 +32,7 @@ dependencies:
- pypolaris==0.0.7
- scikit-image==0.24.0
- scikit-learn==1.5.0
- torch==2.3.1
- Trekker==0.9
- uvicorn[standard]==0.30.1
- wxPython==4.2.1
Expand Down
Binary file added icons/robot_free_drive.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
32 changes: 17 additions & 15 deletions invesalius/control.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
from invesalius import inv_paths, plugins
from invesalius.i18n import tr as _
from invesalius.pubsub import pub as Publisher
from invesalius.segmentation.deep_learning import segment

if TYPE_CHECKING:
from pathlib import Path
Expand Down Expand Up @@ -124,6 +125,9 @@ def __bind_events(self) -> None:

Publisher.subscribe(self.LoadProject, "Load project data")

# for call cranioplasty implant by command line
Publisher.subscribe(segment.run_cranioplasty_implant, "Create implant for cranioplasty")

def SetBitmapSpacing(self, spacing: Tuple[float, float, float]) -> None:
proj = prj.Project()
proj.spacing = spacing
Expand Down Expand Up @@ -384,8 +388,6 @@ def SaveProject(self, path: Optional["str | Path"] = None, compress: bool = Fals
if isinstance(filename, str):
filename = utils.decode(filename, const.FS_ENCODE)

proj = prj.Project()

# Update progress dialog
Publisher.sendMessage(
"Update Progress bar", value=30, msg="Preparing to save project..."
Expand Down Expand Up @@ -702,13 +704,13 @@ def CreateBitmapProject(self, bmp_data, rec_data, matrix, matrix_filename):

name = rec_data[0]
orientation = rec_data[1]
sp_x = float(rec_data[2])
sp_y = float(rec_data[3])
sp_z = float(rec_data[4])
interval = int(rec_data[5])
# sp_x = float(rec_data[2])
# sp_y = float(rec_data[3])
# sp_z = float(rec_data[4])
# interval = int(rec_data[5])

bits = bmp_data.GetFirstPixelSize()
sx, sy = size = bmp_data.GetFirstBitmapSize()
# bits = bmp_data.GetFirstPixelSize()
# sx, sy = size = bmp_data.GetFirstBitmapSize()

proj = prj.Project()
proj.name = name
Expand Down Expand Up @@ -988,20 +990,20 @@ def OpenDicomGroup(

size = dicom.image.size
bits = dicom.image.bits_allocad
sop_class_uid = dicom.acquisition.sop_class_uid
# sop_class_uid = dicom.acquisition.sop_class_uid
xyspacing = dicom.image.spacing
orientation = dicom.image.orientation_label
samples_per_pixel = dicom.image.samples_per_pixel
# samples_per_pixel = dicom.image.samples_per_pixel

wl = float(dicom.image.level)
ww = float(dicom.image.window)

if sop_class_uid == "1.2.840.10008.5.1.4.1.1.7": # Secondary Capture Image Storage
use_dcmspacing = 1
else:
use_dcmspacing = 0
# if sop_class_uid == "1.2.840.10008.5.1.4.1.1.7": # Secondary Capture Image Storage
# use_dcmspacing = 1
# else:
# use_dcmspacing = 0

imagedata = None
# imagedata = None

if dicom.image.number_of_frames == 1:
sx, sy = size
Expand Down
2 changes: 1 addition & 1 deletion invesalius/data/actor_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from invesalius import inv_paths


class ActorFactory(object):
class ActorFactory:
def __init__(self):
pass

Expand Down
2 changes: 1 addition & 1 deletion invesalius/data/brainmesh_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

# import os
import pyvista
from vtkmodules.vtkCommonColor import vtkColorSeries, vtkNamedColors
from vtkmodules.vtkCommonColor import vtkColorSeries

# import Trekker
from vtkmodules.vtkCommonCore import (
Expand Down
4 changes: 2 additions & 2 deletions invesalius/data/coordinates.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from math import cos, sin
from random import uniform
from time import sleep
from typing import TYPE_CHECKING, Any, List, Optional, Sequence, Tuple, Union
from typing import TYPE_CHECKING, List, Optional, Sequence, Tuple, Union

import numpy as np
import wx
Expand Down Expand Up @@ -621,7 +621,7 @@ def dynamic_reference(probe, reference):
# a: rotation of plane (X, Y) around Z axis (azimuth)
# b: rotation of plane (X', Z) around Y' axis (elevation)
# a: rotation of plane (Y', Z') around X'' axis (roll)
m_rot = np.mat(
m_rot = np.asmatrix(
[
[
cos(a) * cos(b),
Expand Down
Loading

0 comments on commit 27cab37

Please sign in to comment.