Example #1
0
    def _save_tod(self, obsname, tod, times, istart, nind, ind, comm,
                  common_ref):
        import pickle

        rank = 0
        if comm is not None:
            rank = comm.rank

        t = times[ind]
        tmin, tmax = t[0], t[-1]
        outdir = "snapshots"
        if rank == 0:
            try:
                os.makedirs(outdir)
            except FileExistsError:
                pass

        try:
            good = common_ref[ind] & tod.UNSTABLE == 0
        except:
            good = slice(0, nind)

        for det in tod.local_dets:
            # Cache the output signal
            cachename = "{}_{}".format(self._out, det)
            ref = tod.cache.reference(cachename)[ind]
            try:
                # Some TOD classes provide a shortcut to Az/El
                az, el = tod.read_azel(detector=det,
                                       local_start=istart,
                                       n=nind)
            except Exception as e:
                azelquat = tod.read_pntg(detector=det,
                                         local_start=istart,
                                         n=nind,
                                         azel=True)
                # Convert Az/El quaternion of the detector back into
                # angles for the simulation.
                theta, phi = qa.to_position(azelquat)
                # Azimuth is measured in the opposite direction
                # than longitude
                az = 2 * np.pi - phi
                el = np.pi / 2 - theta

            fn = os.path.join(
                outdir,
                "atm_tod_{}_{}_t_{}_{}.pck".format(obsname, det, int(tmin),
                                                   int(tmax)),
            )
            with open(fn, "wb") as fout:
                pickle.dump([det, t[good], az[good], el[good], ref[good]],
                            fout)

        return
Example #2
0
    def _observe_atmosphere(
        self,
        sim,
        tod,
        comm,
        prefix,
        common_ref,
        istart,
        nind,
        ind,
        scan_range,
        times,
        absorption,
    ):
        log = Logger.get()
        rank = 0
        if comm is not None:
            rank = comm.rank
        tmr = Timer()
        if self._report_timing:
            if comm is not None:
                comm.Barrier()
            tmr.start()

        azmin, azmax, elmin, elmax = scan_range

        nsamp = tod.local_samples[1]

        if rank == 0:
            log.info("{}Observing the atmosphere".format(prefix))

        ngood_tot = 0
        nbad_tot = 0

        for det in tod.local_dets:
            # Cache the output signal
            cachename = "{}_{}".format(self._out, det)
            if tod.cache.exists(cachename):
                ref = tod.cache.reference(cachename)
            else:
                ref = tod.cache.create(cachename, np.float64, (nsamp, ))

            # Cache the output flags
            flag_ref = tod.local_flags(det, self._flag_name)

            if self._apply_flags:
                good = np.logical_and(
                    common_ref[ind] & self._common_flag_mask == 0,
                    flag_ref[ind] & self._flag_mask == 0,
                )
                ngood = np.sum(good)
            else:
                try:
                    good = common_ref[ind] & tod.UNSTABLE == 0
                    ngood = np.sum(good)
                except:
                    good = slice(0, nind)
                    ngood = nind
            if ngood == 0:
                continue

            try:
                # Some TOD classes provide a shortcut to Az/El
                az, el = tod.read_azel(detector=det,
                                       local_start=istart,
                                       n=nind)
                az = az[good]
                el = el[good]
            except Exception as e:
                azelquat = tod.read_pntg(detector=det,
                                         local_start=istart,
                                         n=nind,
                                         azel=True)[good]
                # Convert Az/El quaternion of the detector back into
                # angles for the simulation.
                theta, phi = qa.to_position(azelquat)
                # Azimuth is measured in the opposite direction
                # than longitude
                az = 2 * np.pi - phi
                el = np.pi / 2 - theta

            if np.ptp(az) < np.pi:
                azmin_det = np.amin(az)
                azmax_det = np.amax(az)
            else:
                # Scanning across the zero azimuth.
                azmin_det = np.amin(az[az > np.pi]) - 2 * np.pi
                azmax_det = np.amax(az[az < np.pi])
            elmin_det = np.amin(el)
            elmax_det = np.amax(el)

            # if min_az_bore == max_az_bore:
            # log.info("You are in the spin_scan modality. Feature in Beta version azmin={} and azmax={}".format(azmin, azmax))
            # Add some controls on the limits
            # else:
            # log.info("Not in spin_scan Mod azmin={} and azmax={}".format(azmin, azmax))
            # if (
            #     not (azmin <= azmin_det and azmax_det <= azmax)
            #     and not (
            #         azmin <= azmin_det - 2 * np.pi and azmax_det - 2 * np.pi <= azmax
            #     )
            # ) or not (elmin <= elmin_det and elmin_det <= elmax):
            #     # DEBUG begin
            #     import pickle

            #     with open("bad_quats_{}_{}.pck".format(rank, det), "wb") as fout:
            #         pickle.dump(
            #             [scan_range, az, el, azelquat, tod._boresight_azel], fout
            #         )
            #     # DEBUG end
            #     # Detector Az/El: [-3.13988, 3.14109], [1.22173, 1.22173] is not contained in [-7.28828, 1.00495], [1.04720 1.39626]
            #     raise RuntimeError(
            #         prefix + "Detector Az/El: [{:.5f}, {:.5f}], "
            #         "[{:.5f}, {:.5f}] is not contained in "
            #         "[{:.5f}, {:.5f}], [{:.5f} {:.5f}]"
            #         "".format(
            #             azmin_det,
            #             azmax_det,
            #             elmin_det,
            #             elmax_det,
            #             azmin,
            #             azmax,
            #             elmin,
            #             elmax,
            #         )
            #     )

            # Integrate detector signal

            atmdata = np.zeros(ngood, dtype=np.float64)

            err = sim.observe(times[ind][good], az, el, atmdata, -1.0)
            if err != 0:
                # Observing failed
                bad = np.abs(atmdata) < 1e-30
                nbad = np.sum(bad)
                log.error(
                    "{}OpSimAtmosphere: Observing FAILED for {} ({:.2f} %) samples. "
                    "det = {}, rank = {}".format(prefix, nbad,
                                                 nbad * 100 / ngood, det,
                                                 rank))
                atmdata[bad] = 0
                flag_ref[ind][good][bad] = 255
                nbad_tot += nbad
            ngood_tot += ngood

            if self._gain:
                atmdata *= self._gain

            if absorption is not None:
                # Apply the frequency-dependent absorption-coefficient
                atmdata *= absorption

            ref[ind][good] += atmdata

            del ref

        if comm is not None:
            comm.Barrier()
            ngood_tot = comm.reduce(ngood_tot)
            nbad_tot = comm.reduce(nbad_tot)
        if rank == 0 and nbad_tot > 0:
            print("{}WARNING: Observe atmosphere FAILED on {:.2f}% of samples".
                  format(prefix, nbad_tot * 100 / ngood_tot))
        if self._report_timing:
            if rank == 0:
                tmr.report_clear(
                    "{}OpSimAtmosphere: Observe atmosphere".format(prefix))
        return