├── .gitattributes
├── tests
├── unittests
│ ├── __init__.py
│ └── test_qgis.py
├── testdata
│ ├── tri-time-test.nc
│ ├── ipf-borehole
│ │ ├── id_3.txt
│ │ ├── id_0.txt
│ │ ├── id_1.txt
│ │ ├── id_2.txt
│ │ └── boreholes.ipf
│ └── ipf-timeseries
│ │ ├── timeseries.ipf
│ │ ├── B30F0059001.txt
│ │ ├── B30F0217001.txt
│ │ └── B30F0222001.txt
└── test_pytest.py
├── imodqgis
├── dependencies
│ └── pyqtgraph_0_12_3
│ │ ├── util
│ │ ├── __init__.py
│ │ ├── colorama
│ │ │ ├── __init__.py
│ │ │ └── LICENSE.txt
│ │ ├── numba_helper.py
│ │ ├── cupy_helper.py
│ │ ├── get_resolution.py
│ │ ├── garbage_collector.py
│ │ └── pil_fix.py
│ │ ├── widgets
│ │ ├── __init__.py
│ │ ├── FileDialog.py
│ │ ├── BusyCursor.py
│ │ ├── MatplotlibWidget.py
│ │ ├── HistogramLUTWidget.py
│ │ ├── PathButton.py
│ │ ├── GraphicsLayoutWidget.py
│ │ ├── JoystickButton.py
│ │ └── ValueLabel.py
│ │ ├── Qt
│ │ ├── QtCore
│ │ │ └── __init__.py
│ │ ├── QtGui
│ │ │ └── __init__.py
│ │ └── QtWidgets
│ │ │ └── __init__.py
│ │ ├── opengl
│ │ ├── items
│ │ │ ├── __init__.py
│ │ │ ├── GLBarGraphItem.py
│ │ │ ├── GLAxisItem.py
│ │ │ ├── GLBoxItem.py
│ │ │ ├── GLGridItem.py
│ │ │ └── GLGradientLegendItem.py
│ │ ├── glInfo.py
│ │ └── __init__.py
│ │ ├── metaarray
│ │ ├── __init__.py
│ │ ├── license.txt
│ │ └── readMeta.m
│ │ ├── GraphicsScene
│ │ ├── __init__.py
│ │ ├── exportDialogTemplate.ui
│ │ ├── exportDialogTemplate_pyqt6.py
│ │ └── exportDialogTemplate_pyqt5.py
│ │ ├── console
│ │ ├── __init__.py
│ │ └── CmdInput.py
│ │ ├── dockarea
│ │ └── __init__.py
│ │ ├── graphicsItems
│ │ ├── ViewBox
│ │ │ └── __init__.py
│ │ ├── PlotItem
│ │ │ └── __init__.py
│ │ ├── ItemGroup.py
│ │ ├── __init__.py
│ │ ├── ButtonItem.py
│ │ ├── GraphicsObject.py
│ │ ├── GraphicsWidget.py
│ │ ├── ScaleBar.py
│ │ ├── MultiPlotItem.py
│ │ └── FillBetweenItem.py
│ │ ├── canvas
│ │ ├── __init__.py
│ │ ├── TransformGuiTemplate.ui
│ │ ├── CanvasManager.py
│ │ ├── TransformGuiTemplate_pyqt5.py
│ │ ├── TransformGuiTemplate_pyqt6.py
│ │ ├── TransformGuiTemplate_pyside2.py
│ │ └── TransformGuiTemplate_pyside6.py
│ │ ├── icons
│ │ ├── auto.png
│ │ ├── ctrl.png
│ │ ├── lock.png
│ │ ├── default.png
│ │ ├── __init__.py
│ │ └── invisibleEye.svg
│ │ ├── flowchart
│ │ ├── __init__.py
│ │ ├── library
│ │ │ └── __init__.py
│ │ ├── FlowchartGraphicsView.py
│ │ ├── FlowchartTemplate_pyside2.py
│ │ ├── FlowchartTemplate_pyqt5.py
│ │ ├── FlowchartTemplate_pyqt6.py
│ │ ├── FlowchartTemplate.ui
│ │ ├── FlowchartTemplate_pyside6.py
│ │ ├── NodeLibrary.py
│ │ ├── FlowchartCtrlTemplate_pyqt5.py
│ │ ├── FlowchartCtrlTemplate_pyqt6.py
│ │ └── FlowchartCtrlTemplate_pyside2.py
│ │ ├── imageview
│ │ └── __init__.py
│ │ ├── parametertree
│ │ ├── __init__.py
│ │ └── parameterTypes
│ │ │ ├── bool.py
│ │ │ ├── str.py
│ │ │ ├── progress.py
│ │ │ ├── text.py
│ │ │ ├── color.py
│ │ │ ├── colormap.py
│ │ │ ├── font.py
│ │ │ ├── action.py
│ │ │ ├── calendar.py
│ │ │ ├── numeric.py
│ │ │ ├── __init__.py
│ │ │ └── qtenum.py
│ │ ├── exporters
│ │ ├── __init__.py
│ │ ├── HDF5Exporter.py
│ │ └── PrintExporter.py
│ │ ├── colors
│ │ └── maps
│ │ │ ├── PAL-relaxed.hex
│ │ │ └── PAL-relaxed_bright.hex
│ │ ├── ordereddict.py
│ │ ├── multiprocess
│ │ ├── __init__.py
│ │ └── bootstrap.py
│ │ ├── ptime.py
│ │ ├── functions_numba.py
│ │ ├── PlotData.py
│ │ ├── ThreadsafeTimer.py
│ │ ├── units.py
│ │ ├── frozenSupport.py
│ │ └── Transform3D.py
├── icon.png
├── arrow
│ ├── __init__.py
│ └── reading.py
├── utils
│ ├── __init__.py
│ ├── pathing.py
│ ├── temporal.py
│ ├── color.py
│ ├── user_communication.py
│ └── layers.py
├── resources.qrc
├── idf
│ ├── __init__.py
│ └── layer_styling.py
├── about
│ ├── __init__.py
│ ├── about_widget.py
│ └── about.md
├── viewer
│ └── __init__.py
├── nhi_data
│ └── __init__.py
├── timeseries
│ └── __init__.py
├── netcdf_manager
│ └── __init__.py
├── cross_section
│ └── __init__.py
├── __init__.py
├── gef
│ └── __init__.py
├── ipf
│ └── __init__.py
├── widgets
│ ├── dock_widget.py
│ ├── __init__.py
│ └── colors_dialog.py
└── icons
│ ├── deltares.svg
│ ├── time-series.svg
│ └── enabling-delta-life.svg
├── pyproject.toml
├── scripts
├── deploy.bat
├── package.bat
├── compile_resources.bat
└── add_spdx.py
├── setup.cfg
├── .gitignore
├── CONTRIBUTING.md
├── .github
├── running_tests_locally.md
└── workflows
│ └── package.yml
└── README.md
/.gitattributes:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/unittests/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/util/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/widgets/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/Qt/QtCore/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/Qt/QtGui/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/Qt/QtWidgets/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/opengl/items/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/util/colorama/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/imodqgis/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Deltares/imod-qgis/main/imodqgis/icon.png
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/metaarray/__init__.py:
--------------------------------------------------------------------------------
1 | from .MetaArray import *
2 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/GraphicsScene/__init__.py:
--------------------------------------------------------------------------------
1 | from .GraphicsScene import *
2 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/console/__init__.py:
--------------------------------------------------------------------------------
1 | from .Console import ConsoleWidget
2 |
--------------------------------------------------------------------------------
/imodqgis/arrow/__init__.py:
--------------------------------------------------------------------------------
1 | from imodqgis.arrow.reading import read_arrow
2 |
3 | __all__ = ["read_arrow"]
--------------------------------------------------------------------------------
/imodqgis/utils/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright © 2021 Deltares
2 | # SPDX-License-Identifier: GPL-2.0-or-later
3 | #
4 |
--------------------------------------------------------------------------------
/tests/testdata/tri-time-test.nc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Deltares/imod-qgis/main/tests/testdata/tri-time-test.nc
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/dockarea/__init__.py:
--------------------------------------------------------------------------------
1 | from .DockArea import DockArea
2 | from .Dock import Dock
3 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/graphicsItems/ViewBox/__init__.py:
--------------------------------------------------------------------------------
1 | from .ViewBox import ViewBox
2 |
3 | __all__ = ['ViewBox']
4 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/canvas/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from .Canvas import *
3 | from .CanvasItem import *
4 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/graphicsItems/PlotItem/__init__.py:
--------------------------------------------------------------------------------
1 | from .PlotItem import PlotItem
2 |
3 | __all__ = ['PlotItem']
4 |
--------------------------------------------------------------------------------
/tests/test_pytest.py:
--------------------------------------------------------------------------------
1 | """
2 | Test using pytest
3 | """
4 |
5 | def test_pytest():
6 | print("Hello world")
7 | assert True is True
8 |
--------------------------------------------------------------------------------
/imodqgis/resources.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | icon.png
4 |
5 |
6 |
--------------------------------------------------------------------------------
/tests/testdata/ipf-borehole/id_3.txt:
--------------------------------------------------------------------------------
1 | 4
2 | 2,2
3 | top,1e+20
4 | lithology,1e+20
5 | -30,"sand"
6 | -100,"sandy loam"
7 | -210,"clay"
8 | -300,"silt"
9 |
--------------------------------------------------------------------------------
/tests/testdata/ipf-borehole/id_0.txt:
--------------------------------------------------------------------------------
1 | 4
2 | 2,2
3 | top,1e+20
4 | lithology,1e+20
5 | 0,"silt"
6 | -100,"sandy loam"
7 | -200,"clay"
8 | -300,"silty clay"
9 |
--------------------------------------------------------------------------------
/tests/testdata/ipf-borehole/id_1.txt:
--------------------------------------------------------------------------------
1 | 4
2 | 2,2
3 | top,1e+20
4 | lithology,1e+20
5 | 50,"sandy loam"
6 | -150,"silty clay"
7 | -250,"clay"
8 | -400,"silt"
9 |
--------------------------------------------------------------------------------
/tests/testdata/ipf-borehole/id_2.txt:
--------------------------------------------------------------------------------
1 | 4
2 | 2,2
3 | top,1e+20
4 | lithology,1e+20
5 | 30,"sand"
6 | -50,"silty clay"
7 | -150,"silt"
8 | -200,"sandy loam"
9 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/icons/auto.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Deltares/imod-qgis/main/imodqgis/dependencies/pyqtgraph_0_12_3/icons/auto.png
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/icons/ctrl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Deltares/imod-qgis/main/imodqgis/dependencies/pyqtgraph_0_12_3/icons/ctrl.png
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/icons/lock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Deltares/imod-qgis/main/imodqgis/dependencies/pyqtgraph_0_12_3/icons/lock.png
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/icons/default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Deltares/imod-qgis/main/imodqgis/dependencies/pyqtgraph_0_12_3/icons/default.png
--------------------------------------------------------------------------------
/tests/testdata/ipf-timeseries/timeseries.ipf:
--------------------------------------------------------------------------------
1 | 3
2 | 3
3 | x
4 | y
5 | id
6 | 3,txt
7 | 92530,463930,"B30F0059001"
8 | 93100,464580,"B30F0217001"
9 | 92840,463680,"B30F0222001"
10 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/flowchart/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from .Flowchart import *
3 |
4 | from .library import getNodeType, registerNodeType, getNodeTree
5 |
--------------------------------------------------------------------------------
/tests/testdata/ipf-borehole/boreholes.ipf:
--------------------------------------------------------------------------------
1 | 4
2 | 3
3 | x
4 | y
5 | id
6 | 3,txt
7 | 139354,376437,"id_0"
8 | 146343,390891,"id_1"
9 | 144914,386603,"id_2"
10 | 141419,381043,"id_3"
11 |
--------------------------------------------------------------------------------
/imodqgis/idf/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright © 2021 Deltares
2 | # SPDX-License-Identifier: GPL-2.0-or-later
3 | #
4 | from imodqgis.idf.idf_dialog import ImodIdfDialog
5 |
6 | __all__ = ["ImodIdfDialog"]
7 |
--------------------------------------------------------------------------------
/imodqgis/about/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright © 2021 Deltares
2 | # SPDX-License-Identifier: GPL-2.0-or-later
3 | #
4 | from imodqgis.about.about_widget import ImodAboutDialog
5 |
6 | __all__ = ["ImodAboutDialog"]
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [tool.ruff]
2 | select = ["E", "F", "NPY", "PD", "C4", "I"]
3 | ignore = ["E501", "PD901"]
4 | fixable = ["I"]
5 | ignore-init-module-imports = true
6 | exclude = ["imodqgis/dependencies/*.py"]
--------------------------------------------------------------------------------
/imodqgis/viewer/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright © 2021 Deltares
2 | # SPDX-License-Identifier: GPL-2.0-or-later
3 | #
4 | from imodqgis.viewer.viewer_widget import ImodViewerWidget
5 |
6 | __all__ = ["ImodViewerWidget"]
--------------------------------------------------------------------------------
/imodqgis/nhi_data/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright © 2021 Deltares
2 | # SPDX-License-Identifier: GPL-2.0-or-later
3 | #
4 | from imodqgis.nhi_data.nhi_data_dialog import ImodNhiDataDialog
5 |
6 | __all__ = ["ImodNhiDataDialog"]
7 |
--------------------------------------------------------------------------------
/imodqgis/timeseries/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright © 2021 Deltares
2 | # SPDX-License-Identifier: GPL-2.0-or-later
3 | #
4 | from imodqgis.timeseries.timeseries_widget import ImodTimeSeriesWidget
5 |
6 | __all__ = ["ImodTimeSeriesWidget"]
7 |
--------------------------------------------------------------------------------
/imodqgis/netcdf_manager/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright © 2021 Deltares
2 | # SPDX-License-Identifier: GPL-2.0-or-later
3 | #
4 | from imodqgis.netcdf_manager.netcdf_widget import ImodNetcdfManagerWidget
5 |
6 | __all__ = ["ImodNetcdfManagerWidget"]
--------------------------------------------------------------------------------
/imodqgis/cross_section/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright © 2021 Deltares
2 | # SPDX-License-Identifier: GPL-2.0-or-later
3 | #
4 | from imodqgis.cross_section.cross_section_widget import ImodCrossSectionWidget
5 |
6 | __all__ = ["ImodCrossSectionWidget"]
--------------------------------------------------------------------------------
/scripts/deploy.bat:
--------------------------------------------------------------------------------
1 | set plugin_dir=%APPDATA%\QGIS\QGIS3\profiles\default\python\plugins
2 |
3 | rem Remove plugin folder before copying
4 | rmdir %plugin_dir%\imodqgis /S /Q
5 | rem Copy
6 | robocopy %~dp0\..\imodqgis %plugin_dir%\imodqgis /E
7 |
--------------------------------------------------------------------------------
/imodqgis/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright © 2021 Deltares
2 | # SPDX-License-Identifier: GPL-2.0-or-later
3 | #
4 | def classFactory(iface): # pylint: disable=invalid-name
5 | from imodqgis.imod_plugin import ImodPlugin
6 |
7 | return ImodPlugin(iface)
8 |
--------------------------------------------------------------------------------
/setup.cfg:
--------------------------------------------------------------------------------
1 | [options]
2 | packages = find:
3 | python_requires = >=3.7
4 | install_requires =
5 | pandas
6 | declxml
7 | pyqtgraph
8 |
9 | [options.extras_require]
10 | docs =
11 | pydata-sphinx-theme
12 | sphinx
13 | sphinx-gallery
14 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/imageview/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | Widget used for display and analysis of 2D and 3D image data.
3 | Includes ROI plotting over time and image normalization.
4 | """
5 |
6 | from .ImageView import ImageView
7 |
8 | __all__ = ['ImageView']
9 |
--------------------------------------------------------------------------------
/imodqgis/arrow/reading.py:
--------------------------------------------------------------------------------
1 | import pandas as pd
2 | from osgeo import ogr
3 |
4 |
5 | def read_arrow(path):
6 | dataset = ogr.Open(path)
7 | layer = dataset.GetLayer(0)
8 | stream = layer.GetArrowStreamAsNumPy()
9 | data = stream.GetNextRecordBatch()
10 | return pd.DataFrame(data=data)
11 |
--------------------------------------------------------------------------------
/imodqgis/gef/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright © 2021 Deltares
2 | # SPDX-License-Identifier: GPL-2.0-or-later
3 | #
4 | from imodqgis.gef.gef_dialog import ImodGefDialog
5 | from imodqgis.gef.reading import CptGefFile, GefType
6 |
7 | __all__ = [
8 | "ImodGefDialog",
9 | "CptGefFile",
10 | "GefType",
11 | ]
--------------------------------------------------------------------------------
/scripts/package.bat:
--------------------------------------------------------------------------------
1 |
2 | rem powershell equivalent to https://github.com/lutraconsulting/qgis-crayfish-plugin/blob/master/package.bash
3 |
4 | %systemroot%\System32\WindowsPowerShell\v1.0\powershell.exe -command "cd ..; rm -r -fo imodqgis.zip; cd imodqgis; git archive --prefix=imodqgis/ -o ../imodqgis.zip HEAD"
5 |
6 | pause
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/parametertree/__init__.py:
--------------------------------------------------------------------------------
1 | from .Parameter import Parameter, registerParameterType, registerParameterItemType
2 | from .ParameterTree import ParameterTree
3 | from .ParameterItem import ParameterItem
4 | from .ParameterSystem import ParameterSystem, SystemSolver
5 | from . import parameterTypes as types
6 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode/
2 | *.pyc
3 | __pycache__/
4 |
5 | # Unit test / coverage reports
6 | htmlcov/
7 | .tox/
8 | .coverage
9 | .coverage.*
10 | .cache
11 | .pytest_cache
12 | nosetests.xml
13 | coverage.xml
14 | *.cover
15 | .hypothesis/
16 |
17 | # Sphinx documentation
18 | docs/_build/
19 |
20 | # Locally packaged plugin
21 | imodqgis.zip
22 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/exporters/__init__.py:
--------------------------------------------------------------------------------
1 | from .Exporter import Exporter
2 | from .ImageExporter import *
3 | from .SVGExporter import *
4 | from .Matplotlib import *
5 | from .CSVExporter import *
6 | from .PrintExporter import *
7 | from .HDF5Exporter import *
8 |
9 | def listExporters():
10 | return Exporter.Exporters[:]
11 |
12 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/colors/maps/PAL-relaxed.hex:
--------------------------------------------------------------------------------
1 | ; PyQtGraph's "relaxed" plot color palette
2 | ; This is the darker variant for plotting on a light background ("light mode")
3 | ;
4 | #f97f10 ; orange
5 | #e5bb00 ; yellow
6 | #94ab00 ; grass
7 | #12a12a ; green
8 | #007c8c ; sea
9 | #0e56c2 ; blue
10 | #813be3 ; indigo
11 | #c01188 ; purple
12 | #e23512 ; red
13 | #f97f10 ; orange
14 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/colors/maps/PAL-relaxed_bright.hex:
--------------------------------------------------------------------------------
1 | ; PyQtGraph's "relaxed" plot color palette
2 | ; This is the brighter variant for plotting on a dark background ("dark mode")
3 | ;
4 | #ff9d47 ; orange
5 | #f7e100 ; yellow
6 | #b3cf00 ; grass
7 | #1ec23a ; green
8 | #00a0b5 ; sea
9 | #1f78ff ; blue
10 | #a54dff ; indigo
11 | #e22ca8 ; purple
12 | #ff532b ; red
13 | #ff9d47 ; orange
14 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/ordereddict.py:
--------------------------------------------------------------------------------
1 | import collections
2 | import warnings
3 |
4 |
5 | class OrderedDict(collections.OrderedDict):
6 | def __init__(self, *args, **kwds):
7 | warnings.warn(
8 | "OrderedDict is in the standard library for supported versions of Python. Will be removed in 0.13",
9 | DeprecationWarning,
10 | stacklevel=2,
11 | )
12 | super().__init__(*args, **kwds)
13 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/parametertree/parameterTypes/bool.py:
--------------------------------------------------------------------------------
1 | from ...Qt import QtWidgets
2 | from .basetypes import WidgetParameterItem
3 |
4 |
5 | class BoolParameterItem(WidgetParameterItem):
6 | """
7 | Registered parameter type which displays a QCheckBox
8 | """
9 | def makeWidget(self):
10 | w = QtWidgets.QCheckBox()
11 | w.sigChanged = w.toggled
12 | w.value = w.isChecked
13 | w.setValue = w.setChecked
14 | self.hideWidget = False
15 | return w
16 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/util/numba_helper.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from warnings import warn
3 |
4 | from .. import getConfigOption
5 |
6 | def getNumbaFunctions():
7 | if getConfigOption("useNumba"):
8 | try:
9 | import numba # noqa
10 | except ImportError:
11 | warn("numba library could not be loaded, but 'useNumba' is set.")
12 | return None
13 |
14 | from .. import functions_numba
15 | return functions_numba
16 | else:
17 | return None
18 |
--------------------------------------------------------------------------------
/imodqgis/ipf/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright © 2021 Deltares
2 | # SPDX-License-Identifier: GPL-2.0-or-later
3 | #
4 | from imodqgis.ipf.ipf_dialog import ImodIpfDialog
5 | from imodqgis.ipf.reading import (
6 | IpfType,
7 | read_associated_borehole,
8 | read_associated_header,
9 | read_associated_timeseries,
10 | read_ipf_header,
11 | )
12 |
13 | __all__ = [
14 | "ImodIpfDialog",
15 | "IpfType",
16 | "read_associated_borehole",
17 | "read_associated_header",
18 | "read_associated_timeseries",
19 | "read_ipf_header",
20 | ]
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/parametertree/parameterTypes/str.py:
--------------------------------------------------------------------------------
1 | from ...Qt import QtWidgets
2 | from .basetypes import WidgetParameterItem
3 |
4 |
5 | class StrParameterItem(WidgetParameterItem):
6 | """Registered parameter type which displays a QLineEdit"""
7 |
8 | def makeWidget(self):
9 | w = QtWidgets.QLineEdit()
10 | w.setStyleSheet('border: 0px')
11 | w.sigChanged = w.editingFinished
12 | w.value = w.text
13 | w.setValue = w.setText
14 | w.sigChanging = w.textChanged
15 | return w
16 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/opengl/glInfo.py:
--------------------------------------------------------------------------------
1 | from ..Qt import QtWidgets
2 | from OpenGL.GL import *
3 |
4 | class GLTest(QtWidgets.QOpenGLWidget):
5 | def initializeGL(self):
6 | print("GL version:" + glGetString(GL_VERSION).decode("utf-8"))
7 | print("MAX_TEXTURE_SIZE: %d" % glGetIntegerv(GL_MAX_TEXTURE_SIZE))
8 | print("MAX_3D_TEXTURE_SIZE: %d" % glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE))
9 | print("Extensions: " + glGetString(GL_EXTENSIONS).decode("utf-8").replace(" ", "\n"))
10 |
11 | app = QtWidgets.QApplication([])
12 | GLTest().show()
13 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/widgets/FileDialog.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from ..Qt import QtGui
3 | import sys
4 |
5 | __all__ = ['FileDialog']
6 |
7 | class FileDialog(QtGui.QFileDialog):
8 | ## Compatibility fix for OSX:
9 | ## For some reason the native dialog doesn't show up when you set AcceptMode to AcceptSave on OS X, so we don't use the native dialog
10 |
11 | def __init__(self, *args):
12 | QtGui.QFileDialog.__init__(self, *args)
13 |
14 | if sys.platform == 'darwin':
15 | self.setOption(QtGui.QFileDialog.Option.DontUseNativeDialog)
16 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/parametertree/parameterTypes/progress.py:
--------------------------------------------------------------------------------
1 | from ...Qt import QtWidgets
2 | from ..Parameter import Parameter
3 | from .basetypes import WidgetParameterItem
4 |
5 |
6 | class ProgressBarParameterItem(WidgetParameterItem):
7 | def makeWidget(self):
8 | w = QtWidgets.QProgressBar()
9 | w.setMaximumHeight(20)
10 | w.sigChanged = w.valueChanged
11 | self.hideWidget = False
12 | return w
13 |
14 |
15 | class ProgressBarParameter(Parameter):
16 | """
17 | Displays a progress bar whose value can be set between 0 and 100
18 | """
19 | itemClass = ProgressBarParameterItem
20 |
--------------------------------------------------------------------------------
/tests/unittests/test_qgis.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Test using the qgis testing framework.
4 |
5 | explained here:
6 | https://github.com/qgis/QGIS/tree/master/.docker
7 | """
8 |
9 | import sys
10 |
11 | from qgis.testing import unittest
12 |
13 |
14 | class TestTest(unittest.TestCase):
15 |
16 | def test_passes(self):
17 | self.assertTrue(True)
18 |
19 | def run_all():
20 | """Default function that is called by the runner if nothing else is specified"""
21 | suite = unittest.TestSuite()
22 | suite.addTests(unittest.makeSuite(TestTest, 'test'))
23 | unittest.TextTestRunner(verbosity=3, stream=sys.stdout).run(suite)
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/util/cupy_helper.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | import os
3 | from warnings import warn
4 |
5 | from .. import getConfigOption
6 |
7 |
8 | def getCupy():
9 | if getConfigOption("useCupy"):
10 | try:
11 | import cupy
12 | except ImportError:
13 | warn("cupy library could not be loaded, but 'useCupy' is set.")
14 | return None
15 | if os.name == "nt" and cupy.cuda.runtime.runtimeGetVersion() < 11000:
16 | warn("In Windows, CUDA toolkit should be version 11 or higher, or some functions may misbehave.")
17 | return cupy
18 | else:
19 | return None
20 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/graphicsItems/ItemGroup.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from ..Qt import QtCore
3 | from .GraphicsObject import GraphicsObject
4 |
5 | __all__ = ['ItemGroup']
6 | class ItemGroup(GraphicsObject):
7 | """
8 | Replacement for QGraphicsItemGroup
9 | """
10 |
11 | def __init__(self, *args):
12 | GraphicsObject.__init__(self, *args)
13 | self.setFlag(self.GraphicsItemFlag.ItemHasNoContents)
14 |
15 | def boundingRect(self):
16 | return QtCore.QRectF()
17 |
18 | def paint(self, *args):
19 | pass
20 |
21 | def addItem(self, item):
22 | item.setParentItem(self)
23 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/graphicsItems/__init__.py:
--------------------------------------------------------------------------------
1 | ### just import everything from sub-modules
2 |
3 | #import os
4 |
5 | #d = os.path.split(__file__)[0]
6 | #files = []
7 | #for f in os.listdir(d):
8 | #if os.path.isdir(os.path.join(d, f)):
9 | #files.append(f)
10 | #elif f[-3:] == '.py' and f != '__init__.py':
11 | #files.append(f[:-3])
12 |
13 | #for modName in files:
14 | #mod = __import__(modName, globals(), locals(), fromlist=['*'])
15 | #if hasattr(mod, '__all__'):
16 | #names = mod.__all__
17 | #else:
18 | #names = [n for n in dir(mod) if n[0] != '_']
19 | #for k in names:
20 | ##print modName, k
21 | #globals()[k] = getattr(mod, k)
22 |
--------------------------------------------------------------------------------
/imodqgis/utils/pathing.py:
--------------------------------------------------------------------------------
1 | # Copyright © 2021 Deltares
2 | # SPDX-License-Identifier: GPL-2.0-or-later
3 | #
4 | import os
5 | import platform
6 | from pathlib import Path
7 |
8 |
9 | def get_configdir() -> Path:
10 | """
11 | Get the location of the imod-qgis plugin settings.
12 |
13 | The location differs per OS. Configdir is created if not exists.
14 |
15 | Returns
16 | -------
17 | configdir: pathlib.Path
18 | """
19 | if platform.system() == "Windows":
20 | configdir = Path(os.environ["APPDATA"]) / "imod-qgis"
21 | else:
22 | configdir = Path(os.environ["HOME"]) / ".imod-qgis"
23 |
24 | # If not present, make directory
25 | configdir.mkdir(exist_ok=True, mode=766)
26 |
27 | return configdir
28 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/util/get_resolution.py:
--------------------------------------------------------------------------------
1 | from .. import mkQApp
2 | from ..Qt import QtGui
3 |
4 | def test_screenInformation():
5 | # a qApp is still needed, otherwise screen is None
6 | qApp = mkQApp()
7 | screen = QtGui.QGuiApplication.primaryScreen()
8 | screens = QtGui.QGuiApplication.screens()
9 | resolution = screen.size()
10 | availableResolution = screen.availableSize()
11 | print("Screen resolution: {}x{}".format(resolution.width(), resolution.height()))
12 | print("Available geometry: {}x{}".format(availableResolution.width(), availableResolution.height()))
13 | print("Number of Screens: {}".format(len(screens)))
14 | return None
15 |
16 |
17 | if __name__ == "__main__":
18 | test_screenInformation()
19 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/parametertree/parameterTypes/text.py:
--------------------------------------------------------------------------------
1 | from .basetypes import WidgetParameterItem
2 | from ..Parameter import Parameter
3 | from ...Qt import QtWidgets, QtCore
4 |
5 |
6 | class TextParameterItem(WidgetParameterItem):
7 | """ParameterItem displaying a QTextEdit widget."""
8 |
9 | def makeWidget(self):
10 | self.hideWidget = False
11 | self.asSubItem = True
12 | self.textBox = w = QtWidgets.QTextEdit()
13 | w.sizeHint = lambda: QtCore.QSize(300, 100)
14 | w.value = w.toPlainText
15 | w.setValue = w.setPlainText
16 | w.sigChanged = w.textChanged
17 | return w
18 |
19 |
20 | class TextParameter(Parameter):
21 | """Editable string, displayed as large text box in the tree."""
22 | itemClass = TextParameterItem
23 |
--------------------------------------------------------------------------------
/scripts/compile_resources.bat:
--------------------------------------------------------------------------------
1 | rem Set the OSGeo4W environmental variables
2 | rem See if OSGeo4W batch file exist in an OSGeo4W dir
3 | rem If that doesn't work, try to find the QGIS dir (version numbers may differ)
4 | if exist c:\OSGeo4W64\OSGeo4W.bat (
5 | call c:\OSGeo4W64\bin\o4w_env.bat
6 | call c:\OSGeo4W64\bin\qt5_env.bat
7 | call c:\OSGeo4W64\bin\py3_env.bat
8 | ) else (
9 | rem You have to use a for loop to set the output as a variable ...
10 | for /f "tokens=*" %%f in ('dir /b "c:\Program Files" ^| find "QGIS 3.1"') do (
11 | set qgis=%%f
12 | )
13 | call "c:\Program Files\%%qgis%%\bin\o4w_env.bat"
14 | call "c:\Program Files\%%qgis%%\bin\qt5_env.bat"
15 | call "c:\Program Files\%%qgis%%\bin\py3_env.bat"
16 | )
17 |
18 | cd ..\imodqgis
19 | call pyrcc5 resources.qrc -o resources.py
20 | pause
--------------------------------------------------------------------------------
/imodqgis/widgets/dock_widget.py:
--------------------------------------------------------------------------------
1 | # Copyright © 2021 Deltares
2 | # SPDX-License-Identifier: GPL-2.0-or-later
3 | #
4 | from qgis.gui import QgsDockWidget
5 | from qgis.PyQt.QtCore import Qt
6 |
7 | FLAGS = (
8 | Qt.CustomizeWindowHint
9 | | Qt.Window
10 | | Qt.WindowMinimizeButtonHint
11 | | Qt.WindowMaximizeButtonHint
12 | | Qt.WindowCloseButtonHint
13 | )
14 |
15 |
16 | class ImodDockWidget(QgsDockWidget):
17 | """
18 | This gives a minimize and maximize button to a DockWidget when detached.
19 | """
20 |
21 | def __init__(self, parent=None):
22 | QgsDockWidget.__init__(self, parent)
23 | self.topLevelChanged.connect(self.onTopLevelChanged)
24 |
25 | def onTopLevelChanged(self):
26 | sender = self.sender()
27 | if sender.isFloating():
28 | sender.setWindowFlags(FLAGS)
29 | sender.show()
30 |
--------------------------------------------------------------------------------
/imodqgis/utils/temporal.py:
--------------------------------------------------------------------------------
1 | # Copyright © 2021 Deltares
2 | # SPDX-License-Identifier: GPL-2.0-or-later
3 | #
4 | from qgis.core import (
5 | QgsMeshDatasetIndex,
6 | )
7 |
8 |
9 | def get_group_is_temporal(layer):
10 | """Returns list of booleans of which meshdataset groups are temporal"""
11 | indexes = layer.datasetGroupsIndexes()
12 | qgs_indexes = [QgsMeshDatasetIndex(group=i, dataset=0) for i in indexes]
13 | return [layer.datasetGroupMetadata(i).isTemporal() for i in qgs_indexes]
14 |
15 |
16 | def is_temporal_meshlayer(layer):
17 | """
18 | Return whether layer is temporal,
19 |
20 | There currently does not seem to exist a qgis mesh layer attribute that
21 | indicates whether there is a temporal dataset stored in a layer.
22 | If there is one, this function is obsolete.
23 | """
24 |
25 | return any(get_group_is_temporal(layer))
26 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/widgets/BusyCursor.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from contextlib import contextmanager
3 |
4 | from ..Qt import QtGui, QtCore
5 |
6 | __all__ = ["BusyCursor"]
7 |
8 |
9 | @contextmanager
10 | def BusyCursor():
11 | """
12 | Display a busy mouse cursor during long operations.
13 | Usage::
14 |
15 | with BusyCursor():
16 | doLongOperation()
17 |
18 | May be nested. If called from a non-gui thread, then the cursor will not be affected.
19 | """
20 | app = QtCore.QCoreApplication.instance()
21 | in_gui_thread = (app is not None) and (QtCore.QThread.currentThread() == app.thread())
22 | try:
23 | if in_gui_thread:
24 | QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.CursorShape.WaitCursor))
25 | yield
26 | finally:
27 | if in_gui_thread:
28 | QtGui.QApplication.restoreOverrideCursor()
29 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/flowchart/library/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from collections import OrderedDict
3 | import os, types
4 | from ...debug import printExc
5 | from ..NodeLibrary import NodeLibrary, isNodeClass
6 | from ... import reload as reload
7 |
8 |
9 | # Build default library
10 | LIBRARY = NodeLibrary()
11 |
12 | # For backward compatibility, expose the default library's properties here:
13 | NODE_LIST = LIBRARY.nodeList
14 | NODE_TREE = LIBRARY.nodeTree
15 | registerNodeType = LIBRARY.addNodeType
16 | getNodeTree = LIBRARY.getNodeTree
17 | getNodeType = LIBRARY.getNodeType
18 |
19 | # Add all nodes to the default library
20 | from . import Data, Display, Filters, Operators
21 | for mod in [Data, Display, Filters, Operators]:
22 | nodes = [getattr(mod, name) for name in dir(mod) if isNodeClass(getattr(mod, name))]
23 | for node in nodes:
24 | LIBRARY.addNodeType(node, [(mod.__name__.split('.')[-1],)])
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | Useful links
2 | ============
3 |
4 | The PyQt5 and PyQgis documentation is quite scattered, and often we have to
5 | resort to reading the C++ API or calling ``dir()``. Here is a list of useful
6 | links which provide some information or examples on how to do things. Below are
7 | some useful links that helped us develop the plugin and its' test bench.
8 |
9 | PyQgis
10 | ------
11 |
12 | * [PyQgis API](https://qgis.org/pyqgis/3.16/)
13 | * [QGIS 3 Cheatsheet](https://github.com/All4Gis/QGIS-cheat-sheet/blob/master/QGIS3.md)
14 |
15 | Testing PyQgis
16 | --------------
17 |
18 | * [QGIS plugin testing demo](https://github.com/opengisch/qgis_plugins_test_demo)
19 | * [Python tests in QGIS repository](https://github.com/qgis/QGIS/tree/master/tests/src/python)
20 | * [GUI testing PyQt5 with signalspy](https://sharplydescribed.wordpress.com/2020/09/17/gui-qt5-testing-with-python-qsignalspy-qtest/)
21 | * [QTest in QGIS](https://gis.stackexchange.com/questions/250234/qtest-interactions-with-the-qgis-map-canvas)
22 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/multiprocess/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | Multiprocessing utility library
3 | (parallelization done the way I like it)
4 |
5 | Luke Campagnola
6 | 2012.06.10
7 |
8 | This library provides:
9 |
10 | - simple mechanism for starting a new python interpreter process that can be controlled from the original process
11 | (this allows, for example, displaying and manipulating plots in a remote process
12 | while the parent process is free to do other work)
13 | - proxy system that allows objects hosted in the remote process to be used as if they were local
14 | - Qt signal connection between processes
15 | - very simple in-line parallelization (fork only; does not work on windows) for number-crunching
16 |
17 | TODO:
18 | allow remote processes to serve as rendering engines that pass pixmaps back to the parent process for display
19 | (RemoteGraphicsView class)
20 | """
21 |
22 | from .processes import *
23 | from .parallelizer import Parallelize, CanceledError
24 | from .remoteproxy import proxy, ClosedError, NoResultError
25 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/parametertree/parameterTypes/color.py:
--------------------------------------------------------------------------------
1 | from ...widgets.ColorButton import ColorButton
2 | from ... import functions as fn
3 | from .basetypes import WidgetParameterItem, SimpleParameter
4 |
5 |
6 | class ColorParameterItem(WidgetParameterItem):
7 | """Registered parameter type which displays a :class:`ColorButton ` """
8 | def makeWidget(self):
9 | w = ColorButton()
10 | w.sigChanged = w.sigColorChanged
11 | w.sigChanging = w.sigColorChanging
12 | w.value = w.color
13 | w.setValue = w.setColor
14 | self.hideWidget = False
15 | w.setFlat(True)
16 | return w
17 |
18 |
19 | class ColorParameter(SimpleParameter):
20 | itemClass = ColorParameterItem
21 |
22 | def _interpretValue(self, v):
23 | return fn.mkColor(v)
24 |
25 | def value(self):
26 | return fn.mkColor(super().value())
27 |
28 | def saveState(self, filter=None):
29 | state = super().saveState(filter)
30 | state['value'] = self.value().getRgb()
31 | return state
32 |
--------------------------------------------------------------------------------
/imodqgis/widgets/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright © 2021 Deltares
2 | # SPDX-License-Identifier: GPL-2.0-or-later
3 | #
4 | from imodqgis.widgets.colors_dialog import PSEUDOCOLOR, UNIQUE_COLOR, ColorsDialog
5 | from imodqgis.widgets.dataset_variable_widget import (
6 | MultipleVariablesWidget,
7 | VariablesWidget,
8 | )
9 | from imodqgis.widgets.dock_widget import ImodDockWidget
10 | from imodqgis.widgets.maptools import (
11 | LineGeometryPickerWidget,
12 | MultipleLineGeometryPickerWidget,
13 | PointGeometryPickerWidget,
14 | RectangleMapTool,
15 | )
16 | from imodqgis.widgets.pseudocolor_widget import ImodPseudoColorWidget
17 | from imodqgis.widgets.unique_color_widget import ImodUniqueColorWidget
18 |
19 | __all__ = [
20 | 'PSEUDOCOLOR',
21 | 'UNIQUE_COLOR',
22 | 'ColorsDialog',
23 | 'ImodDockWidget',
24 | 'ImodPseudoColorWidget',
25 | 'ImodUniqueColorWidget',
26 | 'LineGeometryPickerWidget',
27 | 'MultipleLineGeometryPickerWidget',
28 | 'MultipleVariablesWidget',
29 | 'PointGeometryPickerWidget',
30 | 'RectangleMapTool',
31 | 'VariablesWidget',
32 | ]
--------------------------------------------------------------------------------
/imodqgis/utils/color.py:
--------------------------------------------------------------------------------
1 | from PyQt5.QtGui import QColor
2 |
3 | from qgis.core import (
4 | QgsGradientStop,
5 | QgsGradientColorRamp
6 | )
7 | import numpy as np
8 |
9 | from typing import List
10 |
11 |
12 | def create_colorramp(
13 | boundaries: List[float],
14 | colors: List[QColor],
15 | discrete: bool = False,
16 | ):
17 | """
18 | Manually construct colorramp from boundaries and colors. The stops
19 | determined by the createColorRamp method appear to be broken.
20 | """
21 |
22 | # For some reason discrete colormaps require the last color also added as
23 | # stop
24 | if discrete:
25 | indices_stops = slice(1, None)
26 | else:
27 | indices_stops = slice(1, -1)
28 |
29 | bound_arr = np.array(boundaries)
30 | boundaries_norm = (bound_arr-bound_arr[0])/(bound_arr[-1]-bound_arr[0])
31 | stops = [
32 | QgsGradientStop(stop, color) for stop, color in zip(
33 | boundaries_norm[indices_stops], colors[indices_stops]
34 | )
35 | ]
36 | return QgsGradientColorRamp(colors[0], colors[-1], discrete, stops)
37 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/parametertree/parameterTypes/colormap.py:
--------------------------------------------------------------------------------
1 | from .basetypes import WidgetParameterItem, SimpleParameter
2 | from ...Qt import QtCore
3 | from ...colormap import ColorMap
4 | from ...widgets.GradientWidget import GradientWidget
5 |
6 |
7 | class ColorMapParameterItem(WidgetParameterItem):
8 | """Registered parameter type which displays a :class:`GradientWidget `"""
9 | def makeWidget(self):
10 | w = GradientWidget(orientation='bottom')
11 | w.sizeHint = lambda: QtCore.QSize(300, 35)
12 | w.sigChanged = w.sigGradientChangeFinished
13 | w.sigChanging = w.sigGradientChanged
14 | w.value = w.colorMap
15 | w.setValue = w.setColorMap
16 | self.hideWidget = False
17 | self.asSubItem = True
18 | return w
19 |
20 |
21 | class ColorMapParameter(SimpleParameter):
22 | itemClass = ColorMapParameterItem
23 |
24 | def _interpretValue(self, v):
25 | if v is not None and not isinstance(v, ColorMap):
26 | raise TypeError("Cannot set colormap parameter from object %r" % v)
27 | return v
28 |
--------------------------------------------------------------------------------
/imodqgis/about/about_widget.py:
--------------------------------------------------------------------------------
1 | # Copyright © 2021 Deltares
2 | # SPDX-License-Identifier: GPL-2.0-or-later
3 | #
4 | import os
5 |
6 | from PyQt5.QtWidgets import (
7 | QDialog,
8 | QLabel,
9 | QVBoxLayout,
10 | )
11 |
12 | path_text = os.path.abspath(os.path.join(os.path.dirname(__file__), "about.md"))
13 |
14 | with open(path_text) as file:
15 | TEXT = file.read()
16 |
17 |
18 | class ImodAboutDialog(QDialog):
19 | def __init__(self, iface, parent=None):
20 | QDialog.__init__(self, parent)
21 | self.setWindowTitle("About the iMOD plugin")
22 | self.iface = iface
23 |
24 | # Set minimum width of Dialog
25 | self.setMinimumWidth(800)
26 |
27 | self.text = QLabel()
28 |
29 | # Set MarkdownText as TextFormat
30 | # https://doc.qt.io/qt-5/qt.html#TextFormat-enum
31 | self.text.setTextFormat(3)
32 |
33 | # Allow hyperlinks to open a browser tab
34 | self.text.setOpenExternalLinks(True)
35 |
36 | self.text.setText(TEXT)
37 |
38 | layout = QVBoxLayout()
39 | layout.addWidget(self.text)
40 | self.setLayout(layout)
41 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/metaarray/license.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2010 Luke Campagnola ('luke.campagnola@%s.com' % 'gmail')
2 | The MIT License
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8 |
9 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/opengl/items/GLBarGraphItem.py:
--------------------------------------------------------------------------------
1 | from .GLMeshItem import GLMeshItem
2 | from ..MeshData import MeshData
3 | import numpy as np
4 |
5 | class GLBarGraphItem(GLMeshItem):
6 | def __init__(self, pos, size):
7 | """
8 | pos is (...,3) array of the bar positions (the corner of each bar)
9 | size is (...,3) array of the sizes of each bar
10 | """
11 | nCubes = np.prod(pos.shape[:-1])
12 | cubeVerts = np.mgrid[0:2,0:2,0:2].reshape(3,8).transpose().reshape(1,8,3)
13 | cubeFaces = np.array([
14 | [0,1,2], [3,2,1],
15 | [4,5,6], [7,6,5],
16 | [0,1,4], [5,4,1],
17 | [2,3,6], [7,6,3],
18 | [0,2,4], [6,4,2],
19 | [1,3,5], [7,5,3]]).reshape(1,12,3)
20 | size = size.reshape((nCubes, 1, 3))
21 | pos = pos.reshape((nCubes, 1, 3))
22 | verts = cubeVerts * size + pos
23 | faces = cubeFaces + (np.arange(nCubes) * 8).reshape(nCubes,1,1)
24 | md = MeshData(verts.reshape(nCubes*8,3), faces.reshape(nCubes*12,3))
25 |
26 | GLMeshItem.__init__(self, meshdata=md, shader='shaded', smooth=False)
27 |
--------------------------------------------------------------------------------
/scripts/add_spdx.py:
--------------------------------------------------------------------------------
1 | import sys
2 | from glob import glob
3 | from pathlib import Path
4 |
5 | SPDX = """\
6 | # Copyright © 2021 Deltares
7 | # SPDX-License-Identifier: GPL-2.0-or-later
8 | #
9 | """
10 |
11 | wdir = (Path(sys.path[0]) / ".." / "imodqgis").resolve()
12 |
13 | files = glob(str(wdir / "**" / "*.py"), recursive=True)
14 | files = [Path(file) for file in files]
15 |
16 | # Filter default scripts that were added by the QGIS plugin builder
17 | files = [file for file in files if not file.match("imodqgis/plugin_upload.py")]
18 | files = [file for file in files if not file.match("imodqgis/resources.py")]
19 |
20 | # Filter dependencies, we are not copyrighting those
21 | files = [file for file in files if "dependencies" not in list(file.parts)]
22 |
23 | for file in files:
24 | with open(file, "r+", encoding="utf-8") as fd:
25 | contents = fd.readlines()
26 | if contents[0:3] != SPDX.splitlines(True): # Only add SPDX if not yet in file
27 | contents.insert(0, SPDX) # new_string should end in a newline
28 | fd.seek(0) # readlines consumes the iterator, so we need to start over
29 | fd.writelines(contents) # No need to truncate as we are increasing filesize
30 |
--------------------------------------------------------------------------------
/imodqgis/utils/user_communication.py:
--------------------------------------------------------------------------------
1 | # Copyright © 2021 Deltares
2 | # SPDX-License-Identifier: GPL-2.0-or-later
3 | #
4 | from qgis.core import Qgis, QgsMessageLog
5 | from qgis.PyQt.QtWidgets import QMessageBox
6 |
7 |
8 | class UserCommunication:
9 | """Class for communication with user"""
10 |
11 | def __init__(self, iface, context):
12 | self.iface = iface
13 | self.context = context
14 |
15 | def show_info(self, msg):
16 | QMessageBox.information(self.iface.mainWindow(), self.context, msg)
17 |
18 | def show_warn(self, msg):
19 | QMessageBox.warning(self.iface.mainWindow(), self.context, msg)
20 |
21 | def log_info(self, msg):
22 | QgsMessageLog.logMessage(msg, self.context, QgsMessageLog.INFO)
23 |
24 | def bar_error(self, msg):
25 | self.iface.messageBar().pushMessage(self.context, msg, level=Qgis.Critical)
26 |
27 | def bar_warn(self, msg, dur=5):
28 | self.iface.messageBar().pushMessage(
29 | self.context, msg, level=Qgis.Warning, duration=dur
30 | )
31 |
32 | def bar_info(self, msg, dur=5):
33 | self.iface.messageBar().pushMessage(self.context, msg, duration=dur)
34 |
35 | def clear_bar_messages(self):
36 | self.iface.messageBar().clearWidgets()
37 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/widgets/MatplotlibWidget.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from ..Qt import QtGui
3 |
4 | from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
5 | from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
6 |
7 | from matplotlib.figure import Figure
8 |
9 | __all__ = ['MatplotlibWidget']
10 |
11 | class MatplotlibWidget(QtGui.QWidget):
12 | """
13 | Implements a Matplotlib figure inside a QWidget.
14 | Use getFigure() and redraw() to interact with matplotlib.
15 |
16 | Example::
17 |
18 | mw = MatplotlibWidget()
19 | subplot = mw.getFigure().add_subplot(111)
20 | subplot.plot(x,y)
21 | mw.draw()
22 | """
23 |
24 | def __init__(self, size=(5.0, 4.0), dpi=100):
25 | QtGui.QWidget.__init__(self)
26 | self.fig = Figure(size, dpi=dpi)
27 | self.canvas = FigureCanvas(self.fig)
28 | self.canvas.setParent(self)
29 | self.toolbar = NavigationToolbar(self.canvas, self)
30 |
31 | self.vbox = QtGui.QVBoxLayout()
32 | self.vbox.addWidget(self.toolbar)
33 | self.vbox.addWidget(self.canvas)
34 |
35 | self.setLayout(self.vbox)
36 |
37 | def getFigure(self):
38 | return self.fig
39 |
40 | def draw(self):
41 | self.canvas.draw()
42 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/console/CmdInput.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from ..Qt import QtCore, QtGui
3 |
4 | class CmdInput(QtGui.QLineEdit):
5 |
6 | sigExecuteCmd = QtCore.Signal(object)
7 |
8 | def __init__(self, parent):
9 | QtGui.QLineEdit.__init__(self, parent)
10 | self.history = [""]
11 | self.ptr = 0
12 |
13 | def keyPressEvent(self, ev):
14 | if ev.key() == QtCore.Qt.Key.Key_Up:
15 | if self.ptr < len(self.history) - 1:
16 | self.setHistory(self.ptr+1)
17 | ev.accept()
18 | return
19 | elif ev.key() == QtCore.Qt.Key.Key_Down:
20 | if self.ptr > 0:
21 | self.setHistory(self.ptr-1)
22 | ev.accept()
23 | return
24 | elif ev.key() == QtCore.Qt.Key.Key_Return:
25 | self.execCmd()
26 | else:
27 | super().keyPressEvent(ev)
28 | self.history[0] = self.text()
29 |
30 | def execCmd(self):
31 | cmd = self.text()
32 | if len(self.history) == 1 or cmd != self.history[1]:
33 | self.history.insert(1, cmd)
34 | self.history[0] = ""
35 | self.setHistory(0)
36 | self.sigExecuteCmd.emit(cmd)
37 |
38 | def setHistory(self, num):
39 | self.ptr = num
40 | self.setText(self.history[self.ptr])
41 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/parametertree/parameterTypes/font.py:
--------------------------------------------------------------------------------
1 | from .basetypes import WidgetParameterItem
2 | from ..Parameter import Parameter
3 | from ...Qt import QtWidgets, QtGui
4 |
5 |
6 | class FontParameterItem(WidgetParameterItem):
7 | def makeWidget(self):
8 | w = QtWidgets.QFontComboBox()
9 | w.setMaximumHeight(20)
10 | w.sigChanged = w.currentFontChanged
11 | w.value = w.currentFont
12 | w.setValue = w.setCurrentFont
13 | self.hideWidget = False
14 | return w
15 |
16 | def updateDisplayLabel(self, value=None):
17 | if value is None:
18 | value = self.widget.currentText()
19 | super().updateDisplayLabel(value)
20 |
21 |
22 | class FontParameter(Parameter):
23 | """
24 | Creates and controls a QFont value. Be careful when selecting options from the font dropdown. since not all
25 | fonts are available on all systems
26 | """
27 | itemClass = FontParameterItem
28 |
29 | def _interpretValue(self, v):
30 | if isinstance(v, str):
31 | newVal = QtGui.QFont()
32 | if not newVal.fromString(v):
33 | raise ValueError(f'Error parsing font "{v}"')
34 | v = newVal
35 | return v
36 |
37 | def saveState(self, filter=None):
38 | state = super().saveState(filter)
39 | state['value'] = state['value'].toString()
40 | return state
41 |
--------------------------------------------------------------------------------
/.github/running_tests_locally.md:
--------------------------------------------------------------------------------
1 |
2 | Running workflow on Windows
3 | ==========================
4 | This document describes how to run the github workflow on your windows machine.
5 | This makes writing tests doable.
6 |
7 | 1: Enable WSL2
8 | -------------------
9 | [Follow the instructions
10 | here.](https://docs.microsoft.com/en-us/windows/wsl/install-win10#manual-installation-steps)
11 |
12 | 2: Install Docker
13 | ---------------------
14 | [Follow the instructions here.](
15 | https://docs.docker.com/docker-for-windows/install/)
16 |
17 | 3: Install ``act``
18 | --------------------
19 | [Follow the instructions here.](https://github.com/nektos/act)
20 |
21 | 4: Manually modify 1 line in tests.yml
22 | ---------------------------------------
23 | Change the line under of code in tests.yml, for the step: "Install qgis image"
24 | Change the absolute path if your working directory is not ``c:/src/imod-qgis``!
25 |
26 | 5: Run ``act``
27 | -------------------
28 | Open up a prompt and run the command ``act``. This will fetch the QGIS docker
29 | image, and run the tests on it. **Note that you have to delete the running qgis
30 | container in order to run the complete workflow again!**
31 |
32 | 6: Re-run specific tests
33 | ---------------------------
34 | If you want to run specific tests on a running docker container, in your
35 | prompt, execute the following command:
36 | ``docker exec -t qgis-testing-environment sh -c "cd /tests_directory/tests && qgis_testrunner.sh unittests.test_maptools"``
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/ptime.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | ptime.py - Precision time function made os-independent (should have been taken care of by python)
4 | Copyright 2010 Luke Campagnola
5 | Distributed under MIT/X11 license. See license.txt for more information.
6 | """
7 |
8 |
9 | import sys
10 | import warnings
11 |
12 | from time import perf_counter as clock
13 | from time import time as system_time
14 |
15 | START_TIME = None
16 | time = None
17 |
18 | def winTime():
19 | """Return the current time in seconds with high precision (windows version, use Manager.time() to stay platform independent)."""
20 | warnings.warn(
21 | "'pg.time' will be removed from the library in the first release following January, 2022. Use time.perf_counter instead",
22 | DeprecationWarning, stacklevel=2
23 | )
24 | return clock() + START_TIME
25 |
26 | def unixTime():
27 | """Return the current time in seconds with high precision (unix version, use Manager.time() to stay platform independent)."""
28 | warnings.warn(
29 | "'pg.time' will be removed from the library in the first release following January, 2022. Use time.perf_counter instead",
30 | DeprecationWarning, stacklevel=2
31 | )
32 | return system_time()
33 |
34 |
35 | if sys.platform.startswith('win'):
36 | cstart = clock() ### Required to start the clock in windows
37 | START_TIME = system_time() - cstart
38 |
39 | time = winTime
40 | else:
41 | time = unixTime
42 |
43 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # iMOD-QGIS plugin
2 | This plugin aids exploring 4D geospatial data and links to the iMOD 3D viewer.
3 | It is part of a larger software suite, named [iMOD Suite](https://deltares.github.io/iMOD-Documentation/index.html).
4 |
5 | Primary components are:
6 |
7 | * Timeseries visualization
8 | * Cross-section visualization
9 | * Connecting to the iMOD 3D viewer
10 | * Reading .IPF files
11 | * Connecting to the NHI Data portal
12 |
13 | Mesh data can be used to store data with a time, z, y,
14 | and x dimension.
15 | Currently the z-dimension is only scarcely supported by MDAL.
16 | Therefore, for each vertical layer,
17 | we require a mesh dataset with the following variables:
18 |
19 | * `{var}_layer_{nr}`
20 | * `top_layer_{nr}`
21 | * `bottom_layer_{nr}`
22 |
23 | To prepare your datasets for the iMOD QGIS plugin, [we advice using this utility
24 | function in iMOD
25 | Python](https://deltares.github.io/imod-python/api/generated/util/imod.util.mdal_compliant_ugrid2d.html#imod.util.mdal_compliant_ugrid2d).
26 | If you'd like to prepare data yourself for the plugin, [follow this
27 | example.](https://deltares.github.io/iMOD-Documentation/tutorial_wq.html#convert-output-data).
28 | We expect to make this less specific in the future.
29 |
30 | ## Further reading
31 |
32 | * [Installation instructions](https://deltares.github.io/iMOD-Documentation/qgis_install.html)
33 |
34 | * [User manual](https://deltares.github.io/iMOD-Documentation/qgis_user_manual.html)
35 |
36 | * [Known issues](https://deltares.github.io/iMOD-Documentation/qgis_known_issues.html)
37 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/flowchart/FlowchartGraphicsView.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from ..Qt import QtGui, QtCore
3 | from ..widgets.GraphicsView import GraphicsView
4 | from ..graphicsItems.ViewBox import ViewBox
5 |
6 | translate = QtCore.QCoreApplication.translate
7 |
8 | class FlowchartGraphicsView(GraphicsView):
9 |
10 | sigHoverOver = QtCore.Signal(object)
11 | sigClicked = QtCore.Signal(object)
12 |
13 | def __init__(self, widget, *args):
14 | GraphicsView.__init__(self, *args, useOpenGL=False)
15 | self._vb = FlowchartViewBox(widget, lockAspect=True, invertY=True)
16 | self.setCentralItem(self._vb)
17 | self.setRenderHint(QtGui.QPainter.RenderHint.Antialiasing, True)
18 |
19 | def viewBox(self):
20 | return self._vb
21 |
22 |
23 | class FlowchartViewBox(ViewBox):
24 |
25 | def __init__(self, widget, *args, **kwargs):
26 | ViewBox.__init__(self, *args, **kwargs)
27 | self.widget = widget
28 |
29 | def getMenu(self, ev):
30 | ## called by ViewBox to create a new context menu
31 | self._fc_menu = QtGui.QMenu()
32 | self._subMenus = self.getContextMenus(ev)
33 | for menu in self._subMenus:
34 | self._fc_menu.addMenu(menu)
35 | return self._fc_menu
36 |
37 | def getContextMenus(self, ev):
38 | ## called by scene to add menus on to someone else's context menu
39 | menu = self.widget.buildMenu(ev.scenePos())
40 | menu.setTitle(translate("Context Menu", "Add node"))
41 | return [menu, ViewBox.getMenu(self, ev)]
42 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/util/colorama/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2010 Jonathan Hartley
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright notice, this
8 | list of conditions and the following disclaimer.
9 |
10 | * Redistributions in binary form must reproduce the above copyright notice,
11 | this list of conditions and the following disclaimer in the documentation
12 | and/or other materials provided with the distribution.
13 |
14 | * Neither the name of the copyright holders, nor those of its contributors
15 | may be used to endorse or promote products derived from this software without
16 | specific prior written permission.
17 |
18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 |
29 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/widgets/HistogramLUTWidget.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Widget displaying an image histogram along with gradient editor. Can be used to adjust
4 | the appearance of images. This is a wrapper around HistogramLUTItem
5 | """
6 |
7 | from ..Qt import QtGui, QtCore
8 | from .GraphicsView import GraphicsView
9 | from ..graphicsItems.HistogramLUTItem import HistogramLUTItem
10 |
11 | __all__ = ['HistogramLUTWidget']
12 |
13 |
14 | class HistogramLUTWidget(GraphicsView):
15 | """QWidget wrapper for :class:`~pyqtgraph.HistogramLUTItem`.
16 |
17 | All parameters are passed along in creating the HistogramLUTItem.
18 | """
19 |
20 | def __init__(self, parent=None, *args, **kargs):
21 | background = kargs.pop('background', 'default')
22 | GraphicsView.__init__(self, parent, useOpenGL=False, background=background)
23 | self.item = HistogramLUTItem(*args, **kargs)
24 | self.setCentralItem(self.item)
25 |
26 | self.orientation = kargs.get('orientation', 'vertical')
27 | if self.orientation == 'vertical':
28 | self.setSizePolicy(QtGui.QSizePolicy.Policy.Preferred, QtGui.QSizePolicy.Policy.Expanding)
29 | self.setMinimumWidth(95)
30 | else:
31 | self.setSizePolicy(QtGui.QSizePolicy.Policy.Expanding, QtGui.QSizePolicy.Policy.Preferred)
32 | self.setMinimumHeight(95)
33 |
34 | def sizeHint(self):
35 | if self.orientation == 'vertical':
36 | return QtCore.QSize(115, 200)
37 | else:
38 | return QtCore.QSize(200, 115)
39 |
40 | def __getattr__(self, attr):
41 | return getattr(self.item, attr)
42 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/functions_numba.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import numba
3 |
4 | rescale_functions = {}
5 |
6 | def rescale_clip_source(xx, scale, offset, vmin, vmax, yy):
7 | for i in range(xx.size):
8 | val = (xx[i] - offset) * scale
9 | yy[i] = min(max(val, vmin), vmax)
10 |
11 | def rescaleData(data, scale, offset, dtype, clip):
12 | data_out = np.empty_like(data, dtype=dtype)
13 | key = (data.dtype.name, data_out.dtype.name)
14 | func = rescale_functions.get(key)
15 | if func is None:
16 | func = numba.guvectorize(
17 | [f'{key[0]}[:],f8,f8,f8,f8,{key[1]}[:]'],
18 | '(n),(),(),(),()->(n)',
19 | nopython=True)(rescale_clip_source)
20 | rescale_functions[key] = func
21 | func(data, scale, offset, clip[0], clip[1], out=data_out)
22 | return data_out
23 |
24 | @numba.jit(nopython=True)
25 | def _rescale_and_lookup1d_function(data, scale, offset, lut, out):
26 | vmin, vmax = 0, lut.shape[0] - 1
27 | for r in range(data.shape[0]):
28 | for c in range(data.shape[1]):
29 | val = (data[r, c] - offset) * scale
30 | val = min(max(val, vmin), vmax)
31 | out[r, c] = lut[int(val)]
32 |
33 | def rescale_and_lookup1d(data, scale, offset, lut):
34 | # data should be floating point and 2d
35 | # lut is 1d
36 | data_out = np.empty_like(data, dtype=lut.dtype)
37 | _rescale_and_lookup1d_function(data, float(scale), float(offset), lut, data_out)
38 | return data_out
39 |
40 | @numba.jit(nopython=True)
41 | def numba_take(lut, data):
42 | # numba supports only the 1st two arguments of np.take
43 | return np.take(lut, data)
44 |
--------------------------------------------------------------------------------
/.github/workflows/package.yml:
--------------------------------------------------------------------------------
1 | # Modified from https://github.com/GispoCoding/qaava-qgis-plugin/blob/master/.github/workflows/tests.yml
2 | # workflow name
3 | name: Package
4 |
5 | # Controls when the action will run. Triggers the workflow on push or pull request
6 | # events but only for the wanted branches
7 | on:
8 | push:
9 | branches:
10 | - main
11 | tags:
12 | - 'v*' # or 'v*' if you only want tags starting with 'v'
13 | pull_request:
14 | branches:
15 | - main
16 |
17 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel
18 | jobs:
19 | package:
20 | # The type of runner that the job will run on
21 | runs-on: ubuntu-latest
22 |
23 | steps:
24 | - name: Checkout code
25 | uses: actions/checkout@v3
26 |
27 | - name: Copy plugin to directory for packaging
28 | run: |
29 | rm -rf imodqgis_packaged
30 | mkdir -m 755 imodqgis_packaged
31 | cp -R imodqgis imodqgis_packaged/imodqgis
32 | shell: bash
33 |
34 | - name: Create zip for release
35 | if: startsWith(github.ref, 'refs/tags/')
36 | run: |
37 | cd imodqgis_packaged
38 | zip -r ../imodqgis_${{ github.ref_name }}.zip .
39 | cd ..
40 |
41 | - name: Upload imodqgis to Github artifact
42 | if: always()
43 | uses: actions/upload-artifact@v4
44 | with:
45 | path: imodqgis_packaged
46 | name: imodqgis_${{ github.sha }}
47 |
48 | - name: Upload imodqgis to release
49 | if: startsWith(github.ref, 'refs/tags/')
50 | env:
51 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
52 | run: |
53 | gh release upload ${{ github.ref_name }} imodqgis_${{ github.ref_name }}.zip --clobber
54 |
--------------------------------------------------------------------------------
/imodqgis/icons/deltares.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/PlotData.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 |
3 |
4 | class PlotData(object):
5 | """
6 | Class used for managing plot data
7 | - allows data sharing between multiple graphics items (curve, scatter, graph..)
8 | - each item may define the columns it needs
9 | - column groupings ('pos' or x, y, z)
10 | - efficiently appendable
11 | - log, fft transformations
12 | - color mode conversion (float/byte/qcolor)
13 | - pen/brush conversion
14 | - per-field cached masking
15 | - allows multiple masking fields (different graphics need to mask on different criteria)
16 | - removal of nan/inf values
17 | - option for single value shared by entire column
18 | - cached downsampling
19 | - cached min / max / hasnan / isuniform
20 | """
21 | def __init__(self):
22 | self.fields = {}
23 |
24 | self.maxVals = {} ## cache for max/min
25 | self.minVals = {}
26 |
27 | def addFields(self, **fields):
28 | for f in fields:
29 | if f not in self.fields:
30 | self.fields[f] = None
31 |
32 | def hasField(self, f):
33 | return f in self.fields
34 |
35 | def __getitem__(self, field):
36 | return self.fields[field]
37 |
38 | def __setitem__(self, field, val):
39 | self.fields[field] = val
40 |
41 | def max(self, field):
42 | mx = self.maxVals.get(field, None)
43 | if mx is None:
44 | mx = np.max(self[field])
45 | self.maxVals[field] = mx
46 | return mx
47 |
48 | def min(self, field):
49 | mn = self.minVals.get(field, None)
50 | if mn is None:
51 | mn = np.min(self[field])
52 | self.minVals[field] = mn
53 | return mn
54 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/opengl/__init__.py:
--------------------------------------------------------------------------------
1 | from .GLViewWidget import GLViewWidget
2 |
3 | ## dynamic imports cause too many problems.
4 | #from .. import importAll
5 | #importAll('items', globals(), locals())
6 |
7 | from .items.GLGraphItem import *
8 | from .items.GLGridItem import *
9 | from .items.GLBarGraphItem import *
10 | from .items.GLScatterPlotItem import *
11 | from .items.GLMeshItem import *
12 | from .items.GLLinePlotItem import *
13 | from .items.GLAxisItem import *
14 | from .items.GLImageItem import *
15 | from .items.GLSurfacePlotItem import *
16 | from .items.GLBoxItem import *
17 | from .items.GLVolumeItem import *
18 | from .items.GLTextItem import *
19 | from .items.GLGradientLegendItem import *
20 |
21 | from .MeshData import MeshData
22 | ## for backward compatibility:
23 | #MeshData.MeshData = MeshData ## breaks autodoc.
24 |
25 | from . import shaders
26 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/ThreadsafeTimer.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from .Qt import QtCore
3 |
4 | __all__ = ['ThreadsafeTimer']
5 |
6 | class ThreadsafeTimer(QtCore.QObject):
7 | """
8 | Thread-safe replacement for QTimer.
9 | """
10 |
11 | timeout = QtCore.Signal()
12 | sigTimerStopRequested = QtCore.Signal()
13 | sigTimerStartRequested = QtCore.Signal(object)
14 |
15 | def __init__(self):
16 | QtCore.QObject.__init__(self)
17 | self.timer = QtCore.QTimer()
18 | self.timer.timeout.connect(self.timerFinished)
19 | self.timer.moveToThread(QtCore.QCoreApplication.instance().thread())
20 | self.moveToThread(QtCore.QCoreApplication.instance().thread())
21 | self.sigTimerStopRequested.connect(self.stop, QtCore.Qt.ConnectionType.QueuedConnection)
22 | self.sigTimerStartRequested.connect(self.start, QtCore.Qt.ConnectionType.QueuedConnection)
23 |
24 |
25 | def start(self, timeout):
26 | isGuiThread = QtCore.QThread.currentThread() == QtCore.QCoreApplication.instance().thread()
27 | if isGuiThread:
28 | #print "start timer", self, "from gui thread"
29 | self.timer.start(int(timeout))
30 | else:
31 | #print "start timer", self, "from remote thread"
32 | self.sigTimerStartRequested.emit(timeout)
33 |
34 | def stop(self):
35 | isGuiThread = QtCore.QThread.currentThread() == QtCore.QCoreApplication.instance().thread()
36 | if isGuiThread:
37 | #print "stop timer", self, "from gui thread"
38 | self.timer.stop()
39 | else:
40 | #print "stop timer", self, "from remote thread"
41 | self.sigTimerStopRequested.emit()
42 |
43 | def timerFinished(self):
44 | self.timeout.emit()
45 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/util/garbage_collector.py:
--------------------------------------------------------------------------------
1 | import gc
2 |
3 | from ..Qt import QtCore
4 |
5 | class GarbageCollector(object):
6 | '''
7 | Disable automatic garbage collection and instead collect manually
8 | on a timer.
9 |
10 | This is done to ensure that garbage collection only happens in the GUI
11 | thread, as otherwise Qt can crash.
12 |
13 | Credit: Erik Janssens
14 | Source: http://pydev.blogspot.com/2014/03/should-python-garbage-collector-be.html
15 | '''
16 |
17 | def __init__(self, interval=1.0, debug=False):
18 | self.debug = debug
19 | if debug:
20 | gc.set_debug(gc.DEBUG_LEAK)
21 |
22 | self.timer = QtCore.QTimer()
23 | self.timer.timeout.connect(self.check)
24 |
25 | self.threshold = gc.get_threshold()
26 | gc.disable()
27 | self.timer.start(interval * 1000)
28 |
29 | def check(self):
30 | #return self.debug_cycles() # uncomment to just debug cycles
31 | l0, l1, l2 = gc.get_count()
32 | if self.debug:
33 | print('gc_check called:', l0, l1, l2)
34 | if l0 > self.threshold[0]:
35 | num = gc.collect(0)
36 | if self.debug:
37 | print('collecting gen 0, found: %d unreachable' % num)
38 | if l1 > self.threshold[1]:
39 | num = gc.collect(1)
40 | if self.debug:
41 | print('collecting gen 1, found: %d unreachable' % num)
42 | if l2 > self.threshold[2]:
43 | num = gc.collect(2)
44 | if self.debug:
45 | print('collecting gen 2, found: %d unreachable' % num)
46 |
47 | def debug_cycles(self):
48 | gc.collect()
49 | for obj in gc.garbage:
50 | print(obj, repr(obj), type(obj))
51 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/widgets/PathButton.py:
--------------------------------------------------------------------------------
1 | from ..Qt import QtGui, QtCore
2 | from .. import functions as fn
3 |
4 | __all__ = ['PathButton']
5 |
6 |
7 | class PathButton(QtGui.QPushButton):
8 | """Simple PushButton extension that paints a QPainterPath centered on its face.
9 | """
10 | def __init__(self, parent=None, path=None, pen='default', brush=None, size=(30,30), margin=7):
11 | QtGui.QPushButton.__init__(self, parent)
12 | self.margin = margin
13 | self.path = None
14 | if pen == 'default':
15 | pen = 'k'
16 | self.setPen(pen)
17 | self.setBrush(brush)
18 | if path is not None:
19 | self.setPath(path)
20 | if size is not None:
21 | self.setFixedWidth(size[0])
22 | self.setFixedHeight(size[1])
23 |
24 | def setBrush(self, brush):
25 | self.brush = fn.mkBrush(brush)
26 |
27 | def setPen(self, *args, **kwargs):
28 | self.pen = fn.mkPen(*args, **kwargs)
29 |
30 | def setPath(self, path):
31 | self.path = path
32 | self.update()
33 |
34 | def paintEvent(self, ev):
35 | super().paintEvent(ev)
36 | margin = self.margin
37 | geom = QtCore.QRectF(0, 0, self.width(), self.height()).adjusted(margin, margin, -margin, -margin)
38 | rect = self.path.boundingRect()
39 | scale = min(geom.width() / float(rect.width()), geom.height() / float(rect.height()))
40 |
41 | p = QtGui.QPainter(self)
42 | p.setRenderHint(p.RenderHint.Antialiasing)
43 | p.translate(geom.center())
44 | p.scale(scale, scale)
45 | p.translate(-rect.center())
46 | p.setPen(self.pen)
47 | p.setBrush(self.brush)
48 | p.drawPath(self.path)
49 | p.end()
50 |
51 |
52 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/graphicsItems/ButtonItem.py:
--------------------------------------------------------------------------------
1 | from ..Qt import QtGui, QtCore
2 | from .GraphicsObject import GraphicsObject
3 |
4 | __all__ = ['ButtonItem']
5 | class ButtonItem(GraphicsObject):
6 | """Button graphicsItem displaying an image."""
7 |
8 | clicked = QtCore.Signal(object)
9 |
10 | def __init__(self, imageFile=None, width=None, parentItem=None, pixmap=None):
11 | self.enabled = True
12 | GraphicsObject.__init__(self)
13 | if imageFile is not None:
14 | self.setImageFile(imageFile)
15 | elif pixmap is not None:
16 | self.setPixmap(pixmap)
17 |
18 | if width is not None:
19 | s = float(width) / self.pixmap.width()
20 | self.setScale(s)
21 | if parentItem is not None:
22 | self.setParentItem(parentItem)
23 | self.setOpacity(0.7)
24 |
25 | def setImageFile(self, imageFile):
26 | self.setPixmap(QtGui.QPixmap(imageFile))
27 |
28 | def setPixmap(self, pixmap):
29 | self.pixmap = pixmap
30 | self.update()
31 |
32 | def mouseClickEvent(self, ev):
33 | if self.enabled:
34 | self.clicked.emit(self)
35 |
36 | def mouseHoverEvent(self, ev):
37 | if not self.enabled:
38 | return
39 | if ev.isEnter():
40 | self.setOpacity(1.0)
41 | else:
42 | self.setOpacity(0.7)
43 |
44 | def disable(self):
45 | self.enabled = False
46 | self.setOpacity(0.4)
47 |
48 | def enable(self):
49 | self.enabled = True
50 | self.setOpacity(0.7)
51 |
52 | def paint(self, p, *args):
53 | p.setRenderHint(p.RenderHint.Antialiasing)
54 | p.drawPixmap(0, 0, self.pixmap)
55 |
56 | def boundingRect(self):
57 | return QtCore.QRectF(self.pixmap.rect())
58 |
59 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/units.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Very simple unit support:
3 | # - creates variable names like 'mV' and 'kHz'
4 | # - the value assigned to the variable corresponds to the scale prefix
5 | # (mV = 0.001)
6 | # - the actual units are purely cosmetic for making code clearer:
7 | #
8 | # x = 20*pA is identical to x = 20*1e-12
9 | #
10 | # No unicode variable names (μ,Ω) allowed until python 3, but just assigning
11 | # them to the globals dict doesn't error in python 2.
12 | import unicodedata
13 |
14 | # All unicode identifiers get normalized automatically
15 | SI_PREFIXES = unicodedata.normalize("NFKC", u"yzafpnµm kMGTPEZY")
16 | UNITS = unicodedata.normalize("NFKC", u"m,s,g,W,J,V,A,F,T,Hz,Ohm,Ω,S,N,C,px,b,B,Pa").split(",")
17 | allUnits = {}
18 |
19 |
20 | def addUnit(prefix, val):
21 | g = globals()
22 | for u in UNITS:
23 | g[prefix + u] = val
24 | allUnits[prefix + u] = val
25 |
26 |
27 | for pre in SI_PREFIXES:
28 | v = SI_PREFIXES.index(pre) - 8
29 | if pre == " ":
30 | pre = ""
31 | addUnit(pre, 1000 ** v)
32 |
33 | addUnit("c", 0.01)
34 | addUnit("d", 0.1)
35 | addUnit("da", 10)
36 | addUnit("h", 100)
37 | # py2 compatibility
38 | addUnit("u", 1e-6)
39 |
40 |
41 | def evalUnits(unitStr):
42 | """
43 | Evaluate a unit string into ([numerators,...], [denominators,...])
44 | Examples:
45 | N m/s^2 => ([N, m], [s, s])
46 | A*s / V => ([A, s], [V,])
47 | """
48 | pass
49 |
50 |
51 | def formatUnits(units):
52 | """
53 | Format a unit specification ([numerators,...], [denominators,...])
54 | into a string (this is the inverse of evalUnits)
55 | """
56 | pass
57 |
58 |
59 | def simplify(units):
60 | """
61 | Cancel units that appear in both numerator and denominator, then attempt to replace
62 | groups of units with single units where possible (ie, J/s => W)
63 | """
64 | pass
65 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/multiprocess/bootstrap.py:
--------------------------------------------------------------------------------
1 | """For starting up remote processes"""
2 | import sys, pickle, os
3 | import importlib
4 |
5 | if __name__ == '__main__':
6 | if hasattr(os, 'setpgrp'):
7 | os.setpgrp() ## prevents signals (notably keyboard interrupt) being forwarded from parent to this process
8 | if sys.version[0] == '3':
9 | #name, port, authkey, ppid, targetStr, path, pyside = pickle.load(sys.stdin.buffer)
10 | opts = pickle.load(sys.stdin.buffer)
11 | else:
12 | #name, port, authkey, ppid, targetStr, path, pyside = pickle.load(sys.stdin)
13 | opts = pickle.load(sys.stdin)
14 | #print "key:", ' '.join([str(ord(x)) for x in authkey])
15 | path = opts.pop('path', None)
16 | if path is not None:
17 | if isinstance(path, str):
18 | # if string, just insert this into the path
19 | sys.path.insert(0, path)
20 | else:
21 | # if list, then replace the entire sys.path
22 | ## modify sys.path in place--no idea who already has a reference to the existing list.
23 | while len(sys.path) > 0:
24 | sys.path.pop()
25 | sys.path.extend(path)
26 |
27 | pyqtapis = opts.pop('pyqtapis', None)
28 | if pyqtapis is not None:
29 | try:
30 | from PyQt5 import sip
31 | except ImportError:
32 | import sip
33 | for k,v in pyqtapis.items():
34 | sip.setapi(k, v)
35 |
36 | qt_lib = opts.pop('qt_lib', None)
37 | if qt_lib is not None:
38 | globals()[qt_lib] = importlib.import_module(qt_lib)
39 |
40 | targetStr = opts.pop('targetStr')
41 | try:
42 | target = pickle.loads(targetStr) ## unpickling the target should import everything we need
43 | except:
44 | print("Current sys.path:", sys.path)
45 | raise
46 | target(**opts) ## Send all other options to the target function
47 | sys.exit(0)
48 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/graphicsItems/GraphicsObject.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from ..Qt import QtGui, QT_LIB
3 | if QT_LIB.startswith('PyQt'):
4 | from ..Qt import sip
5 | from .GraphicsItem import GraphicsItem
6 |
7 | __all__ = ['GraphicsObject']
8 | class GraphicsObject(GraphicsItem, QtGui.QGraphicsObject):
9 | """
10 | **Bases:** :class:`GraphicsItem `, :class:`QtGui.QGraphicsObject`
11 |
12 | Extension of QGraphicsObject with some useful methods (provided by :class:`GraphicsItem `)
13 | """
14 | _qtBaseClass = QtGui.QGraphicsObject
15 | def __init__(self, *args):
16 | self.__inform_view_on_changes = True
17 | QtGui.QGraphicsObject.__init__(self, *args)
18 | self.setFlag(self.GraphicsItemFlag.ItemSendsGeometryChanges)
19 | GraphicsItem.__init__(self)
20 |
21 | def itemChange(self, change, value):
22 | ret = super().itemChange(change, value)
23 | if change in [self.GraphicsItemChange.ItemParentHasChanged, self.GraphicsItemChange.ItemSceneHasChanged]:
24 | self.parentChanged()
25 | try:
26 | inform_view_on_change = self.__inform_view_on_changes
27 | except AttributeError:
28 | # It's possible that the attribute was already collected when the itemChange happened
29 | # (if it was triggered during the gc of the object).
30 | pass
31 | else:
32 | if inform_view_on_change and change in [self.GraphicsItemChange.ItemPositionHasChanged, self.GraphicsItemChange.ItemTransformHasChanged]:
33 | self.informViewBoundsChanged()
34 |
35 | ## workaround for pyqt bug:
36 | ## http://www.riverbankcomputing.com/pipermail/pyqt/2012-August/031818.html
37 | if QT_LIB == 'PyQt5' and change == self.GraphicsItemChange.ItemParentChange and isinstance(ret, QtGui.QGraphicsItem):
38 | ret = sip.cast(ret, QtGui.QGraphicsItem)
39 |
40 | return ret
41 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/frozenSupport.py:
--------------------------------------------------------------------------------
1 | ## Definitions helpful in frozen environments (eg py2exe)
2 | import os, sys, zipfile
3 |
4 | def listdir(path):
5 | """Replacement for os.listdir that works in frozen environments."""
6 | if not hasattr(sys, 'frozen'):
7 | return os.listdir(path)
8 |
9 | (zipPath, archivePath) = splitZip(path)
10 | if archivePath is None:
11 | return os.listdir(path)
12 |
13 | with zipfile.ZipFile(zipPath, "r") as zipobj:
14 | contents = zipobj.namelist()
15 | results = set()
16 | for name in contents:
17 | # components in zip archive paths are always separated by forward slash
18 | if name.startswith(archivePath) and len(name) > len(archivePath):
19 | name = name[len(archivePath):].split('/')[0]
20 | results.add(name)
21 | return list(results)
22 |
23 | def isdir(path):
24 | """Replacement for os.path.isdir that works in frozen environments."""
25 | if not hasattr(sys, 'frozen'):
26 | return os.path.isdir(path)
27 |
28 | (zipPath, archivePath) = splitZip(path)
29 | if archivePath is None:
30 | return os.path.isdir(path)
31 | with zipfile.ZipFile(zipPath, "r") as zipobj:
32 | contents = zipobj.namelist()
33 | archivePath = archivePath.rstrip('/') + '/' ## make sure there's exactly one '/' at the end
34 | for c in contents:
35 | if c.startswith(archivePath):
36 | return True
37 | return False
38 |
39 |
40 | def splitZip(path):
41 | """Splits a path containing a zip file into (zipfile, subpath).
42 | If there is no zip file, returns (path, None)"""
43 | components = os.path.normpath(path).split(os.sep)
44 | for index, component in enumerate(components):
45 | if component.endswith('.zip'):
46 | zipPath = os.sep.join(components[0:index+1])
47 | archivePath = ''.join([x+'/' for x in components[index+1:]])
48 | return (zipPath, archivePath)
49 | else:
50 | return (path, None)
51 |
52 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/metaarray/readMeta.m:
--------------------------------------------------------------------------------
1 | function f = readMeta(file)
2 | info = hdf5info(file);
3 | f = readMetaRecursive(info.GroupHierarchy.Groups(1));
4 | end
5 |
6 |
7 | function f = readMetaRecursive(root)
8 | typ = 0;
9 | for i = 1:length(root.Attributes)
10 | if strcmp(root.Attributes(i).Shortname, '_metaType_')
11 | typ = root.Attributes(i).Value.Data;
12 | break
13 | end
14 | end
15 | if typ == 0
16 | printf('group has no _metaType_')
17 | typ = 'dict';
18 | end
19 |
20 | list = 0;
21 | if strcmp(typ, 'list') || strcmp(typ, 'tuple')
22 | data = {};
23 | list = 1;
24 | elseif strcmp(typ, 'dict')
25 | data = struct();
26 | else
27 | printf('Unrecognized meta type %s', typ);
28 | data = struct();
29 | end
30 |
31 | for i = 1:length(root.Attributes)
32 | name = root.Attributes(i).Shortname;
33 | if strcmp(name, '_metaType_')
34 | continue
35 | end
36 | val = root.Attributes(i).Value;
37 | if isa(val, 'hdf5.h5string')
38 | val = val.Data;
39 | end
40 | if list
41 | ind = str2num(name)+1;
42 | data{ind} = val;
43 | else
44 | data.(name) = val;
45 | end
46 | end
47 |
48 | for i = 1:length(root.Datasets)
49 | fullName = root.Datasets(i).Name;
50 | name = stripName(fullName);
51 | file = root.Datasets(i).Filename;
52 | data2 = hdf5read(file, fullName);
53 | if list
54 | ind = str2num(name)+1;
55 | data{ind} = data2;
56 | else
57 | data.(name) = data2;
58 | end
59 | end
60 |
61 | for i = 1:length(root.Groups)
62 | name = stripName(root.Groups(i).Name);
63 | data2 = readMetaRecursive(root.Groups(i));
64 | if list
65 | ind = str2num(name)+1;
66 | data{ind} = data2;
67 | else
68 | data.(name) = data2;
69 | end
70 | end
71 | f = data;
72 | return;
73 | end
74 |
75 |
76 | function f = stripName(str)
77 | inds = strfind(str, '/');
78 | if isempty(inds)
79 | f = str;
80 | else
81 | f = str(inds(length(inds))+1:length(str));
82 | end
83 | end
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/Transform3D.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from .Qt import QtGui
3 | from . import functions as fn
4 | from .Vector import Vector
5 | import numpy as np
6 |
7 |
8 | class Transform3D(QtGui.QMatrix4x4):
9 | """
10 | Extension of QMatrix4x4 with some helpful methods added.
11 | """
12 | def __init__(self, *args):
13 | if len(args) == 1:
14 | if isinstance(args[0], (list, tuple, np.ndarray)):
15 | args = [x for y in args[0] for x in y]
16 | if len(args) != 16:
17 | raise TypeError("Single argument to Transform3D must have 16 elements.")
18 | elif isinstance(args[0], QtGui.QMatrix4x4):
19 | args = list(args[0].copyDataTo())
20 |
21 | QtGui.QMatrix4x4.__init__(self, *args)
22 |
23 | def matrix(self, nd=3):
24 | if nd == 3:
25 | return np.array(self.copyDataTo()).reshape(4,4)
26 | elif nd == 2:
27 | m = np.array(self.copyDataTo()).reshape(4,4)
28 | m[2] = m[3]
29 | m[:,2] = m[:,3]
30 | return m[:3,:3]
31 | else:
32 | raise Exception("Argument 'nd' must be 2 or 3")
33 |
34 | def map(self, obj):
35 | """
36 | Extends QMatrix4x4.map() to allow mapping (3, ...) arrays of coordinates
37 | """
38 | if isinstance(obj, np.ndarray) and obj.shape[0] in (2,3):
39 | if obj.ndim >= 2:
40 | return fn.transformCoordinates(self, obj)
41 | elif obj.ndim == 1:
42 | v = QtGui.QMatrix4x4.map(self, Vector(obj))
43 | return np.array([v.x(), v.y(), v.z()])[:obj.shape[0]]
44 | elif isinstance(obj, (list, tuple)):
45 | v = QtGui.QMatrix4x4.map(self, Vector(obj))
46 | return type(obj)([v.x(), v.y(), v.z()])[:len(obj)]
47 | else:
48 | return QtGui.QMatrix4x4.map(self, obj)
49 |
50 | def inverted(self):
51 | inv, b = QtGui.QMatrix4x4.inverted(self)
52 | return Transform3D(inv), b
53 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/opengl/items/GLAxisItem.py:
--------------------------------------------------------------------------------
1 | from OpenGL.GL import *
2 | from .. GLGraphicsItem import GLGraphicsItem
3 | from ... import QtGui
4 |
5 | __all__ = ['GLAxisItem']
6 |
7 | class GLAxisItem(GLGraphicsItem):
8 | """
9 | **Bases:** :class:`GLGraphicsItem `
10 |
11 | Displays three lines indicating origin and orientation of local coordinate system.
12 |
13 | """
14 |
15 | def __init__(self, size=None, antialias=True, glOptions='translucent'):
16 | GLGraphicsItem.__init__(self)
17 | if size is None:
18 | size = QtGui.QVector3D(1,1,1)
19 | self.antialias = antialias
20 | self.setSize(size=size)
21 | self.setGLOptions(glOptions)
22 |
23 | def setSize(self, x=None, y=None, z=None, size=None):
24 | """
25 | Set the size of the axes (in its local coordinate system; this does not affect the transform)
26 | Arguments can be x,y,z or size=QVector3D().
27 | """
28 | if size is not None:
29 | x = size.x()
30 | y = size.y()
31 | z = size.z()
32 | self.__size = [x,y,z]
33 | self.update()
34 |
35 | def size(self):
36 | return self.__size[:]
37 |
38 |
39 | def paint(self):
40 |
41 | #glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
42 | #glEnable( GL_BLEND )
43 | #glEnable( GL_ALPHA_TEST )
44 | self.setupGLState()
45 |
46 | if self.antialias:
47 | glEnable(GL_LINE_SMOOTH)
48 | glHint(GL_LINE_SMOOTH_HINT, GL_NICEST)
49 |
50 | glBegin( GL_LINES )
51 |
52 | x,y,z = self.size()
53 | glColor4f(0, 1, 0, .6) # z is green
54 | glVertex3f(0, 0, 0)
55 | glVertex3f(0, 0, z)
56 |
57 | glColor4f(1, 1, 0, .6) # y is yellow
58 | glVertex3f(0, 0, 0)
59 | glVertex3f(0, y, 0)
60 |
61 | glColor4f(0, 0, 1, .6) # x is blue
62 | glVertex3f(0, 0, 0)
63 | glVertex3f(x, 0, 0)
64 | glEnd()
65 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/parametertree/parameterTypes/action.py:
--------------------------------------------------------------------------------
1 | from ..ParameterItem import ParameterItem
2 | from ..Parameter import Parameter
3 | from ...Qt import QtWidgets, QtCore
4 |
5 |
6 | class ActionParameterItem(ParameterItem):
7 | """ParameterItem displaying a clickable button."""
8 | def __init__(self, param, depth):
9 | ParameterItem.__init__(self, param, depth)
10 | self.layoutWidget = QtWidgets.QWidget()
11 | self.layout = QtWidgets.QHBoxLayout()
12 | self.layout.setContentsMargins(0, 0, 0, 0)
13 | self.layoutWidget.setLayout(self.layout)
14 | self.button = QtWidgets.QPushButton()
15 | #self.layout.addSpacing(100)
16 | self.layout.addWidget(self.button)
17 | self.layout.addStretch()
18 | self.button.clicked.connect(self.buttonClicked)
19 | self.titleChanged()
20 | self.optsChanged(self.param, self.param.opts)
21 |
22 | def treeWidgetChanged(self):
23 | ParameterItem.treeWidgetChanged(self)
24 | tree = self.treeWidget()
25 | if tree is None:
26 | return
27 |
28 | self.setFirstColumnSpanned(True)
29 | tree.setItemWidget(self, 0, self.layoutWidget)
30 |
31 | def titleChanged(self):
32 | self.button.setText(self.param.title())
33 | self.setSizeHint(0, self.button.sizeHint())
34 |
35 | def optsChanged(self, param, opts):
36 | ParameterItem.optsChanged(self, param, opts)
37 |
38 | if 'enabled' in opts:
39 | self.button.setEnabled(opts['enabled'])
40 |
41 | if 'tip' in opts:
42 | self.button.setToolTip(opts['tip'])
43 |
44 | def buttonClicked(self):
45 | self.param.activate()
46 |
47 |
48 | class ActionParameter(Parameter):
49 | """Used for displaying a button within the tree.
50 |
51 | ``sigActivated(self)`` is emitted when the button is clicked.
52 | """
53 | itemClass = ActionParameterItem
54 | sigActivated = QtCore.Signal(object)
55 |
56 | def activate(self):
57 | self.sigActivated.emit(self)
58 | self.emitStateChanged('activated', None)
59 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/canvas/TransformGuiTemplate.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Form
4 |
5 |
6 |
7 | 0
8 | 0
9 | 224
10 | 117
11 |
12 |
13 |
14 |
15 | 0
16 | 0
17 |
18 |
19 |
20 | PyQtGraph
21 |
22 |
23 |
24 | 1
25 |
26 |
27 | 0
28 |
29 | -
30 |
31 |
32 | Translate:
33 |
34 |
35 |
36 | -
37 |
38 |
39 | Rotate:
40 |
41 |
42 |
43 | -
44 |
45 |
46 | Scale:
47 |
48 |
49 |
50 | -
51 |
52 |
-
53 |
54 |
55 |
56 |
57 |
58 | Mirror
59 |
60 |
61 |
62 | -
63 |
64 |
65 | Reflect
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/parametertree/parameterTypes/calendar.py:
--------------------------------------------------------------------------------
1 | from ...Qt import QtWidgets, QtCore
2 | from ..Parameter import Parameter
3 | from .basetypes import WidgetParameterItem
4 |
5 |
6 | class CalendarParameterItem(WidgetParameterItem):
7 | def makeWidget(self):
8 | self.asSubItem = True
9 | w = QtWidgets.QCalendarWidget()
10 | w.setMaximumHeight(200)
11 | w.sigChanged = w.selectionChanged
12 | w.value = w.selectedDate
13 | w.setValue = w.setSelectedDate
14 | self.hideWidget = False
15 | self.param.opts.setdefault('default', QtCore.QDate.currentDate())
16 | return w
17 |
18 |
19 | class CalendarParameter(Parameter):
20 | """
21 | Displays a Qt calendar whose date is specified by a 'format' option.
22 |
23 | ============== ========================================================
24 | **Options:**
25 | format Format for displaying the date and converting from a string. Can be any value accepted by
26 | `QDate.toString` and `fromString`, or a stringified version of a QDateFormat enum, i.e. 'ISODate',
27 | 'TextDate' (default), etc.
28 | ============== ========================================================
29 | """
30 |
31 | itemClass = CalendarParameterItem
32 |
33 | def __init__(self, **opts):
34 | opts.setdefault('format', 'TextDate')
35 | super().__init__(**opts)
36 |
37 | def _interpretFormat(self, fmt=None):
38 | fmt = fmt or self.opts.get('format')
39 | if hasattr(QtCore.Qt.DateFormat, fmt):
40 | fmt = getattr(QtCore.Qt.DateFormat, fmt)
41 | return fmt
42 |
43 | def _interpretValue(self, v):
44 | if isinstance(v, str):
45 | fmt = self._interpretFormat()
46 | if fmt is None:
47 | raise ValueError('Cannot parse date string without a set format')
48 | v = QtCore.QDate.fromString(v, fmt)
49 | return v
50 |
51 | def saveState(self, filter=None):
52 | state = super().saveState(filter)
53 | fmt = self._interpretFormat()
54 | state['value'] = state['value'].toString(fmt)
55 | return state
56 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/icons/__init__.py:
--------------------------------------------------------------------------------
1 | import os.path as op
2 | import warnings
3 |
4 | from ..Qt import QtGui
5 |
6 | __all__ = ['getGraphIcon', 'getGraphPixmap']
7 |
8 | _ICON_REGISTRY = {}
9 |
10 |
11 | class GraphIcon:
12 | """An icon place holder for lazy loading of QIcons
13 |
14 | The icon must reside in the icons folder and the path refers to the full
15 | name including suffix of the icon file, e.g.:
16 |
17 | tiny = GraphIcon("tiny.png")
18 |
19 | Icons can be later retrieved via the function `getGraphIcon` and providing
20 | the name:
21 |
22 | tiny = getGraphIcon("tiny")
23 | """
24 |
25 | def __init__(self, path):
26 | self._path = path
27 | name = path.split('.')[0]
28 | _ICON_REGISTRY[name] = self
29 | self._icon = None
30 |
31 | def _build_qicon(self):
32 | icon = QtGui.QIcon(op.join(op.dirname(__file__), self._path))
33 | name = self._path.split('.')[0]
34 | _ICON_REGISTRY[name] = icon
35 | self._icon = icon
36 |
37 | @property
38 | def qicon(self):
39 | if self._icon is None:
40 | self._build_qicon()
41 |
42 | return self._icon
43 |
44 |
45 | def getGraphIcon(name):
46 | """Return a `PyQtGraph` icon from the registry by `name`"""
47 | icon = _ICON_REGISTRY[name]
48 | if isinstance(icon, GraphIcon):
49 | icon = icon.qicon
50 | _ICON_REGISTRY[name] = icon
51 |
52 | return icon
53 |
54 |
55 | def getGraphPixmap(name, size=(20, 20)):
56 | """Return a `QPixmap` from the registry by `name`"""
57 | icon = getGraphIcon(name)
58 |
59 | return icon.pixmap(*size)
60 |
61 |
62 | def getPixmap(name, size=(20, 20)):
63 | """Historic `getPixmap` function
64 |
65 | (eg. getPixmap('auto') loads pyqtgraph/icons/auto.png)
66 | """
67 | warnings.warn(
68 | "'getPixmap' is deprecated and will be removed soon, "
69 | "please use `getGraphPixmap` in the future",
70 | DeprecationWarning, stacklevel=2)
71 | return getGraphPixmap(name, size=size)
72 |
73 |
74 | # Note: List all graph icons here ...
75 | auto = GraphIcon("auto.png")
76 | ctrl = GraphIcon("ctrl.png")
77 | default = GraphIcon("default.png")
78 | invisibleEye = GraphIcon("invisibleEye.svg")
79 | lock = GraphIcon("lock.png")
80 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/parametertree/parameterTypes/numeric.py:
--------------------------------------------------------------------------------
1 | from .basetypes import WidgetParameterItem
2 | from ...widgets.SpinBox import SpinBox
3 |
4 | class NumericParameterItem(WidgetParameterItem):
5 | """
6 | Subclasses `WidgetParameterItem` to provide the following types:
7 |
8 | ========================== =============================================================
9 | **Registered Types:**
10 | int Displays a :class:`SpinBox ` in integer
11 | mode.
12 | float Displays a :class:`SpinBox `.
13 | ========================== =============================================================
14 | """
15 | def makeWidget(self):
16 | opts = self.param.opts
17 | t = opts['type']
18 | defs = {
19 | 'value': 0, 'min': None, 'max': None,
20 | 'step': 1.0, 'dec': False,
21 | 'siPrefix': False, 'suffix': '', 'decimals': 3,
22 | }
23 | if t == 'int':
24 | defs['int'] = True
25 | defs['minStep'] = 1.0
26 | for k in defs:
27 | if k in opts:
28 | defs[k] = opts[k]
29 | if 'limits' in opts:
30 | defs['min'], defs['max'] = opts['limits']
31 | w = SpinBox()
32 | w.setOpts(**defs)
33 | w.sigChanged = w.sigValueChanged
34 | w.sigChanging = w.sigValueChanging
35 | return w
36 |
37 | def updateDisplayLabel(self, value=None):
38 | if value is None:
39 | value = self.widget.lineEdit().text()
40 | super().updateDisplayLabel(value)
41 |
42 | def showEditor(self):
43 | super().showEditor()
44 | self.widget.selectNumber() # select the numerical portion of the text for quick editing
45 |
46 | def limitsChanged(self, param, limits):
47 | self.widget.setOpts(bounds=limits)
48 |
49 | def optsChanged(self, param, opts):
50 | super().optsChanged(param, opts)
51 | sbOpts = {}
52 | if 'units' in opts and 'suffix' not in opts:
53 | sbOpts['suffix'] = opts['units']
54 | for k, v in opts.items():
55 | if k in self.widget.opts:
56 | sbOpts[k] = v
57 | self.widget.setOpts(**sbOpts)
58 | self.updateDisplayLabel()
59 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/graphicsItems/GraphicsWidget.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from ..Qt import QtGui
3 | from .GraphicsItem import GraphicsItem
4 |
5 | __all__ = ['GraphicsWidget']
6 |
7 | class GraphicsWidget(GraphicsItem, QtGui.QGraphicsWidget):
8 |
9 | _qtBaseClass = QtGui.QGraphicsWidget
10 | def __init__(self, *args, **kargs):
11 | """
12 | **Bases:** :class:`GraphicsItem `, :class:`QtGui.QGraphicsWidget`
13 |
14 | Extends QGraphicsWidget with several helpful methods and workarounds for PyQt bugs.
15 | Most of the extra functionality is inherited from :class:`GraphicsItem `.
16 | """
17 | QtGui.QGraphicsWidget.__init__(self, *args, **kargs)
18 | GraphicsItem.__init__(self)
19 |
20 | ## done by GraphicsItem init
21 | #GraphicsScene.registerObject(self) ## workaround for pyqt bug in graphicsscene.items()
22 |
23 | # Removed due to https://bugreports.qt-project.org/browse/PYSIDE-86
24 | #def itemChange(self, change, value):
25 | ## BEWARE: Calling QGraphicsWidget.itemChange can lead to crashing!
26 | ##ret = QtGui.QGraphicsWidget.itemChange(self, change, value) ## segv occurs here
27 | ## The default behavior is just to return the value argument, so we'll do that
28 | ## without calling the original method.
29 | #ret = value
30 | #if change in [self.ItemParentHasChanged, self.ItemSceneHasChanged]:
31 | #self._updateView()
32 | #return ret
33 |
34 | def setFixedHeight(self, h):
35 | self.setMaximumHeight(h)
36 | self.setMinimumHeight(h)
37 |
38 | def setFixedWidth(self, h):
39 | self.setMaximumWidth(h)
40 | self.setMinimumWidth(h)
41 |
42 | def height(self):
43 | return self.geometry().height()
44 |
45 | def width(self):
46 | return self.geometry().width()
47 |
48 | def boundingRect(self):
49 | br = self.mapRectFromParent(self.geometry()).normalized()
50 | #print "bounds:", br
51 | return br
52 |
53 | def shape(self): ## No idea why this is necessary, but rotated items do not receive clicks otherwise.
54 | p = QtGui.QPainterPath()
55 | p.addRect(self.boundingRect())
56 | #print "shape:", p.boundingRect()
57 | return p
58 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/icons/invisibleEye.svg:
--------------------------------------------------------------------------------
1 |
2 |
36 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/util/pil_fix.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Importing this module installs support for 16-bit images in PIL.
4 | This works by patching objects in the PIL namespace; no files are
5 | modified.
6 | """
7 |
8 | import warnings
9 | warnings.warn(
10 | "Not used in pyqtgraph. Will be removed in 0.13",
11 | DeprecationWarning, stacklevel=2
12 | )
13 |
14 | from PIL import Image
15 |
16 | if Image.VERSION == '1.1.7':
17 | Image._MODE_CONV["I;16"] = ('%su2' % Image._ENDIAN, None)
18 | Image._fromarray_typemap[((1, 1), " ndmax:
62 | raise ValueError("Too many dimensions.")
63 |
64 | size = shape[:2][::-1]
65 | if strides is not None:
66 | obj = obj.tostring()
67 |
68 | return frombuffer(mode, size, obj, "raw", mode, 0, 1)
69 |
70 | Image.fromarray=fromarray
71 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/parametertree/parameterTypes/__init__.py:
--------------------------------------------------------------------------------
1 | from .action import ActionParameter, ActionParameterItem
2 | from .basetypes import WidgetParameterItem, SimpleParameter, GroupParameter, GroupParameterItem
3 | from .bool import BoolParameterItem
4 | from .calendar import CalendarParameter, CalendarParameterItem
5 | from .checklist import ChecklistParameter, ChecklistParameterItem
6 | from .color import ColorParameter, ColorParameterItem
7 | from .colormap import ColorMapParameter, ColorMapParameterItem
8 | from .file import FileParameter, FileParameterItem
9 | from .font import FontParameter, FontParameterItem
10 | from .list import ListParameter, ListParameterItem
11 | from .numeric import NumericParameterItem
12 | from .pen import PenParameter, PenParameterItem
13 | from .progress import ProgressBarParameter, ProgressBarParameterItem
14 | from .qtenum import QtEnumParameter
15 | from .slider import SliderParameter, SliderParameterItem
16 | from .str import StrParameterItem
17 | from .text import TextParameter, TextParameterItem
18 | from ..Parameter import registerParameterType, registerParameterItemType
19 |
20 | registerParameterItemType('bool', BoolParameterItem, SimpleParameter, override=True)
21 | registerParameterItemType('float', NumericParameterItem, SimpleParameter, override=True)
22 | registerParameterItemType('int', NumericParameterItem, SimpleParameter, override=True)
23 | registerParameterItemType('str', StrParameterItem, SimpleParameter, override=True)
24 |
25 | registerParameterType('group', GroupParameter, override=True)
26 |
27 | registerParameterType('action', ActionParameter, override=True)
28 | registerParameterType('calendar', CalendarParameter, override=True)
29 | registerParameterType('checklist', ChecklistParameter, override=True)
30 | registerParameterType('color', ColorParameter, override=True)
31 | registerParameterType('colormap', ColorMapParameter, override=True)
32 | registerParameterType('file', FileParameter, override=True)
33 | registerParameterType('font', FontParameter, override=True)
34 | registerParameterType('list', ListParameter, override=True)
35 | registerParameterType('pen', PenParameter, override=True)
36 | registerParameterType('progress', ProgressBarParameter, override=True)
37 | # qtenum is a bit specific, hold off on registering for now
38 | registerParameterType('slider', SliderParameter, override=True)
39 | registerParameterType('text', TextParameter, override=True)
40 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/canvas/CanvasManager.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from ..Qt import QtCore, QtGui
3 | if not hasattr(QtCore, 'Signal'):
4 | QtCore.Signal = QtCore.pyqtSignal
5 | import weakref
6 |
7 | class CanvasManager(QtCore.QObject):
8 | SINGLETON = None
9 |
10 | sigCanvasListChanged = QtCore.Signal()
11 |
12 | def __init__(self):
13 | if CanvasManager.SINGLETON is not None:
14 | raise Exception("Can only create one canvas manager.")
15 | CanvasManager.SINGLETON = self
16 | QtCore.QObject.__init__(self)
17 | self.canvases = weakref.WeakValueDictionary()
18 |
19 | @classmethod
20 | def instance(cls):
21 | return CanvasManager.SINGLETON
22 |
23 | def registerCanvas(self, canvas, name):
24 | n2 = name
25 | i = 0
26 | while n2 in self.canvases:
27 | n2 = "%s_%03d" % (name, i)
28 | i += 1
29 | self.canvases[n2] = canvas
30 | self.sigCanvasListChanged.emit()
31 | return n2
32 |
33 | def unregisterCanvas(self, name):
34 | c = self.canvases[name]
35 | del self.canvases[name]
36 | self.sigCanvasListChanged.emit()
37 |
38 | def listCanvases(self):
39 | return list(self.canvases.keys())
40 |
41 | def getCanvas(self, name):
42 | return self.canvases[name]
43 |
44 |
45 | manager = CanvasManager()
46 |
47 |
48 | class CanvasCombo(QtGui.QComboBox):
49 | def __init__(self, parent=None):
50 | QtGui.QComboBox.__init__(self, parent)
51 | man = CanvasManager.instance()
52 | man.sigCanvasListChanged.connect(self.updateCanvasList)
53 | self.hostName = None
54 | self.updateCanvasList()
55 |
56 | def updateCanvasList(self):
57 | canvases = CanvasManager.instance().listCanvases()
58 | canvases.insert(0, "")
59 | if self.hostName in canvases:
60 | canvases.remove(self.hostName)
61 |
62 | sel = self.currentText()
63 | if sel in canvases:
64 | self.blockSignals(True) ## change does not affect current selection; block signals during update
65 | self.clear()
66 | for i in canvases:
67 | self.addItem(i)
68 | if i == sel:
69 | self.setCurrentIndex(self.count())
70 |
71 | self.blockSignals(False)
72 |
73 | def setHostName(self, name):
74 | self.hostName = name
75 | self.updateCanvasList()
76 |
77 |
--------------------------------------------------------------------------------
/tests/testdata/ipf-timeseries/B30F0059001.txt:
--------------------------------------------------------------------------------
1 | 95
2 | 2,1
3 | time,1e+20
4 | head,1e+20
5 | 19520814000000,-2.1
6 | 19520828000000,-2.03
7 | 19520915000000,-1.92
8 | 19520929000000,-1.65
9 | 19521014000000,-1.67
10 | 19521114000000,-1.7
11 | 19521128000000,-1.49
12 | 19521215000000,-1.41
13 | 19521229000000,-1.28
14 | 19530114000000,-1.5
15 | 19530128000000,-1.57
16 | 19530214000000,-1.43
17 | 19530228000000,-1.62
18 | 19530314000000,-1.73
19 | 19530328000000,-1.78
20 | 19530414000000,-1.48
21 | 19530515000000,-1.87
22 | 19530528000000,-2.02
23 | 19530615000000,-1.8
24 | 19530629000000,-1.95
25 | 19530714000000,-2.13
26 | 19530728000000,-2.04
27 | 19530814000000,-2.19
28 | 19530914000000,-1.96
29 | 19531128000000,-1.83
30 | 19531214000000,-1.86
31 | 19531228000000,-1.66
32 | 19540103000000,-1.54
33 | 19540114000000,-1.64
34 | 19540414000000,-1.75
35 | 19540514000000,-1.88
36 | 19540528000000,-2.0
37 | 19540628000000,-1.91
38 | 19540714000000,-2.09
39 | 19540728000000,-1.76
40 | 19540814000000,-1.63
41 | 19540914000000,-1.85
42 | 19540928000000,-1.81
43 | 19541115000000,-1.61
44 | 19541214000000,-1.6
45 | 19550128000000,-1.24
46 | 19550328000000,-1.59
47 | 19550628000000,-1.99
48 | 19550714000000,-2.08
49 | 19550815000000,-1.98
50 | 19550829000000,-2.17
51 | 19551028000000,-1.68
52 | 19551114000000,-1.74
53 | 19551228000000,-1.58
54 | 19560414000000,-1.72
55 | 19560628000000,-1.93
56 | 19560728000000,-1.89
57 | 19560914000000,-1.71
58 | 19561114000000,-1.69
59 | 19561228000000,-1.56
60 | 19570314000000,-2.01
61 | 19570628000000,-2.15
62 | 19570928000000,-1.45
63 | 19571228000000,-1.47
64 | 19580114000000,-1.51
65 | 19580128000000,-1.42
66 | 19580314000000,-1.4
67 | 19580328000000,-1.53
68 | 19580614000000,-1.77
69 | 19581128000000,-2.21
70 | 19590615000000,-1.94
71 | 19590814000000,-2.06
72 | 19590914000000,-2.07
73 | 19590928000000,-2.05
74 | 19591228000000,-1.84
75 | 19600215000000,-1.82
76 | 19600928000000,-1.79
77 | 19601128000000,-1.35
78 | 19601214000000,-1.37
79 | 19601228000000,-1.39
80 | 19610414000000,-1.46
81 | 19610828000000,-1.9
82 | 19611214000000,-1.34
83 | 19620115000000,-1.33
84 | 19620214000000,-1.31
85 | 19630429000000,-1.55
86 | 19630628000000,-1.97
87 | 19641214000000,-1.38
88 | 19650118000000,-1.3
89 | 19730205000000,-1.44
90 | 19731214000000,-1.14
91 | 19740429000000,-1.36
92 | 19741014000000,-1.11
93 | 19741216000000,-1.04
94 | 19750428000000,-1.17
95 | 19750827000000,-1.22
96 | 19751217000000,-1.1
97 | 19761214000000,-1.05
98 | 19770428000000,-1.29
99 | 19771214000000,-1.25
100 |
--------------------------------------------------------------------------------
/tests/testdata/ipf-timeseries/B30F0217001.txt:
--------------------------------------------------------------------------------
1 | 96
2 | 2,1
3 | time,1e+20
4 | head,1e+20
5 | 19550628000000,-2.1
6 | 19550714000000,-2.25
7 | 19550728000000,-2.31
8 | 19550815000000,-2.19
9 | 19550914000000,-2.21
10 | 19550928000000,-2.17
11 | 19551014000000,-2.09
12 | 19551028000000,-1.73
13 | 19551114000000,-1.86
14 | 19551214000000,-1.82
15 | 19551228000000,-1.77
16 | 19560114000000,-1.69
17 | 19560214000000,-1.68
18 | 19560228000000,-1.79
19 | 19560314000000,-1.87
20 | 19560328000000,-1.92
21 | 19560414000000,-1.91
22 | 19560428000000,-1.9
23 | 19560514000000,-2.11
24 | 19560528000000,-2.13
25 | 19560614000000,-2.16
26 | 19560628000000,-2.12
27 | 19560828000000,-1.8
28 | 19560928000000,-2.04
29 | 19561015000000,-1.81
30 | 19561029000000,-1.71
31 | 19561228000000,-1.76
32 | 19570114000000,-1.7
33 | 19570228000000,-1.97
34 | 19570314000000,-2.33
35 | 19570415000000,-2.53
36 | 19570514000000,-2.15
37 | 19570528000000,-2.2
38 | 19570628000000,-2.36
39 | 19570814000000,-2.27
40 | 19571114000000,-1.88
41 | 19571214000000,-1.95
42 | 19580114000000,-1.61
43 | 19580128000000,-1.66
44 | 19580228000000,-1.62
45 | 19580314000000,-1.59
46 | 19580328000000,-1.67
47 | 19580628000000,-2.01
48 | 19580728000000,-1.99
49 | 19580814000000,-2.05
50 | 19580828000000,-2.28
51 | 19580915000000,-2.59
52 | 19581028000000,-2.34
53 | 19581114000000,-2.39
54 | 19581128000000,-2.8
55 | 19581229000000,-2.55
56 | 19590114000000,-2.45
57 | 19590214000000,-2.3
58 | 19590319000000,-2.58
59 | 19590814000000,-2.23
60 | 19590928000000,-2.32
61 | 19591128000000,-2.54
62 | 19591214000000,-2.64
63 | 19600114000000,-2.56
64 | 19600215000000,-2.35
65 | 19600314000000,-2.47
66 | 19600328000000,-2.52
67 | 19600414000000,-1.98
68 | 19600614000000,-2.07
69 | 19600628000000,-2.26
70 | 19610108000000,-2.03
71 | 19610114000000,-1.42
72 | 19610414000000,-1.75
73 | 19610428000000,-1.78
74 | 19610614000000,-1.96
75 | 19610714000000,-2.14
76 | 19611128000000,-1.74
77 | 19611214000000,-1.54
78 | 19620120000000,-1.53
79 | 19620129000000,-1.89
80 | 19620214000000,-1.57
81 | 19620414000000,-1.58
82 | 19630328000000,-1.65
83 | 19631216000000,-1.94
84 | 19640214000000,-1.85
85 | 19640414000000,-1.93
86 | 19641028000000,-1.6
87 | 19650114000000,-1.48
88 | 19651228000000,-1.52
89 | 19660228000000,-1.56
90 | 19660428000000,-1.63
91 | 19660719000000,-1.83
92 | 19661214000000,-1.51
93 | 19670328000000,-1.84
94 | 19670828000000,-2.06
95 | 19680115000000,-1.5
96 | 19690627000000,-2.18
97 | 19691014000000,-2.22
98 | 19691128000000,-2.02
99 | 19700615000000,-2.29
100 | 19700728000000,-2.99
101 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/flowchart/FlowchartTemplate_pyside2.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Form implementation generated from reading ui file 'FlowchartTemplate.ui'
4 | #
5 | # Created: Sun Sep 18 19:16:03 2016
6 | # by: pyside2-uic running on PySide2 2.0.0~alpha0
7 | #
8 | # WARNING! All changes made in this file will be lost!
9 |
10 | from PySide2 import QtCore, QtGui, QtWidgets
11 |
12 | class Ui_Form(object):
13 | def setupUi(self, Form):
14 | Form.setObjectName("Form")
15 | Form.resize(529, 329)
16 | self.selInfoWidget = QtWidgets.QWidget(Form)
17 | self.selInfoWidget.setGeometry(QtCore.QRect(260, 10, 264, 222))
18 | self.selInfoWidget.setObjectName("selInfoWidget")
19 | self.gridLayout = QtWidgets.QGridLayout(self.selInfoWidget)
20 | self.gridLayout.setContentsMargins(0, 0, 0, 0)
21 | self.gridLayout.setObjectName("gridLayout")
22 | self.selDescLabel = QtWidgets.QLabel(self.selInfoWidget)
23 | self.selDescLabel.setText("")
24 | self.selDescLabel.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop)
25 | self.selDescLabel.setWordWrap(True)
26 | self.selDescLabel.setObjectName("selDescLabel")
27 | self.gridLayout.addWidget(self.selDescLabel, 0, 0, 1, 1)
28 | self.selNameLabel = QtWidgets.QLabel(self.selInfoWidget)
29 | font = QtGui.QFont()
30 | font.setWeight(75)
31 | font.setBold(True)
32 | self.selNameLabel.setFont(font)
33 | self.selNameLabel.setText("")
34 | self.selNameLabel.setObjectName("selNameLabel")
35 | self.gridLayout.addWidget(self.selNameLabel, 0, 1, 1, 1)
36 | self.selectedTree = DataTreeWidget(self.selInfoWidget)
37 | self.selectedTree.setObjectName("selectedTree")
38 | self.selectedTree.headerItem().setText(0, "1")
39 | self.gridLayout.addWidget(self.selectedTree, 1, 0, 1, 2)
40 | self.hoverText = QtWidgets.QTextEdit(Form)
41 | self.hoverText.setGeometry(QtCore.QRect(0, 240, 521, 81))
42 | self.hoverText.setObjectName("hoverText")
43 | self.view = FlowchartGraphicsView(Form)
44 | self.view.setGeometry(QtCore.QRect(0, 0, 256, 192))
45 | self.view.setObjectName("view")
46 |
47 | self.retranslateUi(Form)
48 | QtCore.QMetaObject.connectSlotsByName(Form)
49 |
50 | def retranslateUi(self, Form):
51 | Form.setWindowTitle(QtWidgets.QApplication.translate("Form", "Form", None, -1))
52 |
53 | from ..flowchart.FlowchartGraphicsView import FlowchartGraphicsView
54 | from ..widgets.DataTreeWidget import DataTreeWidget
55 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/graphicsItems/ScaleBar.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from ..Qt import QtGui, QtCore
3 | from .GraphicsObject import *
4 | from .GraphicsWidgetAnchor import *
5 | from .TextItem import TextItem
6 | from .. import functions as fn
7 | from .. import getConfigOption
8 | from ..Point import Point
9 |
10 | __all__ = ['ScaleBar']
11 |
12 | class ScaleBar(GraphicsObject, GraphicsWidgetAnchor):
13 | """
14 | Displays a rectangular bar to indicate the relative scale of objects on the view.
15 | """
16 | def __init__(self, size, width=5, brush=None, pen=None, suffix='m', offset=None):
17 | GraphicsObject.__init__(self)
18 | GraphicsWidgetAnchor.__init__(self)
19 | self.setFlag(self.GraphicsItemFlag.ItemHasNoContents)
20 | self.setAcceptedMouseButtons(QtCore.Qt.MouseButton.NoButton)
21 |
22 | if brush is None:
23 | brush = getConfigOption('foreground')
24 | self.brush = fn.mkBrush(brush)
25 | self.pen = fn.mkPen(pen)
26 | self._width = width
27 | self.size = size
28 | if offset == None:
29 | offset = (0,0)
30 | self.offset = offset
31 |
32 | self.bar = QtGui.QGraphicsRectItem()
33 | self.bar.setPen(self.pen)
34 | self.bar.setBrush(self.brush)
35 | self.bar.setParentItem(self)
36 |
37 | self.text = TextItem(text=fn.siFormat(size, suffix=suffix), anchor=(0.5,1))
38 | self.text.setParentItem(self)
39 |
40 | def parentChanged(self):
41 | view = self.parentItem()
42 | if view is None:
43 | return
44 | view.sigRangeChanged.connect(self.updateBar)
45 | self.updateBar()
46 |
47 |
48 | def updateBar(self):
49 | view = self.parentItem()
50 | if view is None:
51 | return
52 | p1 = view.mapFromViewToItem(self, QtCore.QPointF(0,0))
53 | p2 = view.mapFromViewToItem(self, QtCore.QPointF(self.size,0))
54 | w = (p2-p1).x()
55 | self.bar.setRect(QtCore.QRectF(-w, 0, w, self._width))
56 | self.text.setPos(-w/2., 0)
57 |
58 | def boundingRect(self):
59 | return QtCore.QRectF()
60 |
61 | def setParentItem(self, p):
62 | ret = GraphicsObject.setParentItem(self, p)
63 | if self.offset is not None:
64 | offset = Point(self.offset)
65 | anchorx = 1 if offset[0] <= 0 else 0
66 | anchory = 1 if offset[1] <= 0 else 0
67 | anchor = (anchorx, anchory)
68 | self.anchor(itemPos=anchor, parentPos=anchor, offset=offset)
69 | return ret
70 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/flowchart/FlowchartTemplate_pyqt5.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Form implementation generated from reading ui file './pyqtgraph/flowchart/FlowchartTemplate.ui'
4 | #
5 | # Created: Wed Mar 26 15:09:28 2014
6 | # by: PyQt5 UI code generator 5.0.1
7 | #
8 | # WARNING! All changes made in this file will be lost!
9 |
10 | from PyQt5 import QtCore, QtGui, QtWidgets
11 |
12 | class Ui_Form(object):
13 | def setupUi(self, Form):
14 | Form.setObjectName("Form")
15 | Form.resize(529, 329)
16 | self.selInfoWidget = QtWidgets.QWidget(Form)
17 | self.selInfoWidget.setGeometry(QtCore.QRect(260, 10, 264, 222))
18 | self.selInfoWidget.setObjectName("selInfoWidget")
19 | self.gridLayout = QtWidgets.QGridLayout(self.selInfoWidget)
20 | self.gridLayout.setContentsMargins(0, 0, 0, 0)
21 | self.gridLayout.setObjectName("gridLayout")
22 | self.selDescLabel = QtWidgets.QLabel(self.selInfoWidget)
23 | self.selDescLabel.setText("")
24 | self.selDescLabel.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop)
25 | self.selDescLabel.setWordWrap(True)
26 | self.selDescLabel.setObjectName("selDescLabel")
27 | self.gridLayout.addWidget(self.selDescLabel, 0, 0, 1, 1)
28 | self.selNameLabel = QtWidgets.QLabel(self.selInfoWidget)
29 | font = QtGui.QFont()
30 | font.setBold(True)
31 | font.setWeight(75)
32 | self.selNameLabel.setFont(font)
33 | self.selNameLabel.setText("")
34 | self.selNameLabel.setObjectName("selNameLabel")
35 | self.gridLayout.addWidget(self.selNameLabel, 0, 1, 1, 1)
36 | self.selectedTree = DataTreeWidget(self.selInfoWidget)
37 | self.selectedTree.setObjectName("selectedTree")
38 | self.selectedTree.headerItem().setText(0, "1")
39 | self.gridLayout.addWidget(self.selectedTree, 1, 0, 1, 2)
40 | self.hoverText = QtWidgets.QTextEdit(Form)
41 | self.hoverText.setGeometry(QtCore.QRect(0, 240, 521, 81))
42 | self.hoverText.setObjectName("hoverText")
43 | self.view = FlowchartGraphicsView(Form)
44 | self.view.setGeometry(QtCore.QRect(0, 0, 256, 192))
45 | self.view.setObjectName("view")
46 |
47 | self.retranslateUi(Form)
48 | QtCore.QMetaObject.connectSlotsByName(Form)
49 |
50 | def retranslateUi(self, Form):
51 | _translate = QtCore.QCoreApplication.translate
52 | Form.setWindowTitle(_translate("Form", "PyQtGraph"))
53 |
54 | from ..widgets.DataTreeWidget import DataTreeWidget
55 | from ..flowchart.FlowchartGraphicsView import FlowchartGraphicsView
56 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/flowchart/FlowchartTemplate_pyqt6.py:
--------------------------------------------------------------------------------
1 | # Form implementation generated from reading ui file '../pyqtgraph/flowchart/FlowchartTemplate.ui'
2 | #
3 | # Created by: PyQt6 UI code generator 6.1.0
4 | #
5 | # WARNING: Any manual changes made to this file will be lost when pyuic6 is
6 | # run again. Do not edit this file unless you know what you are doing.
7 |
8 |
9 | from PyQt6 import QtCore, QtGui, QtWidgets
10 |
11 |
12 | class Ui_Form(object):
13 | def setupUi(self, Form):
14 | Form.setObjectName("Form")
15 | Form.resize(529, 329)
16 | self.selInfoWidget = QtWidgets.QWidget(Form)
17 | self.selInfoWidget.setGeometry(QtCore.QRect(260, 10, 264, 222))
18 | self.selInfoWidget.setObjectName("selInfoWidget")
19 | self.gridLayout = QtWidgets.QGridLayout(self.selInfoWidget)
20 | self.gridLayout.setContentsMargins(0, 0, 0, 0)
21 | self.gridLayout.setObjectName("gridLayout")
22 | self.selDescLabel = QtWidgets.QLabel(self.selInfoWidget)
23 | self.selDescLabel.setText("")
24 | self.selDescLabel.setAlignment(QtCore.Qt.AlignmentFlag.AlignLeading|QtCore.Qt.AlignmentFlag.AlignLeft|QtCore.Qt.AlignmentFlag.AlignTop)
25 | self.selDescLabel.setWordWrap(True)
26 | self.selDescLabel.setObjectName("selDescLabel")
27 | self.gridLayout.addWidget(self.selDescLabel, 0, 0, 1, 1)
28 | self.selNameLabel = QtWidgets.QLabel(self.selInfoWidget)
29 | font = QtGui.QFont()
30 | font.setBold(True)
31 | self.selNameLabel.setFont(font)
32 | self.selNameLabel.setText("")
33 | self.selNameLabel.setObjectName("selNameLabel")
34 | self.gridLayout.addWidget(self.selNameLabel, 0, 1, 1, 1)
35 | self.selectedTree = DataTreeWidget(self.selInfoWidget)
36 | self.selectedTree.setObjectName("selectedTree")
37 | self.selectedTree.headerItem().setText(0, "1")
38 | self.gridLayout.addWidget(self.selectedTree, 1, 0, 1, 2)
39 | self.hoverText = QtWidgets.QTextEdit(Form)
40 | self.hoverText.setGeometry(QtCore.QRect(0, 240, 521, 81))
41 | self.hoverText.setObjectName("hoverText")
42 | self.view = FlowchartGraphicsView(Form)
43 | self.view.setGeometry(QtCore.QRect(0, 0, 256, 192))
44 | self.view.setObjectName("view")
45 |
46 | self.retranslateUi(Form)
47 | QtCore.QMetaObject.connectSlotsByName(Form)
48 |
49 | def retranslateUi(self, Form):
50 | _translate = QtCore.QCoreApplication.translate
51 | Form.setWindowTitle(_translate("Form", "PyQtGraph"))
52 | from ..flowchart.FlowchartGraphicsView import FlowchartGraphicsView
53 | from ..widgets.DataTreeWidget import DataTreeWidget
54 |
--------------------------------------------------------------------------------
/imodqgis/idf/layer_styling.py:
--------------------------------------------------------------------------------
1 | # Copyright © 2021 Deltares
2 | # SPDX-License-Identifier: GPL-2.0-or-later
3 | #
4 | from typing import List
5 |
6 | from qgis.core import (
7 | QgsColorRampShader,
8 | QgsRasterBandStats,
9 | QgsRasterShader,
10 | QgsSingleBandPseudoColorRenderer,
11 | QgsStyle,
12 | )
13 |
14 |
15 | def color_ramp_items(
16 | colormap: str, minimum: float, maximum: float, nclass: int
17 | ) -> List[QgsColorRampShader.ColorRampItem]:
18 | """
19 | Parameters
20 | ----------
21 | colormap: str
22 | Name of QGIS colormap
23 | minimum: float
24 | maximum: float
25 | nclass: int
26 | Number of colormap classes to create
27 |
28 | Returns
29 | -------
30 | color_ramp: QgsGradientColorRamp
31 | color_ramp_items: List[QgsColorRampShader.ColorRampItem]
32 | Can be used directly by the QgsColorRampShader
33 | """
34 | delta = maximum - minimum
35 | fractional_steps = [i / nclass for i in range(nclass + 1)]
36 | ramp = QgsStyle().defaultStyle().colorRamp(colormap)
37 | colors = [ramp.color(f) for f in fractional_steps]
38 | steps = [minimum + f * delta for f in fractional_steps]
39 | return ramp, [
40 | QgsColorRampShader.ColorRampItem(step, color, str(step))
41 | for step, color in zip(steps, colors)
42 | ]
43 |
44 |
45 | def pseudocolor_renderer(
46 | layer, band: int, colormap: str, nclass: int
47 | ) -> QgsSingleBandPseudoColorRenderer:
48 | """
49 | Parameters
50 | ----------
51 | layer: QGIS map layer
52 | band: int
53 | band number of the raster to create a renderer for
54 | colormap: str
55 | Name of QGIS colormap
56 | nclass: int
57 | Number of colormap classes to create
58 |
59 | Returns
60 | -------
61 | renderer: QgsSingleBandPseudoColorRenderer
62 | """
63 | stats = layer.dataProvider().bandStatistics(band, QgsRasterBandStats.All)
64 | minimum = stats.minimumValue
65 | maximum = stats.maximumValue
66 |
67 | ramp, ramp_items = color_ramp_items(colormap, minimum, maximum, nclass)
68 | shader_function = QgsColorRampShader()
69 | shader_function.setMinimumValue(minimum)
70 | shader_function.setMaximumValue(maximum)
71 | shader_function.setSourceColorRamp(ramp)
72 | shader_function.setColorRampType(QgsColorRampShader.Interpolated)
73 | shader_function.setClassificationMode(QgsColorRampShader.EqualInterval)
74 | shader_function.setColorRampItemList(ramp_items)
75 |
76 | raster_shader = QgsRasterShader()
77 | raster_shader.setRasterShaderFunction(shader_function)
78 |
79 | return QgsSingleBandPseudoColorRenderer(layer.dataProvider(), band, raster_shader)
80 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/flowchart/FlowchartTemplate.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Form
4 |
5 |
6 |
7 | 0
8 | 0
9 | 529
10 | 329
11 |
12 |
13 |
14 | PyQtGraph
15 |
16 |
17 |
18 |
19 | 260
20 | 10
21 | 264
22 | 222
23 |
24 |
25 |
26 | -
27 |
28 |
29 |
30 |
31 |
32 | Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop
33 |
34 |
35 | true
36 |
37 |
38 |
39 | -
40 |
41 |
42 |
43 | true
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | -
52 |
53 |
54 |
55 | 1
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | 0
66 | 240
67 | 521
68 | 81
69 |
70 |
71 |
72 |
73 |
74 |
75 | 0
76 | 0
77 | 256
78 | 192
79 |
80 |
81 |
82 |
83 |
84 |
85 | DataTreeWidget
86 | QTreeWidget
87 |
88 |
89 |
90 | FlowchartGraphicsView
91 | QGraphicsView
92 | ..flowchart.FlowchartGraphicsView
93 |
94 |
95 |
96 |
97 |
98 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/graphicsItems/MultiPlotItem.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | MultiPlotItem.py - Graphics item used for displaying an array of PlotItems
4 | Copyright 2010 Luke Campagnola
5 | Distributed under MIT/X11 license. See license.txt for more information.
6 | """
7 | from . import GraphicsLayout
8 | from ..metaarray import *
9 |
10 | __all__ = ['MultiPlotItem']
11 |
12 |
13 | class MultiPlotItem(GraphicsLayout.GraphicsLayout):
14 | """
15 | :class:`~pyqtgraph.GraphicsLayout` that automatically generates a grid of
16 | plots from a MetaArray.
17 |
18 | .. seealso:: :class:`~pyqtgraph.MultiPlotWidget`: Widget containing a MultiPlotItem
19 | """
20 |
21 | def __init__(self, *args, **kwds):
22 | GraphicsLayout.GraphicsLayout.__init__(self, *args, **kwds)
23 | self.plots = []
24 |
25 | def plot(self, data, **plotArgs):
26 | """Plot the data from a MetaArray with each array column as a separate
27 | :class:`~pyqtgraph.PlotItem`.
28 |
29 | Axis labels are automatically extracted from the array info.
30 |
31 | ``plotArgs`` are passed to :meth:`PlotItem.plot
32 | `.
33 | """
34 | #self.layout.clear()
35 |
36 | if hasattr(data, 'implements') and data.implements('MetaArray'):
37 | if data.ndim != 2:
38 | raise Exception("MultiPlot currently only accepts 2D MetaArray.")
39 | ic = data.infoCopy()
40 | ax = 0
41 | for i in [0, 1]:
42 | if 'cols' in ic[i]:
43 | ax = i
44 | break
45 | #print "Plotting using axis %d as columns (%d plots)" % (ax, data.shape[ax])
46 | for i in range(data.shape[ax]):
47 | pi = self.addPlot()
48 | self.nextRow()
49 | sl = [slice(None)] * 2
50 | sl[ax] = i
51 | pi.plot(data[tuple(sl)], **plotArgs)
52 | #self.layout.addItem(pi, i, 0)
53 | self.plots.append((pi, i, 0))
54 | info = ic[ax]['cols'][i]
55 | title = info.get('title', info.get('name', None))
56 | units = info.get('units', None)
57 | pi.setLabel('left', text=title, units=units)
58 | info = ic[1-ax]
59 | title = info.get('title', info.get('name', None))
60 | units = info.get('units', None)
61 | pi.setLabel('bottom', text=title, units=units)
62 | else:
63 | raise Exception("Data type %s not (yet?) supported for MultiPlot." % type(data))
64 |
65 | def close(self):
66 | for p in self.plots:
67 | p[0].close()
68 | self.plots = None
69 | self.clear()
70 |
--------------------------------------------------------------------------------
/imodqgis/about/about.md:
--------------------------------------------------------------------------------
1 | # iMOD-QGIS plugin
2 |
3 | ## Functionality
4 | The iMOD QGIS plugin provides ways to visualize 4D unstructured subsurface data [time, layer, y, x].
5 |
6 | Primary components are:
7 |
8 | * An IPF reader to read .IPF files into Qgis, which is a Deltares point format that supports assocciated depth or time data.
9 | * Connecting to the iMOD 3D viewer
10 | * Timeseries visualization
11 | * Cross-section visualization
12 | * Connecting to the NHI data portal, which provides subsurface data for the Netherlands
13 |
14 | ## Data Requirements
15 | 3D data needs to be provided as an unstructured file readable by MDAL,
16 | preferably an
17 | [UGRID file](https://ugrid-conventions.github.io/ugrid-conventions/).
18 |
19 | Currently MDAL does not support the reading of 3D layered unstructured UGRID files.
20 |
21 | Therefore, for each vertical layer,
22 | we require a mesh dataset with the following variables:
23 |
24 | * `{var}_layer_{nr}`
25 | * `top_layer_{nr}`
26 | * `bottom_layer_{nr}`
27 |
28 | Here is an example script how to do this with
29 | [iMOD-python](https://gitlab.com/deltares/imod/imod-python/-/snippets/2111702).
30 |
31 | Point data with timeseries or borelogs need to be provided as
32 | [IPF](https://content.oss.deltares.nl/imod/iMOD_Manual_actual/imod-um-IPF-files.html#autosec-591) file.
33 | The IPF file is a Deltares point format that supports assocciated depth or
34 | time data.
35 |
36 | ## Dependencies
37 | To do 3D viewing, the iMOD 3D Viewer is required,
38 | [for which downloading and installing instructions can be found here](https://deltares.github.io/iMOD-Documentation/viewer_install.html).
39 |
40 | This plugin uses:
41 |
42 | * [PyQtGraph 12.2](https://www.pyqtgraph.org/) for graph visualization
43 | * [declxml](https://declxml.readthedocs.io/en/latest/) to create xml files
44 | * [pandas](https://pandas.pydata.org/) to read and process csv files
45 |
46 | PyQtGraph and declxml are pure python packages distributed with the plugin,
47 | pandas comes with the QGIS installation
48 |
49 | NOTE: If you installed QGIS with OSGeo4W, make sure pandas is installed as an extra dependency.
50 | See the [installation instructions](https://deltares.github.io/iMOD-Documentation/qgis_install.html).
51 |
52 | This package was inspired by the [Crayfish plugin](https://github.com/lutraconsulting/qgis-crayfish-plugin/tree/master/crayfish).
53 |
54 | ## Documentation
55 |
56 | * [General iMOD documentation](https://deltares.github.io/iMOD-Documentation/index.html)
57 | * [Plugin Installation Instructions](https://deltares.github.io/iMOD-Documentation/qgis_install.html)
58 | * [Plugin User Manual](https://deltares.github.io/iMOD-Documentation/qgis_index.html)
59 |
60 | ## License
61 | The iMOD plugin is a product of Deltares, and published under the GPLv2 license.
62 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/canvas/TransformGuiTemplate_pyqt5.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Form implementation generated from reading ui file 'pyqtgraph/canvas/TransformGuiTemplate.ui'
4 | #
5 | # Created by: PyQt5 UI code generator 5.5.1
6 | #
7 | # WARNING! All changes made in this file will be lost!
8 |
9 | from PyQt5 import QtCore, QtGui, QtWidgets
10 |
11 | class Ui_Form(object):
12 | def setupUi(self, Form):
13 | Form.setObjectName("Form")
14 | Form.resize(224, 117)
15 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
16 | sizePolicy.setHorizontalStretch(0)
17 | sizePolicy.setVerticalStretch(0)
18 | sizePolicy.setHeightForWidth(Form.sizePolicy().hasHeightForWidth())
19 | Form.setSizePolicy(sizePolicy)
20 | self.verticalLayout = QtWidgets.QVBoxLayout(Form)
21 | self.verticalLayout.setContentsMargins(0, 0, 0, 0)
22 | self.verticalLayout.setSpacing(1)
23 | self.verticalLayout.setObjectName("verticalLayout")
24 | self.translateLabel = QtWidgets.QLabel(Form)
25 | self.translateLabel.setObjectName("translateLabel")
26 | self.verticalLayout.addWidget(self.translateLabel)
27 | self.rotateLabel = QtWidgets.QLabel(Form)
28 | self.rotateLabel.setObjectName("rotateLabel")
29 | self.verticalLayout.addWidget(self.rotateLabel)
30 | self.scaleLabel = QtWidgets.QLabel(Form)
31 | self.scaleLabel.setObjectName("scaleLabel")
32 | self.verticalLayout.addWidget(self.scaleLabel)
33 | self.horizontalLayout = QtWidgets.QHBoxLayout()
34 | self.horizontalLayout.setObjectName("horizontalLayout")
35 | self.mirrorImageBtn = QtWidgets.QPushButton(Form)
36 | self.mirrorImageBtn.setToolTip("")
37 | self.mirrorImageBtn.setObjectName("mirrorImageBtn")
38 | self.horizontalLayout.addWidget(self.mirrorImageBtn)
39 | self.reflectImageBtn = QtWidgets.QPushButton(Form)
40 | self.reflectImageBtn.setObjectName("reflectImageBtn")
41 | self.horizontalLayout.addWidget(self.reflectImageBtn)
42 | self.verticalLayout.addLayout(self.horizontalLayout)
43 |
44 | self.retranslateUi(Form)
45 | QtCore.QMetaObject.connectSlotsByName(Form)
46 |
47 | def retranslateUi(self, Form):
48 | _translate = QtCore.QCoreApplication.translate
49 | Form.setWindowTitle(_translate("Form", "PyQtGraph"))
50 | self.translateLabel.setText(_translate("Form", "Translate:"))
51 | self.rotateLabel.setText(_translate("Form", "Rotate:"))
52 | self.scaleLabel.setText(_translate("Form", "Scale:"))
53 | self.mirrorImageBtn.setText(_translate("Form", "Mirror"))
54 | self.reflectImageBtn.setText(_translate("Form", "Reflect"))
55 |
56 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/parametertree/parameterTypes/qtenum.py:
--------------------------------------------------------------------------------
1 | from ...Qt import QtCore, QT_LIB
2 | from .list import ListParameter
3 |
4 |
5 | class QtEnumParameter(ListParameter):
6 | def __init__(self, enum, searchObj=QtCore.Qt, **opts):
7 | """
8 | Constructs a list of allowed enum values from the enum class provided
9 | `searchObj` is only needed for PyQt5 compatibility, where it must be the module holding the enum.
10 | For instance, if making a QtEnumParameter out of QtWidgets.QFileDialog.Option, `searchObj` would
11 | be QtWidgets.QFileDialog
12 | """
13 | self.enum = enum
14 | self.searchObj = searchObj
15 | opts.setdefault('name', enum.__name__)
16 | self.enumMap = self._getAllowedEnums(enum)
17 |
18 | opts.update(limits=self.formattedLimits())
19 | super().__init__(**opts)
20 |
21 | def setValue(self, value, blockSignal=None):
22 | if isinstance(value, str):
23 | value = self.enumMap[value]
24 | super().setValue(value, blockSignal)
25 |
26 | def formattedLimits(self):
27 | # Title-cased words without the ending substring for brevity
28 | substringEnd = None
29 | mapping = self.enumMap
30 | shortestName = min(len(name) for name in mapping)
31 | names = list(mapping)
32 | cmpName, *names = names
33 | for ii in range(-1, -shortestName-1, -1):
34 | if any(cmpName[ii] != curName[ii] for curName in names):
35 | substringEnd = ii+1
36 | break
37 | # Special case of 0: Set to none to avoid null string
38 | if substringEnd == 0:
39 | substringEnd = None
40 | limits = {}
41 | for kk, vv in self.enumMap.items():
42 | limits[kk[:substringEnd]] = vv
43 | return limits
44 |
45 | def saveState(self, filter=None):
46 | state = super().saveState(filter)
47 | reverseMap = dict(zip(self.enumMap.values(), self.enumMap))
48 | state['value'] = reverseMap[state['value']]
49 | return state
50 |
51 | def _getAllowedEnums(self, enum):
52 | """Pyside provides a dict for easy evaluation"""
53 | if 'PySide' in QT_LIB:
54 | vals = enum.values
55 | elif 'PyQt5' in QT_LIB:
56 | vals = {}
57 | for key in dir(self.searchObj):
58 | value = getattr(self.searchObj, key)
59 | if isinstance(value, enum):
60 | vals[key] = value
61 | elif 'PyQt6' in QT_LIB:
62 | vals = {e.name: e for e in enum}
63 | else:
64 | raise RuntimeError(f'Cannot find associated enum values for qt lib {QT_LIB}')
65 | # Remove "M" since it's not a real option
66 | vals.pop(f'M{enum.__name__}', None)
67 | return vals
68 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/opengl/items/GLBoxItem.py:
--------------------------------------------------------------------------------
1 | from OpenGL.GL import *
2 | from .. GLGraphicsItem import GLGraphicsItem
3 | from ...Qt import QtGui
4 | from ... import functions as fn
5 |
6 | __all__ = ['GLBoxItem']
7 |
8 | class GLBoxItem(GLGraphicsItem):
9 | """
10 | **Bases:** :class:`GLGraphicsItem `
11 |
12 | Displays a wire-frame box.
13 | """
14 | def __init__(self, size=None, color=None, glOptions='translucent'):
15 | GLGraphicsItem.__init__(self)
16 | if size is None:
17 | size = QtGui.QVector3D(1,1,1)
18 | self.setSize(size=size)
19 | if color is None:
20 | color = (255,255,255,80)
21 | self.setColor(color)
22 | self.setGLOptions(glOptions)
23 |
24 | def setSize(self, x=None, y=None, z=None, size=None):
25 | """
26 | Set the size of the box (in its local coordinate system; this does not affect the transform)
27 | Arguments can be x,y,z or size=QVector3D().
28 | """
29 | if size is not None:
30 | x = size.x()
31 | y = size.y()
32 | z = size.z()
33 | self.__size = [x,y,z]
34 | self.update()
35 |
36 | def size(self):
37 | return self.__size[:]
38 |
39 | def setColor(self, *args):
40 | """Set the color of the box. Arguments are the same as those accepted by functions.mkColor()"""
41 | self.__color = fn.mkColor(*args)
42 |
43 | def color(self):
44 | return self.__color
45 |
46 | def paint(self):
47 | #glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
48 | #glEnable( GL_BLEND )
49 | #glEnable( GL_ALPHA_TEST )
50 | ##glAlphaFunc( GL_ALWAYS,0.5 )
51 | #glEnable( GL_POINT_SMOOTH )
52 | #glDisable( GL_DEPTH_TEST )
53 | self.setupGLState()
54 |
55 | glBegin( GL_LINES )
56 |
57 | glColor4f(*self.color().getRgbF())
58 | x,y,z = self.size()
59 | glVertex3f(0, 0, 0)
60 | glVertex3f(0, 0, z)
61 | glVertex3f(x, 0, 0)
62 | glVertex3f(x, 0, z)
63 | glVertex3f(0, y, 0)
64 | glVertex3f(0, y, z)
65 | glVertex3f(x, y, 0)
66 | glVertex3f(x, y, z)
67 |
68 | glVertex3f(0, 0, 0)
69 | glVertex3f(0, y, 0)
70 | glVertex3f(x, 0, 0)
71 | glVertex3f(x, y, 0)
72 | glVertex3f(0, 0, z)
73 | glVertex3f(0, y, z)
74 | glVertex3f(x, 0, z)
75 | glVertex3f(x, y, z)
76 |
77 | glVertex3f(0, 0, 0)
78 | glVertex3f(x, 0, 0)
79 | glVertex3f(0, y, 0)
80 | glVertex3f(x, y, 0)
81 | glVertex3f(0, 0, z)
82 | glVertex3f(x, 0, z)
83 | glVertex3f(0, y, z)
84 | glVertex3f(x, y, z)
85 |
86 | glEnd()
87 |
88 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/flowchart/FlowchartTemplate_pyside6.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | ################################################################################
4 | ## Form generated from reading UI file 'FlowchartTemplate.ui'
5 | ##
6 | ## Created by: Qt User Interface Compiler version 6.1.0
7 | ##
8 | ## WARNING! All changes made in this file will be lost when recompiling UI file!
9 | ################################################################################
10 |
11 | from PySide6.QtCore import *
12 | from PySide6.QtGui import *
13 | from PySide6.QtWidgets import *
14 |
15 | from ..widgets.DataTreeWidget import DataTreeWidget
16 | from ..flowchart.FlowchartGraphicsView import FlowchartGraphicsView
17 |
18 |
19 | class Ui_Form(object):
20 | def setupUi(self, Form):
21 | if not Form.objectName():
22 | Form.setObjectName(u"Form")
23 | Form.resize(529, 329)
24 | self.selInfoWidget = QWidget(Form)
25 | self.selInfoWidget.setObjectName(u"selInfoWidget")
26 | self.selInfoWidget.setGeometry(QRect(260, 10, 264, 222))
27 | self.gridLayout = QGridLayout(self.selInfoWidget)
28 | self.gridLayout.setObjectName(u"gridLayout")
29 | self.selDescLabel = QLabel(self.selInfoWidget)
30 | self.selDescLabel.setObjectName(u"selDescLabel")
31 | self.selDescLabel.setAlignment(Qt.AlignLeading|Qt.AlignLeft|Qt.AlignTop)
32 | self.selDescLabel.setWordWrap(True)
33 |
34 | self.gridLayout.addWidget(self.selDescLabel, 0, 0, 1, 1)
35 |
36 | self.selNameLabel = QLabel(self.selInfoWidget)
37 | self.selNameLabel.setObjectName(u"selNameLabel")
38 | font = QFont()
39 | font.setBold(True)
40 | self.selNameLabel.setFont(font)
41 |
42 | self.gridLayout.addWidget(self.selNameLabel, 0, 1, 1, 1)
43 |
44 | self.selectedTree = DataTreeWidget(self.selInfoWidget)
45 | __qtreewidgetitem = QTreeWidgetItem()
46 | __qtreewidgetitem.setText(0, u"1");
47 | self.selectedTree.setHeaderItem(__qtreewidgetitem)
48 | self.selectedTree.setObjectName(u"selectedTree")
49 |
50 | self.gridLayout.addWidget(self.selectedTree, 1, 0, 1, 2)
51 |
52 | self.hoverText = QTextEdit(Form)
53 | self.hoverText.setObjectName(u"hoverText")
54 | self.hoverText.setGeometry(QRect(0, 240, 521, 81))
55 | self.view = FlowchartGraphicsView(Form)
56 | self.view.setObjectName(u"view")
57 | self.view.setGeometry(QRect(0, 0, 256, 192))
58 |
59 | self.retranslateUi(Form)
60 |
61 | QMetaObject.connectSlotsByName(Form)
62 | # setupUi
63 |
64 | def retranslateUi(self, Form):
65 | Form.setWindowTitle(QCoreApplication.translate("Form", u"PyQtGraph", None))
66 | self.selDescLabel.setText("")
67 | self.selNameLabel.setText("")
68 | # retranslateUi
69 |
70 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/canvas/TransformGuiTemplate_pyqt6.py:
--------------------------------------------------------------------------------
1 | # Form implementation generated from reading ui file '../pyqtgraph/canvas/TransformGuiTemplate.ui'
2 | #
3 | # Created by: PyQt6 UI code generator 6.1.0
4 | #
5 | # WARNING: Any manual changes made to this file will be lost when pyuic6 is
6 | # run again. Do not edit this file unless you know what you are doing.
7 |
8 |
9 | from PyQt6 import QtCore, QtGui, QtWidgets
10 |
11 |
12 | class Ui_Form(object):
13 | def setupUi(self, Form):
14 | Form.setObjectName("Form")
15 | Form.resize(224, 117)
16 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Preferred, QtWidgets.QSizePolicy.Policy.Preferred)
17 | sizePolicy.setHorizontalStretch(0)
18 | sizePolicy.setVerticalStretch(0)
19 | sizePolicy.setHeightForWidth(Form.sizePolicy().hasHeightForWidth())
20 | Form.setSizePolicy(sizePolicy)
21 | self.verticalLayout = QtWidgets.QVBoxLayout(Form)
22 | self.verticalLayout.setContentsMargins(0, 0, 0, 0)
23 | self.verticalLayout.setSpacing(1)
24 | self.verticalLayout.setObjectName("verticalLayout")
25 | self.translateLabel = QtWidgets.QLabel(Form)
26 | self.translateLabel.setObjectName("translateLabel")
27 | self.verticalLayout.addWidget(self.translateLabel)
28 | self.rotateLabel = QtWidgets.QLabel(Form)
29 | self.rotateLabel.setObjectName("rotateLabel")
30 | self.verticalLayout.addWidget(self.rotateLabel)
31 | self.scaleLabel = QtWidgets.QLabel(Form)
32 | self.scaleLabel.setObjectName("scaleLabel")
33 | self.verticalLayout.addWidget(self.scaleLabel)
34 | self.horizontalLayout = QtWidgets.QHBoxLayout()
35 | self.horizontalLayout.setObjectName("horizontalLayout")
36 | self.mirrorImageBtn = QtWidgets.QPushButton(Form)
37 | self.mirrorImageBtn.setToolTip("")
38 | self.mirrorImageBtn.setObjectName("mirrorImageBtn")
39 | self.horizontalLayout.addWidget(self.mirrorImageBtn)
40 | self.reflectImageBtn = QtWidgets.QPushButton(Form)
41 | self.reflectImageBtn.setObjectName("reflectImageBtn")
42 | self.horizontalLayout.addWidget(self.reflectImageBtn)
43 | self.verticalLayout.addLayout(self.horizontalLayout)
44 |
45 | self.retranslateUi(Form)
46 | QtCore.QMetaObject.connectSlotsByName(Form)
47 |
48 | def retranslateUi(self, Form):
49 | _translate = QtCore.QCoreApplication.translate
50 | Form.setWindowTitle(_translate("Form", "PyQtGraph"))
51 | self.translateLabel.setText(_translate("Form", "Translate:"))
52 | self.rotateLabel.setText(_translate("Form", "Rotate:"))
53 | self.scaleLabel.setText(_translate("Form", "Scale:"))
54 | self.mirrorImageBtn.setText(_translate("Form", "Mirror"))
55 | self.reflectImageBtn.setText(_translate("Form", "Reflect"))
56 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/exporters/HDF5Exporter.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from ..Qt import QtCore
3 | from .Exporter import Exporter
4 | from ..parametertree import Parameter
5 | from .. import PlotItem
6 |
7 | import numpy
8 | try:
9 | import h5py
10 | HAVE_HDF5 = True
11 | except ImportError:
12 | HAVE_HDF5 = False
13 |
14 | translate = QtCore.QCoreApplication.translate
15 |
16 | __all__ = ['HDF5Exporter']
17 |
18 |
19 | class HDF5Exporter(Exporter):
20 | Name = "HDF5 Export: plot (x,y)"
21 | windows = []
22 | allowCopy = False
23 |
24 | def __init__(self, item):
25 | Exporter.__init__(self, item)
26 | self.params = Parameter(name='params', type='group', children=[
27 | {'name': 'Name', 'title': translate("Exporter", 'Name'), 'type': 'str', 'value': 'Export', },
28 | {'name': 'columnMode', 'title': translate("Exporter", 'columnMode'), 'type': 'list',
29 | 'limits': ['(x,y) per plot', '(x,y,y,y) for all plots']},
30 | ])
31 |
32 | def parameters(self):
33 | return self.params
34 |
35 | def export(self, fileName=None):
36 | if not HAVE_HDF5:
37 | raise RuntimeError("This exporter requires the h5py package, "
38 | "but it was not importable.")
39 |
40 | if not isinstance(self.item, PlotItem):
41 | raise Exception("Must have a PlotItem selected for HDF5 export.")
42 |
43 | if fileName is None:
44 | self.fileSaveDialog(filter=["*.h5", "*.hdf", "*.hd5"])
45 | return
46 | dsname = self.params['Name']
47 | fd = h5py.File(fileName, 'a') # forces append to file... 'w' doesn't seem to "delete/overwrite"
48 | data = []
49 |
50 | appendAllX = self.params['columnMode'] == '(x,y) per plot'
51 | # Check if the arrays are ragged
52 | len_first = len(self.item.curves[0].getData()[0]) if self.item.curves[0] else None
53 | ragged = any(len(i.getData()[0]) != len_first for i in self.item.curves)
54 |
55 | if ragged:
56 | dgroup = fd.create_group(dsname)
57 | for i, c in enumerate(self.item.curves):
58 | d = c.getData()
59 | fdata = numpy.array([d[0], d[1]]).astype('double')
60 | cname = c.name() if c.name() is not None else str(i)
61 | dset = dgroup.create_dataset(cname, data=fdata)
62 | else:
63 | for i, c in enumerate(self.item.curves):
64 | d = c.getData()
65 | if appendAllX or i == 0:
66 | data.append(d[0])
67 | data.append(d[1])
68 |
69 | fdata = numpy.array(data).astype('double')
70 | dset = fd.create_dataset(dsname, data=fdata)
71 |
72 | fd.close()
73 |
74 | if HAVE_HDF5:
75 | HDF5Exporter.register()
76 |
--------------------------------------------------------------------------------
/imodqgis/icons/time-series.svg:
--------------------------------------------------------------------------------
1 |
2 |
71 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/canvas/TransformGuiTemplate_pyside2.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Form implementation generated from reading ui file 'TransformGuiTemplate.ui'
4 | #
5 | # Created: Sun Sep 18 19:18:41 2016
6 | # by: pyside2-uic running on PySide2 2.0.0~alpha0
7 | #
8 | # WARNING! All changes made in this file will be lost!
9 |
10 | from PySide2 import QtCore, QtGui, QtWidgets
11 |
12 | class Ui_Form(object):
13 | def setupUi(self, Form):
14 | Form.setObjectName("Form")
15 | Form.resize(224, 117)
16 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
17 | sizePolicy.setHorizontalStretch(0)
18 | sizePolicy.setVerticalStretch(0)
19 | sizePolicy.setHeightForWidth(Form.sizePolicy().hasHeightForWidth())
20 | Form.setSizePolicy(sizePolicy)
21 | self.verticalLayout = QtWidgets.QVBoxLayout(Form)
22 | self.verticalLayout.setSpacing(1)
23 | self.verticalLayout.setContentsMargins(0, 0, 0, 0)
24 | self.verticalLayout.setObjectName("verticalLayout")
25 | self.translateLabel = QtWidgets.QLabel(Form)
26 | self.translateLabel.setObjectName("translateLabel")
27 | self.verticalLayout.addWidget(self.translateLabel)
28 | self.rotateLabel = QtWidgets.QLabel(Form)
29 | self.rotateLabel.setObjectName("rotateLabel")
30 | self.verticalLayout.addWidget(self.rotateLabel)
31 | self.scaleLabel = QtWidgets.QLabel(Form)
32 | self.scaleLabel.setObjectName("scaleLabel")
33 | self.verticalLayout.addWidget(self.scaleLabel)
34 | self.horizontalLayout = QtWidgets.QHBoxLayout()
35 | self.horizontalLayout.setObjectName("horizontalLayout")
36 | self.mirrorImageBtn = QtWidgets.QPushButton(Form)
37 | self.mirrorImageBtn.setToolTip("")
38 | self.mirrorImageBtn.setObjectName("mirrorImageBtn")
39 | self.horizontalLayout.addWidget(self.mirrorImageBtn)
40 | self.reflectImageBtn = QtWidgets.QPushButton(Form)
41 | self.reflectImageBtn.setObjectName("reflectImageBtn")
42 | self.horizontalLayout.addWidget(self.reflectImageBtn)
43 | self.verticalLayout.addLayout(self.horizontalLayout)
44 |
45 | self.retranslateUi(Form)
46 | QtCore.QMetaObject.connectSlotsByName(Form)
47 |
48 | def retranslateUi(self, Form):
49 | Form.setWindowTitle(QtWidgets.QApplication.translate("Form", "Form", None, -1))
50 | self.translateLabel.setText(QtWidgets.QApplication.translate("Form", "Translate:", None, -1))
51 | self.rotateLabel.setText(QtWidgets.QApplication.translate("Form", "Rotate:", None, -1))
52 | self.scaleLabel.setText(QtWidgets.QApplication.translate("Form", "Scale:", None, -1))
53 | self.mirrorImageBtn.setText(QtWidgets.QApplication.translate("Form", "Mirror", None, -1))
54 | self.reflectImageBtn.setText(QtWidgets.QApplication.translate("Form", "Reflect", None, -1))
55 |
56 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/flowchart/NodeLibrary.py:
--------------------------------------------------------------------------------
1 | from collections import OrderedDict
2 | from .Node import Node
3 |
4 | def isNodeClass(cls):
5 | try:
6 | if not issubclass(cls, Node):
7 | return False
8 | except:
9 | return False
10 | return hasattr(cls, 'nodeName')
11 |
12 |
13 |
14 | class NodeLibrary:
15 | """
16 | A library of flowchart Node types. Custom libraries may be built to provide
17 | each flowchart with a specific set of allowed Node types.
18 | """
19 |
20 | def __init__(self):
21 | self.nodeList = OrderedDict()
22 | self.nodeTree = OrderedDict()
23 |
24 | def addNodeType(self, nodeClass, paths, override=False):
25 | """
26 | Register a new node type. If the type's name is already in use,
27 | an exception will be raised (unless override=True).
28 |
29 | ============== =========================================================
30 | **Arguments:**
31 |
32 | nodeClass a subclass of Node (must have typ.nodeName)
33 | paths list of tuples specifying the location(s) this
34 | type will appear in the library tree.
35 | override if True, overwrite any class having the same name
36 | ============== =========================================================
37 | """
38 | if not isNodeClass(nodeClass):
39 | raise Exception("Object %s is not a Node subclass" % str(nodeClass))
40 |
41 | name = nodeClass.nodeName
42 | if not override and name in self.nodeList:
43 | raise Exception("Node type name '%s' is already registered." % name)
44 |
45 | self.nodeList[name] = nodeClass
46 | for path in paths:
47 | root = self.nodeTree
48 | for n in path:
49 | if n not in root:
50 | root[n] = OrderedDict()
51 | root = root[n]
52 | root[name] = nodeClass
53 |
54 | def getNodeType(self, name):
55 | try:
56 | return self.nodeList[name]
57 | except KeyError:
58 | raise Exception("No node type called '%s'" % name)
59 |
60 | def getNodeTree(self):
61 | return self.nodeTree
62 |
63 | def copy(self):
64 | """
65 | Return a copy of this library.
66 | """
67 | lib = NodeLibrary()
68 | lib.nodeList = self.nodeList.copy()
69 | lib.nodeTree = self.treeCopy(self.nodeTree)
70 | return lib
71 |
72 | @staticmethod
73 | def treeCopy(tree):
74 | copy = OrderedDict()
75 | for k,v in tree.items():
76 | if isNodeClass(v):
77 | copy[k] = v
78 | else:
79 | copy[k] = NodeLibrary.treeCopy(v)
80 | return copy
81 |
82 | def reload(self):
83 | """
84 | Reload Node classes in this library.
85 | """
86 | raise NotImplementedError()
87 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/opengl/items/GLGridItem.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 |
3 | from OpenGL.GL import *
4 | from .. GLGraphicsItem import GLGraphicsItem
5 | from ... import QtGui
6 | from ... import functions as fn
7 |
8 | __all__ = ['GLGridItem']
9 |
10 | class GLGridItem(GLGraphicsItem):
11 | """
12 | **Bases:** :class:`GLGraphicsItem `
13 |
14 | Displays a wire-frame grid.
15 | """
16 |
17 | def __init__(self, size=None, color=(255, 255, 255, 76.5), antialias=True, glOptions='translucent'):
18 | GLGraphicsItem.__init__(self)
19 | self.setGLOptions(glOptions)
20 | self.antialias = antialias
21 | if size is None:
22 | size = QtGui.QVector3D(20,20,1)
23 | self.setSize(size=size)
24 | self.setSpacing(1, 1, 1)
25 | self.setColor(color)
26 |
27 | def setSize(self, x=None, y=None, z=None, size=None):
28 | """
29 | Set the size of the axes (in its local coordinate system; this does not affect the transform)
30 | Arguments can be x,y,z or size=QVector3D().
31 | """
32 | if size is not None:
33 | x = size.x()
34 | y = size.y()
35 | z = size.z()
36 | self.__size = [x,y,z]
37 | self.update()
38 |
39 | def size(self):
40 | return self.__size[:]
41 |
42 | def setSpacing(self, x=None, y=None, z=None, spacing=None):
43 | """
44 | Set the spacing between grid lines.
45 | Arguments can be x,y,z or spacing=QVector3D().
46 | """
47 | if spacing is not None:
48 | x = spacing.x()
49 | y = spacing.y()
50 | z = spacing.z()
51 | self.__spacing = [x,y,z]
52 | self.update()
53 |
54 | def spacing(self):
55 | return self.__spacing[:]
56 |
57 | def setColor(self, color):
58 | """Set the color of the grid. Arguments are the same as those accepted by functions.mkColor()"""
59 | self.__color = fn.mkColor(color)
60 | self.update()
61 |
62 | def color(self):
63 | return self.__color
64 |
65 | def paint(self):
66 | self.setupGLState()
67 |
68 | if self.antialias:
69 | glEnable(GL_LINE_SMOOTH)
70 | glEnable(GL_BLEND)
71 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
72 | glHint(GL_LINE_SMOOTH_HINT, GL_NICEST)
73 |
74 | glBegin( GL_LINES )
75 |
76 | x,y,z = self.size()
77 | xs,ys,zs = self.spacing()
78 | xvals = np.arange(-x/2., x/2. + xs*0.001, xs)
79 | yvals = np.arange(-y/2., y/2. + ys*0.001, ys)
80 | glColor4f(*self.color().getRgbF())
81 | for x in xvals:
82 | glVertex3f(x, yvals[0], 0)
83 | glVertex3f(x, yvals[-1], 0)
84 | for y in yvals:
85 | glVertex3f(xvals[0], y, 0)
86 | glVertex3f(xvals[-1], y, 0)
87 |
88 | glEnd()
89 |
--------------------------------------------------------------------------------
/tests/testdata/ipf-timeseries/B30F0222001.txt:
--------------------------------------------------------------------------------
1 | 113
2 | 2,1
3 | time,1e+20
4 | head,1e+20
5 | 19571214000000,-1.55
6 | 19571228000000,-1.53
7 | 19580114000000,-1.24
8 | 19580128000000,-1.28
9 | 19580215000000,-1.49
10 | 19580228000000,-1.42
11 | 19580314000000,-1.37
12 | 19580328000000,-1.43
13 | 19580414000000,-1.62
14 | 19580514000000,-1.72
15 | 19580528000000,-1.85
16 | 19580614000000,-1.81
17 | 19580628000000,-1.79
18 | 19580714000000,-1.84
19 | 19580728000000,-1.77
20 | 19580828000000,-1.91
21 | 19580915000000,-2.14
22 | 19581014000000,-1.93
23 | 19581028000000,-1.9
24 | 19581114000000,-2.0
25 | 19581128000000,-2.24
26 | 19581215000000,-2.01
27 | 19581229000000,-1.98
28 | 19590128000000,-1.83
29 | 19590214000000,-1.8
30 | 19590228000000,-2.04
31 | 19590319000000,-2.1
32 | 19590328000000,-1.89
33 | 19590414000000,-1.73
34 | 19590428000000,-1.69
35 | 19590528000000,-1.82
36 | 19590728000000,-2.11
37 | 19590828000000,-2.05
38 | 19590928000000,-2.15
39 | 19591014000000,-2.13
40 | 19591028000000,-1.94
41 | 19591128000000,-2.07
42 | 19591214000000,-2.09
43 | 19600314000000,-1.96
44 | 19600528000000,-1.92
45 | 19600714000000,-2.02
46 | 19600829000000,-1.59
47 | 19600914000000,-1.7
48 | 19600928000000,-1.76
49 | 19601014000000,-1.64
50 | 19601128000000,-1.39
51 | 19601214000000,-1.45
52 | 19601228000000,-1.52
53 | 19610114000000,-1.58
54 | 19610214000000,-1.4
55 | 19610314000000,-1.61
56 | 19610714000000,-1.99
57 | 19610828000000,-1.97
58 | 19611027000000,-1.5
59 | 19611114000000,-1.25
60 | 19611214000000,-1.33
61 | 19620201000000,-1.44
62 | 19620214000000,-1.38
63 | 19620228000000,-1.41
64 | 19620312000000,-1.56
65 | 19620314000000,-1.63
66 | 19620328000000,-1.68
67 | 19620430000000,-1.65
68 | 19620528000000,-1.6
69 | 19620628000000,-1.75
70 | 19620727000000,-1.71
71 | 19620814000000,-1.74
72 | 19620929000000,-1.67
73 | 19621214000000,-1.51
74 | 19630416000000,-1.46
75 | 19630814000000,-1.95
76 | 19640928000000,-1.86
77 | 19641014000000,-1.57
78 | 19641228000000,-1.29
79 | 19650103000000,-1.47
80 | 19650114000000,-1.26
81 | 19650128000000,-1.31
82 | 19651214000000,-1.3
83 | 19660114000000,-1.35
84 | 19660329000000,-1.48
85 | 19660516000000,-1.34
86 | 19660831000000,-1.87
87 | 19670113000000,-1.32
88 | 19680416000000,-1.54
89 | 19680927000000,-1.88
90 | 19690228000000,-1.18
91 | 19690714000000,-2.03
92 | 19690728000000,-2.08
93 | 19690814000000,-2.26
94 | 19691028000000,-2.12
95 | 19700528000000,-2.2
96 | 19720914000000,-1.36
97 | 19721128000000,-1.23
98 | 19731114000000,-1.17
99 | 19731214000000,-1.15
100 | 19740114000000,-1.14
101 | 19740128000000,-1.13
102 | 19740228000000,-1.22
103 | 19740314000000,-1.2
104 | 19740327000000,-1.21
105 | 19741014000000,-1.16
106 | 19741028000000,-1.07
107 | 19741114000000,-1.11
108 | 19741129000000,-1.06
109 | 19741213000000,-1.09
110 | 19750128000000,-1.05
111 | 19750314000000,-1.19
112 | 19751215000000,-1.27
113 | 19770214000000,-1.1
114 | 19781228000000,-1.04
115 | 19791214000000,-1.12
116 | 19810428000000,-1.08
117 | 19880128000000,-1.03
118 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/widgets/GraphicsLayoutWidget.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from ..Qt import mkQApp
3 | from ..graphicsItems.GraphicsLayout import GraphicsLayout
4 | from .GraphicsView import GraphicsView
5 |
6 | __all__ = ['GraphicsLayoutWidget']
7 | class GraphicsLayoutWidget(GraphicsView):
8 | """
9 | Convenience class consisting of a :class:`GraphicsView
10 | ` with a single :class:`GraphicsLayout
11 | ` as its central item.
12 |
13 | This widget is an easy starting point for generating multi-panel figures.
14 | Example::
15 |
16 | w = pg.GraphicsLayoutWidget()
17 | p1 = w.addPlot(row=0, col=0)
18 | p2 = w.addPlot(row=0, col=1)
19 | v = w.addViewBox(row=1, col=0, colspan=2)
20 |
21 | ========= =================================================================
22 | parent (QWidget or None) The parent widget.
23 | show (bool) If True, then immediately show the widget after it is
24 | created. If the widget has no parent, then it will be shown
25 | inside a new window.
26 | size (width, height) tuple. Optionally resize the widget. Note: if
27 | this widget is placed inside a layout, then this argument has no
28 | effect.
29 | title (str or None) If specified, then set the window title for this
30 | widget.
31 | kargs All extra arguments are passed to
32 | :meth:`GraphicsLayout.__init__
33 | `
34 | ========= =================================================================
35 |
36 |
37 | This class wraps several methods from its internal GraphicsLayout:
38 | :func:`nextRow `
39 | :func:`nextColumn `
40 | :func:`addPlot `
41 | :func:`addViewBox `
42 | :func:`addItem `
43 | :func:`getItem `
44 | :func:`addLabel `
45 | :func:`addLayout `
46 | :func:`removeItem `
47 | :func:`itemIndex `
48 | :func:`clear `
49 | """
50 | def __init__(self, parent=None, show=False, size=None, title=None, **kargs):
51 | mkQApp()
52 | GraphicsView.__init__(self, parent)
53 | self.ci = GraphicsLayout(**kargs)
54 | for n in ['nextRow', 'nextCol', 'nextColumn', 'addPlot', 'addViewBox', 'addItem', 'getItem', 'addLayout', 'addLabel', 'removeItem', 'itemIndex', 'clear']:
55 | setattr(self, n, getattr(self.ci, n))
56 | self.setCentralItem(self.ci)
57 |
58 | if size is not None:
59 | self.resize(*size)
60 |
61 | if title is not None:
62 | self.setWindowTitle(title)
63 |
64 | if show is True:
65 | self.show()
66 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/GraphicsScene/exportDialogTemplate.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Form
4 |
5 |
6 |
7 | 0
8 | 0
9 | 241
10 | 367
11 |
12 |
13 |
14 | Export
15 |
16 |
17 |
18 | 0
19 |
20 | -
21 |
22 |
23 | Item to export:
24 |
25 |
26 |
27 | -
28 |
29 |
30 | false
31 |
32 |
33 |
34 | 1
35 |
36 |
37 |
38 |
39 | -
40 |
41 |
42 | Export format
43 |
44 |
45 |
46 | -
47 |
48 |
49 | -
50 |
51 |
52 | Export
53 |
54 |
55 |
56 | -
57 |
58 |
59 | Close
60 |
61 |
62 |
63 | -
64 |
65 |
66 | 2
67 |
68 |
69 | false
70 |
71 |
72 |
73 | 1
74 |
75 |
76 |
77 |
78 | -
79 |
80 |
81 | Export options
82 |
83 |
84 |
85 | -
86 |
87 |
88 | Copy
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 | ParameterTree
97 | QTreeWidget
98 |
99 |
100 |
101 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/exporters/PrintExporter.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from .Exporter import Exporter
3 | from ..parametertree import Parameter
4 | from ..Qt import QtGui, QtCore
5 |
6 | translate = QtCore.QCoreApplication.translate
7 |
8 | __all__ = ['PrintExporter']
9 | #__all__ = [] ## Printer is disabled for now--does not work very well.
10 |
11 | class PrintExporter(Exporter):
12 | Name = "Printer"
13 | def __init__(self, item):
14 | Exporter.__init__(self, item)
15 | tr = self.getTargetRect()
16 | self.params = Parameter(name='params', type='group', children=[
17 | {'name': 'width', 'title': translate("Exporter", 'width'), 'type': 'float', 'value': 0.1,
18 | 'limits': (0, None), 'suffix': 'm', 'siPrefix': True},
19 | {'name': 'height', 'title': translate("Exporter", 'height'), 'type': 'float',
20 | 'value': (0.1 * tr.height()) / tr.width(), 'limits': (0, None), 'suffix': 'm', 'siPrefix': True},
21 | ])
22 | self.params.param('width').sigValueChanged.connect(self.widthChanged)
23 | self.params.param('height').sigValueChanged.connect(self.heightChanged)
24 |
25 | def widthChanged(self):
26 | sr = self.getSourceRect()
27 | ar = sr.height() / sr.width()
28 | self.params.param('height').setValue(self.params['width'] * ar, blockSignal=self.heightChanged)
29 |
30 | def heightChanged(self):
31 | sr = self.getSourceRect()
32 | ar = sr.width() / sr.height()
33 | self.params.param('width').setValue(self.params['height'] * ar, blockSignal=self.widthChanged)
34 |
35 | def parameters(self):
36 | return self.params
37 |
38 | def export(self, fileName=None):
39 | printer = QtGui.QPrinter(QtGui.QPrinter.HighResolution)
40 | dialog = QtGui.QPrintDialog(printer)
41 | dialog.setWindowTitle(translate('Exporter', "Print Document"))
42 | if dialog.exec_() != QtGui.QDialog.DialogCode.Accepted:
43 | return
44 |
45 | #dpi = QtGui.QDesktopWidget().physicalDpiX()
46 |
47 | #self.svg.setSize(QtCore.QSize(100,100))
48 | #self.svg.setResolution(600)
49 | #res = printer.resolution()
50 | sr = self.getSourceRect()
51 | #res = sr.width() * .4 / (self.params['width'] * 100 / 2.54)
52 | res = QtGui.QGuiApplication.primaryScreen().physicalDotsPerInchX()
53 | printer.setResolution(res)
54 | rect = printer.pageRect()
55 | center = rect.center()
56 | h = self.params['height'] * res * 100. / 2.54
57 | w = self.params['width'] * res * 100. / 2.54
58 | x = center.x() - w/2.
59 | y = center.y() - h/2.
60 |
61 | targetRect = QtCore.QRect(x, y, w, h)
62 | sourceRect = self.getSourceRect()
63 | painter = QtGui.QPainter(printer)
64 | try:
65 | self.setExportMode(True, {'painter': painter})
66 | self.getScene().render(painter, QtCore.QRectF(targetRect), QtCore.QRectF(sourceRect))
67 | finally:
68 | self.setExportMode(False)
69 | painter.end()
70 |
71 |
72 | #PrintExporter.register()
73 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/widgets/JoystickButton.py:
--------------------------------------------------------------------------------
1 | from math import hypot
2 | from ..Qt import QtGui, QtCore, mkQApp
3 |
4 |
5 | __all__ = ['JoystickButton']
6 |
7 | class JoystickButton(QtGui.QPushButton):
8 | sigStateChanged = QtCore.Signal(object, object) ## self, state
9 |
10 | def __init__(self, parent=None):
11 | QtGui.QPushButton.__init__(self, parent)
12 | self.radius = 200
13 | self.setCheckable(True)
14 | self.state = None
15 | self.setState(0, 0)
16 | self.setFixedWidth(50)
17 | self.setFixedHeight(50)
18 |
19 |
20 | def mousePressEvent(self, ev):
21 | self.setChecked(True)
22 | lpos = ev.position() if hasattr(ev, 'position') else ev.localPos()
23 | self.pressPos = lpos
24 | ev.accept()
25 |
26 | def mouseMoveEvent(self, ev):
27 | lpos = ev.position() if hasattr(ev, 'position') else ev.localPos()
28 | dif = lpos - self.pressPos
29 | self.setState(dif.x(), -dif.y())
30 |
31 | def mouseReleaseEvent(self, ev):
32 | self.setChecked(False)
33 | self.setState(0,0)
34 |
35 | def wheelEvent(self, ev):
36 | ev.accept()
37 |
38 |
39 | def doubleClickEvent(self, ev):
40 | ev.accept()
41 |
42 | def getState(self):
43 | return self.state
44 |
45 | def setState(self, *xy):
46 | xy = list(xy)
47 | d = hypot(xy[0], xy[1]) # length
48 | nxy = [0, 0]
49 | for i in [0,1]:
50 | if xy[i] == 0:
51 | nxy[i] = 0
52 | else:
53 | nxy[i] = xy[i] / d
54 |
55 | if d > self.radius:
56 | d = self.radius
57 | d = (d / self.radius) ** 2
58 | xy = [nxy[0] * d, nxy[1] * d]
59 |
60 | w2 = self.width() / 2
61 | h2 = self.height() / 2
62 | self.spotPos = QtCore.QPoint(
63 | int(w2 * (1 + xy[0])),
64 | int(h2 * (1 - xy[1]))
65 | )
66 | self.update()
67 | if self.state == xy:
68 | return
69 | self.state = xy
70 | self.sigStateChanged.emit(self, self.state)
71 |
72 | def paintEvent(self, ev):
73 | super().paintEvent(ev)
74 | p = QtGui.QPainter(self)
75 | p.setBrush(QtGui.QBrush(QtGui.QColor(0,0,0)))
76 | p.drawEllipse(
77 | self.spotPos.x() - 3,
78 | self.spotPos.y() - 3,
79 | 6,
80 | 6
81 | )
82 |
83 | def resizeEvent(self, ev):
84 | self.setState(*self.state)
85 | super().resizeEvent(ev)
86 |
87 |
88 |
89 | if __name__ == '__main__':
90 | app = mkQApp()
91 | w = QtGui.QMainWindow()
92 | b = JoystickButton()
93 | w.setCentralWidget(b)
94 | w.show()
95 | w.resize(100, 100)
96 |
97 | def fn(b, s):
98 | print("state changed:", s)
99 |
100 | b.sigStateChanged.connect(fn)
101 |
102 | app.exec() if hasattr(app, 'exec') else app.exec_()
103 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/widgets/ValueLabel.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from time import perf_counter
3 | from ..Qt import QtGui
4 | from .. import functions as fn
5 |
6 | __all__ = ['ValueLabel']
7 |
8 | class ValueLabel(QtGui.QLabel):
9 | """
10 | QLabel specifically for displaying numerical values.
11 | Extends QLabel adding some extra functionality:
12 |
13 | - displaying units with si prefix
14 | - built-in exponential averaging
15 | """
16 |
17 | def __init__(self, parent=None, suffix='', siPrefix=False, averageTime=0, formatStr=None):
18 | """
19 | ============== ==================================================================================
20 | **Arguments:**
21 | suffix (str or None) The suffix to place after the value
22 | siPrefix (bool) Whether to add an SI prefix to the units and display a scaled value
23 | averageTime (float) The length of time in seconds to average values. If this value
24 | is 0, then no averaging is performed. As this value increases
25 | the display value will appear to change more slowly and smoothly.
26 | formatStr (str) Optionally, provide a format string to use when displaying text. The text
27 | will be generated by calling formatStr.format(value=, avgValue=, suffix=)
28 | (see Python documentation on str.format)
29 | This option is not compatible with siPrefix
30 | ============== ==================================================================================
31 | """
32 | QtGui.QLabel.__init__(self, parent)
33 | self.values = []
34 | self.averageTime = averageTime ## no averaging by default
35 | self.suffix = suffix
36 | self.siPrefix = siPrefix
37 | if formatStr is None:
38 | formatStr = '{avgValue:0.2g} {suffix}'
39 | self.formatStr = formatStr
40 |
41 | def setValue(self, value):
42 | now = perf_counter()
43 | self.values.append((now, value))
44 | cutoff = now - self.averageTime
45 | while len(self.values) > 0 and self.values[0][0] < cutoff:
46 | self.values.pop(0)
47 | self.update()
48 |
49 | def setFormatStr(self, text):
50 | self.formatStr = text
51 | self.update()
52 |
53 | def setAverageTime(self, t):
54 | self.averageTime = t
55 |
56 | def averageValue(self):
57 | return sum(v[1] for v in self.values) / float(len(self.values))
58 |
59 |
60 | def paintEvent(self, ev):
61 | self.setText(self.generateText())
62 | return super().paintEvent(ev)
63 |
64 | def generateText(self):
65 | if len(self.values) == 0:
66 | return ''
67 | avg = self.averageValue()
68 | val = self.values[-1][1]
69 | if self.siPrefix:
70 | return fn.siFormat(avg, suffix=self.suffix)
71 | else:
72 | return self.formatStr.format(value=val, avgValue=avg, suffix=self.suffix)
73 |
74 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/GraphicsScene/exportDialogTemplate_pyqt6.py:
--------------------------------------------------------------------------------
1 | # Form implementation generated from reading ui file '../pyqtgraph/GraphicsScene/exportDialogTemplate.ui'
2 | #
3 | # Created by: PyQt6 UI code generator 6.1.0
4 | #
5 | # WARNING: Any manual changes made to this file will be lost when pyuic6 is
6 | # run again. Do not edit this file unless you know what you are doing.
7 |
8 |
9 | from PyQt6 import QtCore, QtGui, QtWidgets
10 |
11 |
12 | class Ui_Form(object):
13 | def setupUi(self, Form):
14 | Form.setObjectName("Form")
15 | Form.resize(241, 367)
16 | self.gridLayout = QtWidgets.QGridLayout(Form)
17 | self.gridLayout.setSpacing(0)
18 | self.gridLayout.setObjectName("gridLayout")
19 | self.label = QtWidgets.QLabel(Form)
20 | self.label.setObjectName("label")
21 | self.gridLayout.addWidget(self.label, 0, 0, 1, 3)
22 | self.itemTree = QtWidgets.QTreeWidget(Form)
23 | self.itemTree.setObjectName("itemTree")
24 | self.itemTree.headerItem().setText(0, "1")
25 | self.itemTree.header().setVisible(False)
26 | self.gridLayout.addWidget(self.itemTree, 1, 0, 1, 3)
27 | self.label_2 = QtWidgets.QLabel(Form)
28 | self.label_2.setObjectName("label_2")
29 | self.gridLayout.addWidget(self.label_2, 2, 0, 1, 3)
30 | self.formatList = QtWidgets.QListWidget(Form)
31 | self.formatList.setObjectName("formatList")
32 | self.gridLayout.addWidget(self.formatList, 3, 0, 1, 3)
33 | self.exportBtn = QtWidgets.QPushButton(Form)
34 | self.exportBtn.setObjectName("exportBtn")
35 | self.gridLayout.addWidget(self.exportBtn, 6, 1, 1, 1)
36 | self.closeBtn = QtWidgets.QPushButton(Form)
37 | self.closeBtn.setObjectName("closeBtn")
38 | self.gridLayout.addWidget(self.closeBtn, 6, 2, 1, 1)
39 | self.paramTree = ParameterTree(Form)
40 | self.paramTree.setColumnCount(2)
41 | self.paramTree.setObjectName("paramTree")
42 | self.paramTree.headerItem().setText(0, "1")
43 | self.paramTree.header().setVisible(False)
44 | self.gridLayout.addWidget(self.paramTree, 5, 0, 1, 3)
45 | self.label_3 = QtWidgets.QLabel(Form)
46 | self.label_3.setObjectName("label_3")
47 | self.gridLayout.addWidget(self.label_3, 4, 0, 1, 3)
48 | self.copyBtn = QtWidgets.QPushButton(Form)
49 | self.copyBtn.setObjectName("copyBtn")
50 | self.gridLayout.addWidget(self.copyBtn, 6, 0, 1, 1)
51 |
52 | self.retranslateUi(Form)
53 | QtCore.QMetaObject.connectSlotsByName(Form)
54 |
55 | def retranslateUi(self, Form):
56 | _translate = QtCore.QCoreApplication.translate
57 | Form.setWindowTitle(_translate("Form", "Export"))
58 | self.label.setText(_translate("Form", "Item to export:"))
59 | self.label_2.setText(_translate("Form", "Export format"))
60 | self.exportBtn.setText(_translate("Form", "Export"))
61 | self.closeBtn.setText(_translate("Form", "Close"))
62 | self.label_3.setText(_translate("Form", "Export options"))
63 | self.copyBtn.setText(_translate("Form", "Copy"))
64 | from ..parametertree import ParameterTree
65 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/flowchart/FlowchartCtrlTemplate_pyqt5.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Form implementation generated from reading ui file './pyqtgraph/flowchart/FlowchartCtrlTemplate.ui'
4 | #
5 | # Created: Wed Mar 26 15:09:28 2014
6 | # by: PyQt5 UI code generator 5.0.1
7 | #
8 | # WARNING! All changes made in this file will be lost!
9 |
10 | from PyQt5 import QtCore, QtGui, QtWidgets
11 |
12 | class Ui_Form(object):
13 | def setupUi(self, Form):
14 | Form.setObjectName("Form")
15 | Form.resize(217, 499)
16 | self.gridLayout = QtWidgets.QGridLayout(Form)
17 | self.gridLayout.setContentsMargins(0, 0, 0, 0)
18 | self.gridLayout.setVerticalSpacing(0)
19 | self.gridLayout.setObjectName("gridLayout")
20 | self.loadBtn = QtWidgets.QPushButton(Form)
21 | self.loadBtn.setObjectName("loadBtn")
22 | self.gridLayout.addWidget(self.loadBtn, 1, 0, 1, 1)
23 | self.saveBtn = FeedbackButton(Form)
24 | self.saveBtn.setObjectName("saveBtn")
25 | self.gridLayout.addWidget(self.saveBtn, 1, 1, 1, 2)
26 | self.saveAsBtn = FeedbackButton(Form)
27 | self.saveAsBtn.setObjectName("saveAsBtn")
28 | self.gridLayout.addWidget(self.saveAsBtn, 1, 3, 1, 1)
29 | self.reloadBtn = FeedbackButton(Form)
30 | self.reloadBtn.setCheckable(False)
31 | self.reloadBtn.setFlat(False)
32 | self.reloadBtn.setObjectName("reloadBtn")
33 | self.gridLayout.addWidget(self.reloadBtn, 4, 0, 1, 2)
34 | self.showChartBtn = QtWidgets.QPushButton(Form)
35 | self.showChartBtn.setCheckable(True)
36 | self.showChartBtn.setObjectName("showChartBtn")
37 | self.gridLayout.addWidget(self.showChartBtn, 4, 2, 1, 2)
38 | self.ctrlList = TreeWidget(Form)
39 | self.ctrlList.setObjectName("ctrlList")
40 | self.ctrlList.headerItem().setText(0, "1")
41 | self.ctrlList.header().setVisible(False)
42 | self.ctrlList.header().setStretchLastSection(False)
43 | self.gridLayout.addWidget(self.ctrlList, 3, 0, 1, 4)
44 | self.fileNameLabel = QtWidgets.QLabel(Form)
45 | font = QtGui.QFont()
46 | font.setBold(True)
47 | font.setWeight(75)
48 | self.fileNameLabel.setFont(font)
49 | self.fileNameLabel.setText("")
50 | self.fileNameLabel.setAlignment(QtCore.Qt.AlignCenter)
51 | self.fileNameLabel.setObjectName("fileNameLabel")
52 | self.gridLayout.addWidget(self.fileNameLabel, 0, 1, 1, 1)
53 |
54 | self.retranslateUi(Form)
55 | QtCore.QMetaObject.connectSlotsByName(Form)
56 |
57 | def retranslateUi(self, Form):
58 | _translate = QtCore.QCoreApplication.translate
59 | Form.setWindowTitle(_translate("Form", "PyQtGraph"))
60 | self.loadBtn.setText(_translate("Form", "Load.."))
61 | self.saveBtn.setText(_translate("Form", "Save"))
62 | self.saveAsBtn.setText(_translate("Form", "As.."))
63 | self.reloadBtn.setText(_translate("Form", "Reload Libs"))
64 | self.showChartBtn.setText(_translate("Form", "Flowchart"))
65 |
66 | from ..widgets.FeedbackButton import FeedbackButton
67 | from ..widgets.TreeWidget import TreeWidget
68 |
--------------------------------------------------------------------------------
/imodqgis/widgets/colors_dialog.py:
--------------------------------------------------------------------------------
1 | # Copyright © 2021 Deltares
2 | # SPDX-License-Identifier: GPL-2.0-or-later
3 | #
4 | import numpy as np
5 | from PyQt5.QtWidgets import (
6 | QComboBox,
7 | QDialog,
8 | QHBoxLayout,
9 | QLabel,
10 | QPushButton,
11 | QVBoxLayout,
12 | )
13 |
14 | PSEUDOCOLOR = 0
15 | UNIQUE_COLOR = 1
16 |
17 |
18 | class ColorsDialog(QDialog):
19 | def __init__(
20 | self, pseudocolor_widget, unique_color_widget, default_to, data, parent
21 | ):
22 | QDialog.__init__(self, parent)
23 | self.pseudocolor_widget = pseudocolor_widget
24 | self.unique_color_widget = unique_color_widget
25 | self.data = data
26 |
27 | self.render_type_box = QComboBox()
28 | self.render_type_box.insertItems(0, ["Pseudocolor", "Unique values"])
29 | self.render_type_box.setCurrentIndex(default_to)
30 | self.render_type_box.currentIndexChanged.connect(self.on_render_type_changed)
31 |
32 | # Check if data is a number dtype, if not: only unique coloring works properly
33 | if not np.issubdtype(data.dtype, np.number):
34 | self.render_type_box.setCurrentIndex(UNIQUE_COLOR)
35 | self.render_type_box.setEnabled(False)
36 | else:
37 | self.render_type_box.setEnabled(True)
38 |
39 | apply_button = QPushButton("Apply")
40 | cancel_button = QPushButton("Cancel")
41 | apply_button.clicked.connect(self.accept)
42 | cancel_button.clicked.connect(self.reject)
43 |
44 | first_row = QHBoxLayout()
45 | first_row.addWidget(QLabel("Render type:"))
46 | first_row.addWidget(self.render_type_box)
47 | first_row.addStretch()
48 |
49 | second_row = QHBoxLayout()
50 | second_row.addWidget(apply_button)
51 | second_row.addWidget(cancel_button)
52 | layout = QVBoxLayout()
53 | layout.addLayout(first_row)
54 | layout.addWidget(self.pseudocolor_widget)
55 | layout.addWidget(self.unique_color_widget)
56 | layout.addLayout(second_row)
57 | self.setLayout(layout)
58 | self.on_render_type_changed()
59 |
60 | def on_render_type_changed(self):
61 | if self.render_type_box.currentIndex() == PSEUDOCOLOR:
62 | self.pseudocolor_widget.setVisible(True)
63 | self.unique_color_widget.setVisible(False)
64 | self.pseudocolor_widget.set_data(self.data)
65 | else:
66 | self.pseudocolor_widget.setVisible(False)
67 | self.unique_color_widget.setVisible(True)
68 | self.unique_color_widget.set_data(self.data)
69 |
70 | def detach(self):
71 | self.pseudocolor_widget.setParent(self.parent())
72 | self.unique_color_widget.setParent(self.parent())
73 |
74 | # NOTA BENE: detach() and these overloaded methods are required, otherwise
75 | # the color_widget is garbage collected when the dialog closes.
76 | def closeEvent(self, e):
77 | self.detach()
78 | QDialog.closeEvent(self, e)
79 |
80 | def reject(self):
81 | self.detach()
82 | QDialog.reject(self)
83 |
84 | def accept(self):
85 | self.detach()
86 | QDialog.accept(self)
87 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/GraphicsScene/exportDialogTemplate_pyqt5.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Form implementation generated from reading ui file '.\exportDialogTemplate.ui'
4 | #
5 | # Created by: PyQt5 UI code generator 5.15.4
6 | #
7 | # WARNING: Any manual changes made to this file will be lost when pyuic5 is
8 | # run again. Do not edit this file unless you know what you are doing.
9 |
10 |
11 | from PyQt5 import QtCore, QtGui, QtWidgets
12 |
13 |
14 | class Ui_Form(object):
15 | def setupUi(self, Form):
16 | Form.setObjectName("Form")
17 | Form.resize(241, 367)
18 | self.gridLayout = QtWidgets.QGridLayout(Form)
19 | self.gridLayout.setSpacing(0)
20 | self.gridLayout.setObjectName("gridLayout")
21 | self.label = QtWidgets.QLabel(Form)
22 | self.label.setObjectName("label")
23 | self.gridLayout.addWidget(self.label, 0, 0, 1, 3)
24 | self.itemTree = QtWidgets.QTreeWidget(Form)
25 | self.itemTree.setObjectName("itemTree")
26 | self.itemTree.headerItem().setText(0, "1")
27 | self.itemTree.header().setVisible(False)
28 | self.gridLayout.addWidget(self.itemTree, 1, 0, 1, 3)
29 | self.label_2 = QtWidgets.QLabel(Form)
30 | self.label_2.setObjectName("label_2")
31 | self.gridLayout.addWidget(self.label_2, 2, 0, 1, 3)
32 | self.formatList = QtWidgets.QListWidget(Form)
33 | self.formatList.setObjectName("formatList")
34 | self.gridLayout.addWidget(self.formatList, 3, 0, 1, 3)
35 | self.exportBtn = QtWidgets.QPushButton(Form)
36 | self.exportBtn.setObjectName("exportBtn")
37 | self.gridLayout.addWidget(self.exportBtn, 6, 1, 1, 1)
38 | self.closeBtn = QtWidgets.QPushButton(Form)
39 | self.closeBtn.setObjectName("closeBtn")
40 | self.gridLayout.addWidget(self.closeBtn, 6, 2, 1, 1)
41 | self.paramTree = ParameterTree(Form)
42 | self.paramTree.setColumnCount(2)
43 | self.paramTree.setObjectName("paramTree")
44 | self.paramTree.headerItem().setText(0, "1")
45 | self.paramTree.header().setVisible(False)
46 | self.gridLayout.addWidget(self.paramTree, 5, 0, 1, 3)
47 | self.label_3 = QtWidgets.QLabel(Form)
48 | self.label_3.setObjectName("label_3")
49 | self.gridLayout.addWidget(self.label_3, 4, 0, 1, 3)
50 | self.copyBtn = QtWidgets.QPushButton(Form)
51 | self.copyBtn.setObjectName("copyBtn")
52 | self.gridLayout.addWidget(self.copyBtn, 6, 0, 1, 1)
53 |
54 | self.retranslateUi(Form)
55 | QtCore.QMetaObject.connectSlotsByName(Form)
56 |
57 | def retranslateUi(self, Form):
58 | _translate = QtCore.QCoreApplication.translate
59 | Form.setWindowTitle(_translate("Form", "Export"))
60 | self.label.setText(_translate("Form", "Item to export:"))
61 | self.label_2.setText(_translate("Form", "Export format"))
62 | self.exportBtn.setText(_translate("Form", "Export"))
63 | self.closeBtn.setText(_translate("Form", "Close"))
64 | self.label_3.setText(_translate("Form", "Export options"))
65 | self.copyBtn.setText(_translate("Form", "Copy"))
66 | from ..parametertree import ParameterTree
67 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/flowchart/FlowchartCtrlTemplate_pyqt6.py:
--------------------------------------------------------------------------------
1 | # Form implementation generated from reading ui file '../pyqtgraph/flowchart/FlowchartCtrlTemplate.ui'
2 | #
3 | # Created by: PyQt6 UI code generator 6.1.0
4 | #
5 | # WARNING: Any manual changes made to this file will be lost when pyuic6 is
6 | # run again. Do not edit this file unless you know what you are doing.
7 |
8 |
9 | from PyQt6 import QtCore, QtGui, QtWidgets
10 |
11 |
12 | class Ui_Form(object):
13 | def setupUi(self, Form):
14 | Form.setObjectName("Form")
15 | Form.resize(217, 499)
16 | self.gridLayout = QtWidgets.QGridLayout(Form)
17 | self.gridLayout.setContentsMargins(0, 0, 0, 0)
18 | self.gridLayout.setVerticalSpacing(0)
19 | self.gridLayout.setObjectName("gridLayout")
20 | self.loadBtn = QtWidgets.QPushButton(Form)
21 | self.loadBtn.setObjectName("loadBtn")
22 | self.gridLayout.addWidget(self.loadBtn, 1, 0, 1, 1)
23 | self.saveBtn = FeedbackButton(Form)
24 | self.saveBtn.setObjectName("saveBtn")
25 | self.gridLayout.addWidget(self.saveBtn, 1, 1, 1, 2)
26 | self.saveAsBtn = FeedbackButton(Form)
27 | self.saveAsBtn.setObjectName("saveAsBtn")
28 | self.gridLayout.addWidget(self.saveAsBtn, 1, 3, 1, 1)
29 | self.reloadBtn = FeedbackButton(Form)
30 | self.reloadBtn.setCheckable(False)
31 | self.reloadBtn.setFlat(False)
32 | self.reloadBtn.setObjectName("reloadBtn")
33 | self.gridLayout.addWidget(self.reloadBtn, 4, 0, 1, 2)
34 | self.showChartBtn = QtWidgets.QPushButton(Form)
35 | self.showChartBtn.setCheckable(True)
36 | self.showChartBtn.setObjectName("showChartBtn")
37 | self.gridLayout.addWidget(self.showChartBtn, 4, 2, 1, 2)
38 | self.ctrlList = TreeWidget(Form)
39 | self.ctrlList.setObjectName("ctrlList")
40 | self.ctrlList.headerItem().setText(0, "1")
41 | self.ctrlList.header().setVisible(False)
42 | self.ctrlList.header().setStretchLastSection(False)
43 | self.gridLayout.addWidget(self.ctrlList, 3, 0, 1, 4)
44 | self.fileNameLabel = QtWidgets.QLabel(Form)
45 | font = QtGui.QFont()
46 | font.setBold(True)
47 | self.fileNameLabel.setFont(font)
48 | self.fileNameLabel.setText("")
49 | self.fileNameLabel.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
50 | self.fileNameLabel.setObjectName("fileNameLabel")
51 | self.gridLayout.addWidget(self.fileNameLabel, 0, 1, 1, 1)
52 |
53 | self.retranslateUi(Form)
54 | QtCore.QMetaObject.connectSlotsByName(Form)
55 |
56 | def retranslateUi(self, Form):
57 | _translate = QtCore.QCoreApplication.translate
58 | Form.setWindowTitle(_translate("Form", "PyQtGraph"))
59 | self.loadBtn.setText(_translate("Form", "Load.."))
60 | self.saveBtn.setText(_translate("Form", "Save"))
61 | self.saveAsBtn.setText(_translate("Form", "As.."))
62 | self.reloadBtn.setText(_translate("Form", "Reload Libs"))
63 | self.showChartBtn.setText(_translate("Form", "Flowchart"))
64 | from ..widgets.FeedbackButton import FeedbackButton
65 | from ..widgets.TreeWidget import TreeWidget
66 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/graphicsItems/FillBetweenItem.py:
--------------------------------------------------------------------------------
1 | from ..Qt import QtGui
2 | from .. import functions as fn
3 | from .PlotDataItem import PlotDataItem
4 | from .PlotCurveItem import PlotCurveItem
5 |
6 | __all__ = ['FillBetweenItem']
7 |
8 | class FillBetweenItem(QtGui.QGraphicsPathItem):
9 | """
10 | GraphicsItem filling the space between two PlotDataItems.
11 | """
12 | def __init__(self, curve1=None, curve2=None, brush=None, pen=None):
13 | QtGui.QGraphicsPathItem.__init__(self)
14 | self.curves = None
15 | if curve1 is not None and curve2 is not None:
16 | self.setCurves(curve1, curve2)
17 | elif curve1 is not None or curve2 is not None:
18 | raise Exception("Must specify two curves to fill between.")
19 |
20 | if brush is not None:
21 | self.setBrush(brush)
22 | self.setPen(pen)
23 | self.updatePath()
24 |
25 | def setBrush(self, *args, **kwds):
26 | """Change the fill brush. Acceps the same arguments as pg.mkBrush()"""
27 | QtGui.QGraphicsPathItem.setBrush(self, fn.mkBrush(*args, **kwds))
28 |
29 | def setPen(self, *args, **kwds):
30 | QtGui.QGraphicsPathItem.setPen(self, fn.mkPen(*args, **kwds))
31 |
32 | def setCurves(self, curve1, curve2):
33 | """Set the curves to fill between.
34 |
35 | Arguments must be instances of PlotDataItem or PlotCurveItem.
36 |
37 | Added in version 0.9.9
38 | """
39 | if self.curves is not None:
40 | for c in self.curves:
41 | try:
42 | c.sigPlotChanged.disconnect(self.curveChanged)
43 | except (TypeError, RuntimeError):
44 | pass
45 |
46 | curves = [curve1, curve2]
47 | for c in curves:
48 | if not isinstance(c, PlotDataItem) and not isinstance(c, PlotCurveItem):
49 | raise TypeError("Curves must be PlotDataItem or PlotCurveItem.")
50 | self.curves = curves
51 | curve1.sigPlotChanged.connect(self.curveChanged)
52 | curve2.sigPlotChanged.connect(self.curveChanged)
53 | self.setZValue(min(curve1.zValue(), curve2.zValue())-1)
54 | self.curveChanged()
55 |
56 | def curveChanged(self):
57 | self.updatePath()
58 |
59 | def updatePath(self):
60 | if self.curves is None:
61 | self.setPath(QtGui.QPainterPath())
62 | return
63 | paths = []
64 | for c in self.curves:
65 | if isinstance(c, PlotDataItem):
66 | paths.append(c.curve.getPath())
67 | elif isinstance(c, PlotCurveItem):
68 | paths.append(c.getPath())
69 |
70 | path = QtGui.QPainterPath()
71 | transform = QtGui.QTransform()
72 | ps1 = paths[0].toSubpathPolygons(transform)
73 | ps2 = paths[1].toReversed().toSubpathPolygons(transform)
74 | ps2.reverse()
75 | if len(ps1) == 0 or len(ps2) == 0:
76 | self.setPath(QtGui.QPainterPath())
77 | return
78 |
79 |
80 | for p1, p2 in zip(ps1, ps2):
81 | path.addPolygon(p1 + p2)
82 | self.setPath(path)
83 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/canvas/TransformGuiTemplate_pyside6.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | ################################################################################
4 | ## Form generated from reading UI file 'TransformGuiTemplate.ui'
5 | ##
6 | ## Created by: Qt User Interface Compiler version 6.1.0
7 | ##
8 | ## WARNING! All changes made in this file will be lost when recompiling UI file!
9 | ################################################################################
10 |
11 | from PySide6.QtCore import *
12 | from PySide6.QtGui import *
13 | from PySide6.QtWidgets import *
14 |
15 |
16 | class Ui_Form(object):
17 | def setupUi(self, Form):
18 | if not Form.objectName():
19 | Form.setObjectName(u"Form")
20 | Form.resize(224, 117)
21 | sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
22 | sizePolicy.setHorizontalStretch(0)
23 | sizePolicy.setVerticalStretch(0)
24 | sizePolicy.setHeightForWidth(Form.sizePolicy().hasHeightForWidth())
25 | Form.setSizePolicy(sizePolicy)
26 | self.verticalLayout = QVBoxLayout(Form)
27 | self.verticalLayout.setSpacing(1)
28 | self.verticalLayout.setContentsMargins(0, 0, 0, 0)
29 | self.verticalLayout.setObjectName(u"verticalLayout")
30 | self.translateLabel = QLabel(Form)
31 | self.translateLabel.setObjectName(u"translateLabel")
32 |
33 | self.verticalLayout.addWidget(self.translateLabel)
34 |
35 | self.rotateLabel = QLabel(Form)
36 | self.rotateLabel.setObjectName(u"rotateLabel")
37 |
38 | self.verticalLayout.addWidget(self.rotateLabel)
39 |
40 | self.scaleLabel = QLabel(Form)
41 | self.scaleLabel.setObjectName(u"scaleLabel")
42 |
43 | self.verticalLayout.addWidget(self.scaleLabel)
44 |
45 | self.horizontalLayout = QHBoxLayout()
46 | self.horizontalLayout.setObjectName(u"horizontalLayout")
47 | self.mirrorImageBtn = QPushButton(Form)
48 | self.mirrorImageBtn.setObjectName(u"mirrorImageBtn")
49 |
50 | self.horizontalLayout.addWidget(self.mirrorImageBtn)
51 |
52 | self.reflectImageBtn = QPushButton(Form)
53 | self.reflectImageBtn.setObjectName(u"reflectImageBtn")
54 |
55 | self.horizontalLayout.addWidget(self.reflectImageBtn)
56 |
57 |
58 | self.verticalLayout.addLayout(self.horizontalLayout)
59 |
60 |
61 | self.retranslateUi(Form)
62 |
63 | QMetaObject.connectSlotsByName(Form)
64 | # setupUi
65 |
66 | def retranslateUi(self, Form):
67 | Form.setWindowTitle(QCoreApplication.translate("Form", u"PyQtGraph", None))
68 | self.translateLabel.setText(QCoreApplication.translate("Form", u"Translate:", None))
69 | self.rotateLabel.setText(QCoreApplication.translate("Form", u"Rotate:", None))
70 | self.scaleLabel.setText(QCoreApplication.translate("Form", u"Scale:", None))
71 | #if QT_CONFIG(tooltip)
72 | self.mirrorImageBtn.setToolTip("")
73 | #endif // QT_CONFIG(tooltip)
74 | self.mirrorImageBtn.setText(QCoreApplication.translate("Form", u"Mirror", None))
75 | self.reflectImageBtn.setText(QCoreApplication.translate("Form", u"Reflect", None))
76 | # retranslateUi
77 |
78 |
--------------------------------------------------------------------------------
/imodqgis/utils/layers.py:
--------------------------------------------------------------------------------
1 | # Copyright © 2021 Deltares
2 | # SPDX-License-Identifier: GPL-2.0-or-later
3 | #
4 | """
5 | Layer utilities, different layers are currently stored
6 | in datasets as individual variables ("group_names").
7 |
8 | When MDAL supports layers for UGRID, these utilities become unnecessary
9 | """
10 |
11 | import re
12 | from collections import defaultdict
13 |
14 | from qgis.core import (
15 | QgsMeshDatasetIndex,
16 | )
17 |
18 | NO_LAYERS = ["0"]
19 |
20 | def natural_sort_key(pair, _nsre=re.compile("([0-9]+)")):
21 | # From: https://stackoverflow.com/questions/4836710/is-there-a-built-in-function-for-string-natural-sort
22 | s = pair[0]
23 | return [int(text) if text.isdigit() else text.lower() for text in _nsre.split(s)]
24 |
25 |
26 | def get_group_names(layer):
27 | indexes = layer.datasetGroupsIndexes()
28 | qgs_indexes = [QgsMeshDatasetIndex(group=i, dataset=0) for i in indexes]
29 | group_names = [layer.datasetGroupMetadata(i).name() for i in qgs_indexes]
30 | # Sort the entries by name
31 | sorted_pairs = sorted(zip(group_names, indexes), key=natural_sort_key)
32 | group_names, indexes = [list(tup) for tup in zip(*sorted_pairs)]
33 | return indexes, group_names
34 |
35 |
36 | def groupby_variable(group_names, dataset_indexes):
37 | EXCEPTED_VARIABLE_NAMES = ["face_x", "face_y"] # Might be further expanded with other UGRID groups.
38 | grouped = defaultdict(dict)
39 | for group_name, dataset_idx in zip(group_names, dataset_indexes):
40 | if "_layer_" in group_name:
41 | parts = group_name.split("_layer_")
42 | name, layer_number = parts
43 | grouped[name][layer_number] = dataset_idx
44 | elif group_name not in EXCEPTED_VARIABLE_NAMES:
45 | layer_number = NO_LAYERS[0]
46 | name = group_name
47 | grouped[name][layer_number] = dataset_idx
48 |
49 | return grouped
50 |
51 |
52 | def groupby_layer(group_names):
53 | """
54 | Groupby layer, provided by a list variable names ("group names", in MDAL terms).
55 |
56 | Parameters
57 | ----------
58 | group_names : list of str
59 | list with dataset group names
60 |
61 |
62 | Returns
63 | -------
64 | gb : dict
65 | A dictionary with "layer_{\d+}" as key and
66 | a list with all full dataset names
67 | as value
68 | """
69 | prog = re.compile("(.+)_(layer_\d+)")
70 | groups = [prog.match(group_name) for group_name in group_names]
71 | # Filter None from list, as to filter variables without "layer" in name, e.g. 'faces_x'
72 | groups = list(filter(None.__ne__, groups))
73 | # Convert to list of tuples: [('layer_1', 'bottom_layer_1'), ...]
74 | # the .group confusingly is a regex method here.
75 | groups = [(g.group(2), g.group(0)) for g in groups]
76 | gb = defaultdict(list)
77 | for key, group in groups:
78 | gb[key].append(group)
79 | return gb
80 |
81 |
82 | def get_layer_idx(layer_key):
83 | """
84 | Extract layer number from a key such as 'layer_1'
85 |
86 | Parameters
87 | ----------
88 | key : str
89 | layer key like 'layer_1'
90 |
91 | Returns
92 | -------
93 | int
94 | """
95 | return int(re.match("layer_(\d+)", layer_key).group(1))
96 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/flowchart/FlowchartCtrlTemplate_pyside2.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Form implementation generated from reading ui file 'FlowchartCtrlTemplate.ui'
4 | #
5 | # Created: Sun Sep 18 19:16:46 2016
6 | # by: pyside2-uic running on PySide2 2.0.0~alpha0
7 | #
8 | # WARNING! All changes made in this file will be lost!
9 |
10 | from PySide2 import QtCore, QtGui, QtWidgets
11 |
12 | class Ui_Form(object):
13 | def setupUi(self, Form):
14 | Form.setObjectName("Form")
15 | Form.resize(217, 499)
16 | self.gridLayout = QtWidgets.QGridLayout(Form)
17 | self.gridLayout.setContentsMargins(0, 0, 0, 0)
18 | self.gridLayout.setVerticalSpacing(0)
19 | self.gridLayout.setObjectName("gridLayout")
20 | self.loadBtn = QtWidgets.QPushButton(Form)
21 | self.loadBtn.setObjectName("loadBtn")
22 | self.gridLayout.addWidget(self.loadBtn, 1, 0, 1, 1)
23 | self.saveBtn = FeedbackButton(Form)
24 | self.saveBtn.setObjectName("saveBtn")
25 | self.gridLayout.addWidget(self.saveBtn, 1, 1, 1, 2)
26 | self.saveAsBtn = FeedbackButton(Form)
27 | self.saveAsBtn.setObjectName("saveAsBtn")
28 | self.gridLayout.addWidget(self.saveAsBtn, 1, 3, 1, 1)
29 | self.reloadBtn = FeedbackButton(Form)
30 | self.reloadBtn.setCheckable(False)
31 | self.reloadBtn.setFlat(False)
32 | self.reloadBtn.setObjectName("reloadBtn")
33 | self.gridLayout.addWidget(self.reloadBtn, 4, 0, 1, 2)
34 | self.showChartBtn = QtWidgets.QPushButton(Form)
35 | self.showChartBtn.setCheckable(True)
36 | self.showChartBtn.setObjectName("showChartBtn")
37 | self.gridLayout.addWidget(self.showChartBtn, 4, 2, 1, 2)
38 | self.ctrlList = TreeWidget(Form)
39 | self.ctrlList.setObjectName("ctrlList")
40 | self.ctrlList.headerItem().setText(0, "1")
41 | self.ctrlList.header().setVisible(False)
42 | self.ctrlList.header().setStretchLastSection(False)
43 | self.gridLayout.addWidget(self.ctrlList, 3, 0, 1, 4)
44 | self.fileNameLabel = QtWidgets.QLabel(Form)
45 | font = QtGui.QFont()
46 | font.setWeight(75)
47 | font.setBold(True)
48 | self.fileNameLabel.setFont(font)
49 | self.fileNameLabel.setText("")
50 | self.fileNameLabel.setAlignment(QtCore.Qt.AlignCenter)
51 | self.fileNameLabel.setObjectName("fileNameLabel")
52 | self.gridLayout.addWidget(self.fileNameLabel, 0, 1, 1, 1)
53 |
54 | self.retranslateUi(Form)
55 | QtCore.QMetaObject.connectSlotsByName(Form)
56 |
57 | def retranslateUi(self, Form):
58 | Form.setWindowTitle(QtWidgets.QApplication.translate("Form", "Form", None, -1))
59 | self.loadBtn.setText(QtWidgets.QApplication.translate("Form", "Load..", None, -1))
60 | self.saveBtn.setText(QtWidgets.QApplication.translate("Form", "Save", None, -1))
61 | self.saveAsBtn.setText(QtWidgets.QApplication.translate("Form", "As..", None, -1))
62 | self.reloadBtn.setText(QtWidgets.QApplication.translate("Form", "Reload Libs", None, -1))
63 | self.showChartBtn.setText(QtWidgets.QApplication.translate("Form", "Flowchart", None, -1))
64 |
65 | from ..widgets.FeedbackButton import FeedbackButton
66 | from ..widgets.TreeWidget import TreeWidget
67 |
--------------------------------------------------------------------------------
/imodqgis/dependencies/pyqtgraph_0_12_3/opengl/items/GLGradientLegendItem.py:
--------------------------------------------------------------------------------
1 | from ... Qt import QtCore, QtGui
2 | from ... import functions as fn
3 | from ... colormap import ColorMap
4 | from ..GLGraphicsItem import GLGraphicsItem
5 |
6 | __all__ = ['GLGradientLegendItem']
7 |
8 | class GLGradientLegendItem(GLGraphicsItem):
9 | """
10 | Displays legend colorbar on the screen.
11 | """
12 |
13 | def __init__(self, **kwds):
14 | """
15 | Arguments:
16 | pos: position of the colorbar on the screen, from the top left corner, in pixels
17 | size: size of the colorbar without the text, in pixels
18 | gradient: a pg.ColorMap used to color the colorbar
19 | labels: a dict of "text":value to display next to the colorbar.
20 | The value corresponds to a position in the gradient from 0 to 1.
21 | fontColor: sets the color of the texts. Accepts any single argument accepted by
22 | :func:`~pyqtgraph.mkColor`
23 | #Todo:
24 | size as percentage
25 | legend title
26 | """
27 | GLGraphicsItem.__init__(self)
28 | glopts = kwds.pop("glOptions", "additive")
29 | self.setGLOptions(glopts)
30 | self.pos = (10, 10)
31 | self.size = (10, 100)
32 | self.fontColor = QtGui.QColor(QtCore.Qt.GlobalColor.white)
33 | # setup a default trivial gradient
34 | stops = (0.0, 1.0)
35 | self.gradient = ColorMap(pos=stops, color=(0.0, 1.0))
36 | self._gradient = None
37 | self.labels = {str(x) : x for x in stops}
38 | self.setData(**kwds)
39 |
40 | def setData(self, **kwds):
41 | args = ["size", "pos", "gradient", "labels", "fontColor"]
42 | for k in kwds.keys():
43 | if k not in args:
44 | raise Exception(
45 | "Invalid keyword argument: %s (allowed arguments are %s)"
46 | % (k, str(args))
47 | )
48 |
49 | self.antialias = False
50 |
51 | for key in kwds:
52 | value = kwds[key]
53 | if key == 'fontColor':
54 | value = fn.mkColor(value)
55 | elif key == 'gradient':
56 | self._gradient = None
57 | setattr(self, key, value)
58 |
59 | ##todo: add title
60 | ##todo: take more gradient types
61 | self.update()
62 |
63 | def paint(self):
64 | self.setupGLState()
65 |
66 | if self._gradient is None:
67 | self._gradient = self.gradient.getGradient()
68 |
69 | barRect = QtCore.QRectF(self.pos[0], self.pos[1], self.size[0], self.size[1])
70 | self._gradient.setStart(barRect.bottomLeft())
71 | self._gradient.setFinalStop(barRect.topLeft())
72 |
73 | painter = QtGui.QPainter(self.view())
74 | painter.fillRect(barRect, self._gradient)
75 | painter.setPen(self.fontColor)
76 | for labelText, labelPosition in self.labels.items():
77 | ## todo: draw ticks, position text properly
78 | x = 1.1 * self.size[0] + self.pos[0]
79 | y = self.size[1] - labelPosition * self.size[1] + self.pos[1] + 8
80 | ##todo: fonts
81 | painter.drawText(QtCore.QPointF(x, y), labelText)
82 | painter.end()
83 |
84 |
--------------------------------------------------------------------------------
/imodqgis/icons/enabling-delta-life.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------