chromaquant 0.3.1__py3-none-any.whl → 0.4.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/__main__.py CHANGED
@@ -16,7 +16,7 @@ License: BSD 3-Clause License
16
16
  SCRIPT FOR SIMPLIFYING ANALYSIS WORKFLOW
17
17
 
18
18
  Julia Hancock
19
- Started 01-04-2024
19
+ Started 12-10-2024
20
20
 
21
21
  """
22
22
 
@@ -27,11 +27,13 @@ from tkinter import ttk
27
27
  from ttkthemes import ThemedTk
28
28
  import tkinter.font as tkFont
29
29
  import os
30
- import subprocess
31
30
  import sys
32
31
  from PIL import Image, ImageTk
33
32
  from datetime import datetime
34
33
  import importlib.util
34
+ import threading
35
+ import time
36
+ import json
35
37
 
36
38
  """ LOCAL PACKAGES """
37
39
  print("[__main__] Importing local packages...")
@@ -41,7 +43,9 @@ file_dir = os.path.dirname(os.path.abspath(__file__))
41
43
  subpack_dir = {'Handle':os.path.join(file_dir,'Handle','__init__.py'),
42
44
  'Manual':os.path.join(file_dir,'Manual','__init__.py'),
43
45
  'Match':os.path.join(file_dir,'Match','__init__.py'),
44
- 'Quant':os.path.join(file_dir,'Quant','__init__.py')}
46
+ 'Quant':os.path.join(file_dir,'Quant','__init__.py'),
47
+ 'UAPP':os.path.join(file_dir,'UAPP','__init__.py'),
48
+ 'Hydro':os.path.join(file_dir,'Hydro','__init__.py')}
45
49
 
46
50
  #Define function to import from path
47
51
  def import_from_path(module_name,path):
@@ -60,14 +64,17 @@ hd = import_from_path("hd",subpack_dir['Handle'])
60
64
  mn = import_from_path("mn",subpack_dir['Manual'])
61
65
  qt = import_from_path("qt",subpack_dir['Quant'])
62
66
  mt = import_from_path("mt",subpack_dir['Match'])
67
+ ua = import_from_path("ua",subpack_dir['UAPP'])
68
+ #hy = import_from_path("hy",subpack_dir['Hydro'])
63
69
 
64
70
  """ PARAMETERS """
65
71
  print("[__main__] Defining parameters...")
66
- version = "0.3.1"
67
- __version__ = "0.3.1"
72
+ __version__ = "0.4.0"
73
+ version = "0.4.0"
68
74
 
69
- """ UI FUNCTION """
75
+ """ RUNUI FUNCTION """
70
76
 
77
+ #Function to run the UI
71
78
  def runUI():
72
79
 
73
80
  """ DIRECTORIES """
@@ -75,419 +82,445 @@ def runUI():
75
82
  print("[__main__] Using Handle package...")
76
83
  #Get directories from handling script
77
84
  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
-
85
+
96
86
  """ DATA SEARCH """
97
87
  print("[__main__] Searching for valid data files...")
98
88
  #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
89
+ sampleList = [f.name for f in os.scandir(directories['data']) if f.is_dir() if f.name != "old"]
90
+
91
+ """ CODE """
92
+ #Define ChromaQuantUI as class
93
+ class chromaUI:
94
+
95
+ #Key variables = sampleVar, fpm_typevar, fpm_modelvar, quant_typevar, quant_modelvar, hydro_typevar
96
+ #Initialization function – master here will be our root widget
97
+ def __init__(self, master, directories):
98
+
99
+ self.master = master
100
+ self.directories = directories
101
+
102
+ #ANALYSIS CONFIGURATION
103
+ print("[__main__] Interpreting analysis configuration...")
104
+ #Read analysis configuration file
105
+ with open(os.path.join(self.directories['resources'],'analysis-config.json')) as f:
106
+ self.analysis_config = json.load(f)
107
+
108
+ #Extract analysis configuration info
109
+ #File suffixes to add to form data filenames
110
+ self.file_suffix_list = [i[0] for i in list(self.analysis_config["file-suffix"].values())]
111
+
112
+ #Standard padding
113
+ self.std_padx = 10
114
+ self.std_pady = 10
115
+
116
+ #Padding for widgets/widget rows
117
+ self.widget_padx = 20
118
+ self.widget_pady = 20
119
+
120
+ #Initialize user variable dictionary
121
+ self.var_dict = {}
122
+ #Initialize user variable entries
123
+ self.var_dict['sampleVar'] = tk.StringVar()
124
+ self.var_dict['fpm_typevar'] = tk.StringVar()
125
+ self.var_dict['fpm_modelvar'] = tk.StringVar()
126
+ self.var_dict['quant_typevar'] = tk.StringVar()
127
+ self.var_dict['quant_modelvar'] = tk.StringVar()
128
+ self.var_dict['hydro_typevar'] = tk.StringVar()
129
+ self.var_dict['hydro_matchvar'] = tk.StringVar()
130
+
131
+ #Initialize list of variables to have an anonymous printing function
132
+ self.varSelect_list = ['sampleVar','fpm_typevar','fpm_modelvar','quant_modelvar','hydro_typevar','hydro_matchvar']
133
+
134
+ #Initialize radiobutton object dictionary
135
+ self.radio_dict = {}
136
+
137
+ #Setup UI
138
+ self.setupUI()
139
+
140
+ #Create font objects
141
+ self.title_font = tkFont.Font(size=18,weight='bold') #Title font
142
+
143
+ #SETUP SELECT FUNCTIONS
144
+ self.setupVarSelect()
145
+
146
+ #IMAGE AND TITLE
147
+ #Add a frame for the logo and title/sample info
148
+ self.topFrame = ttk.Frame(self.mainframe)
149
+ self.topFrame.grid(column=0,row=0,sticky='WE')
150
+ self.topFrame.grid_columnconfigure((0,3),weight=1)
151
+ self.setupTitle()
152
+
153
+ #WIDGETS
154
+ #Add a frame for the first row of widgets
155
+ self.rowoneFrame = ttk.Frame(self.mainframe)
156
+ self.rowoneFrame.grid(column=0,row=1,sticky='WE')
157
+ self.rowoneFrame.grid_columnconfigure((0,4),weight=1)
158
+
159
+ #Add a frame for the second row of widgets
160
+ self.rowtwoFrame = ttk.Frame(self.mainframe)
161
+ self.rowtwoFrame.grid(column=0,row=2,sticky='WE')
162
+ self.rowtwoFrame.grid_columnconfigure((0,4),weight=1)
163
+
164
+ #FILE TRACKING
165
+ #Add a frame for tracking data files
166
+ self.trackFrame = ttk.LabelFrame(self.rowoneFrame,text='File Tracking',style='QuantLabelframe.TLabelframe')
167
+ self.trackFrame.grid(column=1,row=0,sticky='NSWE',padx=self.widget_padx,pady=self.widget_pady)
168
+ self.setupFileTrack()
169
+
170
+ #UNKNOWNS ANALYSIS POSTPROCESS
171
+ #Add a frame for the UA_UPP script
172
+ self.uppFrame = ttk.LabelFrame(self.rowoneFrame,text='Unknowns Analysis Postprocessing',style='QuantLabelframe.TLabelframe')
173
+ self.uppFrame.grid(column=2,row=0,sticky='NSWE',padx=(0,self.widget_padx),pady=self.widget_pady)
174
+ self.setupUPP()
175
+ #padx=self.widget_padx,pady=self.widget_pady
176
+
177
+ #FIDpMS MATCHING
178
+ #Add a frame for the main matching script
179
+ self.matchFrame = ttk.LabelFrame(self.rowoneFrame,text='Peak Matching',style='QuantLabelframe.TLabelframe')
180
+ self.matchFrame.grid(column=3,row=0,sticky='NSWE',padx=(0,self.widget_padx),pady=self.widget_pady)
181
+ self.setupMatch()
182
+
183
+ #QUANTIFICATION
184
+ #Add a frame for the main quantification script
185
+ self.quantFrame = ttk.LabelFrame(self.rowtwoFrame,text='Quantification',style='QuantLabelframe.TLabelframe')
186
+ self.quantFrame.grid(column=1,row=0,sticky='NSWE',padx=self.widget_padx,pady=(0,self.widget_pady))
187
+ self.setupQuant()
188
+
189
+ #HYDROUI
190
+ #Add a frame for the hydroUI script
191
+ self.hydroFrame = ttk.LabelFrame(self.rowtwoFrame,text='HydroUI (WIP)',style='QuantLabelframe.TLabelframe')
192
+ self.hydroFrame.grid(column=2,row=0,sticky='NSWE',padx=(0,self.widget_padx),pady=(0,self.widget_pady))
193
+ self.setupHydro()
194
+
195
+ def default(self):
196
+ print("[__main__][TEST] Testing message")
168
197
 
169
- #Function for fidpms speculative labeling combobox
170
- def fidpms_select2():
198
+ def setupUI(self):
171
199
 
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):
200
+ # Import the tcl file with the tk.call method
201
+ self.master.tk.call('source', self.directories['theme'])
179
202
 
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")
203
+ # Set the theme with the theme_use method
204
+ style = ttk.Style(root)
205
+ style.theme_use('forest-light')
206
+ #Set up style button font
207
+ style.configure('QuantButton.TButton',font=('Arial',16))
208
+ #Set up style accent button font
209
+ style.configure('Accent.TButton',font=('Arial',16))
210
+ #Set up labelframe font
211
+ style.configure('QuantLabelframe.TLabelframe.Label',font=('Arial',16))
212
+ #Set up labelframe border
213
+ style.configure('QuantLabelframe.TLabelframe',borderwidth=5,bordercolor='red')
214
+ #Set up file tracking text font
215
+ self.fileTrackFont = tkFont.Font(size=14)
213
216
 
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
- """
217
+ #root.geometry("890x1000")
218
+ root.title("ChromaQuant – Quantification Made Easy")
235
219
 
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
- """
220
+ #Create a main frame
221
+ self.mainframe = ttk.Frame(root)
222
+ self.mainframe.grid(column=0,row=0)
223
+
224
+ def setupTitle(self):
225
+
226
+ #Add a frame for the ChromaQuant logo
227
+ self.logoFrame = ttk.Frame(self.topFrame)
228
+ self.logoFrame.grid(column=1,row=0,sticky='WE')
252
229
 
253
- #Set default value of reformatted value
254
- var_final = "N/A"
230
+ #Add a frame for the title text and sample selection
231
+ self.tsFrame = ttk.Frame(self.topFrame)
232
+ self.tsFrame.grid(column=2,row=0,sticky='E')
233
+
234
+ #Add title text
235
+ tk.Label(self.tsFrame,text="ChromaQuant v"+version,font=self.title_font)\
236
+ .grid(column=0,row=0,pady=self.std_pady,padx=self.std_padx)
255
237
 
256
- #Get the length of the variable option list
257
- listLength = len(ifTF_list[0])
238
+ #Add an image for the ChromaQuant logo
239
+ #Load the image
240
+ self.image_i = Image.open(os.path.join(self.directories['images'],'ChromaQuantIcon.png'))
241
+ #Resize the image
242
+ self.resize_image = self.image_i.resize((100,100))
243
+ #Redefine the image
244
+ self.image = ImageTk.PhotoImage(self.resize_image)
245
+ #Add the image to a label
246
+ image_label = tk.Label(self.logoFrame, image=self.image)
247
+ image_label.grid(column=0,row=0,pady=10,padx=10)
248
+
249
+ #Add a frame for selecting the sample
250
+ sampleFrame = ttk.Frame(self.tsFrame)
251
+ sampleFrame.grid(column=0,row=1,pady=10,padx=10)
258
252
 
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}
253
+ #Add text to the top of the sample frame
254
+ tk.Label(sampleFrame,text='Select a sample to analyze:').grid(column=0,row=0)
255
+ self.var_dict['sampleVar'] = tk.StringVar()
256
+ self.sampleBox = ttk.Combobox(sampleFrame,textvariable=self.var_dict['sampleVar'])
257
+ self.sampleBox['values'] = sampleList
258
+ self.sampleBox.state(["readonly"])
259
+ self.sampleBox.grid(column=0,row=1)
277
260
 
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))
261
+ #Bind the sampleBox to a function
262
+ self.sampleBox.bind("<<ComboboxSelected>>",self.sampleSelect)
279
263
 
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():
264
+ def setupFileTrack(self):
265
+
266
+ #Create text window, place in grid
267
+ self.fileTrack_Text = tk.Text(self.trackFrame, height=12, width=20, fg='black', font=self.fileTrackFont)
268
+ self.fileTrack_Text.grid(column=0,row=0,padx=20,pady=10,sticky='NSWE')
269
+ #Set text config to NORMAL
270
+ self.fileTrack_Text.config(state=tk.NORMAL)
271
+ #Configure text options
272
+ #Option for default text
273
+ self.fileTrack_Text.tag_config('default', background="white", foreground="black")
274
+ #Option for present file
275
+ self.fileTrack_Text.tag_config('true', background="white", foreground='green')
276
+ #Option for file not found
277
+ self.fileTrack_Text.tag_config('false', background="white", foreground='red')
278
+
279
+ #Create default options
280
+ for i in self.file_suffix_list:
281
+ self.fileTrack_Text.insert(tk.END,"\n{0}".format(i),'default')
282
+
283
+ def updateFileTrack(self):
284
+
285
+ #Delete all text in file tracking widget
286
+ self.fileTrack_Text.delete(1.0,tk.END)
287
+
288
+ #Get list of files currently in data and raw data directory
289
+ self.rawDataFiles = [f.lower() for f in os.listdir(directories['raw']) if os.path.isfile(os.path.join(directories['raw'],f))]
290
+ self.dataFiles = [f.lower() for f in os.listdir(directories['sample']) if os.path.isfile(os.path.join(directories['sample'],f))]
288
291
 
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]))
292
+ #Loop through the data files to search for everything but the INFO file (last index)
293
+ for i in self.file_suffix_list[:-1]:
294
+
295
+ #If given file exists in list, color green
296
+ if (self.sname+i).lower() in self.rawDataFiles:
297
+ self.fileTrack_Text.insert(tk.END,"\n{0}".format(i),'true')
298
+
299
+ #Otherwise, color red
300
+ else:
301
+ self.fileTrack_Text.insert(tk.END,"\n{0}".format(i),'false')
302
+
303
+ #If last data file (INFO) exists in data files directory, color green
304
+ if (self.sname+self.file_suffix_list[-1]).lower() in self.dataFiles:
305
+ self.fileTrack_Text.insert(tk.END,"\n{0}".format(self.file_suffix_list[-1]),'true')
295
306
 
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
307
+ #Otherwise, color red
300
308
  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...")
309
+ self.fileTrack_Text.insert(tk.END,"\n{0}".format(self.file_suffix_list[-1]),'false')
310
+
311
+ print("[__main__] File tracking results updated...")
312
+
313
+ def setupUPP(self):
314
+
315
+ #Add start button
316
+ self.setupStartButton(self.uppFrame,[0,0],[20,20],1,self.runUPP)
317
+
318
+ def setupMatch(self):
319
+
320
+ #Add a radiobutton set for selecting sample type
321
+ self.radio_dict['fpm_typevar'] = self.setupRadioButton(self.matchFrame,'Please select the sample type:',[0,1],[20,20],1,'fpm_typevar',{'Liquid':'L','Gas':'G'},self.select_dict['fpm_typevar'],'L')
322
+ #Add a radiobutton set for selecting match model
323
+ self.radio_dict['fpm_modelvar'] = self.setupRadioButton(self.matchFrame,'Please select the desired matching fit model:',[0,2],[20,20],1,'fpm_modelvar',{'Retention\nTime':'R','Polynomial':'P'},self.select_dict['fpm_modelvar'],'R')
324
+ #Add start button
325
+ self.setupStartButton(self.matchFrame,[0,3],[20,20],4,self.runMatch)
326
+
327
+ def setupQuant(self):
328
+
329
+ #Add a radiobutton set for selecting sample type
330
+ self.radio_dict['quant_typevar'] = self.setupRadioButton(self.quantFrame,'Which components are present in the sample?',[0,1],[20,20],1,'quant_typevar',{'Liquid\nOnly':'L','Gas\nOnly':'G','Liquid\nand Gas':'LG'},self.quant_typevarSelect,'L')
311
331
 
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)
332
+ #Add a radiobutton set for selecting the gas quantification method
333
+ self.radio_dict['quant_modelvar'] = self.setupRadioButton(self.quantFrame,'Which method should be used to quantify gas phase products?',[0,2],[20,0],1,'quant_modelvar',{'CO2\nVolume':'C','Scale\nFactor':'S','Internal\nStandard':'I'},self.select_dict['quant_modelvar'],'Disabled')
334
+
335
+ #Add start button
336
+ self.setupStartButton(self.quantFrame,[0,3],[20,20],4,self.runQuant)
337
+
338
+ def setupHydro(self):
339
+
340
+ #Add a radiobutton set for selecting sample type
341
+ self.radio_dict['hydro_typevar'] = self.setupRadioButton(self.hydroFrame,'Which phase to analyze?',[0,1],[20,20],1,'hydro_typevar',{'Liquid':'L','Gas':'G'},self.select_dict['hydro_typevar'],'L')
342
+ #Add a radiobutton set for selecting sample type
343
+ self.radio_dict['hydro_matchvar'] = self.setupRadioButton(self.hydroFrame,'Display FID and MS matches?',[0,2],[20,20],1,'hydro_matchvar',{'Yes':'T','No':'F'},self.select_dict['hydro_matchvar'],'F')
344
+ #Add start button
345
+ self.setupStartButton(self.hydroFrame,[0,3],[20,20],4,self.runHydro)
346
+
347
+ def setupStartButton(self,frame,placement,pad,columnspan,function):
348
+
349
+ #Add a start button
350
+ ttk.Button(frame,text="\n\n\nRun Script\n\n\n",width=20,style='Accent.TButton',command=function)\
351
+ .grid(column=placement[0],row=placement[1],padx=pad[0],pady=pad[1],columnspan=columnspan)
352
+
353
+ def setupRadioButton(self,frame,label_text,placement,pad,columnspan,var_name,option_val_dict,function,init_state='Option Blank'):
354
+
355
+ #placement = [column,row]
356
+ #pad = [padx,pady]
357
+ #var_dict = {'var_1':tk.StringVar(),...}
358
+ #var_name = 'var_1'
359
+ #text_val_dict = {'option_1':'value_1',...}
360
+
361
+ #Set up a radiobutton for selecting liquid or gas
362
+ #Add a label
363
+ tk.Label(frame,text=label_text).grid(column=placement[0],row=placement[1],padx=pad[0],pady=pad[1],columnspan=columnspan,sticky='e')
364
+
365
+ #Define current column as column to the right of label
366
+ current_col = placement[0] + 1
367
+ #Define radiobutton padding loop iterable
368
+ current_pad = 0
369
+ #Define list to iterate through for radiobutton padding
370
+ radiopad = [(10,10) for i in range(len(option_val_dict))]
371
+ radiopad[-1] = (10,20)
372
+
373
+ #Define list of radiobutton objects
374
+ dict_radiobutton = {i:0 for i in option_val_dict}
375
+
376
+ #For every option in the option-value dictionary, add a radiobutton (iterate over columns)
377
+ for option in option_val_dict:
378
+
379
+ #Store the radiobutton object
380
+ dict_radiobutton[option] = ttk.Radiobutton(frame , text=option , variable=self.var_dict[var_name] , value=option_val_dict[option] , command=function)
381
+ dict_radiobutton[option].grid(column=current_col , row=placement[1] , padx=radiopad[current_pad] , sticky='w')
321
382
 
322
- except subprocess.CalledProcessError as e:
323
- print(f'Command {e.cmd} failed with error {e.returncode}')
383
+ #Iterate current column and radio padding list
384
+ current_col += 1
385
+ current_pad += 1
386
+
387
+ #Select the initial radiobutton state based on the init_state argument
388
+ #If init_state is 'Option Blank', select the first radiobutton
389
+ if init_state == 'Option Blank':
390
+ self.var_dict[var_name].set(next(iter(option_val_dict.values())))
391
+
392
+ #If init_state is 'Disabled', set the radiobuttons to be disabled
393
+ elif init_state == 'Disabled':
394
+ for option in option_val_dict:
395
+ dict_radiobutton[option].config(state=tk.DISABLED)
396
+
397
+ #Otherwise, if the init_state does not have a counterpart in the values of the option_val_dict, select the first radiobutton
398
+ elif init_state not in option_val_dict.values():
399
+ self.var_dict[var_name].set(next(iter(option_val_dict.values())))
400
+
401
+ #Otherwise, select the specified radiobutton
402
+ else:
403
+ self.var_dict[var_name].set(init_state)
404
+
405
+ return dict_radiobutton
324
406
 
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...")
407
+
408
+ def sampleSelect(self,event):
409
+
410
+ self.sname = self.sampleBox.get()
411
+
412
+ print("[__main__] User selected " + self.sname)
413
+
414
+ print("[__main__] Getting sample directories...")
415
+
416
+ #Sample directory
417
+ self.directories['sample'] = os.path.join(self.directories['data'],self.sname)
418
+
419
+ #Data file log directory
420
+ self.directories['log'] = os.path.join(self.directories['sample'],'log')
421
+
422
+ #Data file breakdowns directory
423
+ self.directories['break'] = os.path.join(self.directories['sample'],'breakdowns')
424
+
425
+ #Raw data file directory
426
+ self.directories['raw'] = os.path.join(self.directories['sample'],'raw data')
427
+
428
+ print("[__main__] Checking files...")
429
+ self.updateFileTrack()
430
+
431
+ return self.sname
432
+
433
+ #Function for setting up anonymous varaible select functions for printing messages
434
+ def setupVarSelect(self):
338
435
 
339
- try:
340
- #Run subprocess
341
- runProcess(sname,qt.main_AutoQuantification,[quantphases,directories])
436
+ #Predefine dictionary for selection functions
437
+ self.select_dict = {}
438
+
439
+ #For every variable...
440
+ for i in self.var_dict:
441
+
442
+ #If variable is listed in the anonymous variable list...
443
+ if i in self.varSelect_list:
444
+ #Define lambda function using default argument for user selection message
445
+ self.select_dict[i] = lambda i=i: print("[__main__] User Selected " + self.var_dict[i].get() + " for " + i)
342
446
 
343
- except subprocess.CalledProcessError as e:
344
- print(f'Command {e.cmd} failed with error {e.returncode}')
447
+ #Otherwise, pass
448
+ else:
449
+ pass
450
+
451
+ return None
452
+
453
+ #Function for quant_typevar selection
454
+ def quant_typevarSelect(self):
455
+
456
+ #If the phase selected is either gas or both liquid and gas...
457
+ if self.var_dict['quant_typevar'].get() == 'G' or self.var_dict['quant_typevar'].get() == 'LG':
458
+ #Enable all radiobuttons
459
+ for radiobutton in self.radio_dict['quant_modelvar']:
460
+ self.radio_dict['quant_modelvar'][radiobutton].config(state=tk.NORMAL)
461
+
462
+ #Otherwise, disable all radiobuttons
463
+ else:
464
+ #Disable all radiobuttons
465
+ for radiobutton in self.radio_dict['quant_modelvar']:
466
+ print(radiobutton)
467
+ self.radio_dict['quant_modelvar'][radiobutton].config(state=tk.DISABLED)
468
+
469
+ #Set quant_modelvar to none
470
+ self.var_dict['quant_modelvar'].set(None)
471
+
472
+ print("[__main__] User Selected " + self.var_dict['quant_typevar'].get() + " for quant_typevar")
473
+
474
+ return None
475
+
476
+ #Function for
477
+ def runUPP(self):
478
+ #Function for running the UPP function
479
+ print("[__main__] Running Unknowns Analysis Postprocessing...")
480
+ ua.mainUAPP(self.var_dict['sampleVar'].get())
481
+ print("[__main__] UAPP complete")
482
+ return None
345
483
 
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
484
+ def runMatch(self):
485
+ #Function for running the match function
486
+ print("[__main__] Running FID and MS matching...")
487
+ mt.mainMatch(self.var_dict['sampleVar'].get(), self.var_dict['fpm_typevar'].get(),self.var_dict['fpm_modelvar'].get())
488
+ print("[__main__] Matching complete")
489
+ return None
490
+
491
+ def runQuant(self):
492
+ #Function for running the quantification function
493
+ print("[__main__] Running quantification...")
494
+ qt.mainQuant(self.var_dict['sampleVar'].get(), self.var_dict['quant_typevar'].get(), self.var_dict['quant_modelvar'].get())
495
+ print("[__main__] Quantification complete")
496
+ return None
355
497
 
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
498
+ def runHydro(self):
499
+
500
+ #Function for running the hydroUI function
501
+ print("[__main__] Defining HydroUI application...")
502
+ """ COMMENT OUT FOR NOW, LAGGY
503
+ self.app = hy.mainHydro(self.var_dict['sampleVar'].get(), self.var_dict['hydro_typevar'].get(), self.var_dict['hydro_matchvar'].get())
504
+ print("[__main__] Application defined, running...")
505
+ if __name__ == "__main__":
506
+ #Define a thread and set as daemon – SCRIPT WILL CONTINUE TO RUN UNTIL CHROMAUI CLOSED
507
+ hydroThread = threading.Thread(target=lambda: self.app.run(debug=True, use_reloader=False))
508
+ hydroThread.daemon = True
509
+ #Start thread
510
+ hydroThread.start()
511
+ print("[__main__] HydroUI active")
512
+ """
513
+ return None
514
+
515
+ root = tk.Tk()
516
+ my_gui = chromaUI(root,directories)
517
+
484
518
  root.mainloop()
485
-
486
- #End of runUI function
487
- return None
519
+
520
+ print('[__main__] Program terminated')
521
+
488
522
 
489
523
  """ RUN MAIN FUNCTION """
490
524
  print("[__main__] Starting UI...")
491
525
  if __name__ == "__main__":
492
526
  runUI()
493
-