Skip to content
This repository was archived by the owner on Aug 21, 2019. It is now read-only.

Commit 75d5d55

Browse files
author
Vincent RICCHI
committed
import project source files
* Import project Python source files. * Update `.gitignore` and `README.md`.
1 parent 68b6e8c commit 75d5d55

File tree

4 files changed

+364
-2
lines changed

4 files changed

+364
-2
lines changed

.gitignore

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
#######################################
2+
#### Python '.gitignore' template ####
3+
#######################################
4+
15
# Byte-compiled / optimized / DLL files
26
__pycache__/
37
*.py[cod]
@@ -20,6 +24,8 @@ parts/
2024
sdist/
2125
var/
2226
wheels/
27+
pip-wheel-metadata/
28+
share/python-wheels/
2329
*.egg-info/
2430
.installed.cfg
2531
*.egg
@@ -38,6 +44,7 @@ pip-delete-this-directory.txt
3844
# Unit test / coverage reports
3945
htmlcov/
4046
.tox/
47+
.nox/
4148
.coverage
4249
.coverage.*
4350
.cache
@@ -55,6 +62,7 @@ coverage.xml
5562
*.log
5663
local_settings.py
5764
db.sqlite3
65+
db.sqlite3-journal
5866

5967
# Flask stuff:
6068
instance/
@@ -72,9 +80,20 @@ target/
7280
# Jupyter Notebook
7381
.ipynb_checkpoints
7482

83+
# IPython
84+
profile_default/
85+
ipython_config.py
86+
7587
# pyenv
7688
.python-version
7789

90+
# pipenv
91+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
93+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
94+
# install all needed dependencies.
95+
#Pipfile.lock
96+
7897
# celery beat schedule file
7998
celerybeat-schedule
8099

@@ -102,3 +121,15 @@ venv.bak/
102121

103122
# mypy
104123
.mypy_cache/
124+
.dmypy.json
125+
dmypy.json
126+
127+
# Pyre type checker
128+
.pyre/
129+
130+
#######################################
131+
#### Additional ignored files ####
132+
#######################################
133+
134+
# Ignore JetBrains '.idea' directory if needed
135+
.idea/

GUI.py

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
"""
2+
==============================
3+
3D ploting using PyQt5 for GUI
4+
==============================
5+
6+
Brief:
7+
------
8+
A **matplotlib** widget displays a 3D graph inside
9+
a **PyQt5** widget window.
10+
11+
Important
12+
---------
13+
This project is published under **MIT License**
14+
"""
15+
16+
import argparse
17+
import sys
18+
19+
import numpy as np
20+
21+
from matplotlib import cm
22+
from matplotlib.pyplot import figure
23+
from matplotlib.ticker import LinearLocator, FormatStrFormatter
24+
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
25+
from mpl_toolkits.mplot3d import Axes3D
26+
27+
from PyQt5.QtCore import Qt, pyqtSlot
28+
from PyQt5.QtWidgets import QApplication as Application, QWidget as Widget, QPushButton as Button
29+
from PyQt5.QtWidgets import QLabel as Label, QGridLayout, QDesktopWidget
30+
31+
import print_string_colors as COLOUR
32+
33+
34+
#
35+
# Following functions are used to generate nice looking plots
36+
#
37+
def f(x, y): # For Generating Z coordinates
38+
return np.sin(np.sqrt(x ** 2 + y ** 2))
39+
40+
41+
def g(x, y): # For Generating Z coordinates (alternative)
42+
return np.sin(x) + np.cos(y)
43+
44+
45+
#
46+
# Following class code partly taken from 'StackOverflow'
47+
#
48+
class ThreeDSurfaceGraphWindow(FigureCanvas): # Class for 3D window
49+
def __init__(self):
50+
self.plot_colorbar = None
51+
self.plot_figure = figure(figsize=(7, 7))
52+
FigureCanvas.__init__(self, self.plot_figure) # creating FigureCanvas
53+
self.axes = self.plot_figure.gca(projection='3d') # generates 3D Axes object
54+
self.setWindowTitle("figure") # sets Window title
55+
56+
def draw_graph(self, x, y, z): # Function for graph plotting
57+
self.axes.clear()
58+
if self.plot_colorbar is not None: # avoids adding one more colorbar at each draw operation
59+
self.plot_colorbar.remove()
60+
# plots the 3D surface plot
61+
plot_stuff = self.axes.plot_surface(x, y, z,
62+
cmap=cm.coolwarm, linewidth=0, antialiased=False)
63+
self.axes.zaxis.set_major_locator(LinearLocator(10))
64+
self.axes.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))
65+
# Add a color bar which maps values to colors.
66+
self.plot_colorbar = self.plot_figure.colorbar(plot_stuff, shrink=0.5, aspect=5)
67+
# draw plot
68+
self.draw()
69+
70+
71+
class ProgramGUI(Widget):
72+
73+
def __init__(self):
74+
super().__init__()
75+
# GUI window specific values
76+
self.title = '\'MatPlotLib\' test program'
77+
self.left = 10
78+
self.top = 10
79+
self.width = 640
80+
self.height = 480
81+
# Other object specific values
82+
self.label_str = "This program will test the \'MatPlotLib\' through a Qt widget display."
83+
self.plot_status = u'a'
84+
self.X_plot_val = None
85+
self.Y_plot_val = None
86+
self.Z_plot_val = None
87+
88+
# Call argument parsing to enable/disable debug options
89+
dbg_parse = argparse.ArgumentParser()
90+
dbg_parse.add_argument(u'-d',
91+
u'--debug',
92+
action='store_true',
93+
help=u'Enable DEBUG specific functions')
94+
self.argh = dbg_parse.parse_args()
95+
96+
# Debug output
97+
if self.argh.debug is True:
98+
print(COLOUR.STRONG_BLUE +
99+
"====================\n" +
100+
"==== DEBUG MODE ====\n" +
101+
"====================" +
102+
COLOUR.NORMAL)
103+
104+
# initialize UI
105+
self.init_ui()
106+
107+
def init_ui(self):
108+
#
109+
# Setup Window Title and geometry
110+
#
111+
self.setWindowTitle(self.title)
112+
self.setGeometry(self.left, self.top, self.width, self.height)
113+
self.center()
114+
#
115+
# Setup User message
116+
#
117+
self.label = Label(self.label_str)
118+
#
119+
# Setup "Program" button
120+
#
121+
self.test_graph_button = Button(u'Update graph', self)
122+
self.test_graph_button.setToolTip(u'Call update function to change graph')
123+
self.test_graph_button.clicked.connect(self.test_std_out)
124+
#
125+
# Setup "Plot" object
126+
#
127+
self.plot_container = ThreeDSurfaceGraphWindow() # creating 3D Window
128+
#
129+
# Setup grid layout for global window
130+
#
131+
main_layout = QGridLayout() # Layout for Main Tab Widget
132+
main_layout.setRowMinimumHeight(0, 5) # setting layout parameters
133+
main_layout.setRowMinimumHeight(2, 10)
134+
main_layout.setRowMinimumHeight(4, 5)
135+
main_layout.addWidget(self.label, 1, 1, Qt.AlignHCenter)
136+
main_layout.addWidget(self.test_graph_button, 2, 1)
137+
main_layout.addWidget(self.plot_container, 3, 1) # add 3D Window to Main layout
138+
self.setLayout(main_layout) # sets Main layout
139+
#
140+
# calculate 3D sin function
141+
#
142+
self.test_std_out()
143+
#
144+
# Special setup when '--debug' is passed as an argument
145+
#
146+
if self.argh.debug is True:
147+
# tell user that all debug Widgets are setup
148+
print(COLOUR.YELLOW +
149+
"Debug Wigets & objects setup done" +
150+
COLOUR.NORMAL)
151+
152+
def center(self):
153+
"""centers the window on the screen"""
154+
screen = QDesktopWidget().screenGeometry()
155+
size = self.geometry()
156+
self.move((screen.width() - size.width()) / 2,
157+
(screen.height() - size.height()) / 2)
158+
159+
@pyqtSlot()
160+
def test_std_out(self):
161+
# Make plot data
162+
if self.plot_status == u'a':
163+
self.X_plot_val = np.arange(-10, 10, 0.25) # X coordinates
164+
self.Y_plot_val = np.arange(-10, 10, 0.25) # Y coordinates
165+
# Forming MeshGrid
166+
self.X_plot_val, self.Y_plot_val = np.meshgrid(self.X_plot_val, self.Y_plot_val)
167+
self.Z_plot_val = g(self.X_plot_val, self.Y_plot_val)
168+
self.plot_status = u'b'
169+
else:
170+
self.X_plot_val = np.arange(-5, 5, 0.25) # X coordinates
171+
self.Y_plot_val = np.arange(-5, 5, 0.25) # Y coordinates
172+
# Forming MeshGrid
173+
self.X_plot_val, self.Y_plot_val = np.meshgrid(self.X_plot_val, self.Y_plot_val)
174+
self.Z_plot_val = f(self.X_plot_val, self.Y_plot_val)
175+
self.plot_status = u'a'
176+
# call plot for tests
177+
self.plot_container.draw_graph(self.X_plot_val, self.Y_plot_val, self.Z_plot_val)
178+
179+
180+
if __name__ == '__main__':
181+
app = Application(sys.argv)
182+
gui = ProgramGUI()
183+
184+
qr = gui.frameGeometry()
185+
cp = QDesktopWidget().availableGeometry().center()
186+
qr.moveCenter(cp)
187+
gui.move(qr.topLeft())
188+
app.processEvents()
189+
190+
gui.show()
191+
192+
exit_val = app.exec_()
193+
194+
# behaviour to trigger on exit
195+
sys.exit(exit_val)

README.md

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,27 @@
1-
# 3D-plot-using-PyQt5-GUI
2-
This is a simple example code to show how to create a 3D plot in a dedicated GUI window.
1+
3D plot in a **PyQt5** GUI
2+
==========================
3+
4+
Presentation
5+
------------
6+
7+
This is a simple example code to show how to create a 3D plot in a dedicated
8+
Graphical User Interface window.
9+
10+
It has been written in **Python** to be natively cross plateform and very
11+
simple.
12+
13+
This project is published under **MIT License** to let people do whatever they
14+
like with the source code.
15+
16+
Status
17+
------
18+
19+
This project is _finished_.
20+
Feel free to expand it to any extent you would like to see it.
21+
22+
Notes:
23+
------
24+
25+
* The project has been written in **Python 3.7** using **JetBrains PyCharm**.
26+
* The project uses `PyQt5` to create the _Graphical User Interface_ (GUI).
27+
* The project uses `matplotlib` to plot the data.

0 commit comments

Comments
 (0)