def single_helix(ant1, ant2, source): ra = np.radians(source.ra_angle) dec = np.radians(source.dec_angle) A_full = A_tensor(ra, dec) s_axis = [] f_layer = [] for ni in nu_rl: nu = nu_axis[ni] I = vis.get_I(source, nu) s = np.array([complex(I), 0, 0, 0]) A_n = A_full[ni] t_layer = [] for ti in t_rl: t = t_axis[ti] A_t = A_n[ti] r = rot.radec2lm(ra, dec, ra0=t) phi = ant.phase_factor(ant1, ant2, r, nu) next_vista = np.dot(np.dot(A_t, s), phi) t_layer.append(next_vista) f_layer.append(np.array(t_layer)) return np.array(f_layer)
def visibility(ant1, ant2, source, nu=151e6, time=None): """ Visibility integrand evaluated for a single source. @ant1 and @ant2 are indices of antannae, to specify a baseline @source is a GLEAM catalog object (see catalog.py for specifications) @nu : signal frequency [MHz] @time : local sidereal time [float, radians] default: None corresponds to run-time LST. """ I = get_I(source, nu) s = np.array([complex(I), 0, 0, 0]) ra = np.radians(source.ra_angle) dec = np.radians(source.dec_angle) A = stokes.create_A(ra=ra, dec=dec, lst=time, nu=nu, radians=True) r = rot.radec2lm(ra, dec, ra0=time) phi = ant.phase_factor(ant1, ant2, r, nu) malformed_result = np.dot(np.dot(A, s), phi) # Hack to get rid of extra array shell surrounding answer return malformed_result[:, 0]
def fwhm(ant1, ant2, source, nu, max_): """ Full width at half maximum """ ra = np.radians(source.ra_angle) dec = np.radians(source.dec_angle) A_n = A_tensor(ra, dec, nu) s_axis = [] f_layer = [] I = vis.get_I(source, nu) s = np.array([complex(I), 0, 0, 0]) t_layer = [] vnorm1 = None vnorm2 = None for ti in t_rl: t = t_axis[ti] A_t = A_n[ti] r = rot.radec2lm(ra, dec, ra0=t) phi = ant.phase_factor(ant1, ant2, r, nu) next_vista = np.dot(np.dot(A_t, s), phi) vis_norm = np.linalg.norm(next_vista) temp = vnorm2 vnorm2 = vis_norm vnorm1 = temp if vnorm1 is None: continue elif 2 * vnorm2 >= max_ and 2 * vnorm1 <= max_: print("Rise time:", t, "radians") print("(" + rad_to_time(t) + ")\n") elif 2 * vnorm2 <= max_ and 2 * vnorm1 >= max_: print("Set time:", t) print("(" + rad_to_time(t) + ")")
def picture_tensor(): raise NotImplementedError("Still processes just one source.") nu_axis = np.arange(50e6, 250e6 + MACRO_EPSILON, 1e6) A = f_only() print("\nFinished building partial A-tensor.\n") r = rot.radec2lm(ra, dec, ra0=lst0) s_axis = [] for ni in range(len(nu_axis)): nu = nu_axis[ni] I = vis.get_I(source, nu) s_axis.append(np.array([complex(I), 0, 0, 0])) print("\nFinished building s-vector vector.\n") ants = ant.ant_pos.copy() outer_ants = ants.copy() for outer_ant in outer_ants.keys(): inner_ants = ants.copy() del inner_ants[outer_ant] for inner_ant in inner_ants.keys(): phi = ant.phase_factor(outer_ant, inner_ant, r, nu) next_vt = [] for ni in range(len(nu_axis)): s = s_axis[ni] A_n = A[ni] next_vista = np.dot(np.dot(A_n, s), phi) next_vt.append(next_vista) inner_ants[inner_ant] = next_vt outer_ants[outer_ant] = inner_ants return outer_ants
def vmax(ant1, ant2, source, nu): """ Maximum visibility. For use with fwhm """ max_ = float("-inf") ra = np.radians(source.ra_angle) dec = np.radians(source.dec_angle) A_n = A_tensor(ra, dec, nu) s_axis = [] f_layer = [] I = vis.get_I(source, nu) s = np.array([complex(I), 0, 0, 0]) t_layer = [] for ti in t_rl: t = t_axis[ti] A_t = A_n[ti] r = rot.radec2lm(ra, dec, ra0=t) phi = ant.phase_factor(ant1, ant2, r, nu) next_vista = np.dot(np.dot(A_t, s), phi) vis_norm = np.linalg.norm(next_vista) if (vis_norm > max_): max_ = vis_norm return max_
def single_wedge_spot(source, ti): ra = np.radians(source.ra_angle) dec = np.radians(source.dec_angle) A_full = A_tensor(ra, dec) s_axis = [] for ni in nu_rl: nu = nu_axis[ni] I = vis.get_I(source, nu) s_axis.append(np.array([complex(I), 0, 0, 0])) kill_timer = 0 for outer_ant in outer_ants.keys(): inner_ants = outer_ants.copy() del inner_ants[outer_ant] for inner_ant in inner_ants.keys(): f_layer = [] for ni in nu_rl: nu = nu_axis[ni] s = s_axis[ni] A_n = A_full[ni] t_layer = [] t = t_axis[ti[kill_timer]] r = rot.radec2lm(ra, dec, ra0=t) phi = ant.phase_factor(outer_ant, inner_ant, r, nu) A_t = A_n[ti[kill_timer]] Jonesed = np.dot(A_t, s) next_vista = np.dot(Jonesed, phi) f_layer.append(np.array([Jonesed, next_vista])) f_layer = np.array(f_layer) inner_ants[inner_ant] = f_layer """ * Check the s input vector * Multiply s by the Jones matrix * Output visibilities """ ad_hoc_labels = ["I", "Q", "U", "V"] log_enabled = False x = nu_axis / 1e6 s_axis = np.array(s_axis) if log_enabled: s_plot = np.log10(s_axis[:, 0]) else: s_plot = s_axis[:, 0] # Jonesed for i in range(4): y = f_layer[:, 0, i] if log_enabled: plt.plot(x, np.log10(np.abs(y)), label=ad_hoc_labels[i]) else: plt.plot(x, np.abs(y), label=ad_hoc_labels[i]) """ plt.plot( x, s_plot, label="s vector, I" ) """ plt.legend(loc='upper right') plt.title( "Wedge generator, no phase factor. Antennae: " + \ str(outer_ant) + " to " + \ str(inner_ant) ) plt.xlabel("Frequency [MHz]") plt.ylabel("Brightness Magnitude [Jy]") plt.show() # Jonesed for i in range(4): y = f_layer[:, 1, i] if log_enabled: plt.plot(x, np.log10(np.abs(y)), label=ad_hoc_labels[i]) else: plt.plot(x, np.abs(y), label=ad_hoc_labels[i]) """ * plot A at the point of interest * do Q/I, U/I ratios * plot A multiplied by s """ """ plt.plot( x, s_plot, label="s vector, I" ) """ plt.legend(loc='upper right') plt.title( "Wedge generator, with phase factor. Antennae: " + \ str(outer_ant) + " to " + \ str(inner_ant) ) plt.xlabel("Frequency [MHz]") plt.ylabel("Brightness Magnitude [Jy]") plt.show() kill_timer += 1 if kill_timer > 3: return outer_ants[outer_ant] = inner_ants return outer_ants
def single_wedge_readout(source): """ Return the time indices at which the source is most visible over the first three hypothetical plots. Chiefly for use with the function single_wedge_spot """ ra = np.radians(source.ra_angle) dec = np.radians(source.dec_angle) A_full = A_tensor(ra, dec) s_axis = [] kill_timer = 0 for ni in nu_rl: nu = nu_axis[ni] I = vis.get_I(source, nu) s_axis.append(np.array([complex(I), 0, 0, 0])) for outer_ant in outer_ants.keys(): inner_ants = outer_ants.copy() del inner_ants[outer_ant] for inner_ant in inner_ants.keys(): f_layer = [] for ni in nu_rl: nu = nu_axis[ni] s = s_axis[ni] A_n = A_full[ni] t_layer = [] for ti in t_rl: t = t_axis[ti] r = rot.radec2lm(ra, dec, ra0=t) phi = ant.phase_factor(outer_ant, inner_ant, r, nu) A_t = A_n[ti] next_vista = np.dot(np.dot(A_t, s), phi) t_layer.append(next_vista) t_layer = np.array(t_layer) f_layer.append(t_layer) inner_ants[inner_ant] = np.array(f_layer) f_layer = np.array(f_layer) max_ti = 0 max_V = float('-inf') for ti in range(len(f_layer[0])): if f_layer[0, ti, 0] > max_V: max_ti = ti max_V = f_layer[0, ti, 0] print(max_ti) kill_timer += 1 if kill_timer > 3: return outer_ants[outer_ant] = inner_ants return outer_ants
def single_wedge(source, ignore_I=False, gamma=None): ra = np.radians(source.ra_angle) dec = np.radians(source.dec_angle) A_full = A_tensor(ra, dec) s_axis = [] for ni in nu_rl: nu = nu_axis[ni] I = vis.get_I(source, nu) Q = U = V = 0 if gamma is not None: RM = sample_RM() polarization = polar_unit * RM / nu**2 Q = gamma * I * np.cos(polarization) U = gamma * I * np.sin(polarization) if ignore_I: I = 0 # important to do this here rather than earlier s_axis.append( np.array([complex(I), complex(Q), complex(U), complex(V)])) for outer_ant in outer_ants.keys(): inner_ants = outer_ants.copy() del inner_ants[outer_ant] for inner_ant in inner_ants.keys(): f_layer = [] for ni in nu_rl: nu = nu_axis[ni] s = s_axis[ni] A_n = A_full[ni] t_layer = [] for ti in t_rl: t = t_axis[ti] r = rot.radec2lm(ra, dec, ra0=t) phi = ant.phase_factor(outer_ant, inner_ant, r, nu) A_t = A_n[ti] next_vista = np.dot(np.dot(A_t, s), phi) t_layer.append(next_vista) t_layer = np.array(t_layer) f_layer.append(t_layer) f_layer = np.array(f_layer) inner_ants[inner_ant] = f_layer outer_ants[outer_ant] = inner_ants return outer_ants
def new_sources_over_time(ant1, ant2, list_sources=None, start=0, end=2 / 3 * np.pi, interval=np.pi / 72, nu=151e6, interpolator=None): """ Return an array containing the visibilities at different points of time. @ant1 and @ant2 are indices of antennae, to specify a baseline. @list_sources is an array of GLEAM catalog objects (see catalog.py for specifications) default value translates to the entire downloaded segment of the catalog. @start: starting LST of integration [float, radians] default: 0 hours (cold patch) @end: terminal LST of integration [float, radians] default: 8 hours = 2/3 pi (cold patch) @interval: integration window width [float, radians] default: 10 minutes = np.pi / 72 @nu frequency in Hertz """ if interpolator is None: raise NotImplementedError("We are" + \ " currently hard-coding interpolators.") if list_sources is None: # make a copy to ensure write safety list_sources = catalog.obj_catalog.copy() # If the user has entered a single source directly, # we can automatically standardize the formatting # by placing it by itself in a list if type(list_sources) != list: list_sources = [list_sources] list_lst = [] lst = start while lst <= end: list_lst.append(lst) lst += interval list_lst = np.array(list_lst) list_visibilities = np.zeros((len(list_lst), 4), dtype=np.complex128) for source in list_sources: # establish values common to all visibility calculations I = get_I(source, nu) s = np.array([complex(I), 0, 0, 0]) ra = np.radians(source.ra_angle) dec = np.radians(source.dec_angle) for k in range(len(list_lst)): curr_lst = list_lst[k] # no input for latitude. Code is no longer general :( # no input for radians either. We have to rely on the user # to provide a radian-based interpolator. az, alt = rot.eq_to_topo(ra, dec, lst=curr_lst, radians=True) A = interpolator(az, alt) r = rot.radec2lm(ra, dec, ra0=curr_lst) phi = ant.phase_factor(ant1, ant2, r, nu) malformed_result = np.dot(np.dot(A, s), phi) list_visibilities[k] += malformed_result # perhaps not necessary. Better safe than sorry: return list_lst, np.array(list_visibilities)
def cold_tensor(label, ant1, ant2, start_index=0, end_index=3871, save_interval=4): """ Returns a giant block of visibility sums. Specifications: cold patch: 0 to 8 hours LST in 30 second increments full frequency range: 50 to 250 MHz in 1 MHz increments. The first return value is the x-axis, also known as the first index. It describes the frequency used for that row. The second return value is the y-axis, also known as the second index. It describes the time used for that column. The third return value is the z-axis, also known as the data block. It describes the summed visibilities of all ~3000 catalog objects for a given time and frequency. """ global nu_axis global t_axis print("Unix time upon function call:", str(time.time())) nu_axis = np.arange(50e6, 250e6 + MACRO_EPSILON, 1e6) t_axis = np.arange(0, 2 * np.pi / 3 + MACRO_EPSILON, np.pi / 1440) v_tensor = np.zeros((len(nu_axis), len(t_axis), 4), dtype=np.complex128) cleaned = demo.cleaned_list() percent_interval = 100 / (end_index - start_index + 1) percent = 0 unsaved_counter = 0 i = start_index while i < end_index and i < len(cleaned): next_vt = [] source = cleaned[i] raI = np.radians(source.ra_angle) decI = np.radians(source.dec_angle) AI = A_tensor(raI, decI) for ni in range(len(nu_axis)): nu = nu_axis[ni] next_vt.append([]) I = vis.get_I(source, nu) s = np.array([complex(I), 0, 0, 0]) A_n = AI[ni] for ti in range(len(t_axis)): t = t_axis[ti] A = A_n[ti] r = rot.radec2lm(raI, decI, ra0=t) phi = ant.phase_factor(ant1, ant2, r, nu) next_vista = np.dot(np.dot(A, s), phi) next_vt[len(next_vt) - 1].append(next_vista) v_tensor += np.array(next_vt) percent += percent_interval percent_status = str(np.around(percent, 4)) print("Visibility tensor: " + percent_status + \ "% complete (finished i=" + str(i) + ").") unsaved_counter += 1 if unsaved_counter > save_interval: np.savez("backup_" + label, na=nu_axis, ta=t_axis, vt=v_tensor, dying_index=np.array(i)) unsaved_counter = 0 i += 1 np.savez("backup_" + label, na=nu_axis, ta=t_axis, vt=v_tensor, dying_index=np.array(-1))