Skip to content

Commit cca80ed

Browse files
authored
Merge pull request #1 from SarthakJariwala/lifetime_irf
Lifetime irf
2 parents 36e3dcd + 5beda08 commit cca80ed

24 files changed

+6634
-640
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.pyc

PythonGUI_apps/DataBrowser.py

Lines changed: 47 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,18 @@
66
"""
77

88
# system imports
9+
import sys
910
from pathlib import Path
1011

1112
import pyqtgraph as pg
1213
from pyqtgraph.Qt import QtGui
1314

1415
from Lifetime_analysis import Lifetime_plot_fit
1516
from Spectrum_analysis import Spectra_plot_fit
17+
from FLIM_analysis import FLIM_plot
18+
from UV_Vis_analysis import uv_vis_analysis
19+
from PLQE_analysis import plqe_analysis
20+
from H5_Pkl import h5_pkl_view, h5_view_and_plot
1621

1722
pg.mkQApp()
1823
pg.setConfigOption('background', 'w')
@@ -25,37 +30,49 @@
2530
WindowTemplate, TemplateBaseClass = pg.Qt.loadUiType(uiFile)
2631

2732
class MainWindow(TemplateBaseClass):
28-
29-
def __init__(self):
30-
TemplateBaseClass.__init__(self)
31-
32-
# Create the main window
33-
self.ui = WindowTemplate()
34-
self.ui.setupUi(self)
35-
self.ui.select_comboBox.addItems(["Lifetime Analysis", "Spectrum Analysis", "UV-Vis Analysis"])
36-
self.ui.load_pushButton.clicked.connect(self.load_app)
37-
38-
self.show()
39-
40-
41-
def load_app(self):
42-
43-
analysis_software = self.ui.select_comboBox.currentText()
44-
45-
if analysis_software == "Lifetime Analysis":
46-
self.lifetime_window = Lifetime_plot_fit.MainWindow()
47-
self.lifetime_window.show()
48-
49-
elif analysis_software == "Spectrum Analysis":
50-
self.spectrum_window = Spectra_plot_fit.MainWindow()
51-
self.spectrum_window.show()
52-
53-
else:
54-
print("not yet linked -- coming soon")
33+
34+
def __init__(self):
35+
TemplateBaseClass.__init__(self)
36+
37+
# Create the main window
38+
self.ui = WindowTemplate()
39+
self.ui.setupUi(self)
40+
self.ui.select_comboBox.addItems(["Lifetime Analysis", "Spectrum Analysis", "FLIM Analysis",
41+
"UV-Vis Analysis", "PLQE Analysis", "H5 View/Plot", "H5/PKL Viewer"])
42+
self.ui.load_pushButton.clicked.connect(self.load_app)
43+
44+
self.show()
45+
46+
47+
def load_app(self):
48+
49+
analysis_software = self.ui.select_comboBox.currentText()
50+
51+
if analysis_software == "Lifetime Analysis":
52+
self.lifetime_window = Lifetime_plot_fit.MainWindow()
53+
self.lifetime_window.show()
54+
elif analysis_software == "Spectrum Analysis":
55+
self.spectrum_window = Spectra_plot_fit.MainWindow()
56+
self.spectrum_window.show()
57+
elif analysis_software == "FLIM Analysis":
58+
self.flim_window = FLIM_plot.MainWindow()
59+
self.flim_window.show()
60+
elif analysis_software == "UV-Vis Analysis":
61+
self.uv_vis_window = uv_vis_analysis.MainWindow()
62+
self.uv_vis_window.show()
63+
elif analysis_software == "PLQE Analysis":
64+
self.plqe_window = plqe_analysis.MainWindow()
65+
self.plqe_window.show()
66+
elif analysis_software == "H5 View/Plot":
67+
app = h5_view_and_plot.H5ViewPlot(sys.argv)
68+
#sys.exit(app.exec_())
69+
elif analysis_software == "H5/PKL Viewer":
70+
app = h5_pkl_view.H5PklView(sys.argv)
71+
#sys.exit(app.exec_())
5572

5673
def run():
57-
win = MainWindow()
58-
QtGui.QApplication.instance().exec_()
59-
return
74+
win = MainWindow()
75+
QtGui.QApplication.instance().exec_()
76+
return
6077

6178
run()

PythonGUI_apps/DataBrowser.spec

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# -*- mode: python -*-
2+
3+
block_cipher = None
4+
5+
6+
a = Analysis(['DataBrowser.py'],
7+
pathex=['C:\\Users\\lindat18\\Dropbox\\Ginger_Lab\\Data_Analysis\\PythonGUI_apps'],
8+
binaries=[],
9+
datas=[],
10+
hiddenimports=[],
11+
hookspath=[],
12+
runtime_hooks=[],
13+
excludes=[],
14+
win_no_prefer_redirects=False,
15+
win_private_assemblies=False,
16+
cipher=block_cipher,
17+
noarchive=False)
18+
pyz = PYZ(a.pure, a.zipped_data,
19+
cipher=block_cipher)
20+
exe = EXE(pyz,
21+
a.scripts,
22+
[],
23+
exclude_binaries=True,
24+
name='DataBrowser',
25+
debug=False,
26+
bootloader_ignore_signals=False,
27+
strip=False,
28+
upx=True,
29+
console=True )
30+
coll = COLLECT(exe,
31+
a.binaries,
32+
a.zipfiles,
33+
a.datas,
34+
strip=False,
35+
upx=True,
36+
name='DataBrowser')
Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
import sys
2+
import h5py
3+
from pathlib import Path
4+
import os.path
5+
import pyqtgraph as pg
6+
from pyqtgraph.Qt import QtCore, QtGui, QtWidgets#, QColorDialog
7+
import numpy as np
8+
import matplotlib.pyplot as plt
9+
import pickle
10+
import time
11+
from lmfit.models import GaussianModel
12+
import customplotting.mscope as cpm
13+
# local modules
14+
15+
pg.mkQApp()
16+
pg.setConfigOption('background', 'w')
17+
pg.setConfigOption('imageAxisOrder', 'row-major')
18+
19+
base_path = Path(__file__).parent
20+
file_path = (base_path / "flim_plot_gui.ui").resolve()
21+
22+
uiFile = file_path
23+
24+
WindowTemplate, TemplateBaseClass = pg.Qt.loadUiType(uiFile)
25+
26+
class MainWindow(TemplateBaseClass):
27+
28+
def __init__(self):
29+
super(TemplateBaseClass, self).__init__()
30+
31+
# Create the main window
32+
self.ui = WindowTemplate()
33+
self.ui.setupUi(self)
34+
35+
#set up ui signals
36+
self.ui.load_scan_pushButton.clicked.connect(self.open_pkl_file)
37+
self.ui.plot_intensity_sums_pushButton.clicked.connect(self.plot_intensity_sums)
38+
self.ui.plot_raw_hist_data_pushButton.clicked.connect(self.plot_raw_scan)
39+
self.ui.save_intensities_image_pushButton.clicked.connect(self.save_intensities_image)
40+
self.ui.save_intensities_array_pushButton.clicked.connect(self.save_intensities_array)
41+
self.ui.compare_checkBox.stateChanged.connect(self.switch_compare)
42+
self.ui.intensity_sums_viewBox.roi.sigRegionChanged.connect(self.line_profile_update_plot)
43+
self.ui.import_pkl_pushButton.clicked.connect(self.import_pkl_to_convert)
44+
self.ui.pkl_to_h5_pushButton.clicked.connect(self.pkl_to_h5)
45+
46+
self.show()
47+
48+
def open_pkl_file(self):
49+
""" Open FLIM scan file """
50+
try:
51+
self.filename = QtWidgets.QFileDialog.getOpenFileName(self)
52+
self.pkl_file = pickle.load(open(self.filename[0], 'rb'))
53+
except Exception as err:
54+
print(format(err))
55+
56+
def import_pkl_to_convert(self):
57+
""" Open pkl file to convert to h5 """
58+
try:
59+
self.pkl_to_convert = QtWidgets.QFileDialog.getOpenFileName(self)
60+
self.ui.result_textBrowser.append("Done Loading - .pkl to convert")
61+
except:
62+
pass
63+
64+
def plot_intensity_sums(self):
65+
try:
66+
data = self.pkl_file
67+
self.numb_pixels_X = int((data['Scan Parameters']['X scan size (um)'])/(data['Scan Parameters']['X step size (um)']))
68+
self.numb_pixels_Y = int((data['Scan Parameters']['Y scan size (um)'])/(data['Scan Parameters']['Y step size (um)']))
69+
self.x_step_size = float(data['Scan Parameters']['X step size (um)'])
70+
self.x_scan_size = float(data['Scan Parameters']['X scan size (um)'])
71+
self.y_step_size = float(data['Scan Parameters']['Y step size (um)'])
72+
self.y_scan_size = float(data['Scan Parameters']['Y scan size (um)'])
73+
74+
hist_data = data["Histogram data"]
75+
hist_data = np.reshape(hist_data, newshape=(hist_data.shape[0], self.numb_pixels_X*self.numb_pixels_Y))
76+
self.intensity_sums = np.sum(hist_data, axis=0) #sum intensities for each pixel
77+
self.intensity_sums = np.reshape(self.intensity_sums, newshape=(self.numb_pixels_X, self.numb_pixels_Y))
78+
self.ui.intensity_sums_viewBox.view.invertY(False) # stop y axis invert
79+
self.ui.intensity_sums_viewBox.setImage(self.intensity_sums, scale=
80+
(data['Scan Parameters']['X step size (um)'],
81+
data['Scan Parameters']['Y step size (um)']))
82+
self.ui.intensity_sums_viewBox.roi.setSize([self.x_scan_size, self.y_step_size]) #line roi
83+
scale = pg.ScaleBar(size=1,suffix='um')
84+
scale.setParentItem(self.ui.intensity_sums_viewBox.view)
85+
scale.anchor((1, 1), (1, 1), offset=(-30, -30))
86+
except Exception as err:
87+
print(format(err))
88+
89+
def line_profile_update_plot(self):
90+
""" Handle line profile for intensity sum viewbox """
91+
if hasattr(self, "intensity_sums"):
92+
roiPlot = self.ui.intensity_sums_viewBox.getRoiPlot()
93+
roiPlot.clear()
94+
roi = self.ui.intensity_sums_viewBox.roi
95+
96+
image = self.ui.intensity_sums_viewBox.getProcessedImage()
97+
98+
# Extract image data from ROI
99+
axes = (self.ui.intensity_sums_viewBox.axes['x'], self.ui.intensity_sums_viewBox.axes['y'])
100+
data, coords = roi.getArrayRegion(image.view(np.ndarray), self.ui.intensity_sums_viewBox.imageItem, axes, returnMappedCoords=True)
101+
102+
#calculate sums along columns in region
103+
sums_to_plot = np.sum(data, axis=0)
104+
105+
#get scan x-coordinates in region
106+
x_values = coords[1][0]
107+
108+
try:
109+
roiPlot.plot(x_values, sums_to_plot)
110+
except:
111+
pass
112+
113+
def plot_raw_scan(self):
114+
try:
115+
data = self.pkl_file
116+
self.numb_pixels_X = int((data['Scan Parameters']['X scan size (um)'])/(data['Scan Parameters']['X step size (um)']))
117+
self.numb_pixels_Y = int((data['Scan Parameters']['Y scan size (um)'])/(data['Scan Parameters']['Y step size (um)']))
118+
self.x_step_size = float(data['Scan Parameters']['X step size (um)'])
119+
self.x_scan_size = float(data['Scan Parameters']['X scan size (um)'])
120+
self.y_step_size = float(data['Scan Parameters']['Y step size (um)'])
121+
self.y_scan_size = float(data['Scan Parameters']['Y scan size (um)'])
122+
# TODO test line scan plots
123+
hist_data = data['Histogram data']
124+
125+
self.hist_image = np.reshape(hist_data, newshape=(hist_data.shape[0],self.numb_pixels_X,self.numb_pixels_Y))
126+
time_data = data['Time data']
127+
self.times = time_data[:, 0, 0]*1e-3
128+
self.ui.raw_hist_data_viewBox.view.invertY(False) # stops y-axis invert
129+
self.ui.raw_hist_data_viewBox.setImage(self.hist_image, scale=
130+
(data['Scan Parameters']['X step size (um)'],
131+
data['Scan Parameters']['Y step size (um)']), xvals=self.times)
132+
self.ui.raw_hist_data_viewBox.roi.setSize([self.x_scan_size, self.y_scan_size])
133+
# if self.ui.compare_checkBox.isChecked():
134+
# self.ui.imv2.setImage(self.hist_image, scale= (data['Scan Parameters']['X step size (um)'],
135+
# data['Scan Parameters']['Y step size (um)']), xvals=self.times)
136+
self.switch_compare()
137+
self.ui.raw_hist_data_viewBox.ui.roiBtn.clicked.connect(self.switch_compare)
138+
scale = pg.ScaleBar(size=1,suffix='um')
139+
scale.setParentItem(self.ui.raw_hist_data_viewBox.view)
140+
scale.anchor((1, 1), (1, 1), offset=(-30, -30))
141+
142+
except Exception as err:
143+
print(format(err))
144+
145+
def switch_compare(self):
146+
"""
147+
Handles compare checkbox. If checked, show second ROI on raw histogram data that user can use for comparison to first ROI.
148+
"""
149+
if self.ui.compare_checkBox.isChecked() and hasattr(self, "hist_image"):
150+
if not hasattr(self, "roi2"): #create roi if doesn't exist yet
151+
self.roi2 = pg.ROI(pos=[0,0], size=[int(self.x_scan_size/2), int(self.y_scan_size/2)], movable=True, pen='r')
152+
self.roi2.addScaleHandle([1, 1], [0, 0])
153+
self.roi2.addRotateHandle([0, 0], [1, 1])
154+
self.roi2.sigRegionChanged.connect(self.update_roi2_plot)
155+
self.ui.raw_hist_data_viewBox.addItem(self.roi2)
156+
self.update_roi2_plot()
157+
self.roi2.hide()
158+
self.roi2_plot.hide()
159+
if self.ui.raw_hist_data_viewBox.ui.roiBtn.isChecked():
160+
self.roi2.show()
161+
self.roi2_plot.show()
162+
else:
163+
self.roi2.hide()
164+
self.roi2_plot.hide()
165+
else: #if not checked, hide roi
166+
if hasattr(self, "roi2"):
167+
self.roi2.hide()
168+
self.roi2_plot.hide()
169+
170+
def update_roi2_plot(self):
171+
""" Update plot corresponding to second roi """
172+
#Adapted from pyqtgraph imageview sourcecode
173+
174+
image = self.ui.raw_hist_data_viewBox.getProcessedImage()
175+
176+
# Extract image data from ROI
177+
axes = (self.ui.raw_hist_data_viewBox.axes['x'], self.ui.raw_hist_data_viewBox.axes['y'])
178+
data, coords = self.roi2.getArrayRegion(image.view(np.ndarray), self.ui.raw_hist_data_viewBox.imageItem, axes, returnMappedCoords=True)
179+
if data is None:
180+
return
181+
182+
# Average data within entire ROI for each frame
183+
data = data.mean(axis=max(axes)).mean(axis=min(axes))
184+
xvals = self.ui.raw_hist_data_viewBox.tVals
185+
if hasattr(self, "roi2_plot"):
186+
self.roi2_plot.clear()
187+
self.roi2_plot = self.ui.raw_hist_data_viewBox.getRoiPlot().plot(xvals, data, pen='r')
188+
189+
def save_intensities_image(self):
190+
try:
191+
filename_ext = os.path.basename(self.filename[0])
192+
filename = os.path.splitext(filename_ext)[0] #get filename without extension
193+
save_to = os.getcwd() + "\\" + filename + "_intensity_sums.png"
194+
cpm.plot_confocal(self.intensity_sums, stepsize=np.abs(self.pkl_file['Scan Parameters']['X step size (um)']))
195+
cpm.plt.savefig(save_to, bbox_inches='tight', dpi=300)
196+
except:
197+
pass
198+
199+
def save_intensities_array(self):
200+
try:
201+
filename_ext = os.path.basename(self.filename[0])
202+
filename = os.path.splitext(filename_ext)[0] #get filename without extension
203+
save_to = os.getcwd() + "\\" + filename + "_intensity_sums.txt"
204+
np.savetxt(save_to, self.intensity_sums.T, fmt='%f') #save transposed intensity sums, as original array handles x in cols and y in rows
205+
except:
206+
pass
207+
208+
def pkl_to_h5(self):
209+
#Convert scan .pkl file into h5
210+
try:
211+
folder = os.path.dirname(self.pkl_to_convert[0])
212+
filename_ext = os.path.basename(self.pkl_to_convert[0])
213+
filename = os.path.splitext(filename_ext)[0] #get filename without extension
214+
pkl_file = pickle.load(open(self.pkl_to_convert[0], 'rb'))
215+
216+
h5_filename = folder + "/" + filename + ".h5"
217+
h5_file = h5py.File(h5_filename, "w")
218+
self.traverse_dict_into_h5(pkl_file, h5_file)
219+
except Exception as err:
220+
print(format(err))
221+
222+
def traverse_dict_into_h5(self, dictionary, h5_output):
223+
#Create an h5 file using .pkl with scan data and params
224+
for key in dictionary:
225+
if type(dictionary[key]) == dict: #if subdictionary, create a group
226+
group = h5_output.create_group(key)
227+
previous_dict = dictionary[key]
228+
self.traverse_dict_into_h5(dictionary[key], group) #traverse subdictionary
229+
else:
230+
if key == "Histogram data" or key == "Time data":
231+
h5_output.create_dataset(key, data=dictionary[key])
232+
else:
233+
h5_output.attrs[key] = dictionary[key] #if not dataset, create attribute
234+
235+
def close_application(self):
236+
choice = QtGui.QMessageBox.question(self, 'EXIT!',
237+
"Do you want to exit the app?",
238+
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
239+
if choice == QtGui.QMessageBox.Yes:
240+
sys.exit()
241+
else:
242+
pass
243+
244+
"""Run the Main Window"""
245+
def run():
246+
win = MainWindow()
247+
QtGui.QApplication.instance().exec_()
248+
return win
249+
250+
#Uncomment below if you want to run this as standalone
251+
#run()

0 commit comments

Comments
 (0)