start threading
This commit is contained in:
+109
-19
@@ -77,11 +77,74 @@ import time
|
||||
import datetime
|
||||
import contextlib
|
||||
|
||||
import threading
|
||||
|
||||
# import watchdog.observers
|
||||
|
||||
__VERSION__ = "0.1"
|
||||
__APP_NAME__ = "Uploader"
|
||||
|
||||
# Define notification event for thread completion
|
||||
EVT_RESULT_ID = wx.NewId()
|
||||
|
||||
def EVT_RESULT(win, func):
|
||||
"""Define Result Event."""
|
||||
win.Connect(-1, -1, EVT_RESULT_ID, func)
|
||||
|
||||
class ResultEvent(wx.PyEvent):
|
||||
"""Simple event to carry arbitrary result data."""
|
||||
def __init__(self, data):
|
||||
"""Init Result Event."""
|
||||
wx.PyEvent.__init__(self)
|
||||
self.SetEventType(EVT_RESULT_ID)
|
||||
self.data = data
|
||||
|
||||
# Thread class that executes processing
|
||||
class WorkerThread(threading.Thread):
|
||||
"""Worker Thread Class."""
|
||||
def __init__(self, notify_window):
|
||||
"""Init Worker Thread Class."""
|
||||
threading.Thread.__init__(self)
|
||||
self._notify_window = notify_window
|
||||
self._want_abort = 0
|
||||
# This starts the thread running on creation, but you could
|
||||
# also make the GUI thread responsible for calling this
|
||||
self.start()
|
||||
|
||||
def run(self):
|
||||
"""Run Worker Thread."""
|
||||
# This is the code executing in the new thread. Simulation of
|
||||
# a long process (well, 10s here) as a simple loop - you will
|
||||
# need to structure your processing so that you periodically
|
||||
# peek at the abort variable
|
||||
for i in range(10):
|
||||
time.sleep(1)
|
||||
if self._want_abort:
|
||||
# Use a result of None to acknowledge the abort (of
|
||||
# course you can use whatever you'd like or even
|
||||
# a separate event type)
|
||||
wx.PostEvent(self._notify_window, ResultEvent(None))
|
||||
return
|
||||
# Here's where the result would be returned (this is an
|
||||
# example fixed result of the number 10, but it could be
|
||||
# any Python object)
|
||||
wx.PostEvent(self._notify_window, ResultEvent(10))
|
||||
|
||||
def abort(self):
|
||||
"""abort worker thread."""
|
||||
# Method for use by main thread to signal an abort
|
||||
self._want_abort = 1
|
||||
|
||||
def resource_path(relative_path):
|
||||
""" Get absolute path to resource, works for dev and for PyInstaller """
|
||||
try:
|
||||
# PyInstaller creates a temp folder and stores path in _MEIPASS
|
||||
base_path = sys._MEIPASS
|
||||
except Exception:
|
||||
base_path = os.path.abspath(".")
|
||||
|
||||
return os.path.join(base_path, relative_path)
|
||||
|
||||
anonymizer = dicognito.anonymizer.Anonymizer()
|
||||
|
||||
# determine if application is a script file or frozen exe
|
||||
@@ -194,6 +257,7 @@ def annonymise(
|
||||
i += 1
|
||||
# new_filepath = Path(output_dir).joinpath(f"IMG_{i:03}.dcm")
|
||||
|
||||
logger.debug(f"anon: {n}")
|
||||
anonymize_file(file, new_filepath)
|
||||
|
||||
# progress_dialog.Destroy()
|
||||
@@ -201,6 +265,7 @@ def annonymise(
|
||||
return new_filepath
|
||||
|
||||
|
||||
@logger.catch()
|
||||
def anonymize_file(file: Path, new_filepath: Path, remove_original: bool = False):
|
||||
logger.debug(f"Annonymise file, in={file}, out={new_filepath}")
|
||||
# Ensure the output folder exists
|
||||
@@ -517,6 +582,8 @@ class AnonGui(wx.App):
|
||||
|
||||
self.rqst = None
|
||||
|
||||
self.worker = None
|
||||
|
||||
wx.App.__init__(self, redirect, filename)
|
||||
|
||||
def my_listener(self, message, arg2=None):
|
||||
@@ -571,7 +638,7 @@ class AnonGui(wx.App):
|
||||
size=(300, 400),
|
||||
)
|
||||
|
||||
self.frame.SetIcon(wx.Icon("icon/icon1.ico"))
|
||||
self.frame.SetIcon(wx.Icon(resource_path("icon\icon1.ico")))
|
||||
|
||||
self.panel = wx.Panel(self.frame, wx.ID_ANY)
|
||||
|
||||
@@ -834,6 +901,16 @@ class AnonGui(wx.App):
|
||||
if input_dir.is_dir():
|
||||
logger.debug("is dir")
|
||||
files = list(Path(input_dir).rglob("*.dcm"))
|
||||
|
||||
if not files:
|
||||
# TODO load from DICOMDIR
|
||||
to_exclude = ("DICOMDIR")
|
||||
files = [i for i in Path(input_dir).rglob("*") if i.is_file() and i.name not in to_exclude]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
else:
|
||||
return
|
||||
|
||||
@@ -859,20 +936,25 @@ class AnonGui(wx.App):
|
||||
with self.progress(len(files), "Annonymise files") as p:
|
||||
# p.SetRange(len(files))
|
||||
|
||||
i: int = 0
|
||||
for n, file in enumerate(files):
|
||||
# progress_dialog.Update(n)
|
||||
p.update(n)
|
||||
new_filepath: Path
|
||||
# Get next available filename
|
||||
i: int = 0
|
||||
while os.path.exists(
|
||||
new_filepath := output_dir.joinpath(f"IMG_{i:03}.dcm")
|
||||
):
|
||||
i += 1
|
||||
# new_filepath = Path(output_dir).joinpath(f"IMG_{i:03}.dcm")
|
||||
|
||||
dataset, filepath = anonymize_file(file, new_filepath, remove_original=remove_original)
|
||||
self.add_datails_to_file_detail_map(dataset, filepath)
|
||||
logger.debug(f"anon: {n}")
|
||||
try:
|
||||
dataset, filepath = anonymize_file(file, new_filepath, remove_original=remove_original)
|
||||
except pydicom.errors.InvalidDicomError:
|
||||
continue
|
||||
self.add_datails_to_file_detail_map(dataset, filepath)
|
||||
wx.GetApp().Yield()
|
||||
# progress_dialog.Destroy()
|
||||
|
||||
self.LoadDir(self.dir)
|
||||
@@ -942,7 +1024,7 @@ base site url: {self.base_site_url}
|
||||
info.SetName(__APP_NAME__)
|
||||
info.SetVersion(__VERSION__)
|
||||
info.SetDescription(description)
|
||||
icon_path = "icon/icon1.png"
|
||||
icon_path = resource_path("icon\icon1.png")
|
||||
desired_width = 200
|
||||
desired_height = 200
|
||||
|
||||
@@ -1136,7 +1218,12 @@ base site url: {self.base_site_url}
|
||||
files = [Path(self.dir, f) for f, file_hash in files]
|
||||
|
||||
for f in files:
|
||||
os.remove(f)
|
||||
try:
|
||||
os.remove(f)
|
||||
except OSError:
|
||||
logger.debug(f"File to delete not found: {f}")
|
||||
pass
|
||||
|
||||
|
||||
if load_dir:
|
||||
self.LoadDir(clear_file_detail_map=True)
|
||||
@@ -1252,20 +1339,22 @@ base site url: {self.base_site_url}
|
||||
hashes = []
|
||||
|
||||
for n, f in enumerate(self.files):
|
||||
logger.debug(f"update {n}")
|
||||
# progress_dialog.Update(n)
|
||||
p.update(n)
|
||||
#p.update(n)
|
||||
# dataset = pydicom.read_file(f)
|
||||
|
||||
if f in self.file_detail_map:
|
||||
d, hash, d2 = self.file_detail_map[f]
|
||||
print(f"{n}: in map")
|
||||
#print(f"{n}: in map")
|
||||
else:
|
||||
logger.debug("read: {f}")
|
||||
try:
|
||||
dataset = pydicom.dcmread(f)
|
||||
except FileNotFoundError:
|
||||
return
|
||||
|
||||
print("recalc")
|
||||
#print("recalc")
|
||||
d, hash, d2 = self.add_datails_to_file_detail_map(dataset, f)
|
||||
|
||||
hashes.append(hash)
|
||||
@@ -1283,18 +1372,18 @@ base site url: {self.base_site_url}
|
||||
except:
|
||||
logger.debug(f"Unable to get Series Instance UID: {f.name}")
|
||||
|
||||
logger.debug(d)
|
||||
DATA[n] = d
|
||||
self.list_ctrl.Append(d)
|
||||
self.list_ctrl.SetItemPyData(n, {"file": f, "hash": hash})
|
||||
self.list_ctrl.SetItemData(n, n)
|
||||
#logger.debug(d)
|
||||
#DATA[n] = d
|
||||
#self.list_ctrl.Append(d)
|
||||
#self.list_ctrl.SetItemPyData(n, {"file": f, "hash": hash})
|
||||
##self.list_ctrl.SetItemData(n, n)
|
||||
|
||||
if f in self.file_duplicate_check:
|
||||
if self.file_duplicate_check[f]["id"]:
|
||||
self.list_ctrl.SetItemBackgroundColour(n, wx.RED)
|
||||
|
||||
n = n + 1
|
||||
self.list_ctrl.UpdateData(DATA)
|
||||
#self.list_ctrl.UpdateData(DATA)
|
||||
self.populate_series_grid()
|
||||
|
||||
self.frame.Refresh()
|
||||
@@ -1347,9 +1436,9 @@ base site url: {self.base_site_url}
|
||||
duplicate_files_not_uploaded = []
|
||||
logger.debug("Upload files")
|
||||
for f in self.files:
|
||||
if f in self.file_duplicate_check:
|
||||
# duplicate the api return format so ClearFiles works
|
||||
duplicate_files_not_uploaded.append((f.name, "..."))
|
||||
if f in self.file_duplicate_check and self.file_duplicate_check[f]["id"]:
|
||||
# duplicate the api return format so ClearFiles works
|
||||
duplicate_files_not_uploaded.append((f.name, "..."))
|
||||
else:
|
||||
files_to_upload.append(("files", open(str(f), "rb")))
|
||||
|
||||
@@ -1420,7 +1509,7 @@ base site url: {self.base_site_url}
|
||||
if self.clear_files_on_upload:
|
||||
all_files = upload_file_list + duplicate_file_list + duplicate_files_not_uploaded
|
||||
print(all_files)
|
||||
self.ClearFiles(event=None, load_dir=True, files=all_files)
|
||||
wx.CallAfter(self.ClearFiles,event=None, load_dir=True, files=all_files)
|
||||
|
||||
def upload_complete_message(self, upload_file_list, duplicate_file_list, failed, duplicate_files_not_uploaded):
|
||||
wx.MessageBox(
|
||||
@@ -1501,3 +1590,4 @@ def launchGUI(
|
||||
|
||||
if __name__ == "__main__":
|
||||
app()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user