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

Spectrometer pr v1 #1

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 18 additions & 17 deletions config/example/default.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,11 @@ hardware:
- 'Very long name of a random state'
- 'Another very long name of a random state'

myspectrometer:
module.Class: 'spectrometer.spectrometer_dummy.SpectrometerInterfaceDummy'
connect:
fitlogic: 'fitlogic'
science_camera_dummy:
module.Class: 'dummies.science_camera_dummy.Main'

grating_spectrometer_dummy:
module.Class: 'dummies.grating_spectrometer_dummy.Main'

motordummy:
module.Class: 'motor.motor_dummy.MotorDummy'
Expand Down Expand Up @@ -310,14 +311,6 @@ logic:
save_pdf: True
save_png: True

spectrumlogic:
module.Class: 'spectrum.SpectrumLogic'
connect:
spectrometer: 'myspectrometer'
savelogic: 'savelogic'
odmrlogic: 'odmrlogic' # optional
fitlogic: 'fitlogic'

magnet_logic:
module.Class: 'magnet_logic.MagnetLogic'
connect:
Expand Down Expand Up @@ -372,6 +365,13 @@ logic:
hardware: 'cameradummy'
savelogic: 'savelogic'

spectrumlogic:
module.Class: 'spectrum_logic.SpectrumLogic'
connect:
spectrometer: 'grating_spectrometer_dummy'
camera: 'science_camera_dummy'
savelogic: 'savelogic'

gui:
tray:
module.Class: 'trayicon.TrayIcon'
Expand Down Expand Up @@ -431,11 +431,6 @@ gui:
connect:
automationlogic: 'automationlogic'

spectrometer:
module.Class: 'spectrometer.spectrometergui.SpectrometerGui'
connect:
spectrumlogic: 'spectrumlogic'

pulsedmeasurement:
module.Class: 'pulsed.pulsed_maingui.PulsedMeasurementGui'
connect:
Expand Down Expand Up @@ -509,3 +504,9 @@ gui:
module.Class: 'counter.countergui.CounterGui'
connect:
counterlogic1: 'counterlogic'

spectrometer:
module.Class: 'spectrometer.spectrometer.Main'
connect:
spectrumlogic: 'spectrumlogic'
savelogic: 'savelogic'
2 changes: 2 additions & 0 deletions documentation/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ please use _ni_x_series_in_streamer.py_ as hardware module.
* Added custom circular loading indicator widget `qtwidgets.loading_indicator.CircleLoadingIndicator`
* added property disable_wheel to custom ScienSponBox and ScienDSpinBox to deactivate wheel scrolling if required
* Added possibility to fit data of all ranges in ODMR module when Fit range is -1
* Added new dummy/interface/logic/gui chain for scientific spectrometer
* Added new spectrometer and camera hardware modules for andor devices


Config changes:
Expand Down
166 changes: 166 additions & 0 deletions gui/gui_components/colorbar/colorbar.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
# -*- coding: utf-8 -*-
"""
This module contains a GUI component to crate easily a colorbar in any GUI module

Qudi is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Qudi is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Qudi. If not, see <http://www.gnu.org/licenses/>.

Copyright (c) the Qudi Developers. See the COPYRIGHT.txt file at the
top-level directory of this distribution and at <https://github.com/Ulm-IQO/qudi/>
"""

import os
import pyqtgraph as pg
from functools import partial

from gui.colordefs import QudiPalettePale as Palette
from gui.guibase import GUIBase
from gui.colordefs import ColorScaleInferno
from qtwidgets.scientific_spinbox import ScienDSpinBox, ScienSpinBox

from qtpy import QtWidgets
from qtpy import uic
from gui.guiutils import ColorBar
from gui.colordefs import ColorScaleMagma

import numpy as np

import time

class ColorbarWidget(QtWidgets.QWidget):
""" Create the widget, based on the corresponding *.ui file."""

def __init__(self, image_widget, unit='c/s'):
# Get the path to the *.ui file
this_dir = os.path.dirname(__file__)
ui_file = os.path.join(this_dir, 'ui_colorbar.ui')

# Load it
super(ColorbarWidget, self).__init__()
uic.loadUi(ui_file, self)

self._cb_min = 0
self._cb_max = 100
self.unit = unit

self.init_spin_box()
self.init_colorbar()

self.set_image(image_widget)

self.percentile.clicked.emit()
self.percentile.setChecked(True)

def init_spin_box(self):
""" Initialize all the spinboxes """
self._min_percentile = ScienDSpinBox()
self._min_manual = ScienDSpinBox()
self._max_percentile = ScienDSpinBox()
self._max_manual = ScienDSpinBox()

self._min_percentile.setSuffix('%')
self._min_percentile.setMinimum(0)
self._min_percentile.setMaximum(100)
self._min_percentile.setValue(0)

self._min_manual.setSuffix(self.unit)

self._max_percentile.setSuffix('%')
self._max_percentile.setMinimum(0)
self._max_percentile.setMaximum(100)
self._max_percentile.setValue(100)

self._max_manual.setSuffix(self.unit)

self.min.addWidget(self._min_manual)
self.min.addWidget(self._min_percentile)
self.max.addWidget(self._max_percentile)
self.max.addWidget(self._max_manual)

self._min_percentile.valueChanged.connect(self.shortcut_to_cb_centiles)
self._min_manual.valueChanged.connect(self.shortcut_to_cb_manual)
self._max_percentile.valueChanged.connect(self.shortcut_to_cb_centiles)
self._max_manual.valueChanged.connect(self.shortcut_to_cb_manual)

self.manual.clicked.connect(self.update_cb_range)
self.percentile.clicked.connect(self.update_cb_range)

def init_colorbar(self):
""" Create the colorbar """
self.my_colors = ColorScaleInferno()
self._color_map = ColorScaleMagma()
self._cb = ColorBar(self.my_colors.cmap_normed, width=100, cb_min=self._cb_min, cb_max=self._cb_max)
self.colorbar.addItem(self._cb)
self.colorbar.hideAxis('bottom')
self.colorbar.setLabel('left', 'Intensity', units=self.unit)
self.colorbar.setMouseEnabled(x=False, y=False)

def set_image(self, image_widget):
""" Set the image widget associated to the colorbar """
self._image = image_widget
self._min_manual.setValue(np.min(self._image.image))
self._min_percentile.setValue(0)
self._max_manual.setValue(np.max(self._image.image))
self._max_percentile.setValue(100)
self.refresh_colorbar()

def get_cb_range(self):
""" Determines the cb_min and cb_max values for the image """
# If "Manual" is checked, or the image data is empty (all zeros), then take manual cb range.
if self.manual.isChecked() or np.count_nonzero(self._image.image) < 1:
cb_min = self._min_manual.value()
cb_max = self._max_manual.value()

# Otherwise, calculate cb range from percentiles.
else:
# Exclude any zeros (which are typically due to unfinished scan)
image_nonzero = self._image.image[np.nonzero(self._image.image)]

# Read centile range
low_centile = self._min_percentile.value()
high_centile = self._max_percentile.value()

cb_min = np.percentile(image_nonzero, low_centile)
cb_max = np.percentile(image_nonzero, high_centile)

cb_range = [cb_min, cb_max]

return cb_range

def refresh_colorbar(self):
""" Adjust the colorbar. """
cb_range = self.get_cb_range()
self._cb.refresh_colorbar(cb_range[0], cb_range[1])

def refresh_image(self):
""" Update the image colors range."""

image_data = self._image.image
cb_range = self.get_cb_range()
self._image.setImage(image=image_data, levels=(cb_range[0], cb_range[1]))
self.refresh_colorbar()

def update_cb_range(self):
""" Redraw colour bar and image."""
self.refresh_colorbar()
self.refresh_image()

def shortcut_to_cb_manual(self):
""" Someone edited the absolute counts range for the colour bar, better update."""
self.manual.setChecked(True)
self.update_cb_range()

def shortcut_to_cb_centiles(self):
"""Someone edited the centiles range for the colour bar, better update."""
self.percentile.setChecked(True)
self.update_cb_range()
98 changes: 98 additions & 0 deletions gui/gui_components/colorbar/ui_colorbar.ui
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>colorbarWidget</class>
<widget class="QWidget" name="colorbarWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>93</width>
<height>584</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>93</width>
<height>16777215</height>
</size>
</property>
<property name="font">
<font>
<pointsize>8</pointsize>
</font>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QVBoxLayout" name="max"/>
</item>
<item>
<layout class="QVBoxLayout" name="min">
<item>
<widget class="PlotWidget" name="colorbar">
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QRadioButton" name="percentile">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<pointsize>8</pointsize>
</font>
</property>
<property name="text">
<string>Percentiles</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="manual">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<pointsize>8</pointsize>
</font>
</property>
<property name="text">
<string>Manual</string>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>PlotWidget</class>
<extends>QGraphicsView</extends>
<header location="global">pyqtgraph</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
Loading