Пример #1
0
    def show_data(self,
                  datas,
                  temp_data=False,
                  nav_axes=None,
                  is_spread=False,
                  scan_type='',
                  **kwargs):
        """Display datas as a hyperspaced dataset
        only one numpy ndarray should be used
        """
        self.is_spread = is_spread
        self.ui.spread_widget.setVisible(is_spread)

        self.scan_type = scan_type
        self.data_buffer = []
        self.data_to_export = OrderedDict(
            name=self.title,
            data0D=OrderedDict(),
            data1D=OrderedDict(),
            data2D=OrderedDict(),
            dataND=OrderedDict(),
        )
        self.data_to_export['dataND']['CH000'] = OrderedDict(data=datas,
                                                             source='raw',
                                                             nav_axes=nav_axes)
        for key in kwargs:
            self.data_to_export['dataND']['CH000'][key] = kwargs[key]
        self._datas = datas
        self.datas = Signal(datas)
        self.datas_settings = kwargs
        self.restore_nav_axes(kwargs, nav_axes=nav_axes)
        self.set_nav_shapes()

        try:
            if self.data_axes is not None:
                if datas.ndim != len(
                        self.data_axes) or self.get_selected_axes_indexes(
                        ) != nav_axes:
                    self.set_nav_axes(
                        datas.ndim, nav_axes
                    )  #init the list of axes and set the managers to nav_axes
            else:
                self.set_nav_axes(
                    datas.ndim, nav_axes
                )  #init the list of axes and set the managers to nav_axes

            #self.datas=hs.signals.BaseSignal(datas)

            self.update_data_signal()
            self.settings.child('data_shape_settings',
                                'data_shape_init').setValue(str(datas.shape))
            self.settings.child('data_shape_settings', 'data_shape').setValue(
                self.get_data_dimension())
            self.set_data(self.datas, temp_data=temp_data, **kwargs)

        except Exception as e:
            logger.exception(str(e))
            self.update_status(utils.getLineInfo() + str(e), self.wait_time,
                               'log')
Пример #2
0
    def update_data_signal(self):
        try:
            axes_nav = [len(self.data_axes)-ind-1 for ind in self.get_selected_axes_indexes()]
            axes_signal = [ax for ax in self.data_axes if ax not in axes_nav]
            self.datas = Signal(self._datas)
            self.datas = self.datas.transpose(signal_axes=axes_signal, navigation_axes=axes_nav)

        except Exception as e:
            logger.exception(str(e))
            self.update_status(utils.getLineInfo()+str(e), self.wait_time, 'log')
Пример #3
0
class ViewerND(QtWidgets.QWidget, QObject):
    """

        ======================== =========================================
        **Attributes**            **Type**

        *dockarea*                instance of pyqtgraph.DockArea
        *mainwindow*              instance of pyqtgraph.DockArea
        *title*                   string
        *waitime*                 int
        *x_axis*                  float array
        *y_axis*                  float array
        *data_buffer*             list of data
        *ui*                      QObject
        ======================== =========================================

        Raises
        ------
        parent Exception
            If parent argument is None in constructor abort

        See Also
        --------
        set_GUI


        References
        ----------
        PyQt5, pyqtgraph, QtWidgets, QObject

    """
    command_DAQ_signal = pyqtSignal(list)
    log_signal = pyqtSignal(str)
    data_to_export_signal = pyqtSignal(OrderedDict) #edict(name=self.DAQ_type,data0D=None,data1D=None,data2D=None)


    def __init__(self, parent=None):
        QLocale.setDefault(QLocale(QLocale.English, QLocale.UnitedStates))
        super(ViewerND, self).__init__()
        # if parent is None:
        #     raise Exception('no valid parent container, expected dockarea')
            # parent=DockArea()
            # exit(0)

        if parent is None:
            area = DockArea()
            area.show()
            self.area = area

        elif isinstance(parent, QtWidgets.QWidget):
            area = DockArea()
            self.area = area
            parent.setLayout(QtWidgets.QVBoxLayout())
            parent.layout().addWidget(area)
        elif isinstance(parent, DockArea):
            self.area = parent

        self.area = area

        self.wait_time = 2000
        self.viewer_type = 'DataND'  # ☺by default but coul dbe used for 3D visualization
        self.distribution = 'uniform'
        self.nav_axes_viewers = []
        self.nav_axes_dicts = []

        self.x_axis = dict(data=None, label='', units='')
        self.y_axis = dict(data=None, label='', units='')

        self.data_buffer = []  # convenience list to store 0D data to be displayed
        self.datas = None
        self.datas_settings = None
        # set default data shape case
        self.data_axes = None
        # self.set_nav_axes(3)
        self.ui = QObject()  # the user interface
        self.set_GUI()
        self.setup_spread_UI()
        self.title = ""
        self.data_to_export = OrderedDict(name=self.title, data0D=OrderedDict(), data1D=OrderedDict(),
                                          data2D=OrderedDict(),
                                          dataND=OrderedDict())



    @pyqtSlot(OrderedDict)
    def export_data(self, datas):
        self.data_to_export['acq_time_s'] = datetime.datetime.now().timestamp()
        for key in datas.keys():
            if key in self.data_to_export.keys():
                if isinstance(datas[key], OrderedDict):
                    if list(datas[key].keys()) != []:
                        self.data_to_export[key].update(datas[key])
        self.data_to_export_signal.emit(self.data_to_export)

    def get_data_dimension(self):
        try:
            dimension = "("
            for ind, ax in enumerate(self.datas.axes_manager.navigation_shape):
                if ind != len(self.datas.axes_manager.navigation_shape) - 1:
                    dimension += str(ax) + ','
                else:
                    dimension += str(ax) + '|'
            for ind, ax in enumerate(self.datas.axes_manager.signal_shape):
                if ind != len(self.datas.axes_manager.signal_shape) - 1:
                    dimension += str(ax) + ','
                else:
                    dimension += str(ax) + ')'
            return dimension
        except Exception as e:
            self.update_status(utils.getLineInfo() + str(e), self.wait_time, log='log')
            logger.exception(str(e))
            return ""


    def parameter_tree_changed(self,param,changes):
        """
            Foreach value changed, update :
                * Viewer in case of **DAQ_type** parameter name
                * visibility of button in case of **show_averaging** parameter name
                * visibility of naverage in case of **live_averaging** parameter name
                * scale of axis **else** (in 2D pymodaq type)

            Once done emit the update settings signal to link the commit.

            =============== =================================== ================================================================
            **Parameters**    **Type**                           **Description**
            *param*           instance of ppyqtgraph parameter   the parameter to be checked
            *changes*         tuple list                         Contain the (param,changes,info) list listing the changes made
            =============== =================================== ================================================================

            See Also
            --------
            change_viewer, daq_utils.custom_parameter_tree.iter_children
        """
        try:
            for param, change, data in changes:
                path = self.settings.childPath(param)
                if path is not None:
                    childName = '.'.join(path)
                else:
                    childName = param.name()
                if change == 'childAdded':
                    pass

                elif change == 'value':
                    pass
                    #if param.name()=='navigator_axes':
                    #    self.update_data_signal()
                    #    self.settings.child('data_shape_settings', 'data_shape').setValue(str(datas_transposed))
                    #    self.set_data(self.datas)


        except Exception as e:
            logger.exception(str(e))
            self.update_status(utils.getLineInfo()+str(e),self.wait_time,'log')

    def set_axis(self, Npts):
        """
            | Set axis values from node and a linspace regular distribution

            ================ ======================= ==========================================
            **Parameters**     **Type**                **Description**

             *node*           tables Group instance   the root node of the local treated tree
            ================ ======================= ==========================================

            Returns
            -------
            float array
                the computed values axis.

        """
        axis = np.linspace(0, Npts, Npts, endpoint=False)
        return axis


    def restore_nav_axes(self, navigation_axes, nav_axes=None):
        if nav_axes is None:
            N_nav_axes = len(self.datas.data.shape)
        else:
            N_nav_axes = len(nav_axes)
        nav_axes_dicts = []
        sorted_indexes = []
        for k in navigation_axes:
            if 'nav' in k:
                if navigation_axes[k]['nav_index'] < N_nav_axes:
                    sorted_indexes.append(navigation_axes[k]['nav_index'])
                    nav_axes_dicts.append(copy.deepcopy(navigation_axes[k]))

        for ind in range(N_nav_axes):  # in case there was no nav axes in kwargs
            if ind not in sorted_indexes:
                sorted_indexes.append(ind)
                nav_axes_dicts.append(Axis(nav_index=ind, label=f'Nav {ind:02d}'))
                N = self.datas.data.shape[ind]
                nav_axes_dicts[-1]['data'] = np.linspace(0, N-1, N)

        # sort nav axes:
        sorted_index = np.argsort(sorted_indexes)
        self.nav_axes_dicts = []
        for ind in sorted_index:
            self.nav_axes_dicts.append(nav_axes_dicts[ind])

    def set_data(self, datas_transposed, temp_data=False, restore_nav_axes=True, **kwargs):
        """
        """
        try:

            if restore_nav_axes:
                nav_axes = dict([])
                for ind, ax in enumerate(self.nav_axes_dicts):
                    nav_axes[f'nav_{ind}'] = ax
                self.restore_nav_axes(nav_axes)

            ##########################################################################
            #display the correct signal viewer
            if len(datas_transposed.axes_manager.signal_shape) == 0: #signal data are 0D
                self.ui.viewer1D.parent.setVisible(True)
                self.ui.viewer2D.parent.setVisible(False)
            elif len(datas_transposed.axes_manager.signal_shape) == 1: #signal data are 1D
                self.ui.viewer1D.parent.setVisible(True)
                self.ui.viewer2D.parent.setVisible(False)
            elif len(datas_transposed.axes_manager.signal_shape) == 2: #signal data are 2D
                self.ui.viewer1D.parent.setVisible(False)
                self.ui.viewer2D.parent.setVisible(True)
            self.x_axis = Axis()
            self.y_axis = Axis()
            if len(datas_transposed.axes_manager.signal_shape) == 1 or len(datas_transposed.axes_manager.signal_shape) == 2:#signal data are 1D

                if 'x_axis' in kwargs:
                    if not isinstance(kwargs['x_axis'], dict):
                        self.x_axis['data'] = kwargs['x_axis'][:]
                        self.x_axis = kwargs['x_axis']
                    else:
                        self.x_axis = copy.deepcopy(kwargs['x_axis'])
                else:
                    self.x_axis['data'] = self.set_axis(datas_transposed.axes_manager.signal_shape[0])
                if 'y_axis' in kwargs:
                    self.ui.viewer1D.set_axis_label(axis_settings=dict(orientation='left',
                                                                       label=kwargs['y_axis']['label'],
                                                                       units=kwargs['y_axis']['units']))


            if len(datas_transposed.axes_manager.signal_shape)==2:#signal data is 2D
                if 'y_axis' in kwargs:
                    if not isinstance(kwargs['y_axis'], dict):
                        self.y_axis['data'] = kwargs['y_axis'][:]
                        self.y_axis = kwargs['y_axis']
                    else:
                        self.y_axis = copy.deepcopy(kwargs['y_axis'])
                else:
                    self.y_axis['data'] = self.set_axis(datas_transposed.axes_manager.signal_shape[1])

            axes_nav = self.get_selected_axes_indexes()
            if len(axes_nav) == 0 or len(axes_nav) == 1:
                self.update_viewer_data(*self.ui.navigator1D.ui.crosshair.get_positions())
            elif len(axes_nav) == 2:
                self.update_viewer_data(*self.ui.navigator2D.ui.crosshair.get_positions())



            ##get ROI bounds from viewers if any
            ROI_bounds_1D=[]
            try:
                self.ROI1D.getRegion()
                indexes_values = utils.find_index(self.ui.viewer1D.x_axis, self.ROI1D.getRegion())
                ROI_bounds_1D.append(QPointF(indexes_values[0][0], indexes_values[1][0]))
            except Exception as e:
                logger.warning(str(e))

            ROI_bounds_2D = []
            try:
                ROI_bounds_2D.append(QRectF(self.ROI2D.pos().x(), self.ROI2D.pos().y(),
                                            self.ROI2D.size().x(), self.ROI2D.size().y()))
            except Exception as e:
                logger.warning(str(e))

            #############################################################
            # display the correct navigator viewer and set some parameters
            if len(axes_nav) <= 2:
                for view in self.nav_axes_viewers:
                    self.ui.nav_axes_widget.layout().removeWidget(view.parent)
                    view.parent.close()
                self.nav_axes_viewers = []

            nav_axes = self.get_selected_axes()

            if len(nav_axes) == 0:  # no Navigator
                self.ui.navigator1D.parent.setVisible(False)
                self.ui.navigator2D.parent.setVisible(False)
                #self.navigator_label.setVisible(False)
                self.ui.nav_axes_widget.setVisible(False)
                self.ROI1D.setVisible(False)
                self.ROI2D.setVisible(False)
                navigator_data = []


            elif len(nav_axes) == 1:  # 1D Navigator
                self.ROI1D.setVisible(True)
                self.ROI2D.setVisible(True)
                self.ui.navigator1D.parent.setVisible(True)
                self.ui.navigator2D.parent.setVisible(False)
                self.ui.nav_axes_widget.setVisible(False)
                #self.navigator_label.setVisible(True)
                self.ui.navigator1D.remove_plots()
                self.ui.navigator1D.x_axis = nav_axes[0]

                labels = []
                units = []
                if self.scan_type.lower() == 'tabular' or self.is_spread:
                    if 'datas' in self.nav_axes_dicts[0]:
                        navigator_data = self.nav_axes_dicts[0]['datas'][:]
                        if 'labels' in self.nav_axes_dicts[0]:
                            labels = self.nav_axes_dicts[0]['labels'][:]
                        if 'all_units' in self.nav_axes_dicts[0]:
                            units = self.nav_axes_dicts[0]['all_units'][:]
                    else:
                        navigator_data = [self.nav_axes_dicts[0]['data']]
                    if self.is_spread:
                        if self.scan_type.lower() == 'tabular':
                            data_spread = []
                            for ind_label, lab in enumerate(labels):
                                if 'curvilinear' in lab.lower():
                                    data_spread = [self.nav_axes_dicts[0]['datas'][ind]]
                        else:
                            data_spread = self.nav_axes_dicts[0]['datas'][:]

                        data_spread.append(self.get_nav_data(datas_transposed, ROI_bounds_1D, ROI_bounds_2D)[0])
                        data_spread = np.vstack(data_spread).T

                else:
                    navigator_data = self.get_nav_data(datas_transposed, ROI_bounds_1D, ROI_bounds_2D)

                if self.is_spread:
                    self.ui.spread_viewer_2D.parent.setVisible(data_spread.shape[1] == 3)
                    self.ui.spread_viewer_1D.parent.setVisible(data_spread.shape[1] == 2)
                    if data_spread.shape[1] == 3:
                        self.ui.spread_viewer_2D.setImage(data_spread=data_spread)
                        if len(labels) > 1 and len(units) > 1:
                            self.ui.spread_viewer_2D.set_axis_label(dict(orientation='bottom', label=labels[0],
                                                                         units=units[0]))
                            self.ui.spread_viewer_2D.set_axis_label(dict(orientation='left', label=labels[1],
                                                                         units=units[1]))
                    else:
                        ind_sorted = np.argsort(data_spread[:, 0])
                        self.ui.spread_viewer_1D.show_data([data_spread[:, 1][ind_sorted]], labels=['data'],
                                                           x_axis=data_spread[:, 0][ind_sorted])
                        self.ui.spread_viewer_1D.set_axis_label(dict(orientation='bottom',
                                                                     label='Curvilinear value', units=''))

                if temp_data:
                    self.ui.navigator1D.show_data_temp(navigator_data)
                    self.ui.navigator1D.update_labels(labels)
                else:
                    self.ui.navigator1D.show_data(navigator_data)
                    self.ui.navigator1D.update_labels(labels)

            elif len(nav_axes) == 2:#2D Navigator:
                self.ROI1D.setVisible(True)
                self.ROI2D.setVisible(True)

                self.ui.navigator1D.parent.setVisible(False)
                self.ui.navigator2D.parent.setVisible(True)
                self.ui.nav_axes_widget.setVisible(False)
                #self.navigator_label.setVisible(True)


                self.ui.navigator2D.x_axis = nav_axes[0]
                self.ui.navigator2D.y_axis = nav_axes[1]

                navigator_data = self.get_nav_data(datas_transposed, ROI_bounds_1D, ROI_bounds_2D)

                if temp_data:
                    self.ui.navigator2D.setImageTemp(*navigator_data)
                else:
                    self.ui.navigator2D.setImage(*navigator_data)


            else: #more than 2 nv axes, display all nav axes in 1D plots

                self.ui.navigator1D.parent.setVisible(False)
                self.ui.navigator2D.parent.setVisible(False)
                self.ui.nav_axes_widget.setVisible(True)
                if len(self.nav_axes_viewers) != len(axes_nav):
                    for view in self.nav_axes_viewers:
                        self.ui.nav_axes_widget.layout().removeWidget(view.parent)
                        view.parent.close()
                    widgets = []
                    self.nav_axes_viewers = []
                    for ind in range(len(axes_nav)):
                        widgets.append(QtWidgets.QWidget())
                        self.ui.nav_axes_widget.layout().addWidget(widgets[-1])
                        self.nav_axes_viewers.append(Viewer1DBasic(widgets[-1], show_line=True))

                for ind in range(len(axes_nav)):
                    self.nav_axes_viewers[ind].roi_line_signal.connect(self.update_viewer_data)
                    self.nav_axes_viewers[ind].show_data([nav_axes[ind]['data']])
                    self.nav_axes_viewers[ind].set_axis_label(dict(orientation='bottom',
                                                                  label=nav_axes[ind]['label'],
                                                                  units=nav_axes[ind]['units']))

            self.update_viewer_data()

        except Exception as e:
            logger.exception(str(e))
            self.update_status(utils.getLineInfo() + str(e), self.wait_time, 'log')



    def get_data_from_1Dsignal_roi(self, datas_transposed, ROI_bounds_1D):
        if ROI_bounds_1D != []:
            if self.ui.combomath.currentText() == 'Sum':
                navigator_data = [datas_transposed.isig[pt.x():pt.y() + 1].sum((-1)).data for pt in
                                  ROI_bounds_1D]
            elif self.ui.combomath.currentText() == 'Mean':
                navigator_data = [datas_transposed.isig[pt.x():pt.y() + 1].mean((-1)).data for pt in
                                  ROI_bounds_1D]
            elif self.ui.combomath.currentText() == 'Half-life':
                navigator_data = [datas_transposed.isig[pt.x():pt.y() + 1].halflife((-1)).data for pt in
                                  ROI_bounds_1D]
        else:
            if self.ui.combomath.currentText() == 'Sum':
                navigator_data = [datas_transposed.isig[:].sum((-1)).data]
            elif self.ui.combomath.currentText() == 'Mean':
                navigator_data = [datas_transposed.isig[:].mean((-1)).data]
            elif self.ui.combomath.currentText() == 'Half-life':
                navigator_data = [datas_transposed.isig[:].halflife((-1)).data]
        return navigator_data

    def get_nav_data(self, datas_transposed, ROI_bounds_1D, ROI_bounds_2D):

        if len(datas_transposed.axes_manager.signal_shape) == 0:  # signal data is 0D
            navigator_data = [datas_transposed.data]

        elif len(datas_transposed.axes_manager.signal_shape) == 1:  # signal data is 1D
            navigator_data = self.get_data_from_1Dsignal_roi(datas_transposed, ROI_bounds_1D)

        elif len(datas_transposed.axes_manager.signal_shape) == 2:  # signal data is 2D
            if ROI_bounds_2D != []:
                navigator_data = [datas_transposed.isig[rect.x():rect.x() + rect.width(),
                                  rect.y():rect.y() + rect.height()].sum((-1, -2)).data for rect in
                                  ROI_bounds_2D]
            else:
                navigator_data = [datas_transposed.sum((-1, -2)).data]
        else:
            navigator_data = None
        return navigator_data

    def init_ROI(self):
        nav_axes = self.get_selected_axes()
        if len(nav_axes) != 0:
            self.ui.navigator1D.ui.crosshair.set_crosshair_position(np.mean(nav_axes[0]['data']))
            x, y = self.ui.navigator2D.unscale_axis(np.mean(nav_axes[0]['data']),
                                                    np.mean(nav_axes[1]['data']))
            self.ui.navigator2D.ui.crosshair.set_crosshair_position(x, y)

            if self.x_axis['data'] is not None:
                self.ROI1D.setRegion((np.min(self.x_axis['data']), np.max(self.x_axis['data'])))
            if self.x_axis['data'] is not None and self.y_axis['data'] is not None:
                self.ROI2D.setPos((np.min(self.x_axis['data']), np.min(self.y_axis['data'])))
                self.ROI2D.setSize((np.max(self.x_axis['data']) - np.min(self.x_axis['data']),
                                    np.max(self.y_axis['data']) - np.min(self.y_axis['data'])))

            self.update_Navigator()

    def set_data_test(self, data_shape='3D'):

        x = utils.linspace_step(0, 20, 1)
        y = utils.linspace_step(0, 30, 1)
        t = utils.linspace_step(0, 200, 1)
        z = utils.linspace_step(0, 200, 1)
        datas = np.zeros((len(y), len(x), len(t), len(z)))
        amp = utils.gauss2D(x, 7, 5, y, 12, 10)
        for indx in range(len(x)):
            for indy in range(len(y)):
                datas[indy, indx, :, :] = amp[indy, indx] * (
                            utils.gauss2D(z, 50 + indx * 2, 20, t, 50 + 3 * indy, 30) + np.random.rand(len(t),
                                                                                                       len(z)) / 10)

        nav_axis = dict(nav00=Axis(data=y, nav_index=0, label='y_axis', units='yunits'),
                    nav01=Axis(data=x, nav_index=1, label='x_axis', units='xunits'),
                    nav02=Axis(data=t, nav_index=2, label='t_axis', units='tunits'),
                    nav03=Axis(data=z, nav_index=3, label='z_axis', units='zunits'))

        if data_shape == '4D':
            nav_axes = [2, 3]
            self.show_data(datas, temp_data=False, nav_axes=nav_axes, **nav_axis)
        elif data_shape == '3D':
            self.show_data(np.sum(datas, axis=3), temp_data=False, nav_axes=[0, 1], **nav_axis)
        elif data_shape == '2D':
            self.show_data(np.sum(datas, axis=(2, 3)), **nav_axis)
        elif data_shape == '1D':
            self.show_data(np.sum(datas, axis=(1, 2, 3)), **nav_axis)

    def set_nav_axes(self, Ndim, nav_axes=None):
        self.data_axes = [ind for ind in range(Ndim)]
        if nav_axes is None:
            if Ndim > 0:
                nav_axes = self.data_axes[0:2]
            else:
                nav_axes = self.data_axes[0]

        self.settings.child('data_shape_settings', 'navigator_axes').setValue(
            dict(all_items=[ax['label'] for ax in self.nav_axes_dicts],
                 selected=[self.nav_axes_dicts[ind]['label'] for ind in nav_axes]))


    def set_GUI(self):
        """

        """
        #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

        #main_layout = QtWidgets.QGridLayout()
        #self.area.setLayout(main_layout)

        #vsplitter = QtWidgets.QSplitter(Qt.Vertical)
        # Hsplitter=QtWidgets.QSplitter(Qt.Horizontal)

        params = [
            {'title': 'set data:', 'name': 'set_data_4D', 'type': 'action', 'visible': False},
            {'title': 'set data:', 'name': 'set_data_3D', 'type': 'action', 'visible': False},
            {'title': 'set data:', 'name': 'set_data_2D', 'type': 'action', 'visible': False},
            {'title': 'set data:', 'name': 'set_data_1D', 'type': 'action', 'visible': False},
            {'title': 'Signal shape', 'name': 'data_shape_settings', 'type': 'group', 'children': [
                    {'title': 'Initial Data shape:', 'name': 'data_shape_init', 'type': 'str', 'value': "",
                     'readonly': True},
                    {'title': 'Axes shape:', 'name': 'nav_axes_shapes', 'type': 'group', 'children': [],
                     'readonly': True},
                    {'title': 'Data shape:', 'name': 'data_shape', 'type': 'str', 'value': "", 'readonly': True},
                    {'title': 'Navigator axes:', 'name': 'navigator_axes', 'type': 'itemselect'},
                    {'title': 'Set Nav axes:', 'name': 'set_nav_axes', 'type': 'action', 'visible': True},
                        ]},
                ]

        self.settings = Parameter.create(name='Param', type='group', children=params)
        ##self.signal_axes_selection()

        # connecting from tree
        self.settings.sigTreeStateChanged.connect(self.parameter_tree_changed)  # any changes on the settings
        self.settings.child(('set_data_1D')).sigActivated.connect(lambda: self.set_data_test('1D'))
        self.settings.child(('set_data_2D')).sigActivated.connect(lambda: self.set_data_test('2D'))
        self.settings.child(('set_data_3D')).sigActivated.connect(lambda: self.set_data_test('3D'))
        self.settings.child(('set_data_4D')).sigActivated.connect(lambda: self.set_data_test('4D'))
        self.settings.child('data_shape_settings', 'set_nav_axes').sigActivated.connect(self.update_data)
        ##%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        ##% 1D signalviewer
        viewer1D_widget = QtWidgets.QWidget()
        self.ui.viewer1D = Viewer1D(viewer1D_widget)
        self.ROI1D = LinearRegionItem()
        self.ui.viewer1D.viewer.plotwidget.plotItem.addItem(self.ROI1D)
        self.ui.combomath = QtWidgets.QComboBox()
        self.ui.combomath.addItems(['Sum', 'Mean', 'Half-life'])
        self.ui.viewer1D.ui.button_widget.layout().insertWidget(4, self.ui.combomath)
        self.ui.combomath.currentIndexChanged.connect(self.update_Navigator)

        self.ROI1D.sigRegionChangeFinished.connect(self.update_Navigator)

        # % 2D viewer Dock
        viewer2D_widget = QtWidgets.QWidget()
        self.ui.viewer2D = Viewer2D(viewer2D_widget)
        self.ui.viewer2D.ui.Ini_plot_pb.setVisible(False)
        self.ui.viewer2D.ui.FlipUD_pb.setVisible(False)
        self.ui.viewer2D.ui.FlipLR_pb.setVisible(False)
        self.ui.viewer2D.ui.rotate_pb.setVisible(False)
        self.ui.viewer2D.ui.auto_levels_pb.click()
        self.ui.viewer2D.ui.ROIselect_pb.click()
        self.ROI2D = self.ui.viewer2D.ui.ROIselect
        self.ui.viewer2D.ROI_select_signal.connect(self.update_Navigator)

        dock_signal = Dock('Signal')
        dock_signal.addWidget(viewer1D_widget)
        dock_signal.addWidget(viewer2D_widget)

        ##%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        ##% Navigator viewer Dock
        navigator1D_widget = QtWidgets.QWidget()
        self.ui.navigator1D = Viewer1D(navigator1D_widget)
        self.ui.navigator1D.ui.crosshair.crosshair_dragged.connect(self.update_viewer_data)
        self.ui.navigator1D.ui.crosshair_pb.click()
        self.ui.navigator1D.data_to_export_signal.connect(self.export_data)
        navigator2D_widget = QtWidgets.QWidget()
        self.ui.navigator2D = Viewer2D(navigator2D_widget)
        self.ui.navigator2D.ui.auto_levels_pb.click()
        self.ui.navigator2D.crosshair_dragged.connect(
            self.update_viewer_data)  # export scaled position in conjonction with 2D scaled axes
        self.ui.navigator2D.ui.crosshair_pb.click()
        self.ui.navigator2D.data_to_export_signal.connect(self.export_data)

        self.ui.navigation_widget = QtWidgets.QWidget()
        # vlayout_navigation = QtWidgets.QVBoxLayout()
        # self.navigator_label = QtWidgets.QLabel('Navigation View')
        # self.navigator_label.setMaximumHeight(15)
        #layout_navigation.addWidget(self.navigator_label)
        self.ui.nav_axes_widget = QtWidgets.QWidget()
        self.ui.nav_axes_widget.setLayout(QtWidgets.QVBoxLayout())
        #vlayout_navigation.addWidget(navigator2D_widget)
        #vlayout_navigation.addWidget(self.ui.nav_axes_widget)
        self.ui.nav_axes_widget.setVisible(False)
        #vlayout_navigation.addWidget(navigator1D_widget)
        #self.ui.navigation_widget.setLayout(vlayout_navigation)
        #vsplitter.insertWidget(0, self.ui.navigation_widget)

        dock_navigation = Dock('Navigation')
        dock_navigation.addWidget(navigator1D_widget)
        dock_navigation.addWidget(navigator2D_widget)

        self.area.addDock(dock_navigation)
        self.area.addDock(dock_signal, 'right', dock_navigation)

        # self.ui.signal_widget = QtWidgets.QWidget()
        # VLayout1 = QtWidgets.QVBoxLayout()
        # self.viewer_label = QtWidgets.QLabel('Data View')
        # self.viewer_label.setMaximumHeight(15)
        # VLayout1.addWidget(self.viewer_label)
        # VLayout1.addWidget(viewer1D_widget)
        # VLayout1.addWidget(viewer2D_widget)
        # self.ui.signal_widget.setLayout(VLayout1)
        #vsplitter.insertWidget(1, self.ui.signal_widget)

        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap(":/icons/Icon_Library/cartesian.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.ui.set_signals_pb_1D = QtWidgets.QPushButton('')
        self.ui.set_signals_pb_1D.setToolTip('Change navigation/signal axes')
        self.ui.set_signals_pb_1D_bis = QtWidgets.QPushButton('')
        self.ui.set_signals_pb_1D_bis.setToolTip('Change navigation/signal axes')
        self.ui.set_signals_pb_1D.setIcon(icon)
        self.ui.set_signals_pb_1D_bis.setIcon(icon)
        self.ui.set_signals_pb_2D = QtWidgets.QPushButton('')
        self.ui.set_signals_pb_2D.setToolTip('Change navigation/signal axes')
        self.ui.set_signals_pb_2D.setIcon(icon)
        self.ui.set_signals_pb_2D_bis = QtWidgets.QPushButton('')
        self.ui.set_signals_pb_2D_bis.setToolTip('Change navigation/signal axes')
        self.ui.set_signals_pb_2D_bis.setIcon(icon)

        self.ui.navigator1D.ui.button_widget.layout().insertWidget(0, self.ui.set_signals_pb_1D)
        self.ui.navigator2D.ui.buttons_layout.insertWidget(0, self.ui.set_signals_pb_2D)
        self.ui.viewer1D.ui.button_widget.layout().insertWidget(0, self.ui.set_signals_pb_1D_bis)
        self.ui.viewer2D.ui.buttons_layout.insertWidget(0, self.ui.set_signals_pb_2D_bis)

        #main_layout.addWidget(vsplitter)

        self.ui.set_signals_pb_1D.clicked.connect(self.signal_axes_selection)
        self.ui.set_signals_pb_2D.clicked.connect(self.signal_axes_selection)
        self.ui.set_signals_pb_1D_bis.clicked.connect(self.signal_axes_selection)
        self.ui.set_signals_pb_2D_bis.clicked.connect(self.signal_axes_selection)

        #to start: display as default a 2D navigator and a 1D viewer
        self.ui.navigator1D.parent.setVisible(False)
        self.ui.viewer2D.parent.setVisible(True)

    def setup_spread_UI(self):
        self.ui.spread_widget = QtWidgets.QWidget()
        self.ui.spread_widget.setLayout(QtWidgets.QVBoxLayout())
        widget1D = QtWidgets.QWidget()
        widget2D = QtWidgets.QWidget()
        self.ui.spread_viewer_1D = Viewer1D(widget1D)
        self.ui.spread_viewer_2D = Viewer2D(widget2D)
        self.ui.spread_widget.layout().addWidget(widget1D)
        self.ui.spread_widget.layout().addWidget(widget2D)
        # todo: better connection as discussed
        self.ui.spread_viewer_1D.ui.crosshair.crosshair_dragged.connect(self.get_nav_position)
        self.ui.spread_viewer_1D.ui.crosshair_pb.click()
        self.ui.spread_viewer_2D.ui.auto_levels_pb.click()
        #todo: better connection as discussed
        self.ui.spread_viewer_2D.crosshair_dragged.connect(self.get_nav_position)
        self.ui.spread_viewer_2D.ui.crosshair_pb.click()

        self.ui.spread_widget.show()
        self.ui.spread_widget.setVisible(False)

    def show_data_temp(self, datas, nav_axes=None, distribution='uniform', **kwargs):
        """
        """
        self.show_data(datas, temp_data=True, nav_axes=nav_axes, distribution=distribution, **kwargs)

    def set_nav_shapes(self):
        for child in self.settings.child('data_shape_settings', 'nav_axes_shapes').children():
            child.remove()

        for ind_ax, ax in enumerate(self.nav_axes_dicts):
            self.settings.child('data_shape_settings', 'nav_axes_shapes').addChild(
                {'title': ax['label'], 'name': f'nav_{ind_ax:02d}_shape', 'type': 'str', 'value': str(ax['data'].shape),
                 'readonly': True},
            )

    def show_data(self, datas, temp_data=False, nav_axes=None, is_spread=False, scan_type='', **kwargs):
        """Display datas as a hyperspaced dataset
        only one numpy ndarray should be used
        """
        self.is_spread = is_spread
        self.ui.spread_widget.setVisible(is_spread)

        self.scan_type = scan_type
        self.data_buffer = []
        self.data_to_export = OrderedDict(name=self.title, data0D=OrderedDict(), data1D=OrderedDict(),
                                          data2D=OrderedDict(), dataND=OrderedDict(),)
        self.data_to_export['dataND']['CH000'] = OrderedDict(data=datas, source='raw', nav_axes=nav_axes)
        for key in kwargs:
            self.data_to_export['dataND']['CH000'][key] = kwargs[key]
        self._datas = datas
        self.datas = Signal(datas)
        self.datas_settings = kwargs
        self.restore_nav_axes(kwargs, nav_axes=nav_axes)
        self.set_nav_shapes()


        try:
            if self.data_axes is not None:
                if datas.ndim != len(self.data_axes) or self.get_selected_axes_indexes() != nav_axes:
                    self.set_nav_axes(datas.ndim, nav_axes) #init the list of axes and set the managers to nav_axes
            else:
                self.set_nav_axes(datas.ndim, nav_axes) #init the list of axes and set the managers to nav_axes

            #self.datas=hs.signals.BaseSignal(datas)

            self.update_data_signal()
            self.settings.child('data_shape_settings', 'data_shape_init').setValue(str(datas.shape))
            self.settings.child('data_shape_settings', 'data_shape').setValue(self.get_data_dimension())
            self.set_data(self.datas, temp_data=temp_data, **kwargs)

        except Exception as e:
            logger.exception(str(e))
            self.update_status(utils.getLineInfo() + str(e), self.wait_time, 'log')

    def signal_axes_selection(self):
        self.ui.settings_tree = ParameterTree()
        self.ui.settings_tree.setMinimumWidth(300)
        self.ui.settings_tree.setParameters(self.settings, showTop=False)
        self.signal_axes_widget = QtWidgets.QWidget()
        layout = QtWidgets.QVBoxLayout()
        self.signal_axes_widget.setLayout(layout)
        layout.addWidget(self.ui.settings_tree)
        self.signal_axes_widget.adjustSize()
        self.signal_axes_widget.show()

    def get_selected_axes_indexes(self):
        if self.settings.child('data_shape_settings', 'navigator_axes').value() is None:
            return []
        labels = self.settings.child('data_shape_settings', 'navigator_axes').value()['selected']
        axes_nav = []
        for lab in labels:
            for ax in self.nav_axes_dicts:
                if ax['label'] == lab:
                    axes_nav.append(ax['nav_index'])
        return axes_nav

    def get_selected_axes(self):
        axes_nav = []
        if self.settings.child('data_shape_settings', 'navigator_axes').value() is not None:
            labels = self.settings.child('data_shape_settings', 'navigator_axes').value()['selected']
            for lab in labels:
                for ax in self.nav_axes_dicts:
                    if ax['label'] == lab:
                        axes_nav.append(ax)
                        break
        return axes_nav

    def update_data(self):
        restore_nav_axes = self.get_selected_axes_indexes() != self.get_selected_axes_indexes()

        self.update_data_signal()
        self.settings.child('data_shape_settings', 'data_shape').setValue(self.get_data_dimension())

        nav_axes = dict([])
        for ind, ax in enumerate(self.nav_axes_dicts):
            nav_axes[f'nav_{ind}'] = ax

        self.set_data(self.datas, restore_nav_axes=restore_nav_axes, **nav_axes)

    def update_data_signal(self):
        try:
            axes_nav = [len(self.data_axes)-ind-1 for ind in self.get_selected_axes_indexes()]
            axes_signal = [ax for ax in self.data_axes if ax not in axes_nav]
            self.datas = Signal(self._datas)
            self.datas = self.datas.transpose(signal_axes=axes_signal, navigation_axes=axes_nav)

        except Exception as e:
            logger.exception(str(e))
            self.update_status(utils.getLineInfo()+str(e), self.wait_time, 'log')

    def update_Navigator(self):
        ##self.update_data_signal()
        self.set_data(self.datas, **self.datas_settings)


    def update_status(self,txt, wait_time=1000, log=''):
        """
            | Update the statut bar showing a Message with a delay of wait_time ms (1s by default)

            ================ ======== ===========================
            **Parameters**   **Type**     **Description**

             *txt*            string   the text message to show

             *wait_time*      int      the delay time of showing
            ================ ======== ===========================

        """
        if log != '':
            self.log_signal.emit(txt)


    def get_axis_from_label(self):
        pass

    def get_nav_position(self, posx=0, posy=None):
        """
        crosshair position from the "spread" data viewer. Should return scan index where the scan was closest to posx,
        posy coordinates
        Parameters
        ----------
        posx
        posy

        See Also
        --------
        update_viewer_data
        """
        nav_axes = self.get_selected_axes()
        if len(nav_axes) != 0:
            if 'datas' in nav_axes[0]:
                datas = nav_axes[0]['datas']
                xaxis = datas[0]
                if len(datas) > 1:
                    yaxis = datas[1]
                    ind_scan = utils.find_common_index(xaxis, yaxis, posx, posy)
                else:
                    ind_scan = utils.find_index(xaxis, posx)[0]

                self.ui.navigator1D.ui.crosshair.set_crosshair_position(ind_scan[0])


    def update_viewer_data(self, posx=0, posy=0):
        """
            |PyQt5 slot triggered by the crosshair signal from the 1D or 2D Navigator
            | Update the viewer informations from an x/y given position and store data.
        Parameters
        ----------
        posx: (float) from the 1D or 2D Navigator crosshair or from one of the navigation axis viewer (in that case
            nav_axis tells from wich navigation axis the position comes from)
        posy: (float) from the 2D Navigator crosshair
        nav_axis: (int) index of the navigation axis from where posx comes from

        """
        if self.datas is not None:
            try:
                nav_axes = self.get_selected_axes()
                # datas_transposed=self.update_data_signal(self.datas)
                if len(nav_axes) == 0:
                    data = self.datas.data

                elif len(nav_axes) == 1:
                    if posx < nav_axes[0]['data'][0] or posx > nav_axes[0]['data'][-1]:
                        return
                    ind_x = utils.find_index(nav_axes[0]['data'], posx)[0][0]
                    data = self.datas.inav[ind_x].data
                elif len(nav_axes) == 2:
                    if posx < nav_axes[0]['data'][0] or posx > nav_axes[0]['data'][-1]:
                        return
                    if posy < nav_axes[1]['data'][0] or posy > nav_axes[1]['data'][-1]:
                        return
                    ind_x = utils.find_index(nav_axes[0]['data'], posx)[0][0]
                    ind_y = utils.find_index(nav_axes[1]['data'], posy)[0][0]
                    data = self.datas.inav[ind_x, ind_y].data

                else:
                    pos = []
                    for ind_view, view in enumerate(self.nav_axes_viewers):
                        p = view.roi_line.getPos()[0]
                        if p < 0 or p > len(nav_axes[ind_view]['data']):
                            return
                        ind = int(np.rint(p))
                        pos.append(ind)
                    data = self.datas.inav.__getitem__(pos).data


                if len(self.datas.axes_manager.signal_shape) == 0:  # means 0D data, plot on 1D viewer
                    self.data_buffer.extend(data)
                    self.ui.viewer1D.show_data([self.data_buffer])

                elif len(self.datas.axes_manager.signal_shape) == 1:  # means 1D data, plot on 1D viewer
                    self.ui.viewer1D.remove_plots()
                    self.ui.viewer1D.x_axis = self.x_axis
                    self.ui.viewer1D.show_data([data])

                elif len(self.datas.axes_manager.signal_shape) == 2:  # means 2D data, plot on 2D viewer
                    self.ui.viewer2D.x_axis = self.x_axis
                    self.ui.viewer2D.y_axis = self.y_axis
                    self.ui.viewer2D.setImage(data)
            except Exception as e:
                logger.exception(str(e))
                self.update_status(utils.getLineInfo() + str(e), wait_time=self.wait_time, log='log')