示例#1
0
def is_linear_flow_rate(flow_rate):
    """ Test whether a flow rate (UnitScalar) has a unit of a volume per time.
    """
    try:
        convert(flow_rate, from_unit=flow_rate.units, to_unit=m / second)
        return True
    except InvalidConversion:
        return False
示例#2
0
def volume_to_depth(volume, column, to_unit="meters"):
    """ Translate a volume of fluid into a depth in infinitely long column.
    """
    if volume.units != chr_units.column_volumes:
        volume = convert(volume,
                         from_unit=volume.units,
                         to_unit=column.volume.units)
        volume *= column.volume

    volume = float(volume)
    depth = volume * column.bed_height_actual
    if to_unit:
        depth = convert(depth,
                        from_unit=depth.units,
                        to_unit=parse_unit(to_unit))
    return float(depth)
示例#3
0
def unit_scalar_almost_equal(x1, x2, eps=1e-9):
    """ Returns whether 2 UnitScalars are almost equal.

    Parameters
    ----------
    x1 : UnitScalar
        First unit scalar to compare.

    x2 : UnitScalar
        Second unit scalar to compare.

    eps : float
        Absolute precision of the comparison.
    """
    if not isinstance(x1, UnitScalar):
        msg = "x1 is supposed to be a UnitScalar but a {} was passed."
        msg = msg.format(type(x1))
        logger.exception(msg)
        raise ValueError(msg)

    if not isinstance(x2, UnitScalar):
        msg = "x2 is supposed to be a UnitScalar but a {} was passed."
        msg = msg.format(type(x2))
        logger.exception(msg)
        raise ValueError(msg)

    a1 = float(x1)
    try:
        a2 = convert(float(x2), from_unit=x2.units, to_unit=x1.units)
    except InvalidConversion:
        return False
    return np.abs(a1 - a2) < eps
示例#4
0
    def convertUnit(self, value, unit_from, unit_to):
        if (self.delete == True):
            return
        exec('from scimath.units.SI import *')
        exec('from scimath.units.pressure import *')
        exec('from scimath.units.acceleration import *')
        exec('from scimath.units.angle import *')
        exec('from scimath.units.area import *')
        exec('from scimath.units.density import *')
        exec('from scimath.units.electromagnetism import *')
        exec('from scimath.units.energy import *')
        exec('from scimath.units.force import *')
        exec('from scimath.units.frequency import *')
        exec('from scimath.units.length import *')
        exec('from scimath.units.mass import *')
        exec('from scimath.units.power import *')
        exec('from scimath.units.pressure import *')
        exec('from scimath.units.speed import *')
        exec('from scimath.units.substance import *')
        exec('from scimath.units.temperature import *')
        exec('from scimath.units.time import *')
        exec('from scimath.units.volume import *')
        from scimath.units.api import convert

        try:
            value = convert(value, eval(unit_from), eval(unit_to))
        except:
            print(
                'Einheit "' + unit_from + '" oder "' + unit_to +
                '" wird nicht unterstuetzt von scimath. Funktion wird beendet...'
            )
            return (False)

        return (value)
示例#5
0
def get_step_velocity(step, column=None):
    """ Extract the step linear superficial velocity (flow_rate), in m/s.
    """
    if is_volumetric_flow_rate(step.flow_rate):
        step_velocity = volumetric_flow_rate_to_linear(
            step.flow_rate, column.column_type.diameter, to_unit="m/s")
    else:
        step_velocity = convert(step.flow_rate,
                                from_unit=step.flow_rate.units,
                                to_unit=meter / second)
    return float(step_velocity)
示例#6
0
def linear_flow_rate_to_volumetric(linear_flow_rate, diam, to_unit=""):
    """ Convert a linear flow rate in a column of diameter diam to a volumetric
    flow rate.
    """
    vol_flow_rate = (np.pi * diam**2 / 4.) * linear_flow_rate
    if to_unit:
        parse_unit = unit_parser.parse_unit
        from_unit = vol_flow_rate.units
        to_unit = parse_unit(to_unit)
        vol_flow_rate_val = convert(float(vol_flow_rate),
                                    from_unit=from_unit,
                                    to_unit=to_unit)
        vol_flow_rate = UnitScalar(vol_flow_rate_val, units=to_unit)
    return vol_flow_rate
示例#7
0
def time_to_volume(time, flow_rate, column=None, to_unit="CV"):
    """ Convert a flow time to a volume, assuming a specified flow rate.

    Parameters
    ----------
    time : UnitScalar
        Time of flow.

    flow_rate : UnitScalar
        Flow rate.

    column : Column [OPTIONAL]
        Column in which the flow occur. Only needed if providing linear flow
        rate, or if the output unit must be CV.

    to_unit : str
        String representation of the output unit.

    Returns
    -------
    UnitScalar
        Volume that flowed during the specified time.
    """
    if not isinstance(time, UnitScalar):
        msg = "The time provided should be a UnitScalar."
        logger.exception(msg)
        raise ValueError(msg)

    if not is_volumetric_flow_rate(flow_rate):
        diam = column.column_type.diameter
        flow_rate = linear_flow_rate_to_volumetric(flow_rate, diam)

    volume = time * flow_rate

    if to_unit:
        if to_unit == "CV":
            volume = UnitScalar(float(volume / column.volume), units="CV")
        else:
            # Convert to target unit
            parse_unit = unit_parser.parse_unit
            volume = convert(volume,
                             from_unit=volume.units,
                             to_unit=parse_unit(to_unit))
    return volume
def build_flow_rate_array(times, experiment, to_unit="liter/minute"):
    """ Build array of flow rates in liter/min at each time of 'times' array.

    Parameters
    ----------
    times : numpy.array
        Array of chromatogram times at which to extract the flow rates.

    experiment : Experiment
        Experiment to extract the flow rates from.

    to_unit : str
        Unit of the output.

    Returns
    -------
    UnitArray
        Array of flow rates at the times of the times array.
    """
    method_steps = experiment.method.method_steps
    step_boundary_times = experiment.method_step_boundary_times

    flow_rates = ones(times.shape) * nan
    for i, step in enumerate(method_steps):
        step_start_time = step_boundary_times[i]
        step_stop_time = step_boundary_times[i+1]
        mask = (times >= step_start_time) & (times < step_stop_time)
        if is_linear_flow_rate(step.flow_rate):
            diam = experiment.column.column_type.diameter
            flow_rate = linear_flow_rate_to_volumetric(step.flow_rate, diam,
                                                       to_unit=to_unit)
        elif is_volumetric_flow_rate(step.flow_rate):
            flow_rate = convert(step.flow_rate, from_unit=step.flow_rate.units,
                                to_unit=unit_parser.parse_unit(to_unit))
        else:
            flow_rate = volumetric_CV_flow_rate_to_volumetric_flow_rate(
                step.flow_rate, experiment.column, to_unit=to_unit
            )

        flow_rates[mask] = float(flow_rate)

    return UnitArray(flow_rates, units=to_unit)
示例#9
0
    def create_cadet_external_and_validate(self, sim=None):
        if sim is None:
            sim = self.sim

        cadet_ext = CADETPhExternalProfile.from_simulation(sim)
        # lengths of arrays:
        self.assertEqual(len(cadet_ext.ext_prof_delta),
                         len(cadet_ext.ext_profile))

        one_col_length = float(
            convert_str(self.column.bed_height_actual, "cm", "m"))
        # Initial values: depths start at 0, and includes 1 column of initial
        # buffer:
        self.assertEqual(cadet_ext.ext_prof_delta[0], 0.0)
        self.assertEqual(cadet_ext.ext_prof_delta[1], one_col_length)

        init_solution = self.sim.method.initial_buffer
        first_step = self.sim.method.method_steps[0]
        self.assertEqual(cadet_ext.ext_profile[0], float(init_solution.pH))
        self.assertEqual(cadet_ext.ext_profile[1], first_step.solutions[0].pH)

        flow_rate0 = first_step.flow_rate
        first_velocity = convert(float(flow_rate0),
                                 from_unit=flow_rate0.units,
                                 to_unit=meter / second)
        self.assertEqual(cadet_ext.ext_velocity, first_velocity)

        # Step lengths, in column, all add up to the profile_deltas:
        col_lengths = [one_col_length]

        step_velocity0 = get_step_velocity(first_step)
        for step in self.method.method_steps:
            step_velocity = float(get_step_velocity(step))
            step_volume = float(step.volume)
            # Normalize the duration based on the velocity of the step
            col_length = step_volume * step_velocity0 / step_velocity
            col_length *= one_col_length
            col_lengths.append(float(col_length))

        self.assertAlmostEqual(cadet_ext.ext_prof_delta.sum(),
                               sum(col_lengths))
        return cadet_ext
示例#10
0
def vol_to_time(volume, flow_rate, column=None, to_unit="minute"):
    """ Convert a volume to a time, using a flow rate.

    Parameters
    ----------
    volume : UnitScalar
        Volume to convert to a time.

    flow_rate : UnitScalar
        Flow rate used to convert a volume to a time.

    column : Column [OPTIONAL]
        Column the volume is flowing through. From that object are read the
        diameter and colume of the column for unit conversion if needed.

    to_unit : str [OPTIONAL, default: minutes]
        Target time unit. Must be parsable by scimath's unit parser.

    Returns
    -------
    float
        Value of the time needed for the provided volume to flow through the
        column.
    """
    if not isinstance(volume, UnitScalar):
        raise ValueError("The volume provided should be a UnitScalar.")
    elif volume.units == chr_units.column_volumes:
        volume = float(volume) * column.volume

    # Convert a linear flow rate into a volumetric flow rate
    if not is_volumetric_flow_rate(flow_rate):
        diam = column.column_type.diameter
        flow_rate = linear_flow_rate_to_volumetric(flow_rate, diam)

    # Compute the time
    time = volume / flow_rate
    if to_unit:
        # Convert to target unit
        time = convert(time, from_unit=time.units, to_unit=parse_unit(to_unit))
    return float(time)
    def _set_volume(self, value):
        """ Back-calculate the column's bed height H to have requested volume.

        To make sure that the volume follows::

            vol = pi * D^2 * H / 4

        the bed height is set to::

            H = 4 * vol / (pi * D^2)

        Note that this may raise an exception if the resulting bed height
        doesn't fall in the range set by the column type.
        """
        #: Do nothing if value requested is already the value of the volume:
        if unit_scalar_almost_equal(value, self.volume):
            return

        if not isinstance(value, UnitScalar):
            msg = "Setting the column volume must be done providing a " \
                  "UnitScalar to specify the unit."
            logger.exception(msg)
            raise ValueError(msg)

        if not has_volume_units(value):
            msg = "Setting the column volume must be done providing a " \
                  "UnitScalar to specify the unit."
            logger.exception(msg)
            raise ValueError(msg)

        diam = self.column_type.diameter
        bed_height_actual = 4. * value / (diam**2 * pi)
        val = convert(
            float(bed_height_actual), from_unit=bed_height_actual.units,
            to_unit=centimeter
        )
        self.bed_height_actual = UnitScalar(val, units=centimeter)
示例#12
0
    def from_simulation(cls, sim):
        """ Compute the profiles and instantiate a CADETExternal.
        """
        column = sim.column

        # Initial array values
        step0 = sim.method.method_steps[0]
        step0_ph = float(step0.solutions[0].pH)
        step0_velocity = get_step_velocity(step0, column)

        # Initialization of the profiles to build
        init_ph = sim.method.initial_buffer.pH
        column_length = convert(column.bed_height_actual,
                                to_unit=meter,
                                from_unit=column.bed_height_actual.units)
        ph_values = [init_ph, step0_ph]
        depth_deltas = [0., float(column_length)]
        for step in sim.method.method_steps:
            step_depth = volume_to_depth(step.volume,
                                         column=column,
                                         to_unit="meter")
            step_velocity = get_step_velocity(step, column)

            # If a step flows N times faster, we model this by making its
            # duration N times smaller.
            step_depth *= step0_velocity / step_velocity

            if len(step.solutions) == 0:
                msg = "Step with no solution not supported"
                raise NotImplementedError(msg)

            # Deal with the transition from the previous step
            start_step_ph = float(step.solutions[0].pH)
            transition_needed = ph_values[-1] != start_step_ph
            if transition_needed:
                # Create a fake gradient of pH since CADET requires pH profile
                # to be differentiable
                depth_deltas.append(EPS)
                ph_values.append(start_step_ph)
                step_depth -= EPS

            # Deal with the contributions from this step:
            num_solutions = len(step.solutions)
            if num_solutions == 1:
                end_step_ph = start_step_ph
            elif num_solutions == 2:
                # 2 solutions during gradient elution when the buffer
                # composition goes from 1 solution to the other:
                end_step_ph = float(step.solutions[1].pH)
            else:
                msg = "Found a step with more than 2 solutions. Don't know " \
                      "how to compute the pH profile in that case."
                logger.exception(msg)
                raise NotImplementedError(msg)

            ph_values.append(end_step_ph)
            depth_deltas.append(step_depth)

        ext_profile = np.array(ph_values, dtype="float64")
        ext_prof_delta = np.array(depth_deltas, dtype="float64")

        return cls(ext_profile=ext_profile,
                   ext_prof_delta=ext_prof_delta,
                   ext_velocity=step0_velocity)
def compute_mass_from_abs_data(absorb_data, ext_coeff, experim, t_start=None,
                               t_stop=None, t_start_idx=None, t_stop_idx=None):
    """ Compute total mass of a product component between start and stop times.

    The total mass is computed by integrating the specified chromatogram,
    between t_start and t_stop and using the specified extinction coefficient
    and flow rate at each time.

    Parameters
    ----------
    absorb_data : XYData
        Data (fraction or continuous) to integrate to compute the contained
        mass.

    ext_coeff : UnitScalar
        Extinction coefficient to use to convert the absorbance to a product
        concentration.

    experim : Experiment
        Experiment from which to extract the method (and therefore flow rate)
        information and the system's path length.

    t_start : UnitScalar
        Time at which to start integrating, in minutes. Leave as None to use
        the t_start_idx to specify the time range to integrate.

    t_stop : UnitScalar
        Time at which to stop integrating, in minutes. Leave as None to use
        the t_stop_idx to specify the time range to integrate.

    t_start_idx : Int or None
        Index in the x_data to start integrating at (inclusive).

    t_stop_idx : Int or None
        Index in the x_data to stop integrating at (exclusive). Leave as None
        to go all the way to the end.

    Returns
    -------
    UnitScalar
        Product mass, in grams, estimated to elute between t_start and t_stop.
    """
    all_x_data = absorb_data.x_data
    all_y_data = absorb_data.y_data

    # Convert time inputs into minutes:
    data_time_unit = unit_parser.parse_unit(absorb_data.x_metadata["units"])
    all_x_data = convert(all_x_data, from_unit=data_time_unit, to_unit=minute)

    if t_start is not None and t_stop is not None:
        t_start = convert_units(t_start, tgt_unit=minute)
        t_stop = convert_units(t_stop, tgt_unit=minute)

        t_start_idx = searchsorted(all_x_data, t_start)
        t_stop_idx = searchsorted(all_x_data, t_stop)
        if t_start_idx == t_stop_idx:
            msg = "Unable to compute the integral of the provided because" \
                  "t_start too close to t_stop."
            logger.warning(msg)
            return UnitScalar(0., units="gram")

    collect_idx = slice(t_start_idx, t_stop_idx)
    times = all_x_data[collect_idx]
    absorbances = all_y_data[collect_idx]

    #: Extract the flow rate from the experiment method:
    flow_rates = build_flow_rate_array(times, experim, to_unit="liter/minute")
    missing_flow_rates = where(isnan(flow_rates))[0]
    if len(missing_flow_rates) > 0:
        msg = "The time range requested to integrate results goes beyond the "\
              "known method steps, and will need to be cropped by {} values." \
              " Cropped values are {}.".format(len(missing_flow_rates),
                                               missing_flow_rates)
        logger.warning(msg)
        t_stop_idx = missing_flow_rates[0]
        collect_idx = slice(t_start_idx, t_stop_idx)
        times = all_x_data[collect_idx]
        absorbances = all_y_data[collect_idx]
        flow_rates = flow_rates[collect_idx]

    # Turn absorbances into AU/cm
    path_length = convert_units(experim.system.abs_path_length, "cm")[()]
    data_absorb_unit = unit_parser.parse_unit(absorb_data.y_metadata["units"])
    absorbances_au = convert(absorbances, from_unit=data_absorb_unit,
                             to_unit=absorption_unit)
    # Compute masses in grams
    masses = (absorbances_au*array(flow_rates)) / (path_length*ext_coeff[()])
    total_mass = trapz(masses, times)
    return UnitScalar(total_mass, units="gram")
示例#14
0
def has_volume_units(vol):
    try:
        convert(vol, from_unit=vol.units, to_unit=m**3)
        return True
    except InvalidConversion:
        return False
#! /usr/bin/env python
from __future__ import print_function

import os
import math
from scimath.units.length import km, cm
from scimath.units.api import convert

def deflection_tangent(tangent_length, radius):
    return (tangent_length**2 + radius**2)**(1.0/2.0) - radius
    # cannot use math.hypot or math.sqrt:
    # scimath.units.unit.InvalidConversion: dimensional quantities ('m') cannot be converted to scalars
    # cannot use numpy.hypot:
    # AttributeError: 'unit' object has no attribute 'hypot'

def deflection_arc(arc_length, radius):
    return radius * (math.cos(arc_length/radius)**-1 - 1)

radius_earth = 6371.01 * km
length = 1.0 * km

deflection_1 = convert(deflection_tangent(length, radius_earth).value, km, cm)

deflection_2 = convert(deflection_arc(length, radius_earth).value, km, cm)

print(deflection_1, cm.label)
print(deflection_2, cm.label)
示例#16
0
 def get_step_duration(self, step):
     step_duration = self.column.bed_height_actual / step.flow_rate
     step_duration = convert(float(step_duration),
                             from_unit=step_duration.units,
                             to_unit=second)
     return step_duration