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 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()