def geometric_delay(baselines, skypos, altaz=False, dircos=False, hadec=True, units='mks', latitude=None): """ --------------------------------------------------------------------- Estimates the geometric delays matrix for different baselines from different sky positions. Inputs: baselines: x, y, and z components of baseline vectors in a Mx3 numpy array skypos: Nx2 (Alt-Az or HA-Dec) or Nx3 (direction cosines) numpy array of sky positions altaz: [Boolean flag, default=False] If True, skypos is in Alt-Az coordinates system hadec: [Boolean flag, default=True] If True, skypos is in HA-Dec coordinates system dircos: [Boolean flag, default=False] If True, skypos is in direction cosines coordinates system units: Units of baselines. Default='mks'. Alternative is 'cgs'. latitude: Latitude of the observatory. Required if hadec is True. Outputs: geometric delays [NxM numpy array] Geometric delay for every combination of baselines and skypos. --------------------------------------------------------------------- """ try: baselines, skypos except NameError: raise NameError('baselines and/or skypos not defined in geometric_delay().') if (altaz)+(dircos)+(hadec) != 1: raise ValueError('One and only one of altaz, dircos, hadec must be set to True.') if hadec and (latitude is None): raise ValueError('Latitude must be specified when skypos is in HA-Dec format.') try: units except NameError: print 'No units provided. Assuming MKS units.' units = 'mks' if (units != 'mks') and (units != 'cgs'): print 'Units should be specified to be one of MKS or CGS. Default=MKS' print 'Proceeding with MKS units.' units = 'mks' if not isinstance(baselines, NP.ndarray): raise TypeError('baselines should be a Nx3 numpy array in geometric_delay().') if len(baselines.shape) == 1: baselines = baselines.reshape(1,-1) if baselines.shape[1] == 1: baselines = NP.hstack(baselines, NP.zeros((baselines.size,2))) elif baselines.shape[1] == 2: baselines = NP.hstack(baselines, NP.zeros((baselines.size,1))) elif baselines.shape[1] > 3: baselines = baselines[:,:3] if altaz or hadec: if len(skypos.shape) < 2: if skypos.size != 2: raise ValueError('Sky position in altitude-azimuth or HA-Dec should consist of 2 elements.') else: skypos = skypos.reshape(1,-1) elif len(skypos.shape) > 2: raise ValueError('Sky positions should be a Nx2 numpy array if using altitude-azimuth of HA-Dec.') else: if skypos.shape[1] != 2: raise ValueError('Sky positions should be a Nx2 numpy array if using altitude-azimuth of HA-Dec.') if altaz: dc = GEOM.altaz2dircos(skypos, 'degrees') else: dc = GEOM.altaz2dircos(GEOM.hadec2altaz(skypos, latitude, 'degrees'), 'degrees') else: if len(skypos.shape) < 2: if skypos.size != 3: raise ValueError('Sky position in direction cosines should consist of 3 elements.') else: skypos = skypos.reshape(1,-1) elif len(skypos.shape) > 2: raise ValueError('Sky positions should be a Nx3 numpy array if using direction cosines.') else: if skypos.shape[1] != 3: raise ValueError('Sky positions should be a Nx3 numpy array if using direction cosines.') dc = skypos # geometric_delays = delay_envelope(baselines, dc, units)[:,:,-1] geometric_delays = NP.dot(dc, baselines.T)/c return geometric_delays
# pfbwin_interp = pfb_interp_func(chans) pfbwin_interp = NP.interp(chans, pfbfreq[useful_freq_range]/1e3, pfbwin[useful_freq_range]) bandpass_shape = 10**(pfbwin_interp/10) window = n_channels * DSP.windowing(n_channels, shape=bpass_shape, pad_width=n_pad, centering=True, area_normalize=True) bpass = base_bpass * bandpass_shape n_snaps = int(t_obs/t_snap) lst = (lst_init + (t_snap/3.6e3) * NP.arange(n_snaps)) * 15.0 # in degrees if obs_mode == 'track': pointings_radec = NP.repeat(NP.asarray(pointing_init).reshape(-1,2), n_snaps, axis=0) else: pointings_radec = NP.hstack((NP.asarray(lst-pointing_init[0]).reshape(-1,1), pointing_init[1]+NP.zeros(n_snaps).reshape(-1,1))) pointings_hadec = NP.hstack(((lst-pointings_radec[:,0]).reshape(-1,1), pointings_radec[:,1].reshape(-1,1))) pointings_altaz = GEOM.hadec2altaz(pointings_hadec, latitude, units='degrees') pointings_dircos = GEOM.altaz2dircos(pointings_altaz, units='degrees') ## Interferometer parameters # baseline_orientation = NP.asarray([0.0, 90.0]) # in degrees from East towards North # baseline_length = 1000.0 + NP.zeros(2) # in m # baseline_vect = NP.zeros((2,3)) # baseline_vect[:,0] = baseline_length * NP.cos(NP.radians(baseline_orientation)) # baseline_vect[:,1] = baseline_length * NP.sin(NP.radians(baseline_orientation)) # baseline_orientation_str = '{0:.1f}'.format(baseline_orientation) # baseline_length_str = '{0:.1f}'.format(baseline_length) # ia = RI.InterferometerArray(labels, bl, chans, telescope=telescope, latitude=latitude, A_eff=A_eff, freq_scale='GHz') # # ia = RI.InterferometerArray(['B1','B2'], baseline_vect, chans, telescope=telescope, latitude=latitude, A_eff=A_eff, freq_scale='GHz') # # ints = []
n_snaps = int(1.0 * t_obs / t_snap) lst = (lst_init + (t_snap / 3.6e3) * NP.arange(n_snaps)) * 15.0 # in degrees if obs_mode == 'track': pointings_radec = NP.repeat(NP.asarray(pointing_init).reshape(-1, 2), n_snaps, axis=0) else: pointings_radec = NP.hstack( (NP.asarray(lst - pointing_init[0]).reshape(-1, 1), pointing_init[1] + NP.zeros(n_snaps).reshape(-1, 1))) pointings_hadec = NP.hstack(((lst - pointings_radec[:, 0]).reshape(-1, 1), pointings_radec[:, 1].reshape(-1, 1))) pointings_altaz = GEOM.hadec2altaz(pointings_hadec, latitude, units='degrees') pointings_dircos = GEOM.altaz2dircos(pointings_altaz, units='degrees') use_GSM = args['ASM'] use_DSM = args['DSM'] use_NVSS = args['NVSS'] use_SUMSS = args['SUMSS'] use_MSS = args['MSS'] use_GLEAM = args['GLEAM'] use_PS = args['PS'] fg_str = '' nside = args['nside'] flux_unit = args['flux_unit'] if use_GSM: fg_str = 'asm'
snapshot_type_str = 'drift_averaged_' if beam_switch: snapshot_type_str = 'beam_switches_' if snapshots_range is not None: snapshot_type_str = 'snaps_{0[0]:0d}-{0[1]:0d}_'.format(snapshots_range) duration_str = '' if obs_mode in ['track', 'drift']: if (t_acc is not None) and (n_acc is not None): duration_str = '_{0:0d}x{1:.1f}s'.format(n_acc, t_acc) pc = NP.asarray(pc).reshape(1,-1) if pc_coords == 'dircos': pc_dircos = pc elif pc_coords == 'altaz': pc_dircos = GEOM.altaz2dircos(pc, units='degrees') spindex_seed_str = '' if spindex_rms > 0.0: spindex_rms_str = '{0:.1f}'.format(spindex_rms) else: spindex_rms = 0.0 if spindex_seed is not None: spindex_seed_str = '{0:0d}_'.format(spindex_seed) for k in range(n_sky_sectors): if n_sky_sectors == 1: sky_sector_str = '_all_sky_' else: sky_sector_str = '_sky_sector_{0:0d}_'.format(k)
lst = 0.5 * (lst_edges[1:] + lst_edges[:-1]) t_snap = (lst_edges[1:] - lst_edges[:-1]) / 15.0 * 3.6e3 else: lst = 0.5 * (lst_edges_left + lst_edges_right) t_snap = (lst_edges_right - lst_edges_left) / 15.0 * 3.6e3 else: t_snap = 112.0 + NP.zeros( n_snaps) # in seconds (needs to be generalized) lst = lst_wrapped + 0.5 * t_snap / 3.6e3 * 15.0 # pointings_dircos_orig = GEOM.altaz2dircos(pointings_altaz_orig, units='degrees') # pointings_hadec_orig = GEOM.altaz2hadec(pointings_altaz_orig, latitude, units='degrees') # pointings_radec_orig = NP.hstack(((lst-pointings_hadec_orig[:,0]).reshape(-1,1), pointings_hadec_orig[:,1].reshape(-1,1))) # pointings_radec_orig[:,0] = pointings_radec_orig[:,0] % 360.0 pointings_dircos = GEOM.altaz2dircos(pointings_altaz, units='degrees') pointings_hadec = GEOM.altaz2hadec(pointings_altaz, latitude, units='degrees') pointings_radec = NP.hstack(((lst - pointings_hadec[:, 0]).reshape(-1, 1), pointings_hadec[:, 1].reshape(-1, 1))) pointings_radec[:, 0] = pointings_radec[:, 0] % 360.0 t_obs = NP.sum(t_snap) elif pointing_info is not None: pointing_init = NP.asarray(pointing_info[1:]) lst_init = pointing_info[0] pointing_file = None if t_snap is None: raise NameError( 't_snap must be provided for an automated observing run')
def observe( self, timestamp, Tsys, bandpass, pointing_center, skymodel, tobs, pb_min=0.1, fov_radius=None, lst=None ): if bandpass.size != self.bp.shape[1]: raise ValueError("bandpass length does not match.") self.Tsys = self.Tsys + [Tsys] self.vis_rms_freq = self.vis_rms_freq + [ 2.0 * FCNST.k * Tsys / self.A_eff / self.eff_Q / NP.sqrt(2) / tobs / self.freq_resolution / CNST.Jy ] self.tobs = self.tobs + [tobs] self.lst = self.lst + [lst] if self.timestamp == []: self.bp = NP.asarray(bandpass).reshape(1, -1) self.pointing_center = NP.asarray(pointing_center).reshape(1, -1) else: self.bp = NP.vstack((self.bp, NP.asarray(bandpass).reshape(1, -1))) self.pointing_center = NP.vstack((self.pointing_center, NP.asarray(pointing_center).reshape(1, -1))) pointing_lon = self.pointing_center[-1, 0] pointing_lat = self.pointing_center[-1, 1] if self.skycoords == "radec": if self.pointing_coords == "hadec": if lst is not None: pointing_lon = lst - self.pointing_center[-1, 0] pointing_lat = self.pointing_center[-1, 1] else: raise ValueError( "LST must be provided. Sky coordinates are in RA-Dec format while pointing center is in HA-Dec format." ) elif self.pointing_coords == "altaz": pointing_lonlat = lst - GEOM.altaz2hadec(self.pointing_center[-1, :], self.latitude, units="degrees") pointing_lon = pointing_lonlat[0] pointing_lat = pointing_lonlat[1] elif self.skycoords == "hadec": if self.pointing_coords == "radec": if lst is not None: pointing_lon = lst - self.pointing_center[-1, 0] pointing_lat = self.pointing_center[-1, 1] else: raise ValueError( "LST must be provided. Sky coordinates are in RA-Dec format while pointing center is in HA-Dec format." ) elif self.pointing_coords == "altaz": pointing_lonlat = lst - GEOM.altaz2hadec(self.pointing_center[-1, :], self.latitude, units="degrees") pointing_lon = pointing_lonlat[0] pointing_lat = pointing_lonlat[1] else: if self.pointing_coords == "radec": if lst is not None: pointing_lonlat = GEOM.hadec2altaz( NP.asarray([lst - self.pointing_center[-1, 0], self.pointing_center[-1, 1]]), self.latitude, units="degrees", ) pointing_lon = pointing_lonlat[0] pointing_lat = pointing_lonlat[1] else: raise ValueError( "LST must be provided. Sky coordinates are in Alt-Az format while pointing center is in RA-Dec format." ) elif self.pointing_coords == "hadec": pointing_lonlat = GEOM.hadec2altaz(self.pointing_center, self.latitude, units="degrees") pointing_lon = pointing_lonlat[0] pointing_lat = pointing_lonlat[1] pointing_phase = 0.0 baseline_in_local_frame = self.baseline if self.baseline_coords == "equatorial": baseline_in_local_frame = GEOM.xyz2enu(self.baseline, self.latitude, "degrees") ptmp = self.pointing_center[-1, :] # Convert pointing center to Alt-Az coordinates if self.pointing_coords == "hadec": ptmp = GEOM.hadec2altaz(self.pointing_center[-1, :], self.latitude, units="degrees") elif self.pointing_coords == "radec": if lst is not None: ptmp = GEOM.hadec2altaz( NP.asarray([lst - self.pointing_center[-1, 0], self.pointing_center[-1, 1]]), self.latitude, units="degrees", ) else: raise ValueError( "LST must be provided. Sky coordinates are in Alt-Az format while pointing center is in RA-Dec format." ) ptmp = GEOM.altaz2dircos(ptmp, "degrees") # Convert pointing center to direction cosine coordinates pointing_phase = ( 2.0 * NP.pi * NP.dot(baseline_in_local_frame.reshape(1, -1), ptmp.reshape(-1, 1)) * self.channels.reshape(1, -1) / FCNST.c ) if fov_radius is None: fov_radius = 90.0 # PDB.set_trace() m1, m2, d12 = GEOM.spherematch( pointing_lon, pointing_lat, skymodel.catalog.location[:, 0], skymodel.catalog.location[:, 1], fov_radius, maxmatches=0, ) # if fov_radius is not None: # m1, m2, d12 = GEOM.spherematch(pointing_lon, pointing_lat, skymodel.catalog.location[:,0], skymodel.catalog.location[:,1], fov_radius, maxmatches=0) # else: # m1 = [0] * skymodel.catalog.location.shape[0] # m2 = xrange(skymodel.catalog.location.shape[0]) # d12 = GEOM.sphdist(NP.empty(skymodel.catalog.shape[0]).fill(pointing_lon), NP.empty(skymodel.catalog.shape[0]).fill(pointing_lat), skymodel.catalog.location[:,0], skymodel.catalog.location[:,1]) if len(d12) != 0: pb = NP.empty((len(d12), len(self.channels))) fluxes = NP.empty((len(d12), len(self.channels))) coords_str = self.skycoords if self.skycoords == "radec": coords_str = "altaz" source_positions = GEOM.hadec2altaz( NP.hstack( ( NP.asarray(lst - skymodel.catalog.location[m2, 0]).reshape(-1, 1), skymodel.catalog.location[m2, 1].reshape(-1, 1), ) ), self.latitude, "degrees", ) for i in xrange(len(self.channels)): # pb[:,i] = PB.primary_beam_generator(d12, self.channels[i]/1.0e9, 'degrees', self.telescope) pb[:, i] = PB.primary_beam_generator( source_positions, self.channels[i] / 1.0e9, "altaz", self.telescope ) fluxes[:, i] = ( skymodel.catalog.flux_density[m2] * (self.channels[i] / skymodel.catalog.frequency) ** skymodel.catalog.spectral_index[m2] ) geometric_delays = DLY.geometric_delay( baseline_in_local_frame, source_positions, altaz=(coords_str == "altaz"), hadec=(coords_str == "hadec"), latitude=self.latitude, ) self.geometric_delays = self.geometric_delays + [geometric_delays.reshape(len(source_positions))] phase_matrix = 2.0 * NP.pi * NP.repeat( geometric_delays.reshape(-1, 1), len(self.channels), axis=1 ) * NP.repeat(self.channels.reshape(1, -1), len(d12), axis=0) - NP.repeat(pointing_phase, len(d12), axis=0) skyvis = NP.sum( pb * fluxes * NP.repeat(NP.asarray(bandpass).reshape(1, -1), len(d12), axis=0) * NP.exp(-1j * phase_matrix), axis=0, ) if fov_radius is not None: self.obs_catalog_indices = self.obs_catalog_indices + [m2] # self.obs_catalog = self.obs_catalog + [skymodel.catalog.subset(m2)] else: print "No sources found in the catalog within matching radius. Simply populating the observed visibilities with noise." skyvis = NP.zeros((1, len(self.channels))) if self.timestamp == []: self.skyvis_freq = skyvis.reshape(1, -1) self.vis_noise_freq = self.vis_rms_freq[-1] * ( NP.random.randn(len(self.channels)).reshape(1, -1) + 1j * NP.random.randn(len(self.channels)).reshape(1, -1) ) self.vis_freq = self.skyvis_freq + self.vis_noise_freq else: self.skyvis_freq = NP.vstack((self.skyvis_freq, skyvis.reshape(1, -1))) self.vis_noise_freq = NP.vstack( ( self.vis_noise_freq, self.vis_rms_freq[-1] * ( NP.random.randn(len(self.channels)).reshape(1, -1) + 1j * NP.random.randn(len(self.channels)).reshape(1, -1) ), ) ) self.vis_freq = NP.vstack( (self.vis_freq, (self.skyvis_freq[-1, :] + self.vis_noise_freq[-1, :]).reshape(1, -1)) ) self.timestamp = self.timestamp + [timestamp]
bl_lengths = NP.sqrt(NP.sum(bl**2,axis=1)) decl = -27.0 # in degrees lat = -27.0 # in degrees ha_range = 4.0 # in hrs ha_step = 1.0/60. # in hrs ha = 15.0*NP.arange(-ha_range/2, ha_range/2, ha_step) ha = NP.asarray(ha).reshape(-1,1) dec = decl + NP.zeros((len(ha),1)) dec.reshape(-1,1) hadec = NP.hstack((ha, dec)) altaz = GEOM.hadec2altaz(hadec, lat, units='degrees') dircos = GEOM.altaz2dircos(altaz, units='degrees') dm = DLY.delay_envelope(bl, dircos, units='mks') min_delays = dm[:,:,1]-dm[:,:,0] max_delays = NP.sum(dm,axis=2) fig = PLT.figure(figsize=(14,8)) ax = PLT.axes([0.12,0.1,0.8,0.8]) PLT.xlim(NP.min(bl_lengths)-1.0,NP.max(bl_lengths)+100.0) PLT.ylim(1e9*(NP.min(min_delays)-1.e-8),1e9*(NP.max(max_delays)+1.e-8)) PLT.xlabel('Baseline Length [m]', fontsize=18, weight='semibold') PLT.ylabel('Delay [ns]', fontsize=18, weight='semibold') PLT.title('Delay Envelope', fontsize=18, weight='semibold') hadec_text = ax.text(0.05, 0.9, '', transform=ax.transAxes, fontsize=18)
window = n_channels * DSP.windowing(n_channels, shape=bpass_shape, pad_width=n_pad, centering=True, area_normalize=True) bandpass_shape = DSP.PFB_empirical(nchan, 32, 0.25, 0.25) window = n_channels * DSP.windowing(n_channels, shape=bpass_shape, pad_width=n_pad, centering=True, area_normalize=True) bpass = base_bpass * bandpass_shape n_snaps = int(t_obs / t_snap) lst = (lst_init + (t_snap / 3.6e3) * NP.arange(n_snaps)) * 15.0 # in degrees if obs_mode == "track": pointings_radec = NP.repeat(NP.asarray(pointing_init).reshape(-1, 2), n_snaps, axis=0) else: pointings_radec = NP.hstack( (NP.asarray(lst - pointing_init[0]).reshape(-1, 1), pointing_init[1] + NP.zeros(n_snaps).reshape(-1, 1)) ) pointings_hadec = NP.hstack(((lst - pointings_radec[:, 0]).reshape(-1, 1), pointings_radec[:, 1].reshape(-1, 1))) pointings_altaz = GEOM.hadec2altaz(pointings_hadec, latitude, units="degrees") pointings_dircos = GEOM.altaz2dircos(pointings_altaz, units="degrees") ## Interferometer parameters # baseline_orientation = NP.asarray([0.0, 90.0]) # in degrees from East towards North # baseline_length = 1000.0 + NP.zeros(2) # in m # baseline_vect = NP.zeros((2,3)) # baseline_vect[:,0] = baseline_length * NP.cos(NP.radians(baseline_orientation)) # baseline_vect[:,1] = baseline_length * NP.sin(NP.radians(baseline_orientation)) # baseline_orientation_str = '{0:.1f}'.format(baseline_orientation) # baseline_length_str = '{0:.1f}'.format(baseline_length) # ia = RI.InterferometerArray(labels, bl, chans, telescope=telescope, latitude=latitude, A_eff=A_eff, freq_scale='GHz') # # ia = RI.InterferometerArray(['B1','B2'], baseline_vect, chans, telescope=telescope, latitude=latitude, A_eff=A_eff, freq_scale='GHz') # # ints = []
if not beam_switch: lst = 0.5*(lst_edges[1:]+lst_edges[:-1]) t_snap = (lst_edges[1:]-lst_edges[:-1]) / 15.0 * 3.6e3 else: lst = 0.5*(lst_edges_left + lst_edges_right) t_snap = (lst_edges_right - lst_edges_left) / 15.0 * 3.6e3 else: t_snap = 112.0 + NP.zeros(n_snaps) # in seconds (needs to be generalized) lst = lst_wrapped + 0.5 * t_snap/3.6e3 * 15.0 # pointings_dircos_orig = GEOM.altaz2dircos(pointings_altaz_orig, units='degrees') # pointings_hadec_orig = GEOM.altaz2hadec(pointings_altaz_orig, latitude, units='degrees') # pointings_radec_orig = NP.hstack(((lst-pointings_hadec_orig[:,0]).reshape(-1,1), pointings_hadec_orig[:,1].reshape(-1,1))) # pointings_radec_orig[:,0] = pointings_radec_orig[:,0] % 360.0 pointings_dircos = GEOM.altaz2dircos(pointings_altaz, units='degrees') pointings_hadec = GEOM.altaz2hadec(pointings_altaz, latitude, units='degrees') pointings_radec = NP.hstack(((lst-pointings_hadec[:,0]).reshape(-1,1), pointings_hadec[:,1].reshape(-1,1))) pointings_radec[:,0] = pointings_radec[:,0] % 360.0 t_obs = NP.sum(t_snap) elif pointing_info is not None: pointing_init = NP.asarray(pointing_info[1:]) lst_init = pointing_info[0] pointing_file = None if t_snap is None: raise NameError('t_snap must be provided for an automated observing run') if (n_snaps is None) and (t_obs is None): raise NameError('n_snaps or t_obs must be provided for an automated observing run') elif (n_snaps is not None) and (t_obs is not None): raise ValueError('Only one of n_snaps or t_obs must be provided for an automated observing run')
def isotropic_radiators_array_field_pattern(nax1, nax2, sep1, sep2=None, skypos=None, wavelength=1.0, east2ax1=None, skycoords='altaz'): try: nax1, nax2, sep1 except NameError: raise NameError('Number of radiators along axis 1 and 2 and their separation must be specified. Check inputs.') if skypos is None: raise NameError('skypos must be specified in Alt-Az or direction cosine units as a Numpy array. Check inputs.') if not isinstance(nax1, int): raise TypeError('nax1 must be a positive integer.') elif nax1 <= 0: raise ValueError('nax1 must be a positive integer.') if not isinstance(nax2, int): raise TypeError('nax2 must be a positive integer.') elif nax2 <= 0: raise ValueError('nax2 must be a positive integer.') if not isinstance(sep1, (int,float)): raise TypeError('sep1 must be a positive scalar.') elif sep1 <= 0: raise ValueError('sep1 must be a positive value.') if sep2 is None: sep2 = sep1 if not isinstance(wavelength, (int,float)): raise TypeError('wavelength must be a positive scalar.') elif wavelength <= 0: raise ValueError('wavelength must be a positive value.') if not isinstance(east2ax1, (int,float)): raise TypeError('east2ax1 must be a scalar.') if not isinstance(skypos, NP.ndarray): raise TypeError('skypos must be a Numpy array.') if skycoords is not None: if (skycoords != 'altaz') and (skycoords != 'dircos'): raise ValueError('skycoords must be "altaz" or "dircos" or None (default).') elif skycoords == 'altaz': if skypos.ndim < 2: if len(skypos) == 2: skypos = NP.asarray(skypos).reshape(1,2) else: raise ValueError('skypos must be a Nx2 Numpy array.') elif skypos.ndim > 2: raise ValueError('skypos must be a Nx2 Numpy array.') else: if skypos.shape[1] != 2: raise ValueError('skypos must be a Nx2 Numpy array.') elif NP.any(skypos[:,0] < 0.0) or NP.any(skypos[:,0] > 90.0): raise ValueError('Altitudes in skypos have to be positive and <= 90 degrees') else: if skypos.ndim < 2: if (len(skypos) == 2) or (len(skypos) == 3): skypos = NP.asarray(skypos).reshape(1,-1) else: raise ValueError('skypos must be a Nx2 Nx3 Numpy array.') elif skypos.ndim > 2: raise ValueError('skypos must be a Nx2 or Nx3 Numpy array.') else: if (skypos.shape[1] < 2) or (skypos.shape[1] > 3): raise ValueError('skypos must be a Nx2 or Nx3 Numpy array.') else: if NP.any(NP.abs(skypos[:,0]) > 1.0) or NP.any(NP.abs(skypos[:,1]) > 1.0): raise ValueError('skypos in transverse direction cosine coordinates found to be exceeding unity.') else: if skypos.shape[1] == 3: eps = 1.0e-10 if NP.any(NP.abs(NP.sqrt(NP.sum(skypos**2, axis=1)) - 1.0) > eps) or NP.any(skypos[:,2] < 0.0): print 'Warning: skypos in direction cosine coordinates along line of sight found to be negative or some direction cosines are not unit vectors. Resetting to correct values.' skypos[:,2] = 1.0 - NP.sqrt(NP.sum(skypos[:,:2]**2,axis=1)) else: skypos = NP.hstack((skypos, 1.0 - NP.asarray(NP.sqrt(NP.sum(skypos[:,:2]**2,axis=1))).reshape(-1,1))) else: raise ValueError('skycoords has not been set.') skypos_dircos_relative = NP.empty((skypos.shape[0],3)) if east2ax1 is not None: if not isinstance(east2ax1, (int, float)): raise TypeError('east2ax1 must be a scalar value.') else: if skycoords == 'altaz': skypos_dircos_relative = GEOM.altaz2dircos(NP.hstack((skypos[:,0].reshape(-1,1),NP.asarray(skypos[:,1]-east2ax1).reshape(-1,1))), 'degrees') else: angle = NP.radians(east2ax1) rotation_matrix = NP.asarray([[NP.cos(angle), NP.sin(angle), 0.0], [-NP.sin(angle), NP.cos(angle), 0.0], [0.0, 0.0, 1.0]]) skypos_dircos_relative = NP.dot(skypos, rotation_matrix.T) else: if skycoords == 'altaz': skypos_dircos_relative = GEOM.altaz2dircos(skypos, 'degrees') else: skypos_dircos_relative = skypos phi = 2 * NP.pi * sep1 * skypos_dircos_relative[:,0] / wavelength psi = 2 * NP.pi * sep2 * skypos_dircos_relative[:,1] / wavelength pb = NP.sin(0.5*nax1*phi)/NP.sin(0.5*phi) * NP.sin(0.5*nax2*psi)/NP.sin(0.5*psi) / (nax1*nax2) return pb
def dipole_field_pattern(length, skypos, dipole_coords=None, dipole_orientation=None, skycoords=None, wavelength=1.0, ground_plane=None, angle_units=None, half_wave_dipole_approx=True): try: length, skypos except NameError: raise NameError('Dipole length and sky positions must be specified. Check inputs.') if not isinstance(length, (int,float)): raise TypeError('Dipole length should be a scalar.') if length <= 0.0: raise ValueError('Dipole length should be positive.') if not isinstance(wavelength, (int,float)): raise TypeError('Wavelength should be a scalar.') if wavelength <= 0.0: raise ValueError('Wavelength should be positive.') if ground_plane is not None: if not isinstance(ground_plane, (int,float)): raise TypeError('Height above ground plane should be a scalar.') if ground_plane <= 0.0: raise ValueError('Height above ground plane should be positive.') if dipole_coords is not None: if not isinstance(dipole_coords, str): raise TypeError('dipole_coords must be a string. Allowed values are "altaz" and "dircos"') elif (dipole_coords != 'altaz') and (dipole_coords != 'dircos'): raise ValueError('dipole_coords must be "altaz" or "dircos".') if skycoords is not None: if not isinstance(skycoords, str): raise TypeError('skycoords must be a string. Allowed values are "altaz" and "dircos"') elif (skycoords != 'altaz') and (skycoords != 'dircos'): raise ValueError('skycoords must be "altaz" or "dircos".') if (dipole_coords is None) and (skycoords is None): raise ValueError('At least one of dipole_coords and skycoords must be specified. Allowed values are "altaz" and "dircos"') elif (dipole_coords is not None) and (skycoords is None): skycoords = dipole_coords elif (dipole_coords is None) and (skycoords is not None): dipole_coords = skycoords if (skycoords == 'altaz') or (dipole_coords == 'altaz'): if angle_units is None: angle_units = 'degrees' elif not isinstance(angle_units, str): raise TypeError('angle_units must be a string. Allowed values are "degrees" and "radians".') elif (angle_units != 'degrees') and (angle_units != 'radians'): raise ValueError('angle_units must be "degrees" or "radians".') if skycoords == 'altaz': skypos = NP.asarray(skypos) if angle_units == 'radians': skypos = NP.degrees(skypos) if skypos.ndim < 2: if len(skypos) == 2: skypos = NP.asarray(skypos).reshape(1,2) else: raise ValueError('skypos must be a Nx2 Numpy array.') elif skypos.ndim > 2: raise ValueError('skypos must be a Nx2 Numpy array.') else: if skypos.shape[1] != 2: raise ValueError('skypos must be a Nx2 Numpy array.') elif NP.any(skypos[:,0] < 0.0) or NP.any(skypos[:,0] > 90.0): raise ValueError('Altitudes in skypos have to be positive and <= 90 degrees') skypos_dircos = GEOM.altaz2dircos(skypos, 'degrees') else: if skypos.ndim < 2: if (len(skypos) == 2) or (len(skypos) == 3): skypos = NP.asarray(skypos).reshape(1,-1) else: raise ValueError('skypos must be a Nx2 Nx3 Numpy array.') elif skypos.ndim > 2: raise ValueError('skypos must be a Nx2 or Nx3 Numpy array.') else: if (skypos.shape[1] < 2) or (skypos.shape[1] > 3): raise ValueError('skypos must be a Nx2 or Nx3 Numpy array.') else: if NP.any(NP.abs(skypos[:,0]) > 1.0) or NP.any(NP.abs(skypos[:,1]) > 1.0): raise ValueError('skypos in transverse direction cosine coordinates found to be exceeding unity.') else: if skypos.shape[1] == 3: eps = 1.0e-10 if NP.any(NP.abs(NP.sqrt(NP.sum(skypos**2, axis=1)) - 1.0) > eps) or NP.any(skypos[:,2] < 0.0): print 'Warning: skypos in direction cosine coordinates along line of sight found to be negative or some direction cosines are not unit vectors. Resetting to correct values.' skypos[:,2] = 1.0 - NP.sqrt(NP.sum(skypos[:,:2]**2,axis=1)) else: skypos = NP.hstack((skypos, 1.0 - NP.asarray(NP.sqrt(NP.sum(skypos[:,:2]**2,axis=1))).reshape(-1,1))) skypos_dircos = skypos if dipole_coords == 'altaz': dipole_orientation = NP.asarray(dipole_orientation) if angle_units == 'radians': dipole_orientation = NP.degrees(dipole_orientation) if dipole_orientation.ndim < 2: if len(dipole_orientation) == 2: dipole_orientation = NP.asarray(dipole_orientation).reshape(1,2) else: raise ValueError('dipole_orientation must be a Nx2 Numpy array.') elif dipole_orientation.ndim > 2: raise ValueError('dipole_orientation must be a Nx2 Numpy array.') else: if dipole_orientation.shape[1] != 2: raise ValueError('dipole_orientation must be a Nx2 Numpy array.') elif NP.any(dipole_orientation[:,0] < 0.0) or NP.any(dipole_orientation[:,0] > 90.0): raise ValueError('Altitudes in dipole_orientation have to be positive and <= 90 degrees') dipole_orientation_dircos = GEOM.altaz2dircos(dipole_orientation, 'degrees') else: if dipole_orientation.ndim < 2: if (len(dipole_orientation) == 2) or (len(dipole_orientation) == 3): dipole_orientation = NP.asarray(dipole_orientation).reshape(1,-1) else: raise ValueError('dipole_orientation must be a Nx2 Nx3 Numpy array.') elif dipole_orientation.ndim > 2: raise ValueError('dipole_orientation must be a Nx2 or Nx3 Numpy array.') else: if (dipole_orientation.shape[1] < 2) or (dipole_orientation.shape[1] > 3): raise ValueError('dipole_orientation must be a Nx2 or Nx3 Numpy array.') else: if NP.any(NP.abs(dipole_orientation[:,0]) > 1.0) or NP.any(NP.abs(dipole_orientation[:,1]) > 1.0): raise ValueError('dipole_orientation in transverse direction cosine coordinates found to be exceeding unity.') else: if dipole_orientation.shape[1] == 3: eps = 1.0e-10 if NP.any(NP.abs(NP.sqrt(NP.sum(dipole_orientation**2, axis=1)) - 1.0) > eps) or NP.any(dipole_orientation[:,2] < 0.0): print 'Warning: dipole_orientation in direction cosine coordinates along line of sight found to be negative or some direction cosines are not unit vectors. Resetting to correct values.' dipole_orientation[:,2] = 1.0 - NP.sqrt(NP.sum(dipole_orientation[:,:2]**2,axis=1)) else: dipole_orientation = NP.hstack((dipole_orientation, 1.0 - NP.asarray(NP.sqrt(NP.sum(dipole_orientation[:,:2]**2,axis=1))).reshape(-1,1))) dipole_orientation_dircos = dipole_orientation # PDB.set_trace() k = 2 * NP.pi / wavelength h = 0.5 * length dot_product = NP.dot(dipole_orientation_dircos, skypos_dircos.T) angles = NP.arccos(dot_product) eps = 1.e-10 zero_angles_ind = NP.abs(NP.abs(dot_product) - 1.0) < eps reasonable_angles_ind = NP.abs(NP.abs(dot_product) - 1.0) > eps # field_pattern = NP.empty_like(angles) max_pattern = 1.0 # Normalization factor if half_wave_dipole_approx: field_pattern = NP.cos(0.5 * NP.pi * NP.cos(angles)) / NP.sin(angles) else: max_pattern = 1.0 - NP.cos(k * h) # Maximum occurs at angles = NP.pi / 2 field_pattern = (NP.cos(k * h * NP.cos(angles)) - NP.cos(k * h)) / NP.sin(angles) field_pattern[zero_angles_ind] = k * h * NP.tan(0.5 * angles[zero_angles_ind]) * NP.sin(0.5 * k * h * (1.0 + NP.cos(angles[zero_angles_ind]))) # field_pattern[zero_angles_ind] = 0.0 if ground_plane is not None: # Ground plane formulas to be verified. Use with caution skypos_altaz = GEOM.dircos2altaz(skypos_dircos, 'radians') ground_pattern = 2 * NP.cos(k * ground_plane * NP.sin(skypos_altaz[:,0])) else: ground_pattern = 1.0 return (field_pattern / max_pattern) * ground_pattern
bl_lengths = NP.sqrt(NP.sum(bl ** 2, axis=1)) decl = -27.0 # in degrees lat = -27.0 # in degrees ha_range = 4.0 # in hrs ha_step = 1.0 / 60.0 # in hrs ha = 15.0 * NP.arange(-ha_range / 2, ha_range / 2, ha_step) ha = NP.asarray(ha).reshape(-1, 1) dec = decl + NP.zeros((len(ha), 1)) dec.reshape(-1, 1) hadec = NP.hstack((ha, dec)) altaz = GEOM.hadec2altaz(hadec, lat, units="degrees") dircos = GEOM.altaz2dircos(altaz, units="degrees") dm = DLY.delay_envelope(bl, dircos, units="mks") min_delays = dm[:, :, 1] - dm[:, :, 0] max_delays = NP.sum(dm, axis=2) fig = PLT.figure(figsize=(14, 8)) ax = PLT.axes([0.12, 0.1, 0.8, 0.8]) PLT.xlim(NP.min(bl_lengths) - 1.0, NP.max(bl_lengths) + 100.0) PLT.ylim(1e9 * (NP.min(min_delays) - 1.0e-8), 1e9 * (NP.max(max_delays) + 1.0e-8)) PLT.xlabel("Baseline Length [m]", fontsize=18, weight="semibold") PLT.ylabel("Delay [ns]", fontsize=18, weight="semibold") PLT.title("Delay Envelope", fontsize=18, weight="semibold") hadec_text = ax.text(0.05, 0.9, "", transform=ax.transAxes, fontsize=18)