\(\renewcommand\AA{\unicode{x212B}}\)
MD Workspace¶
The MD Workspace [MDWorkspace] (short for “Multi-Dimensional” Workspace) is a generic data structure holdings points (MDEvents) that are defined by their position in several dimensions.
See also
Description of MDWorkspace¶
- Dimensions: A MDWorkspace can have between 1 and 9 dimensions. - Each dimension is defined with a name, units, and minimum/maximum extents. 
 
- MDEvent: A MDEvent is simply a point in space defined by its coordinates, plus a signal (weight) and error. - The MDLeanEvent type contains only coordinates, signal and error. 
- The MDEvent type also contains a run index (for multiple runs summed into one workspace) and a detector ID, allowing for more information to be extracted. 
 
- The class is named MDEventWorkspace. 
Structure¶
The MDWorkspace is a container that can hold a large number of MDEvents. The events are organized into “boxes”: types are MDBox and MDGridBox. At the simplest level, an MDWorkspace will be a single MDBox with an unsorted bunch of events.
In order to allow for efficient searching and binning of these events, the boxes are organized into a recursive boxing structure (adaptive mesh refinement). During MDWorkspace construction, if a MDBox is found to contain too many events, it will be split into smaller boxes.
 
MDWorkspace_structure.png¶
The threshold for splitting is defined in CreateMDWorkspace as the SplitThreshold parameter. Each parent box will get split into N sub-boxes in each dimension. For example, in a 2D workspace, you might split a parent box into 4x4 sub-boxes, creating 16 MDBoxes under the parent box (which becomes a MDGridBox). The level of splitting is defined in the SplitInto parameter.
Creating a MDWorkspace¶
There are several algorithms that will create a MDWorkspace:
- CreateMDWorkspace creates a blank MDWorkspace with any arbitrary set of dimensions. 
- CreateMD Creates an MDWorkspace in the Q3D, HKL frame. 
- ConvertToDiffractionMDWorkspace converts an EventWorkspace or Workspace2D from detector space to reciprocal space, for elastic single-crystal or powder diffraction experiments. 
- ConvertToMD converts workspaces for inelastic experiments. 
- SliceMD takes a slice out of a MDWorkspace to create a new one. 
- LoadSQW converts from the SQW format. 
File-Backed MDWorkspaces¶
For workspaces with a large number of events that would not fit in memory, it is possible to use a NXS file back-end as a data store. The box structure will always remain in memory, but the underlying events will be stored in a file and retrieved only when required. This can be set at creation (CreateMDWorkspace) or when loading from a file, or an in-memory MDWorkspace can be converted to file-backed with the SaveMD algorithm.
Because of disk IO, file-backed MDWorkspaces are slower to process for some operations (e.g. binning or slicing). Some types of visualization and analysis, however, are just as fast with file-backed MDWorkspaces as their in-memory equivalent.
Viewing MDWorkspaces¶
- Right-click on a MDWorkspace and select: - Show Slice Viewer: to open the Sliceviewer, which shows 2D slices of the multiple-dimensional workspace. 
 
Working with Table Workspaces in Python¶
Accessing Workspaces¶
The methods for getting a variable to an MDWorkspace is the same as shown in the Workspace help page.
If you want to check if a variable points to something that is an MDWorkspace Workspace you can use this:
from mantid.api import IMDEventWorkspace
mdws = CreateMDWorkspace(Dimensions=3, Extents='-10,10,-10,10,-10,10', Names='A,B,C', Units='U,U,U')
if isinstance(mdws, IMDEventWorkspace):
    print(mdws.name() + " is a " + mdws.id())
Output:
mdws is a MDEventWorkspace<MDLeanEvent,3>
MD Workspace Properties¶
For a full list of the available properties and operation look at the IMDEventWorkspace api page.
ws = CreateMDWorkspace(Dimensions='2', EventType='MDEvent', Extents='-10,10,-10,10',
                      Names='Q_lab_x,Q_lab_y', Units='A,B')
FakeMDEventData(ws, UniformParams="1000000")
print("Number of events = {}".format(ws.getNEvents()))
print("Number of dimensions = {}".format(ws.getNumDims()))
print("Normalization = {}".format(ws.displayNormalization()))
for i in range(ws.getNumDims()):
    dimension = ws.getDimension(i)
    print("\tDimension {0} Name: {1}".format(i,
       dimension.name))
bc =ws.getBoxController()
print("Is the workspace using a file back end? {}".format(bc.isFileBacked()))
backEndFilename = bc.getFilename()
Dimensions¶
As a generic multi dimensional container being able to access information about the dimensions is very important.
ws = CreateMDWorkspace(Dimensions='3', EventType='MDEvent', Extents='-10,10,-5,5,-1,1',
                     Names='Q_lab_x,Q_lab_y,Q_lab_z', Units='1\A,1\A,1\A')
FakeMDEventData(ws, UniformParams="1000000")
print("Number of dimensions = {}".format(ws.getNumDims()))
for i in range(ws.getNumDims()):
   dimension = ws.getDimension(i)
   print("\tDimension {0} Name: {1} id: {2} Range: {3}-{4} {5}".format(i,
       dimension.getDimensionId(),
       dimension.name,
       dimension.getMinimum(),
       dimension.getMaximum(),
       dimension.getUnits()))
print("The dimension assigned to X = {}".format(ws.getXDimension().name))
print("The dimension assigned to Y = {}".format(ws.getYDimension().name))
try:
   print("The dimension assigned to Z = {}".format(ws.getZDimension().name))
except RuntimeError:
    # if the dimension does not exist you will get a RuntimeError
   print("Workspace does not have a Z dimension")
# you can also get a dimension by it's id
dim = ws.getDimensionIndexById("Q_lab_x")
# or name
dim = ws.getDimensionIndexByName("Q_lab_x")
Accessing the Data¶
To access the data of an MDWorkspace you need to convert it to a regular grid, or MD Histogram Workspace.
# Setup
mdWS = CreateMDWorkspace(Dimensions=4, Extents=[-1,1,-1,1,-1,1,-10,10], Names="H,K,L,E", Units="U,U,U,V")
FakeMDEventData(InputWorkspace=mdWS, PeakParams='500000,0,0,0,0,3')
# Create a histogrammed (binned) workspace with 100 bins in each of the H, K and L dimensions
histoWS = BinMD(InputWorkspace=mdWS, AlignedDim0='H,-1,1,100', AlignedDim1='K,-1,1,100', AlignedDim2='L,-1,1,100')
# Or you can also use CutMD, to define bin widths and the cut projection
from mantid.api import Projection
SetUB(Workspace=mdWS, a=1, b=1, c=1, alpha=90, beta=90, gamma=90)
SetSpecialCoordinates(InputWorkspace=mdWS, SpecialCoordinates='HKL')
projection = Projection([1,1,0], [-1,1,0])
proj_ws = projection.createWorkspace()
# Apply the cut with bin widths of 0.1 in  H,K and L and integrating over -5 to +5 in E
out_md = CutMD(mdWS, Projection=proj_ws, PBins=([0.1], [0.1], [0.1], [-5,5]), NoPix=True)
Category: Concepts