Python 3 WxPython Radar Graph Plot Visualization Using Plotly and Matplotlib Library in GUI Desktop App Full Project For Beginners

Python 3 WxPython Radar Graph Plot Visualization Using Plotly and Matplotlib Library in GUI Desktop App Full Project For Beginners

 

Welcome folks today in this blog post we will be making a radar graph plot visualization using plotly and matplotlib library in gui desktop app in python. All the full source code of the application is given below.

 

 

Get Started

 

 

In order to get started you need to install the below library using the pip command as shown below

 

pip install wxpython

 

pip install plotly

 

pip install matplotlib

 

After installing this library you need to make an app.py file and copy paste the following code

 

app.py

 

import wx
import math
import random

class RadarGraph(wx.Window):
    """
    A simple radar graph that plots a collection of values in the
    range of 0-100 onto a polar coordinate system designed to easily
    show outliers, etc.  You might use this kind of graph to monitor
    some sort of resource allocation metrics, and a quick glance at
    the graph can tell you when conditions are good (within some
    accepted tolerance level) or approaching critical levels (total
    resource consumption).
    """
    def __init__(self, parent, title, labels):
        wx.Window.__init__(self, parent)
        self.title = title
        self.labels = labels
        self.data = [0.0] * len(labels)
        self.titleFont = wx.Font(14, wx.SWISS, wx.NORMAL, wx.BOLD)
        self.labelFont = wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL)

        self.InitBuffer()

        self.Bind(wx.EVT_SIZE, self.OnSize)
        self.Bind(wx.EVT_PAINT, self.OnPaint)


    def OnSize(self, evt):
        # When the window size changes we need a new buffer.
        self.InitBuffer()


    def OnPaint(self, evt):
        # This automatically Blits self.buffer to a wx.PaintDC when
        # the dc is destroyed, and so nothing else needs done.
        dc = wx.BufferedPaintDC(self, self.buffer)


    def InitBuffer(self):
        # Create the buffer bitmap to be the same size as the window,
        # then draw our graph to it.  Since we use wx.BufferedDC
        # whatever is drawn to the buffer is also drawn to the window.
        w, h = self.GetClientSize()        
        self.buffer = wx.EmptyBitmap(w, h)
        dc = wx.BufferedDC(wx.ClientDC(self), self.buffer)
        self.DrawGraph(dc)
        

    def GetData(self):
        return self.data

    def SetData(self, newData):
        assert len(newData) == len(self.data)
        self.data = newData[:]
        
        # The data has changed, so update the buffer and the window
        dc = wx.BufferedDC(wx.ClientDC(self), self.buffer)
        self.DrawGraph(dc)

    
    def PolarToCartesian(self, radius, angle, cx, cy):
        x = radius * math.cos(math.radians(angle))
        y = radius * math.sin(math.radians(angle))
        return (cx+x, cy-y)


    def DrawGraph(self, dc):
        spacer = 10
        scaledmax = 150.0

        dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
        dc.Clear()
        dw, dh = dc.GetSize()

        # Find out where to draw the title and do it
        dc.SetFont(self.titleFont)
        tw, th = dc.GetTextExtent(self.title)
        dc.DrawText(self.title, (dw-tw)/2, spacer)

        # find the center of the space below the title
        th = th + 2*spacer
        cx = dw/2
        cy = (dh-th)/2 + th

        # calculate a scale factor to use for drawing the graph based
        # on the minimum available width or height
        mindim = min(cx, (dh-th)/2)
        scale = mindim/scaledmax

        # draw the graph axis and "bulls-eye" with rings at scaled 25,
        # 50, 75 and 100 positions
        dc.SetPen(wx.Pen("black", 1))
        dc.SetBrush(wx.TRANSPARENT_BRUSH)
        dc.DrawCircle(cx,cy, 25*scale)
        dc.DrawCircle(cx,cy, 50*scale)
        dc.DrawCircle(cx,cy, 75*scale)
        dc.DrawCircle(cx,cy, 100*scale)

        dc.SetPen(wx.Pen("black", 2))
        dc.DrawLine(cx-110*scale, cy, cx+110*scale, cy)
        dc.DrawLine(cx, cy-110*scale, cx, cy+110*scale)

        # Now find the coordinates for each data point, draw the
        # labels, and find the max data point
        dc.SetFont(self.labelFont)
        maxval = 0
        angle = 0
        polypoints = []
        for i, label in enumerate(self.labels):
            val = self.data[i]
            point = self.PolarToCartesian(val*scale, angle, cx, cy)
            polypoints.append(point)
            x, y = self.PolarToCartesian(125*scale, angle, cx,cy)
            dc.DrawText(label, x, y)
            if val > maxval:
                maxval = val
            angle = angle + 360/len(self.labels)
            
        # Set the brush color based on the max value (green is good,
        # red is bad)
        c = "forest green"
        if maxval > 70:
            c = "yellow"
        if maxval > 95:
            c = "red"

        # Finally, draw the plot data as a filled polygon
        dc.SetBrush(wx.Brush(c))
        dc.SetPen(wx.Pen("navy", 3))
        dc.DrawPolygon(polypoints)
        

        
class TestFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, title="Double Buffered Drawing",
                          size=(480,480))
        self.plot = RadarGraph(self, "Sample 'Radar' Plot",
                          ["A", "B", "C", "D", "E", "F", "G", "H"])

        # Set some random initial data values
        data = []
        for d in self.plot.GetData():
            data.append(random.randint(0, 75))
        self.plot.SetData(data)

        # Create a timer to update the data values
        self.Bind(wx.EVT_TIMER, self.OnTimeout)
        self.timer = wx.Timer(self)
        self.timer.Start(500)


    def OnTimeout(self, evt):
        # simulate the positive or negative growth of each data value
        data = []
        for d in self.plot.GetData():
            val = d + random.uniform(-5, 5)
            if val < 0:
                val = 0
            if val > 110:
                val = 110
            data.append(val)
        self.plot.SetData(data)

        
app = wx.PySimpleApp()
frm = TestFrame()
frm.Show()
app.MainLoop()

 

See also  Python 3 Tkinter Multiple Pages in Multiple Frames Pagination Example Using Button Widget GUI Desktop App Full Project For Beginners

 

If you execute the above python script by typing the below command

 

python app.py

 

 

 

Leave a Reply