Source code for vdat.gui.fplane
"""Panel with the focal plane"""
from __future__ import (absolute_import, division, print_function,
unicode_literals)
from time import sleep
import logging
from PyQt4 import QtGui, QtCore
from pyhetdex.het.fplane import FPlane
import vdat.database as db
import vdat.config as confp
from vdat.gui.relay import get_relay
__FPLANEPANEL__ = None
[docs]class VDATRunControl(object):
"""Class to store variable which controls looping over IFUs """
ifu_loop = True
[docs]def current_fplane():
"""Return the current focal plane (or none if not set)
Returns
-------
fplane : :class:`pyhetdex.het.fplane.FPlane`
the fplane (with the IFUs) of the currently displayed central panel
"""
global __FPLANEPANEL__
if __FPLANEPANEL__:
return __FPLANEPANEL__.fplane
else:
return None
[docs]def yield_all_ifus():
"""Grabs the IFUs from the fplane class variable of FplanePanel and check
that that the IFUs have been properly initialized.
Returns
-------
ifu : :class:`vdat.gui.ifu_widget.IFUWidget`
pyhetdex IFU objects
"""
VDATRunControl.ifu_loop = True
log = logging.getLogger('logger')
fplane = current_fplane()
if not fplane:
log.error("No focal plane available. Did you select a directory?")
ifus = []
else:
ifus = fplane.ifus
# Test to see if the IFUs have been initialized (just look at first file)
for ifu in ifus:
if VDATRunControl.ifu_loop:
yield ifu
else:
raise StopIteration
[docs]def yield_selected_ifus():
"""Grabs the IFUs from the fplane class variable of FplanePanel and check
that that the IFUs have been properly initialized. Yield selected IFUs
Returns
-------
ifu : :class:`vdat.gui.ifu_widget.IFUWidget`
pyhetdex IFU objects
"""
log = logging.getLogger('logger')
VDATRunControl.ifu_loop = True
fplane = current_fplane()
if not fplane:
log.error("No focal plane available. Did you select a directory?")
ifus = []
else:
ifus = fplane.ifus
# Test to see if the IFUs have been initialized (just look at first file)
for ifu in ifus:
if not VDATRunControl.ifu_loop:
raise StopIteration
if ifu.selected:
yield ifu
else:
continue
[docs]def select_all_ifus():
"""Selects all IFUs in the FPlanePanel
"""
log = logging.getLogger('logger')
fplane = current_fplane()
if not fplane:
log.error("No focal plane available. Did you select a directory?")
ifus = []
else:
ifus = fplane.ifus
for ifu in ifus:
ifu.selected = True
[docs]def deselect_all_ifus():
"""Selects all IFUs in the FPlanePanel
"""
log = logging.getLogger('logger')
fplane = current_fplane()
if not fplane:
log.error("No focal plane available. Did you select a directory?")
ifus = []
else:
ifus = fplane.ifus
for ifu in ifus:
ifu.selected = False
[docs]def change_focal_plane_panel(type_, parent=None):
"""Create a new focal plane panel, and save it in the global. Delete the
old one.
Returns
-------
__FPLANEPANEL__ : class:`FplanePanel`
a panel showing the focal plane
"""
from vdat.gui.background import get_background
global __FPLANEPANEL__
# if one exists, delete it
if __FPLANEPANEL__:
bg = get_background()
VDATRunControl.ifu_loop = False
while bg.isImmRunning:
sleep(0.1)
__FPLANEPANEL__.deleteLater()
__FPLANEPANEL__ = FplanePanel(type_, parent=parent)
__FPLANEPANEL__.update_ifus(__FPLANEPANEL__.display_type)
return __FPLANEPANEL__
[docs]class FplanePanel(QtGui.QWidget):
"""Class to create and handle the focal plane window in the GUI
Set up the basic elements, like the combo box and the widget, of a viewer
of HETDEX focal planes
Parameters
----------
type_ : str
a name of one of the sections of the tabs.yml file (e.g. cal, sci...)
"""
updateScaleBoxes = QtCore.pyqtSignal(float, float)
def __init__(self, type_, parent=None):
# put this here to avoid circular imports
from vdat.gui.ifu_widget import IFUWidget
QtGui.QWidget.__init__(self, parent=None)
self.type_ = type_
self._conf = confp.get_config(name='main')
self.tabs_conf = confp.get_config(name='tab', section=type_)
self.global_scale = False
# a grid layout to stick IFUs on
self.layout = QtGui.QVBoxLayout()
# bar to show image scaling parameters
self.scaling_bar = QtGui.QHBoxLayout()
self.scaling_bar.setAlignment(QtCore.Qt.AlignLeft)
self.focalPlane_layout = QtGui.QGridLayout()
self.focalPlane_layout.setSizeConstraint(QtGui.QLayout
.SetMinAndMaxSize)
self.focalPlane_layout.setObjectName("focalPlane_layout")
self.setLayout(self.layout)
self.layout.addLayout(self.focalPlane_layout)
self.layout.addLayout(self.scaling_bar)
# load in the IFUs
self.fplane = FPlane(self._conf.get("fplane", "fp_filename"),
ifu_class=IFUWidget)
# combo box to decide what is displayed, based on whats in the tabs.yml
self.comboBox = QtGui.QComboBox()
self.comboBox.addItems(list(self.tabs_conf['tabs'].keys()))
self.comboBox.activated[str].connect(self.update_ifus)
self.focalPlane_layout.addWidget(self.comboBox, 0, 0, 1, 2)
# combo box to decide the image (brightness) scaling
self.comboBoxScaling = QtGui.QComboBox()
self.comboBoxScaling.addItems(["Individual scaling", "Global scaling"])
self.comboBoxScaling.activated[str].connect(self.set_scaling_mode)
self.comboBoxScaling.setFixedWidth(150)
self.scaling_bar.addWidget(self.comboBoxScaling)
# QLineEdits to display global image scaling parameters
self.minScaleBox = QtGui.QLineEdit()
self.maxScaleBox = QtGui.QLineEdit()
self.minScaleBox.setFixedWidth(80)
self.maxScaleBox.setFixedWidth(80)
# make sure the user inputs a valid number here
self.validator = QtGui.QDoubleValidator()
self.minScaleBox.setValidator(self.validator)
self.maxScaleBox.setValidator(self.validator)
# connect the scale boxes to the automatic global scaling
self.updateScaleBoxes.connect(self.update_scale_boxes)
relay = get_relay()
relay.add_signal("scaleboxes", self.updateScaleBoxes)
# add information on the image scale
self.minLabel = QtGui.QLabel("Min: ")
self.maxLabel = QtGui.QLabel("Max: ")
self.scaling_bar.addWidget(self.minLabel)
self.scaling_bar.addWidget(self.minScaleBox)
self.scaling_bar.addWidget(self.maxLabel)
self.scaling_bar.addWidget(self.maxScaleBox)
# add a button to do manual scaling
self.rescaleButton = QtGui.QPushButton("Rescale")
self.rescaleButton.released.connect(self.set_scaling)
self.scaling_bar.addWidget(self.rescaleButton)
# set the displayed tab to the default one
self.display_type = (self.tabs_conf['main'])['default_tab']
self.comboBox.setCurrentIndex(self.comboBox
.findText(self.display_type))
self.set_scaling_mode("Individual scaling", noFplane=True)
[docs] def update_scale_boxes(self, min_scale, max_scale):
"""
Update the contents of the image scale boxes
Parameters
----------
min_scale : float
value to display in the min_scale box
max_scale : float
value to display in the max_scale box
"""
self.minScaleBox.setText("{:4.2f}".format(min_scale))
self.maxScaleBox.setText("{:4.2f}".format(max_scale))
[docs] def set_scaling(self):
"""
Set the image scale parameters, based on what is
written in the min_cut and max_cut boxes.
"""
cdir = self._conf.get("redux_dirs", "selected_dir")
min_cut = self.minScaleBox.text()
max_cut = self.maxScaleBox.text()
with db.connect():
q = (db.ThumbnailScaling.select()
.where((db.ThumbnailScaling.path == cdir) &
(db.ThumbnailScaling.tab == self.display_type)))
if q.exists():
entry = q.get()
entry.min_cut = min_cut
entry.max_cut = max_cut
entry.save()
self.update_ifus(self.display_type)
[docs] def set_scaling_mode(self, option_string, noFplane=False):
"""Set what type of image scaling the focal plane has.
Parameters
----------
option_string: str
"Global scaling" or "individual scaling"
noFplane : optional
if true, do nbot attempt to update the IFUs in the panel
"""
if option_string == "Global scaling":
self.global_scale = True
self.minScaleBox.setVisible(True)
self.maxScaleBox.setVisible(True)
self.rescaleButton.setVisible(True)
self.minLabel.setVisible(True)
self.maxLabel.setVisible(True)
else:
self.global_scale = False
self.minScaleBox.setVisible(False)
self.maxScaleBox.setVisible(False)
self.rescaleButton.setVisible(False)
self.minLabel.setVisible(False)
self.maxLabel.setVisible(False)
if not noFplane:
self.update_ifus(self.display_type)
[docs] def update_ifus(self, display_type):
""" Loop through an fplane object
plotting the IFUs
Parameters
----------
display_type : str
an entry in a ``tabs`` subsection of tabs.yml. Determines what is
shown as a thumbnail for the IFU
"""
from vdat.gui.background import get_background
from vdat.libvdat.show_fits import show_thumbnails
self.display_type = display_type
# add widgets for each IFU
for ifu in self.fplane.ifus:
ifu.type_ = self.type_ # save this here for the IFU viewer
self.focalPlane_layout.addWidget(ifu, ifu.yid, ifu.xid, 1, 1)
# now create and show the thumbnails
get_background().run_now(show_thumbnails, self._conf,
self.display_type,
(self.tabs_conf['tabs'])[display_type],
global_scale=self.global_scale)