Skip to main content
Mathematics LibreTexts

Chapter 1

  • 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()

    Chapter 1 is shared under a not declared license and was authored, remixed, and/or curated by LibreTexts.

    • Was this article helpful?