Skip to content

Commit

Permalink
Merge pull request #79 from GES-ppravatto/main
Browse files Browse the repository at this point in the history
Update with new loading features and examples
  • Loading branch information
Pierpaolo Pravatto authored Jul 13, 2023
2 parents 9217957 + d167ec7 commit e9a7a21
Show file tree
Hide file tree
Showing 76 changed files with 685 additions and 54 deletions.
6 changes: 6 additions & 0 deletions docs/API/api_cellcycling_read_input.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,9 @@
.. autoclass:: echemsuite.cellcycling.read_input.FileManager
:members:
```

## The `quickload_folder` function

```{eval-rst}
.. autofunction:: echemsuite.cellcycling.read_input.quickload_folder
```
14 changes: 7 additions & 7 deletions docs/Examples/plot-cycles.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ from echemsuite.cellcycling.read_input import FileManager
from echemsuite.graphicaltools import ColorShader, Palette
# Read a single set of .DTA files using the `fetch_from_folder` method
path = "../utils/gamry_cellcycling/step_0,1A" # Set here the path to the folder containing the files
path = "../utils/gamry_cellcycling/step_0,1A/CHARGE_DISCHARGE" # Set here the path to the folder containing the files
manager = FileManager()
manager.fetch_from_folder(path, extension=".DTA")
cellcycling = manager.get_cellcycling()
Expand Down Expand Up @@ -128,8 +128,8 @@ def quickload_folder(folder: str, extension: str) -> CellCycling:
# Define a dictionary encoding the name of the experiment and the corresponding cellcycling object
experiments = {}
experiments["0.1A"] = quickload_folder("../utils/gamry_cellcycling/step_0,1A", ".DTA")
experiments["0.3A"] = quickload_folder("../utils/gamry_cellcycling/step_0,3A", ".DTA")
experiments["0.1A"] = quickload_folder("../utils/gamry_cellcycling/step_0,1A/CHARGE_DISCHARGE", ".DTA")
experiments["0.3A"] = quickload_folder("../utils/gamry_cellcycling/step_0,3A/CHARGE_DISCHARGE", ".DTA")
# Select a color palette and set the font size
palette = Palette("matplotlib")
Expand Down Expand Up @@ -189,8 +189,8 @@ def quickload_folder(folder: str, extension: str) -> CellCycling:
# Define a dictionary encoding the name of the experiment and the corresponding cellcycling object
experiments = {}
experiments["Experiment A"] = quickload_folder("../utils/biologic_single_cycling", ".mpt")
experiments["Experiment B"] = quickload_folder("../utils/gamry_cellcycling/step_0,1A", ".DTA")
experiments["Experiment C"] = quickload_folder("../utils/gamry_cellcycling/step_0,3A", ".DTA")
experiments["Experiment B"] = quickload_folder("../utils/gamry_cellcycling/step_0,1A/CHARGE_DISCHARGE", ".DTA")
experiments["Experiment C"] = quickload_folder("../utils/gamry_cellcycling/step_0,3A/CHARGE_DISCHARGE", ".DTA")
# Select a color palette and set the font size
palette = Palette("pastel")
Expand Down Expand Up @@ -245,8 +245,8 @@ def quickload_folder(folder: str, extension: str) -> CellCycling:
# Define a dictionary encoding the name of the experiment and the corresponding cellcycling object
experiments = {}
experiments["Experiment A"] = quickload_folder("../utils/biologic_single_cycling", ".mpt")
experiments["Experiment B"] = quickload_folder("../utils/gamry_cellcycling/step_0,1A", ".DTA")
experiments["Experiment C"] = quickload_folder("../utils/gamry_cellcycling/step_0,3A", ".DTA")
experiments["Experiment B"] = quickload_folder("../utils/gamry_cellcycling/step_0,1A/CHARGE_DISCHARGE", ".DTA")
experiments["Experiment C"] = quickload_folder("../utils/gamry_cellcycling/step_0,3A/CHARGE_DISCHARGE", ".DTA")
# Select a color palette and set the font size
palette = Palette("pastel")
Expand Down
237 changes: 213 additions & 24 deletions docs/Examples/plot-rate-experiments.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ A rate experiment can be constructed directly from a Biologic battery module fil
* [Plot a single set of data from a Biologic Battery module file](Examples-plot-rate-experiments-battmodule)
* [Plot a single set of data from an ARBIN `.csv` file](Examples-plot-rate-experiments-ARBIN)
* [Plot a single set of data from a user defined experiment](Examples-plot-rate-experiments-user-defined)
* [Plot a single set of data from a GAMRY folder tree](Examples-plot-rate-experiments-GAMRY-tree)
* [Plot multiple efficiency series on the same axis for a single experiment](Examples-plot-rate-experiments-multiple-efficiencies)
* [Plot more than one experiment in the same figure](Examples-plot-rate-experiments-comparison)
* [Plot multiple efficiency series on the same axis for multiple experiments](Examples-plot-rate-experiments-multiple-efficiencies-many-experiment)



(Examples-plot-rate-experiments-battmodule)=
Expand Down Expand Up @@ -127,19 +131,12 @@ The following script can be used to generate a `RateExperiment` object starting
```{code-cell} python
import matplotlib.pyplot as plt
from echemsuite.cellcycling.cycles import CellCycling
from echemsuite.cellcycling.read_input import FileManager
from echemsuite.cellcycling.read_input import quickload_folder
from echemsuite.cellcycling.experiments import RateExperiment
# Simple helper function defined to load a cellcycling experiment in a single line
def quickload_folder(folder: str, extension: str) -> CellCycling:
manager = FileManager()
manager.fetch_from_folder(folder, extension)
cellcycling = manager.get_cellcycling()
return cellcycling
# Manually read the cell-cycling steps recorded, at different currents, in the .DTA files
step_1 = quickload_folder("../utils/gamry_cellcycling/step_0,1A", ".DTA")
step_2 = quickload_folder("../utils/gamry_cellcycling/step_0,3A", ".DTA")
step_1 = quickload_folder("../utils/gamry_cellcycling/step_0,1A/CHARGE_DISCHARGE", ".DTA")
step_2 = quickload_folder("../utils/gamry_cellcycling/step_0,3A/CHARGE_DISCHARGE", ".DTA")
# Define an experiment from the data just obtained and set the electrolyte volume
experiment = RateExperiment(current_steps=[0.1, 0.3], cellcycling_steps=[step_1, step_2])
Expand Down Expand Up @@ -181,6 +178,138 @@ plt.tight_layout()
plt.show()
```

(Examples-plot-rate-experiments-GAMRY-tree)=
## Plot a single set of data from a GAMRY folder tree

In the previous example an experiment has been created from a set of `.DTA` files generated by a GAMRY instrument. That example can, however, be greatly simplified if the data-files are organized in a "standard" GAMRY folder structure. Such a structure is identified as follows:

* A `basefolder` contains a set of subfolders associated to different current steps.
* Each subfolder contains a `CHARGE_DISCHARGE` folder in which all the `.DTA` files are stored.

This is the case for the file structure used in the previous example that is structured as follows:

```
gamry_cellcycling
├── step_0,1A
│   ├── 0,1A Cycling.DTA
│   └── CHARGE_DISCHARGE
│   ├── 0,1A Charge_#10.DTA
│   ├── ...
│   └── 0,1A D-Charge_#9.DTA
└── step_0,3A
├── 0,3 Cycling.DTA
└── CHARGE_DISCHARGE
   ├── 0,3A Charge_#10.DTA
   ├── ...
   └── 0,3A D-Charge_#9.DTA
```

The `gamry_cellcycling` represents the `basefolder` while the `step_0,1A` and `step_0,3A` folders represents the folders containin the `CHARGE_DISCHARGE` data-folders.

This file structure can be easily loaded using the `from_GAMRY_folder_tree` classmethod of the `RateExperiment` class. As before the volumetric capacity and coulombic efficiencies are then plotted on a double y-axis graph. In this case the color of the markers has been set manually to `#00FFDD` and a transparency of 20% (`alpha=0.8`) has been set.

```{code-cell} python
import matplotlib.pyplot as plt
from echemsuite.cellcycling.cycles import CellCycling
from echemsuite.cellcycling.experiments import RateExperiment
# Define an experiment from the data just obtained and set the electrolyte volume
experiment = RateExperiment.from_GAMRY_folder_tree("../utils/gamry_cellcycling")
volume = 0.1
# Set the color to be used in the plot
color = "#00FFDD"
# Extract the data that needs to be plotted
N = experiment.numbers
Q = experiment.capacity
CE = experiment.coulomb_efficiencies
# Compute on the fly the volumetric capacity in Ah/L starting from the capacity list (in mAh)
VC = [q/(1000*volume) if q is not None else None for q in Q]
# Setup the figure and define a second y-axis
plt.rcParams.update({'font.size': 18})
fig, ax1 = plt.subplots(figsize=(10, 6))
ax2 = ax1.twinx()
# Plot the volumetric capacity on the main axis
ax1.scatter(N, VC, s=100, c=color, marker="s", edgecolors="black", alpha=0.8, zorder=3)
ax1.set_ylabel("◼ Volumetric capacity (Ah/L)", size=20)
ax1.set_ylim((0, 7.5))
ax1.grid(which="major", c="#DDDDDD")
ax1.grid(which="minor", c="#EEEEEE")
# Plot the coulombic efficiency on the secondary axis
ax2.scatter(N, CE, s=100, c=color, marker="o", edgecolors="black", alpha=0.8, zorder=3)
ax2.set_ylabel("● Coulumbic efficiency (%)", size=20)
ax2.set_ylim((20, 110))
# Set the x-label of the plot
ax1.set_xlabel("Cycle number", size=20)
# Show the plot
plt.tight_layout()
plt.show()
```

(Examples-plot-rate-experiments-multiple-efficiencies)=
## Plot multiple efficiency series on the same axis

Often it can be useful to plot more than one efficiency value on the same axis. This poses a new challenge since the marker used in the plot cannot be easily associated to the data series printed as an axis label. To achieve the desired result a legend should be included merging the data from both axes. An example script, reading data from a Biologic battery module, to do so is reported in what follows:

```{code-cell} python
import matplotlib.pyplot as plt
from echemsuite.cellcycling.experiments import RateExperiment
# Define a Rate experiment (in this case from a Biologic battery module file)
experiment = RateExperiment.from_Biologic_battery_module("../utils/biologic_battery_module.mpt")
volume = 0.05
# Set the color to be used in the plot
color = "#FF8C00"
# Extract the data that needs to be plotted
N = experiment.numbers
Q = experiment.capacity
CE = experiment.coulomb_efficiencies
EE = experiment.energy_efficiencies
# Compute on the fly the volumetric capacity in Ah/L starting from the capacity list (in mAh)
VC = [q/(1000*volume)if q is not None else None for q in Q]
# Setup the figure and define a second y-axis
plt.rcParams.update({'font.size': 18})
fig, ax1 = plt.subplots(figsize=(10, 6))
ax2 = ax1.twinx()
# Plot the volumetric capacity on the main axis
s1=ax1.scatter(N, VC, s=100, c=color, marker="s", edgecolors="black", alpha=0.8, zorder=3, label="Experiment")
ax1.set_ylabel("◼ Volumetric capacity (Ah/L)", size=20)
ax1.set_ylim((10, 110))
ax1.grid(which="major", c="#DDDDDD")
ax1.grid(which="minor", c="#EEEEEE")
# Plot the coulombic and energy efficiencies on the secondary axis
s2=ax2.scatter(N, CE, s=100, c=color, marker="o", edgecolors="black", alpha=0.8, zorder=3, label="Experiment - CE")
s3=ax2.scatter(N,EE, s=100, c=color, marker="d", edgecolors="black", alpha=0.8, zorder=3, label="Experiment - EE")
ax2.set_ylabel("Efficiency (%)", size=20)
ax2.set_ylim((-20, 130))
# Set the x-label of the plot
ax1.set_xlabel("Cycle number", size=20)
# Merge the ledend entries for both axes and print them in the primary axis legend
labs = [l.get_label() for l in (s1, s2, s3)]
ax1.legend((s1, s2, s3), labs, loc=3)
# Show the plot
plt.tight_layout()
plt.show()
```


(Examples-plot-rate-experiments-comparison)=
## Plot more than one experiment in the same figure

Expand All @@ -189,23 +318,11 @@ More than one experiment can be plotted on the same figure to compare performanc
```{code-cell} python
import matplotlib.pyplot as plt
from echemsuite.cellcycling.cycles import CellCycling
from echemsuite.cellcycling.read_input import FileManager
from echemsuite.cellcycling.experiments import RateExperiment
from echemsuite.graphicaltools import Palette
# Simple helper function defined to load a cellcycling experiment in a single line
def quickload_folder(folder: str, extension: str) -> CellCycling:
manager = FileManager()
manager.fetch_from_folder(folder, extension)
cellcycling = manager.get_cellcycling()
return cellcycling
# Manually read the cell-cycling steps recorded, at different currents, in the .DTA files
step_1 = quickload_folder("../utils/gamry_cellcycling/step_0,1A", ".DTA")
step_2 = quickload_folder("../utils/gamry_cellcycling/step_0,3A", ".DTA")
# Define an experiment from the data just obtained and define a second one using the Biologic battery module file
experiment_1 = RateExperiment(current_steps=[0.1, 0.3], cellcycling_steps=[step_1, step_2])
experiment_1 = RateExperiment.from_GAMRY_folder_tree("../utils/gamry_cellcycling")
experiment_2 = RateExperiment.from_Biologic_battery_module("../utils/biologic_battery_module.mpt")
# Group the experiments in a dictionary and define a volume list for the electrolytes
Expand All @@ -219,7 +336,7 @@ palette = Palette("matplotlib")
# Setup the figure and define a second y-axis
plt.rcParams.update({'font.size': 18})
fig, ax1 = plt.subplots(figsize=(10, 8))
fig, ax1 = plt.subplots(figsize=(10, 6))
ax2 = ax1.twinx()
for i, (name, experiment) in enumerate(experiments.items()):
Expand Down Expand Up @@ -256,6 +373,78 @@ ax2.set_ylim((10, 110))
ax1.legend(loc=4)
# Show the plot
plt.tight_layout()
plt.show()
```

(Examples-plot-rate-experiments-multiple-efficiencies-many-experiment)=
## Plot multiple efficiency series on the same axis for multiple experiments

Often it can be useful to plot more than one efficiency value on the same axis for multiple experiments. This poses a new challenge since the marker used in the plot cannot be easily associated to the data series printed as an axis label. To achieve the desired result a legend should be included merging the data from both axes. An example script, reading data from a Biologic battery module, to do so is reported in what follows. Please notice also the use of `ncols` in the call to `legend` allowing us to set a two column format of the legend shown.

```{code-cell} python
import matplotlib.pyplot as plt
from echemsuite.cellcycling.experiments import RateExperiment
from echemsuite.graphicaltools import Palette
# Define a Rate experiment (in this case from a Biologic battery module file) and the electrolyte volume
experiments = {}
experiments["ARBIN"] = RateExperiment.from_ARBIN_csv_file("../utils/arbin_sample.CSV")
experiments["Biologic"] = RateExperiment.from_Biologic_battery_module("../utils/biologic_battery_module.mpt")
volume = 0.1
# Create a palette object to easily handle color schemes
palette = Palette("bold")
# Setup the figure and define a second y-axis
plt.rcParams.update({'font.size': 18})
fig, ax1 = plt.subplots(figsize=(10, 6))
ax2 = ax1.twinx()
# Iterate over each experiment and plot the required scatters
scatters = []
for i, (name, experiment) in enumerate(experiments.items()):
color = palette[i].HEX
# Extract the data that needs to be plotted
N = experiment.numbers
Q = experiment.capacity
CE = experiment.coulomb_efficiencies
EE = experiment.energy_efficiencies
# Compute on the fly the volumetric capacity in Ah/L starting from the capacity list (in mAh)
VC = [q/(1000*volume)if q is not None else None for q in Q]
# Plot the volumetric capacity on the main axis
s1=ax1.scatter(N, VC, s=100, c=color, marker="s", edgecolors="black", alpha=0.8, zorder=3, label=f"{name}")
# Plot the coulombic and energy efficiencies on the secondary axis
s2=ax2.scatter(N, CE, s=100, c=color, marker="o", edgecolors="black", alpha=0.8, zorder=3, label=f"{name} - CE")
s3=ax2.scatter(N,EE, s=100, c=color, marker="d", edgecolors="black", alpha=0.8, zorder=3, label=f"{name} - EE")
# Append all the scatters to the scatters list
scatters.append(s1)
scatters.append(s2)
scatters.append(s3)
# Apply settings to the main y-axis
ax1.set_ylabel("◼ Volumetric capacity (Ah/L)", size=20)
ax1.set_ylim((0, 60))
ax1.grid(which="major", c="#DDDDDD")
ax1.grid(which="minor", c="#EEEEEE")
# Apply settings to the secondary y-axis
ax2.set_ylabel("Efficiency (%)", size=20)
ax2.set_ylim((-50, 130))
# Set the x-label of the plot
ax1.set_xlabel("Cycle number", size=20)
# Show the plot
labs = [l.get_label() for l in scatters]
ax1.legend(scatters, labs, loc=3, ncol=2)
plt.tight_layout()
plt.show()
```
10 changes: 2 additions & 8 deletions docs/Guide/CellCycling/analyzing-experiments.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@
"* Directly constructued by the user, by providing a list of current values and a list of the corresponding `CellCycling` objects\n",
"* Constructed from a Bilogic Battery module file using the `from_Biologic_battery_module` classmethod.\n",
"* Constructed from a ARBIN datafile formatted as a `.csv` table using the `from_ARBIN_csv_file` classmethod.\n",
"* Constructed from a GAMRY \"standard\" folder tree using the `from_GAMRY_folder_tree` classmethod.\n",
"\n",
"A ARBIN `.csv` file can be loaded following the code:"
"An ARBIN `.csv` file can be loaded following the code:"
]
},
{
Expand Down Expand Up @@ -155,13 +156,6 @@
"plt.tight_layout()\n",
"plt.show() "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In similar manner a ARBIN `.csv` file can be easily loaded following this"
]
}
],
"metadata": {
Expand Down
2 changes: 1 addition & 1 deletion docs/intro.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# GES-echem-suite Documentation

Version: [0.2.1b](ReleaseNotes)
Version: [0.2.1b2](ReleaseNotes)

The `GES-echem-suite` library is a small collection of tools for the manipulation and analysis of electrochemical data. The library allows to load, organize, and process the data-files collected during electrochemical experiments such as battery cycling and cyclic voltammetries.

Expand Down
7 changes: 7 additions & 0 deletions docs/release-notes.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
(ReleaseNotes)=
# Release notes

* Version 0.2.1b2
* Added classmethod to `RateExperiment` to load ARBIN `.csv` files.
* Added timestamp propery to `CellCycling` class to more easily track the start of the experiment.
* Added a `quickload_folder` method to the `cellcycling.read_input` module.
* Added classmethod to `RateExperiment` to load GAMRY standard folder format.
* Update to the documentation with more examples and new types of plot

* Version 0.2.1b
* Added a graphicaltools module to help the user in the creation of graphs and plots
* Defined a simple `Color` class to hold, manipulate and carry around RGB color values.
Expand Down
Loading

0 comments on commit e9a7a21

Please sign in to comment.