def plot_gate_ring(sigma=np.deg2rad(13), shift=np.deg2rad(40), theta_t=0., phi_t=0., subplot=111): theta, phi = fibonacci_sphere(samples=1000, fov=161) d_cl1 = (np.sin(shift - theta) * np.cos(theta_t) + np.cos(shift - theta) * np.sin(theta_t) * np.cos(phi - phi_t)) gate = np.power(np.exp(-np.square(d_cl1) / (2. * np.square(sigma))), 1) ax = plt.subplot(subplot, polar=True) ax.scatter(phi, theta, s=10, marker='o', c=gate, cmap="Reds", vmin=0, vmax=1) ax.set_theta_zero_location("N") ax.set_theta_direction(-1) ax.set_ylim([0, np.deg2rad(90)]) plt.yticks([np.deg2rad(28)], [r'$28^\circ$']) ax.set_xticks(np.linspace(0, 2 * np.pi, 8, endpoint=False)) ax.set_xticklabels([ r'$0^\circ$', r'$45^\circ$', r'$90^\circ$', r'$135^\circ$', r'$180^\circ$', r'$-135^\circ$', r'$-90^\circ$', r'$-45^\circ$' ]) return plt
def plot_res2ele(samples=1000, noise=0., subplot=111): ele, azi, azi_diff, res = [], [], [], [] theta_s, phi_s = fibonacci_sphere(samples=samples, fov=161) phi_s = phi_s[theta_s <= np.pi / 2] theta_s = theta_s[theta_s <= np.pi / 2] phi_s = phi_s[theta_s > np.pi / 18] theta_s = theta_s[theta_s > np.pi / 18] samples = theta_s.size for e, a in zip(theta_s, phi_s): d_err, d_eff, tau, _, _ = evaluate(sun_azi=a, sun_ele=e, tilting=False, noise=noise) azi.append(a) ele.append(e) res.append(tau.flatten()) ele = np.rad2deg(ele).flatten() res = (np.array(res).flatten() - 1.06) * 7 / 4 ele = ele[res <= 2] res = res[res <= 2] ele_pred = 26 * (1 - 2 * np.arcsin(1 - res) / np.pi) + 15 # + np.random.randn(res.size) plt.subplot(subplot) plt.scatter(res, ele, c='black', marker='.') plt.scatter(res, ele_pred, c='red', marker='.') plt.plot([-.5, 3 * np.pi / 4], [18.75, 18.75], "k--") plt.plot([-.5, 3 * np.pi / 4], [65.98, 65.98], "k--") plt.ylabel(r'$\epsilon (\circ)$') plt.xlabel(r'$\tau$') plt.xlim([-.5, 3 * np.pi / 4]) plt.ylim([90, 0]) # plt.xticks([0, 90, 180, 270, 360]) return plt
def plot_gate_cost(samples=500, **kwargs): d_err, d_eff, tau, _, _ = evaluate(samples=samples, tilting=True, **kwargs) tau = np.rad2deg(tau) d_mean = np.nanmean(d_err) d_se = d_err.std() / np.sqrt(d_err.size) print "Tilt overall 0 deg 30 deg 60 deg " print "---------------------------------------------------------------------------------------" print "Mean cost %.2f +/- %.4f" % (d_mean, d_se), if samples == 1000: samples /= 2 theta_s, phi_s = fibonacci_sphere(samples=samples, fov=161) phi_s = phi_s[theta_s <= np.pi / 2] theta_s = theta_s[theta_s <= np.pi / 2] d_00 = d_err[:, 0] d_30 = np.nanmean(d_err[:, 1:9], axis=1) d_60 = np.nanmean(d_err[:, 9:], axis=1) print " %.2f +/- %.4f" % (np.nanmean(d_00), np.nanstd(d_00) / d_00.size), print " %.2f +/- %.4f" % (np.nanmean( d_err[:, 1:9]), np.nanstd(d_err[:, 1:9]) / d_err[:, 1:9].size), print " %.2f +/- %.4f" % (np.nanmean( d_err[:, 9:]), np.nanstd(d_err[:, 9:]) / d_err[:, 9:].size) for i, ang, dd in zip(range(3), [0, np.pi / 6, np.pi / 3], [d_00, d_30, d_60]): ax = plt.subplot2grid((1, 10), (0, i * 3), colspan=3, polar=True) ax.set_theta_zero_location("N") ax.set_theta_direction(-1) plt.scatter(phi_s, np.rad2deg(theta_s), marker=".", c=dd, cmap="Reds", vmin=0, vmax=90) plt.scatter(np.pi, np.rad2deg(ang), marker="o", c="yellowgreen", edgecolors="black") plt.text(-np.deg2rad(50), 145, ["A", "B", "C"][i], fontsize=12) plt.axis("off") plt.subplot2grid((3, 10), (1, 9)) plt.imshow(np.array([np.arange(0, np.pi / 2, np.pi / 180)] * 10).T, cmap="Reds") plt.xticks([]) plt.yticks([0, 45, 89], [r"0", r"$\frac{\pi}{4}$", r"$\geq\frac{\pi}{2}$"]) return plt
def plot_res2ele(samples=1000, noise=0., subplot=111): ele, azi, azi_diff, res = [], [], [], [] theta_s, phi_s = fibonacci_sphere(samples=samples, fov=161) phi_s = phi_s[theta_s <= np.pi / 2] theta_s = theta_s[theta_s <= np.pi / 2] phi_s = phi_s[theta_s > np.pi / 18] theta_s = theta_s[theta_s > np.pi / 18] samples = theta_s.size for e, a in zip(theta_s, phi_s): d_err, d_eff, tau, _, _ = evaluate(sun_azi=a, sun_ele=e, tilting=False, noise=noise) azi.append(a) ele.append(e) res.append(tau.flatten()) ele = np.rad2deg(ele).flatten() res = np.array(res).flatten() ele_pred = 26 * ( 1 - 2 * np.arcsin(np.clip(2.855 - 3.5 * res, -1, 1)) / np.pi) + 15 plt.subplot(subplot) plt.scatter(res, ele, c='black', marker='.') plt.scatter(np.clip(res, 0, 4), ele_pred, c='red', marker='.') plt.plot([-.5, 3 * np.pi / 4], [18.75, 18.75], "k--") plt.plot([-.5, 3 * np.pi / 4], [65.98, 65.98], "k--") plt.ylabel(r'$\epsilon (\circ)$') plt.xlabel(r'$\tau$') plt.xticks([0.5, 0.75, 1, 1.25]) plt.xlim([.43, 1.21]) plt.ylim([90, 0]) return plt
def __init__(self, nb_lenses=60, fov=60, nb_tb1=8, consider_tilting=False, b_thetas=True, b_phis=True, b_alphas=True, b_ws=True, noise=0.5): # Initialise the position and orientation of the lenses with fibonacci distribution thetas, phis = fibonacci_sphere(samples=nb_lenses, fov=fov) thetas = (thetas + np.pi) % (2 * np.pi) - np.pi phis = (phis + np.pi) % (2 * np.pi) - np.pi alphas = (phis + 3 * np.pi / 2) % (2 * np.pi) - np.pi # initialise weights of the computational model phi_tb1 = np.linspace(0., 2 * np.pi, nb_tb1, endpoint=False) # TB1 preference angles w = nb_tb1 / (2. * nb_lenses) * np.sin(phi_tb1[np.newaxis] - alphas[:, np.newaxis]) # create initial feature-vector self.x_init = self.vectorise(thetas, phis, alphas, w) self.theta_init = thetas self.phi_init = phis self.w_f = lambda a: nb_tb1 / (2. * nb_lenses) * np.maximum(np.sin(phi_tb1[np.newaxis] - a[:, np.newaxis]), 0.) self.ndim = (3 + nb_tb1) * nb_lenses # number of features self.lb = np.hstack(( # lower bound of parameters np.zeros(nb_lenses), # theta np.full(nb_lenses, -np.pi), # phi np.full(nb_lenses, -np.pi), # alpha -np.ones(nb_tb1 * nb_lenses) # weights )) self.ub = np.hstack(( # upper bound of parameters np.full(nb_lenses, np.deg2rad(fov) / 2), # theta np.full(nb_lenses, np.pi), # phi np.full(nb_lenses, np.pi), # alpha np.ones(nb_tb1 * nb_lenses) # weights )) self._thetas = b_thetas self._phis = b_phis self._alphas = b_alphas self._ws = b_ws self.__consider_tilting = consider_tilting self._noise = noise
vmin=-np.pi, vmax=np.pi) ax.scatter(phi_s, theta_s, s=100, edgecolor='black', facecolor='yellow') # ax.scatter(sky.phi_t + np.pi, sky.theta_t, s=200, edgecolor='black', facecolor='greenyellow') ax.set_ylim([0, np.pi / 2]) ax.set_yticks([]) ax.set_xticks(np.linspace(0, 2 * np.pi, 8, endpoint=False)) ax.set_xticklabels([ r'$0^\circ$ (N)', r'$45^\circ$ (NE)', r'$90^\circ$ (E)', r'$135^\circ$ (SE)', r'$180^\circ$ (S)', r'$-135^\circ$ (SW)', r'$-90^\circ$ (W)', r'$-45^\circ$ (NW)' ]) plt.show() if __name__ == "__main__": from compoundeye.geometry import fibonacci_sphere t, p = fibonacci_sphere(10000, 180) s = Sky(theta_s=np.pi / 6) # s = sky_from_observer() # s = Sky.from_type(11) # s.theta_s = np.pi/6 y, p, a = s(t, p) visualise_luminance(s) # visualise_degree_of_polarisation(s) # visualise_angle_of_polarisation(s)
n = 60 omega = 56 theta, phi, fit = angles_distribution(n, float(omega)) theta_t, phi_t = 0., 0. # sun position seville = ephem.Observer() seville.lat = '37.392509' seville.lon = '-5.983877' seville.date = datetime(2018, 6, 21, 9, 0, 0) sun = ephem.Sun() sun.compute(seville) theta_s = np.array([np.pi / 2 - sun.alt]) phi_s = np.array([(sun.az + np.pi) % (2 * np.pi) - np.pi]) theta_sky, phi_sky = fibonacci_sphere(1000, 180) # ant-world noise_type = "canopy" mode = "uneven" noise = 0.0 ttau = .06 dx = 1e-02 # world = load_world() routes = load_routes() flow = dx * np.ones(2) / np.sqrt(2) max_theta = 0. for ni, noise in enumerate([0.0, 0.2, 0.4, 0.6, 0.8, 1.0]): # for ni, noise in enumerate([0.0]):
def skyfeatures(noise=0., simple_pol=False, samples=1000, verbose=False): # default parameters tau_L = 2. c1 = .6 c2 = 4. eps = np.finfo(float).eps AA, BB, CC, DD, EE = SensorObjective.T_L.dot(np.array( [tau_L, 1.])) # sky parameters T_T = np.linalg.pinv(SensorObjective.T_L) tau_L, c = T_T.dot(np.array([AA, BB, CC, DD, EE])) tau_L /= c # turbidity correction # Prez. et. al. Luminance function def L(cchi, zz): ii = zz < (np.pi / 2) ff = np.zeros_like(zz) if zz.ndim > 0: ff[ii] = (1. + AA * np.exp(BB / (np.cos(zz[ii]) + eps))) elif ii: ff = (1. + AA * np.exp(BB / (np.cos(zz) + eps))) pphi = (1. + CC * np.exp(DD * cchi) + EE * np.square(np.cos(cchi))) return ff * pphi theta_s, phi_s = np.array([np.pi / 6]), np.array([np.pi]) theta, phi = fibonacci_sphere(samples, 180) phi = phi[theta <= np.pi / 2] theta = theta[theta <= np.pi / 2] samples = theta.size theta = (theta - np.pi) % (2 * np.pi) - np.pi phi = (phi + np.pi) % (2 * np.pi) - np.pi alpha = (phi + np.pi / 2) % (2 * np.pi) - np.pi # SKY INTEGRATION gamma = np.arccos( np.cos(theta) * np.cos(theta_s) + np.sin(theta) * np.sin(theta_s) * np.cos(phi - phi_s)) # Intensity I_prez, I_00, I_90 = L(gamma, theta), L(0., theta_s), L( np.pi / 2, np.absolute(theta_s - np.pi / 2)) # influence of sky intensity I = (1. / (I_prez + eps) - 1. / (I_00 + eps)) * I_00 * I_90 / (I_00 - I_90 + eps) chi = (4. / 9. - tau_L / 120.) * (np.pi - 2 * theta_s) Y_z = (4.0453 * tau_L - 4.9710) * np.tan(chi) - 0.2155 * tau_L + 2.4192 Y = np.maximum(Y_z * I_prez / (I_00 + eps), 0.) # Illumination # Degree of Polarisation M_p = np.exp(-(tau_L - c1) / (c2 + eps)) LP = np.square(np.sin(gamma)) / (1 + np.square(np.cos(gamma))) if simple_pol: P = np.clip(2. / np.pi * M_p * LP, 0., 1.) else: P = np.clip( 2. / np.pi * M_p * LP * (theta * np.cos(theta) + (np.pi / 2 - theta) * I), 0., 1.) # Angle of polarisation _, A = tilt(theta_s, phi_s + np.pi, theta, phi) # create cloud disturbance if type(noise) is np.ndarray: if noise.size == P.size: # print "yeah!" eta = np.array(noise, dtype=bool) else: eta = np.zeros_like(theta, dtype=bool) eta[:noise.size] = noise elif noise > 0: eta = np.argsort(np.absolute( np.random.randn(*P.shape)))[:int(noise * P.shape[0])] # eta = np.array(np.absolute(np.random.randn(*P.shape)) < noise, dtype=bool) if verbose: print "Noise level: %.4f (%.2f %%)" % (noise, 100. * eta.sum() / float(eta.size)) else: eta = np.zeros_like(theta, dtype=bool) P[eta] = 0. # destroy the polarisation pattern Y[eta] = 10. return Y, P, A, theta, phi
eta = np.zeros_like(theta, dtype=bool) P[eta] = 0. # destroy the polarisation pattern Y[eta] = 10. return Y, P, A, theta, phi if __name__ == "__main__": from compoundeye import POLCompassDRA from environment import Sky samples = 1000 noise = .0 # noise = .99 theta, phi = fibonacci_sphere(samples, 180) sky = Sky(np.pi / 6, np.pi) y, p, a = sky(theta, phi) # y, p, a, theta, phi = skyfeatures(noise, samples=50000) # dra = POLCompassDRA() # r = dra(sky, noise=noise) # # print r.shape # print r # # plt.figure("pol-%02d" % (10 * noise), figsize=(3, 3)) # ax = plt.subplot(111, polar=True) # ax.scatter(dra.phi, dra.theta, s=100, marker='.', c=r, cmap="coolwarm", vmin=-.1, vmax=.1) # ax.set_theta_zero_location("N") # ax.set_theta_direction(-1) # ax.set_ylim([0, np.deg2rad(30)])
def azirot(vec, phi): """ Rotate a vector horizontally and clockwise. :param vec: the 3D vector :param phi: the azimuth of the rotation """ Rz = np.asarray([[np.cos(phi), -np.sin(phi), 0], [np.sin(phi), np.cos(phi), 0], [0, 0, 1]]) return Rz.dot(vec) if __name__ == "__main__": from compoundeye.geometry import fibonacci_sphere # v = np.array([[1], [0], [0]], dtype=float) # v = np.array([0, 1, 0], dtype=float) theta_s, phi_s = fibonacci_sphere(samples=1000, fov=161) phi_s = phi_s[theta_s <= np.pi / 2] theta_s = theta_s[theta_s <= np.pi / 2] samples = theta_s.size theta_t, phi_t = np.pi / 4, np.pi / 4 v_s = sph2vec(theta_s, phi_s, zenith=True) R = sph2rotmat(theta_t, phi_t) theta_s_1, phi_s_1, _ = vec2sph(R.dot(v_s), zenith=True) theta_s_2, phi_s_2 = tilt(theta_t, phi_t, theta_s, phi_s) print "Elevation:", np.all(np.isclose(theta_s_1, theta_s_2)), print "--- Azimuth:", np.all(np.isclose(phi_s_1, phi_s_2))
def evaluate_old( n=60, omega=56, noise=0., nb_cl1=16, sigma=np.deg2rad(13), shift=np.deg2rad(40), nb_tb1=8, use_default=False, weighted=True, fibonacci=False, simple_pol=False, uniform_poliriser=False, # single evaluation sun_azi=None, sun_ele=None, # data parameters tilting=True, samples=1000, show_plots=False, show_structure=False, verbose=False): # default parameters tau_L = 2. c1 = .6 c2 = 4. eps = np.finfo(float).eps AA, BB, CC, DD, EE = T_L.dot(np.array([tau_L, 1.])) # sky parameters T_T = np.linalg.pinv(T_L) tau_L, c = T_T.dot(np.array([AA, BB, CC, DD, EE])) tau_L /= c # turbidity correction # Prez. et. al. Luminance function def L(cchi, zz): ii = zz < (np.pi / 2) ff = np.zeros_like(zz) if zz.ndim > 0: ff[ii] = (1. + AA * np.exp(BB / (np.cos(zz[ii]) + eps))) elif ii: ff = (1. + AA * np.exp(BB / (np.cos(zz) + eps))) pphi = (1. + CC * np.exp(DD * cchi) + EE * np.square(np.cos(cchi))) return ff * pphi if tilting: angles = np.array([[0., 0.], [np.pi / 6, 0.], [np.pi / 6, np.pi / 4], [np.pi / 6, 2 * np.pi / 4], [np.pi / 6, 3 * np.pi / 4], [np.pi / 6, 4 * np.pi / 4], [np.pi / 6, 5 * np.pi / 4], [np.pi / 6, 6 * np.pi / 4], [np.pi / 6, 7 * np.pi / 4], [np.pi / 3, 0.], [np.pi / 3, np.pi / 4], [np.pi / 3, 2 * np.pi / 4], [np.pi / 3, 3 * np.pi / 4], [np.pi / 3, 4 * np.pi / 4], [np.pi / 3, 5 * np.pi / 4], [np.pi / 3, 6 * np.pi / 4], [np.pi / 3, 7 * np.pi / 4]]) # 17 if samples == 1000: samples /= 2 else: angles = np.array([[0., 0.]]) # 1 # generate the different sun positions if sun_azi is not None or sun_ele is not None: theta_s = sun_ele if type(sun_ele) is np.ndarray else np.array( [sun_ele]) phi_s = sun_azi if type(sun_azi) is np.ndarray else np.array([sun_azi]) else: theta_s, phi_s = fibonacci_sphere(samples=samples, fov=161) phi_s = phi_s[theta_s <= np.pi / 2] theta_s = theta_s[theta_s <= np.pi / 2] samples = theta_s.size # generate the properties of the sensor try: theta, phi, fit = angles_distribution(n, float(omega)) except ValueError: theta = np.empty(0, dtype=np.float32) phi = np.empty(0, dtype=np.float32) fit = False if not fit or n > 100 or fibonacci: theta, phi = fibonacci_sphere(n, float(omega)) # theta, phi, fit = angles_distribution(n, omega) # if not fit: # print theta.shape, phi.shape theta = (theta - np.pi) % (2 * np.pi) - np.pi phi = (phi + np.pi) % (2 * np.pi) - np.pi alpha = (phi + np.pi / 2) % (2 * np.pi) - np.pi # computational model parameters phi_cl1 = np.linspace(0., 4 * np.pi, nb_cl1, endpoint=False) # CL1 preference angles phi_tb1 = np.linspace(0., 2 * np.pi, nb_tb1, endpoint=False) # TB1 preference angles # initialise lists for the statistical data d = np.zeros((samples, angles.shape[0]), dtype=np.float32) t = np.zeros_like(d) d_eff = np.zeros((samples, angles.shape[0]), dtype=np.float32) a_ret = np.zeros_like(t) tb1 = np.zeros((samples, angles.shape[0], nb_tb1), dtype=np.float32) # iterate through the different tilting angles for j, (theta_t, phi_t) in enumerate(angles): # transform relative coordinates theta_s_, phi_s_ = tilt(theta_t, phi_t, theta=theta_s, phi=phi_s) theta_, phi_ = tilt(theta_t, phi_t + np.pi, theta=theta, phi=phi) _, alpha_ = tilt(theta_t, phi_t + np.pi, theta=np.pi / 2, phi=alpha) for i, (e, a, e_org, a_org) in enumerate(zip(theta_s_, phi_s_, theta_s, phi_s)): # SKY INTEGRATION gamma = np.arccos( np.cos(theta_) * np.cos(e_org) + np.sin(theta_) * np.sin(e_org) * np.cos(phi_ - a_org)) # Intensity I_prez, I_00, I_90 = L(gamma, theta_), L(0., e_org), L( np.pi / 2, np.absolute(e_org - np.pi / 2)) # influence of sky intensity I = (1. / (I_prez + eps) - 1. / (I_00 + eps)) * I_00 * I_90 / (I_00 - I_90 + eps) chi = (4. / 9. - tau_L / 120.) * (np.pi - 2 * e_org) Y_z = (4.0453 * tau_L - 4.9710) * np.tan(chi) - 0.2155 * tau_L + 2.4192 if uniform_poliriser: Y = np.maximum(np.full_like(I_prez, Y_z), 0.) else: Y = np.maximum(Y_z * I_prez / (I_00 + eps), 0.) # Illumination # Degree of Polarisation M_p = np.exp(-(tau_L - c1) / (c2 + eps)) LP = np.square(np.sin(gamma)) / (1 + np.square(np.cos(gamma))) if uniform_poliriser: P = np.ones_like(LP) elif simple_pol: P = np.clip(2. / np.pi * M_p * LP, 0., 1.) else: P = np.clip( 2. / np.pi * M_p * LP * (theta_ * np.cos(theta_) + (np.pi / 2 - theta_) * I), 0., 1.) # Angle of polarisation if uniform_poliriser: A = np.full_like(P, a_org + np.pi) else: _, A = tilt(e_org, a_org + np.pi, theta_, phi_) # create cloud disturbance if noise > 0: eta = np.absolute(np.random.randn(*P.shape)) < noise if verbose: print "Noise level: %.4f (%.2f %%)" % ( noise, 100. * eta.sum() / float(eta.size)) P[eta] = 0. # destroy the polarisation pattern else: eta = np.zeros(1) # COMPUTATIONAL MODEL # Input (POL) layer -- Photo-receptors s_1 = 15. * (np.square(np.sin(A - alpha_)) + np.square(np.cos(A - alpha_)) * np.square(1. - P)) s_2 = 15. * (np.square(np.cos(A - alpha_)) + np.square(np.sin(A - alpha_)) * np.square(1. - P)) r_1, r_2 = np.sqrt(s_1), np.sqrt(s_2) # r_1, r_2 = np.log(s_1 + 1.), np.log(s_2 + 1.) r_pol = (r_1 - r_2) / (r_1 + r_2 + eps) # Tilting (CL1) layer d_cl1 = ( np.sin(shift - theta) * np.cos(theta_t) + np.cos(shift - theta) * np.sin(theta_t) * np.cos(phi - phi_t)) gate = np.power( np.exp(-np.square(d_cl1) / (2. * np.square(sigma))), 1) w_cl1 = float(nb_cl1) / float(n) * np.sin( alpha[:, np.newaxis] - phi_cl1[np.newaxis]) * gate[:, np.newaxis] r_cl1 = r_pol.dot(w_cl1) # Output (TB1) layer w_tb1 = float(nb_tb1) / float( 2 * nb_cl1) * np.cos(phi_tb1[np.newaxis] - phi_cl1[:, np.newaxis]) r_tb1 = r_cl1.dot(w_tb1) if use_default: w = -float(nb_tb1) / (2. * float(n)) * np.sin(phi_tb1[ np.newaxis] - alpha[:, np.newaxis]) * gate[:, np.newaxis] r_tb1 = r_pol.dot(w) # decode response - FFT R = r_tb1.dot( np.exp(-np.arange(nb_tb1) * (0. + 1.j) * np.pi / (float(nb_tb1) / 2.))) a_pred = (np.pi - np.arctan2(R.imag, R.real)) % ( 2. * np.pi) - np.pi # sun azimuth (prediction) tau_pred = np.absolute(R) # certainty of prediction d[i, j] = np.absolute( azidist(np.array([e, a]), np.array([0., a_pred]))) t[i, j] = tau_pred if weighted else 1. a_ret[i, j] = a_pred tb1[i, j] = r_tb1 # effective degree of polarisation M = r_cl1.max() - r_cl1.min() # M = t[i, j] * 2. p = np.power(10, M / 2.) d_eff[i, j] = np.mean((p - 1.) / (p + 1.)) if show_plots: plt.figure("sensor-noise-%2d" % (100. * eta.sum() / float(eta.size)), figsize=(18, 4.5)) ax = plt.subplot(1, 12, 10) plt.imshow(w_cl1, cmap="coolwarm", vmin=-1, vmax=1) plt.xlabel("CBL", fontsize=16) plt.xticks([0, 15], ["1", "16"]) plt.yticks([0, 59], ["1", "60"]) ax.tick_params(axis='both', which='major', labelsize=16) ax.tick_params(axis='both', which='minor', labelsize=16) ax = plt.subplot(1, 6, 6) # , sharey=ax) plt.imshow(w_tb1, cmap="coolwarm", vmin=-1, vmax=1) plt.xlabel("TB1", fontsize=16) plt.xticks([0, 7], ["1", "8"]) plt.yticks([0, 15], ["1", "16"]) cbar = plt.colorbar(ticks=[-1, 0, 1]) cbar.ax.set_yticklabels([r'$\leq$ -1', r'0', r'$\geq$ 1']) ax.tick_params(axis='both', which='major', labelsize=16) ax.tick_params(axis='both', which='minor', labelsize=16) ax = plt.subplot(1, 4, 1, polar=True) ax.scatter(phi, theta, s=150, c=r_pol, marker='o', cmap="coolwarm", vmin=-1, vmax=1) ax.scatter(a, e, s=100, marker='o', edgecolor='black', facecolor='yellow') ax.scatter(phi_t + np.pi, theta_t, s=200, marker='o', edgecolor='black', facecolor='yellowgreen') ax.set_theta_zero_location("N") ax.set_theta_direction(-1) ax.set_ylim([0, np.deg2rad(40)]) ax.set_yticks([]) ax.set_xticks( np.linspace(-3 * np.pi / 4, 5 * np.pi / 4, 8, endpoint=False)) ax.set_title("POL Response", fontsize=16) ax.tick_params(axis='both', which='major', labelsize=16) ax.tick_params(axis='both', which='minor', labelsize=16) ax = plt.subplot(1, 4, 2, polar=True) ax.scatter(phi, theta, s=150, c=r_pol * gate, marker='o', cmap="coolwarm", vmin=-1, vmax=1) ax.scatter(a, e, s=100, marker='o', edgecolor='black', facecolor='yellow') ax.scatter(phi_t + np.pi, theta_t, s=200, marker='o', edgecolor='black', facecolor='yellowgreen') ax.set_theta_zero_location("N") ax.set_theta_direction(-1) ax.set_ylim([0, np.deg2rad(40)]) ax.set_yticks([]) ax.set_xticks( np.linspace(-3 * np.pi / 4, 5 * np.pi / 4, 8, endpoint=False)) ax.set_title("Gated Response", fontsize=16) ax.tick_params(axis='both', which='major', labelsize=16) ax.tick_params(axis='both', which='minor', labelsize=16) ax = plt.subplot(1, 4, 3, polar=True) x = np.linspace(0, 2 * np.pi, 721) # CBL ax.fill_between(x, np.full_like(x, np.deg2rad(60)), np.full_like(x, np.deg2rad(90)), facecolor="C1", alpha=.5, label="CBL") ax.scatter(phi_cl1[:nb_cl1 / 2] - np.pi / 24, np.full(nb_cl1 / 2, np.deg2rad(75)), s=600, c=r_cl1[:nb_cl1 / 2], marker='o', edgecolor='red', cmap="coolwarm", vmin=-1, vmax=1) ax.scatter(phi_cl1[nb_cl1 / 2:] + np.pi / 24, np.full(nb_cl1 / 2, np.deg2rad(75)), s=600, c=r_cl1[nb_cl1 / 2:], marker='o', edgecolor='green', cmap="coolwarm", vmin=-1, vmax=1) for ii, pp in enumerate(phi_cl1[:nb_cl1 / 2] - np.pi / 24): ax.text(pp - np.pi / 20, np.deg2rad(75), "%d" % (ii + 1), ha="center", va="center", size=10, bbox=dict(boxstyle="circle", fc="w", ec="k")) for ii, pp in enumerate(phi_cl1[nb_cl1 / 2:] + np.pi / 24): ax.text(pp + np.pi / 20, np.deg2rad(75), "%d" % (ii + 9), ha="center", va="center", size=10, bbox=dict(boxstyle="circle", fc="w", ec="k")) # TB1 ax.fill_between(x, np.full_like(x, np.deg2rad(30)), np.full_like(x, np.deg2rad(60)), facecolor="C2", alpha=.5, label="TB1") ax.scatter(phi_tb1, np.full_like(phi_tb1, np.deg2rad(45)), s=600, c=r_tb1, marker='o', edgecolor='blue', cmap="coolwarm", vmin=-1, vmax=1) for ii, pp in enumerate(phi_tb1): ax.text(pp, np.deg2rad(35), "%d" % (ii + 1), ha="center", va="center", size=10, bbox=dict(boxstyle="circle", fc="w", ec="k")) ax.arrow(pp, np.deg2rad(35), 0, np.deg2rad(10), fc='k', ec='k', head_width=.1, overhang=.3) # Sun position ax.scatter(a, e, s=500, marker='o', edgecolor='black', facecolor='yellow') # Decoded TB1 # ax.plot([0, a_pred], [0, e_pred], 'k--', lw=1) ax.plot([0, a_pred], [0, np.pi / 2], 'k--', lw=1) ax.arrow(a_pred, 0, 0, np.deg2rad(20), fc='k', ec='k', head_width=.3, head_length=.2, overhang=.3) ax.legend(ncol=2, loc=(-.55, -.1), fontsize=16) ax.set_theta_zero_location("N") ax.set_theta_direction(-1) ax.set_ylim([0, np.pi / 2]) ax.set_yticks([]) ax.set_xticks([]) ax.set_title("Sensor Response", fontsize=16) plt.subplots_adjust(left=.02, bottom=.12, right=.98, top=.88) ax.tick_params(axis='both', which='major', labelsize=16) ax.tick_params(axis='both', which='minor', labelsize=16) plt.show() d_deg = np.rad2deg(d) if show_structure: plt.figure("sensor-structure", figsize=(4.5, 4.5)) ax = plt.subplot(111, polar=True) ax.scatter(phi, theta, s=150, c="black", marker='o') ax.set_theta_zero_location("N") ax.set_theta_direction(-1) ax.set_ylim([0, np.deg2rad(50)]) ax.set_yticks([]) ax.set_xticks( np.linspace(-3 * np.pi / 4, 5 * np.pi / 4, 8, endpoint=False)) ax.set_title("POL Response") plt.show() return d_deg, d_eff, t, a_ret, tb1
def evaluate_slow( n=60, omega=56, noise=0., nb_cl1=8, sigma_pol=np.deg2rad(13), shift_pol=np.deg2rad(40), nb_tb1=8, sigma_sol=np.deg2rad(13), shift_sol=np.deg2rad(40), use_default=False, weighted=True, fibonacci=False, uniform_polariser=False, # single evaluation sun_azi=None, sun_ele=None, # data parameters tilting=True, samples=1000, show_plots=False, show_structure=False, verbose=False): if tilting: angles = np.array([[0., 0.], [np.pi / 6, 0.], [np.pi / 6, np.pi / 4], [np.pi / 6, 2 * np.pi / 4], [np.pi / 6, 3 * np.pi / 4], [np.pi / 6, 4 * np.pi / 4], [np.pi / 6, 5 * np.pi / 4], [np.pi / 6, 6 * np.pi / 4], [np.pi / 6, 7 * np.pi / 4], [np.pi / 3, 0.], [np.pi / 3, np.pi / 4], [np.pi / 3, 2 * np.pi / 4], [np.pi / 3, 3 * np.pi / 4], [np.pi / 3, 4 * np.pi / 4], [np.pi / 3, 5 * np.pi / 4], [np.pi / 3, 6 * np.pi / 4], [np.pi / 3, 7 * np.pi / 4]]) # 17 if samples == 1000: samples /= 2 else: angles = np.array([[0., 0.]]) # 1 # generate the different sun positions if sun_azi is not None or sun_ele is not None: theta_s = sun_ele if type(sun_ele) is np.ndarray else np.array( [sun_ele]) phi_s = sun_azi if type(sun_azi) is np.ndarray else np.array([sun_azi]) else: theta_s, phi_s = fibonacci_sphere(samples=samples, fov=161) phi_s = phi_s[theta_s <= np.pi / 2] theta_s = theta_s[theta_s <= np.pi / 2] samples = theta_s.size # generate the properties of the sensor try: theta, phi, fit = angles_distribution(n, float(omega)) except ValueError: theta = np.empty(0, dtype=np.float32) phi = np.empty(0, dtype=np.float32) fit = False if not fit or n > 100 or fibonacci: theta, phi = fibonacci_sphere(n, float(omega)) # theta, phi, fit = angles_distribution(n, omega) # if not fit: # print theta.shape, phi.shape theta = (theta - np.pi) % (2 * np.pi) - np.pi phi = (phi + np.pi) % (2 * np.pi) - np.pi alpha = (phi + np.pi / 2) % (2 * np.pi) - np.pi # computational model parameters phi_cl1 = np.linspace(0., 2 * np.pi, nb_cl1, endpoint=False) # CL1 preference angles phi_tb1 = np.linspace(0., 2 * np.pi, nb_tb1, endpoint=False) # TB1 preference angles # initialise lists for the statistical data d = np.zeros((samples, angles.shape[0]), dtype=np.float32) t = np.zeros_like(d) d_eff = np.zeros((samples, angles.shape[0]), dtype=np.float32) a_ret = np.zeros_like(t) tb1 = np.zeros((samples, angles.shape[0], nb_tb1), dtype=np.float32) # iterate through the different tilting angles for j, (theta_t, phi_t) in enumerate(angles): # transform relative coordinates theta_s_, phi_s_ = tilt(theta_t, phi_t, theta=theta_s, phi=phi_s) _, alpha_ = tilt(theta_t, phi_t + np.pi, theta=np.pi / 2, phi=alpha) for i, (e, a, e_org, a_org) in enumerate(zip(theta_s_, phi_s_, theta_s, phi_s)): sky = Sky(theta_s=e_org, phi_s=a_org, theta_t=theta_t, phi_t=phi_t) sky.verbose = verbose # COMPUTATIONAL MODEL # Input (POL) layer -- Photo-receptors dra = POLCompassDRA(n=n, omega=omega) dra.theta_t = theta_t dra.phi_t = phi_t r_pol = dra(sky, noise=noise, uniform_polariser=uniform_polariser) r_sol = dra.r_po # Tilting (SOL) layer d_pol = (np.sin(shift_pol - theta) * np.cos(theta_t) + np.cos(shift_pol - theta) * np.sin(theta_t) * np.cos(phi - phi_t)) gate_pol = np.power( np.exp(-np.square(d_pol) / (2. * np.square(sigma_pol))), 1) z_pol = -float(nb_cl1) / float(n) w_cl1_pol = z_pol * np.sin(phi_cl1[ np.newaxis] - alpha[:, np.newaxis]) * gate_pol[:, np.newaxis] d_sol = (np.sin(shift_sol - theta) * np.cos(theta_t) + np.cos(shift_sol - theta) * np.sin(theta_t) * np.cos(phi - phi_t)) gate_sol = np.power( np.exp(-np.square(d_sol) / (2. * np.square(sigma_sol))), 1) z_sol = float(nb_cl1) / float(n) w_cl1_sol = z_sol * np.sin(phi_cl1[ np.newaxis] - alpha[:, np.newaxis]) * gate_sol[:, np.newaxis] o = 1. / 64. f_pol, f_sol = .5 * np.power(2 * theta_t / np.pi, o), .5 * ( 1 - np.power(2 * theta_t / np.pi, o)) r_cl1_pol = r_pol.dot(w_cl1_pol) r_cl1_sol = r_sol.dot(w_cl1_sol) r_cl1 = f_pol * r_cl1_pol + f_sol * r_cl1_sol # r_cl1 = r_cl1_sol # Output (TCL) layer # w_tb1 = np.eye(nb_tb1) w_tb1 = float(nb_tb1) / float(nb_cl1) * np.cos( phi_tb1[np.newaxis] - phi_cl1[:, np.newaxis]) r_tb1 = r_cl1.dot(w_tb1) if use_default: w = -float(nb_tb1) / (2. * float(n)) * np.sin( phi_tb1[np.newaxis] - alpha[:, np.newaxis]) * gate_pol[:, np.newaxis] r_tb1 = r_pol.dot(w) # decode response - FFT R = r_tb1.dot( np.exp(-np.arange(nb_tb1) * (0. + 1.j) * np.pi / (float(nb_tb1) / 2.))) a_pred = (np.pi - np.arctan2(R.imag, R.real)) % ( 2. * np.pi) - np.pi # sun azimuth (prediction) tau_pred = np.maximum(np.absolute(R), 0) # certainty of prediction d[i, j] = np.absolute( azidist(np.array([e, a]), np.array([0., a_pred]))) t[i, j] = tau_pred if weighted else 1. a_ret[i, j] = a_pred tb1[i, j] = r_tb1 # effective degree of polarisation M = r_cl1.max() - r_cl1.min() # M = t[i, j] * 2. p = np.power(10, M / 2.) d_eff[i, j] = np.mean((p - 1.) / (p + 1.)) if show_plots: plt.figure("sensor-noise-%2d" % (100. * sky.eta.sum() / float(sky.eta.size)), figsize=(18, 4.5)) ax = plt.subplot(1, 12, 10) plt.imshow(w_cl1_pol, cmap="coolwarm", vmin=-1, vmax=1) plt.xlabel("CBL", fontsize=16) plt.xticks([0, 15], ["1", "16"]) plt.yticks([0, 59], ["1", "60"]) ax.tick_params(axis='both', which='major', labelsize=16) ax.tick_params(axis='both', which='minor', labelsize=16) ax = plt.subplot(1, 6, 6) # , sharey=ax) plt.imshow(w_tb1, cmap="coolwarm", vmin=-1, vmax=1) plt.xlabel("TB1", fontsize=16) plt.xticks([0, 7], ["1", "8"]) plt.yticks([0, 15], ["1", "16"]) cbar = plt.colorbar(ticks=[-1, 0, 1]) cbar.ax.set_yticklabels([r'$\leq$ -1', r'0', r'$\geq$ 1']) ax.tick_params(axis='both', which='major', labelsize=16) ax.tick_params(axis='both', which='minor', labelsize=16) ax = plt.subplot(1, 4, 1, polar=True) ax.scatter(phi, theta, s=150, c=r_pol, marker='o', cmap="coolwarm", vmin=-1, vmax=1) ax.scatter(a, e, s=100, marker='o', edgecolor='black', facecolor='yellow') ax.scatter(phi_t + np.pi, theta_t, s=200, marker='o', edgecolor='black', facecolor='yellowgreen') ax.set_theta_zero_location("N") ax.set_theta_direction(-1) ax.set_ylim([0, np.deg2rad(40)]) ax.set_yticks([]) ax.set_xticks(np.linspace(0, 2 * np.pi, 8, endpoint=False)) ax.set_xticklabels([ r'$0^\circ$', r'$45^\circ$', r'$90^\circ$', r'$135^\circ$', r'$180^\circ$', r'$-135^\circ$', r'$-90^\circ$', r'$-45^\circ$' ]) ax.set_title("POL Response", fontsize=16) ax.tick_params(axis='both', which='major', labelsize=16) ax.tick_params(axis='both', which='minor', labelsize=16) ax = plt.subplot(1, 4, 2, polar=True) ax.scatter(phi, theta, s=150, c=r_pol * gate_pol, marker='o', cmap="coolwarm", vmin=-1, vmax=1) ax.scatter(a, e, s=100, marker='o', edgecolor='black', facecolor='yellow') ax.scatter(phi_t + np.pi, theta_t, s=200, marker='o', edgecolor='black', facecolor='yellowgreen') ax.set_theta_zero_location("N") ax.set_theta_direction(-1) ax.set_ylim([0, np.deg2rad(40)]) ax.set_yticks([]) ax.set_xticks(np.linspace(0, 2 * np.pi, 8, endpoint=False)) ax.set_xticklabels([ r'$0^\circ$', r'$45^\circ$', r'$90^\circ$', r'$135^\circ$', r'$180^\circ$', r'$-135^\circ$', r'$-90^\circ$', r'$-45^\circ$' ]) ax.set_title("Gated Response", fontsize=16) ax.tick_params(axis='both', which='major', labelsize=16) ax.tick_params(axis='both', which='minor', labelsize=16) ax = plt.subplot(1, 4, 3, polar=True) x = np.linspace(0, 2 * np.pi, 721) # CBL ax.fill_between(x, np.full_like(x, np.deg2rad(60)), np.full_like(x, np.deg2rad(90)), facecolor="C1", alpha=.5, label="CBL") ax.scatter(phi_cl1[:nb_cl1 / 2] - np.pi / 24, np.full(nb_cl1 / 2, np.deg2rad(75)), s=600, c=r_cl1[:nb_cl1 / 2], marker='o', edgecolor='red', cmap="coolwarm", vmin=-1, vmax=1) ax.scatter(phi_cl1[nb_cl1 / 2:] + np.pi / 24, np.full(nb_cl1 / 2, np.deg2rad(75)), s=600, c=r_cl1[nb_cl1 / 2:], marker='o', edgecolor='green', cmap="coolwarm", vmin=-1, vmax=1) for ii, pp in enumerate(phi_cl1[:nb_cl1 / 2] - np.pi / 24): ax.text(pp - np.pi / 20, np.deg2rad(75), "%d" % (ii + 1), ha="center", va="center", size=10, bbox=dict(boxstyle="circle", fc="w", ec="k")) for ii, pp in enumerate(phi_cl1[nb_cl1 / 2:] + np.pi / 24): ax.text(pp + np.pi / 20, np.deg2rad(75), "%d" % (ii + 9), ha="center", va="center", size=10, bbox=dict(boxstyle="circle", fc="w", ec="k")) # TB1 ax.fill_between(x, np.full_like(x, np.deg2rad(30)), np.full_like(x, np.deg2rad(60)), facecolor="C2", alpha=.5, label="TB1") ax.scatter(phi_tb1, np.full_like(phi_tb1, np.deg2rad(45)), s=600, c=r_tb1, marker='o', edgecolor='blue', cmap="coolwarm", vmin=-1, vmax=1) for ii, pp in enumerate(phi_tb1): ax.text(pp, np.deg2rad(35), "%d" % (ii + 1), ha="center", va="center", size=10, bbox=dict(boxstyle="circle", fc="w", ec="k")) ax.arrow(pp, np.deg2rad(35), 0, np.deg2rad(10), fc='k', ec='k', head_width=.1, overhang=.3) # Sun position ax.scatter(a, e, s=500, marker='o', edgecolor='black', facecolor='yellow') # Decoded TB1 # ax.plot([0, a_pred], [0, e_pred], 'k--', lw=1) ax.plot([0, a_pred], [0, np.pi / 2], 'k--', lw=1) ax.arrow(a_pred, 0, 0, np.deg2rad(20), fc='k', ec='k', head_width=.3, head_length=.2, overhang=.3) ax.legend(ncol=2, loc=(-.55, -.1), fontsize=16) ax.set_theta_zero_location("N") ax.set_theta_direction(-1) ax.set_ylim([0, np.pi / 2]) ax.set_yticks([]) ax.set_xticks([]) ax.set_title("Sensor Response", fontsize=16) plt.subplots_adjust(left=.02, bottom=.12, right=.98, top=.88) ax.tick_params(axis='both', which='major', labelsize=16) ax.tick_params(axis='both', which='minor', labelsize=16) plt.show() d_deg = np.rad2deg(d) if show_structure: plt.figure("sensor-structure", figsize=(4.5, 4.5)) ax = plt.subplot(111, polar=True) ax.scatter(phi, theta, s=150, c="black", marker='o') ax.set_theta_zero_location("N") ax.set_theta_direction(-1) ax.set_ylim([0, np.deg2rad(50)]) ax.set_yticks([]) ax.set_xticks( np.linspace(-3 * np.pi / 4, 5 * np.pi / 4, 8, endpoint=False)) ax.set_title("POL Response") plt.show() return d_deg, d_eff, t, a_ret, tb1
def _fitness(theta, phi, alpha, w=None, samples=1000, tilt=False, error=azidist, noise=0., gate_shift=np.deg2rad(55.5), gate_order=7.5, activation="linear", return_mean=True): import matplotlib.pyplot as plt if tilt: angles = np.array([ [0., 0.], [np.pi/6, 0.], [np.pi/6, np.pi/4], [np.pi/6, 2*np.pi/4], [np.pi/6, 3*np.pi/4], [np.pi/6, 4*np.pi/4], [np.pi/6, 5*np.pi/4], [np.pi/6, 6*np.pi/4], [np.pi/6, 7*np.pi/4], [np.pi/3, 0.], [np.pi/3, np.pi/4], [np.pi/3, 2*np.pi/4], [np.pi/3, 3*np.pi/4], [np.pi/3, 4*np.pi/4], [np.pi/3, 5*np.pi/4], [np.pi/3, 6*np.pi/4], [np.pi/3, 7*np.pi/4] ]) # 17 if samples == 1000: samples /= 2 else: angles = np.array([[0., 0.]]) # 1 theta_s, phi_s = fibonacci_sphere(samples=samples, fov=161) phi_s = phi_s[theta_s <= np.pi/2] theta_s = theta_s[theta_s <= np.pi/2] samples = theta_s.size d = np.zeros((samples, angles.shape[0])) d_eff = np.zeros((samples, angles.shape[0])) nb_tl2, nb_tb1 = 16, 8 phi_tl2 = np.linspace(0., 4 * np.pi, nb_tl2, endpoint=False) # TL2 preference angles phi_tb1 = np.linspace(0., 2 * np.pi, nb_tb1, endpoint=False) # TB1 preference angles for j, (theta_t, phi_t) in enumerate(angles): theta_s_, phi_s_ = transtilt(theta_t, phi_t, theta=theta_s, phi=phi_s) theta_, phi_ = transtilt(theta_t, phi_t+np.pi, theta=theta, phi=phi) _, alpha_ = transtilt(theta_t, phi_t+np.pi, theta=np.pi/2, phi=alpha) if w is None or True: # Gate + Shift g = np.power(np.sqrt(1 - np.square( np.cos(theta + gate_shift) * np.cos(theta_t) + np.sin(theta + gate_shift) * np.sin(theta_t) * np.cos(phi_t - phi) # )), gate_order) )), 0) # alternative form (w/o shift) # g = np.power(np.sin(theta_ + shift), order) # dynamic gating # w_tl2 = 1. / 60. * np.cos(d_tl2) # w_tl2 = -1. / 60. * np.cos(phi_tl2[np.newaxis] - phi[:, np.newaxis]) * g[..., np.newaxis] # w_tb1 = float(nb_tb1) / float(nb_tl2) * np.sin(phi_tb1[np.newaxis] - phi_tl2[:, np.newaxis]) w = 8. / (2. * 60.) * np.sin(phi_tb1[np.newaxis] - phi[:, np.newaxis] - np.pi/2) * g[:, np.newaxis] for i, (e, a, e_org, a_org) in enumerate(zip(theta_s_, phi_s_, theta_s, phi_s)): _, dop, aop = SensorObjective.encode(e_org, a_org, theta_, phi_) # ele, azi = SensorObjective.decode(dop, aop, alpha_, w=w, noise=noise) r = SensorObjective.opticalencode(dop, aop, alpha, noise=noise) ele, azi = SensorObjective.decode(r, theta, phi, activation=activation, # w_tl2=w_tl2) w=w) d[i, j] = np.absolute(error(np.array([e, a]), np.array([ele, azi]))) # r = np.maximum(r*g, 0) r = r*g M = r.max() - r.min() P = np.power(10, M/2.) d_eff[i, j] = np.mean((P - 1.) / (P + 1.)) d_deg = np.rad2deg(d) # plt.figure("Tilts", figsize=(10, 15)) # for i, ang, dd in zip(range(angles.shape[0]), angles, d.T): # ax = plt.subplot2grid((5, 4), ((i-1) // 4, (i-1) % 4), polar=True) # ax.set_theta_zero_location("N") # ax.set_theta_direction(-1) # plt.scatter(phi_s, np.rad2deg(theta_s), marker=".", c=dd, cmap="Reds", vmin=0, vmax=np.pi/2) # plt.scatter(ang[1]+np.pi, np.rad2deg(ang[0]), marker="o", c="yellow", edgecolors="black") # plt.title(r"$\epsilon_t=%03d, \alpha_t=%03d$" % tuple(np.rad2deg(ang))) # plt.axis("off") # plt.subplot2grid((5, 4), (4, 0), colspan=3) # plt.imshow([np.arange(0, np.pi/2, np.pi/180)] * 3, cmap="Reds") # plt.yticks([]) # plt.xticks([0, 45, 89], [r"0", r"$\frac{\pi}{4}$", r"$\geq\frac{\pi}{2}$"]) # plt.show() # plt.figure("Tilts", figsize=(10, 3)) # for i, ang, dd in zip(range(3), angles[[0, 1, 9]], d.T[[0, 1, 9]]): # ax = plt.subplot2grid((1, 10), (0, i * 3), colspan=3, polar=True) # ax.set_theta_zero_location("N") # ax.set_theta_direction(-1) # plt.scatter(phi_s, np.rad2deg(theta_s), marker="o", c=dd, cmap="Reds", vmin=0, vmax=np.pi/2) # plt.scatter(ang[1]+np.pi, np.rad2deg(ang[0]), marker="o", c="yellowgreen", edgecolors="black") # plt.text(-np.deg2rad(50), 145, ["A.", "B.", "C."][i], fontsize=12) # plt.axis("off") # plt.subplot2grid((3, 10), (1, 9)) # plt.imshow(np.array([np.arange(0, np.pi/2, np.pi/180)] * 10).T, cmap="Reds") # plt.xticks([]) # plt.yticks([0, 45, 89], [r"0", r"$\frac{\pi}{4}$", r"$\geq\frac{\pi}{2}$"]) # plt.show() # plt.figure("cost-function") # wd = np.bartlett(10) # wd /= wd.sum() # d_000 = np.convolve(wd, np.rad2deg(d[:, 0]), mode="same") # plt.plot(np.rad2deg(theta_s), d_000, label=r"$0^\circ$") # if angles.shape[0] > 1: # d_030 = np.convolve(wd, np.rad2deg(d[:, 1]), mode="same") # d_060 = np.convolve(wd, np.rad2deg(d[:, 9]), mode="same") # plt.plot(np.rad2deg(theta_s), d_030, label=r"$30^\circ$") # plt.plot(np.rad2deg(theta_s), d_060, label=r"$60^\circ$") # plt.legend() # plt.xlim([0, 90]) # plt.ylim([0, 90]) # plt.xlabel(r"sun elevation ($^\circ$)") # plt.ylabel(r"cost ($^\circ$)") # plt.show() if return_mean: return d_deg.mean() else: return d_deg, d_eff, theta_s