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.
Files changed (63) hide show
  1. chromaquant/__init__.py +9 -2
  2. chromaquant/data/__init__.py +14 -0
  3. chromaquant/data/breakdown.py +430 -0
  4. chromaquant/data/dataset.py +195 -0
  5. chromaquant/data/table.py +412 -0
  6. chromaquant/data/value.py +215 -0
  7. chromaquant/formula/__init__.py +13 -0
  8. chromaquant/formula/base_formulas.py +168 -0
  9. chromaquant/formula/formula.py +507 -0
  10. chromaquant/import_local_packages.py +55 -0
  11. chromaquant/logging_and_handling.py +76 -0
  12. chromaquant/match/__init__.py +13 -0
  13. chromaquant/match/match.py +184 -0
  14. chromaquant/match/match_config.py +296 -0
  15. chromaquant/match/match_tools.py +154 -0
  16. chromaquant/{Quant → results}/__init__.py +2 -2
  17. chromaquant/results/reporting_tools.py +190 -0
  18. chromaquant/results/results.py +250 -0
  19. chromaquant/utils/__init__.py +14 -0
  20. chromaquant/utils/categories.py +127 -0
  21. chromaquant/utils/chemical_formulas.py +104 -0
  22. chromaquant/utils/dataframe_processing.py +222 -0
  23. chromaquant/utils/file_tools.py +100 -0
  24. chromaquant/utils/formula_tools.py +119 -0
  25. chromaquant-0.5.0.dist-info/METADATA +61 -0
  26. chromaquant-0.5.0.dist-info/RECORD +29 -0
  27. {chromaquant-0.4.0.dist-info → chromaquant-0.5.0.dist-info}/WHEEL +1 -1
  28. {chromaquant-0.4.0.dist-info → chromaquant-0.5.0.dist-info}/licenses/LICENSE.txt +1 -1
  29. chromaquant-0.5.0.dist-info/licenses/LICENSES_bundled.txt +251 -0
  30. chromaquant/Handle/__init__.py +0 -13
  31. chromaquant/Handle/fileChecks.py +0 -172
  32. chromaquant/Handle/handleDirectories.py +0 -89
  33. chromaquant/Hydro/__init__.py +0 -12
  34. chromaquant/Hydro/hydroMain.py +0 -496
  35. chromaquant/Manual/HydroUI.py +0 -418
  36. chromaquant/Manual/QuantUPP.py +0 -373
  37. chromaquant/Manual/Quantification.py +0 -1305
  38. chromaquant/Manual/__init__.py +0 -10
  39. chromaquant/Manual/duplicateMatch.py +0 -211
  40. chromaquant/Manual/fpm_match.py +0 -798
  41. chromaquant/Manual/label-type.py +0 -179
  42. chromaquant/Match/AutoFpmMatch.py +0 -1133
  43. chromaquant/Match/MatchSub/__init__.py +0 -13
  44. chromaquant/Match/MatchSub/matchTools.py +0 -282
  45. chromaquant/Match/MatchSub/peakTools.py +0 -259
  46. chromaquant/Match/__init__.py +0 -13
  47. chromaquant/Match/matchMain.py +0 -233
  48. chromaquant/Quant/AutoQuantification.py +0 -1329
  49. chromaquant/Quant/QuantSub/__init__.py +0 -15
  50. chromaquant/Quant/QuantSub/gasFID.py +0 -241
  51. chromaquant/Quant/QuantSub/gasTCD.py +0 -425
  52. chromaquant/Quant/QuantSub/liquidFID.py +0 -310
  53. chromaquant/Quant/QuantSub/parseTools.py +0 -162
  54. chromaquant/Quant/quantMain.py +0 -417
  55. chromaquant/UAPP/__init__.py +0 -12
  56. chromaquant/UAPP/uappMain.py +0 -427
  57. chromaquant/__main__.py +0 -526
  58. chromaquant/oldui.py +0 -492
  59. chromaquant/properties.json +0 -4
  60. chromaquant-0.4.0.dist-info/METADATA +0 -189
  61. chromaquant-0.4.0.dist-info/RECORD +0 -38
  62. chromaquant-0.4.0.dist-info/entry_points.txt +0 -2
  63. chromaquant-0.4.0.dist-info/licenses/LICENSES_bundled.txt +0 -1035
@@ -1,418 +0,0 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
- """
4
-
5
- COPYRIGHT STATEMENT:
6
-
7
- ChromaQuant – A quantification software for complex gas chromatographic data
8
-
9
- Copyright (c) 2024, by Julia Hancock
10
- Affiliation: Dr. Julie Elaine Rorrer
11
- URL: https://www.rorrerlab.com/
12
-
13
- License: BSD 3-Clause License
14
-
15
- ---
16
-
17
- SCRIPT WHICH RUNS A DESKTOP APPLICATION FOR FUTURE USE IN SPECTRA VISUALIZATION
18
-
19
- Julia Hancock
20
- Started 11/21/2023
21
-
22
- """
23
-
24
- """ PACKAGES """
25
- import sys
26
- import pandas as pd
27
- #Dash and plotly – dcc = "Dash Core Components", px = "Plotly express" with visualization tools
28
- from dash import Dash, html, dash_table, dcc, callback, Output, Input
29
- from plotly.subplots import make_subplots
30
- import plotly.express as px
31
- import plotly.graph_objects as go
32
- from pubchempy import Compound, get_compounds
33
- from rdkit import Chem
34
- from rdkit.Chem.Draw import MolsToGridImage, MolDrawing, rdMolDraw2D
35
- import base64
36
- from io import BytesIO
37
- import os
38
- from molmass import Formula
39
-
40
- """ PARAMETERS """
41
- #Write sample name
42
- sname = "MBPR048_01"
43
-
44
- #Write whether sample is liquid ("L") or gas ("G")
45
- stype = "G"
46
-
47
- #Write whether there exists a file containing matched FID and MS peaks (True/False)
48
- smatchtf = False
49
-
50
- """ DIRECTORIES """
51
- #Current script directory
52
- script_directory = os.path.dirname(__file__)
53
-
54
- """ DATA IMPORTS """
55
- #Define file names using user parameters
56
- if stype == "G":
57
- fn_FID_SPEC = sname+"_GS2_FID_SPEC.csv"
58
- fn_MS_SPEC = sname+"_GS1_MS_SPEC.csv"
59
-
60
- if smatchtf == True:
61
- fn_FPM = sname+"_GS2_FIDpMS.csv"
62
- else:
63
- fn_FPM = "default_FIDpMS.csv"
64
-
65
- if stype == "L":
66
- fn_FID_SPEC = sname+"_LQ1_FID_SPEC.csv"
67
- fn_MS_SPEC = sname+"_LQ1_MS_SPEC.csv"
68
-
69
- if smatchtf == True:
70
- fn_FPM = sname+"_LQ1_FIDpMS.csv"
71
- else:
72
- fn_FPM = "default_FIDpMS.csv"
73
-
74
- #Define directories for desired dataframes
75
- DIR_LQ_FIDpMS_PeaksLB = "/Users/connards/Desktop/University/Rorrer Lab/Scripts/Quantification/data/"+sname+"/"+fn_FPM
76
- DIR_LQ_FID_SPEC = "/Users/connards/Desktop/University/Rorrer Lab/Scripts/Quantification/data/"+sname+"/"+fn_FID_SPEC
77
- DIR_LQ_MS_SPEC = "/Users/connards/Desktop/University/Rorrer Lab/Scripts/Quantification/data/"+sname+"/"+fn_MS_SPEC
78
- #Column names to add to imported spectral data
79
- col_names_SPEC = ['RT','Signal']
80
-
81
- #Read matched peak data between FID and MS
82
- LQ_FIDpMS_PeaksLB = pd.read_csv(DIR_LQ_FIDpMS_PeaksLB)
83
-
84
- #Read spectra data for FID
85
- LQ_FID_SPEC = pd.read_csv(DIR_LQ_FID_SPEC, names=col_names_SPEC, header=None)
86
- #Add column labeling FID data
87
- LQ_FID_SPEC['SignalType'] = 'FID'
88
-
89
- #Read spectra data for MS
90
- LQ_MS_SPEC = pd.read_csv(DIR_LQ_MS_SPEC, names=col_names_SPEC, header=None)
91
- #Add column labeling MS data
92
- LQ_MS_SPEC['SignalType'] = 'MS'
93
-
94
- #Get dictionary of checklist entries to SignalType entries
95
- dictSPEC = {'FID':'FID','MS':'MS'}
96
- #Get list of checklist keys
97
- dictSPEC_keys = list(dictSPEC.keys())
98
-
99
- #Append MS dataframe to FID dataframe
100
- LQ_FIDpMS_SPEC = pd.concat([LQ_FID_SPEC,LQ_MS_SPEC],ignore_index=True)
101
-
102
- """ ACCESSING PUBCHEM """
103
-
104
- #If there exists FIDpMS files, proceed
105
- if smatchtf == True:
106
- #Create a copy of the PeaksLB dataframe called PeaksLB_SMILES
107
- PeaksLB_Smiles = LQ_FIDpMS_PeaksLB.copy()
108
- #Read the existing smilePairs.csv
109
- smilePairs = pd.read_csv(os.path.join(script_directory,'resources','smilePairs.csv'))
110
- #Add a column to the PeaksLB dataframe with the smiles of matched compounds, ignoring 'No match'
111
- PeaksLB_Smiles['isoSMILES'] = ''
112
- #List of indices with compound names
113
- compindex = []
114
- #Set up temporary smile string for use in for loop
115
- tempSmile = smilePairs.loc[smilePairs['Compound Name']==PeaksLB_Smiles.at[4,'Compound Name']]
116
-
117
- #Loop through all rows in PeaksLB_Smiles
118
- print('[MAIN] Assessing compound structures through SMILES...')
119
- for i, row in PeaksLB_Smiles.iterrows():
120
-
121
- #Only add peaks with matched compounds
122
- if PeaksLB_Smiles.at[i,'Compound Name'] != 'No match' and PeaksLB_Smiles.at[i,'Compound Name'] != 'No Match':
123
-
124
- #Try/except to catch error in accessing dataframe
125
- try:
126
- #If the compound name can be found in the compound-SMILES .csv file, add to dataframe
127
- if any(smilePairs['Compound Name']==row['Compound Name']):
128
- tempSmile = smilePairs.loc[smilePairs['Compound Name']==row['Compound Name'],'isoSMILES']
129
- #Choose the first SMILES in the series
130
- tempSmile = tempSmile[tempSmile.index[0]]
131
- #Save SMILES to PeaksLB_Smiles dataframe
132
- PeaksLB_Smiles.at[i,'isoSMILES'] = tempSmile
133
- #If the compound isn't in the list, get SMILES from PubCHEM
134
- else:
135
- PeaksLB_Smiles.at[i,'isoSMILES'] = get_compounds(PeaksLB_Smiles.at[i,'Compound Name'],\
136
- 'name')[0].isomeric_smiles
137
- print('[MAIN] Downloading SMILES for {0}...'.format(PeaksLB_Smiles.at[i,'Compound Name']))
138
- compindex.append(i)
139
-
140
- except:
141
- print('[ERROR] An error occurred in accessing SMILES for {0}'.format(row['Compound Name']))
142
-
143
- else:
144
- pass
145
-
146
- #If any compounds were previously unlabelled, save the compound name and SMILES pairs as a .csv
147
- smilePairsOut = pd.concat([smilePairs,PeaksLB_Smiles.loc[compindex,['Compound Name','isoSMILES']]],ignore_index=True)
148
- if smilePairsOut.size > smilePairs.size:
149
- print("[MAIN] Saving updated compound-SMILES pairs...")
150
- smilePairsOut.to_csv(os.path.join(script_directory,'resources','smilePairs.csv'),index=False)
151
- else:
152
- pass
153
-
154
-
155
- """ LABELLING SPECTRA """
156
- print("[MAIN] Labelling the FID spectrum using the peak-compound dataframe...")
157
- #Find only the PeaksLB_Smiles rows which have compound matches
158
- PeaksLB_Smiles = PeaksLB_Smiles[~PeaksLB_Smiles['Compound Name'].isin(['No Match','No match'])]
159
- #For every entry in this new PeaksLB_Smiles dataframe, find the nearest FID Spectra RT to the labelled peak RT's
160
- for i, row in PeaksLB_Smiles.iterrows():
161
- #Find the closest row index in LQ_FID_SPEC
162
- df_closestIN = LQ_FID_SPEC.iloc[(LQ_FID_SPEC['RT']-row['FID RT']).abs().argsort()[:1]].index[0]
163
- #Add four columns to the spectral data: compound name, formula, match factor, and isosmiles
164
- LQ_FID_SPEC.at[df_closestIN,'Compound Name'] = row['Compound Name']
165
- LQ_FID_SPEC.at[df_closestIN,'Formula'] = row['Formula']
166
- LQ_FID_SPEC.at[df_closestIN,'Match Factor'] = row['Match Factor']
167
- LQ_FID_SPEC.at[df_closestIN,'isoSMILES'] = row['isoSMILES']
168
- #Find the molecular weight of the given compound and assign to a new column in the spectral data
169
- LQ_FID_SPEC.at[df_closestIN,'MW'] = Formula(row['Formula']).mass
170
-
171
- #Otherwise, pass
172
- else:
173
- pass
174
-
175
- """ WEB APPLICATION """
176
-
177
- #Initialize the application with the Dash constructor
178
- app = Dash(__name__)
179
-
180
- #App layout
181
- app.layout = html.Div([
182
-
183
- #First row
184
- html.Div(children=[
185
- #First row first column
186
- html.Div(children=[
187
- #Scatter plot inside of a dcc interactive figure module
188
- dcc.Graph(id='controls_and_graph')],\
189
- style={'display':'inline-block','vertical-align':'top','margin-left': 5,'margin-top': '3vw','width':'70%'}),
190
-
191
- #First row second column
192
- html.Div(children=[
193
- #Checklist for selecting viewed data
194
- html.Div(children=[dcc.Checklist(dictSPEC_keys,[dictSPEC_keys[0]],id='controls_and_checklist')],style={'margin-top':100},className='row'),
195
- #Axis limit entries
196
- #x limit lower
197
- html.Div(children=[dcc.Input(id='xlim_l',type='number',placeholder='Lower x-limit')],style={'margin-top':20},className='row'),
198
- #x limit upper
199
- html.Div(children=[dcc.Input(id='xlim_u',type='number',placeholder='Upper x-limit')],className='row'),
200
- #y limit lower
201
- html.Div(children=[dcc.Input(id='ylim_l',type='number',placeholder='Lower y-limit')],className='row'),
202
- #y limit upper
203
- html.Div(children=[dcc.Input(id='ylim_u',type='number',placeholder='Upper y-limit')],className='row'),
204
- #y2 limit lower
205
- html.Div(children=[dcc.Input(id='y2lim_l',type='number',placeholder='Secondary Lower y-limit')],className='row'),
206
- #y2 limit upper
207
- html.Div(children=[dcc.Input(id='y2lim_u',type='number',placeholder='Secondary Upper y-limit')],className='row')],
208
-
209
- #Set display style to inline-block
210
- style={'display':'inline-block','vertical-align':'middle','margin-left': 0,'margin-top': '3vw','width':'25%'})],
211
- className='row'),
212
-
213
- #Second row
214
- html.Div(children=[
215
- #Compound structure image
216
- html.Img(id='structure-image')],className='row')
217
-
218
- ])
219
-
220
- """ CALLBACK CONTROLS """
221
- #FID and MS spectra selection and axis limits callback
222
- @callback(
223
- Output(component_id='controls_and_graph',component_property='figure'),
224
- Input(component_id='controls_and_checklist',component_property='value'),
225
- Input('xlim_l','value'),
226
- Input('xlim_u','value'),
227
- Input('ylim_l','value'),
228
- Input('ylim_u','value'),
229
- Input('y2lim_l','value'),
230
- Input('y2lim_u','value')
231
- )
232
- #Callback graph updating function
233
- def update_graph(fig_chosen,xlim_lval,xlim_uval,ylim_lval,ylim_uval,y2lim_lval,y2lim_uval):
234
- #Format axis limits into a list
235
- axLim = [xlim_lval,xlim_uval,ylim_lval,ylim_uval,y2lim_lval,y2lim_uval]
236
- #Dictionary of colors for specific use for MS and FID spectra
237
- colorDict = {'FID':px.colors.qualitative.Safe[4],'MS':px.colors.qualitative.Safe[1]}
238
- #List of applicable dataframe titles based on fig_chosen as keys in dictSPEC
239
- fig_chosen_dictSPEC = [dictSPEC[i] for i in fig_chosen]
240
- #Filter DataFrame based on fig_chosen
241
- #filDF = LQ_FIDpMS_SPEC[LQ_FIDpMS_SPEC['SignalType'].isin(fig_chosen_dictSPEC)]
242
-
243
- #Initialize figure
244
- fig = make_subplots(specs=[[{'secondary_y': True}]])
245
- #If there are any spectra chosen, plot them
246
- if len(fig_chosen) != 0:
247
- #Add a trace to the figure for each entry in fig_chosen
248
- for i in range(len(fig_chosen_dictSPEC)):
249
- #If the entry is past the first, set secondary_y axis value to True, otherwise set to False
250
- if i > 0:
251
- yTF = True
252
- else:
253
- yTF = False
254
- #Filter DataFrame based on ith entry in fig_chosen_dictSPEC
255
- filDF = LQ_FIDpMS_SPEC[LQ_FIDpMS_SPEC['SignalType'].str.match(fig_chosen_dictSPEC[i])]
256
-
257
- #Add a trace
258
- fig.add_trace(go.Scattergl(x=filDF['RT'],y=filDF['Signal'],\
259
- name=fig_chosen_dictSPEC[i],marker=dict(color=colorDict[fig_chosen[i]]),mode='lines+markers'),\
260
- secondary_y=yTF)
261
-
262
- #Update figure layout by adding titles
263
- fig.update_layout(title={'text':sname+' Spectra','font':{'color':'rgb(76, 46, 132)','size':20,'family':'Arial'}},\
264
- legend_title='Displayed Spectra')
265
- fig.update_xaxes(title_text='Retention time (min)')
266
- fig.update_yaxes(title_text=fig_chosen_dictSPEC[0]+' Signal (a.u.)',secondary_y=False)
267
- #Add a secondary y-axis title if necessary
268
- if len(fig_chosen_dictSPEC) > 1:
269
- fig.update_yaxes(title_text=fig_chosen_dictSPEC[1]+' Signal (a.u.)',secondary_y=True)
270
- #Check if user-inputted axis limits are viable
271
- #If lower ylim is less than upper ylim, update y-axis
272
- #If any NoneType exist in the axis limits list, do not update limits
273
- if None not in axLim[4:] and axLim[4] < axLim[5]:
274
- fig.update_yaxes(range=[axLim[4],axLim[5]],secondary_y=True)
275
- else:
276
- pass
277
- else:
278
- pass
279
-
280
- #Check if user-inputted axis limits are viable
281
- #If lower xlim is less than upper xlim, update x-axis
282
- #If any NoneType exist in the axis limits list, do not update limits
283
- if None not in axLim[:1] and axLim[0] < axLim[1]:
284
- fig.update_xaxes(range=[axLim[0],axLim[1]])
285
- else:
286
- pass
287
- #If lower ylim is less than upper ylim, update y-axis
288
- #If any NoneType exist in the axis limits list, do not update limits
289
- if None not in axLim[2:4] and axLim[2] < axLim[3]:
290
- fig.update_yaxes(range=[axLim[2],axLim[3]],secondary_y=False)
291
- else:
292
- pass
293
-
294
- #If no spectra are chosen, don't plot anything
295
- else:
296
- pass
297
-
298
- return fig
299
-
300
-
301
- #Compound structure drawing function
302
- @callback(
303
- Output('structure-image','src'),
304
- Input('controls_and_graph','selectedData')
305
- )
306
- def draw_structure(selectedData):
307
- max_structs = 6
308
- empty_plot = "data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA="
309
-
310
- if selectedData:
311
- #Take first point in selectedData, creating nested list
312
- checkPoint = [selectedData['points'][0]['curveNumber'],\
313
- selectedData['points'][0]['x'],\
314
- selectedData['points'][0]['y']]
315
-
316
- #Dictionary assigning each spectra to a curve number
317
- specKeys = {'FID':'','MS':''}
318
-
319
- #Assign spectra to curve numbers according to whether or not the first point matches any points in the FID signal
320
- try:
321
- if checkPoint[2] == LQ_FID_SPEC.at[LQ_FID_SPEC[LQ_FID_SPEC['RT']==checkPoint[1]].index[0],'Signal']:
322
- specKeys['FID'] = int(checkPoint[0])
323
- specKeys['MS'] = int(not checkPoint[0])
324
- else:
325
- pass
326
- except:
327
- specKeys['FID'] = int(not checkPoint[0])
328
- specKeys['MS'] = int(checkPoint[0])
329
-
330
- #Create list of selected points filtered so only FID results show
331
- selectedFIDData = []
332
- for i in selectedData['points']:
333
- if i['curveNumber'] == specKeys['FID']:
334
- selectedFIDData.append({'x':i['x'],'y':i['y'],'pointIndex':i['pointIndex']})
335
-
336
- if len(selectedFIDData) == 0:
337
- return empty_plot
338
- #List of selected point indices on FID spectrum
339
- match_idx = [x['pointIndex'] for x in selectedFIDData]
340
- #Dataframe with smiles and related data for selected points
341
- smilesDF = LQ_FID_SPEC.loc[match_idx,['RT','Compound Name','Formula','Match Factor','isoSMILES']]
342
- #Set FID spectra index to its own column and reset the indices
343
- smilesDF.reset_index(inplace=True)
344
- smilesDF = smilesDF.rename(columns={'index':'Spectra Index'})
345
- #Filter dataframe to only include non-NaN smiles entries
346
- smilesDF_F = smilesDF[smilesDF['isoSMILES'].notnull()].reset_index(drop=True)
347
- #Get lists of smiles rdkit objects and corresponding compound names
348
- list_smiles = [Chem.MolFromSmiles(x) for x in smilesDF_F['isoSMILES'].tolist()][:max_structs]
349
- #Create a list of legend entries using data from smilesDF_F
350
- list_legends = [smilesDF_F.loc[smilesDF_F.index[i],'Compound Name']+'\n'+\
351
- smilesDF_F.loc[smilesDF_F.index[i],'Formula']+' - '+\
352
- '{:.4}% Match'.format(smilesDF_F.loc[smilesDF_F.index[i],'Match Factor'])+'\n'+\
353
- '{:.3} min'.format(smilesDF_F.loc[smilesDF_F.index[i],'RT']) for i in range(len(smilesDF_F))][:max_structs]
354
- #Initialize MolDraw2DCairo drawer
355
- drawer = rdMolDraw2D.MolDraw2DCairo(1200,180,200,180)
356
- #Set drawing options
357
- drawer.drawOptions().useBWAtomPalette()
358
- drawer.drawOptions().legendFontSize = 16
359
- drawer.drawOptions().legendFraction = 0.3
360
- drawer.drawOptions().maxFontSize = 16
361
- drawer.drawOptions().padding = 0.05
362
- drawer.drawOptions().centreMoleculesBeforeDrawing = True
363
- #Draw the molecules
364
- drawer.DrawMolecules(list_smiles,legends=list_legends)
365
- drawer.FinishDrawing()
366
- #Set buffered image using BytesIO encoding
367
- buffered = BytesIO(drawer.GetDrawingText())
368
-
369
- #OLD METHOD FOR DRAWING GRID OF MOLECULE IMAGES
370
- #Create a grid of molecule images using rdkit
371
- #img = MolsToGridImage(list_smiles[0:max_structs], molsPerRow=structs_per_row, legends=list_legends, subImgSize=(300,300))
372
- #img = SVG(drawer.GetDrawingText())
373
- #Encode and save the image
374
- #buffered = BytesIO()
375
- #img.save(buffered, format="JPEG")
376
-
377
- #Encode the image
378
- encoded_image = base64.b64encode(buffered.getvalue())
379
- #Define and return the image string
380
- src_str = 'data:image/png;base64,{}'.format(encoded_image.decode())
381
- return src_str
382
- else:
383
- #Return a blank string
384
- return ''
385
-
386
- """ EXECUTE APPLICATION """
387
-
388
- #Run the application
389
- if __name__ == '__main__':
390
- app.run(debug=True)
391
-
392
-
393
- """
394
- #Callback controls
395
- @callback(
396
- Output(component_id='controls_and_graph',component_property='figure'),
397
- Input(component_id='controls_and_checklist',component_property='value')
398
- )
399
-
400
- def update_graph(fig_chosen):
401
- #List of applicable dataframe titles based on fig_chosen as keys in dictSPEC
402
- fig_chosen_dictSPEC = [dictSPEC[i] for i in fig_chosen]
403
- #Filter DataFrame based on fig_chosen
404
- filDF = LQ_FIDpMS_SPEC[LQ_FIDpMS_SPEC['SignalType'].isin(fig_chosen_dictSPEC)]
405
- fig = px.scatter(filDF,x='RT',y='Signal',color='SignalType',\
406
- color_discrete_sequence=[px.colors.qualitative.Safe[4],\
407
- px.colors.qualitative.Safe[1]])
408
- #Update figure layout
409
- fig.update_layout(title='MBPR031 Spectra',xaxis_title='Retention time (min)',yaxis_title='Signal (a.u.)',legend_title='Displayed Spectra')
410
- return fig
411
- """
412
-
413
-
414
-
415
-
416
-
417
-
418
-