multinterp

A Unified Interface for Multivariate Interpolation in the Scientific Python Ecosystem

from manim import *
%%manim -qm LinearInterpolationUniform

class LinearInterpolationUniform(Scene):
    def construct(self):
        axes = Axes(
            x_range=[.5,10],
            y_range=[-2.5, 0.5],
            axis_config={"color": BLUE},
        )

        # Define the function and create its graph
        func = lambda x: x**(1-2)/(1-2)
        graph = axes.plot(func, color=WHITE)
        graph_label = axes.get_graph_label(graph, label='u(c)=-c^{-1}')
        graph_label.to_corner(DR)

        # Create points for the uniform grid and linear interpolation lines
        x_vals = np.linspace(.5, 10, 10)
        y_vals = [func(x) for x in x_vals]
        points = [axes.coords_to_point(x, func(x)) for x in x_vals]
        interp_lines = [
            Line(points[i], points[i+1], color=ORANGE)
            for i in range(len(points) - 1)
        ]

        # Create dots at the grid points
        dots = VGroup(*[Dot(point, color=RED) for point in points])

        # Display everything
        self.play(Create(axes), Create(graph))
        self.play(Write(graph_label, run_time=1))
        self.wait(1)
        self.play(LaggedStart(*[Create(dot) for dot in dots], lag_ratio=0.2))
        self.wait(1)
        self.play(LaggedStart(*[Create(line) for line in interp_lines], lag_ratio=0.2))
        self.wait(2)
Loading...
%%manim -qm LinearInterpolationGeometric

class LinearInterpolationGeometric(Scene):
    def construct(self):
        axes = Axes(
            x_range=[.5, 10],
            y_range=[-2.5, 0.5],
            axis_config={"color": BLUE},
        )

        # Define the function and create its graph
        func = lambda x: x**(1-2)/(1-2)
        graph = axes.plot(func, color=WHITE)
        graph_label = axes.get_graph_label(graph, label='u(c)=-c^{-1}')
        graph_label.to_corner(DR)

        # Create points for the uniform grid and linear interpolation lines
        x_vals_uniform = np.linspace(.5, 10, 10)
        y_vals_uniform = [func(x) for x in x_vals_uniform]
        points_uniform = [axes.coords_to_point(x, func(x)) for x in x_vals_uniform]
        interp_lines_uniform = [
            Line(points_uniform[i], points_uniform[i+1], color=ORANGE)
            for i in range(len(points_uniform) - 1)
        ]

        # Create dots at the grid points for uniform grid
        dots_uniform = VGroup(*[Dot(point, color=RED) for point in points_uniform])

        # Create points for the log grid and linear interpolation lines
        x_vals_log = np.geomspace(.5, 10, 10)
        y_vals_log = [func(x) for x in x_vals_log]
        points_log = [axes.coords_to_point(x, func(x)) for x in x_vals_log]
        interp_lines_log = [
            Line(points_log[i], points_log[i+1], color=ORANGE)
            for i in range(len(points_log) - 1)
        ]

        # Create dots at the grid points for log grid
        dots_log = VGroup(*[Dot(point, color=GREEN) for point in points_log])

        # Display everything
        self.play(Create(axes), Create(graph))
        self.play(Write(graph_label, run_time=1))
        # self.wait(1)
        self.play(LaggedStart(*[Create(dot) for dot in dots_uniform], lag_ratio=0.1))
        # self.wait(1)
        self.play(LaggedStart(*[Create(line) for line in interp_lines_uniform], lag_ratio=0.1))
        self.wait(2)

        # Transition to log grid
        self.play(
            Transform(dots_uniform, dots_log),
            *[Transform(interp_lines_uniform[i], interp_lines_log[i]) for i in range(len(interp_lines_uniform))]
        )
        self.wait(2)
Loading...
%%manim -qm BilinearInterpolation


class BilinearInterpolation(Scene):
    def construct(self):
        # Create axes
        axes = Axes(
            x_range=[0, 12],
            y_range=[0, 12],
            axis_config={"color": BLUE},
        )
        self.play(Create(axes))
        
        # Create initial 2D meshgrid with np.linspace
        x_lin = np.linspace(1, 11, 10)
        y_lin = np.linspace(1, 11, 10)
        X_lin, Y_lin = np.meshgrid(x_lin, y_lin)
        
        lines_lin = VGroup()
        dots_lin = VGroup()
        for i in range(X_lin.shape[0]):
            for j in range(X_lin.shape[1]):
                dot = Dot(point=axes.c2p(X_lin[i, j], Y_lin[i, j]), radius=0.1)
                dots_lin.add(dot)
        
        for x in x_lin:
            line = Line(axes.c2p(x, 1), axes.c2p(x, 11))
            lines_lin.add(line)
        
        for y in y_lin:
            line = Line(axes.c2p(1, y), axes.c2p(11, y))
            lines_lin.add(line)

        # Display initial meshgrid
        self.play(LaggedStart(*[Create(dot) for dot in dots_lin], lag_ratio=0.01))
        self.play(LaggedStart(*[Create(line) for line in lines_lin], lag_ratio=0.05))
        self.wait(1)

        # Create transformed 2D meshgrid with np.geomspace
        x_geom = np.geomspace(1, 11, 10)
        y_geom = np.geomspace(1, 11, 10)
        X_geom, Y_geom = np.meshgrid(x_geom, y_geom)
        
        lines_geom = VGroup()
        dots_geom = VGroup()
        for i in range(X_geom.shape[0]):
            for j in range(X_geom.shape[1]):
                dot = Dot(point=axes.c2p(X_geom[i, j], Y_geom[i, j]), radius=0.1, color=ORANGE)
                dots_geom.add(dot)
        
        for x in x_geom:
            line = Line(axes.c2p(x, 1), axes.c2p(x, 11), color=GREEN)
            lines_geom.add(line)
        
        for y in y_geom:
            line = Line(axes.c2p(1, y), axes.c2p(11, y), color=GREEN)
            lines_geom.add(line)
            
        # Transform linspace meshgrid to geomspace meshgrid
        self.play(
            *[Transform(dots_lin[i], dots_geom[i]) for i in range(len(dots_lin))],
            *[Transform(lines_lin[i], lines_geom[i]) for i in range(len(lines_lin))]
        )
        self.wait(2)
Loading...
%%manim -qm CurvilinearInterpolation


class CurvilinearInterpolation(Scene):
    def construct(self):
        # Create axes with an extended range to accommodate the transformed points
        axes = Axes(
            x_range=[0, 20],
            y_range=[0, 20],
            axis_config={"color": BLUE},
        )
        self.play(Create(axes))

        # Create transformed 2D meshgrid with np.geomspace
        X_geom = np.zeros((10, 10))
        Y_geom = np.zeros((10, 10))

        for i in range(X_geom.shape[0]):
            X_geom[i, :] = np.geomspace(1, 11 + i, 10)

        for j in range(Y_geom.shape[1]):
            Y_geom[:, j] = np.geomspace(1 + .5 * j, 11 + j, 10)

        lines_geom = VGroup()
        dots_geom = VGroup()
        for i in range(X_geom.shape[0]):
            for j in range(X_geom.shape[1]):
                dot = Dot(point=axes.c2p(X_geom[i, j], Y_geom[i, j]), radius=0.1, color=ORANGE)
                dots_geom.add(dot)

        # Lines for the transformed grid
        for row in range(X_geom.shape[0]):
            for col in range(X_geom.shape[1] - 1):
                line = Line(axes.c2p(X_geom[row, col], Y_geom[row, col]), axes.c2p(X_geom[row, col + 1], Y_geom[row, col + 1]), color=GREEN)
                lines_geom.add(line)
        for col in range(X_geom.shape[1]):
            for row in range(X_geom.shape[0] - 1):
                line = Line(axes.c2p(X_geom[row, col], Y_geom[row, col]), axes.c2p(X_geom[row + 1, col], Y_geom[row + 1, col]), color=GREEN)
                lines_geom.add(line)
                

        self.play(LaggedStart(*[Create(dot) for dot in dots_geom], lag_ratio=0.05))
        self.wait(2)
        self.play(LaggedStart(*[Create(line) for line in lines_geom], lag_ratio=0.01))
        self.wait(1)

        # Create initial 2D meshgrid with np.linspace
        x_lin = np.linspace(1, 11, 10)
        y_lin = np.linspace(1, 11, 10)
        X_lin, Y_lin = np.meshgrid(x_lin, y_lin)

        lines_lin = VGroup()
        dots_lin = VGroup()
        for i in range(X_lin.shape[0]):
            for j in range(X_lin.shape[1]):
                dot = Dot(point=axes.c2p(X_lin[i, j], Y_lin[i, j]), radius=0.1)
                dots_lin.add(dot)

        # Lines for the initial grid
        for row in range(X_lin.shape[0]):
            for col in range(X_lin.shape[1] - 1):
                line = Line(axes.c2p(X_lin[row, col], Y_lin[row, col]), axes.c2p(X_lin[row, col + 1], Y_lin[row, col + 1]))
                lines_lin.add(line)
        for col in range(X_lin.shape[1]):
            for row in range(X_lin.shape[0] - 1):
                line = Line(axes.c2p(X_lin[row, col], Y_lin[row, col]), axes.c2p(X_lin[row + 1, col], Y_lin[row + 1, col]))
                lines_lin.add(line)

        self.play(
            *[Transform(dots_geom[i], dots_lin[i]) for i in range(len(dots_geom))],
            *[Transform(lines_geom[i], lines_lin[i]) for i in range(len(lines_geom))], 
            run_time = 5
        )
        self.wait(2)
Loading...
%%manim -qm UnstructuredGrid

from scipy.spatial import Delaunay


from scipy.stats import qmc  # Import the quasi-Monte Carlo module

class UnstructuredGrid(Scene):
    def construct(self):
        # Create axes
        axes = Axes(
            x_range=[-1, 10],
            y_range=[-1, 10],
            axis_config={"color": BLUE},
        )
        self.play(Create(axes))

        # Generate quasi-Monte Carlo points (Halton sequence)
        sampler = qmc.Halton(2, seed=1)  # 2 for 2D
        points = 9 * sampler.random(50)  # Scale to fit within the 9x9 grid
        x_coords = points[:, 0]
        y_coords = points[:, 1]
        
        dots = VGroup(*[Dot(axes.c2p(x, y), radius=0.1) for x, y in points])

        # Delaunay triangulation
        tri = Delaunay(points)
        lines = VGroup()
        for simplex in tri.simplices:
            for i in range(3):
                for j in range(i+1, 3):
                    start = points[simplex[i]]
                    end = points[simplex[j]]
                    line = Line(axes.c2p(start[0], start[1]), axes.c2p(end[0], end[1]), color=ORANGE)
                    lines.add(line)

        # Display everything
        self.play(LaggedStart(*[Create(dot) for dot in dots], lag_ratio=0.05))
        self.play(LaggedStart(*[Create(line) for line in lines], lag_ratio=0.05))
        self.wait(2)
Loading...