コード例 #1
0
    def photometry_to_table(
            self,
            output: str = None,
            best: bool = False,
            fmts: List[str] = ("ascii.ecsv", "ascii.csv")
    ):
        """
        Converts the photometry information, which is stored internally as a dictionary, into an astropy QTable.
        :param output: Where to write table.
        :return:
        """

        if output is None:
            output = self.build_photometry_table_path()

        # if self.photometry_tbl is None:

        tbls = []
        for instrument_name in self.photometry:
            instrument = inst.Instrument.from_params(instrument_name)
            for filter_name in self.photometry[instrument_name]:
                fil = instrument.filters[filter_name]

                if best:
                    phot_dict, _ = self.select_photometry_sep(fil=filter_name, instrument=instrument_name)
                    phot_dict["band"] = filter_name
                    phot_dict["instrument"] = instrument_name
                    phot_dict["lambda_eff"] = u.check_quantity(
                        number=fil.lambda_eff,
                        unit=units.Angstrom
                    )
                    # tbl = table.QTable([phot_dict])
                    tbls.append(phot_dict)
                    print("phot_dict:")
                    print(phot_dict)

                else:
                    for epoch in self.photometry[instrument_name][filter_name]:
                        phot_dict = self.photometry[instrument_name][filter_name][epoch].copy()
                        phot_dict["band"] = filter_name
                        phot_dict["instrument"] = instrument_name
                        phot_dict["lambda_eff"] = u.check_quantity(
                            number=fil.lambda_eff,
                            unit=units.Angstrom
                        )
                        # tbl = table.QTable([phot_dict])
                        tbls.append(phot_dict)

        print(tbls)
        if best:
            self.photometry_tbl = table.vstack(tbls)
        else:
            self.photometry_tbl = table.QTable(tbls)

        if output is not False:
            for fmt in fmts:
                self.photometry_tbl.write(output.replace(".ecsv", fmt[fmt.find("."):]), format=fmt, overwrite=True)
        return self.photometry_tbl
コード例 #2
0
def solve_field(
        image_files: Union[str, list],
        base_filename: str = "astrometry",
        overwrite: bool = True,
        tweak: bool = True,
        search_radius: units.Quantity = 1 * units.degree,
        centre: SkyCoord = None,
        guess_scale: bool = True,
        time_limit: units.Quantity = None,
        verify: bool = True,
        odds_to_tune_up: float = 1e6,
        odds_to_solve: float = 1e9,
        *flags,
        **params):
    """
    Returns True if successful (by checking whether the corrected file is generated); False if not.
    :param image_files:
    :param base_filename:
    :param overwrite:
    :param flags:
    :param params:
    :return:
    """

    params["o"] = base_filename
    params["odds-to-tune-up"] = odds_to_tune_up
    params["odds-to-solve"] = odds_to_solve
    if time_limit is not None:
        params["l"] = check_quantity(time_limit, units.second).value
    if search_radius is not None:
        params["radius"] = search_radius.to(units.deg).value
    if centre is not None:
        params["ra"] = centre.ra.to(units.deg).value
        params["dec"] = centre.dec.to(units.deg).value
    debug_print(1, "solve_field(): tweak ==", tweak)

    flags = list(flags)
    if overwrite:
        flags.append("O")
    if guess_scale:
        flags.append("g")
    if not tweak:
        flags.append("T")
    if not verify:
        flags.append("y")


    system_command("solve-field", image_files, False, True, False, *flags, **params)
    if isinstance(image_files, list):
        image_path = image_files[0]
    else:
        image_path = image_files
    check_dir = os.path.split(image_path)[0]
    check_path = os.path.join(check_dir, f"{base_filename}.new")
    print(f"Checking for result file at {check_path}...")
    return os.path.isfile(check_path)
コード例 #3
0
def test_check_quantity():
    number = 10.
    assert u.check_quantity(number=number, unit=units.meter) == number * units.meter
    number = 10. * units.meter
    assert u.check_quantity(number=number, unit=units.meter) == number
    number = 1000. * units.centimeter
    assert u.check_quantity(number=number, unit=units.meter, convert=True) == 10. * units.meter
    assert u.check_quantity(number=number, unit=units.meter, convert=True).unit == units.meter
    assert u.check_quantity(number=number, unit=units.meter, convert=False).unit == units.centimeter
    with pytest.raises(units.UnitsError) as e:
        u.check_quantity(number=number, unit=units.meter, allow_mismatch=False)
    assert e.type is units.UnitsError
    with pytest.raises(units.UnitsError) as e:
        u.check_quantity(number=number, unit=units.joule)
    assert e.type is units.UnitsError
コード例 #4
0
    def __init__(
            self,
            name: str = None,
            position: Union[SkyCoord, str] = None,
            position_err: Union[float, units.Quantity, dict, PositionUncertainty, tuple] = 0.0 * units.arcsec,
            field=None,
            row: table.Row = None,
            plotting: dict = None
    ):
        self.name = name

        self.cat_row = row
        self.position = None
        self.position_err = None
        if self.cat_row is not None:
            self.position_from_cat_row()
        else:
            self.position = astm.attempt_skycoord(position)
            if type(position_err) is not PositionUncertainty:
                self.position_err = PositionUncertainty(uncertainty=position_err, position=self.position)
            self.position_galactic = None
            if isinstance(self.position, SkyCoord):
                self.position_galactic = self.position.transform_to("galactic")

        if self.name is None:
            self.jname()
        self.name_filesys = None
        self.set_name_filesys()

        self.photometry = {}
        self.photometry_tbl = None
        self.data_path = None
        self.output_file = None
        self.field = field
        self.irsa_extinction_path = None
        self.irsa_extinction = None
        self.ebv_sandf = None
        self.extinction_power_law = None
        self.paths = {}
        if self.data_path is not None:
            self.load_output_file()
        if isinstance(plotting, dict):
            self.plotting_params = plotting
            if "frame" in self.plotting_params and self.plotting_params["frame"] is not None:
                self.plotting_params["frame"] = u.check_quantity(self.plotting_params["frame"], units.arcsec)
        else:
            self.plotting_params = {}

        self.a = None
        self.b = None
        self.theta = None
        self.kron = None
コード例 #5
0
def source_extractor(
        image_path: str,
        output_dir: str = None,
        configuration_file: str = None,
        parameters_file: str = None,
        catalog_name: str = None,
        copy_params: bool = True,
        template_image_path: str = None,
        **configs):
    """
    :param configs: Any source-extractor (sextractor) parameter, normally read via the config file but that can be
    overridden by passing to the shell command, can be given here.
    """

    if "gain" in configs:
        configs["gain"] = u.check_quantity(number=configs["gain"], unit=gain_unit).to(gain_unit).value

    old_dir = os.getcwd()
    if output_dir is None:
        output_dir = os.getcwd()
    else:
        u.mkdir_check(output_dir)
        os.chdir(output_dir)

    if copy_params:
        os.system(f"cp {os.path.join(p.path_to_config_psfex(), '*')} .")

    sys_str = "source-extractor "
    if template_image_path is not None:
        sys_str += f"{template_image_path},"
    sys_str += image_path + " "
    if configuration_file is not None:
        sys_str += f" -c {configuration_file}"
    if catalog_name is None:
        image_name = os.path.split(image_path)[-1]
        catalog_name = f"{image_name}.cat"
    sys_str += f" -CATALOG_NAME {catalog_name}"
    if parameters_file is not None:
        sys_str += f" -PARAMETERS_NAME {parameters_file}"
    for param in configs:
        sys_str += f" -{param.upper()} {configs[param]}"
    u.system_command_verbose(sys_str, error_on_exit_code=True)
    catalog_path = os.path.join(output_dir, catalog_name)
    os.chdir(old_dir)
    return catalog_path
コード例 #6
0
 def __init__(
         self,
         name: str = None,
         position: Union[SkyCoord, str] = None,
         position_err: Union[float, units.Quantity, dict, PositionUncertainty, tuple] = 0.0 * units.arcsec,
         host_galaxy: Galaxy = None,
         dm: Union[float, units.Quantity] = None,
         field=None,
         plotting: dict = None,
 ):
     super().__init__(
         name=name,
         position=position,
         position_err=position_err,
         field=field,
         plotting=plotting
     )
     self.host_galaxy = host_galaxy
     self.dm = dm
     if self.dm is not None:
         self.dm = u.check_quantity(self.dm, unit=dm_units)
コード例 #7
0
def ingest_filter_transmission(path: str,
                               fil_name: str,
                               instrument: str,
                               instrument_response: bool = False,
                               atmosphere: bool = False,
                               lambda_eff: units.Quantity = None,
                               fwhm: float = None,
                               source: str = None,
                               wavelength_unit: units.Unit = units.Angstrom,
                               percentage: bool = False,
                               quiet: bool = False):
    """

    :param path:
    :param fil_name:
    :param instrument:
    :param instrument_response: Filter curve includes instrument response
    :param atmosphere: Filter curve includes atmospheric transmission
    :param lambda_eff:
    :param fwhm:
    :param source:
    :param wavelength_unit:
    :param percentage:
    :param quiet:
    :return:
    """

    if not wavelength_unit.is_equivalent(units.Angstrom):
        raise units.UnitTypeError(
            f"Wavelength units must be of type length, not {wavelength_unit}")

    type_str = "_filter"
    if instrument_response:
        type_str += "_instrument"
    if atmosphere:
        type_str += "_atmosphere"

    params = filter_params(f=fil_name, instrument=instrument, quiet=quiet)
    if params is None:
        params = new_filter_params(quiet=quiet)
        params['name'] = fil_name
        params['instrument'] = instrument

    if lambda_eff is not None:
        lambda_eff = u.check_quantity(lambda_eff,
                                      unit=units.Angstrom,
                                      convert=True)
        params['lambda_eff'] = lambda_eff
        # TODO: If None, measure?
    if fwhm is not None:
        params['fwhm'] = fwhm
        # TODO: If None, measure?
    if source is not None:
        params[f'source{type_str}'] = source

    tbl = QTable.read(path, format="ascii")
    tbl["col1"].name = "wavelength"
    tbl["wavelength"] *= wavelength_unit
    tbl["wavelength"] = tbl["wavelength"].to("Angstrom")

    tbl["col2"].name = "transmission"

    if percentage:
        tbl["transmission"] /= 100

    tbl.sort("wavelength")

    params[f'wavelengths{type_str}'] = tbl["wavelength"].value.tolist()
    params[f'transmissions{type_str}'] = tbl["transmission"].value.tolist()

    save_params(file=os.path.join(param_dir, 'filters',
                                  f'{instrument}-{fil_name}'),
                dictionary=params,
                quiet=quiet)
コード例 #8
0
    def __init__(
            self,
            uncertainty: Union[float, units.Quantity, dict, tuple] = None,
            position: SkyCoord = None,
            ra_err_sys: Union[float, units.Quantity] = None,
            ra_err_stat: Union[float, units.Quantity] = None,
            dec_err_sys: Union[float, units.Quantity] = None,
            dec_err_stat: Union[float, units.Quantity] = None,
            a_stat: Union[float, units.Quantity] = None,
            a_sys: Union[float, units.Quantity] = None,
            b_stat: Union[float, units.Quantity] = None,
            b_sys: Union[float, units.Quantity] = None,
            theta: Union[float, units.Quantity] = None,
            sigma: float = None
    ):
        """
        If a single value is provided for uncertainty, the uncertainty ellipse will be assumed to be circular.
        Values in dictionary, if provided, override values given as arguments.
        Position values provided without units are assumed to be in degrees.
        On the other hand, uncertainty values provided without units are assumed to be in arcseconds;
        except for uncertainties in RA, which are assumed in RA seconds.
        :param uncertainty:
        :param position:
        :param ra_err_sys:
        :param ra_err_stat:
        :param dec_err_sys:
        :param dec_err_stat:
        :param a_stat:
        :param a_sys:
        :param b_stat:
        :param b_sys:
        :param theta:
        :param sigma: The confidence interval (expressed in multiples of sigma) of the uncertainty ellipse.
        """
        self.sigma = sigma
        # Assign values from dictionary, if provided.
        if type(uncertainty) is dict:
            if "ra" in uncertainty and uncertainty["ra"] is not None:
                if "sys" in uncertainty["ra"] and uncertainty["ra"]["sys"] is not None:
                    ra_err_sys = uncertainty["ra"]["sys"]
                if "stat" in uncertainty["ra"] and uncertainty["ra"]["stat"] is not None:
                    ra_err_stat = uncertainty["ra"]["stat"]
            if "dec" in uncertainty and uncertainty["dec"] is not None:
                if "sys" in uncertainty["dec"] and uncertainty["dec"]["sys"] is not None:
                    dec_err_sys = uncertainty["dec"]["sys"]
                if "stat" in uncertainty["dec"] and uncertainty["dec"]["stat"] is not None:
                    dec_err_stat = uncertainty["dec"]["stat"]
            if "a" in uncertainty and uncertainty["a"] is not None:
                if "sys" in uncertainty["a"] and uncertainty["a"]["sys"] is not None:
                    a_sys = uncertainty["a"]["sys"]
                if "stat" in uncertainty["a"] and uncertainty["a"]["stat"] is not None:
                    a_stat = uncertainty["a"]["stat"]
            if "b" in uncertainty and uncertainty["b"] is not None:
                if "sys" in uncertainty["b"] and uncertainty["b"]["sys"] is not None:
                    b_sys = uncertainty["b"]["sys"]
                if "stat" in uncertainty["b"] and uncertainty["a"]["stat"] is not None:
                    b_stat = uncertainty["b"]["stat"]
            if "theta" in uncertainty and uncertainty["theta"] is not None:
                theta = uncertainty["theta"]

        # If uncertainty is a single value, assume a circular uncertainty region without distinction between systematic
        # and statistical.
        elif uncertainty is not None:
            a_stat = uncertainty
            a_sys = 0.0
            b_stat = uncertainty
            b_sys = 0.0
            theta = 0.0

        # Check whether we're specifying uncertainty using equatorial coordinates or ellipse parameters.
        u.debug_print(2, "PositionUncertainty.__init__(): a_stat, a_sys, b_stat, b_sys, theta, position ==", a_stat,
                      a_sys, b_stat, b_sys, theta, position)
        u.debug_print(2, "PositionUncertainty.__init__(): ra_err_sys, ra_err_stat, dec_err_sys, dec_err_stat ==",
                      ra_err_sys, ra_err_stat, dec_err_sys, dec_err_stat)
        if a_stat is not None and a_sys is not None and b_stat is not None and b_sys is not None and theta is not None and position is not None:
            ellipse = True
        elif ra_err_sys is not None and ra_err_stat is not None and dec_err_sys is not None and dec_err_stat is not None:
            ellipse = False
        else:
            raise ValueError(
                "Either all ellipse values (a, b, theta) or all equatorial values (ra, dec, position) must be provided.")

        ra_err_sys = u.check_quantity(number=ra_err_sys, unit=units.hourangle / 3600)
        ra_err_stat = u.check_quantity(number=ra_err_stat, unit=units.hourangle / 3600)
        dec_err_sys = u.check_quantity(number=dec_err_sys, unit=units.arcsec)
        dec_err_stat = u.check_quantity(number=dec_err_stat, unit=units.arcsec)
        # Convert equatorial uncertainty to ellipse with theta=0
        if not ellipse:
            ra = position.ra
            dec = position.dec
            a_sys = SkyCoord(0.0 * units.degree, dec).separation(SkyCoord(ra_err_sys, dec))
            a_stat = SkyCoord(0.0 * units.degree, dec).separation(SkyCoord(ra_err_stat, dec))
            b_sys = SkyCoord(ra, dec).separation(SkyCoord(ra, dec + dec_err_sys))
            b_stat = SkyCoord(ra, dec).separation(SkyCoord(ra, dec + dec_err_stat))
            a_sys, b_sys = max(a_sys, b_sys), min(a_sys, b_sys)
            a_stat, b_stat = max(a_stat, b_stat), min(a_stat, b_stat)
            theta = 0.0 * units.degree
        # Or use ellipse parameters as given.
        else:
            a_sys = u.check_quantity(number=a_sys, unit=units.arcsec)
            a_stat = u.check_quantity(number=a_stat, unit=units.arcsec)
            b_sys = u.check_quantity(number=b_sys, unit=units.arcsec)
            b_stat = u.check_quantity(number=b_stat, unit=units.arcsec)
            theta = u.check_quantity(number=theta, unit=units.arcsec)

        self.a_sys = a_sys
        self.a_stat = a_stat
        self.b_sys = b_sys
        self.b_stat = b_stat
        self.theta = theta

        self.ra_sys = ra_err_sys
        self.dec_sys = dec_err_sys
        self.ra_stat = ra_err_stat
        self.dec_stat = dec_err_stat
コード例 #9
0
    def add_photometry(
            self,
            instrument: Union[str, inst.Instrument],
            fil: Union[str, inst.Filter],
            epoch_name: str,
            mag: units.Quantity, mag_err: units.Quantity,
            snr: float,
            ellipse_a: units.Quantity, ellipse_a_err: units.Quantity,
            ellipse_b: units.Quantity, ellipse_b_err: units.Quantity,
            ellipse_theta: units.Quantity, ellipse_theta_err: units.Quantity,
            ra: units.Quantity, ra_err: units.Quantity,
            dec: units.Quantity, dec_err: units.Quantity,
            kron_radius: float,
            image_path: str,
            good_image_path: str = None,
            separation_from_given: units.Quantity = None,
            epoch_date: str = None,
            class_star: float = None,
            mag_psf: units.Quantity = None, mag_psf_err: units.Quantity = None,
            snr_psf: float = None,
            image_depth: units.Quantity = None,
            do_mask: bool = True,
            **kwargs
    ):
        if good_image_path is None:
            good_image_path = image_path
        if isinstance(epoch_date, time.Time):
            epoch_date = epoch_date.strftime('%Y-%m-%d')
        photometry = {
            "instrument": str(instrument),
            "filter": str(fil),
            "epoch_name": epoch_name,
            "mag": u.check_quantity(mag, unit=units.mag),
            "mag_err": u.check_quantity(mag_err, unit=units.mag),
            "snr": float(snr),
            "a": u.check_quantity(ellipse_a, unit=units.arcsec, convert=True),
            "a_err": u.check_quantity(ellipse_a_err, unit=units.arcsec, convert=True),
            "b": u.check_quantity(ellipse_b, unit=units.arcsec, convert=True),
            "b_err": u.check_quantity(ellipse_b_err, unit=units.arcsec, convert=True),
            "theta": u.check_quantity(ellipse_theta, unit=units.deg, convert=True),
            "theta_err": u.check_quantity(ellipse_theta_err, unit=units.deg, convert=True),
            "ra": u.check_quantity(ra, units.deg, convert=True),
            "ra_err": u.check_quantity(ra_err, units.deg, convert=True),
            "dec": u.check_quantity(dec, units.deg, convert=True),
            "dec_err": u.check_quantity(dec_err, units.deg, convert=True),
            "kron_radius": float(kron_radius),
            "separation_from_given": u.check_quantity(separation_from_given, units.arcsec, convert=True),
            "epoch_date": str(epoch_date),
            "class_star": float(class_star),
            "mag_psf": u.check_quantity(mag_psf, unit=units.mag),
            "mag_psf_err": u.check_quantity(mag_psf_err, unit=units.mag),
            "snr_psf": snr_psf,
            "image_depth": u.check_quantity(image_depth, unit=units.mag),
            "image_path": image_path,
            "good_image_path": good_image_path,
            "do_mask": do_mask,
        }

        kwargs.update(photometry)
        if instrument not in self.photometry:
            self.photometry[instrument] = {}
        if fil not in self.photometry[instrument]:
            self.photometry[instrument][fil] = {}
        self.photometry[instrument][fil][epoch_name] = kwargs
        self.update_output_file()
        return kwargs