def func(c1, c2): op1 = Cartesian2SphericalOperator(c1) op2 = Spherical2CartesianOperator(c2) op = op1(op2) if c1 == c2: assert_is_type(op, IdentityOperator) else: assert_is_type(op, CompositionOperator)
def create_random_pointings(center, npointings, dtheta, date_obs=None, period=None, latitude=None, longitude=None, seed=None): """ Return pointings randomly and uniformly distributed in a spherical cap. Parameters ---------- center : 2-tuple The R.A. and declination of the center of the FOV, in degrees. npointings : int The number of requested pointings dtheta : float The maximum angular distance to the center. date_obs : str or astropy.time.Time, optional The starting date of the observation (UTC). period : float, optional The sampling period of the pointings, in seconds. latitude : float, optional The observer's latitude [degrees]. Default is DOMEC's. longitude : float, optional The observer's longitude [degrees]. Default is DOMEC's. """ r = np.random.RandomState(seed) cosdtheta = np.cos(np.radians(dtheta)) theta = np.degrees( np.arccos(cosdtheta + (1 - cosdtheta) * r.rand(npointings))) phi = r.rand(npointings) * 360 pitch = r.rand(npointings) * 360 p = QubicSampling(npointings, date_obs=date_obs, period=period, latitude=latitude, longitude=longitude) time = p.date_obs + TimeDelta(p.time, format='sec') c2s = Cartesian2SphericalOperator('azimuth,elevation', degrees=True) e2h = CartesianEquatorial2HorizontalOperator('NE', time, p.latitude, p.longitude) rot = Rotation3dOperator("ZY'", center[0], 90 - center[1], degrees=True) s2c = Spherical2CartesianOperator('zenith,azimuth', degrees=True) rotation = c2s(e2h(rot(s2c))) coords = rotation(np.asarray([theta.T, phi.T]).T) p.azimuth = coords[..., 0] p.elevation = coords[..., 1] p.pitch = pitch p.angle_hwp = r.random_integers(0, 7, npointings) * 11.25 p.fix_az = False return p
def func(c, v, s, d, r): orig = v if not d: v = np.radians(v) s2c = Spherical2CartesianOperator(c, degrees=d) c2s = Cartesian2SphericalOperator(c, degrees=d) assert_allclose(s2c(v), r) a = c2s(s2c(v)) if not d: a = np.degrees(a) assert_equal(a.shape, s + (2, )) assert_allclose(a, orig, atol=1e-16)
def test_spherical_cartesian_error(): assert_raises(TypeError, Spherical2CartesianOperator, 3) assert_raises(ValueError, Spherical2CartesianOperator, 'bla') op = Spherical2CartesianOperator('zenith,azimuth') def func(i, o): if i.shape == (2, ) and o.shape == (3, ): op(i, o) return assert_raises(ValueError, op.__call__, i, o) for i, o in itertools.product((np.array(1.), np.zeros(2), np.zeros(3)), (np.array(1.), np.zeros(2), np.zeros(3))): yield func, i, o
def test_spherical_cartesian_rules(): def func(c1, c2): op1 = Spherical2CartesianOperator(c1) op2 = Cartesian2SphericalOperator(c2) op = op1(op2) if c1 == c2: assert_is_type(op, IdentityOperator) else: assert_is_type(op, CompositionOperator) for c1 in 'zenith,azimuth', 'azimuth,elevation': op = Spherical2CartesianOperator(c1) assert_is_type(op.I, Cartesian2SphericalOperator) assert_equal(op.convention, c1) for c2 in 'zenith,azimuth', 'azimuth,elevation': yield func, c1, c2
def func(cls_sph, cls_car, cin, cout, v, s, d): if 'Horizontal' in str(cls_sph): args = ('NE', Time('1980-04-22 14:36:51.67', scale='ut1'), 100.1, -80) else: args = () op_sph = cls_sph(*args, conventionin=cin, conventionout=cout, degrees=d) actual = op_sph(v) assert_equal(actual.shape, s + (2, )) if d: v = np.radians(v) expected = Cartesian2SphericalOperator(cout)(cls_car(*args)( Spherical2CartesianOperator(cin)(v))) if d: np.degrees(expected, expected) assert_same(actual, expected)
def test_spherical_cartesian(): dirs_za = ((0, 0), (20, 0), (130, 0), (10, 20), (20, 190), ((0, 0), (20, 0), (130, 0), (10, 20), (20, 130)), (((0, 0), (20, 200), (130, 300)), )) dirs_az = ((0, 0), (0, 20), (0, 130), (20, 10), (190, 20), ((0, 0), (0, 20), (0, 130), (20, 10), (130, 20)), (((0, 0), (200, 20), (300, 130)), )) dirs_ea = ((90, 0), (70, 0), (-40, 0), (80, 20), (70, 190), ((90, 0), (70, 0), (-40, 0), (80, 20), (70, 130)), (((90, 0), (70, 200), (-40, 300)), )) dirs_ae = ((0, 90), (0, 70), (0, -40), (20, 80), (190, 70), ((0, 90), (0, 70), (0, -40), (20, 80), (130, 70)), (((0, 90), (200, 70), (300, -40)), )) shapes = ((), (), (), (), (), (5, ), (1, 3)) op_ref = Spherical2CartesianOperator('zenith,azimuth') refs = [op_ref(np.radians(v)) for v in dirs_za] def func(c, v, s, d, r): orig = v if not d: v = np.radians(v) s2c = Spherical2CartesianOperator(c, degrees=d) c2s = Cartesian2SphericalOperator(c, degrees=d) assert_allclose(s2c(v), r) a = c2s(s2c(v)) if not d: a = np.degrees(a) assert_equal(a.shape, s + (2, )) assert_allclose(a, orig, atol=1e-16) for c, vs in (('zenith,azimuth', dirs_za), ('azimuth,zenith', dirs_az), ('elevation,azimuth', dirs_ea), ('azimuth,elevation', dirs_ae)): for v, s, r in zip(vs, shapes, refs): for d in (False, True): yield func, c, v, s, d, r
def test_equ2hor(): lat = 52 lon = -64 date = Time('1980-04-22 14:36:51.67', scale='ut1') E2h = CartesianEquatorial2HorizontalOperator gst = E2h._jd2gst(date.jd) lst = E2h._gst2lst(gst, lon) # Duffett-Smith §21 assert_allclose(gst, 4.668119) assert_allclose(lst, 0.401453, rtol=1e-6) ra = Angle(lst - 5.862222, unit='hour').radian dec = Angle((23, 13, 10), unit='degree').radian s2c = Spherical2CartesianOperator('azimuth,elevation') op = CartesianEquatorial2HorizontalOperator('NE', date, lat, lon) incoords = s2c([ra, dec]) outcoords = op(incoords) assert_same(op.I(outcoords), incoords) az, el = np.degrees(s2c.I(outcoords)) # Duffett-Smith §25 assert_allclose(az % 360, 283.271027) assert_allclose(el, 19.334345, rtol=1e-6)
def spherical2cartesian(self): return Spherical2CartesianOperator('azimuth,elevation', degrees=self.degrees)
def create_repeat_pointings(center, npointings, dtheta, nhwp_angles=3, date_obs=None, period=None, latitude=None, longitude=None, seed=None): """ Return pointings randomly and uniformly distributed in a spherical cap. The same pointing is repeated nhwp_angles times with a different hwp angle each time. Parameters ---------- center : 2-tuple The R.A. and declination of the center of the FOV, in degrees. npointings : int The number of requested pointings dtheta : float The maximum angular distance to the center. nhwp_angles : int The number of HWP angles used. date_obs : str or astropy.time.Time, optional The starting date of the observation (UTC). period : float, optional The sampling period of the pointings, in seconds. latitude : float, optional The observer's latitude [degrees]. Default is DOMEC's. longitude : float, optional The observer's longitude [degrees]. Default is DOMEC's. seed : int Random seed. """ r = np.random.RandomState(seed) nrandom = np.int(npointings / nhwp_angles) # number of real random pointings # Creation of nrandom pointing cosdtheta = np.cos(np.radians(dtheta)) theta = np.degrees(np.arccos(cosdtheta + (1 - cosdtheta) * r.rand(nrandom))) phi = r.rand(nrandom) * 360 pitch = r.rand(nrandom) * 360 p = QubicSampling(nrandom, date_obs=date_obs, period=period, latitude=latitude, longitude=longitude) time = p.date_obs + TimeDelta(p.time, format='sec') c2s = Cartesian2SphericalOperator('azimuth,elevation', degrees=True) e2h = CartesianEquatorial2HorizontalOperator('NE', time, p.latitude, p.longitude) rot = Rotation3dOperator("ZY'", center[0], 90 - center[1], degrees=True) s2c = Spherical2CartesianOperator('zenith,azimuth', degrees=True) rotation = c2s(e2h(rot(s2c))) coords = rotation(np.asarray([theta.T, phi.T]).T) p.azimuth = coords[..., 0] p.elevation = coords[..., 1] p.pitch = pitch p.fix_az = False # Replication of the same pointing with others fix hwp angles pp = QubicSampling(nrandom * nhwp_angles, date_obs=date_obs, period=period, latitude=latitude, longitude=longitude) pp.azimuth = np.tile(p.azimuth, nhwp_angles) pp.elevation = np.tile(p.elevation, nhwp_angles) pp.pitch = np.tile(p.pitch, nhwp_angles) pp.time = np.tile(p.time, nhwp_angles) pp.angle_hwp = np.zeros(nrandom * nhwp_angles) pp.fix_az = False for hwp in range(nhwp_angles): pp.angle_hwp[hwp * nrandom:(hwp + 1) * nrandom] = np.array( np.rad2deg(hwp * np.pi / (nhwp_angles * 2))) return pp
def _get_projection_operator(rotation, scene, nu, position, synthbeam, horn, primary_beam, verbose=True): ndetectors = position.shape[0] ntimes = rotation.data.shape[0] nside = scene.nside thetas, phis, vals = QubicInstrument._peak_angles( scene, nu, position, synthbeam, horn, primary_beam) ncolmax = thetas.shape[-1] thetaphi = _pack_vector(thetas, phis) # (ndetectors, ncolmax, 2) direction = Spherical2CartesianOperator('zenith,azimuth')(thetaphi) e_nf = direction[:, None, :, :] if nside > 8192: dtype_index = np.dtype(np.int64) else: dtype_index = np.dtype(np.int32) cls = { 'I': FSRMatrix, 'QU': FSRRotation2dMatrix, 'IQU': FSRRotation3dMatrix }[scene.kind] ndims = len(scene.kind) nscene = len(scene) nscenetot = product(scene.shape[:scene.ndim]) s = cls((ndetectors * ntimes * ndims, nscene * ndims), ncolmax=ncolmax, dtype=synthbeam.dtype, dtype_index=dtype_index, verbose=verbose) index = s.data.index.reshape((ndetectors, ntimes, ncolmax)) c2h = Cartesian2HealpixOperator(nside) if nscene != nscenetot: table = np.full(nscenetot, -1, dtype_index) table[scene.index] = np.arange(len(scene), dtype=dtype_index) def func_thread(i): # e_nf[i] shape: (1, ncolmax, 3) # e_ni shape: (ntimes, ncolmax, 3) e_ni = rotation.T(e_nf[i].swapaxes(0, 1)).swapaxes(0, 1) if nscene != nscenetot: np.take(table, c2h(e_ni).astype(int), out=index[i]) else: index[i] = c2h(e_ni) with pool_threading() as pool: pool.map(func_thread, xrange(ndetectors)) if scene.kind == 'I': value = s.data.value.reshape(ndetectors, ntimes, ncolmax) value[...] = vals[:, None, :] shapeout = (ndetectors, ntimes) else: if str(dtype_index) not in ('int32', 'int64') or \ str(synthbeam.dtype) not in ('float32', 'float64'): raise TypeError( 'The projection matrix cannot be created with types: {0} a' 'nd {1}.'.format(dtype_index, synthbeam.dtype)) func = 'matrix_rot{0}d_i{1}_r{2}'.format(ndims, dtype_index.itemsize, synthbeam.dtype.itemsize) getattr(flib.polarization, func)(rotation.data.T, direction.T, s.data.ravel().view(np.int8), vals.T) if scene.kind == 'QU': shapeout = (ndetectors, ntimes, 2) else: shapeout = (ndetectors, ntimes, 3) return ProjectionOperator(s, shapeout=shapeout)
def _index2coord(nside, index): s2c = Spherical2CartesianOperator('zenith,azimuth') t, p = hp.pix2ang(nside, index) return t, p, s2c(np.concatenate([t[..., None], p[..., None]], axis=-1))
def create_hall_pointing(d, az, el, hor_center, angspeed_psi=0, maxpsi=0, period=0, fillfield=False, date_obs=None, latitude=None, longitude=None, doplot=False, fix_azimuth=None, random_hwp=True, verbose=False): ''' Model of the pointing used in the hall. No back and forth. Input coordinates are az, el. The function authomatically will convert (az, el) into (phi, theta) defined as qubic.sampling.create_random_pointing to match with qubicsoft. The coverage map center the region in hor_center coordinates. Take it into account for plotting and projecting maps Parameters: d: QUBIC dictionary az, el: azimuth and elevation data from housekeeping data or fits file. 1-d array period: QubicSampling parameter. If equal to zero, it matches with transformation from az,el to ra, dec using qubic.hor2equ(az, el time = 0). Otherwise is not equal. Default: zero. hor_center: center of the FOV Return: QUBIC's pointing object ''' if fillfield: az = np.arange(az[0], az[-1], hp.nside2resol(d['nside'], arcmin=True) / 60) el = np.arange(el[0], el[-1], hp.nside2resol(d['nside'], arcmin=True) / 60) nsamples = len(az) * len(el) mult_az, mult_el = generate_region(az, el) theta = np.array(mult_el) #- np.mean(el) phi = np.array(mult_az[0]) #- np.mean(az) # By defalut it computes HorizontalSampling in with SphericalSamplig pp = qubic.QubicSampling( nsamples, #azimuth = mult_az[0], elevation = mult_el[0], date_obs=d['date_obs'], period=period, latitude=latitude, longitude=longitude) time = pp.date_obs + TimeDelta(pp.time, format='sec') print("time", np.shape(time)) c2s = Cartesian2SphericalOperator('azimuth,elevation', degrees=True) h2e = CartesianHorizontal2EquatorialOperator('NE', time, pp.latitude, pp.longitude) s2c = Spherical2CartesianOperator('elevation,azimuth', degrees=True) rotation = c2s(h2e(s2c)) coords = rotation(np.asarray([theta.T, phi.T]).T) pp.elevation = mult_el pp.azimuth = mult_az[0] pp.equatorial[:, 0] = coords[:, 0] pp.equatorial[:, 1] = coords[:, 1] if doplot: fig, ax = subplots(nrows=1, ncols=1, figsize=(14, 6)) pixsH = hp.ang2pix(d['nside'], np.radians(90 - theta), np.radians(phi)) mapaH = np.ones((12 * d['nside']**2)) mapaH[pixsH] = 100 axes(ax) hp.gnomview(mapaH, title="Horizontal coordinates Nside = {}".format( d['nside']), reso=12, xsize=320, ysize=190, rot=[np.mean(phi), np.mean(theta)], hold=True, cbar=False) hp.graticule(verbose=False, dmer=10, dpar=10) #pixsEq = hp.ang2pix(d['nside'], np.radians(90 - pp.equatorial[:,1]), np.radians(pp.equatorial[:,0])) #mapaEq = np.ones((12*d['nside']**2)) #mapaEq[pixsEq] = 100 #axes(ax[1]) #hp.mollview(mapaEq, title = "Equatorial coordinates", hold = True) #hp.graticule(verbose = False) azcen_fov, elcen_fov = hor_center[0], hor_center[1] if period < 1e-4: newcenter = qubic.hor2equ(azcen_fov, elcen_fov, 0) else: newcenter = qubic.hor2equ(azcen_fov, elcen_fov, pp.time[int(len(pp.time) / 2)]) warn("Update RA, DEC in dictionary") d['RA_center'], d['DEC_center'] = newcenter[0], newcenter[1] # center = ra, dec #center = (d['RA_center'], d['DEC_center']) if verbose: print("Time: len(time) = {} \n t0 {} \n time/2 {} \n tf {}".format( time, time[0], time[int(len(time) / 2)], time[-1])) ### scan psi as well, pitch = pp.time * angspeed_psi pitch = pitch % (4 * maxpsi) mask = pitch > (2 * maxpsi) pitch[mask] = -pitch[mask] + 4 * maxpsi pitch -= maxpsi pp.pitch = pitch if random_hwp: pp.angle_hwp = np.random.randint(0, 7, nsamples) * 11.25 if d['fix_azimuth']['apply']: pp.fix_az = True if d['fix_azimuth']['fix_hwp']: pp.angle_hwp = pp.pitch * 0 + 11.25 if d['fix_azimuth']['fix_pitch']: pp.pitch = 0 else: pp.fix_az = False return pp
def create_random_pointings(center, npointings, dtheta, hwp_stepsize, date_obs=None, period=None, latitude=None, longitude=None, seed=None): """ Return pointings randomly and uniformly distributed in a spherical cap. 1) Creates random coordinates theta, phi. Range: 0 < theta < dtheta, 0 < phi < 360 (then are converted from spherical to cartesian coordinates), 2) It rotates the points to center them in direction (RA, DEC) using Rotation3dOperator (equatorial reference system) 3) Convertion: Equatorial to Horizontal reference system (using CartesianEquatorial2HorizontalOperator's operator) 4) Back to cartesian coordinates (using Cartesian2SphericalOperator) Parameters ---------- center : 2-tuple The R.A. and declination of the center of the FOV, in degrees. npointings : int The number of requested pointings dtheta : float The maximum angular distance to the center. hwp_stepsize : float Step angle size for the HWP. date_obs : str or astropy.time.Time, optional The starting date of the observation (UTC). period : float, optional The sampling period of the pointings, in seconds. latitude : float, optional The observer's latitude [degrees]. Default is DOMEC's. longitude : float, optional The observer's longitude [degrees]. Default is DOMEC's. seed : int Random seed. """ r = np.random.RandomState(seed) cosdtheta = np.cos(np.radians(dtheta)) theta = np.degrees( np.arccos(cosdtheta + (1 - cosdtheta) * r.rand(npointings))) phi = r.rand(npointings) * 360 pitch = r.rand(npointings) * 360 p = QubicSampling(npointings, date_obs=date_obs, period=period, latitude=latitude, longitude=longitude) time = p.date_obs + TimeDelta(p.time, format='sec') c2s = Cartesian2SphericalOperator('azimuth,elevation', degrees=True) e2h = CartesianEquatorial2HorizontalOperator('NE', time, p.latitude, p.longitude) rot = Rotation3dOperator("ZY'", center[0], 90 - center[1], degrees=True) s2c = Spherical2CartesianOperator('zenith,azimuth', degrees=True) rotation = c2s(e2h(rot(s2c))) coords = rotation(np.asarray([theta.T, phi.T]).T) p.azimuth = coords[..., 0] p.elevation = coords[..., 1] p.pitch = pitch p.fix_az = False p.angle_hwp = r.randint(0, int(90 / hwp_stepsize + 1), npointings) * hwp_stepsize return p
def func(c, v, s, d): c2s = Cartesian2SphericalOperator(c, degrees=d) s2c = Spherical2CartesianOperator(c, degrees=d) a = s2c(c2s(v)) assert_equal(a.shape, s + (3, )) assert_allclose(a, v, atol=1e-16)