def gp_adjust(lon, lat, gp_x, gp_y):
    x,y,z = sphere.spherical_to_cartesian((lon, lat))
    az_x, az_y = sphere.polar_to_az(lon, lat)
    xc = gp_x.predict([x,y,z])
    yc = gp_y.predict([x,y,z])
    corr_touch_lon, corr_touch_lat = sphere.az_to_polar(az_x+xc, az_y+yc)
    return corr_touch_lon, corr_touch_lat
def augment_calibration(calibration):
    xs, ys = calibration["tuio_x"], calibration["tuio_y"]
    lonlat = np.array([sphere.tuio_to_polar(x,y) for x,y in zip(xs,ys)])
    calibration["touch_lon"],calibration["touch_lat"] = lonlat[:,0], lonlat[:,1]

    lons,lats = calibration["target_lon"], calibration["target_lat"]
    xys = np.array([sphere.polar_to_tuio(lon,lat) for lon,lat in zip(lons,lats)])
    calibration["target_x"],calibration["target_y"] = xys[:,0], xys[:,1]

    # remove extreme targets which could not be hit (distance > 1 radian)

    calibration["target_lon"] = calibration["target_lon"] % (2*np.pi) - np.pi
    calibration["touch_lon"] = calibration["touch_lon"] % (2*np.pi) - np.pi
    
    # calculate co-ordinates in azimuthal space

    lons, lats = calibration["touch_lon"], calibration["touch_lat"]
    xy = np.array([sphere.polar_to_az(lon,lat) for lon,lat in zip(lons,lats)])
    calibration["touch_az_x"],calibration["touch_az_y"] = xy[:,0], xy[:,1]

    lons, lats = calibration["target_lon"], calibration["target_lat"]
    xy = np.array([sphere.polar_to_az(lon,lat) for lon,lat in zip(lons,lats)])
    calibration["target_az_x"],calibration["target_az_y"] = xy[:,0], xy[:,1]
def gp_offset_shading(calibration, gp_x, gp_y, best_s):
    """Plot the GP offset model for x and y, after removing the constant correction"""
    proj = proj_wrapper(pyproj.Proj("+proj=robin"))
    plt.figure(figsize=(9,4))
    plot_reference_grid(pyproj.Proj("+proj=robin"), labels=False)    
    xs, ys, zs = [], [], []
    us, vs = [], []
    test_pts = spiral_layout(2000)
    for lon, lat in test_pts:
        
        # gp corrected lon, lat
        az_x,az_y = sphere.polar_to_az(lon, lat)
        tinput = [az_x, az_y]
        xc = gp_x.predict(tinput)
        yc = gp_y.predict(tinput)
        lonc, latc = sphere.az_to_polar(az_x+xc, az_y+yc)
        # constant corrected lon, lat
        lons, lats = polar_adjust(lon, lat, best_s)
        
        # compute offset from constant corrected
        px,py = proj(lon, lat)
        px_c,py_c = proj(lonc, latc)
        px_s,py_s = proj(lons, lats)
        d = (px_s-px_c)**2 + (py_s-py_c)**2
        xs.append(px)        
        ys.append(py)
        
        if np.sqrt(d)<6e7:            
            us.append(px_s-px_c)
            vs.append(py_s-py_c)
        else:
            us.append(0)
            vs.append(0)
        zs.append(np.sqrt(d))
    
    
    xi = np.linspace(np.min(xs), np.max(xs), 500)
    yi = np.linspace(np.min(ys), np.max(ys), 500)
    #zi = matplotlib.mlab.griddata(xs, ys, zs, xi, yi, interp='linear')
    
    
    #levels = np.linspace(np.min(zi), np.max(zi), 30)
    #plt.contourf(xi, yi, zi, cmap="bone", levels=levels)
    plt.quiver(xs,ys,us,vs,scale=3e7,width=5e-4)
def gp_adjust(lon, lat, gp_x, gp_y):
    """Given a lon,lat input position, convert to azimuthal, predict offset
    using the given GP, and convert to lon, lat as the return value"""
    x,y = sphere.polar_to_az(lon, lat)
    return gp_predict(gp_x, gp_y, x, y)