from scipy.optimize import curve_fit
from scipy.odr import *
from math import exp
import matplotlib
import string
import os
from colour import Color
import numpy as np
#matplotlib.use('pgf')
import matplotlib.pyplot as plt
from matplotlib.patches import Ellipse, Polygon
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d import proj3d
from matplotlib.colors import LinearSegmentedColormap, ListedColormap
import platform
from matplotlib import cm
from pyg.colors import pu as color
from copy import copy
from IPython.display import SVG, display, Latex, HTML, display_latex
import subprocess
import sys
import random
import weakref
import re
import lyxithea.lyxithea as lyx
from pyg import twod as pyg2d
if "DISPLAY" not in os.environ.keys():
import matplotlib
matplotlib.use('Agg')
else:
import matplotlib
matplotlib.use('pgf')
import matplotlib.pyplot as plt
global context
context = 'writeup'
global __figcount__
__figcount__ = 1
exported_files = {}
plt.close("all")
preamble = ['\usepackage{nicefrac}',
'\usepackage{gensymb}',
'\usepackage{xcolor}',
'\definecolor{grey60}{HTML}{746C66}',
'\definecolor{grey40}{HTML}{A7A9AC}',
r'\usepackage{amsmath, amssymb}',
r'\usepackage{stackrel}',
'\\providecommand{\unit}[1]{\ensuremath{\\textcolor{grey60}' +
'{\mathrm{#1}}}}']
# make the line graphing class
[docs]class pyg3d(pyg2d.pyg2d):
""" A ``pyg.pyg3d`` object plots many three-dimensional data types.
The ``pyg3d`` class provides an access to ``matplotlib`` charting functions
and some hook ins to making these functions easier to use and more
repeatable. The constructor itself takes only one optional argument,
``env``.
:param str env: The environement option defines where you are going to use
the generated plot, with the default option being plot (or printing).
If you are using this to generate plots for a gui, define this option
as ``gui`` and the class will choose a prettier parameter set for your
chart. Default: ``plot``.
:type env: ``plot``, ``gui``, or ``None``
:return: the ``pyg3d`` object.
:rtype: ``pyg3d``
"""
leg_col_one_col = 2
leg_col_two_col = 3
leg_col_full_page = 4
marker = {0: '+',
1: '.',
2: '1',
3: '1',
4: '2',
5: '3',
6: '4'}
linestyle = {0: '-',
1: '--',
2: '-.',
3: ':'}
sizestring = {'1': 'onecolumn',
'2': 'twocolumn',
'fp': 'fullpage',
'cs': 'customsize',
'none': ''}
def __init__(self, env='plot', colors='purdue'):
super(pyg3d, self).__init__(env=env, polar=False, colors=colors)
matplotlib.rcParams['_internal.classic_mode'] = True
self.ax = self.fig.gca(projection='3d')
self.cax = []
self.surfs = {}
self.contours = {}
self.annotations = []
self.ax.xaxis._axinfo['tick']['outward_factor'] = 0
self.ax.yaxis._axinfo['tick']['outward_factor'] = 0
self.ax.zaxis._axinfo['tick']['outward_factor'] = 0
self.ax.view_init(30, 245)
self.ax.w_xaxis.gridlines.set_lw(0.1)
self.ax.w_yaxis.gridlines.set_lw(0.1)
self.ax.w_zaxis.gridlines.set_lw(0.1)
self.ax.w_xaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))
self.ax.w_yaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))
self.ax.w_zaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))
def orthogonal_proj(self, zfront, zback):
a = (zfront+zback)/(zfront-zback)
b = -2*(zfront*zback)/(zfront-zback)
return np.array([[1,0,0,0],
[0,1,0,0],
[0,0,a,b],
[0,0,-1.0e-9,zback]])
def upright_orthogonal_proj(self, zfront, zback):
a = (zfront+zback)/(zfront-zback)
b = -2*(zfront*zback)/(zfront-zback)
return np.array([[1,0,0,0],
[0,1,0,0],
[0,0,a,b],
[0,0,1.0e-9,zback]])
def surf2d(self, x, y, z, c, cmap=color.brand_cmap, addto=None, name='plot',
**kwargs):
from matplotlib.collections import PolyCollection
if addto is None:
axes = self.ax
else:
axes = addto.ax
cmaplist = [_c.rgb for _c in cmap]
self.cmap = matplotlib.colors.ListedColormap(cmaplist,
name='brand_cmap')
m = np.ma.masked_where(np.isnan(c), c)
levels = np.linspace(np.min(c), np.max(c), 50)
if len(x) == 1:
print 'x'
Y, Z = np.meshgrid(y, z)
zdir = 'x'
zs = x[0]
self.cax.extend([axes.contourf(c, Y, Z, cmap=self.cmap, offset=zs, zdir='x',
levels=levels, linestyle='-', **kwargs)])
elif len(y) == 1:
print 'y'
Z, X = np.meshgrid(z, x)
zdir = 'y'
zs = y[0]
self.cax.extend([axes.contourf(X, c.T, Z, cmap=self.cmap, offset=zs, zdir='y',
levels=levels, linestyle='-', **kwargs)])
elif len(z) == 1:
print 'z'
X, Y = np.meshgrid(x, y)
zdir = 'z'
zs = z[0]
self.cax.extend([axes.contourf(X, Y, c, cmap=self.cmap, offset=zs, zdir='z',
levels=levels, linestyle='-', **kwargs)])
def colorbar(self):
self.norm = self.cax[0].norm
maxes = []
mins = []
for c in self.cax:
c.set_norm = self.norm
maxes.extend([c.levels[-1]])
mins.extend([c.levels[0]])
levels = np.linspace(np.nanmin(mins), np.nanmax(maxes))
for c in self.cax:
c.vmin = np.nanmin(mins)
c.vmax = np.nanmax(maxes)
self.cbar = self.fig.colorbar(self.cax[0])
#self.artists.append(self.cbar)
def surf(self, x, y, z, c=None, cmap=color.brand_cmap, addto=None,
name='surf', **kwargs):
if addto is None:
axes = self.ax
else:
axes = addto.ax
X, Y = np.meshgrid(x, y)
# z = np.nan_to_num(z)
m = np.ma.masked_where(np.isnan(z),z)
cmaplist = [_c.rgb for _c in cmap]
cmap = matplotlib.colors.ListedColormap(cmaplist,
name='brand_cmap')
surf = axes.plot_surface(X, Y, m, cmap=cmap,
linewidth=0, antialiased=False,
rstride=1, cstride=1,
vmin=np.nanmin(z), vmax=np.nanmax(z),
**kwargs)
self.surfs[name] = surf
return self
def contour(self, x, y, z, name='countour', addto=None, **kwargs):
if addto is None:
axes = self.ax
else:
axes = addto.ax
X, Y = np.meshgrid(x, y)
# z = np.nan_to_num(z)
m = np.ma.masked_where(np.isnan(z),z)
#cmaplist = [_c.rgb for _c in cmap]
#cmap = matplotlib.colors.ListedColormap(cmaplist, name='brand_cmap')
cs = axes.contour(X, Y, m, **kwargs)
self.contours[name] = cs
return self
def legend(self):
surfs = []
labels = []
for key, val in self.surfs.iteritems():
labels.extend([key])
surfs.extend([val])
self.ax.legend(surfs, labels, numpoints=1)
def view(self, phi, theta, perspective=False, upright=False):
if not perspective:
if upright:
proj3d.persp_transformation = self.upright_orthogonal_proj
else:
proj3d.persp_transformation = self.orthogonal_proj
self.ax.view_init(phi, theta)
return self
def cylinder(self, center, h, r, color, planes=True, lines=False,
axes=None):
try:
self.c_data
except AttributeError:
self.c_data = []
try:
self.c_data.extend([center[2]])
except AttributeError:
pass
if isinstance(planes, float):
planes_alpha = planes
elif planes:
planes_alpha = 0.1
else:
planes_alpha = 0.0
if axes is None:
axes = self.ax
else:
axes = axes.ax
if lines:
linewidth = 0.01
else:
linewidth = 0.0
# draw the cylindrical surface
t = np.linspace(0, 2.0 * np.pi, 100)
if h[0] > h[1] and h[0] > h[2]:
cz = center[0]
cx = center[2]
cy = center[1]
elif h[2] > h[1] and h[2] > h[0]:
cz = center[2]
cx = center[0]
cy = center[1]
x = cx + r * np.cos(t)
y = cy + r * np.sin(t)
z = cz + np.linspace(- np.max(h) / 2, np.max(h) / 2, 100)
Tc, Zc =np.meshgrid(t, z)
Xc = cx + r * np.cos(Tc)
Yc = cy + r * np.sin(Tc)
rstride = 20
cstride = 10
if h[0] > h[1] and h[0] > h[2]:
cylsurface = axes.plot_surface(Zc, Yc, Xc, alpha=planes_alpha,
rstride=rstride, cstride=cstride,
color=color, shade=False,
linewidth=linewidth)
elif h[2] > h[1] and h[2] > h[0]:
cylsurface = axes.plot_surface(Xc, Yc, Zc, alpha=planes_alpha,
rstride=rstride, cstride=cstride,
color=color, shade=False,
linewidth=linewidth)
t = np.linspace(0.0, 2.0 * np.pi, 100)
radius = np.linspace(0.0, r, 100)
R, Theta = np.meshgrid(radius, t)
Xc, Yc = cx + R * np.cos(Theta), cy + R * np.sin(Theta)
Zc = cz + np.max(h) / 2.0
if h[0] > h[1] and h[0] > h[2]:
top = axes.plot_surface(Zc, Yc, Xc, alpha=planes_alpha, rstride=100,
cstride=100, color=color, shade=False,
linewidth=linewidth)
elif h[2] > h[1] and h[2] > h[0]:
top = axes.plot_surface(Xc, Yc, Zc, alpha=planes_alpha, rstride=100,
cstride=100, color=color, shade=False,
linewidth=linewidth)
Zc = cz - np.max(h) / 2.0
if h[0] > h[1] and h[0] > h[2]:
bottom = axes.plot_surface(Zc, Yc, Xc, alpha=planes_alpha, rstride=100,
cstride=100, color=color, shade=False,
linewidth=linewidth)
elif h[2] > h[1] and h[2] > h[0]:
bottom = axes.plot_surface(Xc, Yc, Zc, alpha=planes_alpha, rstride=100,
cstride=100, color=color, shade=False,
linewidth=linewidth)
return self
def sphere(self, center, r, color='gray', planes=True, lines=False,
axes=None):
if axes is None:
axes = self.ax
else:
axes = axes.ax
if isinstance(planes, float):
planes_alpha = planes
elif planes:
planes_alpha = 0.1
else:
planes_alpha = 0.0
if lines:
linewidth = 0.01
else:
linewidth = 0.0
rstride = 20
cstride = 20
theta = np.linspace(0., 2. * np.pi, 100)
phi = np.linspace(0., np.pi, 100)
x = center[0] + r * np.outer(np.cos(theta), np.sin(phi))
y = center[1] + r * np.outer(np.sin(theta), np.sin(phi))
z = center[2] + r * np.outer(np.ones(np.size(theta)), np.cos(phi))
sph = axes.plot_surface(x, y, z,
rstride=cstride, cstride=rstride,
color=color, alpha=planes_alpha, shade=False,
linewidth=linewidth)
return self
def box(self, corner, d1, d2, d3, color='gray', planes=True, lines=False,
axes=None):
if axes is None:
axes = self.ax
else:
axes = axes.ax
if isinstance(planes, float):
planes_alpha = planes
elif planes:
planes_alpha = 0.1
else:
planes_alpha = 0.0
if lines:
linewidth = 0.5
else:
linewidth = 0.0
rstride = 10
cstride = 10
l1 = np.sqrt(d1[0]**2 + d1[1]**2 + d1[2]**2)
l2 = np.sqrt(d2[0]**2 + d2[1]**2 + d2[2]**2)
l3 = np.sqrt(d3[0]**2 + d3[1]**2 + d3[2]**2)
numpts = 10
planes = []
top_corner = np.array(corner) + np.array(d1) + np.array(d2) + \
np.array(d3)
for ds in [(d1, d2), (d2, d3), (d1, d3)]:
a1 = ds[0]
a2 = ds[1]
xx = np.zeros((numpts, numpts))
yy = np.zeros((numpts, numpts))
zz = np.zeros((numpts, numpts))
for i in range(0, numpts):
for j in range(0, numpts):
xx[i, j] = corner[0] + a1[0] * float(i) / float(numpts - 1) + \
a2[0] * float(j) / float(numpts - 1)
yy[i, j] = corner[1] + a1[1] * float(i) / float(numpts - 1) + \
a2[1] * float(j) / float(numpts - 1)
zz[i, j] = corner[2] + a1[2] * float(i) / float(numpts - 1) + \
a2[2] * float(j) / float(numpts - 1)
planes.extend([axes.plot_surface(xx, yy, zz,
rstride=cstride, cstride=rstride,
color=color, alpha=planes_alpha, shade=False,
linewidth=linewidth)])
for i in range(0, numpts):
for j in range(0, numpts):
xx[i, j] = top_corner[0] - \
a1[0] * float(i) / float(numpts - 1) - \
a2[0] * float(j) / float(numpts - 1)
yy[i, j] = top_corner[1] - \
a1[1] * float(i) / float(numpts - 1) - \
a2[1] * float(j) / float(numpts - 1)
zz[i, j] = top_corner[2] - \
a1[2] * float(i) / float(numpts - 1) - \
a2[2] * float(j) / float(numpts - 1)
planes.extend([axes.plot_surface(xx, yy, zz,
rstride=cstride, cstride=rstride,
color=color, alpha=planes_alpha, shade=False,
linewidth=linewidth)])
#top = axes.plot_surface(Xc, Yc, )
return self
def cube(self, center, dx, dy, dz, color='gray', planes=True, lines=False,
axes=None):
if axes is None:
axes = self.ax
else:
axes = axes.ax
if isinstance(planes, float):
planes_alpha = planes
elif planes:
planes_alpha = 0.1
else:
planes_alpha = 0.0
if lines:
linewidth = 1.0
else:
linewidth = 0.0
rstride = 100
cstride = 100
Xc, Yc = np.meshgrid(np.linspace(center[0] - dx/2.,
center[0] + dx/2., 100),
np.linspace(center[1] - dy/2.,
center[1] + dy/2., 100))
top = axes.plot_surface(Xc, Yc, center[2] + dz/2.,
rstride=cstride, cstride=rstride,
color=color, alpha=planes_alpha, shade=False,
linewidth=linewidth)
bottom = axes.plot_surface(Xc, Yc, center[2] - dz/2.,
rstride=cstride, cstride=rstride,
color=color, alpha=planes_alpha, shade=False,
linewidth=linewidth)
Xc, Zc = np.meshgrid(np.linspace(center[0] - dx/2.,
center[0] + dx/2., 100),
np.linspace(center[2] - dz/2.,
center[2] + dz/2., 100))
left = axes.plot_surface(Xc, center[1] + dy/2., Zc,
rstride=cstride, cstride=rstride,
color=color, alpha=planes_alpha, shade=False,
linewidth=linewidth)
right = axes.plot_surface(Xc, center[1] - dy/2., Zc,
rstride=cstride, cstride=rstride,
color=color, alpha=planes_alpha, shade=False,
linewidth=linewidth)
Yc, Zc = np.meshgrid(np.linspace(center[1] - dy/2.,
center[1] + dy/2., 100),
np.linspace(center[2] - dz/2.,
center[2] + dz/2., 100))
front = axes.plot_surface(center[0] + dx/2., Yc, Zc,
rstride=cstride, cstride=rstride,
color=color, alpha=planes_alpha, shade=False,
linewidth=linewidth)
back = axes.plot_surface(center[0] - dx/2., Yc, Zc,
rstride=cstride, cstride=rstride,
color=color, alpha=planes_alpha, shade=False,
linewidth=linewidth)
return self
def add_data_pointer(self, x, y, z, string=None,
place='up-right', axes=None):
if axes is None:
axes = self.ax
_x, _y, _ = proj3d.proj_transform(x, y, z, self.ax.get_proj())
super(pyg3d, self).add_data_pointer(_x, point=_y, string=string,
place='up-right', axes=None)
def update_data_pointers(self):
for ann in self.annotations:
x = ann[0]
y = ann[1]
z = ann[2]
_x, _y, _ = proj3d.proj_transform(x, y, z, self.ax.get_proj())
ann[3].xy = (_x, _y)
'''
def colorbar(self):#, cmap, cmap_name='Color Map'):
if cmap.__class__.__name__ == "list" and \
cmap[0].__class__.__name__ == "Color":
colors = [c.rgb for c in cmap]
ax1 = self.fig.add_axes([0.95, 0.05, 0.04, 0.9])
self.ax_subp.extend([ax1])
cm = LinearSegmentedColormap.from_list(
cmap_name, colors, N=len(cmap))
norm = matplotlib.colors\
.Normalize(vmin=np.min(self.c_data), vmax=np.max(self.c_data))
cb1 = matplotlib.colorbar \
.ColorbarBase(ax1, cmap=cm, norm=norm)
ax1.set_ylabel(cmap_name)
'''
[docs] def zlabel(self, label, axes=None):
r""" ``pyg2d.xlabel`` adds a label to the x-axis.
``pyg2d.xlabel`` adds a label to the x-axis of the current axes (or
other axis given by kwarg ``axes``).
:param str label: The label added to the x-axis of the defined axis.
The label can take LaTeX arguments and the ah style guide asks for
labels given as 'Label ($variable$) [$unit$]'.
:param axes: If not ``None``, this argument will apply the x-label
to the provided axis.
:type axes: axes, or ``None``
:return: None
"""
if axes is None:
axes = self.ax
zlab = axes.set_zlabel(label)
self.artists.append(zlab)
[docs] def clabel(self, label, axes=None):
r""" ``pyg2d.xlabel`` adds a label to the x-axis.
``pyg2d.xlabel`` adds a label to the x-axis of the current axes (or
other axis given by kwarg ``axes``).
:param str label: The label added to the x-axis of the defined axis.
The label can take LaTeX arguments and the ah style guide asks for
labels given as 'Label ($variable$) [$unit$]'.
:param axes: If not ``None``, this argument will apply the x-label
to the provided axis.
:type axes: axes, or ``None``
:return: None
"""
if axes is None:
axes = self.ax
self.clab = self.cbar.set_label(label)
#self.artists.append(self.clab)
[docs] def zlim(self, minz, maxz, axes=None):
""" ``pyg2d.ylim`` limits the view of the y-axis to limits.
:param float miny: The minimum value of y that will be shown.
:param float maxy: The maximum value of y that will be shown.
:param axes: If not ``None``, this argument will apply the y-limit
to the provided axis.
:type axes: axes, or ``None``
:return: None
"""
if axes is None:
axes = self.ax
axes.set_zlim([minz, maxz])