├── .gitignore
├── LICENSE
├── Makefile
├── README.md
├── __init__.py
├── apicompat
├── __init__.py
├── qgiscoreqgis.py
├── qgisutilsqgis.py
├── qgsgeometry.py
├── qgsmaplayer.py
├── qgspointxy.py
├── qgsproject.py
└── qgswkbtypes.py
├── dxfwrite
├── __init__.py
├── acadctb.py
├── algebra
│ ├── __init__.py
│ ├── base.py
│ ├── bezier.py
│ ├── circle.py
│ ├── clothoid.py
│ ├── cspline.py
│ └── ray.py
├── allplancfg.py
├── base.py
├── const.py
├── curves.py
├── dimlines.py
├── drawing.py
├── engine.py
├── entities.py
├── hdrvars.py
├── helpers.py
├── htmlcolors.py
├── insert2.py
├── mixins.py
├── mtext.py
├── rect.py
├── sections.py
├── std.py
├── table.py
├── tableentries.py
├── tables.py
├── ucs.py
├── util.py
├── vector2d.py
└── vector3d.py
├── i18n
├── profiletool.pro
├── profiletool_de.qm
└── profiletool_de.ts
├── icons
└── profileIcon.png
├── metadata.txt
├── profile_points
└── profile_points.qml
├── profileplugin.py
├── pyqtgraph
├── GraphicsScene
│ ├── GraphicsScene.py
│ ├── __init__.py
│ ├── exportDialog.py
│ ├── exportDialogTemplate.ui
│ ├── exportDialogTemplate_generic.py
│ └── mouseEvents.py
├── PlotData.py
├── Point.py
├── Qt
│ ├── QtCore
│ │ ├── __init__.py
│ │ └── __init__.pyi
│ ├── QtGui
│ │ ├── __init__.py
│ │ └── __init__.pyi
│ ├── QtSvg.pyi
│ ├── QtTest.pyi
│ ├── QtWidgets
│ │ ├── __init__.py
│ │ └── __init__.pyi
│ ├── __init__.py
│ ├── __init__.pyi
│ ├── compat
│ │ └── __init__.py
│ └── internals.py
├── SRTTransform.py
├── SRTTransform3D.py
├── SignalProxy.py
├── ThreadsafeTimer.py
├── Transform3D.py
├── Vector.py
├── WidgetGroup.py
├── __init__.py
├── canvas
│ ├── Canvas.py
│ ├── CanvasItem.py
│ ├── CanvasManager.py
│ ├── CanvasTemplate.ui
│ ├── CanvasTemplate_generic.py
│ ├── TransformGuiTemplate.ui
│ ├── TransformGuiTemplate_generic.py
│ └── __init__.py
├── colormap.py
├── colors
│ ├── __init__.py
│ ├── maps
│ │ ├── CC-BY license - applies to CET color map data.txt
│ │ ├── CC0 legal code - applies to virids, magma, plasma, inferno and cividis.txt
│ │ ├── CET-C1.csv
│ │ ├── CET-C1s.csv
│ │ ├── CET-C2.csv
│ │ ├── CET-C2s.csv
│ │ ├── CET-C3.csv
│ │ ├── CET-C3s.csv
│ │ ├── CET-C4.csv
│ │ ├── CET-C4s.csv
│ │ ├── CET-C5.csv
│ │ ├── CET-C5s.csv
│ │ ├── CET-C6.csv
│ │ ├── CET-C6s.csv
│ │ ├── CET-C7.csv
│ │ ├── CET-C7s.csv
│ │ ├── CET-CBC1.csv
│ │ ├── CET-CBC2.csv
│ │ ├── CET-CBD1.csv
│ │ ├── CET-CBL1.csv
│ │ ├── CET-CBL2.csv
│ │ ├── CET-CBTC1.csv
│ │ ├── CET-CBTC2.csv
│ │ ├── CET-CBTD1.csv
│ │ ├── CET-CBTL1.csv
│ │ ├── CET-CBTL2.csv
│ │ ├── CET-D1.csv
│ │ ├── CET-D10.csv
│ │ ├── CET-D11.csv
│ │ ├── CET-D12.csv
│ │ ├── CET-D13.csv
│ │ ├── CET-D1A.csv
│ │ ├── CET-D2.csv
│ │ ├── CET-D3.csv
│ │ ├── CET-D4.csv
│ │ ├── CET-D6.csv
│ │ ├── CET-D7.csv
│ │ ├── CET-D8.csv
│ │ ├── CET-D9.csv
│ │ ├── CET-I1.csv
│ │ ├── CET-I2.csv
│ │ ├── CET-I3.csv
│ │ ├── CET-L1.csv
│ │ ├── CET-L10.csv
│ │ ├── CET-L11.csv
│ │ ├── CET-L12.csv
│ │ ├── CET-L13.csv
│ │ ├── CET-L14.csv
│ │ ├── CET-L15.csv
│ │ ├── CET-L16.csv
│ │ ├── CET-L17.csv
│ │ ├── CET-L18.csv
│ │ ├── CET-L19.csv
│ │ ├── CET-L2.csv
│ │ ├── CET-L3.csv
│ │ ├── CET-L4.csv
│ │ ├── CET-L5.csv
│ │ ├── CET-L6.csv
│ │ ├── CET-L7.csv
│ │ ├── CET-L8.csv
│ │ ├── CET-L9.csv
│ │ ├── CET-R1.csv
│ │ ├── CET-R2.csv
│ │ ├── CET-R3.csv
│ │ ├── CET-R4.csv
│ │ ├── PAL-relaxed.hex
│ │ ├── PAL-relaxed_bright.hex
│ │ ├── cividis.csv
│ │ ├── inferno.csv
│ │ ├── magma.csv
│ │ ├── plasma.csv
│ │ ├── turbo.csv
│ │ └── viridis.csv
│ └── palette.py
├── configfile.py
├── console
│ ├── CmdInput.py
│ ├── Console.py
│ ├── __init__.py
│ ├── exception_widget.py
│ ├── repl_widget.py
│ └── stackwidget.py
├── debug.py
├── dockarea
│ ├── Container.py
│ ├── Dock.py
│ ├── DockArea.py
│ ├── DockDrop.py
│ └── __init__.py
├── examples
│ ├── Arrow.py
│ ├── AxisItem_label_overlap.py
│ ├── BarGraphItem.py
│ ├── CLIexample.py
│ ├── ColorBarItem.py
│ ├── ColorButton.py
│ ├── ColorGradientPlots.py
│ ├── ConsoleWidget.py
│ ├── CustomGraphItem.py
│ ├── DataSlicing.py
│ ├── DataTreeWidget.py
│ ├── DateAxisItem.py
│ ├── DateAxisItem_QtDesigner.py
│ ├── DateAxisItem_QtDesigner.ui
│ ├── DiffTreeWidget.py
│ ├── Draw.py
│ ├── ErrorBarItem.py
│ ├── ExampleApp.py
│ ├── FillBetweenItem.py
│ ├── Flowchart.py
│ ├── FlowchartCustomNode.py
│ ├── GLBarGraphItem.py
│ ├── GLGradientLegendItem.py
│ ├── GLGraphItem.py
│ ├── GLImageItem.py
│ ├── GLIsosurface.py
│ ├── GLLinePlotItem.py
│ ├── GLMeshItem.py
│ ├── GLPainterItem.py
│ ├── GLScatterPlotItem.py
│ ├── GLSurfacePlot.py
│ ├── GLTextItem.py
│ ├── GLViewWidget.py
│ ├── GLVolumeItem.py
│ ├── GLshaders.py
│ ├── GradientEditor.py
│ ├── GradientWidget.py
│ ├── GraphItem.py
│ ├── GraphicsLayout.py
│ ├── GraphicsScene.py
│ ├── HistogramLUT.py
│ ├── ImageItem.py
│ ├── ImageView.py
│ ├── InfiniteLine.py
│ ├── InteractiveParameter.py
│ ├── JoystickButton.py
│ ├── Legend.py
│ ├── LogPlotTest.py
│ ├── MatrixDisplayExample.py
│ ├── MouseSelection.py
│ ├── MultiDataPlot.py
│ ├── MultiPlotSpeedTest.py
│ ├── MultiplePlotAxes.py
│ ├── NonUniformImage.py
│ ├── PColorMeshItem.py
│ ├── PanningPlot.py
│ ├── PlotAutoRange.py
│ ├── PlotSpeedTest.py
│ ├── PlotWidget.py
│ ├── Plotting.py
│ ├── ProgressDialog.py
│ ├── ROIExamples.py
│ ├── ROItypes.py
│ ├── RemoteGraphicsView.py
│ ├── RemoteSpeedTest.py
│ ├── RunExampleApp.py
│ ├── ScaleBar.py
│ ├── ScatterPlot.py
│ ├── ScatterPlotSpeedTest.py
│ ├── ScatterPlotWidget.py
│ ├── SimplePlot.py
│ ├── SpinBox.py
│ ├── Symbols.py
│ ├── TableWidget.py
│ ├── TreeWidget.py
│ ├── VideoSpeedTest.py
│ ├── VideoTemplate.ui
│ ├── VideoTemplate_generic.py
│ ├── ViewBox.py
│ ├── ViewBoxFeatures.py
│ ├── ViewLimits.py
│ ├── __init__.py
│ ├── __main__.py
│ ├── _buildParamTypes.py
│ ├── _paramtreecfg.py
│ ├── beeswarm.py
│ ├── colorMaps.py
│ ├── colorMapsLinearized.py
│ ├── console_exception_inspection.py
│ ├── contextMenu.py
│ ├── crosshair.py
│ ├── customGraphicsItem.py
│ ├── customPlot.py
│ ├── cx_freeze
│ │ ├── plotTest.py
│ │ └── setup.py
│ ├── designerExample.py
│ ├── designerExample.ui
│ ├── dockarea.py
│ ├── exampleLoaderTemplate.ui
│ ├── exampleLoaderTemplate_generic.py
│ ├── fractal.py
│ ├── glow.py
│ ├── hdf5.py
│ ├── histogram.py
│ ├── imageAnalysis.py
│ ├── infiniteline_performance.py
│ ├── isocurve.py
│ ├── jupyter_console_example.py
│ ├── linkedViews.py
│ ├── logAxis.py
│ ├── multiplePlotSpeedTest.py
│ ├── multiprocess.py
│ ├── notebooks
│ │ ├── ImageAnalysis.ipynb
│ │ ├── PColorMeshItem.ipynb
│ │ ├── Plotting.ipynb
│ │ ├── ROIExamples.ipynb
│ │ ├── ScatterPlot.ipynb
│ │ └── simple.ipynb
│ ├── optics
│ │ ├── __init__.py
│ │ ├── pyoptic.py
│ │ └── schott_glasses.csv.gz
│ ├── optics_demos.py
│ ├── parallelize.py
│ ├── parametertree.py
│ ├── py2exe
│ │ ├── plotTest.py
│ │ └── setup.py
│ ├── relativity
│ │ ├── __init__.py
│ │ ├── presets
│ │ │ ├── Grid Expansion.cfg
│ │ │ ├── Twin Paradox (grid).cfg
│ │ │ └── Twin Paradox.cfg
│ │ └── relativity.py
│ ├── relativity_demo.py
│ ├── scrollingPlots.py
│ ├── syntax.py
│ ├── template.py
│ ├── test_examples.py
│ ├── text.py
│ ├── utils.py
│ ├── verlet_chain
│ │ ├── __init__.py
│ │ ├── chain.py
│ │ ├── make
│ │ ├── relax.c
│ │ └── relax.py
│ └── verlet_chain_demo.py
├── exceptionHandling.py
├── exporters
│ ├── CSVExporter.py
│ ├── Exporter.py
│ ├── HDF5Exporter.py
│ ├── ImageExporter.py
│ ├── Matplotlib.py
│ ├── PrintExporter.py
│ ├── SVGExporter.py
│ └── __init__.py
├── flowchart
│ ├── Flowchart.py
│ ├── FlowchartCtrlTemplate.ui
│ ├── FlowchartCtrlTemplate_generic.py
│ ├── FlowchartGraphicsView.py
│ ├── Node.py
│ ├── NodeLibrary.py
│ ├── Terminal.py
│ ├── __init__.py
│ └── library
│ │ ├── Data.py
│ │ ├── Display.py
│ │ ├── Filters.py
│ │ ├── Operators.py
│ │ ├── __init__.py
│ │ ├── common.py
│ │ └── functions.py
├── frozenSupport.py
├── functions.py
├── functions_numba.py
├── functions_qimage.py
├── graphicsItems
│ ├── ArrowItem.py
│ ├── AxisItem.py
│ ├── BarGraphItem.py
│ ├── ButtonItem.py
│ ├── ColorBarItem.py
│ ├── CurvePoint.py
│ ├── DateAxisItem.py
│ ├── ErrorBarItem.py
│ ├── FillBetweenItem.py
│ ├── GradientEditorItem.py
│ ├── GradientLegend.py
│ ├── GradientPresets.py
│ ├── GraphItem.py
│ ├── GraphicsItem.py
│ ├── GraphicsLayout.py
│ ├── GraphicsObject.py
│ ├── GraphicsWidget.py
│ ├── GraphicsWidgetAnchor.py
│ ├── GridItem.py
│ ├── HistogramLUTItem.py
│ ├── ImageItem.py
│ ├── InfiniteLine.py
│ ├── IsocurveItem.py
│ ├── ItemGroup.py
│ ├── LabelItem.py
│ ├── LegendItem.py
│ ├── LinearRegionItem.py
│ ├── MultiPlotItem.py
│ ├── NonUniformImage.py
│ ├── PColorMeshItem.py
│ ├── PlotCurveItem.py
│ ├── PlotDataItem.py
│ ├── PlotItem
│ │ ├── PlotItem.py
│ │ ├── __init__.py
│ │ ├── plotConfigTemplate.ui
│ │ └── plotConfigTemplate_generic.py
│ ├── ROI.py
│ ├── ScaleBar.py
│ ├── ScatterPlotItem.py
│ ├── TargetItem.py
│ ├── TextItem.py
│ ├── UIGraphicsItem.py
│ ├── VTickGroup.py
│ ├── ViewBox
│ │ ├── ViewBox.py
│ │ ├── ViewBoxMenu.py
│ │ ├── __init__.py
│ │ ├── axisCtrlTemplate.ui
│ │ └── axisCtrlTemplate_generic.py
│ └── __init__.py
├── icons
│ ├── __init__.py
│ ├── auto.png
│ ├── ctrl.png
│ ├── default.png
│ ├── icons.svg
│ ├── invisibleEye.svg
│ ├── lock.png
│ └── peegee
│ │ ├── peegee.svg
│ │ ├── peegee_128px.png
│ │ ├── peegee_128px@2x.png
│ │ ├── peegee_192px.png
│ │ ├── peegee_256px.png
│ │ ├── peegee_256px@2x.png
│ │ ├── peegee_512px.png
│ │ └── peegee_512px@2x.png
├── imageview
│ ├── ImageView.py
│ ├── ImageViewTemplate.ui
│ ├── ImageViewTemplate_generic.py
│ └── __init__.py
├── jupyter
│ ├── GraphicsView.py
│ └── __init__.py
├── metaarray
│ ├── MetaArray.py
│ ├── __init__.py
│ ├── license.txt
│ └── readMeta.m
├── multiprocess
│ ├── __init__.py
│ ├── bootstrap.py
│ ├── parallelizer.py
│ ├── processes.py
│ └── remoteproxy.py
├── opengl
│ ├── GLGraphicsItem.py
│ ├── GLViewWidget.py
│ ├── MeshData.py
│ ├── __init__.py
│ ├── items
│ │ ├── GLAxisItem.py
│ │ ├── GLBarGraphItem.py
│ │ ├── GLBoxItem.py
│ │ ├── GLGradientLegendItem.py
│ │ ├── GLGraphItem.py
│ │ ├── GLGridItem.py
│ │ ├── GLImageItem.py
│ │ ├── GLLinePlotItem.py
│ │ ├── GLMeshItem.py
│ │ ├── GLScatterPlotItem.py
│ │ ├── GLSurfacePlotItem.py
│ │ ├── GLTextItem.py
│ │ ├── GLVolumeItem.py
│ │ └── __init__.py
│ └── shaders.py
├── parametertree
│ ├── Parameter.py
│ ├── ParameterItem.py
│ ├── ParameterSystem.py
│ ├── ParameterTree.py
│ ├── SystemSolver.py
│ ├── __init__.py
│ ├── interactive.py
│ └── parameterTypes
│ │ ├── __init__.py
│ │ ├── action.py
│ │ ├── actiongroup.py
│ │ ├── basetypes.py
│ │ ├── bool.py
│ │ ├── calendar.py
│ │ ├── checklist.py
│ │ ├── color.py
│ │ ├── colormap.py
│ │ ├── colormaplut.py
│ │ ├── file.py
│ │ ├── font.py
│ │ ├── list.py
│ │ ├── numeric.py
│ │ ├── pen.py
│ │ ├── progress.py
│ │ ├── qtenum.py
│ │ ├── slider.py
│ │ ├── str.py
│ │ └── text.py
├── reload.py
├── units.py
├── util
│ ├── __init__.py
│ ├── colorama
│ │ ├── LICENSE.txt
│ │ ├── README.txt
│ │ ├── __init__.py
│ │ ├── win32.py
│ │ └── winterm.py
│ ├── cprint.py
│ ├── cupy_helper.py
│ ├── garbage_collector.py
│ ├── get_resolution.py
│ ├── glinfo.py
│ ├── mutex.py
│ └── numba_helper.py
└── widgets
│ ├── BusyCursor.py
│ ├── CheckTable.py
│ ├── ColorButton.py
│ ├── ColorMapButton.py
│ ├── ColorMapMenu.py
│ ├── ColorMapWidget.py
│ ├── ComboBox.py
│ ├── DataFilterWidget.py
│ ├── DataTreeWidget.py
│ ├── DiffTreeWidget.py
│ ├── FeedbackButton.py
│ ├── FileDialog.py
│ ├── GradientWidget.py
│ ├── GraphicsLayoutWidget.py
│ ├── GraphicsView.py
│ ├── GroupBox.py
│ ├── HistogramLUTWidget.py
│ ├── JoystickButton.py
│ ├── LayoutWidget.py
│ ├── MatplotlibWidget.py
│ ├── MultiPlotWidget.py
│ ├── PathButton.py
│ ├── PenPreviewLabel.py
│ ├── PlotWidget.py
│ ├── ProgressDialog.py
│ ├── RawImageWidget.py
│ ├── RemoteGraphicsView.py
│ ├── ScatterPlotWidget.py
│ ├── SpinBox.py
│ ├── TableWidget.py
│ ├── TreeWidget.py
│ ├── ValueLabel.py
│ ├── VerticalLabel.py
│ └── __init__.py
├── resources.py
├── resources.qrc
├── tests
└── test_dist.py
├── tools
├── __init__.py
├── dataReaderTool.py
├── plottingtool.py
├── profilers.py
├── profiletool_core.py
├── ptmaptool.py
├── selectlinetool.py
├── tableviewtool.py
└── utils.py
└── ui
├── __init__.py
├── about.ui
├── dlgabout.py
├── profiletool.ui
└── ptdockwidget.py
/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 | __pycache__
3 | .venv
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Profile Tool 
2 |
3 | This tool plots profile lines from raster layers or point vector layer with elevation field.
4 | Supports multiple lines as well as graph export to svg, pdf, png or csv file.
5 | Supports 3D polyline export to dxf.
6 |
7 | **Authors:** Borys Jurgiel - Patrice Verchere - Etienne Tourigny - Javier Becerra
8 |
9 | **Current mantainer:** PANOimagen S.L.
10 |
11 | **email:** *javier@panoimagen.com*
12 |
13 | Fork of etiennesky/profiletool QGis plugin. We add support to select all
14 | the features in a Layer and visualization of slope profile in addition to height profile.
15 | This work has been partially funded by the C.A. La Rioja
16 |
17 | **Profile Tool license:**
18 |
19 | This program is free software: you can redistribute it and/or modify
20 | it under the terms of the GNU General Public License as published by
21 | the Free Software Foundation, either version 2 of the License, or
22 | (at your option) any later version.
23 |
24 | This program is distributed in the hope that it will be useful,
25 | but WITHOUT ANY WARRANTY; without even the implied warranty of
26 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 | GNU General Public License for more details.
28 |
29 | You should have received a copy of the GNU General Public License
30 | along with this program. If not, see .
31 |
--------------------------------------------------------------------------------
/__init__.py:
--------------------------------------------------------------------------------
1 | # -----------------------------------------------------------
2 | #
3 | # Profile
4 | # Copyright (C) 2008 Borys Jurgiel
5 | # Copyright (C) 2012 Patrice Verchere
6 | # -----------------------------------------------------------
7 | #
8 | # licensed under the terms of GNU GPL 2
9 | #
10 | # This program is free software; you can redistribute it and/or modify
11 | # it under the terms of the GNU General Public License as published by
12 | # the Free Software Foundation; either version 2 of the License, or
13 | # (at your option) any later version.
14 | #
15 | # This program is distributed in the hope that it will be useful,
16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | # GNU General Public License for more details.
19 | #
20 | # You should have received a copy of the GNU General Public License along
21 | # with this program; if not, write to the Free Software Foundation, Inc.,
22 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 | #
24 | # ---------------------------------------------------------------------
25 | from . import apicompat
26 |
27 |
28 | def classFactory(iface):
29 | from .profileplugin import ProfilePlugin
30 |
31 | return ProfilePlugin(iface)
32 |
--------------------------------------------------------------------------------
/apicompat/__init__.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 | import qgis.utils
3 |
4 | # Based on qgis2compat plugin from opengis.ch
5 |
6 | # Dealing with a QGIS 2 version, monkey patch some things
7 | # also guard with initialized so monkeypatching happens only once
8 | initialized = False
9 | if not initialized and hasattr(qgis.utils, "QGis"):
10 | initialized = True
11 | # log('Running apicompat on QGIS version %s' % QGIS_VERSION)
12 |
13 | # Here import all the compatibility fixes modules
14 | import qgiscoreqgis
15 | import qgisutilsqgis
16 | import qgsgeometry
17 | import qgsmaplayer
18 | import qgspointxy
19 | import qgsproject
20 | import qgswkbtypes
21 |
--------------------------------------------------------------------------------
/apicompat/qgiscoreqgis.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 |
3 | import qgis.core
4 |
5 | # QGis in QGIS version 2 was renamed to Qgis in QGIS version 3
6 |
7 | qgis.core.Qgis = qgis.core.QGis
8 |
--------------------------------------------------------------------------------
/apicompat/qgisutilsqgis.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 |
3 | import qgis.utils
4 |
5 | # QGis in QGIS version 2 was renamed to Qgis in QGIS version 3
6 |
7 | qgis.utils.Qgis = qgis.utils.QGis
8 |
--------------------------------------------------------------------------------
/apicompat/qgsgeometry.py:
--------------------------------------------------------------------------------
1 | import qgis.core
2 |
3 | # fromPoint() was renamed to fromPointXY() in QGis3
4 | # The same with the other QgsGeometries -- from [geometry] in QGIS 2 to [geometry]XY in QGIS 3
5 | qgis.core.QgsGeometry.fromPointXY = qgis.core.QgsGeometry.fromPoint
6 | qgis.core.QgsGeometry.fromPolylineXY = qgis.core.QgsGeometry.fromPolyline
7 | qgis.core.QgsGeometry.fromMultiPolylineXY = qgis.core.QgsGeometry.fromMultiPolyline
8 |
--------------------------------------------------------------------------------
/apicompat/qgsmaplayer.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 |
3 | import qgis.core
4 |
5 |
6 | # log('Monkeypatching QgsPointXY')
7 | # hasGeometryType has been replaced by isSpatial in QGis 3.0 api
8 | def isSpatial(self):
9 | # Will raise AttributeError when used with layers that are not
10 | # QgsVectorLayer, but that is the expected behaviour in Qgis 2.x
11 | return self.hasGeometryType()
12 |
13 |
14 | qgis.core.QgsMapLayer.isSpatial = isSpatial
15 | # MeshLayer is defined in QGis 3.x, should not appear in QGis 2.x
16 | qgis.core.QgsMapLayer.MeshLayer = 3
17 |
--------------------------------------------------------------------------------
/apicompat/qgspointxy.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 |
3 | import qgis.core
4 |
5 | # log('Monkeypatching QgsPointXY')
6 | # QgsPoint has been renamed to QgsPoint in QGis 3.0 api
7 | qgis.core.QgsPointXY = qgis.core.QgsPoint
8 |
--------------------------------------------------------------------------------
/apicompat/qgsproject.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 | """Monkey patching for QgsProject - QGis 3 compatibility in QGis 2.
3 |
4 | From qgis2compat plugin by opengis.ch
5 | """
6 | import qgis.core
7 | import qgis.utils
8 | from PyQt4.QtCore import QFileInfo
9 |
10 | # from qgis2compat import log
11 |
12 |
13 | # log('Monkeypatching QgsProject')
14 |
15 |
16 | def visibilityPresetCollection(self):
17 | return self.visibilityPresetCollection()
18 |
19 |
20 | qgis.core.QgsProject.mapThemeCollection = visibilityPresetCollection
21 |
22 |
23 | def mapLayers(self):
24 | return qgis.core.QgsMapLayerRegistry.instance().mapLayers()
25 |
26 |
27 | qgis.core.QgsProject.mapLayers = mapLayers
28 |
29 |
30 | def mapLayersByName(self, layerName):
31 | return qgis.core.QgsMapLayerRegistry.instance().mapLayersByName(layerName)
32 |
33 |
34 | qgis.core.QgsProject.mapLayersByName = mapLayersByName
35 |
36 |
37 | def removeMapLayer(self, layer):
38 | return qgis.core.QgsMapLayerRegistry.instance().removeMapLayer(layer)
39 |
40 |
41 | qgis.core.QgsProject.removeMapLayer = removeMapLayer
42 |
43 |
44 | def addMapLayer(self, mapLayer, addToLegend=True, takeOwnership=True):
45 | return qgis.core.QgsMapLayerRegistry.instance().addMapLayer(mapLayer, addToLegend)
46 |
47 |
48 | qgis.core.QgsProject.addMapLayer = addMapLayer
49 |
50 |
51 | def mapLayer(self, layerId):
52 | return qgis.core.QgsMapLayerRegistry.instance().mapLayer(layerId)
53 |
54 |
55 | qgis.core.QgsProject.mapLayer = mapLayer
56 |
57 | original_QgsProject_write = qgis.core.QgsProject.write
58 |
59 |
60 | def write(self, filename):
61 | return original_QgsProject_write(self, QFileInfo(filename))
62 |
63 |
64 | qgis.core.QgsProject.write = write
65 |
66 | original_QgsProject_read = qgis.core.QgsProject.read
67 |
68 |
69 | def read(self, param=None):
70 | if param:
71 | try:
72 | return original_QgsProject_read(self, QFileInfo(param))
73 | except TypeError:
74 | return original_QgsProject_read(self, param)
75 | else:
76 | return original_QgsProject_read(self)
77 |
78 |
79 | qgis.core.QgsProject.read = read
80 |
--------------------------------------------------------------------------------
/apicompat/qgswkbtypes.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | import qgis.core
4 |
5 |
6 | class QgsWkbTypes:
7 |
8 | Point = qgis.core.QGis.WKBPoint
9 | # 2- qgis.core.QGis.WKBPoint -> 3- qgis.core.QgsWkbTypes.Point
10 | LineString = qgis.core.QGis.WKBLineString
11 | # 2- qgis.core.QGis.WKBLineString -> 3- qgis.core.QgsWkbTypes.MultiLineString
12 | # qgis.core.QGis.WKBMultiLineString = qgis.core.QgsWkbTypes.MultiLineString
13 | MultiLineString = qgis.core.QGis.WKBMultiLineString
14 | # 2- qgis.core.QGis.WKBMultiLineString -> 3- qgis.core.QgsWkbTypes.MultiLineString
15 | # qgis.core.QGis.WKBPolygon = qgis.core.QgsWkbTypes.Polygon
16 | Polygon = qgis.core.QGis.WKBPolygon
17 |
18 | LineGeometry = qgis.core.QGis.Line
19 | PointGeometry = qgis.core.QGis.Point
20 |
21 |
22 | qgis.core.QgsWkbTypes = QgsWkbTypes
23 |
--------------------------------------------------------------------------------
/dxfwrite/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #coding:utf-8
3 | # Purpose: write DXF R12 files
4 | # Based on the ideas of Stani Michiels(Stani) sdxf.py and
5 | # Remigiusz Fiedler(migius) dxflibrary133.py
6 | # Created: 14.03.2010
7 | # Copyright (C) 2010, Manfred Moitzi
8 | # License: MIT License
9 |
10 | from .const import *
11 | from .base import *
12 | from .engine import DXFEngine
13 |
14 |
15 | version = (1, 2, 1)
16 | VERSION = "%d.%d.%d" % version
17 |
18 | CYEAR = "2010-2017"
19 | AUTHOR_NAME = "Manfred Moitzi"
20 | AUTHOR_EMAIL = "mozman@gmx.at"
21 | LICENSE = "MIT License"
22 |
23 | __author__ = "mozman "
24 | __doc__ = """A Python library to create DXF R12 drawings.
25 |
26 | Copyright %s
27 | Version %s
28 | License %s
29 |
30 | IMPLEMENTED R12 WRITING:
31 | - POINT
32 | - LINE
33 | - CIRCLE
34 | - ARC
35 | - TEXT
36 | - SOLID
37 | - TRACE
38 | - FACE3D
39 | - POLYLINE (POLYMESH, POLYFACE)
40 | - BLOCK
41 | - INSERT
42 | - ATTDEF
43 | - ATTRIB
44 |
45 | NOT IMPLEMENTED:
46 | - DIMENSION (use LinearDimension, AngularDimension, ArcDimension or
47 | RadialDimension)
48 | """ % (AUTHOR_NAME, VERSION, LICENSE,)
49 |
--------------------------------------------------------------------------------
/dxfwrite/algebra/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #coding:utf-8
3 | # Purpose: algebra lib to calculate with geometric forms
4 | # Created: 27.03.2010
5 | # License: MIT License
6 |
7 |
8 |
9 | import math
10 |
11 | from .base import *
12 | from .ray import Ray2D, ParallelRaysError
13 | from .clothoid import Clothoid
14 | from .circle import Circle
15 | from .bezier import CubicBezierCurve
16 | from .cspline import CubicSpline
17 |
18 | __version__ = "v0.2 - 2010.03.27"
19 | __author__ = "mozman "
20 | __license__ = "MIT License"
21 |
22 | __doc__ = """A library to calculate with geometric forms.
23 |
24 | Copyright %s
25 | Version %s
26 | License %s
27 | """ % (__author__,__version__,__license__,)
28 |
29 | # --------------------------------------------------------------------------
30 | # algebra: copyright (C) 2010 by Manfred Moitzi (mozman)
31 | # --------------------------------------------------------------------------
32 | # ***** BEGIN GPL LICENSE BLOCK *****
33 | #
34 | # This program is free software; you can redistribute it and/or
35 | # modify it under the terms of the GNU General Public License
36 | # as published by the Free Software Foundation; either version 2
37 | # of the License, or (at your option) any later version.
38 | #
39 | # This program is distributed in the hope that it will be useful,
40 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
41 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
42 | # GNU General Public License for more details.
43 | #
44 | # You should have received a copy of the GNU General Public License
45 | # along with this program; if not, write to the Free Software Foundation,
46 | # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
47 | #
48 | # ***** END GPL LICENCE BLOCK *****
49 |
--------------------------------------------------------------------------------
/dxfwrite/algebra/base.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #coding:utf-8
3 | # Purpose:
4 | # Created: 27.03.2010
5 |
6 | __author__ = "mozman "
7 |
8 | import math
9 |
10 | HALF_PI = math.pi / 2.
11 | THREE_PI_HALF = 1.5 * math.pi
12 | DOUBLE_PI = math.pi * 2.
13 |
14 | def rotate_2d(point, angle):
15 | """ rotate point around origin point about angle """
16 | x = point[0] * math.cos(angle) - point[1] * math.sin(angle)
17 | y = point[1] * math.cos(angle) + point[0] * math.sin(angle)
18 | return (x, y)
19 |
20 | def equals_almost(v1, v2, places=7):
21 | """compare two float values
22 | places: significant decimal places
23 | """
24 | return round(v1, places) == round(v2, places)
25 |
26 | def normalize_angle(angle):
27 | """ return an angle between 0 and 2*pi """
28 | angle = math.fmod(angle, DOUBLE_PI)
29 | if angle < 0:
30 | angle += DOUBLE_PI
31 | return angle
32 |
33 | def is_vertical_angle(angle, places=7):
34 | """ returns True for 1/2pi and 3/2pi """
35 | angle = normalize_angle(angle)
36 | return (equals_almost(angle, HALF_PI, places) or
37 | equals_almost(angle, THREE_PI_HALF, places))
38 |
39 | def get_angle(p1, p2):
40 | """calc angle between the line p1-p2 and the x-axis
41 | input: points as tuples
42 | result: angle in radians
43 | """
44 | dx = p2[0] - p1[0]
45 | dy = p2[1] - p1[1]
46 | return math.atan2(dy, dx)
47 |
48 | def right_of_line(point, p1, p2):
49 | """ True if the point self is right of the line p1 -> p2
50 | """
51 | return not left_of_line(point, p1, p2)
52 |
53 | def left_of_line(point, p1, p2):
54 | """ True if the point self is left of the line p1 -> p2
55 | """
56 | # check if a and b are on the same vertical line
57 | if p1[0] == p2[0]:
58 | # compute # on which site of the line self should be
59 | should_be_left = p1[1] < p2[1]
60 | if should_be_left:
61 | return point[0] < p1[0]
62 | else:
63 | return point[0] > p1[0]
64 | else:
65 | # get pitch of line
66 | pitch = (p2[1] - p1[1]) / (p2[0] - p1[0])
67 |
68 | # get y-value at c's x-position
69 | y = pitch * (point[0] - p1[0]) + p1[1]
70 |
71 | # compute if point should be above or below the line
72 | should_be_above = p1[0] < p2[0]
73 | if should_be_above :
74 | return point[1] > y
75 | else:
76 | return point[1] < y
77 |
--------------------------------------------------------------------------------
/dxfwrite/algebra/clothoid.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #coding:utf-8
3 | # Purpose: 2d clothoid
4 | # module belongs to package: dxfwrite.py
5 | # Created: 26.03.2010
6 | # License: MIT License
7 |
8 | __author__ = "mozman "
9 |
10 | import sys
11 | if sys.version_info[0] > 2:
12 | xrange = range
13 |
14 | import math
15 |
16 | class Clothoid(object):
17 | """This object represents a clothoid (a.k.a. Euler spiral) for parameter
18 | . The curve always starts at the coordinate system origin = (0, 0).
19 | """
20 | def __init__(self, paramA=1.0):
21 | self.A = paramA # Clothiod Parameter A
22 | self.powersA = [paramA**power for power in xrange(19)]
23 | self.coords = {} # coordinates cache
24 |
25 | def get_radius(self, L):
26 | """Get radius of circle at distance ."""
27 | if L > 0.:
28 | return self.powersA[2] / L
29 | else :
30 | return 0. # radius = infinite
31 |
32 | def get_tau(self, L):
33 | """Get tangent angle at distance in radians."""
34 | return L**2 / (2. * self.powersA[2])
35 |
36 | def get_L(self, radius):
37 | """Get distance L from origin for ."""
38 | return self.powersA[2] / float(radius)
39 |
40 | def get_xy(self, L):
41 | """Get xy-coordinates of curve point at distance ."""
42 | def term(powerL, powerA, const):
43 | return L**powerL/(const * self.powersA[powerA])
44 | if L not in self.coords:
45 | y = term(3, 2, 6.) - term(7, 6, 336.) + term(11, 10, 42240.) - \
46 | term(15, 14, 9676800.) + term(19, 18, 3530096640.)
47 | x = L - term(5, 4, 40.) + term(9, 8, 3456.) - term(13, 12, 599040.) + \
48 | term(17, 16, 175472640.)
49 | self.coords[L] = (x, y)
50 | return self.coords[L]
51 |
52 | def approximate(self, length, segments):
53 | """Approximate curve of with line-segments.
54 |
55 | Generates +1 2D points (float, float).
56 | """
57 | delta_l = float(length) / float(segments)
58 | yield (0., 0.)
59 | for index in xrange(1, segments+1):
60 | yield self.get_xy(delta_l * index)
61 |
62 | def get_center(self, L):
63 | """Get center point of circle at point L."""
64 | x, y = self.get_xy(L)
65 | r = self.get_radius(L)
66 | tau = self.get_tau(L)
67 | xm = x - r * math.sin(tau)
68 | ym = y + r * math.cos(tau)
69 | return (xm, ym)
70 |
--------------------------------------------------------------------------------
/dxfwrite/helpers.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #coding:utf-8
3 | # Purpose: normalize dxf chunks
4 | # Created: 24.02.2011
5 | # Copyright (C) 2011, Manfred Moitzi
6 | # License: MIT License
7 |
8 | __author__ = "mozman "
9 |
10 |
11 | def normalize_dxf_chunk(dxfstr):
12 | def round_floats_but_not_ints(tag, places=7):
13 | try:
14 | return int(tag)
15 | except ValueError:
16 | pass
17 | try:
18 | value = float(tag)
19 | return round(value, places)
20 | except ValueError:
21 | return tag
22 |
23 | return [round_floats_but_not_ints(tag) for tag in dxfstr.split('\n')]
24 |
--------------------------------------------------------------------------------
/dxfwrite/mixins.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #coding:utf-8
3 | # Purpose: provide class mixins
4 | # Created: 11.12.11
5 | # Copyright (C) 2011, Manfred Moitzi
6 | # License: MIT License
7 |
8 | __author__ = "mozman "
9 |
10 |
11 | class SubscriptAttributes(object):
12 | def __getitem__(self, item):
13 | if hasattr(self, item):
14 | return getattr(self, item)
15 | else:
16 | raise KeyError(item)
17 |
18 | def __setitem__(self, key, value):
19 | if hasattr(self, key):
20 | setattr(self, key, value)
21 | else:
22 | raise KeyError(key)
23 |
24 | def __contains__(self, item):
25 | return hasattr(self, item)
26 |
--------------------------------------------------------------------------------
/dxfwrite/tables.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # coding:utf-8
3 | # Purpose: tables R12
4 | # module belongs to package: dxfwrite.py
5 | # Created: 09.02.2010
6 | # Copyright (C) 2010, Manfred Moitzi
7 | # License: MIT License
8 |
9 | __author__ = "mozman "
10 |
11 | __all__ = ['create_table']
12 |
13 | from .base import *
14 |
15 |
16 | def create_table(name):
17 | """ Table factory.
18 | """
19 | if name == 'VPORT':
20 | return Viewports()
21 | elif name in ['LTYPE', 'LAYER', 'STYLE', 'VIEW', 'APPID', 'UCS']:
22 | return _Table(name)
23 | else:
24 | raise ValueError("unknown table '%s'" % str(name))
25 |
26 |
27 | class _Table(object):
28 | """ Base table class.
29 | """
30 |
31 | def __init__(self, tablename):
32 | self.tablename = tablename
33 | self._entries = {} # use only add() for adding objects
34 |
35 | def __dxf__(self):
36 | return dxfstr(self.__dxftags__())
37 |
38 | def __dxftags__(self):
39 | return DXFList((
40 | DXFAtom('TABLE'),
41 | DXFName(self.tablename),
42 | DXFInt(len(self._entries)),
43 | DXFList(self._get_values()),
44 | DXFAtom('ENDTAB')
45 | ))
46 |
47 | def __contains__(self, name):
48 | return name in self._entries
49 |
50 | def __getitem__(self, name):
51 | """ Get table entry by `name` -> TableEntry.
52 | """
53 | return self._entries[name]
54 |
55 | def clear(self):
56 | self._entries.clear()
57 |
58 | def _get_values(self):
59 | return self._entries.values()
60 |
61 | def add(self, entry):
62 | """ Add a table entry.
63 | """
64 | self._entries[entry['name']] = entry
65 |
66 |
67 | class Viewports(_Table):
68 | def __init__(self):
69 | super(Viewports, self).__init__('VPORT')
70 | # because the VPORT-table can have multiple entries with the same name
71 | # use a list() instead of a dict().
72 | self._entries = []
73 |
74 | def __getitem__(self, name):
75 | """ Get all table entries `name`, because multiple entries are possible -> list
76 | """
77 | return [entry for entry in self._entries if entry['name'] == name]
78 |
79 | def _get_values(self):
80 | return self._entries
81 |
82 | def add(self, viewport):
83 | self._entries.append(viewport)
84 |
85 | def clear(self):
86 | self._entries = []
87 |
88 |
--------------------------------------------------------------------------------
/dxfwrite/util.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # coding:utf-8
3 | # Purpose: utility functions
4 | # module belongs to package dxfwrite
5 | # Created: 09.02.2010
6 | # Copyright (C) 2010, Manfred Moitzi
7 | # License: MIT License
8 |
9 | __author__ = "mozman "
10 |
11 | import sys
12 | PYTHON3 = sys.version_info[0] > 2
13 |
14 | if PYTHON3:
15 | from io import StringIO
16 | izip = zip
17 |
18 | def is_string(value):
19 | return isinstance(value, str)
20 |
21 | def to_unicode(value):
22 | return str(value)
23 |
24 | def to_string(value):
25 | if not isinstance(value, str):
26 | return str(value)
27 | else:
28 | escaped_value = value.encode("raw_unicode_escape")
29 | if b'\\u' in escaped_value:
30 | return str(escaped_value.replace(b'\\u', b'\\U+'), 'utf-8')
31 | else:
32 | return value
33 | else: # PYTHON2
34 | from itertools import izip
35 | from StringIO import StringIO
36 |
37 | def is_string(value):
38 | return isinstance(value, basestring)
39 |
40 | def to_unicode(value):
41 | return str(value).decode('utf-8')
42 |
43 | def to_string(value):
44 | if not isinstance(value, basestring):
45 | return str(value)
46 | else:
47 | escaped_value = value.encode("raw_unicode_escape")
48 | if '\\u' in escaped_value:
49 | return escaped_value.replace('\\u', '\\U+')
50 | else:
51 | return value
52 |
53 | # end of Python 2/3 adaption
54 |
55 |
56 | def int2hex(value):
57 | return hex(value)[2:].upper()
58 |
59 |
60 | def hex2int(string):
61 | return int(string, 16)
62 |
63 |
64 | def set_flag(value, bitmask, switch_on=True):
65 | if switch_on:
66 | return value | bitmask
67 | else:
68 | return value & ~bitmask
69 |
70 |
71 | def iterflatlist(alist):
72 | for element in alist:
73 | if hasattr(element, "__iter__") and not is_string(element):
74 | for item in iterflatlist(element):
75 | yield item
76 | else:
77 | yield element
78 |
--------------------------------------------------------------------------------
/dxfwrite/vector2d.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # coding:utf-8
3 | # Purpose: 2d vector math
4 | # module belongs to package dxfwrite
5 | # Created: 16.03.2010
6 | # Copyright (C) 2010, Manfred Moitzi
7 | # License: MIT License
8 | """
9 | 2d vector math module
10 | """
11 |
12 | __author__ = "mozman "
13 |
14 | from math import hypot, atan2, sin, cos
15 |
16 |
17 | def vector2d(vector):
18 | """ return a 2d vector """
19 | return (float(vector[0]), float(vector[1]))
20 |
21 |
22 | def vector2angle(vector):
23 | """ get angle of vector """
24 | return atan2(vector[1], vector[0])
25 |
26 |
27 | def angle2uv(angle):
28 | """ get unit_vector from angle """
29 | return (cos(angle), sin(angle))
30 |
31 |
32 | def magnitude(vector):
33 | """ length of a 2d vector """
34 | return hypot(vector[0], vector[1])
35 |
36 |
37 | def unit_vector(vector):
38 | """ 2d unit vector """
39 | return vdiv_scalar(vector, magnitude(vector))
40 |
41 |
42 | def normal_vector(vector):
43 | """ 2d perpendicular vector """
44 | return (-vector[1], vector[0])
45 |
46 |
47 | def distance(point1, point2):
48 | """ calc distance between two 2d points """
49 | return hypot(point1[0] - point2[0], point1[1] - point2[1])
50 |
51 |
52 | def midpoint(point1, point2):
53 | """ calc midpoint between point1 and point2 """
54 | return ((point1[0] + point2[0]) * .5, (point1[1] + point2[1]) * .5)
55 |
56 |
57 | def vsub(vector1, vector2):
58 | """ substract vectors """
59 | return (vector1[0] - vector2[0], vector1[1] - vector2[1])
60 |
61 |
62 | def vadd(vector1, vector2):
63 | """ add vectors """
64 | return (vector1[0] + vector2[0], vector1[1] + vector2[1])
65 |
66 |
67 | def vdiv_scalar(vector, scalar):
68 | """ div vectors """
69 | return (vector[0] / scalar, vector[1] / scalar)
70 |
71 |
72 | def vmul_scalar(vector, scalar):
73 | """ mul vector with scalar """
74 | return (vector[0] * scalar, vector[1] * scalar)
75 |
--------------------------------------------------------------------------------
/dxfwrite/vector3d.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # coding:utf-8
3 | # Created: 27.03.2010
4 | # Purpose: 3d vectormath
5 | # module belongs to package dxfwrite
6 | # Copyright (C) 2010, Manfred Moitzi
7 | # License: MIT License
8 | """
9 | 3d vector math module
10 | """
11 |
12 | __author__ = "mozman "
13 |
14 |
15 | def vector3d(vector):
16 | """ return a 3d vector """
17 | if len(vector) == 2:
18 | return float(vector[0]), float(vector[1]), 0.
19 | else:
20 | return float(vector[0]), float(vector[1]), float(vector[2])
21 |
22 |
23 | def magnitude(vector):
24 | """ get magnitude (length) of vector """
25 | return (vector[0] ** 2 + vector[1] ** 2 + vector[2] ** 2) ** .5
26 |
27 |
28 | def unit_vector(vector):
29 | """ get unit-vector of 3D vector (magnitude = 1.0) """
30 | m = magnitude(vector)
31 | return vector[0] / m, vector[1] / m, vector[2] / m
32 |
33 |
34 | def dot_product(vector1, vector2):
35 | """ get dot-product for vectors """
36 | return reduce(lambda x, y: x + y,
37 | (a * b for a, b in zip(vector1, vector2)))
38 |
39 |
40 | def cross_product(vector1, vector2):
41 | """ get cross-product for 3D vectors """
42 | a1, a2, a3 = vector1
43 | b1, b2, b3 = vector2
44 | return a2 * b3 - a3 * b2, a3 * b1 - a1 * b3, a1 * b2 - a2 * b1
45 |
46 |
47 | def distance(point1, point2):
48 | """ calc distance between two 3d points """
49 | return ((point1[0] - point2[0]) ** 2 +
50 | (point1[1] - point2[1]) ** 2 +
51 | (point1[2] - point2[2]) ** 2) ** 0.5
52 |
53 |
54 | def midpoint(point1, point2):
55 | """ calc midpoint between point1 and point2 """
56 | return ((point1[0] + point2[0]) * .5,
57 | (point1[1] + point2[1]) * .5,
58 | (point1[2] + point2[2]) * .5)
59 |
--------------------------------------------------------------------------------
/i18n/profiletool.pro:
--------------------------------------------------------------------------------
1 | FORMS = ../ui/profiletool.ui \
2 | ../ui/about.ui
3 |
4 | SOURCES = ../profileplugin.py \
5 | ../ui/ptdockwidget.py \
6 | ../ui/dlgabout.py
7 |
8 | TRANSLATIONS = profiletool_de.ts
9 |
--------------------------------------------------------------------------------
/i18n/profiletool_de.qm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PANOimagen/profiletool/0fec10efe93ce437eec7c6128869c1b997e8a836/i18n/profiletool_de.qm
--------------------------------------------------------------------------------
/icons/profileIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PANOimagen/profiletool/0fec10efe93ce437eec7c6128869c1b997e8a836/icons/profileIcon.png
--------------------------------------------------------------------------------
/pyqtgraph/GraphicsScene/__init__.py:
--------------------------------------------------------------------------------
1 | from .GraphicsScene import *
2 |
--------------------------------------------------------------------------------
/pyqtgraph/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 |
--------------------------------------------------------------------------------
/pyqtgraph/Qt/QtCore/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PANOimagen/profiletool/0fec10efe93ce437eec7c6128869c1b997e8a836/pyqtgraph/Qt/QtCore/__init__.py
--------------------------------------------------------------------------------
/pyqtgraph/Qt/QtCore/__init__.pyi:
--------------------------------------------------------------------------------
1 | # Import packages in reverse libOrder as defined in pyqtgraph/Qt/__init__.py
2 | from PySide2.QtCore import *
3 | from PyQt5.QtCore import *
4 | from PySide6.QtCore import *
5 | from PyQt6.QtCore import *
6 |
--------------------------------------------------------------------------------
/pyqtgraph/Qt/QtGui/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PANOimagen/profiletool/0fec10efe93ce437eec7c6128869c1b997e8a836/pyqtgraph/Qt/QtGui/__init__.py
--------------------------------------------------------------------------------
/pyqtgraph/Qt/QtGui/__init__.pyi:
--------------------------------------------------------------------------------
1 | # Import packages in reverse libOrder as defined in pyqtgraph/Qt/__init__.py
2 | from PySide2.QtGui import *
3 | from PyQt5.QtGui import *
4 | from PySide6.QtGui import *
5 | from PyQt6.QtGui import *
6 |
--------------------------------------------------------------------------------
/pyqtgraph/Qt/QtSvg.pyi:
--------------------------------------------------------------------------------
1 | # Import packages in reverse libOrder as defined in pyqtgraph/Qt/__init__.py
2 | from PySide2.QtSvg import *
3 | from PyQt5.QtSvg import *
4 | from PySide6.QtSvg import *
5 | from PyQt6.QtSvg import *
6 |
--------------------------------------------------------------------------------
/pyqtgraph/Qt/QtTest.pyi:
--------------------------------------------------------------------------------
1 | # Import packages in reverse libOrder as defined in pyqtgraph/Qt/__init__.py
2 | from PySide2.QtTest import *
3 | from PyQt5.QtTest import *
4 | from PySide6.QtTest import *
5 | from PyQt6.QtTest import *
6 |
--------------------------------------------------------------------------------
/pyqtgraph/Qt/QtWidgets/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PANOimagen/profiletool/0fec10efe93ce437eec7c6128869c1b997e8a836/pyqtgraph/Qt/QtWidgets/__init__.py
--------------------------------------------------------------------------------
/pyqtgraph/Qt/QtWidgets/__init__.pyi:
--------------------------------------------------------------------------------
1 | # Import packages in reverse libOrder as defined in pyqtgraph/Qt/__init__.py
2 | from PySide2.QtWidgets import *
3 | from PyQt5.QtWidgets import *
4 | from PySide6.QtWidgets import *
5 | from PyQt6.QtWidgets import *
6 |
--------------------------------------------------------------------------------
/pyqtgraph/Qt/__init__.pyi:
--------------------------------------------------------------------------------
1 | """
2 | This stub file is to aid in the PyCharm and VSCode auto-completion of the Qt imports.
3 | """
4 |
5 | from . import QtCore as QtCore
6 | from . import QtGui as QtGui
7 | from . import QtSvg as QtSvg
8 | from . import QtTest as QtTest
9 | from . import QtWidgets as QtWidgets
10 |
11 | App: QtWidgets.QApplication
12 | VERSION_INFO: str
13 | QT_LIB: str
14 | QtVersion: str
15 |
16 | def exec_() -> QtWidgets.QApplication: ...
17 | def mkQApp(name: str | None = None) -> QtWidgets.QApplication: ...
18 | def isQObjectAlive(obj: QtCore.QObject) -> bool: ...
19 |
--------------------------------------------------------------------------------
/pyqtgraph/Qt/compat/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PANOimagen/profiletool/0fec10efe93ce437eec7c6128869c1b997e8a836/pyqtgraph/Qt/compat/__init__.py
--------------------------------------------------------------------------------
/pyqtgraph/ThreadsafeTimer.py:
--------------------------------------------------------------------------------
1 | from .Qt import QtCore
2 |
3 | __all__ = ['ThreadsafeTimer']
4 |
5 | class ThreadsafeTimer(QtCore.QObject):
6 | """
7 | Thread-safe replacement for QTimer.
8 | """
9 |
10 | timeout = QtCore.Signal()
11 | sigTimerStopRequested = QtCore.Signal()
12 | sigTimerStartRequested = QtCore.Signal(object)
13 |
14 | def __init__(self):
15 | QtCore.QObject.__init__(self)
16 | self.timer = QtCore.QTimer()
17 | self.timer.timeout.connect(self.timerFinished)
18 | self.timer.moveToThread(QtCore.QCoreApplication.instance().thread())
19 | self.moveToThread(QtCore.QCoreApplication.instance().thread())
20 | self.sigTimerStopRequested.connect(self.stop, QtCore.Qt.ConnectionType.QueuedConnection)
21 | self.sigTimerStartRequested.connect(self.start, QtCore.Qt.ConnectionType.QueuedConnection)
22 |
23 |
24 | def start(self, timeout):
25 | isGuiThread = QtCore.QThread.currentThread() == QtCore.QCoreApplication.instance().thread()
26 | if isGuiThread:
27 | #print "start timer", self, "from gui thread"
28 | self.timer.start(int(timeout))
29 | else:
30 | #print "start timer", self, "from remote thread"
31 | self.sigTimerStartRequested.emit(timeout)
32 |
33 | def stop(self):
34 | isGuiThread = QtCore.QThread.currentThread() == QtCore.QCoreApplication.instance().thread()
35 | if isGuiThread:
36 | #print "stop timer", self, "from gui thread"
37 | self.timer.stop()
38 | else:
39 | #print "stop timer", self, "from remote thread"
40 | self.sigTimerStopRequested.emit()
41 |
42 | def timerFinished(self):
43 | self.timeout.emit()
44 |
--------------------------------------------------------------------------------
/pyqtgraph/Transform3D.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 |
3 | from . import functions as fn
4 | from .Qt import QtGui
5 | from .Vector import Vector
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 |
--------------------------------------------------------------------------------
/pyqtgraph/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 |
--------------------------------------------------------------------------------
/pyqtgraph/canvas/__init__.py:
--------------------------------------------------------------------------------
1 | from .Canvas import *
2 | from .CanvasItem import *
3 |
--------------------------------------------------------------------------------
/pyqtgraph/colors/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PANOimagen/profiletool/0fec10efe93ce437eec7c6128869c1b997e8a836/pyqtgraph/colors/__init__.py
--------------------------------------------------------------------------------
/pyqtgraph/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 |
--------------------------------------------------------------------------------
/pyqtgraph/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 |
--------------------------------------------------------------------------------
/pyqtgraph/console/CmdInput.py:
--------------------------------------------------------------------------------
1 | from ..Qt import QtCore, QtWidgets
2 |
3 |
4 | class CmdInput(QtWidgets.QLineEdit):
5 |
6 | sigExecuteCmd = QtCore.Signal(object)
7 |
8 | def __init__(self, parent):
9 | QtWidgets.QLineEdit.__init__(self, parent)
10 | self.ps1 = ">>> "
11 | self.ps2 = "... "
12 | self.history = [""]
13 | self.ptr = 0
14 | self.setMultiline(False)
15 |
16 | def setMultiline(self, ml):
17 | if ml:
18 | self.setPlaceholderText(self.ps2)
19 | else:
20 | self.setPlaceholderText(self.ps1)
21 |
22 | def keyPressEvent(self, ev):
23 | if ev.key() == QtCore.Qt.Key.Key_Up:
24 | if self.ptr < len(self.history) - 1:
25 | self.setHistory(self.ptr+1)
26 | ev.accept()
27 | return
28 | elif ev.key() == QtCore.Qt.Key.Key_Down:
29 | if self.ptr > 0:
30 | self.setHistory(self.ptr-1)
31 | ev.accept()
32 | return
33 | elif ev.key() in (QtCore.Qt.Key.Key_Return, QtCore.Qt.Key.Key_Enter):
34 | self.execCmd()
35 | else:
36 | super().keyPressEvent(ev)
37 | self.history[0] = self.text()
38 |
39 | def execCmd(self):
40 | cmd = self.text()
41 | if len(self.history) == 1 or cmd != self.history[1]:
42 | self.history.insert(1, cmd)
43 | self.history[0] = ""
44 | self.setHistory(0)
45 | self.sigExecuteCmd.emit(cmd)
46 |
47 | def setHistory(self, num):
48 | self.ptr = num
49 | self.setText(self.history[self.ptr])
50 |
--------------------------------------------------------------------------------
/pyqtgraph/console/__init__.py:
--------------------------------------------------------------------------------
1 | from .Console import ConsoleWidget
2 |
--------------------------------------------------------------------------------
/pyqtgraph/dockarea/__init__.py:
--------------------------------------------------------------------------------
1 | from .Dock import Dock, DockLabel
2 | from .DockArea import DockArea
3 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/Arrow.py:
--------------------------------------------------------------------------------
1 | """
2 | Display an animated arrowhead following a curve.
3 | This example uses the CurveArrow class, which is a combination
4 | of ArrowItem and CurvePoint.
5 |
6 | To place a static arrow anywhere in a scene, use ArrowItem.
7 | To attach other types of item to a curve, use CurvePoint.
8 | """
9 |
10 | import numpy as np
11 |
12 | import pyqtgraph as pg
13 | from pyqtgraph.Qt import QtCore, QtWidgets
14 |
15 | app = pg.mkQApp("Arrow Example")
16 |
17 | w = QtWidgets.QMainWindow()
18 | cw = pg.GraphicsLayoutWidget()
19 | w.show()
20 | w.resize(400,600)
21 | w.setCentralWidget(cw)
22 | w.setWindowTitle('pyqtgraph example: Arrow')
23 |
24 | p = cw.addPlot(row=0, col=0)
25 | p2 = cw.addPlot(row=1, col=0)
26 |
27 | ## variety of arrow shapes
28 | a1 = pg.ArrowItem(angle=-160, tipAngle=60, headLen=40, tailLen=40, tailWidth=20, pen={'color': 'w', 'width': 3})
29 | a2 = pg.ArrowItem(angle=-120, tipAngle=30, baseAngle=20, headLen=40, tailLen=40, tailWidth=8, pen=None, brush='y')
30 | a3 = pg.ArrowItem(angle=-60, baseAngle=20, headLen=40, headWidth=20, tailLen=None, brush=None)
31 | a4 = pg.ArrowItem(angle=-20, tipAngle=30, baseAngle=-30, headLen=40, tailLen=None)
32 | a2.setPos(10,0)
33 | a3.setPos(20,0)
34 | a4.setPos(30,0)
35 | p.addItem(a1)
36 | p.addItem(a2)
37 | p.addItem(a3)
38 | p.addItem(a4)
39 | p.setRange(QtCore.QRectF(-20, -10, 60, 20))
40 |
41 |
42 | ## Animated arrow following curve
43 | c = p2.plot(x=np.sin(np.linspace(0, 2*np.pi, 1000)), y=np.cos(np.linspace(0, 6*np.pi, 1000)))
44 | a = pg.CurveArrow(c)
45 | a.setStyle(headLen=40)
46 | p2.addItem(a)
47 | anim = a.makeAnimation(loop=-1)
48 | anim.start()
49 |
50 | if __name__ == '__main__':
51 | pg.exec()
52 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/AxisItem_label_overlap.py:
--------------------------------------------------------------------------------
1 | """
2 | This example demonstrates many of the 2D plotting capabilities
3 | in pyqtgraph. All of the plots may be panned/scaled by dragging with
4 | the left/right mouse buttons. Right click on any plot to show a context menu.
5 | """
6 |
7 | import numpy as np
8 |
9 | import pyqtgraph as pg
10 | from pyqtgraph.Qt import QtGui
11 |
12 | app = pg.mkQApp("AxisItem - label overlap settings")
13 |
14 | win = pg.GraphicsLayoutWidget(show=True, title="AxisItem - label overlap settings")
15 | win.resize(800,600)
16 | win.setWindowTitle("AxisItem - label overlap settings")
17 |
18 | # Enable antialiasing for prettier plots
19 | pg.setConfigOptions(antialias=True)
20 |
21 | x_data = np.arange(101) + 1_000.
22 | y_data = np.random.normal(scale=40., size=101)
23 |
24 | font = QtGui.QFont()
25 | font.setPointSize(14) # A larger font makes the effects more visible
26 |
27 | p1 = win.addPlot(title="Default settings: Overlap allowed for y axis", x=x_data, y=y_data)
28 | for axis_key in ('top', 'bottom', 'left', 'right'):
29 | ax = p1.getAxis(axis_key)
30 | ax.setTickFont( font )
31 |
32 | p2 = win.addPlot(title="Overlap allowed for X axis", x=x_data, y=y_data)
33 | for axis_key, hide_overlap in (
34 | ('top' , False),
35 | ('bottom', False),
36 | ('left' , True ),
37 | ('right' , True )
38 | ):
39 | ax = p2.getAxis(axis_key)
40 | ax.setStyle( hideOverlappingLabels = hide_overlap )
41 | ax.setTickFont( font )
42 |
43 | win.nextRow()
44 |
45 | p3 = win.addPlot(title="All overlap disabled", x=x_data, y=y_data)
46 | for axis_key in ('top', 'bottom', 'left', 'right'):
47 | ax = p3.getAxis(axis_key)
48 | ax.setStyle( hideOverlappingLabels = True )
49 | ax.setTickFont( font )
50 |
51 | p4 = win.addPlot(title="All overlap enabled, custom tolerances", x=x_data, y=y_data)
52 | for axis_key, tolerance in (
53 | ('top' , 15 ),
54 | ('bottom', 200 ),
55 | ('left' , 100 ),
56 | ('right' , 15 )
57 | ):
58 | ax = p4.getAxis(axis_key)
59 | ax.setStyle( hideOverlappingLabels = tolerance )
60 | ax.setTickFont( font )
61 |
62 | # Link all axes and set viewing range with no padding:
63 | for p in (p1, p2, p3, p4):
64 | p.showAxes(True, showValues=(True, True, True, True))
65 | if p != p1:
66 | p.setXLink(p1)
67 | p.setYLink(p1)
68 | ax.setTickFont( font )
69 | p1.setXRange( 1_000., 1_100., padding=0.0)
70 | p1.setYRange(-60., 60., padding=0.0)
71 |
72 |
73 | if __name__ == '__main__':
74 | pg.exec()
75 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/BarGraphItem.py:
--------------------------------------------------------------------------------
1 | """
2 | Simple example using BarGraphItem
3 | """
4 |
5 | import numpy as np
6 |
7 | import pyqtgraph as pg
8 |
9 | win = pg.plot()
10 | win.setWindowTitle('pyqtgraph example: BarGraphItem')
11 |
12 | x = np.arange(10)
13 | y1 = np.sin(x)
14 | y2 = 1.1 * np.sin(x+1)
15 | y3 = 1.2 * np.sin(x+2)
16 |
17 | bg1 = pg.BarGraphItem(x=x, height=y1, width=0.3, brush='r')
18 | bg2 = pg.BarGraphItem(x=x+0.33, height=y2, width=0.3, brush='g')
19 | bg3 = pg.BarGraphItem(x=x+0.66, height=y3, width=0.3, brush='b')
20 |
21 | win.addItem(bg1)
22 | win.addItem(bg2)
23 | win.addItem(bg3)
24 |
25 |
26 | # Final example shows how to handle mouse clicks:
27 | class BarGraph(pg.BarGraphItem):
28 | def mouseClickEvent(self, event):
29 | print("clicked")
30 |
31 |
32 | bg = BarGraph(x=x, y=y1*0.3+2, height=0.4+y1*0.2, width=0.8)
33 | win.addItem(bg)
34 |
35 | if __name__ == '__main__':
36 | pg.exec()
37 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/CLIexample.py:
--------------------------------------------------------------------------------
1 | """
2 | Display a plot and an image with minimal setup.
3 |
4 | pg.plot() and pg.image() are indended to be used from an interactive prompt
5 | to allow easy data inspection (but note that PySide unfortunately does not
6 | call the Qt event loop while the interactive prompt is running, in this case
7 | it is necessary to call QApplication.exec_() to make the windows appear).
8 | """
9 |
10 | import numpy as np
11 |
12 | import pyqtgraph as pg
13 |
14 | data = np.random.normal(size=1000)
15 | pg.plot(data, title="Simplest possible plotting example")
16 |
17 | data = np.random.normal(size=(500,500))
18 | pg.image(data, title="Simplest possible image example")
19 |
20 | if __name__ == '__main__':
21 | pg.exec()
22 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/ColorButton.py:
--------------------------------------------------------------------------------
1 | """
2 | Simple example demonstrating a button which displays a colored rectangle
3 | and allows the user to select a new color by clicking on the button.
4 | """
5 |
6 |
7 | import pyqtgraph as pg
8 | from pyqtgraph.Qt import QtWidgets
9 |
10 | app = pg.mkQApp("ColorButton Example")
11 | win = QtWidgets.QMainWindow()
12 | btn = pg.ColorButton()
13 | win.setCentralWidget(btn)
14 | win.show()
15 | win.setWindowTitle('pyqtgraph example: ColorButton')
16 |
17 | def change(btn):
18 | print("change", btn.color())
19 | def done(btn):
20 | print("done", btn.color())
21 |
22 | btn.sigColorChanging.connect(change)
23 | btn.sigColorChanged.connect(done)
24 |
25 | if __name__ == '__main__':
26 | pg.exec()
27 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/ConsoleWidget.py:
--------------------------------------------------------------------------------
1 | """
2 | ConsoleWidget is used to allow execution of user-supplied python commands
3 | in an application. It also includes a command history and functionality for trapping
4 | and inspecting stack traces.
5 |
6 | """
7 |
8 | import numpy as np
9 |
10 | import pyqtgraph as pg
11 | import pyqtgraph.console
12 |
13 | app = pg.mkQApp()
14 |
15 | ## build an initial namespace for console commands to be executed in (this is optional;
16 | ## the user can always import these modules manually)
17 | namespace = {'pg': pg, 'np': np}
18 |
19 | ## initial text to display in the console
20 | text = """
21 | This is an interactive python console. The numpy and pyqtgraph modules have already been imported
22 | as 'np' and 'pg'.
23 |
24 | Go, play.
25 | """
26 | c = pyqtgraph.console.ConsoleWidget(namespace=namespace, text=text)
27 | c.resize(800, 400)
28 | c.show()
29 | c.setWindowTitle('pyqtgraph example: ConsoleWidget')
30 |
31 | if __name__ == '__main__':
32 | pg.exec()
33 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/DataSlicing.py:
--------------------------------------------------------------------------------
1 | """
2 | Demonstrate a simple data-slicing task: given 3D data (displayed at top), select
3 | a 2D plane and interpolate data along that plane to generate a slice image
4 | (displayed at bottom).
5 | """
6 |
7 | import numpy as np
8 |
9 | import pyqtgraph as pg
10 | from pyqtgraph.Qt import QtWidgets
11 |
12 | app = pg.mkQApp("Data Slicing Example")
13 |
14 | ## Create window with two ImageView widgets
15 | win = QtWidgets.QMainWindow()
16 | win.resize(800,800)
17 | win.setWindowTitle('pyqtgraph example: DataSlicing')
18 | cw = QtWidgets.QWidget()
19 | win.setCentralWidget(cw)
20 | l = QtWidgets.QGridLayout()
21 | cw.setLayout(l)
22 | imv1 = pg.ImageView()
23 | imv2 = pg.ImageView()
24 | l.addWidget(imv1, 0, 0)
25 | l.addWidget(imv2, 1, 0)
26 | win.show()
27 |
28 | roi = pg.LineSegmentROI([[10, 64], [120,64]], pen='r')
29 | imv1.addItem(roi)
30 |
31 | x1 = np.linspace(-30, 10, 128)[:, np.newaxis, np.newaxis]
32 | x2 = np.linspace(-20, 20, 128)[:, np.newaxis, np.newaxis]
33 | y = np.linspace(-30, 10, 128)[np.newaxis, :, np.newaxis]
34 | z = np.linspace(-20, 20, 128)[np.newaxis, np.newaxis, :]
35 | d1 = np.sqrt(x1**2 + y**2 + z**2)
36 | d2 = 2*np.sqrt(x1[::-1]**2 + y**2 + z**2)
37 | d3 = 4*np.sqrt(x2**2 + y[:,::-1]**2 + z**2)
38 | data = (np.sin(d1) / d1**2) + (np.sin(d2) / d2**2) + (np.sin(d3) / d3**2)
39 |
40 | def update():
41 | global data, imv1, imv2
42 | d2 = roi.getArrayRegion(data, imv1.imageItem, axes=(1,2))
43 | imv2.setImage(d2)
44 |
45 | roi.sigRegionChanged.connect(update)
46 |
47 |
48 | ## Display the data
49 | imv1.setImage(data)
50 | imv1.setHistogramRange(-0.01, 0.01)
51 | imv1.setLevels(-0.003, 0.003)
52 |
53 | update()
54 |
55 | if __name__ == '__main__':
56 | pg.exec()
57 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/DataTreeWidget.py:
--------------------------------------------------------------------------------
1 |
2 | """
3 | Simple use of DataTreeWidget to display a structure of nested dicts, lists, and arrays
4 | """
5 |
6 | import numpy as np
7 |
8 | import pyqtgraph as pg
9 |
10 |
11 | # for generating a traceback object to display
12 | def some_func1():
13 | return some_func2()
14 | def some_func2():
15 | try:
16 | raise Exception()
17 | except:
18 | import sys
19 | return sys.exc_info()[2]
20 |
21 |
22 | app = pg.mkQApp("DataTreeWidget Example")
23 | d = {
24 | 'a list': [1,2,3,4,5,6, {'nested1': 'aaaaa', 'nested2': 'bbbbb'}, "seven"],
25 | 'a dict': {
26 | 'x': 1,
27 | 'y': 2,
28 | 'z': 'three'
29 | },
30 | 'an array': np.random.randint(10, size=(40,10)),
31 | 'a traceback': some_func1(),
32 | 'a function': some_func1,
33 | 'a class': pg.DataTreeWidget,
34 | }
35 |
36 | tree = pg.DataTreeWidget(data=d)
37 | tree.show()
38 | tree.setWindowTitle('pyqtgraph example: DataTreeWidget')
39 | tree.resize(600,600)
40 |
41 |
42 | if __name__ == '__main__':
43 | pg.exec()
44 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/DateAxisItem.py:
--------------------------------------------------------------------------------
1 | """
2 | Demonstrates the usage of DateAxisItem to display properly-formatted
3 | timestamps on x-axis which automatically adapt to current zoom level.
4 |
5 | """
6 |
7 | import time
8 |
9 | import numpy as np
10 |
11 | import pyqtgraph as pg
12 |
13 | app = pg.mkQApp("DateAxisItem Example")
14 |
15 | # Create a plot with a date-time axis
16 | w = pg.PlotWidget(axisItems = {'bottom': pg.DateAxisItem()})
17 | w.showGrid(x=True, y=True)
18 |
19 | # Plot sin(1/x^2) with timestamps in the last 100 years
20 | now = time.time()
21 | x = np.linspace(2*np.pi, 1000*2*np.pi, 8301)
22 | w.plot(now-(2*np.pi/x)**2*100*np.pi*1e7, np.sin(x), symbol='o')
23 |
24 | w.setWindowTitle('pyqtgraph example: DateAxisItem')
25 | w.show()
26 |
27 | if __name__ == '__main__':
28 | pg.exec()
29 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/DateAxisItem_QtDesigner.py:
--------------------------------------------------------------------------------
1 | """
2 | Demonstrates the usage of DateAxisItem in a layout created with Qt Designer.
3 |
4 | The spotlight here is on the 'setAxisItems' method, without which
5 | one would have to subclass plotWidget in order to attach a dateaxis to it.
6 | """
7 |
8 | import os
9 | import time
10 |
11 | import numpy as np
12 |
13 | import pyqtgraph as pg
14 | from pyqtgraph.Qt import QtWidgets, loadUiType
15 |
16 | pg.setConfigOption('background', 'w')
17 | pg.setConfigOption('foreground', 'k')
18 |
19 | BLUE = pg.mkPen('#1f77b4')
20 |
21 | path = os.path.dirname(os.path.abspath(__file__))
22 | uiFile = os.path.join(path, 'DateAxisItem_QtDesigner.ui')
23 | Design, _ = loadUiType(uiFile)
24 |
25 | class ExampleApp(QtWidgets.QMainWindow, Design):
26 | def __init__(self):
27 | super().__init__()
28 | self.setupUi(self)
29 | now = time.time()
30 | # Plot random values with timestamps in the last 6 months
31 | timestamps = np.linspace(now - 6*30*24*3600, now, 100)
32 | self.curve = self.plotWidget.plot(x=timestamps, y=np.random.rand(100),
33 | symbol='o', symbolSize=5, pen=BLUE)
34 | # 'o' circle 't' triangle 'd' diamond '+' plus 's' square
35 | self.plotWidget.setAxisItems({'bottom': pg.DateAxisItem()})
36 | self.plotWidget.showGrid(x=True, y=True)
37 |
38 | app = pg.mkQApp("DateAxisItem_QtDesigner Example")
39 | window = ExampleApp()
40 | window.setWindowTitle('pyqtgraph example: DateAxisItem_QtDesigner')
41 | window.show()
42 |
43 | if __name__ == '__main__':
44 | pg.exec()
45 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/DateAxisItem_QtDesigner.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | MainWindow
4 |
5 |
6 |
7 | 0
8 | 0
9 | 536
10 | 381
11 |
12 |
13 |
14 | MainWindow
15 |
16 |
17 |
18 | -
19 |
20 |
21 |
22 |
23 |
33 |
34 |
35 |
36 |
37 | PlotWidget
38 | QGraphicsView
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/DiffTreeWidget.py:
--------------------------------------------------------------------------------
1 |
2 | """
3 | Simple use of DiffTreeWidget to display differences between structures of
4 | nested dicts, lists, and arrays.
5 | """
6 |
7 | import numpy as np
8 |
9 | import pyqtgraph as pg
10 |
11 | app = pg.mkQApp("DiffTreeWidget Example")
12 | A = {
13 | 'a list': [1,2,2,4,5,6, {'nested1': 'aaaa', 'nested2': 'bbbbb'}, "seven"],
14 | 'a dict': {
15 | 'x': 1,
16 | 'y': 2,
17 | 'z': 'three'
18 | },
19 | 'an array': np.random.randint(10, size=(40,10)),
20 | #'a traceback': some_func1(),
21 | #'a function': some_func1,
22 | #'a class': pg.DataTreeWidget,
23 | }
24 |
25 | B = {
26 | 'a list': [1,2,3,4,5,5, {'nested1': 'aaaaa', 'nested2': 'bbbbb'}, "seven"],
27 | 'a dict': {
28 | 'x': 2,
29 | 'y': 2,
30 | 'z': 'three',
31 | 'w': 5
32 | },
33 | 'another dict': {1:2, 2:3, 3:4},
34 | 'an array': np.random.randint(10, size=(40,10)),
35 | }
36 |
37 | tree = pg.DiffTreeWidget()
38 | tree.setData(A, B)
39 | tree.show()
40 | tree.setWindowTitle('pyqtgraph example: DiffTreeWidget')
41 | tree.resize(1000, 800)
42 |
43 |
44 | if __name__ == '__main__':
45 | pg.exec()
46 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/Draw.py:
--------------------------------------------------------------------------------
1 | """
2 | Demonstrate ability of ImageItem to be used as a canvas for painting with
3 | the mouse.
4 | """
5 |
6 | import numpy as np
7 |
8 | import pyqtgraph as pg
9 | from pyqtgraph.Qt import QtCore
10 |
11 | app = pg.mkQApp("Draw Example")
12 |
13 | ## Create window with GraphicsView widget
14 | w = pg.GraphicsView()
15 | w.show()
16 | w.resize(800,800)
17 | w.setWindowTitle('pyqtgraph example: Draw')
18 |
19 | view = pg.ViewBox()
20 | w.setCentralItem(view)
21 |
22 | ## lock the aspect ratio
23 | view.setAspectLocked(True)
24 |
25 | ## Create image item
26 | img = pg.ImageItem(np.zeros((200,200)))
27 | view.addItem(img)
28 |
29 | ## Set initial view bounds
30 | view.setRange(QtCore.QRectF(0, 0, 200, 200))
31 |
32 | ## start drawing with 3x3 brush
33 | kern = np.array([
34 | [0.0, 0.5, 0.0],
35 | [0.5, 1.0, 0.5],
36 | [0.0, 0.5, 0.0]
37 | ])
38 | img.setDrawKernel(kern, mask=kern, center=(1,1), mode='add')
39 | img.setLevels([0, 10])
40 |
41 | if __name__ == '__main__':
42 | pg.exec()
43 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/ErrorBarItem.py:
--------------------------------------------------------------------------------
1 | """
2 | Demonstrates basic use of ErrorBarItem
3 | """
4 |
5 | import numpy as np
6 |
7 | import pyqtgraph as pg
8 |
9 | pg.setConfigOptions(antialias=True)
10 |
11 | x = np.arange(10)
12 | y = np.arange(10) %3
13 | top = np.linspace(1.0, 3.0, 10)
14 | bottom = np.linspace(2, 0.5, 10)
15 |
16 | plt = pg.plot()
17 | plt.setWindowTitle('pyqtgraph example: ErrorBarItem')
18 | err = pg.ErrorBarItem(x=x, y=y, top=top, bottom=bottom, beam=0.5)
19 | plt.addItem(err)
20 | plt.plot(x, y, symbol='o', pen={'color': 0.8, 'width': 2})
21 |
22 | if __name__ == '__main__':
23 | pg.exec()
24 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/FillBetweenItem.py:
--------------------------------------------------------------------------------
1 | """
2 | Demonstrates use of FillBetweenItem to fill the space between two plot curves.
3 | """
4 |
5 | import numpy as np
6 |
7 | import pyqtgraph as pg
8 | from pyqtgraph.Qt import QtCore
9 |
10 | #FIXME: When running on Qt5, not as perfect as on Qt4
11 |
12 | win = pg.plot()
13 | win.setWindowTitle('pyqtgraph example: FillBetweenItem')
14 | win.setXRange(-10, 10)
15 | win.setYRange(-10, 10)
16 |
17 | N = 200
18 | x = np.linspace(-10, 10, N)
19 | gauss = np.exp(-x**2 / 20.)
20 | mn = mx = np.zeros(len(x))
21 | curves = [win.plot(x=x, y=np.zeros(len(x)), pen='k') for i in range(4)]
22 | brushes = [0.5, (100, 100, 255), 0.5]
23 | fills = [pg.FillBetweenItem(curves[0], curves[3], brushes[0]),
24 | pg.FillBetweenItem(curves[1], curves[2], brushes[1])]
25 | for f in fills:
26 | win.addItem(f)
27 |
28 | def update():
29 | global mx, mn, curves, gauss, x
30 | a = 5 / abs(np.random.normal(loc=1, scale=0.2))
31 | y1 = -np.abs(a*gauss + np.random.normal(size=len(x)))
32 | y2 = np.abs(a*gauss + np.random.normal(size=len(x)))
33 |
34 | s = 0.01
35 | mn = np.where(y1mx, y2, mx) * (1-s) + y2 * s
37 | curves[0].setData(x, mn)
38 | curves[1].setData(x, y1)
39 | curves[2].setData(x, y2)
40 | curves[3].setData(x, mx)
41 |
42 |
43 | timer = QtCore.QTimer()
44 | timer.timeout.connect(update)
45 | timer.start(30)
46 |
47 |
48 | if __name__ == '__main__':
49 | pg.exec()
50 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/Flowchart.py:
--------------------------------------------------------------------------------
1 | """
2 | This example demonstrates a very basic use of flowcharts: filter data,
3 | displaying both the input and output of the filter. The behavior of
4 | the filter can be reprogrammed by the user.
5 |
6 | Basic steps are:
7 | - create a flowchart and two plots
8 | - input noisy data to the flowchart
9 | - flowchart connects data to the first plot, where it is displayed
10 | - add a gaussian filter to lowpass the data, then display it in the second plot.
11 | """
12 |
13 | import numpy as np
14 |
15 | import pyqtgraph as pg
16 | import pyqtgraph.metaarray as metaarray
17 | from pyqtgraph.flowchart import Flowchart
18 | from pyqtgraph.Qt import QtWidgets
19 |
20 | app = pg.mkQApp("Flowchart Example")
21 |
22 | ## Create main window with grid layout
23 | win = QtWidgets.QMainWindow()
24 | win.setWindowTitle('pyqtgraph example: Flowchart')
25 | cw = QtWidgets.QWidget()
26 | win.setCentralWidget(cw)
27 | layout = QtWidgets.QGridLayout()
28 | cw.setLayout(layout)
29 |
30 | ## Create flowchart, define input/output terminals
31 | fc = Flowchart(terminals={
32 | 'dataIn': {'io': 'in'},
33 | 'dataOut': {'io': 'out'}
34 | })
35 | w = fc.widget()
36 |
37 | ## Add flowchart control panel to the main window
38 | layout.addWidget(fc.widget(), 0, 0, 2, 1)
39 |
40 | ## Add two plot widgets
41 | pw1 = pg.PlotWidget()
42 | pw2 = pg.PlotWidget()
43 | layout.addWidget(pw1, 0, 1)
44 | layout.addWidget(pw2, 1, 1)
45 |
46 | win.show()
47 |
48 | ## generate signal data to pass through the flowchart
49 | data = np.random.normal(size=1000)
50 | data[200:300] += 1
51 | data += np.sin(np.linspace(0, 100, 1000))
52 | data = metaarray.MetaArray(data, info=[{'name': 'Time', 'values': np.linspace(0, 1.0, len(data))}, {}])
53 |
54 | ## Feed data into the input terminal of the flowchart
55 | fc.setInput(dataIn=data)
56 |
57 | ## populate the flowchart with a basic set of processing nodes.
58 | ## (usually we let the user do this)
59 | plotList = {'Top Plot': pw1, 'Bottom Plot': pw2}
60 |
61 | pw1Node = fc.createNode('PlotWidget', pos=(0, -150))
62 | pw1Node.setPlotList(plotList)
63 | pw1Node.setPlot(pw1)
64 |
65 | pw2Node = fc.createNode('PlotWidget', pos=(150, -150))
66 | pw2Node.setPlot(pw2)
67 | pw2Node.setPlotList(plotList)
68 |
69 | fNode = fc.createNode('GaussianFilter', pos=(0, 0))
70 | fNode.ctrls['sigma'].setValue(5)
71 | fc.connectTerminals(fc['dataIn'], fNode['In'])
72 | fc.connectTerminals(fc['dataIn'], pw1Node['In'])
73 | fc.connectTerminals(fNode['Out'], pw2Node['In'])
74 | fc.connectTerminals(fNode['Out'], fc['dataOut'])
75 |
76 | if __name__ == '__main__':
77 | pg.exec()
78 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/GLBarGraphItem.py:
--------------------------------------------------------------------------------
1 | """
2 | This example demonstrates the use of GLBarGraphItem.
3 |
4 | """
5 |
6 | import numpy as np
7 |
8 | import pyqtgraph as pg
9 | import pyqtgraph.opengl as gl
10 |
11 | app = pg.mkQApp("GLBarGraphItem Example")
12 | w = gl.GLViewWidget()
13 | w.show()
14 | w.setWindowTitle('pyqtgraph example: GLBarGraphItem')
15 | w.setCameraPosition(distance=40)
16 |
17 | gx = gl.GLGridItem()
18 | gx.rotate(90, 0, 1, 0)
19 | gx.translate(-10, 0, 10)
20 | w.addItem(gx)
21 | gy = gl.GLGridItem()
22 | gy.rotate(90, 1, 0, 0)
23 | gy.translate(0, -10, 10)
24 | w.addItem(gy)
25 | gz = gl.GLGridItem()
26 | gz.translate(0, 0, 0)
27 | w.addItem(gz)
28 |
29 | # regular grid of starting positions
30 | pos = np.mgrid[0:10, 0:10, 0:1].reshape(3,10,10).transpose(1,2,0)
31 | # fixed widths, random heights
32 | size = np.empty((10,10,3))
33 | size[...,0:2] = 0.4
34 | size[...,2] = np.random.normal(size=(10,10))
35 |
36 | bg = gl.GLBarGraphItem(pos, size)
37 | w.addItem(bg)
38 |
39 | if __name__ == '__main__':
40 | pg.exec()
41 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/GLGradientLegendItem.py:
--------------------------------------------------------------------------------
1 | import numpy
2 |
3 | import pyqtgraph as pg
4 | import pyqtgraph.opengl as gl
5 |
6 | app = pg.mkQApp()
7 | w = gl.GLViewWidget()
8 | w.show()
9 | w.setWindowTitle("pyqtgraph example: GLGradientLegendItem")
10 | w.setCameraPosition(distance=60)
11 |
12 | gx = gl.GLGridItem()
13 | gx.rotate(90, 0, 1, 0)
14 | w.addItem(gx)
15 |
16 | md = gl.MeshData.cylinder(rows=10, cols=20, radius=[5.0, 5], length=20.0)
17 | md._vertexes[:, 2] = md._vertexes[:, 2] - 10
18 |
19 | # set color based on z coordinates
20 | color_map = pg.colormap.get("CET-L10")
21 |
22 | h = md.vertexes()[:, 2]
23 | # remember these
24 | h_max, h_min = h.max(), h.min()
25 | h = (h - h_min) / (h_max - h_min)
26 | colors = color_map.map(h, mode="float")
27 | md.setFaceColors(colors)
28 | m = gl.GLMeshItem(meshdata=md, smooth=True)
29 | w.addItem(m)
30 |
31 | legendLabels = numpy.linspace(h_max, h_min, 5)
32 | legendPos = numpy.linspace(1, 0, 5)
33 | legend = dict(zip(map(str, legendLabels), legendPos))
34 |
35 | gll = gl.GLGradientLegendItem(
36 | pos=(10, 10), size=(50, 300), gradient=color_map, labels=legend
37 | )
38 | w.addItem(gll)
39 |
40 | ## Start Qt event loop unless running in interactive mode.
41 | if __name__ == "__main__":
42 | pg.exec()
43 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/GLGraphItem.py:
--------------------------------------------------------------------------------
1 | """
2 | Demonstrates use of GLGraphItem
3 | """
4 |
5 | import numpy as np
6 |
7 | import pyqtgraph as pg
8 | import pyqtgraph.opengl as gl
9 |
10 | app = pg.mkQApp("GLGraphItem Example")
11 | w = gl.GLViewWidget()
12 | w.setCameraPosition(distance=20)
13 | w.show()
14 |
15 | edges = np.array([
16 | [0, 2],
17 | [0, 3],
18 | [1, 2],
19 | [1, 3],
20 | [2, 3]
21 | ])
22 |
23 | nodes = np.array(
24 | [
25 | [0, 0, 0],
26 | [1, 0, 0],
27 | [0, 1, 0],
28 | [1, 1, 1]
29 | ]
30 | )
31 |
32 | edgeColor=pg.glColor("w")
33 |
34 | gi = gl.GLGraphItem(
35 | edges=edges,
36 | nodePositions=nodes,
37 | edgeWidth=1.,
38 | nodeSize=10.
39 | )
40 |
41 | w.addItem(gi)
42 |
43 | if __name__ == "__main__":
44 | pg.exec()
45 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/GLImageItem.py:
--------------------------------------------------------------------------------
1 | """
2 | Use GLImageItem to display image data on rectangular planes.
3 |
4 | In this example, the image data is sampled from a volume and the image planes
5 | placed as if they slice through the volume.
6 | """
7 |
8 | import numpy as np
9 |
10 | import pyqtgraph as pg
11 | import pyqtgraph.opengl as gl
12 |
13 | app = pg.mkQApp("GLImageItem Example")
14 | w = gl.GLViewWidget()
15 | w.show()
16 | w.setWindowTitle('pyqtgraph example: GLImageItem')
17 | w.setCameraPosition(distance=200)
18 |
19 | ## create volume data set to slice three images from
20 | shape = (100,100,70)
21 | data = pg.gaussianFilter(np.random.normal(size=shape), (4,4,4))
22 | data += pg.gaussianFilter(np.random.normal(size=shape), (15,15,15))*15
23 |
24 | ## slice out three planes, convert to RGBA for OpenGL texture
25 | levels = (-0.08, 0.08)
26 | tex1 = pg.makeRGBA(data[shape[0]//2], levels=levels)[0] # yz plane
27 | tex2 = pg.makeRGBA(data[:,shape[1]//2], levels=levels)[0] # xz plane
28 | tex3 = pg.makeRGBA(data[:,:,shape[2]//2], levels=levels)[0] # xy plane
29 | #tex1[:,:,3] = 128
30 | #tex2[:,:,3] = 128
31 | #tex3[:,:,3] = 128
32 |
33 | ## Create three image items from textures, add to view
34 | v1 = gl.GLImageItem(tex1)
35 | v1.translate(-shape[1]/2, -shape[2]/2, 0)
36 | v1.rotate(90, 0,0,1)
37 | v1.rotate(-90, 0,1,0)
38 | w.addItem(v1)
39 | v2 = gl.GLImageItem(tex2)
40 | v2.translate(-shape[0]/2, -shape[2]/2, 0)
41 | v2.rotate(-90, 1,0,0)
42 | w.addItem(v2)
43 | v3 = gl.GLImageItem(tex3)
44 | v3.translate(-shape[0]/2, -shape[1]/2, 0)
45 | w.addItem(v3)
46 |
47 | ax = gl.GLAxisItem()
48 | w.addItem(ax)
49 |
50 | if __name__ == '__main__':
51 | pg.exec()
52 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/GLIsosurface.py:
--------------------------------------------------------------------------------
1 | """
2 | This example uses the isosurface function to convert a scalar field
3 | (a hydrogen orbital) into a mesh for 3D display.
4 | """
5 |
6 | import numpy as np
7 |
8 | import pyqtgraph as pg
9 | import pyqtgraph.opengl as gl
10 |
11 | app = pg.mkQApp("GLIsosurface Example")
12 | w = gl.GLViewWidget()
13 | w.show()
14 | w.setWindowTitle('pyqtgraph example: GLIsosurface')
15 |
16 | w.setCameraPosition(distance=40)
17 |
18 | g = gl.GLGridItem()
19 | g.scale(2,2,1)
20 | w.addItem(g)
21 |
22 | ## Define a scalar field from which we will generate an isosurface
23 | def psi(i, j, k, offset=(25, 25, 50)):
24 | x = i-offset[0]
25 | y = j-offset[1]
26 | z = k-offset[2]
27 | th = np.arctan2(z, np.hypot(x, y))
28 | r = np.sqrt(x**2 + y**2 + z **2)
29 | a0 = 1
30 | ps = (1./81.) * 1./(6.*np.pi)**0.5 * (1./a0)**(3/2) * (r/a0)**2 * np.exp(-r/(3*a0)) * (3 * np.cos(th)**2 - 1)
31 | return ps
32 |
33 |
34 | print("Generating scalar field..")
35 | data = np.abs(np.fromfunction(psi, (50,50,100)))
36 |
37 |
38 | print("Generating isosurface..")
39 | verts, faces = pg.isosurface(data, data.max()/4.)
40 |
41 | md = gl.MeshData(vertexes=verts, faces=faces)
42 |
43 | colors = np.ones((md.faceCount(), 4), dtype=float)
44 | colors[:,3] = 0.2
45 | colors[:,2] = np.linspace(0, 1, colors.shape[0])
46 | md.setFaceColors(colors)
47 | m1 = gl.GLMeshItem(meshdata=md, smooth=False, shader='balloon')
48 | m1.setGLOptions('additive')
49 |
50 | #w.addItem(m1)
51 | m1.translate(-25, -25, -20)
52 |
53 | m2 = gl.GLMeshItem(meshdata=md, smooth=True, shader='balloon')
54 | m2.setGLOptions('additive')
55 |
56 | w.addItem(m2)
57 | m2.translate(-25, -25, -50)
58 |
59 | if __name__ == '__main__':
60 | pg.exec()
61 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/GLLinePlotItem.py:
--------------------------------------------------------------------------------
1 | """
2 | Demonstrate use of GLLinePlotItem to draw cross-sections of a surface.
3 | """
4 |
5 | import numpy as np
6 |
7 | import pyqtgraph as pg
8 | import pyqtgraph.opengl as gl
9 |
10 | app = pg.mkQApp("GLLinePlotItem Example")
11 | w = gl.GLViewWidget()
12 | w.show()
13 | w.setWindowTitle('pyqtgraph example: GLLinePlotItem')
14 | w.setCameraPosition(distance=40)
15 |
16 | gx = gl.GLGridItem()
17 | gx.rotate(90, 0, 1, 0)
18 | gx.translate(-10, 0, 0)
19 | w.addItem(gx)
20 | gy = gl.GLGridItem()
21 | gy.rotate(90, 1, 0, 0)
22 | gy.translate(0, -10, 0)
23 | w.addItem(gy)
24 | gz = gl.GLGridItem()
25 | gz.translate(0, 0, -10)
26 | w.addItem(gz)
27 |
28 | n = 51
29 | y = np.linspace(-10,10,n)
30 | x = np.linspace(-10,10,100)
31 | for i in range(n):
32 | yi = y[i]
33 | d = np.hypot(x, yi)
34 | z = 10 * np.cos(d) / (d+1)
35 | pts = np.column_stack([x, np.full_like(x, yi), z])
36 | plt = gl.GLLinePlotItem(pos=pts, color=pg.mkColor((i,n*1.3)), width=(i+1)/10., antialias=True)
37 | w.addItem(plt)
38 |
39 | if __name__ == '__main__':
40 | pg.exec()
41 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/GLTextItem.py:
--------------------------------------------------------------------------------
1 | """
2 | Simple examples demonstrating the use of GLTextItem.
3 |
4 | """
5 |
6 | import pyqtgraph as pg
7 | import pyqtgraph.opengl as gl
8 | from pyqtgraph.Qt import mkQApp
9 |
10 | app = mkQApp("GLTextItem Example")
11 |
12 | gvw = gl.GLViewWidget()
13 | gvw.show()
14 | gvw.setWindowTitle('pyqtgraph example: GLTextItem')
15 |
16 | griditem = gl.GLGridItem()
17 | griditem.setSize(10, 10)
18 | griditem.setSpacing(1, 1)
19 | gvw.addItem(griditem)
20 |
21 | axisitem = gl.GLAxisItem()
22 | gvw.addItem(axisitem)
23 |
24 | txtitem1 = gl.GLTextItem(pos=(0.0, 0.0, 0.0), text='text1')
25 | gvw.addItem(txtitem1)
26 |
27 | txtitem2 = gl.GLTextItem()
28 | txtitem2.setData(pos=(1.0, -1.0, 2.0), color=(127, 255, 127, 255), text='text2')
29 | gvw.addItem(txtitem2)
30 |
31 | if __name__ == '__main__':
32 | pg.exec()
33 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/GLViewWidget.py:
--------------------------------------------------------------------------------
1 | """
2 | Very basic 3D graphics example; create a view widget and add a few items.
3 |
4 | """
5 |
6 | import pyqtgraph as pg
7 | import pyqtgraph.opengl as gl
8 |
9 | pg.mkQApp("GLViewWidget Example")
10 | w = gl.GLViewWidget()
11 | w.show()
12 | w.setWindowTitle('pyqtgraph example: GLViewWidget')
13 | w.setCameraPosition(distance=20)
14 |
15 | ax = gl.GLAxisItem()
16 | ax.setSize(5,5,5)
17 | w.addItem(ax)
18 |
19 | b = gl.GLBoxItem()
20 | w.addItem(b)
21 |
22 | ax2 = gl.GLAxisItem()
23 | ax2.setParentItem(b)
24 |
25 | b.translate(1,1,1)
26 |
27 | if __name__ == '__main__':
28 | pg.exec()
29 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/GradientEditor.py:
--------------------------------------------------------------------------------
1 |
2 | import pyqtgraph as pg
3 |
4 | app = pg.mkQApp("Gradiant Editor Example")
5 | mw = pg.GraphicsView()
6 | mw.resize(800,800)
7 | mw.show()
8 |
9 | #ts = pg.TickSliderItem()
10 | #mw.setCentralItem(ts)
11 | #ts.addTick(0.5, 'r')
12 | #ts.addTick(0.9, 'b')
13 |
14 | ge = pg.GradientEditorItem()
15 | mw.setCentralItem(ge)
16 |
17 | if __name__ == '__main__':
18 | pg.exec()
19 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/GradientWidget.py:
--------------------------------------------------------------------------------
1 | """
2 | Demonstrates the appearance / interactivity of GradientWidget
3 | (without actually doing anything useful with it)
4 | """
5 |
6 |
7 | import pyqtgraph as pg
8 | from pyqtgraph.Qt import QtWidgets
9 |
10 | app = pg.mkQApp("Gradiant Widget Example")
11 | w = QtWidgets.QMainWindow()
12 | w.show()
13 | w.setWindowTitle('pyqtgraph example: GradientWidget')
14 | w.setGeometry(10, 50, 400, 400)
15 | cw = QtWidgets.QWidget()
16 | w.setCentralWidget(cw)
17 |
18 | l = QtWidgets.QGridLayout()
19 | l.setSpacing(0)
20 | cw.setLayout(l)
21 |
22 | w1 = pg.GradientWidget(orientation='top')
23 | w2 = pg.GradientWidget(orientation='right', allowAdd=False)
24 | #w2.setTickColor(1, QtGui.QColor(255,255,255))
25 | w3 = pg.GradientWidget(orientation='bottom', allowAdd=False, allowRemove=False)
26 | w4 = pg.GradientWidget(orientation='left')
27 | w4.loadPreset('spectrum')
28 | label = QtWidgets.QLabel("""
29 | - Click a triangle to change its color
30 | - Drag triangles to move
31 | - Right-click a gradient to load triangle presets
32 | - Click in an empty area to add a new color
33 | (adding is disabled for the bottom-side and right-side widgets)
34 | - Right click a triangle to remove
35 | (only possible if more than two triangles are visible)
36 | (removing is disabled for the bottom-side widget)
37 | """)
38 |
39 | l.addWidget(w1, 0, 1)
40 | l.addWidget(w2, 1, 2)
41 | l.addWidget(w3, 2, 1)
42 | l.addWidget(w4, 1, 0)
43 | l.addWidget(label, 1, 1)
44 |
45 | if __name__ == '__main__':
46 | pg.exec()
47 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/GraphItem.py:
--------------------------------------------------------------------------------
1 | """
2 | Simple example of GraphItem use.
3 | """
4 |
5 | import numpy as np
6 |
7 | import pyqtgraph as pg
8 |
9 | # Enable antialiasing for prettier plots
10 | pg.setConfigOptions(antialias=True)
11 |
12 | w = pg.GraphicsLayoutWidget(show=True)
13 | w.setWindowTitle('pyqtgraph example: GraphItem')
14 | v = w.addViewBox()
15 | v.setAspectLocked()
16 |
17 | g = pg.GraphItem()
18 | v.addItem(g)
19 |
20 | ## Define positions of nodes
21 | pos = np.array([
22 | [0,0],
23 | [10,0],
24 | [0,10],
25 | [10,10],
26 | [5,5],
27 | [15,5]
28 | ])
29 |
30 | ## Define the set of connections in the graph
31 | adj = np.array([
32 | [0,1],
33 | [1,3],
34 | [3,2],
35 | [2,0],
36 | [1,5],
37 | [3,5],
38 | ])
39 |
40 | ## Define the symbol to use for each node (this is optional)
41 | symbols = ['o','o','o','o','t','+']
42 |
43 | ## Define the line style for each connection (this is optional)
44 | lines = np.array([
45 | (255,0,0,255,1),
46 | (255,0,255,255,2),
47 | (255,0,255,255,3),
48 | (255,255,0,255,2),
49 | (255,0,0,255,1),
50 | (255,255,255,255,4),
51 | ], dtype=[('red',np.ubyte),('green',np.ubyte),('blue',np.ubyte),('alpha',np.ubyte),('width',float)])
52 |
53 | ## Update the graph
54 | g.setData(pos=pos, adj=adj, pen=lines, size=1, symbol=symbols, pxMode=False)
55 |
56 | if __name__ == '__main__':
57 | pg.exec()
58 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/GraphicsLayout.py:
--------------------------------------------------------------------------------
1 | """
2 | Demonstrate the use of layouts to control placement of multiple plots / views /
3 | labels
4 | """
5 |
6 |
7 | import numpy as np
8 |
9 | import pyqtgraph as pg
10 |
11 | app = pg.mkQApp("Gradiant Layout Example")
12 | view = pg.GraphicsView()
13 | l = pg.GraphicsLayout(border=(100,100,100))
14 | view.setCentralItem(l)
15 | view.show()
16 | view.setWindowTitle('pyqtgraph example: GraphicsLayout')
17 | view.resize(800,600)
18 |
19 | ## Title at top
20 | text = """
21 | This example demonstrates the use of GraphicsLayout to arrange items in a grid.
22 | The items added to the layout must be subclasses of QGraphicsWidget (this includes
23 | PlotItem, ViewBox, LabelItem, and GrphicsLayout itself).
24 | """
25 | l.addLabel(text, col=1, colspan=4)
26 | l.nextRow()
27 |
28 | ## Put vertical label on left side
29 | l.addLabel('Long Vertical Label', angle=-90, rowspan=3)
30 |
31 | ## Add 3 plots into the first row (automatic position)
32 | p1 = l.addPlot(title="Plot 1")
33 | p2 = l.addPlot(title="Plot 2")
34 | vb = l.addViewBox(lockAspect=True)
35 | img = pg.ImageItem(np.random.normal(size=(100,100)))
36 | vb.addItem(img)
37 | vb.autoRange()
38 |
39 |
40 | ## Add a sub-layout into the second row (automatic position)
41 | ## The added item should avoid the first column, which is already filled
42 | l.nextRow()
43 | l2 = l.addLayout(colspan=3, border=(50,0,0))
44 | l2.setContentsMargins(10, 10, 10, 10)
45 | l2.addLabel("Sub-layout: this layout demonstrates the use of shared axes and axis labels", colspan=3)
46 | l2.nextRow()
47 | l2.addLabel('Vertical Axis Label', angle=-90, rowspan=2)
48 | p21 = l2.addPlot()
49 | p22 = l2.addPlot()
50 | l2.nextRow()
51 | p23 = l2.addPlot()
52 | p24 = l2.addPlot()
53 | l2.nextRow()
54 | l2.addLabel("HorizontalAxisLabel", col=1, colspan=2)
55 |
56 | ## hide axes on some plots
57 | p21.hideAxis('bottom')
58 | p22.hideAxis('bottom')
59 | p22.hideAxis('left')
60 | p24.hideAxis('left')
61 | p21.hideButtons()
62 | p22.hideButtons()
63 | p23.hideButtons()
64 | p24.hideButtons()
65 |
66 |
67 | ## Add 2 more plots into the third row (manual position)
68 | p4 = l.addPlot(row=3, col=1)
69 | p5 = l.addPlot(row=3, col=2, colspan=2)
70 |
71 | ## show some content in the plots
72 | p1.plot([1,3,2,4,3,5])
73 | p2.plot([1,3,2,4,3,5])
74 | p4.plot([1,3,2,4,3,5])
75 | p5.plot([1,3,2,4,3,5])
76 |
77 | if __name__ == '__main__':
78 | pg.exec()
79 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/GraphicsScene.py:
--------------------------------------------------------------------------------
1 | import pyqtgraph as pg
2 | from pyqtgraph.Qt import QtCore, QtWidgets
3 |
4 | app = pg.mkQApp("GraphicsScene Example")
5 | win = pg.GraphicsView()
6 | win.show()
7 |
8 |
9 | class Obj(QtWidgets.QGraphicsObject):
10 | def __init__(self):
11 | QtWidgets.QGraphicsObject.__init__(self)
12 |
13 | def paint(self, p, *args):
14 | p.setPen(pg.mkPen(200,200,200))
15 | p.drawRect(self.boundingRect())
16 |
17 | def boundingRect(self):
18 | return QtCore.QRectF(0, 0, 20, 20)
19 |
20 | def mouseClickEvent(self, ev):
21 | if ev.double():
22 | print("double click")
23 | else:
24 | print("click")
25 | ev.accept()
26 |
27 | #def mouseDragEvent(self, ev):
28 | #print "drag"
29 | #ev.accept()
30 | #self.setPos(self.pos() + ev.pos()-ev.lastPos())
31 |
32 |
33 |
34 | vb = pg.ViewBox()
35 | win.setCentralItem(vb)
36 |
37 | obj = Obj()
38 | vb.addItem(obj)
39 |
40 | obj2 = Obj()
41 | win.addItem(obj2)
42 |
43 | def clicked():
44 | print("button click")
45 | btn = QtWidgets.QPushButton("BTN")
46 | btn.clicked.connect(clicked)
47 | prox = QtWidgets.QGraphicsProxyWidget()
48 | prox.setWidget(btn)
49 | prox.setPos(100,0)
50 | vb.addItem(prox)
51 |
52 | g = pg.GridItem()
53 | vb.addItem(g)
54 |
55 | if __name__ == '__main__':
56 | pg.exec()
57 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/HistogramLUT.py:
--------------------------------------------------------------------------------
1 | """
2 | Use a HistogramLUTWidget to control the contrast / coloration of an image.
3 | """
4 |
5 | import numpy as np
6 |
7 | import pyqtgraph as pg
8 | from pyqtgraph.Qt import QtWidgets
9 |
10 | app = pg.mkQApp("Histogram Lookup Table Example")
11 | win = QtWidgets.QMainWindow()
12 | win.resize(880, 600)
13 | win.show()
14 | win.setWindowTitle('pyqtgraph example: Histogram LUT')
15 |
16 | cw = QtWidgets.QWidget()
17 | win.setCentralWidget(cw)
18 |
19 | layout = QtWidgets.QGridLayout()
20 | cw.setLayout(layout)
21 | layout.setSpacing(0)
22 |
23 | view = pg.GraphicsView()
24 | vb = pg.ViewBox()
25 | vb.setAspectLocked()
26 | view.setCentralItem(vb)
27 | layout.addWidget(view, 0, 1, 3, 1)
28 |
29 | hist = pg.HistogramLUTWidget(gradientPosition="left")
30 | layout.addWidget(hist, 0, 2)
31 |
32 |
33 | monoRadio = QtWidgets.QRadioButton('mono')
34 | rgbaRadio = QtWidgets.QRadioButton('rgba')
35 | layout.addWidget(monoRadio, 1, 2)
36 | layout.addWidget(rgbaRadio, 2, 2)
37 | monoRadio.setChecked(True)
38 |
39 |
40 | def setLevelMode():
41 | mode = 'mono' if monoRadio.isChecked() else 'rgba'
42 | hist.setLevelMode(mode)
43 |
44 |
45 | monoRadio.toggled.connect(setLevelMode)
46 |
47 | data = pg.gaussianFilter(np.random.normal(size=(256, 256, 3)), (20, 20, 0))
48 | for i in range(32):
49 | for j in range(32):
50 | data[i*8, j*8] += .1
51 | img = pg.ImageItem(data)
52 | vb.addItem(img)
53 | vb.autoRange()
54 |
55 | hist.setImageItem(img)
56 |
57 | if __name__ == '__main__':
58 | pg.exec()
59 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/ImageItem.py:
--------------------------------------------------------------------------------
1 | """
2 | Demonstrates very basic use of ImageItem to display image data inside a ViewBox.
3 | """
4 |
5 | from time import perf_counter
6 |
7 | import numpy as np
8 |
9 | import pyqtgraph as pg
10 | from pyqtgraph.Qt import QtCore
11 |
12 | app = pg.mkQApp("ImageItem Example")
13 |
14 | ## Create window with GraphicsView widget
15 | win = pg.GraphicsLayoutWidget()
16 | win.show() ## show widget alone in its own window
17 | win.setWindowTitle('pyqtgraph example: ImageItem')
18 | view = win.addViewBox()
19 |
20 | ## lock the aspect ratio so pixels are always square
21 | view.setAspectLocked(True)
22 |
23 | ## Create image item
24 | img = pg.ImageItem(border='w')
25 | view.addItem(img)
26 |
27 | ## Set initial view bounds
28 | view.setRange(QtCore.QRectF(0, 0, 600, 600))
29 |
30 | ## Create random image
31 | data = np.random.normal(size=(15, 600, 600), loc=1024, scale=64).astype(np.uint16)
32 | i = 0
33 |
34 | updateTime = perf_counter()
35 | elapsed = 0
36 |
37 | timer = QtCore.QTimer()
38 | timer.setSingleShot(True)
39 | # not using QTimer.singleShot() because of persistence on PyQt. see PR #1605
40 |
41 | def updateData():
42 | global img, data, i, updateTime, elapsed
43 |
44 | ## Display the data
45 | img.setImage(data[i])
46 | i = (i+1) % data.shape[0]
47 |
48 | timer.start(1)
49 | now = perf_counter()
50 | elapsed_now = now - updateTime
51 | updateTime = now
52 | elapsed = elapsed * 0.9 + elapsed_now * 0.1
53 |
54 | # print(f"{1 / elapsed:.1f} fps")
55 |
56 | timer.timeout.connect(updateData)
57 | updateData()
58 |
59 | if __name__ == '__main__':
60 | pg.exec()
61 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/ImageView.py:
--------------------------------------------------------------------------------
1 | """
2 | This example demonstrates the use of ImageView with 3-color image stacks.
3 | ImageView is a high-level widget for displaying and analyzing 2D and 3D data.
4 | ImageView provides:
5 |
6 | 1. A zoomable region (ViewBox) for displaying the image
7 | 2. A combination histogram and gradient editor (HistogramLUTItem) for
8 | controlling the visual appearance of the image
9 | 3. A timeline for selecting the currently displayed frame (for 3D data only).
10 | 4. Tools for very basic analysis of image data (see ROI and Norm buttons)
11 |
12 | """
13 |
14 | import numpy as np
15 |
16 | import pyqtgraph as pg
17 | from pyqtgraph.Qt import QtWidgets
18 |
19 | # Interpret image data as row-major instead of col-major
20 | pg.setConfigOptions(imageAxisOrder='row-major')
21 |
22 | app = pg.mkQApp("ImageView Example")
23 |
24 | ## Create window with ImageView widget
25 | win = QtWidgets.QMainWindow()
26 | win.resize(800,800)
27 | imv = pg.ImageView(discreteTimeLine=True, levelMode='rgba')
28 | win.setCentralWidget(imv)
29 | win.show()
30 | win.setWindowTitle('pyqtgraph example: ImageView')
31 | imv.setHistogramLabel("Histogram label goes here")
32 |
33 | ## Create random 3D data set with time varying signals
34 | dataRed = np.ones((100, 200, 200)) * np.linspace(90, 150, 100)[:, np.newaxis, np.newaxis]
35 | dataRed += pg.gaussianFilter(np.random.normal(size=(200, 200)), (5, 5)) * 100
36 | dataGrn = np.ones((100, 200, 200)) * np.linspace(90, 180, 100)[:, np.newaxis, np.newaxis]
37 | dataGrn += pg.gaussianFilter(np.random.normal(size=(200, 200)), (5, 5)) * 100
38 | dataBlu = np.ones((100, 200, 200)) * np.linspace(180, 90, 100)[:, np.newaxis, np.newaxis]
39 | dataBlu += pg.gaussianFilter(np.random.normal(size=(200, 200)), (5, 5)) * 100
40 |
41 | data = np.concatenate(
42 | (dataRed[:, :, :, np.newaxis], dataGrn[:, :, :, np.newaxis], dataBlu[:, :, :, np.newaxis]), axis=3
43 | )
44 |
45 |
46 | # Display the data and assign each frame a time value from 1.0 to 3.0
47 | imv.setImage(data, xvals=np.linspace(1., 3., data.shape[0]))
48 | imv.play(10)
49 |
50 | # Start up with an ROI
51 | imv.ui.roiBtn.setChecked(True)
52 | imv.roiClicked()
53 |
54 | if __name__ == '__main__':
55 | pg.exec()
56 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/JoystickButton.py:
--------------------------------------------------------------------------------
1 | """
2 | JoystickButton is a button with x/y values. When the button is depressed and the
3 | mouse dragged, the x/y values change to follow the mouse.
4 | When the mouse button is released, the x/y values change to 0,0 (rather like
5 | letting go of the joystick).
6 | """
7 |
8 | import pyqtgraph as pg
9 | from pyqtgraph.Qt import QtCore, QtWidgets
10 |
11 | app = pg.mkQApp("Joystick Button Example")
12 | mw = QtWidgets.QMainWindow()
13 | mw.resize(300,50)
14 | mw.setWindowTitle('pyqtgraph example: JoystickButton')
15 | cw = QtWidgets.QWidget()
16 | mw.setCentralWidget(cw)
17 | layout = QtWidgets.QGridLayout()
18 | cw.setLayout(layout)
19 | mw.show()
20 |
21 | l1 = pg.ValueLabel(siPrefix=True, suffix='m')
22 | l2 = pg.ValueLabel(siPrefix=True, suffix='m')
23 | jb = pg.JoystickButton()
24 | jb.setFixedWidth(30)
25 | jb.setFixedHeight(30)
26 |
27 |
28 | layout.addWidget(l1, 0, 0)
29 | layout.addWidget(l2, 0, 1)
30 | layout.addWidget(jb, 0, 2)
31 |
32 | x = 0
33 | y = 0
34 | def update():
35 | global x, y, l1, l2, jb
36 | dx, dy = jb.getState()
37 | x += dx * 1e-3
38 | y += dy * 1e-3
39 | l1.setValue(x)
40 | l2.setValue(y)
41 | timer = QtCore.QTimer()
42 | timer.timeout.connect(update)
43 | timer.start(30)
44 |
45 | if __name__ == '__main__':
46 | pg.exec()
47 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/Legend.py:
--------------------------------------------------------------------------------
1 | """
2 | Demonstrates basic use of LegendItem
3 | """
4 |
5 | import numpy as np
6 |
7 | import pyqtgraph as pg
8 |
9 | win = pg.plot()
10 | win.setWindowTitle('pyqtgraph example: BarGraphItem')
11 |
12 | # # option1: only for .plot(), following c1,c2 for example-----------------------
13 | # win.addLegend(frame=False, colCount=2)
14 |
15 | # bar graph
16 | x = np.arange(10)
17 | y = np.sin(x+2) * 3
18 | bg1 = pg.BarGraphItem(x=x, height=y, width=0.3, brush='b', pen='w', name='bar')
19 | win.addItem(bg1)
20 |
21 | # curve
22 | c1 = win.plot([np.random.randint(0,8) for i in range(10)], pen='r', symbol='t', symbolPen='r', symbolBrush='g', name='curve1')
23 | c2 = win.plot([2,1,4,3,1,3,2,4,3,2], pen='g', fillLevel=0, fillBrush=(255,255,255,30), name='curve2')
24 |
25 | # scatter plot
26 | s1 = pg.ScatterPlotItem(size=10, pen=pg.mkPen(None), brush=pg.mkBrush(255, 255, 255, 120), name='scatter')
27 | spots = [{'pos': [i, np.random.randint(-3, 3)], 'data': 1} for i in range(10)]
28 | s1.addPoints(spots)
29 | win.addItem(s1)
30 |
31 | # # option2: generic method------------------------------------------------
32 | legend = pg.LegendItem((80,60), offset=(70,20))
33 | legend.setParentItem(win.graphicsItem())
34 | legend.addItem(bg1, 'bar')
35 | legend.addItem(c1, 'curve1')
36 | legend.addItem(c2, 'curve2')
37 | legend.addItem(s1, 'scatter')
38 |
39 | if __name__ == '__main__':
40 | pg.exec()
41 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/LogPlotTest.py:
--------------------------------------------------------------------------------
1 | """
2 | Simple logarithmic plotting test
3 | """
4 |
5 | import numpy as np
6 |
7 | import pyqtgraph as pg
8 |
9 | app = pg.mkQApp("Log Plot Example")
10 |
11 | win = pg.GraphicsLayoutWidget(show=True, title="Basic plotting examples")
12 | win.resize(1000,600)
13 | win.setWindowTitle('pyqtgraph example: LogPlotTest')
14 |
15 |
16 | p5 = win.addPlot(title="Scatter plot, axis labels, log scale")
17 | x = np.random.normal(size=1000) * 1e-5
18 | y = x*1000 + 0.005 * np.random.normal(size=1000)
19 | y -= y.min()-1.0
20 | mask = x > 1e-15
21 | x = x[mask]
22 | y = y[mask]
23 | p5.plot(x, y, pen=None, symbol='t', symbolPen=None, symbolSize=10, symbolBrush=(100, 100, 255, 50))
24 | p5.setLabel('left', "Y Axis", units='A')
25 | p5.setLabel('bottom', "Y Axis", units='s')
26 | p5.setLogMode(x=True, y=False)
27 |
28 |
29 | if __name__ == '__main__':
30 | pg.exec()
31 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/MouseSelection.py:
--------------------------------------------------------------------------------
1 | """
2 | Demonstrates selecting plot curves by mouse click
3 | """
4 |
5 | import numpy as np
6 |
7 | import pyqtgraph as pg
8 |
9 | win = pg.plot()
10 | win.setWindowTitle('pyqtgraph example: Plot data selection')
11 |
12 | curves = [
13 | pg.PlotCurveItem(y=np.sin(np.linspace(0, 20, 1000)), pen='r', clickable=True),
14 | pg.PlotCurveItem(y=np.sin(np.linspace(1, 21, 1000)), pen='g', clickable=True),
15 | pg.PlotCurveItem(y=np.sin(np.linspace(2, 22, 1000)), pen='b', clickable=True),
16 | ]
17 |
18 | def plotClicked(curve):
19 | global curves
20 | for i,c in enumerate(curves):
21 | if c is curve:
22 | c.setPen('rgb'[i], width=3)
23 | else:
24 | c.setPen('rgb'[i], width=1)
25 |
26 |
27 | for c in curves:
28 | win.addItem(c)
29 | c.sigClicked.connect(plotClicked)
30 |
31 | if __name__ == '__main__':
32 | pg.exec()
33 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/MultiDataPlot.py:
--------------------------------------------------------------------------------
1 | import traceback
2 | import numpy as np
3 |
4 | import pyqtgraph as pg
5 | from pyqtgraph.graphicsItems.ScatterPlotItem import name_list
6 | from pyqtgraph.Qt import QtWidgets, QtCore
7 | from pyqtgraph.parametertree import interact, ParameterTree, Parameter
8 | import random
9 |
10 | pg.mkQApp()
11 |
12 | rng = np.random.default_rng(10)
13 | random.seed(10)
14 |
15 |
16 | def sortedRandint(low, high, size):
17 | return np.sort(rng.integers(low, high, size))
18 |
19 |
20 | def isNoneOrScalar(value):
21 | return value is None or np.isscalar(value[0])
22 |
23 |
24 | values = {
25 | # Convention 1
26 | "None (replaced by integer indices)": None,
27 | # Convention 2
28 | "Single curve values": sortedRandint(0, 20, 15),
29 | # Convention 3 list form
30 | "container of (optionally) mixed-size curve values": [
31 | sortedRandint(0, 20, 15),
32 | *[sortedRandint(0, 20, 15) for _ in range(4)],
33 | ],
34 | # Convention 3 array form
35 | "2D matrix": np.row_stack([sortedRandint(20, 40, 15) for _ in range(6)]),
36 | }
37 |
38 |
39 | def next_plot(xtype="random", ytype="random", symbol="o", symbolBrush="#f00"):
40 | constKwargs = locals()
41 | x = y = None
42 | if xtype == "random":
43 | xtype = random.choice(list(values))
44 | if ytype == "random":
45 | ytype = random.choice(list(values))
46 | x = values[xtype]
47 | y = values[ytype]
48 | textbox.setValue(f"x={xtype}\ny={ytype}")
49 | pltItem.clear()
50 | try:
51 | pltItem.multiDataPlot(
52 | x=x, y=y, pen=cmap.getLookupTable(nPts=6), constKwargs=constKwargs
53 | )
54 | except Exception as e:
55 | QtWidgets.QMessageBox.critical(widget, "Error", traceback.format_exc())
56 |
57 |
58 | cmap = pg.colormap.get("viridis")
59 | widget = pg.PlotWidget()
60 | pltItem: pg.PlotItem = widget.plotItem
61 |
62 | xytype = dict(type="list", values=list(values))
63 | topParam = interact(
64 | next_plot,
65 | symbolBrush=dict(type="color"),
66 | symbol=dict(type="list", values=name_list),
67 | xtype=xytype,
68 | ytype=xytype,
69 | )
70 | tree = ParameterTree()
71 | tree.setMinimumWidth(150)
72 | tree.addParameters(topParam, showTop=True)
73 |
74 | textbox = Parameter.create(name="text", type="text", readonly=True)
75 | tree.addParameters(textbox)
76 |
77 | win = QtWidgets.QWidget()
78 | win.setLayout(lay := QtWidgets.QHBoxLayout())
79 | lay.addWidget(widget)
80 | lay.addWidget(tree)
81 | if __name__ == "__main__":
82 | win.show()
83 | pg.exec()
84 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/MultiPlotSpeedTest.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | """
3 | Test the speed of rapidly updating multiple plot curves
4 | """
5 | import argparse
6 | import itertools
7 |
8 | import numpy as np
9 | from utils import FrameCounter
10 |
11 | import pyqtgraph as pg
12 | from pyqtgraph.Qt import QtCore
13 |
14 | parser = argparse.ArgumentParser()
15 | parser.add_argument('--iterations', default=float('inf'), type=float,
16 | help="Number of iterations to run before exiting"
17 | )
18 | args = parser.parse_args()
19 | iterations_counter = itertools.count()
20 |
21 | # pg.setConfigOptions(useOpenGL=True)
22 | app = pg.mkQApp("MultiPlot Speed Test")
23 |
24 | plot = pg.plot()
25 | plot.setWindowTitle('pyqtgraph example: MultiPlotSpeedTest')
26 | plot.setLabel('bottom', 'Index', units='B')
27 |
28 | nPlots = 100
29 | nSamples = 500
30 | curves = []
31 | for idx in range(nPlots):
32 | curve = pg.PlotCurveItem(pen=({'color': (idx, nPlots*1.3), 'width': 1}), skipFiniteCheck=True)
33 | plot.addItem(curve)
34 | curve.setPos(0,idx*6)
35 | curves.append(curve)
36 |
37 | plot.setYRange(0, nPlots*6)
38 | plot.setXRange(0, nSamples)
39 | plot.resize(600,900)
40 |
41 | rgn = pg.LinearRegionItem([nSamples/5.,nSamples/3.])
42 | plot.addItem(rgn)
43 |
44 |
45 | data = np.random.normal(size=(nPlots*23,nSamples))
46 | ptr = 0
47 | def update():
48 | global ptr
49 | if next(iterations_counter) > args.iterations:
50 | timer.stop()
51 | app.quit()
52 | return None
53 | for i in range(nPlots):
54 | curves[i].setData(data[(ptr+i)%data.shape[0]])
55 |
56 | ptr += nPlots
57 | framecnt.update()
58 |
59 | timer = QtCore.QTimer()
60 | timer.timeout.connect(update)
61 | timer.start(0)
62 |
63 | framecnt = FrameCounter()
64 | framecnt.sigFpsUpdate.connect(lambda fps: plot.setTitle(f'{fps:.1f} fps'))
65 |
66 | if __name__ == '__main__':
67 | pg.exec()
68 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/MultiplePlotAxes.py:
--------------------------------------------------------------------------------
1 | """
2 | Demonstrates a way to put multiple axes around a single plot.
3 |
4 | (This will eventually become a built-in feature of PlotItem)
5 | """
6 |
7 |
8 | import pyqtgraph as pg
9 |
10 | pg.mkQApp()
11 |
12 | pw = pg.PlotWidget()
13 | pw.show()
14 | pw.setWindowTitle('pyqtgraph example: MultiplePlotAxes')
15 | p1 = pw.plotItem
16 | p1.setLabels(left='axis 1')
17 |
18 | ## create a new ViewBox, link the right axis to its coordinate system
19 | p2 = pg.ViewBox()
20 | p1.showAxis('right')
21 | p1.scene().addItem(p2)
22 | p1.getAxis('right').linkToView(p2)
23 | p2.setXLink(p1)
24 | p1.getAxis('right').setLabel('axis2', color='#0000ff')
25 |
26 | ## create third ViewBox.
27 | ## this time we need to create a new axis as well.
28 | p3 = pg.ViewBox()
29 | ax3 = pg.AxisItem('right')
30 | p1.layout.addItem(ax3, 2, 3)
31 | p1.scene().addItem(p3)
32 | ax3.linkToView(p3)
33 | p3.setXLink(p1)
34 | ax3.setZValue(-10000)
35 | ax3.setLabel('axis 3', color='#ff0000')
36 |
37 |
38 | ## Handle view resizing
39 | def updateViews():
40 | ## view has resized; update auxiliary views to match
41 | global p1, p2, p3
42 | p2.setGeometry(p1.vb.sceneBoundingRect())
43 | p3.setGeometry(p1.vb.sceneBoundingRect())
44 |
45 | ## need to re-update linked axes since this was called
46 | ## incorrectly while views had different shapes.
47 | ## (probably this should be handled in ViewBox.resizeEvent)
48 | p2.linkedViewChanged(p1.vb, p2.XAxis)
49 | p3.linkedViewChanged(p1.vb, p3.XAxis)
50 |
51 | updateViews()
52 | p1.vb.sigResized.connect(updateViews)
53 |
54 |
55 | p1.plot([1,2,4,8,16,32])
56 | p2.addItem(pg.PlotCurveItem([10,20,40,80,40,20], pen='b'))
57 | p3.addItem(pg.PlotCurveItem([3200,1600,800,400,200,100], pen='r'))
58 |
59 | if __name__ == '__main__':
60 | pg.exec()
61 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/NonUniformImage.py:
--------------------------------------------------------------------------------
1 | """
2 | Display a non-uniform image.
3 | This example displays 2-d data as an image with non-uniformly
4 | distributed sample points.
5 | """
6 |
7 | import numpy as np
8 |
9 | import pyqtgraph as pg
10 | from pyqtgraph.graphicsItems.NonUniformImage import NonUniformImage
11 |
12 | RPM2RADS = 2 * np.pi / 60
13 | RADS2RPM = 1 / RPM2RADS
14 |
15 | kfric = 1 # [Ws/rad] angular damping coefficient [0;100]
16 | kfric3 = 1.5e-6 # [Ws3/rad3] angular damping coefficient (3rd order) [0;10-3]
17 | psi = 0.2 # [Vs] flux linkage [0.001;10]
18 | res = 5e-3 # [Ohm] resistance [0;100]
19 | v_ref = 200 # [V] reference DC voltage [0;1000]
20 | k_v = 5 # linear voltage coefficient [-100;100]
21 |
22 | # create the (non-uniform) scales
23 | tau = np.array([0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 120, 140, 160, 180, 200, 220], dtype=np.float32)
24 | w = np.array([0, 250, 500, 750, 1000, 1500, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000], dtype=np.float32) * RPM2RADS
25 | v = 380
26 |
27 | # calculate the power losses
28 | TAU, W = np.meshgrid(tau, w, indexing='ij')
29 | V = np.ones_like(TAU) * v
30 |
31 | P_loss = kfric * W + kfric3 * W ** 3 + (res * (TAU / psi) ** 2) + k_v * (V - v_ref)
32 |
33 | P_mech = TAU * W
34 | P_loss[P_mech > 1.5e5] = np.nan
35 |
36 | app = pg.mkQApp("NonUniform Image Example")
37 |
38 | win = pg.GraphicsLayoutWidget()
39 | win.show()
40 | win.resize(600, 400)
41 | win.setWindowTitle('pyqtgraph example: Non-uniform Image')
42 |
43 | p = win.addPlot(title="Power Losses [W]", row=0, col=0)
44 | hist = pg.HistogramLUTItem(orientation="horizontal")
45 |
46 | p.setMouseEnabled(x=False, y=False)
47 |
48 | win.nextRow()
49 | win.addItem(hist)
50 |
51 | image = NonUniformImage(w * RADS2RPM, tau, P_loss.T)
52 | image.setZValue(-1)
53 | p.addItem(image)
54 |
55 | # green - orange - red
56 | cmap = pg.ColorMap([0.0, 0.5, 1.0], [(74, 158, 71), (255, 230, 0), (191, 79, 76)])
57 | hist.gradient.setColorMap(cmap)
58 | hist.setImageItem(image)
59 |
60 | p.showGrid(x=True, y=True)
61 |
62 | p.setLabel(axis='bottom', text='Speed [rpm]')
63 | p.setLabel(axis='left', text='Torque [Nm]')
64 |
65 | # elevate the grid lines
66 | p.axes['bottom']['item'].setZValue(1000)
67 | p.axes['left']['item'].setZValue(1000)
68 |
69 | if __name__ == '__main__':
70 | pg.exec()
71 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/PanningPlot.py:
--------------------------------------------------------------------------------
1 | """
2 | Shows use of PlotWidget to display panning data
3 | """
4 |
5 | import numpy as np
6 |
7 | import pyqtgraph as pg
8 | from pyqtgraph.Qt import QtCore
9 |
10 | win = pg.GraphicsLayoutWidget(show=True)
11 | win.setWindowTitle('pyqtgraph example: PanningPlot')
12 |
13 | plt = win.addPlot()
14 | #plt.setAutoVisibleOnly(y=True)
15 | curve = plt.plot()
16 |
17 | data = []
18 | count = 0
19 | def update():
20 | global data, curve, count
21 | data.append(np.random.normal(size=10) + np.sin(count * 0.1) * 5)
22 | if len(data) > 100:
23 | data.pop(0)
24 | curve.setData(np.hstack(data))
25 | count += 1
26 |
27 | timer = QtCore.QTimer()
28 | timer.timeout.connect(update)
29 | timer.start(50)
30 |
31 | if __name__ == '__main__':
32 | pg.exec()
33 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/PlotAutoRange.py:
--------------------------------------------------------------------------------
1 |
2 | """
3 | This example demonstrates the different auto-ranging capabilities of ViewBoxes
4 | """
5 |
6 | import time
7 |
8 | import numpy as np
9 |
10 | import pyqtgraph as pg
11 | from pyqtgraph.Qt import QtCore
12 |
13 | app = pg.mkQApp("Plot Auto Range Example")
14 |
15 | win = pg.GraphicsLayoutWidget(show=True, title="Plot auto-range examples")
16 | win.resize(800,600)
17 | win.setWindowTitle('pyqtgraph example: PlotAutoRange')
18 |
19 | d = np.random.normal(size=100)
20 | d[50:54] += 10
21 | p1 = win.addPlot(title="95th percentile range", y=d)
22 | p1.enableAutoRange('y', 0.95)
23 |
24 |
25 | p2 = win.addPlot(title="Auto Pan Only")
26 | p2.setAutoPan(y=True)
27 | curve = p2.plot()
28 | t0 = time.time()
29 |
30 | def update():
31 | t = time.time() - t0
32 |
33 | data = np.ones(100) * np.sin(t)
34 | data[50:60] += np.sin(t)
35 | curve.setData(data)
36 |
37 | timer = QtCore.QTimer()
38 | timer.timeout.connect(update)
39 | timer.start(50)
40 |
41 | if __name__ == '__main__':
42 | pg.exec()
43 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/PlotWidget.py:
--------------------------------------------------------------------------------
1 | """
2 | Demonstrates use of PlotWidget class. This is little more than a
3 | GraphicsView with a PlotItem placed in its center.
4 | """
5 |
6 | import numpy as np
7 |
8 | import pyqtgraph as pg
9 | from pyqtgraph.Qt import QtCore, QtWidgets
10 |
11 | app = pg.mkQApp()
12 | mw = QtWidgets.QMainWindow()
13 | mw.setWindowTitle('pyqtgraph example: PlotWidget')
14 | mw.resize(800,800)
15 | cw = QtWidgets.QWidget()
16 | mw.setCentralWidget(cw)
17 | l = QtWidgets.QVBoxLayout()
18 | cw.setLayout(l)
19 |
20 | pw = pg.PlotWidget(name='Plot1') ## giving the plots names allows us to link their axes together
21 | l.addWidget(pw)
22 | pw2 = pg.PlotWidget(name='Plot2')
23 | l.addWidget(pw2)
24 | pw3 = pg.PlotWidget()
25 | l.addWidget(pw3)
26 |
27 | mw.show()
28 |
29 | ## Create an empty plot curve to be filled later, set its pen
30 | p1 = pw.plot()
31 | p1.setPen((200,200,100))
32 |
33 | ## Add in some extra graphics
34 | rect = QtWidgets.QGraphicsRectItem(QtCore.QRectF(0, 0, 1, 5e-11))
35 | rect.setPen(pg.mkPen(100, 200, 100))
36 | pw.addItem(rect)
37 |
38 | pw.setLabel('left', 'Value', units='V')
39 | pw.setLabel('bottom', 'Time', units='s')
40 | pw.setXRange(0, 2)
41 | pw.setYRange(0, 1e-10)
42 |
43 | def rand(n):
44 | data = np.random.random(n)
45 | data[int(n*0.1):int(n*0.13)] += .5
46 | data[int(n*0.18)] += 2
47 | data[int(n*0.1):int(n*0.13)] *= 5
48 | data[int(n*0.18)] *= 20
49 | data *= 1e-12
50 | return data, np.arange(n, n+len(data)) / float(n)
51 |
52 |
53 | def updateData():
54 | yd, xd = rand(10000)
55 | p1.setData(y=yd, x=xd)
56 |
57 | ## Start a timer to rapidly update the plot in pw
58 | t = QtCore.QTimer()
59 | t.timeout.connect(updateData)
60 | t.start(50)
61 | #updateData()
62 |
63 | ## Multiple parameterized plots--we can autogenerate averages for these.
64 | for i in range(0, 5):
65 | for j in range(0, 3):
66 | yd, xd = rand(10000)
67 | pw2.plot(y=yd*(j+1), x=xd, params={'iter': i, 'val': j})
68 |
69 | ## Test large numbers
70 | curve = pw3.plot(np.random.normal(size=100)*1e0, clickable=True)
71 | curve.curve.setClickable(True)
72 | curve.setPen('w') ## white pen
73 | curve.setShadowPen(pg.mkPen((70,70,30), width=6, cosmetic=True))
74 |
75 | def clicked():
76 | print("curve clicked")
77 | curve.sigClicked.connect(clicked)
78 |
79 | lr = pg.LinearRegionItem([1, 30], bounds=[0,100], movable=True)
80 | pw3.addItem(lr)
81 | line = pg.InfiniteLine(angle=90, movable=True)
82 | pw3.addItem(line)
83 | line.setBounds([0,200])
84 |
85 | if __name__ == '__main__':
86 | pg.exec()
87 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/ProgressDialog.py:
--------------------------------------------------------------------------------
1 | """
2 | Using ProgressDialog to show progress updates in a nested process.
3 |
4 | """
5 |
6 | import time
7 |
8 | import pyqtgraph as pg
9 |
10 | app = pg.mkQApp("Progress Dialog Example")
11 |
12 |
13 | def runStage(i):
14 | """Waste time for 2 seconds while incrementing a progress bar.
15 | """
16 | with pg.ProgressDialog("Running stage %s.." % i, maximum=100, nested=True) as dlg:
17 | for j in range(100):
18 | time.sleep(0.02)
19 | dlg += 1
20 | if dlg.wasCanceled():
21 | print("Canceled stage %s" % i)
22 | break
23 |
24 |
25 | def runManyStages(i):
26 | """Iterate over runStage() 3 times while incrementing a progress bar.
27 | """
28 | with pg.ProgressDialog("Running stage %s.." % i, maximum=3, nested=True, wait=0) as dlg:
29 | for j in range(1,4):
30 | runStage('%d.%d' % (i, j))
31 | dlg += 1
32 | if dlg.wasCanceled():
33 | print("Canceled stage %s" % i)
34 | break
35 |
36 |
37 | with pg.ProgressDialog("Doing a multi-stage process..", maximum=5, nested=True, wait=0) as dlg1:
38 | for i in range(1,6):
39 | if i == 3:
40 | # this stage will have 3 nested progress bars
41 | runManyStages(i)
42 | else:
43 | # this stage will have 2 nested progress bars
44 | runStage(i)
45 |
46 | dlg1 += 1
47 | if dlg1.wasCanceled():
48 | print("Canceled process")
49 | break
50 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/RemoteGraphicsView.py:
--------------------------------------------------------------------------------
1 | """
2 | Very simple example demonstrating RemoteGraphicsView.
3 |
4 | This allows graphics to be rendered in a child process and displayed in the
5 | parent, which can improve CPU usage on multi-core processors.
6 | """
7 |
8 | import pyqtgraph as pg
9 | from pyqtgraph.widgets.RemoteGraphicsView import RemoteGraphicsView
10 |
11 | app = pg.mkQApp()
12 |
13 | ## Create the widget
14 | v = RemoteGraphicsView(debug=False) # setting debug=True causes both processes to print information
15 | # about interprocess communication
16 | v.show()
17 | v.setWindowTitle('pyqtgraph example: RemoteGraphicsView')
18 |
19 | ## v.pg is a proxy to the remote process' pyqtgraph module. All attribute
20 | ## requests and function calls made with this object are forwarded to the
21 | ## remote process and executed there. See pyqtgraph.multiprocess.remoteproxy
22 | ## for more inormation.
23 | plt = v.pg.PlotItem()
24 | v.setCentralItem(plt)
25 | plt.plot([1,4,2,3,6,2,3,4,2,3], pen='g')
26 |
27 | if __name__ == '__main__':
28 | pg.exec()
29 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/RunExampleApp.py:
--------------------------------------------------------------------------------
1 | """
2 | This file is used by test_examples.py for ensuring the Example App works.
3 | It is not named test_ExampleApp.py as that way the Example application is
4 | not run twice.
5 | """
6 |
7 | from ExampleApp import ExampleLoader
8 |
9 | import pyqtgraph as pg
10 | from pyqtgraph.Qt import QtTest
11 |
12 | pg.mkQApp()
13 |
14 | def test_ExampleLoader():
15 | loader = ExampleLoader()
16 | QtTest.QTest.qWaitForWindowExposed(loader)
17 | QtTest.QTest.qWait(200)
18 | loader.close()
19 |
20 | if __name__ == "__main__":
21 | test_ExampleLoader()
22 | pg.exec()
23 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/ScaleBar.py:
--------------------------------------------------------------------------------
1 | """
2 | Demonstrates ScaleBar
3 | """
4 |
5 | import numpy as np
6 |
7 | import pyqtgraph as pg
8 |
9 | pg.mkQApp()
10 | win = pg.GraphicsLayoutWidget(show=True)
11 | win.setWindowTitle('pyqtgraph example: ScaleBar')
12 |
13 | vb = win.addViewBox()
14 | vb.setAspectLocked()
15 |
16 | img = pg.ImageItem()
17 | img.setImage(np.random.normal(size=(100,100)))
18 | img.setScale(0.01)
19 | vb.addItem(img)
20 |
21 | scale = pg.ScaleBar(size=0.1)
22 | scale.setParentItem(vb)
23 | scale.anchor((1, 1), (1, 1), offset=(-20, -20))
24 |
25 | if __name__ == '__main__':
26 | pg.exec()
27 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/SimplePlot.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 |
3 | import pyqtgraph as pg
4 |
5 | plt = pg.plot(np.random.normal(size=100), title="Simplest possible plotting example")
6 |
7 | if __name__ == '__main__':
8 | pg.exec()
9 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/TableWidget.py:
--------------------------------------------------------------------------------
1 | """
2 | Simple demonstration of TableWidget, which is an extension of QTableWidget
3 | that automatically displays a variety of tabluar data formats.
4 | """
5 |
6 | import numpy as np
7 |
8 | import pyqtgraph as pg
9 |
10 | app = pg.mkQApp("Table Widget Example")
11 |
12 | w = pg.TableWidget()
13 | w.show()
14 | w.resize(500,500)
15 | w.setWindowTitle('pyqtgraph example: TableWidget')
16 |
17 |
18 | data = np.array([
19 | (1, 1.6, 'x'),
20 | (3, 5.4, 'y'),
21 | (8, 12.5, 'z'),
22 | (443, 1e-12, 'w'),
23 | ], dtype=[('Column 1', int), ('Column 2', float), ('Column 3', object)])
24 |
25 | w.setData(data)
26 |
27 | if __name__ == '__main__':
28 | pg.exec()
29 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/TreeWidget.py:
--------------------------------------------------------------------------------
1 | """
2 | Simple demonstration of TreeWidget, which is an extension of QTreeWidget
3 | that allows widgets to be added and dragged within the tree more easily.
4 | """
5 |
6 |
7 | import pyqtgraph as pg
8 | from pyqtgraph.Qt import QtWidgets
9 |
10 | app = pg.mkQApp("TreeWidget Example")
11 |
12 | w = pg.TreeWidget()
13 | w.setColumnCount(2)
14 | w.show()
15 | w.setWindowTitle('pyqtgraph example: TreeWidget')
16 |
17 | i1 = QtWidgets.QTreeWidgetItem(["Item 1"])
18 | i11 = QtWidgets.QTreeWidgetItem(["Item 1.1"])
19 | i12 = QtWidgets.QTreeWidgetItem(["Item 1.2"])
20 | i2 = QtWidgets.QTreeWidgetItem(["Item 2"])
21 | i21 = QtWidgets.QTreeWidgetItem(["Item 2.1"])
22 | i211 = pg.TreeWidgetItem(["Item 2.1.1"])
23 | i212 = pg.TreeWidgetItem(["Item 2.1.2"])
24 | i22 = pg.TreeWidgetItem(["Item 2.2"])
25 | i3 = pg.TreeWidgetItem(["Item 3"])
26 | i4 = pg.TreeWidgetItem(["Item 4"])
27 | i5 = pg.TreeWidgetItem(["Item 5"])
28 | b5 = QtWidgets.QPushButton('Button')
29 | i5.setWidget(1, b5)
30 |
31 |
32 |
33 | w.addTopLevelItem(i1)
34 | w.addTopLevelItem(i2)
35 | w.addTopLevelItem(i3)
36 | w.addTopLevelItem(i4)
37 | w.addTopLevelItem(i5)
38 | i1.addChild(i11)
39 | i1.addChild(i12)
40 | i2.addChild(i21)
41 | i21.addChild(i211)
42 | i21.addChild(i212)
43 | i2.addChild(i22)
44 |
45 | b1 = QtWidgets.QPushButton("Button")
46 | w.setItemWidget(i1, 1, b1)
47 |
48 | if __name__ == '__main__':
49 | pg.exec()
50 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/ViewBoxFeatures.py:
--------------------------------------------------------------------------------
1 | """
2 | ViewBox is the general-purpose graphical container that allows the user to
3 | zoom / pan to inspect any area of a 2D coordinate system.
4 |
5 | This example demonstrates many of the features ViewBox provides.
6 | """
7 |
8 | import numpy as np
9 |
10 | import pyqtgraph as pg
11 |
12 | x = np.arange(1000, dtype=float)
13 | y = np.random.normal(size=1000)
14 | y += 5 * np.sin(x/100)
15 |
16 | win = pg.GraphicsLayoutWidget(show=True)
17 | win.setWindowTitle('pyqtgraph example: ____')
18 | win.resize(1000, 800)
19 | win.ci.setBorder((50, 50, 100))
20 |
21 | sub1 = win.addLayout()
22 | sub1.addLabel("Standard mouse interaction:
left-drag to pan, right-drag to zoom.")
23 | sub1.nextRow()
24 | v1 = sub1.addViewBox()
25 | l1 = pg.PlotDataItem(y)
26 | v1.addItem(l1)
27 |
28 |
29 | sub2 = win.addLayout()
30 | sub2.addLabel("One-button mouse interaction:
left-drag zoom to box, wheel to zoom out.")
31 | sub2.nextRow()
32 | v2 = sub2.addViewBox()
33 | v2.setMouseMode(v2.RectMode)
34 | l2 = pg.PlotDataItem(y)
35 | v2.addItem(l2)
36 |
37 | win.nextRow()
38 |
39 | sub3 = win.addLayout()
40 | sub3.addLabel("Locked aspect ratio when zooming.")
41 | sub3.nextRow()
42 | v3 = sub3.addViewBox()
43 | v3.setAspectLocked(1.0)
44 | l3 = pg.PlotDataItem(y)
45 | v3.addItem(l3)
46 |
47 | sub4 = win.addLayout()
48 | sub4.addLabel("View limits:
prevent panning or zooming past limits.")
49 | sub4.nextRow()
50 | v4 = sub4.addViewBox()
51 | v4.setLimits(xMin=-100, xMax=1100,
52 | minXRange=20, maxXRange=500,
53 | yMin=-10, yMax=10,
54 | minYRange=1, maxYRange=10)
55 | l4 = pg.PlotDataItem(y)
56 | v4.addItem(l4)
57 |
58 | win.nextRow()
59 |
60 | sub5 = win.addLayout()
61 | sub5.addLabel("Linked axes: Data in this plot is always X-aligned to
the plot above.")
62 | sub5.nextRow()
63 | v5 = sub5.addViewBox()
64 | v5.setXLink(v3)
65 | l5 = pg.PlotDataItem(y)
66 | v5.addItem(l5)
67 |
68 | sub6 = win.addLayout()
69 | sub6.addLabel("Disable mouse: Per-axis control over mouse input.
"
70 | "Auto-scale-visible: Automatically fit *visible* data within view
"
71 | "(try panning left-right).")
72 | sub6.nextRow()
73 | v6 = sub6.addViewBox()
74 | v6.setMouseEnabled(x=True, y=False)
75 | v6.enableAutoRange(x=False, y=True)
76 | v6.setXRange(300, 450)
77 | v6.setAutoVisible(x=False, y=True)
78 | l6 = pg.PlotDataItem(y)
79 | v6.addItem(l6)
80 |
81 | if __name__ == '__main__':
82 | pg.exec()
83 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/ViewLimits.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 |
3 | import pyqtgraph as pg
4 |
5 | plt = pg.plot(np.random.normal(size=100), title="View limit example")
6 | plt.centralWidget.vb.setLimits(xMin=-20, xMax=120, minXRange=5, maxXRange=100)
7 |
8 | if __name__ == '__main__':
9 | pg.exec()
10 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/__init__.py:
--------------------------------------------------------------------------------
1 | from .ExampleApp import main as run
2 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/__main__.py:
--------------------------------------------------------------------------------
1 |
2 |
3 | if __name__ == '__main__':
4 | from .ExampleApp import main as run
5 | run()
6 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/beeswarm.py:
--------------------------------------------------------------------------------
1 | """
2 | Example beeswarm / bar chart
3 | """
4 |
5 | import numpy as np
6 |
7 | import pyqtgraph as pg
8 |
9 | win = pg.plot()
10 | win.setWindowTitle('pyqtgraph example: beeswarm')
11 |
12 | data = np.random.normal(size=(4,20))
13 | data[0] += 5
14 | data[1] += 7
15 | data[2] += 5
16 | data[3] = 10 + data[3] * 2
17 |
18 | ## Make bar graph
19 | #bar = pg.BarGraphItem(x=range(4), height=data.mean(axis=1), width=0.5, brush=0.4)
20 | #win.addItem(bar)
21 |
22 | ## add scatter plots on top
23 | for i in range(4):
24 | xvals = pg.pseudoScatter(data[i], spacing=0.4, bidir=True) * 0.2
25 | win.plot(x=xvals+i, y=data[i], pen=None, symbol='o', symbolBrush=pg.intColor(i,6,maxValue=128))
26 |
27 | ## Make error bars
28 | err = pg.ErrorBarItem(x=np.arange(4), y=data.mean(axis=1), height=data.std(axis=1), beam=0.5, pen={'color':'w', 'width':2})
29 | win.addItem(err)
30 |
31 |
32 | if __name__ == '__main__':
33 | pg.exec()
34 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/colorMaps.py:
--------------------------------------------------------------------------------
1 | """
2 | This example displays all color maps currently available, either as local data
3 | or imported from Matplotlib of ColorCET.
4 | """
5 |
6 | import pyqtgraph as pg
7 | from pyqtgraph.Qt import QtCore, QtWidgets
8 |
9 | app = pg.mkQApp()
10 |
11 | win = QtWidgets.QMainWindow()
12 | win.resize(1000,800)
13 |
14 | lw = pg.GraphicsLayoutWidget()
15 | lw.setFixedWidth(1000)
16 | lw.setSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Expanding)
17 |
18 | scr = QtWidgets.QScrollArea()
19 | scr.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarPolicy.ScrollBarAlwaysOn)
20 | scr.setWidget(lw)
21 | win.setCentralWidget(scr)
22 | win.setWindowTitle('pyqtgraph example: Color maps')
23 | win.show()
24 |
25 | bar_width = 32
26 | bar_data = pg.colormap.modulatedBarData(width=bar_width)
27 |
28 | num_bars = 0
29 |
30 | def add_heading(lw, name):
31 | global num_bars
32 | lw.addLabel('=== '+name+' ===')
33 | num_bars += 1
34 | lw.nextRow()
35 |
36 | def add_bar(lw, name, cm):
37 | global num_bars
38 | lw.addLabel(name)
39 | imi = pg.ImageItem( bar_data )
40 | imi.setLookupTable( cm.getLookupTable(alpha=True) )
41 | vb = lw.addViewBox(lockAspect=True, enableMouse=False)
42 | vb.addItem( imi )
43 | num_bars += 1
44 | lw.nextRow()
45 |
46 | add_heading(lw, 'local color maps')
47 | list_of_maps = pg.colormap.listMaps()
48 | list_of_maps = sorted( list_of_maps, key=lambda x: x.swapcase() )
49 | for map_name in list_of_maps:
50 | cm = pg.colormap.get(map_name)
51 | add_bar(lw, map_name, cm)
52 |
53 | add_heading(lw, 'Matplotlib import')
54 | list_of_maps = pg.colormap.listMaps('matplotlib')
55 | list_of_maps = sorted( list_of_maps, key=lambda x: x.lower() )
56 | for map_name in list_of_maps:
57 | cm = pg.colormap.get(map_name, source='matplotlib', skipCache=True)
58 | if cm is not None:
59 | add_bar(lw, map_name, cm)
60 |
61 | add_heading(lw, 'ColorCET import')
62 | list_of_maps = pg.colormap.listMaps('colorcet')
63 | list_of_maps = sorted( list_of_maps, key=lambda x: x.lower() )
64 | for map_name in list_of_maps:
65 | cm = pg.colormap.get(map_name, source='colorcet', skipCache=True)
66 | if cm is not None:
67 | add_bar(lw, map_name, cm)
68 |
69 | lw.setFixedHeight(num_bars * (bar_width+5) )
70 |
71 | if __name__ == '__main__':
72 | pg.exec()
73 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/customGraphicsItem.py:
--------------------------------------------------------------------------------
1 | """
2 | Demonstrate creation of a custom graphic (a candlestick plot)
3 |
4 | """
5 |
6 | import pyqtgraph as pg
7 | from pyqtgraph import QtCore, QtGui
8 |
9 |
10 | ## Create a subclass of GraphicsObject.
11 | ## The only required methods are paint() and boundingRect()
12 | ## (see QGraphicsItem documentation)
13 | class CandlestickItem(pg.GraphicsObject):
14 | def __init__(self, data):
15 | pg.GraphicsObject.__init__(self)
16 | self.data = data ## data must have fields: time, open, close, min, max
17 | self.generatePicture()
18 |
19 | def generatePicture(self):
20 | ## pre-computing a QPicture object allows paint() to run much more quickly,
21 | ## rather than re-drawing the shapes every time.
22 | self.picture = QtGui.QPicture()
23 | p = QtGui.QPainter(self.picture)
24 | p.setPen(pg.mkPen('w'))
25 | w = (self.data[1][0] - self.data[0][0]) / 3.
26 | for (t, open, close, min, max) in self.data:
27 | p.drawLine(QtCore.QPointF(t, min), QtCore.QPointF(t, max))
28 | if open > close:
29 | p.setBrush(pg.mkBrush('r'))
30 | else:
31 | p.setBrush(pg.mkBrush('g'))
32 | p.drawRect(QtCore.QRectF(t-w, open, w*2, close-open))
33 | p.end()
34 |
35 | def paint(self, p, *args):
36 | p.drawPicture(0, 0, self.picture)
37 |
38 | def boundingRect(self):
39 | ## boundingRect _must_ indicate the entire area that will be drawn on
40 | ## or else we will get artifacts and possibly crashing.
41 | ## (in this case, QPicture does all the work of computing the bouning rect for us)
42 | return QtCore.QRectF(self.picture.boundingRect())
43 |
44 | data = [ ## fields are (time, open, close, min, max).
45 | (1., 10, 13, 5, 15),
46 | (2., 13, 17, 9, 20),
47 | (3., 17, 14, 11, 23),
48 | (4., 14, 15, 5, 19),
49 | (5., 15, 9, 8, 22),
50 | (6., 9, 15, 8, 16),
51 | ]
52 | item = CandlestickItem(data)
53 | plt = pg.plot()
54 | plt.addItem(item)
55 | plt.setWindowTitle('pyqtgraph example: customGraphicsItem')
56 |
57 | if __name__ == '__main__':
58 | pg.exec()
59 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/cx_freeze/plotTest.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | import pyqtgraph as pg
4 | from pyqtgraph.Qt import QtWidgets
5 |
6 | # For packages that require scipy, these may be needed:
7 | # from scipy.stats import futil
8 | # from scipy.sparse.csgraph import _validation
9 |
10 | pg.setConfigOption('background','w')
11 | pg.setConfigOption('foreground','k')
12 | app = QtWidgets.QApplication(sys.argv)
13 |
14 | pw = pg.plot(x = [0, 1, 2, 4], y = [4, 5, 9, 6])
15 | pw.showGrid(x=True,y=True)
16 | text = pg.TextItem(html=' %s
' % "here",anchor=(0.0, 0.0))
17 | text.setPos(1.0, 5.0)
18 | pw.addItem(text)
19 | status = app.exec_()
20 | sys.exit(status)
21 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/cx_freeze/setup.py:
--------------------------------------------------------------------------------
1 | # Build with `python setup.py build_exe`
2 | import shutil
3 | from pathlib import Path
4 |
5 | from cx_Freeze import Executable, setup
6 |
7 | # Remove the build folder
8 | shutil.rmtree("build", ignore_errors=True)
9 | shutil.rmtree("dist", ignore_errors=True)
10 | import sys
11 |
12 | includes = ['pyqtgraph.graphicsItems',
13 | 'numpy', 'atexit']
14 | excludes = ['cvxopt','_gtkagg', '_tkagg', 'bsddb', 'curses', 'email', 'pywin.debugger',
15 | 'pywin.debugger.dbgcon', 'pywin.dialogs', 'tcl','tables',
16 | 'Tkconstants', 'Tkinter', 'zmq','PySide','pysideuic','scipy','matplotlib']
17 |
18 | # Workaround for making sure the templates are included in the frozen app package
19 | include_files = []
20 | import pyqtgraph
21 |
22 | pg_folder = Path(pyqtgraph.__file__).parent
23 | templates = pg_folder.rglob('*template*.py')
24 | sources = [str(w) for w in templates]
25 | destinations = ['lib' + w.replace(str(pg_folder.parent), '') for w in sources]
26 | for a in zip(sources, destinations):
27 | include_files.append(a)
28 |
29 | print(include_files)
30 |
31 | if sys.version[0] == '2':
32 | # causes syntax error on py2
33 | excludes.append('PyQt4.uic.port_v3')
34 |
35 | base = None
36 | if sys.platform == "win32":
37 | base = "Win32GUI"
38 |
39 | build_exe_options = {'excludes': excludes,
40 | 'includes':includes, 'include_msvcr':True,
41 | 'optimize':1, "include_files": include_files,}
42 |
43 | setup(name = "cx_freeze plot test",
44 | version = "0.2",
45 | description = "cx_freeze plot test",
46 | options = {"build_exe": build_exe_options},
47 | executables = [Executable("plotTest.py", base=base)])
48 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/designerExample.py:
--------------------------------------------------------------------------------
1 | """
2 | Simple example of loading UI template created with Qt Designer.
3 |
4 | This example uses uic.loadUiType to parse and load the ui at runtime. It is also
5 | possible to pre-compile the .ui file using pyuic (see VideoSpeedTest and
6 | ScatterPlotSpeedTest examples; these .ui files have been compiled with the
7 | tools/rebuildUi.py script).
8 | """
9 |
10 | import os
11 |
12 | import numpy as np
13 |
14 | import pyqtgraph as pg
15 |
16 | pg.mkQApp()
17 |
18 | ## Define main window class from template
19 | path = os.path.dirname(os.path.abspath(__file__))
20 | uiFile = os.path.join(path, 'designerExample.ui')
21 | WindowTemplate, TemplateBaseClass = pg.Qt.loadUiType(uiFile)
22 |
23 | class MainWindow(TemplateBaseClass):
24 | def __init__(self):
25 | TemplateBaseClass.__init__(self)
26 | self.setWindowTitle('pyqtgraph example: Qt Designer')
27 |
28 | # Create the main window
29 | self.ui = WindowTemplate()
30 | self.ui.setupUi(self)
31 | self.ui.plotBtn.clicked.connect(self.plot)
32 |
33 | self.show()
34 |
35 | def plot(self):
36 | self.ui.plot.plot(np.random.normal(size=100), clear=True)
37 |
38 | win = MainWindow()
39 |
40 | if __name__ == '__main__':
41 | pg.exec()
42 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/designerExample.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Form
4 |
5 |
6 |
7 | 0
8 | 0
9 | 400
10 | 300
11 |
12 |
13 |
14 | PyQtGraph
15 |
16 |
17 | -
18 |
19 |
20 | Plot!
21 |
22 |
23 |
24 | -
25 |
26 |
27 |
28 |
29 |
30 |
31 | PlotWidget
32 | QGraphicsView
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/histogram.py:
--------------------------------------------------------------------------------
1 | """
2 | In this example we draw two different kinds of histogram.
3 | """
4 |
5 | import numpy as np
6 |
7 | import pyqtgraph as pg
8 |
9 | win = pg.GraphicsLayoutWidget(show=True)
10 | win.resize(800,480)
11 | win.setWindowTitle('pyqtgraph example: Histogram')
12 | plt1 = win.addPlot()
13 | plt2 = win.addPlot()
14 |
15 | ## make interesting distribution of values
16 | vals = np.hstack([np.random.normal(size=500), np.random.normal(size=260, loc=4)])
17 |
18 | ## compute standard histogram
19 | y,x = np.histogram(vals, bins=np.linspace(-3, 8, 40))
20 |
21 | ## Using stepMode="center" causes the plot to draw two lines for each sample.
22 | ## notice that len(x) == len(y)+1
23 | plt1.plot(x, y, stepMode="center", fillLevel=0, fillOutline=True, brush=(0,0,255,150))
24 |
25 | ## Now draw all points as a nicely-spaced scatter plot
26 | psy = pg.pseudoScatter(vals, spacing=0.15)
27 | plt2.plot(vals, psy, pen=None, symbol='o', symbolSize=5, symbolPen=(255,255,255,200), symbolBrush=(0,0,255,150))
28 |
29 | # draw histogram using BarGraphItem
30 | win.nextRow()
31 | plt3 = win.addPlot()
32 | bgi = pg.BarGraphItem(x0=x[:-1], x1=x[1:], height=y, pen='w', brush=(0,0,255,150))
33 | plt3.addItem(bgi)
34 |
35 | if __name__ == '__main__':
36 | pg.exec()
37 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/infiniteline_performance.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 |
3 | import numpy as np
4 |
5 | import pyqtgraph as pg
6 | from pyqtgraph.Qt import QtCore
7 | from utils import FrameCounter
8 |
9 | app = pg.mkQApp("Infinite Line Performance")
10 |
11 | p = pg.plot()
12 | p.setWindowTitle('pyqtgraph performance: InfiniteLine')
13 | p.setRange(QtCore.QRectF(0, -10, 5000, 20))
14 | p.setLabel('bottom', 'Index', units='B')
15 | curve = p.plot()
16 |
17 | # Add a large number of horizontal InfiniteLine to plot
18 | for i in range(100):
19 | line = pg.InfiniteLine(pos=np.random.randint(5000), movable=True)
20 | p.addItem(line)
21 |
22 | data = np.random.normal(size=(50, 5000))
23 | ptr = 0
24 |
25 | def update():
26 | global ptr
27 | curve.setData(data[ptr % 10])
28 | ptr += 1
29 | framecnt.update()
30 |
31 |
32 | timer = QtCore.QTimer()
33 | timer.timeout.connect(update)
34 | timer.start(0)
35 |
36 | framecnt = FrameCounter()
37 | framecnt.sigFpsUpdate.connect(lambda fps: p.setTitle(f'{fps:.1f} fps'))
38 |
39 | if __name__ == '__main__':
40 | pg.exec()
41 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/isocurve.py:
--------------------------------------------------------------------------------
1 | """
2 | Tests use of IsoCurve item displayed with image
3 | """
4 |
5 | import numpy as np
6 |
7 | import pyqtgraph as pg
8 | from pyqtgraph.Qt import QtCore
9 |
10 | app = pg.mkQApp("Isocurve Example")
11 |
12 | ## make pretty looping data
13 | frames = 200
14 | data = np.random.normal(size=(frames,30,30), loc=0, scale=100)
15 | data = np.concatenate([data, data], axis=0)
16 | data = pg.gaussianFilter(data, (10, 10, 10))[frames//2:frames + frames//2]
17 | data[:, 15:16, 15:17] += 1
18 |
19 | win = pg.GraphicsLayoutWidget(show=True)
20 | win.setWindowTitle('pyqtgraph example: Isocurve')
21 | vb = win.addViewBox()
22 | img = pg.ImageItem(data[0])
23 | vb.addItem(img)
24 | vb.setAspectLocked()
25 |
26 | ## generate empty curves
27 | curves = []
28 | levels = np.linspace(data.min(), data.max(), 10)
29 | for i in range(len(levels)):
30 | v = levels[i]
31 | ## generate isocurve with automatic color selection
32 | c = pg.IsocurveItem(level=v, pen=(i, len(levels)*1.5))
33 | c.setParentItem(img) ## make sure isocurve is always correctly displayed over image
34 | c.setZValue(10)
35 | curves.append(c)
36 |
37 | ## animate!
38 | ptr = 0
39 | imgLevels = (data.min(), data.max() * 2)
40 | def update():
41 | global data, curves, img, ptr, imgLevels
42 | ptr = (ptr + 1) % data.shape[0]
43 | data[ptr]
44 | img.setImage(data[ptr], levels=imgLevels)
45 | for c in curves:
46 | c.setData(data[ptr])
47 |
48 | timer = QtCore.QTimer()
49 | timer.timeout.connect(update)
50 | timer.start(50)
51 |
52 | if __name__ == '__main__':
53 | pg.exec()
54 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/linkedViews.py:
--------------------------------------------------------------------------------
1 | """
2 | This example demonstrates the ability to link the axes of views together
3 | Views can be linked manually using the context menu, but only if they are given
4 | names.
5 | """
6 |
7 | import numpy as np
8 |
9 | import pyqtgraph as pg
10 |
11 | app = pg.mkQApp("Linked Views Example")
12 | #mw = QtWidgets.QMainWindow()
13 | #mw.resize(800,800)
14 |
15 | x = np.linspace(-50, 50, 1000)
16 | y = np.sin(x) / x
17 |
18 | win = pg.GraphicsLayoutWidget(show=True, title="pyqtgraph example: Linked Views")
19 | win.resize(800,600)
20 |
21 | win.addLabel("Linked Views", colspan=2)
22 | win.nextRow()
23 |
24 | p1 = win.addPlot(x=x, y=y, name="Plot1", title="Plot1")
25 | p2 = win.addPlot(x=x, y=y, name="Plot2", title="Plot2: Y linked with Plot1")
26 | p2.setLabel('bottom', "Label to test offset")
27 | p2.setYLink('Plot1') ## test linking by name
28 |
29 |
30 | ## create plots 3 and 4 out of order
31 | p4 = win.addPlot(x=x, y=y, name="Plot4", title="Plot4: X -> Plot3 (deferred), Y -> Plot1", row=2, col=1)
32 | p4.setXLink('Plot3') ## Plot3 has not been created yet, but this should still work anyway.
33 | p4.setYLink(p1)
34 | p3 = win.addPlot(x=x, y=y, name="Plot3", title="Plot3: X linked with Plot1", row=2, col=0)
35 | p3.setXLink(p1)
36 | p3.setLabel('left', "Label to test offset")
37 | #QtWidgets.QApplication.processEvents()
38 |
39 | if __name__ == '__main__':
40 | pg.exec()
41 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/logAxis.py:
--------------------------------------------------------------------------------
1 | """
2 | Demonstrate programmatic setting of log transformation modes.
3 | """
4 |
5 | import numpy as np
6 |
7 | import pyqtgraph as pg
8 |
9 | app = pg.mkQApp("Log Axis Example")
10 |
11 | w = pg.GraphicsLayoutWidget(show=True)
12 | w.resize(800,800)
13 | w.setWindowTitle('pyqtgraph example: Log Axis, or How to Recognise Different Types of Curves from Quite a Long Way Away')
14 |
15 | p0 = w.addPlot(0,0, title="Linear")
16 | p1 = w.addPlot(0,1, title="X Semilog")
17 | p2 = w.addPlot(1,0, title="Y Semilog")
18 | p3 = w.addPlot(1,1, title="XY Log")
19 | # configure logarithmic axis scaling:
20 | p1.setLogMode(True, False)
21 | p2.setLogMode(False, True)
22 | p3.setLogMode(True, True)
23 |
24 | # 1000 points from 0.1 to 10, chosen to give a compatible range of values across curves:
25 | x = np.logspace(-1, 1, 1000)
26 | plotdata = ( # legend entry, color, and plotted equation:
27 | ('1 / 3x' , '#ff9d47', 1./(3*x) ),
28 | ('sqrt x' , '#b3cf00', 1/np.sqrt(x) ),
29 | ('exp. decay', '#00a0b5', 5 * np.exp(-x/1) ),
30 | ('-log x' , '#a54dff', - np.log10(x) )
31 | )
32 | p0.addLegend(offset=(-20,20)) # include legend only in top left plot
33 | for p in (p0, p1, p2, p3): # draw identical numerical data in all four plots
34 | p.showGrid(True, True) # turn on grid for all four plots
35 | p.showAxes(True, size=(40,None)) # show a full frame, and reserve identical room for y labels
36 | for name, color, y in plotdata: # draw all four curves as defined in plotdata
37 | pen = pg.mkPen(color, width=2)
38 | p.plot( x,y, pen=pen, name=name )
39 |
40 | w.show()
41 |
42 | if __name__ == '__main__':
43 | pg.exec()
44 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/multiplePlotSpeedTest.py:
--------------------------------------------------------------------------------
1 | from time import perf_counter
2 |
3 | import numpy as np
4 |
5 | import pyqtgraph as pg
6 |
7 | app = pg.mkQApp()
8 | plt = pg.PlotWidget()
9 |
10 | app.processEvents()
11 |
12 | ## Putting this at the beginning or end does not have much effect
13 | plt.show()
14 |
15 | ## The auto-range is recomputed after each item is added,
16 | ## so disabling it before plotting helps
17 | plt.enableAutoRange(False, False)
18 |
19 | def plot():
20 | start = perf_counter()
21 | n = 15
22 | pts = 100
23 | x = np.linspace(0, 0.8, pts)
24 | y = np.random.random(size=pts)*0.8
25 | for i in range(n):
26 | for j in range(n):
27 | ## calling PlotWidget.plot() generates a PlotDataItem, which
28 | ## has a bit more overhead than PlotCurveItem, which is all
29 | ## we need here. This overhead adds up quickly and makes a big
30 | ## difference in speed.
31 |
32 | plt.addItem(pg.PlotCurveItem(x=x+i, y=y+j))
33 |
34 | dt = perf_counter() - start
35 | print(f"Create plots took: {dt * 1000:.3f} ms")
36 |
37 | ## Plot and clear 5 times, printing the time it took
38 | for _ in range(5):
39 | plt.clear()
40 | plot()
41 | app.processEvents()
42 | plt.autoRange()
43 |
44 |
45 |
46 |
47 |
48 | def fastPlot():
49 | ## Different approach: generate a single item with all data points.
50 | ## This runs many times faster.
51 | start = perf_counter()
52 | n = 15
53 | pts = 100
54 | x = np.linspace(0, 0.8, pts)
55 | y = np.random.random(size=pts)*0.8
56 | shape = (n, n, pts)
57 | xdata = np.empty(shape)
58 | xdata[:] = x + np.arange(shape[1]).reshape((1,-1,1))
59 | ydata = np.empty(shape)
60 | ydata[:] = y + np.arange(shape[0]).reshape((-1,1,1))
61 | conn = np.ones(shape, dtype=bool)
62 | conn[...,-1] = False # make sure plots are disconnected
63 | item = pg.PlotCurveItem()
64 | item.setData(xdata.ravel(), ydata.ravel(), connect=conn.ravel())
65 | plt.addItem(item)
66 |
67 | dt = perf_counter() - start
68 | print("Create plots took: %0.3fms" % (dt*1000))
69 |
70 |
71 | ## Plot and clear 5 times, printing the time it took
72 | for _ in range(5):
73 | plt.clear()
74 | fastPlot()
75 | app.processEvents()
76 | plt.autoRange()
77 |
78 | if __name__ == '__main__':
79 | pg.exec()
80 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/multiprocess.py:
--------------------------------------------------------------------------------
1 |
2 | import numpy as np
3 |
4 | import pyqtgraph as pg
5 | import pyqtgraph.multiprocess as mp
6 |
7 | print("\n=================\nStart Process")
8 | proc = mp.Process()
9 | import os
10 |
11 | print("parent:", os.getpid(), "child:", proc.proc.pid)
12 | print("started")
13 | rnp = proc._import('numpy')
14 | arr = rnp.array([1,2,3,4])
15 | print(repr(arr))
16 | print(str(arr))
17 | print("return value:", repr(arr.mean(_returnType='value')))
18 | print( "return proxy:", repr(arr.mean(_returnType='proxy')))
19 | print( "return auto: ", repr(arr.mean(_returnType='auto')))
20 | proc.join()
21 | print( "process finished")
22 |
23 |
24 |
25 | print( "\n=================\nStart ForkedProcess")
26 | proc = mp.ForkedProcess()
27 | rnp = proc._import('numpy')
28 | arr = rnp.array([1,2,3,4])
29 | print( repr(arr))
30 | print( str(arr))
31 | print( repr(arr.mean()))
32 | proc.join()
33 | print( "process finished")
34 |
35 |
36 |
37 |
38 | import pyqtgraph as pg
39 |
40 | app = pg.mkQApp("Multiprocess Example")
41 |
42 | print( "\n=================\nStart QtProcess")
43 | import sys
44 |
45 | if (sys.flags.interactive != 1):
46 | print( " (not interactive; remote process will exit immediately.)")
47 | proc = mp.QtProcess()
48 | d1 = proc.transfer(np.random.normal(size=1000))
49 | d2 = proc.transfer(np.random.normal(size=1000))
50 | rpg = proc._import('pyqtgraph')
51 | plt = rpg.plot(d1+d2)
52 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/optics/__init__.py:
--------------------------------------------------------------------------------
1 | from .pyoptic import *
2 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/optics/schott_glasses.csv.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PANOimagen/profiletool/0fec10efe93ce437eec7c6128869c1b997e8a836/pyqtgraph/examples/optics/schott_glasses.csv.gz
--------------------------------------------------------------------------------
/pyqtgraph/examples/parallelize.py:
--------------------------------------------------------------------------------
1 | import time
2 |
3 | import pyqtgraph as pg
4 | import pyqtgraph.multiprocess as mp
5 |
6 | print( "\n=================\nParallelize")
7 |
8 | ## Do a simple task:
9 | ## for x in range(N):
10 | ## sum([x*i for i in range(M)])
11 | ##
12 | ## We'll do this three times
13 | ## - once without Parallelize
14 | ## - once with Parallelize, but forced to use a single worker
15 | ## - once with Parallelize automatically determining how many workers to use
16 | ##
17 |
18 | tasks = range(10)
19 | results = [None] * len(tasks)
20 | results2 = results[:]
21 | results3 = results[:]
22 | size = 2000000
23 |
24 | pg.mkQApp()
25 |
26 | ### Purely serial processing
27 | start = time.time()
28 | with pg.ProgressDialog('processing serially..', maximum=len(tasks)) as dlg:
29 | for i, x in enumerate(tasks):
30 | tot = 0
31 | for j in range(size):
32 | tot += j * x
33 | results[i] = tot
34 | dlg += 1
35 | if dlg.wasCanceled():
36 | raise Exception('processing canceled')
37 | print( "Serial time: %0.2f" % (time.time() - start))
38 |
39 | ### Use parallelize, but force a single worker
40 | ### (this simulates the behavior seen on windows, which lacks os.fork)
41 | start = time.time()
42 | with mp.Parallelize(enumerate(tasks), results=results2, workers=1, progressDialog='processing serially (using Parallelizer)..') as tasker:
43 | for i, x in tasker:
44 | tot = 0
45 | for j in range(size):
46 | tot += j * x
47 | tasker.results[i] = tot
48 | print( "\nParallel time, 1 worker: %0.2f" % (time.time() - start))
49 | print( "Results match serial: %s" % str(results2 == results))
50 |
51 | ### Use parallelize with multiple workers
52 | start = time.time()
53 | with mp.Parallelize(enumerate(tasks), results=results3, progressDialog='processing in parallel..') as tasker:
54 | for i, x in tasker:
55 | tot = 0
56 | for j in range(size):
57 | tot += j * x
58 | tasker.results[i] = tot
59 | print( "\nParallel time, %d workers: %0.2f" % (mp.Parallelize.suggestedWorkerCount(), time.time() - start))
60 | print( "Results match serial: %s" % str(results3 == results))
61 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/py2exe/plotTest.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | import pyqtgraph as pg
4 |
5 | # For packages that require scipy, these may be needed:
6 | # from scipy.stats import futil
7 | # from scipy.sparse.csgraph import _validation
8 |
9 | pg.setConfigOption('background','w')
10 | pg.setConfigOption('foreground','k')
11 | app = QtWidgets.QApplication(sys.argv)
12 |
13 | pw = pg.plot(x = [0, 1, 2, 4], y = [4, 5, 9, 6])
14 | pw.showGrid(x=True,y=True)
15 | text = pg.TextItem(html=' %s
' % "here",anchor=(0.0, 0.0))
16 | text.setPos(1.0, 5.0)
17 | pw.addItem(text)
18 | status = app.exec_()
19 | sys.exit(status)
20 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/py2exe/setup.py:
--------------------------------------------------------------------------------
1 | import shutil
2 | from distutils.core import setup
3 |
4 | # Remove the build folder
5 | shutil.rmtree("build", ignore_errors=True)
6 | shutil.rmtree("dist", ignore_errors=True)
7 | import sys
8 |
9 | includes = ['PyQt4', 'PyQt4.QtGui', 'PyQt4.QtSvg', 'sip', 'pyqtgraph.graphicsItems']
10 | excludes = ['_gtkagg', '_tkagg', 'bsddb', 'curses', 'email', 'pywin.debugger',
11 | 'pywin.debugger.dbgcon', 'pywin.dialogs', 'tcl',
12 | 'Tkconstants', 'Tkinter', 'zmq']
13 | if sys.version[0] == '2':
14 | # causes syntax error on py2
15 | excludes.append('PyQt4.uic.port_v3')
16 |
17 | packages = []
18 | dll_excludes = ['libgdk-win32-2.0-0.dll', 'libgobject-2.0-0.dll', 'tcl84.dll',
19 | 'tk84.dll', 'MSVCP90.dll']
20 | icon_resources = []
21 | bitmap_resources = []
22 | other_resources = []
23 | data_files = []
24 | setup(
25 | data_files=data_files,
26 | console=['plotTest.py'] ,
27 | options={"py2exe": {"excludes": excludes,
28 | "includes": includes,
29 | "dll_excludes": dll_excludes,
30 | "optimize": 0,
31 | "compressed": 2,
32 | "bundle_files": 1}},
33 | zipfile=None,
34 | )
35 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/relativity/__init__.py:
--------------------------------------------------------------------------------
1 | from .relativity import *
2 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/relativity_demo.py:
--------------------------------------------------------------------------------
1 | """
2 | Special relativity simulation
3 | """
4 |
5 | from relativity import RelativityGUI
6 |
7 | import pyqtgraph as pg
8 |
9 | pg.mkQApp()
10 | win = RelativityGUI()
11 | win.setWindowTitle("Relativity!")
12 | win.resize(1100,700)
13 | win.show()
14 | win.loadPreset(None, 'Twin Paradox (grid)')
15 |
16 | if __name__ == '__main__':
17 | pg.exec()
18 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/template.py:
--------------------------------------------------------------------------------
1 | """
2 | Description of example
3 | """
4 |
5 | import numpy as np
6 |
7 | import pyqtgraph as pg
8 | from pyqtgraph.Qt import QtCore, QtGui, QtWidgets, mkQApp
9 |
10 | app = mkQApp()
11 |
12 | # win.setWindowTitle('pyqtgraph example: ____')
13 |
14 | if __name__ == '__main__':
15 | pg.exec()
16 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/text.py:
--------------------------------------------------------------------------------
1 | """
2 | This example shows how to insert text into a scene using TextItem. This class
3 | is for displaying text that is anchored to a particular location in the data
4 | coordinate system, but which is always displayed unscaled.
5 |
6 | For text that scales with the data, use QTextItem.
7 | For text that can be placed in a layout, use LabelItem.
8 | """
9 |
10 | import numpy as np
11 |
12 | import pyqtgraph as pg
13 | from pyqtgraph.Qt import QtCore
14 |
15 | x = np.linspace(-20, 20, 1000)
16 | y = np.sin(x) / x
17 | plot = pg.plot() ## create an empty plot widget
18 | plot.setYRange(-1, 2)
19 | plot.setWindowTitle('pyqtgraph example: text')
20 | curve = plot.plot(x,y) ## add a single curve
21 |
22 | ## Create text object, use HTML tags to specify color/size
23 | text = pg.TextItem(html='This is the
PEAK
', anchor=(-0.3,0.5), angle=45, border='w', fill=(0, 0, 255, 100))
24 | plot.addItem(text)
25 | text.setPos(0, y.max())
26 |
27 | ## Draw an arrowhead next to the text box
28 | arrow = pg.ArrowItem(pos=(0, y.max()), angle=-45)
29 | plot.addItem(arrow)
30 |
31 |
32 | ## Set up an animated arrow and text that track the curve
33 | curvePoint = pg.CurvePoint(curve)
34 | plot.addItem(curvePoint)
35 | text2 = pg.TextItem("test", anchor=(0.5, -1.0))
36 | text2.setParentItem(curvePoint)
37 | arrow2 = pg.ArrowItem(angle=90)
38 | arrow2.setParentItem(curvePoint)
39 |
40 | ## update position every 10ms
41 | index = 0
42 | def update():
43 | global curvePoint, index
44 | index = (index + 1) % len(x)
45 | curvePoint.setPos(float(index)/(len(x)-1))
46 | text2.setText('[%0.1f, %0.1f]' % (x[index], y[index]))
47 |
48 | timer = QtCore.QTimer()
49 | timer.timeout.connect(update)
50 | timer.start(10)
51 |
52 | if __name__ == '__main__':
53 | pg.exec()
54 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/verlet_chain/__init__.py:
--------------------------------------------------------------------------------
1 | from .chain import ChainSim
2 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/verlet_chain/make:
--------------------------------------------------------------------------------
1 | gcc -fPIC -c relax.c
2 | gcc -shared -o maths.so relax.o
3 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/verlet_chain/relax.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | void relax(
5 | double* pos,
6 | long* links,
7 | double* mrel1,
8 | double* mrel2,
9 | double* lengths,
10 | char* push,
11 | char* pull,
12 | int nlinks,
13 | int iters)
14 | {
15 | int i, l, p1, p2;
16 | double x1, x2, y1, y2, dx, dy, dist, change;
17 | // printf("%d, %d\n", iters, nlinks);
18 | for( i=0; i lengths[l] )
36 | dist = lengths[l];
37 |
38 | change = (lengths[l]-dist) / dist;
39 | dx *= change;
40 | dy *= change;
41 |
42 | pos[p1] -= mrel2[l] * dx;
43 | pos[p1+1] -= mrel2[l] * dy;
44 | pos[p2] += mrel1[l] * dx;
45 | pos[p2+1] += mrel1[l] * dy;
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/pyqtgraph/examples/verlet_chain/relax.py:
--------------------------------------------------------------------------------
1 | import ctypes
2 | import os
3 |
4 | so = os.path.join(os.path.dirname(__file__), 'maths.so')
5 | try:
6 | lib = ctypes.CDLL(so)
7 | COMPILED = True
8 | except OSError:
9 | COMPILED = False
10 |
11 |
12 | if COMPILED:
13 | lib.relax.argtypes = [
14 | ctypes.c_void_p,
15 | ctypes.c_void_p,
16 | ctypes.c_void_p,
17 | ctypes.c_void_p,
18 | ctypes.c_void_p,
19 | ctypes.c_void_p,
20 | ctypes.c_void_p,
21 | ctypes.c_int,
22 | ctypes.c_int,
23 | ]
24 |
25 | def relax(pos, links, mrel1, mrel2, lengths, push, pull, iters):
26 | nlinks = links.shape[0]
27 | lib.relax(pos.ctypes, links.ctypes, mrel1.ctypes, mrel2.ctypes, lengths.ctypes, push.ctypes, pull.ctypes, nlinks, iters)
28 |
29 | else:
30 | def relax(pos, links, mrel1, mrel2, lengths, push, pull, iters):
31 | lengths2 = lengths**2
32 | for i in range(iters):
33 | #p1 = links[:, 0]
34 | #p2 = links[:, 1]
35 | #x1 = pos[p1]
36 | #x2 = pos[p2]
37 |
38 | #dx = x2 - x1
39 |
40 | #dist = (dx**2).sum(axis=1)**0.5
41 |
42 | #mask = (npush & (dist < lengths)) | (npull & (dist > lengths))
43 | ##dist[mask] = lengths[mask]
44 | #change = (lengths-dist) / dist
45 | #change[mask] = 0
46 |
47 | #dx *= change[:, np.newaxis]
48 | #print dx
49 |
50 | ##pos[p1] -= mrel2 * dx
51 | ##pos[p2] += mrel1 * dx
52 | #for j in range(links.shape[0]):
53 | #pos[links[j,0]] -= mrel2[j] * dx[j]
54 | #pos[links[j,1]] += mrel1[j] * dx[j]
55 |
56 |
57 | for l in range(links.shape[0]):
58 | p1, p2 = links[l];
59 | x1 = pos[p1]
60 | x2 = pos[p2]
61 |
62 | dx = x2 - x1
63 | dist2 = (dx**2).sum()
64 |
65 | if (push[l] and dist2 < lengths2[l]) or (pull[l] and dist2 > lengths2[l]):
66 | dist = dist2 ** 0.5
67 | change = (lengths[l]-dist) / dist
68 | dx *= change
69 | pos[p1] -= mrel2[l] * dx
70 | pos[p2] += mrel1[l] * dx
71 |
--------------------------------------------------------------------------------
/pyqtgraph/exporters/__init__.py:
--------------------------------------------------------------------------------
1 | from .CSVExporter import *
2 | from .Exporter import Exporter
3 | from .HDF5Exporter import *
4 | from .ImageExporter import *
5 | from .Matplotlib import *
6 | from .PrintExporter import *
7 | from .SVGExporter import *
8 |
9 |
10 | def listExporters():
11 | return Exporter.Exporters[:]
12 |
--------------------------------------------------------------------------------
/pyqtgraph/flowchart/FlowchartGraphicsView.py:
--------------------------------------------------------------------------------
1 | from ..graphicsItems.ViewBox import ViewBox
2 | from ..Qt import QtCore, QtGui, QtWidgets
3 | from ..widgets.GraphicsView import GraphicsView
4 |
5 | translate = QtCore.QCoreApplication.translate
6 |
7 | class FlowchartGraphicsView(GraphicsView):
8 |
9 | sigHoverOver = QtCore.Signal(object)
10 | sigClicked = QtCore.Signal(object)
11 |
12 | def __init__(self, widget, *args):
13 | GraphicsView.__init__(self, *args, useOpenGL=False)
14 | self._vb = FlowchartViewBox(widget, lockAspect=True, invertY=True)
15 | self.setCentralItem(self._vb)
16 | self.setRenderHint(QtGui.QPainter.RenderHint.Antialiasing, True)
17 |
18 | def viewBox(self):
19 | return self._vb
20 |
21 |
22 | class FlowchartViewBox(ViewBox):
23 |
24 | def __init__(self, widget, *args, **kwargs):
25 | ViewBox.__init__(self, *args, **kwargs)
26 | self.widget = widget
27 |
28 | def getMenu(self, ev):
29 | ## called by ViewBox to create a new context menu
30 | self._fc_menu = QtWidgets.QMenu()
31 | self._subMenus = self.getContextMenus(ev)
32 | for menu in self._subMenus:
33 | self._fc_menu.addMenu(menu)
34 | return self._fc_menu
35 |
36 | def getContextMenus(self, ev):
37 | ## called by scene to add menus on to someone else's context menu
38 | menu = self.widget.buildMenu(ev.scenePos())
39 | menu.setTitle(translate("Context Menu", "Add node"))
40 | return [menu, ViewBox.getMenu(self, ev)]
41 |
--------------------------------------------------------------------------------
/pyqtgraph/flowchart/__init__.py:
--------------------------------------------------------------------------------
1 | from .Flowchart import *
2 | from .library import getNodeTree, getNodeType, registerNodeType
3 |
--------------------------------------------------------------------------------
/pyqtgraph/flowchart/library/__init__.py:
--------------------------------------------------------------------------------
1 | from ..NodeLibrary import NodeLibrary, isNodeClass
2 | from . import Data, Display, Filters, Operators
3 |
4 | # Build default library
5 | LIBRARY = NodeLibrary()
6 |
7 | # For backward compatibility, expose the default library's properties here:
8 | NODE_LIST = LIBRARY.nodeList
9 | NODE_TREE = LIBRARY.nodeTree
10 | registerNodeType = LIBRARY.addNodeType
11 | getNodeTree = LIBRARY.getNodeTree
12 | getNodeType = LIBRARY.getNodeType
13 |
14 | # Add all nodes to the default library
15 | for mod in [Data, Display, Filters, Operators]:
16 | nodes = [getattr(mod, name) for name in dir(mod) if isNodeClass(getattr(mod, name))]
17 | for node in nodes:
18 | LIBRARY.addNodeType(node, [(mod.__name__.split('.')[-1],)])
19 |
20 |
--------------------------------------------------------------------------------
/pyqtgraph/frozenSupport.py:
--------------------------------------------------------------------------------
1 | ## Definitions helpful in frozen environments (eg py2exe)
2 | import os
3 | import sys
4 | import zipfile
5 |
6 |
7 | def listdir(path):
8 | """Replacement for os.listdir that works in frozen environments."""
9 | if not hasattr(sys, 'frozen'):
10 | return os.listdir(path)
11 |
12 | (zipPath, archivePath) = splitZip(path)
13 | if archivePath is None:
14 | return os.listdir(path)
15 |
16 | with zipfile.ZipFile(zipPath, "r") as zipobj:
17 | contents = zipobj.namelist()
18 | results = set()
19 | for name in contents:
20 | # components in zip archive paths are always separated by forward slash
21 | if name.startswith(archivePath) and len(name) > len(archivePath):
22 | name = name[len(archivePath):].split('/')[0]
23 | results.add(name)
24 | return list(results)
25 |
26 | def isdir(path):
27 | """Replacement for os.path.isdir that works in frozen environments."""
28 | if not hasattr(sys, 'frozen'):
29 | return os.path.isdir(path)
30 |
31 | (zipPath, archivePath) = splitZip(path)
32 | if archivePath is None:
33 | return os.path.isdir(path)
34 | with zipfile.ZipFile(zipPath, "r") as zipobj:
35 | contents = zipobj.namelist()
36 | archivePath = archivePath.rstrip('/') + '/' ## make sure there's exactly one '/' at the end
37 | for c in contents:
38 | if c.startswith(archivePath):
39 | return True
40 | return False
41 |
42 |
43 | def splitZip(path):
44 | """Splits a path containing a zip file into (zipfile, subpath).
45 | If there is no zip file, returns (path, None)"""
46 | components = os.path.normpath(path).split(os.sep)
47 | for index, component in enumerate(components):
48 | if component.endswith('.zip'):
49 | zipPath = os.sep.join(components[0:index+1])
50 | archivePath = ''.join([x+'/' for x in components[index+1:]])
51 | return (zipPath, archivePath)
52 | else:
53 | return (path, None)
54 |
55 |
56 |
--------------------------------------------------------------------------------
/pyqtgraph/functions_numba.py:
--------------------------------------------------------------------------------
1 | import numba
2 | import numpy as np
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_lookup(data, scale, offset, lut):
26 | # data should be floating point and 2d
27 | # lut is 1d
28 | vmin, vmax = 0, lut.shape[0] - 1
29 | out = np.empty_like(data, dtype=lut.dtype)
30 | for (x, y) in np.nditer((data, out)):
31 | val = (x - offset) * scale
32 | val = min(max(val, vmin), vmax)
33 | y[...] = lut[int(val)]
34 | return out
35 |
36 | @numba.jit(nopython=True)
37 | def rescale_and_clip(data, scale, offset, vmin, vmax):
38 | # vmin and vmax <= 255
39 | out = np.empty_like(data, dtype=np.uint8)
40 | for (x, y) in np.nditer((data, out)):
41 | val = (x - offset) * scale
42 | val = min(max(val, vmin), vmax)
43 | y[...] = val
44 | return out
45 |
46 | @numba.jit(nopython=True)
47 | def numba_take(lut, data):
48 | # numba supports only the 1st two arguments of np.take
49 | return np.take(lut, data)
50 |
--------------------------------------------------------------------------------
/pyqtgraph/graphicsItems/ButtonItem.py:
--------------------------------------------------------------------------------
1 | from ..Qt import QtCore, QtGui
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 | self._width = width
19 | if self._width is None:
20 | self._width = self.pixmap.width() / self.pixmap.devicePixelRatio()
21 |
22 | if parentItem is not None:
23 | self.setParentItem(parentItem)
24 | self.setOpacity(0.7)
25 |
26 | def setImageFile(self, imageFile):
27 | self.setPixmap(QtGui.QPixmap(imageFile))
28 |
29 | def setPixmap(self, pixmap):
30 | self.pixmap = pixmap
31 | self.update()
32 |
33 | def mouseClickEvent(self, ev):
34 | if self.enabled:
35 | self.clicked.emit(self)
36 |
37 | def hoverEvent(self, ev):
38 | if not self.enabled:
39 | return
40 | if ev.isEnter():
41 | self.setOpacity(1.0)
42 | elif ev.isExit():
43 | self.setOpacity(0.7)
44 |
45 | def disable(self):
46 | self.enabled = False
47 | self.setOpacity(0.4)
48 |
49 | def enable(self):
50 | self.enabled = True
51 | self.setOpacity(0.7)
52 |
53 | def paint(self, p, *args):
54 | p.setRenderHint(p.RenderHint.Antialiasing)
55 | tgtRect = QtCore.QRectF(0, 0, self._width, self._width)
56 | srcRect = QtCore.QRectF(self.pixmap.rect())
57 | p.drawPixmap(tgtRect, self.pixmap, srcRect)
58 |
59 | def boundingRect(self):
60 | return QtCore.QRectF(0, 0, self._width, self._width)
61 |
62 |
--------------------------------------------------------------------------------
/pyqtgraph/graphicsItems/GradientPresets.py:
--------------------------------------------------------------------------------
1 | __all__ = ['Gradients']
2 |
3 |
4 | Gradients = dict([
5 | ('thermal', {'ticks': [(0.3333, (185, 0, 0, 255)), (0.6666, (255, 220, 0, 255)), (1, (255, 255, 255, 255)), (0, (0, 0, 0, 255))], 'mode': 'rgb'}),
6 | ('flame', {'ticks': [(0.2, (7, 0, 220, 255)), (0.5, (236, 0, 134, 255)), (0.8, (246, 246, 0, 255)), (1.0, (255, 255, 255, 255)), (0.0, (0, 0, 0, 255))], 'mode': 'rgb'}),
7 | ('yellowy', {'ticks': [(0.0, (0, 0, 0, 255)), (0.2328863796753704, (32, 0, 129, 255)), (0.8362738179251941, (255, 255, 0, 255)), (0.5257586450247, (115, 15, 255, 255)), (1.0, (255, 255, 255, 255))], 'mode': 'rgb'} ),
8 | ('bipolar', {'ticks': [(0.0, (0, 255, 255, 255)), (1.0, (255, 255, 0, 255)), (0.5, (0, 0, 0, 255)), (0.25, (0, 0, 255, 255)), (0.75, (255, 0, 0, 255))], 'mode': 'rgb'}),
9 | ('spectrum', {'ticks': [(1.0, (255, 0, 255, 255)), (0.0, (255, 0, 0, 255))], 'mode': 'hsv'}),
10 | ('cyclic', {'ticks': [(0.0, (255, 0, 4, 255)), (1.0, (255, 0, 0, 255))], 'mode': 'hsv'}),
11 | ('greyclip', {'ticks': [(0.0, (0, 0, 0, 255)), (0.99, (255, 255, 255, 255)), (1.0, (255, 0, 0, 255))], 'mode': 'rgb'}),
12 | ('grey', {'ticks': [(0.0, (0, 0, 0, 255)), (1.0, (255, 255, 255, 255))], 'mode': 'rgb'}),
13 | # Perceptually uniform sequential colormaps from Matplotlib 2.0
14 | ('viridis', {'ticks': [(0.0, (68, 1, 84, 255)), (0.25, (58, 82, 139, 255)), (0.5, (32, 144, 140, 255)), (0.75, (94, 201, 97, 255)), (1.0, (253, 231, 36, 255))], 'mode': 'rgb'}),
15 | ('inferno', {'ticks': [(0.0, (0, 0, 3, 255)), (0.25, (87, 15, 109, 255)), (0.5, (187, 55, 84, 255)), (0.75, (249, 142, 8, 255)), (1.0, (252, 254, 164, 255))], 'mode': 'rgb'}),
16 | ('plasma', {'ticks': [(0.0, (12, 7, 134, 255)), (0.25, (126, 3, 167, 255)), (0.5, (203, 71, 119, 255)), (0.75, (248, 149, 64, 255)), (1.0, (239, 248, 33, 255))], 'mode': 'rgb'}),
17 | ('magma', {'ticks': [(0.0, (0, 0, 3, 255)), (0.25, (80, 18, 123, 255)), (0.5, (182, 54, 121, 255)), (0.75, (251, 136, 97, 255)), (1.0, (251, 252, 191, 255))], 'mode': 'rgb'}),
18 | # turbo from https://ai.googleblog.com/2019/08/turbo-improved-rainbow-colormap-for.html
19 | ('turbo', {'ticks': [(0.0, (51, 27, 61, 255)), (0.125, (77, 110, 223, 255)), (0.25, (61, 185, 233, 255)), (0.375, (68, 238, 154, 255)), (0.5, (164, 250, 80, 255)),
20 | (0.625, (235, 206, 76, 255)), (0.75, (247, 129, 55, 255)), (0.875, (206, 58, 32, 255)), (1.0, (119, 21, 19, 255))], 'mode': 'rgb'}),
21 | ])
22 |
--------------------------------------------------------------------------------
/pyqtgraph/graphicsItems/GraphicsObject.py:
--------------------------------------------------------------------------------
1 | import warnings
2 | from ..Qt import QT_LIB, QtCore, QtWidgets
3 | from .GraphicsItem import GraphicsItem
4 |
5 | __all__ = ['GraphicsObject']
6 | class GraphicsObject(GraphicsItem, QtWidgets.QGraphicsObject):
7 | """
8 | **Bases:** :class:`GraphicsItem `, :class:`QtWidgets.QGraphicsObject`
9 |
10 | Extension of QGraphicsObject with some useful methods (provided by :class:`GraphicsItem `)
11 | """
12 | _qtBaseClass = QtWidgets.QGraphicsObject
13 | def __init__(self, *args):
14 | self.__inform_view_on_changes = True
15 | QtWidgets.QGraphicsObject.__init__(self, *args)
16 | self.setFlag(self.GraphicsItemFlag.ItemSendsGeometryChanges)
17 | GraphicsItem.__init__(self)
18 |
19 | def itemChange(self, change, value):
20 | ret = super().itemChange(change, value)
21 | if change in [self.GraphicsItemChange.ItemParentHasChanged, self.GraphicsItemChange.ItemSceneHasChanged]:
22 | if self.__class__.__dict__.get('parentChanged') is not None:
23 | # user's GraphicsObject subclass has a parentChanged() method
24 | warnings.warn(
25 | "parentChanged() is deprecated and will be removed in the future. "
26 | "Use changeParent() instead.",
27 | DeprecationWarning, stacklevel=2
28 | )
29 | if QT_LIB == 'PySide6' and QtCore.__version_info__ == (6, 2, 2):
30 | # workaround PySide6 6.2.2 issue https://bugreports.qt.io/browse/PYSIDE-1730
31 | # note that the bug exists also in PySide6 6.2.2.1 / Qt 6.2.2
32 | getattr(self.__class__, 'parentChanged')(self)
33 | else:
34 | self.parentChanged()
35 | else:
36 | self.changeParent()
37 | try:
38 | inform_view_on_change = self.__inform_view_on_changes
39 | except AttributeError:
40 | # It's possible that the attribute was already collected when the itemChange happened
41 | # (if it was triggered during the gc of the object).
42 | pass
43 | else:
44 | if inform_view_on_change and change in [self.GraphicsItemChange.ItemPositionHasChanged, self.GraphicsItemChange.ItemTransformHasChanged]:
45 | self.informViewBoundsChanged()
46 |
47 | return ret
48 |
--------------------------------------------------------------------------------
/pyqtgraph/graphicsItems/ItemGroup.py:
--------------------------------------------------------------------------------
1 | from ..Qt import QtCore
2 | from .GraphicsObject import GraphicsObject
3 |
4 | __all__ = ['ItemGroup']
5 | class ItemGroup(GraphicsObject):
6 | """
7 | Replacement for QGraphicsItemGroup
8 | """
9 |
10 | def __init__(self, *args):
11 | GraphicsObject.__init__(self, *args)
12 | self.setFlag(self.GraphicsItemFlag.ItemHasNoContents)
13 |
14 | def boundingRect(self):
15 | return QtCore.QRectF()
16 |
17 | def paint(self, *args):
18 | pass
19 |
20 | def addItem(self, item):
21 | item.setParentItem(self)
22 |
--------------------------------------------------------------------------------
/pyqtgraph/graphicsItems/PlotItem/__init__.py:
--------------------------------------------------------------------------------
1 | from .PlotItem import PlotItem
2 |
3 | __all__ = ['PlotItem']
4 |
--------------------------------------------------------------------------------
/pyqtgraph/graphicsItems/ViewBox/__init__.py:
--------------------------------------------------------------------------------
1 | from .ViewBox import ViewBox
2 |
3 | __all__ = ['ViewBox']
4 |
--------------------------------------------------------------------------------
/pyqtgraph/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 |
--------------------------------------------------------------------------------
/pyqtgraph/icons/__init__.py:
--------------------------------------------------------------------------------
1 | import os.path as op
2 | import warnings
3 |
4 | from ..Qt import QtGui, QtWidgets
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 | # Note: List all graph icons here ...
63 | auto = GraphIcon("auto.png")
64 | ctrl = GraphIcon("ctrl.png")
65 | default = GraphIcon("default.png")
66 | invisibleEye = GraphIcon("invisibleEye.svg")
67 | lock = GraphIcon("lock.png")
68 |
--------------------------------------------------------------------------------
/pyqtgraph/icons/auto.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PANOimagen/profiletool/0fec10efe93ce437eec7c6128869c1b997e8a836/pyqtgraph/icons/auto.png
--------------------------------------------------------------------------------
/pyqtgraph/icons/ctrl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PANOimagen/profiletool/0fec10efe93ce437eec7c6128869c1b997e8a836/pyqtgraph/icons/ctrl.png
--------------------------------------------------------------------------------
/pyqtgraph/icons/default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PANOimagen/profiletool/0fec10efe93ce437eec7c6128869c1b997e8a836/pyqtgraph/icons/default.png
--------------------------------------------------------------------------------
/pyqtgraph/icons/lock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PANOimagen/profiletool/0fec10efe93ce437eec7c6128869c1b997e8a836/pyqtgraph/icons/lock.png
--------------------------------------------------------------------------------
/pyqtgraph/icons/peegee/peegee_128px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PANOimagen/profiletool/0fec10efe93ce437eec7c6128869c1b997e8a836/pyqtgraph/icons/peegee/peegee_128px.png
--------------------------------------------------------------------------------
/pyqtgraph/icons/peegee/peegee_128px@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PANOimagen/profiletool/0fec10efe93ce437eec7c6128869c1b997e8a836/pyqtgraph/icons/peegee/peegee_128px@2x.png
--------------------------------------------------------------------------------
/pyqtgraph/icons/peegee/peegee_192px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PANOimagen/profiletool/0fec10efe93ce437eec7c6128869c1b997e8a836/pyqtgraph/icons/peegee/peegee_192px.png
--------------------------------------------------------------------------------
/pyqtgraph/icons/peegee/peegee_256px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PANOimagen/profiletool/0fec10efe93ce437eec7c6128869c1b997e8a836/pyqtgraph/icons/peegee/peegee_256px.png
--------------------------------------------------------------------------------
/pyqtgraph/icons/peegee/peegee_256px@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PANOimagen/profiletool/0fec10efe93ce437eec7c6128869c1b997e8a836/pyqtgraph/icons/peegee/peegee_256px@2x.png
--------------------------------------------------------------------------------
/pyqtgraph/icons/peegee/peegee_512px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PANOimagen/profiletool/0fec10efe93ce437eec7c6128869c1b997e8a836/pyqtgraph/icons/peegee/peegee_512px.png
--------------------------------------------------------------------------------
/pyqtgraph/icons/peegee/peegee_512px@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PANOimagen/profiletool/0fec10efe93ce437eec7c6128869c1b997e8a836/pyqtgraph/icons/peegee/peegee_512px@2x.png
--------------------------------------------------------------------------------
/pyqtgraph/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 |
--------------------------------------------------------------------------------
/pyqtgraph/jupyter/__init__.py:
--------------------------------------------------------------------------------
1 | from .GraphicsView import GraphicsLayoutWidget
2 | from .GraphicsView import PlotWidget
3 |
4 |
--------------------------------------------------------------------------------
/pyqtgraph/metaarray/__init__.py:
--------------------------------------------------------------------------------
1 | from .MetaArray import *
2 |
--------------------------------------------------------------------------------
/pyqtgraph/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 |
--------------------------------------------------------------------------------
/pyqtgraph/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 |
--------------------------------------------------------------------------------
/pyqtgraph/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 .parallelizer import CanceledError, Parallelize
23 | from .processes import *
24 | from .remoteproxy import ClosedError, NoResultError, proxy
25 |
--------------------------------------------------------------------------------
/pyqtgraph/multiprocess/bootstrap.py:
--------------------------------------------------------------------------------
1 | """For starting up remote processes"""
2 | import importlib
3 | import os
4 | import pickle
5 | import sys
6 |
7 | if __name__ == '__main__':
8 | if hasattr(os, 'setpgrp'):
9 | os.setpgrp() ## prevents signals (notably keyboard interrupt) being forwarded from parent to this process
10 | #name, port, authkey, ppid, targetStr, path, pyside = pickle.load(sys.stdin.buffer)
11 | opts = pickle.load(sys.stdin.buffer)
12 | #print "key:", ' '.join([str(ord(x)) for x in authkey])
13 | path = opts.pop('path', None)
14 | if path is not None:
15 | if isinstance(path, str):
16 | # if string, just insert this into the path
17 | sys.path.insert(0, path)
18 | else:
19 | # if list, then replace the entire sys.path
20 | ## modify sys.path in place--no idea who already has a reference to the existing list.
21 | while len(sys.path) > 0:
22 | sys.path.pop()
23 | sys.path.extend(path)
24 |
25 | qt_lib = opts.pop('qt_lib', None)
26 | if qt_lib is not None:
27 | globals()[qt_lib] = importlib.import_module(qt_lib)
28 |
29 | targetStr = opts.pop('targetStr')
30 | try:
31 | target = pickle.loads(targetStr) ## unpickling the target should import everything we need
32 | except:
33 | print("Current sys.path:", sys.path)
34 | raise
35 | target(**opts) ## Send all other options to the target function
36 | sys.exit(0)
37 |
--------------------------------------------------------------------------------
/pyqtgraph/opengl/__init__.py:
--------------------------------------------------------------------------------
1 | from . import shaders
2 | from .GLViewWidget import GLViewWidget
3 | from .items.GLAxisItem import *
4 | from .items.GLBarGraphItem import *
5 | from .items.GLBoxItem import *
6 | from .items.GLGradientLegendItem import *
7 | from .items.GLGraphItem import *
8 | from .items.GLGridItem import *
9 | from .items.GLImageItem import *
10 | from .items.GLLinePlotItem import *
11 | from .items.GLMeshItem import *
12 | from .items.GLScatterPlotItem import *
13 | from .items.GLSurfacePlotItem import *
14 | from .items.GLTextItem import *
15 | from .items.GLVolumeItem import *
16 | from .MeshData import MeshData
17 |
18 | ## dynamic imports cause too many problems.
19 | #from .. import importAll
20 | #importAll('items', globals(), locals())
21 |
22 |
23 | ## for backward compatibility:
24 | #MeshData.MeshData = MeshData ## breaks autodoc.
25 |
--------------------------------------------------------------------------------
/pyqtgraph/opengl/items/GLAxisItem.py:
--------------------------------------------------------------------------------
1 | from OpenGL.GL import * # noqa
2 | from ... import QtGui
3 | from ..GLGraphicsItem import GLGraphicsItem
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', parentItem=None):
16 | super().__init__(parentItem=parentItem)
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 |
--------------------------------------------------------------------------------
/pyqtgraph/opengl/items/GLBarGraphItem.py:
--------------------------------------------------------------------------------
1 | __all__ = ["GLBarGraphItem"]
2 |
3 | import numpy as np
4 |
5 | from ..MeshData import MeshData
6 | from .GLMeshItem import GLMeshItem
7 |
8 |
9 | class GLBarGraphItem(GLMeshItem):
10 | def __init__(self, pos, size, parentItem=None):
11 | """
12 | pos is (...,3) array of the bar positions (the corner of each bar)
13 | size is (...,3) array of the sizes of each bar
14 | """
15 | nCubes = np.prod(pos.shape[:-1])
16 | cubeVerts = np.mgrid[0:2,0:2,0:2].reshape(3,8).transpose().reshape(1,8,3)
17 | cubeFaces = np.array([
18 | [0,1,2], [3,2,1],
19 | [4,5,6], [7,6,5],
20 | [0,1,4], [5,4,1],
21 | [2,3,6], [7,6,3],
22 | [0,2,4], [6,4,2],
23 | [1,3,5], [7,5,3]]).reshape(1,12,3)
24 | size = size.reshape((nCubes, 1, 3))
25 | pos = pos.reshape((nCubes, 1, 3))
26 | verts = cubeVerts * size + pos
27 | faces = cubeFaces + (np.arange(nCubes) * 8).reshape(nCubes,1,1)
28 | md = MeshData(verts.reshape(nCubes*8,3), faces.reshape(nCubes*12,3))
29 |
30 | super().__init__(meshdata=md, shader='shaded', smooth=False, parentItem=parentItem)
31 |
--------------------------------------------------------------------------------
/pyqtgraph/opengl/items/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PANOimagen/profiletool/0fec10efe93ce437eec7c6128869c1b997e8a836/pyqtgraph/opengl/items/__init__.py
--------------------------------------------------------------------------------
/pyqtgraph/parametertree/__init__.py:
--------------------------------------------------------------------------------
1 | from . import parameterTypes as types
2 | from .Parameter import Parameter, registerParameterItemType, registerParameterType
3 | from .ParameterItem import ParameterItem
4 | from .ParameterSystem import ParameterSystem, SystemSolver
5 | from .ParameterTree import ParameterTree
6 | from .interactive import RunOptions, interact, InteractiveFunction, Interactor
7 |
--------------------------------------------------------------------------------
/pyqtgraph/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 |
--------------------------------------------------------------------------------
/pyqtgraph/parametertree/parameterTypes/calendar.py:
--------------------------------------------------------------------------------
1 | from ...Qt import QtCore, QtWidgets
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 | if state.get('value', None) is not None:
55 | state['value'] = state['value'].toString(fmt)
56 | return state
57 |
--------------------------------------------------------------------------------
/pyqtgraph/parametertree/parameterTypes/color.py:
--------------------------------------------------------------------------------
1 | from ... import functions as fn
2 | from ...widgets.ColorButton import ColorButton
3 | from .basetypes import SimpleParameter, WidgetParameterItem
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 | value = super().value()
27 | if value is None:
28 | return None
29 | return fn.mkColor(value)
30 |
31 | def saveState(self, filter=None):
32 | state = super().saveState(filter)
33 | state['value'] = self.value().getRgb()
34 | return state
35 |
--------------------------------------------------------------------------------
/pyqtgraph/parametertree/parameterTypes/colormap.py:
--------------------------------------------------------------------------------
1 | from ...colormap import ColorMap
2 | from ...Qt import QtCore
3 | from ...widgets.GradientWidget import GradientWidget
4 | from .basetypes import SimpleParameter, WidgetParameterItem
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 |
--------------------------------------------------------------------------------
/pyqtgraph/parametertree/parameterTypes/colormaplut.py:
--------------------------------------------------------------------------------
1 | from ... import colormap
2 | from ...widgets.ColorMapButton import ColorMapButton
3 | from .basetypes import Parameter, WidgetParameterItem
4 |
5 |
6 | class ColorMapLutParameterItem(WidgetParameterItem):
7 | def makeWidget(self):
8 | w = ColorMapButton()
9 | w.sigChanged = w.sigColorMapChanged
10 | w.value = w.colorMap
11 | w.setValue = w.setColorMap
12 | self.hideWidget = False
13 | return w
14 |
15 |
16 | class ColorMapLutParameter(Parameter):
17 | itemClass = ColorMapLutParameterItem
18 |
19 | def _interpretValue(self, v):
20 | if isinstance(v, str):
21 | v = colormap.get(v)
22 | if v is not None and not isinstance(v, colormap.ColorMap):
23 | raise TypeError("Cannot set colormap parameter from object %r" % v)
24 | return v
25 |
--------------------------------------------------------------------------------
/pyqtgraph/parametertree/parameterTypes/font.py:
--------------------------------------------------------------------------------
1 | from ...Qt import QtGui, QtWidgets
2 | from ..Parameter import Parameter
3 | from .basetypes import WidgetParameterItem
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 |
--------------------------------------------------------------------------------
/pyqtgraph/parametertree/parameterTypes/numeric.py:
--------------------------------------------------------------------------------
1 | from ...widgets.SpinBox import SpinBox
2 | from .basetypes import WidgetParameterItem
3 |
4 |
5 | class NumericParameterItem(WidgetParameterItem):
6 | """
7 | Subclasses `WidgetParameterItem` to provide the following types:
8 |
9 | ========================== =============================================================
10 | **Registered Types:**
11 | int Displays a :class:`SpinBox ` in integer
12 | mode.
13 | float Displays a :class:`SpinBox `.
14 | ========================== =============================================================
15 | """
16 | def makeWidget(self):
17 | opts = self.param.opts
18 | t = opts['type']
19 | defs = {
20 | 'value': 0, 'min': None, 'max': None,
21 | 'step': 1.0, 'dec': False,
22 | 'siPrefix': False, 'suffix': '', 'decimals': 3,
23 | }
24 | if t == 'int':
25 | defs['int'] = True
26 | defs['minStep'] = 1.0
27 | for k in defs:
28 | if k in opts:
29 | defs[k] = opts[k]
30 | if opts.get('limits') is not None:
31 | defs['min'], defs['max'] = opts['limits']
32 | w = SpinBox()
33 | w.setOpts(**defs)
34 | w.sigChanged = w.sigValueChanged
35 | w.sigChanging = w.sigValueChanging
36 | return w
37 |
38 | def updateDisplayLabel(self, value=None):
39 | if value is None:
40 | value = self.widget.lineEdit().text()
41 | super().updateDisplayLabel(value)
42 |
43 | def showEditor(self):
44 | super().showEditor()
45 | self.widget.selectNumber() # select the numerical portion of the text for quick editing
46 |
47 | def limitsChanged(self, param, limits):
48 | self.widget.setOpts(bounds=limits)
49 |
50 | def optsChanged(self, param, opts):
51 | super().optsChanged(param, opts)
52 | sbOpts = {}
53 | if 'units' in opts and 'suffix' not in opts:
54 | sbOpts['suffix'] = opts['units']
55 | for k, v in opts.items():
56 | if k in self.widget.opts:
57 | sbOpts[k] = v
58 | self.widget.setOpts(**sbOpts)
59 | self.updateDisplayLabel()
60 |
--------------------------------------------------------------------------------
/pyqtgraph/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 |
--------------------------------------------------------------------------------
/pyqtgraph/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 |
--------------------------------------------------------------------------------
/pyqtgraph/parametertree/parameterTypes/text.py:
--------------------------------------------------------------------------------
1 | from ...Qt import QtCore, QtWidgets
2 | from ..Parameter import Parameter
3 | from .basetypes import WidgetParameterItem
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 |
--------------------------------------------------------------------------------
/pyqtgraph/units.py:
--------------------------------------------------------------------------------
1 | # Very simple unit support:
2 | # - creates variable names like 'mV' and 'kHz'
3 | # - the value assigned to the variable corresponds to the scale prefix
4 | # (mV = 0.001)
5 | # - the actual units are purely cosmetic for making code clearer:
6 | #
7 | # x = 20*pA is identical to x = 20*1e-12
8 | #
9 | # No unicode variable names (μ,Ω) allowed until python 3, but just assigning
10 | # them to the globals dict doesn't error in python 2.
11 | import unicodedata
12 |
13 | # All unicode identifiers get normalized automatically
14 | SI_PREFIXES = unicodedata.normalize("NFKC", u"yzafpnµm kMGTPEZY")
15 | UNITS = unicodedata.normalize("NFKC", u"m,s,g,W,J,V,A,F,T,Hz,Ohm,Ω,S,N,C,px,b,B,Pa").split(",")
16 | allUnits = {}
17 |
18 |
19 | def addUnit(prefix, val):
20 | g = globals()
21 | for u in UNITS:
22 | g[prefix + u] = val
23 | allUnits[prefix + u] = val
24 |
25 |
26 | for pre in SI_PREFIXES:
27 | v = SI_PREFIXES.index(pre) - 8
28 | if pre == " ":
29 | pre = ""
30 | addUnit(pre, 1000 ** v)
31 |
32 | addUnit("c", 0.01)
33 | addUnit("d", 0.1)
34 | addUnit("da", 10)
35 | addUnit("h", 100)
36 | # py2 compatibility
37 | addUnit("u", 1e-6)
38 |
39 |
40 | def evalUnits(unitStr):
41 | """
42 | Evaluate a unit string into ([numerators,...], [denominators,...])
43 | Examples:
44 | N m/s^2 => ([N, m], [s, s])
45 | A*s / V => ([A, s], [V,])
46 | """
47 | pass
48 |
49 |
50 | def formatUnits(units):
51 | """
52 | Format a unit specification ([numerators,...], [denominators,...])
53 | into a string (this is the inverse of evalUnits)
54 | """
55 | pass
56 |
57 |
58 | def simplify(units):
59 | """
60 | Cancel units that appear in both numerator and denominator, then attempt to replace
61 | groups of units with single units where possible (ie, J/s => W)
62 | """
63 | pass
64 |
--------------------------------------------------------------------------------
/pyqtgraph/util/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PANOimagen/profiletool/0fec10efe93ce437eec7c6128869c1b997e8a836/pyqtgraph/util/__init__.py
--------------------------------------------------------------------------------
/pyqtgraph/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 |
--------------------------------------------------------------------------------
/pyqtgraph/util/colorama/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PANOimagen/profiletool/0fec10efe93ce437eec7c6128869c1b997e8a836/pyqtgraph/util/colorama/__init__.py
--------------------------------------------------------------------------------
/pyqtgraph/util/cupy_helper.py:
--------------------------------------------------------------------------------
1 | import os
2 | from warnings import warn
3 |
4 | from .. import getConfigOption
5 |
6 |
7 | def getCupy():
8 | if getConfigOption("useCupy"):
9 | try:
10 | import cupy
11 | except ImportError:
12 | warn("cupy library could not be loaded, but 'useCupy' is set.")
13 | return None
14 | if os.name == "nt" and cupy.cuda.runtime.runtimeGetVersion() < 11000:
15 | warn("In Windows, CUDA toolkit should be version 11 or higher, or some functions may misbehave.")
16 | return cupy
17 | else:
18 | return None
19 |
--------------------------------------------------------------------------------
/pyqtgraph/util/garbage_collector.py:
--------------------------------------------------------------------------------
1 | import gc
2 |
3 | from ..Qt import QtCore
4 |
5 |
6 | class GarbageCollector(object):
7 | '''
8 | Disable automatic garbage collection and instead collect manually
9 | on a timer.
10 |
11 | This is done to ensure that garbage collection only happens in the GUI
12 | thread, as otherwise Qt can crash.
13 |
14 | Credit: Erik Janssens
15 | Source: http://pydev.blogspot.com/2014/03/should-python-garbage-collector-be.html
16 | '''
17 |
18 | def __init__(self, interval=1.0, debug=False):
19 | self.debug = debug
20 | if debug:
21 | gc.set_debug(gc.DEBUG_LEAK)
22 |
23 | self.timer = QtCore.QTimer()
24 | self.timer.timeout.connect(self.check)
25 |
26 | self.threshold = gc.get_threshold()
27 | gc.disable()
28 | self.timer.start(int(interval * 1000))
29 |
30 | def check(self):
31 | #return self.debug_cycles() # uncomment to just debug cycles
32 | l0, l1, l2 = gc.get_count()
33 | if self.debug:
34 | print('gc_check called:', l0, l1, l2)
35 | if l0 > self.threshold[0]:
36 | num = gc.collect(0)
37 | if self.debug:
38 | print('collecting gen 0, found: %d unreachable' % num)
39 | if l1 > self.threshold[1]:
40 | num = gc.collect(1)
41 | if self.debug:
42 | print('collecting gen 1, found: %d unreachable' % num)
43 | if l2 > self.threshold[2]:
44 | num = gc.collect(2)
45 | if self.debug:
46 | print('collecting gen 2, found: %d unreachable' % num)
47 |
48 | def debug_cycles(self):
49 | gc.collect()
50 | for obj in gc.garbage:
51 | print(obj, repr(obj), type(obj))
52 |
--------------------------------------------------------------------------------
/pyqtgraph/util/get_resolution.py:
--------------------------------------------------------------------------------
1 | from .. import mkQApp
2 | from ..Qt import QtGui
3 |
4 |
5 | def test_screenInformation():
6 | # a qApp is still needed, otherwise screen is None
7 | qApp = mkQApp() # noqa
8 | screen = QtGui.QGuiApplication.primaryScreen()
9 | screens = QtGui.QGuiApplication.screens()
10 | resolution = screen.size()
11 | availableResolution = screen.availableSize()
12 | print("Screen resolution: {}x{}".format(resolution.width(), resolution.height()))
13 | print("Available geometry: {}x{}".format(availableResolution.width(), availableResolution.height()))
14 | print("Number of Screens: {}".format(len(screens)))
15 | return None
16 |
17 |
18 | if __name__ == "__main__":
19 | test_screenInformation()
20 |
--------------------------------------------------------------------------------
/pyqtgraph/util/glinfo.py:
--------------------------------------------------------------------------------
1 | import importlib
2 |
3 | from ..Qt import QT_LIB, QtGui
4 |
5 | GL_VENDOR = 7936
6 | GL_RENDERER = 7937
7 | GL_VERSION = 7938
8 |
9 |
10 | def print_version(funcs):
11 | glGetString = funcs.glGetString
12 | print('VENDOR:', glGetString(GL_VENDOR))
13 | print('RENDERER:', glGetString(GL_RENDERER))
14 | print('VERSION:', glGetString(GL_VERSION))
15 |
16 |
17 | def print_extensions(ctx):
18 | extensions = sorted([ext.data().decode() for ext in ctx.extensions()])
19 | print("Extensions:")
20 | for ext in extensions:
21 | print(f" {ext}")
22 |
23 |
24 | app = QtGui.QGuiApplication([])
25 | surf = QtGui.QOffscreenSurface()
26 | surf.create()
27 | ctx = QtGui.QOpenGLContext()
28 | ctx.create()
29 | ctx.makeCurrent(surf)
30 |
31 | if QT_LIB == 'PySide2':
32 | funcs = ctx.functions()
33 | elif QT_LIB == 'PyQt5':
34 | profile = QtGui.QOpenGLVersionProfile()
35 | profile.setVersion(2, 0)
36 | funcs = ctx.versionFunctions(profile)
37 | elif QT_LIB in ['PyQt6', 'PySide6']:
38 | QtOpenGL = importlib.import_module(f'{QT_LIB}.QtOpenGL')
39 | profile = QtOpenGL.QOpenGLVersionProfile()
40 | profile.setVersion(2, 0)
41 | funcs_factory = QtOpenGL.QOpenGLVersionFunctionsFactory()
42 | funcs = funcs_factory.get(profile, ctx)
43 |
44 | print('isOpenGLES:', ctx.isOpenGLES())
45 | print_version(funcs)
46 | print_extensions(ctx)
47 |
--------------------------------------------------------------------------------
/pyqtgraph/util/numba_helper.py:
--------------------------------------------------------------------------------
1 | from warnings import warn
2 |
3 | from .. import getConfigOption
4 |
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 |
--------------------------------------------------------------------------------
/pyqtgraph/widgets/BusyCursor.py:
--------------------------------------------------------------------------------
1 | from contextlib import contextmanager
2 |
3 | from ..Qt import QtCore, QtGui, QtWidgets
4 |
5 | __all__ = ["BusyCursor"]
6 |
7 |
8 | @contextmanager
9 | def BusyCursor():
10 | """
11 | Display a busy mouse cursor during long operations.
12 | Usage::
13 |
14 | with BusyCursor():
15 | doLongOperation()
16 |
17 | May be nested. If called from a non-gui thread, then the cursor will not be affected.
18 | """
19 | app = QtCore.QCoreApplication.instance()
20 | in_gui_thread = (app is not None) and (QtCore.QThread.currentThread() == app.thread())
21 | try:
22 | if in_gui_thread:
23 | guard = QtWidgets.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.CursorShape.WaitCursor))
24 | # on PySide6 6.3.0, setOverrideCursor() returns a QOverrideCursorGuard object
25 | # that, on its destruction, calls restoreOverrideCursor() if the user had not
26 | # already done so.
27 | # if the user wants to call it manually, they must do it via the returned object,
28 | # and not via the QtWidgets.QApplication static method; otherwise the restore
29 | # would get called twice.
30 | yield
31 | finally:
32 | if in_gui_thread:
33 | if hasattr(guard, 'restoreOverrideCursor'):
34 | guard.restoreOverrideCursor()
35 | else:
36 | QtWidgets.QApplication.restoreOverrideCursor()
37 |
--------------------------------------------------------------------------------
/pyqtgraph/widgets/FileDialog.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | from ..Qt import QtWidgets
4 |
5 | __all__ = ['FileDialog']
6 |
7 | class FileDialog(QtWidgets.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 | QtWidgets.QFileDialog.__init__(self, *args)
13 |
14 | if sys.platform == 'darwin':
15 | self.setOption(QtWidgets.QFileDialog.Option.DontUseNativeDialog)
16 |
--------------------------------------------------------------------------------
/pyqtgraph/widgets/HistogramLUTWidget.py:
--------------------------------------------------------------------------------
1 | """
2 | Widget displaying an image histogram along with gradient editor. Can be used to adjust
3 | the appearance of images. This is a wrapper around HistogramLUTItem
4 | """
5 |
6 | from ..graphicsItems.HistogramLUTItem import HistogramLUTItem
7 | from ..Qt import QtCore, QtWidgets
8 | from .GraphicsView import GraphicsView
9 |
10 | __all__ = ['HistogramLUTWidget']
11 |
12 |
13 | class HistogramLUTWidget(GraphicsView):
14 | """QWidget wrapper for :class:`~pyqtgraph.HistogramLUTItem`.
15 |
16 | All parameters are passed along in creating the HistogramLUTItem.
17 | """
18 |
19 | def __init__(self, parent=None, *args, **kargs):
20 | background = kargs.pop('background', 'default')
21 | GraphicsView.__init__(self, parent, useOpenGL=False, background=background)
22 | self.item = HistogramLUTItem(*args, **kargs)
23 | self.setCentralItem(self.item)
24 |
25 | self.orientation = kargs.get('orientation', 'vertical')
26 | if self.orientation == 'vertical':
27 | self.setSizePolicy(QtWidgets.QSizePolicy.Policy.Preferred, QtWidgets.QSizePolicy.Policy.Expanding)
28 | self.setMinimumWidth(95)
29 | else:
30 | self.setSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Preferred)
31 | self.setMinimumHeight(95)
32 |
33 | def sizeHint(self):
34 | if self.orientation == 'vertical':
35 | return QtCore.QSize(115, 200)
36 | else:
37 | return QtCore.QSize(200, 115)
38 |
39 | def __getattr__(self, attr):
40 | return getattr(self.item, attr)
41 |
--------------------------------------------------------------------------------
/pyqtgraph/widgets/MatplotlibWidget.py:
--------------------------------------------------------------------------------
1 | from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg as FigureCanvas
2 | from matplotlib.backends.backend_qtagg import NavigationToolbar2QT as NavigationToolbar
3 | from matplotlib.figure import Figure
4 |
5 | from ..Qt import QtWidgets
6 | import typing
7 |
8 | __all__ = ['MatplotlibWidget']
9 |
10 |
11 | class MatplotlibWidget(QtWidgets.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 | parent_default = None
25 | figsize_default = (5.0, 4.0)
26 | dpi_default = 100
27 |
28 | @typing.overload
29 | def __init__(self, figsize=(5.0, 4.0), dpi=100, parent=None):
30 | pass
31 |
32 | @typing.overload
33 | def __init__(self, parent=None, figsize=(5.0, 4.0), dpi=100):
34 | pass
35 |
36 | def __init__(self, *args, **kwargs):
37 | if (args and not isinstance(args[0], QtWidgets.QWidget)):
38 | figsize = args[0] if len(args) > 0 \
39 | else kwargs.get("figsize", MatplotlibWidget.figsize_default)
40 | dpi = args[1] if len(args) > 1 \
41 | else kwargs.get("dpi", MatplotlibWidget.dpi_default)
42 | parent = args[2] if len(args) > 2 \
43 | else kwargs.get("parent", MatplotlibWidget.parent_default)
44 | else:
45 | parent = args[0] if len(args) > 0 \
46 | else kwargs.get("parent", MatplotlibWidget.parent_default)
47 | figsize = args[1] if len(args) > 1 \
48 | else kwargs.get("figsize", MatplotlibWidget.figsize_default)
49 | dpi = args[2] if len(args) > 2 \
50 | else kwargs.get("dpi", MatplotlibWidget.dpi_default)
51 | super().__init__(parent)
52 |
53 | self.fig = Figure(figsize, dpi=dpi)
54 | self.canvas = FigureCanvas(self.fig)
55 | self.canvas.setParent(self)
56 | self.toolbar = NavigationToolbar(self.canvas, self)
57 |
58 | self.vbox = QtWidgets.QVBoxLayout()
59 | self.vbox.addWidget(self.toolbar)
60 | self.vbox.addWidget(self.canvas)
61 |
62 | self.setLayout(self.vbox)
63 |
64 | def getFigure(self):
65 | return self.fig
66 |
67 | def draw(self):
68 | self.canvas.draw()
69 |
--------------------------------------------------------------------------------
/pyqtgraph/widgets/PathButton.py:
--------------------------------------------------------------------------------
1 | from .. import functions as fn
2 | from ..Qt import QtCore, QtGui, QtWidgets
3 |
4 | __all__ = ['PathButton']
5 |
6 |
7 | class PathButton(QtWidgets.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 | QtWidgets.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 |
--------------------------------------------------------------------------------
/pyqtgraph/widgets/PenPreviewLabel.py:
--------------------------------------------------------------------------------
1 | from ..Qt import QtWidgets, QtGui, QtCore
2 | from ..functions import mkPen
3 |
4 |
5 | class PenPreviewLabel(QtWidgets.QLabel):
6 | def __init__(self, param):
7 | super().__init__()
8 | self.param = param
9 | self.pen = QtGui.QPen(self.param.pen)
10 | param.sigValueChanging.connect(self.onPenChanging)
11 |
12 | def onPenChanging(self, param, val):
13 | self.pen = QtGui.QPen(val)
14 | self.update()
15 |
16 | def paintEvent(self, ev):
17 | path = QtGui.QPainterPath()
18 | displaySize = self.size()
19 | w, h = displaySize.width(), displaySize.height()
20 | # draw a squiggle with the pen
21 | path.moveTo(w * .2, h * .2)
22 | path.lineTo(w * .4, h * .8)
23 | path.cubicTo(w * .5, h * .1, w * .7, h * .1, w * .8, h * .8)
24 |
25 | painter = QtGui.QPainter(self)
26 | painter.setPen(self.pen)
27 | painter.drawPath(path)
28 |
29 | # No indication of "cosmetic" from just the paint path, so add something extra in that case
30 | if self.pen.isCosmetic():
31 | painter.setPen(mkPen('k'))
32 | painter.drawText(QtCore.QPointF(w * 0.81, 12), 'C')
33 | painter.end()
34 |
--------------------------------------------------------------------------------
/pyqtgraph/widgets/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PANOimagen/profiletool/0fec10efe93ce437eec7c6128869c1b997e8a836/pyqtgraph/widgets/__init__.py
--------------------------------------------------------------------------------
/resources.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | icons/profileIcon.png
4 |
5 |
6 |
--------------------------------------------------------------------------------
/tests/test_dist.py:
--------------------------------------------------------------------------------
1 | import qgis
2 |
3 |
4 | vl = iface.activeLayer()
5 |
6 | crs1 = vl.crs()
7 | crs2 = iface.mapCanvas().mapSettings().destinationCrs()
8 |
9 | dist = qgis.core.QgsDistanceArea()
10 | #dist.setEllipsoid(qgis.core.QgsProject().instance().ellipsoid())
11 | #dist.setEllipsoidalMode(True)
12 | dist.setSourceCrs(crs2)
13 |
14 | dist2 = qgis.core.QgsDistanceArea()
15 | #dist2.setEllipsoid(qgis.core.QgsProject().instance().ellipsoid())
16 | #dist2.setEllipsoidalMode(True)
17 | dist2.setSourceCrs(crs1)
18 |
19 | print(dist.convertLengthMeasurement(1.0, crs1.mapUnits()) )
20 | print(dist2.convertLengthMeasurement(1.0, crs2.mapUnits()) )
21 |
22 |
--------------------------------------------------------------------------------
/tools/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PANOimagen/profiletool/0fec10efe93ce437eec7c6128869c1b997e8a836/tools/__init__.py
--------------------------------------------------------------------------------
/tools/profilers.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # -----------------------------------------------------------
3 | #
4 | # Profilers
5 | # Copyright (C) 2017 Javier Becerra
6 | # -----------------------------------------------------------
7 | #
8 | # licensed under the terms of GNU GPL 2
9 | #
10 | # This program is free software; you can redistribute it and/or modify
11 | # it under the terms of the GNU General Public License as published by
12 | # the Free Software Foundation; either version 2 of the License, or
13 | # (at your option) any later version.
14 | #
15 | # This program is distributed in the hope that it will be useful,
16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | # GNU General Public License for more details.
19 | #
20 | # You should have received a copy of the GNU General Public License along
21 | # with this program; if not, print to the Free Software Foundation, Inc.,
22 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 | #
24 | # ---------------------------------------------------------------------
25 |
26 | import numpy as np
27 |
28 |
29 | def height(p):
30 | """Return the height profile for given track p.
31 |
32 | Returns the x (distance from origin) and y (height)
33 | coordinates for the plot.
34 | """
35 | return p["l"], p["z"]
36 |
37 |
38 | def slopes_pct(p):
39 | """Return a profile's slope in percentage.
40 |
41 | Returns the x (distance from origin) and y (slope in percentage)
42 | coordinates for the plot.
43 | """
44 | x = np.array(p["l"], dtype=float)
45 | y = np.array(p["z"], dtype=float)
46 | slope_pct = 100.0 * (y[1:] - y[:-1]) / (x[1:] - x[:-1])
47 | slope_pct = np.concatenate(
48 | (slope_pct[0:1], 0.5 * (slope_pct[1:] + slope_pct[:-1]), slope_pct[-1:])
49 | )
50 | slope_pct[np.isnan(slope_pct)] = 0
51 | slope_pct[np.isinf(slope_pct)] = 0
52 | return x, slope_pct
53 |
54 |
55 | def slopes_deg(p):
56 | """Return a profile's slope in degrees.
57 |
58 | Returns the x (distance from origin) and y (slope in degrees)
59 | coordinates for the plot.
60 | """
61 | x, slope_pct = slopes_pct(p)
62 | slope_deg = np.degrees(np.arctan(slope_pct / 100.0))
63 | return x, slope_deg
64 |
65 |
66 | PLOT_PROFILERS = {"Height": height, "Slope (%)": slopes_pct, "Slope (°)": slopes_deg}
67 |
--------------------------------------------------------------------------------
/tools/utils.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # -----------------------------------------------------------
3 | #
4 | # Profile
5 | # Copyright (C) 2013 Peter Wells
6 | # -----------------------------------------------------------
7 | #
8 | # licensed under the terms of GNU GPL 2
9 | #
10 | # This program is free software; you can redistribute it and/or modify
11 | # it under the terms of the GNU General Public License as published by
12 | # the Free Software Foundation; either version 2 of the License, or
13 | # (at your option) any later version.
14 | #
15 | # This program is distributed in the hope that it will be useful,
16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | # GNU General Public License for more details.
19 | #
20 | # You should have received a copy of the GNU General Public License along
21 | # with this program; if not, print to the Free Software Foundation, Inc.,
22 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 | #
24 | # ---------------------------------------------------------------------
25 |
26 | from qgis.core import QgsWkbTypes
27 |
28 |
29 | def isProfilable(layer):
30 | """Returns True if layer can be profiled, else returns False"""
31 | return (
32 | (layer.type() == layer.RasterLayer)
33 | or (layer.type() == layer.MeshLayer)
34 | or (layer.type() == layer.PluginLayer and layer.LAYER_TYPE == "selafin_viewer")
35 | or (layer.type() == layer.VectorLayer and layer.geometryType() == QgsWkbTypes.PointGeometry)
36 | )
37 |
--------------------------------------------------------------------------------
/ui/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PANOimagen/profiletool/0fec10efe93ce437eec7c6128869c1b997e8a836/ui/__init__.py
--------------------------------------------------------------------------------
/ui/dlgabout.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # -----------------------------------------------------------
3 | #
4 | # Profile
5 | # Copyright (C) 2012 Patrice Verchere
6 | # -----------------------------------------------------------
7 | #
8 | # licensed under the terms of GNU GPL 2
9 | #
10 | # This program is free software; you can redistribute it and/or modify
11 | # it under the terms of the GNU General Public License as published by
12 | # the Free Software Foundation; either version 2 of the License, or
13 | # (at your option) any later version.
14 | #
15 | # This program is distributed in the hope that it will be useful,
16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | # GNU General Public License for more details.
19 | #
20 | # You should have received a copy of the GNU General Public License along
21 | # with this program; if not, print to the Free Software Foundation, Inc.,
22 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 | #
24 | # ---------------------------------------------------------------------
25 |
26 | import os
27 | import platform
28 |
29 | from qgis.PyQt import uic
30 | from qgis.PyQt.QtCore import *
31 | from qgis.PyQt.QtGui import *
32 | from qgis.PyQt.QtWidgets import QDialog
33 |
34 | uiFilePath = os.path.abspath(os.path.join(os.path.dirname(__file__), "about.ui"))
35 | FormClass = uic.loadUiType(uiFilePath)[0]
36 |
37 |
38 | class DlgAbout(QDialog, FormClass):
39 | def __init__(self, parent=None):
40 | QDialog.__init__(self, parent)
41 | self.setupUi(self)
42 |
43 | fp = os.path.join(
44 | os.path.abspath(os.path.join(os.path.dirname(__file__), "..")), "metadata.txt"
45 | )
46 |
47 | iniText = QSettings(fp, QSettings.IniFormat)
48 | verno = iniText.value("version")
49 | name = iniText.value("name")
50 | description = iniText.value("description")
51 |
52 | self.title.setText(name)
53 | self.description.setText(description + " - " + verno)
54 |
--------------------------------------------------------------------------------