chromaquant 0.3.1__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.
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+
4
+ """
5
+ ChromaQuant.Quant package initialization
6
+
7
+ Julia Hancock
8
+ Created 10-19-2024
9
+
10
+ """
11
+
12
+ from .AutoQuantification import main_AutoQuantification
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+
4
+ """
5
+ ChromaQuant package initialization
6
+
7
+ Julia Hancock
8
+ Created 10-20-2024
9
+
10
+ """
@@ -0,0 +1,493 @@
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) 2024, 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
+ SCRIPT FOR SIMPLIFYING ANALYSIS WORKFLOW
17
+
18
+ Julia Hancock
19
+ Started 01-04-2024
20
+
21
+ """
22
+
23
+ """ PACKAGES """
24
+ print("[__main__] Loading packages...")
25
+ import tkinter as tk
26
+ from tkinter import ttk
27
+ from ttkthemes import ThemedTk
28
+ import tkinter.font as tkFont
29
+ import os
30
+ import subprocess
31
+ import sys
32
+ from PIL import Image, ImageTk
33
+ from datetime import datetime
34
+ import importlib.util
35
+
36
+ """ LOCAL PACKAGES """
37
+ print("[__main__] Importing local packages...")
38
+ #Get current file absolute directory
39
+ file_dir = os.path.dirname(os.path.abspath(__file__))
40
+ #Get absolute directories for subpackages
41
+ subpack_dir = {'Handle':os.path.join(file_dir,'Handle','__init__.py'),
42
+ 'Manual':os.path.join(file_dir,'Manual','__init__.py'),
43
+ 'Match':os.path.join(file_dir,'Match','__init__.py'),
44
+ 'Quant':os.path.join(file_dir,'Quant','__init__.py')}
45
+
46
+ #Define function to import from path
47
+ def import_from_path(module_name,path):
48
+ #Define spec
49
+ spec = importlib.util.spec_from_file_location(module_name,path)
50
+ #Define module
51
+ module = importlib.util.module_from_spec(spec)
52
+ #Expand sys.modules dict
53
+ sys.modules[module_name] = module
54
+ #Load module
55
+ spec.loader.exec_module(module)
56
+ return module
57
+
58
+ #Import all local packages
59
+ hd = import_from_path("hd",subpack_dir['Handle'])
60
+ mn = import_from_path("mn",subpack_dir['Manual'])
61
+ qt = import_from_path("qt",subpack_dir['Quant'])
62
+ mt = import_from_path("mt",subpack_dir['Match'])
63
+
64
+ """ PARAMETERS """
65
+ print("[__main__] Defining parameters...")
66
+ version = "0.3.1"
67
+ __version__ = "0.3.1"
68
+
69
+ """ UI FUNCTION """
70
+
71
+ def runUI():
72
+
73
+ """ DIRECTORIES """
74
+ print("[__main__] Defining directories...")
75
+ print("[__main__] Using Handle package...")
76
+ #Get directories from handling script
77
+ directories = hd.handle(os.path.dirname(os.path.abspath(__file__)))
78
+ #Unpack directories
79
+ #Primary files directory
80
+ files = directories['files']
81
+ #Resources directory
82
+ RE_Dir = directories['resources']
83
+ #Theme directory
84
+ theme_Dir = directories['theme']
85
+ #Response factor directory
86
+ RF_Dir = directories['rf']
87
+ #Data directory
88
+ DF_Dir = directories['data']
89
+ #Images directory
90
+ img_Dir = directories['images']
91
+ #AutoFpmMatch directory + file
92
+ afm_Dir = os.path.join(os.path.dirname(os.path.abspath(__file__)),'AutoFpmMatch.py')
93
+ #AutoQuantification directory + file
94
+ aq_Dir = os.path.join(os.path.dirname(os.path.abspath(__file__)),'AutoQuantification.py')
95
+
96
+ """ DATA SEARCH """
97
+ print("[__main__] Searching for valid data files...")
98
+ #Get a list of all available sample data directories (excluding "old") in the data files directory
99
+ sampleList = [f.name for f in os.scandir(DF_Dir) if f.is_dir() if f.name != "old"]
100
+
101
+ """ FUNCTIONS """
102
+ print("[__main__] Defining functions...")
103
+ #Function for setting up the UI
104
+ def uiSetup(theme_Dir):
105
+
106
+ #Initialize UI window
107
+ root = ThemedTk(theme='adapta')
108
+
109
+ # Import the tcl file with the tk.call method
110
+ root.tk.call('source', theme_Dir)
111
+
112
+ # Set the theme with the theme_use method
113
+ style = ttk.Style(root)
114
+ style.theme_use('forest-light')
115
+ #Set up style button font
116
+ style.configure('QuantButton.TButton',font=('TKDefaultFont',16))
117
+ #Set up style accent button font
118
+ style.configure('Accent.TButton',font=('TKDefaultFont',16))
119
+ #Set up labelframe font
120
+ style.configure('QuantLabelframe.TLabelframe.Label',font=('TKDefaultFont',16))
121
+
122
+ root.geometry("1090x560")
123
+ root.title("ChromaQuant – Quantification Made Easy")
124
+ root.resizable(0,0)
125
+
126
+ #style.theme_use('forest')
127
+ #Configure the grid
128
+ root.columnconfigure(0,weight=2)
129
+ root.columnconfigure(1,weight=2)
130
+ root.columnconfigure(2,weight=2)
131
+ root.columnconfigure(3,weight=2)
132
+
133
+ #Create a main frame
134
+ mainframe = ttk.Frame(root)
135
+ mainframe.grid(column=0,row=0)
136
+
137
+ return root, mainframe
138
+ #Function for sample selection combobox
139
+ def on_select(event):
140
+
141
+ sname = sampleBox.get()
142
+ print("User selected "+sampleBox.get())
143
+ return sname
144
+
145
+ #Function for fidpms phase selection combobox
146
+ def fidpms_select():
147
+
148
+ sphase = fpmVar.get()
149
+ print("User selected " + sphase)
150
+
151
+ if sphase == "Liquid":
152
+ #Set variable to first order
153
+ fpmMVar.set('First order (linear)')
154
+ #Disable third order
155
+ third.config(state=tk.DISABLED)
156
+ else:
157
+ third.config(state=tk.NORMAL)
158
+
159
+ return sphase
160
+
161
+ #Function for model selection combobox
162
+ def fidpms_select_model():
163
+
164
+ model = fpmMVar.get()
165
+ print("User selected " + model)
166
+
167
+ return model
168
+
169
+ #Function for fidpms speculative labeling combobox
170
+ def fidpms_select2():
171
+
172
+ specLabTF = fpm2Var.get()
173
+ print("User selected " + specLabTF)
174
+
175
+ return specLabTF
176
+
177
+ #Function for quant phase selection combobox
178
+ def quant_select(event):
179
+
180
+ global quantphases
181
+ quantphases = logBox.get
182
+
183
+ #Function for running method functions
184
+ def runProcess(sname,pythonFun,varList):
185
+ """
186
+ Function that runs an external main function
187
+ Parameters
188
+ ----------
189
+ sname : String
190
+ Name of sample to be analyzed.
191
+ pythonFun : Function
192
+ Function to be run.
193
+ varList : List
194
+ List of reformatted variables to be passed to the function.
195
+
196
+ Returns
197
+ -------
198
+ None.
199
+
200
+ """
201
+ #Start time for execution time
202
+ exec_start = datetime.now()
203
+ #Insert sname at the beginning of the variables list
204
+ varList.insert(0,sname)
205
+ #Run the method function
206
+ pythonFun(*varList)
207
+ #End time for execution time
208
+ exec_end = datetime.now()
209
+ #Execution time
210
+ exec_time = (exec_end-exec_start).total_seconds()*10**3
211
+ print("Time to execute: {:.03f}ms".format(exec_time))
212
+ print("Program complete")
213
+
214
+ return None
215
+
216
+ #Function for running FIDpMS script
217
+ def runFIDpMS(sname,specLabTF,sphase,model):
218
+ """
219
+ Parameters
220
+ ----------
221
+ sname : STRING
222
+ Name of sample to be analyzed.
223
+ specLabTF : STRING
224
+ True/false string describing whether speculative labeling is to be performed.
225
+ sphase : TYPE
226
+ String describing whether liquid or gas is to be performed.
227
+ model : TYPE
228
+ String describing which model is to be performed.
229
+
230
+ Returns
231
+ -------
232
+ NONE
233
+
234
+ """
235
+
236
+ #Function for reformatting provided variables
237
+ def reformatVar(var_initial,ifTF_list):
238
+ """
239
+ Parameters
240
+ ----------
241
+ var_initial : STRING, BOOLEAN
242
+ The initial variable to be reformatted.
243
+ ifTF_list : LIST
244
+ A list containing two lists, the first containing the variable options and the second containing reformatted values.
245
+
246
+ Returns
247
+ -------
248
+ var_final : STRING
249
+ The final, reformatted variable.
250
+
251
+ """
252
+
253
+ #Set default value of reformatted value
254
+ var_final = "N/A"
255
+
256
+ #Get the length of the variable option list
257
+ listLength = len(ifTF_list[0])
258
+
259
+ #For every entry in the variable option list...
260
+ for i in range(listLength):
261
+
262
+ #If the variable is equal to the ith variable option...
263
+ if var_initial == ifTF_list[0][i]:
264
+ #Assign the variable to the first reformatted value
265
+ var_final = ifTF_list[1][i]
266
+ #Otherwise, pass
267
+ else:
268
+ pass
269
+
270
+ return var_final
271
+
272
+ #A dictionary containing the ifTF_lists for every passed variable
273
+ ifTF_Dict = {'specLabTF':[[1,0],['True','False']],'sphase':[['Gas','Liquid'],['G','L']],'model':[['First order (linear)','Third order','Retention time'],['F','T','R']]}
274
+
275
+ #A dictionary of all passed variables excluding sname
276
+ passed_dict = {'sphase':sphase,'specLabTF':specLabTF,'model':model}
277
+
278
+ print("User selected sample name {0} with phase {2} and entered {1} for running speculative labeling. Modeling is {3}".format(sname,specLabTF,sphase,model))
279
+
280
+ #A dictionary for all reformatted variables
281
+ reformatVar_dict = {}
282
+
283
+ #A dictionary of booleans describing whether or not values in reformatVar_dict are "N/A"
284
+ reformatBool_dict = {}
285
+
286
+ #Reformat all variables
287
+ for i in passed_dict.keys():
288
+
289
+ #Print reformatted variable name
290
+ print("Reformatting " + i + "...")
291
+ #Reformat variable, append to dictionary
292
+ reformatVar_dict[i] = reformatVar(passed_dict[i],ifTF_Dict[i])
293
+ #Print resulting reformatted value
294
+ print("Variable has been reformatted to {0}".format(reformatVar_dict[i]))
295
+
296
+ #Check if reformatted variable is equal to "N/A". If it is, assign False
297
+ if reformatVar_dict[i] == "N/A":
298
+ reformatBool_dict[i] = False
299
+ #Otherwise, assign True
300
+ else:
301
+ reformatBool_dict[i] = True
302
+
303
+ #If any of the required fields are empty, pass
304
+ if False in list(reformatBool_dict.values()) or sname == "":
305
+ print("Cannot run FIDpMS script, one or more variables are not defined")
306
+ pass
307
+
308
+ #Otherwise, run the FIDpMS script
309
+ else:
310
+ print("Running FIDpMS script...")
311
+
312
+ try:
313
+ #Get list of reformatVar_dict values
314
+ reformatVar_list = list(reformatVar_dict.values())
315
+ print(reformatVar_list)
316
+ #Append list with directories list
317
+ reformatVar_list.append(directories)
318
+ print(reformatVar_list)
319
+ #Run subprocess
320
+ runProcess(sname,mt.main_AutoFpmMatch,reformatVar_list)
321
+
322
+ except subprocess.CalledProcessError as e:
323
+ print(f'Command {e.cmd} failed with error {e.returncode}')
324
+
325
+ return None
326
+
327
+ #Function for running quant script
328
+ def runQuant(sname,quantphases):
329
+
330
+ print("User selected sample name {0} with phase(s) {1}".format(sname,quantphases))
331
+ #If any of the required fields are empty, pass
332
+ if sname == "" or quantphases == "":
333
+ print("User did not enter a value for at least one required argument, canceling script run")
334
+ pass
335
+ #Otherwise, run the FIDpMS script
336
+ else:
337
+ print("Running Quantification script...")
338
+
339
+ try:
340
+ #Run subprocess
341
+ runProcess(sname,qt.main_AutoQuantification,[quantphases,directories])
342
+
343
+ except subprocess.CalledProcessError as e:
344
+ print(f'Command {e.cmd} failed with error {e.returncode}')
345
+
346
+ return None
347
+
348
+ """ CODE """
349
+ print("[__main__] Initializing UI mainframe...")
350
+ #Run the UI setup
351
+ root, mainframe = uiSetup(theme_Dir)
352
+
353
+ #Create font objects
354
+ title_font = tkFont.Font(size=18) #Title font
355
+
356
+ #IMAGE AND TITLE
357
+ #Add a frame for the logo and title/sample info
358
+ topFrame = ttk.Frame(mainframe)
359
+ topFrame.grid(column=0,row=0,sticky='w',padx=(350,0))
360
+
361
+ #Add a frame for the ChromaQuant logo
362
+ logoFrame = ttk.Frame(topFrame)
363
+ logoFrame.grid(column=0,row=0)
364
+
365
+ #Add a frame for the title text and sample selection
366
+ tsFrame = ttk.Frame(topFrame)
367
+ tsFrame.grid(column=1,row=0)
368
+
369
+ #Add title text
370
+ tk.Label(tsFrame,text="ChromaQuant v"+version,font=title_font).grid(column=0,row=0,pady=10,padx=10)
371
+
372
+ #Add an image for the ChromaQuant logo
373
+ #Load the image
374
+ #image = tk.PhotoImage(file=img_Dir+'ChromaQuantIcon.png')
375
+ image_i = Image.open(os.path.join(img_Dir,'ChromaQuantIcon.png'))
376
+ #Resize the image
377
+ resize_image = image_i.resize((100,100))
378
+ #Redefine the image
379
+ image = ImageTk.PhotoImage(resize_image)
380
+ #Add the image to a label
381
+ image_label = tk.Label(logoFrame, image=image)
382
+ image_label.grid(column=0,row=0,pady=10,padx=10)
383
+
384
+ #SAMPLE SELECTION
385
+ #Add a frame for selecting the sample
386
+ sampleFrame = ttk.Frame(tsFrame)
387
+ sampleFrame.grid(column=0,row=1,pady=10,padx=10)
388
+
389
+ #Add text to the top of the sample frame
390
+ tk.Label(sampleFrame,text='Select a sample to analyze:').grid(column=0,row=0)
391
+ sampleVar = tk.StringVar()
392
+ sampleBox = ttk.Combobox(sampleFrame,textvariable=sampleVar)
393
+ sampleBox['values'] = sampleList
394
+ sampleBox.state(["readonly"])
395
+ sampleBox.grid(column=0,row=1)
396
+
397
+ #Bind the sampleBox to a function
398
+ sampleBox.bind("<<ComboboxSelected>>",on_select)
399
+
400
+ #WIDGET FRAME
401
+ #Add a frame for the fidpms and quantification widgets
402
+ widgetFrame = ttk.Frame(mainframe)
403
+ widgetFrame.grid(column=0,row=1)
404
+
405
+ #FIDPMS WIDGET
406
+ #Add a frame
407
+ fidpms_content = ttk.LabelFrame(widgetFrame,text='Peak Matching',style='QuantLabelframe.TLabelframe')
408
+ fidpms_content.grid(column=0,row=0,pady=10,padx=10)
409
+
410
+ #Add text to the top of the frame
411
+ tk.Label(fidpms_content,text='Please enter all information').grid(column=0,row=0,columnspan=4,padx=20)
412
+
413
+ #Set up a radiobutton for selecting liquid or gas
414
+ tk.Label(fidpms_content,text='Please select the sample type:').grid(column=0,row=1,padx=10,pady=20,sticky='e')
415
+ fpmVar = tk.StringVar()
416
+ Liquid = ttk.Radiobutton(fidpms_content,text='Liquid',variable=fpmVar,value="Liquid",command=fidpms_select)
417
+ Gas = ttk.Radiobutton(fidpms_content,text='Gas',variable=fpmVar,value="Gas",command=fidpms_select)
418
+ Liquid.grid(column=1,row=1,padx=1,sticky='w')
419
+ Gas.grid(column=2,row=1,padx=1,sticky='w')
420
+
421
+ #Initially start with liquid selected
422
+ fpmVar.set('Liquid')
423
+
424
+ #Set up a radiobutton for selecting the model type
425
+ tk.Label(fidpms_content,text='Please select the desired matching fit model:').grid(column=0,row=2,padx=10,pady=20,sticky='e')
426
+ fpmMVar = tk.StringVar()
427
+ third = ttk.Radiobutton(fidpms_content,text='Third order',variable=fpmMVar,value='Third order',command=fidpms_select_model)
428
+ first = ttk.Radiobutton(fidpms_content,text='First order (linear)',variable=fpmMVar,value='First order (linear)',command=fidpms_select_model)
429
+ rt = ttk.Radiobutton(fidpms_content,text='Retention time',variable=fpmMVar,value='Retention time',command=fidpms_select_model)
430
+ third.grid(column=1,row=2,padx=1,sticky='w')
431
+ first.grid(column=2,row=2,padx=1,sticky='w')
432
+ rt.grid(column=3,row=2,padx=1,sticky='w')
433
+
434
+ #Initially start with first order selected and third order disabled
435
+ fpmMVar.set('First order (linear')
436
+ third.config(state=tk.DISABLED)
437
+
438
+ #Set up a checkbox for selecting whether or not to perform speculative labeling
439
+ tk.Label(fidpms_content,text='Perform speculative labeling?').grid(column=0,row=3,padx=10,pady=20,sticky='e')
440
+ fpm2Var = tk.IntVar()
441
+ fpm2Box = tk.Checkbutton(fidpms_content,text='',variable=fpm2Var,onvalue=1,offvalue=0,command=fidpms_select2)
442
+ fpm2Box.grid(column=1,row=3,padx=1,sticky='w')
443
+
444
+ #Add a start button
445
+ fidpms_sbutton = ttk.Button(fidpms_content,text="\n\n\nRun Script\n\n\n",width=20,style='Accent.TButton',command=lambda: runFIDpMS(sampleVar.get(),fpm2Var.get(),fpmVar.get(),fpmMVar.get()))
446
+ fidpms_sbutton.grid(column=0,row=4,pady=20,padx=20,columnspan=2)
447
+
448
+ #DISABLING SPECULATIVE LABELING
449
+ fpm2Box.config(state=tk.DISABLED)
450
+
451
+ #Bind the button to a function to run the appropriate script
452
+ #fidpms_sbutton.bind("<Button-1>",runFIDpMS)
453
+
454
+ #QUANT WIDGET
455
+ #Add a frame
456
+ quant_content = ttk.LabelFrame(widgetFrame,text='Quantification',style='QuantLabelframe.TLabelframe')
457
+ quant_content.grid(column=1,row=0,pady=10,padx=10,sticky="n")
458
+
459
+ #Add text to the top of the frame
460
+ tk.Label(quant_content,text='Please enter all information').grid(column=0,row=0,columnspan=2,padx=20)
461
+ #Set up a combobox for selecting liquid or gas
462
+ tk.Label(quant_content,text='Does the sample have liquid and/or gas components?').grid(column=0,row=1,padx=10,pady=20)
463
+ logVar = tk.StringVar()
464
+ logBox = ttk.Combobox(quant_content,textvariable=logVar)
465
+ logBox['values'] = ['Liquid','Gas','Liquid and Gas']
466
+ logBox.state(["readonly"])
467
+ logBox.grid(column=1,row=1,padx=10)
468
+
469
+ #Bind the combobox to a function
470
+ logBox.bind("<<ComboboxSelected>>",quant_select)
471
+
472
+ #Add a start button
473
+ quant_sbutton = ttk.Button(quant_content,text="\n\n\nRun Script\n\n\n",width=20,style='Accent.TButton',command=lambda: runQuant(sampleVar.get(),logVar.get()))
474
+ quant_sbutton.grid(column=0,row=2,pady=20,padx=20,columnspan=2)
475
+
476
+ #Bind the start button to a function
477
+ #quant_sbutton.bind("<Button-1>",runQuant)
478
+
479
+ #var = ""
480
+ #togglebutton = ttk.Checkbutton(root, text='Switch', style='Switch',variable=var)
481
+ #togglebutton.grid(row=3,column=0)
482
+
483
+ #Main loop
484
+ root.mainloop()
485
+
486
+ #End of runUI function
487
+ return None
488
+
489
+ """ RUN MAIN FUNCTION """
490
+ print("[__main__] Starting UI...")
491
+ if __name__ == "__main__":
492
+ runUI()
493
+
@@ -0,0 +1,4 @@
1
+ {
2
+ "app-directory": "/Users/[user]/Desktop/University/Rorrer Lab/Scripts/chromaquant/src/chromaquant",
3
+ "file-directory": "/Users/[user]/Documents/ChromaQuant"
4
+ }