예제 #1
0
def read_detector(parameters: Dict[str, Any], imo: lbs.Imo):
    if "channel_obj" in parameters:
        detobj = lbs.FreqChannelInfo.from_imo(
            imo, parameters["channel_obj"]).get_boresight_detector()

    elif "detector_obj" in parameters:
        detobj = lbs.DetectorInfo.from_imo(imo, parameters["detector_obj"])
    else:
        detobj = lbs.DetectorInfo()

    for param_name in (
            "name",
            "wafer",
            "pixel",
            "pixtype",
            "channel",
            "sampling_rate_hz",
            "fwhm_arcmin",
            "ellipticity",
            "net_ukrts",
            "fknee_mhz",
            "fmin_hz",
            "alpha",
            "pol",
            "orient",
            "bandwidth_ghz",
            "bandcenter_ghz",
    ):
        if param_name in parameters:
            setattr(detobj, param_name, parameters[param_name])

    return detobj
예제 #2
0
def test_make_bin_map_api_simulation(tmp_path):
    # We should add a more meaningful observation:
    # Currently this test just shows the interface
    sim = lbs.Simulation(base_path=tmp_path / "tut04",
                         start_time=0.0,
                         duration_s=86400.0)

    sim.generate_spin2ecl_quaternions(
        scanning_strategy=lbs.SpinningScanningStrategy(
            spin_sun_angle_rad=np.radians(30),  # CORE-specific parameter
            spin_rate_hz=0.5 / 60,  # Ditto
            # We use astropy to convert the period (4 days) in
            # minutes, the unit expected for the precession period
            precession_rate_hz=1 / (4 * u.day).to("s").value,
        ))
    instr = lbs.InstrumentInfo(name="core",
                               spin_boresight_angle_rad=np.radians(65))
    det = lbs.DetectorInfo(name="foo", sampling_rate_hz=10)
    obss = sim.create_observations(detectors=[det])
    pointings = lbs.get_pointings(
        obss[0],
        sim.spin2ecliptic_quats,
        detector_quats=[det.quat],
        bore2spin_quat=instr.bore2spin_quat,
    )

    nside = 64
    obss[0].pixind = hp.ang2pix(nside, pointings[..., 0], pointings[..., 1])
    obss[0].psi = pointings[..., 2]
    mapping.make_bin_map(obss, nside)
예제 #3
0
def __write_complex_observation(tmp_path, use_mjd: bool):
    start_time = AstroTime("2021-01-01") if use_mjd else 0
    time_span_s = 60
    sampling_hz = 10

    sim = lbs.Simulation(
        base_path=tmp_path,
        start_time=start_time,
        duration_s=time_span_s,
    )
    scanning = lbs.SpinningScanningStrategy(
        spin_sun_angle_rad=0.785_398_163_397_448_3,
        precession_rate_hz=8.664_850_513_998_931e-05,
        spin_rate_hz=0.000_833_333_333_333_333_4,
        start_time=start_time,
    )

    spin2ecliptic_quats = scanning.generate_spin2ecl_quaternions(
        start_time, time_span_s, delta_time_s=1.0)

    instr = lbs.InstrumentInfo(
        boresight_rotangle_rad=0.0,
        spin_boresight_angle_rad=0.872_664_625_997_164_8,
        spin_rotangle_rad=3.141_592_653_589_793,
    )

    det = lbs.DetectorInfo(
        name="Dummy detector",
        sampling_rate_hz=sampling_hz,
        bandcenter_ghz=100.0,
        quat=[0.0, 0.0, 0.0, 1.0],
    )

    sim.create_observations(detectors=[det])

    obs = sim.observations[0]
    obs.tod = np.random.random(obs.tod.shape)

    obs.pointings = lbs.scanning.get_pointings(
        obs,
        spin2ecliptic_quats=spin2ecliptic_quats,
        detector_quats=[det.quat],
        bore2spin_quat=instr.bore2spin_quat,
    )

    obs.local_flags = np.zeros(obs.tod.shape, dtype="uint16")
    obs.local_flags[0, 12:15] = 1

    obs.global_flags = np.zeros(obs.tod.shape[1], dtype="uint32")
    obs.global_flags[12:15] = 15

    return obs, det, lbs.write_observations(sim=sim, subdir_name="")
예제 #4
0
def test_distribute_observation_astropy(tmp_path):
    sim = lbs.Simulation(
        base_path=tmp_path / "simulation_dir",
        start_time=astropy.time.Time("2020-01-01T00:00:00"),
        duration_s=11.0,
    )
    det = lbs.DetectorInfo("dummy", sampling_rate_hz=15)
    obs_list = sim.create_observations(detectors=[det],
                                       num_of_obs_per_detector=5)

    assert len(obs_list) == 5
    assert int(obs_list[-1].get_times()[-1] - obs_list[0].get_times()[0]) == 10
    assert sum([o.n_samples
                for o in obs_list]) == sim.duration_s * det.sampling_rate_hz
예제 #5
0
def test_distribute_observation(tmp_path):
    for dtype in (np.float16, np.float32, np.float64, np.float128):
        sim = lbs.Simulation(base_path=tmp_path / "simulation_dir",
                             start_time=1.0,
                             duration_s=11.0)
        det = lbs.DetectorInfo("dummy", sampling_rate_hz=15)
        obs_list = sim.create_observations(detectors=[det],
                                           num_of_obs_per_detector=5,
                                           dtype_tod=dtype)

        assert len(obs_list) == 5
        assert int(obs_list[-1].get_times()[-1] -
                   obs_list[0].get_times()[0]) == 10
        assert (sum([o.n_samples for o in obs_list
                     ]) == sim.duration_s * det.sampling_rate_hz)
예제 #6
0
def test_write_hdf5_mpi(tmp_path):
    start_time = 0
    time_span_s = 60
    sampling_hz = 10

    sim = lbs.Simulation(
        base_path=tmp_path,
        start_time=start_time,
        duration_s=time_span_s,
    )

    det = lbs.DetectorInfo(
        name="Dummy detector",
        sampling_rate_hz=sampling_hz,
        bandcenter_ghz=100.0,
        quat=[0.0, 0.0, 0.0, 1.0],
    )

    num_of_obs = 12
    sim.create_observations(detectors=[det],
                            num_of_obs_per_detector=num_of_obs)

    file_names = lbs.write_observations(
        sim,
        subdir_name="tod",
        file_name_mask="litebird_tod{global_index:04d}.h5")

    assert len(file_names) == len(sim.observations)

    if lbs.MPI_ENABLED:
        # Wait that all the processes have completed writing the files
        lbs.MPI_COMM_WORLD.barrier()

    tod_path = sim.base_path / "tod"
    files_found = list(tod_path.glob("litebird_tod*.h5"))
    assert len(files_found) == num_of_obs, (
        f"{len(files_found)} files found in {tod_path} instead of " +
        f"{num_of_obs}: {files_found}")
    for idx in range(num_of_obs):
        cur_tod = tod_path / f"litebird_tod{idx:04d}.h5"
        assert cur_tod.is_file(), f"File {cur_tod} was expected but not found"
예제 #7
0
sim.generate_spin2ecl_quaternions(
    scanning_strategy=lbs.SpinningScanningStrategy(
        spin_sun_angle_rad=np.deg2rad(30),  # CORE-specific parameter
        spin_rate_hz=0.5 / 60,  # Ditto
        # We use astropy to convert the period (4 days) in
        # seconds
        precession_rate_hz=1.0 / (4 * u.day).to("s").value,
    ))
instr = lbs.InstrumentInfo(name="core",
                           spin_boresight_angle_rad=np.deg2rad(65))

# We create two detectors, whose polarization angles are separated by π/2
sim.create_observations(
    detectors=[
        lbs.DetectorInfo(name="0A", sampling_rate_hz=10),
        lbs.DetectorInfo(name="0B",
                         sampling_rate_hz=10,
                         quat=lbs.quat_rotation_z(np.pi / 2)),
    ],
    dtype_tod=np.float64,
    n_blocks_time=lbs.MPI_COMM_WORLD.size,
    split_list_over_processes=False,
)

# Generate some white noise
rs = RandomState(MT19937(SeedSequence(123456789)))
for curobs in sim.observations:
    curobs.tod *= 0.0
    curobs.tod += rs.randn(*curobs.tod.shape)
예제 #8
0
def test_solar_dipole_fit(tmpdir):
    tmpdir = Path(tmpdir)

    test = unittest.TestCase()

    # The purpose of this test is to simulate the motion of the spacecraft
    # for one year (see `time_span_s`) and produce *two* timelines: the first
    # is associated with variables `*_s_o` and refers to the case of a nonzero
    # velocity of the Solar System, and the second is associated with variables
    # `*_o` and assumes that the reference frame of the Solar System is the
    # same as the CMB's (so that there is no dipole).

    start_time = Time("2022-01-01")
    time_span_s = 365 * 24 * 3600
    nside = 256
    sampling_hz = 1

    sim = lbs.Simulation(start_time=start_time, duration_s=time_span_s)

    scanning = lbs.SpinningScanningStrategy(
        spin_sun_angle_rad=0.785_398_163_397_448_3,
        precession_rate_hz=8.664_850_513_998_931e-05,
        spin_rate_hz=0.000_833_333_333_333_333_4,
        start_time=start_time,
    )

    spin2ecliptic_quats = scanning.generate_spin2ecl_quaternions(
        start_time, time_span_s, delta_time_s=7200
    )

    instr = lbs.InstrumentInfo(
        boresight_rotangle_rad=0.0,
        spin_boresight_angle_rad=0.872_664_625_997_164_8,
        spin_rotangle_rad=3.141_592_653_589_793,
    )

    det = lbs.DetectorInfo(
        name="Boresight_detector",
        sampling_rate_hz=sampling_hz,
        bandcenter_ghz=100.0,
        quat=[0.0, 0.0, 0.0, 1.0],
    )

    (obs_s_o,) = sim.create_observations(detectors=[det])
    (obs_o,) = sim.create_observations(detectors=[det])

    pointings = lbs.scanning.get_pointings(
        obs_s_o,
        spin2ecliptic_quats=spin2ecliptic_quats,
        detector_quats=[det.quat],
        bore2spin_quat=instr.bore2spin_quat,
    )

    orbit_s_o = lbs.SpacecraftOrbit(obs_s_o.start_time)
    orbit_o = lbs.SpacecraftOrbit(obs_o.start_time, solar_velocity_km_s=0.0)

    assert orbit_s_o.solar_velocity_km_s == 369.8160
    assert orbit_o.solar_velocity_km_s == 0.0

    pos_vel_s_o = lbs.spacecraft_pos_and_vel(orbit_s_o, obs_s_o, delta_time_s=86400.0)
    pos_vel_o = lbs.spacecraft_pos_and_vel(orbit_o, obs_o, delta_time_s=86400.0)

    assert pos_vel_s_o.velocities_km_s.shape == (366, 3)
    assert pos_vel_o.velocities_km_s.shape == (366, 3)

    lbs.add_dipole_to_observations(
        obs_s_o, pointings, pos_vel_s_o, dipole_type=lbs.DipoleType.LINEAR
    )
    lbs.add_dipole_to_observations(
        obs_o, pointings, pos_vel_o, dipole_type=lbs.DipoleType.LINEAR
    )

    npix = hp.nside2npix(nside)
    pix_indexes = hp.ang2pix(nside, pointings[0, :, 0], pointings[0, :, 1])

    h = np.zeros(npix)
    m = np.zeros(npix)
    map_s_o = np.zeros(npix)
    map_o = np.zeros(npix)

    bin_map(
        tod=obs_s_o.tod,
        pixel_indexes=pix_indexes,
        binned_map=map_s_o,
        accum_map=m,
        hit_map=h,
    )
    import healpy

    healpy.write_map(tmpdir / "map_s_o.fits.gz", map_s_o, overwrite=True)

    bin_map(
        tod=obs_o.tod,
        pixel_indexes=pix_indexes,
        binned_map=map_o,
        accum_map=m,
        hit_map=h,
    )

    healpy.write_map(tmpdir / "map_o.fits.gz", map_o, overwrite=True)

    dip_map = map_s_o - map_o

    assert np.abs(np.nanmean(map_s_o) * 1e6) < 1
    assert np.abs(np.nanmean(map_o) * 1e6) < 1
    assert np.abs(np.nanmean(dip_map) * 1e6) < 1

    dip_map[np.isnan(dip_map)] = healpy.UNSEEN
    mono, dip = hp.fit_dipole(dip_map)

    r = hp.Rotator(coord=["E", "G"])
    l, b = hp.vec2ang(r(dip), lonlat=True)

    # Amplitude, longitude and latitude
    test.assertAlmostEqual(np.sqrt(np.sum(dip ** 2)) * 1e6, 3362.08, 1)
    test.assertAlmostEqual(l[0], 264.021, 1)
    test.assertAlmostEqual(b[0], 48.253, 1)
예제 #9
0
def test_destriper(tmp_path):
    sim = lbs.Simulation(base_path=tmp_path / "destriper_output",
                         start_time=0,
                         duration_s=86400.0)

    sim.generate_spin2ecl_quaternions(
        scanning_strategy=lbs.SpinningScanningStrategy(
            spin_sun_angle_rad=np.deg2rad(30),  # CORE-specific parameter
            spin_rate_hz=0.5 / 60,  # Ditto
            # We use astropy to convert the period (4 days) in
            # seconds
            precession_rate_hz=1.0 / (4 * u.day).to("s").value,
        ))
    instr = lbs.InstrumentInfo(name="core",
                               spin_boresight_angle_rad=np.deg2rad(65))
    sim.create_observations(
        detectors=[
            lbs.DetectorInfo(name="0A", sampling_rate_hz=10),
            lbs.DetectorInfo(name="0B",
                             sampling_rate_hz=10,
                             quat=lbs.quat_rotation_z(np.pi / 2)),
        ],
        # num_of_obs_per_detector=lbs.MPI_COMM_WORLD.size,
        dtype_tod=np.float64,
        n_blocks_time=lbs.MPI_COMM_WORLD.size,
        split_list_over_processes=False,
    )

    # Generate some white noise
    rs = RandomState(MT19937(SeedSequence(123456789)))
    for curobs in sim.observations:
        curobs.tod *= 0.0
        curobs.tod += rs.randn(*curobs.tod.shape)

    params = lbs.DestriperParameters(
        nside=16,
        nnz=3,
        baseline_length=100,
        iter_max=10,
        return_hit_map=True,
        return_binned_map=True,
        return_destriped_map=True,
        return_npp=True,
        return_invnpp=True,
        return_rcond=True,
    )

    results = lbs.destripe(sim, instr, params=params)

    ref_map_path = Path(__file__).parent / "destriper_reference"

    hit_map_filename = ref_map_path / "destriper_hit_map.fits.gz"
    # healpy.write_map(hit_map_filename, results.hit_map, dtype="int32", overwrite=True)
    np.testing.assert_allclose(
        results.hit_map,
        healpy.read_map(hit_map_filename, field=None, dtype=np.int32))

    binned_map_filename = ref_map_path / "destriper_binned_map.fits.gz"
    # healpy.write_map(
    #     binned_map_filename,
    #     results.binned_map,
    #     dtype=list((np.float32 for i in range(3))),
    #     overwrite=True,
    # )
    ref_binned = healpy.read_map(binned_map_filename,
                                 field=None,
                                 dtype=list((np.float32 for i in range(3))))
    assert results.binned_map.shape == ref_binned.shape
    np.testing.assert_allclose(results.binned_map,
                               ref_binned,
                               rtol=1e-2,
                               atol=1e-3)

    destriped_map_filename = ref_map_path / "destriper_destriped_map.fits.gz"
    # healpy.write_map(
    #     destriped_map_filename,
    #     results.destriped_map,
    #     dtype=list((np.float32 for i in range(3))),
    #     overwrite=True,
    # )
    ref_destriped = healpy.read_map(destriped_map_filename,
                                    field=None,
                                    dtype=list((np.float32 for i in range(3))))
    assert results.destriped_map.shape == ref_destriped.shape
    np.testing.assert_allclose(results.destriped_map,
                               ref_destriped,
                               rtol=1e-2,
                               atol=1e-3)

    npp_filename = ref_map_path / "destriper_npp.fits.gz"
    # healpy.write_map(
    #     npp_filename,
    #     results.npp,
    #     dtype=list((np.float32 for i in range(6))),
    #     overwrite=True,
    # )
    ref_npp = healpy.read_map(npp_filename,
                              field=None,
                              dtype=list((np.float32 for i in range(6))))
    assert results.npp.shape == ref_npp.shape
    np.testing.assert_allclose(results.npp, ref_npp, rtol=1e-2, atol=1e-3)

    invnpp_filename = ref_map_path / "destriper_invnpp.fits.gz"
    # healpy.write_map(
    #     invnpp_filename,
    #     results.invnpp,
    #     dtype=list((np.float32 for i in range(6))),
    #     overwrite=True,
    # )
    ref_invnpp = healpy.read_map(invnpp_filename,
                                 field=None,
                                 dtype=list((np.float32 for i in range(6))))
    assert results.invnpp.shape == ref_invnpp.shape
    np.testing.assert_allclose(results.invnpp,
                               ref_invnpp,
                               rtol=1e-2,
                               atol=1e-3)

    rcond_filename = ref_map_path / "destriper_rcond.fits.gz"
    # healpy.write_map(
    #     rcond_filename,
    #     results.rcond,
    #     dtype=np.float32,
    #     overwrite=True,
    # )
    assert np.allclose(
        results.rcond,
        healpy.read_map(rcond_filename, field=None, dtype=np.float32))
예제 #10
0
def test_scan_map():

    # The purpose of this test is to simulate the motion of the spacecraft
    # for one year (see `time_span_s`) and produce *two* maps: the first
    # is associated with the Observation `obs1` and is built using
    # `scan_map_in_observations` and `make_bin_map`, the second is associated
    # the Observation `obs2` and is built directly filling in the test
    # `tod`, `psi` and `pixind` and then using `make_bin_map`
    # In the final test `out_map1` is compared with both `out_map2` and the
    # input map. Both simulations use two orthogonal detectors at the boresight
    # and input maps generated with `np.random.normal`.

    start_time = 0
    time_span_s = 365 * 24 * 3600
    nside = 16
    sampling_hz = 1
    hwp_radpsec = 4.084_070_449_666_731

    npix = hp.nside2npix(nside)

    sim = lbs.Simulation(start_time=start_time, duration_s=time_span_s)

    scanning = lbs.SpinningScanningStrategy(
        spin_sun_angle_rad=0.785_398_163_397_448_3,
        precession_rate_hz=8.664_850_513_998_931e-05,
        spin_rate_hz=0.000_833_333_333_333_333_4,
        start_time=start_time,
    )

    spin2ecliptic_quats = scanning.generate_spin2ecl_quaternions(
        start_time, time_span_s, delta_time_s=7200)

    instr = lbs.InstrumentInfo(
        boresight_rotangle_rad=0.0,
        spin_boresight_angle_rad=0.872_664_625_997_164_8,
        spin_rotangle_rad=3.141_592_653_589_793,
    )

    detT = lbs.DetectorInfo(
        name="Boresight_detector_T",
        sampling_rate_hz=sampling_hz,
        bandcenter_ghz=100.0,
        quat=[0.0, 0.0, 0.0, 1.0],
    )

    detB = lbs.DetectorInfo(
        name="Boresight_detector_B",
        sampling_rate_hz=sampling_hz,
        bandcenter_ghz=100.0,
        quat=[0.0, 0.0, 1.0 / np.sqrt(2.0), 1.0 / np.sqrt(2.0)],
    )

    np.random.seed(seed=123_456_789)
    maps = np.random.normal(0, 1, (3, npix))

    in_map = {"Boresight_detector_T": maps, "Boresight_detector_B": maps}

    (obs1, ) = sim.create_observations(detectors=[detT, detB])
    (obs2, ) = sim.create_observations(detectors=[detT, detB])

    pointings = lbs.scanning.get_pointings(
        obs1,
        spin2ecliptic_quats=spin2ecliptic_quats,
        detector_quats=[detT.quat, detB.quat],
        bore2spin_quat=instr.bore2spin_quat,
    )

    lbs.scan_map_in_observations(obs1,
                                 pointings,
                                 hwp_radpsec,
                                 in_map,
                                 fill_psi_and_pixind_in_obs=True)
    out_map1 = lbs.make_bin_map(obs1, nside).T

    times = obs2.get_times()
    obs2.pixind = np.empty(obs2.tod.shape, dtype=np.int32)
    obs2.psi = np.empty(obs2.tod.shape)
    for idet in range(obs2.n_detectors):
        obs2.pixind[idet, :] = hp.ang2pix(nside, pointings[idet, :, 0],
                                          pointings[idet, :, 1])
        obs2.psi[idet, :] = np.mod(
            pointings[idet, :, 2] + 2 * times * hwp_radpsec, 2 * np.pi)

    for idet in range(obs2.n_detectors):
        obs2.tod[idet, :] = (
            maps[0, obs2.pixind[idet, :]] +
            np.cos(2 * obs2.psi[idet, :]) * maps[1, obs2.pixind[idet, :]] +
            np.sin(2 * obs2.psi[idet, :]) * maps[2, obs2.pixind[idet, :]])

    out_map2 = lbs.make_bin_map(obs2, nside).T

    np.testing.assert_allclose(out_map1,
                               in_map["Boresight_detector_T"],
                               rtol=1e-6,
                               atol=1e-6)

    np.testing.assert_allclose(out_map1, out_map2, rtol=1e-6, atol=1e-6)
예제 #11
0
def main():
    warnings.filterwarnings("ignore", category=ErfaWarning)

    sim = lbs.Simulation(
        parameter_file=sys.argv[1],
        name="Observation of planets",
        description="""
This report contains the result of a simulation of the observation
of the sky, particularly with respect to the observation of planets.
""",
    )

    params = load_parameters(sim)

    if lbs.MPI_ENABLED:
        log.info("Using MPI with %d processes", lbs.MPI_COMM_WORLD.size)
    else:
        log.info("Not using MPI, serial execution")

    log.info("Generating the quaternions")
    scanning_strategy = read_scanning_strategy(
        sim.parameters["scanning_strategy"], sim.imo, sim.start_time)
    sim.generate_spin2ecl_quaternions(
        scanning_strategy=scanning_strategy,
        delta_time_s=params.spin2ecl_delta_time_s)

    log.info("Creating the observations")
    instr = lbs.InstrumentInfo(
        name="instrum",
        spin_boresight_angle_rad=params.spin_boresight_angle_rad)
    detector = lbs.DetectorInfo(
        sampling_rate_hz=params.detector_sampling_rate_hz)

    conversions = [
        ("years", astropy.units.year),
        ("year", astropy.units.year),
        ("days", astropy.units.day),
        ("day", astropy.units.day),
        ("hours", astropy.units.hour),
        ("hour", astropy.units.hour),
        ("minutes", astropy.units.minute),
        ("min", astropy.units.minute),
        ("sec", astropy.units.second),
        ("s", astropy.units.second),
        ("km", astropy.units.kilometer),
        ("Km", astropy.units.kilometer),
        ("au", astropy.units.au),
        ("AU", astropy.units.au),
        ("deg", astropy.units.deg),
        ("rad", astropy.units.rad),
    ]

    def conversion(x, new_unit):
        if isinstance(x, str):
            for conv_str, conv_unit in conversions:
                if x.endswith(" " + conv_str):
                    value = float(x.replace(conv_str, ""))
                    return (value * conv_unit).to(new_unit).value
                    break
        else:
            return float(x)

    sim_params = sim.parameters["simulation"]
    durations = ["duration_s", "duration_of_obs_s"]
    for dur in durations:
        sim_params[dur] = conversion(sim_params[dur], "s")

    delta_t_s = sim_params["duration_of_obs_s"]
    sim.create_observations(
        detectors=[detector],
        num_of_obs_per_detector=int(sim_params["duration_s"] /
                                    sim_params["duration_of_obs_s"]),
    )

    #################################################################
    # Here begins the juicy part

    log.info("The loop starts on %d processes", lbs.MPI_COMM_WORLD.size)
    sky_hitmap = np.zeros(healpy.nside2npix(params.output_nside),
                          dtype=np.int32)
    detector_hitmap = np.zeros(healpy.nside2npix(params.output_nside),
                               dtype=np.int32)
    dist_map_m2 = np.zeros(len(detector_hitmap))

    iterator = tqdm
    if lbs.MPI_ENABLED and lbs.MPI_COMM_WORLD.rank != 0:
        iterator = lambda x: x

    # Time variable inizialized at the beginning of the simulation
    t = 0.0
    for obs in iterator(sim.observations):
        solar_system_ephemeris.set("builtin")

        times = obs.get_times(astropy_times=True)

        # We only compute the planet's position for the first sample in
        # the observation and then assume that it does not move
        # significantly. (In Ecliptic coordinates, Jupiter moves by
        # fractions of an arcmin over a time span of one hour)
        time0 = times[0]
        icrs_pos = get_ecliptic_vec(
            get_body_barycentric(params.planet_name, time0))
        earth_pos = get_ecliptic_vec(get_body_barycentric("earth", time0))

        # Move the spacecraft to L2
        L2_pos = earth_pos * (
            1.0 + params.earth_L2_distance_km / norm(earth_pos).to("km").value)
        # Creating a Lissajous orbit
        R1 = conversion(params.radius_au[0], "au")
        R2 = conversion(params.radius_au[1], "au")
        phi1_t = params.L2_orbital_velocity_rad_s[0] * t
        phi2_t = params.L2_orbital_velocity_rad_s[1] * t
        phase = conversion(params.phase_rad, "rad")
        orbit_pos = np.array([
            -R1 * np.sin(np.arctan(L2_pos[1] / L2_pos[0])) * np.cos(phi1_t),
            R1 * np.cos(np.arctan(L2_pos[1] / L2_pos[0])) * np.cos(phi1_t),
            R2 * np.sin(phi2_t + phase),
        ])
        orbit_pos = astropy.units.Quantity(orbit_pos, unit="AU")

        # Move the spacecraft to a Lissajous orbit around L2
        sat_pos = orbit_pos + L2_pos

        # Compute the distance between the spacecraft and the planet
        distance_m = norm(sat_pos - icrs_pos).to("m").value

        # This is the direction of the solar system body with respect
        # to the spacecraft, in Ecliptic coordinates
        ecl_vec = (icrs_pos - sat_pos).value

        # The variable ecl_vec is a 3-element vector. We normalize it so
        # that it has length one (using the L_2 norm, hence ord=2)
        ecl_vec /= np.linalg.norm(ecl_vec, axis=0, ord=2)

        # Convert the matrix to a N×3 shape by repeating the vector:
        # planets move slowly, so we assume that the planet stays fixed
        # during this observation.
        ecl_vec = np.repeat(ecl_vec.reshape(1, 3), len(times), axis=0)

        # Calculate the quaternions that convert the Ecliptic
        # reference system into the detector's reference system
        quats = lbs.get_ecl2det_quaternions(
            obs,
            sim.spin2ecliptic_quats,
            detector_quats=[detector.quat],
            bore2spin_quat=instr.bore2spin_quat,
        )

        # Make room for the xyz vectors in the detector's reference frame
        det_vec = np.empty_like(ecl_vec)

        # Do the rotation!
        lbs.all_rotate_vectors(det_vec, quats[0], ecl_vec)

        pixidx = healpy.vec2pix(params.output_nside, det_vec[:, 0],
                                det_vec[:, 1], det_vec[:, 2])
        bincount = np.bincount(pixidx, minlength=len(detector_hitmap))
        detector_hitmap += bincount
        dist_map_m2 += bincount / ((4 * np.pi * (distance_m**2))**2)

        pointings = lbs.get_pointings(obs, sim.spin2ecliptic_quats,
                                      [detector.quat], instr.bore2spin_quat)[0]

        pixidx = healpy.ang2pix(params.output_nside, pointings[:, 0],
                                pointings[:, 1])
        bincount = np.bincount(pixidx, minlength=len(sky_hitmap))
        sky_hitmap += bincount

        # updating the time variable
        t += delta_t_s

    if lbs.MPI_ENABLED:
        sky_hitmap = lbs.MPI_COMM_WORLD.allreduce(sky_hitmap)
        detector_hitmap = lbs.MPI_COMM_WORLD.allreduce(detector_hitmap)
        dist_map_m2 = lbs.MPI_COMM_WORLD.allreduce(dist_map_m2)

    time_map_s = detector_hitmap / params.detector_sampling_rate_hz
    dist_map_m2[dist_map_m2 > 0] = np.power(dist_map_m2[dist_map_m2 > 0], -0.5)

    obs_time_per_radius_s = [
        time_per_radius(time_map_s, angular_radius_rad=np.deg2rad(radius_deg))
        for radius_deg in params.radii_deg
    ]

    if lbs.MPI_COMM_WORLD.rank == 0:
        # Create a plot of the observation time of the planet as a
        # function of the angular radius
        fig, ax = plt.subplots()
        ax.loglog(params.radii_deg, obs_time_per_radius_s)
        ax.set_xlabel("Radius [deg]")
        ax.set_ylabel("Observation time [s]")

        # Create a map showing how the observation time is distributed on
        # the sphere (in the reference frame of the detector)
        healpy.orthview(time_map_s,
                        title="Time spent observing the source",
                        unit="s")

        if scanning_strategy.spin_rate_hz != 0:
            spin_period_min = 1.0 / (60.0 * scanning_strategy.spin_rate_hz)
        else:
            spin_period_min = 0.0

        if scanning_strategy.precession_rate_hz != 0:
            precession_period_min = 1.0 / (
                60.0 * scanning_strategy.precession_rate_hz)
        else:
            precession_period_min = 0.0

        sim.append_to_report(
            """

## Scanning strategy parameters

Parameter | Value
--------- | --------------
Angle between the spin axis and the Sun-Earth axis | {{ sun_earth_angle_deg }} deg
Angle between the spin axis and the boresight | {{ spin_boresight_angle_deg }} deg
Precession period | {{ precession_period_min }} min
Spin period | {{ spin_period_min }} min

## Observation of {{ params.planet_name | capitalize }}

![](detector_hitmap.png)

The overall time spent in the map is {{ overall_time_s }} seconds.

The time resolution of the simulation was {{ delta_time_s }} seconds.

Angular radius [deg] | Time spent [s]
-------------------- | ------------------------
{% for row in radius_vs_time_s -%}
{{ "%.1f"|format(row[0]) }} | {{ "%.1f"|format(row[1]) }}
{% endfor -%}

![](radius_vs_time.svg)

""",
            figures=[(plt.gcf(), "detector_hitmap.png"),
                     (fig, "radius_vs_time.svg")],
            params=params,
            overall_time_s=np.sum(detector_hitmap) /
            params.detector_sampling_rate_hz,
            radius_vs_time_s=list(zip(params.radii_deg,
                                      obs_time_per_radius_s)),
            delta_time_s=1.0 / params.detector_sampling_rate_hz,
            sun_earth_angle_deg=np.rad2deg(
                scanning_strategy.spin_sun_angle_rad),
            spin_boresight_angle_deg=np.rad2deg(
                params.spin_boresight_angle_rad),
            precession_period_min=precession_period_min,
            spin_period_min=spin_period_min,
            det=detector,
        )

        healpy.write_map(
            params.output_map_file_name,
            (detector_hitmap, time_map_s, dist_map_m2, sky_hitmap),
            coord="DETECTOR",
            column_names=["HITS", "OBSTIME", "SQDIST", "SKYHITS"],
            column_units=["", "s", "m^2", ""],
            dtype=[np.int32, np.float32, np.float64, np.int32],
            overwrite=True,
        )

        np.savetxt(
            params.output_table_file_name,
            np.array(list(zip(params.radii_deg, obs_time_per_radius_s))),
            fmt=["%.2f", "%.5e"],
        )

        with (sim.base_path / "parameters.json").open("wt") as outf:
            time_value = scanning_strategy.start_time
            if not isinstance(time_value, (int, float)):
                time_value = str(time_value)
            json.dump(
                {
                    "scanning_strategy": {
                        "spin_sun_angle_rad":
                        scanning_strategy.spin_sun_angle_rad,
                        "precession_rate_hz":
                        scanning_strategy.precession_rate_hz,
                        "spin_rate_hz": scanning_strategy.spin_rate_hz,
                        "start_time": time_value,
                    },
                    "detector": {
                        "sampling_rate_hz": params.detector_sampling_rate_hz
                    },
                    "planet": {
                        "name": params.planet_name
                    },
                },
                outf,
                indent=2,
            )

    sim.flush()
예제 #12
0
#Imo work
imo = lbs.Imo()
sim_params = sim.parameters["simulation"]
scanning_params = sim.parameters["scanning_strategy"]
planet_params = sim.parameters["planet_scanning"]
scan_params = imo.query(scanning_params["scanning_strategy_obj"])

#Instrumental variables
metadata = scan_params.metadata
strat = ss.LBScanningStrategy(metadata)
instr = lbs.Instrument(
    name="LiteBIRD",
    spin_boresight_angle_deg=sim.parameters["scanning_strategy"]
    ["spin_boresight_angle_deg"])
det = lbs.DetectorInfo(
    name="Boresight",
    sampling_rate_hz=sim.parameters["planet_scanning"]["sampling_rate_hz"])
obs, = sim.create_observations(detectors=[det])

utils.print_inputs(simulation=sim,
                   detector=det,
                   instrument=instr,
                   strategy=strat)

sim.generate_spin2ecl_quaternions(
    scanning_strategy=ss.LBScanningStrategy(metadata=metadata)
)  #Get quaternions responsible for rotation from spin-axis to ecliptic plane

planet = planet_params["planet_name"]
solar_system_ephemeris.set("builtin")
start = time.time()
예제 #13
0
def create_fake_detector(sampling_rate_hz=1,
                         quat=np.array([0.0, 0.0, 0.0, 1.0])):
    return lbs.DetectorInfo(name="dummy",
                            sampling_rate_hz=sampling_rate_hz,
                            quat=quat)
예제 #14
0
spin2ecliptic_quats = scanning.generate_spin2ecl_quaternions(start_time,
                                                             time_span_s,
                                                             delta_time_s=5.0)

# We simulate an instrument whose boresight is perpendicular to
# the spin axis.
instr = lbs.InstrumentInfo(
    boresight_rotangle_rad=0.0,
    spin_boresight_angle_rad=np.deg2rad(90),
    spin_rotangle_rad=np.deg2rad(75),
)

# A simple detector looking along the boresight direction
det = lbs.DetectorInfo(
    name="Boresight_detector",
    sampling_rate_hz=sampling_hz,
    bandcenter_ghz=100.0,
)

(obs, ) = sim.create_observations(detectors=[det])
pointings = lbs.scanning.get_pointings(
    obs,
    spin2ecliptic_quats=spin2ecliptic_quats,
    detector_quats=[det.quat],
    bore2spin_quat=instr.bore2spin_quat,
)

# Simulate the orbit of the spacecraft and compute positions and
# velocities
orbit = lbs.SpacecraftOrbit(obs.start_time)
pos_vel = lbs.spacecraft_pos_and_vel(orbit, obs, delta_time_s=60.0)