Exemplo n.º 1
0
	def residual(mod_basis,uch_basis,y,z,dz):
		edge = ogp_util.transform_pt(ball_basis,uch_basis,ogp_util.transform_pt(null_basis,mod_basis,axial_edge))
		#print edge
		nominal = [math.sin(0.0305)*(z+dz-700)-8.789, y, math.cos(0.0305)*(z+dz)]
		vec = ogp_util.transform_vec(ball_basis,uch_basis,ogp_util.transform_vec(null_basis,mod_basis,axial_vec))
		#print vec
		angle = math.atan2(vec[1],vec[0])
		if (abs(angle)>math.pi/2):
			angle = angle-math.copysign(math.pi,angle)
		#print edge-nominal
		#print angle
		return np.append(edge-nominal,angle*1000)
Exemplo n.º 2
0
	def residual(mod_basis,uch_basis,y,z,dz):
		edge = ogp_util.transform_pt(ball_basis,uch_basis,ogp_util.transform_pt(null_basis,mod_basis,axial_edge))
		#print edge
		#nominal = [math.sin(0.0305)*(z+dz-700), y, math.cos(0.0305)*(z+dz-700)+700]
		nominal = [math.sin(0.0305)*(z+dz-700)-8.789, y, math.cos(0.0305)*(z+dz)]
		vec = ogp_util.transform_vec(ball_basis,uch_basis,ogp_util.transform_vec(null_basis,mod_basis,axial_vec))
		#print vec
		angle = math.atan2(vec[1],vec[0])
		if (abs(angle)>math.pi/2):
			angle = angle-math.copysign(math.pi,angle)
		#print edge-nominal
		#print angle
		return np.append(edge-nominal,angle*1000)
Exemplo n.º 3
0
def axial_residuals(dict, layer, nom_height, ball_basis, global_basis):

    az = math.radians(dict[layer]['XY Angle'][1])
    el = math.radians(dict[layer]['Elevation'][1])
    vec = np.array([
        math.cos(az) * math.cos(el),
        math.sin(az) * math.cos(el),
        math.sin(el)
    ])
    pos = np.array([
        dict[layer]['X Location'][1], dict[layer]['Y Location'][1],
        dict[layer]['Z Location'][1]
    ])
    vec = ogp_util.transform_vec(ball_basis, global_basis, vec)
    pos = ogp_util.transform_pt(ball_basis, global_basis, pos)
    angle = math.atan2(vec[1], vec[0])
    #height = pos[1] - pos[0]*(vec[1]/vec[0])
    height = pos[1]
    if (abs(angle) > math.pi / 2):
        angle = angle - math.copysign(math.pi, angle)
    #print pos
    #print vec
    #print angle
    height_residual = height - nom_height
    print 'Y residual {0}, angle residual {1}'.format(height_residual, angle)
    return np.array([height_residual, angle])
Exemplo n.º 4
0
def axial_residuals(dict, layer, nom_height, ball_basis, global_basis):

	az = math.radians(dict[layer]['XY Angle'][1])
	el = math.radians(dict[layer]['Elevation'][1])
	vec = np.array([math.cos(az)*math.cos(el),
		math.sin(az)*math.cos(el),
		math.sin(el)])
	pos = np.array([dict[layer]['X Location'][1],
		dict[layer]['Y Location'][1],
		dict[layer]['Z Location'][1]])
	vec = ogp_util.transform_vec(ball_basis,global_basis,vec)
	pos = ogp_util.transform_pt(ball_basis,global_basis,pos)
	angle = math.atan2(vec[1],vec[0])
	#height = pos[1] - pos[0]*(vec[1]/vec[0])
	height = pos[1]
	if (abs(angle)>math.pi/2):
		angle = angle-math.copysign(math.pi,angle)
	#print pos
	#print vec
	#print angle
	height_residual = height-nom_height
	print 'Y residual {0}, angle residual {1}'.format(height_residual,angle)
	return np.array([height_residual,angle])
Exemplo n.º 5
0
print 'Eigenvectors of curvature matrix: \n{0}'.format(v)

edgeangle = math.radians(stepdict[far + ' upper edge']['XY Angle'][1])
edgeel = math.radians(stepdict[far + ' upper edge']['Elevation'][1])
edgevec = np.array([
    math.cos(edgeangle) * math.cos(edgeel),
    math.sin(edgeangle) * math.cos(edgeel),
    math.sin(edgeel)
])
edgepos = np.array([
    stepdict[far + ' upper edge']['X Location'][1],
    stepdict[far + ' upper edge']['Y Location'][1],
    stepdict[far + ' upper edge']['Z Location'][1]
])
edgevec = ogp_util.transform_vec(meas_basis, fixture_basis, edgevec)
edgepos = ogp_util.transform_pt(meas_basis, fixture_basis, edgepos)

topedge1 = edgepos[1] + (6.500 * 25.4 - edgepos[0]) * (edgevec[1] / edgevec[0])
topedge2 = edgepos[1] + (3.125 * 25.4 - edgepos[0]) * (edgevec[1] / edgevec[0])

if (side == 'front'):
    nominal1 = 2.337
    nominal2 = 2.337
else:
    nominal1 = 2.505
    nominal2 = 2.166

print far + ' edge 1: nominal {0:.4f}, actual {1:.4f} (deviation {2:.2f} um)'.format(
    nominal1 * 25.4, topedge1, 1000 * (topedge1 - nominal1 * 25.4))
print far + ' edge 2: nominal {0:.4f}, actual {1:.4f} (deviation {2:.2f} um)'.format(
    nominal2 * 25.4, topedge2, 1000 * (topedge2 - nominal2 * 25.4))
Exemplo n.º 6
0
	def residual(mod_basis,uch_basis,y,z,dz):
		edge = ogp_util.transform_pt(ball_basis,uch_basis,ogp_util.transform_pt(null_basis,mod_basis,axial_edge))
		#print edge
		#nominal = [math.sin(0.0305)*(z+dz-700), y, math.cos(0.0305)*(z+dz-700)+700]
		nominal = [math.sin(0.0305)*(z+dz-700)-8.789, y, math.cos(0.0305)*(z+dz)]
		vec = ogp_util.transform_vec(ball_basis,uch_basis,ogp_util.transform_vec(null_basis,mod_basis,axial_vec))
		#print vec
		angle = math.atan2(vec[1],vec[0])
		if (abs(angle)>math.pi/2):
			angle = angle-math.copysign(math.pi,angle)
		#print edge-nominal
		#print angle
		return np.append(edge-nominal,angle*1000)
	return np.concatenate((residual(l1_basis,global_basis,is_top*6.5,500,dz),
		residual(l2_basis,global_basis,is_top*9.5,700,dz),
		residual(l3_basis,global_basis,is_top*12.5,900,dz)))

sol = scipy.optimize.leastsq(f_min,p0,args=())[0]
print sol
print f_min(sol)

global_basis =ogp_util.make_parametrized_basis(sol[0],sol[1],sol[2],sol[3],sol[4],sol[5])
if (is_top==1):
	print 'top 4-6:'
else:
	print 'bottom 4-6:'
print ogp_util.transform_pt(ball_basis,global_basis,ball_basis[2])/25.4
print ogp_util.transform_pt(ball_basis,global_basis,ball_basis[3])/25.4
print ogp_util.transform_pt(ball_basis,global_basis,ball_basis[4])/25.4
print ogp_util.transform_pt(ball_basis,global_basis,ball_basis[5])/25.4
Exemplo n.º 7
0
def check_alignment(moduleend):
    sensorname = near + ' ' + moduleend
    points = np.empty([3, 11])
    points = ogp_util.get_points(stepdict, sensorname, 4, 7)

    #print points
    for i in range(0, 11):
        points[:, i] = ogp_util.transform_pt(meas_basis, fixture_basis,
                                             points[:, i])

    #print points

    [fiducials_nominal, p0] = ogp_util.l456_fiducials(moduleend, side)

    sol = scipy.optimize.leastsq(ogp_util.sensor_fitfunc,
                                 p0,
                                 args=(points, fiducials_nominal))[0]
    print 'Sensor fit parameters: ' + str(sol)
    print 'Sensor fit residuals (um): ' + str(
        1000.0 * ogp_util.sensor_fitfunc(sol, points, fiducials_nominal))

    sensor_origin = np.array(sol[0:3])
    sensor_rotation = ogp_util.make_rotation(sol[3], sol[4], sol[5])
    print 'Sensor origin: {0}'.format(sensor_origin)
    norm_vec = sensor_rotation.T.dot([0.0, 0.0, 1.0])
    print 'Normal vector: {0}'.format(norm_vec)
    meas_vec = sensor_rotation.T.dot([1.0, 0.0, 0.0])
    print 'Strip vector: {0}'.format(meas_vec)
    angle = math.atan2(meas_vec[1], meas_vec[0])
    print 'Strip angle: {0}'.format(angle)

    if (moduleend == 'block'):
        fixture_x1 = 5.875
        fixture_x2 = 2.500
        if (side == 'front'):
            nominal1 = 2.176
            nominal2 = 2.008
        else:
            nominal1 = 2.176
            nominal2 = 2.176
    else:
        fixture_x1 = 9.250
        fixture_x2 = 5.875
        if (side == 'front'):
            nominal1 = 2.346
            nominal2 = 2.176
        else:
            nominal1 = 2.176
            nominal2 = 2.176

    topedge1 = sensor_origin[1] + 20.17 / abs(math.cos(angle)) + (
        fixture_x1 * 25.4 - sensor_origin[0]) * math.tan(angle)
    topedge2 = sensor_origin[1] + 20.17 / abs(math.cos(angle)) + (
        fixture_x2 * 25.4 - sensor_origin[0]) * math.tan(angle)

    print near + ' ' + moduleend + ' edge 1: nominal {0:.4f}, actual {1:.4f} (deviation {2:.2f} um)'.format(
        nominal1 * 25.4, topedge1, 1000 * (topedge1 - nominal1 * 25.4))
    print near + ' ' + moduleend + ' edge 2: nominal {0:.4f}, actual {1:.4f} (deviation {2:.2f} um)'.format(
        nominal2 * 25.4, topedge2, 1000 * (topedge2 - nominal2 * 25.4))

    corner1 = sol[6] * (50.0)**2 + sol[7] * (20.17)**2 + sol[8] * 50.0 * 20.17
    corner2 = sol[6] * (50.0)**2 + sol[7] * (20.17)**2 - sol[8] * 50.0 * 20.17
    print 'Deviation from plane at corners (um): {0:.2f}, {1:.2f}'.format(
        corner1 * 1000, corner2 * 1000)

    hess = np.array([[2 * sol[6], sol[8]], [sol[8], 2 * sol[7]]])
    w, v = np.linalg.eigh(hess)
    print 'Eigenvalues of curvature matrix:'
    print w
    print 'Eigenvectors of curvature matrix:'
    print v

    if (moduleend == 'block'):
        if (side == 'front'):
            nominal1 = 2.176
            nominal2 = 2.176
            visible = 'upper'
            edgedistance = 0.0
        else:
            nominal1 = 2.176
            nominal2 = 2.008
            visible = 'lower'
            edgedistance = 40.34
    else:
        if (side == 'front'):
            nominal1 = 2.176
            nominal2 = 2.176
            visible = 'lower'
            edgedistance = 40.34
        else:
            nominal1 = 2.346
            nominal2 = 2.176
            visible = 'upper'
            edgedistance = 0.0

    edgeangle = math.radians(stepdict[far + ' ' + moduleend + ' ' + visible +
                                      ' edge']['XY Angle'][1])
    edgeel = math.radians(stepdict[far + ' ' + moduleend + ' ' + visible +
                                   ' edge']['Elevation'][1])
    edgevec = np.array([
        math.cos(edgeangle) * math.cos(edgeel),
        math.sin(edgeangle) * math.cos(edgeel),
        math.sin(edgeel)
    ])
    edgepos = np.array([
        stepdict[far + ' ' + moduleend + ' ' + visible +
                 ' edge']['X Location'][1],
        stepdict[far + ' ' + moduleend + ' ' + visible +
                 ' edge']['Y Location'][1] +
        edgedistance / abs(math.cos(edgeangle)),
        stepdict[far + ' ' + moduleend + ' ' + visible +
                 ' edge']['Z Location'][1]
    ])
    edgevec = ogp_util.transform_vec(meas_basis, fixture_basis, edgevec)
    edgepos = ogp_util.transform_pt(meas_basis, fixture_basis, edgepos)

    topedge1 = edgepos[1] + (fixture_x1 * 25.4 - edgepos[0]) * (edgevec[1] /
                                                                edgevec[0])
    topedge2 = edgepos[1] + (fixture_x2 * 25.4 - edgepos[0]) * (edgevec[1] /
                                                                edgevec[0])

    print far + ' ' + moduleend + ' edge 1: nominal {0:.4f}, actual {1:.4f} (deviation {2:.2f} um)'.format(
        nominal1 * 25.4, topedge1, 1000 * (topedge1 - nominal1 * 25.4))
    print far + ' ' + moduleend + ' edge 2: nominal {0:.4f}, actual {1:.4f} (deviation {2:.2f} um)'.format(
        nominal2 * 25.4, topedge2, 1000 * (topedge2 - nominal2 * 25.4))
Exemplo n.º 8
0
def check_alignment(moduleend):
	sensorname = near+' '+moduleend
	points = np.empty([3,11])
	points = ogp_util.get_points(stepdict, sensorname, 4, 7)

	#print points
	for i in range(0,11):
		points[:,i] = ogp_util.transform_pt(meas_basis,fixture_basis,points[:,i])

	#print points

	[fiducials_nominal,p0] = ogp_util.l456_fiducials(moduleend,side)

	sol = scipy.optimize.leastsq(ogp_util.sensor_fitfunc,p0,args=(points,fiducials_nominal))[0]
	print 'Sensor fit parameters: '+str(sol)
	print 'Sensor fit residuals (um): '+str(1000.0*ogp_util.sensor_fitfunc(sol, points, fiducials_nominal))

	sensor_origin = np.array(sol[0:3])
	sensor_rotation = ogp_util.make_rotation(sol[3],sol[4],sol[5])
	print 'Sensor origin: {0}'.format(sensor_origin)
	norm_vec = sensor_rotation.T.dot([0.0, 0.0, 1.0])
	print 'Normal vector: {0}'.format(norm_vec)
	meas_vec = sensor_rotation.T.dot([1.0, 0.0, 0.0])
	print 'Strip vector: {0}'.format(meas_vec)
	angle = math.atan2(meas_vec[1],meas_vec[0])
	print 'Strip angle: {0}'.format(angle)

	if (moduleend=='block'):
		fixture_x1 = 5.875
		fixture_x2 = 2.500
		if (side=='front'):
			nominal1 = 2.176
			nominal2 = 2.008
		else:
			nominal1 = 2.176
			nominal2 = 2.176
	else:
		fixture_x1 = 9.250
		fixture_x2 = 5.875
		if (side=='front'):
			nominal1 = 2.346
			nominal2 = 2.176
		else:
			nominal1 = 2.176
			nominal2 = 2.176

	topedge1 = sensor_origin[1] + 20.17/abs(math.cos(angle)) + (fixture_x1*25.4 - sensor_origin[0])*math.tan(angle)
	topedge2 = sensor_origin[1] + 20.17/abs(math.cos(angle)) + (fixture_x2*25.4 - sensor_origin[0])*math.tan(angle)

	print near+' '+moduleend+' edge 1: nominal {0:.4f}, actual {1:.4f} (deviation {2:.2f} um)'.format(nominal1*25.4, topedge1, 1000*(topedge1-nominal1*25.4))
	print near+' '+moduleend+' edge 2: nominal {0:.4f}, actual {1:.4f} (deviation {2:.2f} um)'.format(nominal2*25.4, topedge2, 1000*(topedge2-nominal2*25.4))

	corner1 = sol[6]*(50.0)**2 + sol[7]*(20.17)**2 + sol[8]*50.0*20.17
	corner2 = sol[6]*(50.0)**2 + sol[7]*(20.17)**2 - sol[8]*50.0*20.17
	print 'Deviation from plane at corners (um): {0:.2f}, {1:.2f}'.format(corner1*1000,corner2*1000)

	hess = np.array([[2*sol[6],sol[8]], [sol[8],2*sol[7]]])
	w, v = np.linalg.eigh(hess)
	print 'Eigenvalues of curvature matrix:'
	print w
	print 'Eigenvectors of curvature matrix:'
	print v


	if (moduleend=='block'):
		if (side=='front'):
			nominal1 = 2.176
			nominal2 = 2.176
			visible = 'upper'
			edgedistance = 0.0
		else:
			nominal1 = 2.176
			nominal2 = 2.008
			visible = 'lower'
			edgedistance = 40.34
	else:
		if (side=='front'):
			nominal1 = 2.176
			nominal2 = 2.176
			visible = 'lower'
			edgedistance = 40.34
		else:
			nominal1 = 2.346
			nominal2 = 2.176
			visible = 'upper'
			edgedistance = 0.0

	edgeangle = math.radians(stepdict[far+' '+moduleend+' '+visible+' edge']['XY Angle'][1])
	edgeel = math.radians(stepdict[far+' '+moduleend+' '+visible+' edge']['Elevation'][1])
	edgevec = np.array([math.cos(edgeangle)*math.cos(edgeel),
		math.sin(edgeangle)*math.cos(edgeel),
		math.sin(edgeel)])
	edgepos = np.array([stepdict[far+' '+moduleend+' '+visible+' edge']['X Location'][1],
		stepdict[far+' '+moduleend+' '+visible+' edge']['Y Location'][1]+edgedistance/abs(math.cos(edgeangle)),
		stepdict[far+' '+moduleend+' '+visible+' edge']['Z Location'][1]])
	edgevec = ogp_util.transform_vec(meas_basis,fixture_basis,edgevec)
	edgepos = ogp_util.transform_pt(meas_basis,fixture_basis,edgepos)

	topedge1 = edgepos[1] + (fixture_x1*25.4 - edgepos[0])*(edgevec[1]/edgevec[0])
	topedge2 = edgepos[1] + (fixture_x2*25.4 - edgepos[0])*(edgevec[1]/edgevec[0])

	print far+' '+moduleend+' edge 1: nominal {0:.4f}, actual {1:.4f} (deviation {2:.2f} um)'.format(nominal1*25.4, topedge1, 1000*(topedge1-nominal1*25.4))
	print far+' '+moduleend+' edge 2: nominal {0:.4f}, actual {1:.4f} (deviation {2:.2f} um)'.format(nominal2*25.4, topedge2, 1000*(topedge2-nominal2*25.4))
Exemplo n.º 9
0
            ball_basis, uch_basis,
            ogp_util.transform_vec(null_basis, mod_basis, axial_vec))
        #print vec
        angle = math.atan2(vec[1], vec[0])
        if (abs(angle) > math.pi / 2):
            angle = angle - math.copysign(math.pi, angle)
        #print edge-nominal
        #print angle
        return np.append(edge - nominal, angle * 1000)

    return np.concatenate(
        (residual(l1_basis, global_basis, is_top * 6.5, 500,
                  dz), residual(l2_basis, global_basis, is_top * 9.5, 700, dz),
         residual(l3_basis, global_basis, is_top * 12.5, 900, dz)))


sol = scipy.optimize.leastsq(f_min, p0, args=())[0]
print sol
print f_min(sol)

global_basis = ogp_util.make_parametrized_basis(sol[0], sol[1], sol[2], sol[3],
                                                sol[4], sol[5])
if (is_top == 1):
    print 'top 4-6:'
else:
    print 'bottom 4-6:'
print ogp_util.transform_pt(ball_basis, global_basis, ball_basis[2]) / 25.4
print ogp_util.transform_pt(ball_basis, global_basis, ball_basis[3]) / 25.4
print ogp_util.transform_pt(ball_basis, global_basis, ball_basis[4]) / 25.4
print ogp_util.transform_pt(ball_basis, global_basis, ball_basis[5]) / 25.4
Exemplo n.º 10
0
    slotdownst[0] = dict[downst + ' slot ball reference']['X Location'][1]
    slotdownst[1] = dict[downst + ' slot ball reference']['Y Location'][1]
    slotdownst[2] = dict[downst + ' slot ball reference']['Z Location'][1]

    basis = ogp_util.make_uch_basis(holeupst, holedownst, slotupst, slotdownst)

    return basis


print 'top 1-3:'
t13_basis = ball_basis(t13dict, 'L1', 'L3')
#print t13_basis
t13_global = ogp_util.t13_global()
#print t13_global
print 'ball {0}, nominal {1}, residual {2}'.format(
    ogp_util.transform_pt(t13_basis, t13_global, t13_basis[2]), t13_global[2],
    ogp_util.transform_pt(t13_basis, t13_global, t13_basis[2]) - t13_global[2])
print 'ball {0}, nominal {1}, residual {2}'.format(
    ogp_util.transform_pt(t13_basis, t13_global, t13_basis[3]), t13_global[3],
    ogp_util.transform_pt(t13_basis, t13_global, t13_basis[3]) - t13_global[3])
print 'ball {0}, nominal {1}, residual {2}'.format(
    ogp_util.transform_pt(t13_basis, t13_global, t13_basis[4]), t13_global[4],
    ogp_util.transform_pt(t13_basis, t13_global, t13_basis[4]) - t13_global[4])
print 'ball {0}, nominal {1}, residual {2}'.format(
    ogp_util.transform_pt(t13_basis, t13_global, t13_basis[5]), t13_global[5],
    ogp_util.transform_pt(t13_basis, t13_global, t13_basis[5]) - t13_global[5])

print 'bottom 1-3:'
b13_basis = ball_basis(b13dict, 'L1', 'L3')
#print b13_basis
b13_global = ogp_util.b13_global()
Exemplo n.º 11
0
	slotupst[1]=dict[upst+' slot ball reference']['Y Location'][1]
	slotupst[2]=dict[upst+' slot ball reference']['Z Location'][1]
	slotdownst[0]=dict[downst+' slot ball reference']['X Location'][1]
	slotdownst[1]=dict[downst+' slot ball reference']['Y Location'][1]
	slotdownst[2]=dict[downst+' slot ball reference']['Z Location'][1]

	basis = ogp_util.make_uch_basis(holeupst,holedownst,slotupst,slotdownst)

	return basis

print 'top 1-3:'
t13_basis = ball_basis(t13dict,'L1','L3')
#print t13_basis
t13_global = ogp_util.t13_global()
#print t13_global
print 'ball {0}, nominal {1}, residual {2}'.format(ogp_util.transform_pt(t13_basis,t13_global,t13_basis[2]),t13_global[2],ogp_util.transform_pt(t13_basis,t13_global,t13_basis[2])-t13_global[2])
print 'ball {0}, nominal {1}, residual {2}'.format(ogp_util.transform_pt(t13_basis,t13_global,t13_basis[3]),t13_global[3],ogp_util.transform_pt(t13_basis,t13_global,t13_basis[3])-t13_global[3])
print 'ball {0}, nominal {1}, residual {2}'.format(ogp_util.transform_pt(t13_basis,t13_global,t13_basis[4]),t13_global[4],ogp_util.transform_pt(t13_basis,t13_global,t13_basis[4])-t13_global[4])
print 'ball {0}, nominal {1}, residual {2}'.format(ogp_util.transform_pt(t13_basis,t13_global,t13_basis[5]),t13_global[5],ogp_util.transform_pt(t13_basis,t13_global,t13_basis[5])-t13_global[5])

print 'bottom 1-3:'
b13_basis = ball_basis(b13dict,'L1','L3')
#print b13_basis
b13_global = ogp_util.b13_global()
#print b13_global
print 'ball {0}, nominal {1}, residual {2}'.format(ogp_util.transform_pt(b13_basis,b13_global,b13_basis[2]),b13_global[2],ogp_util.transform_pt(b13_basis,b13_global,b13_basis[2])-b13_global[2])
print 'ball {0}, nominal {1}, residual {2}'.format(ogp_util.transform_pt(b13_basis,b13_global,b13_basis[3]),b13_global[3],ogp_util.transform_pt(b13_basis,b13_global,b13_basis[3])-b13_global[3])
print 'ball {0}, nominal {1}, residual {2}'.format(ogp_util.transform_pt(b13_basis,b13_global,b13_basis[4]),b13_global[4],ogp_util.transform_pt(b13_basis,b13_global,b13_basis[4])-b13_global[4])
print 'ball {0}, nominal {1}, residual {2}'.format(ogp_util.transform_pt(b13_basis,b13_global,b13_basis[5]),b13_global[5],ogp_util.transform_pt(b13_basis,b13_global,b13_basis[5])-b13_global[5])

print 'top 4-6:'
Exemplo n.º 12
0
w, v = np.linalg.eigh(hess)
print "Eigenvalues of curvature matrix: {0}".format(w)
print "Eigenvectors of curvature matrix: \n{0}".format(v)

edgeangle = math.radians(stepdict[far + " upper edge"]["XY Angle"][1])
edgeel = math.radians(stepdict[far + " upper edge"]["Elevation"][1])
edgevec = np.array([math.cos(edgeangle) * math.cos(edgeel), math.sin(edgeangle) * math.cos(edgeel), math.sin(edgeel)])
edgepos = np.array(
    [
        stepdict[far + " upper edge"]["X Location"][1],
        stepdict[far + " upper edge"]["Y Location"][1],
        stepdict[far + " upper edge"]["Z Location"][1],
    ]
)
edgevec = ogp_util.transform_vec(meas_basis, fixture_basis, edgevec)
edgepos = ogp_util.transform_pt(meas_basis, fixture_basis, edgepos)

topedge1 = edgepos[1] + (6.500 * 25.4 - edgepos[0]) * (edgevec[1] / edgevec[0])
topedge2 = edgepos[1] + (3.125 * 25.4 - edgepos[0]) * (edgevec[1] / edgevec[0])

if side == "front":
    nominal1 = 2.337
    nominal2 = 2.337
else:
    nominal1 = 2.505
    nominal2 = 2.166

print far + " edge 1: nominal {0:.4f}, actual {1:.4f} (deviation {2:.2f} um)".format(
    nominal1 * 25.4, topedge1, 1000 * (topedge1 - nominal1 * 25.4)
)
print far + " edge 2: nominal {0:.4f}, actual {1:.4f} (deviation {2:.2f} um)".format(