Esempio n. 1
0
def table_line(
    datetime,
    target,
    horizon,
    sep_angle=None,
    cal_limit=None,
    sol_limit=None,
    lst=False,
    notes="",
):
    """Construct a line of target information to display on command line output.

    Parameters
    ----------
    datetime: ephem.Date
        ephem date and time object
    target: katpoint.Catalogue
        target from katpoint.Catalogue object
    horizon: float
        minimum pointing angle in degrees
    sep_angle: float
        separation angle in degrees [optional param]
    cal_limit: float
        maximum separation angle between target and calibrator [optional]
    sol_limit: float
        minimum separation angle between target and Sun [optional]
    lst: str
        display times in LST rather than UTC
    notes: str
        user provided extra information

    Returns
    -------
        <name> <risetime UTC> <settime UTC> <Separation> <Notes>

    """
    observatory = Observatory(horizon=horizon, datetime=datetime)
    rise_time = observatory._ephem_risetime_(target.body, lst=lst)
    set_time = observatory._ephem_settime_(target.body, lst=lst)
    if not lst:
        rise_time = rise_time.datetime().strftime("%H:%M:%S")
        set_time = set_time.datetime().strftime("%H:%M:%S")
    else:
        rise_time = str(rise_time)
        set_time = str(set_time)

    clo_clr = bcolors.ENDC
    sep_note = ""
    if sep_angle is not None:
        sep_note = "%.2f" % sep_angle
    if cal_limit is not None:
        if sep_angle > cal_limit:
            clo_clr = bcolors.WARNING
            sep_note += " ***"
    if sol_limit is not None:
        if sep_angle < sol_limit:
            clo_clr = bcolors.FAIL
            sep_note += " ***"

    table_info = "{: <16}{: <32}{: <16}{: <16}{: <16}{: <16}{: <16}{: <16}\n".format(
        target.name,
        " ".join(target.tags),
        str(target.body._ra),
        str(target.body._dec),
        rise_time,
        set_time,
        sep_note,
        notes,
    )
    return clo_clr + table_info + bcolors.ENDC
Esempio n. 2
0
def best_cal_cover(catalogue, katpt_target, ref_antenna):
    """Find calibrator with best coverage (>80%) of target visibility period.

    else return 2 calibrators to cover the whole target visibility period

    Parameters
    ----------
    catalogue: katpoint.Catalogue
    katpt_target: katpoint.Target
    ref_antenna: katpoint.Antenna

    Returns
    -------
    calibrator: katpoint.Target object
        closest calibrator
    separation_angle: float
        separation angle in degrees
    buffer_calibrator: katpoint.Target object
        additional calibrator for LST coverage
    buffer_separation: float
        additional separation_angle in degrees

    """
    calibrator, separation = _closest_calibrator_(catalogue, katpt_target.body,
                                                  ref_antenna.observer)
    buffer_calibrator = None
    buffer_separation = 180.0
    horizon = numpy.degrees(ref_antenna.observer.horizon)
    if separation > 20.0:  # calibrator rises some time after target
        # add another calibrator preceding the target
        observatory = Observatory(horizon=horizon,
                                  datetime=ref_antenna.observer.date)
        [tgt_rise_time, tgt_set_time
         ] = observatory.target_rise_and_set_times(katpt_target.body,
                                                   lst=False)
        closest_cals = []
        for each_cal in catalogue:
            try:
                [cal_rise_time, cal_set_time
                 ] = observatory.target_rise_and_set_times(each_cal.body,
                                                           lst=False)
            except ephem.NeverUpError:
                continue
            except ephem.AlwaysUpError:
                continue
            delta_time_to_cal_rise = cal_set_time - tgt_rise_time
            if delta_time_to_cal_rise > 0:
                # calc that rise before the target
                closest_cals.append([each_cal.name, delta_time_to_cal_rise])
            delta_time_to_cal_set = tgt_set_time - cal_rise_time
            if delta_time_to_cal_set > 0:
                # calc that sets after the target
                closest_cals.append([each_cal.name, delta_time_to_cal_set])
        if len(closest_cals) > 0:
            buffer_cal_idx = numpy.array(closest_cals)[:, 1].astype(
                float).argmin()
            buffer_calibrator = catalogue[closest_cals[buffer_cal_idx][0]]
            buffer_separation = ephem.separation(katpt_target.body,
                                                 buffer_calibrator.body)
            buffer_separation = numpy.degrees(buffer_separation)
    return calibrator, separation, buffer_calibrator, buffer_separation
Esempio n. 3
0
def main(creation_time,
         horizon=20.,
         solar_angle=20.,
         cal_tags=None,
         target=None,
         header_info=None,
         view_tags=None,
         mkat_catalogues=False,
         lst=False,
         all_cals=False,
         user_text_only=False,
         save_fig=False,
         infile=None,
         viewfile=None,
         outfile=None,
         **kwargs):
    """Run calibration observation."""

    # set defaults
    if cal_tags is None:
        cal_tags = ['gain']
    if view_tags is None:
        view_tags = ['elevation']

    observatory = Observatory()
    location = observatory.location
    node_config_available = observatory.node_config_available
    ref_antenna = katpoint.Antenna(location)
    ref_antenna.observer.date = ephem.Date(creation_time)
    ref_antenna.observer.horizon = ephem.degrees(str(horizon))

    text_only = (user_text_only or global_text_only)

    if viewfile is not None:
        # check if view file in CSV or YAML
        data_dict = read_yaml(viewfile)
        if data_dict:
            catalogue = katpoint.Catalogue()
            catalogue.antenna = ref_antenna
            for observation_cycle in data_dict["observation_loop"]:
                for target_item in observation_cycle["target_list"]:
                    name, target = katpoint_target_string(target_item)
                    catalogue.add(katpoint.Target(target))
        else:  # assume CSV
            # output observation stats for catalogue
            with open(viewfile, 'r') as fin:
                catalogue = katpoint.Catalogue(fin)
        obs_summary = obs_table(
            ref_antenna,
            catalogue=catalogue,
            solar_sep=solar_angle,
            lst=lst,
        )
        print(obs_summary)

        if not text_only:
            for view_option in view_tags:
                cp_cat = deepcopy(catalogue)
                if "elevation" in view_option:
                    plot_func = source_elevation
                if "solarangle" in view_option:
                    plot_func = source_solar_angle
                if "riseset" in view_option:
                    plot_func = source_rise_set
                plot_func(cp_cat, ref_antenna)
            plt.show()
        return

    if mkat_catalogues and os.path.isdir(mkat_catalogues):
        catalogue_path = mkat_catalogues
        config_file_available = True
    else:
        catalogue_path = "katconfig/user/catalogues"
        config_file_available = False

    # before doing anything, verify that calibrator catalogues can be accessed
    if not os.path.isdir(catalogue_path) and not node_config_available:
        msg = "Could not access calibrator catalogue default location\n"
        msg += "add explicit location of catalogue folder using --cat-path <dirname>"
        raise RuntimeError(msg)

    # constructing observational catalogue
    observation_catalogue = katpoint.Catalogue()
    observation_catalogue.antenna = ref_antenna

    # targets to obtain calibrators for
    header = ""
    cal_targets = []
    if target is not None:
        if len(target) > 2:
            # input target from command line
            target = [tgt.strip() for tgt in target]
            target = ", ".join(
                map(str, [target[0], "radec target", target[1], target[2]]))
            cal_targets = [katpoint.Target(target)]
        elif len(target) < 2:
            # input solar body from command line
            solar_body = target[0].capitalize()
            katpt_target = katpoint.Target("{}, special".format(solar_body))
            cal_targets = [katpt_target]
        else:  # if len(target) == 2
            # input target from command line
            target = [tgt.strip() for tgt in target]
            target = ", ".join(
                map(str, [target[0], "xephem target", target[1]]))
            cal_targets = [katpoint.Target(target)]
    else:  # assume the targets are in a file
        if infile is None:
            raise RuntimeError('Specify --target or CSV catalogue --infile')
        with open(infile, "r") as fin:
            # extract targets tagged to be used for calibrator selection
            for line in fin.readlines():
                if line[0] == "#":  # catch and keep header lines
                    header += line
                    continue
                if len(line) < 1:  # ignore empty lines
                    continue
                if "calref" in line:
                    target = line.strip().replace("calref", "target")
                    cal_targets.append(katpoint.Target(target))
                else:  # add target to catalogue
                    target = line.strip().replace("radec", "radec target")
                    observation_catalogue.add(katpoint.Target(target))
        # if not reference target for calibrator selection is specified,
        # simply select the first target listed in the catalogue
        if len(cal_targets) < 1:
            cal_targets = [observation_catalogue.targets[0]]

    for target in cal_targets:
        # add calibrator catalogues and calibrators to catalogue
        for cal_tag in cal_tags:
            cal_catalogue = os.path.join(
                catalogue_path,
                "Lband-{}-calibrators.csv".format(caltag_dict[cal_tag]))
            try:
                fin = open(cal_catalogue, 'r')
                if config_file_available:
                    calibrators = katpoint.Catalogue(fin)
                elif node_config_available:
                    calibrators = katpoint.Catalogue(
                        observatory.read_file_from_node_config(cal_catalogue))
                else:  # user specified calibrator file
                    calibrators = katpoint.Catalogue(fin)
            except (AssertionError, IOError):
                msg = bcolors.WARNING
                msg += "Unable to open {}\n".format(cal_catalogue)
                msg += "Observation file will still be created,"
                "please add calibrator manually\n"
                msg += bcolors.ENDC
                print(msg)
                continue
            if "gain" in cal_tag or "delay" in cal_tag:
                # for secondary calibrators such as gain:
                # find the closest calibrator
                calibrator, separation_angle = get_cal(calibrators, target,
                                                       ref_antenna)
                observation_catalogue = add_target(calibrator,
                                                   observation_catalogue,
                                                   tag=cal_tag + "cal")
            else:
                # for primary calibrators:
                if all_cals:
                    # show all calibrators
                    for calibrator in calibrators:
                        observation_catalogue = add_target(
                            calibrator,
                            observation_catalogue,
                            tag=cal_tag + "cal")
                else:
                    # find the best coverage over the target visibility period
                    [
                        calibrator, separation_angle, buffer_calibrator,
                        buffer_calibrator_separation_angle
                    ] = best_cal_cover(calibrators, target, ref_antenna)
                    if (buffer_calibrator is not None
                            and buffer_calibrator_separation_angle < 90.0):
                        observation_catalogue = add_target(
                            buffer_calibrator,
                            observation_catalogue,
                            tag=cal_tag + "cal",
                        )
                    observation_catalogue = add_target(calibrator,
                                                       observation_catalogue,
                                                       tag=cal_tag + "cal")
        observation_catalogue = add_target(target, observation_catalogue)

    # write observation catalogue
    catalogue_header = write_header(header_info, userheader=header)
    catalogue_data = observation_catalogue.sort()
    if outfile is not None:
        filename = os.path.splitext(os.path.basename(outfile))[0] + ".csv"
        outfile = os.path.join(os.path.dirname(outfile), filename)
        write_catalogue(outfile, catalogue_header, catalogue_data)
        print("Observation catalogue {}".format(outfile))

    # output observation stats for catalogue
    obs_summary = obs_table(
        ref_antenna,
        catalogue=catalogue_data,
        ref_tgt_list=cal_targets,
        solar_sep=solar_angle,
        lst=lst,
    )
    print(obs_summary)

    if global_text_only and not user_text_only:
        msg = "Required matplotlib functionalities not available\n"
        msg += "Cannot create elevation plot\n"
        msg += "Only producing catalogue file and output to screen"
        print(msg)

    if not text_only:
        # create elevation plot for sources
        obs_catalogue = catalogue_header
        for target in catalogue_data:
            obs_catalogue += "{}\n".format(target)
        source_elevation(observation_catalogue, ref_antenna)
        if save_fig:
            imfile = "elevation_utc_lst.png"
            print("Elevation plot {}".format(imfile))
            plt.savefig(imfile, dpi=300)
        plt.show()
        plt.close()
Esempio n. 4
0
def table_line(
    datetime,
    target,
    horizon,
    sep_angle=None,
    cal_limit=None,
    sol_limit=None,
    lst=False,
    notes="",
):
    """Construct a line of target information to display on command line output.

    Parameters
    ----------
    datetime: ephem.Date
        ephem date and time object
    target: katpoint.Catalogue
        target from katpoint.Catalogue object
    horizon: float
        minimum pointing angle in degrees
    sep_angle: float
        separation angle in degrees [optional param]
    cal_limit: float
        maximum separation angle between target and calibrator [optional]
    sol_limit: float
        minimum separation angle between target and Sun [optional]
    lst: str
        display times in LST rather than UTC
    notes: str
        user provided extra information

    Returns
    -------
        <name> <risetime UTC> <settime UTC> <Separation> <Notes>

    """
    observatory = Observatory(horizon=horizon, datetime=datetime)
    [rise_time, set_time] = observatory.target_rise_and_set_times(target.body,
                                                                  lst=lst)

    if type(rise_time) is ephem.Angle:
        rise_time = str(rise_time)
        set_time = str(set_time)
    elif type(rise_time) is ephem.Date:
        rise_time = rise_time.datetime().strftime("%H:%M:%S")
        set_time = set_time.datetime().strftime("%H:%M:%S")
    else:
        rise_time = None
        set_time = None

    clo_clr = bcolors.ENDC
    sep_note = ""
    if sep_angle is not None:
        sep_note = "%.2f" % sep_angle
        if cal_limit is not None:
            if sep_angle > cal_limit:
                clo_clr = bcolors.WARNING
                sep_note += " ***"
        if sol_limit is not None:
            if sep_angle < sol_limit:
                clo_clr = bcolors.FAIL
                sep_note += " ***"

    # ephem has difference between defining astrometric coordinates
    # for FixedBody vs Body objects
    try:
        RA = target.body._ra
        DECL = target.body._dec
    except AttributeError:
        RA = target.body.a_ra
        DECL = target.body.a_dec
    table_info = "{: <16}{: <32}{: <16}{: <16}{: <16}{: <16}{: <16}{: <16}\n".format(
        target.name,
        " ".join(target.tags),
        str(RA),
        str(DECL),
        rise_time,
        set_time,
        sep_note,
        notes,
    )
    return clo_clr + table_info + bcolors.ENDC