Beispiel #1
0
def test_convert_gwp(units, metric, species_in, species_out, expected_value):
    # Bare masses can be converted
    qty = registry.Quantity(1.0, units.format(""))
    expected = registry(f"{expected_value} {units}")

    observed = convert_gwp(metric, qty, species_in, species_out)
    assert observed.units == expected.units
    np.testing.assert_almost_equal(observed.magnitude, expected.magnitude)

    # '[mass] [speciesname] (/ [time])' can be converted; the input species is extracted
    # from the *qty* argument
    qty = "1.0 " + units.format(species_in)
    expected = registry(f"{expected_value} {units}")

    observed = convert_gwp(metric, qty, species_out)
    assert observed.units == expected.units
    np.testing.assert_almost_equal(observed.magnitude, expected.magnitude)

    # Tuple of (vector magnitude, unit expression) can be converted where the
    # the unit expression contains the input species name
    arr = np.array([1.0, 2.5, 0.1])
    qty = (arr, units.format(species_in))
    expected = arr * expected_value

    # Conversion works
    result = convert_gwp(metric, qty, species_out)
    # Magnitudes are as expected
    assert_array_almost_equal(result.magnitude, expected)
Beispiel #2
0
def convert_units(df, units_from, units_to, cols=("Value", "Unit")):
    """Convert units of *df*.

    Uses a vector :class:`registry.Quantity` to convert an entire column of values
    efficiently.

    Parameters
    ----------
    units_from : str or pint.Unit
        Units to convert from.
    units_to : str or pint.Unit
        Units to convert to.
    cols : 2-tuple of str
        Names of the columns in *df* containing the magnitude and unit,
        respectively.

    Returns
    -------
    pandas.DataFrame
    """
    # Create a vector pint.Quantity; convert units
    qty = registry.Quantity(df[cols[0]].values, units_from).to(units_to)

    # Assign magnitude and unit columns in output DataFrame
    return df.assign(**{cols[0]: qty.magnitude, cols[1]: f"{qty.units:~}"})
Beispiel #3
0
def test_format_mass(units_in, species_str, spec, output):
    # Quantity object can be formatted
    qty = registry.Quantity(3.5, units_in)
    assert format_mass(qty, species_str, spec) == output

    # Unit object can be formatted
    qty = registry.Unit(units_in)
    assert format_mass(qty, species_str, spec) == output
Beispiel #4
0
def _to_quantity(data):
    """Convert the values of an indexed pd.Series into pint.Quantity instances"""
    return pd.Series(
        [
            registry.Quantity(v, u)
            for v, u in zip(data.values, data.index.get_level_values("unit"))
        ],
        index=data.reset_index("unit", drop=True).index,
        name=data.name,
    )
Beispiel #5
0
def test_convert_gwp_carbon(context):
    # CO2 can be converted to C
    qty = (44.0 / 12, "tonne CO2")
    result = convert_gwp(context, qty, "C")
    assert result.units == registry("tonne")
    assert_almost_equal(result.magnitude, 1.0)

    # C can be converted to CO2
    qty = (1, "tonne C")
    expected = registry.Quantity(44.0 / 12, "tonne")
    assert convert_gwp(context, qty, "CO2e") == expected
Beispiel #6
0
def test_convert_gwp_carbon():
    # CO2 can be converted to C
    qty = (44. / 12, 'tonne CO2')
    result = convert_gwp('AR5GWP100', qty, 'C')
    assert result.units == registry('tonne')
    assert_almost_equal(result.magnitude, 1.0)

    # C can be converted to CO2
    qty = (1, 'tonne C')
    expected = registry.Quantity(44. / 12, 'tonne')
    assert convert_gwp('AR5GWP100', qty, 'CO2e') == expected
def convert_units(
    s: pd.Series,
    unit_info: Mapping[str, Tuple[float, str, Optional[str]]],
    store="magnitude",
) -> pd.Series:
    """Convert units of `s`, for use with :meth:`~pandas.DataFrame.apply`.

    ``s.name`` is used to retrieve a tuple of (`factor`, `input_unit`, `output_unit`)
    from `unit_info`. The (:class:`float`) values of `s` are converted to
    :class:`pint.Quantity` with the `input_unit` and factor; then cast to `output_unit`,
    if provided.

    Parameters
    ----------
    s : pandas.Series
    unit_info : dict (str -> tuple)
        Mapping from quantity name (matched to ``s.name``) to 3-tuples of (`factor`,
        `input_unit`, `output_unit`). `output_unit` may be :obj:`None`. For example,
        see :data:`.ikarus.UNITS`.
    store : "magnitude" or "quantity"
        If "magnitude", the values of the returned series are the magnitudes of the
        results, with no output units. If "quantity", the values are scalar
        :class:`~pint.Quantity` objects.

    Returns
    -------
    pandas.Series
        Same shape, index, and values as `s`, with output units.
    """
    if store not in "magnitude quantity":
        raise ValueError(f"store={repr(store)}")

    # Retrieve the information from `unit_info`
    factor, unit_in, unit_out = unit_info[s.name]

    # Default: `unit_out` is the same as `unit_in`
    unit_out = unit_out or unit_in

    # - Convert the values to a pint.Quantity(array) with the input units
    # - Convert to output units
    # - According to `store`, either extract just the magnitude, or store scalar
    #   pint.Quantity objects.
    # - Reassemble into a series with index matching `s`
    result = registry.Quantity(factor * s.values, unit_in).to(unit_out)

    return series_of_pint_quantity(
        result.magnitude if store == "magnitude" else result.tolist(),
        index=s.index,
        dtype=object,
        name=s.name,
    )
Beispiel #8
0
def convert_units(df: pd.DataFrame,
                  units_from,
                  units_to,
                  cols: Optional[Sequence[str]] = None) -> pd.DataFrame:
    """Convert units of `df`.

    Uses a vector :class:`registry.Quantity` to convert an entire column of values
    efficiently.

    Parameters
    ----------
    units_from : str or pint.Unit
        Units to convert from.
    units_to : str or pint.Unit
        Units to convert to.
    cols : 2-tuple of str
        Names of the columns in `df` containing the magnitude and unit, respectively.
        Default for the mangnitude is whichever column of `df` matches “value”, case-
        insensitive; if multiple columns have different cases of this name, the first
        is used.

    Returns
    -------
    pandas.DataFrame
    """
    # Default values
    cols = cols or [
        next(filter(lambda name: name.lower() == "value", df.columns)),
        "UNIT",
    ]

    # Create a vector pint.Quantity; convert units
    qty = registry.Quantity(df[cols[0]].values, units_from).to(units_to)

    # Assign magnitude and unit columns in output DataFrame
    return df.assign(**{cols[0]: qty.magnitude, cols[1]: f"{qty.units:~}"})
Beispiel #9
0
    """Calling an operation with args that don't return an IamDataFrame raises"""
    match = "Value returned by `add` cannot be cast to an IamDataFrame: 5"
    with pytest.raises(ValueError, match=match):
        test_df_year.add(2, 3, "foo")


@pytest.mark.parametrize(
    "arg, df_func, fillna, ignore_units",
    (
        ("Primary Energy|Coal", df_ops_variable, None, False),
        ("Primary Energy|Coal", df_ops_variable_default, {
            "c": 7,
            "b": 5
        }, "foo"),
        ("Primary Energy|Coal", df_ops_variable_default, 5, "foo"),
        (registry.Quantity(2, "EJ/yr"), df_ops_variable_number, None, False),
        (2, df_ops_variable_number, None, "foo"),
    ),
)
@pytest.mark.parametrize("append", (False, True))
def test_add_variable(test_df_year, arg, df_func, fillna, ignore_units,
                      append):
    """Verify that in-dataframe addition works on the default `variable` axis"""

    # change one unit to make ignore-units strictly necessary
    if ignore_units:
        test_df_year.rename(
            variable={"Primary Energy": "Primary Energy"},
            unit={"EJ/yr": "custom_unit"},
            inplace=True,
        )