Source code for dclab.features.emodulus.scale_linear

"""Scale conversion applicable to a linear elastic model"""
from __future__ import annotations

import warnings

import numpy as np
import numpy.typing as npt


[docs] def convert(area_um: npt.NDArray, deform: npt.NDArray, channel_width_in: float, channel_width_out: float, emodulus: npt.NDArray = None, flow_rate_in: float = None, flow_rate_out: float = None, viscosity_in: float = None, viscosity_out: float | npt.NDArray = None, inplace: bool = False ) -> ( tuple[npt.NDArray, npt.NDArray] | tuple[npt.NDArray, npt.NDArray, npt.NDArray] ): """Convert area-deformation-emodulus triplet The conversion formula is described in :cite:`Mietke2015`. Parameters ---------- area_um Convex cell area [µm²] deform Deformation channel_width_in Original channel width [µm] channel_width_out Target channel width [µm] emodulus Young's Modulus [kPa] flow_rate_in Original flow rate [µL/s] flow_rate_out Target flow rate [µL/s] viscosity_in Original viscosity [mPa*s] viscosity_out Target viscosity [mPa*s]; This can be an array inplace If True, override input arrays with corrected data Returns ------- area_um_corr Corrected cell area [µm²] deform_corr Deformation (a copy if `inplace` is False) emodulus_corr Corrected emodulus [kPa]; only returned if `emodulus` is given. Notes ----- If only `area_um`, `deform`, `channel_width_in` and `channel_width_out` are given, then only the area is corrected and returned together with the original deform. If all other arguments are not set to None, the emodulus is corrected and returned as well. """ warnings.warn("Usage of the `convert` method is deprecated! Please use " + "the scale_feature method instead.", DeprecationWarning) copy = not inplace deform_corr = np.array(deform, copy=copy) if channel_width_in != channel_width_out: area_um_corr = scale_area_um(area_um, channel_width_in, channel_width_out, inplace) else: area_um_corr = np.array(area_um, copy=copy) if (emodulus is not None and flow_rate_in is not None and flow_rate_out is not None and viscosity_in is not None and viscosity_out is not None): emodulus_corr = scale_emodulus(emodulus, channel_width_in, channel_width_out, flow_rate_in, flow_rate_out, viscosity_in, viscosity_out, inplace) if emodulus is None: return area_um_corr, deform_corr else: return area_um_corr, deform_corr, emodulus_corr
[docs] def scale_area_um(area_um: npt.NDArray, channel_width_in: float, channel_width_out: float, inplace: bool = False, **kwargs) -> npt.NDArray: """Perform scale conversion for area_um (linear elastic model) The area scales with the characteristic length "channel radius" L according to (L'/L)². The conversion formula is described in :cite:`Mietke2015`. .. versionadded: 0.25.0 Parameters ---------- area_um Convex area [µm²] channel_width_in Original channel width [µm] channel_width_out Target channel width [µm] inplace If True, override input arrays with corrected data kwargs not used Returns ------- area_um_corr Scaled area [µm²] """ copy = not inplace if issubclass(area_um.dtype.type, np.integer) and inplace: raise ValueError("Cannot correct integer `area_um` in-place!") area_um_corr = np.array(area_um, copy=copy) if channel_width_in != channel_width_out: area_um_corr *= (channel_width_out / channel_width_in)**2 return area_um_corr
[docs] def scale_emodulus(emodulus: npt.NDArray, channel_width_in: float, channel_width_out: float, flow_rate_in: float, flow_rate_out: float, viscosity_in: float, viscosity_out: float | npt.NDArray, inplace: bool = False) -> npt.NDArray: """Perform scale conversion for area_um (linear elastic model) The conversion formula is described in :cite:`Mietke2015`. .. versionadded: 0.25.0 Parameters ---------- emodulus Young's Modulus [kPa] channel_width_in Original channel width [µm] channel_width_out Target channel width [µm] flow_rate_in Original flow rate [µL/s] flow_rate_out Target flow rate [µL/s] viscosity_in Original viscosity [mPa*s] viscosity_out Target viscosity [mPa*s]; This can be an array inplace If True, override input arrays with corrected data Returns ------- emodulus_corr Scaled emodulus [kPa] """ copy = not inplace emodulus_corr = np.array(emodulus, copy=copy) if viscosity_in is not None: if isinstance(viscosity_in, np.ndarray): raise ValueError("`viscosity_in` must not be an array!") has_nones = (flow_rate_in is None or flow_rate_out is None or viscosity_in is None or viscosity_out is None or channel_width_in is None or channel_width_out is None ) has_changes = (flow_rate_in != flow_rate_out or channel_width_in != channel_width_out or (isinstance(viscosity_out, np.ndarray) # check before or viscosity_in != viscosity_out) ) if not has_nones and has_changes: emodulus_corr *= (flow_rate_out / flow_rate_in) \ * (viscosity_out / viscosity_in) \ * (channel_width_in / channel_width_out)**3 return emodulus_corr
[docs] def scale_feature(feat: str, data: float | npt.NDArray, inplace: bool = False, **scale_kw) -> npt.NDArray: """Convenience function for scale conversions (linear elastic model) This method wraps around all the other scale_* methods and also supports deform/circ. Parameters ---------- feat Valid scalar feature name data Feature data inplace If True, override input arrays with corrected data **scale_kw Scale keyword arguments for the wrapped methods """ if feat == "area_um": return scale_area_um(area_um=data, inplace=inplace, **scale_kw) elif feat in ["circ", "deform"]: # no units return np.array(data, copy=not inplace) elif feat == "emodulus": return scale_emodulus(emodulus=data, inplace=inplace, **scale_kw) elif feat == "volume": return scale_volume(volume=data, inplace=inplace, **scale_kw) else: raise KeyError("No recipe to scale feature '{}'!".format(feat))
[docs] def scale_volume(volume: npt.NDArray, channel_width_in: float, channel_width_out: float, inplace: bool = False, **kwargs) -> npt.NDArray: """Perform scale conversion for volume (linear elastic model) The volume scales with the characteristic length "channel radius" L according to (L'/L)³. .. versionadded: 0.25.0 Parameters ---------- volume Volume [µm³] channel_width_in Original channel width [µm] channel_width_out Target channel width [µm] inplace If True, override input arrays with corrected data kwargs not used Returns ------- volume_corr Scaled volume [µm³] """ copy = not inplace volume_corr = np.array(volume, copy=copy) if channel_width_in != channel_width_out: volume_corr *= (channel_width_out / channel_width_in)**3 return volume_corr