From 28d61c57069a006cdcc996731361fe8a5b63e93c Mon Sep 17 00:00:00 2001 From: BruisVanVlijmen2020 Date: Tue, 22 Sep 2020 17:59:01 -0700 Subject: [PATCH 1/3] Initial commit to discharge throughput normalization --- beep/features/featurizer_helpers.py | 48 +++++++++++++++++++++++++++++ beep/featurize.py | 3 +- beep/tests/test_features.py | 4 +-- 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/beep/features/featurizer_helpers.py b/beep/features/featurizer_helpers.py index b3d19cbc..f8706590 100644 --- a/beep/features/featurizer_helpers.py +++ b/beep/features/featurizer_helpers.py @@ -867,6 +867,7 @@ def get_fractional_quantity_remaining( """ Determine relative loss of in diagnostic_cycles of type after 100 regular cycles + Args: processed_cycler_run (beep.structure.ProcessedCyclerRun): information about cycler run metric (str): column name to use for measuring degradation @@ -886,3 +887,50 @@ def get_fractional_quantity_remaining( ) summary_diag_cycle_type.columns = ["cycle_index", "fractional_metric"] return summary_diag_cycle_type + +def get_fractional_quantity_remaining_nx( + processed_cycler_run, metric="discharge_energy", diagnostic_cycle_type="rpt_0.2C" +): + """ + Similar to get_fractional_quantity_remaining() + Determine relative loss of in diagnostic_cycles of type after 100 regular cycles + 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 + + Returns: + a dataframe with cycle_index and corresponding degradation relative to the first measured value + """ + 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.summary.copy() + regular_summary[normalize_qty_throughput] = regular_summary[normalize_qty].cumsum() + indices = summary_diag_cycle_type.cycle_index + initial_throughput = regular_summary.loc[regular_summary.cycle_index == indices.iloc[0]][normalize_qty_throughput].iloc[0] + x = regular_summary.loc[regular_summary.cycle_index == indices.iloc[1]]\ + [normalize_qty_throughput].iloc[0] - initial_throughput + + summary_diag_cycle_type['x'] = x + summary_diag_cycle_type['n'] = ((1/x) * regular_summary[regular_summary.cycle_index.isin(indices)][normalize_qty_throughput]).values + + ## + summary_diag_cycle_type[metric] = ( + summary_diag_cycle_type[metric] + / processed_cycler_run.diagnostic_summary[metric].iloc[0] + ) + + summary_diag_cycle_type.columns = ["cycle_index", "fractional_metric", "x", "n"] + return summary_diag_cycle_type diff --git a/beep/featurize.py b/beep/featurize.py index 32c0c8b1..de8d3307 100644 --- a/beep/featurize.py +++ b/beep/featurize.py @@ -1113,9 +1113,10 @@ def features_from_processed_cycler_run(cls, processed_cycler_run, params_dict=No X = pd.DataFrame() for quantity in params_dict["quantities"]: for cycle_type in cycle_types: - summary_diag_cycle_type = featurizer_helpers.get_fractional_quantity_remaining( + summary_diag_cycle_type = featurizer_helpers.get_fractional_quantity_remaining_nx( processed_cycler_run, quantity, cycle_type ) + summary_diag_cycle_type["cycle_type"] = cycle_type summary_diag_cycle_type["metric"] = quantity X = X.append(summary_diag_cycle_type) diff --git a/beep/tests/test_features.py b/beep/tests/test_features.py index 3795279b..539636a1 100644 --- a/beep/tests/test_features.py +++ b/beep/tests/test_features.py @@ -357,8 +357,8 @@ def test_DiagnosticProperties_class(self): folder = os.path.split(path)[-1] dumpfn(featurizer, featurizer.name) self.assertEqual(folder, "DiagnosticProperties") - self.assertEqual(featurizer.X.shape, (10, 4)) + self.assertEqual(featurizer.X.shape, (30, 6)) self.assertListEqual( list(featurizer.X.iloc[2, :]), - [143, 0.9753520623934744, "rpt_0.2C", "discharge_energy"], + [141,0.9859837086597274,91.17758004259996,2.578137278917377,'reset','discharge_energy'] ) From 73724cb76bbc97543f745253775c98967b98d318 Mon Sep 17 00:00:00 2001 From: BruisVanVlijmen2020 Date: Tue, 22 Sep 2020 18:36:36 -0700 Subject: [PATCH 2/3] Solving pycodestyle issues --- beep/features/featurizer_helpers.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/beep/features/featurizer_helpers.py b/beep/features/featurizer_helpers.py index f8706590..786958e6 100644 --- a/beep/features/featurizer_helpers.py +++ b/beep/features/featurizer_helpers.py @@ -888,13 +888,15 @@ def get_fractional_quantity_remaining( summary_diag_cycle_type.columns = ["cycle_index", "fractional_metric"] return summary_diag_cycle_type + def get_fractional_quantity_remaining_nx( processed_cycler_run, metric="discharge_energy", diagnostic_cycle_type="rpt_0.2C" ): """ Similar to get_fractional_quantity_remaining() Determine relative loss of in diagnostic_cycles of type after 100 regular cycles - Also returns value of 'x', the discharge throughput passed by the first diagnostic and the value 'n' at each diagnostic + 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 @@ -919,12 +921,17 @@ def get_fractional_quantity_remaining_nx( regular_summary = processed_cycler_run.summary.copy() regular_summary[normalize_qty_throughput] = regular_summary[normalize_qty].cumsum() indices = summary_diag_cycle_type.cycle_index - initial_throughput = regular_summary.loc[regular_summary.cycle_index == indices.iloc[0]][normalize_qty_throughput].iloc[0] - x = regular_summary.loc[regular_summary.cycle_index == indices.iloc[1]]\ - [normalize_qty_throughput].iloc[0] - initial_throughput + initial_throughput = regular_summary.loc[ + regular_summary.cycle_index == indices.iloc[0] + ][normalize_qty_throughput].iloc[0] + x = regular_summary.loc[ + regular_summary.cycle_index == indices.iloc[1] + ][normalize_qty_throughput].iloc[0] - initial_throughput summary_diag_cycle_type['x'] = x - summary_diag_cycle_type['n'] = ((1/x) * regular_summary[regular_summary.cycle_index.isin(indices)][normalize_qty_throughput]).values + summary_diag_cycle_type['n'] = ( + (1/x) * regular_summary[regular_summary.cycle_index.isin(indices)][normalize_qty_throughput] + ).values ## summary_diag_cycle_type[metric] = ( From e70c55d649ce5ed16a4e5ed147eb238b2f7e5353 Mon Sep 17 00:00:00 2001 From: BruisVanVlijmen2020 Date: Wed, 23 Sep 2020 14:23:41 -0700 Subject: [PATCH 3/3] Changed test assertions, function description - still JSON decoder error on end_to_end test --- beep/features/featurizer_helpers.py | 8 +++++--- beep/featurize.py | 4 +++- beep/tests/test_features.py | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/beep/features/featurizer_helpers.py b/beep/features/featurizer_helpers.py index 786958e6..ad8082ff 100644 --- a/beep/features/featurizer_helpers.py +++ b/beep/features/featurizer_helpers.py @@ -894,7 +894,7 @@ def get_fractional_quantity_remaining_nx( ): """ Similar to get_fractional_quantity_remaining() - Determine relative loss of in diagnostic_cycles of type after 100 regular cycles + Determine relative loss of in diagnostic_cycles of type Also returns value of 'x', the discharge throughput passed by the first diagnostic and the value 'n' at each diagnostic @@ -904,7 +904,9 @@ def get_fractional_quantity_remaining_nx( diagnostic_cycle_type (str): the diagnostic cycle to use for computing the amount of degradation Returns: - a dataframe with cycle_index and corresponding degradation relative to the first measured value + 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) @@ -933,7 +935,7 @@ def get_fractional_quantity_remaining_nx( (1/x) * regular_summary[regular_summary.cycle_index.isin(indices)][normalize_qty_throughput] ).values - ## + # end of nx addition summary_diag_cycle_type[metric] = ( summary_diag_cycle_type[metric] / processed_cycler_run.diagnostic_summary[metric].iloc[0] diff --git a/beep/featurize.py b/beep/featurize.py index de8d3307..803a957b 100644 --- a/beep/featurize.py +++ b/beep/featurize.py @@ -1099,12 +1099,14 @@ def validate_data(cls, processed_cycler_run, params_dict=None): @classmethod def features_from_processed_cycler_run(cls, processed_cycler_run, params_dict=None): """ + Generates diagnostic-property features from processed cycler run, including values for n*x method Args: processed_cycler_run (beep.structure.ProcessedCyclerRun): data from cycler run params_dict (dict): dictionary of parameters governing how the ProcessedCyclerRun object gets featurized. These could be filters for column or row operations Returns: - pd.DataFrame: cycles at which capacity/energy degradation exceeds thresholds + pd.DataFrame: with "cycle_index", "fractional_metric", "x", "n", "cycle_type" and "metric" columns, rows + for each diagnostic cycle of the cell """ if params_dict is None: params_dict = FEATURE_HYPERPARAMS[cls.class_feature_name] diff --git a/beep/tests/test_features.py b/beep/tests/test_features.py index 539636a1..da93f5e4 100644 --- a/beep/tests/test_features.py +++ b/beep/tests/test_features.py @@ -198,7 +198,7 @@ def test_feature_generation_list_to_json(self): self.assertIsInstance(features_reloaded, DiagnosticProperties) self.assertListEqual( list(features_reloaded.X.iloc[2, :]), - [143, 0.9753520623934744, "rpt_0.2C", "discharge_energy"], + [141,0.9859837086597274,91.17758004259996,2.578137278917377,'reset','discharge_energy'], ) # Workflow output