Skip to content

Support Lazy Loading for Large Signals. #267

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
8 changes: 8 additions & 0 deletions hyperspyui/mainwindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,12 @@ def create_default_actions(self):
icon="open.svg",
tip="Open existing file(s)",
)
self.add_action(
"open_zspy",
"&Open zspy",
self.load_zspy,
tip="Open a zspy file",
)
self.add_action(
"open_stack",
"Open S&tack",
Expand Down Expand Up @@ -342,6 +348,8 @@ def create_menu(self):
# File menu (I/O)
self.menus["File"] = mb.addMenu(tr("&File"))
self.add_menuitem("File", self.actions["open"])
self.add_menuitem("File", self.actions["open_zspy"])

self.add_menuitem("File", self.actions["open_stack"])
self.add_menuitem("File", self.actions["close"])
self.add_menuitem("File", self.actions["save"])
Expand Down
1 change: 1 addition & 0 deletions hyperspyui/mainwindowbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ def create_default_actions(self):
ac_nested.triggered[bool].connect(self.setDockNestingEnabled)
self.actions["nested_docking"] = ac_nested


# Tile windows action
ac_tile = QtWidgets.QAction(tr("Tile"), self)
ac_tile.setStatusTip(tr("Arranges all figures in a tile pattern"))
Expand Down
32 changes: 29 additions & 3 deletions hyperspyui/mainwindowhyperspy.py
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,7 @@ def load_stack(self, filenames=None, stack_axis=None):
self.record_code(f"ui.load_stack({filenames}, {stack_axis})")
return None

def load(self, filenames=None):
def load(self, filenames=None, zspy=False):
"""
Load 'filenames', or if 'filenames' is None, open a dialog to let the
user interactively browse for files. It then load these files using
Expand All @@ -531,13 +531,29 @@ def load(self, filenames=None):
type_choices = ";;".join(["*." + e for e in extensions])
type_choices = ";;".join(("Python code (*.py)", type_choices))
type_choices = ";;".join(("All types (*.*)", type_choices))
filenames = self.prompt_files(type_choices)
filenames = self.prompt_files(type_choices, zspy=zspy)
if not filenames:
return False
self.cur_dir = filenames[0]

files_loaded = []
for filename in filenames:
logger.info(f"loading file {filename}")
try:
logger.info(f"Filesize {os.path.getsize(filename)}")
size = os.path.getsize(filename)
except FileNotFoundError:
size = 0
if size > 1e9:
msg = QMessageBox.question(self, "Lazy Loading",
"The file is larger than 1GB. Do you want to load it lazily?",
QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
lazy = msg == QMessageBox.Yes
else:
lazy = False
if zspy:
lazy = True

self.set_status('Loading "' + filename + '"...')
ext = os.path.splitext(filename)[1]
if ext == ".py":
Expand All @@ -549,7 +565,7 @@ def load(self, filenames=None):
self.setUpdatesEnabled(False) # Prevent flickering during load
try:
escaped = glob_escape.sub(r"[\1]", filename) # glob escapes
sig = hs.load(escaped)
sig = hs.load(escaped, lazy=lazy)
if isinstance(sig, list):
for s in sig:
s.plot()
Expand Down Expand Up @@ -582,6 +598,9 @@ def load(self, filenames=None):

return files_loaded

def load_zspy(self, *args, **kwargs):
return self.load(*args, **kwargs, zspy=True)

def save(self, signals=None, filenames=None):
logger.debug("entering save(), with args: %s, %s", str(signals), str(filenames))
if signals is None:
Expand Down Expand Up @@ -642,20 +661,27 @@ def get_signal_filepath_suggestion(self, signal, default_ext=None):

def dragEnterEvent(self, event):
# Check file name extensions to see if we should accept
logger.info(f"Drag enter event {event}")
extensions = set(self.get_accepted_extensions_load().union(("py",)))
mimeData = event.mimeData()
logger.info(f"mimeData {mimeData.hasUrls()}")

if mimeData.hasUrls():
pathList = [url.toLocalFile() for url in mimeData.urls()]
pathList = [url[:-1] if ".zspy/" in url else url for url in pathList]
data_ext = set([os.path.splitext(p)[1][1:] for p in pathList])
# Accept as long as we can read some of the files being dropped
if 0 < len(data_ext.intersection(extensions)):
event.acceptProposedAction()

def dropEvent(self, event):
logger.info(f"Drop event {event}")
# Something has been dropped. Try to load all file urls
mimeData = event.mimeData()
if mimeData.hasUrls():
pathList = [url.toLocalFile() for url in mimeData.urls()]
pathList = [url[:-1] if ".zspy/" in url else url for url in pathList]
logger.info(f"pathList {pathList}")
if self.load(pathList):
event.acceptProposedAction()

Expand Down
10 changes: 8 additions & 2 deletions hyperspyui/mainwindowutillayer.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,18 +317,24 @@ def make_icon(self, icon):
return icon

def prompt_files(
self, extension_filter=None, path=None, exists=True, title=None, def_filter=None
self, extension_filter=None, path=None, exists=True,
title=None, def_filter=None, zspy=False
):
if title is None:
title = tr("Load file") if exists else tr("Save file")
path = path or self.cur_dir or ""
if def_filter is None and extension_filter:
def_filter = extension_filter.split(";;", maxsplit=1)[0]

if exists:
if exists and not zspy:
filenames = QtWidgets.QFileDialog.getOpenFileNames(
self, title, path, extension_filter
)
elif exists and zspy:
filenames = QtWidgets.QFileDialog.getExistingDirectory(
self, title, path,)
_logger.info(f"filenames: {filenames}")
filenames = [filenames,] # needs to be a list ...
else:
filenames = QtWidgets.QFileDialog.getSaveFileName(
self, title, path, extension_filter, def_filter
Expand Down
Empty file added hyperspyui/tests/__init__.py
Empty file.
Loading