def jones(self, ra, dec, freq): alt, az = radec_to_altaz(ra, dec, self.time, self.location) return pb.MWA_Tile_full_EE(np.pi / 2 - alt, az, freq, delays=self.delays, jones=True)
def power(self, ras, decs, freq, time=None): if time is None: time = self.time alt, az = radec_to_altaz(ras, decs, time, self.location) with threadlock: return pb.MWA_Tile_full_EE(np.pi / 2 - alt, az, freq, delays=self.delays, power=True)
def jones(self, ras, decs, freq, time=None): if time is None: time = self.time t0 = tm.time() alt, az = radec_to_altaz(ras, decs, time, self.location) print("Altaz elapsed: %g" % (tm.time() - t0)) with threadlock: return pb.MWA_Tile_full_EE(np.pi / 2 - alt, az, freq, delays=self.delays, jones=True)
def get_beam_weights(ras=None, decs=None): '''Takes ra and dec coords, and works out the overall beam power at that location using the 2016 spherical harmonic beam code from mwapy''' mwatime = Time(obsID, format='gps', scale='utc') coords = SkyCoord(ra=ras, dec=decs, equinox='J2000', unit=(astropy.units.hour, astropy.units.deg)) coords.location = MWAPOS coords.obstime = mwatime coords_prec = coords.transform_to('altaz') za_rad = math.pi - coords_prec.alt.rad # Need zenith angle in radians, not altitude in radians az_rad = coords_prec.az.rad # go from altitude to zenith angle # theta = numpy.radians((90 - Alt)) # phi = numpy.radians(Az) ##For each component, work out it's position, convolve with the beam and sum for the source #for ra,dec in zip(source.ras,source.decs): ##HA=LST-RA in def of ephem_utils.py # has = LST - array(ras)*15.0 ##RTS stores things in hours ##Convert to zenith angle, azmuth in rad # Az,Alt=ephem_utils.eq2horz(has,array(decs),mwa_lat) # za=(90-Alt)*pi/180 # az=Az*pi/180 XX, YY = primary_beam.MWA_Tile_full_EE([za_rad], [az_rad], freq=freqcent, delays=delays, zenithnorm=True, power=True, interp=False) beam_weights = (XX[0] + YY[0]) / 2.0 ##OLd way of combining XX and YY - end up with beam values greater than 1, not good! #beam_weights = n.sqrt(XX[0]**2+YY[0]**2) return beam_weights
def get_beam_weights(ras=None,decs=None,LST=None, mwa_lat=None, freqcent=None,delays=None): '''Takes ra and dec coords, and works out the overall beam power at that location using the 2016 spherical harmonic beam code from mwapy''' ##For each component, work out it's position, convolve with the beam and sum for the source #for ra,dec in zip(source.ras,source.decs): ##HA=LST-RA in def of ephem_utils.py has = LST - array(ras)*15.0 ##RTS stores things in hours ##Convert to zenith angle, azmuth in rad Az,Alt=eq2horz(has,array(decs),mwa_lat) za=(90-Alt)*pi/180 az=Az*pi/180 XX,YY = primary_beam.MWA_Tile_full_EE([za], [az], freq=freqcent, delays=delays, zenithnorm=True, power=True, interp=False) beam_weights = (XX[0]+YY[0]) / 2.0 ##OLd way of combining XX and YY - end up with beam values greater than 1, not good! #beam_weights = sqrt(XX[0]**2+YY[0]**2) return beam_weights
def get_beam_power_over_time(beam_meta_data, names_ra_dec, dt=296, centeronly=True, verbose=False, option='analytic', degrees=False, start_time=0): """ Calulates the power (gain at coordinate/gain at zenith) for each source over time. get_beam_power_over_time(beam_meta_data, names_ra_dec, dt=296, centeronly=True, verbose=False, option = 'analytic') Args: beam_meta_data: [obsid,ra, dec, time, delays,centrefreq, channels] obsid metadata obtained from meta.get_common_obs_metadata names_ra_dec: and array in the format [[source_name, RAJ, DecJ]] dt: time step in seconds for power calculations (default 296) centeronly: only calculates for the centre frequency (default True) verbose: prints extra data to (default False) option: primary beam model [analytic, advanced, full_EE] start_time: the time in seconds from the begining of the observation to start calculating at """ obsid, _, _, time, delays, centrefreq, channels = beam_meta_data names_ra_dec = np.array(names_ra_dec) logger.info("Calculating beam power for OBS ID: {0}".format(obsid)) starttimes = np.arange(start_time, time + start_time, dt) stoptimes = starttimes + dt stoptimes[stoptimes > time] = time Ntimes = len(starttimes) midtimes = float(obsid) + 0.5 * (starttimes + stoptimes) if not centeronly: PowersX = np.zeros((len(names_ra_dec), Ntimes, len(channels))) PowersY = np.zeros((len(names_ra_dec), Ntimes, len(channels))) # in Hz frequencies = np.array(channels) * 1.28e6 else: PowersX = np.zeros((len(names_ra_dec), Ntimes, 1)) PowersY = np.zeros((len(names_ra_dec), Ntimes, 1)) if centrefreq > 1e6: logger.warning( "centrefreq is greater than 1e6, assuming input with units of Hz." ) frequencies = np.array([centrefreq]) else: frequencies = np.array([centrefreq]) * 1e6 if degrees: RAs = np.array(names_ra_dec[:, 1], dtype=float) Decs = np.array(names_ra_dec[:, 2], dtype=float) else: RAs, Decs = sex2deg(names_ra_dec[:, 1], names_ra_dec[:, 2]) if len(RAs) == 0: sys.stderr.write('Must supply >=1 source positions\n') return None if not len(RAs) == len(Decs): sys.stderr.write('Must supply equal numbers of RAs and Decs\n') return None if verbose is False: #Supress print statements of the primary beam model functions sys.stdout = open(os.devnull, 'w') for itime in range(Ntimes): # this differ's from the previous ephem_utils method by 0.1 degrees _, Azs, Zas = mwa_alt_az_za(midtimes[itime], ra=RAs, dec=Decs, degrees=True) # go from altitude to zenith angle theta = np.radians(Zas) phi = np.radians(Azs) for ifreq in range(len(frequencies)): #Decide on beam model if option == 'analytic': rX, rY = primary_beam.MWA_Tile_analytic( theta, phi, freq=frequencies[ifreq], delays=delays, zenithnorm=True, power=True) elif option == 'advanced': rX, rY = primary_beam.MWA_Tile_advanced( theta, phi, freq=frequencies[ifreq], delays=delays, zenithnorm=True, power=True) elif option == 'full_EE': rX, rY = primary_beam.MWA_Tile_full_EE(theta, phi, freq=frequencies[ifreq], delays=delays, zenithnorm=True, power=True) PowersX[:, itime, ifreq] = rX PowersY[:, itime, ifreq] = rY if verbose is False: sys.stdout = sys.__stdout__ Powers = 0.5 * (PowersX + PowersY) return Powers
print "Number of sources above the horizon:", len(Alt0_samp) # Creating new sampled table. Sky_Mod = temp_table[Alt0 > 0.0] #start1 = time.time() #""" ################################################################################ # Thresholding the apparent brightest 1500 sources in the OBSID ################################################################################ #""" # Determining the beam power at the central frequency for each source above the horizon. beam_power = pb.MWA_Tile_full_EE(Zen0_samp, Az0_samp, cent_freq, delays_flt) #end1 = time.time() # Splitting the xx and yy cross correlation power components beam_power_XX = np.array(beam_power[0]) beam_power_YY = np.array(beam_power[1]) # Determining the average power or stokes I power. beamvalue = (beam_power_XX + beam_power_YY) / 2 S300_fit = Sky_Mod.field("Fint300") """ # Replace this remaping section with JOOF.py log-poly map
def calc_jones(az, za, target_freq_Hz=205e6): za_rad = za * math.pi / 180.0 az_rad = az * math.pi / 180.0 za_rad = np.array([[za_rad]]) az_rad = np.array([[az_rad]]) gridpoint = mwa_sweet_spots.find_closest_gridpoint(az, za) print("Az = %.2f [deg], za = %.2f [deg], gridpoint = %d" % (az, za, gridpoint[0])) delays = gridpoint[4] delays = np.vstack((delays, delays)) print(delays) print("-----------") Jones_FullEE = primary_beam.MWA_Tile_full_EE(za_rad, az_rad, target_freq_Hz, delays=delays, zenithnorm=True, jones=True, interp=True) # swap axis to have Jones martix in the 1st Jones_FullEE_swap = np.swapaxes(np.swapaxes(Jones_FullEE, 0, 2), 1, 3) # TEST if equivalent to : Jones_FullEE_2D = Jones_FullEE_swap[:, :, 0, 0] # Jones_FullEE_2D = np.array([ [Jones_FullEE_swap[0, 0][0][0], Jones_FullEE_swap[0, 1][0][0]] , [Jones_FullEE_swap[1, 0][0][0], Jones_FullEE_swap[1, 1][0][0]] ]) print("Jones FullEE:") print("----------------------") print(Jones_FullEE) print("----------------------") print(Jones_FullEE_2D) print("----------------------") beams = {} beams['XX'], beams['YY'] = primary_beam.MWA_Tile_full_EE(za_rad, az_rad, target_freq_Hz, delays=delays, zenithnorm=True, power=True) print("Beams power = %.4f / %.4f" % (beams['XX'], beams['YY'])) # Average Embeded Element model: print("size(delays) = %d" % np.size(delays)) Jones_AEE = primary_beam.MWA_Tile_advanced(za_rad, az_rad, target_freq_Hz, delays=delays, jones=True) # Jones_AEE = primary_beam.MWA_Tile_advanced(np.array([[0]]), np.array([[0]]), target_freq_Hz,delays=delays, zenithnorm=True, jones=True) Jones_AEE_swap = np.swapaxes(np.swapaxes(Jones_AEE, 0, 2), 1, 3) Jones_AEE_2D = Jones_AEE_swap[:, :, 0, 0] # Jones_AEE_2D = np.array([ [Jones_AEE_swap[0, 0][0][0], Jones_AEE_swap[0, 1][0][0]], [Jones_AEE_swap[1, 0][0][0], Jones_AEE_swap[1, 1][0][0]] ]) print("----------------------") print("Jones AEE:") print("----------------------") print(Jones_AEE) print("----------------------") print(Jones_AEE_2D) print("----------------------") Jones_Anal = primary_beam.MWA_Tile_analytic(za_rad, az_rad, target_freq_Hz, delays=delays, zenithnorm=True, jones=True) Jones_Anal_swap = np.swapaxes(np.swapaxes(Jones_Anal, 0, 2), 1, 3) Jones_Anal_2D = Jones_Anal_swap[:, :, 0, 0] print("---------------------- COMPARISON OF JONES MATRICES FEE vs. AEE ----------------------") print("Jones FullEE:") print("----------------------") print(Jones_FullEE_2D) print("----------------------") print() print("Jones AEE:") print("----------------------") print(Jones_AEE_2D) print("----------------------") print() print("----------------------") print("Jones Analytic:") print("----------------------") print(Jones_Anal_2D) print("----------------------") return (Jones_FullEE_2D, Jones_AEE_2D, Jones_Anal_2D)
def calc_ratio(dec, target_freq_Hz, gridpoint): za = dec + 26.7 az = 0 print("\n\n\n\n") print("################################# DEC = %.2f #################################" % dec) za_rad = za * math.pi / 180.0 az_rad = az * math.pi / 180.0 za_rad = np.array([[za_rad]]) az_rad = np.array([[az_rad]]) # non-realistic scenario - I am ~tracking the source with the closest sweetspot - whereas I should be staying at the same sweetspot # gridpoint=find_closest_gridpoint(za) # print("dec=%.4f [deg] -> za=%.4f [deg] - %s" % (dec, za, gridpoint)) delays = gridpoint[4] delays = np.vstack((delays, delays)) print(delays) print("-----------") Jones_FullEE = primary_beam.MWA_Tile_full_EE(za_rad, az_rad, target_freq_Hz, delays=delays, zenithnorm=True, jones=True, interp=True) # swap axis to have Jones martix in the 1st Jones_FullEE_swap = np.swapaxes(np.swapaxes(Jones_FullEE, 0, 2), 1, 3) # TEST if equivalent to : Jones_FullEE_2D = Jones_FullEE_swap[:, :, 0, 0] # Jones_FullEE_2D = np.array([ [Jones_FullEE_swap[0, 0][0][0], Jones_FullEE_swap[0, 1][0][0]], [Jones_FullEE_swap[1, 0][0][0], Jones_FullEE_swap[1, 1][0][0]] ]) print("Jones FullEE:") print("----------------------") print(Jones_FullEE) print("----------------------") print(Jones_FullEE_2D) print("----------------------") # Average Embeded Element model: print("size(delays) = %d" % np.size(delays)) Jones_AEE = primary_beam.MWA_Tile_advanced(za_rad, az_rad, target_freq_Hz, delays=delays, jones=True) # Jones_AEE = primary_beam.MWA_Tile_advanced(np.array([[0]]), np.array([[0]]), target_freq_Hz, delays=delays, zenithnorm=True, jones=True) Jones_AEE_swap = np.swapaxes(np.swapaxes(Jones_AEE, 0, 2), 1, 3) Jones_AEE_2D = Jones_AEE_swap[:, :, 0, 0] # Jones_AEE_2D = np.array([ [Jones_AEE_swap[0, 0][0][0], Jones_AEE_swap[0, 1][0][0]], [Jones_AEE_swap[1, 0][0][0], Jones_AEE_swap[1, 1][0][0]] ]) print("----------------------") print("Jones AEE:") print("----------------------") print(Jones_AEE) print("----------------------") print(Jones_AEE_2D) print("----------------------") # Analytical Model: # beams = {} # beams['XX'], beams['YY'] = primary_beam.MWA_Tile_analytic(za_rad, az_rad, target_freq_Hz, delays=delays, zenithnorm=True, jones=True) Jones_Anal = primary_beam.MWA_Tile_analytic(za_rad, az_rad, target_freq_Hz, delays=delays, zenithnorm=True, jones=True) Jones_Anal_swap = np.swapaxes(np.swapaxes(Jones_Anal, 0, 2), 1, 3) Jones_Anal_2D = Jones_Anal_swap[:, :, 0, 0] # Jones_Anal_2D = np.array([ [Jones_Anal_swap[0, 0][0][0], Jones_Anal_swap[0, 1][0][0]] , [Jones_Anal_swap[1, 0][0][0],Jones_Anal_swap[1, 1][0][0]] ]) print("----------------------") print("Jones Analytic:") print("----------------------") print(Jones_Anal) print("----------------------") print(Jones_Anal_2D) print("----------------------") print("TEST:") print("----------------------") print("%.8f %.8f" % (Jones_Anal_2D[0, 0], Jones_Anal_2D[0, 1])) print("%.8f %.8f" % (Jones_Anal_2D[1, 0], Jones_Anal_2D[1, 1])) print("----------------------") # Use Jones_FullEE_2D as REAL sky and then ... B_sky = np.array([[1, 0], [0, 1]]) Jones_FullEE_2D_H = np.transpose(Jones_FullEE_2D.conj()) B_app = np.dot(Jones_FullEE_2D, np.dot(B_sky, Jones_FullEE_2D_H)) # E x B x E^H # test the procedure itself: Jones_FullEE_2D_H_Inv = inv2x2(Jones_FullEE_2D_H) Jones_FullEE_2D_Inv = inv2x2(Jones_FullEE_2D) B_sky_cal = np.dot(Jones_FullEE_2D_Inv, np.dot(B_app, Jones_FullEE_2D_H_Inv)) print(B_sky) print("Recovered using FullEE model:") print(B_sky_cal) # calibrate back using AEE model : # Jones_AEE_2D=Jones_Anal_2D # overwrite Jones_AEE_2D with Analytic to use it for calibration Jones_AEE_2D_H = np.transpose(Jones_AEE_2D.conj()) Jones_AEE_2D_H_Inv = inv2x2(Jones_AEE_2D_H) Jones_AEE_2D_Inv = inv2x2(Jones_AEE_2D) B_sky_cal = np.dot(Jones_AEE_2D_Inv, np.dot(B_app, Jones_AEE_2D_H_Inv)) print("Recovered using AEE model:") print(B_sky_cal) # I_cal = B_sky_cal[0, 0] + B_sky_cal[1, 1] # print "FINAL : %.8f ratio = %.8f / 2 = %.8f" % (dec,abs(I_cal),(abs(I_cal)/2.00)) # ratio = abs(B_sky_cal[0][0] / B_sky_cal[1][1]) # FINAL VALUES for the paper to compare with Figure 4 in GLEAM paper : ratio_ms = B_sky_cal[0][0] / B_sky_cal[1][1] gleam_ratio = ratio_ms gleam_XX = B_sky_cal[0][0] gleam_YY = B_sky_cal[1][1] # gleam_q_leakage = (B_sky_cal[0][0] - B_sky_cal[1][1]) / (B_sky_cal[0][0] + B_sky_cal[1][1]) print("DEBUG (DEC = %.2f deg) : GLEAM-ratio = %.4f = (%s / %s)" % (dec, gleam_ratio, gleam_XX, gleam_YY)) return (gleam_ratio.real, gleam_XX, gleam_YY)
def main(): parser = argparse.ArgumentParser() parser.add_argument('--ms', help="The measurement set from which to peel") parser.add_argument('--meta', help="The observation metafits file") parser.add_argument('--model', help="The skymodel to peel, in aoskymodel 1.1 format") parser.add_argument('--aegean', help="Aegean CSV") parser.add_argument('--datacolumn', default='CORRECTED_DATA') parser.add_argument('--width', type=int, required=True) parser.add_argument('--passes', type=int, default=2) parser.add_argument('--minuv', type=float, default=0, help="Fit models only on baselines above this minimum uv distance (metres)") parser.add_argument('--workers', type=int, default=0) parser.add_argument('--threshold', type=float, default=0.8) args = parser.parse_args() metafits = getheader(args.meta) date = Time(metafits['DATE-OBS'], location=mwa_pb.config.MWAPOS) delays = [int(d) for d in metafits['DELAYS'].split(',')] delays = [delays, delays] # Shuts up mwa_pb location = mwa_pb.config.MWAPOS print("Observation date: ", date) print("Delays: ", delays) # Retrieve telescope position dm = measures() obs = table(args.ms + '/OBSERVATION', ack=False) if 'TELESCOPE_NAME' in obs.colnames(): names = obs.getcol('TELESCOPE_NAME') if len(names) == 1: obspos = dm.observatory(names[0]) dm.do_frame(obspos) else: print("Failed to work out the telescope name of this observation") exit(1) else: print("Measurement set did not provide the telescope name") exit(1) print("Observation taken using telescope %s" % names[0]) ms = table(args.ms, readonly=False, ack=False) freqs = table(args.ms + '/SPECTRAL_WINDOW', ack=False).getcell('CHAN_FREQ', 0) midfreq = (max(freqs) + min(freqs)) / 2 lambdas = speed_of_light / freqs ra0, dec0 = table(args.ms + '/FIELD', ack=False).getcell('PHASE_DIR', 0)[0] # Phase centre in radians chans, pols = ms.getcell(args.datacolumn, 0).shape print("There are %d channels" % chans) # Check whether width evenly divides the total channels if chans % args.width != 0: print("Width (%d) does not evenly divide channel number (%d)" % (args.width, chans)) exit(1) widefreqs = np.array([ np.mean(freqs[i:i+args.width]) for i in range(0, len(freqs), args.width) ]) widelambdas = speed_of_light / widefreqs antennas = table(args.ms + '/ANTENNA', ack=False).getcol('POSITION') antennas = dm.position( 'itrf', quantity(antennas.T[0], 'm'), quantity(antennas.T[1], 'm'), quantity(antennas.T[2], 'm'), ) # Create PEELED_DATA column if it does not exist if ('CORRECTED_DATA' not in ms.colnames()): print("Creating CORRECTED_DATA column...", end=" ") sys.stdout.flush() coldesc = ms.getcoldesc('DATA') coldesc['name'] = 'CORRECTED_DATA' ms.addcols(coldesc) peeled = ms.getcol(args.datacolumn) ms.putcol('CORRECTED_DATA', peeled) print("Done") # Load models if args.model: with open(args.model) as f: models = model_parser(f) comps = [c for m in models for c in m.components] elif args.aegean: with open(args.aegean) as f: comps = aegean_parser(f, midfreq) else: print("No model (--aegean or --model) specified", file=sys.stderr) exit(1) print("Initialised %d model sources" % len(comps)) # Calculate Jones matrices for each model component # JBeams[widefreq, component, row, col] JBeams = [] for widefreq in widefreqs: altaz = [radec_to_altaz(comp.ra, comp.dec, date, location) for comp in comps] altaz = np.array(zip(*altaz)) JBeam = pb.MWA_Tile_full_EE(np.pi/2 - altaz[0], altaz[1], widefreq, delays=delays, jones=True) JBeams.append(JBeam) sources = [] for i, comp in enumerate(comps): xx_fluxes = [] yy_fluxes = [] for j, widefreq in enumerate(widefreqs): stokes = comp.flux(widefreq) # Model flux per Stokes paramter # XX = I + V; XY = U + iV; YY = Q - iU; YY = I -Q linear = np.array([ [stokes[0] + stokes[3], stokes[2] + 1j * stokes[3]], [stokes[1] - 1j * stokes[2], stokes[0] - stokes[1]], ]) # apparent = JBeam x linear x (JBeam)^H ..... where H is the Hermitian transpose JBeam = JBeams[j][i] apparent = np.matmul(np.matmul(JBeam, linear), np.conj(JBeam.T)) # For now (FIX?) we just take the real part xx_fluxes.append(np.real(apparent[0, 0])) yy_fluxes.append(np.real(apparent[1, 1])) xx_fluxes, yy_fluxes = np.array(xx_fluxes), np.array(yy_fluxes) # Estimate initial parameters log_widefreqs = np.log(widefreqs) log_xx_fluxes = np.log(xx_fluxes) log_yy_fluxes = np.log(yy_fluxes) xx3 = np.polyfit(log_widefreqs, log_xx_fluxes, 0) yy3 = np.polyfit(log_widefreqs, log_yy_fluxes, 0) sources.append( #Point(0, 0, xx3, 0, 0, yy3, comp.ra, comp.dec), Gaussian(0, 0, xx3, 0, 0, yy3, 0.1, 0.1, 0, comp.ra, comp.dec), ) # Group sources by a spatial threshold threshold = (4 / 60) * np.pi / 180 partitions = spatial_partition(sources, threshold) # Read data minus flagged rows tbl = taql("select * from $ms where not FLAG_ROW") uvw = tbl.getcol('UVW') uvw.flags.writeable = False times = tbl.getcol('TIME_CENTROID') times.flags.writeable = False ant1 = tbl.getcol('ANTENNA1') ant1.flags.writeable = False ant2 = tbl.getcol('ANTENNA2') ant2.flags.writeable = False data = tbl.getcol(args.datacolumn)[:, :, [True, False, False, True]].copy() # Just XX, YY # Handle flags by setting entries that are flagged as NaN flags = tbl.getcol('FLAG')[:, :, [True, False, False, True]] data[flags] = np.nan # For some reason, it is necessary to rotate onto # the current phase direction. Somehow this makes future offsets # internally self-consistent. dm = measures() phasecentre = dm.direction( 'j2000', quantity(ra0, 'rad'), quantity(dec0, 'rad'), ) uvw, data = phase_rotate( uvw, times, data, ant1, ant2, obspos, phasecentre, antennas, speed_of_light / freqs, ) # tbl.putcol('UVW', uvw) # d = tbl.getcol('DATA') # d[:, :, [True, False, False, True]] = data # tbl.putcol('DATA', d) if args.workers > 0: pool = Pool(args.workers) for passno in range(args.passes): i = 0 # Order sources by apparent flux at midfreq partitions = sorted( partitions, reverse=True, key=lambda xs: sum([x.flux(midfreq) for x in xs]) ) print("Beginning pass %d... 0%%" % (passno + 1), end="") sys.stdout.flush() while i < len(partitions): # TODO: use prior partitions to estimate updated values for l,m of this partition # Find the next batch of partitions that are within some threshold # of the currently brightest partition due to process. fluxlimit = args.threshold * sum([ x.flux(midfreq) for x in partitions[i] ]) for n, partition in enumerate(partitions[i:] + [None]): if partition is None: break elif sum([x.flux(midfreq) for x in partition]) < fluxlimit: break batch = partitions[i:i+n] data.flags.writeable = False if args.workers: diffs = pool.imap_unordered( peel_star, zip( [uvw] * len(batch), [times] * len(batch), [data] * len(batch), [ant1] * len(batch), [ant2] * len(batch), batch, [antennas] * len(batch), [freqs] * len(batch), [obspos] * len(batch), [ra0] * len(batch), [dec0] * len(batch), [args] * len(batch), [passno] * len(batch), ) ) else: diffs = imap( peel, [uvw] * len(batch), [times] * len(batch), [data] * len(batch), [ant1] * len(batch), [ant2] * len(batch), batch, [antennas] * len(batch), [freqs] * len(batch), [obspos] * len(batch), [ra0] * len(batch), [dec0] * len(batch), [args] * len(batch), [passno] * len(batch), ) data.flags.writeable = True data = data.copy() # Avoid changing data for running threads for j, diff in enumerate(diffs): data += diff print("\b\b\b\b% 3d%%" % ((i + j + 1) / len(partitions) * 100), end="") sys.stdout.flush() i += n print("") print("\n Finishing peeling. Writing data back to disk...", end=" ") sys.stdout.flush() peeled = tbl.getcol(args.datacolumn) peeled[:, :, 0] = data[:, :, 0] peeled[:, :, 3] = data[:, :, 1] tbl.putcol('CORRECTED_DATA', peeled) ms.close() with open('peeled.reg', 'w') as f: to_ds9_regions(f, partitions) print("Done")
Vij = np.array([[data_yy, data_xy + 1j * data_xyi], [data_xy - 1j * data_xyi, data_xx]]) # delays = beam_tools.gridpoint2delays(gridpoint, os.path.join(MWAtools_pb_dir, 'MWA_sweet_spot_gridpoints.csv')) print("delays = %s , frequency = %.2f Hz" % (delays, target_freq_Hz)) sign_uv = 1 sign_q = 1 if model == 'full_EE' or model == '2016' or model == 'FEE' or model == 'Full_EE': logger.info("Correcting with full_EE(%s) model at frequency %.2f Hz" % (model, target_freq_Hz)) # print "DEBUG = %s" % (az) Jones = primary_beam.MWA_Tile_full_EE(za, az, target_freq_Hz, delays=delays, zenithnorm=options.zenithnorm, jones=True, interp=True) if options.wsclean_image: sign_uv = -1 elif model == 'avg_EE' or model == 'advanced' or model == '2015' or model == 'AEE': logger.info("Correcting with AEE(%s) model at frequency %.2f Hz" % (model, target_freq_Hz)) # logging.getLogger("mwa_tile").setLevel(logging.DEBUG) Jones = primary_beam.MWA_Tile_advanced(za, az, target_freq_Hz, delays=delays, zenithnorm=options.zenithnorm,
def get_beam_power(obsid_data, sources, beam_model="analytic", centeronly=True): obsid, _, _, duration, delays, centrefreq, channels = obsid_data # Figure out GPS times to evaluate the beam in order to map the drift scan midtimes = np.array([ float(obsid) + 0.5 * duration ]) # although only includes one element, could in future be extended Ntimes = len(midtimes) # Make an EarthLocation for the MWA MWA_LAT = -26.7033 # degrees MWA_LON = 116.671 # degrees MWA_HEIGHT = 377.827 # metres mwa_location = EarthLocation(lat=MWA_LAT * u.deg, lon=MWA_LON * u.deg, height=MWA_HEIGHT * u.m) # Pre-allocate arrays for the beam patterns if not centeronly: PowersX = np.zeros((len(sources), Ntimes, len(channels))) PowersY = np.zeros((len(sources), Ntimes, len(channels))) frequencies = np.array(channels) * 1.28e6 else: PowersX = np.zeros((len(sources), Ntimes, 1)) PowersY = np.zeros((len(sources), Ntimes, 1)) frequencies = [centrefreq] # Create arrays of the RAs and DECs to be sampled (already in degrees) #print "Constructing RA and DEC arrays for beam model..." logger.info("Constructing RA and DEC arrays for beam model...") RAs = np.array([x[0] for x in sources]) Decs = np.array([x[1] for x in sources]) if len(RAs) == 0: sys.stderr.write('Must supply >=1 source positions\n') return None if not len(RAs) == len(Decs): sys.stderr.write('Must supply equal numbers of RAs and Decs\n') return None # Turn RAs and DECs into SkyCoord objects that are to be fed to Alt/Az conversion coords = SkyCoord(RAs, Decs, unit=(u.deg, u.deg)) # Make times to feed to Alt/Az conversion obstimes = Time(midtimes, format='gps', scale='utc') #print "Converting RA and DEC to Alt/Az and computing beam pattern..." logger.info( "Converting RA and DEC to Alt/Az and computing beam pattern...") for t, time in enumerate(obstimes): # Convert to Alt/Az given MWA position and observing time altaz = coords.transform_to(AltAz(obstime=time, location=mwa_location)) # Change Altitude to Zenith Angle theta = np.pi / 2 - altaz.alt.rad phi = altaz.az.rad # Calculate beam pattern for each frequency, and store the results in a ndarray for f, freq in enumerate(frequencies): if beam_model == "analytic": rX, rY = primary_beam.MWA_Tile_analytic(theta, phi, freq=freq, delays=delays, zenithnorm=True, power=True) elif beam_model == "FEE": rX, rY = primary_beam.MWA_Tile_full_EE(theta, phi, freq=freq, delays=delays, zenithnorm=True, power=True) else: #print "Unrecognised beam model '{0}'. Defaulting to 'analytic'." logger.warning( "Unrecognised beam model '{0}'. Defaulting to 'analytic'.") rX, rY = primary_beam.MWA_Tile_analytic(theta, phi, freq=freq, delays=delays, zenithnorm=True, power=True) PowersX[:, t, f] = rX PowersY[:, t, f] = rY # Convert X and Y powers into total intensity Powers = 0.5 * (PowersX + PowersY) return Powers
def createArrayFactor(za, az, pixel_area, data): """ Primary function to calculate the array factor with the given information. Input: delays - the beamformer delays required for point tile beam (should be a set of 16 numbers) time - the time at which to evaluate the target position (as we need Azimuth and Zenith angle, which are time dependent) obsfreq - the centre observing frequency for the observation eff - the array efficiency (frequency and pointing dependent, currently require engineers to calculate for us...) flagged_tiles - the flagged tiles from the calibration solution (in the RTS format) xpos - x position of the tiles ypos - y position of the tiles zpos - z position of the tiles theta_res - the zenith angle resolution in degrees phi_res - the azimuth resolution in degrees za_chunk - list of ZA to compute array factor for write - whether to actually write a file to disk rank - mpi rank (thread index) Return: results - a list of lists cotaining [ZA, Az, beam power], for all ZA and Az in the given band """ obsid = data['obsid'] ra = data['ra'] dec = data['dec'] times = data['time'] delays = data['delays'] xpos = data['x'] ypos = data['y'] zpos = data['z'] cable_delays = data['cd'] theta_res = data['tres'] phi_res = data['pres'] beam_model = data['beam'] coplanar = data['coplanar'] ord_version = data['ord_version'] no_delays = data['no_delays'] plot_jobid = data['plot_jobid'] # work out core depent part of data to process nfreq = len(data['freqs']) ifreq = rank % nfreq ichunk = rank // nfreq obsfreq = data['freqs'][ifreq] logger.info( "rank {:3d} Calculating phase of each sky position for each tile".format(rank)) # calculate the relevent wavenumber for (theta,phi) #logger.info( "rank {:3d} Calculating wavenumbers".format(rank)) if ord_version: #gx, gy, gz = calc_geometric_delay_distance((np.pi / 2) - az, za) gx, gy, gz = calc_geometric_delay_distance(az, za) logger.debug("rank {:3d} Wavenumbers shapes: {} {} {}".format(rank, gx.shape, gy.shape, gz.shape)) # phase of each sky position for each tile ph_tile = cal_phase_ord(xpos, ypos, zpos, cable_delays, gx, gy, gz, obsfreq, coplanar=coplanar, no_delays=no_delays) gx = gy = gz = None # Dereference for garbage collection else: kx, ky, kz = calcWaveNumbers(obsfreq, (np.pi / 2) - az, za) #logger.debug("kx[0] {} ky[0] {} kz[0] {}".format(kx[0], ky[0], kz[0])) logger.debug("rank {:3d} Wavenumbers shapes: {} {} {}".format(rank, kx.shape, ky.shape, kz.shape)) # phase of each sky position for each tile ph_tile = calcSkyPhase(xpos, ypos, zpos, kx, ky, kz, coplanar=coplanar) kx = ky = kz = None # Dereference for garbage collection requests.get('https://ws.mwatelescope.org/progress/update', params={'jobid':plot_jobid, 'workid':rank, 'current':2, 'total':5, 'desc':'Tile beam'}) # calculate the tile beam at the given Az,ZA pixel logger.info( "rank {:3d} Calculating tile beam".format(rank)) if beam_model == 'hyperbeam': # This method is no longer needed as mwa_pb uses hyperbeam jones = beam.calc_jones_array(az, za, obsfreq, delays, [1.0] * 16, True) jones = jones.reshape(za.shape[0], 1, 2, 2) vis = pb.mwa_tile.makeUnpolInstrumentalResponse(jones, jones) jones = None # Dereference for garbage collection tile_xpol, tile_ypol = (vis[:, :, 0, 0].real, vis[:, :, 1, 1].real) vis = None # Dereference for garbage collection elif beam_model == 'analytic': tile_xpol, tile_ypol = pb.MWA_Tile_analytic(za, az, freq=obsfreq, delays=[delays, delays], zenithnorm=True, power=True) elif beam_model == 'advanced': tile_xpol, tile_ypol = pb.MWA_Tile_advanced(za, az, freq=obsfreq, delays=[delays, delays], zenithnorm=True, power=True) elif beam_model == 'full_EE': tile_xpol, tile_ypol = pb.MWA_Tile_full_EE(za, az, freq=obsfreq, delays=np.array([delays, delays]), zenithnorm=True, power=True, interp=False) #logger.info("rank {:3d} Combining tile pattern".format(rank)) tile_pattern = np.divide(np.add(tile_xpol, tile_ypol), 2.0) tile_pattern = tile_pattern.flatten() logger.debug("max(tile_pattern) {}".format(max(tile_pattern))) omega_A_times = [] sum_B_T_times = [] sum_B_times = [] phased_array_pattern_times = [] for ti, time in enumerate(times): requests.get('https://ws.mwatelescope.org/progress/update', params={'jobid':plot_jobid, 'workid':rank, 'current':3+ti, 'total' :3+len(times), 'desc':'{}/{} array factor'.format(1+ti, len(times))}) # get the target azimuth and zenith angle in radians and degrees # these are defined in the normal sense: za = 90 - elevation, az = angle east of North (i.e. E=90) logger.info( "rank {:3d} Calculating phase of each sky position for the target at time {}".format(rank, time)) srcAz, srcZA, _, _ = getTargetAZZA(ra, dec, time)# calculate the target (kx,ky,kz) if ord_version: #t_gx, t_gy, t_gz = calc_geometric_delay_distance((np.pi / 2) - srcAz, srcZA) t_gx, t_gy, t_gz = calc_geometric_delay_distance(srcAz, srcZA) # phase of each sky position for each tile ph_target = cal_phase_ord(xpos, ypos, zpos, cable_delays, t_gx, t_gy, t_gz, obsfreq, coplanar=coplanar, no_delays=no_delays) else: target_kx, target_ky, target_kz = calcWaveNumbers(obsfreq, (np.pi / 2) - srcAz, srcZA) # Get phase of target for each tile phase of each sky position for each tile ph_target = calcSkyPhase(xpos, ypos, zpos, target_kx, target_ky, target_kz) # determine the interference pattern seen for each tile logger.info( "rank {:3d} Calculating array_factor".format(rank)) #logger.debug("rank {:3d} ti: {} ph_tile {}".format(rank, ti, ph_tile)) #logger.debug("rank {:3d} ti: {} ph_target {}".format(rank, ti, ph_target)) array_factor, array_factor_power = calcArrayFactor(ph_tile, ph_target) ph_target = None # Dereference for garbage collection #logger.debug("array_factor_power[0] {}".format(array_factor_power[0])) logger.debug("rank {:3d} array_factor[0] {}".format(rank, array_factor[0])) logger.debug("rank {:3d} array_factor shapes: {}".format(rank, array_factor.shape)) logger.debug("rank {:3d} array factor maximum = {}".format(rank, np.amax(array_factor_power))) # calculate the phased array power pattern logger.info( "rank {:3d} Calculating phased array pattern".format(rank)) logger.debug("rank {:3d} tile_pattern.shape {} array_factor_power.shape {}".format(rank, tile_pattern.shape, array_factor_power.shape)) phased_array_pattern = np.multiply(tile_pattern, array_factor_power) #phased_array_pattern = tile_pattern[0][0] * np.abs(array_factor)**2 # indexing due to tile_pattern now being a 2-D array phased_array_pattern_times.append(phased_array_pattern) # add this contribution to the beam solid angle logger.info( "rank {:3d} Calculating omega_A".format(rank)) #omega_A_array = np.sin(za) * array_factor_power * np.radians(theta_res) * np.radians(phi_res) #omega_A_array = np.multiply(np.multiply(np.multiply(np.sin(za), array_factor_power), np.radians(theta_res)), np.radians(phi_res)) omega_A_array = np.multiply(array_factor_power, pixel_area) logger.debug("rank {:3d} omega_A_array shapes: {}".format(rank, omega_A_array.shape)) omega_A = np.sum(omega_A_array) logger.debug("rank {:3d} freq {:.2f}MHz beam_area: {}".format(rank, obsfreq/1e6, omega_A)) omega_A_times.append(omega_A) #logger.debug("omega_A[1] vals: za[1] {}, array_factor_power[1] {}, theta_res {}, phi_res {}".format(za[1], array_factor_power[1], theta_res, phi_res)) #logger.debug("omega_A[1] {}".format(omega_A_array[1])) # Do a partial sum over the sky and frequency to be finished outside of the function sum_B_T, sum_B = partial_convolve_sky_map(az, za, pixel_area, phased_array_pattern, obsfreq, time) sum_B_T_times.append(sum_B_T) sum_B_times.append(sum_B) ph_tile = None # Dereference for garbage collection # Average over time #omega_A = np.average(omega_A_times) #sum_B_T = np.average(sum_B_T_times) #sum_B = np.average(sum_B_times) #phased_array_pattern = np.average(phased_array_pattern_times, axis=0) logger.debug("rank {:3d} phased_array_pattern: {}".format(rank, phased_array_pattern)) logger.debug("rank {:3d} omega_A_times: {}".format(rank, omega_A_times)) logger.info("rank {:3d} done".format(rank)) # return lists of results for each time step return np.array(omega_A_times), np.array(sum_B_T_times), np.array(sum_B_times), np.array(phased_array_pattern_times)
def test_hyperbeam_vs_pb(): """Compares the results of the FEE beam model using mwa_pb and mwa_hyperbeam.""" beam = mwa_hyperbeam.FEEBeam(config.h5file) # Set up fake data. n = 100000 az = np.linspace(0, 0.9 * np.pi, n) za = np.linspace(0.1, 0.9 * np.pi / 2, n) freq = 167000000 delays = [0] * 16 amps = [1.0] * 16 test_decimals = 4 # Jones -------------------------------------------------- print("Jones benchmarks") # mwa_pb method start_time = time.perf_counter() pb_jones = primary_beam.MWA_Tile_full_EE(za, az, freq=freq, delays=np.array(delays), zenithnorm=True, power=True, jones=True, interp=False) print("mwa_pb: {:6.3f} s".format(time.perf_counter() - start_time)) # hyperbeam method #print(freq, delays, amps) start_time = time.perf_counter() hb_jones = beam.calc_jones_array(az, za, freq, delays, amps, True) print("hyperbeam: {:6.3f} s".format(time.perf_counter() - start_time)) hb_jones = hb_jones.reshape(n, 2, 2) # Compare Jones assert_almost_equal(pb_jones, hb_jones, decimal=test_decimals) # Power --------------------------------------------------- print("\nPower benchmarks") # mwa_pb method start_time = time.perf_counter() pb_xx, pb_yy = primary_beam.MWA_Tile_full_EE(za, az, freq=freq, delays=np.array(delays), zenithnorm=True, power=True) print("mwa_pb: {:6.3f} s".format(time.perf_counter() - start_time)) # hyperbeam method start_time = time.perf_counter() hb_jones = beam.calc_jones_array(az, za, freq, delays, amps, True) hb_jones = hb_jones.reshape(1, n, 2, 2) vis = primary_beam.mwa_tile.makeUnpolInstrumentalResponse( hb_jones, hb_jones) hb_xx, hb_yy = (vis[:, :, 0, 0].real, vis[:, :, 1, 1].real) print("hyperbeam: {:6.3f} s".format(time.perf_counter() - start_time)) # Compare power assert_almost_equal(pb_xx, hb_xx[0], decimal=test_decimals) assert_almost_equal(pb_yy, hb_yy[0], decimal=test_decimals)
def mwapbeam(za, az, frequencies, fluxes, metafits=None, jones=False): """Calculate MWA beam response using MWAPB package Parameters ---------- za : array-like Zenith angles in radians az : array-like Azimuth angles in radians frequencies : array-like frequency channels fluxes : array-like Source flux densities in Jys metafits : string, optional Path to observation ID metafits file, by default None jones : bool, optional True calculates beam jones else XX and YY attenuaton values directly, by default False Returns ------- [type] [description] """ with fits.open(metafits) as hdu: delays = list(map(int, hdu[0].header["DELAYS"].split(","))) delays = [delays, delays] if jones: pjones = np.zeros((len(za), len(frequencies), 4), dtype=np.complex64) for chan in range(len(frequencies)): pjones[:, chan, :] = np.reshape( primary_beam.MWA_Tile_full_EE(za, az, freq=frequencies[chan], delays=delays, jones=True), (len(az), 4), ) fluxes[:, :, 0] = ( pjones[:, :, 0] * np.conj(pjones[:, :, 0]) * fluxes[:, :, 0] + pjones[:, :, 1] * np.conj(pjones[:, :, 1]) * fluxes[:, :, 0]) fluxes[:, :, 3] = ( pjones[:, :, 2] * np.conj(pjones[:, :, 2]) * fluxes[:, :, 3] + pjones[:, :, 3] * np.conj(pjones[:, :, 3]) * fluxes[:, :, 3]) else: attenuations = np.zeros((len(za), len(frequencies), 4), dtype=np.float32) for chan in range(len(frequencies)): XX, YY = primary_beam.MWA_Tile_full_EE( za, az, freq=frequencies[chan], delays=delays, zenithnorm=True, power=True, interp=False, ) attenuations[:, chan, 0] = XX attenuations[:, chan, 3] = YY fluxes *= attenuations return fluxes
def get_beam_power_over_time(names_ra_dec, common_metadata=None, dt=296, centeronly=True, verbose=False, option='analytic', degrees=False, start_time=0): """Calculates the zenith normalised power for each source over time. Parameters ---------- names_ra_dec : `list` An array in the format [[source_name, RAJ, DecJ]] common_metadata : `list`, optional The list of common metadata generated from :py:meth:`vcstools.metadb_utils.get_common_obs_metadata` dt : `int`, optional The time interval of how often powers are calculated. |br| Default: 296. centeronly : `boolean`, optional Only calculates for the centre frequency. |br| Default: `True`. verbose : `boolean`, optional If `True` will not supress the output from mwa_pb. |br| Default: `False`. option : `str`, optional The primary beam model to use out of [analytic, advanced, full_EE, hyperbeam]. |br| Default: analytic. degrees : `boolean`, optional If true assumes RAJ and DecJ are in degrees. |br| Default: `False`. start_time : `int`, optional The time in seconds from the begining of the observation to start calculating at. |br| Default: 0. Returns ------- Powers : `numpy.array`, (len(names_ra_dec), ntimes, nfreqs) The zenith normalised power for each source over time. """ if common_metadata is None: common_metadata = get_common_obs_metadata(obsid) obsid, _, _, time, delays, centrefreq, channels = common_metadata names_ra_dec = np.array(names_ra_dec) amps = [1.0] * 16 logger.debug("Calculating beam power for OBS ID: {0}".format(obsid)) if option == 'hyperbeam': if "mwa_hyperbeam" not in sys.modules: logger.error( "mwa_hyperbeam not installed so can not use hyperbeam to create a beam model. Exiting" ) sys.exit(1) beam = mwa_hyperbeam.FEEBeam(config.h5file) # Work out time steps to calculate over starttimes = np.arange(start_time, time + start_time, dt) stoptimes = starttimes + dt stoptimes[stoptimes > time] = time ntimes = len(starttimes) midtimes = float(obsid) + 0.5 * (starttimes + stoptimes) # Work out frequency steps if centeronly: if centrefreq > 1e6: logger.warning( "centrefreq is greater than 1e6, assuming input with units of Hz." ) frequencies = np.array([centrefreq]) else: frequencies = np.array([centrefreq]) * 1e6 nfreqs = 1 else: # in Hz frequencies = np.array(channels) * 1.28e6 nfreqs = len(channels) # Set up np power array PowersX = np.zeros((len(names_ra_dec), ntimes, nfreqs)) PowersY = np.zeros((len(names_ra_dec), ntimes, nfreqs)) # Convert RA and Dec to desired units if degrees: RAs = np.array(names_ra_dec[:, 1], dtype=float) Decs = np.array(names_ra_dec[:, 2], dtype=float) else: RAs, Decs = sex2deg(names_ra_dec[:, 1], names_ra_dec[:, 2]) # Then check if they're valid if len(RAs) == 0: sys.stderr.write('Must supply >=1 source positions\n') return None if not len(RAs) == len(Decs): sys.stderr.write('Must supply equal numbers of RAs and Decs\n') return None if verbose is False: #Supress print statements of the primary beam model functions sys.stdout = open(os.devnull, 'w') for itime in range(ntimes): # this differ's from the previous ephem_utils method by 0.1 degrees _, Azs, Zas = mwa_alt_az_za(midtimes[itime], ra=RAs, dec=Decs, degrees=True) # go from altitude to zenith angle theta = np.radians(Zas) phi = np.radians(Azs) for ifreq in range(nfreqs): #Decide on beam model if option == 'analytic': rX, rY = primary_beam.MWA_Tile_analytic( theta, phi, freq=frequencies[ifreq], delays=delays, zenithnorm=True, power=True) elif option == 'advanced': rX, rY = primary_beam.MWA_Tile_advanced( theta, phi, freq=frequencies[ifreq], delays=delays, zenithnorm=True, power=True) elif option == 'full_EE': rX, rY = primary_beam.MWA_Tile_full_EE(theta, phi, freq=frequencies[ifreq], delays=delays, zenithnorm=True, power=True) elif option == 'hyperbeam': jones = beam.calc_jones_array(phi, theta, int(frequencies[ifreq]), delays[0], amps, True) jones = jones.reshape(1, len(phi), 2, 2) vis = primary_beam.mwa_tile.makeUnpolInstrumentalResponse( jones, jones) rX, rY = (vis[:, :, 0, 0].real, vis[:, :, 1, 1].real) PowersX[:, itime, ifreq] = rX PowersY[:, itime, ifreq] = rY if verbose is False: sys.stdout = sys.__stdout__ Powers = 0.5 * (PowersX + PowersY) return Powers