Skip to content

Commit

Permalink
(PR #29) Refactor/modify results parsers
Browse files Browse the repository at this point in the history
- Moved parsers out to utility file. These will be used in the new monitors.
- Replaced cycle number entry in parsed data with length of discharge capacities (cycle number key not guaranteed in results)
  • Loading branch information
edan-bainglass authored Aug 24, 2023
2 parents b963232 + 83a2f1c commit 2ef4462
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 85 deletions.
88 changes: 3 additions & 85 deletions aiida_aurora/utils/cycling_analysis.py
Original file line number Diff line number Diff line change
@@ -1,99 +1,17 @@
import itertools
import json

import numpy as np

from aiida.common.exceptions import AiidaException
from aiida.orm import ArrayData, CalcJobNode, QueryBuilder, RemoteData


def get_data_from_raw(jsdata):
"Extract raw data from json file."
if not isinstance(jsdata, dict):
raise TypeError('jsdata should be a dictionary')
if len(jsdata["steps"]) > 1:
raise NotImplementedError('Analysis of multiple steps is not implemented.')

raw_data = jsdata["steps"][0]["data"]

# extract raw data
t = np.array([ts["uts"] for ts in raw_data]) - raw_data[0]["uts"]
Ewe = np.array([ts["raw"]["Ewe"]["n"] for ts in raw_data])
I = np.array([ts["raw"]["I"]["n"] for ts in raw_data])
cn = np.array([ts["raw"]["cycle number"] for ts in raw_data])

# find indices of sign changes in I
idx = np.where(np.diff(np.sign(I)) != 0)[0]

# integrate and store charge and discharge currents
Qc, Qd = [], []
for ii in range(len(idx) - 1):
i0, ie = idx[ii], idx[ii + 1]
q = np.trapz(I[i0:ie], t[i0:ie])
if q > 0:
Qc.append(q)
else:
Qd.append(abs(q))
data = {
'time': t,
'Ewe': Ewe,
'I': I,
'cn': cn,
'time-cycles': t[idx[2::2]],
'Qd': np.array(Qd),
'Qc': np.array(Qc)
}
return data
from aiida.orm import CalcJobNode, QueryBuilder, RemoteData


def get_data_from_results(array_node):
"Extract data from parsed ArrayData node."
if not isinstance(array_node, ArrayData):
raise TypeError('array_node should be an ArrayData')

# collect data
t = array_node.get_array('step0_uts')
t -= t[0]
Ewe = array_node.get_array('step0_Ewe_n')
I = array_node.get_array('step0_I_n')
cn = array_node.get_array('step0_cycle_number')

# find indices of sign changes in I
idx = np.where(np.diff(np.sign(I)) != 0)[0]

# integrate and store charge and discharge currents
Qc, Qd = [], []
for ii in range(len(idx) - 1):
i0, ie = idx[ii], idx[ii + 1]
q = np.trapz(I[i0:ie], t[i0:ie])
if q > 0:
Qc.append(q)
else:
Qd.append(abs(q))
data = {
'time': t,
'Ewe': Ewe,
'I': I,
'cn': cn,
'time-cycles': t[idx[2::2]],
'Qd': np.array(Qd),
'Qc': np.array(Qc)
}
return data


def get_capacities(data_dic, discharge=True):
if discharge:
return data_dic['Qd']
else:
return data_dic['Qc']
from .parsers import get_data_from_raw, get_data_from_results


def analyze_cycling_results(data, consecutive_cycles, threshold, discharge):
"""Analyse cycling results.
`data` should be a dictionary generated by `get_data_from_*`.
"""
Qs = get_capacities(data, discharge=discharge)
Qs = data['Qd'] if discharge else data['Qc']
print(f" capacities: {Qs}")
print(f" relative capacities: {Qs / Qs[0]}")

Expand Down
76 changes: 76 additions & 0 deletions aiida_aurora/utils/parsers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import numpy as np

from aiida.orm import ArrayData


def get_data_from_raw(jsdata):
"Extract raw data from json file."
if not isinstance(jsdata, dict):
raise TypeError('jsdata should be a dictionary')
if len(jsdata["steps"]) > 1:
raise NotImplementedError('Analysis of multiple steps is not implemented.')

raw_data = jsdata["steps"][0]["data"]

# extract raw data
t = np.array([ts["uts"] for ts in raw_data]) - raw_data[0]["uts"]
Ewe = np.array([ts["raw"]["Ewe"]["n"] for ts in raw_data])
I = np.array([ts["raw"]["I"]["n"] for ts in raw_data])

# find indices of sign changes in I
idx = np.where(np.diff(np.sign(I)) != 0)[0]

# integrate and store charge and discharge currents
Qc, Qd = [], []
for ii in range(len(idx) - 1):
i0, ie = idx[ii], idx[ii + 1]
q = np.trapz(I[i0:ie], t[i0:ie])
if q > 0:
Qc.append(q)
else:
Qd.append(abs(q))

return {
'time': t,
'Ewe': Ewe,
'I': I,
'cn': len(Qd),
'time-cycles': t[idx[2::2]],
'Qd': np.array(Qd),
'Qc': np.array(Qc),
}


def get_data_from_results(array_node):
"Extract data from parsed ArrayData node."
if not isinstance(array_node, ArrayData):
raise TypeError('array_node should be an ArrayData')

# collect data
t = array_node.get_array('step0_uts')
t -= t[0]
Ewe = array_node.get_array('step0_Ewe_n')
I = array_node.get_array('step0_I_n')

# find indices of sign changes in I
idx = np.where(np.diff(np.sign(I)) != 0)[0]

# integrate and store charge and discharge currents
Qc, Qd = [], []
for ii in range(len(idx) - 1):
i0, ie = idx[ii], idx[ii + 1]
q = np.trapz(I[i0:ie], t[i0:ie])
if q > 0:
Qc.append(q)
else:
Qd.append(abs(q))

return {
'time': t,
'Ewe': Ewe,
'I': I,
'cn': len(Qd),
'time-cycles': t[idx[2::2]],
'Qd': np.array(Qd),
'Qc': np.array(Qc),
}

0 comments on commit 2ef4462

Please sign in to comment.