Skip to content

Commit

Permalink
Merge pull request #509 from mantidproject/11304_createmd
Browse files Browse the repository at this point in the history
CreateMD
  • Loading branch information
AndreiSavici committed Apr 2, 2015
2 parents 3f3e36e + 0dc118d commit fb04718
Show file tree
Hide file tree
Showing 5 changed files with 473 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
#pylint: disable=invalid-name,no-init
from mantid.kernel import *
from mantid.api import *
from mantid.simpleapi import *
import numpy as np
import __builtin__


class CreateMD(DataProcessorAlgorithm):

def _possible_emodes(self):
return ['Elastic', 'Direct', 'Indirect']

def _add_sample_log(self, workspace, log_name, log_number):
add_log = self.createChildAlgorithm('AddSampleLog')
add_log.setProperty('Workspace', workspace)
add_log.setProperty('LogName', str(log_name))
add_log.setProperty('LogText', str(log_number))
add_log.setProperty('LogType', 'Number')
add_log.execute()

def _set_goniometer(self, workspace):

axis0 = ','.join(map(str, ['gl', 0, 0, 1, 1]))
axis1 = ','.join(map(str, ['gs', 1, 0, 0, 1]))
axis2 = ','.join(map(str, ['psi', 0, 1, 0, 1]))

set_goniometer = self.createChildAlgorithm('SetGoniometer')
set_goniometer.setProperty('Workspace', workspace)
set_goniometer.setProperty('Axis0', axis0)
set_goniometer.setProperty('Axis1', axis1)
set_goniometer.setProperty('Axis2', axis2)
set_goniometer.execute()

def _set_ub(self, workspace, a, b, c, alpha, beta, gamma, u, v):
set_ub = self.createChildAlgorithm('SetUB')
set_ub.setProperty('Workspace', workspace)
set_ub.setProperty('a', a)
set_ub.setProperty('b', b)
set_ub.setProperty('c', c)
set_ub.setProperty('alpha', alpha)
set_ub.setProperty('beta', beta)
set_ub.setProperty('gamma', gamma)
set_ub.setProperty('u', u)
set_ub.setProperty('v', v)
set_ub.execute()

def _convert_to_md(self, workspace, analysis_mode):

# Find the Min Max extents
min_max_alg = self.createChildAlgorithm('ConvertToMDMinMaxGlobal')
min_max_alg.setProperty('InputWorkspace', workspace)
min_max_alg.setProperty('QDimensions', 'Q3D')
min_max_alg.setProperty('dEAnalysisMode', analysis_mode)
min_max_alg.execute()
min_values = min_max_alg.getProperty('MinValues').value
max_values = min_max_alg.getProperty('MaxValues').value

# Convert to MD
convert_alg = self.createChildAlgorithm('ConvertToMD')
convert_alg.setProperty('InputWorkspace', workspace)
convert_alg.setPropertyValue('OutputWorkspace', 'dummy')
convert_alg.setProperty('QDimensions', 'Q3D')
convert_alg.setProperty('QConversionScales', 'HKL')
convert_alg.setProperty('dEAnalysisMode', analysis_mode)
convert_alg.setProperty('MinValues', min_values)
convert_alg.setProperty('MaxValues', max_values)
convert_alg.execute()
return convert_alg.getProperty('OutputWorkspace').value

def _merge_runs(self, to_merge):

merge_alg = self.createChildAlgorithm('MergeMD')
merge_alg.setProperty('InputWorkspaces', to_merge)
merge_alg.setPropertyValue('OutputWorkspace', 'dummy')
merge_alg.execute()
return merge_alg.getProperty('OutputWorkspace').value

def _single_run(self, input_workspace, emode, psi, gl, gs, alatt=None, angdeg=None, u=None, v=None,):
import numpy as np
ub_params = map(any, [alatt, angdeg, u, v])
goniometer_params = [psi, gl, gs]
if any(ub_params) and not all(ub_params):
raise ValueError("Either specify all of alatt, angledeg, u, v or none of them")
elif all(ub_params):
if input_workspace.sample().hasOrientedLattice():
logger.warning("Sample already has a UB. This will not be overwritten by %s. Use ClearUB and re-run."%self.name())
else:
self._set_ub(workspace=input_workspace, a=alatt[0], b=alatt[1], c=alatt[2], alpha=angdeg[0], beta=angdeg[1], gamma=angdeg[2], u=u, v=v)

if any(goniometer_params):
self._add_sample_log(workspace=input_workspace, log_name='gl', log_number=gl)
self._add_sample_log(workspace=input_workspace, log_name='gs', log_number=gs)
self._add_sample_log(workspace=input_workspace, log_name='psi', log_number=psi)
self._set_goniometer(workspace=input_workspace)

output_run = self._convert_to_md(workspace=input_workspace, analysis_mode=emode)
return output_run


def category(self):
return 'MDAlgorithms'

def summary(self):
return 'Creates a mutlidimensional workspace by transforming and combining individual runs.'

def PyInit(self):
self.declareProperty(StringArrayProperty('InputWorkspaces', values=[], direction=Direction.Input, validator=StringArrayMandatoryValidator()),
doc='Matrix workspace to slice')

self.declareProperty('Emode', defaultValue='Direct', validator=StringListValidator(self._possible_emodes()), direction=Direction.Input, doc='Analysis mode ' + str(self._possible_emodes()) )

self.declareProperty(FloatArrayProperty('Alatt', values=[], validator=FloatArrayMandatoryValidator(), direction=Direction.Input ), doc='Lattice parameters' )

self.declareProperty(FloatArrayProperty('Angdeg', values=[], validator=FloatArrayMandatoryValidator(), direction=Direction.Input ), doc='Lattice angles' )

self.declareProperty(FloatArrayProperty('u', values=[], validator=FloatArrayMandatoryValidator(), direction=Direction.Input ), doc='Lattice vector parallel to neutron beam' )

self.declareProperty(FloatArrayProperty('v', values=[], validator=FloatArrayMandatoryValidator(), direction=Direction.Input ), doc='Lattice vector perpendicular to neutron beam in the horizontal plane' )

self.declareProperty(FloatArrayProperty('Psi', values=[], direction=Direction.Input), doc='Psi rotation in degrees. Optional or one entry per run.' )

self.declareProperty(FloatArrayProperty('Gl', values=[], direction=Direction.Input), doc='gl rotation in degrees. Optional or one entry per run.' )

self.declareProperty(FloatArrayProperty('Gs', values=[], direction=Direction.Input), doc='gs rotation in degrees. Optional or one entry per run.' )

self.declareProperty(IMDWorkspaceProperty('OutputWorkspace', '', direction=Direction.Output ), doc='Output MDWorkspace')

def _validate_inputs(self):

emode = self.getProperty('Emode').value
alatt = self.getProperty('Alatt').value
angdeg = self.getProperty('Angdeg').value
u = self.getProperty('u').value
v = self.getProperty('v').value
psi = self.getProperty('Psi').value
gl = self.getProperty('Gl').value
gs = self.getProperty('Gs').value

input_workspaces = self.getProperty("InputWorkspaces").value

ws_entries = len(input_workspaces)

if ws_entries < 1:
raise ValueError("Need one or more input workspace")

if len(u) != 3:
raise ValueError("u must have 3 components")

if len(v) != 3:
raise ValueError("v must have 3 components")

if len(alatt) != 3:
raise ValueError("lattice parameters must have 3 components")

if len(angdeg) != 3:
raise ValueError("Angle must have 3 components")

if not emode in self._possible_emodes():
raise ValueError("Unknown emode %s Allowed values are %s" % (emode, self._possible_emodes()))

if len(psi) > 0 and len(psi) != ws_entries:
raise ValueError("If Psi is given a entry should be provided for every input workspace")

if len(gl) > 0 and len(gl) != ws_entries:
raise ValueError("If Gl is given a entry should be provided for every input workspace")

if len(gs) > 0 and len(gs) != ws_entries:
raise ValueError("If Gs is given a entry should be provided for every input workspace")


def PyExec(self):

logger.warning('You are running algorithm %s that is the beta stage of development' % (self.name()))

emode = self.getProperty('Emode').value
alatt = self.getProperty('Alatt').value
angdeg = self.getProperty('Angdeg').value
u = self.getProperty('u').value
v = self.getProperty('v').value
psi = self.getProperty('Psi').value
gl = self.getProperty('Gl').value
gs = self.getProperty('Gs').value

input_workspaces = self.getProperty("InputWorkspaces").value

ws_entries = len(input_workspaces)

self._validate_inputs()

if len(psi) == 0:
psi = [0.0] * ws_entries

if len(gl) == 0:
gl = [0.0] * ws_entries

if len(gs) == 0:
gs = [0.0] * ws_entries

output_workspace = None
run_md = None

to_merge_names = list()

run_data = zip(input_workspaces, psi, gl, gs)
for run_entry in run_data:
ws_name, psi_entry, gl_entry, gs_entry = run_entry
ws = AnalysisDataService.retrieve(ws_name)
run_md = self._single_run(input_workspace=ws, emode=emode, alatt=alatt, angdeg=angdeg, u=u, v=v, psi=psi_entry, gl=gl_entry, gs=gs_entry)
to_merge_name = ws_name + "_md"
AnalysisDataService.addOrReplace(to_merge_name, run_md)
to_merge_names.append(to_merge_name)

if len(to_merge_names) > 1:
output_workspace = self._merge_runs(to_merge_names)
else:
output_workspace = AnalysisDataService.retrieve(to_merge_names[0])

# Clear out temporary workspaces.
for ws in to_merge_names:
DeleteWorkspace(ws)

self.setProperty("OutputWorkspace", output_workspace)








AlgorithmFactory.subscribe(CreateMD)
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import unittest
import testhelpers
import numpy as np
from mantid.simpleapi import *
from mantid.api import AlgorithmManager, IMDHistoWorkspace, IMDEventWorkspace


class CreateMDTest(unittest.TestCase):

def test_init(self):
alg = AlgorithmManager.create("CreateMD")
alg.initialize()

def test_must_have_more_than_one_input_workspace(self):
alg = AlgorithmManager.create("CreateMD")
alg.setRethrows(True)
alg.initialize()
self.assertRaises(ValueError, alg.setProperty, "InputWorkspaces", [])

def test_set_up_madatory(self):

alg = AlgorithmManager.create("CreateMD")
alg.setRethrows(True)
alg.initialize()
alg.setPropertyValue("OutputWorkspace", "mdworkspace")
alg.setProperty("InputWorkspaces", ['a', 'b'])
alg.setProperty("Emode", "Direct")
alg.setProperty("Alatt", [1,1,1])
alg.setProperty("Angdeg", [90,90,90])
alg.setProperty("u", [0,0,1])
alg.setProperty("v", [1,0,0])

def test_psi_right_size(self):

input_workspace = CreateSampleWorkspace(NumBanks=1, BinWidth=2000)
AddSampleLog(input_workspace, LogName='Ei', LogText='12.0', LogType='Number')

alg = AlgorithmManager.create("CreateMD")
alg.setRethrows(True)
alg.initialize()
alg.setPropertyValue("OutputWorkspace", "mdworkspace")
alg.setProperty("InputWorkspaces", ['input_workspace'])
alg.setProperty("Emode", "Direct")
alg.setProperty("Alatt", [1,1,1])
alg.setProperty("Angdeg", [90,90,90])
alg.setProperty("u", [0,0,1])
alg.setProperty("v", [1,0,0])
alg.setProperty("Psi", [0, 0, 0]) # Too large
alg.setProperty("Gl", [0]) # Right size
alg.setProperty("Gs", [0]) # Right size
self.assertRaises(RuntimeError, alg.execute)
DeleteWorkspace(input_workspace)

def test_gl_right_size(self):

input_workspace = CreateSampleWorkspace(NumBanks=1, BinWidth=2000)
AddSampleLog(input_workspace, LogName='Ei', LogText='12.0', LogType='Number')

alg = AlgorithmManager.create("CreateMD")
alg.setRethrows(True)
alg.initialize()
alg.setPropertyValue("OutputWorkspace", "mdworkspace")
alg.setProperty("InputWorkspaces", ['input_workspace'])
alg.setProperty("Emode", "Direct")
alg.setProperty("Alatt", [1,1,1])
alg.setProperty("Angdeg", [90,90,90])
alg.setProperty("u", [0,0,1])
alg.setProperty("v", [1,0,0])
alg.setProperty("Psi", [0]) # Right size
alg.setProperty("Gl", [0, 0]) # Too many
alg.setProperty("Gs", [0]) # Right size
self.assertRaises(RuntimeError, alg.execute)
DeleteWorkspace(input_workspace)

def test_gs_right_size(self):

input_workspace = CreateSampleWorkspace(NumBanks=1, BinWidth=2000)
AddSampleLog(input_workspace, LogName='Ei', LogText='12.0', LogType='Number')

alg = AlgorithmManager.create("CreateMD")
alg.setRethrows(True)
alg.initialize()
alg.setPropertyValue("OutputWorkspace", "mdworkspace")
alg.setProperty("InputWorkspaces", ['input_workspace'])
alg.setProperty("Emode", "Direct")
alg.setProperty("Alatt", [1,1,1])
alg.setProperty("Angdeg", [90,90,90])
alg.setProperty("u", [0,0,1])
alg.setProperty("v", [1,0,0])
alg.setProperty("Psi", [0]) # Right size
alg.setProperty("Gl", [0]) # Right size
alg.setProperty("Gs", [0,0]) # Too large
self.assertRaises(RuntimeError, alg.execute)
DeleteWorkspace(input_workspace)


def test_execute_single_workspace(self):

input_workspace = CreateSampleWorkspace(NumBanks=1, BinWidth=2000)
AddSampleLog(input_workspace, LogName='Ei', LogText='12.0', LogType='Number')

alg = AlgorithmManager.create("CreateMD")
alg.setRethrows(True)
alg.initialize()
alg.setPropertyValue("OutputWorkspace", "mdworkspace")
alg.setProperty("InputWorkspaces", ['input_workspace'])
alg.setProperty("Alatt", [1,1,1])
alg.setProperty("Angdeg", [90,90,90])
alg.setProperty("u", [0,0,1])
alg.setProperty("v", [1,0,0])
alg.execute()
out_ws = AnalysisDataService.retrieve("mdworkspace")

self.assertTrue(isinstance(out_ws, IMDEventWorkspace), "Expected an MDEventWorkspace back")
DeleteWorkspace(input_workspace)

















if __name__ == '__main__':
unittest.main()
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
"MaxPositionChange_meters"),
"SetUB(v1)":("a", "b", "c", "alpha", "beta", "gamma", "u", "v"),
"ViewBOA(v1)":("CD-Distance"),
"PoldiCreatePeaksFromCell(v1)":("a", "b", "c", "alpha", "beta", "gamma")
"PoldiCreatePeaksFromCell(v1)":("a", "b", "c", "alpha", "beta", "gamma"),
"CreateMD(v1)" : ("u", "v")
}

# TODO this list should be empty
Expand Down
Loading

0 comments on commit fb04718

Please sign in to comment.