├── .gitignore ├── README.md ├── setup.py ├── streamplot.py └── test.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | streamplot.egg-info 3 | dist 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # StreamPlot 2 | 3 | Real Time Plotting in Python with pyqtgraph. 4 | Simple to use. 5 | 6 | 7 | 8 | - Install 9 | - Test 10 | - Use 11 | - Install from source 12 | 13 | 14 | 15 | 16 | ## Install 17 | 18 | Install `pyqtgraph` following the instructions on [this webpage](http://www.pyqtgraph.org) 19 | 20 | Use pip (install from repo, see below) 21 | ``` 22 | pip install streamplot 23 | ``` 24 | 25 | ## Test 26 | 27 | To test the install, run the `test.py` script. 28 | 29 | ``` 30 | python test.py 31 | ``` 32 | 33 | ## Use 34 | 35 | In a python code 36 | 37 | - Import package 38 | ```python 39 | from streamplot import PlotManager 40 | ``` 41 | - Create instance of `PlotManager` with 42 | ```python 43 | plt_mgr = PlotManager(title="My first plot") 44 | ``` 45 | - Send data to the plot 46 | ```python 47 | x, y = 1, 2 48 | plt_mgr.add(name="name_of_variable", x=x, y=y) 49 | plt_mgr.update() 50 | ``` 51 | - If you want to plot multiple variables, do something like 52 | ```python 53 | x1, y1 = 2, 4 54 | plt_mgr.add(name="1", x=x1, y=y1) 55 | plt_mgr.add(name="2", x=x2, y=y2) 56 | plt_mgr.update() 57 | ``` 58 | - close the graphs from Terminal 59 | ```python 60 | plt_mgr.close() 61 | ``` 62 | 63 | ## Install from source 64 | 65 | Clone repo, and run from Terminal 66 | 67 | ``` 68 | python setup.py install 69 | ``` 70 | 71 | Alternatively, if you want to modify the package and just add an egg-link to site-packages 72 | 73 | ``` 74 | python setup.py develop 75 | ``` 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | try: 2 | from setuptools import setup 3 | except ImportError: 4 | from distutils.core import setup 5 | 6 | setup(name='streamplot', 7 | version='0.1', 8 | description='Real Time Plots with pyqtgraph', 9 | url="https://github.com/GuillaumeGenthial/streamplot", 10 | author='Guillaume Genthial', 11 | author_email='genthial@stanford.edu', 12 | license='MIT', 13 | install_requires=[ 14 | 'numpy', 15 | 'pyqtgraph', 16 | ], 17 | zip_safe=False) -------------------------------------------------------------------------------- /streamplot.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import time 3 | import collections 4 | import numpy as np 5 | try: 6 | import pyqtgraph as pg 7 | from pyqtgraph.Qt import QtGui, QtCore 8 | pg.setConfigOption('background', 'w') 9 | except Exception as e: 10 | print ("Unable to import pyqtgraph") 11 | 12 | class LivePlotter(object): 13 | """ 14 | Creates instance of QT app for plotting 15 | Defines usefull methods to update data and plot 16 | 17 | # Attributes 18 | frequency (float): time in second, minimum time between two updates 19 | downsample (integer): downsampling parameter, unused in this version 20 | size (tuple of integers): size of the window 21 | 22 | # Methods 23 | add(x,y): adds data to plot data 24 | update(): update the plot 25 | """ 26 | def __init__(self, **kwargs): 27 | 28 | self.name = kwargs.get("name", "live_plotter") 29 | self.frequency = kwargs.get("frequency", 0.1) 30 | self.downsample = kwargs.get("downsample", 10) 31 | self.point_nb = kwargs.get("point_nb", 100) 32 | self.size = kwargs.get("size", (600, 300)) 33 | self.pen = kwargs.get("pen", "r") 34 | self.x_axis = kwargs.get("x_axis", "x") 35 | self.y_axis = kwargs.get("y_axis", "y") 36 | self.x_unit = kwargs.get("x_unit", "t") 37 | self.y_unit = kwargs.get("y_unit", "") 38 | 39 | self.x_min = kwargs.get("x_min", 0) 40 | self.x_max = kwargs.get("x_max", 100) 41 | self.x_pad = kwargs.get("x_pad", 0) 42 | 43 | self.y_min = kwargs.get("y_min", 0) 44 | self.y_max = kwargs.get("y_max", 100) 45 | self.y_pad = kwargs.get("y_pad", 0) 46 | 47 | self.last_refresh = time.time() 48 | 49 | self.x, self.y = [], [] 50 | 51 | try: 52 | self.win = kwargs.get("win", pg.GraphicsWindow().resize(self.size[0], self.size[1])) 53 | self.p = self.win.addPlot(title=self.name) 54 | self.p.setLabel('left', self.y_axis, units=self.y_unit) 55 | self.p.setLabel('bottom', self.x_axis, units=self.x_unit) 56 | self.p.setXRange(self.x_min, self.x_max,self.x_pad) 57 | self.p.setYRange(self.y_min, self.y_max,self.y_pad) 58 | self.plot = self.p.plot(self.x, self.y, pen=self.pen) 59 | 60 | except Exception as e: 61 | print ("Unable to initialize Live Plotter") 62 | 63 | 64 | def add(self, y, x=None): 65 | """ 66 | Adds data to the plot 67 | If x is None, will take time for x axis 68 | """ 69 | if x is None: 70 | x = time.time() 71 | self.x += [x] 72 | self.y += [y] 73 | 74 | def update(self): 75 | """ 76 | After having added data to the graph data, calling update updates the plot 77 | """ 78 | try: 79 | t = time.time() 80 | frequency = self.frequency 81 | last_refresh = self.last_refresh 82 | downsample = self.downsample 83 | point_nb = self.point_nb 84 | 85 | if frequency is not None: 86 | if t - last_refresh < frequency: 87 | return 88 | 89 | if point_nb is not None: 90 | x_size = len(self.x) 91 | downsample = x_size / point_nb 92 | 93 | # self.plot.setData(self.x, self.y, downsample=downsample) 94 | self.plot.setData(self.x, self.y) 95 | pg.QtGui.QApplication.processEvents() 96 | self.last_refresh = t 97 | 98 | except Exception as e: 99 | pass 100 | 101 | def close(self): 102 | """ 103 | Closes the window 104 | """ 105 | try: 106 | self.win.close() 107 | except Exception as e: 108 | pass 109 | 110 | class PlotManager(object): 111 | """ 112 | General class to handle multiple variable plotting in the same window 113 | 114 | # Attributes 115 | title (string): title of the window 116 | size (tuple of integers): size of the window 117 | nline (integer): number of plots for each line of the window, default 3 118 | frequency (float): see LivePlotter 119 | plots (OrderedDict of LivePlotter instances): where the plots are 120 | 121 | # Example 122 | length = 10000 123 | costs = np.arange(length) 124 | 125 | plt_mgr = PlotManager( 126 | title="plots", 127 | nline=3) 128 | 129 | for i in range(length): 130 | cost = costs[i] 131 | plt_mgr.add("cost", cost) 132 | plt_mgr.add("time", time.time()) 133 | plt_mgr.add("time2", time.time()) 134 | plt_mgr.update() 135 | 136 | plt_mgr.close() 137 | 138 | """ 139 | def __init__(self, **kwargs): 140 | self.title = kwargs.get("title", "Plots") 141 | self.size = kwargs.get("size", (800, 400)) 142 | self.nline = kwargs.get("nline", 3) 143 | self.frequency = kwargs.get("frequency", 1) 144 | self.downsample = kwargs.get("downsample", 1) 145 | self.point_nb = kwargs.get("point_nb", 100) 146 | self.nplots = -1 147 | 148 | self.x_min = kwargs.get("x_min", 0) 149 | self.x_max = kwargs.get("x_max", 100) 150 | self.x_pad = kwargs.get("x_pad", 0) 151 | 152 | self.y_min = kwargs.get("y_min", -50) 153 | self.y_max = kwargs.get("y_max", 50) 154 | self.y_pad = kwargs.get("y_pad", 0) 155 | try: 156 | self.plots = collections.OrderedDict() 157 | self.win = pg.GraphicsWindow(title=self.title) 158 | self.win.resize(self.size[0], self.size[1]) 159 | except Exception as e: 160 | print ("Unable to initialize Plot Manager") 161 | 162 | def add(self, name, y, x=None, **kwargs): 163 | """ 164 | Adds data x, y to the data of the variable with name name. 165 | """ 166 | try: 167 | if name not in self.plots: 168 | self.nplots += 1 169 | if self.nplots % self.nline == 0: 170 | self.win.nextRow() 171 | 172 | self.plots[name] = LivePlotter( 173 | name=name, 174 | win=self.win, 175 | frequency=self.frequency, 176 | downsample=self.downsample, 177 | point_nb=self.point_nb, 178 | x_min=self.x_min, 179 | x_max=self.x_max, 180 | x_pad=self.x_pad, 181 | y_min=self.y_min, 182 | y_max=self.y_max, 183 | y_pad=self.y_pad, 184 | **kwargs) 185 | 186 | self.plots[name].add(y, x) 187 | except Exception as e: 188 | pass 189 | 190 | def update(self): 191 | """ 192 | Updates all subplots 193 | """ 194 | for name, plot in self.plots.items(): 195 | plot.update() 196 | 197 | def close(self): 198 | """ 199 | Close window from Terminal 200 | """ 201 | try: 202 | wait = input("Press ENTER to close plots") 203 | except Exception as e: 204 | pass 205 | for name, plot in self.plots.iteritems(): 206 | plot.close() -------------------------------------------------------------------------------- /test.py: -------------------------------------------------------------------------------- 1 | from streamplot import PlotManager 2 | import numpy as np 3 | import time 4 | 5 | length = 10000 6 | costs = np.arange(length) 7 | 8 | plt_mgr = PlotManager( 9 | title="plots", 10 | nline=3) 11 | 12 | for i in range(length): 13 | cost = costs[i] 14 | plt_mgr.add("cost", cost) 15 | plt_mgr.add("time", time.time()) 16 | plt_mgr.add("time2", time.time()) 17 | plt_mgr.update() 18 | 19 | plt_mgr.close() 20 | --------------------------------------------------------------------------------