source: sasview/src/sas/qtgui/ColorMap.py @ 5d89f43

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalc
Last change on this file since 5d89f43 was 5d89f43, checked in by Piotr Rozyczko <rozyczko@…>, 7 years ago

Code review for ColorMap?

  • Property mode set to 100644
File size: 8.8 KB
Line 
1"""
2Allows users to change the range of the current graph
3"""
4from PyQt4 import QtGui
5from PyQt4 import QtCore
6import path_prepare
7
8import matplotlib as mpl
9from matplotlib import pylab
10import numpy
11
12from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
13from sas.sasgui.guiframe.dataFitting import Data2D
14from sas.qtgui.GuiUtils import formatNumber
15from rangeSlider import RangeSlider
16
17DEFAULT_MAP = 'jet'
18
19# Local UI
20from sas.qtgui.UI.ColorMapUI import Ui_ColorMapUI
21
22class ColorMap(QtGui.QDialog, Ui_ColorMapUI):
23    apply_signal = QtCore.pyqtSignal(tuple, str)
24    def __init__(self, parent=None, cmap=None, vmin=0.0, vmax=100.0, data=None):
25        super(ColorMap, self).__init__()
26
27        self.setupUi(self)
28        assert(isinstance(data, Data2D))
29
30        self.data = data
31        self._cmap_orig = self._cmap = cmap if cmap is not None else DEFAULT_MAP
32        self.all_maps = [m for m in pylab.cm.datad]
33        self.maps = sorted(m for m in self.all_maps if not m.endswith("_r"))
34        self.rmaps = sorted(set(self.all_maps) - set(self.maps))
35
36        self.vmin = self.vmin_orig = vmin
37        self.vmax = self.vmax_orig = vmax
38
39        # Initialize detector labels
40        self.initDetectorData()
41
42        # Initialize the combo box
43        self.initMapCombobox()
44
45        self.initRangeSlider()
46
47        # Add the color map component
48        self.initColorMap()
49
50        # Initialize validators on amplitude textboxes
51        validator_min = QtGui.QDoubleValidator(self.txtMinAmplitude)
52        validator_min.setNotation(0)
53        self.txtMinAmplitude.setValidator(validator_min)
54        validator_max = QtGui.QDoubleValidator(self.txtMaxAmplitude)
55        validator_max.setNotation(0)
56        self.txtMaxAmplitude.setValidator(validator_max)
57
58        # Set the initial amplitudes
59        self.txtMinAmplitude.setText(formatNumber(self.vmin))
60        self.txtMaxAmplitude.setText(formatNumber(self.vmax))
61
62        # Enforce constant size on the widget
63        self.setFixedSize(self.minimumSizeHint())
64
65        # Handle combobox changes
66        self.cbColorMap.currentIndexChanged.connect(self.onMapIndexChange)
67
68        # Handle checkbox changes
69        self.chkReverse.stateChanged.connect(self.onColorMapReversed)
70
71        # Handle the Reset button click
72        self.buttonBox.button(QtGui.QDialogButtonBox.Reset).clicked.connect(self.onReset)
73
74        # Handle the Apply button click
75        self.buttonBox.button(QtGui.QDialogButtonBox.Apply).clicked.connect(self.onApply)
76
77        # Handle the amplitude setup
78        self.txtMinAmplitude.editingFinished.connect(self.onAmplitudeChange)
79        self.txtMaxAmplitude.editingFinished.connect(self.onAmplitudeChange)
80
81    def cmap(self):
82        """
83        Getter for the color map
84        """
85        return self._cmap
86
87    def norm(self):
88        """
89        Getter for the color map norm
90        """
91        return (self._norm.vmin, self._norm.vmax)
92
93    def onReset(self):
94        """
95        Respond to the Reset button click
96        """
97        # Go back to original settings
98        self._cmap = self._cmap_orig
99        self.vmin = self.vmin_orig
100        self.vmax = self.vmax_orig
101        self._norm = mpl.colors.Normalize(vmin=self.vmin, vmax=self.vmax)
102        self.txtMinAmplitude.setText(formatNumber(self.vmin))
103        self.txtMaxAmplitude.setText(formatNumber(self.vmax))
104        self.initMapCombobox()
105        self.slider.setMinimum(self.vmin)
106        self.slider.setMaximum(self.vmax)
107        self.slider.setLowValue(self.vmin)
108        self.slider.setHighValue(self.vmax)
109        # Redraw the widget
110        self.redrawColorBar()
111        self.canvas.draw()
112
113    def onApply(self):
114        """
115        Respond to the Apply button click.
116        Send a signal to the plotter with vmin/vmax/cmap for chart update
117        """
118        self.apply_signal.emit(self.norm(), self.cmap())
119
120    def initDetectorData(self):
121        """
122        Fill out the Detector labels
123        """
124        xnpts = len(self.data.x_bins)
125        ynpts = len(self.data.y_bins)
126        self.lblWidth.setText(formatNumber(xnpts))
127        self.lblHeight.setText(formatNumber(ynpts))
128        xmax = max(self.data.xmin, self.data.xmax)
129        ymax = max(self.data.ymin, self.data.ymax)
130        qmax = numpy.sqrt(numpy.power(xmax, 2) + numpy.power(ymax, 2))
131        self.lblQmax.setText(formatNumber(qmax))
132        self.lblStopRadius.setText(formatNumber(self.data.xmin))
133
134    def initMapCombobox(self):
135        """
136        Fill out the combo box with all available color maps
137        """
138        if self._cmap in self.rmaps:
139            maps = self.rmaps
140            # Assure correct state of the checkbox
141            self.chkReverse.setChecked(True)
142        else:
143            maps = self.maps
144            # Assure correct state of the checkbox
145            self.chkReverse.setChecked(False)
146
147        self.cbColorMap.addItems(maps)
148        # Set the default/passed map
149        self.cbColorMap.setCurrentIndex(self.cbColorMap.findText(self._cmap))
150
151    def initRangeSlider(self):
152        """
153        Create and display the double slider for data range mapping.
154        """
155        self.slider = RangeSlider()
156        self.slider.setMinimum(self.vmin)
157        self.slider.setMaximum(self.vmax)
158        self.slider.setLowValue(self.vmin)
159        self.slider.setHighValue(self.vmax)
160        self.slider.setOrientation(QtCore.Qt.Horizontal)
161
162        self.slider_label = QtGui.QLabel()
163        self.slider_label.setText("Drag the sliders to adjust color range.")
164
165        def set_vmin(value):
166            self.vmin = value
167            self.txtMinAmplitude.setText(str(value))
168            self.updateMap()
169        def set_vmax(value):
170            self.vmax = value
171            self.txtMaxAmplitude.setText(str(value))
172            self.updateMap()
173
174        self.slider.lowValueChanged.connect(set_vmin)
175        self.slider.highValueChanged.connect(set_vmin)
176
177    def updateMap(self):
178        self._norm = mpl.colors.Normalize(vmin=self.vmin, vmax=self.vmax)
179        self.redrawColorBar()
180        self.canvas.draw()
181
182    def initColorMap(self):
183        """
184        Prepare and display the color map
185        """
186        self.fig = mpl.figure.Figure(figsize=(4, 1))
187        self.ax1 = self.fig.add_axes([0.05, 0.65, 0.9, 0.15])
188
189        self._norm = mpl.colors.Normalize(vmin=self.vmin, vmax=self.vmax)
190        self.redrawColorBar()
191        self.canvas = FigureCanvas(self.fig)
192
193        layout = QtGui.QVBoxLayout()
194        layout.addWidget(self.slider_label)
195        layout.addWidget(self.slider)
196        layout.addWidget(self.canvas)
197
198        self.widget.setLayout(layout)
199
200    def onMapIndexChange(self, index):
201        """
202        Respond to the color map change event
203        """
204        new_map = str(self.cbColorMap.itemText(index))
205        self._cmap = new_map
206        self.redrawColorBar()
207        self.canvas.draw()
208
209    def redrawColorBar(self):
210        """
211        Call ColorbarBase with current values, effectively redrawing the widget
212        """
213        self.cb = mpl.colorbar.ColorbarBase(self.ax1, cmap=self._cmap,
214                                            norm=self._norm,
215                                            orientation='horizontal')
216        self.cb.set_label('Color map range')
217
218    def onColorMapReversed(self, isChecked):
219        """
220        Respond to ticking/unticking the color map reverse checkbox
221        """
222        current_map = str(self.cbColorMap.currentText())
223        if isChecked:
224            # Add "_r" to map name for the reversed version
225            new_map = current_map + "_r"
226            maps = self.rmaps
227            # Assure the reversed map exists.
228            if new_map not in maps:
229                new_map = maps[0]
230        else:
231            new_map = current_map[:-2] # "_r" = last two chars
232            maps = self.maps
233            # Base map for the reversed map should ALWAYS exist,
234            # but let's be paranoid here
235            if new_map not in maps:
236                new_map = maps[0]
237
238        self._cmap = new_map
239        # Clear the content of the combobox.
240        # Needs signal blocking, or else onMapIndexChange() spoils it all
241        self.cbColorMap.blockSignals(True)
242        self.cbColorMap.clear()
243        # Add the new set of maps
244        self.cbColorMap.addItems(maps)
245        # Remove the signal block before the proper index set
246        self.cbColorMap.blockSignals(False)
247        self.cbColorMap.setCurrentIndex(self.cbColorMap.findText(new_map))
248
249    def onAmplitudeChange(self):
250        """
251        Respond to editing the amplitude fields
252        """
253        min_amp = self.vmin
254        max_amp = self.vmax
255
256        try:
257            min_amp = float(self.txtMinAmplitude.text())
258        except ValueError:
259            pass
260        try:
261            max_amp = float(self.txtMaxAmplitude.text())
262        except ValueError:
263            pass
264
265        self._norm = mpl.colors.Normalize(vmin=min_amp, vmax=max_amp)
266        self.redrawColorBar()
267        self.canvas.draw()
Note: See TracBrowser for help on using the repository browser.