예제 #1
0
 def test_400_child(self):
     dets = ['det0', 'det1', 'det2']
     n, ofs = 1000, 0
     aman = core.AxisManager(core.LabelAxis('dets', dets),
                             core.OffsetAxis('samps', n, ofs))
     child = core.AxisManager(core.LabelAxis('dets', dets + ['det3']),
                              core.OffsetAxis('samps', n, ofs - n // 2))
     aman.wrap('child', child)
     self.assertEqual(aman.shape, (3, n // 2))
     self.assertEqual(aman._axes['samps'].offset, ofs)
예제 #2
0
 def test_410_merge(self):
     dets = ['det0', 'det1', 'det2']
     n, ofs = 1000, 0
     aman = core.AxisManager(core.LabelAxis('dets', dets),
                             core.OffsetAxis('samps', n, ofs))
     coparent = core.AxisManager(
         core.LabelAxis('dets', dets + ['det3']),
         core.OffsetAxis('samps', n, ofs - n//2))\
         .wrap('x', np.arange(n), [(0, 'samps')])
     aman.merge(coparent)
     self.assertEqual(aman.shape, (3, n // 2))
     self.assertEqual(aman._axes['samps'].offset, ofs)
     self.assertEqual(aman.x[0], n // 2)
예제 #3
0
 def test_900_everything(self):
     tod = core.AxisManager(core.LabelAxis('dets', list('abcdef')),
                            core.OffsetAxis('samps', 1000))
     cal = core.AxisManager(core.LabelAxis('dets', list('feghij')))
     cuts = core.AxisManager(core.OffsetAxis('samps', 800, 100))
     tod.wrap(
         'data',
         np.ones(tod.shape, 'float32'),
     )
     cal.wrap('cal', np.linspace(.9, 1.2, 6), [(0, 'dets')])
     cuts.wrap('cuts', np.ones(cuts.shape, 'int32'), [(0, 'samps')])
     tod.merge(cal, cuts)
     self.assertEqual(tod.shape, (2, 800))
예제 #4
0
    def test_120_label(self):
        dets = ['det0', 'det1', 'det2']
        a1 = np.zeros(len(dets))
        a1[1] = 1.
        aman = core.AxisManager(core.LabelAxis('dets', dets))
        aman.wrap('a1', a1, [(0, 'dets')])
        aman.restrict('dets', ['det1'])
        self.assertNotEqual(aman.a1[0], 0.)

        # Don't let people use non string labels
        dets_int = [0, 1, 2]
        with self.assertRaises(TypeError):
            aman = core.AxisManager(core.LabelAxis('dets', dets_int))
예제 #5
0
    def test_160_scalars(self):
        aman = core.AxisManager(core.LabelAxis('dets', ['a', 'b']),
                                core.OffsetAxis('samps', 100))

        # Accept trivially promoted scalars
        aman.wrap('x', 12)
        aman.wrap('z', 'hello')

        # Check that numpy int/float types are unpacked.
        aman.wrap('a', np.int32(12))
        aman.wrap('b', np.float32(12.))
        aman.wrap('c', np.str_('twelve'))
        self.assertNotIsInstance(aman['a'], np.integer)
        self.assertNotIsInstance(aman['b'], np.floating)
        self.assertNotIsInstance(aman['c'], np.str_)

        # Don't let people wrap the same scalar twice
        with self.assertRaises(ValueError):
            aman.wrap('x', 13)

        # Don't just let people wrap any old thing.
        with self.assertRaises(AttributeError):
            aman.wrap('a_dict', {'a': 123})
        with self.assertRaises(ValueError):
            aman.wrap('square_root', 1j)
예제 #6
0
    def test_500_io(self):
        # Test save/load HDF5
        dets = ['det0', 'det1', 'det2']
        n, ofs = 1000, 0
        aman = core.AxisManager(core.LabelAxis('dets', dets),
                                core.OffsetAxis('samps', n, ofs),
                                core.IndexAxis('indexaxis', 12))
        # Make sure this has axes, scalars, a string array ...
        aman.wrap_new('test1', ('dets', 'samps'), dtype='float32')
        aman.wrap_new('flag1',
                      shape=('dets', 'samps'),
                      cls=so3g.proj.RangesMatrix.zeros)
        aman.wrap('scalar', 8)
        aman.wrap('test_str', np.array(['a', 'b', 'cd']))
        aman.wrap('flags', core.FlagManager.for_tod(aman, 'dets', 'samps'))

        aman.wrap('a', np.int32(12))
        aman.wrap('b', np.float32(12.))
        aman.wrap('c', np.str_('twelve'))
        aman.wrap('d', np.bool_(False))

        with tempfile.TemporaryDirectory() as tempdir:
            filename = os.path.join(tempdir, 'test.h5')
            aman.save(filename, 'my_axisman')
            aman2 = aman.load(filename, 'my_axisman')
            shutil.copy(filename, 'debug.h5')
        # This is not a very satisfying comparison ... support for ==
        # should be required for all AxisManager members!
        for k in aman._fields.keys():
            self.assertEqual(aman[k].__class__, aman2[k].__class__)
            if hasattr(aman[k], 'shape'):
                self.assertEqual(aman[k].shape, aman2[k].shape)
            else:
                self.assertEqual(aman[k], aman2[k])  # scalar
예제 #7
0
파일: pca.py 프로젝트: simonsobs/sotodlib
def get_pca_model(tod=None, pca=None, n_modes=None, signal=None,
                  wrap=None, wrap_pca=None):
    """Convert a PCA decomposition into the signal basis, i.e. into
    time-dependent modes that one might use for cleaning or
    calibrating.

    The generalization of "common mode" computation is to convert the
    eigen-decomposition of the covariance matrix into a limited set of
    modes that explain a high fraction of the power in the input
    signals.

    Here we select the strongest eigenmodes from the PCA and compute
    the time-dependent modes and the projection of each detector
    signal onto each mode.  An approximation for the input signal may
    then be computed as

       signal_model = weights . modes

    where weights has shape (dets, eigen), modes has shape (eigen,
    samps), and . indicates matrix multipliaction.  The size of the
    eigen axis can be as large as the number of dets, but is typically
    smaller and in this routine is set by n_modes.

    Arguments:
        tod: AxisManager with dets and samps axes.
        pca: AxisManager holding a PCA decomposition, as returned by
            get_pca.  If not specified, it will be computed from the
            data.
        n_modes: integer specifying the number of modes to compute;
            the strongest modes are taken and this sets the size of
            the "eigen" axis in the output.  Defaults to len(dets),
            but beware that the resulting data object will be the same
            size as the input signal.
        signal: array of shape (dets, samps) that is used to construct
            the requested eigen modes.  If pca is not passed in, this
            signal is also used to compute the covariance for PCA.
        wrap: string; if specified then the returned result is also
            stored in tod under that name.

    Returns:
        An AxisManager with (dets, eigen, samps) axes.  The field
        'weights' has shape (dets, eigen) and the field 'modes' has
        shape (eigen, samps).

    """
    if pca is None:
        pca = get_pca(tod=tod, signal=signal)
    if n_modes is None:
        n_modes = pca.eigen.count

    mode_axis = core.IndexAxis('eigen', n_modes)
    output = core.AxisManager(tod.dets, mode_axis, tod.samps)
    if signal is None:
        signal = tod.signal

    R = pca.R[:, :n_modes]
    output.wrap('weights', R, [(0, 'dets'), (1, 'eigen')])
    output.wrap('modes', np.dot(R.transpose(), signal),
                [(0, 'eigen'), (1, 'samps')])
    return output
예제 #8
0
    def unpack(self, packed_items, dest=None):
        """Unpack items from packed_items, and return then in a single
        AxisManager.

        """
        if dest is None:
            dest = core.AxisManager()
        for unpackers, metadata_instance in packed_items:
            # Convert to AxisManager...
            if isinstance(metadata_instance, core.AxisManager):
                child_axes = metadata_instance
            else:
                child_axes = metadata_instance.axismanager(detdb=self.detdb)
            fields_to_delete = list(child_axes._fields.keys())
            # Unpack to requested field names.
            for unpack in unpackers:
                if unpack.src is None:
                    dest.wrap(unpack.dest, child_axes)
                    break
                else:
                    fields_to_delete.remove(unpack.src)
                    if unpack.src != unpack.dest:
                        child_axes.move(unpack.src, unpack.dest)
            else:
                for f in fields_to_delete:
                    child_axes.move(f, None)
                dest.merge(child_axes)
        return dest
예제 #9
0
def load_act_cuts(filename, pa=None):
    """Read ACT cuts file and return an AxisManager containing the flags.

    The pa is needed to define the dets axis properly, but if passed
    as None then the code will try to determine it by searching for a
    standard ACT TOD basename in filename.
n
    """
    if pa is None:
        _, _, _, ar = extract_basename(filename)
        pa = 'pa' + ar[-1]

    cuts_in = moby2.tod.TODCuts.from_actpol_cuts_file(filename)
    det_names = ['%s_%04i' % (pa, u) for u in cuts_in.det_uid]

    flags = []
    for d, c in zip(det_names, cuts_in.cuts):
        i = so3g.proj.Ranges.from_array(c + cuts_in.sample_offset, cuts_in.nsamps)
        flags.append(i)
    flags = so3g.proj.RangesMatrix(flags)

    aman = core.AxisManager(
        core.LabelAxis('dets', det_names),
        core.OffsetAxis('samps', cuts_in.nsamps, cuts_in.sample_offset),
    )

    aman.wrap('flags', flags, [(0, 'dets'), (1, 'samps')])
    return aman
예제 #10
0
    def test_10_kernels(self):
        """Test creation of sensible WCS kernels for basic cases."""
        ra0, dec0 = CRVAL
        res = 0.01 * DEG

        # Test zenithal -- (ra0, dec0) is the reference point.
        for proj in ['TAN', 'ZEA']:
            wcsk = coords.get_wcs_kernel(proj, ra0, dec0, res)
            msg = f'Check crpix for {proj}'
            self.assertAlmostEqual(wcsk.wcs.crpix[0], 1, delta=TOL_RAD, msg=msg)
            self.assertAlmostEqual(wcsk.wcs.crpix[1], 1, delta=TOL_RAD, msg=msg)

        # Test cylindrical -- pixell puts the crval[1] on the equator
        # and dec0 is used for the conformal latitude.
        for proj in ['CAR', 'CEA']:
            wcsk = coords.get_wcs_kernel(proj, ra0, dec0, res)
            msg = f'Check crpix for {proj}'
            self.assertAlmostEqual(wcsk.wcs.crpix[0], 1, delta=TOL_RAD, msg=msg)
            self.assertNotAlmostEqual(wcsk.wcs.crpix[1], 1, delta=TOL_RAD, msg=msg)

        # This is going to break.
        fp = FP(xi =[0., -0.01*DEG],
                eta=[0., -0.01*DEG])
        sight = get_sightline()
        tod = core.AxisManager(core.LabelAxis('dets', ['a']))
        fp = coords.get_footprint(tod, wcs_kernel=wcsk, focal_plane=fp, sight=sight)
예제 #11
0
 def test_120_label(self):
     dets = ['det0', 'det1', 'det2']
     a1 = np.zeros(len(dets))
     a1[1] = 1.
     aman = core.AxisManager(core.LabelAxis('dets', dets))
     aman.wrap('a1', a1, [(0, 'dets')])
     aman.restrict('dets', ['det1'])
     self.assertNotEqual(aman.a1[0], 0.)
예제 #12
0
 def test_100_index(self):
     a1 = np.zeros(100)
     a1[10] = 1.
     aman = core.AxisManager(core.IndexAxis('samps', len(a1)))
     aman.wrap('a1', a1, [(0, 'samps')])
     aman.restrict('samps', (10, 30))
     self.assertNotEqual(aman.a1[0], 0.)
     self.assertEqual(len(aman.a1), 20)
예제 #13
0
 def test_401_restrict(self):
     # Test AxisManager.restrict when it has AxisManager members.
     dets = ['det0', 'det1', 'det2']
     n, ofs = 1000, 0
     for in_place in [True, False]:
         aman = core.AxisManager(core.LabelAxis('dets', dets),
                                 core.OffsetAxis('samps', n, ofs))
         child = core.AxisManager(aman.dets, aman.samps)
         child2 = core.AxisManager(
             core.LabelAxis('not_dets', ['x', 'y', 'z']))
         aman.wrap('child', child)
         aman.wrap('rebel_child', child2)
         aout = aman.restrict('dets', ['det1'], in_place=in_place)
         msg = f'Note restrict was with in_place={in_place}'
         self.assertTrue(aout is aman or not in_place, msg=msg)
         self.assertEqual(aout['child'].shape, (1, n), msg=msg)
         self.assertIn('rebel_child', aout, msg=msg)
         self.assertEqual(aout['rebel_child'].shape, (3, ), msg=msg)
예제 #14
0
 def test_200_multid(self):
     dets = ['det0', 'det1', 'det2']
     a1 = np.zeros((len(dets), len(dets)))
     a1[2, 2] = 1.
     aman = core.AxisManager(core.LabelAxis('dets', dets))
     aman.wrap('a1', a1, [(0, 'dets'), (1, 'dets')])
     aman.restrict('dets', ['det1', 'det2'])
     self.assertEqual(aman.a1.shape, (2, 2))
     self.assertNotEqual(aman.a1[1, 1], 0.)
예제 #15
0
 def test_valid_arg(self):
     from sotodlib.coords.helpers import _valid_arg
     tod = core.AxisManager()
     tod.wrap('a', np.array([1,2,3]))
     self.assertIs(_valid_arg(None, 'a', src=tod), tod.a)
     self.assertIs(_valid_arg('a', None, src=tod), tod.a)
     self.assertIs(_valid_arg(None, tod.a), tod.a)
     self.assertIs(_valid_arg(tod.get('b')), None)
     self.assertIs(_valid_arg(tod.get('b'), 'a', src=tod), tod.a)
예제 #16
0
 def test_110_offset(self):
     a1 = np.zeros(100)
     # Place the mark at index 10, and offset 15 -- so the mark is
     # at absolute index 25.
     a1[10] = 1.
     aman = core.AxisManager(core.OffsetAxis('samps', len(a1), 15))
     aman.wrap('a1', a1, [(0, 'samps')])
     aman.restrict('samps', (25, 30))
     self.assertNotEqual(aman.a1[0], 0.)
     self.assertEqual(len(aman.a1), 5)
예제 #17
0
 def test_100_index(self):
     a1 = np.zeros(100)
     a1[10] = 1.
     aman = core.AxisManager(core.IndexAxis('samps', len(a1)))
     aman.wrap('a1', a1, [(0, 'samps')])
     # Don't let people wrap the same field twice
     with self.assertRaises(ValueError):
         aman.wrap('a1', 2 * a1, [(0, 'samps')])
     aman.restrict('samps', (10, 30))
     self.assertNotEqual(aman.a1[0], 0.)
     self.assertEqual(len(aman.a1), 20)
예제 #18
0
 def test_130_not_inplace(self):
     a1 = np.zeros(100)
     a1[10] = 1.
     aman = core.AxisManager(core.IndexAxis('samps', len(a1)))
     aman.wrap('a1', a1, [(0, 'samps')])
     # This should return a separate thing.
     rman = aman.restrict('samps', (10, 30), in_place=False)
     #self.assertNotEqual(aman.a1[0], 0.)
     self.assertEqual(len(aman.a1), 100)
     self.assertEqual(len(rman.a1), 20)
     self.assertNotEqual(aman.a1[10], 0.)
     self.assertNotEqual(rman.a1[0], 0.)
예제 #19
0
 def test_300_restrict(self):
     dets = ['det0', 'det1', 'det2']
     n, ofs = 1000, 5000
     aman = core.AxisManager(core.LabelAxis('dets', dets),
                             core.OffsetAxis('samps', n, ofs))
     # Super-correlation matrix.
     a1 = np.zeros((len(dets), len(dets), n, n))
     a1[1, 1, 20, 21] = 1.
     aman.wrap('a1', a1, [(0, 'dets'), (1, 'dets'), (2, 'samps'),
                          (3, 'samps')])
     aman.restrict('dets', ['det1']).restrict('samps', (20 + ofs, 30 + ofs))
     self.assertEqual(aman.shape, (1, 10))
     self.assertEqual(aman.a1.shape, (1, 1, 10, 10))
     self.assertNotEqual(aman.a1[0, 0, 0, 1], 0.)
예제 #20
0
 def test_150_wrap_new(self):
     dets = ['det0', 'det1', 'det2']
     a1 = np.zeros((len(dets), 100))
     a1[1, 10] = 1.
     aman = core.AxisManager(core.LabelAxis('dets', dets),
                             core.OffsetAxis('samps', a1.shape[1]))
     x = aman.wrap_new('x', shape=('dets', 'samps'))
     y = aman.wrap_new('y', shape=('dets', 'samps'), dtype='float32')
     self.assertEqual(aman.x.shape, aman.y.shape)
     if hasattr(so3g.proj.RangesMatrix, 'zeros'):
         # Jan 2021 -- some so3g might not have this method yet...
         f = aman.wrap_new('f',
                           shape=('dets', 'samps'),
                           cls=so3g.proj.RangesMatrix.zeros)
         self.assertEqual(aman.x.shape, aman.f.shape)
예제 #21
0
파일: pca.py 프로젝트: simonsobs/sotodlib
def get_pca(tod=None, cov=None, signal=None, wrap=None):
    """Compute a PCA decomposition of the kind useful for signal analysis.
    A symmetric non-negative matrix cov of shape(n_dets, n_dets) can
    be decomposed into matrix R (same shape) and vector E (length
    n_dets) such that

        cov = R . diag(E) . R^T

    with . denoting matrix multiplication and T denoting matrix
    transposition.

    Arguments:
        tod: AxisManager with dets and samps axes.
        cov: covariance matrix to decompose; if None then cov is
            computed from tod.signal (or signal).
        signal: array of shape (dets, samps).  If cov is not provided,
            it will be computed from this matrix.  Defaults to
            tod.signal.
        wrap: string; if set then the returned result is also stored
            in tod under this name.

    Returns:
        AxisManager with axes 'dets' and 'eigen' (of the same length),
        containing fields 'R' of shape (dets, eigen) and 'E' of shape
        (eigen).  The eigenmodes are sorted from strongest to weakest.

    """
    if cov is None:
        # Compute it from signal
        if signal is None:
            signal = tod.signal
        cov = np.cov(signal)
    dets = tod.dets

    mode_axis = core.IndexAxis('eigen', dets.count)
    output = core.AxisManager(dets, mode_axis)
    output.wrap('cov', cov, [(0, dets.name), (1, dets.name)])

    E, R = np.linalg.eig(cov)  # eigh nans sometimes...
    E[np.isnan(E)] = 0.
    idx = np.argsort(-E)
    output.wrap('E', E[idx], [(0, mode_axis.name)])
    output.wrap('R', R[:, idx], [(0, dets.name), (1, mode_axis.name)])
    return output
예제 #22
0
def get_tod(sig_type='trendy'):
    tod = core.AxisManager(core.LabelAxis('dets', ['a', 'b', 'c']),
                           core.IndexAxis('samps', 1000))
    tod.wrap_new('signal', ('dets', 'samps'), dtype='float32')
    tod.wrap_new('timestamps', ('samps', ))[:] = (np.arange(tod.samps.count) /
                                                  SAMPLE_FREQ_HZ)
    if sig_type == 'zero':
        pass
    elif sig_type == 'trendy':
        x = np.linspace(0, 1., tod.samps.count)
        tod.signal[:] = [(i + 1) + (i + 1)**2 * x
                         for i in range(tod.dets.count)]
    elif sig_type == 'white':
        tod.signal = np.random.normal(size=tod.shape)
    elif sig_type == 'red':
        tod.signal = np.random.normal(size=tod.shape)
        tod.signal[:] = np.cumsum(tod.signal, axis=1)
    else:
        raise RuntimeError(f'sig_type={sig_type}?')
    return tod
예제 #23
0
def load_act_cal(filename, pa=None):
    """Read ACT relcal file and return an AxisManager containing the
    info.

    The pa is needed to define the dets axis properly, but if passed
    as None then the code will try to determine it by searching for a
    standard ACT TOD basename in filename.

    """
    if pa is None:
        _, _, _, ar = extract_basename(filename)
        pa = 'pa' + ar[-1]

    cal_in = moby2.Calibration.from_dict(filename)
    det_names = ['%s_%04i' % (pa, u) for u in cal_in.det_uid]

    aman = core.AxisManager(
        core.LabelAxis('dets', det_names),
    )

    aman.wrap('cal', cal_in.cal, [(0, 'dets')])
    return aman
예제 #24
0
    def test_140_restrict_axes(self):
        dets = ['det0', 'det1', 'det2']
        a1 = np.zeros((len(dets), 100))
        a1[1, 10] = 1.
        aman = core.AxisManager(core.LabelAxis('dets', dets),
                                core.OffsetAxis('samps', a1.shape[1]))
        aman.wrap('a1', a1, [(0, 'dets'), (1, 'samps')])

        r_axes = {
            'dets': core.LabelAxis('dets', dets[1:2]),
            'samps': core.OffsetAxis('samps', 20, 10)
        }
        # Not-in-place...
        rman = aman.restrict_axes(r_axes, in_place=False)
        self.assertCountEqual(aman.a1.shape, (3, 100))
        self.assertCountEqual(rman.a1.shape, (1, 20))
        self.assertNotEqual(aman.a1[1, 10], 0.)
        self.assertNotEqual(rman.a1[0, 0], 0.)
        # In-place.
        aman.restrict_axes(r_axes, in_place=True)
        self.assertCountEqual(aman.a1.shape, (1, 20))
        self.assertNotEqual(aman.a1[0, 0], 0.)
예제 #25
0
파일: pca.py 프로젝트: simonsobs/sotodlib
def get_trends(tod, remove=False, size=1, signal=None):
    """Computes trends for each detector signal that remove the slope
    connecting first and last points, as well as the mean of the
    signal.  The returned object can be treated like PCA model (e.g.,
    it can be passed as the model input to add_model).

    Arguments:
        tod: AxisManager with dets and samps axes.
        remove: boolean, if True then the computed trends (and means)
            are removed from the signal.
        size: the number of samples on each end of the signal to use
            for trend level computation.  Defaults to 1.
        signal: array of shape (dets, samps) to compute trends on.
            Defaults to tod.signal.

    Returns:
        An AxisManager with (dets, eigen, samps) axes.  The field
        'weights' has shape (dets, eigen) and the field 'modes' has
        shape (eigen, samps).  There are two modes, which always have
        the same form: index 0 is all ones, and index1 is a smooth
        line from -0.5 to +0.5.

    """
    if signal is None:
        signal = tod.signal
    trends = core.AxisManager(tod.dets, core.IndexAxis('eigen', 2), tod.samps)
    modes = np.ones((trends.eigen.count, trends.samps.count))
    modes[1] = np.linspace(-0.5, 0.5, modes.shape[1])
    weights = np.empty((trends.dets.count, trends.eigen.count))
    weights[:, 0] = signal.mean(axis=1)
    size = max(1, min(size, signal.shape[1] // 2))
    weights[:, 1] = (signal[:, -size:].mean(axis=1) -
                     signal[:, :size].mean(axis=1))
    trends.wrap('modes', modes)
    trends.wrap('weights', weights)
    if remove:
        add_model(tod, trends, scale=-1, signal=signal)
    return trends
예제 #26
0
def load_act_timeconst(filename, pa=None):
    """Read ACT timeconstants file and return an AxisManager containing
    the info.

    The pa is needed to define the dets axis properly, but if passed
    as None then the code will try to determine it by searching for a
    standard ACT TOD basename in filename.

    """
    if pa is None:
        _, _, _, ar = extract_basename(filename)
        pa = 'pa' + ar[-1]

    db = moby2.util.StructDB.from_column_file(
        filename, [('det_uid', 0), ('tau_s', 1)])
    det_names = ['%s_%04i' % (pa, u) for u in db['det_uid']]

    aman = core.AxisManager(
        core.LabelAxis('dets', det_names),
    )

    aman.wrap('timeconst', db['tau_s'], [(0, 'dets')])
    return aman
예제 #27
0
def load_detoffsets_file(position, polarization, pa=None):
    """Read ACT detector offsets + polarization angles files and return an
    AxisManager.

    """
    def guess_pa(text):
        # Find 'pa?' or 'ar?' in text (perhaps a filename) and return it.
        m = re.search('pa[123456789]', text)
        if m is not None:
            return m.group(0)
        m = re.search('ar[123456789]', text)
        if m is not None:
            return 'pa' + m.group(0)[-1]
        raise ValueError('Could not determine "pa" based on filename; '
                         'pass it in yourself.')

    if pa is None:
        pa = guess_pa(position)

    # Load position data...
    fp = moby2.scripting.products.get_detector_offsets(
        {'format': 'ascii',
         'columns': [('det_uid', 0), ('x', 2), ('y', 4), ('mask', 1)],
         'match_bad': 0,
         'filename': position})
    fp = fp.subset(fp.mask)

    det_names = ['%s_%04i' % (pa, u) for u in fp.det_uid]
    aman = core.AxisManager(core.LabelAxis('dets', det_names))
    aman.wrap('act_x', fp.x, [(0, 'dets')])
    aman.wrap('act_y', fp.y, [(0, 'dets')])
    aman.fp = fp

    if polarization is None:
        aman.wrap('act_pol', np.zeros(len(fp.x)), [(0, 'dets')])
    else:
        cols = moby2.util.ascii.read_columns(polarization)
        mask = cols[1] >= 0

        det_names = ['%s_%04i' % (pa, u) for u in cols[0][mask]]
        pol_ang = cols[1][mask]
        amanp = core.AxisManager(core.LabelAxis('dets', det_names))
        amanp.wrap('act_pol', pol_ang, [(0, 'dets')])
        aman.merge(amanp)

    # The coordinate convention for ACT and SO is ever-so-slightly
    # different.  Here's the libactpol construction:
    #
    #    Quaternion_r3(q, -pol_angle);
    #    Quaternion_r2_mul(focalplane_x, q);
    #    Quaternion_r1_mul(-focalplane_y, q);
    #
    # Note focalplane_{x,y} correspond to moby2.FocalPlane.{y,x}.
    # Also pol_angle is FocalPlane.phi - pi/2.
    #
    # The SO (xi, eta) will differ from (act_x, act_y) by O(x^3 + y^4).
    DEG = np.pi/180
    q = (so3g.proj.quat.euler(0,  aman['act_x']) *
         so3g.proj.quat.euler(1, -aman['act_y']) *
         so3g.proj.quat.euler(2, np.pi/2 - aman['act_pol']*DEG))

    xieta = so3g.proj.quat.decompose_xieta(q)
    for i, k in enumerate(['xi', 'eta', 'gamma']):
        aman.wrap(k, xieta[i], [(0, 'dets')])

    return aman
예제 #28
0
 def test_100_inheritance(self):
     tod = core.AxisManager(core.LabelAxis('dets', list('abcdef')),
                            core.OffsetAxis('samps', 1000))
     flags = core.FlagManager.for_tod(tod, 'dets', 'samps')
     tod.wrap('flags', flags)
     self.assertTrue(type(tod.flags) == core.FlagManager)