Skip to content

Commit fd5b22b

Browse files
authored
Merge pull request #38609 from mantidproject/ornl-next
Prepare for release candidate v6.11.0.3rc2
2 parents 17493fd + 4f567e7 commit fd5b22b

File tree

7 files changed

+139
-8
lines changed

7 files changed

+139
-8
lines changed

Framework/Algorithms/src/RebinRagged2.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ void RebinRagged::init() {
5757
declareProperty(std::make_unique<ArrayProperty<double>>("XMax"), "maximum x values with NaN meaning no maximum");
5858
declareProperty(std::make_unique<ArrayProperty<double>>("Delta"), "step parameter for rebin");
5959
declareProperty("PreserveEvents", true, "False converts event workspaces to histograms");
60+
declareProperty("FullBinsOnly", false, "Omit the final bin if it's width is smaller than the step size");
6061
}
6162

6263
std::map<std::string, std::string> RebinRagged::validateInputs() {
@@ -107,6 +108,7 @@ void RebinRagged::exec() {
107108
MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace");
108109

109110
bool preserveEvents = getProperty("PreserveEvents");
111+
bool fullBinsOnly = getProperty("FullBinsOnly");
110112

111113
// Rebinning in-place
112114
bool inPlace = (inputWS == outputWS);
@@ -123,6 +125,7 @@ void RebinRagged::exec() {
123125
auto rebin = createChildAlgorithm("Rebin", 0.0, 1.0);
124126
rebin->setProperty("InputWorkspace", inputWS);
125127
rebin->setProperty("PreserveEvents", preserveEvents);
128+
rebin->setProperty("FullBinsOnly", fullBinsOnly);
126129
const std::vector<double> params = {xmins[0], deltas[0], xmaxs[0]};
127130
rebin->setProperty("Params", params);
128131
rebin->execute();
@@ -164,7 +167,8 @@ void RebinRagged::exec() {
164167
const auto delta = deltas[hist];
165168

166169
HistogramData::BinEdges XValues_new(0);
167-
static_cast<void>(VectorHelper::createAxisFromRebinParams({xmin, delta, xmax}, XValues_new.mutableRawData()));
170+
static_cast<void>(VectorHelper::createAxisFromRebinParams({xmin, delta, xmax}, XValues_new.mutableRawData(),
171+
true, fullBinsOnly));
168172
EventList &el = eventOutputWS->getSpectrum(hist);
169173
el.setHistogram(XValues_new);
170174
}
@@ -188,7 +192,8 @@ void RebinRagged::exec() {
188192
const EventList &el = eventInputWS->getSpectrum(hist);
189193

190194
HistogramData::BinEdges XValues_new(0);
191-
static_cast<void>(VectorHelper::createAxisFromRebinParams({xmin, delta, xmax}, XValues_new.mutableRawData()));
195+
static_cast<void>(VectorHelper::createAxisFromRebinParams({xmin, delta, xmax}, XValues_new.mutableRawData(),
196+
true, fullBinsOnly));
192197

193198
MantidVec y_data, e_data;
194199
// The EventList takes care of histogramming.
@@ -242,7 +247,8 @@ void RebinRagged::exec() {
242247
const auto delta = deltas[hist];
243248

244249
HistogramData::BinEdges XValues_new(0);
245-
static_cast<void>(VectorHelper::createAxisFromRebinParams({xmin, delta, xmax}, XValues_new.mutableRawData()));
250+
static_cast<void>(VectorHelper::createAxisFromRebinParams({xmin, delta, xmax}, XValues_new.mutableRawData(), true,
251+
fullBinsOnly));
246252

247253
outputWS->setHistogram(hist, HistogramData::rebin(inputWS->histogram(hist), XValues_new));
248254
prog.report();

Framework/PythonInterface/test/python/plugins/algorithms/RebinRaggedTest.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,73 @@ def test_event_workspace(self):
126126
# parameters are set so all y-values are 0.6
127127
np.testing.assert_almost_equal(14, y, err_msg=label)
128128

129+
def test_FullBinsOnly(self):
130+
xExpected = [0.5, 2.5, 4.5, 6.5]
131+
yExpected = [10, 24, 38]
132+
133+
def Create1DWorkspace(size):
134+
xData = []
135+
yData = []
136+
j = 0.5
137+
for i in range(0, size + 1):
138+
xData.append(j)
139+
yData.append((i + 1) * 2)
140+
j = 0.75 + j
141+
yData.pop()
142+
ws = api.CreateWorkspace(xData, yData)
143+
return ws
144+
145+
inputWs = Create1DWorkspace(10)
146+
147+
api.RebinRagged(InputWorkspace=inputWs, OutputWorkspace="NotFullBinsOnly", Delta=2.0, PreserveEvents=True, FullBinsOnly=False)
148+
fullBinsOnlyWs = api.RebinRagged(
149+
InputWorkspace=inputWs, OutputWorkspace="FullBinsOnly", Delta=2.0, PreserveEvents=True, FullBinsOnly=True
150+
)
151+
152+
fullBinsXValues = AnalysisDataService.retrieve("FullBinsOnly").readX(0)
153+
fullBinsYValues = AnalysisDataService.retrieve("FullBinsOnly").readY(0)
154+
155+
notFullBinsXValues = AnalysisDataService.retrieve("NotFullBinsOnly").readX(0)
156+
157+
assert not fullBinsOnlyWs.isRaggedWorkspace()
158+
159+
assert len(fullBinsXValues) == len(xExpected)
160+
assert len(notFullBinsXValues) != len(fullBinsXValues)
161+
162+
for i in range(len(fullBinsXValues)):
163+
np.testing.assert_almost_equal(fullBinsXValues[i], xExpected[i])
164+
165+
for i in range(len(fullBinsYValues)):
166+
np.testing.assert_almost_equal(fullBinsYValues[i], yExpected[i])
167+
168+
api.DeleteWorkspace("NotFullBinsOnly")
169+
api.DeleteWorkspace("FullBinsOnly")
170+
api.DeleteWorkspace(inputWs)
171+
172+
def test_hist_workspace_fullBinsOnly(self):
173+
# numpy 1.7 (on rhel7) doesn't have np.full
174+
xmins = np.full((200,), 50.0)
175+
xmins[11] = 3000.0
176+
xmaxs = np.full((200,), 650.0)
177+
xmaxs[12] = 5000.0
178+
deltas = np.full(200, -2.0)
179+
deltas[13] = 100.0
180+
181+
inputWs = api.CreateSampleWorkspace(OutputWorkspace="RebinRagged_hist", WorkspaceType="Histogram", BinWidth=75, XMin=50)
182+
183+
notFullBinsOnlyWs = api.RebinRagged(
184+
InputWorkspace=inputWs, OutputWorkspace="NotFullBinsOnly", XMin=xmins, XMax=xmaxs, Delta=deltas, FullBinsOnly=False
185+
)
186+
fullBinsOnlyWs = api.RebinRagged(
187+
InputWorkspace=inputWs, OutputWorkspace="FullBinsOnly", XMin=xmins, XMax=xmaxs, Delta=deltas, FullBinsOnly=True
188+
)
189+
190+
assert len(fullBinsOnlyWs.readX(0)) != len(notFullBinsOnlyWs.readX(0))
191+
assert fullBinsOnlyWs.isRaggedWorkspace()
192+
api.DeleteWorkspace("NotFullBinsOnly")
193+
api.DeleteWorkspace("FullBinsOnly")
194+
api.DeleteWorkspace(inputWs)
195+
129196

130197
if __name__ == "__main__":
131198
unittest.main()

docs/source/algorithms/RebinRagged-v2.rst

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ The minimum and maximum values that are specified are interpreted as follows:
2020
The ``Delta`` parameter is required and can either be a single number which is common to all, or one number per spectra.
2121
Positive values are interpreted as constant step-size. Negative are logorithmic.
2222

23+
Please refer to :ref:`Rebin <algm-Rebin>` for a more analytical explanation of `FullBinsOnly`.
24+
2325
Usage
2426
-----
2527

@@ -39,6 +41,40 @@ This particular use-case, which uses the input workspace's binning, could be don
3941
Xmax=[10.20, 20.8, nan, nan, nan, 9.35])
4042
4143
44+
Sometimes due to the data or logarithmic rebinning, there are incomplete bins left over at the end of the spectrum. These incomplete bins may result in artifacts at the tail end. This can be removed by setting the `FullBinsOnly` parameter to `True`.
45+
46+
.. code-block:: python
47+
48+
from mantid.simpleapi import *
49+
50+
from time import time
51+
52+
53+
## create a workspace to be rebin-ragged
54+
wsname = "ws"
55+
CreateSampleWorkspace(
56+
OutputWorkspace=wsname,
57+
BankPixelWidth=3,
58+
)
59+
GroupDetectors(
60+
InputWorkspace=wsname,
61+
OutputWorkspace=wsname,
62+
GroupingPattern="0-3,4-5,6-8,9-12,13-14,15-17",
63+
)
64+
65+
# rebin the workspace raggedly
66+
xMin = [0.05,0.06,0.1,0.07,0.04, 0.04]
67+
xMax = [0.36,0.41,0.64,0.48,0.48,0.48]
68+
delta = [-0.000401475,-0.000277182,-0.000323453,-0.000430986,-0.000430986,-0.000430986]
69+
RebinRagged(
70+
InputWorkspace=wsname,
71+
XMin=xMin,
72+
XMax=xMax,
73+
Delta=delta,
74+
FullBinsOnly=True,
75+
OutputWorkspace=wsname,
76+
)
77+
4278
.. categories::
4379

4480
.. sourcelink::
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- :ref:`RebinRagged <algm-RebinRagged>` exposes FullBinsOnly from Rebin Algo.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- The colorbar (used in Sliceviewer) has been updated to again allow the registration of custom matplotlib colormaps in scripts.

qt/python/mantidqt/mantidqt/widgets/colorbar/colorbar.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,16 @@ class ColorbarWidget(QWidget):
4545
scaleNormChanged = Signal()
4646
# register additional color maps from file
4747
register_customized_colormaps()
48-
# create the list
49-
cmap_list = sorted([cmap for cmap in colormaps.keys() if not cmap.endswith("_r")])
5048

5149
def __init__(self, parent=None, default_norm_scale=None):
5250
"""
5351
:param default_scale: None uses linear, else either a string or tuple(string, other arguments), e.g. tuple('Power', exponent)
5452
"""
5553

56-
super(ColorbarWidget, self).__init__(parent)
54+
super().__init__(parent)
55+
56+
# create the list. Initialize in the init so that it can be updated if new colormaps are added
57+
self.cmap_list = sorted([cmap for cmap in colormaps.keys() if not cmap.endswith("_r")])
5758

5859
self.setWindowTitle("Colorbar")
5960
self.setMaximumWidth(100)
@@ -181,7 +182,11 @@ def set_mappable(self, mappable):
181182
self.colorbar = Colorbar(ax=self.ax, mappable=mappable)
182183
self.cmin_value, self.cmax_value = mappable.get_clim()
183184
self.update_clim_text()
184-
self.cmap_changed(cmap, False)
185+
try:
186+
self.cmap_changed(cmap, False)
187+
except ValueError:
188+
# the default mantid colormap is not available, just use matplotlib default
189+
pass
185190

186191
mappable_cmap = get_current_cmap(mappable)
187192

qt/python/mantidqt/mantidqt/widgets/colorbar/test/test_colorbar.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
from mantidqt.utils.qt.testing import start_qapplication
1515
from mantidqt.widgets.colorbar.colorbar import ColorbarWidget, NORM_OPTS
16-
from matplotlib.colors import LogNorm, Normalize, SymLogNorm
16+
from matplotlib.colors import LogNorm, Normalize, SymLogNorm, ListedColormap
1717

1818

1919
@start_qapplication
@@ -239,3 +239,18 @@ def test_invalid_cmin_syntax_is_reset(self):
239239
self.widget.clim_changed()
240240

241241
self.assertEqual("0.0", self.widget.cmin.text())
242+
243+
def test_custom_colormaps(self):
244+
# test that users can register custom colormaps and have it as an option in the colorbar
245+
cmap_name = "custom_cmap"
246+
self.assertFalse(cmap_name in plt.colormaps)
247+
self.assertTrue(self.widget.cmap.findText(cmap_name) == -1)
248+
249+
plt.colormaps.register(cmap=ListedColormap([[0, 0, 0], [0, 0, 1]]), name=cmap_name)
250+
self.assertTrue(cmap_name in plt.colormaps)
251+
252+
# now when you create a colorbar widget, the custom colormap should now be available
253+
cb = ColorbarWidget()
254+
self.assertTrue(cb.cmap.findText(cmap_name) != -1)
255+
256+
plt.colormaps.unregister(cmap_name)

0 commit comments

Comments
 (0)