def test_plot_export(self):
     data = XYData(name="test",
                   x_data=arange(20),
                   y_data=arange(20),
                   x_metadata={"units": "min"},
                   y_metadata={"units": "AU"})
     filepath = "test.png"
     with temp_fname(filepath):
         data.mpl_show(filepath=filepath)
         self.assertIn(filepath, listdir("."))
    def setUp(self):
        # Build a fake peak
        x = range(5)
        y = [0., 1., 2., 1., 0.]
        self.data = XYData(x_data=x,
                           y_data=y,
                           name="sample data",
                           x_metadata={"units": "seconds"})

        # Build a fake double peak
        x = range(10)
        y = [0., 1., 2., 1., 0., 0., 1., 2., 1., 0.]
        self.data_2peaks = XYData(x_data=x,
                                  y_data=y,
                                  name="sample data",
                                  x_metadata={"units": "seconds"})

        self.step_start = UnitScalar(0 / 60., units="minute")
        self.step_stop = UnitScalar(4 / 60., units="minute")
    def setUp(self):
        #: Build a fake peak:
        # times is in seconds
        x = range(5)
        y = [0., 1., 2., 1., 0.]
        self.data = XYData(x_data=x, y_data=y, name="sample data")

        column_type = ColumnType(**COLUMN_TYPE_DATA)
        resin = Resin(**RESIN_DATA)
        self.column = Column(column_type=column_type,
                             resin=resin,
                             **COLUMN_DATA)
        self.column.volume = UnitScalar(100., units="liter")
def continuous_data_from_akta(import_settings, target_experiment):
    """ Utility to load/transform AKTA data from settings dict, and target exp.

    Parameters
    ----------
    import_settings : dict
        AKTA file import settings.

    target_experiment : Experiment
        Target experiment for which AKTA file contains data. Used to shift the
        data by the hold up volume.

    Returns
    -------
    dict
        Dict mapping data type to XYData storing traces.
    """
    continuous_data = {}
    # AKTA reader applies the truncation of the data for every point before the
    # time of origin:
    akta_reader = AKTAReader(
        file_path=import_settings["akta_fname"],
        time_of_origin=float(import_settings["time_of_origin"]),
        col_name_patterns=import_settings["col_name_patterns"]
    )

    header_info = akta_reader.header_info
    for key in akta_reader.available_dataset_types:
        time_key = 'time_' + key
        cont_data = XYData(
            name=key,
            x_data=akta_reader.get_data([time_key])[time_key],
            x_metadata=header_info[time_key],
            y_data=akta_reader.get_data([key])[key],
            y_metadata=header_info[key],
        )
        continuous_data[key] = cont_data

    # Modify results to shift output data by the holdup volume
    offset = shift_continuous_data_by_holdup_vol(continuous_data,
                                                 target_experiment)
    # Record volume used:
    import_settings["holdup_volume"] = offset
    return continuous_data
def read_continuous_data_from_cadet_h5(output_fname, product, step_names):
    """ Returns a dictionary of output data found in the provided.

    Parameters
    ----------
    output_fname : str
        Path to the HDF5 file produced by CADET.

    product : Product
        Product this file is modeling.

    step_names : list(str)
        List of the step/section names.
    """
    output_data = read_from_h5(output_fname, root='/output/solution')
    input_data = read_from_h5(output_fname, root='/input')
    bind_type = input_data["adsorption_type"]

    continuous_data = {}

    # The timestamps for the simulation correspond to the CADET output
    # timestamps
    solution_timestamps = output_data['solution_times']

    # FIXME: should x_data be copied for each data entry ?
    # FIXME: should we create UnitArrays ?
    x_data = solution_timestamps
    x_metadata = {
        'name': 'time',
        'units': 's',
        'source': 'simulation',
    }

    # Read in 1D component chromatograms --------------------------------------

    data_shape = input_data['number_user_solution_points']
    total_conc = np.zeros(data_shape)

    key_fmt = 'solution_column_outlet_comp_{:03d}'
    # These are CADET binding model types, not Reveal:
    if bind_type in ['STERIC_MASS_ACTION', 'EXTERNAL_STERIC_MASS_ACTION_PH']:
        # Read in cation concentration
        cation_conc = output_data[key_fmt.format(0)]
        y_metadata = {
            'name': 'cation_Sim',
            'type': 'cation',
            'source': 'simulation',
            'units': 'mM'
        }

        continuous_data['cation_Sim'] = XYData(name='cation_Sim',
                                               x_data=x_data,
                                               x_metadata=x_metadata,
                                               y_data=cation_conc,
                                               y_metadata=y_metadata)
        offset = 1
    else:
        offset = 0

    # Read in product concentrations:
    for ii, comp in enumerate(product.product_components):
        comp_name = comp.name
        molecular_weight = comp.molecular_weight[()]
        ext_coeff = comp.extinction_coefficient[()]

        name = comp_name + '_Sim'
        y_metadata = {
            'name': name,
            'type': 'chromatogram',
            'source': 'simulation',
            'units': 'AU/cm'
        }
        y_data = output_data[key_fmt.format(ii + offset)]
        y_data = y_data * molecular_weight * ext_coeff

        continuous_data[name] = XYData(name=name,
                                       x_data=x_data,
                                       x_metadata=x_metadata,
                                       y_data=y_data,
                                       y_metadata=y_metadata)

        # Aggregate all component to build the total UV
        total_conc += y_data

    # create total concentration var
    y_metadata = {
        'name': 'Total_Sim',
        'type': 'chromatogram',
        'source': 'simulation',
        'units': 'AU/cm'
    }
    continuous_data['Total_Sim'] = XYData(name='Total_Sim',
                                          x_data=x_data,
                                          x_metadata=x_metadata,
                                          y_data=total_conc,
                                          y_metadata=y_metadata)

    # Read 3D column comp concentrations (across column and over time)---------

    # Read in component concentrations inside the column liquid phase
    key_fmt = 'solution_column'
    column = output_data[key_fmt]
    column = np.array(column)
    for i, comp in enumerate(product.product_components):
        # Collect component attributes:
        comp_name = comp.name
        molecular_weight = comp.molecular_weight[()]
        ext_coeff = comp.extinction_coefficient[()]

        name = comp_name + '_Column_Sim'
        y_metadata = {
            'name': name,
            'type': 'column_liquid',
            'source': 'simulation',
            'units': 'AU/cm'
        }
        y_data = column[:, i + offset, :] * molecular_weight * ext_coeff
        continuous_data[name] = XYData(name=name,
                                       x_data=x_data,
                                       x_metadata=x_metadata,
                                       y_data=y_data,
                                       y_metadata=y_metadata)

    # Read in component concentrations inside the bead liquid phase
    key_fmt = 'solution_particle'
    data = np.array(output_data[key_fmt])
    for i, comp in enumerate(product.product_components):
        # Collect component attributes:
        comp_name = comp.name
        molecular_weight = comp.molecular_weight[()]
        ext_coeff = comp.extinction_coefficient[()]

        name = comp_name + '_Particle_Liq_Sim'
        y_metadata = {
            'name': name,
            'type': 'particle_liquid',
            'source': 'simulation',
            'units': 'AU/cm'
        }

        y_data = data[:, :, :, 0, i + offset] * molecular_weight * ext_coeff
        continuous_data[name] = XYData(name=name,
                                       x_data=x_data,
                                       x_metadata=x_metadata,
                                       y_data=y_data,
                                       y_metadata=y_metadata)

    # Read in component concentrations inside the bead bound phase
    key_fmt = 'solution_particle'
    data = np.array(output_data[key_fmt])
    for i, comp in enumerate(product.product_components):
        # Collect component attributes:
        comp_name = comp.name
        molecular_weight = comp.molecular_weight[()]
        ext_coeff = comp.extinction_coefficient[()]

        name = comp_name + '_Particle_Bound_Sim'
        y_metadata = {
            'name': name,
            'type': 'particle_bound',
            'source': 'simulation',
            'units': 'AU/cm'
        }
        y_data = data[:, :, :, 1, i + offset] * molecular_weight * ext_coeff
        continuous_data[name] = XYData(name=name,
                                       x_data=x_data,
                                       x_metadata=x_metadata,
                                       y_data=y_data,
                                       y_metadata=y_metadata)

    # Build tags for steps in simulation --------------------------------------

    inlet_data = read_from_h5(output_fname, root='/input/model/inlet')
    key_fmt = 'section_times'
    section_times = inlet_data[key_fmt]
    x_data = section_times[:-1]
    x_metadata = {
        'name': 'time',
        'units': 's',
        'source': 'simulation',
    }

    y_data = step_names
    name = 'Section_Tags_Sim'
    y_metadata = {
        'name': name,
        'type': 'section_tags',
        'source': 'simulation',
        'units': ''
    }
    continuous_data[name] = XYData(name=name,
                                   x_data=x_data,
                                   x_metadata=x_metadata,
                                   y_data=y_data,
                                   y_metadata=y_metadata)

    return continuous_data
 def test_plot_export_to_jpeg(self):
     data = XYData(name="test", x_data=arange(20), y_data=arange(20))
     filepath = "test.jpg"
     with temp_fname(filepath):
         data.mpl_show(filepath=filepath)
         self.assertIn(filepath, listdir("."))
 def test_create_fail_when_missing_name(self):
     with self.assertRaises(ValueError):
         XYData(x_data=arange(20), y_data=arange(20))
 def test_create(self):
     XYData(name="test", x_data=arange(20), y_data=arange(20))
    def _build_fraction_data(self,
                             fraction_data,
                             time_of_origin=None,
                             target_experiment=None):
        """ Convert fraction data from Excel fraction sheet into a fraction
        data dictionary to describe ChromatographyResults.

        Parameters
        ----------
        fraction_data : dict
            Data loaded from Excel.

        time_of_origin : UnitScalar [OPTIONAL]
            User specified custom time shift to apply to the data, if the
            experimental output wasn't recorded starting at the desired start.
        """
        if fraction_data is None:
            return {}

        if time_of_origin is None:
            time_of_origin = UnitScalar(0., units="minute")

        # Faction times at which product is sampled and analyzed:
        frac_time = []
        # Component concentration at each fraction time:
        frac_comp_conc = defaultdict(list)
        # Total concentration of product, corrected from extinction at each
        # fraction time:
        frac_prod_absorbances = []

        product = self.product
        for fraction in fraction_data:
            prod_comp_assays = fraction.pop('product_component_assay_dict')
            # FIXME: read units instead of guessing
            total_concentration = self._get_unitted_value(
                'fraction_product_concentration',
                fraction['total_concentration'])
            conc_units = total_concentration.units

            # To compute the product concentrations in the fraction,
            # we must first compute the concentration of each product component
            # then multiply each by their respective extinction coefficient
            # finally sum these values together

            # FIXME: Fraction component concentrations shoud be calculated in
            #        SolutionWithProduct.  This is probably unnecessary --
            #        Look into later.
            namespace = {}
            namespace.update(prod_comp_assays)
            namespace["product_concentration"] = float(total_concentration)
            prod_comp_conc = [
                eval(expression, namespace)
                for expression in product.product_component_concentration_exps
            ]

            frac_component_concs = UnitArray(prod_comp_conc, units=conc_units)
            # Total concentration, corrected by the components' extinction coef
            ext_coefs = [
                comp.extinction_coefficient
                for comp in product.product_components
            ]
            ext_coef_array = unitted_list_to_array(ext_coefs)
            # This converts the component concentration to absorption
            frac_component_absorb = frac_component_concs * ext_coef_array
            tot_prod_absorbance = sum(frac_component_absorb)
            frac_prod_absorbances.append(tot_prod_absorbance)

            frac_time.append(fraction['time'])
            for ii, comp_name in enumerate(product.product_component_names):
                frac_comp_conc[comp_name].append(frac_component_absorb[ii])

        # Apply the user defined origin shift:
        # Warning: this leads to all fraction XYData sharing the same array!
        frac_time = np.array(frac_time, dtype='float64') - time_of_origin[()]
        frac_prod_absorbances = np.array(frac_prod_absorbances,
                                         dtype='float64')

        fraction_outputs = {}
        for key, data in frac_comp_conc.items():
            fraction_outputs[key] = XYData(
                name=key,
                x_data=frac_time,
                # FIXME: read units instead of guessing
                x_metadata={
                    "time_of_origin": time_of_origin,
                    "units": "min"
                },
                y_data=data,
                # FIXME: read units instead of guessing
                y_metadata={
                    "Description":
                    "Absorbances for product "
                    "components {}".format(key),
                    "units":
                    "AU/cm"
                },
            )

        fraction_outputs[FRACTION_TOTAL_DATA_KEY] = XYData(
            name=FRACTION_TOTAL_DATA_KEY,
            x_data=frac_time,
            # FIXME: read units instead of guessing
            x_metadata={
                "time_of_origin": time_of_origin,
                "units": "min"
            },
            y_data=frac_prod_absorbances,
            # FIXME: read units instead of guessing
            y_metadata={
                "Description": "Sum of absorbances per unit path "
                "length for all product components.",
                "units": "AU/cm"
            },
        )

        shift_fraction_data_by_holdup_vol(fraction_outputs, target_experiment)
        return fraction_outputs