Ejemplo n.º 1
0
def error_shading(calibration, fn):
    """Plot the GP offset model for x and y, after removing the constant correction"""
    proj = proj_wrapper(pyproj.Proj("+proj=robin"))    
    plot_reference_grid(pyproj.Proj("+proj=robin"))    
    xs, ys, zs = [], [], []
    
    for ix, row in calibration.iterrows():
        tlon, tlat = row["target_lon"], row["target_lat"]
        lon, lat = row["touch_lon"], row["touch_lat"]
        # compute offset from constant corrected
        px,py = proj(lon, lat)
        lonc, latc = fn(lon, lat)        
        d = np.degrees(sphere.spherical_distance((tlon, tlat), (lonc, latc)))
        xs.append(px)        
        ys.append(py)
        zs.append(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')
    #xr, yr = np.meshgrid(xi,yi)
    #iv = scipy.interpolate.interp2d(xs,ys,zs,kind='cubic')
    #zi = iv(xi, yi)
    #zi = scipy.interpolate.griddata((np.array(xs).flatten(),np.array(ys).flatten()),np.array(zs).flatten(),(xr,yr), method='cubic')
    levels = np.linspace(np.min(zi), np.max(zi), 30)
    plt.contourf(xi, yi, zi, cmap="bone", levels=levels, vmin=0, vmax=9)
    plt.colorbar()
Ejemplo n.º 2
0
 def valid(a, b, name):
     d = sphere.spherical_distance(a,b)
     if d<1e-6:
         print "Testing %s: OK, error is within %.4e" % (name, d)
         return True
     else:
         print "Testing %s: FAIL! error exceeds 1e-6 at %.4e" % (name, d)
         return False
Ejemplo n.º 3
0
def process_calibration(calibration_name=None, fit=None):            
    
    if calibration_name is None:
        print "WARNING: No calibration file specified."
        latest_csv = latest_file("calibration", ".csv")
        print "Using latest calibration file found: %s" % latest_csv
        calibration_name = latest_csv
    
    print "Processing calibration %s" % calibration_name
    print
    # load the calibration data
    calibration = pd.io.parsers.read_table(os.path.join("calibration", calibration_name), delimiter=",", skipinitialspace=True)
    augment_calibration(calibration)
    
    calibration["distance"] = [sphere.spherical_distance((r["target_lon"], r["target_lat"]),
                                                     (r["touch_lon"], r["touch_lat"])) for ix, r in calibration.iterrows()]
    total_targets = len(calibration)
    print "Read %d calibration targets" % total_targets
    calibration = calibration[calibration["distance"]<np.radians(22)]
    print "%d targets excluded as being outliers with >25 degree offset\n%d calibration targets remain" % (total_targets-len(calibration), len(calibration))

    grouped = calibration.groupby(["target_x", "target_y"])
    print "%d unique targets identified; %d repeats per target" % (len(grouped), int(0.5+total_targets/float(len(grouped))))
    print
    true_rms = estimate_touch_error(calibration, grouped)
    
    if fit is None:
        correction_factor, cubic_coeff, quadratic_coeff, gp_x, gp_y = fit_models(calibration)       
    else:
        correction_factor, cubic_coeff, quadratic_coeff, gp_x, gp_y = fit
        
            
    errors = {}    
    errors["none"] =  error_distribution(calibration, lambda x,y:polar_adjust(x,y,s=1))
    errors["constant"] = error_distribution(calibration, lambda x,y:polar_adjust(x,y,s=correction_factor))
    errors["quadratic"] = error_distribution(calibration, lambda x,y:quadratic_polar_adjust(x,y,quadratic_coeff))
    errors["cubic"] = error_distribution(calibration, lambda x,y:cubic_polar_adjust(x,y,cubic_coeff))
    errors["gp"] = error_distribution(calibration, lambda x,y:gp_adjust(x,y,gp_x,gp_y))
    
    
    report_errors(errors)
        
    #plot_calibration_state(calibration, (correction_factor, cubic_coeff, quadratic_coeff, gp_x, gp_y))                
    #plot_error_distribution(calibration, ["Constant", "Quadratic", "Cubic", "GP"], [constant, quadratic, cubic, gp])        
    #plot_offset_shading(calibration, gp_x, gp_y, correction_factor)
    
    # only write the calibration if we fitted new models
    if fit is None: 
        generate_module(calibration_name, calibration, errors, (correction_factor, cubic_coeff, quadratic_coeff, gp_x, gp_y))
   
    #generate_offset_map("gp", lambda x,y:gp_adjust(x,y,gp_x,gp_y))
    #generate_offset_map_gp(gp_x, gp_y)
    mode_times = time_module(calibration)
    for mode in mode_times:
        print "%s took %d ms" %(mode, 1000*mode_times[mode])
    
        
    return (correction_factor, cubic_coeff, quadratic_coeff, gp_x, gp_y), calibration
Ejemplo n.º 4
0
def spherical_mse(fn):  
    """Return the mse error using the given correction"""
    distances = []
    for ix,row in calibration.iterrows():        
        corr_touch_lon, corr_touch_lat = fn(row["touch_lon"], row["touch_lat"])                
        distances.append(sphere.spherical_distance((row["target_lon"],row["target_lat"]), (corr_touch_lon, corr_touch_lat)))
        
    #return np.median(distances)
    return np.sqrt(np.mean(np.array(distances)**2))  
Ejemplo n.º 5
0
def error_distribution(calibration, fn):
    """Return the error distribution after applying fn"""
    ds = []
    for ix, row in calibration.iterrows():
        lon, lat = row["target_lon"], row["target_lat"]
        tlon, tlat = row["touch_lon"], row["touch_lat"]
        # compute offset from constant corrected
        lonc, latc = fn(tlon, tlat)
        d = sphere.spherical_distance((lon, lat), (lonc, latc))
        ds.append(np.degrees(d))        
    return ds    
Ejemplo n.º 6
0
def spherical_mean_rms(lonlats):
    """Compute spherical mean, rms error and geodesic distances, using Robinson projection method"""
    proj = pyproj.Proj("+proj=robin")
    pts = []
    for lon, lat in lonlats:
        pts.append(proj(lon, lat))
    pts = np.array(pts)
    proj_mean = np.mean(pts, axis=0)    
    lon_mean, lat_mean = proj(proj_mean[0], proj_mean[1], inverse=True)        
    distances = []
    for lon, lat in lonlats:
        distances.append(sphere.spherical_distance((lon_mean, lat_mean), (lon, lat)))
    rms = np.sqrt(np.mean(np.array(distances)**2))    
    return (lon_mean, lat_mean), rms, distances
Ejemplo n.º 7
0
def process_calibration(calibration_name=None, fit=None):        
    global calibration
    
    if calibration_name is None:
        print "WARNING: No calibration file specified."
        latest_csv = latest_file("calibration", ".csv")
        print "Using latest calibration file found: %s" % latest_csv
        calibration_name = latest_csv
    
    print "Processing calibration %s" % calibration_name
    print
    # load the calibration data
    calibration = pd.io.parsers.read_table(os.path.join("calibration", calibration_name), delimiter=",", skipinitialspace=True)
    augment_calibration(calibration)
    
    calibration["distance"] = [sphere.spherical_distance((r["target_lon"], r["target_lat"]),
                                                     (r["touch_lon"], r["touch_lat"])) for ix, r in calibration.iterrows()]
    total_targets = len(calibration)
    print "Read %d calibration targets" % total_targets
    calibration = calibration[calibration["distance"]<np.radians(25)]
    print "%d targets excluded as being outliers with >25 degree offset\n%d calibration targets remain" % (total_targets-len(calibration), len(calibration))

    grouped = calibration.groupby(["target_x", "target_y"])
    print "%d unique targets identified; %d repeats per target" % (len(grouped), int(0.5+total_targets/float(len(grouped))))
    print
    true_rms = estimate_touch_error(calibration, grouped)
    
    if fit is None:
        correction_factor, cubic_coeff, quadratic_coeff, gp_x, gp_y = fit_models()
    else:
        correction_factor, cubic_coeff, quadratic_coeff, gp_x, gp_y = fit
    
    uncorrected_rmse =  np.degrees(correction_error(1))
    constant_rmse = np.degrees((correction_error(correction_factor)))
    quadratic_rmse = np.degrees(quadratic_error(quadratic_coeff))
    cubic_rmse = np.degrees(cubic_error(cubic_coeff))
    gp_rmse = np.degrees(gp_error(gp_x, gp_y))    
    
    print "RMS Uncorrected error: %.2f degrees" % uncorrected_rmse
    print "RMS Corrected error: %.2f degrees" %  constant_rmse
    print "RMS Quadratic corrected error: %.2f degrees" %  quadratic_rmse
    print "RMS Cubic corrected error: %.2f degrees" % cubic_rmse
    print "RMS GP corrected error: %.2f degrees" % gp_rmse
    
    print
    plot_correction_models(calibration, correction_factor, cubic_coeff, quadratic_coeff, gp_x, gp_y)
    fname = "calibration_plot.pdf"
    print
    print "Writing calibration plot to %s" % fname
    try:
        plt.savefig(fname,bbox_inches='tight', pad_inches=0)
    except IOError:
        print "WARNING: Could not write to %s" % fname
    
    plt.figtext(0.04, 0.16, "Calibration data from %s" % calibration_name, fontdict={"size":5})
    plt.figtext(0.04, 0.13, "%d calibration targets; %d unique" % (len(calibration), len(grouped)), fontdict={"size":5})
    plt.figtext(0.04, 0.1, "%.2f degrees intra-target error" % np.degrees(true_rms), fontdict={"size":5})
    error_labels(calibration, uncorrected_rmse, constant_rmse, quadratic_rmse, cubic_rmse, gp_rmse)    
    fname = "calibration_state.pdf"
    print
    print "Writing calibration plot to %s" % fname
    try:
        plt.savefig(fname)
    except IOError:
        print "WARNING: Could not write to %s" % fname
        
    plt.figure(figsize=(6,9))
    errors = [
    #error_distribution(calibration, lambda x,y: polar_adjust(x,y,1)),
    error_distribution(calibration, lambda x,y:polar_adjust(x,y,s=correction_factor)),
    error_distribution(calibration, lambda x,y:quadratic_polar_adjust(x,y,quadratic_coeff)),
    error_distribution(calibration, lambda x,y:cubic_polar_adjust(x,y,cubic_coeff)),
    error_distribution(calibration, lambda x,y:gp_adjust(x,y,gp_x,gp_y))]        
    plt.xlabel("Correction method")
    plt.ylabel("Error (degrees)")
    plt.gca().set_frame_on(False)
    simpleaxis(plt.gca())    
    seaborn.boxplot(errors)
    plt.xticks([0,1,2,3,4], ["","Constant", "Quadratic", "Cubic", "GP"])
    
    
    fname = "calibration_dist.pdf"    
    print "Writing calibration boxplot to %s" % fname
    try:
        plt.savefig(fname,bbox_inches='tight', pad_inches=0)
    except IOError:
        print "WARNING: Could not write to %s" % fname
    
        
    gp_offset_shading(calibration, gp_x, gp_y, correction_factor)
    fname = "gp_offset.pdf"
    plt.savefig("gp_offset.svg",bbox_inches='tight', pad_inches=0)
    print "Writing GP offset plot to %s" % fname
    try:
        plt.savefig(fname,bbox_inches='tight', pad_inches=0)
    except IOError:
        print "WARNING: Could not write to %s" % fname

    cal = calibration        
    # only write the calibration if we fitted new models
    if fit is None:    
        print
        print "Generating calibration.py"    
        write_module("calibration.py", calibration_name, calibration, correction_factor, cubic_coeff, quadratic_coeff, gp_x, gp_y)    
        print
        print "Testing calibration.py..."

        import calibration as cal
        def test_calibration(test_x, test_y):
            def valid(a, b, name):
                d = sphere.spherical_distance(a,b)
                if d<1e-6:
                    print "Testing %s: OK, error is within %.4e" % (name, d)
                    return True
                else:
                    print "Testing %s: FAIL! error exceeds 1e-6 at %.4e" % (name, d)
                    return False
                
            lat, lon = sphere.tuio_to_polar(test_x, test_y)  
            lon += np.pi
            assert(valid(cal.test_calibrated_touch(test_x, test_y, 'gp'),gp_adjust(lon, lat, gp_x, gp_y), 'GP'))        
            assert(valid(cal.test_calibrated_touch(test_x, test_y, 'cubic'),cubic_polar_adjust(lon, lat, cubic_coeff), 'cubic'))        
            assert(valid(cal.test_calibrated_touch(test_x, test_y, 'quadratic'),quadratic_polar_adjust(lon, lat, quadratic_coeff),'quadratic'))        
            assert(valid(cal.test_calibrated_touch(test_x, test_y, 'constant'),polar_adjust(lon, lat, correction_factor), 'constant'))        
            assert(valid(cal.test_calibrated_touch(test_x, test_y, 'none'),polar_adjust(lon, lat, 1), 'none'))
        test_calibration(0.5, 0.5)
        print "calibration.py seems to be working"
        
        
    import calibration as cal
    tuio_time = timeit.timeit("lon, lat = sphere.polar_to_tuio(0.5, 0.5)", setup="import sphere", number=1000)
    for mode in ["none", "constant", "quadratic", "cubic", "gp"]:
        ds = []
        
        tx,ty=0.5,0.5
        mode_time = timeit.timeit("lon, lat = calibration.test_calibrated_touch(0.5, 0.5, mode='%s')"%mode, setup="import calibration", number=1000)
        print "%s took %d ms, %d ms more thant TUIO time" %(mode, 1000*mode_time, 1000*(mode_time-tuio_time))
        
        for ix, row in calibration.iterrows():
            tx, ty = row["tuio_x"], row["tuio_y"]                               
            lon, lat = cal.test_calibrated_touch(tx, ty, mode=mode)
            d = np.degrees(sphere.spherical_distance((lon, lat), (row["target_lon"], row["target_lat"])))
            ds.append(d)
        print "calibration.py median error for mode %s is %.2f degrees" % (mode, np.median(ds))
        
        
    return (correction_factor, cubic_coeff, quadratic_coeff, gp_x, gp_y)