Skip to content

Commit

Permalink
feat: add cv data with offset
Browse files Browse the repository at this point in the history
  • Loading branch information
Lan Le committed Dec 1, 2023
1 parent b6343eb commit 17b0f7d
Show file tree
Hide file tree
Showing 9 changed files with 187 additions and 37 deletions.
2 changes: 2 additions & 0 deletions chem_spectra/controller/helper/share.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ def extract_params(request):
# simulatenmr = bool(request.form.get('simulatenmr', default=False))
simulatenmr = request.form.get('simulatenmr', default=False) == 'true'
waveLength = request.form.get('wave_length', default=None)
axesUnits = request.form.get('axes_units', default=None)
cyclicvolta = request.form.get('cyclic_volta', default=None)
jcamp_idx = parse_int(request.form.get('jcamp_idx', default=0), 0)
list_file_names = request.form.getlist('list_file_names[]')
Expand All @@ -125,6 +126,7 @@ def extract_params(request):
'cyclic_volta': cyclicvolta,
'jcamp_idx': jcamp_idx,
'list_file_names': list_file_names,
'axesUnits': axesUnits,
}
has_params = (
params.get('peaks_str') or
Expand Down
2 changes: 1 addition & 1 deletion chem_spectra/controller/transform_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ def combine_images():
list_files.append(file_container)

params = extract_params(request)
transform_model = TraModel(None, params=params, multiple_files=list_files)
transform_model = TraModel(None, params=params, multiple_files=list_files)
tf_combine = transform_model.tf_combine(list_file_names=params['list_file_names'])
if (not tf_combine):
abort(400)
Expand Down
81 changes: 51 additions & 30 deletions chem_spectra/lib/composer/ni.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
extrac_dic, calc_npoints, BaseComposer
)
from chem_spectra.lib.shared.calc import ( # noqa: E402
calc_mpy_center, calc_ks, get_curve_endpoint, cal_slope, cal_xyIntegration
calc_mpy_center, calc_ks, get_curve_endpoint, cal_slope, cal_xyIntegration,
)


Expand Down Expand Up @@ -141,6 +141,8 @@ def __gen_cyclic_voltammetry_data_peaks(self):
content = ['##$CSCYCLICVOLTAMMETRYDATA=\n']
if self.core.is_cyclic_volta:
listMaxMinPeaks = self.core.max_min_peaks_table
cyclicvolta_data = self.core.params['cyclicvolta']
current_jcamp_idx = self.core.params['jcamp_idx']
if self.core.params['list_max_min_peaks'] is not None:
listMaxMinPeaks = self.core.params['list_max_min_peaks']

Expand All @@ -152,36 +154,44 @@ def __gen_cyclic_voltammetry_data_peaks(self):
y_pecker = self.core.ys[idx]

for peak in listMaxMinPeaks:
max_peak, min_peak = peak['max'], peak['min']
max_peak, min_peak = None, None
if 'max' in peak:
max_peak = peak['max']
if 'min' in peak:
min_peak = peak['min']
x_max_peak, y_max_peak = self.__get_xy_of_peak(max_peak)
x_min_peak, y_min_peak = self.__get_xy_of_peak(min_peak)

if (x_max_peak == '' and x_min_peak == ''):
x_pecker = ''
if 'pecker' in peak and peak['pecker'] is not None:
pecker = peak['pecker']
x_pecker = pecker['x']
y_pecker = pecker['y']
x_pecker = f"{float(x_pecker)}"

if (x_max_peak == '' and x_min_peak == '' and x_pecker == ''):
# ignore if missing both max and min peak
continue

if (x_max_peak == '' or x_min_peak == ''):
delta = ''
else:
delta = abs(x_max_peak - x_min_peak)

x_pecker = ''

# calculate ratio
if (y_min_peak == '' or y_max_peak == ''):
ratio = ''
else:
if 'pecker' in peak and peak['pecker'] is not None:
pecker = peak['pecker']
x_pecker = pecker['x']
y_pecker = pecker['y']
first_expr = abs(y_min_peak) / abs(y_max_peak)
second_expr = 0.485 * abs(y_pecker) / abs(y_max_peak)
ratio = first_expr + second_expr + 0.086
if (y_pecker) == 0:
y_pecker = ''

is_ref = peak.get('isRef', False)
is_ref_in_number = 1 if is_ref else 0
content.append(
'({x_max}, {y_max}, {x_min}, {y_min}, {ratio}, {delta}, {x_pecker}, {y_pecker})\n'.format(x_max=x_max_peak, y_max=y_max_peak, x_min=x_min_peak, y_min=y_min_peak, ratio=ratio, delta=delta, x_pecker=x_pecker, y_pecker=y_pecker) # noqa: E501
'({x_max}, {y_max}, {x_min}, {y_min}, {ratio}, {delta}, {x_pecker}, {y_pecker}, {is_ref})\n'.format(x_max=x_max_peak, y_max=y_max_peak, x_min=x_min_peak, y_min=y_min_peak, ratio=ratio, delta=delta, x_pecker=x_pecker, y_pecker=y_pecker, is_ref=is_ref_in_number) # noqa: E501
)

return content
Expand Down Expand Up @@ -256,6 +266,7 @@ def tf_img(self):
# PLOT data
plt.plot(self.core.xs, self.core.ys)
x_max, x_min = self.core.boundary['x']['max'], self.core.boundary['x']['min'] # noqa: E501

xlim_left, xlim_right = [x_min, x_max] if (self.core.is_tga or self.core.is_uv_vis or self.core.is_hplc_uv_vis or self.core.is_xrd or self.core.is_cyclic_volta or self.core.is_sec or self.core.is_cds or self.core.is_aif or self.core.is_emissions or self.core.is_dls_acf or self.core.is_dls_intensity) else [x_max, x_min] # noqa: E501
plt.xlim(xlim_left, xlim_right)
y_max, y_min = np.max(self.core.ys), np.min(self.core.ys)
Expand Down Expand Up @@ -296,7 +307,11 @@ def tf_img(self):
listMaxMinPeaks = self.core.params['list_max_min_peaks']

for peak in listMaxMinPeaks:
max_peak, min_peak = peak['max'], peak['min']
max_peak, min_peak = None, None
if 'max' in peak:
max_peak = peak['max']
if 'min' in peak:
min_peak = peak['min']
x_max_peak, y_max_peak = self.__get_xy_of_peak(max_peak)
x_min_peak, y_min_peak = self.__get_xy_of_peak(min_peak)

Expand Down Expand Up @@ -470,26 +485,26 @@ def tf_img(self):

def __prepare_metadata_info_for_csv(self, csv_writer: csv.DictWriter):
csv_writer.writerow({
'Max x': 'Measurement type',
'Max y': 'Cyclic Voltammetry',
'Ox E(V)': 'Measurement type',
'Red E(V)': 'Cyclic Voltammetry',
})
csv_writer.writerow({
'Max x': 'Measurement type ID',
'Ox E(V)': 'Measurement type ID',
})
csv_writer.writerow({
'Max x': 'Sample ID',
'Ox E(V)': 'Sample ID',
})
csv_writer.writerow({
'Max x': 'Analysis ID',
'Ox E(V)': 'Analysis ID',
})
csv_writer.writerow({
'Max x': 'Dataset ID',
'Ox E(V)': 'Dataset ID',
})
csv_writer.writerow({
'Max x': 'Dataset name',
'Ox E(V)': 'Dataset name',
})
csv_writer.writerow({
'Max x': 'Link to sample',
'Ox E(V)': 'Link to sample',
})
csv_writer.writerow({
})
Expand All @@ -507,8 +522,7 @@ def tf_csv(self):
listMaxMinPeaks = self.core.params['list_max_min_peaks']

with open(tf_csv.name, 'w', newline='', encoding='utf-8') as csvfile:
# fieldnames = ['Max', 'Min', 'I λ0', 'I ratio', 'Pecker']
fieldnames = ['Max x', 'Max y', 'Min x', 'Min y', 'Delta Ep', 'I lambda0', 'I ratio']
fieldnames = ['Ox E(V)', 'Ox I(A)', 'Red E(V)', 'Red I(A)', 'I lambda0(A)', 'I ratio', 'E1/2(V)', 'Delta Ep(mV)']
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)

self.__prepare_metadata_info_for_csv(writer)
Expand All @@ -523,7 +537,13 @@ def tf_csv(self):
y_pecker = self.core.ys[idx]

for peak in listMaxMinPeaks:
max_peak, min_peak = peak['max'], peak['min']
max_peak, min_peak, e12 = None, None, None
if 'max' in peak:
max_peak = peak['max']
if 'min' in peak:
min_peak = peak['min']
if 'e12' in peak:
e12 = peak['e12']
x_max_peak, y_max_peak = self.__get_xy_of_peak(max_peak)
x_min_peak, y_min_peak = self.__get_xy_of_peak(min_peak)

Expand All @@ -534,7 +554,7 @@ def tf_csv(self):
if (x_max_peak == '' or x_min_peak == ''):
delta = ''
else:
delta = abs(x_max_peak - x_min_peak)
delta = abs(x_max_peak - x_min_peak) * 1000

x_pecker = ''
# calculate ratio
Expand All @@ -552,13 +572,14 @@ def tf_csv(self):
y_pecker = ''

writer.writerow({
'Max x': '{x_max}'.format(x_max=x_max_peak),
'Max y': '{y_max}'.format(y_max=y_max_peak),
'Min x': '{x_min}'.format(x_min=x_min_peak),
'Min y': '{y_min}'.format(y_min=y_min_peak),
'Delta Ep': '{y_pecker}'.format(y_pecker=y_pecker),
'I lambda0': '{ratio}'.format(ratio=ratio),
'I ratio': '{delta}'.format(delta=delta)
'Ox E(V)': '{x_max}'.format(x_max=x_max_peak),
'Ox I(A)': '{y_max}'.format(y_max=y_max_peak),
'Red E(V)': '{x_min}'.format(x_min=x_min_peak),
'Red I(A)': '{y_min}'.format(y_min=y_min_peak),
'I lambda0(A)': '{y_pecker}'.format(y_pecker=y_pecker),
'I ratio': '{ratio}'.format(ratio=ratio),
'E1/2(V)': '{e12}'.format(e12=e12),
'Delta Ep(mV)': '{delta}'.format(delta=delta)
})
return tf_csv

Expand Down
27 changes: 26 additions & 1 deletion chem_spectra/lib/converter/jcamp/ni.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from scipy import signal

from chem_spectra.lib.converter.datatable import DatatableModel
from chem_spectra.lib.shared.calc import to_float
from chem_spectra.lib.shared.calc import (to_float, cal_cyclic_volta_shift_prev_offset_at_index)
from chem_spectra.lib.converter.jcamp.data_parse import make_ni_data_ys, make_ni_data_xs


Expand Down Expand Up @@ -54,6 +54,8 @@ def __init__(self, base):
self.x_unit = self.__set_x_unit()
self.ys = self.__read_ys()
self.xs = self.__read_xs(base)
self.__check_cylic_volta_shifted_info()

self.factor = self.__set_factor(base)
self.__set_first_last_xs()
self.clear = self.__refresh_solvent()
Expand Down Expand Up @@ -250,6 +252,14 @@ def __set_label(self):
target['y'] = 'TRANSMITTANCE'
if (self.is_xrd):
target['x'] = '2Theta'

if 'axesUnits' in self.params and self.params['axesUnits'] is not None:
axesUnits = self.params['axesUnits']
xUnit, yUnit = axesUnits['xUnit'], axesUnits['yUnit']
if xUnit != '':
target['x'] = xUnit
if yUnit != '':
target['y'] = yUnit

return target

Expand Down Expand Up @@ -302,6 +312,12 @@ def __set_factor(self, base):

def __set_x_unit(self):
x_unit = None

if 'axesUnits' in self.params and self.params['axesUnits'] is not None:
axesUnits = self.params['axesUnits']
xUnit = axesUnits['xUnit']
if xUnit != '':
return xUnit

try: # jcamp version 6
units = self.dic['UNITS']
Expand Down Expand Up @@ -634,3 +650,12 @@ def __refresh_solvent(self):
def __set_first_last_xs(self):
self.first_x = self.xs[0]
self.last_x = self.xs[-1]

def __check_cylic_volta_shifted_info(self):
if self.is_cyclic_volta == False:
return

cyclicvolta_data = self.params['cyclicvolta']
current_jcamp_idx = self.params['jcamp_idx']
offset = cal_cyclic_volta_shift_prev_offset_at_index(cyclicvolta_data, current_jcamp_idx)
self.xs = np.array([x - offset for x in self.xs])
8 changes: 8 additions & 0 deletions chem_spectra/lib/converter/share.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ def parse_params(params):
'fname': '',
'waveLength': default_wavelength,
'list_max_min_peaks': None,
'cyclicvolta': None,
'jcamp_idx': 0,
'axesUnits': None,
}

select_x = params.get('select_x', None)
Expand All @@ -42,6 +45,8 @@ def parse_params(params):
fname = '.'.join(fname)
waveLength = params.get('waveLength')
waveLength = json.loads(waveLength) if waveLength else default_wavelength
axesUnits = params.get('axesUnits')
axesUnits = json.loads(axesUnits) if axesUnits else None

jcamp_idx = params.get('jcamp_idx', 0)
cyclicvolta = params.get('cyclic_volta')
Expand Down Expand Up @@ -75,6 +80,9 @@ def parse_params(params):
'fname': fname,
'waveLength': waveLength,
'list_max_min_peaks': listMaxMinPeaks,
'cyclicvolta': cyclicvolta,
'jcamp_idx': jcamp_idx,
'axesUnits': axesUnits,
}


Expand Down
57 changes: 57 additions & 0 deletions chem_spectra/lib/shared/calc.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,60 @@ def cal_area_multiplicity(xL, xU, data_xs, data_ys):
lower_value = Decimal(str(ks[iL]))

return float(abs(upper_value - lower_value))

def cal_cyclic_volta_shift_offset(cyclic_data):
if cyclic_data is None:
return []
if isinstance(cyclic_data, dict) == False:
return []
if 'spectraList' not in cyclic_data:
return []

spectra_list = cyclic_data['spectraList']
if isinstance(spectra_list, list) == False:
return []

list_offsets = []

for spectra in spectra_list:
offset = 0.0
analysed_data = spectra['list']
arr_has_ref_value = list(filter(lambda x: x['isRef'] == True, analysed_data))
if len(arr_has_ref_value) > 0:
shift = spectra['shift']
val = shift['val']
ref_value = arr_has_ref_value[0]
e12 = ref_value['e12']
offset = e12 - val
list_offsets.append(offset)

return list_offsets

def cal_cyclic_volta_shift_prev_offset_at_index(cyclic_data, index=0):
if cyclic_data is None:
return 0.0
if isinstance(cyclic_data, dict) == False:
return 0.0
if 'spectraList' not in cyclic_data:
return 0.0

spectra_list = cyclic_data['spectraList']
if isinstance(spectra_list, list) == False:
return 0.0
if len(spectra_list) < index:
return 0.0

offset = 0.0

if index == len(spectra_list):
return 0.0

spectra = spectra_list[index]
analysed_data = spectra['list']
arr_has_ref_value = list(filter(lambda x: ('isRef' in x and x['isRef'] == True), analysed_data))
if len(arr_has_ref_value) > 0:
shift = spectra['shift']
if 'prevValue' in shift:
offset = shift['prevValue']

return offset
Loading

0 comments on commit 17b0f7d

Please sign in to comment.