A Matrix Workspace is a generic name for a family which contains measured (or derived) data (Y) with associated errors (E) and an axis (X) giving information about where the the measurement was made. The Matrix Workspace forms a 2D structure, more details on this will be provided below. This is the most common structure for storing data in Mantid. This covers several more detailed workspace types including:
All Matrix Workspaces contain one or more rows of data. A single row is formed of a set of arrays (Y, E, X). For example, the output of a single detector in a white-beam measuring wavelength would form a single row. In this scenario The x-axis (or “horizontal axis”) has units of length for wavelength, and Y would be the counts at each wavelength. The rows may have no correlation to each other. However, they are usually marked and sorted by some other attribute, such as detector number, or scattering angle. We call this row axis the “vertical axis”. Axis have Units.
Also they may contain:
As alluded to above, Matrix Workspace is an abstraction. Matrix Workspace provides access to the majority of the common information for all 2D workspaces in its family, without needing to know all the details of how that data is actually stored.
Matrix Workspaces have all the data and operations of the base Workspace class, but add operations to access the 2D data itself a useful way.
You can look at the Matrix Workspace API reference for a full list of properties and operations, but here are some of the key ones.
The methods for getting a variable to a Matrix Workspace is the same as shown in the Workspace help page.
If you want to check if a variable points to something that is a Matrix Workspace you can use this:
from mantid.simpleapi import *
from mantid.api import MatrixWorkspace
histoWS = CreateSampleWorkspace(WorkspaceType="Histogram")
if isinstance(histoWS, MatrixWorkspace):
print(histoWS.name() + " is a " + histoWS.id() + \
" and can be treated as a Matrix Workspace")
print("\nFor more Matrix Workspace types")
eventWS = CreateSampleWorkspace(WorkspaceType="Event")
svWS = CreateSingleValuedWorkspace()
tableWS = CreateEmptyTableWorkspace()
groupWS = GroupWorkspaces("histoWS,eventWS")
mdWS = CreateMDWorkspace(Dimensions=3, Extents='-10,10,-10,10,-10,10', Names='A,B,C', Units='U,U,U')
mdHistoWS=CreateMDHistoWorkspace(Dimensionality=2,Extents='-3,3,-10,10',SignalInput=range(0,100),ErrorInput=range(0,100),\
NumberOfBins='10,10',Names='Dim1,Dim2',Units='MomentumTransfer,EnergyTransfer')
myWorkspaceList = [histoWS,eventWS,svWS,tableWS,mdWS,mdHistoWS]
print("Is Matrix Workspace?\tType")
for ws in myWorkspaceList:
print("{0}\t{1}".format(isinstance(ws, MatrixWorkspace), ws.id()))
Output:
histoWS is a Workspace2D and can be treated as a Matrix Workspace
For more Matrix Workspace types
Is Matrix Workspace? Type
True Workspace2D
True EventWorkspace
True WorkspaceSingleValue
False TableWorkspace
False MDEventWorkspace<MDLeanEvent,3>
False MDHistoWorkspace
# find out the number of histograms on a workspace use getNumberHistograms()
print("number of histograms = {0}".format(ws.getNumberHistograms()))
# To find out the number of bins along the x-axis use blocksize()
print("number of bins = {0}".format(ws.blocksize()))
# To find out the bin containing a value use yIndexOfX()
print("bin index containing 502.2 for a histogram (0 by default) = {0}".format(ws.yIndexOfX(502.2)))
print("bin index containing 997.1 for histogram 272 = {0}".format(ws.yIndexOfX(997.1,272)))
# To find a workspace index from a spectrum number
print("workspace index for histogram 272 = {0}".format(ws.getIndexFromSpectrumNumber(272)))
# To get the Run Number use getRunNumber()
print("run number = {0}".format(ws.getRunNumber()))
Output:
number of histograms = 922
number of bins = 2663
bin index containing 502.2 for a histogram (0 by default) = 19
bin index containing 997.1 for histogram 272 = 39
workspace index for histogram 272 = 271
run number = 11015
You can get access to the Instrument for a workspace with
instrument = ws.getInstrument()
For the properties and operations of the instrument look at the Instrument help.
You can get access to the Run for a workspace with
run = ws.getRun()
For the properties and operations of the run object and how to access log data look at the Run help.
Axes are used primarily for labeling plots, but are also used as validation criteria for several algorithms. You can list out the axes of a workspace using the following code.
from mantid.simpleapi import CreateSampleWorkspace
ws = CreateSampleWorkspace()
for i in range(ws.axes()):
axis = ws.getAxis(i)
print("Axis {0} is a {1}{2}{3}".format(i,
"Spectrum Axis" if axis.isSpectra() else "",
"Text Axis" if axis.isText() else "",
"Numeric Axis" if axis.isNumeric() else ""))
unit = axis.getUnit()
print("\t caption:{0}".format(unit.caption()))
print("\t symbol:{0}".format(unit.symbol()))
Output:
Axis 0 is a Numeric Axis
caption:Time-of-flight
symbol:microsecond
Axis 1 is a Spectrum Axis
caption:Spectrum
symbol:
Setting the axisLabel
from mantid.simpleapi import CreateSampleWorkspace
ws = CreateSampleWorkspace()
axis = ws.getAxis(1)
# Create a new axis
axis.setUnit("Label").setLabel('Temperature', 'K')
unit = axis.getUnit()
print("New caption:{0}".format(unit.caption()))
print("New symbol:{0}".format(unit.symbol()))
Output:
New caption:Temperature
New symbol:K
Replacing the Axis
from mantid.api import NumericAxis
axis = ws.getAxis(1)
unit = axis.getUnit()
print("Old caption:{0}".format(unit.caption()))
print("Old symbol:{0}".format(unit.symbol()))
# Create a new axis
newAxis = NumericAxis.create(ws.getNumberHistograms())
newAxis.setUnit("Label").setLabel('Temperature', 'K')
# Set the vertical axis values
for idx in range(0, ws.getNumberHistograms()):
tempValue = idx*3+25 # some made up value
newAxis.setValue(idx, tempValue)
# Replace axis 1 with the new axis
ws.replaceAxis(1, newAxis)
axis = ws.getAxis(1)
unit = axis.getUnit()
print("New caption:{0}".format(unit.caption()))
print("New symbol:{0}".format(unit.symbol()))
print("New values: {0}".format(axis.extractValues()))
Output:
Old caption:Spectrum
Old symbol:
New caption:Temperature
New symbol:K
New values: [ 25. 28. ... 2785. 2788.]
Setting the Y Label
print(ws.YUnitLabel())
ws.setYUnitLabel("Elephants")
print(ws.YUnitLabel())
Output:
Counts
Elephants
# To create a copy of a workspace
wsClone = ws.clone()
# or
wsClone = CloneWorkspace(ws)
# To check if two variables point to the same workspace
if ws == wsClone:
print("They are the same workspace")
# To check if two workspaces have equal values
if ws.equals(wsClone, tolerance = 0.05):
print("They have the same data")
# To create a copy of a workspace
wsWavelength = ws.convertUnits(Target="Wavelength")
# or
wsWavelength = ConvertUnits(ws,Target="Wavelength")
# To rebin the workspace
ws = ws.rebin(Params = 200)
# or
ws = Rebin(ws, Params = 200)
# Mask detectors or spectra (or use the MaskDetectors algorithm
ws.maskDetectors(SpectraList=[2,3,4])
ws.maskDetectors(WorkspaceIndexList=range(101,105))
ws.maskDetectors(DetectorList=[150,160,170])
# To delete the workspace
ws.delete()
# or
DeleteWorkspace(wsClone)
# Do not access the python variable again as you will get a RuntimeError
# e.g. RuntimeError: Variable invalidated, data has been deleted.
A Matrix Workspace is essentially a 2D list of binned data where a workspace index, starting at 0, gives access to the data fields in each spectra.
The data is accessed using the readX(), readY() and readE() commands. Each of these commands takes a number that refers to the index on the workspace and returns a list of the data for that workspace index, i.e
# Get the Y vector for the second row of data
y_data2 = ws.readY(1)
for y in y_data2:
print(y)
# Or in loop access. Print the first value in all spectra
for index in range(0, ws.getNumberHistograms()):
#Note the round brackets followed by the square brackets
print(ws.readY(index)[0])
There are more examples how to Extract and manipulate workspace data here.
Matrix Workspaces can have algebraic operations applied to them directly without the need to call a specific algorithm, e.g. Plus
The expected operations of +,-,*,/ are supported with either a single number or another workspace as the second argument, e.g.
w1 = mtd['workspace1']
w2 = mtd['workspace2']
# Sum the two workspaces and place the output into a third
w3 = w1 + w2
# Multiply the new workspace by 2 and place the output into a new workspace
w4 = w3 * 2
It is also possible to replace one of the input workspaces using one of +=,-=,*=,/= e.g.
# Multiply a workspace by 2 and replace w1 with the output
w1 *= 2.0
# Add 'workspace2' to 'workspace1' and replace 'workspace1' with the output
w1 += w2
Category: Concepts