chromaquant 0.4.0__py3-none-any.whl → 0.5.0__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.
- chromaquant/__init__.py +9 -2
- chromaquant/data/__init__.py +14 -0
- chromaquant/data/breakdown.py +430 -0
- chromaquant/data/dataset.py +195 -0
- chromaquant/data/table.py +412 -0
- chromaquant/data/value.py +215 -0
- chromaquant/formula/__init__.py +13 -0
- chromaquant/formula/base_formulas.py +168 -0
- chromaquant/formula/formula.py +507 -0
- chromaquant/import_local_packages.py +55 -0
- chromaquant/logging_and_handling.py +76 -0
- chromaquant/match/__init__.py +13 -0
- chromaquant/match/match.py +184 -0
- chromaquant/match/match_config.py +296 -0
- chromaquant/match/match_tools.py +154 -0
- chromaquant/{Quant → results}/__init__.py +2 -2
- chromaquant/results/reporting_tools.py +190 -0
- chromaquant/results/results.py +250 -0
- chromaquant/utils/__init__.py +14 -0
- chromaquant/utils/categories.py +127 -0
- chromaquant/utils/chemical_formulas.py +104 -0
- chromaquant/utils/dataframe_processing.py +222 -0
- chromaquant/utils/file_tools.py +100 -0
- chromaquant/utils/formula_tools.py +119 -0
- chromaquant-0.5.0.dist-info/METADATA +61 -0
- chromaquant-0.5.0.dist-info/RECORD +29 -0
- {chromaquant-0.4.0.dist-info → chromaquant-0.5.0.dist-info}/WHEEL +1 -1
- {chromaquant-0.4.0.dist-info → chromaquant-0.5.0.dist-info}/licenses/LICENSE.txt +1 -1
- chromaquant-0.5.0.dist-info/licenses/LICENSES_bundled.txt +251 -0
- chromaquant/Handle/__init__.py +0 -13
- chromaquant/Handle/fileChecks.py +0 -172
- chromaquant/Handle/handleDirectories.py +0 -89
- chromaquant/Hydro/__init__.py +0 -12
- chromaquant/Hydro/hydroMain.py +0 -496
- chromaquant/Manual/HydroUI.py +0 -418
- chromaquant/Manual/QuantUPP.py +0 -373
- chromaquant/Manual/Quantification.py +0 -1305
- chromaquant/Manual/__init__.py +0 -10
- chromaquant/Manual/duplicateMatch.py +0 -211
- chromaquant/Manual/fpm_match.py +0 -798
- chromaquant/Manual/label-type.py +0 -179
- chromaquant/Match/AutoFpmMatch.py +0 -1133
- chromaquant/Match/MatchSub/__init__.py +0 -13
- chromaquant/Match/MatchSub/matchTools.py +0 -282
- chromaquant/Match/MatchSub/peakTools.py +0 -259
- chromaquant/Match/__init__.py +0 -13
- chromaquant/Match/matchMain.py +0 -233
- chromaquant/Quant/AutoQuantification.py +0 -1329
- chromaquant/Quant/QuantSub/__init__.py +0 -15
- chromaquant/Quant/QuantSub/gasFID.py +0 -241
- chromaquant/Quant/QuantSub/gasTCD.py +0 -425
- chromaquant/Quant/QuantSub/liquidFID.py +0 -310
- chromaquant/Quant/QuantSub/parseTools.py +0 -162
- chromaquant/Quant/quantMain.py +0 -417
- chromaquant/UAPP/__init__.py +0 -12
- chromaquant/UAPP/uappMain.py +0 -427
- chromaquant/__main__.py +0 -526
- chromaquant/oldui.py +0 -492
- chromaquant/properties.json +0 -4
- chromaquant-0.4.0.dist-info/METADATA +0 -189
- chromaquant-0.4.0.dist-info/RECORD +0 -38
- chromaquant-0.4.0.dist-info/entry_points.txt +0 -2
- chromaquant-0.4.0.dist-info/licenses/LICENSES_bundled.txt +0 -1035
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
COPYRIGHT STATEMENT:
|
|
5
|
+
|
|
6
|
+
ChromaQuant – A quantification software for complex gas chromatographic data
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026, by Julia Hancock
|
|
9
|
+
Affiliation: Dr. Julie Elaine Rorrer
|
|
10
|
+
URL: https://www.rorrerlab.com/
|
|
11
|
+
|
|
12
|
+
License: BSD 3-Clause License
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
COLLECTION OF SIMPLE FORMULAS
|
|
17
|
+
|
|
18
|
+
Julia Hancock
|
|
19
|
+
Started 1-23-2026
|
|
20
|
+
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from .formula import Formula
|
|
24
|
+
|
|
25
|
+
""" FUNCTIONS """
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
# Create formula using formula string and (optionally) pointer
|
|
29
|
+
def CREATE_FORMULA_FROM_STRING(formula_string: str,
|
|
30
|
+
key_pointer: str = '',
|
|
31
|
+
table_pointer: str = ''):
|
|
32
|
+
|
|
33
|
+
# Create Formula
|
|
34
|
+
formula = Formula(formula_string, key_pointer, table_pointer)
|
|
35
|
+
|
|
36
|
+
return formula
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
# Create formula by wrapping existing formula in stated Excel formula
|
|
40
|
+
def WRAP_FORMULA_STRING(inner_formula_string: str,
|
|
41
|
+
wrapping_formula_string: str):
|
|
42
|
+
|
|
43
|
+
# Get a new formula string
|
|
44
|
+
formula_string = \
|
|
45
|
+
f'={wrapping_formula_string}({inner_formula_string})'
|
|
46
|
+
|
|
47
|
+
return formula_string
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
# Wrap existing formula in IFERROR()
|
|
51
|
+
def FORMULA_IF_ERROR(formula: Formula):
|
|
52
|
+
|
|
53
|
+
# Get the formula string
|
|
54
|
+
formula_string = formula.formula_string
|
|
55
|
+
|
|
56
|
+
# If there is an equals sign at the beginning...
|
|
57
|
+
if formula_string[0] == '=':
|
|
58
|
+
# Remove the equals sign
|
|
59
|
+
formula_string = formula_string[1:]
|
|
60
|
+
|
|
61
|
+
# Otherwise, pass
|
|
62
|
+
else:
|
|
63
|
+
pass
|
|
64
|
+
|
|
65
|
+
# Wrap the formula string in IFERROR()
|
|
66
|
+
formula_string = '=IFERROR(' + formula_string + ', "")'
|
|
67
|
+
|
|
68
|
+
# Set the formula string in Formula again
|
|
69
|
+
formula.formula_string = formula_string
|
|
70
|
+
|
|
71
|
+
return formula
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
# Create formula for binary operations
|
|
75
|
+
def FORMULA_BINARY_OPERATION(left_hand_side: str,
|
|
76
|
+
right_hand_side: str,
|
|
77
|
+
operator: str,
|
|
78
|
+
key_pointer: str = '',
|
|
79
|
+
table_pointer: str = ''):
|
|
80
|
+
|
|
81
|
+
# Get a list of sides
|
|
82
|
+
side_list = [left_hand_side, right_hand_side]
|
|
83
|
+
|
|
84
|
+
# For each passed side of the operator...
|
|
85
|
+
for i in range(len(side_list)):
|
|
86
|
+
|
|
87
|
+
# If the side starts with equals...
|
|
88
|
+
if side_list[i][0] == '=':
|
|
89
|
+
# Remove the equals sign
|
|
90
|
+
side_list[i] = side_list[i][1:]
|
|
91
|
+
|
|
92
|
+
# Otherwise, pass
|
|
93
|
+
else:
|
|
94
|
+
pass
|
|
95
|
+
|
|
96
|
+
# Get a formula string
|
|
97
|
+
formula_string = f'=({side_list[0]}{operator}{side_list[1]})'
|
|
98
|
+
|
|
99
|
+
# Get a Formula instance using CREATE_FORMULA_FROM_STRING
|
|
100
|
+
formula = CREATE_FORMULA_FROM_STRING(formula_string,
|
|
101
|
+
key_pointer,
|
|
102
|
+
table_pointer)
|
|
103
|
+
|
|
104
|
+
return formula
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
# Create formula for binary addition
|
|
108
|
+
def FORMULA_ADDITION(left_hand_side: str,
|
|
109
|
+
right_hand_side: str,
|
|
110
|
+
key_pointer: str = '',
|
|
111
|
+
table_pointer: str = ''):
|
|
112
|
+
|
|
113
|
+
# Get a Formula instance using FORMULA_BINARY_OPERATION
|
|
114
|
+
formula = FORMULA_BINARY_OPERATION(left_hand_side,
|
|
115
|
+
right_hand_side,
|
|
116
|
+
'+',
|
|
117
|
+
key_pointer,
|
|
118
|
+
table_pointer)
|
|
119
|
+
|
|
120
|
+
return formula
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
# Create formula for binary subtraction
|
|
124
|
+
def FORMULA_SUBTRACTION(left_hand_side: str,
|
|
125
|
+
right_hand_side: str,
|
|
126
|
+
key_pointer: str = '',
|
|
127
|
+
table_pointer: str = ''):
|
|
128
|
+
|
|
129
|
+
# Get a Formula instance using FORMULA_BINARY_OPERATION
|
|
130
|
+
formula = FORMULA_BINARY_OPERATION(left_hand_side,
|
|
131
|
+
right_hand_side,
|
|
132
|
+
'-',
|
|
133
|
+
key_pointer,
|
|
134
|
+
table_pointer)
|
|
135
|
+
|
|
136
|
+
return formula
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
# Create formula for binary multiplication
|
|
140
|
+
def FORMULA_MULTIPLICATION(left_hand_side: str,
|
|
141
|
+
right_hand_side: str,
|
|
142
|
+
key_pointer: str = '',
|
|
143
|
+
table_pointer: str = ''):
|
|
144
|
+
|
|
145
|
+
# Get a Formula instance using FORMULA_BINARY_OPERATION
|
|
146
|
+
formula = FORMULA_BINARY_OPERATION(left_hand_side,
|
|
147
|
+
right_hand_side,
|
|
148
|
+
'*',
|
|
149
|
+
key_pointer,
|
|
150
|
+
table_pointer)
|
|
151
|
+
|
|
152
|
+
return formula
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
# Create formula for binary division
|
|
156
|
+
def FORMULA_DIVISION(left_hand_side: str,
|
|
157
|
+
right_hand_side: str,
|
|
158
|
+
key_pointer: str = '',
|
|
159
|
+
table_pointer: str = ''):
|
|
160
|
+
|
|
161
|
+
# Get a Formula instance using FORMULA_BINARY_OPERATION
|
|
162
|
+
formula = FORMULA_BINARY_OPERATION(left_hand_side,
|
|
163
|
+
right_hand_side,
|
|
164
|
+
'/',
|
|
165
|
+
key_pointer,
|
|
166
|
+
table_pointer)
|
|
167
|
+
|
|
168
|
+
return formula
|
|
@@ -0,0 +1,507 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
COPYRIGHT STATEMENT:
|
|
5
|
+
|
|
6
|
+
ChromaQuant – A quantification software for complex gas chromatographic data
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026, by Julia Hancock
|
|
9
|
+
Affiliation: Dr. Julie Elaine Rorrer
|
|
10
|
+
URL: https://www.rorrerlab.com/
|
|
11
|
+
|
|
12
|
+
License: BSD 3-Clause License
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
CLASS DEFINITION FOR FORMULA
|
|
17
|
+
|
|
18
|
+
Julia Hancock
|
|
19
|
+
Started 1-07-2026
|
|
20
|
+
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
import logging
|
|
24
|
+
import re
|
|
25
|
+
from typing import Any
|
|
26
|
+
from ..logging_and_handling import setup_logger, setup_error_logging
|
|
27
|
+
|
|
28
|
+
""" LOGGING AND HANDLING """
|
|
29
|
+
|
|
30
|
+
# Create a logger
|
|
31
|
+
logger = logging.getLogger(__name__)
|
|
32
|
+
|
|
33
|
+
# Format the logger
|
|
34
|
+
logger = setup_logger(logger)
|
|
35
|
+
|
|
36
|
+
# Get an error logging decorator
|
|
37
|
+
error_logging = setup_error_logging(logger)
|
|
38
|
+
|
|
39
|
+
""" CLASSES """
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# Define the formula class
|
|
43
|
+
class Formula:
|
|
44
|
+
|
|
45
|
+
""" SPECIAL METHODS """
|
|
46
|
+
# Initialize class
|
|
47
|
+
def __init__(self,
|
|
48
|
+
formula: str = '',
|
|
49
|
+
key_pointer: str = '',
|
|
50
|
+
table_pointer: str = ''):
|
|
51
|
+
"""__init__ summary
|
|
52
|
+
|
|
53
|
+
Parameters
|
|
54
|
+
----------
|
|
55
|
+
formula : str
|
|
56
|
+
Passed formula with or without inserts and pointers
|
|
57
|
+
pointer: dict
|
|
58
|
+
Dictionary with key and (optionally) table name where
|
|
59
|
+
the formula will be located
|
|
60
|
+
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
# Extract the formula if passed
|
|
64
|
+
if formula != '':
|
|
65
|
+
self._formula = formula
|
|
66
|
+
self.get_formula_cell_inserts()
|
|
67
|
+
|
|
68
|
+
# Otherwise set to a default value
|
|
69
|
+
else:
|
|
70
|
+
self._formula = None
|
|
71
|
+
|
|
72
|
+
# Add passed pointers, even if blank
|
|
73
|
+
self.point_to(key_pointer, table_pointer)
|
|
74
|
+
|
|
75
|
+
# Object representation method, allows for direct access to formula
|
|
76
|
+
def __repr__(self):
|
|
77
|
+
# Return formula string
|
|
78
|
+
return self._formula
|
|
79
|
+
|
|
80
|
+
""" PROPERTIES """
|
|
81
|
+
# Formula properties
|
|
82
|
+
# Formula getter
|
|
83
|
+
@property
|
|
84
|
+
def formula_string(self):
|
|
85
|
+
return self._formula
|
|
86
|
+
|
|
87
|
+
# Formula setter
|
|
88
|
+
@formula_string.setter
|
|
89
|
+
def formula_string(self, value):
|
|
90
|
+
self._formula = value
|
|
91
|
+
self.get_formula_cell_inserts()
|
|
92
|
+
|
|
93
|
+
# Formula deleter
|
|
94
|
+
@formula_string.deleter
|
|
95
|
+
def formula_string(self):
|
|
96
|
+
del self._formula
|
|
97
|
+
del self.insert_list
|
|
98
|
+
|
|
99
|
+
""" METHODS """
|
|
100
|
+
# Method to set formula pointer values
|
|
101
|
+
@error_logging
|
|
102
|
+
def point_to(self,
|
|
103
|
+
key_or_column_id: str,
|
|
104
|
+
table_id: str = ''):
|
|
105
|
+
|
|
106
|
+
# Set the key pointer
|
|
107
|
+
self.key_pointer = key_or_column_id
|
|
108
|
+
|
|
109
|
+
# Set the table pointer
|
|
110
|
+
self.table_pointer = table_id
|
|
111
|
+
|
|
112
|
+
return None
|
|
113
|
+
|
|
114
|
+
# Method to get cases in a formula where cells need to be inserted
|
|
115
|
+
@error_logging
|
|
116
|
+
def get_formula_cell_inserts(self):
|
|
117
|
+
|
|
118
|
+
# Initialize a list to contain parsed pipe contents
|
|
119
|
+
insert_list = []
|
|
120
|
+
|
|
121
|
+
# If the formula contains at least one pipe character...
|
|
122
|
+
if '|' in self._formula:
|
|
123
|
+
|
|
124
|
+
# Get the number of pipes in the formula
|
|
125
|
+
pipe_count = self._formula.count('|')
|
|
126
|
+
|
|
127
|
+
# If the number of pipes is divisible by two...
|
|
128
|
+
if pipe_count % 2 == 0:
|
|
129
|
+
|
|
130
|
+
# Get a list of every substring within pipes
|
|
131
|
+
insert_list = [{'start': match.start(),
|
|
132
|
+
'end': match.end(),
|
|
133
|
+
'raw': match.group(),
|
|
134
|
+
'pipe': [],
|
|
135
|
+
'pointers': {}}
|
|
136
|
+
for match in re.finditer(r'\|(.*?)\|',
|
|
137
|
+
self._formula)]
|
|
138
|
+
|
|
139
|
+
# For each pipe substring...
|
|
140
|
+
for i in range(len(insert_list)):
|
|
141
|
+
|
|
142
|
+
# Split each substring if it contains commas
|
|
143
|
+
insert_list[i]['pipe'] = \
|
|
144
|
+
insert_list[i]['raw'].split(',')
|
|
145
|
+
|
|
146
|
+
# For each newly-split substring...
|
|
147
|
+
for j in range(len(insert_list[i]['pipe'])):
|
|
148
|
+
|
|
149
|
+
# If the substring contains one colon...
|
|
150
|
+
if insert_list[i]['pipe'][j].count(':') == 1:
|
|
151
|
+
|
|
152
|
+
# Split the substring by that colon
|
|
153
|
+
key_value_list = \
|
|
154
|
+
insert_list[i]['pipe'][j].split(':')
|
|
155
|
+
|
|
156
|
+
# Strip the key and value of pipes and whitespace
|
|
157
|
+
key_value_list = \
|
|
158
|
+
[k.strip('|').strip() for k in key_value_list]
|
|
159
|
+
|
|
160
|
+
# Add the key-value pair to the pointers dictionary
|
|
161
|
+
insert_list[i]['pointers'][key_value_list[0]] = \
|
|
162
|
+
key_value_list[1]
|
|
163
|
+
|
|
164
|
+
# Otherwise, raise error
|
|
165
|
+
else:
|
|
166
|
+
raise ValueError('At least one pointer contains an'
|
|
167
|
+
' unexpected number of colons')
|
|
168
|
+
|
|
169
|
+
# Remove the pipe key-value pairs
|
|
170
|
+
del insert_list[i]['pipe']
|
|
171
|
+
|
|
172
|
+
# Otherwise, raise an error
|
|
173
|
+
else:
|
|
174
|
+
raise ValueError('Formula contains at least'
|
|
175
|
+
'one hanging pipe delimeter:'
|
|
176
|
+
f' "{self._formula}"')
|
|
177
|
+
|
|
178
|
+
# Otherwise, pass
|
|
179
|
+
else:
|
|
180
|
+
pass
|
|
181
|
+
|
|
182
|
+
# Save the insert list to a class attribute
|
|
183
|
+
self.insert_list = insert_list
|
|
184
|
+
|
|
185
|
+
return None
|
|
186
|
+
|
|
187
|
+
# Method to replace formula inserts with references
|
|
188
|
+
@error_logging
|
|
189
|
+
def insert_references(self,
|
|
190
|
+
dataset_references: dict[str, dict[Any]]):
|
|
191
|
+
|
|
192
|
+
# Get a dataset references attribute
|
|
193
|
+
self.dataset_references = dataset_references
|
|
194
|
+
|
|
195
|
+
# If the insert list is not None (i.e., there are inserts)...
|
|
196
|
+
if self.insert_list is not None:
|
|
197
|
+
|
|
198
|
+
# If function was passed a table to output to...
|
|
199
|
+
if self.table_pointer != '' and self.key_pointer != '':
|
|
200
|
+
|
|
201
|
+
# Get the list of referenced formulas
|
|
202
|
+
self.referenced_formulas = \
|
|
203
|
+
self.process_table_formula_inserts()
|
|
204
|
+
|
|
205
|
+
# Otherwise, if the function was passed a value to output to...
|
|
206
|
+
elif self.key_pointer != '':
|
|
207
|
+
|
|
208
|
+
# Get the list of referenced formulas
|
|
209
|
+
self.referenced_formulas = \
|
|
210
|
+
self.process_value_formula_inserts()
|
|
211
|
+
|
|
212
|
+
# Otherwise, raise an error
|
|
213
|
+
else:
|
|
214
|
+
raise ValueError('Passed output pointers do not'
|
|
215
|
+
' point to either a value or table')
|
|
216
|
+
|
|
217
|
+
return None
|
|
218
|
+
|
|
219
|
+
# Method to process table formula inserts
|
|
220
|
+
@error_logging
|
|
221
|
+
def process_table_formula_inserts(self):
|
|
222
|
+
"""
|
|
223
|
+
process_table_formula_inserts
|
|
224
|
+
|
|
225
|
+
Parameters
|
|
226
|
+
----------
|
|
227
|
+
None
|
|
228
|
+
|
|
229
|
+
Returns
|
|
230
|
+
-------
|
|
231
|
+
new_formula : list or str
|
|
232
|
+
New formula or list of new formulas.
|
|
233
|
+
|
|
234
|
+
Raises
|
|
235
|
+
------
|
|
236
|
+
ValueError
|
|
237
|
+
'Insert list contains non-key or non-table elements'
|
|
238
|
+
ValueError
|
|
239
|
+
'Formula missing necessary keys'
|
|
240
|
+
ValueError
|
|
241
|
+
'Passed output pointers do not point to either a value or table'
|
|
242
|
+
"""
|
|
243
|
+
|
|
244
|
+
# Try...
|
|
245
|
+
try:
|
|
246
|
+
|
|
247
|
+
# Get the table length
|
|
248
|
+
# NOTE: USES THE LENGTH FROM THE FIRST COLUMN IN THE TABLE
|
|
249
|
+
output_table_length = \
|
|
250
|
+
self.dataset_references[
|
|
251
|
+
self.table_pointer
|
|
252
|
+
][
|
|
253
|
+
next(iter(self.table_pointer[self.table_pointer]))
|
|
254
|
+
]['length']
|
|
255
|
+
|
|
256
|
+
# If length is less than one, set to five
|
|
257
|
+
if output_table_length < 1:
|
|
258
|
+
output_table_length = 5
|
|
259
|
+
|
|
260
|
+
# Otherwise, pass
|
|
261
|
+
else:
|
|
262
|
+
pass
|
|
263
|
+
|
|
264
|
+
# If can't get the length, set to five
|
|
265
|
+
except Exception:
|
|
266
|
+
# logger.info('Formula output pointer indicates empty column.')
|
|
267
|
+
output_table_length = 5
|
|
268
|
+
|
|
269
|
+
# If there is at least one table among inserts...
|
|
270
|
+
if any('table' in insert.get('pointers', {})
|
|
271
|
+
and 'key' in insert.get('pointers', {})
|
|
272
|
+
for insert in self.insert_list):
|
|
273
|
+
|
|
274
|
+
# Get the length of the longest named table
|
|
275
|
+
max_table_length = max(
|
|
276
|
+
[self.dataset_references[
|
|
277
|
+
insert['pointers']['table']
|
|
278
|
+
][
|
|
279
|
+
insert['pointers']['key']
|
|
280
|
+
]['length']
|
|
281
|
+
for insert in self.insert_list
|
|
282
|
+
if 'table' in insert.get('pointers', {})]
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
# If the max_table_length is greater than 1, set
|
|
286
|
+
# the output_table_length to the max_table_length
|
|
287
|
+
if max_table_length > 1:
|
|
288
|
+
output_table_length = max_table_length
|
|
289
|
+
|
|
290
|
+
# Otherwise, pass
|
|
291
|
+
else:
|
|
292
|
+
pass
|
|
293
|
+
|
|
294
|
+
# Initialize a new formula list
|
|
295
|
+
new_formula = \
|
|
296
|
+
[self._formula for i in range(output_table_length)]
|
|
297
|
+
|
|
298
|
+
# For every insert...
|
|
299
|
+
for insert in self.insert_list:
|
|
300
|
+
|
|
301
|
+
# If the insert has a table and key pointer...
|
|
302
|
+
if 'table' in insert['pointers'] \
|
|
303
|
+
and 'key' in insert['pointers']:
|
|
304
|
+
|
|
305
|
+
# Get the insert's table and key pointers
|
|
306
|
+
table_id = insert['pointers']['table']
|
|
307
|
+
column_name = insert['pointers']['key']
|
|
308
|
+
|
|
309
|
+
# Get the current table reference
|
|
310
|
+
table_ref = self.dataset_references[table_id]
|
|
311
|
+
|
|
312
|
+
# If the insert has range pointer equal to true...
|
|
313
|
+
if 'range' in insert['pointers'] and \
|
|
314
|
+
insert['pointers']['range'].capitalize() \
|
|
315
|
+
== 'True':
|
|
316
|
+
|
|
317
|
+
# Get a range substring for each
|
|
318
|
+
# new entry in the output table
|
|
319
|
+
insert['reference'] = \
|
|
320
|
+
table_ref[column_name]['range']
|
|
321
|
+
|
|
322
|
+
# Replace the insert's raw substring
|
|
323
|
+
# for every formula in the new formula list
|
|
324
|
+
new_formula = \
|
|
325
|
+
[self.replace_insert(one_formula,
|
|
326
|
+
insert['raw'],
|
|
327
|
+
insert['reference'])
|
|
328
|
+
for one_formula in new_formula]
|
|
329
|
+
|
|
330
|
+
# Otherwise...
|
|
331
|
+
else:
|
|
332
|
+
|
|
333
|
+
# Get the column letter
|
|
334
|
+
column_letter = \
|
|
335
|
+
table_ref[column_name]['column_letter']
|
|
336
|
+
# Get the column sheet
|
|
337
|
+
column_sheet = \
|
|
338
|
+
table_ref[column_name]['sheet']
|
|
339
|
+
|
|
340
|
+
# Get the start and end rows
|
|
341
|
+
start_row = \
|
|
342
|
+
table_ref[column_name]['start_row']
|
|
343
|
+
end_row = \
|
|
344
|
+
table_ref[column_name]['end_row']
|
|
345
|
+
|
|
346
|
+
# Get a list of insert references for each
|
|
347
|
+
# row iterated over, adjusted to ignore header
|
|
348
|
+
insert['reference'] = \
|
|
349
|
+
[
|
|
350
|
+
f"'{column_sheet}'!"
|
|
351
|
+
f"${column_letter}${row}"
|
|
352
|
+
for row in
|
|
353
|
+
range(start_row, end_row + 1)
|
|
354
|
+
]
|
|
355
|
+
|
|
356
|
+
# Replace the insert's raw substring
|
|
357
|
+
# for every formula in the new formula list
|
|
358
|
+
new_formula = \
|
|
359
|
+
[self.replace_insert(new_formula[i],
|
|
360
|
+
insert['raw'],
|
|
361
|
+
insert['reference'][i]
|
|
362
|
+
)
|
|
363
|
+
for i in range(output_table_length)]
|
|
364
|
+
|
|
365
|
+
# Otherwise, if the insert has a key pointer...
|
|
366
|
+
elif 'key' in insert['pointers']:
|
|
367
|
+
|
|
368
|
+
# Get the key pointer
|
|
369
|
+
key_id = insert['pointers']['key']
|
|
370
|
+
|
|
371
|
+
# Get the value's data reference string
|
|
372
|
+
insert['reference'] = \
|
|
373
|
+
self.dataset_references[key_id]['data_cell']
|
|
374
|
+
|
|
375
|
+
# Replace the insert's raw substring
|
|
376
|
+
# for every formula in the new formula list
|
|
377
|
+
new_formula = \
|
|
378
|
+
[self.replace_insert(one_formula,
|
|
379
|
+
insert['raw'],
|
|
380
|
+
insert['reference'])
|
|
381
|
+
for one_formula in new_formula]
|
|
382
|
+
|
|
383
|
+
# Otherwise, raise an error
|
|
384
|
+
else:
|
|
385
|
+
raise ValueError('Insert list contains '
|
|
386
|
+
'non-key or non-table elements')
|
|
387
|
+
|
|
388
|
+
# Otherwise, if there are only values among inserts...
|
|
389
|
+
elif all('key' in insert.get('pointers', {})
|
|
390
|
+
for insert in self.insert_list):
|
|
391
|
+
|
|
392
|
+
# Initialize a new formula list
|
|
393
|
+
new_formula = \
|
|
394
|
+
[self._formula for i in range(output_table_length)]
|
|
395
|
+
|
|
396
|
+
# Initialize a string formula to use in iterations
|
|
397
|
+
iterate_formula = self._formula
|
|
398
|
+
|
|
399
|
+
# For every insert...
|
|
400
|
+
for insert in self.insert_list:
|
|
401
|
+
|
|
402
|
+
# Get the key pointer
|
|
403
|
+
key_id = insert['pointers']['key']
|
|
404
|
+
|
|
405
|
+
# Get the value's reference string
|
|
406
|
+
insert['reference'] = \
|
|
407
|
+
self.dataset_references[key_id]['data_cell']
|
|
408
|
+
|
|
409
|
+
# Replace insert substring with value's reference
|
|
410
|
+
iterate_formula = \
|
|
411
|
+
self.replace_insert(iterate_formula,
|
|
412
|
+
insert['raw'],
|
|
413
|
+
insert['reference'])
|
|
414
|
+
|
|
415
|
+
# Set the new formula list to be iterate_formula for
|
|
416
|
+
# every entry in the output_table's column
|
|
417
|
+
new_formula = [iterate_formula
|
|
418
|
+
for row in range(output_table_length)]
|
|
419
|
+
|
|
420
|
+
# Otherwise, raise an exception
|
|
421
|
+
else:
|
|
422
|
+
raise ValueError(
|
|
423
|
+
'Insert list contains non-key or non-table elements'
|
|
424
|
+
)
|
|
425
|
+
|
|
426
|
+
return new_formula
|
|
427
|
+
|
|
428
|
+
# Method to process value formula inserts
|
|
429
|
+
@error_logging
|
|
430
|
+
def process_value_formula_inserts(self):
|
|
431
|
+
"""
|
|
432
|
+
process_value_formula_inserts
|
|
433
|
+
|
|
434
|
+
Parameters
|
|
435
|
+
----------
|
|
436
|
+
None
|
|
437
|
+
|
|
438
|
+
Returns
|
|
439
|
+
-------
|
|
440
|
+
new_formula : str
|
|
441
|
+
New formula.
|
|
442
|
+
|
|
443
|
+
Raises
|
|
444
|
+
------
|
|
445
|
+
ValueError
|
|
446
|
+
'Formula missing necessary keys'
|
|
447
|
+
"""
|
|
448
|
+
|
|
449
|
+
# Initialize a new formula
|
|
450
|
+
new_formula = self._formula
|
|
451
|
+
|
|
452
|
+
# For every insert...
|
|
453
|
+
for insert in self.insert_list:
|
|
454
|
+
|
|
455
|
+
# If the insert has a table and key pointer...
|
|
456
|
+
if 'table' in insert['pointers'] \
|
|
457
|
+
and 'key' in insert['pointers']:
|
|
458
|
+
|
|
459
|
+
# Get the insert's table and key pointers
|
|
460
|
+
table_id = insert['pointers']['table']
|
|
461
|
+
column_name = insert['pointers']['key']
|
|
462
|
+
|
|
463
|
+
# Get the table reference
|
|
464
|
+
table_ref = self.dataset_references[table_id]
|
|
465
|
+
|
|
466
|
+
# Get a range substring and save to insert['reference']
|
|
467
|
+
insert['reference'] = \
|
|
468
|
+
table_ref[column_name]['range']
|
|
469
|
+
|
|
470
|
+
# Replace pointer substring with range substring
|
|
471
|
+
new_formula = \
|
|
472
|
+
new_formula.replace(
|
|
473
|
+
insert['raw'],
|
|
474
|
+
insert['reference'])
|
|
475
|
+
|
|
476
|
+
# Otherwise, if insert has a key pointer...
|
|
477
|
+
elif 'key' in insert['pointers']:
|
|
478
|
+
|
|
479
|
+
# Get the key pointer
|
|
480
|
+
key_id = insert['pointers']['key']
|
|
481
|
+
|
|
482
|
+
# Get the value's reference string
|
|
483
|
+
insert['reference'] = \
|
|
484
|
+
self.dataset_references[key_id]['data_cell']
|
|
485
|
+
|
|
486
|
+
# Replace insert substring with value's reference
|
|
487
|
+
new_formula = \
|
|
488
|
+
self.replace_insert(new_formula,
|
|
489
|
+
insert['raw'],
|
|
490
|
+
insert['reference'])
|
|
491
|
+
|
|
492
|
+
# Otherwise, raise an error
|
|
493
|
+
else:
|
|
494
|
+
raise ValueError('Formula missing necessary keys')
|
|
495
|
+
|
|
496
|
+
return new_formula
|
|
497
|
+
|
|
498
|
+
""" STATIC METHODS """
|
|
499
|
+
# Method to replace formula raw insert with reference
|
|
500
|
+
@staticmethod
|
|
501
|
+
def replace_insert(formula, raw, reference):
|
|
502
|
+
|
|
503
|
+
# Replace pointer substring with value's reference
|
|
504
|
+
new_formula = \
|
|
505
|
+
formula.replace(raw, reference)
|
|
506
|
+
|
|
507
|
+
return new_formula
|