"""Widget showing the IFU in the focal plane"""
from __future__ import (absolute_import, division, print_function,
unicode_literals)
import os
from textwrap import dedent
from PyQt4 import QtGui
from PyQt4.QtCore import pyqtSignal
from PyQt4.QtGui import QFrame, QMessageBox
from pyhetdex.het.fplane import IFU
import logging
import vdat.config as confp
from vdat.gui.ifu_viewer import IFUViewer
import vdat.utilities as vdatutil
[docs]class IFUWidget(QtGui.QLabel, IFU):
"""A custom class, derived from QLabel, desgined to contain a
picture of the IFU.
Initialize the widget and set a background colour and picture. Set the
passed ifu 'selected' parameter and set a appropriate style for the border
that reflects whether the IFU is selected or not. Save a reference to the
IFU object.
Parameters
----------
ifuid : string
id of the ifu
x, y : string or float
x and y position of the ifu in the focal plane
xid, yid : string or int
x (column) and y (row) id of the ifu in the ifu head mounting plate
(IHMP)
specid : string
id of the spectrograph where the ifu is plugged into
parent : :class:`QWidget` or derived instance, optional
A window to parent the widget to.
"""
set_image_signal = pyqtSignal()
"""A signal that triggers setImage(), allowing the image on the IFU widget
to be prompted to update from a thread """
def __init__(self, ifuid, x, y, xid, yid, specid, parent=None):
QtGui.QLabel.__init__(self, parent=parent)
IFU.__init__(self, ifuid, x, y, xid, yid, specid)
self._conf = confp.get_config('main')
self.borderStyleSelected = QFrame.Box | QFrame.Raised
self.borderStyleUnselected = 0
self._selected = False
self.widget = False # TODO: what is it?
self._exists = False # if exists different symbol
self.thumbnail = None
# Set the basic look of the widget
self.xsize = 42
self.ysize = 42
self.setScaledContents(True)
self.setLineWidth(3)
self.setMidLineWidth(3)
# Set the widget colour scheme button colour, background colour
palette = QtGui.QPalette(QtGui.QColor.fromRgb(0, 0, 255),
QtGui.QColor.fromRgb(0, 0, 0))
self.setPalette(palette)
# Add some info for the user when they hover a mouse over the button
self.setToolTip("""<html><head/><body><p>
<strong>IHMP:</strong>{:s},
<strong>IFUID:</strong>{:s}
</p></body></html>""".format(self.ihmpid,
self.ifuid))
self.setWhatsThis("<html><head/><body><p>An IFU</p></body></html>")
# Set the appropriate style for whether the IFU is selected or not
if self.selected:
self.setFrameStyle(self.borderStyleSelected)
else:
self.setFrameStyle(self.borderStyleUnselected)
# Minimum size of widget in pixels
self.setFixedWidth(self.xsize)
self.setFixedHeight(self.ysize)
# Stick a picture in, connect set image routine to signal
self.setImage()
self.set_image_signal.connect(self.setImage)
[docs] def setImage(self):
"""Set the image on the Widget, based on whether or not the IFU has
any input files, and as to whether any thumbnail exists for the IFU
.. todo::
Consider saving processing time by having scaled versions of the
empty.png and unreduced.png as class variables
"""
if self.thumbnail is not None:
self.pixmap = QtGui.QPixmap(self.thumbnail)
if self.pixmap.isNull():
log = logging.getLogger('logger')
log.debug("Marking corrupted file {:}".format(self.thumbnail))
if self.thumbnail.split('.')[-1] == "png":
os.rename(self.thumbnail, self.thumbnail+".corrupted")
self.thumbnail = None
else:
log.error("Thumbnail not a PNG file! %s", self.thumbnail)
self.thumbnail = None
return
elif self.exists:
unreduced = os.path.join(vdatutil.resource_directory(),
"unreduced.png")
self.pixmap = QtGui.QPixmap(unreduced)
else:
empty = os.path.join(vdatutil.resource_directory(), "empty.png")
self.pixmap = QtGui.QPixmap(empty)
# everything is OK
self.setPixmap(self.pixmap.scaled(self.xsize, self.ysize))
self.update()
[docs] def mouseDoubleClickEvent(self, event):
"""On double click open a popup with details on the selected IFU """
conf = confp.get_config('main')
try:
seldir = conf.get('redux_dirs', 'selected_dir')
except Exception:
infoBox = QMessageBox(QMessageBox.Information,
"Select a directory",
dedent(
"""
Select a directory from the panel on
the left to begin.
"""),
parent=self)
infoBox.exec_()
return
self.ifu_viewer = IFUViewer(seldir,
self, parent=self.window())
self.ifu_viewer.show()
[docs] def mouseReleaseEvent(self, event):
"""On a user clicking on the button, swap the logical value of the
ifu.selected parameter and change the look of the button to reflect
this.
Parameters
----------
event : :class:`QMouseReleaseEvent`
"""
self.selected = not self.selected
@property
def selected(self):
return self._selected
@selected.setter
[docs] def selected(self, isSel):
self._selected = isSel
if isSel:
self.setFrameStyle(self.borderStyleSelected)
else:
self.setFrameStyle(self.borderStyleUnselected)
self.set_image_signal.emit()
@property
def exists(self):
return self._exists
@exists.setter
[docs] def exists(self, exists):
self._exists = exists
self.set_image_signal.emit()
# Breaks everything....
# def resizeEvent(self, event):
# """
# A custom handler for resize events.
# Overrides a method of QWidget.
# Scales the picture with the resize.
#
# Parameters
# ----------
# event (QResizeEvent)
#
# """
# # Have to check the window had an old size (i.e. hasn't just
# # initialised)
# if event.oldSize().width() > -1:
# self.xsize *= event.size().width() / event.oldSize().width()
# self.ysize *= event.size().height() / event.oldSize().height()
# self.setPixmap(self.pixmap.scaled(self.xsize, self.ysize))