direct_load.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. from PyQt5.QtWidgets import QVBoxLayout, QMessageBox, QWidget, QPushButton
  2. from .file_selector_combobox import get_file_selector_combobox_using_settings
  3. from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject, QMetaObject
  4. from ..python_core.p1_class import Default_P1_Getter, P1SingleWavelengthTIF, \
  5. P1SingleWavelengthLSM, P1DualWavelengthTill, P1SingleWavelengthTill, P1DualWavelengthTIFSingleFile, \
  6. P1SingleWavelengthLIF, P1SingleWavelength666, get_empty_p1
  7. from view.python_core.flags import FlagsManager
  8. import pathlib as pl
  9. import traceback
  10. import sys
  11. from abc import abstractmethod
  12. import tempfile
  13. # modified version of solution from https://stackoverflow.com/questions/9374063/remove-all-items-from-a-layout
  14. def clear_layout(layout):
  15. if layout is not None:
  16. while layout.count():
  17. item = layout.takeAt(0)
  18. widget = item.widget()
  19. if widget is not None:
  20. widget.setParent(None)
  21. else:
  22. clear_layout(item.layout())
  23. class DirectDataLoader(QWidget):
  24. data_loaded_signal = pyqtSignal(dict, FlagsManager)
  25. def __init__(self, parent, default_LE_loadExp=3):
  26. super().__init__(parent=parent)
  27. vbox = QVBoxLayout(self)
  28. self.refresh_layout(default_LE_loadExp)
  29. @pyqtSlot(int)
  30. def refresh_layout(self, LE_loadExp):
  31. loader_interface_class = get_loader_interface_class(LE_loadExp)
  32. self.loader_interface = loader_interface_class(self)
  33. self.loader_interface.refresh_layout(self)
  34. self.loader_interface.data_loaded_signal.connect(self.data_loaded_signal)
  35. def get_a_pst_combobox(parent, multiple_selection_allowed=True):
  36. combobox_class = get_file_selector_combobox_using_settings(multiple_selection_allowed=multiple_selection_allowed)
  37. return combobox_class(parent=parent,
  38. groupbox_title="Till Vision Raw Data File(s)",
  39. use_list_in_settings="raw data files",
  40. settings_list_value_filter=lambda x: x.endswith(".pst"),
  41. default_directory=None,
  42. file_type="PST",
  43. file_filter="PST files(*.pst)",
  44. comment=None)
  45. def get_an_lsm_combobox(parent):
  46. combobox_class = get_file_selector_combobox_using_settings(multiple_selection_allowed=True)
  47. return combobox_class(parent=parent,
  48. groupbox_title="Zeiss Raw Data File(s)",
  49. use_list_in_settings="raw data files",
  50. settings_list_value_filter=lambda x: x.endswith(".lsm"),
  51. default_directory=None,
  52. file_type="LSM",
  53. file_filter="LSM files(*.lsm)",
  54. comment=None)
  55. def get_a_lif_combobox(parent):
  56. combobox_class = get_file_selector_combobox_using_settings(multiple_selection_allowed=True)
  57. return combobox_class(parent=parent,
  58. groupbox_title="Leica .lif Data File(s)",
  59. use_list_in_settings="raw data files",
  60. settings_list_value_filter=lambda x: x.endswith(".lif"),
  61. default_directory=None,
  62. file_type="Lif",
  63. file_filter="Llif files(*.lif)",
  64. comment=None)
  65. def get_a_tiff_combobox(parent):
  66. combobox_class = get_file_selector_combobox_using_settings(multiple_selection_allowed=True)
  67. return combobox_class(parent=parent,
  68. groupbox_title="VIEW-tif File(s)",
  69. use_list_in_settings="raw data files",
  70. settings_list_value_filter=lambda x: x.endswith(".tif") or x.endswith(".tiff"),
  71. default_directory=None,
  72. file_type="TIF",
  73. file_filter="TIF files(*.tif *.tiff)",
  74. comment=None)
  75. class BaseLoaderInterface(QObject):
  76. data_loaded_signal = pyqtSignal(dict, FlagsManager)
  77. def __init__(self, parent):
  78. super().__init__(parent)
  79. self.default_p1_getter = Default_P1_Getter()
  80. def write_status(self, msg):
  81. self.parent().parent().parent().parent().write_status(msg)
  82. @pyqtSlot(list)
  83. @pyqtSlot(str)
  84. def load_list(self, filenames):
  85. filenames = self.check_revise_filenames(filenames)
  86. temp_dir = pl.Path(filenames[0][0]).parent / "temp_dir_for_view_analyses"
  87. temp_dir.mkdir(exist_ok=True)
  88. if filenames is not None:
  89. current_flags = self.parent().parent().parent().parent().flags.copy()
  90. # by default, compound path flags are not set, so set to parent of the raw files
  91. for flag_name in current_flags.compound_path_flags:
  92. current_flags.update_flags({flag_name: str(temp_dir)})
  93. current_flags.update_flags({"STG_Datapath": str(temp_dir.parent)})
  94. label_p1_mapping = {}
  95. for filename in filenames:
  96. p1 = self.check_read_data(current_flags, filename)
  97. if p1 is not None:
  98. p1.calculate_signals(current_flags)
  99. label_p1_mapping[p1.metadata.ex_name] = p1
  100. if label_p1_mapping:
  101. self.data_loaded_signal.emit(label_p1_mapping, current_flags)
  102. def check_read_data(self, flags, filenames):
  103. p1 = get_empty_p1(LE_loadExp=flags["LE_loadExp"], odor_conc=10) # here p1 has not data, i.e. empty
  104. self.write_status(f"[working] Loading raw data directly from {filenames} using {p1.__class__.__name__}")
  105. try:
  106. p1.load_without_metadata(filenames=filenames, flags=flags)
  107. except Exception as e:
  108. exception_formatted = traceback.format_exception(*sys.exc_info())
  109. QMessageBox.critical(self.parent(), "Error reading file",
  110. f"Please check {filenames}.\n\n"
  111. f"Complete error message:\n"
  112. f"\n{''.join(exception_formatted)}")
  113. self.write_status(f"[failure] Loading raw data directly from {filenames}")
  114. return None
  115. self.write_status(f"[success] Loading raw data directly from {filenames}")
  116. return p1
  117. def check_revise_filenames(self, filenames):
  118. return [[x] for x in filenames]
  119. @abstractmethod
  120. def refresh_layout(self, widget):
  121. pass
  122. class SampleData666LoaderInterface(BaseLoaderInterface):
  123. def __init__(self, parent):
  124. super().__init__(parent)
  125. self.temp_sample_dir = pl.Path(tempfile.gettempdir()) / "SampleDataPyView"
  126. self.temp_sample_dir.mkdir(exist_ok=True)
  127. def load_list_fake(self):
  128. self.load_list([str(self.temp_sample_dir / "Fake")])
  129. def refresh_layout(self, widget):
  130. clear_layout(widget.layout())
  131. button = QPushButton("&Load sample Data", widget)
  132. button.clicked.connect(self.load_list_fake)
  133. widget.layout().addWidget(button)
  134. class VIEWTIFFLoaderInterface(BaseLoaderInterface):
  135. def __init__(self, parent):
  136. super().__init__(parent)
  137. def refresh_layout(self, widget):
  138. clear_layout(widget.layout())
  139. view_tif_combobox = get_a_tiff_combobox(widget)
  140. view_tif_combobox.return_filenames_signal.connect(self.load_list)
  141. widget.layout().addWidget(view_tif_combobox)
  142. class TillSingleLoaderInterface(BaseLoaderInterface):
  143. def __init__(self, parent):
  144. super().__init__(parent)
  145. def refresh_layout(self, widget):
  146. clear_layout(widget.layout())
  147. pst_combobox = get_a_pst_combobox(widget, multiple_selection_allowed=True)
  148. pst_combobox.return_filenames_signal.connect(self.load_list)
  149. widget.layout().addWidget(pst_combobox)
  150. class TillDualLoaderInterface(BaseLoaderInterface):
  151. def __init__(self, parent):
  152. super().__init__(parent)
  153. def refresh_layout(self, widget):
  154. clear_layout(widget.layout())
  155. self.pst_1_combobox = get_a_pst_combobox(widget, multiple_selection_allowed=False)
  156. # for the case when pst2 combobox is selected before pst1 combobox
  157. self.pst_1_combobox.return_filename_signal.connect(self.load_list)
  158. widget.layout().addWidget(self.pst_1_combobox)
  159. self.pst_2_combobox = get_a_pst_combobox(widget, multiple_selection_allowed=False)
  160. # for the case when pst1 combobox is selected before pst2 combobox
  161. self.pst_2_combobox.return_filename_signal.connect(self.load_list)
  162. widget.layout().addWidget(self.pst_2_combobox)
  163. @pyqtSlot(str)
  164. def check_revise_filenames(self, filenames):
  165. dbb1_filename = self.pst_1_combobox.get_current_entry()
  166. dbb2_filename = self.pst_2_combobox.get_current_entry()
  167. # load data and return only if both dbb1 and dbb2 files have been selected
  168. if dbb1_filename is not None and dbb2_filename is not None:
  169. return [[dbb1_filename, dbb2_filename]]
  170. else:
  171. return None
  172. class LifSingleLoaderInterface(BaseLoaderInterface):
  173. def __init__(self, parent):
  174. super().__init__(parent)
  175. def refresh_layout(self, widget):
  176. clear_layout(widget.layout())
  177. lif_combobox = get_a_lif_combobox(widget)
  178. lif_combobox.return_filenames_signal.connect(self.load_list)
  179. widget.layout().addWidget(lif_combobox)
  180. class ZeissSingleLoaderInterface(BaseLoaderInterface):
  181. def __init__(self, parent):
  182. super().__init__(parent)
  183. def refresh_layout(self, widget):
  184. clear_layout(widget.layout())
  185. lsm_combobox = get_an_lsm_combobox(widget)
  186. lsm_combobox.return_filenames_signal.connect(self.load_list)
  187. widget.layout().addWidget(lsm_combobox)
  188. def get_loader_interface_class(LE_loadExp):
  189. if LE_loadExp == 3:
  190. return TillSingleLoaderInterface
  191. elif LE_loadExp == 4:
  192. return TillDualLoaderInterface
  193. elif LE_loadExp == 20:
  194. return ZeissSingleLoaderInterface
  195. elif LE_loadExp == 21:
  196. return LifSingleLoaderInterface
  197. elif LE_loadExp == 33:
  198. return VIEWTIFFLoaderInterface
  199. elif LE_loadExp == 35:
  200. return VIEWTIFFLoaderInterface
  201. elif LE_loadExp in (665, 667, 676):
  202. return SampleData666LoaderInterface
  203. else:
  204. raise NotImplementedError