Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Couldn't open MDA, issue with MDA QWidget #293

Closed
raulbola opened this issue Oct 11, 2023 · 8 comments
Closed

Couldn't open MDA, issue with MDA QWidget #293

raulbola opened this issue Oct 11, 2023 · 8 comments

Comments

@raulbola
Copy link

raulbola commented Oct 11, 2023

Hi everyone,

Sorry if this issue is so simple, but I have not managed to open the MDA by pressing the MDA button on the toolbar. I always get the same error.

I am using the test configuration file provided and it seems that the same error persists.

AttributeError                            Traceback (most recent call last)
File ~\anaconda3\envs\holoAOD\Lib\site-packages\napari_micromanager\_gui_objects\_toolbar.py:172, in MicroManagerToolbar._show_dock_widget(self=<napari_micromanager.main_window.MainWindow object>, key='MDA')
    166 except KeyError as e:
    167     raise KeyError(
    168         "Not a recognized dock widget key. "
    169         f"Must be one of {list(DOCK_WIDGETS)} "
    170         " or the `whatsThis` property of a `sender` `QPushButton`."
    171     ) from e
--> 172 wdg = wdg_cls(parent=self, mmcore=self._mmc)
        self = <napari_micromanager.main_window.MainWindow object at 0x000001FE332ABD90>
        wdg_cls = <class 'napari_micromanager._gui_objects._mda_widget.MultiDWidget'>
        self._mmc = <CMMCorePlus at 0x1fe3315cb30>
    174 if isinstance(wdg, PropertyBrowser):
    175     wdg.setSizePolicy(
    176         QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding
    177     )

File ~\anaconda3\envs\holoAOD\Lib\site-packages\napari_micromanager\_gui_objects\_mda_widget.py:33, in MultiDWidget.__init__(self=<napari_micromanager._gui_objects._mda_widget.MultiDWidget object>, parent=<napari_micromanager.main_window.MainWindow object>, mmcore=<CMMCorePlus>)
     30 def __init__(
     31     self, *, parent: QWidget | None = None, mmcore: CMMCorePlus | None = None
     32 ) -> None:
---> 33     super().__init__(include_run_button=True, parent=parent, mmcore=mmcore)
        parent = <napari_micromanager.main_window.MainWindow object at 0x000001FE332ABD90>
        mmcore = <CMMCorePlus at 0x1fe3315cb30>
     34     # add save widget
     35     v_layout = cast(QVBoxLayout, self._central_widget.layout())

File ~\anaconda3\envs\holoAOD\Lib\site-packages\pymmcore_widgets\_mda\_mda_widget.py:194, in MDAWidget.__init__(self=<napari_micromanager._gui_objects._mda_widget.MultiDWidget object>, parent=<napari_micromanager.main_window.MainWindow object>, include_run_button=True, mmcore=<CMMCorePlus>)
    191     self.buttons_wdg.cancel_button.released.connect(self._mmc.mda.cancel)
    192     acq_order_run_layout.addWidget(self.buttons_wdg)
--> 194 self._on_sys_cfg_loaded()
        self = <napari_micromanager._gui_objects._mda_widget.MultiDWidget object at 0x000001FE35C87C70>
    196 self.destroyed.connect(self._disconnect)

File ~\anaconda3\envs\holoAOD\Lib\site-packages\pymmcore_widgets\_mda\_mda_widget.py:199, in MDAWidget._on_sys_cfg_loaded(self=<napari_micromanager._gui_objects._mda_widget.MultiDWidget object>)
    198 def _on_sys_cfg_loaded(self) -> None:
--> 199     self._enable_run_btn()
        self = <napari_micromanager._gui_objects._mda_widget.MultiDWidget object at 0x000001FE35C87C70>

File ~\anaconda3\envs\holoAOD\Lib\site-packages\pymmcore_widgets\_mda\_mda_widget.py:245, in MDAWidget._enable_run_btn(self=<napari_micromanager._gui_objects._mda_widget.MultiDWidget object>)
    243     else:
    244         self.buttons_wdg.run_button.setEnabled(True)
--> 245 elif not self.ch_cbox.isChecked() or not self.channel_widget._table.rowCount():
        self = <napari_micromanager._gui_objects._mda_widget.MultiDWidget object at 0x000001FE35C87C70>
        self.ch_cbox = <PyQt5.QtWidgets.QWidget object at 0x000001FE35C9DD80>
        self.channel_widget._table = <PyQt5.QtWidgets.QTableWidget object at 0x000001FE35C87F40>
        self.channel_widget = <pymmcore_widgets._mda._channel_table_widget.ChannelTable object at 0x000001FE35C87E20>
    246     self.buttons_wdg.run_button.setEnabled(False)
    247 else:

AttributeError: 'QWidget' object has no attribute 'isChecked'_

Thank you very much in advance.

@tlambert03
Copy link
Member

hey @raulbola and sorry for the trouble.
That was fixed in pymmcore-plus/pymmcore-widgets#220 ... but it looks like it hasn't been released yet. I'll push the release with the fix today

@tlambert03
Copy link
Member

pymmcore-widgets 0.5.1 has the fix, please try: pip install -U pymmcore-widgets

@raulbola
Copy link
Author

raulbola commented Oct 12, 2023

Hi @tlambert03 , thank you very much for the response, now it works. I thought that pymmcore-widgets you get when installing napari-micromanager was already the latest version.

Amazing work by the way, I am really enjoy using napari-micromanger. I think it is a huge step forward.

I just found two more issues, may I post them here? or open individual issues?

  • The camera exposure control is limited at 1ms, there is no way I can put for example 0.1ms. Of course I can modify the QDoubleSpinbox, but I want to know if there is a better way to solve that. Rather than opening the "device property browser" and change the exposure there.

  • Another issue I found is when using Photometrics cameras (Photometrics Kinetix) and opening the "device property browser". There is a specific camera property "PreampOffLimit" that the property browser cannot create the slider, hence property browser never shows up. It seems there is an issue with the maximum and minimum values.
    The slider range must be between -2147483648 and 2147483647 (int32), and when calling that Kinetix camera property, the value is between 0 and 4294967295 (uint32).

---------------------------------------------------------------------------
OverflowError                             Traceback (most recent call last)
File ~\anaconda3\envs\holoAOD\Lib\site-packages\napari_micromanager\_gui_objects\_toolbar.py:172, in MicroManagerToolbar._show_dock_widget(self=<napari_micromanager.main_window.MainWindow object>, key='Device Property Browser')
    166 except KeyError as e:
    167     raise KeyError(
    168         "Not a recognized dock widget key. "
    169         f"Must be one of {list(DOCK_WIDGETS)} "
    170         " or the `whatsThis` property of a `sender` `QPushButton`."
    171     ) from e
--> 172 wdg = wdg_cls(parent=self, mmcore=self._mmc)
        self = <napari_micromanager.main_window.MainWindow object at 0x0000020C9A9B3EB0>
        wdg_cls = <class 'pymmcore_widgets._property_browser.PropertyBrowser'>
        self._mmc = <CMMCorePlus at 0x20c8ff2b6a0>
    174 if isinstance(wdg, PropertyBrowser):
    175     wdg.setSizePolicy(
    176         QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding
    177     )

File ~\anaconda3\envs\holoAOD\Lib\site-packages\pymmcore_widgets\_property_browser.py:30, in PropertyBrowser.__init__(self=<pymmcore_widgets._property_browser.PropertyBrowser object>, parent=<napari_micromanager.main_window.MainWindow object>, mmcore=<CMMCorePlus>)
     27 super().__init__(parent=parent)
     28 self._mmc = mmcore or CMMCorePlus.instance()
---> 30 self._prop_table = DevicePropertyTable(mmcore=mmcore)
        self = <pymmcore_widgets._property_browser.PropertyBrowser object at 0x0000020C9D5C83A0>
        mmcore = <CMMCorePlus at 0x20c8ff2b6a0>
        DevicePropertyTable = <class 'pymmcore_widgets._device_property_table.DevicePropertyTable'>
     31 self._device_filters = DeviceTypeFilters()
     32 self._device_filters.filtersChanged.connect(self._update_filter)

File ~\anaconda3\envs\holoAOD\Lib\site-packages\pymmcore_widgets\_device_property_table.py:98, in DevicePropertyTable.__init__(self=<pymmcore_widgets._device_property_table.DevicePropertyTable object>, parent=None, enable_property_widgets=True, mmcore=<CMMCorePlus>, connect_core=True)
     95 self.setWordWrap(False)  # makes for better elided labels
     97 self.resize(500, 500)
---> 98 self._rebuild_table()
        self = <pymmcore_widgets._device_property_table.DevicePropertyTable object at 0x0000020C9D5C8310>

File ~\anaconda3\envs\holoAOD\Lib\site-packages\pymmcore_widgets\_device_property_table.py:149, in DevicePropertyTable._rebuild_table(self=<pymmcore_widgets._device_property_table.DevicePropertyTable object>)
    146     item.setIcon(icon(icon_string, color="Gray"))
    147 self.setItem(i, 0, item)
--> 149 wdg = PropertyWidget(
        wdg = <pymmcore_widgets._property_widget.PropertyWidget object at 0x0000020C9D5DD1B0>
        PropertyWidget = <class 'pymmcore_widgets._property_widget.PropertyWidget'>
        prop = <Property 'Camera-1::PreampOffLimit' on CMMCorePlus at 0x20c8ff2b6a0: value=10000>
        prop.device = 'Camera-1'
        prop.name = 'PreampOffLimit'
        self = <pymmcore_widgets._device_property_table.DevicePropertyTable object at 0x0000020C9D5C8310>
        self._mmc = <CMMCorePlus at 0x20c8ff2b6a0>
        self._connect_core = True
    150     prop.device,
    151     prop.name,
    152     mmcore=self._mmc,
    153     connect_core=self._connect_core,
    154 )
    155 self.setCellWidget(i, 1, wdg)
    156 if not self._prop_widgets_enabled:

File ~\anaconda3\envs\holoAOD\Lib\site-packages\pymmcore_widgets\_property_widget.py:325, in PropertyWidget.__init__(self=<pymmcore_widgets._property_widget.PropertyWidget object>, device_label='Camera-1', prop_name='PreampOffLimit', parent=None, mmcore=<CMMCorePlus>, connect_core=True)
    322 self.layout().setContentsMargins(0, 0, 0, 0)
    324 # Create the widget based on property type and allowed choices
--> 325 self._value_widget = _creat_prop_widget(self._mmc, device_label, prop_name)
        self._mmc = <CMMCorePlus at 0x20c8ff2b6a0>
        device_label = 'Camera-1'
        prop_name = 'PreampOffLimit'
        self = <pymmcore_widgets._property_widget.PropertyWidget object at 0x0000020C9D5DD480>
    326 # set current value from core
    327 self._try_update_from_core()

File ~\anaconda3\envs\holoAOD\Lib\site-packages\pymmcore_widgets\_property_widget.py:254, in _creat_prop_widget(mmcore=<CMMCorePlus>, dev='Camera-1', prop='PreampOffLimit')
    248         wdg = (
    249             RangedIntegerWidget()
    250             if ptype is PropertyType.Integer
    251             else RangedFloatWidget()
    252         )
    253         wdg.setMinimum(wdg.type_cast(mmcore.getPropertyLowerLimit(dev, prop)))
--> 254         wdg.setMaximum(wdg.type_cast(mmcore.getPropertyUpperLimit(dev, prop)))
        wdg = <pymmcore_widgets._property_widget.RangedIntegerWidget object at 0x0000020C9D5DD630>
        dev = 'Camera-1'
        prop = 'PreampOffLimit'
        mmcore = <CMMCorePlus at 0x20c8ff2b6a0>
        wdg.type_cast = <class 'int'>
    255 else:
    256     wdg = StringWidget()

File ~\anaconda3\envs\holoAOD\Lib\site-packages\superqt\sliders\_labeled.py:68, in _SliderProxy.setMaximum(self=<pymmcore_widgets._property_widget.RangedIntegerWidget object>, maximum=4294967295)
     67 def setMaximum(self, maximum: int) -> None:
---> 68     self._slider.setMaximum(maximum)
        maximum = 4294967295
        self._slider = <PyQt5.QtWidgets.QSlider object at 0x0000020C9D5DD6C0>
        self = <pymmcore_widgets._property_widget.RangedIntegerWidget object at 0x0000020C9D5DD630>

OverflowError: argument 1 overflowed: value must be in the range -2147483648 to 2147483647

@tlambert03
Copy link
Member

I thought that pymmcore-widgets you get when installing napari-micromanager was already the latest version.

it is ... but the "fix" wasn't yet in the released version. I just pushed a new release of widgets, but since you had already installed napari-micromanager, you needed to update to pull in that fix :)

The camera exposure control is limited at 1ms, there is no way I can put for example 0.1ms.

That's an oversight. will open an issue to fix. Good catch thanks

The slider range must be between -2147483648 and 2147483647 (int32), and when calling that Kinetix camera property, the value is between 0 and 4294967295 (uint32).

Another good catch thanks! Yeah, this is a limitation of sliders in Qt... We have a solution in the superqt package QLargeIntSpinBox, so I should just use that spinbox here instead of QSpinBox. I'll make that change as well.

Thanks so much for these very helpful notes!

@tlambert03
Copy link
Member

The camera issue is fixed in pymmcore-plus/pymmcore-widgets#222. The overflow issue needs following up. I opened pymmcore-plus/pymmcore-widgets#223 to deal with it.
I'm going to close this issue as completed, but please keep opening issues as you find them! We greatly appreciate it

@tlambert03
Copy link
Member

I just pushed a new version of pymmcore-widgets (v0.5.2) that will include the range extension in the camera widget, and a patch that will at least allow you to open the property browser (but for now, things like PreampOffLimit will simply be missing until we fix the underlying overflow issues).

So, @raulbola, when you have a moment, please run pip install -U pymmcore-widgets again.

@raulbola
Copy link
Author

@tlambert03 Thank you very much for the fast and effective response, I really appreciate it. I was just trying those changes locally and you already updated pymmcore-widgets!

I will keep opening issues if I find more.

Just as a curiosity, I have a question regarding "on-the-fly" processing. We are developing a very fast OS-SIM microscope and I have implemented the image reconstruction algorithms such that the inference time is so fast that allows me to have a real time prview of the sample. Up to now I was using my own Labview/Matlab GUIs and control programs with Live Preview modes that continously acquire the set of N raw images, combine them using OS-SIM algoritm and display the result in the Live window (such as the Apotome mode in Zeiss SIM).

May I ask if there is a way to do so with napari micromanger?Something like the on-the-fly processor of Micromanager, but changing the Frame Averaging or Maximum projection by our OS-SIM algorithm?

@tlambert03
Copy link
Member

Thanks @raulbola, opened a new issue #294 to discuss that

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants