diff --git a/chem_spectra/controller/transform_api.py b/chem_spectra/controller/transform_api.py index 3df88b9a..fecf0c3c 100644 --- a/chem_spectra/controller/transform_api.py +++ b/chem_spectra/controller/transform_api.py @@ -212,8 +212,10 @@ def combine_images(): list_files.append(file_container) params = extract_params(request) + extras = request.form.get('extras', default=None) + transform_model = TraModel(None, params=params, multiple_files=list_files) - tf_combine = transform_model.tf_combine(list_file_names=params['list_file_names']) + tf_combine = transform_model.tf_combine(list_file_names=params['list_file_names'], extraParams=extras) if (not tf_combine): abort(400) diff --git a/chem_spectra/lib/composer/ms.py b/chem_spectra/lib/composer/ms.py index 7960d8d5..00401eff 100644 --- a/chem_spectra/lib/composer/ms.py +++ b/chem_spectra/lib/composer/ms.py @@ -60,13 +60,22 @@ def __gen_config(self): def __gen_ms_spectra(self): msspcs = [] + ms_tempfile = tempfile.TemporaryFile() for idx, dt in enumerate(self.core.datatables): msspc = [ '##PAGE={}\n'.format(idx + 1), '##NPOINTS={}\n'.format(dt['pts']), TEXT_MS_DATA_TABLE, ] - msspcs = msspcs + msspc + dt['dt'] + my_content = msspc + dt['dt'] + file_content = ''.join(my_content) + ms_tempfile.write(file_content.encode('utf-8')) + + ms_tempfile.seek(0) + lines = ms_tempfile.readlines() + decoded_lines = [line.decode('utf-8').strip() for line in lines] + msspcs = '\n'.join(decoded_lines) + ms_tempfile.close() return msspcs def __compose(self): diff --git a/chem_spectra/lib/composer/ni.py b/chem_spectra/lib/composer/ni.py index 3ed13c7c..59edd683 100644 --- a/chem_spectra/lib/composer/ni.py +++ b/chem_spectra/lib/composer/ni.py @@ -130,6 +130,16 @@ def __gen_header_cyclic_voltammetry(self): '$$ === CHEMSPECTRA CYCLIC VOLTAMMETRY ===\n', ] + def __gen_header_sec(self): + core_dic = self.core.dic + sec_data_key = ['MN', 'MW', 'MP', 'D'] + result = [] + for key in sec_data_key: + dic_value = core_dic.get(key, []) + key_str = f"##{key}={dic_value[0]}\n" if len(dic_value) > 0 else f'##{key}=\n' + result.append(key_str) + return result + def __get_xy_of_peak(self, peak): if peak is None: return '', '' @@ -201,6 +211,8 @@ def __compose(self): meta.extend(self.gen_headers_root()) meta.extend(self.__gen_headers_spectrum_orig()) + if self.core.is_sec: + meta.extend(self.__gen_header_sec()) meta.extend(self.gen_spectrum_orig()) meta.extend(self.__gen_headers_im()) meta.extend(self.__gen_headers_integration()) @@ -285,6 +297,12 @@ def tf_img(self): ] codes, verts = zip(*path_data) marker = mpath.Path(verts, codes) + + circle = mpath.Path.unit_circle() + cirle_verts = np.concatenate([circle.vertices, verts]) + cirle_codes = np.concatenate([circle.codes, codes]) + cut_star_marker = mpath.Path(cirle_verts, cirle_codes) + x_peaks = [] y_peaks = [] if self.core.edit_peaks: @@ -296,6 +314,7 @@ def tf_img(self): x_peckers = [] y_peckers = [] + x_peaks_ref, y_peaks_ref = [], [] if self.core.is_cyclic_volta: x_peaks = [] y_peaks = [] @@ -328,8 +347,13 @@ def tf_img(self): x_peaks.extend([x_max_peak]) y_peaks.extend([y_max_peak]) else: - x_peaks.extend([x_max_peak, x_min_peak]) - y_peaks.extend([y_max_peak, y_min_peak]) + is_ref = peak.get('isRef', False) if 'isRef' in peak else False + if is_ref: + x_peaks_ref.extend([x_max_peak, x_min_peak]) + y_peaks_ref.extend([y_max_peak, y_min_peak]) + else: + x_peaks.extend([x_max_peak, x_min_peak]) + y_peaks.extend([y_max_peak, y_min_peak]) if 'pecker' in peak and peak['pecker'] is not None: pecker = peak['pecker'] @@ -346,6 +370,15 @@ def tf_img(self): peak_label = 'x: {x}\ny: {y}'.format(x=x_float, y=y_float) plt.text(x_pos, y_pos, peak_label) + # display x value of ref peak for cyclic voltammetry + for i in range(len(x_peaks_ref)): + x_pos = x_peaks_ref[i] + y_pos = y_peaks_ref[i] + h * 0.1 + x_float = '{:.2e}'.format(x_pos) + y_float = '{:.2e}'.format(y_peaks_ref[i]) + peak_label = 'x: {x}\ny: {y}'.format(x=x_float, y=y_float) + plt.text(x_pos, y_pos, peak_label) + plt.plot( x_peaks, y_peaks, @@ -364,6 +397,15 @@ def tf_img(self): markersize=50, ) + plt.plot( + x_peaks_ref, + y_peaks_ref, + 'r', + ls='', + marker=cut_star_marker, + markersize=50, + ) + # ----- PLOT integration ----- refShift, refArea = self.refShift, self.refArea itg_h = y_max + h * 0.1 @@ -479,6 +521,9 @@ def tf_img(self): plt.ylabel("Y ({})".format(self.core.label['y']), fontsize=18) plt.locator_params(nbins=self.__plt_nbins()) plt.grid(False) + + self.__generate_info_box(plt) + # Save tf_img = tempfile.NamedTemporaryFile(suffix='.png') plt.savefig(tf_img, format='png') @@ -487,6 +532,25 @@ def tf_img(self): plt.cla() return tf_img + + def __generate_info_box(self, plotlib): + if not self.core.is_sec: + return + core_dic = self.core.dic + sec_data_key = ['MN', 'MW', 'MP', 'D'] + result = [] + for key in sec_data_key: + dic_value = core_dic.get(key, []) + key_str = f"{key}={dic_value[0]}" if len(dic_value) > 0 else None + if key_str is not None: + result.append(key_str) + + info_str = '\n'.join(result) + props = dict(boxstyle='round', facecolor='wheat', alpha=0.5) + ax = plotlib.gca() + ax.text(0.05, 0.95, info_str, fontsize=14, verticalalignment='top', bbox=props, transform=ax.transAxes) + + def __prepare_metadata_info_for_csv(self, csv_writer: csv.DictWriter): csv_writer.writerow({ 'Anodic E(V)': 'Measurement type', diff --git a/chem_spectra/lib/converter/share.py b/chem_spectra/lib/converter/share.py index ac0de974..7766d420 100644 --- a/chem_spectra/lib/converter/share.py +++ b/chem_spectra/lib/converter/share.py @@ -33,23 +33,35 @@ def parse_params(params): peaks_str = params.get('peaks_str', None) delta = 0.0 mass = params.get('mass', 0) + mass = mass if mass else 0 scan = params.get('scan', None) thres = params.get('thres', None) clear = params.get('clear', False) + clear = clear if clear else False integration = params.get('integration') integration = json.loads(integration) if integration else default_itg multiplicity = params.get('multiplicity') multiplicity = json.loads(multiplicity) if multiplicity else default_mpy ext = params.get('ext', '') + ext = ext if ext else '' fname = params.get('fname', '').split('.') fname = fname[:-2] if (len(fname) > 2 and (fname[-2] in ['edit', 'peak'])) else fname[:-1] 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) + jcamp_idx = jcamp_idx if jcamp_idx else 0 + axesUnitsJson = params.get('axesUnits') + axesUnitsDic = json.loads(axesUnitsJson) if axesUnitsJson else None + axesUnits = None + if axesUnitsDic != None and 'axes' in axesUnitsDic: + axes = axesUnitsDic.get('axes', [{'xUnit': '', 'yUnit': ''}]) + try: + axesUnits = axes[jcamp_idx] + except: + pass + cyclicvolta = params.get('cyclic_volta') cyclicvolta = json.loads(cyclicvolta) if cyclicvolta else None listMaxMinPeaks = None diff --git a/chem_spectra/lib/shared/calc.py b/chem_spectra/lib/shared/calc.py index c4494b92..0558ab92 100644 --- a/chem_spectra/lib/shared/calc.py +++ b/chem_spectra/lib/shared/calc.py @@ -149,11 +149,9 @@ def cal_cyclic_volta_shift_prev_offset_at_index(cyclic_data, index=0): 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'] + hasRefPeak = spectra.get('hasRefPeak', False) == True + shift = spectra['shift'] + if 'prevValue' in shift: + offset = shift['prevValue'] if hasRefPeak else -shift['prevValue'] return offset diff --git a/chem_spectra/model/transformer.py b/chem_spectra/model/transformer.py index b42c926c..ea2211e1 100644 --- a/chem_spectra/model/transformer.py +++ b/chem_spectra/model/transformer.py @@ -19,6 +19,8 @@ from chem_spectra.lib.composer.base import BaseComposer # noqa: F401 from chem_spectra.lib.converter.nmrium.base import NMRiumDataConverter import matplotlib.pyplot as plt # noqa: E402 +import matplotlib.path as mpath # noqa: E402 +import numpy as np # noqa: E402 from chem_spectra.model.concern.property import decorate_sim_property @@ -268,13 +270,45 @@ def tf_nmrium(self): nicp = NIComposer(converter) tf_jcamp = nicp.tf_jcamp() return tf_jcamp - - def tf_combine(self, list_file_names=None): + + def __get_cyclic_volta_ref_peaks(self, curve_idx, extraParams): + x_peaks, y_peaks = [], [] + try: + extras_dict = json.loads(extraParams) if extraParams else None + cyclic_volta_str = extras_dict['cyclicvolta'] if extras_dict else None + cyclic_volta = json.loads(cyclic_volta_str) if cyclic_volta_str else None + spectra_list = cyclic_volta['spectraList'] if cyclic_volta else None + spectra_extra = spectra_list[curve_idx] if spectra_list and curve_idx < len(spectra_list) else None + list_peaks = spectra_extra['list'] if spectra_extra else [] + x_peaks, y_peaks = [], [] + for peak in list_peaks: + min_peak, max_peak, isRef = peak['min'], peak['max'], peak['isRef'] + if isRef == True: + x_peaks.extend([min_peak['x'], max_peak['x']]) + y_peaks.extend([min_peak['y'], max_peak['y']]) + except: + pass + + return x_peaks, y_peaks + + def tf_combine(self, list_file_names=None, extraParams=None): if not self.multiple_files: return False + + path_data = [ + (mpath.Path.MOVETO, (0, 5)), + (mpath.Path.LINETO, (0, 20)), + ] + codes, verts = zip(*path_data) + + circle = mpath.Path.unit_circle() + cirle_verts = np.concatenate([circle.vertices, verts]) + cirle_codes = np.concatenate([circle.codes, codes]) + cut_star_marker = mpath.Path(cirle_verts, cirle_codes) plt.rcParams['figure.figsize'] = [16, 9] plt.rcParams['font.size'] = 14 + plt.rcParams['legend.loc'] = 'upper left' curve_idx = self.params.get('jcamp_idx', 0) xlabel, ylabel = '', '' @@ -315,6 +349,17 @@ def tf_combine(self, list_file_names=None): core_label_x = nicp.core.label['x'] core_label_y = nicp.core.label['y'] if nicp.core.is_cyclic_volta: + x_peaks, y_peaks = self.__get_cyclic_volta_ref_peaks(curve_idx, extraParams) + + plt.plot( + x_peaks, + y_peaks, + 'r', + ls='', + marker=cut_star_marker, + markersize=50, + ) + if core_label_x not in dic_x_label: xlabel_set.append(core_label_x) dic_x_label[core_label_x] = 1 diff --git a/setup.py b/setup.py index 7bc7e34e..fc5db5fc 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ setup( name='chem-spectra-app', - version='1.1.2', + version='1.2.0', packages=find_packages(), include_package_data=True, zip_safe=False, diff --git a/tests/fixtures/source/sec/SEC-ExFile.zip b/tests/fixtures/source/sec/SEC-ExFile.zip new file mode 100644 index 00000000..cabf0d47 Binary files /dev/null and b/tests/fixtures/source/sec/SEC-ExFile.zip differ diff --git a/tests/lib/composer/test_ni_composer.py b/tests/lib/composer/test_ni_composer.py index 8f6eeea0..e55fb4df 100644 --- a/tests/lib/composer/test_ni_composer.py +++ b/tests/lib/composer/test_ni_composer.py @@ -1,15 +1,19 @@ import json import pytest import numpy as np +import tempfile +import zipfile from chem_spectra.lib.converter.jcamp.base import JcampBaseConverter from chem_spectra.lib.converter.jcamp.ni import JcampNIConverter from chem_spectra.lib.composer.ni import NIComposer from chem_spectra.controller.helper.file_container import FileContainer +from chem_spectra.lib.converter.bagit.base import BagItBaseConverter as BagItConveter source_nmr = './tests/fixtures/source/1H.dx' source_nmr_edit = './tests/fixtures/source/1H.edit.jdx' source_ir = './tests/fixtures/source/IR.dx' source_dir_molfile = './tests/fixtures/source/molfile/c60h57fn4.mol' +source_sec = './tests/fixtures/source/sec/SEC-ExFile.zip' @pytest.fixture def data_schema(): @@ -37,6 +41,10 @@ def molfile_data(): molfile_str = molfile.read() return molfile_str +@pytest.fixture +def bagit_file_sec(): + return source_sec + def test_init_ni_composer_failed(): with pytest.raises(Exception) as error: _ = NIComposer(None) @@ -250,3 +258,19 @@ def test_ni_composer_generate_nmrium_with_molfile(jcamp_file_1h, molfile_data): assert 'id' in molecule_data.keys() assert molecule_data['label'] == 'P1' assert molecule_data['molfile'] == molfile_data + +def test_ni_composer_generate_jcamp(bagit_file_sec): + with tempfile.TemporaryDirectory() as td: + with zipfile.ZipFile(bagit_file_sec, 'r') as z: + z.extractall(td) + + converter = BagItConveter(td) + for jcamp_file in converter.data: + base_converter = JcampBaseConverter(jcamp_file.name) + ni_converter = JcampNIConverter(base=base_converter) + ni_composer = NIComposer(core=ni_converter) + headers = ni_composer._NIComposer__gen_header_sec() + assert headers in [ + ['##MN=1.287E+3\n', '##MW=1.465E+3\n', '##MP=1.345E+3\n', '##D=1.139E+0\n'], + ['##MN=\n', '##MW=\n', '##MP=\n', '##D=\n'] + ] diff --git a/tests/lib/converter/test_share.py b/tests/lib/converter/test_share.py index b2adf166..cd19ba11 100644 --- a/tests/lib/converter/test_share.py +++ b/tests/lib/converter/test_share.py @@ -1,9 +1,226 @@ import numpy as np +import pytest from chem_spectra.lib.converter.share import ( - parse_solvent, reduce_pts + parse_params, parse_solvent, reduce_pts ) +@pytest.fixture +def expected_default_params(): + default_itg = {'stack': [], 'refArea': 1, 'refFactor': 1, 'shift': 0} + default_mpy = {'stack': [], 'smExtext': False, 'shift': 0} + default_wavelength = {'name': 'CuKalpha', 'value': 0.15406, 'label': 'Cu K-alpha', 'unit': 'nm'} + return { + 'select_x': None, + 'ref_name': None, + 'ref_value': None, + 'peaks_str': None, + 'delta': 0.0, + 'mass': 0, + 'scan': None, + 'thres': None, + 'clear': False, + 'integration': default_itg, + 'multiplicity': default_mpy, + 'fname': '', + 'waveLength': default_wavelength, + 'list_max_min_peaks': None, + 'cyclicvolta': None, + 'jcamp_idx': 0, + 'axesUnits': None, + 'detector': None, + } + +def test_parse_params_without_params(expected_default_params): + parsed_data = parse_params(None) + assert expected_default_params == parsed_data + +def test_parse_params_select_x(): + params = {'select_x': None} + parsed_data = parse_params(params) + assert parsed_data['select_x'] is None + + params = {'select_x': 0.0} + parsed_data = parse_params(params) + assert parsed_data['select_x'] == 0.0 + +def test_parse_params_ref_name(): + params = {'ref_name': None} + parsed_data = parse_params(params) + assert parsed_data['ref_name'] is None + + params = {'ref_name': 'just a text'} + parsed_data = parse_params(params) + assert parsed_data['ref_name'] == 'just a text' + +def test_parse_params_ref_value(): + params = {'ref_value': None} + parsed_data = parse_params(params) + assert parsed_data['ref_value'] is None + + params = {'ref_value': 0.0} + parsed_data = parse_params(params) + assert parsed_data['ref_value'] == 0.0 + +def test_parse_params_peaks_str(): + params = {'peaks_str': None} + parsed_data = parse_params(params) + assert parsed_data['peaks_str'] is None + + params = {'peaks_str': 'just a text'} + parsed_data = parse_params(params) + assert parsed_data['peaks_str'] == 'just a text' + +def test_parse_params_delta(): + params = {'select_x': None} + parsed_data = parse_params(params) + assert parsed_data['delta'] == 0.0 + + params = {'select_x': 0.0} + parsed_data = parse_params(params) + assert parsed_data['delta'] == 0.0 + + params = {'select_x': 1.0, 'ref_name': '- - -'} + parsed_data = parse_params(params) + assert parsed_data['delta'] == 0.0 + + params = {'select_x': 1.0, 'ref_name': 'just a text'} + parsed_data = parse_params(params) + assert parsed_data['delta'] == 0.0 + + params = {'select_x': 1.0, 'ref_name': 'just a text', 'ref_value': 1.5} + parsed_data = parse_params(params) + assert parsed_data['delta'] == 0.5 + +def test_parse_params_mass(): + params = {'mass': None} + parsed_data = parse_params(params) + assert parsed_data['mass'] == 0 + + params = {'mass': 1.5} + parsed_data = parse_params(params) + assert parsed_data['mass'] == 1.5 + +def test_parse_params_scan(): + params = {'scan': None} + parsed_data = parse_params(params) + assert parsed_data['scan'] is None + + params = {'scan': 2} + parsed_data = parse_params(params) + assert parsed_data['scan'] == 2 + +def test_parse_params_thres(): + params = {'thres': None} + parsed_data = parse_params(params) + assert parsed_data['thres'] is None + + params = {'thres': 2} + parsed_data = parse_params(params) + assert parsed_data['thres'] == 2 + +def test_parse_params_clear(): + params = {'clear': None} + parsed_data = parse_params(params) + assert parsed_data['clear'] == False + + params = {'clear': False} + parsed_data = parse_params(params) + assert parsed_data['clear'] == False + + params = {'clear': True} + parsed_data = parse_params(params) + assert parsed_data['clear'] == True + +def test_parse_params_ext(): + params = {'ext': None} + parsed_data = parse_params(params) + assert parsed_data['ext'] == '' + + params = {'ext': '.jdx'} + parsed_data = parse_params(params) + assert parsed_data['ext'] == '.jdx' + +def test_parse_params_fname(): + params = {'fname': 'just a normal text'} + parsed_data = parse_params(params) + assert parsed_data['fname'] == '' + + params = {'fname': 'original.jdx'} + parsed_data = parse_params(params) + assert parsed_data['fname'] == 'original' + + params = {'fname': 'original.changed.jdx'} + parsed_data = parse_params(params) + assert parsed_data['fname'] == 'original.changed' + + params = {'fname': 'original.peak.jdx'} + parsed_data = parse_params(params) + assert parsed_data['fname'] == 'original' + + params = {'fname': 'original.edit.jdx'} + parsed_data = parse_params(params) + assert parsed_data['fname'] == 'original' + +def test_parse_params_integration(): + #TODO: need to be updated + assert 1==1 + +def test_parse_params_multiplicity(): + #TODO: need to be updated + assert 1==1 + +def test_parse_params_waveLength(): + #TODO: need to be updated + assert 1==1 + +def test_parse_params_list_max_min_peaks(): + #TODO: need to be updated + assert 1==1 + +def test_parse_params_cyclic_volta(): + #TODO: need to be updated + assert 1==1 + +def test_parse_params_jcamp_idx(): + params = {'jcamp_idx': None} + parsed_data = parse_params(params) + assert parsed_data['jcamp_idx'] == 0 + + params = {'jcamp_idx': 1} + parsed_data = parse_params(params) + assert parsed_data['jcamp_idx'] == 1 + +def test_parse_params_axesUnits(): + params = {'axesUnits': None} + parsed_data = parse_params(params) + assert parsed_data['axesUnits'] is None + + params = {'axesUnits': '{"axes": null}'} + parsed_data = parse_params(params) + assert parsed_data['axesUnits'] is None + + params = {'axesUnits': '{"axes": []}'} + parsed_data = parse_params(params) + assert parsed_data['axesUnits'] is None + + params = {'jcamp_idx': 1, 'axesUnits': '{"axes": [{"xUnit": "label x", "yUnit": "label y"}]}'} + parsed_data = parse_params(params) + assert parsed_data['axesUnits'] is None + + params = {'axesUnits': '{"axes": [{"xUnit": "label x", "yUnit": "label y"}]}'} + parsed_data = parse_params(params) + assert parsed_data['axesUnits'] == {"xUnit": "label x", "yUnit": "label y"} + +def test_parse_params_data_type_mapping(): + #TODO: need to be updated + assert 1==1 + +def test_parse_params_detector(): + #TODO: need to be updated + assert 1==1 + def test_parse_solvent(): + #TODO: need to be updated assert 1==1 def test_reduce_pts_when_does_not_have_any_x(): diff --git a/tests/lib/shared/test_calc.py b/tests/lib/shared/test_calc.py index 0aa33da9..0c587145 100644 --- a/tests/lib/shared/test_calc.py +++ b/tests/lib/shared/test_calc.py @@ -105,10 +105,20 @@ def test_cal_area_multiplicity(): @pytest.fixture def cyclic_data(): - cyclic_data = {'spectraList':[{'list':[{'min':{'x':-1.48904,'y':-1.10686e-05},'max':{'x':1.80895,'y':9.51171e-06},'isRef':True,'e12':0.15995500000000007,'pecker':{'x':-0.129871,'y':7.78418e-07}}],'selectedIdx':0,'isWorkMaxPeak':True,'jcampIdx':0,'shift':{'ref':None,'val':0,'prevValue': 2.5,}},{'list':[{'min':{'x':-1.48904,'y':-3.3747399999999995e-05},'max':{'x':0.929483,'y':0.00023741},'isRef':True,'e12':-0.27977849999999993}],'selectedIdx':0,'isWorkMaxPeak':True,'jcampIdx':1,'shift':{'ref':None,'val':5}},{'list':[{'min':{'x':0.45977,'y':-0.000226347},'max':{'x':1.00943,'y':0.000371349},'isRef':False,'e12':0.7346}],'selectedIdx':0,'isWorkMaxPeak':True,'jcampIdx':2,'shift':{'ref':None,'val':0}}]} + cyclic_data = {'spectraList':[{'list':[{'min':{'x':-1.48904,'y':-1.10686e-05},'max':{'x':1.80895,'y':9.51171e-06},'isRef':True,'e12':0.15995500000000007,'pecker':{'x':-0.129871,'y':7.78418e-07}}],'selectedIdx':0,'isWorkMaxPeak':True,'jcampIdx':0,'shift':{'ref':None,'val':0,'prevValue': 2.5,}, 'hasRefPeak':True},{'list':[{'min':{'x':-1.48904,'y':-3.3747399999999995e-05},'max':{'x':0.929483,'y':0.00023741},'isRef':True,'e12':-0.27977849999999993}],'selectedIdx':0,'isWorkMaxPeak':True,'jcampIdx':1,'shift':{'ref':None,'val':5}},{'list':[{'min':{'x':0.45977,'y':-0.000226347},'max':{'x':1.00943,'y':0.000371349},'isRef':False,'e12':0.7346}],'selectedIdx':0,'isWorkMaxPeak':True,'jcampIdx':2,'shift':{'ref':None,'val':0}}]} + return cyclic_data + +@pytest.fixture +def cyclic_data_no_ref_value(): + cyclic_data = {'spectraList':[{'list':[{'min':{'x':-1.48904,'y':-1.10686e-05},'max':{'x':1.80895,'y':9.51171e-06},'isRef':True,'e12':0.15995500000000007,'pecker':{'x':-0.129871,'y':7.78418e-07}}],'selectedIdx':0,'isWorkMaxPeak':True,'jcampIdx':0,'shift':{'ref':None,'val':0,'prevValue': 2.5,}, 'hasRefPeak':False},{'list':[{'min':{'x':-1.48904,'y':-3.3747399999999995e-05},'max':{'x':0.929483,'y':0.00023741},'isRef':True,'e12':-0.27977849999999993}],'selectedIdx':0,'isWorkMaxPeak':True,'jcampIdx':1,'shift':{'ref':None,'val':5}},{'list':[{'min':{'x':0.45977,'y':-0.000226347},'max':{'x':1.00943,'y':0.000371349},'isRef':False,'e12':0.7346}],'selectedIdx':0,'isWorkMaxPeak':True,'jcampIdx':2,'shift':{'ref':None,'val':0}}]} return cyclic_data def test_cal_cyclic_volta_shift_prev_offset_at_index(cyclic_data): expected_offset = 2.5 offset = cal_cyclic_volta_shift_prev_offset_at_index(cyclic_data, 0) assert offset == expected_offset + +def test_cal_cyclic_volta_shift_prev_offset_at_index_no_ref_value(cyclic_data_no_ref_value): + expected_offset = -2.5 + offset = cal_cyclic_volta_shift_prev_offset_at_index(cyclic_data_no_ref_value, 0) + assert offset == expected_offset