Skip to content
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

silx view: Added --slices option #3860

Merged
merged 9 commits into from
Jul 20, 2023
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
4 changes: 2 additions & 2 deletions ci/appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ environment:
WITH_GL_TEST: True
PIP_OPTIONS: "-q --pre"

# Python 3.7
- PYTHON_DIR: "C:\\Python37-x64"
# Python 3.9
- PYTHON_DIR: "C:\\Python39-x64"
QT_BINDING: "PySide6"
WITH_GL_TEST: False # OpenGL not working
PIP_OPTIONS: "-q --pre"
Expand Down
50 changes: 42 additions & 8 deletions doc/source/applications/view.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,25 +41,59 @@ and to view this data in plot widgets or in simple table views.
Usage
-----

::
.. code-block:: none

silx view [-h] [--debug] [--use-opengl-plot] [files [files ...]]
silx view [-h] [--slices SLICES [SLICES ...]] [--debug] [--use-opengl-plot] [-f] [--hdf5-file-locking] [files ...]


Options
-------

-h, --help Show this help message and exit
--debug Set logging system in debug mode
--use-opengl-plot Use OpenGL for plots (instead of matplotlib)
-f, --fresh Start the application using new fresh user preferences
--hdf5-file-locking Start the application with HDF5 file locking enabled (it is disabled by default)
.. code-block:: none

-h, --help show this help message and exit
--slices SLICES [SLICES ...]
List of slice indices to open (Only for dataset)
--debug Set logging system in debug mode
--use-opengl-plot Use OpenGL for plots (instead of matplotlib)
-f, --fresh Start the application using new fresh user preferences
--hdf5-file-locking Start the application with HDF5 file locking enabled (it is disabled by
default)

Examples of usage
-----------------

::
Open file(s)
............

.. code-block:: none

silx view 31oct98.dat
silx view *.edf
silx view myfile.h5


Open HDF5 dataset(s)
....................

Using the HDF5 path to the dataset:

.. code-block:: none

silx view my_hdf5_file.h5::entry/instrument/detector/data

Using wildcard:

.. code-block:: none

silx view my_hdf5_file.h5::entry/*/data


Open HDF5 dataset slices
........................

Open first and last slices of datasets:

.. code-block:: none

silx view my_hdf5_file.h5::entry/*/data --slices 0 -1
30 changes: 23 additions & 7 deletions src/silx/app/utils/parseutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,13 @@
# ############################################################################*/
"""Utils related to parsing"""

from __future__ import annotations

__authors__ = ["V. Valls"]
__license__ = "MIT"
__date__ = "28/05/2018"

from collections.abc import Sequence
import glob
import logging
from typing import Generator, Iterable, Union, Any, Optional
Expand Down Expand Up @@ -69,14 +72,19 @@ def to_bool(thing: Any, default: Optional[bool]=None) -> bool:
raise


def filenames_to_dataurls(filenames: Iterable[Union[str, Path]]) -> Generator[object, None, None]:
def filenames_to_dataurls(
filenames: Iterable[Union[str, Path]],
slices: Sequence[int]=tuple(),
) -> Generator[object, None, None]:
"""Expand filenames and HDF5 data path in files input argument"""
# Imports here so they are performed after setting HDF5_USE_FILE_LOCKING and logging level
import silx.io
from silx.io.utils import match
from silx.io.url import DataUrl
import silx.utils.files

extra_slices = tuple(slices)

for filename in filenames:
url = DataUrl(filename)

Expand All @@ -94,13 +102,21 @@ def filenames_to_dataurls(filenames: Iterable[Union[str, Path]]) -> Generator[ob
else:
data_paths = [url.data_path()]

if not extra_slices:
data_slices = (url.data_slice(),)
elif not url.data_slice():
data_slices = extra_slices
else:
data_slices = [tuple(url.data_slice()) + (s,) for s in extra_slices]

for data_path in data_paths:
yield DataUrl(
file_path=file_path,
data_path=data_path,
data_slice=url.data_slice(),
scheme=url.scheme(),
)
for data_slice in data_slices:
yield DataUrl(
file_path=file_path,
data_path=data_path,
data_slice=data_slice,
scheme=url.scheme(),
)


def to_enum(thing: Any, enum_type, default: Optional[object]=None):
Expand Down
10 changes: 9 additions & 1 deletion src/silx/app/view/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ def createParser():
'files',
nargs=argparse.ZERO_OR_MORE,
help='Data file to show (h5 file, edf files, spec files)')
parser.add_argument(
'--slices',
dest='slices',
default=tuple(),
type=int,
nargs='+',
help='List of slice indices to open (Only for dataset)',
)
Copy link
Contributor

@vallsv vallsv Jun 16, 2023

Choose a reason for hiding this comment

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

I think it would be better to use a real slice here

--slice 1,2,3

instead of

--slice 1 2 3

As we already have the parser from the DataUrl, it's costless, and it will support stuffs like 1::2,:10,...

Copy link
Member Author

@t20100 t20100 Jun 16, 2023

Choose a reason for hiding this comment

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

--slice 1 2 3 opens not just one slice (data[1,2,3]) as a dataset but 3 slices as 3 different datasets: data[1], data[2], data[3].
Maybe best to call it --slices.

I haven't done it, but we could also support --slice 1::4,:10,...,1 3:5,:,1 if needed.... but the current main need is to open slices in a 3D stack.

parser.add_argument(
'--debug',
dest="debug",
Expand Down Expand Up @@ -151,7 +159,7 @@ def sigintHandler(*args):
# It have to be done after the settings (after the Viewer creation)
silx.config.DEFAULT_PLOT_BACKEND = "opengl"

for url in parseutils.filenames_to_dataurls(options.files):
for url in parseutils.filenames_to_dataurls(options.files, options.slices):
# TODO: Would be nice to add a process widget and a cancel button
try:
window.appendFile(url.path())
Expand Down
4 changes: 4 additions & 0 deletions src/silx/gui/data/DataViewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,10 @@ def __updateDataInView(self):
def __setDataInView(self):
self.__currentView.setData(self.__displayedData)
self.__currentView.setDataSelection(self.__displayedSelection)

if self.__displayedSelection is None:
return

# Emit signal only when selection has changed
if (self.__previousSelection.slice != self.__displayedSelection.slice or
self.__previousSelection.permutation != self.__displayedSelection.permutation
Expand Down
12 changes: 9 additions & 3 deletions src/silx/gui/hdf5/Hdf5TreeModel.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
from .Hdf5LoadingItem import Hdf5LoadingItem
from . import _utils
from ... import io as silx_io
from ...io._sliceh5 import DatasetSlice

import h5py

Expand All @@ -61,6 +62,8 @@ def _createRootLabel(h5obj):
if path.startswith("/"):
path = path[1:]
label = "%s::%s" % (filename, path)
if isinstance(h5obj, DatasetSlice):
label += str(list(h5obj.indices))
Comment on lines +65 to +66
Copy link
Member Author

Choose a reason for hiding this comment

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

I'm not a fan of having specific code for DatasetSlice here, but I couldn't find a better way, except maybe adding this in the silx.io.commonh5 API...

return label


Expand Down Expand Up @@ -573,9 +576,12 @@ def __areH5pyObjectEqual(obj1, obj2):
if not isinstance(obj2, type(obj1)):
return False
def key(item):
if item.file is None:
return item.name
return item.file.filename, item.file.mode, item.name
info = [item.name]
if item.file is not None:
info += [item.file.filename, item.file.mode]
if isinstance(item, DatasetSlice):
info.append(item.indices)
Comment on lines +582 to +583
Copy link
Member Author

Choose a reason for hiding this comment

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

Same, it'd be best to avoid specific code here.
I wanted to rework the way to check equality, but that's complex changes

return tuple(info)
return key(obj1) == key(obj2)

def h5pyObjectRow(self, h5pyObject):
Expand Down
7 changes: 4 additions & 3 deletions src/silx/gui/plot/tools/profile/core.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# /*##########################################################################
#
# Copyright (c) 2018-2020 European Synchrotron Radiation Facility
# Copyright (c) 2018-2023 European Synchrotron Radiation Facility
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
Expand Down Expand Up @@ -37,6 +37,7 @@
from silx.image.bilinear import BilinearImage
from silx.gui import qt
from silx.gui import colors
import silx.gui.plot.items


class CurveProfileData(typing.NamedTuple):
Expand Down Expand Up @@ -120,7 +121,7 @@ def invalidateProperties(self):
def _setPlotItem(self, plotItem):
"""Specify the plot item to use with this profile

:param `~silx.gui.plot.items.item.Item` plotItem: A plot item
:param `~silx.gui.plot.items.Item` plotItem: A plot item
"""
previousPlotItem = self.getPlotItem()
if previousPlotItem is plotItem:
Expand All @@ -131,7 +132,7 @@ def _setPlotItem(self, plotItem):
def getPlotItem(self):
"""Returns the plot item used by this profile

:rtype: `~silx.gui.plot.items.item.Item`
:rtype: `~silx.gui.plot.items.Item`
"""
if self.__plotItem is None:
return None
Expand Down
Loading