In [47]:
%pylab inline

import csv
import pandas as pd

from scipy.interpolate import SmoothBivariateSpline
from scipy.optimize import minimize
from mpl_toolkits.mplot3d import Axes3D

from threshold_functions import *


Populating the interactive namespace from numpy and matplotlib
WARNING: pylab import has clobbered these variables: ['f']
`%matplotlib` prevents importing * from pylab and numpy

In [48]:
pylab.rcParams['savefig.dpi'] = 130

In [49]:
# Define thresholds
giveThreshold = 0.25
gapThreshold = 130

In [50]:
with open('cutout_factors','r') as f:
    
    loaded_factor = eval(f.read())
    
dictArray = array(list(loaded_factor.items()),float)
cutoutRef = dictArray[:,0].astype(int)
ref = argsort(cutoutRef)

factor = dictArray[:,1]

cutoutRef = cutoutRef[ref]
factor = factor[ref]


with open('circle_cutout_factors','r') as f:
    
    loaded_circle_factor = eval(f.read())
    
circleDictArray = array(list(loaded_circle_factor.items()),float)
circleDiameter = circleDictArray[:,0]
circleFactor = circleDictArray[:,1]

factor = append(factor,circleFactor)


with open('custom_cutout_factors','r') as f:
    
    loaded_custom_factor = eval(f.read())

customDimensionsDict = {'5x13':[5,13],
                   '5x10':[5,10],
                   '5x8':[5,8],
                   '4x13':[4,13],
                   '4x10':[4,10],
                   '4x8':[4,8],
                   '4x6.5':[4,6.5],
                   '3x13':[3,13],
                   '3x9':[3,9],
                   '3x6.5':[3,6.5],
                   '3x5':[3,5]}

customDataLabelList = list(customDimensionsDict.keys())

custom_factors = [loaded_custom_factor[x] for x in customDataLabelList]
custom_widths = [customDimensionsDict[x][0] for x in customDataLabelList]
custom_lengths = [customDimensionsDict[x][1] for x in customDataLabelList]


factor = append(factor,custom_factors)

In [51]:
# loaded_factor.items()

In [52]:
cutoutRef


Out[52]:
array([  3,   6,  14,  16,  18,  19,  20,  22,  32,  33,  34,  38,  41,
        43,  57,  58,  70,  73,  82,  83, 104, 106, 109, 112])

In [52]:


In [53]:
cutout_dimensions = pd.DataFrame.from_csv('new_cutoutdata.csv',index_col =None)

ref = argsort(cutout_dimensions['cutoutRef'].values.astype(int))

width = cutout_dimensions['new_width'].values[ref]
length = cutout_dimensions['new_length'].values[ref]

weight = concatenate((ones(shape(width)), 1*ones(shape(circleDiameter)), ones(shape(custom_widths))))


width = append(width,circleDiameter)
length = append(length,circleDiameter)

nanFill = empty(shape(circleDiameter))
nanFill.fill(nan)

cutoutRef = append(cutoutRef,nanFill)


width = append(width,custom_widths)
length = append(length,custom_lengths)

nanFill = empty(shape(custom_widths))
nanFill.fill(nan)

cutoutRef = append(cutoutRef,nanFill)



# editRef = cutoutRef == 14
# width[editRef] = 4.3
# length[editRef] = 4.6

ratio = width / length

In [54]:
circleDiameter


Out[54]:
array([ 9.,  8.,  6.,  4.,  7.,  3.,  5.])

In [55]:
scatter(circleDiameter,circleFactor)


Out[55]:
<matplotlib.collections.PathCollection at 0xbc619b0>

In [56]:
scatter(width,ratio)
title('Data so far')
xlabel('Width (cm)')
ylabel('Ratio')


Out[56]:
<matplotlib.text.Text at 0xcc3a4e0>

In [57]:
# Spline fitting

widthMirrored = np.append(width,width)
ratioLogMirrored = np.log2(np.append(width/length,length/width))
factorMirrored = np.append(factor,factor)
weightMirrored = append(weight,weight)

splineFit = SmoothBivariateSpline(widthMirrored,ratioLogMirrored,factorMirrored,w=weightMirrored,s=len(width))

In [58]:
# Create surface mesh
xVec2 = linspace(width.min(),width.max(),100)
yVec2 = linspace(ratio.min(),ratio.max(),100)
xMesh2, yMesh2 = meshgrid(xVec2, yVec2)

gapMesh2 = angle_gap(xMesh2,log2(yMesh2),widthMirrored,ratioLogMirrored,1,2)
giveMesh2 = fit_give(xMesh2,log2(yMesh2),widthMirrored,ratioLogMirrored,factorMirrored,s=len(width))

zMesh2 = splineFit.ev(xMesh2, log2(yMesh2))

ref2 = (gapMesh2>gapThreshold) | (giveMesh2>giveThreshold)
zMesh2[ref2] = nan

In [59]:
# Plot the fit
fig = plt.figure()

ax = fig.add_subplot(111, projection='3d')

bot = np.amin(factor) - 0.04 * np.ptp(factor)
top = np.amax(factor) + 0.04 * np.ptp(factor)

ax.contour(xMesh2,yMesh2,gapMesh2, offset=bot, levels=[gapThreshold], colors='r',alpha=0.3)
ax.contour(xMesh2,yMesh2,giveMesh2, offset=bot, levels=[giveThreshold], colors='g',alpha=0.3)

proxyGap, = ax.plot([width.min(),width.min()],[ratio.min(),ratio.min()],[bot,bot],'r-',alpha=0.3)
proxyGive, = ax.plot([width.min(),width.min()],[ratio.min(),ratio.min()],[bot,bot],'g-',alpha=0.3)

ax.plot_surface(xMesh2,yMesh2,zMesh2,alpha=0.3,rstride=4,cstride=4)
sc = ax.scatter(width,ratio,factor)

ax.set_title('Fit displayed against width and aspect ratio')
ax.set_xlabel('Width')
ax.set_ylabel('Ratio')
ax.set_zlabel('Factor')
legend([proxyGap,proxyGive],['Gap threshold', 'Give threshold'],loc=7,prop={'size':8})

right = ratio.min()-0.01*ratio.ptp()
ax.set_ylim(right,1)
ax.set_zlim(bot,top)
ax.view_init(elev=10, azim=-80)



In [60]:
# Remove data and predict
predictedFactor = zeros(shape(width))
predictionAngleGap = zeros(shape(width))
predictionFitGive = zeros(shape(width))

for i in range(len(width)):
    
    x = width[i]
    y = log2(width[i]/length[i])

    adjWidth = np.delete(width,i)
    adjLength = np.delete(length,i)
    adjFactor = np.delete(factor,i)
    adjWeight = delete(weight,i)
    
    adjWidthMirrored = np.append(adjWidth,adjWidth)
    adjRatioLogMirrored = np.log2(np.append(adjWidth/adjLength,adjLength/adjWidth))
    adjFactorMirrored = np.append(adjFactor,adjFactor)
    adjWeightMirrored = append(adjWeight,adjWeight)
    
    adjSplineFit = SmoothBivariateSpline(adjWidthMirrored,adjRatioLogMirrored,adjFactorMirrored,w=adjWeightMirrored,s=len(width))
    
    predictedFactor[i] = adjSplineFit.ev(x,y)
    predictionAngleGap[i] = angle_gap(x,y,adjWidthMirrored,adjRatioLogMirrored,1,2)
    predictionFitGive[i] = fit_give(x,y,adjWidthMirrored,adjRatioLogMirrored,adjFactorMirrored,s=len(width))
    
difference = factor - predictedFactor
withinThresholds = ((predictionAngleGap<gapThreshold) & 
                    (predictionFitGive<giveThreshold)
                    )

In [61]:
# Display table
df = pd.DataFrame(transpose([cutoutRef,width, length, factor, predictedFactor, difference,
                             predictionAngleGap, predictionFitGive, withinThresholds]))
df.columns = ['Reference','width', 'length', 'factor', 'Predicted Factor', 'Difference',
              'Angle Gap', 'Fit Give', 'Within thresholds']

df.to_csv(path_or_buf = "cutoutdata.csv", index=False)

df


Out[61]:
Reference width length factor Predicted Factor Difference Angle Gap Fit Give Within thresholds
0 3 4.498726 6.077114 1.032704 1.032554 0.000150 40.977521 0.090650 1
1 6 6.996235 10.669437 1.001302 0.994946 0.006356 149.034331 0.238766 0
2 14 4.388701 5.288022 1.043027 1.035050 0.007976 30.216700 0.074103 1
3 16 6.107799 10.515871 0.999567 1.001926 -0.002359 147.146965 0.220360 0
4 18 7.602645 10.075798 0.998054 0.993712 0.004343 112.153248 0.252614 0
5 19 5.799849 10.375006 1.001089 1.005132 -0.004043 141.954852 0.171163 0
6 20 4.289047 5.112375 1.037967 1.038136 -0.000170 32.157230 0.072502 1
7 22 5.178076 10.260920 1.011713 1.011741 -0.000029 125.980282 0.140112 1
8 32 7.715225 11.165712 0.993330 0.995087 -0.001756 186.072993 0.586979 0
9 33 5.905678 6.209543 1.006789 1.010366 -0.003577 17.749270 0.051678 1
10 34 7.044718 9.674088 0.993330 0.997099 -0.003768 78.690071 0.106505 1
11 38 4.677451 5.724189 1.027190 1.030113 -0.002923 25.600690 0.073041 1
12 41 6.919052 10.011766 0.994829 0.997401 -0.002572 70.197302 0.108176 1
13 43 6.100202 7.735733 1.007783 1.006309 0.001474 49.539330 0.077249 1
14 57 3.574667 4.618824 1.059704 1.053915 0.005789 122.389861 0.081924 1
15 58 5.880419 7.454923 1.008999 1.009282 -0.000283 43.463477 0.069509 1
16 70 7.461006 8.363232 0.997190 0.994697 0.002493 93.216439 0.155305 1
17 73 7.294143 9.137754 0.995472 0.995826 -0.000353 65.141182 0.167701 1
18 82 6.268781 7.974677 1.000867 1.004645 -0.003778 51.842216 0.084731 1
19 83 5.782263 7.931109 1.010552 1.009668 0.000883 44.035344 0.074592 1
20 104 5.658933 8.328343 1.006601 1.010681 -0.004080 31.299034 0.077555 1
21 106 6.087204 9.708158 1.000871 1.003567 -0.002696 97.630809 0.111782 1
22 109 6.306754 7.827168 1.006979 1.003923 0.003056 47.726711 0.084134 1
23 112 3.538729 4.149551 1.053904 1.056279 -0.002375 119.885508 0.072446 1
24 NaN 9.000000 9.000000 0.991661 0.994870 -0.003209 271.094662 0.753144 0
25 NaN 8.000000 8.000000 0.993360 0.992770 0.000590 100.662521 0.135843 1
26 NaN 6.000000 6.000000 1.014436 1.008201 0.006234 17.739797 0.052334 1
27 NaN 4.000000 4.000000 1.045826 1.045048 0.000778 54.703154 0.056992 1
28 NaN 7.000000 7.000000 0.996776 0.998603 -0.001827 45.376312 0.096162 1
29 NaN 3.000000 3.000000 1.075771 1.068043 0.007729 180.000000 0.214056 0
30 NaN 5.000000 5.000000 1.030396 1.023750 0.006646 24.031169 0.056497 1
31 NaN 5.000000 13.000000 1.013374 1.000441 0.012933 175.177391 0.718879 0
32 NaN 4.000000 13.000000 1.024896 1.020767 0.004129 172.049667 0.796183 0
33 NaN 4.000000 6.500000 1.040668 1.041506 -0.000838 69.195263 0.134589 1
34 NaN 5.000000 8.000000 1.017153 1.020235 -0.003082 48.785028 0.090337 1
35 NaN 3.000000 6.500000 1.054423 1.065733 -0.011310 180.000000 0.315148 0
36 NaN 3.000000 5.000000 1.069714 1.066945 0.002769 180.000000 0.265881 0
37 NaN 4.000000 8.000000 1.030055 1.038438 -0.008384 54.858700 0.169045 1
38 NaN 3.000000 9.000000 1.053516 1.057226 -0.003710 180.000000 0.299196 0
39 NaN 4.000000 10.000000 1.029933 1.032573 -0.002640 80.882662 0.234719 1
40 NaN 5.000000 10.000000 1.012277 1.015187 -0.002910 101.984536 0.130035 1
41 NaN 3.000000 13.000000 1.049271 1.046220 0.003050 319.815249 0.887039 0

In [62]:
print("There are", sum(withinThresholds), "points within give and gap thresholds."+
      "\nThe standard deviation of the prediction differences for these is", std(difference[withinThresholds]))


There are 29 points within give and gap thresholds.
The standard deviation of the prediction differences for these is 0.003627214747

In [63]:
# Histogram
fig = plt.figure()
ax = fig.add_subplot(111)

n, bins, patches = hist(difference[withinThresholds])

setp(patches, 'facecolor', 'g', 'alpha', 0.5)
ax.set_xlabel('Prediction differences')
ax.set_ylabel('Frequency')
ax.set_title('Histogram of prediction differences')


Out[63]:
<matplotlib.text.Text at 0x98cb9e8>

In [64]:
# Visual representation of differences
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

ax.plot_surface(xMesh2,yMesh2,zMesh2,alpha=0.3,rstride=4,cstride=4)

diffColour = copy(difference)
diffColour[~withinThresholds] = nan

colourRange = nanmax(abs(diffColour))

sc = ax.scatter(width,ratio,factor,c=diffColour, vmin=-colourRange, vmax=colourRange)
colorbar(sc)

ax.set_title('Differences')
ax.set_xlabel('Width')
ax.set_ylabel('Ratio')
ax.set_zlabel('Factor')

ax.set_ylim(right,1)
ax.set_zlim(bot,top)

ax.view_init(elev=10, azim=-80)



In [65]:
diffTest = abs(difference)
diffTest[~withinThresholds] = 0

testRef = argmax(diffTest)
cutoutRef[testRef]


Out[65]:
nan

In [66]:
factor[testRef]


Out[66]:
1.0300546759398521

In [67]:
scatter(width,ratio)
scatter(width[testRef],ratio[testRef],c='red')


Out[67]:
<matplotlib.collections.PathCollection at 0xbca6c50>

In [68]:
def to_minimise(cut_increase,ref):
    
    test_width = width[ref] + cut_increase
    test_length = length[ref] + cut_increase
    test_ratio = test_width / test_length
    
    return (factor[ref] - splineFit.ev(test_width,log2(test_ratio)))**2

In [69]:
output = minimize(to_minimise,0,args=(testRef,))
output


Out[69]:
  message: 'Optimization terminated successfully.'
      fun: 9.053234613510035e-10
     njev: 16
        x: array([ 0.34389289])
 hess_inv: array([[ 1046.93369908]])
  success: True
   status: 0
     nfev: 48
      jac: array([ -1.26175225e-06])

In [69]: