Skip to content

Commit 96f8fce

Browse files
committed
Merge branch 'master' into debian
2 parents d71dc97 + 876b04a commit 96f8fce

File tree

3 files changed

+160
-6
lines changed

3 files changed

+160
-6
lines changed

README.org

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,8 @@ Plot generation is controlled by two sets of options:
113113
plot, the axis labels, the extents, 2d/3d selection, etc. All the plot options
114114
are described below in "Plot options".
115115

116-
- Curve options: parameters that affect only a single curve
116+
- Curve options: parameters that affect only a single curve. Each is described
117+
below in "Curve options".
117118

118119
** Data arguments
119120

@@ -221,6 +222,69 @@ represent each data point. For example, if we want a 2D line plot with varying
221222
colors plotted with an implicit domain, set tuplesize=3 as before (x,y,color),
222223
but pass in only 2 arrays (y, color).
223224

225+
** Symbolic equations
226+
227+
Gnuplot can plot both data and equations. This module exists largely for the
228+
data-plotting case, but sometimes it can be useful to plot equations together
229+
with some data. This is supported by the 'equation' plot option. This plot
230+
option is either a string (for a single equation) or a list/tuple containing
231+
multiple strings for multiple equations. Note that plotting only equations
232+
without data is not supported (and generally is better done with gnuplot
233+
directly). An example:
234+
235+
#+BEGIN_SRC python
236+
import numpy as np
237+
import numpy.random as nr
238+
import numpy.linalg
239+
import gnuplotlib as gp
240+
241+
# generate data
242+
x = np.arange(100)
243+
c = np.array([1, 1800, -100, 0.8]) # coefficients
244+
m = x[:, np.newaxis] ** np.arange(4) # 1, x, x**2, ...
245+
noise = 1e4 * nr.random(x.shape)
246+
y = np.dot( m, c) + noise # polynomial corrupted by noise
247+
248+
c_fit = np.dot(numpy.linalg.pinv(m), y) # coefficients obtained by a curve fit
249+
250+
# generate a string that describes the curve-fitted equation
251+
fit_equation = '+'.join( '{} * {}'.format(c,m) for c,m in zip( c_fit.tolist(), ('x**0','x**1','x**2','x**3')))
252+
253+
# plot the data points and the fitted curve
254+
gp.plot(x, y, _with='points', equation = fit_equation)
255+
#+END_SRC
256+
257+
Here I generated some data, performed a curve fit to it, and plotted the data
258+
points together with the best-fitting curve. Here the best-fitting curve was
259+
plotted by gnuplot as an equation, so gnuplot was free to choose the proper
260+
sampling frequency. And as we zoom around the plot, the sampling frequency is
261+
adjusted to keep things looking nice.
262+
263+
Note that the various styles and options set by the other options do NOT apply
264+
to these equation plots. Instead, the string is passed to gnuplot directly, and
265+
any styling can be applied there. For instance, to plot a parabola with thick
266+
lines, you can issue
267+
268+
#+BEGIN_SRC python
269+
gp.plot( ....., equation = 'x**2 with lines linewidth 2')
270+
#+END_SRC
271+
272+
As before, see the gnuplot documentation for details. You can also do fancy
273+
things:
274+
275+
#+BEGIN_SRC python
276+
x = np.arange(100, dtype=float) / 100 * np.pi * 2;
277+
c,s = np.cos(x), np.sin(x)
278+
279+
gp.plot( c,s,
280+
square=1, _with='points',
281+
set = ('parametric', 'trange [0:2*3.14]'),
282+
equation = "sin(t),cos(t)" )
283+
#+END_SRC
284+
285+
Here the data are points evently spaced around a unit circle. Along with these
286+
points we plot a unit circle as a parametric equation.
287+
224288
** Interactivity
225289

226290
The graphical backends of Gnuplot are interactive, allowing the user to pan,
@@ -303,6 +367,13 @@ generated
303367

304368
These specify axis labels
305369

370+
- equation
371+
372+
This option allows equations represented as formula strings to be plotted along
373+
with data passed in as numpy arrays. This can be a string (for a single
374+
equation) or an array/tuple of strings (for multiple equations). See the
375+
"Symbolic equations" section above.
376+
306377
- hardcopy
307378

308379
Instead of drawing a plot on screen, plot into a file instead. The output

gnuplotlib.py

Lines changed: 87 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,8 @@ class gnuplotlib has a gnuplot process associated with it, which has (usually) a
116116
plot, the axis labels, the extents, 2d/3d selection, etc. All the plot options
117117
are described below in "Plot options".
118118
119-
- Curve options: parameters that affect only a single curve
119+
- Curve options: parameters that affect only a single curve. Each is described
120+
below in "Curve options".
120121
121122
** Data arguments
122123
@@ -224,6 +225,69 @@ class gnuplotlib has a gnuplot process associated with it, which has (usually) a
224225
colors plotted with an implicit domain, set tuplesize=3 as before (x,y,color),
225226
but pass in only 2 arrays (y, color).
226227
228+
** Symbolic equations
229+
230+
Gnuplot can plot both data and equations. This module exists largely for the
231+
data-plotting case, but sometimes it can be useful to plot equations together
232+
with some data. This is supported by the 'equation' plot option. This plot
233+
option is either a string (for a single equation) or a list/tuple containing
234+
multiple strings for multiple equations. Note that plotting only equations
235+
without data is not supported (and generally is better done with gnuplot
236+
directly). An example:
237+
238+
#+BEGIN_SRC python
239+
import numpy as np
240+
import numpy.random as nr
241+
import numpy.linalg
242+
import gnuplotlib as gp
243+
244+
# generate data
245+
x = np.arange(100)
246+
c = np.array([1, 1800, -100, 0.8]) # coefficients
247+
m = x[:, np.newaxis] ** np.arange(4) # 1, x, x**2, ...
248+
noise = 1e4 * nr.random(x.shape)
249+
y = np.dot( m, c) + noise # polynomial corrupted by noise
250+
251+
c_fit = np.dot(numpy.linalg.pinv(m), y) # coefficients obtained by a curve fit
252+
253+
# generate a string that describes the curve-fitted equation
254+
fit_equation = '+'.join( '{} * {}'.format(c,m) for c,m in zip( c_fit.tolist(), ('x**0','x**1','x**2','x**3')))
255+
256+
# plot the data points and the fitted curve
257+
gp.plot(x, y, _with='points', equation = fit_equation)
258+
#+END_SRC
259+
260+
Here I generated some data, performed a curve fit to it, and plotted the data
261+
points together with the best-fitting curve. Here the best-fitting curve was
262+
plotted by gnuplot as an equation, so gnuplot was free to choose the proper
263+
sampling frequency. And as we zoom around the plot, the sampling frequency is
264+
adjusted to keep things looking nice.
265+
266+
Note that the various styles and options set by the other options do NOT apply
267+
to these equation plots. Instead, the string is passed to gnuplot directly, and
268+
any styling can be applied there. For instance, to plot a parabola with thick
269+
lines, you can issue
270+
271+
#+BEGIN_SRC python
272+
gp.plot( ....., equation = 'x**2 with lines linewidth 2')
273+
#+END_SRC
274+
275+
As before, see the gnuplot documentation for details. You can also do fancy
276+
things:
277+
278+
#+BEGIN_SRC python
279+
x = np.arange(100, dtype=float) / 100 * np.pi * 2;
280+
c,s = np.cos(x), np.sin(x)
281+
282+
gp.plot( c,s,
283+
square=1, _with='points',
284+
set = ('parametric', 'trange [0:2*3.14]'),
285+
equation = "sin(t),cos(t)" )
286+
#+END_SRC
287+
288+
Here the data are points evently spaced around a unit circle. Along with these
289+
points we plot a unit circle as a parametric equation.
290+
227291
** Interactivity
228292
229293
The graphical backends of Gnuplot are interactive, allowing the user to pan,
@@ -306,6 +370,13 @@ class gnuplotlib has a gnuplot process associated with it, which has (usually) a
306370
307371
These specify axis labels
308372
373+
- equation
374+
375+
This option allows equations represented as formula strings to be plotted along
376+
with data passed in as numpy arrays. This can be a string (for a single
377+
equation) or an array/tuple of strings (for multiple equations). See the
378+
"Symbolic equations" section above.
379+
309380
- hardcopy
310381
311382
Instead of drawing a plot on screen, plot into a file instead. The output
@@ -717,7 +788,7 @@ class gnuplotlib has a gnuplot process associated with it, which has (usually) a
717788
knownPlotOptions = frozenset(('3d', 'dump', 'ascii', 'log',
718789
'cmds', 'set', 'unset', 'square', 'square_xy', 'title',
719790
'hardcopy', 'terminal', 'output',
720-
'with',
791+
'with', 'equation',
721792
'xmax', 'xmin', 'xrange', 'xinv', 'xlabel',
722793
'y2max', 'y2min', 'y2range', 'y2inv', 'y2label',
723794
'ymax', 'ymin', 'yrange', 'yinv', 'ylabel',
@@ -974,8 +1045,13 @@ def _getPlotOptionsCmds(self):
9741045
self.plotOptions['output'] = outputfile
9751046

9761047

977-
if 'terminal' in self.plotOptions and not 'output' in self.plotOptions:
978-
sys.stderr.write('Warning: defined gnuplot terminal, but NOT an output file. Is this REALLY what you want?\n')
1048+
if 'terminal' in self.plotOptions:
1049+
if self.plotOptions['terminal'] in ('x11', 'wxt', 'qt', 'aquaterm'):
1050+
if 'output' in self.plotOptions:
1051+
sys.stderr.write("Warning: requested a known-interactive gnuplot terminal AND an output file. Is this REALLY what you want?\n")
1052+
else:
1053+
if not 'output' in self.plotOptions:
1054+
sys.stderr.write("Warning: requested a gnuplot terminal (not a known-interactive one), but NOT an output file. Is this REALLY what you want?\n")
9791055

9801056
# add the extra global options
9811057
if 'cmds' in self.plotOptions:
@@ -1323,6 +1399,13 @@ def getTestDataLen(curve):
13231399
if self.plotOptions.get('3d'): basecmd += 'splot '
13241400
else: basecmd += 'plot '
13251401

1402+
# send all equations
1403+
if 'equation' in self.plotOptions:
1404+
if isinstance(self.plotOptions['equation'], (list, tuple)):
1405+
basecmd += ''.join( eq + ', ' for eq in self.plotOptions['equation'])
1406+
else:
1407+
basecmd += self.plotOptions['equation'] + ', '
1408+
13261409
plotCurveCmds = []
13271410
plotCurveCmdsMinimal = [] # same as above, but with a single data point per plot only
13281411
testData = '' # data to make a minimal plot

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ def run(self):
1414

1515

1616
setup(name = 'gnuplotlib',
17-
version = '0.8',
17+
version = '0.9',
1818
author = 'Dima Kogan',
1919
author_email = 'dima@secretsauce.net',
2020
url = 'http://github.com/dkogan/gnuplotlib',

0 commit comments

Comments
 (0)