Skip to content
Snippets Groups Projects
Unverified Commit 4248d376 authored by Pete Peterson's avatar Pete Peterson Committed by GitHub
Browse files

Merge pull request #22398 from mantidproject/22027_directtools_log_scale

Add plotting in log scale to directtools
parents 834edca9 36717927
No related branches found
No related tags found
No related merge requests found
......@@ -42,5 +42,10 @@ Instrument Definitions
- The source component of ILL's IN6 has been moved from :math:`z = -0.395` to :math:`z = -0.595` meters and renamed to ``suppressor_chopper``.
- New CNCS geometry and parameters for 2018B cycle
Python
------
- The plotting methods in the :ref:`directtools <Directtools Python module>` python module now support logarithmic scales.
:ref:`Release 3.13.0 <v3.13.0>`
......@@ -4,6 +4,7 @@ import collections
from mantid import mtd
from mantid.simpleapi import DeleteWorkspace, LineProfile, OneMinusExponentialCor, Transpose
import matplotlib
import matplotlib.colors
from matplotlib import pyplot
import numpy
from scipy import constants
......@@ -294,7 +295,7 @@ def nanminmax(workspace, horMin=-numpy.inf, horMax=numpy.inf, vertMin=-numpy.inf
return cMin, cMax
def plotconstE(workspaces, E, dE, style='l', keepCutWorkspaces=True):
def plotconstE(workspaces, E, dE, style='l', keepCutWorkspaces=True, xscale='linear', yscale='linear'):
"""Plot line profiles at constant energy transfer from :math:`S(Q,E)` workspace.
Creates cut workspaces using :ref:`algm-LineProfile`, then plots the cuts. A list of workspaces,
......@@ -313,9 +314,14 @@ def plotconstE(workspaces, E, dE, style='l', keepCutWorkspaces=True):
:type style: str
:param keepCutWorkspaces: whether or not keep the cut workspaces in the ADS
:type keepCutWorkspaces: bool
:param xscale: horizontal axis scaling: 'linear', 'log', 'symlog', 'logit'
:type xscale: str
:param yscale: vertical axis scaling: 'linear', 'log', 'symlog', 'logit'
:type yscale: str
:returns: A tuple of (:class:`matplotlib.Figure`, :class:`matplotlib.Axes`, a :class:`list` of names)
"""
figure, axes, cutWSList = plotcuts('Horizontal', workspaces, E, dE, '$E$', 'meV', style, keepCutWorkspaces)
figure, axes, cutWSList = plotcuts('Horizontal', workspaces, E, dE, '$E$', 'meV', style, keepCutWorkspaces,
xscale, yscale)
_profiletitle(workspaces, '$E$', 'meV', E, dE, figure)
axes.legend()
axes.set_xlim(xmin=0.)
......@@ -326,7 +332,7 @@ def plotconstE(workspaces, E, dE, style='l', keepCutWorkspaces=True):
return figure, axes, cutWSList
def plotconstQ(workspaces, Q, dQ, style='l', keepCutWorkspaces=True):
def plotconstQ(workspaces, Q, dQ, style='l', keepCutWorkspaces=True, xscale='linear', yscale='linear'):
"""Plot line profiles at constant momentum transfer from :math:`S(Q,E)` workspace.
Creates cut workspaces using :ref:`algm-LineProfile`, then plots the cuts. A list of workspaces,
......@@ -345,9 +351,14 @@ def plotconstQ(workspaces, Q, dQ, style='l', keepCutWorkspaces=True):
:type style: str
:param keepCutWorkspaces: whether or not keep the cut workspaces in the ADS
:type keepCutWorkspaces: bool
:param xscale: horizontal axis scaling: 'linear', 'log', 'symlog', 'logit'
:type xscale: str
:param yscale: vertical axis scaling: 'linear', 'log', 'symlog', 'logit'
:type yscale: str
:returns: A tuple of (:class:`matplotlib.Figure`, :class:`matplotlib.Axes`, a :class:`list` of names)
"""
figure, axes, cutWSList = plotcuts('Vertical', workspaces, Q, dQ, '$Q$', '\\AA$^{-1}$', style, keepCutWorkspaces)
figure, axes, cutWSList = plotcuts('Vertical', workspaces, Q, dQ, '$Q$', '\\AA$^{-1}$', style, keepCutWorkspaces,
xscale, yscale)
_profiletitle(workspaces, '$Q$', '\\AA$^{-1}$', Q, dQ, figure)
axes.legend()
axes.set_xlim(xmin=-10.)
......@@ -359,7 +370,7 @@ def plotconstQ(workspaces, Q, dQ, style='l', keepCutWorkspaces=True):
return figure, axes, cutWSList
def plotcuts(direction, workspaces, cuts, widths, quantity, unit, style='l', keepCutWorkspaces=True):
def plotcuts(direction, workspaces, cuts, widths, quantity, unit, style='l', keepCutWorkspaces=True, xscale='linear', yscale='linear'):
"""Cut and plot multiple line profiles.
Creates cut workspaces using :ref:`algm-LineProfile`, then plots the cuts. A list of workspaces,
......@@ -384,6 +395,10 @@ def plotcuts(direction, workspaces, cuts, widths, quantity, unit, style='l', kee
:type style: str
:param keepCutWorkspaces: whether or not keep the cut workspaces in the ADS
:type keepCutWorkspaces: bool
:param xscale: horizontal axis scaling: 'linear', 'log', 'symlog', 'logit'
:type xscale: str
:param yscale: vertical axis scaling: 'linear', 'log', 'symlog', 'logit'
:type yscale: str
:returns: A tuple of (:class:`matplotlib.Figure`, :class:`matplotlib.Axes`, a :class:`list` of names)
"""
workspaces = _normwslist(workspaces)
......@@ -416,11 +431,13 @@ def plotcuts(direction, workspaces, cuts, widths, quantity, unit, style='l', kee
markerStyle, markerIndex = _chooseMarker(markers, markerIndex)
label = _label(ws, cut, width, len(workspaces) == 1, len(cuts) == 1, len(widths) == 1, quantity, unit)
axes.errorbar(line, specNum=0, linestyle=lineStyle, marker=markerStyle, label=label, distribution=True)
axes.set_xscale(xscale)
axes.set_yscale(yscale)
_profileytitle(workspaces[0], axes)
return figure, axes, cutWSList
def plotprofiles(workspaces, labels=None, style='l'):
def plotprofiles(workspaces, labels=None, style='l', xscale='linear', yscale='linear'):
"""Plot line profile workspaces.
Plots the first histograms from given workspaces.
......@@ -431,6 +448,10 @@ def plotprofiles(workspaces, labels=None, style='l'):
:type labels: str, a :class:`list` of strings or None
:param style: plot style: 'l' for lines, 'm' for markers, 'lm' for both
:type style: str
:param xscale: horizontal axis scaling: 'linear', 'log', 'symlog', 'logit'
:type xscale: str
:param yscale: vertical axis scaling: 'linear', 'log', 'symlog', 'logit'
:type yscale: str
:returns: a tuple of (:mod:`matplotlib.Figure`, :mod:`matplotlib.Axes`)
"""
workspaces = _normwslist(workspaces)
......@@ -450,6 +471,8 @@ def plotprofiles(workspaces, labels=None, style='l'):
if 'm' in style:
markerStyle, markerIndex = _chooseMarker(markers, markerIndex)
axes.errorbar(ws, specNum=0, linestyle=lineStyle, marker=markerStyle, label=label, distribution=True)
axes.set_xscale(xscale)
axes.set_yscale(yscale)
_profileytitle(workspaces[0], axes)
xUnit = workspaces[0].getAxis(0).getUnit().unitID()
if xUnit == 'DeltaE':
......@@ -459,7 +482,7 @@ def plotprofiles(workspaces, labels=None, style='l'):
return figure, axes
def plotSofQW(workspace, QMin=0., QMax=None, EMin=None, EMax=None, VMin=0., VMax=None, colormap='jet'):
def plotSofQW(workspace, QMin=0., QMax=None, EMin=None, EMax=None, VMin=0., VMax=None, colormap='jet', colorscale='linear'):
"""Plot a 2D :math:`S(Q,E)` workspace.
:param workspace: a workspace to plot
......@@ -478,6 +501,8 @@ def plotSofQW(workspace, QMin=0., QMax=None, EMin=None, EMax=None, VMin=0., VMax
:type VMax: float or None
:param colormap: name of the colormap
:type colormap: str
:param colorscale: color map scaling: 'linear', 'log'
:type colorscale: str
:returns: a tuple of (:mod:`matplotlib.Figure`, :mod:`matplotlib.Axes`)
"""
# Accept both workspace names and actual workspaces.
......@@ -496,14 +521,26 @@ def plotSofQW(workspace, QMin=0., QMax=None, EMin=None, EMax=None, VMin=0., VMax
if EMax is None:
EAxis = workspace.getAxis(1).extractValues()
EMax = numpy.amax(EAxis)
if VMin is None:
VMin = 0.
if VMax is None:
vertMax = EMax if EMax is not None else numpy.inf
dummy, VMax = nanminmax(workspace, horMin=QMin, horMax=QMax, vertMin=EMin, vertMax=vertMax)
VMax /= 100.
if VMin is None:
VMin = 0.
colorNormalization = None
if colorscale == 'linear':
colorNormalization = matplotlib.colors.Normalize()
elif colorscale == 'log':
if VMin <= 0.:
if VMax > 0.:
VMin = VMax / 1000.
else:
raise RuntimeError('Cannot plot negative range in log scale.')
colorNormalization = matplotlib.colors.LogNorm()
else:
raise RuntimeError('Unknown colorscale: ' + colorscale)
print('Plotting intensity range: {}...{}'.format(VMin, VMax))
contours = axes.pcolor(workspace, vmin=VMin, vmax=VMax, distribution=True, cmap=colormap)
contours = axes.pcolor(workspace, vmin=VMin, vmax=VMax, distribution=True, cmap=colormap, norm=colorNormalization)
colorbar = figure.colorbar(contours)
if isSusceptibility:
colorbar.set_label("$\\chi''(Q,E)$ (arb. units)")
......
......@@ -182,6 +182,19 @@ class DirectTest(unittest.TestCase):
}
testhelpers.assertRaisesNothing(self, directtools.plotconstE, **kwargs)
def test_plotconstE_loglog(self):
ws = LoadILLTOF('ILL/IN4/084446.nxs')
kwargs = {
'workspaces': ws,
'E' : 13.,
'dE' : 1.5,
'xscale': 'log',
'yscale': 'log'
}
figure, axes, cuts = testhelpers.assertRaisesNothing(self, directtools.plotconstE, **kwargs)
self.assertEquals(axes.get_xscale(), 'log')
self.assertEquals(axes.get_yscale(), 'log')
def test_plotconstQ_nonListArgsExecutes(self):
ws = LoadILLTOF('ILL/IN4/084446.nxs')
kwargs = {
......@@ -221,6 +234,19 @@ class DirectTest(unittest.TestCase):
}
testhelpers.assertRaisesNothing(self, directtools.plotconstQ, **kwargs)
def test_plotconstQ_loglog(self):
ws = LoadILLTOF('ILL/IN4/084446.nxs')
kwargs = {
'workspaces': ws,
'Q' : 523.,
'dQ' : 17.,
'xscale': 'log',
'yscale': 'log'
}
figure, axes, cuts = testhelpers.assertRaisesNothing(self, directtools.plotconstQ, **kwargs)
self.assertEquals(axes.get_xscale(), 'log')
self.assertEquals(axes.get_yscale(), 'log')
def test_plotcuts_keepCutWorkspaces(self):
ws = LoadILLTOF('ILL/IN4/084446.nxs', StoreInADS=False)
kwargs = {
......@@ -253,6 +279,23 @@ class DirectTest(unittest.TestCase):
self.assertEquals(len(cuts), 0)
self.assertEquals(mtd.size(), 0)
def test_plotcuts_loglog(self):
ws = LoadILLTOF('ILL/IN4/084446.nxs', StoreInADS=False)
kwargs = {
'direction' : 'Vertical',
'workspaces' : ws,
'cuts' : 500.,
'widths': 10.,
'quantity': 'TOF',
'unit': 'microseconds',
'xscale': 'log',
'yscale': 'log'
}
self.assertEquals(mtd.size(), 0)
figure, axes, cuts = testhelpers.assertRaisesNothing(self, directtools.plotcuts, **kwargs)
self.assertEquals(axes.get_xscale(), 'log')
self.assertEquals(axes.get_yscale(), 'log')
def test_plotprofiles_noXUnitsExecutes(self):
xs = numpy.linspace(-3., 10., 12)
ys = numpy.tile(1., len(xs) - 1)
......@@ -286,6 +329,15 @@ class DirectTest(unittest.TestCase):
numpy.testing.assert_equal(axes.get_lines()[0].get_data()[0], (xs[1:] + xs[:-1])/2)
numpy.testing.assert_equal(axes.get_lines()[0].get_data()[1], ys)
def test_plotprofiles_loglog(self):
xs = numpy.linspace(-3., 10., 12)
ys = numpy.tile(1., len(xs) - 1)
ws = CreateWorkspace(DataX=xs, DataY=ys, NSpec=1, UnitX='MomentumTransfer', StoreInADS=False)
kwargs = {'workspaces': ws, 'xscale': 'log', 'yscale': 'log'}
figure, axes = testhelpers.assertRaisesNothing(self, directtools.plotprofiles, **kwargs)
self.assertEquals(axes.get_xscale(), 'log')
self.assertEquals(axes.get_yscale(), 'log')
def test_plotSofQW(self):
ws = LoadILLTOF('ILL/IN4/084446.nxs')
kwargs = {'workspace': 'ws'}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment