Ejemplo n.º 1
0
    def test_get_step_index(self):
        structured_datapath_loc = os.path.join(
            TEST_FILE_DIR, "PreDiag_000240_000227_truncated_structure.json")

        parameters_path = os.path.join(TEST_FILE_DIR, "data-share", "raw",
                                       "parameters")
        structured_datapath = auto_load_processed(structured_datapath_loc)
        data = structured_datapath.diagnostic_data
        hppc_cycles = data.loc[data.cycle_type == "hppc"]
        # print(hppc_cycles.step_index.unique())
        _, protocol_name = os.path.split(structured_datapath.metadata.protocol)
        parameter_row, _ = parameters_lookup.get_protocol_parameters(
            protocol_name, parameters_path=parameters_path)

        for cycle in hppc_cycles.cycle_index.unique():
            hppc_cycle = hppc_cycles[hppc_cycles.cycle_index == cycle]
            for step in hppc_cycle.step_index.unique():
                hppc_cycle_step = hppc_cycle[(hppc_cycle.step_index == step)]
                for step_iter in hppc_cycle_step.step_index_counter.unique():
                    hppc_cycle_step_iter = hppc_cycle_step[(
                        hppc_cycle_step.step_index_counter == step_iter)]
                    duration = hppc_cycle_step_iter.test_time.max(
                    ) - hppc_cycle_step_iter.test_time.min()
                    median_crate = np.round(
                        hppc_cycle_step.current.median() /
                        parameter_row["capacity_nominal"].iloc[0], 2)
                    # print(step, median_crate, duration)

        step_ind = featurizer_helpers.get_step_index(structured_datapath,
                                                     cycle_type="hppc",
                                                     diag_pos=0)
        self.assertEqual(len(step_ind.values()), 6)
        print([
            step_ind["hppc_long_rest"], step_ind["hppc_discharge_pulse"],
            step_ind["hppc_short_rest"], step_ind["hppc_charge_pulse"],
            step_ind["hppc_discharge_to_next_soc"]
        ])

        self.assertEqual(
            step_ind, {
                'hppc_charge_to_soc': 9,
                'hppc_long_rest': 11,
                'hppc_discharge_pulse': 12,
                'hppc_short_rest': 13,
                'hppc_charge_pulse': 14,
                'hppc_discharge_to_next_soc': 15
            })
        step_ind = featurizer_helpers.get_step_index(structured_datapath,
                                                     cycle_type="hppc",
                                                     diag_pos=1)
        self.assertEqual(len(step_ind.values()), 6)
        self.assertEqual(
            step_ind, {
                'hppc_charge_to_soc': 41,
                'hppc_long_rest': 43,
                'hppc_discharge_pulse': 44,
                'hppc_short_rest': 45,
                'hppc_charge_pulse': 46,
                'hppc_discharge_to_next_soc': 47
            })
Ejemplo n.º 2
0
    def test_get_protocol_parameters(self):
        filepath = os.path.join(TEST_FILE_DIR,
                                "PredictionDiagnostics_000109_tztest.010")
        parameters, _ = parameters_lookup.get_protocol_parameters(
            filepath, parameters_path=PROTOCOL_PARAMETERS_DIR)

        self.assertEqual(parameters["diagnostic_type"].iloc[0], "HPPC+RPT")
        self.assertEqual(parameters["diagnostic_parameter_set"].iloc[0],
                         "Tesla21700")
        self.assertEqual(parameters["seq_num"].iloc[0], 109)
        self.assertEqual(len(parameters.index), 1)

        parameters_missing, project_missing = parameters_lookup.get_protocol_parameters(
            "Fake", parameters_path=PROTOCOL_PARAMETERS_DIR)
        self.assertEqual(parameters_missing, None)
        self.assertEqual(project_missing, None)

        filepath = os.path.join(TEST_FILE_DIR, "PreDiag_000292_tztest.010")
        parameters, _ = parameters_lookup.get_protocol_parameters(
            filepath, parameters_path=PROTOCOL_PARAMETERS_DIR)
        self.assertEqual(parameters["diagnostic_type"].iloc[0], "HPPC+RPT")
        self.assertEqual(parameters["seq_num"].iloc[0], 292)
Ejemplo n.º 3
0
def get_parameter_dict(file_list, parameters_path):
    """
    Helper function to generate a dictionary with

    Args:
        file_list (list): List of filenames from self.filenames
        parameters_path (str): Root directory storing project parameter files.

    Returns:
        Dictionary with file_list as keys, and corresponding dictionary of protocol parameters as values
    """
    d = {
    }  # dict allows combining two different project parameter sets into the same structure
    for file in file_list:
        param_row, _ = parameters_lookup.get_protocol_parameters(
            file, parameters_path)
        d[file] = param_row.to_dict('records')[
            0]  # to_dict('records') returns a list.
    return d
Ejemplo n.º 4
0
def get_fractional_quantity_remaining_nx(
        processed_cycler_run,
        metric="discharge_energy",
        diagnostic_cycle_type="rpt_0.2C",
        parameters_path="data-share/raw/parameters"):
    """
    Similar to get_fractional_quantity_remaining()
    Determine relative loss of <metric> in diagnostic_cycles of type <diagnostic_cycle_type>
    Also returns value of 'x', the discharge throughput passed by the first diagnostic
    and the value 'n' at each diagnostic

    Args:
        processed_cycler_run (beep.structure.ProcessedCyclerRun): information about cycler run
        metric (str): column name to use for measuring degradation
        diagnostic_cycle_type (str): the diagnostic cycle to use for computing the amount of degradation
        parameters_path (str): path to the parameters file for this run

    Returns:
        a dataframe with cycle_index, corresponding degradation relative to the first measured value, 'x',
        i.e. the discharge throughput passed by the first diagnostic
        and the value 'n' at each diagnostic, i.e. the equivalent scaling factor for lifetime using n*x
    """
    summary_diag_cycle_type = processed_cycler_run.diagnostic_summary[(
        processed_cycler_run.diagnostic_summary.cycle_type ==
        diagnostic_cycle_type)].reset_index()
    summary_diag_cycle_type = summary_diag_cycle_type[["cycle_index", metric]]

    # For the nx addition
    if 'energy' in metric:
        normalize_qty = 'discharge' + '_energy'
    else:
        normalize_qty = 'discharge' + '_capacity'

    normalize_qty_throughput = normalize_qty + '_throughput'
    regular_summary = processed_cycler_run.structured_summary.copy()
    regular_summary = regular_summary[regular_summary.cycle_index != 0]
    diagnostic_summary = processed_cycler_run.diagnostic_summary.copy()
    # TODO the line below should become superfluous
    regular_summary = regular_summary[~regular_summary.cycle_index.
                                      isin(diagnostic_summary.cycle_index)]

    regular_summary.loc[:, normalize_qty_throughput] = regular_summary[
        normalize_qty].cumsum()
    diagnostic_summary.loc[:, normalize_qty_throughput] = diagnostic_summary[
        normalize_qty].cumsum()

    # Trim the cycle index in summary_diag_cycle_type to the max cycle in the regular cycles
    # (no partial cycles in the regular cycle summary) so that only full cycles are used for n
    summary_diag_cycle_type = summary_diag_cycle_type[
        summary_diag_cycle_type.cycle_index <=
        regular_summary.cycle_index.max()]

    # Second gap in the regular cycles indicates the second set of diagnostics, bookending the
    # initial set of regular cycles.
    first_degradation_cycle = int(regular_summary.cycle_index[
        regular_summary.cycle_index.diff() > 1].iloc[0])
    last_initial_cycle = int(regular_summary.cycle_index[
        regular_summary.cycle_index < first_degradation_cycle].iloc[-1])

    initial_regular_throughput = regular_summary[
        regular_summary.cycle_index ==
        last_initial_cycle][normalize_qty_throughput].values[0]

    summary_diag_cycle_type.loc[:,
                                'initial_regular_throughput'] = initial_regular_throughput

    summary_diag_cycle_type.loc[:,
                                'normalized_regular_throughput'] = summary_diag_cycle_type.apply(
                                    lambda x:
                                    (1 / initial_regular_throughput) *
                                    regular_summary[regular_summary.cycle_index
                                                    < x['cycle_index']]
                                    [normalize_qty_throughput].max(),
                                    axis=1)
    summary_diag_cycle_type['normalized_regular_throughput'].fillna(
        value=0, inplace=True)
    summary_diag_cycle_type.loc[:,
                                'normalized_diagnostic_throughput'] = summary_diag_cycle_type.apply(
                                    lambda x: (1 / initial_regular_throughput)
                                    * diagnostic_summary[
                                        diagnostic_summary.cycle_index <
                                        x['cycle_index']][
                                            normalize_qty_throughput].max(),
                                    axis=1)
    summary_diag_cycle_type['normalized_diagnostic_throughput'].fillna(
        value=0, inplace=True)
    # end of nx addition, calculate the fractional capacity compared to the first diagnostic cycle (reset)
    summary_diag_cycle_type.loc[:, metric] = (
        summary_diag_cycle_type[metric] /
        processed_cycler_run.diagnostic_summary[metric].iloc[0])

    if "\\" in processed_cycler_run.metadata.protocol:
        protocol_name = processed_cycler_run.metadata.protocol.split("\\")[-1]
    else:
        _, protocol_name = os.path.split(
            processed_cycler_run.metadata.protocol)

    parameter_row, _ = parameters_lookup.get_protocol_parameters(
        protocol_name, parameters_path=parameters_path)

    summary_diag_cycle_type.loc[:, 'diagnostic_start_cycle'] = parameter_row[
        'diagnostic_start_cycle'].values[0]
    summary_diag_cycle_type.loc[:, 'diagnostic_interval'] = parameter_row[
        'diagnostic_interval'].values[0]
    # TODO add number of initial regular cycles and interval to the dataframe
    summary_diag_cycle_type.columns = [
        "cycle_index", "fractional_metric", "initial_regular_throughput",
        "normalized_regular_throughput", "normalized_diagnostic_throughput",
        "diagnostic_start_cycle", "diagnostic_interval"
    ]
    return summary_diag_cycle_type
Ejemplo n.º 5
0
def get_step_index(pcycler_run, cycle_type="hppc", diag_pos=0):
    """
        Gets the step indices of the diagnostic cycle which correspond to specific attributes

        Args:
            pcycler_run (beep.structure.ProcessedCyclerRun): processed data
            cycle_type (str): which diagnostic cycle type to evaluate
            diag_pos (int): which iteration of the diagnostic cycle to use (0 for first, 1 for second, -1 for last)

        Returns:
            dict: descriptive keys with step index as values
    """

    pulse_time = 120  # time in seconds used to decide if a current is a pulse or an soc change
    pulse_c_rate = 0.5  # c-rate to decide if a current is a discharge pulse
    rest_long_vs_short = 600  # time in seconds to decide if the rest is the long or short rest step
    soc_change_threshold = 0.05
    parameters_path = os.path.join(os.environ.get("BEEP_PROCESSING_DIR", "/"),
                                   "data-share", "raw", "parameters")

    if "\\" in pcycler_run.metadata.protocol:
        protocol_name = pcycler_run.metadata.protocol.split("\\")[-1]
    else:
        _, protocol_name = os.path.split(pcycler_run.metadata.protocol)

    parameter_row, _ = parameters_lookup.get_protocol_parameters(
        protocol_name, parameters_path=parameters_path)

    step_indices_annotated = {}
    diag_data = pcycler_run.diagnostic_data
    cycles = diag_data.loc[diag_data.cycle_type == cycle_type]
    cycle = cycles[cycles.cycle_index == cycles.cycle_index.unique()[diag_pos]]

    if cycle_type == "hppc":
        for step in cycle.step_index.unique():
            cycle_step = cycle[(cycle.step_index == step)]
            median_crate = np.round(
                cycle_step.current.median() /
                parameter_row["capacity_nominal"].iloc[0], 2)
            mean_crate = np.round(
                cycle_step.current.mean() /
                parameter_row["capacity_nominal"].iloc[0], 2)
            remaining_time = cycle.test_time.max() - cycle_step.test_time.max()
            recurring = len(cycle_step.step_index_counter.unique()) > 1
            step_counter_duration = []
            for step_iter in cycle_step.step_index_counter.unique():
                cycle_step_iter = cycle_step[(
                    cycle_step.step_index_counter == step_iter)]
                duration = cycle_step_iter.test_time.max(
                ) - cycle_step_iter.test_time.min()
                step_counter_duration.append(duration)
            median_duration = np.round(np.median(step_counter_duration), 0)

            if median_crate == 0.0:
                if median_duration > rest_long_vs_short:
                    step_indices_annotated["hppc_long_rest"] = step
                elif rest_long_vs_short >= median_duration > 0:
                    step_indices_annotated["hppc_short_rest"] = step
                else:
                    raise ValueError
            elif median_crate <= -pulse_c_rate and median_duration < pulse_time:
                step_indices_annotated["hppc_discharge_pulse"] = step
            elif median_crate >= pulse_c_rate and median_duration < pulse_time:
                step_indices_annotated["hppc_charge_pulse"] = step
            elif mean_crate != median_crate < 0 and remaining_time == 0.0 and not recurring:
                step_indices_annotated["hppc_final_discharge"] = step
            elif mean_crate == median_crate < 0 and remaining_time == 0.0 and not recurring:
                step_indices_annotated["hppc_final_discharge"] = step
            elif mean_crate == median_crate < 0 and abs(
                    mean_crate * median_duration /
                    3600) > soc_change_threshold:
                step_indices_annotated["hppc_discharge_to_next_soc"] = step
            elif median_crate > 0 and median_duration > pulse_time:
                step_indices_annotated["hppc_charge_to_soc"] = step

    elif cycle_type == "rpt_0.2C" or cycle_type == "rpt_1C" or cycle_type == "rpt_2C" or cycle_type == "reset":
        for step in cycle.step_index.unique():
            cycle_step = cycle[(cycle.step_index == step)]
            median_crate = np.round(
                cycle_step.current.median() /
                parameter_row["capacity_nominal"].iloc[0], 2)
            if median_crate > 0:
                step_indices_annotated[cycle_type + "_charge"] = step
            elif median_crate < 0:
                step_indices_annotated[cycle_type + "_discharge"] = step
            else:
                raise ValueError
    else:
        raise NotImplementedError

    assert len(cycle.step_index.unique()) == len(
        step_indices_annotated.values())

    return step_indices_annotated
Ejemplo n.º 6
0
    def test_get_step_index_2(self):
        pcycler_run_loc = os.path.join(
            TEST_FILE_DIR, "PreDiag_000400_000084_truncated_structure.json")
        parameters_path = os.path.join(TEST_FILE_DIR, "data-share", "raw",
                                       "parameters")
        os.environ["BEEP_PROCESSING_DIR"] = TEST_FILE_DIR
        pcycler_run = auto_load_processed(pcycler_run_loc)
        _, protocol_name = os.path.split(pcycler_run.metadata.protocol)
        parameter_row, _ = parameters_lookup.get_protocol_parameters(
            protocol_name, parameters_path=parameters_path)

        step_ind = featurizer_helpers.get_step_index(pcycler_run,
                                                     cycle_type="hppc",
                                                     diag_pos=0)
        self.assertEqual(len(step_ind.values()), 7)

        self.assertEqual(
            step_ind, {
                'hppc_charge_to_soc': 9,
                'hppc_long_rest': 11,
                'hppc_discharge_pulse': 12,
                'hppc_short_rest': 13,
                'hppc_charge_pulse': 14,
                'hppc_discharge_to_next_soc': 15,
                'hppc_final_discharge': 17
            })
        step_ind = featurizer_helpers.get_step_index(pcycler_run,
                                                     cycle_type="hppc",
                                                     diag_pos=1)
        self.assertEqual(len(step_ind.values()), 7)
        self.assertEqual(
            step_ind, {
                'hppc_charge_to_soc': 41,
                'hppc_long_rest': 43,
                'hppc_discharge_pulse': 44,
                'hppc_short_rest': 45,
                'hppc_charge_pulse': 46,
                'hppc_discharge_to_next_soc': 47,
                'hppc_final_discharge': 49
            })
        step_ind = featurizer_helpers.get_step_index(pcycler_run,
                                                     cycle_type="reset",
                                                     diag_pos=0)
        self.assertEqual(step_ind, {'reset_charge': 5, 'reset_discharge': 6})
        step_ind = featurizer_helpers.get_step_index(pcycler_run,
                                                     cycle_type="reset",
                                                     diag_pos=1)
        self.assertEqual(step_ind, {'reset_charge': 38, 'reset_discharge': 39})

        step_ind = featurizer_helpers.get_step_index(pcycler_run,
                                                     cycle_type="rpt_0.2C",
                                                     diag_pos=0)
        self.assertEqual(step_ind, {
            'rpt_0.2C_charge': 19,
            'rpt_0.2C_discharge': 20
        })
        step_ind = featurizer_helpers.get_step_index(pcycler_run,
                                                     cycle_type="rpt_0.2C",
                                                     diag_pos=1)
        self.assertEqual(step_ind, {
            'rpt_0.2C_charge': 51,
            'rpt_0.2C_discharge': 52
        })

        step_ind = featurizer_helpers.get_step_index(pcycler_run,
                                                     cycle_type="rpt_1C",
                                                     diag_pos=0)
        self.assertEqual(step_ind, {
            'rpt_1C_charge': 22,
            'rpt_1C_discharge': 23
        })
        step_ind = featurizer_helpers.get_step_index(pcycler_run,
                                                     cycle_type="rpt_1C",
                                                     diag_pos=1)
        self.assertEqual(step_ind, {
            'rpt_1C_charge': 54,
            'rpt_1C_discharge': 55
        })

        step_ind = featurizer_helpers.get_step_index(pcycler_run,
                                                     cycle_type="rpt_2C",
                                                     diag_pos=0)
        self.assertEqual(step_ind, {
            'rpt_2C_charge': 25,
            'rpt_2C_discharge': 26
        })
        step_ind = featurizer_helpers.get_step_index(pcycler_run,
                                                     cycle_type="rpt_2C",
                                                     diag_pos=1)
        self.assertEqual(step_ind, {
            'rpt_2C_charge': 57,
            'rpt_2C_discharge': 58
        })