Source code for elphick.geomet.utils.moisture

import logging
import re
from copy import deepcopy
from typing import Optional, Dict, List

import numpy as np
import pandas as pd


[docs] def detect_moisture_column(columns: List[str]) -> Optional[str]: """Detects the moisture column in a list of columns Args: columns: List of column names Returns: """ res: Optional[str] = None search_regex: str = '(h2o)|(moisture)|(moist)|(mc)|(moisture_content)' for col in columns: if re.search(search_regex, col, re.IGNORECASE): res = col break return res
[docs] def solve_mass_moisture(mass_wet: pd.Series = None, mass_dry: pd.Series = None, moisture: pd.Series = None, moisture_column_name: str = 'h2o', rtol: float = 1e-05, atol: float = 1e-08) -> pd.Series: logger = logging.getLogger(name=__name__) _vars: Dict = {k: v for k, v in deepcopy(locals()).items()} key_columns = ['mass_wet', 'mass_dry', 'moisture'] vars_supplied: List[str] = [k for k in key_columns if _vars.get(k) is not None] if len(vars_supplied) == 3: logger.info('Over-specified - checking for balance.') re_calc_moisture = (mass_wet - mass_dry) / mass_wet * 100 if not np.isclose(re_calc_moisture, moisture, rtol=rtol, atol=atol).all(): msg = f"Mass balance is not satisfied: {re_calc_moisture}" logger.error(msg) raise ValueError(msg) elif len(vars_supplied) == 1: raise ValueError('Insufficient arguments supplied - at least 2 required.') var_to_solve: str = next((k for k, v in _vars.items() if v is None), None) res: Optional[pd.Series] = None if var_to_solve: calculations = { 'mass_wet': lambda: mass_dry / (1 - moisture / 100), 'mass_dry': lambda: mass_wet - (mass_wet * moisture / 100), 'moisture': lambda: (mass_wet - mass_dry) / mass_wet * 100 } res = calculations[var_to_solve]() res.name = var_to_solve if var_to_solve != 'moisture' else moisture_column_name # use the supplied column name return res