Beispiel #1
0
    def test_sim_full(self):
        hw = get_example()
        hw.data["detectors"] = OrderedDict()
        for tele, teleprops in hw.data["telescopes"].items():
            if tele != "SAT1":
                continue
            dets = sim_telescope_detectors(hw, tele)
            hw.data["detectors"].update(dets)
        dbpath = os.path.join(self.outdir, "hardware_SAT1.toml.gz")
        hw.dump(dbpath, overwrite=True, compress=True)
        check = Hardware(dbpath)

        # Test selection of 90GHz detectors on wafers 25 and 26 which have
        # "A" polarization configuration and are located in pixels 20-29.
        wbhw = hw.select(
            match={
                "wafer_slot": ["w25", "w26"],
                "band": "SAT_f090",
                "pol": "A",
                "pixel": "02."
            })
        dbpath = os.path.join(self.outdir, "w25-26_p20-29_SAT_f090_A.toml.gz")
        wbhw.dump(dbpath, overwrite=True, compress=True)
        check = Hardware(dbpath)
        self.assertTrue(len(check.data["detectors"]) == 20)
        chkpath = os.path.join(self.outdir, "w25-26_p20-29_SAT_f090_A.txt")
        with open(chkpath, "w") as f:
            for d in check.data["detectors"]:
                f.write("{}\n".format(d))
        return
Beispiel #2
0
 def test_sim_wafer(self):
     hw = get_example()
     # Simulate some wafers
     for tele, teleprops in hw.data["telescopes"].items():
         if tele != "SAT1":
             continue
         platescale = teleprops["platescale"]
         fwhm = teleprops["fwhm"]
         for tube_slot in teleprops["tube_slots"]:
             if tube_slot != "ST1":
                 continue
             tubeprops = hw.data["tube_slots"][tube_slot]
             for wafer in tubeprops["wafer_slots"]:
                 if wafer != "w25":
                     continue
                 outpath = os.path.join(self.outdir,
                                        "wafer_{}.toml.gz".format(wafer))
                 dets = sim_wafer_detectors(hw, wafer, platescale, fwhm)
                 # replace detectors with this set for dumping
                 hw.data["detectors"] = dets
                 hw.dump(outpath, overwrite=True, compress=True)
                 if not self.skip_plots:
                     outpath = os.path.join(self.outdir,
                                            "wafer_{}.pdf".format(wafer))
                     plot_detectors(dets, outpath, labels=True)
     return
Beispiel #3
0
 def test_config_example(self):
     outpath = os.path.join(self.outdir, "hardware_example.toml.gz")
     hw = get_example()
     hw.dump(outpath, overwrite=True, compress=True)
     hwcheck = Hardware(outpath)
     checkpath = os.path.join(self.outdir, "hardware_example_check.toml.gz")
     hwcheck.dump(checkpath, overwrite=True, compress=True)
     return
Beispiel #4
0
 def test_sim_telescope(self):
     fullhw = get_example()
     fullhw.data["detectors"] = sim_telescope_detectors(fullhw, "SAT1")
     hw = fullhw.select(match={
         "wafer_slot": [
             "w25",
         ],
     })
     outpath = os.path.join(self.outdir, "telescope_SAT1_w25.toml.gz")
     hw.dump(outpath, overwrite=True, compress=True)
     if not self.skip_plots:
         outpath = os.path.join(self.outdir, "telescope_SAT1_w25.pdf")
         plot_detectors(hw.data["detectors"], outpath, labels=False)
     return
Beispiel #5
0
def main():
    parser = argparse.ArgumentParser(
        description="This program measures the median offset of subset of "
        "detectors from boresight.",
        usage="get_wafer_offset [options] (use --help for details)")

    group = parser.add_mutually_exclusive_group(required=True)
    group.add_argument(
        "--tube_slots",
        help="Comma-separated list of optics tube slots: c1 (UHF), i5 (UHF), "
        " i6 (MF), i1 (MF), i3 (MF), i4 (MF), o6 (LF).  ")
    group.add_argument("--wafer_slots",
                       help="Comma-separated list of optics tube slots. ")
    parser.add_argument("--reverse",
                        action="store_true",
                        help="Reverse offsets")
    # LAT specific params
    parser.add_argument(
        "--corotate-lat",
        required=False,
        action="store_true",
        help="Rotate LAT receiver to maintain focalplane orientation",
        dest="corotate_lat",
    )
    parser.add_argument(
        "--no-corotate-lat",
        required=False,
        action="store_false",
        help="Do not Rotate LAT receiver to maintain focalplane orientation",
        dest="corotate_lat",
    )
    parser.set_defaults(corotate_lat=True)
    parser.add_argument(
        "--elevation-deg",
        required=False,
        type=np.float,
        help="Observing elevation",
    )

    args = parser.parse_args()

    hw = hardware.get_example()

    # Which telescope?

    if args.wafer_slots is not None:
        wafer_slots = args.wafer_slots.split(",")
        wafer_map = hw.wafer_map()
        tube_slots = [wafer_map["tube_slots"][ws] for ws in wafer_slots]
    else:
        tube_slots = args.tube_slots.split(",")

    telescope = None
    for tube_slot in tube_slots:
        for telescope_name, telescope_data in hw.data["telescopes"].items():
            if tube_slot in telescope_data["tube_slots"]:
                if telescope is None:
                    telescope = telescope_name
                elif telescope != telescope.name:
                    raise RuntimeError(
                        f"Tubes '{tube_slots}' span more than one telescope")
        if telescope is None:
            raise RuntimeError(
                f"Failed to match tube_slot = '{tube_slot}' with a telescope")

    # Which detectors?

    hw.data["detectors"] = hardware.sim_telescope_detectors(hw, telescope)

    match = {}
    tube_slots = None
    if args.wafer_slots is not None:
        match["wafer_slot"] = args.wafer_slots.split(",")
    elif args.tube_slots is not None:
        tube_slots = args.tube_slots.split(",")

    hw = hw.select(tube_slots=tube_slots, match=match)
    ndet = len(hw.data["detectors"])

    # print(f"tube_slots = {tube_slots}, match = {match} leaves {ndet} detectors")

    # Optional corotator rotation

    if telescope == "LAT":
        if args.corotate_lat:
            rot = qa.rotation(ZAXIS, np.radians(LAT_COROTATOR_OFFSET_DEG))
        else:
            if args.elevation_deg is None:
                raise RuntimeError(
                    "You must set the observing elevation when not co-rotating."
                )
            rot = qa.rotation(
                ZAXIS,
                np.radians(args.elevation_deg - 60 + LAT_COROTATOR_OFFSET_DEG))
    else:
        if args.elevation_deg is not None:
            raise RuntimeError("Observing elevation does not matter for SAT")
        rot = None

    # Average detector offset

    vec_mean = np.zeros(3)
    for det_name, det_data in hw.data["detectors"].items():
        quat = det_data["quat"]
        if rot is not None:
            quat = qa.mult(rot, quat)
        vec = qa.rotate(quat, ZAXIS)
        vec_mean += vec
    vec_mean /= ndet

    # Radius

    all_dist = []
    for det_name, det_data in hw.data["detectors"].items():
        quat = det_data["quat"]
        if rot is not None:
            quat = qa.mult(rot, quat)
        vec = qa.rotate(quat, ZAXIS)
        all_dist.append(np.degrees(np.arccos(np.dot(vec_mean, vec))))
    dist_max = np.amax(all_dist)

    # Wafers

    if args.tube_slots is None:
        wafer_slots = set(wafer_slots)
    else:
        wafer_slots = set()
        for tube_slot in tube_slots:
            wafer_slots.update(hw.data["tube_slots"][tube_slot]["wafer_slots"])
    waferstring = ""
    for wafer_slot in sorted(wafer_slots):
        waferstring += f" {wafer_slot}"

    # Translate into Az/El offsets at el=0

    rot = hp.Rotator(rot=[0, 90, 0])
    vec_mean = rot(vec_mean)
    az_offset, el_offset = hp.vec2dir(vec_mean, lonlat=True)

    el_offset *= -1
    if args.reverse:
        az_offset *= -1
        el_offset *= -1

    print(f"{az_offset:.3f} {el_offset:.3f} {dist_max:.3f}" + waferstring)

    return
Beispiel #6
0
    zmap.write_healpix_fits(os.path.join(out, "binned.fits"))
    if cworld.rank == 0:
        print("Binned map done", flush=True)

    return


# Our toast communicator- use the default for now, which is one
# process group spanning all processes.
comm = toast.Comm()

if comm.world_rank == 0:
    print("Simulating all detector properties...", flush=True)
# First, get the list of detectors we want to use
# (Eventually we would load this from disk.  Here we simulate it.)
hw = get_example()
dets = sim_telescope_detectors(hw, "LAT")
hw.data["detectors"] = dets

if comm.world_rank == 0:
    print("Selecting detectors...", flush=True)
# Downselect to just 10 pixels on one wafer
#small_hw = hw.select(match={"wafer_slot": "41", "pixel": "00."})
#small_hw = hw.select(match={"wafer_slot": "41"})
small_hw = hw.select(match={"wafer_slot": "40"})
#small_hw = hw.select(match={"band": "LF1"})
if comm.world_rank == 0:
    small_hw.dump("selected.toml", overwrite=True)

# The data directory (this is a single band)
# dir = "/project/projectdirs/sobs/sims/pipe-s0001/datadump_LAT_LF1"
Beispiel #7
0
    def setUp(self):
        fixture_name = os.path.splitext(os.path.basename(__file__))[0]
        if not toast_available:
            print(
                "toast cannot be imported ({})- skipping unit test".format(
                    toast_import_error),
                flush=True,
            )
            return

        self.outdir = None
        if MPI.COMM_WORLD.rank == 0:
            self.outdir = create_outdir(fixture_name)
        self.outdir = MPI.COMM_WORLD.bcast(self.outdir, root=0)

        toastcomm = toast.Comm()
        self.data = toast.Data(toastcomm)

        # Focalplane
        hwfull = get_example()
        dets = sim_telescope_detectors(hwfull, "SAT4")
        hwfull.data["detectors"] = dets
        hw = hwfull.select(match={
            "wafer_slot": "w42",
            "band": "f030",
            "pixel": "00[01]"
        })
        # print(hw.data["detectors"], flush=True)
        detquats = {k: v["quat"] for k, v in hw.data["detectors"].items()}

        # Samples per observation
        self.totsamp = 10000

        # Scan properties
        self.site_lon = '-67:47:10'
        self.site_lat = '-22:57:30'
        self.site_alt = 5200.
        self.coord = 'C'
        self.azmin = 45
        self.azmax = 55
        self.el = 60
        self.scanrate = 1.0
        self.scan_accel = 0.1
        self.CES_start = None

        # Noise properties
        self.rate = 100.0
        self.NET = 1e-3  # 1 mK NET
        self.epsilon = 0.0
        self.fmin = 1.0e-5
        self.alpha = 1.0
        self.fknee = 0.05

        for ob in range(3):
            ftime = (self.totsamp / self.rate) * ob + 1564015655.88
            tod = TODGround(self.data.comm.comm_group,
                            detquats,
                            self.totsamp,
                            detranks=self.data.comm.group_size,
                            firsttime=ftime,
                            rate=self.rate,
                            site_lon=self.site_lon,
                            site_lat=self.site_lat,
                            site_alt=self.site_alt,
                            azmin=self.azmin,
                            azmax=self.azmax,
                            el=self.el,
                            coord=self.coord,
                            scanrate=self.scanrate,
                            scan_accel=self.scan_accel,
                            CES_start=self.CES_start)

            # Analytic noise model
            detnames = list(detquats.keys())
            drate = {x: self.rate for x in detnames}
            dfmin = {x: self.fmin for x in detnames}
            dfknee = {x: self.fknee for x in detnames}
            dalpha = {x: self.alpha for x in detnames}
            dnet = {x: self.NET for x in detnames}
            nse = AnalyticNoise(rate=drate,
                                fmin=dfmin,
                                detectors=detnames,
                                fknee=dfknee,
                                alpha=dalpha,
                                NET=dnet)

            # Single observation
            obs = dict()
            obs["tod"] = tod
            obs["noise"] = nse
            obs["id"] = 12345
            obs["intervals"] = tod.subscans
            obs["site"] = "SimonsObs"
            obs["telescope"] = "SAT4"
            obs["site_id"] = 1
            obs["telescope_id"] = 4
            obs["fpradius"] = 5.0
            obs["start_time"] = ftime
            obs["altitude"] = self.site_alt
            obs["name"] = "test_{:02}".format(ob)

            # Add a focalplane dictionary with just the detector index
            focalplane = {}
            for idet, det in enumerate(detnames):
                focalplane[det] = {"index": idet}
            obs["focalplane"] = focalplane

            # Add the observation to the dataset
            self.data.obs.append(obs)

        nse = toast.tod.OpSimNoise(out="signal", realization=0)
        nse.exec(self.data)

        return
Beispiel #8
0
def main():
    parser = argparse.ArgumentParser(
        description="This program measures the median offset of subset of "
        "detectors from boresight.",
        usage="get_wafer_offset [options] (use --help for details)")

    group = parser.add_mutually_exclusive_group(required=True)
    group.add_argument(
        "--tube_slots",
        help="Comma-separated list of optics tube slots: c1 (UHF), i5 (UHF), "
        " i6 (MF), i1 (MF), i3 (MF), i4 (MF), o6 (LF).  ")
    group.add_argument("--wafer_slots",
                       help="Comma-separated list of optics tube slots. ")
    parser.add_argument("--reverse",
                        action="store_true",
                        help="Reverse offsets")

    args = parser.parse_args()

    hw = hardware.get_example()

    # Which telescope?

    if args.wafer_slots is not None:
        wafer_slots = args.wafer_slots.split(",")
        wafer_map = hw.wafer_map()
        tube_slots = [wafer_map["tube_slots"][ws] for ws in wafer_slots]
    else:
        tube_slots = args.tube_slots.split(",")

    telescope = None
    for tube_slot in tube_slots:
        for telescope_name, telescope_data in hw.data["telescopes"].items():
            if tube_slot in telescope_data["tube_slots"]:
                if telescope is None:
                    telescope = telescope_name
                elif telescope != telescope.name:
                    raise RuntimeError(
                        f"Tubes '{tube_slots}' span more than one telescope")
        if telescope is None:
            raise RuntimeError(
                f"Failed to match tube_slot = '{tube_slot}' with a telescope")

    # Which detectors?

    hw.data["detectors"] = hardware.sim_telescope_detectors(hw, telescope)

    match = {}
    tube_slots = None
    if args.wafer_slots is not None:
        match["wafer_slot"] = args.wafer_slots.split(",")
    elif args.tube_slots is not None:
        tube_slots = args.tube_slots.split(",")

    hw = hw.select(tube_slots=tube_slots, match=match)
    ndet = len(hw.data["detectors"])

    # print(f"tube_slots = {tube_slots}, match = {match} leaves {ndet} detectors")

    # Average detector offset

    vec_mean = np.zeros(3)
    zaxis = np.array([0, 0, 1])
    for det_name, det_data in hw.data["detectors"].items():
        quat = det_data["quat"]
        vec = qa.rotate(quat, zaxis)
        vec_mean += vec
    vec_mean /= ndet

    # Radius

    all_dist = []
    for det_name, det_data in hw.data["detectors"].items():
        quat = det_data["quat"]
        vec = qa.rotate(quat, zaxis)
        all_dist.append(np.degrees(np.arccos(np.dot(vec_mean, vec))))
    dist_max = np.amax(all_dist)

    # Translate into Az/El offsets at el=0

    rot = hp.Rotator(rot=[0, 90, 0])
    vec_mean = rot(vec_mean)
    az_offset, el_offset = hp.vec2dir(vec_mean, lonlat=True)

    el_offset *= -1
    if args.reverse:
        az_offset *= -1
        el_offset *= -1

    print(f"{az_offset:.3f} {el_offset:.3f} {dist_max:.3f}")

    return
Beispiel #9
0
    def setUp(self):
        fixture_name = os.path.splitext(os.path.basename(__file__))[0]
        if not toast_available:
            print("toast cannot be imported- skipping unit tests", flush=True)
            return

        self.comm, self.procs, self.rank = get_world()

        self.outdir = create_outdir(fixture_name, comm=self.comm)

        toastcomm = toast.Comm()
        self.data = toast.Data(toastcomm)

        # Focalplane
        hwfull = get_example()
        dets = sim_telescope_detectors(hwfull, "SAT4")
        hwfull.data["detectors"] = dets
        hw = hwfull.select(match={
            "wafer_slot": "w42",
            "band": "f030",
            "pixel": "00[01]"
        })
        print(hw.data["detectors"], flush=True)
        detquats = {k: v["quat"] for k, v in hw.data["detectors"].items()}

        # Samples per observation
        self.totsamp = 10000

        # Pixelization
        nside = 512
        self.sim_nside = nside
        self.map_nside = nside

        # Scan properties
        self.site_lon = '-67:47:10'
        self.site_lat = '-22:57:30'
        self.site_alt = 5200.
        self.coord = 'C'
        self.azmin = 45
        self.azmax = 55
        self.el = 60
        self.scanrate = 1.0
        self.scan_accel = 0.1
        self.CES_start = None

        # Noise properties
        self.rate = 100.0
        self.NET = 5.0
        self.epsilon = 0.0
        self.fmin = 1.0e-5
        self.alpha = 1.0
        self.fknee = 0.05

        tod = TODGround(self.data.comm.comm_group,
                        detquats,
                        self.totsamp,
                        detranks=self.data.comm.group_size,
                        firsttime=0.0,
                        rate=self.rate,
                        site_lon=self.site_lon,
                        site_lat=self.site_lat,
                        site_alt=self.site_alt,
                        azmin=self.azmin,
                        azmax=self.azmax,
                        el=self.el,
                        coord=self.coord,
                        scanrate=self.scanrate,
                        scan_accel=self.scan_accel,
                        CES_start=self.CES_start)

        # Analytic noise model
        detnames = list(detquats.keys())
        drate = {x: self.rate for x in detnames}
        dfmin = {x: self.fmin for x in detnames}
        dfknee = {x: self.fknee for x in detnames}
        dalpha = {x: self.alpha for x in detnames}
        dnet = {x: self.NET for x in detnames}
        nse = AnalyticNoise(rate=drate,
                            fmin=dfmin,
                            detectors=detnames,
                            fknee=dfknee,
                            alpha=dalpha,
                            NET=dnet)

        # Single observation
        obs = dict()
        obs["tod"] = tod
        obs["noise"] = nse
        obs["id"] = 12345
        obs["intervals"] = tod.subscans
        obs["site"] = "SimonsObs"
        obs["telescope"] = "SAT4"
        obs["site_id"] = 1
        obs["telescope_id"] = 4
        obs["fpradius"] = 5.0
        obs["start_time"] = 0
        obs["altitude"] = self.site_alt
        obs["name"] = "test"

        # Add the observation to the dataset
        self.data.obs.append(obs)
        return