def test_compute_start_collect_time_fixed_abs_searching_too_far(self):
     coll_criteria = CollectionCriteria(
         name="Test collec crit",
         start_collection_target=0.5,
         start_collection_type="Fixed Absorbance",
         stop_collection_target=1.5,
         stop_collection_type="Fixed Absorbance",
     )
     # These times are larger than the end of the dataset
     step_start = UnitScalar(5 / 60., units="minute")
     step_stop = UnitScalar(6 / 60., units="minute")
     with self.assertRaises(ValueError):
         calculate_start_stop_collect(self.data, coll_criteria, step_start,
                                      step_stop)
    def test_compute_start_collect_time_fixed_abs_stop_before_start(self):
        coll_criteria = CollectionCriteria(
            name="Test collec crit",
            start_collection_target=0.5,
            start_collection_type="Fixed Absorbance",
            start_collection_while="Descending",
            stop_collection_target=1.5,
            stop_collection_type="Fixed Absorbance",
        )
        self.assertEqual(coll_criteria.stop_collection_while, "Descending")

        collections = calculate_start_stop_collect(self.data, coll_criteria,
                                                   self.step_start,
                                                   self.step_stop)
        start_time, start_idx, stop_time, stop_idx = collections
        self.assertGreater(start_time, stop_time)
 def test_compute_start_collect_time_ppm(self):
     coll_criteria = CollectionCriteria(
         name="Test collec crit",
         start_collection_target=40,
         start_collection_type="Percent Peak Maximum",
         stop_collection_target=60,
         stop_collection_type="Percent Peak Maximum",
     )
     collections = calculate_start_stop_collect(self.data, coll_criteria,
                                                self.step_start,
                                                self.step_stop)
     start_time, start_idx, stop_time, stop_idx = collections
     self.assertEqual(start_time, UnitScalar(1. / 60., units="minute"))
     self.assertEqual(start_idx, 1)
     self.assertEqual(stop_time, UnitScalar(3. / 60., units="minute"))
     self.assertEqual(stop_idx, 3)
 def test_compute_start_collect_time_fixed_abs(self):
     coll_criteria = CollectionCriteria(
         name="Test collec crit",
         start_collection_target=0.5,
         start_collection_type="Fixed Absorbance",
         stop_collection_target=1.5,
         stop_collection_type="Fixed Absorbance",
     )
     self.assertEqual(coll_criteria.start_collection_while, "Ascending")
     self.assertEqual(coll_criteria.stop_collection_while, "Descending")
     collections = calculate_start_stop_collect(self.data, coll_criteria,
                                                self.step_start,
                                                self.step_stop)
     start_time, start_idx, stop_time, stop_idx = collections
     self.assertEqual(start_time, UnitScalar(1. / 60., units="minute"))
     self.assertEqual(start_idx, 1)
     self.assertEqual(stop_time, UnitScalar(3. / 60., units="minute"))
     self.assertEqual(stop_idx, 3)
    def test_compute_start_collect_time_fixed_abs_double_peak(self):
        coll_criteria = CollectionCriteria(
            name="Test collec crit",
            start_collection_target=0.5,
            start_collection_type="Fixed Absorbance",
            stop_collection_target=1.5,
            stop_collection_type="Fixed Absorbance",
        )

        step_start = UnitScalar(5 / 60., units="minute")
        step_stop = UnitScalar(10 / 60., units="minute")
        collections = calculate_start_stop_collect(self.data_2peaks,
                                                   coll_criteria, step_start,
                                                   step_stop)
        start_time, start_idx, stop_time, stop_idx = collections
        self.assertEqual(start_time, UnitScalar(6. / 60., units="minute"))
        self.assertEqual(start_idx, 6)
        self.assertEqual(stop_time, UnitScalar(8. / 60., units="minute"))
        self.assertEqual(stop_idx, 8)
def calculate_experiment_performance_data(exp):
    """ Calculates the performance data based on continuous_data.
    Performance data includes the start and stop times from the start and stop
    collection criteria, the pool's concentrations, volume and purities, and
    the yield. Used to build the output of a simulation once the solver has
    run.

    Parameters
    ----------
    exp : Experiment
        Experiment object we are computing the performance for. Used to collect
        information about the product it models and the collection criteria.

    Returns
    -------
    PerformanceData or None
        Returns None if no collection criteria was specified in the
        simulation's method.
    """
    # Use the section_times from the continuous data to set the time to start
    # looking for the start collection criteria
    col_criteria = exp.method.collection_criteria
    if col_criteria is None:
        msg = "Skipping performance data for exp {} since no collection " \
              "criteria was set.".format(exp.name)
        logger.debug(msg)
        return None

    continuous_data = exp.output.continuous_data
    exp_data = continuous_data[UV_DATA_KEY]
    pooling_step_num = exp.method.collection_step_number
    # Collect pooling boundaries from fraction data times:
    fraction_data = exp.output.fraction_data
    pooling_start = fraction_data[FRACTION_TOTAL_DATA_KEY].x_data.min()
    pooling_stop = fraction_data[FRACTION_TOTAL_DATA_KEY].x_data.max()

    start_stop_collect_data = calculate_start_stop_collect(
        exp_data, col_criteria, step_start=pooling_start,
        step_stop=pooling_stop
    )

    start_collect_time, start_collect_idx, stop_collect_time, stop_collect_idx\
        = start_stop_collect_data

    # The flow rate of collecting the pool is the flow rate during the elution
    # or pooling step in general (that is the step creating the pool):
    pooling_step = exp.method.method_steps[pooling_step_num]
    yield_flow_rate = pooling_step.flow_rate
    pool_volume = calculate_pool_volume(start_collect_time, stop_collect_time,
                                        yield_flow_rate, exp.column)

    product_component_concentrations = \
        calculate_exp_component_concentrations(
            exp, exp.output.fraction_data, pooling_step.flow_rate,
            pool_volume, start_collect_time, stop_collect_time
        )

    pool_concentration = calculate_pool_concentration(
        product_component_concentrations
    )

    load_step = exp.method.load
    step_yield = calculate_step_yield(pool_concentration, pool_volume,
                                      load_step)

    pool = SolutionWithProduct(
        name='{}_Pool'.format(exp.name),
        source="{} {}".format(exp.__class__.__name__, exp.name),
        lot_id="unknown",
        solution_type="Pool",
        product=exp.product,
        product_concentration=pool_concentration,
        product_component_concentrations=product_component_concentrations
    )

    performance_data = PerformanceData(
        name=exp.name,
        pool=pool,
        # Parameters to be displayed in the perf param pane:
        start_collect_time=start_collect_time,
        stop_collect_time=stop_collect_time,
        pool_volume=pool_volume,
        step_yield=step_yield,
        pool_concentration=pool_concentration,
    )

    return performance_data