Skip to content

Commit 750f8b6

Browse files
fix update file_list
1 parent ce1605f commit 750f8b6

File tree

3 files changed

+197
-59
lines changed

3 files changed

+197
-59
lines changed

ephys/GUI/sessioninfo.py

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import uuid
22
import numpy as np
3+
from ephys import MetaData
34

45

56
class SessionInfo:
@@ -12,18 +13,52 @@ def __init__(self):
1213
self.theme = ""
1314
self.session_id = str(uuid.uuid4())
1415

15-
def set_file_list(self, file_list: list[str] | str | np.ndarray) -> None:
16-
if isinstance(file_list, str):
17-
self.file_list = [file_list]
18-
elif isinstance(file_list, np.ndarray):
19-
self.file_list = file_list.tolist()
16+
def set_attribute(
17+
self, attr_name: str, value: str | list[str] | np.ndarray
18+
) -> None:
19+
if hasattr(self, attr_name):
20+
if isinstance(value, str):
21+
value_list = [value]
22+
elif isinstance(value, np.ndarray):
23+
value_list = value.tolist()
24+
elif isinstance(value, list):
25+
value_list = value
26+
else:
27+
raise ValueError(
28+
"Value must be a string, list of strings, or numpy array."
29+
)
30+
setattr(self, attr_name, value_list)
2031
else:
21-
self.file_list = file_list
32+
raise AttributeError(
33+
f"Attribute '{attr_name}' does not exist in SessionInfo."
34+
)
2235

2336
def set_file_path(self, file_path: list[str] | str | np.ndarray) -> None:
24-
if isinstance(file_path, str):
25-
self.file_path = file_path
26-
elif isinstance(file_path, np.ndarray):
27-
self.file_path = file_path.tolist()
28-
else:
29-
self.file_path = file_path
37+
self.set_attribute("file_path", file_path)
38+
39+
def set_file_list(self, file_list: list[str] | str | np.ndarray) -> None:
40+
self.set_attribute("file_list", file_list)
41+
42+
def set_experimenter_name(
43+
self, experimenter_name: str | list[str] | np.ndarray
44+
) -> None:
45+
self.set_attribute("experimenter_name_val", experimenter_name)
46+
47+
def set_exp_date(self, exp_date: str | list[str] | np.ndarray) -> None:
48+
self.set_attribute("exp_date", exp_date)
49+
50+
def set_theme(self, theme: str) -> None:
51+
self.theme: str = theme
52+
53+
def set_current_user(self, current_user: str) -> None:
54+
self.current_user: str = current_user
55+
56+
def sync_metadata(self, meta_data: MetaData) -> None:
57+
if hasattr(meta_data, "experimenter"):
58+
self.set_experimenter_name(meta_data.get_experimenter())
59+
if hasattr(meta_data, "exp_date"):
60+
self.set_exp_date(meta_data.get_date_of_experiment())
61+
if hasattr(meta_data, "file_name"):
62+
self.set_file_list(meta_data.get_file_name())
63+
if hasattr(meta_data, "file_path"):
64+
self.set_file_path(meta_data.get_file_path())

ephys/GUI/sidemenu.py

Lines changed: 141 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,17 @@
1111
QLabel,
1212
)
1313

14-
from PySide6.QtGui import QPainter, QColor, QBrush
14+
from PySide6.QtGui import QPainter, QColor
1515
from PySide6.QtSvg import QSvgRenderer
1616

17-
from PySide6.QtCore import Qt, QDate
18-
from ephys.GUI.labfolder import LabfolderWindow, LabfolderLoginWindow
17+
from PySide6.QtCore import Qt, QDate, Signal, QObject, QRunnable, Slot
18+
from ephys.GUI.labfolder import LabfolderWindow
1919
from ephys.GUI.meta_data import MetaDataWindow
2020
from ephys.GUI.styles import apply_style
2121
from ephys.GUI.trace_view import TracePlotWindow
22-
from ephys.classes.experiment_objects import ExpData
22+
from ephys.classes.experiment_objects import ExpData, MetaData
2323
import ephys.GUI.GUI_config as config
24+
import numpy as np
2425

2526
if TYPE_CHECKING:
2627
from ephys.GUI.gui_app import MainWindow
@@ -149,6 +150,7 @@ def change_style(self) -> None:
149150
header_format.setBackground(QColor("blue"))
150151
header_format.setForeground(QColor("white"))
151152
self.main_window.session_info.theme = self.theme
153+
self.main_window.highlight_switch.setChecked(False)
152154

153155
def connect_to_main_window(self) -> None:
154156
self.main_window.session_info.current_user = self.current_user_label.text()
@@ -159,50 +161,75 @@ def connect_to_main_window(self) -> None:
159161

160162
def file_loading(
161163
self,
162-
file_path: list | str = "data/WCP/WholeCell/180207_005.cc_step_40_comp.1.wcp",
164+
file_path: list | str = "",
163165
):
166+
if file_path == "":
167+
print("No files selected")
168+
return None
164169
self.clicked_status = True
165170
experimenter_name = self.main_window.session_info.experimenter_name_val
166171
print(f"Experimenter name: {experimenter_name}")
167172
print("Date of experiment: ", self.main_window.session_info.exp_date)
168-
173+
# if isinstance(self.main_window.session_info.file_path, list):
174+
# new_files = np.array(file_path)[
175+
# np.invert(np.isin(file_path, self.main_window.session_info.file_list))
176+
# ].tolist()
177+
print(f"File: {file_path}")
169178
if self.main_window.data is None:
170-
data = ExpData(file_path=file_path, experimenter=experimenter_name)
179+
# to do add worker with slot
180+
data_worker = DataLoader(
181+
file_path=file_path, experimenter=experimenter_name
182+
)
183+
data_worker.signals.result.connect(self.on_data_loaded)
184+
self.main_window.threadpool.start(data_worker)
185+
print("DataWorker is an instance of DataLoader")
186+
# data = ExpData(file_path=file_path, experimenter=experimenter_name)
171187
else:
172188
print("Data already loaded, adding file to existing data")
173-
print(self.main_window.data.meta_data_summary())
174-
data: ExpData = self.main_window.data
175-
data.add_file(file_path=file_path, experimenter=experimenter_name)
189+
new_files = self.main_window.data.new_file_paths(file_path)
190+
print("New files to add: ", new_files)
191+
self.main_window.data.add_file(
192+
file_path=new_files, experimenter=experimenter_name
193+
)
194+
if isinstance(self.main_window.data, ExpData):
195+
self.main_window.session_info.sync_metadata(self.main_window.data.meta_data)
176196

177197
# data = DataLoader(file_path=file_path, experimenter_name=experimenter_name)
178198
# self.main_window.threadpool.start(data)
179-
if data is None:
180-
print("Data could not be loaded")
181-
self.combobox.clear()
182-
183-
# data = data.get_data()
184-
self.file_list = [
185-
file_info["file_name"] for file_info in data.meta_data.file_info
199+
# The rest of the logic is now handled in on_data_loaded for new data
200+
if self.main_window.data is not None and isinstance(
201+
self.main_window.data, ExpData
202+
):
203+
# does clearing not work?
204+
self.combobox.clear()
205+
self.file_list = self.main_window.data.meta_data.get_file_name()
206+
self.file_paths = self.main_window.data.meta_data.get_file_path()
207+
208+
print("Data loaded successfully")
209+
print(f"File list: {self.file_list}")
210+
print("File_path:", file_path)
211+
if isinstance(self.main_window.data, ExpData):
212+
print(self.main_window.data.meta_data_summary())
213+
214+
# make for every file a new tab on the main window
215+
# check if tab already exists
216+
self.update_plot_tab()
217+
self.refresh_file_list()
218+
219+
def check_new_tabs(self, file_list: list[str] | str) -> list[str]:
220+
"""Check which files in file_list do not have a tab yet.
221+
Args:
222+
file_list (list[str] | str): List of file names to check.
223+
Returns:
224+
list[str]: List of file names that do not have a tab yet.
225+
"""
226+
if isinstance(file_list, str):
227+
file_list = [file_list]
228+
tabl_list = [
229+
self.main_window.trace_plot.tabText(tab_index)
230+
for tab_index in range(self.main_window.trace_plot.count())
186231
]
187-
self.main_window.data = data
188-
print("Data loaded successfully")
189-
print(f"File list: {self.file_list}")
190-
print(f"Clicked status: {self.clicked_status}")
191-
if isinstance(self.main_window.data, ExpData):
192-
print(self.main_window.data.meta_data_summary())
193-
194-
# make for every file a new tab on the main window
195-
for i, file_name in enumerate(self.file_list):
196-
print(f"File {i}: {file_name}")
197-
# Create a new tab for each file
198-
199-
trace_plot = TracePlotWindow(
200-
main_window=self.main_window, file_name=file_name
201-
)
202-
trace_plot.add_trace_plot(trace=self.main_window.data.protocols[i])
203-
self.main_window.trace_plot.addTab(trace_plot, file_name)
204-
205-
self.refresh_file_list()
232+
return list(set(file_list) - set(tabl_list))
206233

207234
def choose_file(self) -> None:
208235
# Store the dialog as an instance attribute to prevent it from being deleted
@@ -214,13 +241,9 @@ def choose_file(self) -> None:
214241
"data/WCP/WholeCell",
215242
"All supported (*.wcp and *.abf);;WCP files (*.wcp);;ABF files (*.abf)",
216243
)[0]
217-
# if not file_path:
218-
# print("No files selected")
219-
# return None
244+
245+
print("choose files: ", file_path)
220246
self.file_loading(file_path)
221-
if isinstance(file_path, str):
222-
file_path = [file_path]
223-
self.main_window.session_info.file_list = file_path
224247

225248
def add_meta_data(self) -> None:
226249
from ephys.GUI.meta_data import MetaDataWindow
@@ -253,11 +276,52 @@ def refresh_file_list(self) -> None:
253276
"""
254277
self.combobox.clear()
255278
if self.main_window.data is not None:
256-
self.combobox.addItems(
257-
self.main_window.data.meta_data_summary()["file_name"]
279+
self.combobox.addItems(self.main_window.data.meta_data.get_file_name())
280+
281+
# get current tab
282+
self.combobox.setCurrentText(
283+
self.main_window.trace_plot.tabText(
284+
self.main_window.trace_plot.currentIndex()
258285
)
286+
)
287+
259288
print("File list refreshed")
260289

290+
def on_data_loaded(self, data: ExpData) -> None:
291+
# find why it is duplicate
292+
"""
293+
Slot to handle the result from DataLoader.
294+
"""
295+
296+
self.main_window.data = data
297+
self.combobox.clear()
298+
self.file_list = data.meta_data.get_file_name()
299+
self.file_paths = data.meta_data.get_file_path()
300+
print("Data loaded successfully")
301+
print(f"File list: {self.file_list}")
302+
print(f"Clicked status: {getattr(self, 'clicked_status', None)}")
303+
if isinstance(self.main_window.data, ExpData):
304+
print(self.main_window.data.meta_data_summary())
305+
self.update_plot_tab()
306+
self.refresh_file_list()
307+
308+
def update_plot_tab(self) -> None:
309+
if isinstance(self.main_window.data, ExpData):
310+
new_tabs = self.check_new_tabs(self.file_list)
311+
for i, file_name in enumerate(self.file_list):
312+
if file_name not in new_tabs:
313+
continue
314+
print(f"File {i}: {file_name}")
315+
# Create a new tab for each file
316+
print(self.file_paths[i])
317+
trace_plot = TracePlotWindow(
318+
main_window=self.main_window, file_name=self.file_paths[i]
319+
)
320+
trace_plot.add_trace_plot(trace=self.main_window.data.protocols[i])
321+
self.main_window.trace_plot.addTab(trace_plot, file_name)
322+
else:
323+
print("No data loaded yet.")
324+
261325

262326
class SideMenuContainer(QWidget):
263327
def __init__(self) -> None:
@@ -274,3 +338,36 @@ def paintEvent(self, event) -> None:
274338
self.svg_renderer.render(painter, self.rect())
275339
else:
276340
super().paintEvent(event)
341+
342+
343+
class DataLoaderSignals(QObject):
344+
345+
finished = Signal()
346+
error = Signal(object)
347+
result = Signal(object)
348+
progress = Signal(int)
349+
350+
351+
class DataLoader(QRunnable):
352+
353+
def __init__(self, file_path: str | list[str], experimenter: str):
354+
super().__init__()
355+
self.file_path = file_path
356+
self.experimenter = experimenter
357+
self.signals = DataLoaderSignals()
358+
359+
@Slot()
360+
def run(self):
361+
# Load data from the file
362+
try:
363+
data = self.load_data(self.file_path, self.experimenter)
364+
except Exception as e:
365+
self.signals.error.emit(e)
366+
else:
367+
self.signals.result.emit(data)
368+
finally:
369+
self.signals.finished.emit()
370+
371+
def load_data(self, file_path: str | list[str], experimenter: str) -> object:
372+
# Implement the data loading logic here
373+
return ExpData(file_path=file_path, experimenter=experimenter)

ephys/classes/experiment_objects.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,9 @@ def get_experiment_attribute(self, attribute: str) -> list[str]:
399399
list[str]: The values of the specified attribute(s) from the ExperimentInfo object.
400400
"""
401401
# check that attribute exists
402-
if attribute not in self.experiment_info[0]:
402+
if self.experiment_info.size == 0:
403+
return []
404+
elif attribute not in self.experiment_info[0]:
403405
raise ValueError(f"Attribute '{attribute}' not found in experiment_info.")
404406
else:
405407
return [
@@ -418,7 +420,9 @@ def get_file_attribute(self, attribute: str) -> list[str]:
418420
list[str]: The values of the specified attribute(s) from the MetaData object.
419421
"""
420422
# check that attribute exists
421-
if attribute not in self.file_info[0]:
423+
if self.file_info.size == 0:
424+
return []
425+
elif attribute not in self.file_info[0]:
422426
raise ValueError(f"Attribute '{attribute}' not found in file_info.")
423427
else:
424428
return [file[attribute] for file in self.file_info if attribute in file]
@@ -434,7 +438,9 @@ def get_subject_attribute(self, attribute: str) -> list[str]:
434438
list[str]: The values of the specified attribute(s) from the SubjectInfo object.
435439
"""
436440
# check that attribute exists
437-
if attribute not in self.subject_info[0]:
441+
if self.subject_info.size == 0:
442+
return []
443+
elif attribute not in self.subject_info[0]:
438444
raise ValueError(f"Attribute '{attribute}' not found in subject_info.")
439445
else:
440446
return [

0 commit comments

Comments
 (0)