diff --git a/bandviewsettings_widget_base.ui b/bandviewsettings_widget_base.ui new file mode 100644 index 0000000000000000000000000000000000000000..36cc7eae92c871631f3f8059893e43f5fd2dbbba --- /dev/null +++ b/bandviewsettings_widget_base.ui @@ -0,0 +1,144 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>BandViewSettings</class> + <widget class="QGroupBox" name="BandViewSettings"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>274</width> + <height>71</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="windowTitle"> + <string>GroupBox</string> + </property> + <property name="title"> + <string>Sensor</string> + </property> + <property name="flat"> + <bool>true</bool> + </property> + <property name="checkable"> + <bool>false</bool> + </property> + <layout class="QFormLayout" name="formLayout"> + <property name="sizeConstraint"> + <enum>QLayout::SetMinimumSize</enum> + </property> + <property name="fieldGrowthPolicy"> + <enum>QFormLayout::AllNonFixedFieldsGrow</enum> + </property> + <property name="horizontalSpacing"> + <number>2</number> + </property> + <property name="verticalSpacing"> + <number>2</number> + </property> + <property name="margin"> + <number>2</number> + </property> + <item row="0" column="0"> + <widget class="QLabel" name="label_r"> + <property name="text"> + <string>RGB</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="0" column="1"> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <widget class="QComboBox" name="cb_r"> + <property name="minimumSize"> + <size> + <width>75</width> + <height>21</height> + </size> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="cb_g"> + <property name="minimumSize"> + <size> + <width>75</width> + <height>21</height> + </size> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="cb_b"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>75</width> + <height>21</height> + </size> + </property> + </widget> + </item> + </layout> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_g"> + <property name="text"> + <string>Range</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <layout class="QHBoxLayout" name="horizontalLayout_4"> + <item> + <widget class="QLineEdit" name="tb_range_min"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip"> + <string>Minimum data value to show</string> + </property> + <property name="text"> + <string>0</string> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="tb_range_max"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip"> + <string>Maximum data value to show.</string> + </property> + <property name="text"> + <string>5000</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/imagechipviewsettings_widget.py b/imagechipviewsettings_widget.py deleted file mode 100644 index 3c4b97c7fc53d0c1e4923b60a840806d8037aff7..0000000000000000000000000000000000000000 --- a/imagechipviewsettings_widget.py +++ /dev/null @@ -1,146 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'imagechipviewsettings_widget_base.ui' -# -# Created: Mon Oct 26 16:10:40 2015 -# by: PyQt4 UI code generator 4.10.2 -# -# WARNING! All changes made in this file will be lost! - -''' -/*************************************************************************** - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - ***************************************************************************/ -''' - -import os - -from PyQt4 import uic -from PyQt4.QtCore import * -from PyQt4.QtGui import * - -import sys -sys.path.append(os.path.dirname(__file__)) -FORM_CLASS, _ = uic.loadUiType(os.path.join( - os.path.dirname(__file__), 'imagechipviewsettings_widget_base.ui'), resource_suffix='') - - - -class ImageChipViewSettings(QGroupBox, FORM_CLASS): - - #define signals - - removeView = pyqtSignal() - - def __init__(self, SensorConfiguration, parent=None): - """Constructor.""" - super(ImageChipViewSettings, self).__init__(parent) - # Set up the user interface from Designer. - # After setupUI you can access any designer object by doing - # self.<objectname>, and you can use autoconnect slots - see - # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html - # #widgets-and-dialogs-with-auto-connect - self.setupUi(self) - - - self.SensorConfiguration = SensorConfiguration - self.setTitle(SensorConfiguration.sensor_name) - - self.tb_range_r_min.setValidator(QDoubleValidator()) - self.tb_range_g_min.setValidator(QDoubleValidator()) - self.tb_range_b_min.setValidator(QDoubleValidator()) - self.tb_range_r_max.setValidator(QDoubleValidator()) - self.tb_range_g_max.setValidator(QDoubleValidator()) - self.tb_range_b_max.setValidator(QDoubleValidator()) - - self._initBands(self.SensorConfiguration.band_names) - - def ua_setMask(self, state): - - useMask = state != 0 - for w in [self.bt_color, self.label_maskexpression, self.tb_maskexpression]: - w.setEnabled(useMask) - - def ua_setMaskColor(self, color): - if color is None: - color = QColorDialog.getColor() - - if color is not None: - self.maskcolor = color - r = color.red() - g = color.green() - b = color.blue() - style = "background:rgb({},{},{})".format(r,g,b) - self.bt_color.setStyleSheet(style) - self.bt_color.update() - - def getMaskColor(self): - return (self.maskcolor.red(), self.maskcolor.green(), self.maskcolor.blue()) - - def useMaskValues(self): - return self.cb_useMask.isChecked() - - def _initBands(self, band_names): - cb_R = self.cb_r - cb_G = self.cb_g - cb_B = self.cb_b - - for i, bandname in enumerate(band_names): - cb_R.addItem(bandname, i+1) - cb_G.addItem(bandname, i+1) - cb_B.addItem(bandname, i+1) - - if len(self.SensorConfiguration.band_names) >= 3: - cb_R.setCurrentIndex(2) - cb_G.setCurrentIndex(1) - cb_B.setCurrentIndex(0) - - - def setBands(self,bands): - assert len(bands) == 3 - for b in bands: - assert type(b) is int and b > 0 - assert b <= len(self.SensorConfiguration.band_names), 'TimeSeries is not initializes/has no bands to show' - self.cb_r.setCurrentIndex(bands[0]-1) - self.cb_g.setCurrentIndex(bands[1]-1) - self.cb_b.setCurrentIndex(bands[2]-1) - - s = "" - pass - - def getBands(self): - bands = [self.cb_r.currentIndex()+1, \ - self.cb_g.currentIndex()+1, \ - self.cb_b.currentIndex()+1] - return bands - - def getRanges(self): - range_r = [float(self.tb_range_r_min.text()), float(self.tb_range_r_max.text())] - range_g = [float(self.tb_range_g_min.text()), float(self.tb_range_g_max.text())] - range_b = [float(self.tb_range_b_min.text()), float(self.tb_range_b_max.text())] - return (range_r, range_g, range_b) - - def getSettings(self): - - s = "" - - -if __name__ == '__main__': - - import PyQt4.Qt - - app=PyQt4.Qt.QApplication([]) - W = QDialog() - W.setLayout(QHBoxLayout()) - L = W.layout() - w = ImageChipViewSettings() - L.addWidget(w) - W.show() - sys.exit(app.exec_()) - - print('Done') \ No newline at end of file diff --git a/imagechipviewsettings_widget_base.ui b/imagechipviewsettings_widget_base.ui index 005abf82c1164b43f860d84a160e6550f66c75c0..69123a651bd4b9cca679e4ee810eb0d3dc1ecf83 100644 --- a/imagechipviewsettings_widget_base.ui +++ b/imagechipviewsettings_widget_base.ui @@ -206,6 +206,17 @@ </item> </layout> </widget> + <tabstops> + <tabstop>cb_r</tabstop> + <tabstop>tb_range_r_min</tabstop> + <tabstop>tb_range_r_max</tabstop> + <tabstop>cb_g</tabstop> + <tabstop>tb_range_g_min</tabstop> + <tabstop>tb_range_g_max</tabstop> + <tabstop>cb_b</tabstop> + <tabstop>tb_range_b_min</tabstop> + <tabstop>tb_range_b_max</tabstop> + </tabstops> <resources/> <connections/> </ui> diff --git a/libs/qimage2ndarray/LICENSE.txt b/libs/qimage2ndarray/LICENSE.txt deleted file mode 100644 index 96d599dac8fc563eb78b9305e428df72944a6678..0000000000000000000000000000000000000000 --- a/libs/qimage2ndarray/LICENSE.txt +++ /dev/null @@ -1,30 +0,0 @@ -Copyright (c) 2009, Hans Meine <hans_meine@gmx.net> -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the - distribution. - -3. Neither the name of the University of Hamburg nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/libs/qimage2ndarray/__init__.py b/libs/qimage2ndarray/__init__.py deleted file mode 100644 index 6e56e0e06dd75127d37a7b5918acf431b9824c32..0000000000000000000000000000000000000000 --- a/libs/qimage2ndarray/__init__.py +++ /dev/null @@ -1,403 +0,0 @@ -import sys as _sys -import numpy as _np - -from .dynqt import QtGui as _qt - -from .dynqt import qt as _qt_driver -if _qt_driver.name() == 'PythonQt': - from .qimageview import QImage2ndarray as _temp - _qimageview = _temp.qimageview -else: - from .qimageview_python import qimageview as _qimageview - -__version__ = "1.5" - -if _sys.byteorder == 'little': - _bgra = (0, 1, 2, 3) -else: - _bgra = (3, 2, 1, 0) - -_bgra_fields = {'b': (_np.uint8, _bgra[0], 'blue'), - 'g': (_np.uint8, _bgra[1], 'green'), - 'r': (_np.uint8, _bgra[2], 'red'), - 'a': (_np.uint8, _bgra[3], 'alpha')} - -bgra_dtype = _np.dtype(_bgra_fields) -"""Complex dtype offering the named fields 'r','g','b', and 'a' and -corresponding long names, conforming to QImage_'s 32-bit memory layout.""" - -try: - _basestring = basestring -except NameError: - # 'basestring' undefined, must be Python 3 - _basestring = str - -def _qimage_or_filename_view(qimage): - if isinstance(qimage, _basestring): - qimage = _qt.QImage(qimage) - return _qimageview(qimage) - -def raw_view(qimage): - """Returns raw 2D view of the given QImage_'s memory. The result - will be a 2-dimensional numpy.ndarray with an appropriately sized - integral dtype. (This function is not intented to be used - directly, but used internally by the other -- more convenient -- - view creation functions.) - - :param qimage: image whose memory shall be accessed via NumPy - :type qimage: QImage_ - :rtype: numpy.ndarray_ with shape (height, width)""" - return _qimage_or_filename_view(qimage) - - -def byte_view(qimage, byteorder = 'little'): - """Returns raw 3D view of the given QImage_'s memory. This will - always be a 3-dimensional numpy.ndarray with dtype numpy.uint8. - - Note that for 32-bit images, the last dimension will be in the - [B,G,R,A] order (if little endian) due to QImage_'s memory layout - (the alpha channel will be present for Format_RGB32 images, too). - - For 8-bit (indexed) images, the array will still be 3-dimensional, - i.e. shape will be (height, width, 1). - - The order of channels in the last axis depends on the `byteorder`, - which defaults to 'little', i.e. BGRA order. You may set the - argument `byteorder` to 'big' to get ARGB, or use None which means - sys.byteorder here, i.e. return native order for the machine the - code is running on. - - For your convenience, `qimage` may also be a filename, see - `Loading and Saving Images`_ in the documentation. - - :param qimage: image whose memory shall be accessed via NumPy - :type qimage: QImage_ - :param byteorder: specify order of channels in last axis - :rtype: numpy.ndarray_ with shape (height, width, 1 or 4) and dtype uint8""" - raw = _qimage_or_filename_view(qimage) - result = raw.view(_np.uint8).reshape(raw.shape + (-1, )) - if byteorder and byteorder != _sys.byteorder: - result = result[...,::-1] - return result - - -def rgb_view(qimage, byteorder = 'big'): - """Returns RGB view of a given 32-bit color QImage_'s memory. - Similarly to byte_view(), the result is a 3D numpy.uint8 array, - but reduced to the rgb dimensions (without alpha), and reordered - (using negative strides in the last dimension) to have the usual - [R,G,B] order. The image must have 32 bit pixel size, i.e. be - RGB32, ARGB32, or ARGB32_Premultiplied. (Note that in the latter - case, the values are of course premultiplied with alpha.) - - The order of channels in the last axis depends on the `byteorder`, - which defaults to 'big', i.e. RGB order. You may set the argument - `byteorder` to 'little' to get BGR, or use None which means - sys.byteorder here, i.e. return native order for the machine the - code is running on. - - For your convenience, `qimage` may also be a filename, see - `Loading and Saving Images`_ in the documentation. - - :param qimage: image whose memory shall be accessed via NumPy - :type qimage: QImage_ with 32-bit pixel type - :param byteorder: specify order of channels in last axis - :rtype: numpy.ndarray_ with shape (height, width, 3) and dtype uint8""" - if byteorder is None: - byteorder = _sys.byteorder - bytes = byte_view(qimage, byteorder) - if bytes.shape[2] != 4: - raise ValueError("For rgb_view, the image must have 32 bit pixel size (use RGB32, ARGB32, or ARGB32_Premultiplied)") - - if byteorder == 'little': - return bytes[...,:3] # strip A off BGRA - else: - return bytes[...,1:] # strip A off ARGB - - -def alpha_view(qimage): - """Returns alpha view of a given 32-bit color QImage_'s memory. - The result is a 2D numpy.uint8 array, equivalent to - byte_view(qimage)[...,3]. The image must have 32 bit pixel size, - i.e. be RGB32, ARGB32, or ARGB32_Premultiplied. Note that it is - not enforced that the given qimage has a format that actually - *uses* the alpha channel -- for Format_RGB32, the alpha channel - usually contains 255 everywhere. - - For your convenience, `qimage` may also be a filename, see - `Loading and Saving Images`_ in the documentation. - - :param qimage: image whose memory shall be accessed via NumPy - :type qimage: QImage_ with 32-bit pixel type - :rtype: numpy.ndarray_ with shape (height, width) and dtype uint8""" - bytes = byte_view(qimage, byteorder = None) - if bytes.shape[2] != 4: - raise ValueError("For alpha_view, the image must have 32 bit pixel size (use RGB32, ARGB32, or ARGB32_Premultiplied)") - return bytes[...,_bgra[3]] - - -def recarray_view(qimage): - """Returns recarray_ view of a given 32-bit color QImage_'s - memory. - - The result is a 2D array with a complex record dtype, offering the - named fields 'r','g','b', and 'a' and corresponding long names. - Thus, each color components can be accessed either via string - indexing or via attribute lookup (through numpy.recarray_): - - For your convenience, `qimage` may also be a filename, see - `Loading and Saving Images`_ in the documentation. - - >>> from PyQt4.QtGui import QImage, qRgb - >>> qimg = QImage(320, 240, QImage.Format_ARGB32) - >>> qimg.fill(qRgb(12,34,56)) - >>> - >>> import qimage2ndarray - >>> v = qimage2ndarray.recarray_view(qimg) - >>> - >>> red = v["r"] - >>> red[10,10] - 12 - >>> pixel = v[10,10] - >>> pixel["r"] - 12 - >>> (v.g == v["g"]).all() - True - >>> (v.alpha == 255).all() - True - - :param qimage: image whose memory shall be accessed via NumPy - :type qimage: QImage_ with 32-bit pixel type - :rtype: numpy.ndarray_ with shape (height, width) and dtype :data:`bgra_dtype`""" - raw = _qimage_or_filename_view(qimage) - if raw.itemsize != 4: - raise ValueError("For rgb_view, the image must have 32 bit pixel size (use RGB32, ARGB32, or ARGB32_Premultiplied)") - return raw.view(bgra_dtype, _np.recarray) - - - -def _normalize255(array, normalize, clip = (0, 255)): - if normalize: - if normalize is True: - normalize = array.min(), array.max() - if clip == (0, 255): - clip = None - elif _np.isscalar(normalize): - normalize = (0, normalize) - - nmin, nmax = normalize - - if nmin: - array = array - nmin - - if nmax != nmin: - scale = 255. / (nmax - nmin) - if scale != 1.0: - array = array * scale - - if clip: - low, high = clip - _np.clip(array, low, high, array) - - return array - - -def gray2qimage(gray, normalize = False): - """Convert the 2D numpy array `gray` into a 8-bit, indexed QImage_ - with a gray colormap. The first dimension represents the vertical - image axis. - - The parameter `normalize` can be used to normalize an image's - value range to 0..255: - - `normalize` = (nmin, nmax): - scale & clip image values from nmin..nmax to 0..255 - - `normalize` = nmax: - lets nmin default to zero, i.e. scale & clip the range 0..nmax - to 0..255 - - `normalize` = True: - scale image values to 0..255 (same as passing (gray.min(), - gray.max())) - - If the source array `gray` contains masked values, the result will - have only 255 shades of gray, and one color map entry will be used - to make the corresponding pixels transparent. - - A full alpha channel cannot be supported with indexed images; - instead, use `array2qimage` to convert into a 32-bit QImage. - - :param gray: image data which should be converted (copied) into a QImage_ - :type gray: 2D or 3D numpy.ndarray_ or `numpy.ma.array <masked arrays>`_ - :param normalize: normalization parameter (see above, default: no value changing) - :type normalize: bool, scalar, or pair - :rtype: QImage_ with RGB32 or ARGB32 format""" - if _np.ndim(gray) != 2: - raise ValueError("gray2QImage can only convert 2D arrays" + - " (try using array2qimage)" if _np.ndim(gray) == 3 else "") - - h, w = gray.shape - result = _qt.QImage(w, h, _qt.QImage.Format_Indexed8) - - if not _np.ma.is_masked(gray): - for i in range(256): - result.setColor(i, _qt.qRgb(i,i,i)) - - _qimageview(result)[:] = _normalize255(gray, normalize) - else: - # map gray value 1 to gray value 0, in order to make room for - # transparent colormap entry: - result.setColor(0, _qt.qRgb(0,0,0)) - for i in range(2, 256): - result.setColor(i-1, _qt.qRgb(i,i,i)) - - _qimageview(result)[:] = _normalize255(gray, normalize, clip = (1, 255)) - 1 - - result.setColor(255, 0) - _qimageview(result)[gray.mask] = 255 - - return result - - -def array2qimage(array, normalize = False): - """Convert a 2D or 3D numpy array into a 32-bit QImage_. The - first dimension represents the vertical image axis; the optional - third dimension is supposed to contain 1-4 channels: - - ========= =================== - #channels interpretation - ========= =================== - 1 scalar/gray - 2 scalar/gray + alpha - 3 RGB - 4 RGB + alpha - ========= =================== - - Scalar data will be converted into corresponding gray RGB triples; - if you want to convert to an (indexed) 8-bit image instead, use - `gray2qimage` (which cannot support an alpha channel though). - - The parameter `normalize` can be used to normalize an image's - value range to 0..255: - - `normalize` = (nmin, nmax): - scale & clip image values from nmin..nmax to 0..255 - - `normalize` = nmax: - lets nmin default to zero, i.e. scale & clip the range 0..nmax - to 0..255 - - `normalize` = True: - scale image values to 0..255 (same as passing (array.min(), - array.max())) - - If `array` contains masked values, the corresponding pixels will - be transparent in the result. Thus, the result will be of - QImage.Format_ARGB32 if the input already contains an alpha - channel (i.e. has shape (H,W,4)) or if there are masked pixels, - and QImage.Format_RGB32 otherwise. - - :param array: image data which should be converted (copied) into a QImage_ - :type array: 2D or 3D numpy.ndarray_ or `numpy.ma.array <masked arrays>`_ - :param normalize: normalization parameter (see above, default: no value changing) - :type normalize: bool, scalar, or pair - :rtype: QImage_ with RGB32 or ARGB32 format""" - if _np.ndim(array) == 2: - array = array[...,None] - elif _np.ndim(array) != 3: - raise ValueError("array2qimage can only convert 2D or 3D arrays (got %d dimensions)" % _np.ndim(array)) - if array.shape[2] not in (1, 2, 3, 4): - raise ValueError("array2qimage expects the last dimension to contain exactly one (scalar/gray), two (gray+alpha), three (R,G,B), or four (R,G,B,A) channels") - - h, w, channels = array.shape - - hasAlpha = _np.ma.is_masked(array) or channels in (2, 4) - fmt = _qt.QImage.Format_ARGB32 if hasAlpha else _qt.QImage.Format_RGB32 - - result = _qt.QImage(w, h, fmt) - - array = _normalize255(array, normalize) - - if channels >= 3: - rgb_view(result)[:] = array[...,:3] - else: - rgb_view(result)[:] = array[...,:1] # scalar data - - alpha = alpha_view(result) - - if channels in (2, 4): - alpha[:] = array[...,-1] - else: - alpha[:] = 255 - - if _np.ma.is_masked(array): - alpha[:] *= _np.logical_not(_np.any(array.mask, axis = -1)) - - return result - - -def imread(filename, masked = False): - """Convenience function that uses the QImage_ constructor to read an - image from the given file and return an `rgb_view` of the result. - This is intentionally similar to scipy.ndimage.imread (which uses - PIL), scipy.misc.imread, or matplotlib.pyplot.imread (using PIL - for non-PNGs). - - For grayscale images, return 2D array (even if it comes from a 32-bit - representation; this is a consequence of the QImage API). - - For images with an alpha channel, the resulting number of channels - will be 2 (grayscale+alpha) or 4 (RGB+alpha). Alternatively, one may - pass `masked = True' in order to get `numpy.ma.array <masked - arrays>`_ back. Note that only fully transparent pixels are masked - (and that masked arrays only support binary masks). The value of - `masked` is ignored when the loaded image has no alpha channel - (i.e., one would not get a masked array in that case). - - This function has been added in version 1.3. - - """ - qImage = _qt.QImage(filename) - - isGray = qImage.isGrayscale() - if isGray and qImage.depth() == 8: - return byte_view(qImage)[...,0] - - hasAlpha = qImage.hasAlphaChannel() - - if hasAlpha: - targetFormat = _qt.QImage.Format_ARGB32 - else: - targetFormat = _qt.QImage.Format_RGB32 - if qImage.format() != targetFormat: - qImage = qImage.convertToFormat(targetFormat) - - result = rgb_view(qImage) - if isGray: - result = result[...,0] - if hasAlpha: - if masked: - mask = (alpha_view(qImage) == 0) - if _np.ndim(result) == 3: - mask = _np.repeat(mask[...,None], 3, axis = 2) - result = _np.ma.masked_array(result, mask) - else: - result = _np.dstack((result, alpha_view(qImage))) - return result - - -def imsave(filename, image, normalize = False, format = None, quality = -1): - """Convenience function that uses QImage.save to save an image to the - given file. This is intentionally similar to scipy.misc.imsave. - However, it supports different optional arguments: - - :param normalize: see :func:`array2qimage` (which is used internally) - :param format: image filetype (e.g. 'PNG'), (default: check filename's suffix) - :param quality: see QImage.save (0 = small .. 100 = uncompressed, -1 = default compression) - :returns: boolean success, see QImage.save - - This function has been added in version 1.4. - """ - qImage = array2qimage(image, normalize = normalize) - return qImage.save(filename, format, quality) diff --git a/libs/qimage2ndarray/dynqt.py b/libs/qimage2ndarray/dynqt.py deleted file mode 100644 index a4f1a18bce006d81d848dfd98d881901e3af5bda..0000000000000000000000000000000000000000 --- a/libs/qimage2ndarray/dynqt.py +++ /dev/null @@ -1,4 +0,0 @@ -from .qt_driver import QtDriver - -qt = QtDriver() -QtGui = qt.QtGui diff --git a/libs/qimage2ndarray/qimageview_python.py b/libs/qimage2ndarray/qimageview_python.py deleted file mode 100644 index 83efb2ddf0f9351992aef016f7ce1f4ac2eb83c9..0000000000000000000000000000000000000000 --- a/libs/qimage2ndarray/qimageview_python.py +++ /dev/null @@ -1,60 +0,0 @@ -import numpy as np -from qimage2ndarray.dynqt import qt, QtGui - -def PyQt_data(image): - # PyQt4/PyQt5's QImage.bits() returns a sip.voidptr that supports - # conversion to string via asstring(size) or getting its base - # address via int(...): - return (int(image.bits()), False) - -def _re_buffer_address_match(buf_repr): - import re - _re_buffer_address = re.compile('<read-write buffer ptr 0x([0-9a-fA-F]*),') - global _re_buffer_address_match - _re_buffer_address_match = _re_buffer_address.match - return _re_buffer_address_match(buf_repr) - -def PySide_data(image): - # PySide's QImage.bits() returns a buffer object like this: - # <read-write buffer ptr 0x7fc3f4821600, size 76800 at 0x111269570> - ma = _re_buffer_address_match(repr(image.bits())) - assert ma, 'could not parse address from %r' % (image.bits(), ) - return (int(ma.group(1), 16), False) - -getdata = dict( - PyQt4 = PyQt_data, - PyQt5 = PyQt_data, - PySide = PySide_data, -)[qt.name()] - - -def qimageview(image): - if not isinstance(image, QtGui.QImage): - raise TypeError("image argument must be a QImage instance") - - shape = image.height(), image.width() - strides0 = image.bytesPerLine() - - format = image.format() - if format == QtGui.QImage.Format_Indexed8: - dtype = "|u1" - strides1 = 1 - elif format in (QtGui.QImage.Format_RGB32, QtGui.QImage.Format_ARGB32, QtGui.QImage.Format_ARGB32_Premultiplied): - dtype = "|u4" - strides1 = 4 - elif format == QtGui.QImage.Format_Invalid: - raise ValueError("qimageview got invalid QImage") - else: - raise ValueError("qimageview can only handle 8- or 32-bit QImages") - - image.__array_interface__ = { - 'shape': shape, - 'typestr': dtype, - 'data': getdata(image), - 'strides': (strides0, strides1), - 'version': 3, - } - - result = np.asarray(image) - del image.__array_interface__ - return result diff --git a/libs/qimage2ndarray/qt_driver.py b/libs/qimage2ndarray/qt_driver.py deleted file mode 100644 index 483cd287af1976d6c665860fa84d3304ece7273d..0000000000000000000000000000000000000000 --- a/libs/qimage2ndarray/qt_driver.py +++ /dev/null @@ -1,125 +0,0 @@ -# Copyright 2014-2014 Hans Meine <hans_meine@gmx.net> -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""This module contains a wrapper around three different Qt python bindings. -It will dynamically decide which one to use: - -* First, the environment variable QT_DRIVER is checked - (may be one of 'PyQt5', 'PyQt4', 'PySide', 'PythonQt'). -* If unset, previously imported binding modules are detected (in sys.modules). -* If no bindings are loaded, the environment variable QT_API is checked - (used by ETS and ipython, may be 'pyside' or 'pyqt'). - -In order to have compatible behavior between the different bindings, -PyQt4 (if used) is configured as follows:: - - sip.setapi("QString", 2) - sip.setapi("QVariant", 2) - -Furthermore, there is a 'getprop' function that solves the following -problem: PythonQt exports Qt properties as Python properties *and* -gives the precedence over getters with the same name. Instead of -calling getters with parentheses (which must not be used in PythonQt, -but are required in PyQt and PySide), one may e.g. write -`getprop(widget.width)`. -""" - -import sys, os - -def getprop_PythonQt(prop): - """getprop(property_or_getter) - - Used on getters that have the same name as a corresponding - property. For PythonQt, this version will just return the - argument, which is assumed to be (the value of) a python property - through which PythonQt exposes Qt properties.""" - return prop - -def getprop_other(getter): - """getprop(property_or_getter) - - Used on getters that have the same name as a corresponding - property. For Qt bindings other than PythonQt, this version will - return the result of calling the argument, which is assumed to be - a Qt getter function. (With PythonQt, properties override getters - and no calling must be done.)""" - return getter() - -class QtDriver(object): - DRIVERS = ('PyQt5', 'PyQt4', 'PySide', 'PythonQt') - DEFAULT = 'PyQt4' - - @classmethod - def detect_qt(cls): - for drv in cls.DRIVERS: - if drv in sys.modules: - return drv - if '_PythonQt' in sys.modules: - return 'PythonQt' - return None - - def name(self): - return self._drv - - def getprop(self): - return getprop_PythonQt if self._drv == 'PythonQt' else getprop_other - - def __init__(self, drv = os.environ.get('QT_DRIVER')): - """Supports QT_API (used by ETS and ipython)""" - if drv is None: - drv = self.detect_qt() - if drv is None: - drv = os.environ.get('QT_API') - if drv is None: - drv = self.DEFAULT - drv = {'pyside' : 'PySide', 'pyqt' : 'PyQt4', 'pyqt5' : 'PyQt5'}.get(drv, drv) # map ETS syntax - assert drv in self.DRIVERS - self._drv = drv - - @staticmethod - def _initPyQt4(): - """initialize PyQt4 to be compatible with PySide""" - if 'PyQt4.QtCore' in sys.modules: - # too late to configure API - pass - else: - import sip - sip.setapi("QString", 2) - sip.setapi("QVariant", 2) - - @staticmethod - def requireCompatibleAPI(): - """If PyQt4's API should be configured to be compatible with PySide's - (i.e. QString and QVariant should not be explicitly exported, - cf. documentation of sip.setapi()), call this function to check that - the PyQt4 was properly imported. (It will always be configured this - way by this module, but it could have been imported before we got a - hand on doing so.) - """ - if 'PyQt4.QtCore' in sys.modules: - import sip - for api in ('QVariant', 'QString'): - if sip.getapi(api) != 2: - raise RuntimeError('%s API already set to V%d, but should be 2' % (api, sip.getapi(api))) - - def importMod(self, mod): - if self._drv == 'PyQt4': - self._initPyQt4() - qt = __import__('%s.%s' % (self._drv, mod)) - return getattr(qt, mod) - - def __getattr__(self, name): - if name.startswith('Qt'): - return self.importMod(name) - return super(QtDriver, self).__getattr__(name) diff --git a/libs/qrangeslider-0.1.1/PKG-INFO b/libs/qrangeslider-0.1.1/PKG-INFO deleted file mode 100644 index 5374908bfa8050c16057076ebc3c909efc4b6441..0000000000000000000000000000000000000000 --- a/libs/qrangeslider-0.1.1/PKG-INFO +++ /dev/null @@ -1,10 +0,0 @@ -Metadata-Version: 1.0 -Name: qrangeslider -Version: 0.1.1 -Summary: The QRangeSlider class implements a horizontal PyQt range slider widget. -Home-page: http://github.com/rsgalloway/qrangeslider -Author: Ryan Galloway -Author-email: ryan@rsgalloway.com -License: UNKNOWN -Description: UNKNOWN -Platform: UNKNOWN diff --git a/libs/qrangeslider-0.1.1/README b/libs/qrangeslider-0.1.1/README deleted file mode 100644 index 8048e6bbc834e6f1fca94eccc5fb61b1c9bf0790..0000000000000000000000000000000000000000 --- a/libs/qrangeslider-0.1.1/README +++ /dev/null @@ -1,34 +0,0 @@ -QRangeSlider - -Thu Apr 28 00:08:07 PDT 2011 - - -1 Overview -~~~~~~~~~~ - -The QRangeSlider class implements a horizontal PyQt range slider widget. - - * README this file - * LICENSE the license under which QRangeSlider is released - * qrangeslider.py qrangeslider python module - * examples.py some usage examples - - -2 Installation -~~~~~~~~~~~~~~ - - $ sudo easy_install qrangeslider - -or download the source and run - - $ sudo python setup.py install - - -3 Basic Usage -~~~~~~~~~~~~~ - - >>> from qrangeslider import QRangeSlider - >>> app = QtGui.QApplication(sys.argv) - >>> slider = QRangeSlider() - >>> slider.show() - >>> app.exec_() \ No newline at end of file diff --git a/libs/qrangeslider-0.1.1/qrangeslider.py b/libs/qrangeslider-0.1.1/qrangeslider.py deleted file mode 100644 index 1267a1a459b364bab0196f53979fa351ec40dff6..0000000000000000000000000000000000000000 --- a/libs/qrangeslider-0.1.1/qrangeslider.py +++ /dev/null @@ -1,521 +0,0 @@ -#!/usr/bin/env python -# --------------------------------------------------------------------------------------------- -# Copyright (c) 2011-2014, Ryan Galloway (ryan@rsgalloway.com) -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# - Redistributions of source code must retain the above copyright notice, this -# list of conditions and the following disclaimer. -# -# - Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# -# - Neither the name of the software nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# --------------------------------------------------------------------------------------------- -# docs and latest version available for download at -# http://rsgalloway.github.com/qrangeslider -# --------------------------------------------------------------------------------------------- - -__author__ = "Ryan Galloway <ryan@rsgalloway.com>" -__version__ = "0.1.1" - - -# --------------------------------------------------------------------------------------------- -# SUMMARY -# --------------------------------------------------------------------------------------------- -"""The QRangeSlider class implements a horizontal range slider widget. - -""" - -# --------------------------------------------------------------------------------------------- -# TODO -# --------------------------------------------------------------------------------------------- - -""" - - smoother mouse move event handler - - support splits and joins - - verticle sliders - - ticks - -""" - -# --------------------------------------------------------------------------------------------- -# IMPORTS -# --------------------------------------------------------------------------------------------- -import os -import sys - -from PyQt4 import QtCore -from PyQt4 import QtGui -from PyQt4 import uic - -try: - _fromUtf8 = QtCore.QString.fromUtf8 -except AttributeError: - _fromUtf8 = lambda s: s - -__all__ = ['QRangeSlider'] - -DEFAULT_CSS = """ -QRangeSlider * { - border: 0px; - padding: 0px; -} -QRangeSlider #Head { - background: #222; -} -QRangeSlider #Span { - background: #393; -} -QRangeSlider #Span:active { - background: #282; -} -QRangeSlider #Tail { - background: #222; -} -QRangeSlider > QSplitter::handle { - background: #393; -} -QRangeSlider > QSplitter::handle:vertical { - height: 4px; -} -QRangeSlider > QSplitter::handle:pressed { - background: #ca5; -} - -""" - -def scale(val, src, dst): - """ - Scale the given value from the scale of src to the scale of dst. - """ - return int(((val - src[0]) / float(src[1]-src[0])) * (dst[1]-dst[0]) + dst[0]) - -class Ui_Form(object): - """default range slider form""" - - def setupUi(self, Form): - Form.setObjectName(_fromUtf8("QRangeSlider")) - Form.resize(300, 30) - Form.setStyleSheet(_fromUtf8(DEFAULT_CSS)) - self.gridLayout = QtGui.QGridLayout(Form) - self.gridLayout.setMargin(0) - self.gridLayout.setSpacing(0) - self.gridLayout.setObjectName(_fromUtf8("gridLayout")) - self._splitter = QtGui.QSplitter(Form) - self._splitter.setMinimumSize(QtCore.QSize(0, 0)) - self._splitter.setMaximumSize(QtCore.QSize(16777215, 16777215)) - self._splitter.setOrientation(QtCore.Qt.Horizontal) - self._splitter.setObjectName(_fromUtf8("splitter")) - self._head = QtGui.QGroupBox(self._splitter) - self._head.setTitle(_fromUtf8("")) - self._head.setObjectName(_fromUtf8("Head")) - self._handle = QtGui.QGroupBox(self._splitter) - self._handle.setTitle(_fromUtf8("")) - self._handle.setObjectName(_fromUtf8("Span")) - self._tail = QtGui.QGroupBox(self._splitter) - self._tail.setTitle(_fromUtf8("")) - self._tail.setObjectName(_fromUtf8("Tail")) - self.gridLayout.addWidget(self._splitter, 0, 0, 1, 1) - - self.retranslateUi(Form) - QtCore.QMetaObject.connectSlotsByName(Form) - - def retranslateUi(self, Form): - encoding = QtGui.QApplication.UnicodeUTF8 - Form.setWindowTitle(QtGui.QApplication.translate("QRangeSlider", - "QRangeSlider", - None, encoding)) - - -class Element(QtGui.QGroupBox): - - def __init__(self, parent, main): - super(Element, self).__init__(parent) - self.main = main - - def setStyleSheet(self, style): - """redirect style to parent groupbox""" - self.parent().setStyleSheet(style) - - def textColor(self): - """text paint color""" - return getattr(self, '__textColor', QtGui.QColor(125, 125, 125)) - - def setTextColor(self, color): - """set the text paint color""" - if type(color) == tuple and len(color) == 3: - color = QtGui.QColor(color[0], color[1], color[2]) - elif type(color) == int: - color = QtGui.QColor(color, color, color) - setattr(self, '__textColor', color) - - def paintEvent(self, event): - """overrides paint event to handle text""" - qp = QtGui.QPainter() - qp.begin(self) - if self.main.drawValues(): - self.drawText(event, qp) - qp.end() - - -class Head(Element): - """area before the handle""" - - def __init__(self, parent, main): - super(Head, self).__init__(parent, main) - - def drawText(self, event, qp): - qp.setPen(self.textColor()) - qp.setFont(QtGui.QFont('Arial', 10)) - qp.drawText(event.rect(), QtCore.Qt.AlignLeft, str(self.main.min())) - - -class Tail(Element): - """area after the handle""" - - def __init__(self, parent, main): - super(Tail, self).__init__(parent, main) - - def drawText(self, event, qp): - qp.setPen(self.textColor()) - qp.setFont(QtGui.QFont('Arial', 10)) - qp.drawText(event.rect(), QtCore.Qt.AlignRight, str(self.main.max())) - - -class Handle(Element): - """handle area""" - - def __init__(self, parent, main): - super(Handle, self).__init__(parent, main) - - def drawText(self, event, qp): - qp.setPen(self.textColor()) - qp.setFont(QtGui.QFont('Arial', 10)) - qp.drawText(event.rect(), QtCore.Qt.AlignLeft, str(self.main.start())) - qp.drawText(event.rect(), QtCore.Qt.AlignRight, str(self.main.end())) - - def mouseMoveEvent(self, event): - event.accept() - mx = event.globalX() - _mx = getattr(self, '__mx', None) - - if not _mx: - setattr(self, '__mx', mx) - dx = 0 - else: - dx = mx - _mx - - setattr(self, '__mx', mx) - - if dx == 0: - event.ignore() - return - elif dx > 0: - dx = 1 - elif dx < 0: - dx = -1 - - s = self.main.start() + dx - e = self.main.end() + dx - if s >= self.main.min() and e <= self.main.max(): - self.main.setRange(s, e) - - -class QRangeSlider(QtGui.QWidget, Ui_Form): - """ - The QRangeSlider class implements a horizontal range slider widget. - - Inherits QWidget. - - Methods - - * __init__ (self, QWidget parent = None) - * bool drawValues (self) - * int end (self) - * (int, int) getRange (self) - * int max (self) - * int min (self) - * int start (self) - * setBackgroundStyle (self, QString styleSheet) - * setDrawValues (self, bool draw) - * setEnd (self, int end) - * setStart (self, int start) - * setRange (self, int start, int end) - * setSpanStyle (self, QString styleSheet) - - Signals - - * endValueChanged (int) - * maxValueChanged (int) - * minValueChanged (int) - * startValueChanged (int) - - Customizing QRangeSlider - - You can style the range slider as below: - :: - QRangeSlider * { - border: 0px; - padding: 0px; - } - QRangeSlider #Head { - background: #222; - } - QRangeSlider #Span { - background: #393; - } - QRangeSlider #Span:active { - background: #282; - } - QRangeSlider #Tail { - background: #222; - } - - Styling the range slider handles follows QSplitter options: - :: - QRangeSlider > QSplitter::handle { - background: #393; - } - QRangeSlider > QSplitter::handle:vertical { - height: 4px; - } - QRangeSlider > QSplitter::handle:pressed { - background: #ca5; - } - - """ - endValueChanged = QtCore.pyqtSignal(int) - maxValueChanged = QtCore.pyqtSignal(int) - minValueChanged = QtCore.pyqtSignal(int) - startValueChanged = QtCore.pyqtSignal(int) - - # define splitter indices - _SPLIT_START = 1 - _SPLIT_END = 2 - - # signals - minValueChanged = QtCore.pyqtSignal(int) - maxValueChanged = QtCore.pyqtSignal(int) - startValueChanged = QtCore.pyqtSignal(int) - endValueChanged = QtCore.pyqtSignal(int) - - def __init__(self, parent=None): - """Create a new QRangeSlider instance. - - :param parent: QWidget parent - :return: New QRangeSlider instance. - - """ - super(QRangeSlider, self).__init__(parent) - self.setupUi(self) - self.setMouseTracking(False) - - #self._splitter.setChildrenCollapsible(False) - self._splitter.splitterMoved.connect(self._handleMoveSplitter) - - # head layout - self._head_layout = QtGui.QHBoxLayout() - self._head_layout.setSpacing(0) - self._head_layout.setMargin(0) - self._head.setLayout(self._head_layout) - self.head = Head(self._head, main=self) - self._head_layout.addWidget(self.head) - - # handle layout - self._handle_layout = QtGui.QHBoxLayout() - self._handle_layout.setSpacing(0) - self._handle_layout.setMargin(0) - self._handle.setLayout(self._handle_layout) - self.handle = Handle(self._handle, main=self) - self.handle.setTextColor((150, 255, 150)) - self._handle_layout.addWidget(self.handle) - - # tail layout - self._tail_layout = QtGui.QHBoxLayout() - self._tail_layout.setSpacing(0) - self._tail_layout.setMargin(0) - self._tail.setLayout(self._tail_layout) - self.tail = Tail(self._tail, main=self) - self._tail_layout.addWidget(self.tail) - - # defaults - self.setMin(0) - self.setMax(99) - self.setStart(0) - self.setEnd(99) - self.setDrawValues(True) - - def min(self): - """:return: minimum value""" - return getattr(self, '__min', None) - - def max(self): - """:return: maximum value""" - return getattr(self, '__max', None) - - def setMin(self, value): - """sets minimum value""" - assert type(value) is int - setattr(self, '__min', value) - self.minValueChanged.emit(value) - - def setMax(self, value): - """sets maximum value""" - assert type(value) is int - setattr(self, '__max', value) - self.maxValueChanged.emit(value) - - def start(self): - """:return: range slider start value""" - return getattr(self, '__start', None) - - def end(self): - """:return: range slider end value""" - return getattr(self, '__end', None) - - def _setStart(self, value): - """stores the start value only""" - setattr(self, '__start', value) - self.startValueChanged.emit(value) - - def setStart(self, value): - """sets the range slider start value""" - assert type(value) is int - v = self._valueToPos(value) - self._splitter.splitterMoved.disconnect() - self._splitter.moveSplitter(v, self._SPLIT_START) - self._splitter.splitterMoved.connect(self._handleMoveSplitter) - self._setStart(value) - - def _setEnd(self, value): - """stores the end value only""" - setattr(self, '__end', value) - self.endValueChanged.emit(value) - - def setEnd(self, value): - """set the range slider end value""" - assert type(value) is int - v = self._valueToPos(value) - self._splitter.splitterMoved.disconnect() - self._splitter.moveSplitter(v, self._SPLIT_END) - self._splitter.splitterMoved.connect(self._handleMoveSplitter) - self._setEnd(value) - - def drawValues(self): - """:return: True if slider values will be drawn""" - return getattr(self, '__drawValues', None) - - def setDrawValues(self, draw): - """sets draw values boolean to draw slider values""" - assert type(draw) is bool - setattr(self, '__drawValues', draw) - - def getRange(self): - """:return: the start and end values as a tuple""" - return (self.start(), self.end()) - - def setRange(self, start, end): - """set the start and end values""" - self.setStart(start) - self.setEnd(end) - - def keyPressEvent(self, event): - """overrides key press event to move range left and right""" - key = event.key() - if key == QtCore.Qt.Key_Left: - s = self.start()-1 - e = self.end()-1 - elif key == QtCore.Qt.Key_Right: - s = self.start()+1 - e = self.end()+1 - else: - event.ignore() - return - event.accept() - if s >= self.min() and e <= self.max(): - self.setRange(s, e) - - def setBackgroundStyle(self, style): - """sets background style""" - self._tail.setStyleSheet(style) - self._head.setStyleSheet(style) - - def setSpanStyle(self, style): - """sets range span handle style""" - self._handle.setStyleSheet(style) - - def _valueToPos(self, value): - """converts slider value to local pixel x coord""" - return scale(value, (self.min(), self.max()), (0, self.width())) - - def _posToValue(self, xpos): - """converts local pixel x coord to slider value""" - return scale(xpos, (0, self.width()), (self.min(), self.max())) - - def _handleMoveSplitter(self, xpos, index): - """private method for handling moving splitter handles""" - hw = self._splitter.handleWidth() - - def _lockWidth(widget): - width = widget.size().width() - widget.setMinimumWidth(width) - widget.setMaximumWidth(width) - - def _unlockWidth(widget): - widget.setMinimumWidth(0) - widget.setMaximumWidth(16777215) - - v = self._posToValue(xpos) - - if index == self._SPLIT_START: - _lockWidth(self._tail) - if v >= self.end(): - return - - offset = -20 - w = xpos + offset - self._setStart(v) - - elif index == self._SPLIT_END: - _lockWidth(self._head) - if v <= self.start(): - return - - offset = -40 - w = self.width() - xpos + offset - self._setEnd(v) - - _unlockWidth(self._tail) - _unlockWidth(self._head) - _unlockWidth(self._handle) - - -#------------------------------------------------------------------------------- -# MAIN -#------------------------------------------------------------------------------- - -if __name__ == '__main__': - app = QtGui.QApplication(sys.argv) - rs = QRangeSlider() - rs.show() - rs.setRange(15, 35) - rs.setBackgroundStyle('background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #222, stop:1 #333);') - rs.handle.setStyleSheet('background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #282, stop:1 #393);') - app.exec_() diff --git a/libs/qrangeslider-0.1.1/setup.py b/libs/qrangeslider-0.1.1/setup.py deleted file mode 100644 index 76fd96a6274e1b39ae0bcd207f0d4dac5ca4d190..0000000000000000000000000000000000000000 --- a/libs/qrangeslider-0.1.1/setup.py +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env python -# -# Copyright (C) 2011-2014 Ryan Galloway (ryan@rsgalloway.com) -# -# This module is part of Shotman and is released under -# the BSD License: http://www.opensource.org/licenses/bsd-license.php - -from distutils.core import setup -from qrangeslider import __version__ -setup(name='qrangeslider', - version=__version__, - description='The QRangeSlider class implements a horizontal PyQt range slider widget.', - author='Ryan Galloway', - author_email='ryan@rsgalloway.com', - url='http://github.com/rsgalloway/qrangeslider', - py_modules=['qrangeslider'] - ) diff --git a/qimage2ndarray/LICENSE.txt b/qimage2ndarray/LICENSE.txt deleted file mode 100644 index 96d599dac8fc563eb78b9305e428df72944a6678..0000000000000000000000000000000000000000 --- a/qimage2ndarray/LICENSE.txt +++ /dev/null @@ -1,30 +0,0 @@ -Copyright (c) 2009, Hans Meine <hans_meine@gmx.net> -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the - distribution. - -3. Neither the name of the University of Hamburg nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/qimage2ndarray/__init__.py b/qimage2ndarray/__init__.py deleted file mode 100644 index 6e56e0e06dd75127d37a7b5918acf431b9824c32..0000000000000000000000000000000000000000 --- a/qimage2ndarray/__init__.py +++ /dev/null @@ -1,403 +0,0 @@ -import sys as _sys -import numpy as _np - -from .dynqt import QtGui as _qt - -from .dynqt import qt as _qt_driver -if _qt_driver.name() == 'PythonQt': - from .qimageview import QImage2ndarray as _temp - _qimageview = _temp.qimageview -else: - from .qimageview_python import qimageview as _qimageview - -__version__ = "1.5" - -if _sys.byteorder == 'little': - _bgra = (0, 1, 2, 3) -else: - _bgra = (3, 2, 1, 0) - -_bgra_fields = {'b': (_np.uint8, _bgra[0], 'blue'), - 'g': (_np.uint8, _bgra[1], 'green'), - 'r': (_np.uint8, _bgra[2], 'red'), - 'a': (_np.uint8, _bgra[3], 'alpha')} - -bgra_dtype = _np.dtype(_bgra_fields) -"""Complex dtype offering the named fields 'r','g','b', and 'a' and -corresponding long names, conforming to QImage_'s 32-bit memory layout.""" - -try: - _basestring = basestring -except NameError: - # 'basestring' undefined, must be Python 3 - _basestring = str - -def _qimage_or_filename_view(qimage): - if isinstance(qimage, _basestring): - qimage = _qt.QImage(qimage) - return _qimageview(qimage) - -def raw_view(qimage): - """Returns raw 2D view of the given QImage_'s memory. The result - will be a 2-dimensional numpy.ndarray with an appropriately sized - integral dtype. (This function is not intented to be used - directly, but used internally by the other -- more convenient -- - view creation functions.) - - :param qimage: image whose memory shall be accessed via NumPy - :type qimage: QImage_ - :rtype: numpy.ndarray_ with shape (height, width)""" - return _qimage_or_filename_view(qimage) - - -def byte_view(qimage, byteorder = 'little'): - """Returns raw 3D view of the given QImage_'s memory. This will - always be a 3-dimensional numpy.ndarray with dtype numpy.uint8. - - Note that for 32-bit images, the last dimension will be in the - [B,G,R,A] order (if little endian) due to QImage_'s memory layout - (the alpha channel will be present for Format_RGB32 images, too). - - For 8-bit (indexed) images, the array will still be 3-dimensional, - i.e. shape will be (height, width, 1). - - The order of channels in the last axis depends on the `byteorder`, - which defaults to 'little', i.e. BGRA order. You may set the - argument `byteorder` to 'big' to get ARGB, or use None which means - sys.byteorder here, i.e. return native order for the machine the - code is running on. - - For your convenience, `qimage` may also be a filename, see - `Loading and Saving Images`_ in the documentation. - - :param qimage: image whose memory shall be accessed via NumPy - :type qimage: QImage_ - :param byteorder: specify order of channels in last axis - :rtype: numpy.ndarray_ with shape (height, width, 1 or 4) and dtype uint8""" - raw = _qimage_or_filename_view(qimage) - result = raw.view(_np.uint8).reshape(raw.shape + (-1, )) - if byteorder and byteorder != _sys.byteorder: - result = result[...,::-1] - return result - - -def rgb_view(qimage, byteorder = 'big'): - """Returns RGB view of a given 32-bit color QImage_'s memory. - Similarly to byte_view(), the result is a 3D numpy.uint8 array, - but reduced to the rgb dimensions (without alpha), and reordered - (using negative strides in the last dimension) to have the usual - [R,G,B] order. The image must have 32 bit pixel size, i.e. be - RGB32, ARGB32, or ARGB32_Premultiplied. (Note that in the latter - case, the values are of course premultiplied with alpha.) - - The order of channels in the last axis depends on the `byteorder`, - which defaults to 'big', i.e. RGB order. You may set the argument - `byteorder` to 'little' to get BGR, or use None which means - sys.byteorder here, i.e. return native order for the machine the - code is running on. - - For your convenience, `qimage` may also be a filename, see - `Loading and Saving Images`_ in the documentation. - - :param qimage: image whose memory shall be accessed via NumPy - :type qimage: QImage_ with 32-bit pixel type - :param byteorder: specify order of channels in last axis - :rtype: numpy.ndarray_ with shape (height, width, 3) and dtype uint8""" - if byteorder is None: - byteorder = _sys.byteorder - bytes = byte_view(qimage, byteorder) - if bytes.shape[2] != 4: - raise ValueError("For rgb_view, the image must have 32 bit pixel size (use RGB32, ARGB32, or ARGB32_Premultiplied)") - - if byteorder == 'little': - return bytes[...,:3] # strip A off BGRA - else: - return bytes[...,1:] # strip A off ARGB - - -def alpha_view(qimage): - """Returns alpha view of a given 32-bit color QImage_'s memory. - The result is a 2D numpy.uint8 array, equivalent to - byte_view(qimage)[...,3]. The image must have 32 bit pixel size, - i.e. be RGB32, ARGB32, or ARGB32_Premultiplied. Note that it is - not enforced that the given qimage has a format that actually - *uses* the alpha channel -- for Format_RGB32, the alpha channel - usually contains 255 everywhere. - - For your convenience, `qimage` may also be a filename, see - `Loading and Saving Images`_ in the documentation. - - :param qimage: image whose memory shall be accessed via NumPy - :type qimage: QImage_ with 32-bit pixel type - :rtype: numpy.ndarray_ with shape (height, width) and dtype uint8""" - bytes = byte_view(qimage, byteorder = None) - if bytes.shape[2] != 4: - raise ValueError("For alpha_view, the image must have 32 bit pixel size (use RGB32, ARGB32, or ARGB32_Premultiplied)") - return bytes[...,_bgra[3]] - - -def recarray_view(qimage): - """Returns recarray_ view of a given 32-bit color QImage_'s - memory. - - The result is a 2D array with a complex record dtype, offering the - named fields 'r','g','b', and 'a' and corresponding long names. - Thus, each color components can be accessed either via string - indexing or via attribute lookup (through numpy.recarray_): - - For your convenience, `qimage` may also be a filename, see - `Loading and Saving Images`_ in the documentation. - - >>> from PyQt4.QtGui import QImage, qRgb - >>> qimg = QImage(320, 240, QImage.Format_ARGB32) - >>> qimg.fill(qRgb(12,34,56)) - >>> - >>> import qimage2ndarray - >>> v = qimage2ndarray.recarray_view(qimg) - >>> - >>> red = v["r"] - >>> red[10,10] - 12 - >>> pixel = v[10,10] - >>> pixel["r"] - 12 - >>> (v.g == v["g"]).all() - True - >>> (v.alpha == 255).all() - True - - :param qimage: image whose memory shall be accessed via NumPy - :type qimage: QImage_ with 32-bit pixel type - :rtype: numpy.ndarray_ with shape (height, width) and dtype :data:`bgra_dtype`""" - raw = _qimage_or_filename_view(qimage) - if raw.itemsize != 4: - raise ValueError("For rgb_view, the image must have 32 bit pixel size (use RGB32, ARGB32, or ARGB32_Premultiplied)") - return raw.view(bgra_dtype, _np.recarray) - - - -def _normalize255(array, normalize, clip = (0, 255)): - if normalize: - if normalize is True: - normalize = array.min(), array.max() - if clip == (0, 255): - clip = None - elif _np.isscalar(normalize): - normalize = (0, normalize) - - nmin, nmax = normalize - - if nmin: - array = array - nmin - - if nmax != nmin: - scale = 255. / (nmax - nmin) - if scale != 1.0: - array = array * scale - - if clip: - low, high = clip - _np.clip(array, low, high, array) - - return array - - -def gray2qimage(gray, normalize = False): - """Convert the 2D numpy array `gray` into a 8-bit, indexed QImage_ - with a gray colormap. The first dimension represents the vertical - image axis. - - The parameter `normalize` can be used to normalize an image's - value range to 0..255: - - `normalize` = (nmin, nmax): - scale & clip image values from nmin..nmax to 0..255 - - `normalize` = nmax: - lets nmin default to zero, i.e. scale & clip the range 0..nmax - to 0..255 - - `normalize` = True: - scale image values to 0..255 (same as passing (gray.min(), - gray.max())) - - If the source array `gray` contains masked values, the result will - have only 255 shades of gray, and one color map entry will be used - to make the corresponding pixels transparent. - - A full alpha channel cannot be supported with indexed images; - instead, use `array2qimage` to convert into a 32-bit QImage. - - :param gray: image data which should be converted (copied) into a QImage_ - :type gray: 2D or 3D numpy.ndarray_ or `numpy.ma.array <masked arrays>`_ - :param normalize: normalization parameter (see above, default: no value changing) - :type normalize: bool, scalar, or pair - :rtype: QImage_ with RGB32 or ARGB32 format""" - if _np.ndim(gray) != 2: - raise ValueError("gray2QImage can only convert 2D arrays" + - " (try using array2qimage)" if _np.ndim(gray) == 3 else "") - - h, w = gray.shape - result = _qt.QImage(w, h, _qt.QImage.Format_Indexed8) - - if not _np.ma.is_masked(gray): - for i in range(256): - result.setColor(i, _qt.qRgb(i,i,i)) - - _qimageview(result)[:] = _normalize255(gray, normalize) - else: - # map gray value 1 to gray value 0, in order to make room for - # transparent colormap entry: - result.setColor(0, _qt.qRgb(0,0,0)) - for i in range(2, 256): - result.setColor(i-1, _qt.qRgb(i,i,i)) - - _qimageview(result)[:] = _normalize255(gray, normalize, clip = (1, 255)) - 1 - - result.setColor(255, 0) - _qimageview(result)[gray.mask] = 255 - - return result - - -def array2qimage(array, normalize = False): - """Convert a 2D or 3D numpy array into a 32-bit QImage_. The - first dimension represents the vertical image axis; the optional - third dimension is supposed to contain 1-4 channels: - - ========= =================== - #channels interpretation - ========= =================== - 1 scalar/gray - 2 scalar/gray + alpha - 3 RGB - 4 RGB + alpha - ========= =================== - - Scalar data will be converted into corresponding gray RGB triples; - if you want to convert to an (indexed) 8-bit image instead, use - `gray2qimage` (which cannot support an alpha channel though). - - The parameter `normalize` can be used to normalize an image's - value range to 0..255: - - `normalize` = (nmin, nmax): - scale & clip image values from nmin..nmax to 0..255 - - `normalize` = nmax: - lets nmin default to zero, i.e. scale & clip the range 0..nmax - to 0..255 - - `normalize` = True: - scale image values to 0..255 (same as passing (array.min(), - array.max())) - - If `array` contains masked values, the corresponding pixels will - be transparent in the result. Thus, the result will be of - QImage.Format_ARGB32 if the input already contains an alpha - channel (i.e. has shape (H,W,4)) or if there are masked pixels, - and QImage.Format_RGB32 otherwise. - - :param array: image data which should be converted (copied) into a QImage_ - :type array: 2D or 3D numpy.ndarray_ or `numpy.ma.array <masked arrays>`_ - :param normalize: normalization parameter (see above, default: no value changing) - :type normalize: bool, scalar, or pair - :rtype: QImage_ with RGB32 or ARGB32 format""" - if _np.ndim(array) == 2: - array = array[...,None] - elif _np.ndim(array) != 3: - raise ValueError("array2qimage can only convert 2D or 3D arrays (got %d dimensions)" % _np.ndim(array)) - if array.shape[2] not in (1, 2, 3, 4): - raise ValueError("array2qimage expects the last dimension to contain exactly one (scalar/gray), two (gray+alpha), three (R,G,B), or four (R,G,B,A) channels") - - h, w, channels = array.shape - - hasAlpha = _np.ma.is_masked(array) or channels in (2, 4) - fmt = _qt.QImage.Format_ARGB32 if hasAlpha else _qt.QImage.Format_RGB32 - - result = _qt.QImage(w, h, fmt) - - array = _normalize255(array, normalize) - - if channels >= 3: - rgb_view(result)[:] = array[...,:3] - else: - rgb_view(result)[:] = array[...,:1] # scalar data - - alpha = alpha_view(result) - - if channels in (2, 4): - alpha[:] = array[...,-1] - else: - alpha[:] = 255 - - if _np.ma.is_masked(array): - alpha[:] *= _np.logical_not(_np.any(array.mask, axis = -1)) - - return result - - -def imread(filename, masked = False): - """Convenience function that uses the QImage_ constructor to read an - image from the given file and return an `rgb_view` of the result. - This is intentionally similar to scipy.ndimage.imread (which uses - PIL), scipy.misc.imread, or matplotlib.pyplot.imread (using PIL - for non-PNGs). - - For grayscale images, return 2D array (even if it comes from a 32-bit - representation; this is a consequence of the QImage API). - - For images with an alpha channel, the resulting number of channels - will be 2 (grayscale+alpha) or 4 (RGB+alpha). Alternatively, one may - pass `masked = True' in order to get `numpy.ma.array <masked - arrays>`_ back. Note that only fully transparent pixels are masked - (and that masked arrays only support binary masks). The value of - `masked` is ignored when the loaded image has no alpha channel - (i.e., one would not get a masked array in that case). - - This function has been added in version 1.3. - - """ - qImage = _qt.QImage(filename) - - isGray = qImage.isGrayscale() - if isGray and qImage.depth() == 8: - return byte_view(qImage)[...,0] - - hasAlpha = qImage.hasAlphaChannel() - - if hasAlpha: - targetFormat = _qt.QImage.Format_ARGB32 - else: - targetFormat = _qt.QImage.Format_RGB32 - if qImage.format() != targetFormat: - qImage = qImage.convertToFormat(targetFormat) - - result = rgb_view(qImage) - if isGray: - result = result[...,0] - if hasAlpha: - if masked: - mask = (alpha_view(qImage) == 0) - if _np.ndim(result) == 3: - mask = _np.repeat(mask[...,None], 3, axis = 2) - result = _np.ma.masked_array(result, mask) - else: - result = _np.dstack((result, alpha_view(qImage))) - return result - - -def imsave(filename, image, normalize = False, format = None, quality = -1): - """Convenience function that uses QImage.save to save an image to the - given file. This is intentionally similar to scipy.misc.imsave. - However, it supports different optional arguments: - - :param normalize: see :func:`array2qimage` (which is used internally) - :param format: image filetype (e.g. 'PNG'), (default: check filename's suffix) - :param quality: see QImage.save (0 = small .. 100 = uncompressed, -1 = default compression) - :returns: boolean success, see QImage.save - - This function has been added in version 1.4. - """ - qImage = array2qimage(image, normalize = normalize) - return qImage.save(filename, format, quality) diff --git a/qimage2ndarray/dynqt.py b/qimage2ndarray/dynqt.py deleted file mode 100644 index a4f1a18bce006d81d848dfd98d881901e3af5bda..0000000000000000000000000000000000000000 --- a/qimage2ndarray/dynqt.py +++ /dev/null @@ -1,4 +0,0 @@ -from .qt_driver import QtDriver - -qt = QtDriver() -QtGui = qt.QtGui diff --git a/qimage2ndarray/qimageview_python.py b/qimage2ndarray/qimageview_python.py deleted file mode 100644 index 83efb2ddf0f9351992aef016f7ce1f4ac2eb83c9..0000000000000000000000000000000000000000 --- a/qimage2ndarray/qimageview_python.py +++ /dev/null @@ -1,60 +0,0 @@ -import numpy as np -from qimage2ndarray.dynqt import qt, QtGui - -def PyQt_data(image): - # PyQt4/PyQt5's QImage.bits() returns a sip.voidptr that supports - # conversion to string via asstring(size) or getting its base - # address via int(...): - return (int(image.bits()), False) - -def _re_buffer_address_match(buf_repr): - import re - _re_buffer_address = re.compile('<read-write buffer ptr 0x([0-9a-fA-F]*),') - global _re_buffer_address_match - _re_buffer_address_match = _re_buffer_address.match - return _re_buffer_address_match(buf_repr) - -def PySide_data(image): - # PySide's QImage.bits() returns a buffer object like this: - # <read-write buffer ptr 0x7fc3f4821600, size 76800 at 0x111269570> - ma = _re_buffer_address_match(repr(image.bits())) - assert ma, 'could not parse address from %r' % (image.bits(), ) - return (int(ma.group(1), 16), False) - -getdata = dict( - PyQt4 = PyQt_data, - PyQt5 = PyQt_data, - PySide = PySide_data, -)[qt.name()] - - -def qimageview(image): - if not isinstance(image, QtGui.QImage): - raise TypeError("image argument must be a QImage instance") - - shape = image.height(), image.width() - strides0 = image.bytesPerLine() - - format = image.format() - if format == QtGui.QImage.Format_Indexed8: - dtype = "|u1" - strides1 = 1 - elif format in (QtGui.QImage.Format_RGB32, QtGui.QImage.Format_ARGB32, QtGui.QImage.Format_ARGB32_Premultiplied): - dtype = "|u4" - strides1 = 4 - elif format == QtGui.QImage.Format_Invalid: - raise ValueError("qimageview got invalid QImage") - else: - raise ValueError("qimageview can only handle 8- or 32-bit QImages") - - image.__array_interface__ = { - 'shape': shape, - 'typestr': dtype, - 'data': getdata(image), - 'strides': (strides0, strides1), - 'version': 3, - } - - result = np.asarray(image) - del image.__array_interface__ - return result diff --git a/qimage2ndarray/qt_driver.py b/qimage2ndarray/qt_driver.py deleted file mode 100644 index 483cd287af1976d6c665860fa84d3304ece7273d..0000000000000000000000000000000000000000 --- a/qimage2ndarray/qt_driver.py +++ /dev/null @@ -1,125 +0,0 @@ -# Copyright 2014-2014 Hans Meine <hans_meine@gmx.net> -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""This module contains a wrapper around three different Qt python bindings. -It will dynamically decide which one to use: - -* First, the environment variable QT_DRIVER is checked - (may be one of 'PyQt5', 'PyQt4', 'PySide', 'PythonQt'). -* If unset, previously imported binding modules are detected (in sys.modules). -* If no bindings are loaded, the environment variable QT_API is checked - (used by ETS and ipython, may be 'pyside' or 'pyqt'). - -In order to have compatible behavior between the different bindings, -PyQt4 (if used) is configured as follows:: - - sip.setapi("QString", 2) - sip.setapi("QVariant", 2) - -Furthermore, there is a 'getprop' function that solves the following -problem: PythonQt exports Qt properties as Python properties *and* -gives the precedence over getters with the same name. Instead of -calling getters with parentheses (which must not be used in PythonQt, -but are required in PyQt and PySide), one may e.g. write -`getprop(widget.width)`. -""" - -import sys, os - -def getprop_PythonQt(prop): - """getprop(property_or_getter) - - Used on getters that have the same name as a corresponding - property. For PythonQt, this version will just return the - argument, which is assumed to be (the value of) a python property - through which PythonQt exposes Qt properties.""" - return prop - -def getprop_other(getter): - """getprop(property_or_getter) - - Used on getters that have the same name as a corresponding - property. For Qt bindings other than PythonQt, this version will - return the result of calling the argument, which is assumed to be - a Qt getter function. (With PythonQt, properties override getters - and no calling must be done.)""" - return getter() - -class QtDriver(object): - DRIVERS = ('PyQt5', 'PyQt4', 'PySide', 'PythonQt') - DEFAULT = 'PyQt4' - - @classmethod - def detect_qt(cls): - for drv in cls.DRIVERS: - if drv in sys.modules: - return drv - if '_PythonQt' in sys.modules: - return 'PythonQt' - return None - - def name(self): - return self._drv - - def getprop(self): - return getprop_PythonQt if self._drv == 'PythonQt' else getprop_other - - def __init__(self, drv = os.environ.get('QT_DRIVER')): - """Supports QT_API (used by ETS and ipython)""" - if drv is None: - drv = self.detect_qt() - if drv is None: - drv = os.environ.get('QT_API') - if drv is None: - drv = self.DEFAULT - drv = {'pyside' : 'PySide', 'pyqt' : 'PyQt4', 'pyqt5' : 'PyQt5'}.get(drv, drv) # map ETS syntax - assert drv in self.DRIVERS - self._drv = drv - - @staticmethod - def _initPyQt4(): - """initialize PyQt4 to be compatible with PySide""" - if 'PyQt4.QtCore' in sys.modules: - # too late to configure API - pass - else: - import sip - sip.setapi("QString", 2) - sip.setapi("QVariant", 2) - - @staticmethod - def requireCompatibleAPI(): - """If PyQt4's API should be configured to be compatible with PySide's - (i.e. QString and QVariant should not be explicitly exported, - cf. documentation of sip.setapi()), call this function to check that - the PyQt4 was properly imported. (It will always be configured this - way by this module, but it could have been imported before we got a - hand on doing so.) - """ - if 'PyQt4.QtCore' in sys.modules: - import sip - for api in ('QVariant', 'QString'): - if sip.getapi(api) != 2: - raise RuntimeError('%s API already set to V%d, but should be 2' % (api, sip.getapi(api))) - - def importMod(self, mod): - if self._drv == 'PyQt4': - self._initPyQt4() - qt = __import__('%s.%s' % (self._drv, mod)) - return getattr(qt, mod) - - def __getattr__(self, name): - if name.startswith('Qt'): - return self.importMod(name) - return super(QtDriver, self).__getattr__(name) diff --git a/testdata.txt b/testdata.txt index c6a15aa571c7bfed3e14fa9e31a7baf8a05a233c..04588d6a95fc1cecb9fdad358d26f2a5fdc6fbf1 100644 --- a/testdata.txt +++ b/testdata.txt @@ -1,26 +1,26 @@ -#Time series definition file: 2016-02-16T14:00:25Z +#Time series definition file: 2016-02-19T14:13:05Z #<image path>[;<mask path>] \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2012-04-07_LE72270652012098EDC00_BOA.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2012-04-23_LE72270652012114EDC00_BOA.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2012-05-09_LE72270652012130EDC00_BOA.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2012-05-25_LE72270652012146EDC00_BOA.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2012-06-10_LE72270652012162EDC00_BOA.vrt -\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A\2135822_2012-06-12_RE2_3A_328202\2135822_2012-06-12_RE2_3A_328202.tif +\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A_VRTs\re_2012-06-12.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2012-06-26_LE72270652012178EDC00_BOA.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2012-07-12_LE72270652012194EDC00_BOA.vrt -\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A\2135821_2012-07-24_RE1_3A_328202\2135821_2012-07-24_RE1_3A_328202.tif -\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A\2135822_2012-07-25_RE2_3A_328202\2135822_2012-07-25_RE2_3A_328202.tif +\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A_VRTs\re_2012-07-24.vrt +\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A_VRTs\re_2012-07-25.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2012-07-28_LE72270652012210EDC00_BOA.vrt -\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A\2135821_2012-08-05_RE3_3A_328202\2135821_2012-08-05_RE3_3A_328202.tif +\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A_VRTs\re_2012-08-05.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2012-08-29_LE72270652012242CUB00_BOA.vrt -\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A\2135822_2012-09-06_RE2_3A_328202\2135822_2012-09-06_RE2_3A_328202.tif +\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A_VRTs\re_2012-09-06.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2012-09-14_LE72270652012258EDC00_BOA.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2012-09-30_LE72270652012274CUB00_BOA.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2012-10-16_LE72270652012290CUB00_BOA.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2012-11-01_LE72270652012306CUB02_BOA.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2013-02-05_LE72270652013036CUB00_BOA.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2013-05-12_LE72270652013132CUB00_BOA.vrt -\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A\2135821_2013-05-18_RE4_3A_328202\2135821_2013-05-18_RE4_3A_328202.tif +\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A_VRTs\re_2013-05-18.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2013-05-20_LC82270652013140LGN01_BOA.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2013-06-05_LC82270652013156LGN00_BOA.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2013-06-21_LC82270652013172LGN00_BOA.vrt @@ -48,31 +48,31 @@ \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2014-05-23_LC82270652014143LGN00_BOA.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2014-05-31_LE72270652014151CUB00_BOA.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2014-06-08_LC82270652014159LGN00_BOA.vrt -\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A\2135821_2014-06-12_RE3_3A_328202\2135821_2014-06-12_RE3_3A_328202.tif +\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A_VRTs\re_2014-06-12.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2014-06-16_LE72270652014167CUB00_BOA.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2014-06-24_LC82270652014175LGN00_BOA.vrt -\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A\2135821_2014-06-25_RE2_3A_328202\2135821_2014-06-25_RE2_3A_328202.tif +\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A_VRTs\re_2014-06-25.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2014-07-02_LE72270652014183CUB00_BOA.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2014-07-10_LC82270652014191LGN00_BOA.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2014-07-18_LE72270652014199CUB00_BOA.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2014-07-26_LC82270652014207LGN00_BOA.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2014-08-03_LE72270652014215CUB00_BOA.vrt -\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A\2135821_2014-08-08_RE3_3A_328202\2135821_2014-08-08_RE3_3A_328202.tif -\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A\2136022_2014-08-10_RE5_3A_328202\2136022_2014-08-10_RE5_3A_328202.tif +\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A_VRTs\re_2014-08-08.vrt +\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A_VRTs\re_2014-08-10.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2014-08-11_LC82270652014223LGN00_BOA.vrt -\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A\2135822_2014-08-17_RE3_3A_328202\2135822_2014-08-17_RE3_3A_328202.tif +\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A_VRTs\re_2014-08-17.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2014-08-19_LE72270652014231CUB00_BOA.vrt -\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A\2135922_2014-08-20_RE1_3A_328202\2135922_2014-08-20_RE1_3A_328202.tif -\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A\2135821_2014-08-23_RE4_3A_328202\2135821_2014-08-23_RE4_3A_328202.tif -\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A\2135822_2014-08-25_RE1_3A_328202\2135822_2014-08-25_RE1_3A_328202.tif -\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A\2135822_2014-08-26_RE2_3A_328202\2135822_2014-08-26_RE2_3A_328202.tif +\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A_VRTs\re_2014-08-20.vrt +\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A_VRTs\re_2014-08-23.vrt +\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A_VRTs\re_2014-08-25.vrt +\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A_VRTs\re_2014-08-26.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2014-08-27_LC82270652014239LGN00_BOA.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2014-09-04_LE72270652014247CUB00_BOA.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2014-09-12_LC82270652014255LGN00_BOA.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2014-09-20_LE72270652014263CUB00_BOA.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2014-09-28_LC82270652014271LGN00_BOA.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2014-10-06_LE72270652014279CUB00_BOA.vrt -\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A\2135821_2014-10-10_RE4_3A_328202\2135821_2014-10-10_RE4_3A_328202.tif +\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A_VRTs\re_2014-10-10.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2014-10-14_LC82270652014287LGN00_BOA.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2014-11-07_LE72270652014311CUB00_BOA.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2014-11-15_LC82270652014319LGN00_BOA.vrt @@ -92,23 +92,25 @@ \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2015-05-26_LC82270652015146LGN00_BOA.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2015-06-03_LE72270652015154CUB00_BOA.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2015-06-11_LC82270652015162LGN00_BOA.vrt +\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A_VRTs\re_2015-06-13.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2015-06-19_LE72270652015170CUB00_BOA.vrt +\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A_VRTs\re_2015-06-19.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2015-06-27_LC82270652015178LGN00_BOA.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2015-07-13_LC82270652015194LGN00_BOA.vrt -\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A\2135822_2015-07-13_RE4_3A_328202\2135822_2015-07-13_RE4_3A_328202.tif -\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A\2135821_2015-07-17_RE3_3A_328202\2135821_2015-07-17_RE3_3A_328202.tif +\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A_VRTs\re_2015-07-13.vrt +\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A_VRTs\re_2015-07-17.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2015-07-21_LE72270652015202CUB00_BOA.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2015-07-29_LC82270652015210LGN00_BOA.vrt -\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A\2135822_2015-07-30_RE2_3A_328202\2135822_2015-07-30_RE2_3A_328202.tif -\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A\2135821_2015-08-04_RE2_3A_328202\2135821_2015-08-04_RE2_3A_328202.tif +\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A_VRTs\re_2015-07-30.vrt +\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A_VRTs\re_2015-08-04.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2015-08-06_LE72270652015218CUB00_BOA.vrt -\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A\2135821_2015-08-10_RE4_3A_328202\2135821_2015-08-10_RE4_3A_328202.tif +\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A_VRTs\re_2015-08-10.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2015-08-14_LC82270652015226LGN00_BOA.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2015-08-22_LE72270652015234CUB00_BOA.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2015-08-30_LC82270652015242LGN00_BOA.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2015-09-07_LE72270652015250ASN00_BOA.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2015-09-15_LC82270652015258LGN00_BOA.vrt -\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A\2136022_2015-09-18_RE5_3A_328202\2136022_2015-09-18_RE5_3A_328202.tif +\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A_VRTs\re_2015-09-18.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2015-09-23_LE72270652015266ASN00_BOA.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2015-10-01_LC82270652015274LGN00_BOA.vrt \\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT\2015-10-09_LE72270652015282ASN00_BOA.vrt