pyKES 0.1.2__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.
- pyKES/__init__.py +0 -0
- pyKES/database/__init__.py +0 -0
- pyKES/database/data_processing.py +217 -0
- pyKES/database/database_experiments.py +541 -0
- pyKES/fitting_ODE.py +613 -0
- pyKES/pathways/__init__.py +0 -0
- pyKES/pathways/pathways.py +509 -0
- pyKES/pathways/transform_pathways_data.py +680 -0
- pyKES/plotting/__init__.py +0 -0
- pyKES/plotting/lighten_colors.py +26 -0
- pyKES/plotting/plotting_pathways_transformed.py +283 -0
- pyKES/plotting/plotting_tools.py +560 -0
- pyKES/reaction_ODE.py +504 -0
- pyKES/reaction_model.py +321 -0
- pyKES/streamlit_app/components/__init__.py +35 -0
- pyKES/streamlit_app/components/analysis_results_component.py +1294 -0
- pyKES/streamlit_app/components/data_upload_component.py +310 -0
- pyKES/streamlit_app/components/home_component.py +91 -0
- pyKES/streamlit_app/components/time_series_component.py +293 -0
- pyKES/streamlit_app/config_interface.py +241 -0
- pyKES/utilities/__init__.py +0 -0
- pyKES/utilities/calculate_absorption.py +481 -0
- pyKES/utilities/find_nearest.py +40 -0
- pyKES/utilities/get_experiments.py +51 -0
- pyKES/utilities/harmonize_time_series.py +64 -0
- pyKES/utilities/make_json_serializable.py +19 -0
- pyKES/utilities/offset_correction.py +22 -0
- pyKES/utilities/resolve_attributes.py +170 -0
- pyKES/utilities/time_series_resampling.py +35 -0
- pykes-0.1.2.dist-info/METADATA +57 -0
- pykes-0.1.2.dist-info/RECORD +32 -0
- pykes-0.1.2.dist-info/WHEEL +4 -0
pyKES/__init__.py
ADDED
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from concurrent.futures import ProcessPoolExecutor
|
|
3
|
+
import multiprocessing
|
|
4
|
+
from functools import partial
|
|
5
|
+
import traceback
|
|
6
|
+
from typing import Optional
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
from pyKES.database.database_experiments import ExperimentalDataset, Experiment
|
|
10
|
+
|
|
11
|
+
def generate_list_of_files(keywords, directory):
|
|
12
|
+
|
|
13
|
+
files = [
|
|
14
|
+
os.path.join(directory, file)
|
|
15
|
+
for file in os.listdir(directory)
|
|
16
|
+
if any(keyword in file for keyword in keywords)
|
|
17
|
+
and not file.startswith('~$')
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
return files
|
|
21
|
+
|
|
22
|
+
def read_in_single_experiment(file_name: str,
|
|
23
|
+
database: ExperimentalDataset,
|
|
24
|
+
metadata_retrival_function: callable,
|
|
25
|
+
raw_data_reading_function: callable,
|
|
26
|
+
processing_function: callable,
|
|
27
|
+
directory: Optional[Path] = None,
|
|
28
|
+
legacy_mode = True):
|
|
29
|
+
"""
|
|
30
|
+
Legacy mode is for use with file-based processing and use in multi-processing mode.
|
|
31
|
+
|
|
32
|
+
Non-legacy mode is for use with overview_df-based processing in single-threaded mode,
|
|
33
|
+
where the file name is not necessarily the key to retrieve metadata and raw data.
|
|
34
|
+
In this case, the file name is used as an argument to the metadata retrieval function,
|
|
35
|
+
which then retrieves the necessary metadata and file paths for raw data reading and processing.
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
try:
|
|
41
|
+
if legacy_mode:
|
|
42
|
+
metadata_dict = metadata_retrival_function(file_name, database.overview_df)
|
|
43
|
+
raw_data_dict = raw_data_reading_function(file_name, metadata_dict)
|
|
44
|
+
processed_data_dict = processing_function(raw_data_dict, metadata_dict)
|
|
45
|
+
|
|
46
|
+
else:
|
|
47
|
+
metadata_dict = metadata_retrival_function(file_name, database.overview_df)
|
|
48
|
+
raw_data_dict = raw_data_reading_function(directory, metadata_dict)
|
|
49
|
+
processed_data_dict = processing_function(raw_data_dict, metadata_dict)
|
|
50
|
+
|
|
51
|
+
experiment = Experiment(
|
|
52
|
+
experiment_name = metadata_dict['experiment_name'],
|
|
53
|
+
raw_data_file = file_name,
|
|
54
|
+
color = metadata_dict.get('color', 'black'),
|
|
55
|
+
group = metadata_dict.get('group', 'default'),
|
|
56
|
+
metadata = metadata_dict,
|
|
57
|
+
raw_data = raw_data_dict,
|
|
58
|
+
processed_data = processed_data_dict
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
'success': True,
|
|
63
|
+
'data': experiment
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
except Exception as e:
|
|
67
|
+
tb = traceback.format_exc()
|
|
68
|
+
print(f'{file_name} analysis failed, not added to dataset, error: {str(e)}')
|
|
69
|
+
print("Full traceback:")
|
|
70
|
+
print(tb)
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
'success': False,
|
|
74
|
+
'file': file_name,
|
|
75
|
+
'error': f"{str(e)}\n\nFull traceback:\n{tb}"
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def read_in_experiments_single_threaded(database: ExperimentalDataset,
|
|
80
|
+
metadata_retrival_function: callable,
|
|
81
|
+
raw_data_reading_function: callable,
|
|
82
|
+
processing_function: callable,
|
|
83
|
+
overview_df_experiment_column: Optional[str] = 'Experiment',
|
|
84
|
+
directory: Optional[Path] = None):
|
|
85
|
+
"""
|
|
86
|
+
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
if "Processed" not in database.overview_df.columns:
|
|
90
|
+
database.overview_df["Processed"] = False
|
|
91
|
+
|
|
92
|
+
# Returning only the experiments which have not been processed
|
|
93
|
+
# Do not contain "Processed" column or "Processed" is not True
|
|
94
|
+
# also returns experiments which are not in the database.experiments dict,
|
|
95
|
+
|
|
96
|
+
mask = (
|
|
97
|
+
database.overview_df["Processed"].ne('True')
|
|
98
|
+
| ~database.overview_df[overview_df_experiment_column].isin(database.experiments))
|
|
99
|
+
experiments = database.overview_df.loc[mask,
|
|
100
|
+
overview_df_experiment_column].astype(str).tolist()
|
|
101
|
+
|
|
102
|
+
results = []
|
|
103
|
+
|
|
104
|
+
for experiment_name in experiments:
|
|
105
|
+
|
|
106
|
+
result = read_in_single_experiment(
|
|
107
|
+
file_name = experiment_name,
|
|
108
|
+
database = database,
|
|
109
|
+
metadata_retrival_function = metadata_retrival_function,
|
|
110
|
+
raw_data_reading_function = raw_data_reading_function,
|
|
111
|
+
processing_function = processing_function,
|
|
112
|
+
directory = directory,
|
|
113
|
+
legacy_mode = False
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
results.append(result)
|
|
117
|
+
|
|
118
|
+
if result['success']:
|
|
119
|
+
# Add experiment to database
|
|
120
|
+
database.add_experiment(result['data'])
|
|
121
|
+
|
|
122
|
+
# Setting "Processed" to True in dataframe
|
|
123
|
+
database.overview_df.loc[
|
|
124
|
+
database.overview_df[overview_df_experiment_column].eq(result['data'].experiment_name),
|
|
125
|
+
"Processed",
|
|
126
|
+
] = 'True'
|
|
127
|
+
|
|
128
|
+
else:
|
|
129
|
+
print(f"Failed to process {result['file']}: {result['error']}")
|
|
130
|
+
|
|
131
|
+
return results
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def read_in_experiments_multiprocessing(database: ExperimentalDataset,
|
|
135
|
+
metadata_retrival_function: callable,
|
|
136
|
+
raw_data_reading_function: callable,
|
|
137
|
+
processing_function: callable,
|
|
138
|
+
keywords: Optional[list] = None,
|
|
139
|
+
directory: Optional[str] = None,
|
|
140
|
+
overview_df_based_processing: Optional[bool] = False,
|
|
141
|
+
overview_df_experiment_column: Optional[str] = 'Experiment'):
|
|
142
|
+
"""
|
|
143
|
+
|
|
144
|
+
"""
|
|
145
|
+
|
|
146
|
+
if overview_df_based_processing:
|
|
147
|
+
files = database.overview_df[overview_df_experiment_column].tolist()
|
|
148
|
+
else:
|
|
149
|
+
files = generate_list_of_files(keywords, directory)
|
|
150
|
+
|
|
151
|
+
read_in_single_experiment_partial = partial(read_in_single_experiment,
|
|
152
|
+
database = database,
|
|
153
|
+
metadata_retrival_function = metadata_retrival_function,
|
|
154
|
+
raw_data_reading_function = raw_data_reading_function,
|
|
155
|
+
processing_function = processing_function)
|
|
156
|
+
|
|
157
|
+
with ProcessPoolExecutor(max_workers=multiprocessing.cpu_count()) as executor:
|
|
158
|
+
results = list(executor.map(read_in_single_experiment_partial, files))
|
|
159
|
+
|
|
160
|
+
for result in results:
|
|
161
|
+
if result['success']:
|
|
162
|
+
database.add_experiment(result['data'])
|
|
163
|
+
else:
|
|
164
|
+
print(f"Failed to process {result['file']}: {result['error']}")
|
|
165
|
+
|
|
166
|
+
return results
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def testing():
|
|
170
|
+
|
|
171
|
+
from tests.data.processing_functions_overview_df import (metadata_retrival_function,
|
|
172
|
+
raw_data_reading_function,
|
|
173
|
+
processing_function)
|
|
174
|
+
from tests.data.processing_parameters import PROCESSING_PARAMETERS, GROUP_MAPPING, PLOTTING_INSTRUCTIONS
|
|
175
|
+
|
|
176
|
+
import pandas as pd
|
|
177
|
+
import pprint as pp
|
|
178
|
+
|
|
179
|
+
overview_df = pd.read_excel(
|
|
180
|
+
'/Users/jacob/Documents/Water_Splitting/Projects/pyKES/pyKES/src/tests/data/251204_O2_H2_Experiment_Overview.xlsx',
|
|
181
|
+
sheet_name='Sheet1',
|
|
182
|
+
dtype={'active': str,
|
|
183
|
+
'D2O': str,
|
|
184
|
+
'Processed': str} # Force 'active' and 'D2O' columns to be read as strings
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
dataset = ExperimentalDataset(
|
|
188
|
+
overview_df = overview_df,
|
|
189
|
+
group_mapping = GROUP_MAPPING,
|
|
190
|
+
plotting_instruction = PLOTTING_INSTRUCTIONS,
|
|
191
|
+
processing_parameters = PROCESSING_PARAMETERS
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
read_in_experiments_single_threaded(
|
|
195
|
+
database = dataset,
|
|
196
|
+
metadata_retrival_function = metadata_retrival_function,
|
|
197
|
+
raw_data_reading_function = raw_data_reading_function,
|
|
198
|
+
processing_function = processing_function,
|
|
199
|
+
overview_df_experiment_column = 'Experiment',
|
|
200
|
+
directory = Path('/Users/jacob/Documents/Water_Splitting/Projects/pyKES/pyKES/src/tests/data/data_files')
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
pp.pprint(dataset.experiments['NB-316'])
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
if __name__ == '__main__':
|
|
217
|
+
testing()
|