steer-core 0.1.35__py3-none-any.whl → 0.1.37__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- steer_core/Constants/Units.py +24 -1
- steer_core/Constants/Universal.py +5 -0
- steer_core/Mixins/Serializer.py +1 -1
- steer_core/__init__.py +1 -1
- {steer_core-0.1.35.dist-info → steer_core-0.1.37.dist-info}/METADATA +3 -6
- {steer_core-0.1.35.dist-info → steer_core-0.1.37.dist-info}/RECORD +8 -10
- {steer_core-0.1.35.dist-info → steer_core-0.1.37.dist-info}/WHEEL +1 -1
- steer_core/Data/DataManager.py +0 -432
- steer_core/Data/__init__.py +0 -0
- {steer_core-0.1.35.dist-info → steer_core-0.1.37.dist-info}/top_level.txt +0 -0
steer_core/Constants/Units.py
CHANGED
|
@@ -19,6 +19,19 @@ mG_TO_G = 1e-3
|
|
|
19
19
|
G_TO_mG = 1e3
|
|
20
20
|
CM_TO_UM = 1e4
|
|
21
21
|
UM_TO_CM = 1e-4
|
|
22
|
+
KG_TO_T = 1e-3
|
|
23
|
+
T_TO_KG = 1e3
|
|
24
|
+
T_TO_MT = 1e-6
|
|
25
|
+
MT_TO_T = 1e6
|
|
26
|
+
LB_TO_KG = 0.453592
|
|
27
|
+
KG_TO_LB = 1 / 0.453592
|
|
28
|
+
T_TO_SHORT_TON = 1.10231
|
|
29
|
+
SHORT_TON_TO_T = 1 / 1.10231
|
|
30
|
+
LB_TO_SHORT_TON = 1 / 2000
|
|
31
|
+
SHORT_TON_TO_LB = 2000
|
|
32
|
+
LB_TO_T = 1 / 2000 * 1/1.10231
|
|
33
|
+
|
|
34
|
+
|
|
22
35
|
|
|
23
36
|
# Current units
|
|
24
37
|
A_TO_mA = 1e3
|
|
@@ -31,6 +44,9 @@ S_TO_MIN = 1 / 60
|
|
|
31
44
|
MIN_TO_S = 60
|
|
32
45
|
S_TO_Y = 1 / (3600 * 24 * 365)
|
|
33
46
|
Y_TO_S = 3600 * 24 * 365
|
|
47
|
+
H_TO_Y = 1 / 8760
|
|
48
|
+
Y_TO_H = 8760
|
|
49
|
+
|
|
34
50
|
|
|
35
51
|
# Energy units
|
|
36
52
|
W_TO_KW = 1e-3
|
|
@@ -42,7 +58,14 @@ DEG_TO_RAD = 0.017453292519943295
|
|
|
42
58
|
# Percentage units
|
|
43
59
|
PERCENT_TO_FRACTION = 1e-2
|
|
44
60
|
FRACTION_TO_PERCENT = 1e2
|
|
61
|
+
FRACTION_TO_PPM = 1e6
|
|
62
|
+
PPM_TO_FRACTION = 1e-6
|
|
45
63
|
|
|
46
64
|
# Volume units
|
|
47
65
|
L_TO_M3 = 1e-3
|
|
48
|
-
M3_TO_L = 1e3
|
|
66
|
+
M3_TO_L = 1e3
|
|
67
|
+
GAL_TO_L = 3.78541
|
|
68
|
+
L_TO_GAL = 1 / 3.78541
|
|
69
|
+
MMGAL_TO_GAL = 1e-6
|
|
70
|
+
GAL_TO_MMGAL = 1e6
|
|
71
|
+
|
steer_core/Mixins/Serializer.py
CHANGED
|
@@ -257,7 +257,7 @@ class SerializerMixin:
|
|
|
257
257
|
ValueError
|
|
258
258
|
If the object name is not found in any of the tables.
|
|
259
259
|
"""
|
|
260
|
-
from
|
|
260
|
+
from steer_opencell_data.DataManager import DataManager
|
|
261
261
|
|
|
262
262
|
database = DataManager()
|
|
263
263
|
|
steer_core/__init__.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: steer-core
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.37
|
|
4
4
|
Summary: Modelling energy storage from cell to site - STEER OpenCell Design
|
|
5
5
|
Author-email: Nicholas Siemons <nsiemons@stanford.edu>
|
|
6
6
|
Maintainer-email: Nicholas Siemons <nsiemons@stanford.edu>
|
|
@@ -21,14 +21,11 @@ Classifier: Topic :: Scientific/Engineering
|
|
|
21
21
|
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
22
22
|
Requires-Python: >=3.10
|
|
23
23
|
Description-Content-Type: text/markdown
|
|
24
|
-
Requires-Dist: pandas==2.
|
|
25
|
-
Requires-Dist: numpy==
|
|
24
|
+
Requires-Dist: pandas==2.3.3
|
|
25
|
+
Requires-Dist: numpy==2.2.6
|
|
26
26
|
Requires-Dist: datetime==5.5
|
|
27
27
|
Requires-Dist: plotly==6.2.0
|
|
28
28
|
Requires-Dist: scipy==1.15.3
|
|
29
|
-
Requires-Dist: msgpack==1.1.2
|
|
30
|
-
Requires-Dist: msgpack-numpy==0.4.8
|
|
31
|
-
Requires-Dist: nbformat==5.10.4
|
|
32
29
|
Provides-Extra: dev
|
|
33
30
|
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
34
31
|
Requires-Dist: pytest-cov; extra == "dev"
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
steer_core/__init__.py,sha256=
|
|
2
|
-
steer_core/Constants/Units.py,sha256=
|
|
3
|
-
steer_core/Constants/Universal.py,sha256=
|
|
1
|
+
steer_core/__init__.py,sha256=iv1Zv2edpDkh91ynlce2_TditJjHT03A-Lt6ECkaBIA,321
|
|
2
|
+
steer_core/Constants/Units.py,sha256=wfbR52HHhFyeYBYyiJTTbFISuSQNzxnnfj-ifeDHDts,1114
|
|
3
|
+
steer_core/Constants/Universal.py,sha256=_9FlNWGdGyjDx5zI8J-4M7B4_ThqXD4xauCNytv2KdY,135
|
|
4
4
|
steer_core/Constants/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
5
|
steer_core/ContextManagers/ContextManagers.py,sha256=4rSeBdBi6xtKLMAbERklrYmZlbFr0zceAiwu-gjTR38,1869
|
|
6
6
|
steer_core/ContextManagers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
-
steer_core/Data/DataManager.py,sha256=AUbuK1lmibTeY5oZ_RSmfof9FyFd9HQ5J2vMoLWsuAo,14707
|
|
8
|
-
steer_core/Data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
7
|
steer_core/Decorators/Coordinates.py,sha256=MxUWXQNrR9Q0_p4gGAywS4qnPAztajJzSay1Cu6lCRQ,1441
|
|
10
8
|
steer_core/Decorators/General.py,sha256=lc7YdvxU-JDo8b4kunVzSjxcB3_8C185458HrXQq-lk,970
|
|
11
9
|
steer_core/Decorators/Objects.py,sha256=aYaRQBFgdSE0IB4QgBVfb6GhEPagoU6TRNrW_pOaqQI,506
|
|
@@ -15,10 +13,10 @@ steer_core/Mixins/Coordinates.py,sha256=DEPKvySoiDT8JhQSEQDiQgAxGjEJK7MezuZysSvf
|
|
|
15
13
|
steer_core/Mixins/Data.py,sha256=c313F85muxlBHQ6yl6AKrifNyV2toHvVwEy35fNNUNE,4434
|
|
16
14
|
steer_core/Mixins/Dunder.py,sha256=cIwh1VhcwzlwelUo2eM1KllVtxZddrkr6g0a5CkXea8,7146
|
|
17
15
|
steer_core/Mixins/Plotter.py,sha256=wRRF0C5fz_6polCKKRVnZ07UFL4HBohZ5K2BSm_ULsg,13505
|
|
18
|
-
steer_core/Mixins/Serializer.py,sha256=
|
|
16
|
+
steer_core/Mixins/Serializer.py,sha256=1kqoY1U-SpGb-x3f46V4flhD6-PE19RjgLft2uJG19A,10462
|
|
19
17
|
steer_core/Mixins/TypeChecker.py,sha256=eXgu1G4d2_btNg5AJ3UkTXpoFJ79bc6tSasInCnXqc0,10539
|
|
20
18
|
steer_core/Mixins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
21
|
-
steer_core-0.1.
|
|
22
|
-
steer_core-0.1.
|
|
23
|
-
steer_core-0.1.
|
|
24
|
-
steer_core-0.1.
|
|
19
|
+
steer_core-0.1.37.dist-info/METADATA,sha256=OgqOn6S5ae7gjAJMbb9iqkqLj72lWd8hPX8LsJFs-cI,1600
|
|
20
|
+
steer_core-0.1.37.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
|
|
21
|
+
steer_core-0.1.37.dist-info/top_level.txt,sha256=6LFpGCSDE_SqRoT7raeM3Ax7KTBKQnyXLXxM9kXtw5M,11
|
|
22
|
+
steer_core-0.1.37.dist-info/RECORD,,
|
steer_core/Data/DataManager.py
DELETED
|
@@ -1,432 +0,0 @@
|
|
|
1
|
-
import sqlite3 as sql
|
|
2
|
-
from pathlib import Path
|
|
3
|
-
from typing import TypeVar
|
|
4
|
-
import pandas as pd
|
|
5
|
-
import importlib.resources
|
|
6
|
-
|
|
7
|
-
from steer_core.Constants.Units import *
|
|
8
|
-
from steer_core.Mixins.Serializer import SerializerMixin
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
T = TypeVar('T', bound='SerializerMixin')
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class DataManager:
|
|
15
|
-
|
|
16
|
-
def __init__(self):
|
|
17
|
-
with importlib.resources.path("steer_opencell_data", "database.db") as db_path:
|
|
18
|
-
self._db_path = db_path
|
|
19
|
-
self._connection = sql.connect(self._db_path)
|
|
20
|
-
self._cursor = self._connection.cursor()
|
|
21
|
-
|
|
22
|
-
def create_table(self, table_name: str, columns: dict):
|
|
23
|
-
"""
|
|
24
|
-
Function to create a table in the database.
|
|
25
|
-
|
|
26
|
-
:param table_name: Name of the table.
|
|
27
|
-
:param columns: Dictionary of columns and their types.
|
|
28
|
-
"""
|
|
29
|
-
columns_str = ", ".join([f"{k} {v}" for k, v in columns.items()])
|
|
30
|
-
self._cursor.execute(f"CREATE TABLE IF NOT EXISTS {table_name} ({columns_str})")
|
|
31
|
-
self._connection.commit()
|
|
32
|
-
|
|
33
|
-
def drop_table(self, table_name: str):
|
|
34
|
-
"""
|
|
35
|
-
Function to drop a table from the database.
|
|
36
|
-
|
|
37
|
-
:param table_name: Name of the table.
|
|
38
|
-
"""
|
|
39
|
-
self._cursor.execute(f"DROP TABLE IF EXISTS {table_name}")
|
|
40
|
-
self._connection.commit()
|
|
41
|
-
|
|
42
|
-
def get_table_names(self):
|
|
43
|
-
"""
|
|
44
|
-
Function to get the names of all tables in the database.
|
|
45
|
-
|
|
46
|
-
:return: List of table names.
|
|
47
|
-
"""
|
|
48
|
-
self._cursor.execute("SELECT name FROM sqlite_master WHERE type='table';")
|
|
49
|
-
return [row[0] for row in self._cursor.fetchall()]
|
|
50
|
-
|
|
51
|
-
def insert_data(self, table_name: str, data: pd.DataFrame):
|
|
52
|
-
"""
|
|
53
|
-
Inserts data into the database only if it doesn’t already exist.
|
|
54
|
-
|
|
55
|
-
:param table_name: Name of the table.
|
|
56
|
-
:param data: DataFrame containing the data to insert.
|
|
57
|
-
"""
|
|
58
|
-
for _, row in data.iterrows():
|
|
59
|
-
conditions = " AND ".join([f"{col} = ?" for col in data.columns])
|
|
60
|
-
check_query = f"SELECT COUNT(*) FROM {table_name} WHERE {conditions}"
|
|
61
|
-
|
|
62
|
-
self._cursor.execute(check_query, tuple(row))
|
|
63
|
-
if self._cursor.fetchone()[0] == 0: # If the row does not exist, insert it
|
|
64
|
-
insert_query = f"INSERT INTO {table_name} ({', '.join(data.columns)}) VALUES ({', '.join(['?'] * len(row))})"
|
|
65
|
-
self._cursor.execute(insert_query, tuple(row))
|
|
66
|
-
|
|
67
|
-
self._connection.commit()
|
|
68
|
-
|
|
69
|
-
def get_data(
|
|
70
|
-
self,
|
|
71
|
-
table_name: str,
|
|
72
|
-
columns: list = None,
|
|
73
|
-
condition: str | list[str] = None,
|
|
74
|
-
latest_column: str = None,
|
|
75
|
-
):
|
|
76
|
-
"""
|
|
77
|
-
Retrieve data from the database.
|
|
78
|
-
|
|
79
|
-
:param table_name: Name of the table.
|
|
80
|
-
:param columns: List of columns to retrieve. If None, retrieves all columns.
|
|
81
|
-
:param condition: Optional condition (single string or list of conditions).
|
|
82
|
-
:param latest_column: Column name to find the most recent row.
|
|
83
|
-
"""
|
|
84
|
-
# If columns is not provided, get all columns from the table
|
|
85
|
-
if columns is None:
|
|
86
|
-
self._cursor.execute(f"PRAGMA table_info({table_name})")
|
|
87
|
-
columns_info = self._cursor.fetchall()
|
|
88
|
-
columns = [col[1] for col in columns_info] # Extract column names
|
|
89
|
-
if not columns:
|
|
90
|
-
raise ValueError(
|
|
91
|
-
f"Table '{table_name}' does not exist or has no columns."
|
|
92
|
-
)
|
|
93
|
-
|
|
94
|
-
columns_str = ", ".join(columns)
|
|
95
|
-
query = f"SELECT {columns_str} FROM {table_name}"
|
|
96
|
-
|
|
97
|
-
# Add condition if specified
|
|
98
|
-
if condition:
|
|
99
|
-
if isinstance(condition, list):
|
|
100
|
-
condition_str = " AND ".join(condition)
|
|
101
|
-
else:
|
|
102
|
-
condition_str = condition
|
|
103
|
-
query += f" WHERE {condition_str}"
|
|
104
|
-
|
|
105
|
-
# If latest_column is provided, get the most recent entry
|
|
106
|
-
if latest_column:
|
|
107
|
-
query += f" ORDER BY {latest_column} DESC LIMIT 1"
|
|
108
|
-
|
|
109
|
-
# Execute and return the result
|
|
110
|
-
self._cursor.execute(query)
|
|
111
|
-
data = self._cursor.fetchall()
|
|
112
|
-
|
|
113
|
-
return pd.DataFrame(data, columns=columns)
|
|
114
|
-
|
|
115
|
-
def get_unique_values(self, table_name: str, column_name: str):
|
|
116
|
-
"""
|
|
117
|
-
Retrieves all unique values from a specified column.
|
|
118
|
-
|
|
119
|
-
:param table_name: The name of the table.
|
|
120
|
-
:param column_name: The column to retrieve unique values from.
|
|
121
|
-
:return: A list of unique values.
|
|
122
|
-
"""
|
|
123
|
-
query = f"SELECT DISTINCT {column_name} FROM {table_name}"
|
|
124
|
-
self._cursor.execute(query)
|
|
125
|
-
return [row[0] for row in self._cursor.fetchall()]
|
|
126
|
-
|
|
127
|
-
def get_current_collector_materials(self, most_recent: bool = True) -> pd.DataFrame:
|
|
128
|
-
"""
|
|
129
|
-
Retrieves current collector materials from the database.
|
|
130
|
-
|
|
131
|
-
:param most_recent: If True, returns only the most recent entry.
|
|
132
|
-
:return: DataFrame with current collector materials.
|
|
133
|
-
"""
|
|
134
|
-
data = (
|
|
135
|
-
self.get_data(table_name="current_collector_materials")
|
|
136
|
-
.groupby("name", group_keys=False)
|
|
137
|
-
.apply(
|
|
138
|
-
lambda x: x.sort_values("date", ascending=False).head(1)
|
|
139
|
-
if most_recent
|
|
140
|
-
else x
|
|
141
|
-
)
|
|
142
|
-
.reset_index(drop=True)
|
|
143
|
-
)
|
|
144
|
-
|
|
145
|
-
return data
|
|
146
|
-
|
|
147
|
-
def get_insulation_materials(self, most_recent: bool = True) -> pd.DataFrame:
|
|
148
|
-
"""
|
|
149
|
-
Retrieves insulation materials from the database.
|
|
150
|
-
|
|
151
|
-
:param most_recent: If True, returns only the most recent entry.
|
|
152
|
-
:return: DataFrame with insulation materials.
|
|
153
|
-
"""
|
|
154
|
-
data = (
|
|
155
|
-
self.get_data(table_name="insulation_materials")
|
|
156
|
-
.groupby("name", group_keys=False)
|
|
157
|
-
.apply(
|
|
158
|
-
lambda x: x.sort_values("date", ascending=False).head(1)
|
|
159
|
-
if most_recent
|
|
160
|
-
else x
|
|
161
|
-
)
|
|
162
|
-
.reset_index(drop=True)
|
|
163
|
-
)
|
|
164
|
-
|
|
165
|
-
return data
|
|
166
|
-
|
|
167
|
-
def get_cathode_materials(self, most_recent: bool = True) -> pd.DataFrame:
|
|
168
|
-
"""
|
|
169
|
-
Retrieves cathode materials from the database.
|
|
170
|
-
|
|
171
|
-
:param most_recent: If True, returns only the most recent entry.
|
|
172
|
-
:return: DataFrame with cathode materials.
|
|
173
|
-
"""
|
|
174
|
-
data = (
|
|
175
|
-
self.get_data(table_name="cathode_materials")
|
|
176
|
-
.groupby("name", group_keys=False)
|
|
177
|
-
.apply(
|
|
178
|
-
lambda x: x.sort_values("date", ascending=False).head(1)
|
|
179
|
-
if most_recent
|
|
180
|
-
else x
|
|
181
|
-
)
|
|
182
|
-
.reset_index(drop=True)
|
|
183
|
-
)
|
|
184
|
-
|
|
185
|
-
return data
|
|
186
|
-
|
|
187
|
-
def get_anode_materials(self, most_recent: bool = True) -> pd.DataFrame:
|
|
188
|
-
"""
|
|
189
|
-
Retrieves anode materials from the database.
|
|
190
|
-
|
|
191
|
-
:param most_recent: If True, returns only the most recent entry.
|
|
192
|
-
:return: DataFrame with anode materials.
|
|
193
|
-
"""
|
|
194
|
-
data = (
|
|
195
|
-
self.get_data(table_name="anode_materials")
|
|
196
|
-
.groupby("name", group_keys=False)
|
|
197
|
-
.apply(
|
|
198
|
-
lambda x: x.sort_values("date", ascending=False).head(1)
|
|
199
|
-
if most_recent
|
|
200
|
-
else x
|
|
201
|
-
)
|
|
202
|
-
.reset_index(drop=True)
|
|
203
|
-
)
|
|
204
|
-
|
|
205
|
-
return data
|
|
206
|
-
|
|
207
|
-
def get_binder_materials(self, most_recent: bool = True) -> pd.DataFrame:
|
|
208
|
-
"""
|
|
209
|
-
Retrieves binder materials from the database.
|
|
210
|
-
|
|
211
|
-
:param most_recent: If True, returns only the most recent entry.
|
|
212
|
-
:return: DataFrame with binder materials.
|
|
213
|
-
"""
|
|
214
|
-
data = (
|
|
215
|
-
self.get_data(table_name="binder_materials")
|
|
216
|
-
.groupby("name", group_keys=False)
|
|
217
|
-
.apply(
|
|
218
|
-
lambda x: x.sort_values("date", ascending=False).head(1)
|
|
219
|
-
if most_recent
|
|
220
|
-
else x
|
|
221
|
-
)
|
|
222
|
-
.reset_index(drop=True)
|
|
223
|
-
)
|
|
224
|
-
|
|
225
|
-
return data
|
|
226
|
-
|
|
227
|
-
def get_conductive_additive_materials(
|
|
228
|
-
self, most_recent: bool = True
|
|
229
|
-
) -> pd.DataFrame:
|
|
230
|
-
"""
|
|
231
|
-
Retrieves conductive additives from the database.
|
|
232
|
-
|
|
233
|
-
:param most_recent: If True, returns only the most recent entry.
|
|
234
|
-
:return: DataFrame with conductive additives.
|
|
235
|
-
"""
|
|
236
|
-
data = (
|
|
237
|
-
self.get_data(table_name="conductive_additive_materials")
|
|
238
|
-
.groupby("name", group_keys=False)
|
|
239
|
-
.apply(
|
|
240
|
-
lambda x: x.sort_values("date", ascending=False).head(1)
|
|
241
|
-
if most_recent
|
|
242
|
-
else x
|
|
243
|
-
)
|
|
244
|
-
.reset_index(drop=True)
|
|
245
|
-
)
|
|
246
|
-
|
|
247
|
-
return data
|
|
248
|
-
|
|
249
|
-
def get_separator_materials(self, most_recent: bool = True) -> pd.DataFrame:
|
|
250
|
-
"""
|
|
251
|
-
Retrieves separator materials from the database.
|
|
252
|
-
|
|
253
|
-
:param most_recent: If True, returns only the most recent entry.
|
|
254
|
-
:return: DataFrame with separator materials.
|
|
255
|
-
"""
|
|
256
|
-
data = (
|
|
257
|
-
self.get_data(table_name="separator_materials")
|
|
258
|
-
.groupby("name", group_keys=False)
|
|
259
|
-
.apply(
|
|
260
|
-
lambda x: x.sort_values("date", ascending=False).head(1)
|
|
261
|
-
if most_recent
|
|
262
|
-
else x
|
|
263
|
-
)
|
|
264
|
-
.reset_index(drop=True)
|
|
265
|
-
)
|
|
266
|
-
|
|
267
|
-
return data
|
|
268
|
-
|
|
269
|
-
def get_tape_materials(self, most_recent: bool = True) -> pd.DataFrame:
|
|
270
|
-
"""
|
|
271
|
-
Retrieves tape materials from the database.
|
|
272
|
-
|
|
273
|
-
:param most_recent: If True, returns only the most recent entry.
|
|
274
|
-
:return: DataFrame with tape materials.
|
|
275
|
-
"""
|
|
276
|
-
data = (
|
|
277
|
-
self.get_data(table_name="tape_materials")
|
|
278
|
-
.groupby("name", group_keys=False)
|
|
279
|
-
.apply(
|
|
280
|
-
lambda x: x.sort_values("date", ascending=False).head(1)
|
|
281
|
-
if most_recent
|
|
282
|
-
else x
|
|
283
|
-
)
|
|
284
|
-
.reset_index(drop=True)
|
|
285
|
-
)
|
|
286
|
-
|
|
287
|
-
return data
|
|
288
|
-
|
|
289
|
-
def get_prismatic_container_materials(self, most_recent: bool = True) -> pd.DataFrame:
|
|
290
|
-
"""
|
|
291
|
-
Retrieves prismatic container materials from the database.
|
|
292
|
-
|
|
293
|
-
:param most_recent: If True, returns only the most recent entry.
|
|
294
|
-
:return: DataFrame with prismatic container materials.
|
|
295
|
-
"""
|
|
296
|
-
data = (
|
|
297
|
-
self.get_data(table_name="prismatic_container_materials")
|
|
298
|
-
.groupby("name", group_keys=False)
|
|
299
|
-
.apply(
|
|
300
|
-
lambda x: x.sort_values("date", ascending=False).head(1)
|
|
301
|
-
if most_recent
|
|
302
|
-
else x
|
|
303
|
-
)
|
|
304
|
-
.reset_index(drop=True)
|
|
305
|
-
)
|
|
306
|
-
|
|
307
|
-
return data
|
|
308
|
-
|
|
309
|
-
@staticmethod
|
|
310
|
-
def read_half_cell_curve(half_cell_path) -> pd.DataFrame:
|
|
311
|
-
"""
|
|
312
|
-
Function to read in a half cell curve for this active material
|
|
313
|
-
|
|
314
|
-
:param half_cell_path: Path to the half cell data file.
|
|
315
|
-
:return: DataFrame with the specific capacity and voltage.
|
|
316
|
-
"""
|
|
317
|
-
try:
|
|
318
|
-
data = pd.read_csv(half_cell_path)
|
|
319
|
-
except:
|
|
320
|
-
raise FileNotFoundError(f"Could not find the file at {half_cell_path}")
|
|
321
|
-
|
|
322
|
-
if "Specific Capacity (mAh/g)" not in data.columns:
|
|
323
|
-
raise ValueError(
|
|
324
|
-
"The file must have a column named 'Specific Capacity (mAh/g)'"
|
|
325
|
-
)
|
|
326
|
-
|
|
327
|
-
if "Voltage (V)" not in data.columns:
|
|
328
|
-
raise ValueError("The file must have a column named 'Voltage (V)'")
|
|
329
|
-
|
|
330
|
-
if "Step_ID" not in data.columns:
|
|
331
|
-
raise ValueError("The file must have a column named 'Step_ID'")
|
|
332
|
-
|
|
333
|
-
data = (
|
|
334
|
-
data.rename(
|
|
335
|
-
columns={
|
|
336
|
-
"Specific Capacity (mAh/g)": "specific_capacity",
|
|
337
|
-
"Voltage (V)": "voltage",
|
|
338
|
-
"Step_ID": "step_id",
|
|
339
|
-
}
|
|
340
|
-
)
|
|
341
|
-
.assign(
|
|
342
|
-
specific_capacity=lambda x: x["specific_capacity"]
|
|
343
|
-
* (H_TO_S * mA_TO_A / G_TO_KG)
|
|
344
|
-
)
|
|
345
|
-
.filter(["specific_capacity", "voltage", "step_id"])
|
|
346
|
-
.groupby(["specific_capacity", "step_id"], group_keys=False)["voltage"]
|
|
347
|
-
.max()
|
|
348
|
-
.reset_index()
|
|
349
|
-
.sort_values(["step_id", "specific_capacity"])
|
|
350
|
-
)
|
|
351
|
-
|
|
352
|
-
return data
|
|
353
|
-
|
|
354
|
-
def remove_data(self, table_name: str, condition: str):
|
|
355
|
-
"""
|
|
356
|
-
Function to remove data from the database.
|
|
357
|
-
|
|
358
|
-
:param table_name: Name of the table.
|
|
359
|
-
:param condition: Condition to remove rows.
|
|
360
|
-
"""
|
|
361
|
-
self._cursor.execute(f"DELETE FROM {table_name} WHERE {condition}")
|
|
362
|
-
self._connection.commit()
|
|
363
|
-
|
|
364
|
-
@classmethod
|
|
365
|
-
def from_database(cls: type[T], name: str, table_name: str = None) -> T:
|
|
366
|
-
"""
|
|
367
|
-
Pull object from the database by name.
|
|
368
|
-
|
|
369
|
-
Subclasses must define a '_table_name' class variable (str or list of str)
|
|
370
|
-
unless table_name is explicitly provided.
|
|
371
|
-
|
|
372
|
-
Parameters
|
|
373
|
-
----------
|
|
374
|
-
name : str
|
|
375
|
-
Name of the object to retrieve.
|
|
376
|
-
table_name : str, optional
|
|
377
|
-
Specific table to search. If provided, '_table_name' is not required.
|
|
378
|
-
If None, uses class's _table_name.
|
|
379
|
-
|
|
380
|
-
Returns
|
|
381
|
-
-------
|
|
382
|
-
T
|
|
383
|
-
Instance of the class.
|
|
384
|
-
|
|
385
|
-
Raises
|
|
386
|
-
------
|
|
387
|
-
NotImplementedError
|
|
388
|
-
If the subclass doesn't define '_table_name' and table_name is not provided.
|
|
389
|
-
ValueError
|
|
390
|
-
If the object name is not found in any of the tables.
|
|
391
|
-
"""
|
|
392
|
-
database = cls()
|
|
393
|
-
|
|
394
|
-
# Get list of tables to search
|
|
395
|
-
if table_name:
|
|
396
|
-
tables_to_search = [table_name]
|
|
397
|
-
else:
|
|
398
|
-
# Only check for _table_name if table_name wasn't provided
|
|
399
|
-
if not hasattr(cls, '_table_name'):
|
|
400
|
-
raise NotImplementedError(
|
|
401
|
-
f"{cls.__name__} must define a '_table_name' class variable "
|
|
402
|
-
"or provide 'table_name' argument"
|
|
403
|
-
)
|
|
404
|
-
|
|
405
|
-
if isinstance(cls._table_name, (list, tuple)):
|
|
406
|
-
tables_to_search = cls._table_name
|
|
407
|
-
else:
|
|
408
|
-
tables_to_search = [cls._table_name]
|
|
409
|
-
|
|
410
|
-
# Try each table until found
|
|
411
|
-
for table in tables_to_search:
|
|
412
|
-
available_materials = database.get_unique_values(table, "name")
|
|
413
|
-
|
|
414
|
-
if name in available_materials:
|
|
415
|
-
data = database.get_data(table, condition=f"name = '{name}'")
|
|
416
|
-
serialized_bytes = data["object"].iloc[0]
|
|
417
|
-
return cls.deserialize(serialized_bytes)
|
|
418
|
-
|
|
419
|
-
# Not found in any table
|
|
420
|
-
all_available = []
|
|
421
|
-
for table in tables_to_search:
|
|
422
|
-
all_available.extend(database.get_unique_values(table, "name"))
|
|
423
|
-
|
|
424
|
-
raise ValueError(
|
|
425
|
-
f"'{name}' not found in tables {tables_to_search}. "
|
|
426
|
-
f"Available: {all_available}"
|
|
427
|
-
)
|
|
428
|
-
|
|
429
|
-
def __del__(self):
|
|
430
|
-
self._connection.close()
|
|
431
|
-
|
|
432
|
-
|
steer_core/Data/__init__.py
DELETED
|
File without changes
|
|
File without changes
|