Commit 1e69ddb5 authored by Carsten Richter's avatar Carsten Richter

Merge branch 'use-silx-resources' into 'master'

Use silx resources management

Closes #26

See merge request !82
parents ab008a1b 86f6feb9
Pipeline #6221 passed with stages
in 9 minutes and 47 seconds
......@@ -28,12 +28,11 @@ from __future__ import absolute_import
import os
from silx.gui import qt as Qt
from silx.gui.icons import getQIcon
from silx.utils.weakref import WeakList
from .Utils import nextFileName
from .icons import getQIcon as getXsocsIcon
from .widgets.Wizard import XsocsWizard
from .widgets.ProjectChooser import ProjectChooserDialog
......@@ -313,7 +312,7 @@ class XsocsGui(Qt.QMainWindow):
actions['open'] = openAct
# create
icon = getXsocsIcon('create_project')
icon = getQIcon('xsocs:gui/icons/create_project')
createAct = Qt.QAction(icon, '&Create project', self)
createAct.setShortcuts(Qt.QKeySequence.New)
createAct.setStatusTip('Create a new project')
......
......@@ -37,12 +37,16 @@ except ImportError as e:
_logger.error("Cannot load PyQt5: PyQt5 is required to run XSocs")
raise e
from silx import resources as _silx_resources
from silx.gui import colors as _colors
# Set colormaps available from silx colormap dialog
_colors.setPreferredColormaps(
['viridis', 'magma', 'inferno', 'plasma', 'jet', 'afmhot', 'gray'])
# Add xsocs resources to silx resource management
_silx_resources.register_resource_directory('xsocs', 'xsocs.resources')
from .gui import (xsocs_main,
merge_window,
conversion_window) # noqa
......@@ -35,8 +35,8 @@ import os
from functools import partial
from silx.gui import qt as Qt
from silx.gui import icons
from .. import icons as XsocsIcons
from .FileChooser import FileChooser
from ..widgets.Containers import GroupBox
from ..process.MergeWidget import MergeWidget
......@@ -77,9 +77,9 @@ class LoadXsocsDataPage(Qt.QWizardPage):
self.__nextId = XsocsWizard.ReviewId
icon = XsocsIcons.getQPixmap('xsocs')
icon = icons.getQPixmap('xsocs:gui/icons/xsocs')
self.setPixmap(Qt.QWizard.WatermarkPixmap, icon)
icon = XsocsIcons.getQPixmap('logo')
icon = icons.getQPixmap('xsocs:gui/icons/logo')
self.setPixmap(Qt.QWizard.LogoPixmap, icon)
layout = Qt.QVBoxLayout(self)
......@@ -126,9 +126,9 @@ class SelectDataPage(Qt.QWizardPage):
self.setTitle('X-Socs')
self.setSubTitle('New project : select data to load/import.')
icon = XsocsIcons.getQPixmap('xsocs')
icon = icons.getQPixmap('xsocs:gui/icons/xsocs')
self.setPixmap(Qt.QWizard.WatermarkPixmap, icon)
icon = XsocsIcons.getQPixmap('logo')
icon = icons.getQPixmap('xsocs:gui/icons/logo')
self.setPixmap(Qt.QWizard.LogoPixmap, icon)
self.setTitle('Select input data.')
......@@ -136,13 +136,13 @@ class SelectDataPage(Qt.QWizardPage):
self.__nextId = -1
layout = Qt.QGridLayout(self)
icon = XsocsIcons.getQIcon('logo')
icon = icons.getQIcon('xsocs:gui/icons/logo')
xsocsBn = Qt.QToolButton()
xsocsBn.setIcon(icon)
layout.addWidget(xsocsBn, 1, 1)
layout.addWidget(Qt.QLabel('Load X-Socs Data (HDF5).'), 1, 2)
icon = XsocsIcons.getQIcon('spec')
icon = icons.getQIcon('xsocs:gui/icons/spec')
specBn = Qt.QToolButton()
specBn.setIcon(icon)
layout.addWidget(specBn, 2, 1)
......@@ -208,9 +208,9 @@ class ReviewProjectPage(Qt.QWizardPage):
self.setTitle('X-Socs')
self.setSubTitle('New project created.')
icon = XsocsIcons.getQPixmap('xsocs')
icon = icons.getQPixmap('xsocs:gui/icons/xsocs')
self.setPixmap(Qt.QWizard.WatermarkPixmap, icon)
icon = XsocsIcons.getQPixmap('logo')
icon = icons.getQPixmap('xsocs:gui/icons/logo')
self.setPixmap(Qt.QWizard.LogoPixmap, icon)
layout = Qt.QVBoxLayout(self)
......@@ -242,9 +242,9 @@ class IntroPage(Qt.QWizardPage):
self.setSubTitle('X-ray Strain Orientation Calculation Software')
style = Qt.QApplication.style()
icon = XsocsIcons.getQPixmap('xsocs')
icon = icons.getQPixmap('xsocs:gui/icons/xsocs')
self.setPixmap(Qt.QWizard.WatermarkPixmap, icon)
icon = XsocsIcons.getQPixmap('logo')
icon = icons.getQPixmap('xsocs:gui/icons/logo')
self.setPixmap(Qt.QWizard.LogoPixmap, icon)
layout = Qt.QGridLayout(self)
......@@ -291,9 +291,9 @@ class NewProjectPage(Qt.QWizardPage):
self.setTitle('X-Socs')
self.setSubTitle('New project : select a project directory.')
icon = XsocsIcons.getQPixmap('xsocs')
icon = icons.getQPixmap('xsocs:gui/icons/xsocs')
self.setPixmap(Qt.QWizard.WatermarkPixmap, icon)
icon = XsocsIcons.getQPixmap('logo')
icon = icons.getQPixmap('xsocs:gui/icons/logo')
self.setPixmap(Qt.QWizard.LogoPixmap, icon)
self.__nextId = XsocsWizard.SelectDataId
......@@ -360,9 +360,9 @@ class OpenProjectPage(Qt.QWizardPage):
self.setTitle('X-Socs')
self.setSubTitle('Open project : select the project file.')
icon = XsocsIcons.getQPixmap('xsocs')
icon = icons.getQPixmap('xsocs:gui/icons/xsocs')
self.setPixmap(Qt.QWizard.WatermarkPixmap, icon)
icon = XsocsIcons.getQPixmap('logo')
icon = icons.getQPixmap('xsocs:gui/icons/logo')
self.setPixmap(Qt.QWizard.LogoPixmap, icon)
layout = Qt.QVBoxLayout(self)
......
......@@ -49,7 +49,6 @@ from silx.gui.plot.matplotlib import Colormap
from ..widgets.Containers import GroupBox
from ..widgets.PointWidget import PointWidget
from ...gui.icons import getQIcon as getKmapIcon
from ..widgets.Input import StyledLineEdit
......@@ -560,7 +559,7 @@ class XsocsPlot2D(PlotWindow):
colormapBn.clicked.connect(self.__colormapBnClicked)
optionsLayoutB.addWidget(colormapBn)
icon = getKmapIcon('gears')
icon = getQIcon('xsocs:gui/icons/gears')
options = Qt.QToolButton()
options.setToolTip('Options')
......@@ -571,7 +570,9 @@ class XsocsPlot2D(PlotWindow):
# save scatter as 3D
self.__save2DAction = action = Qt.QAction(
getKmapIcon('save_2dscatter'), 'Save "2D" scatter', self)
getQIcon('xsocs:gui/icons/save_2dscatter'),
'Save "2D" scatter',
self)
action.setIconVisibleInMenu(True)
action.triggered.connect(self.__save2DTriggered)
action.setEnabled(False)
......
......@@ -42,7 +42,7 @@ import numpy as np
from silx.utils.testutils import ParametricTestCase
from xsocs import config
from xsocs.test.testfilesmanager import TestFilesManager
from xsocs.test.utils import test_resources
from xsocs.process.fit.peak_fit import PeakFitter
from xsocs.io.FitH5 import FitH5
......@@ -134,11 +134,9 @@ class TestPeakFitter(ParametricTestCase):
config.DEFAULT_PROCESS_NUMBER = 2 # Limit number of processes
cls._tmpdir = tempfile.mkdtemp()
manager = cls._manager = TestFilesManager('www.silx.org/pub/'
'xsocs/test_data/')
manager.checksum_lifetime = 0
manager.get_files('qspace')
manager.get_files('fit')
test_resources.getdir('qspace.zip')
test_resources.getdir('fit_2018_03.zip')
@classmethod
def tearDownClass(cls):
......@@ -155,8 +153,6 @@ class TestPeakFitter(ParametricTestCase):
self._tmpTestDir = None
def test_nominal(self):
manager = self._manager
keys = ['fit_f', 'qspace_f']
parameters = [
('gaussian_1.h5', 'qspace_1.h5'),
......@@ -170,8 +166,8 @@ class TestPeakFitter(ParametricTestCase):
with self.subTest(**params):
qspace_f = manager.get_file('qspace/{0}'
''.format(params['qspace_f']))
qspace_f = test_resources.getfile(
'qspace/{0}'.format(params['qspace_f']))
fit_out = os.path.join(self._tmpTestDir, params['fit_f'])
fitter = PeakFitter(qspace_f)
......@@ -186,8 +182,8 @@ class TestPeakFitter(ParametricTestCase):
results.to_fit_h5(fit_out)
fit_ref = manager.get_file('fit_2018_03/{0}'
''.format(params['fit_f']))
fit_ref = test_resources.getfile(
'fit_2018_03/{0}'.format(params['fit_f']))
fit_ref_h5 = FitH5(fit_ref)
fit_out_h5 = FitH5(fit_out)
......
......@@ -38,8 +38,7 @@ import unittest
from xsocs import config
from xsocs.test.testfilesmanager import TestFilesManager
from xsocs.test.utils import test_resources
from xsocs.process.merge.KmapMerger import KmapMerger
from xsocs.process.merge.KmapSpecParser import KmapSpecParser
......@@ -83,14 +82,10 @@ class TestMerger(unittest.TestCase):
cls._tmpdir = tempfile.mkdtemp()
cls._spec_h5 = os.path.join(cls._tmpdir, 'spec_h5.h5')
manager = cls._manager = TestFilesManager('www.silx.org/pub/'
'xsocs/test_data/spec')
manager.checksum_lifetime = 0
cls._manager.get_files('img')
cls._manager.get_files('spec')
spec_f = manager.get_file('spec/test.spec')
img_dir = manager.get_local_dir('img')
test_resources.getdir('spec.zip')
spec_f = test_resources.getfile('spec/spec/test.spec')
img_dir = os.path.dirname(
test_resources.getfile('spec/img/test_340800_0000.edf.gz'))
parser = cls._parser = KmapSpecParser(spec_f,
cls._spec_h5,
......
......@@ -36,7 +36,7 @@ import shutil
import tempfile
import unittest
from xsocs.test.testfilesmanager import TestFilesManager
from xsocs.test.utils import test_resources
from xsocs.process.merge.KmapSpecParser import KmapSpecParser
......@@ -64,13 +64,6 @@ class TestParser(unittest.TestCase):
'test_344000_0000.edf.gz',
'test_344200_0000.edf.gz'}
@classmethod
def setUpClass(cls):
cls._manager = TestFilesManager('www.silx.org/pub/'
'xsocs/test_data/spec/')
cls._manager.get_files('img')
cls._manager.get_files('spec')
def setUp(self):
self._tmpTestDir = tempfile.mkdtemp()
......@@ -81,9 +74,10 @@ class TestParser(unittest.TestCase):
def test_nominal(self):
"""
"""
manager = self._manager
spec_f = manager.get_file('spec/test.spec')
img_dir = manager.get_local_dir('img')
test_resources.getdir('spec.zip')
spec_f = test_resources.getfile('spec/spec/test.spec')
img_dir = os.path.dirname(
test_resources.getfile('spec/img/test_340800_0000.edf.gz'))
spec_h5 = os.path.join(self._tmpTestDir, 'spec.h5')
......
......@@ -39,7 +39,7 @@ import numpy as np
from silx.utils.testutils import ParametricTestCase
from xsocs import config
from xsocs.test.testfilesmanager import TestFilesManager
from xsocs.test.utils import test_resources
from xsocs.io.QSpaceH5 import QSpaceH5
from xsocs.io.XsocsH5 import XsocsH5
......@@ -54,11 +54,9 @@ class TestQSpace(ParametricTestCase):
config.DEFAULT_PROCESS_NUMBER = 2 # Limit number of processes
cls._tmpdir = tempfile.mkdtemp()
manager = cls._manager = TestFilesManager(
'www.silx.org/pub/xsocs/test_data/')
manager.checksum_lifetime = 0
manager.get_files('merged')
manager.get_files('qspace')
test_resources.getdir('merged.zip')
test_resources.getdir('qspace.zip')
@classmethod
def tearDownClass(cls):
......@@ -76,9 +74,7 @@ class TestQSpace(ParametricTestCase):
def test_nominal(self):
"""Test of QSpaceConverter"""
manager = self._manager
master_f = manager.get_file('merged/test.h5')
master_f = test_resources.getfile('merged/test.h5')
keys = ['output_f', 'medfilt_dims', 'mask']
parameters = [
......@@ -100,7 +96,7 @@ class TestQSpace(ParametricTestCase):
maskFilename = params['mask']
if maskFilename is not None: # Load mask
mask = np.load(manager.get_file('qspace/' + maskFilename))
mask = np.load(test_resources.getfile('qspace/' + maskFilename))
converter.mask = mask
converter.convert()
......@@ -109,8 +105,8 @@ class TestQSpace(ParametricTestCase):
converter.DONE,
msg=converter.status_msg)
q_ref = manager.get_file('qspace/{0}'
''.format(params['output_f']))
q_ref = test_resources.getfile(
'qspace/{0}'.format(params['output_f']))
q_out = converter.results
q_ref_h5 = QSpaceH5(q_ref)
......@@ -124,10 +120,8 @@ class TestQSpace(ParametricTestCase):
def test_normalization(self):
"""Test QSpaceConverter with normalization"""
manager = self._manager
output_f = os.path.join(self._tmpTestDir, 'qspace_normalization.h5')
master_f = manager.get_file('merged/test.h5')
master_f = test_resources.getfile('merged/test.h5')
normalizer = 'ccdint1'
master_h5 = XsocsH5(master_f)
......
......@@ -22,97 +22,4 @@
# THE SOFTWARE.
#
# ###########################################################################*/
"""Access project's data and documentation files.
All access to data and documentation files MUST be made through the functions
of this modules to ensure access accross different distribution schemes:
- Installing from source or from wheel
- Installing package as a zip (through the use of pkg_resources)
- Linux packaging willing to install data files (and doc files) in
alternative folders. In this case, this file must be patched.
- Frozen fat binary application using xsocs (forzen with cx_Freeze or py2app).
This needs special care for the resource files in the setup:
- With cx_Freeze, add xsocs/resources to include_files:
.. code-block:: python
import xsocs.resources
xsocs_include_files = (os.path.dirname(xsocs.resources.__file__),
os.path.join('xsocs', 'resources'))
setup(...
options={'build_exe': {'include_files': [xsocs_include_files]}}
)
- With py2app, add xsocs in the packages list of the py2app options:
.. code-block:: python
setup(...
options={'py2app': {'packages': ['xsocs']}}
)
"""
__authors__ = ["V.A. Sole", "Thomas Vincent", "D. Naudet"]
__license__ = "MIT"
__date__ = "24/10/2016"
import os
import sys
# pkg_resources is useful when this package is stored in a zip
# When pkg_resources is not available, the resources dir defaults to the
# directory containing this module.
try:
import pkg_resources
except ImportError:
pkg_resources = None
# For packaging purpose, patch this variable to use an alternative directory
# E.g., replace with _RESOURCES_DIR = '/usr/share/xsocs/data'
_RESOURCES_DIR = None
# For packaging purpose, patch this variable to use an alternative directory
# E.g., replace with _RESOURCES_DIR = '/usr/share/xsocs/doc'
# Not in use, uncomment when functionnality is needed
# _RESOURCES_DOC_DIR = None
# cx_Freeze forzen support
# See http://cx-freeze.readthedocs.io/en/latest/faq.html#using-data-files
if getattr(sys, 'frozen', False):
# Running in a frozen application:
# We expect resources to be located either in a xsocs/resources/ dir
# relative to the executable or within this package.
_dir = os.path.join(os.path.dirname(sys.executable), 'xsocs', 'resources')
if os.path.isdir(_dir):
_RESOURCES_DIR = _dir
def resource_filename(resource):
"""Return filename corresponding to resource.
resource can be the name of either a file or a directory.
The existence of the resource is not checked.
:param str resource: Resource path relative to resource directory
using '/' path separator.
:return: Absolute resource path in the file system
"""
# Not in use, uncomment when functionnality is needed
# If _RESOURCES_DOC_DIR is set, use it to get resources in doc/ subflodler
# from an alternative directory.
# if _RESOURCES_DOC_DIR is not None and (resource is 'doc' or
# resource.startswith('doc/')):
# # Remove doc folder from resource relative path
# return os.path.join(_RESOURCES_DOC_DIR, *resource.split('/')[1:])
if _RESOURCES_DIR is not None: # if set, use this directory
return os.path.join(_RESOURCES_DIR, *resource.split('/'))
elif pkg_resources is None: # Fallback if pkg_resources is not available
return os.path.join(os.path.abspath(os.path.dirname(__file__)),
*resource.split('/'))
else: # Preferred way to get resources as it supports zipfile package
return pkg_resources.resource_filename(__name__, resource)
"""Store resource files (i.e., icons)"""
This diff is collapsed.
# coding: utf-8
# /*##########################################################################
#
# Copyright (c) 2016 European Synchrotron Radiation Facility
# Copyright (c) 2018 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
......@@ -22,96 +22,14 @@
# THE SOFTWARE.
#
# ###########################################################################*/
"""Set of icons for buttons.
Use :func:`getQIcon` to create Qt QIcon from the name identifying an icon.
"""Shared test resource manager
"""
__authors__ = ["T. Vincent"]
__license__ = "MIT"
__date__ = "15/09/2016"
import logging
import weakref
from silx.gui import qt
from ..resources import resource_filename
_logger = logging.getLogger(__name__)
"""Module logger"""
_cached_icons = weakref.WeakValueDictionary()
"""Cache loaded icons in a weak structure"""
_supported_formats = None
"""Order of file format extension to check"""
_process_working = None
"""Cache an AnimatedIcon for working process"""
def getQIcon(name):
"""Create a QIcon from its name.
:param str name: Name of the icon, in one of the defined icons
in this module.
:return: Corresponding QIcon
:raises: ValueError when name is not known
"""
if name not in _cached_icons:
qfile = getQFile(name)
icon = qt.QIcon(qfile.fileName())
_cached_icons[name] = icon
else:
icon = _cached_icons[name]
return icon
def getQPixmap(name):
"""Create a QPixmap from its name.
:param str name: Name of the icon, in one of the defined icons
in this module.
:return: Corresponding QPixmap
:raises: ValueError when name is not known
"""
qfile = getQFile(name)
return qt.QPixmap(qfile.fileName())
def getQFile(name):
"""Create a QFile from an icon name. Filename is found
according to supported Qt formats.
from silx.resources import ExternalResources
:param str name: Name of the icon, in one of the defined icons
in this module.
:return: Corresponding QFile
:rtype: qt.QFile
:raises: ValueError when name is not known
"""
global _supported_formats
if _supported_formats is None:
_supported_formats = []
supported_formats = qt.supportedImageFormats()
order = ["mng", "gif", "svg", "png", "jpg"]
for format_ in order:
if format_ in supported_formats:
_supported_formats.append(format_)
if len(_supported_formats) == 0:
_logger.error("No format supported for icons")
else:
_logger.debug("Format %s supported", ", ".join(_supported_formats))
for format_ in _supported_formats:
format_ = str(format_)
filename = resource_filename('gui/icons/%s.%s' % (name, format_))
qfile = qt.QFile(filename)
if qfile.exists():
return qfile
raise ValueError('Not an icon name: %s' % name)
test_resources = ExternalResources(
project="xsocs",
url_base="http://www.silx.org/pub/xsocs/test_data",
env_key="XSOCS_DATA")
"""Shared test resources manager"""
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment