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 MDHistoWorkspace.

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

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:

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

Or, you can load a MDWorkspace .nxs file in Paraview if the proper plugin is installed.

Working with Table Workspaces in Python

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.getName() + " is a " + mdws.id()

Output:

mdws is a MDEventWorkspace<MDLeanEvent,3>

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 =", ws.getNEvents()
print "Number of dimensions =", ws.getNumDims()
print "Normalization =", ws.displayNormalization()
for i in range(ws.getNumDims()):
    dimension = ws.getDimension(i)
    print "\tDimension {0} Name: {1}".format(i,
       dimension.getName())

bc =ws.getBoxController()
print "Is the workspace using a file back end?", bc.isFileBacked()
backEndFilename = bc.getFilename()

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 =", 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.getName(),
       dimension.getMinimum(),
       dimension.getMaximum(),
       dimension.getUnits())

print "The dimension assigned to X =", ws.getXDimension().getName()
print "The dimension assigned to Y =", ws.getYDimension().getName()
try:
   print "The dimension assigned to Z =", ws.getZDimension().getName()
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")

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