Browse Source

added LE_LoadExp 665,667, 676 to direct load; minor bug fix

Ajayrama Kumaraswamy 1 year ago
parent
commit
b1598faa31

+ 2 - 2
view/flags_and_metadata_definitions/metadata_definition.csv

@@ -15,8 +15,8 @@ Stim2ON,stimulus,,stim2on,,,,onset in frames for second odorant (used only when
 Stim2ONms,stimulus,,stim2on_ms,,,,onset in ms for second odorant (used only when timings of one odorant has been given above),-1
 Stim2OFF,stimulus,,stim2off,,,,offset in frames for second odorant (used only when timings of one odorant has been given above),0
 Stim2Len,stimulus,,stim2Len,,,,length in ms for second odorant (used only when timings of one odorant has been given above),0
-Cycle,recording,ms,GDMfreq,"(“TimeIntervall”,)",trial_ticks,all,Sampling Period of the Ca imaging video data for the measurement (1000/Sampling frequency),1E-06
-SampFreq,recording,Hz,SampFreq,,frequency,,Sampling frequency of measurement,1000000
+Cycle,recording,ms,GDMfreq,"(“TimeIntervall”,)",trial_ticks,all,Sampling Period of the Ca imaging video data for the measurement (1000/Sampling frequency),200
+SampFreq,recording,Hz,SampFreq,,frequency,,Sampling frequency of measurement,200
 MTime,,,mtime,,m_time,,"time since first evidence that the animal is under the microscope, formatted as “HH:MM:SS.ssss”",“-00:00:00”
 Control,,,control,,kontrollmessung,,'Measu’ of the control measurement,0
 Pharma,treatment,,pharma,,treatment,,Pharmacological treatment applied,not set yet

+ 2 - 1
view/flags_and_metadata_definitions/setup_definitions.csv

@@ -6,5 +6,6 @@ LE_loadExp,Description
 33,"OME/generic TIF, single Wavelength"
 35,"Singe OME TIF file, Dual Wavelength (FURA)"
 665,"Synthetic data, type 665"
-666,"Synthetic data, type 666"
 667,"Synthetic data, type 667"
+676,"Synthetic data, type 676"
+

+ 8 - 4
view/gui/central_widget.py

@@ -2,6 +2,7 @@ import gc
 import logging
 import os
 import pathlib as pl
+import sys
 import traceback
 from inspect import currentframe, getframeinfo
 
@@ -298,8 +299,10 @@ class CentralWidget(QWidget):
                 lambda p1: [x / pd.Timedelta(seconds=1)
                             for x in p1.metadata["pulsed_stimuli_handler"].get_pulse_end_times()],
             "Measurement\nLabel": temp("ex_name"), "Raw File Name": temp("full_raw_data_path_str"),
-            "No. of frames": temp("frames"), "No. of Pixels along X": temp("format_x"),
-            "No. of Pixels along Y": temp("format_y")
+            "No. of frames": temp("frames"),
+            "Frames per second": lambda p1: p1.metadata.frequency,
+            "No. of Pixels along X": temp("format_x"),
+            "No. of Pixels along Y": temp("format_y"),
         }
 
         self.data_manager = DataManager(
@@ -310,7 +313,7 @@ class CentralWidget(QWidget):
                 "Stimulus", "Stimulus\nConcentration", "Component\nOdors",
                 "No. of pulses in stimuli", "Stimulus pulse start times\nrelative to imaging start (s)",
                 "Stimulus pulse end times\nrelative to imaging start (s)",
-                "No. of frames", "No. of Pixels along X", "No. of Pixels along Y",
+                "No. of frames", "Frames per second", "No. of Pixels along X", "No. of Pixels along Y",
                 "LE_loadExp", "LE_CalcMethod"]
         )
         self.data_manager.remove_data_signal.connect(self.remove_data)
@@ -858,7 +861,8 @@ class CentralWidget(QWidget):
             return
         except Exception as e:
 
-            QMessageBox.critical(self, f"VIEW encountered a {type(e).__name__}", str(e))
+            exception_formatted = traceback.format_exception(*sys.exc_info())
+            QMessageBox.critical(self, f"VIEW encountered an error!", "".join(exception_formatted))
 
         self.write_status(f"[failure] Save movie with new method")
 

+ 24 - 34
view/gui/direct_load.py

@@ -1,14 +1,15 @@
-from PyQt5.QtWidgets import QVBoxLayout, QMessageBox, QWidget
+from PyQt5.QtWidgets import QVBoxLayout, QMessageBox, QWidget, QPushButton
 from .file_selector_combobox import get_file_selector_combobox_using_settings
 from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject, QMetaObject
 from ..python_core.p1_class import Default_P1_Getter, P1SingleWavelengthTIF, \
     P1SingleWavelengthLSM, P1DualWavelengthTill, P1SingleWavelengthTill, P1DualWavelengthTIFSingleFile, \
-        P1SingleWavelengthLIF
+    P1SingleWavelengthLIF, P1SingleWavelength666, get_empty_p1
 from view.python_core.flags import FlagsManager
 import pathlib as pl
 import traceback
 import sys
 from abc import abstractmethod
+import tempfile
 
 
 # modified version of solution from https://stackoverflow.com/questions/9374063/remove-all-items-from-a-layout
@@ -67,6 +68,7 @@ def get_an_lsm_combobox(parent):
                           file_filter="LSM files(*.lsm)",
                           comment=None)
 
+
 def get_a_lif_combobox(parent):
     combobox_class = get_file_selector_combobox_using_settings(multiple_selection_allowed=True)
 
@@ -133,7 +135,7 @@ class BaseLoaderInterface(QObject):
 
     def check_read_data(self, flags, filenames):
 
-        p1 = self.get_p1_class()()  # here p1 has not data, i.e. empty
+        p1 = get_empty_p1(LE_loadExp=flags["LE_loadExp"], odor_conc=10)  # here p1 has not data, i.e. empty
         self.write_status(f"[working] Loading raw data directly from {filenames} using {p1.__class__.__name__}")
         try:
             p1.load_without_metadata(filenames=filenames, flags=flags)
@@ -157,10 +159,23 @@ class BaseLoaderInterface(QObject):
     def refresh_layout(self, widget):
         pass
 
-    @abstractmethod
-    def get_p1_class(self):
 
-        pass
+class SampleData666LoaderInterface(BaseLoaderInterface):
+
+    def __init__(self, parent):
+        super().__init__(parent)
+        self.temp_sample_dir = pl.Path(tempfile.gettempdir()) / "SampleDataPyView"
+        self.temp_sample_dir.mkdir(exist_ok=True)
+
+    def load_list_fake(self):
+        self.load_list([str(self.temp_sample_dir / "Fake")])
+
+    def refresh_layout(self, widget):
+
+        clear_layout(widget.layout())
+        button = QPushButton("&Load sample Data", widget)
+        button.clicked.connect(self.load_list_fake)
+        widget.layout().addWidget(button)
 
 
 class VIEWTIFFLoaderInterface(BaseLoaderInterface):
@@ -177,9 +192,6 @@ class VIEWTIFFLoaderInterface(BaseLoaderInterface):
 
         widget.layout().addWidget(view_tif_combobox)
 
-    def get_p1_class(self):
-        return P1SingleWavelengthTIF
-
 
 class TillSingleLoaderInterface(BaseLoaderInterface):
 
@@ -195,9 +207,6 @@ class TillSingleLoaderInterface(BaseLoaderInterface):
 
         widget.layout().addWidget(pst_combobox)
 
-    def get_p1_class(self):
-        return P1SingleWavelengthTill
-
 
 class TillDualLoaderInterface(BaseLoaderInterface):
 
@@ -234,10 +243,6 @@ class TillDualLoaderInterface(BaseLoaderInterface):
         else:
             return None
 
-    def get_p1_class(self):
-        
-        return P1DualWavelengthTill
-
 
 class LifSingleLoaderInterface(BaseLoaderInterface):
 
@@ -254,9 +259,6 @@ class LifSingleLoaderInterface(BaseLoaderInterface):
 
         widget.layout().addWidget(lif_combobox)
 
-    def get_p1_class(self):
-        return P1SingleWavelengthLIF
-
 
 class ZeissSingleLoaderInterface(BaseLoaderInterface):
 
@@ -273,20 +275,6 @@ class ZeissSingleLoaderInterface(BaseLoaderInterface):
 
         widget.layout().addWidget(lsm_combobox)
 
-    def get_p1_class(self):
-        return P1SingleWavelengthLSM
-
-
-class OmeFuraTiffInterface(VIEWTIFFLoaderInterface):
-
-    def __init__(self, parent):
-
-        super().__init__(parent)
-
-    def get_p1_class(self):
-
-        return P1DualWavelengthTIFSingleFile
-
 
 def get_loader_interface_class(LE_loadExp):
 
@@ -301,7 +289,9 @@ def get_loader_interface_class(LE_loadExp):
     elif LE_loadExp == 33:
         return VIEWTIFFLoaderInterface
     elif LE_loadExp == 35:
-        return OmeFuraTiffInterface
+        return VIEWTIFFLoaderInterface
+    elif LE_loadExp in (665, 667, 676):
+        return SampleData666LoaderInterface
     else:
         raise NotImplementedError
 

+ 21 - 31
view/python_core/measurement_list/importers.py

@@ -1,3 +1,4 @@
+import datetime
 import pathlib as pl
 from tillvisionio.vws import VWSDataManager
 import pandas as pd
@@ -102,15 +103,30 @@ class BaseImporter(ABC):
 
         pass
 
-    @abstractmethod
     def get_animal_tag_raw_data_mapping(self, files_chosen: list) -> dict:
         """
-        Parses the animal tag from raw data file names (<file_chosen>). Revises the raw data file names if necessary.
         Returns a one-element dictionary with the animal tag as key and list of (revised) raw data files as value.
-        :param list files_chosen: list of raw data file names
-        :rtype: dict
+
+        Parameters
+        ----------
+        files_chosen : list
+            list of lif files.
+
+        Returns
+        -------
+        dict
+            file names without path.
+
         """
-        pass
+        if len(files_chosen) == 0:
+            return {}
+        else:
+            dict2return = {}
+            for fle in files_chosen:
+                fle_path = pl.Path(fle)
+                dict2return[fle_path.name] = [fle]
+
+            return dict2return
 
     @abstractmethod
     def get_path_relative_to_data_dir(self, fle):
@@ -268,32 +284,6 @@ class LifImporter(BaseImporter):
         self.movie_data_extensions = [".lif"]  # possible extension of file containing data (calcium imaging movies)
         self.LE_loadExp = 21  # associated value of the flag LE_loadExp
 
-    def get_animal_tag_raw_data_mapping(self, files_chosen: list) -> dict:
-        """
-        Returns a one-element dictionary with the animal tag as key and list of (revised) raw data files as value.
-
-        Parameters
-        ----------
-        files_chosen : list
-            list of lif files.
-
-        Returns
-        -------
-        dict
-            file names without path.
-
-        """
-        if len(files_chosen) == 0:
-            return {}
-        else:
-            dict2return = {}
-            for fle in files_chosen:
-
-                fle_path = pl.Path(fle)
-                dict2return[fle_path.name] = [fle]
-
-            return dict2return
-
     def get_path_relative_to_data_dir(self, fle):
 
         for movie_data_extension in self.movie_data_extensions:

+ 38 - 6
view/python_core/p1_class/__init__.py

@@ -223,7 +223,7 @@ class P1SingleWavelengthAbstract(ABC):
         data_sampling_period = pd.to_timedelta(self.metadata['trial_ticks'], unit='ms')
         self.pulsed_stimuli_handler.initialize_stimulus_offset(flags["mv_correctStimulusOnset"], data_sampling_period)
 
-    def load_without_metadata(self, filenames, flags, sampling_rate=1e6):
+    def load_without_metadata(self, filenames, flags, sampling_rate=5):
         """
         load raw data in p1 structure directly, without other metadata
         :param sequence filenames: raw data file names, compatible with the flag `LE_loadExp`
@@ -353,6 +353,7 @@ class P1SingleWavelengthTIF(P1SingleWavelengthAbstract):
         data, _ = read_tif_2Dor3D(filename)
         return data
 
+
 class P1SingleWavelengthLIF(P1SingleWavelengthAbstract):
     """
     Load Leica .lif file data
@@ -381,7 +382,6 @@ class P1SingleWavelengthLIF(P1SingleWavelengthAbstract):
         return data
 
 
-
 class P1SingleWavelengthTill(P1SingleWavelengthAbstract):
 
     def __init__(self):
@@ -440,7 +440,7 @@ class P1SingleWavelengthLSM(P1SingleWavelengthAbstract):
         # selection of the first row is required as this function returns a one-row DataFrame
         row = lsm_importer.parse_metadata(fle=filenames[0], fle_ind=-2).iloc[0]
         # revise index names to be lower case
-        row.rename(index={x: x.lower() for x in row.index.values}, inplace=True)
+        # row.rename(index={x: x.lower() for x in row.index.values}, inplace=True)
         p1_metadata, extra_metadata = parse_p1_metadata_from_measurement_list_row(row)
         p1_metadata.dbb1 = filenames[0]
         label = pl.Path(filenames[0]).name.split(".")[0]
@@ -617,7 +617,7 @@ class P1DualWavelengthTill(P1DualWavelengthTIFTwoFiles):
 
 class P1SingleWavelength666(P1SingleWavelengthAbstract):
 
-    def __init__(self, peaksignal):
+    def __init__(self, peaksignal=10):
 
         super().__init__()
         self.peaksignal = peaksignal
@@ -633,9 +633,41 @@ class P1SingleWavelength666(P1SingleWavelengthAbstract):
             raw_data: np.ndarray
         """
 
-        raw_data66 = create_raw_data666(p1_metadata=metadata, peaksignal=self.peaksignal)
+        raw_data666 = create_raw_data666(p1_metadata=metadata, peaksignal=self.peaksignal)
 
-        return str(pl.Path(flags["STG_Datapath"]) / f"{metadata.dbb1}.fake"), raw_data66
+        return str(pl.Path(flags["STG_Datapath"]) / f"{metadata.dbb1}.fake"), raw_data666
+
+    def load_without_metadata(self, filenames, flags, sampling_rate=5):
+        """
+        load raw data in p1 structure directly, without other metadata
+        :param sequence filenames: raw data file names, compatible with the flag `LE_loadExp`
+        :param FlagManager flags:
+        :param sampling_rate: unused, hardcoded below
+        """
+
+        # for all other cases, it is better to not override the current method and instead override
+        # get_p1_metadata_from_filenames. However, I am overriding the current method as an exception as
+        # I need to make sure that stimulus information gets added, without which "loading", i.e., creating synthetic
+        # data would fail.
+
+        label = pl.Path(filenames[0]).name.split(".")[0]
+        fake_measurement_list_row = MetadataDefinition().get_default_row()
+        fake_measurement_list_row.update(
+            {
+                    "DBB1": label,
+                    "Label": label,
+                    # need to add stimulus information here as it is later needed when loading data, i.e., in this
+                    # case, creating synthetic data
+                    "StimON": 25,
+                    "StimOFF": 35,
+                    "Stim2ON": 65,
+                    "Stim2OFF": 75
+                }
+            )
+
+        p1_metadata, extra_metadata = parse_p1_metadata_from_measurement_list_row(fake_measurement_list_row)
+
+        self.load_from_metadata(p1_metadata=p1_metadata, flags=flags, extra_metadata=extra_metadata)
 
     def read_data(self, filename: str):