#!/usr/bin/env python3 # -*- python -*- # Copyright © 2014, 2015, 2016, 2017 Mattias Andrée (m@maandree.se) # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # Test of cubic interpolation. # Load matplotlib.pyplot, # it can take some time so # print information about it. print('Loading matplotlib.pyplot...') import matplotlib.pyplot as plot print('Done loading matplotlib.pyplot') # Modules used for input data generation from math import * from random import * def main(): # Create a page with graphs fig = plot.figure() # Add graphs add_graph(fig, 221, [i / 15 for i in range(16)]) add_graph(fig, 222, [sin(6 * i / 15) for i in range(16)]) add_graph(fig, 223, [(i / 15) ** 0.5 for i in range(16)]) #add_graph(fig, 224, [random() for i in range(16)]) add_graph(fig, 224, [(-1) ** (i // 2) for i in range(16)]) #add_graph(fig, 224, [i / 15 * (-1) ** (i // 2) for i in range(16)]) # Show graphs plot.show() def add_graph(fig, graph_pos, input_values): ''' Add a graph @param fig:Figure The page to which to add the graph @param graph_pos:int Where to place the graph @param input_values:list The input values for each point ''' # Interpolate data output_values = interpolate(input_values) # Number of input points n = len(input_values) # Number of output points m = len(output_values) # Create graph graph = fig.add_subplot(graph_pos) # Plot interpolated data graph.plot([i / (m - 1) for i in range(m)], output_values, 'b-') # Plot input data graph.plot([i / (n - 1) for i in range(n)], input_values, 'ro') def interpolate(small, tension = 0): ''' Interpolate data @param small:list The input values for each point @param tension:float A [0, 1] value of the interpolation tension @return :list The values for each point in a scaled up version ''' large = [None] * len(small) ** 2 small_, large_ = len(small) - 1, len(large) - 1 # Basis functions #h00 = lambda t : (1 + 2 * t) * (1 - t) ** 2 h10 = lambda t : t * (1 - t) ** 2 h01 = lambda t : t ** 2 * (3 - 2 * t) h11 = lambda t : t ** 2 * (t - 1) def tangent(values, index, last): ''' Calculate the tangent at a point @param values:list Mapping from points to values @param index:int The point @param last:int The last point @return :float The tangent at the point `index` ''' if last == 0: return 0 if index == 0: return values[1] - values[0] if index == last: return values[last] - values[last - 1] return (values[index + 1] - values[index - 1]) / 2 # Tension coefficent c_ = 1 - tension for i in range(len(large)): # Scaling j = i * small_ / large_ # Floor, weight, ceiling j, w, k = int(j), j % 1, min(int(j) + 1, small_) # Points pj, pk = small[j], small[k] # Tangents mj, mk = c_ * tangent(small, j, small_), c_ * tangent(small, k, small_) # Interpolation large[i] = pj + h10(w) * mj + h01(w) * (pk - pj) + h11(w) * mk return large # Plot interpolation main()