Chapter 1
- Last updated
- Save as PDF
- Page ID
- 38411
\( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \) \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)\(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\) \(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\)\(\newcommand{\AA}{\unicode[.8,0]{x212B}}\)
Static Volume \(\PageIndex{1}\) (Python):
import matplotlib.pyplot as plt import numpy as np from mpl_toolkits.mplot3d import Axes3D import mpl_toolkits.axes_grid1 %matplotlib widget pi = np.pi lowerLimit = -2 upperLimit = 2 step = .01 eq = "1-x**2" def f(x): return 1-x**2 xs = np.arange(lowerLimit, upperLimit+step, step) ys = f(xs) maximum = abs(ys).max() fig = plt.figure('Volume Animated Circle Slices around X axis', figsize=(6,3)) ax1 = fig.gca(projection='3d') plt.style.use('seaborn-pastel') ax1.set_title('\nRegion under parabola ' + eq + '\n circular slices around x axis') ax1.view_init(elev=45, azim=-90) ax1.set_xlabel('X axis') ax1.set_ylabel('Y axis') ax1.set_zlabel('Z axis') ax1.axes.set_xlim3d(lowerLimit,upperLimit) ticks = np.linspace(lowerLimit, upperLimit, 5) ax1.axes.set_xticks(ticks) ticks = np.linspace(-maximum, maximum, 5) ax1.axes.set_ylim3d(maximum, -maximum) ax1.axes.set_yticks(ticks) ax1.axes.set_zlim3d(-maximum, maximum) ax1.axes.set_zticks(ticks) for x in xs: theta = -pi a = [] b = [] c = [] while theta <= pi: bx = np.cos(theta)*f(x) cx = np.sin(theta)*f(x) a.append(x) b.append(bx) c.append(cx) theta += pi/36.0 circle, = ax1.plot3D(a, b, c, color='b') plt.show()
Animated Square Slices \(\PageIndex{2}\) (Python):
import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D from matplotlib.animation import FuncAnimation %matplotlib widget def square(startX, startY, startZ, width): lines = [] lines.append([[startX, startX], [startY, startY+width], [startZ, startZ]]) lines.append([[startX, startX], [startY, startY], [startZ, startZ+width]]) lines.append([[startX, startX], [startY, startY+width], [startZ+width, startZ+width]]) lines.append([[startX, startX], [startY+width, startY+width], [startZ, startZ+width]]) return lines x = np.arange(0, 1, .01) y = 1-x**2 z = 0 def animate(i): lines = square(i, 0, 0, 1-i**2) for line in lines: thisSquare = ax1.plot3D(line[0], line[1], line[2], color = 'b') plt.draw() return thisSquare fig = plt.figure('Animated Squares', figsize=(6,3)) ax1 = fig.gca(projection='3d') ax1.plot3D(x, y, z, color='b') ax1.view_init(azim=45) plt.style.use('seaborn-pastel') ax1.set_title('Region under parabola y=1-x^2 in first quadrant \n square slices perpendicular to xy plane') ax1.set_xlabel('X axis') ax1.set_ylabel('Y axis') ax1.set_zlabel('Z axis') ax1.axes.set_xlim3d(0, 1) ax1.axes.set_ylim3d(0, 1) ax1.axes.set_zlim3d(0, 1) ax1.set_zticks([0, 0.5, 1]) ax1.set_yticks([0, 0.5, 1]) ax1.set_xticks([0, 0.5, 1]) step = -.05 steps = np.arange(1, 0+step, step) ani = FuncAnimation(fig, animate, steps, interval=400, blit=True, repeat=False) plt.show()
Disc Integration around X-Axis \(\PageIndex{3}\) (Python):
import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D from matplotlib.animation import FuncAnimation from matplotlib.ticker import FormatStrFormatter import mpl_toolkits.axes_grid1 import matplotlib.widgets as widgets import sympy as sp from sympy.parsing.sympy_parser import parse_expr %matplotlib widget x = sp.symbols('x') eq = '1-x^2' pi = np.pi oneDecimal = '%.1f' noDecimals = '%.0f' lowerFlag = False colourSchemes = [] colourSchemes.append(['#00b8ff', '#1500ff', '#3445c3', '#26477e', '#1e225c']) #Blues colourSchemes.append(['#9400D3', '#00ff00', '#ffff00', '#FFA500', '#ff0000']) #Purple(low) to red(high) colourSchemes.append(['#009ee3', '#00a3c9', '#00a6aa', '#00a989', '#2eac66']) #Blue(low) to green(high) colourChoice = 0 def f(x): return 1 - x**2 def on_colour_change(label): global colourChoice colourDict = {'Blues': 0, 'Purple-Red': 1, 'Blue-Green': 2} colourChoice = colourDict[label] restart() def limit_change(newMin, newMax): global lowerLimit, upperLimit, step, x, part, maximum, minimum, firstTime, function lowerLimit = newMin upperLimit = newMax step =(upperLimit-lowerLimit)/100.0 x = np.arange(lowerLimit, upperLimit+step, step) radii = np.abs(f(x)) maximum = radii.max() minimum = radii.min() part = (maximum - minimum)/5.0 if firstTime: firstTime = False else: restart() def checkValue(entry): global lowerFlag, errMsg try: newLimit = float(entry) errMsg.set_text('') except: errMsg.set_text('ERROR: Numbers only!') if lowerFlag: newLimit = lowerLimit else: newLimit = upperLimit if lowerFlag: if newLimit != upperLimit: newLowerLimit = newLimit newUpperLimit = upperLimit if newLimit > upperLimit: newLowerLimit = upperLimit newUpperLimit = newLimit else: if newLimit != lowerLimit: newUpperLimit = newLimit newLowerLimit = lowerLimit if newLimit < lowerLimit: newUpperLimit = lowerLimit newLowerLimit = newLimit lowerFlag = False limit_change(newLowerLimit, newUpperLimit) def setLowerFlag(entry): global lowerFlag lowerFlag = True checkValue(entry) def saveFigure(entry): """Routine to save a figure -- Needs Work, Simpy Restarts Animation for now""" """ global ani, plt ani.stop() saveFile = './Images/' + 'ImageSaveTest' + '.png' plt.savefig(saveFile, bbox_inches='tight', transparent=True) """ restart() def setUpOptions(selection=0): global radio_colourChoice, text_llimit, text_ulimit, check_save t1 = fig.text(0, .76,'Colour scheme', fontsize=9) radio_colourChoice = widgets.RadioButtons(colour_ax1, ('Blues', 'Purple-Red', 'Blue-Green'), active=selection) radio_colourChoice.on_clicked(on_colour_change) stringLimit = '' text_llimit = widgets.TextBox(llimit_ax1, "Lower limit ", initial=stringLimit, color='.95', label_pad=.01) text_llimit.on_submit(setLowerFlag) text_ulimit = widgets.TextBox(ulimit_ax1, "Upper limit ", initial=stringLimit, color='.95', label_pad=.01) text_ulimit.on_submit(checkValue) check_save = widgets.Button(save_ax1, label=u'$\u25F3$', color='.95') check_save.on_clicked(saveFigure) class Animator(FuncAnimation): def __init__(self, fig, func, frames=None, init_func=None,fargs=None, save_count=None, mini=0, maxi=100, pos=(0.3, 0.01), **kwargs): self.i = 0 self.min=mini self.max=maxi self.runs = True self.forwards = True self.fig = fig self.func = func self.setup(pos) FuncAnimation.__init__(self,self.fig, self.update, frames=self.play(), init_func=init_func, fargs=fargs, save_count=save_count, **kwargs ) def play(self): while self.runs: self.i = self.i+self.forwards-(not self.forwards) if self.i > self.min and self.i < self.max: yield self.i else: self.stop() yield self.i def start(self): self.runs=True self.event_source.start() def stop(self, event=None): self.runs = False self.event_source.stop() def forward(self, event=None): self.forwards = True self.start() def oneforward(self, event=None): self.forwards = True self.onestep() def onestep(self): if self.i > self.min and self.i < self.max: self.i = self.i+self.forwards-(not self.forwards) elif self.i == self.min and self.forwards: self.i+=1 elif self.i == self.max and not self.forwards: self.i-=1 self.func(self.i) self.slider.set_val(self.i) self.fig.canvas.draw_idle() def setup(self, pos): sax = self.fig.add_axes([pos[0],pos[1], .42, 0.04]) divider = mpl_toolkits.axes_grid1.make_axes_locatable(sax) fax = divider.append_axes("right", size="80%", pad=0.01) ofax = divider.append_axes("right", size="80%", pad=0.01) sliderax = divider.append_axes("right", size="500%", pad=0.01) self.button_stop = widgets.Button(sax, label=u'$\u25A0$') self.button_forward = widgets.Button(fax, label=u'$\u25B6$') self.button_oneforward = widgets.Button(ofax, label=u'$\u29D0$') self.button_stop.on_clicked(self.stop) self.button_forward.on_clicked(self.forward) self.button_oneforward.on_clicked(self.oneforward) self.slider = widgets.Slider(sliderax, '', self.min, self.max, valinit=self.min, valfmt='%1.0f%%') self.slider.on_changed(self.set_pos) def set_pos(self,i): self.i = int(self.slider.val) self.func(self.i) def update(self, i): self.slider.set_val(i) def circle(spot, radius): theta = np.arange(0, 2*pi+.1, .1) ys = radius*np.cos(theta) zs = radius*np.sin(theta) xs = np.full(len(ys), spot) return xs, ys, zs def chooseColour(val): for j in range(4): if val < minimum+(j+1)*part: return j return 4 def animate(i): incrementedX = x[i] incrementedY = np.abs(f(x[i])) xs, ys, zs = circle(incrementedX, incrementedY) heatColour = colourSchemes[colourChoice][chooseColour(incrementedY)] line, = ax1.plot3D(xs, ys, zs, color = heatColour) return line, def init(): plt.style.use('seaborn-pastel') ax1.set_title('\nRegion under parabola ' + eq + '\n circular slices around x axis') ax1.view_init(elev=45, azim=-90) ax1.set_xlabel('X axis') ax1.set_ylabel('Y axis') ax1.set_zlabel('Z axis') fmt2Use = oneDecimal if maximum >= 100: fmt2Use = noDecimals ax1.w_xaxis.set_major_formatter(FormatStrFormatter(oneDecimal)) ax1.w_yaxis.set_major_formatter(FormatStrFormatter(fmt2Use)) ax1.w_zaxis.set_major_formatter(FormatStrFormatter(fmt2Use)) ax1.axes.set_xlim3d(lowerLimit,upperLimit) ticks = np.linspace(lowerLimit, upperLimit, 5) ax1.axes.set_xticks(ticks) ticks = np.linspace(-maximum, maximum, 5) ax1.axes.set_ylim3d(maximum, -maximum) ax1.axes.set_yticks(ticks) ax1.axes.set_zlim3d(-maximum, maximum) ax1.axes.set_zticks(ticks) setUpOptions(colourChoice) def restart(): ax1.cla() llimit_ax1.cla() ulimit_ax1.cla() firstTime = False init() ani.i = 0 ani.start() lowerLimit = -pi upperLimit = pi firstTime = True g = np.vectorize(f) limit_change(lowerLimit, upperLimit) fig = plt.figure('Volume Animated Circle Slices around X axis', figsize=(6,3)) ax1 = fig.gca(projection='3d') colour_ax1 = fig.add_axes([0, .6, .19, .15]) # [x start, y start, width, height] llimit_ax1 = fig.add_axes([.14, .5, .09, .05]) ulimit_ax1 = fig.add_axes([.14, .4, .09, .05]) save_ax1 = fig.add_axes([.09, .3, .04, .06]) errMsg = fig.text(0, .1,'', fontsize=9, color='b') init() ani = Animator(fig, animate) plt.show()