Commit 24de58350db20db24f2267d4ac91feaaf9f24341

Authored by okahilak
Committed by GitHub
1 parent 9d79c88d
Exists in master

ADD: Remote control via Socket.IO (#282)

* ADD: Remote control via Socket.IO

- Add a command line option (--remote-host) to connect to
  a remote server via Socket.IO.

- Add a hook to send all internal events to the remote server using
  `from_neuronavigation` event.

- Add a Socket.IO event listener for `to_neuronavigation` events, send
  publish those events internally.

* FIX: WxPython-UI modifying Socket.IO messages not working

* FIX: Allow sending message to neuronavigation with data None

* Review comments: Create RemoteControl class under invesalius/net

* Review comments: Move invesalius_pubsub dir to invesalius/pubsub

* ADD: Python modules needed by Socket.IO to requirements.txt

* MOD: Move python-socketio to optional-requirements.txt

- Also, change the requirement name from python-socketio to
  python-socketio[client], causing all dependencies needed by the Socket.IO
  client (e.g., requests) to be installed

- Due to that, remove explicit 'requests' library from the requirements

Co-authored-by: Olli-Pekka Kahilakoski <olli-pekka.kahilakoski@aalto.fi>
Showing 54 changed files with 234 additions and 52 deletions   Show diff stats
app.py
... ... @@ -51,7 +51,7 @@ try:
51 51 except ImportError:
52 52 from wx import SplashScreen
53 53  
54   -from pubsub import pub as Publisher
  54 +from invesalius.pubsub import pub as Publisher
55 55  
56 56 #import wx.lib.agw.advancedsplash as agw
57 57 #if sys.platform.startswith('linux'):
... ... @@ -323,6 +323,10 @@ def parse_comand_line():
323 323  
324 324 parser.add_option("--import-folder", action="store", dest="import_folder")
325 325  
  326 + parser.add_option("--remote-host",
  327 + action="store",
  328 + dest="remote_host")
  329 +
326 330 parser.add_option("-s", "--save",
327 331 help="Save the project after an import.")
328 332  
... ... @@ -503,6 +507,12 @@ def main():
503 507 """
504 508 options, args = parse_comand_line()
505 509  
  510 + if options.remote_host is not None:
  511 + from invesalius.net.remote_control import RemoteControl
  512 +
  513 + remote_control = RemoteControl(options.remote_host)
  514 + remote_control.connect()
  515 +
506 516 if options.no_gui:
507 517 non_gui_startup(options, args)
508 518 else:
... ...
docs/devel/example_pubsub.py
... ... @@ -3,7 +3,7 @@
3 3 # More information about this design pattern can be found at:
4 4 # http://wiki.wxpython.org/ModelViewController
5 5 # http://wiki.wxpython.org/PubSub
6   -from pubsub import pub as Publisher
  6 +from invesalius.pubsub import pub as Publisher
7 7  
8 8 # The maintainer of Pubsub module is Oliver Schoenborn.
9 9 # Since the end of 2006 Pubsub is now maintained separately on SourceForge at:
... ...
docs/devel/example_singleton_pubsub.py
1 1 # Singleton and Publisher-Subscriber design patterns example.
2 2  
3   -from pubsub import pub as Publisher
  3 +from invesalius.pubsub import pub as Publisher
4 4  
5 5 class Singleton(type):
6 6 # This is a Gary Robinson implementation:
... ...
invesalius/control.py
... ... @@ -24,7 +24,7 @@ import textwrap
24 24 import wx
25 25 import numpy as np
26 26  
27   -from pubsub import pub as Publisher
  27 +from invesalius.pubsub import pub as Publisher
28 28  
29 29 import invesalius.constants as const
30 30 import invesalius.data.imagedata_utils as image_utils
... ...
invesalius/data/coordinates.py
... ... @@ -26,7 +26,7 @@ import invesalius.constants as const
26 26  
27 27 from time import sleep
28 28 from random import uniform
29   -from pubsub import pub as Publisher
  29 +from invesalius.pubsub import pub as Publisher
30 30  
31 31  
32 32 def GetCoordinates(trck_init, trck_id, ref_mode):
... ...
invesalius/data/editor.py
... ... @@ -18,7 +18,7 @@
18 18 #--------------------------------------------------------------------------
19 19  
20 20 import math
21   -from pubsub import pub as Publisher
  21 +from invesalius.pubsub import pub as Publisher
22 22 import vtk
23 23  
24 24 AXIAL = 2
... ...
invesalius/data/geometry.py
... ... @@ -22,7 +22,7 @@ import math
22 22  
23 23 import numpy as np
24 24 import vtk
25   -from pubsub import pub as Publisher
  25 +from invesalius.pubsub import pub as Publisher
26 26  
27 27 import invesalius.constants as const
28 28 import invesalius.utils as utils
... ...
invesalius/data/imagedata_utils.py
... ... @@ -27,7 +27,8 @@ import imageio
27 27 import numpy
28 28 import numpy as np
29 29 import vtk
30   -from pubsub import pub as Publisher
  30 +from invesalius.pubsub import pub as Publisher
  31 +
31 32 from scipy.ndimage import shift, zoom
32 33 from vtk.util import numpy_support
33 34  
... ...
invesalius/data/mask.py
... ... @@ -33,7 +33,7 @@ from invesalius.data.volume import VolumeMask
33 33 import numpy as np
34 34 import vtk
35 35 from invesalius_cy import floodfill
36   -from pubsub import pub as Publisher
  36 +from invesalius.pubsub import pub as Publisher
37 37 from scipy import ndimage
38 38 from vtk.util import numpy_support
39 39  
... ...
invesalius/data/measures.py
... ... @@ -4,7 +4,7 @@ import math
4 4 import random
5 5 import sys
6 6  
7   -from pubsub import pub as Publisher
  7 +from invesalius.pubsub import pub as Publisher
8 8  
9 9 import numpy as np
10 10 import vtk
... ...
invesalius/data/polydata_utils.py
... ... @@ -21,7 +21,7 @@ import sys
21 21  
22 22 import vtk
23 23 import wx
24   -from pubsub import pub as Publisher
  24 +from invesalius.pubsub import pub as Publisher
25 25  
26 26 import invesalius.constants as const
27 27 import invesalius.data.vtk_utils as vu
... ...
invesalius/data/record_coords.py
... ... @@ -23,7 +23,7 @@ import time
23 23 import wx
24 24 from numpy import array, savetxt, hstack,vstack, asarray
25 25 import invesalius.gui.dialogs as dlg
26   -from pubsub import pub as Publisher
  26 +from invesalius.pubsub import pub as Publisher
27 27  
28 28  
29 29 class Record(threading.Thread):
... ...
invesalius/data/slice_.py
... ... @@ -22,7 +22,7 @@ import tempfile
22 22 import numpy as np
23 23 import vtk
24 24 from scipy import ndimage
25   -from pubsub import pub as Publisher
  25 +from invesalius.pubsub import pub as Publisher
26 26  
27 27 import invesalius.constants as const
28 28 import invesalius.data.converters as converters
... ...
invesalius/data/styles.py
... ... @@ -31,7 +31,7 @@ from scipy import ndimage
31 31 from imageio import imsave
32 32 from scipy.ndimage import generate_binary_structure, watershed_ift
33 33 from skimage.morphology import watershed
34   -from pubsub import pub as Publisher
  34 +from invesalius.pubsub import pub as Publisher
35 35  
36 36 import invesalius.constants as const
37 37 import invesalius.data.converters as converters
... ...
invesalius/data/styles_3d.py
... ... @@ -23,7 +23,7 @@ import wx
23 23 import invesalius.constants as const
24 24 import invesalius.project as prj
25 25  
26   -from pubsub import pub as Publisher
  26 +from invesalius.pubsub import pub as Publisher
27 27  
28 28  
29 29 PROP_MEASURE = 0.8
... ...
invesalius/data/surface.py
... ... @@ -38,7 +38,7 @@ import vtk
38 38 import wx
39 39 import wx.lib.agw.genericmessagedialog as GMD
40 40  
41   -from pubsub import pub as Publisher
  41 +from invesalius.pubsub import pub as Publisher
42 42  
43 43 if sys.platform == 'win32':
44 44 try:
... ...
invesalius/data/tractography.py
... ... @@ -28,7 +28,7 @@ import time
28 28  
29 29 import numpy as np
30 30 import queue
31   -from pubsub import pub as Publisher
  31 +from invesalius.pubsub import pub as Publisher
32 32 from scipy.stats import norm
33 33 import vtk
34 34  
... ...
invesalius/data/trigger.py
... ... @@ -21,7 +21,7 @@ import threading
21 21 from time import sleep
22 22  
23 23 import wx
24   -from pubsub import pub as Publisher
  24 +from invesalius.pubsub import pub as Publisher
25 25  
26 26  
27 27 class Trigger(threading.Thread):
... ...
invesalius/data/viewer_slice.py
... ... @@ -31,7 +31,7 @@ from vtk.wx.wxVTKRenderWindowInteractor import wxVTKRenderWindowInteractor
31 31 import invesalius.data.styles as styles
32 32 import wx
33 33 import sys
34   -from pubsub import pub as Publisher
  34 +from invesalius.pubsub import pub as Publisher
35 35  
36 36 try:
37 37 from agw import floatspin as FS
... ...
invesalius/data/viewer_volume.py
... ... @@ -29,7 +29,7 @@ from numpy.core.umath_tests import inner1d
29 29 import wx
30 30 import vtk
31 31 from vtk.wx.wxVTKRenderWindowInteractor import wxVTKRenderWindowInteractor
32   -from pubsub import pub as Publisher
  32 +from invesalius.pubsub import pub as Publisher
33 33 import random
34 34 from scipy.spatial import distance
35 35  
... ... @@ -622,6 +622,7 @@ class Viewer(wx.Panel):
622 622  
623 623 self.ren.AddActor(self.staticballs[self.ball_id])
624 624 self.ball_id = self.ball_id + 1
  625 +
625 626 #self.UpdateRender()
626 627 self.Refresh()
627 628  
... ...
invesalius/data/volume.py
... ... @@ -24,7 +24,7 @@ from distutils.version import LooseVersion
24 24 import numpy
25 25 import vtk
26 26 import wx
27   -from pubsub import pub as Publisher
  27 +from invesalius.pubsub import pub as Publisher
28 28  
29 29 import invesalius.constants as const
30 30 import invesalius.project as prj
... ...
invesalius/data/vtk_utils.py
... ... @@ -20,7 +20,7 @@ import sys
20 20  
21 21 import vtk
22 22 import wx
23   -from pubsub import pub as Publisher
  23 +from invesalius.pubsub import pub as Publisher
24 24 import invesalius.constants as const
25 25 from invesalius.gui.dialogs import ProgressDialog
26 26  
... ...
invesalius/gui/bitmap_preview_panel.py
... ... @@ -5,7 +5,7 @@ import numpy
5 5  
6 6 from vtk.util import numpy_support
7 7 from vtk.wx.wxVTKRenderWindowInteractor import wxVTKRenderWindowInteractor
8   -from pubsub import pub as Publisher
  8 +from invesalius.pubsub import pub as Publisher
9 9  
10 10 import invesalius.constants as const
11 11 import invesalius.data.vtk_utils as vtku
... ...
invesalius/gui/brain_seg_dialog.py
... ... @@ -12,7 +12,7 @@ import time
12 12  
13 13 import numpy as np
14 14 import wx
15   -from pubsub import pub as Publisher
  15 +from invesalius.pubsub import pub as Publisher
16 16  
17 17 import invesalius.data.slice_ as slc
18 18 from invesalius.segmentation.brain import segment, utils
... ...
invesalius/gui/data_notebook.py
... ... @@ -34,7 +34,7 @@ except ImportError:
34 34 import wx.lib.flatnotebook as fnb
35 35  
36 36 import wx.lib.platebtn as pbtn
37   -from pubsub import pub as Publisher
  37 +from invesalius.pubsub import pub as Publisher
38 38  
39 39 import invesalius.constants as const
40 40 import invesalius.data.slice_ as slice_
... ...
invesalius/gui/default_tasks.py
... ... @@ -22,7 +22,7 @@ try:
22 22 import wx.lib.agw.foldpanelbar as fpb
23 23 except ModuleNotFoundError:
24 24 import wx.lib.foldpanelbar as fpb
25   -from pubsub import pub as Publisher
  25 +from invesalius.pubsub import pub as Publisher
26 26  
27 27 import invesalius.constants as const
28 28 import invesalius.gui.data_notebook as nb
... ...
invesalius/gui/default_viewers.py
... ... @@ -21,7 +21,7 @@ import os
21 21  
22 22 import wx
23 23 import wx.lib.agw.fourwaysplitter as fws
24   -from pubsub import pub as Publisher
  24 +from invesalius.pubsub import pub as Publisher
25 25  
26 26 import invesalius.data.viewer_slice as slice_viewer
27 27 import invesalius.data.viewer_volume as volume_viewer
... ... @@ -316,7 +316,7 @@ class VolumeInteraction(wx.Panel):
316 316  
317 317 import wx.lib.platebtn as pbtn
318 318 import wx.lib.buttons as btn
319   -from pubsub import pub as Publisher
  319 +from invesalius.pubsub import pub as Publisher
320 320 import wx.lib.colourselect as csel
321 321  
322 322 RAYCASTING_TOOLS = wx.NewId()
... ...
invesalius/gui/dialogs.py
... ... @@ -47,7 +47,7 @@ from vtk.wx.wxVTKRenderWindowInteractor import wxVTKRenderWindowInteractor
47 47 from wx.lib import masked
48 48 from wx.lib.agw import floatspin
49 49 from wx.lib.wordwrap import wordwrap
50   -from pubsub import pub as Publisher
  50 +from invesalius.pubsub import pub as Publisher
51 51  
52 52 try:
53 53 from wx.adv import AboutDialogInfo, AboutBox
... ...
invesalius/gui/dicom_preview_panel.py
... ... @@ -29,7 +29,7 @@ import vtk
29 29  
30 30 from vtk.util import numpy_support
31 31 from vtk.wx.wxVTKRenderWindowInteractor import wxVTKRenderWindowInteractor
32   -from pubsub import pub as Publisher
  32 +from invesalius.pubsub import pub as Publisher
33 33  
34 34 import invesalius.constants as const
35 35 import invesalius.reader.dicom_reader as dicom_reader
... ...
invesalius/gui/frame.py
... ... @@ -43,7 +43,7 @@ import wx.lib.popupctl as pc
43 43 from invesalius import inv_paths
44 44 from invesalius.gui import project_properties
45 45 from wx.lib.agw.aui.auibar import AUI_TB_PLAIN_BACKGROUND, AuiToolBar
46   -from pubsub import pub as Publisher
  46 +from invesalius.pubsub import pub as Publisher
47 47  
48 48 try:
49 49 from wx.adv import TaskBarIcon as wx_TaskBarIcon
... ...
invesalius/gui/import_bitmap_panel.py
... ... @@ -18,7 +18,7 @@
18 18 #--------------------------------------------------------------------------
19 19 import wx
20 20 import wx.gizmos as gizmos
21   -from pubsub import pub as Publisher
  21 +from invesalius.pubsub import pub as Publisher
22 22 import wx.lib.splitter as spl
23 23  
24 24 import invesalius.constants as const
... ...
invesalius/gui/import_network_panel.py
... ... @@ -19,7 +19,7 @@
19 19 import wx
20 20 import sys
21 21 import wx.gizmos as gizmos
22   -from pubsub import pub as Publisher
  22 +from invesalius.pubsub import pub as Publisher
23 23 import wx.lib.splitter as spl
24 24  
25 25 import invesalius.constants as const
... ...
invesalius/gui/import_panel.py
... ... @@ -18,7 +18,7 @@
18 18 #--------------------------------------------------------------------------
19 19 import wx
20 20 import wx.gizmos as gizmos
21   -from pubsub import pub as Publisher
  21 +from invesalius.pubsub import pub as Publisher
22 22 import wx.lib.splitter as spl
23 23  
24 24 import invesalius.constants as const
... ...
invesalius/gui/preferences.py
... ... @@ -4,7 +4,7 @@ import invesalius.constants as const
4 4 import invesalius.session as ses
5 5 import wx
6 6 from invesalius.gui.language_dialog import ComboBoxLanguage
7   -from pubsub import pub as Publisher
  7 +from invesalius.pubsub import pub as Publisher
8 8  
9 9  
10 10 class Preferences(wx.Dialog):
... ...
invesalius/gui/project_properties.py
... ... @@ -19,7 +19,7 @@
19 19  
20 20 import wx
21 21 import invesalius.project as prj
22   -from pubsub import pub as Publisher
  22 +from invesalius.pubsub import pub as Publisher
23 23 from invesalius.gui import utils
24 24 from invesalius import constants as const
25 25  
... ...
invesalius/gui/task_exporter.py
... ... @@ -29,7 +29,7 @@ except ImportError:
29 29 import wx.lib.hyperlink as hl
30 30  
31 31 import wx.lib.platebtn as pbtn
32   -from pubsub import pub as Publisher
  32 +from invesalius.pubsub import pub as Publisher
33 33  
34 34 import invesalius.constants as const
35 35 import invesalius.gui.dialogs as dlg
... ...
invesalius/gui/task_importer.py
... ... @@ -26,7 +26,7 @@ except ImportError:
26 26 import wx.lib.hyperlink as hl
27 27 import wx.lib.platebtn as pbtn
28 28  
29   -from pubsub import pub as Publisher
  29 +from invesalius.pubsub import pub as Publisher
30 30  
31 31 import invesalius.constants as const
32 32 import invesalius.gui.dialogs as dlg
... ...
invesalius/gui/task_navigator.py
... ... @@ -42,7 +42,7 @@ except ImportError:
42 42  
43 43 import wx.lib.colourselect as csel
44 44 import wx.lib.masked.numctrl
45   -from pubsub import pub as Publisher
  45 +from invesalius.pubsub import pub as Publisher
46 46 from time import sleep
47 47  
48 48 import invesalius.constants as const
... ...
invesalius/gui/task_slice.py
... ... @@ -31,7 +31,7 @@ except ImportError:
31 31  
32 32 import wx.lib.platebtn as pbtn
33 33 import wx.lib.colourselect as csel
34   -from pubsub import pub as Publisher
  34 +from invesalius.pubsub import pub as Publisher
35 35  
36 36 import invesalius.data.mask as mask
37 37 import invesalius.data.slice_ as slice_
... ...
invesalius/gui/task_surface.py
... ... @@ -28,7 +28,7 @@ except ImportError:
28 28 import wx.lib.hyperlink as hl
29 29 import wx.lib.foldpanelbar as fpb
30 30  
31   -from pubsub import pub as Publisher
  31 +from invesalius.pubsub import pub as Publisher
32 32 import wx.lib.colourselect as csel
33 33 import wx.lib.scrolledpanel as scrolled
34 34  
... ...
invesalius/gui/task_tools.py
... ... @@ -27,7 +27,7 @@ except ImportError:
27 27 import wx.lib.hyperlink as hl
28 28  
29 29 import wx.lib.platebtn as pbtn
30   -from pubsub import pub as Publisher
  30 +from invesalius.pubsub import pub as Publisher
31 31  
32 32 import invesalius.constants as constants
33 33 import invesalius.constants as const
... ...
invesalius/gui/widgets/canvas_renderer.py
... ... @@ -30,7 +30,7 @@ except ImportError:
30 30 from weakrefmethod import WeakMethod
31 31  
32 32 from invesalius.data import converters
33   -from pubsub import pub as Publisher
  33 +from invesalius.pubsub import pub as Publisher
34 34  
35 35  
36 36 class CanvasEvent:
... ...
invesalius/gui/widgets/clut_raycasting.py
... ... @@ -24,7 +24,7 @@ import sys
24 24  
25 25 import numpy
26 26 import wx
27   -from pubsub import pub as Publisher
  27 +from invesalius.pubsub import pub as Publisher
28 28  
29 29 import invesalius.gui.dialogs as dialog
30 30 import invesalius.constants as const
... ...
invesalius/gui/widgets/slice_menu.py
... ... @@ -26,7 +26,7 @@ except(ImportError):
26 26 from ordereddict import OrderedDict
27 27  
28 28 import wx
29   -from pubsub import pub as Publisher
  29 +from invesalius.pubsub import pub as Publisher
30 30  
31 31 import invesalius.constants as const
32 32 import invesalius.data.slice_ as sl
... ...
invesalius/net/remote_control.py 0 → 100644
... ... @@ -0,0 +1,83 @@
  1 +#!/usr/bin/env python3
  2 +#--------------------------------------------------------------------------
  3 +# Software: InVesalius - Software de Reconstrucao 3D de Imagens Medicas
  4 +# Copyright: (C) 2001 Centro de Pesquisas Renato Archer
  5 +# Homepage: http://www.softwarepublico.gov.br
  6 +# Contact: invesalius@cti.gov.br
  7 +# License: GNU - GPL 2 (LICENSE.txt/LICENCA.txt)
  8 +#--------------------------------------------------------------------------
  9 +# Este programa e software livre; voce pode redistribui-lo e/ou
  10 +# modifica-lo sob os termos da Licenca Publica Geral GNU, conforme
  11 +# publicada pela Free Software Foundation; de acordo com a versao 2
  12 +# da Licenca.
  13 +#
  14 +# Este programa eh distribuido na expectativa de ser util, mas SEM
  15 +# QUALQUER GARANTIA; sem mesmo a garantia implicita de
  16 +# COMERCIALIZACAO ou de ADEQUACAO A QUALQUER PROPOSITO EM
  17 +# PARTICULAR. Consulte a Licenca Publica Geral GNU para obter mais
  18 +# detalhes.
  19 +#-------------------------------------------------------------------------
  20 +
  21 +import time
  22 +
  23 +import socketio
  24 +import wx
  25 +
  26 +from invesalius.pubsub import pub as Publisher
  27 +
  28 +class RemoteControl:
  29 + def __init__(self, remote_host):
  30 + self._remote_host = remote_host
  31 + self._connected = False
  32 + self._sio = None
  33 +
  34 + def _on_connect(self):
  35 + print("Connected to {}".format(self._remote_host))
  36 + self._connected = True
  37 +
  38 + def _on_disconnect(self):
  39 + print("Disconnected")
  40 + self._connected = False
  41 +
  42 + def _to_neuronavigation(self, msg):
  43 + topic = msg["topic"]
  44 + data = msg["data"]
  45 + if data is None:
  46 + data = {}
  47 +
  48 + print("Received an event into topic '{}' with data {}".format(topic, str(data)))
  49 + Publisher.sendMessage_no_hook(
  50 + topicName=topic,
  51 + **data
  52 + )
  53 +
  54 + def _to_neuronavigation_wrapper(self, msg):
  55 + # wx.CallAfter wrapping is needed to make messages that update WxPython UI work properly, as the
  56 + # Socket.IO listener runs inside a thread. (See WxPython and thread-safety for more information.)
  57 + wx.CallAfter(self._to_neuronavigation, msg)
  58 +
  59 + def connect(self):
  60 + self._sio = socketio.Client()
  61 +
  62 + self._sio.on('connect', self._on_connect)
  63 + self._sio.on('disconnect', self._on_disconnect)
  64 + self._sio.on('to_neuronavigation', self._to_neuronavigation_wrapper)
  65 +
  66 + self._sio.connect(self._remote_host)
  67 +
  68 + while not self._connected:
  69 + print("Connecting...")
  70 + time.sleep(1.0)
  71 +
  72 + def _emit(topic, data):
  73 + print("Emitting data {} to topic {}".format(data, topic))
  74 + try:
  75 + if isinstance(topic, str):
  76 + self._sio.emit("from_neuronavigation", {
  77 + "topic": topic,
  78 + "data": data,
  79 + })
  80 + except TypeError:
  81 + pass
  82 +
  83 + Publisher.add_sendMessage_hook(_emit)
... ...
invesalius/plugins.py
... ... @@ -24,7 +24,7 @@ import pathlib
24 24 import sys
25 25 from itertools import chain
26 26  
27   -from pubsub import pub as Publisher
  27 +from invesalius.pubsub import pub as Publisher
28 28  
29 29 import invesalius.constants as consts
30 30 from invesalius import inv_paths
... ...
invesalius/presets.py
... ... @@ -22,7 +22,7 @@ import plistlib
22 22  
23 23 import invesalius.constants as const
24 24  
25   -from pubsub import pub as Publisher
  25 +from invesalius.pubsub import pub as Publisher
26 26  
27 27 from invesalius import inv_paths
28 28 from invesalius.utils import TwoWaysDictionary
... ...
invesalius/project.py
... ... @@ -30,7 +30,7 @@ import numpy as np
30 30 import vtk
31 31 import wx
32 32  
33   -from pubsub import pub as Publisher
  33 +from invesalius.pubsub import pub as Publisher
34 34  
35 35 import invesalius.constants as const
36 36 import invesalius.data.polydata_utils as pu
... ...
invesalius/pubsub/pub.py 0 → 100644
... ... @@ -0,0 +1,86 @@
  1 +#--------------------------------------------------------------------------
  2 +# Software: InVesalius - Software de Reconstrucao 3D de Imagens Medicas
  3 +# Copyright: (C) 2001 Centro de Pesquisas Renato Archer
  4 +# Homepage: http://www.softwarepublico.gov.br
  5 +# Contact: invesalius@cti.gov.br
  6 +# License: GNU - GPL 2 (LICENSE.txt/LICENCA.txt)
  7 +#--------------------------------------------------------------------------
  8 +# Este programa e software livre; voce pode redistribui-lo e/ou
  9 +# modifica-lo sob os termos da Licenca Publica Geral GNU, conforme
  10 +# publicada pela Free Software Foundation; de acordo com a versao 2
  11 +# da Licenca.
  12 +#
  13 +# Este programa eh distribuido na expectativa de ser util, mas SEM
  14 +# QUALQUER GARANTIA; sem mesmo a garantia implicita de
  15 +# COMERCIALIZACAO ou de ADEQUACAO A QUALQUER PROPOSITO EM
  16 +# PARTICULAR. Consulte a Licenca Publica Geral GNU para obter mais
  17 +# detalhes.
  18 +#--------------------------------------------------------------------------
  19 +
  20 +from typing import Callable
  21 +
  22 +from pubsub import pub as Publisher
  23 +from pubsub.core.listener import UserListener
  24 +
  25 +__all__ = [
  26 + # subscribing
  27 + 'subscribe',
  28 + 'unsubscribe',
  29 +
  30 + # publishing
  31 + 'sendMessage',
  32 + 'sendMessage_no_hook',
  33 +
  34 + # adding hooks
  35 + 'add_sendMessage_hook'
  36 +]
  37 +
  38 +Hook = Callable[[str, dict], None]
  39 +
  40 +sendMessage_hook: Hook = None
  41 +
  42 +def add_sendMessage_hook(hook: Hook):
  43 + """Add a hook for sending messages. The hook is a function that takes the topic
  44 + name as the first parameter and the message dict as the second parameter, and
  45 + returns None.
  46 +
  47 + :param hook:
  48 + """
  49 + global sendMessage_hook
  50 + sendMessage_hook = hook
  51 +
  52 +def subscribe(listener: UserListener, topicName: str, **curriedArgs):
  53 + """Subscribe to a topic.
  54 +
  55 + :param listener:
  56 + :param topicName:
  57 + :param curriedArgs:
  58 + """
  59 + subscribedListener, success = Publisher.subscribe(listener, topicName, **curriedArgs)
  60 + return subscribedListener, success
  61 +
  62 +def unsubscribe(*args, **kwargs):
  63 + """Unsubscribe from a topic.
  64 +
  65 + """
  66 + Publisher.unsubscribe(*args, **kwargs)
  67 +
  68 +def sendMessage(topicName: str, **msgdata):
  69 + """Send a message in a given topic.
  70 +
  71 + :param topicName:
  72 + :param msgdata:
  73 + """
  74 + Publisher.sendMessage(topicName, **msgdata)
  75 + if sendMessage_hook is not None:
  76 + sendMessage_hook(topicName, msgdata)
  77 +
  78 +def sendMessage_no_hook(topicName: str, **msgdata):
  79 + """Send a message in a given topic, but do not call the hook.
  80 +
  81 + :param topicName:
  82 + :param msgdata:
  83 + """
  84 + Publisher.sendMessage(topicName, **msgdata)
  85 +
  86 +AUTO_TOPIC = Publisher.AUTO_TOPIC
... ...
invesalius/reader/bitmap_reader.py
... ... @@ -28,7 +28,7 @@ import numpy
28 28 import vtk
29 29 import wx
30 30 from imageio import imread
31   -from pubsub import pub as Publisher
  31 +from invesalius.pubsub import pub as Publisher
32 32 from vtk.util import numpy_support
33 33  
34 34 import invesalius.constants as const
... ...
invesalius/reader/dicom_reader.py
... ... @@ -28,7 +28,7 @@ import gdcm
28 28 # Not showing GDCM warning and debug messages
29 29 gdcm.Trace_DebugOff()
30 30 gdcm.Trace_WarningOff()
31   -from pubsub import pub as Publisher
  31 +from invesalius.pubsub import pub as Publisher
32 32  
33 33 import invesalius.constants as const
34 34 import invesalius.reader.dicom as dicom
... ...
invesalius/session.py
... ... @@ -31,7 +31,7 @@ import codecs
31 31 import collections
32 32 import json
33 33  
34   -from pubsub import pub as Publisher
  34 +from invesalius.pubsub import pub as Publisher
35 35 import wx
36 36  
37 37 from invesalius.utils import Singleton, debug, decode, deep_merge_dict
... ...
invesalius/style.py
... ... @@ -17,7 +17,7 @@
17 17 # detalhes.
18 18 #--------------------------------------------------------------------------
19 19  
20   -from pubsub import pub as Publisher
  20 +from invesalius.pubsub import pub as Publisher
21 21  
22 22  
23 23 # mode.py
... ...
optional-requirements.txt
1 1 mido==1.2.10
2 2 python-rtmidi==1.4.9
  3 +python-socketio[client]==5.3.0
... ...