# Licensed under a 3-clause BSD style license - see LICENSE.rst"""Units and Quantity related helper functions."""importloggingfrommathimportfloorimportnumpyasnpimportastropy.unitsasu__all__=["standardise_unit","unit_from_fits_image_hdu"]log=logging.getLogger(__name__)
[docs]defstandardise_unit(unit):"""Standardise unit. Changes applied by this function: * Drop "photon" == "ph" from the unit * Drop "count" == "ct" from the unit Parameters ---------- unit : `~astropy.units.Unit` or str Any old unit. Returns ------- unit : `~astropy.units.Unit` Shiny new, standardised unit. Examples -------- >>> from gammapy.utils.units import standardise_unit >>> standardise_unit('ph cm-2 s-1') Unit("1 / (s cm2)") >>> standardise_unit('ct cm-2 s-1') Unit("1 / (s cm2)") >>> standardise_unit('cm-2 s-1') Unit("1 / (s cm2)") """unit=u.Unit(unit)bases,powers=[],[]forbase,powerinzip(unit.bases,unit.powers):ifstr(base)notin{"ph","ct"}:bases.append(base)powers.append(power)returnu.CompositeUnit(scale=unit.scale,bases=bases,powers=powers)
[docs]defunit_from_fits_image_hdu(header):"""Read unit from a FITS image HDU. - The ``BUNIT`` key is used. - `astropy.units.Unit` is called. If the ``BUNIT`` value is invalid, a log warning is emitted and the empty unit is used. - `standardise_unit` is called """unit=header.get("BUNIT","")try:u.Unit(unit)exceptValueError:log.warning(f"Invalid value BUNIT={unit!r} in FITS header. Setting empty unit.")unit=""returnstandardise_unit(unit)
defenergy_unit_format(E):"""Format energy quantities to a string representation that is more comfortable to read. This is done by switching to the most relevant unit (keV, MeV, GeV, TeV) and changing the float precision. Parameters ---------- E: `~astropy.units.Quantity` Quantity or list of quantities. Returns ------- str : str A string or tuple of strings with energy unit formatted. """try:iter(E)exceptTypeError:passelse:returntuple(map(energy_unit_format,E))i=floor(np.log10(E.to_value(u.eV))/3)# a new unit every 3 decadesunit=(u.eV,u.keV,u.MeV,u.GeV,u.TeV,u.PeV)[i]ifi<5elseu.PeVv=E.to_value(unit)i=floor(np.log10(v))prec=(2,1,0)[i]ifi<3else0returnf"{v:0.{prec}f}{unit}"