Source code for pyBADA.conversions

"""
Common unit conversions module
"""

from datetime import datetime
from math import pi
from time import mktime

import numpy as np
import pandas as pd
import xarray as xr

from pyBADA import utils


def _unit_converter(factor):
    """
    Returns a function that multiplies its input by `factor`,
    vectorized through utils._extract / utils._wrap.
    """

    def converter(val):
        # pull out the raw array
        arr = utils._extract(val)
        # do the multiplication
        core = arr * factor
        # pass both the result and the original to _wrap
        return utils._wrap(core, original=val)

    return converter


# Linear unit conversions (factor-based)
_factor_map = {
    "ft2m": 0.3048,
    "nm2m": 1852.0,
    "h2s": 3600.0,
    "kt2ms": 0.514444,
    "lb2kg": 0.453592,
    "deg2rad": pi / 180.0,
    "rad2deg": 180.0 / pi,
    "m2ft": 1 / 0.3048,
    "m2nm": 1 / 1852.0,
    "s2h": 1 / 3600.0,
    "ms2kt": 1 / 0.514444,
    "kg2lb": 1 / 0.453592,
    "hp2W": 745.699872,
}

# Dynamically create each converter in the module namespace
for _name, _factor in _factor_map.items():
    globals()[_name] = _unit_converter(_factor)


[docs] def date2posix(val): """ Convert date(s) to POSIX timestamp in seconds since 1970-01-01, vectorized for numpy arrays, pandas Series/DataFrame, and xarray.DataArray. :param val: Input date(s). Can be string, datetime, numpy array of strings/datetimes, pandas Series/DataFrame of datetime-like, or xarray.DataArray of datetime64. :type val: str or datetime or array-like or pandas Series/DataFrame or xarray.DataArray :returns: POSIX timestamp(s) in seconds, matching input type. """ # xarray DataArray of datetime64 if isinstance(val, xr.DataArray): out = val.astype("datetime64[s]").astype(int) out.attrs.update(units="s", long_name="POSIX timestamp") return out if isinstance(val, (pd.Series, pd.DataFrame)): ts = pd.to_datetime(val) arr = ts.values.astype("datetime64[s]").astype(int) if isinstance(val, pd.Series): return pd.Series(arr, index=val.index, name=val.name) return pd.DataFrame(arr, index=val.index, columns=val.columns) if isinstance(val, str): dt = datetime.strptime(val, "%Y-%m-%d %H:%M:%S") return mktime(dt.timetuple()) try: if isinstance(val, datetime): return mktime(val.timetuple()) except NameError: pass arr = np.asarray(val) try: dt64 = arr.astype("datetime64[s]") return dt64.astype(int) except Exception: flat = arr.ravel() result = [] for v in flat: if isinstance(v, str): dt = datetime.strptime(v, "%Y-%m-%d %H:%M:%S") result.append(mktime(dt.timetuple())) else: result.append(mktime(v.timetuple())) out = np.array(result) return out.reshape(arr.shape)
[docs] def unix2date(val): """ Convert POSIX timestamp(s) in seconds to date string(s) in "%Y-%m-%d %H:%M:%S" format, vectorized for numpy arrays, pandas Series/DataFrame, and xarray.DataArray. :param val: Input POSIX timestamp(s). Float, numpy array, pandas Series/DataFrame of floats, or xarray.DataArray of ints. :type val: float or array-like or pandas Series/DataFrame or xarray.DataArray :returns: Date string(s) in "%Y-%m-%d %H:%M:%S", matching input type. """ if isinstance(val, xr.DataArray): dt64 = val.astype("datetime64[s]") return dt64.dt.strftime("%Y-%m-%d %H:%M:%S") if isinstance(val, (pd.Series, pd.DataFrame)): ts = pd.to_datetime(val, unit="s") return ts.dt.strftime("%Y-%m-%d %H:%M:%S") arr = np.asarray(val, dtype=float) flat = arr.ravel() result = [] for v in flat: dt = datetime.fromtimestamp(int(v)) result.append(dt.strftime("%Y-%m-%d %H:%M:%S")) res_arr = np.array(result) if res_arr.ndim == 0: return res_arr.item() return res_arr.reshape(arr.shape)
convertFrom = { "unix": unix2date, "ft": ft2m, "nm": nm2m, "h": h2s, "kt": kt2ms, "lb": lb2kg, "deg": deg2rad, "date": date2posix, "rad": rad2deg, "ms": ms2kt, "m": m2ft, "kg": kg2lb, "s": s2h, }