Skip to content
Snippets Groups Projects
Commit a747a717 authored by Marina Ganeva's avatar Marina Ganeva
Browse files

CompareSampleLogs refactored.

parent 699e1011
No related branches found
No related tags found
No related merge requests found
from mantid.api import PythonAlgorithm, AlgorithmFactory, WorkspaceGroup, MatrixWorkspace
from mantid.kernel import Direction, StringListValidator, StringArrayProperty, StringArrayLengthValidator,\
FloatBoundedValidator
from mantid.kernel import Direction, StringArrayLengthValidator, StringArrayProperty, FloatBoundedValidator
import mantid.simpleapi as api
......@@ -40,10 +39,9 @@ class CompareSampleLogs(PythonAlgorithm):
doc="Comma separated list of sample logs to compare.")
self.declareProperty("Tolerance", 1e-3, validator=FloatBoundedValidator(lower=1e-7, upper=1.0),
doc="Tolerance for comparison of double values.")
self.declareProperty("Result", "A string that will be empty if all the logs match, "
"otherwise will contain a comma separated list of not matching logs", Direction.Output)
actions = ['warning', 'error']
self.declareProperty("DoNotMatchAction", "warning", StringListValidator(actions),
doc="Action to perform if sample logs do not match.")
return
def validateInputs(self):
......@@ -77,59 +75,7 @@ class CompareSampleLogs(PythonAlgorithm):
return input_workspaces
def compare_properties(self, lhs_run, rhs_run, plist, tolerance=5e-3):
"""
checks whether properties match in the given runs, produces warnings
@param lhs_run Left-hand-side run
@param rhs_run Right-hand-side run
@param plist List of properties to compare
"""
lhs_title = ""
rhs_title = ""
if lhs_run.hasProperty('run_title') and rhs_run.hasProperty('run_title'):
lhs_title = lhs_run.getProperty('run_title').value
rhs_title = rhs_run.getProperty('run_title').value
# for TOFTOF run_titles can be identical
if lhs_title == rhs_title:
if lhs_run.hasProperty('run_number') and rhs_run.hasProperty('run_number'):
lhs_title = str(lhs_run.getProperty('run_number').value)
rhs_title = str(rhs_run.getProperty('run_number').value)
for property_name in plist:
if lhs_run.hasProperty(property_name) and rhs_run.hasProperty(property_name):
lhs_property = lhs_run.getProperty(property_name)
rhs_property = rhs_run.getProperty(property_name)
if lhs_property.type == rhs_property.type:
if lhs_property.type == 'string':
if lhs_property.value != rhs_property.value:
message = "Property " + property_name + " does not match! " + \
lhs_title + ": " + lhs_property.value + ", but " + \
rhs_title + ": " + rhs_property.value
print message
self.log().warning(message)
elif lhs_property.type == 'number':
if abs(lhs_property.value - rhs_property.value) > tolerance:
message = "Property " + property_name + " does not match! " + \
lhs_title + ": " + str(lhs_property.value) + ", but " + \
rhs_title + ": " + str(rhs_property.value)
print message
self.log().warning(message)
else:
message = "Property " + property_name + " does not match! " + \
lhs_title + ": " + str(lhs_property.value) + " has type " + \
str(lhs_property.type) + ", but " + rhs_title + ": " + \
str(rhs_property.value) + " has type " + str(rhs_property.type)
print message
self.log().warning(message)
else:
message = "Property " + property_name + " is not present in " +\
lhs_title + " or " + rhs_title + " - skipping comparison."
print message
self.log().warning(message)
return
def compare_mandatory(self, wslist, plist, tolerance=0.01):
def compare_properties(self, wslist, plist, tolerance):
"""
Compares properties which are required to be the same.
Produces error message and throws exception if difference is observed
......@@ -141,42 +87,49 @@ class CompareSampleLogs(PythonAlgorithm):
"""
# retrieve the workspaces, form dictionary {wsname: run}
runs = {}
does_not_match = []
for wsname in wslist:
wks = api.AnalysisDataService.retrieve(wsname)
runs[wsname] = wks.getRun()
for prop in plist:
properties = []
isnum = False
for wsname in wslist:
run = runs[wsname]
if not run.hasProperty(prop):
message = "Workspace " + wsname + " does not have sample log " + prop
self.log().error(message)
raise RuntimeError(message)
curprop = run.getProperty(prop)
if curprop.type == 'string':
properties.append(curprop.value)
elif curprop.type == 'number':
properties.append(int(curprop.value/tolerance))
self.log().warning(message)
else:
message = "Unknown type " + str(curprop.type) + " for the sample log " +\
prop + " in the workspace " + wsname
self.log().error(message)
raise RuntimeError(message)
# this should never happen, but lets check
curprop = run.getProperty(prop)
if curprop.type == 'string':
properties.append(curprop.value)
elif curprop.type == 'number':
properties.append(int(curprop.value/tolerance))
isnum = True
else:
message = "Comparison of " + str(curprop.type) + " properties is not yes supported. Property " +\
prop + " in the workspace " + wsname
self.log().warning(message)
# check whether number of properties and workspaces match
nprop = len(properties)
if nprop != len(wslist):
message = "Error. Number of properties " + str(nprop) + " for property " + prop +\
message = "Number of properties " + str(nprop) + " for property " + prop +\
" is not equal to number of workspaces " + str(len(wslist))
self.log().error(message)
raise RuntimeError(message)
pvalue = properties[0]
if properties.count(pvalue) != nprop:
message = "Sample log " + prop + " is not identical in the given list of workspaces. \n" +\
"Workspaces: " + ", ".join(wslist) + "\n Values: " + str(properties)
self.log().error(message)
raise RuntimeError(message)
self.log().warning(message)
does_not_match.append(prop)
else:
pvalue = properties[0]
if properties.count(pvalue) != nprop:
if isnum:
properties = [tolerance*value for value in properties]
message = "Sample log " + prop + " is not identical in the given list of workspaces. \n" +\
"Workspaces: " + ", ".join(wslist) + "\n Values: " + str(properties)
self.log().warning(message)
does_not_match.append(prop)
return does_not_match
def PyExec(self):
wslist = self._expand_groups()
......@@ -189,19 +142,14 @@ class CompareSampleLogs(PythonAlgorithm):
lognames = self.getProperty("SampleLogs").value
tolerance = self.getProperty("Tolerance").value
action = self.getProperty("DoNotMatchAction").value
result = ''
do_not_match = self.compare_properties(wslist, lognames, tolerance)
if action == 'error':
self.compare_mandatory(wslist, lognames, tolerance)
if action == 'warning':
ws1 = api.AnalysisDataService.retrieve(wslist[0])
run1 = ws1.getRun()
for wsname in wslist[1:]:
wks = api.AnalysisDataService.retrieve(wsname)
run = wks.getRun()
self.compare_properties(run1, run, lognames, tolerance)
# return list of not matching properties
if len(do_not_match) > 0:
result = ",".join(do_not_match)
self.setProperty("Result", result)
return
......
......@@ -145,7 +145,9 @@ class DNSDetEffCorrVana(PythonAlgorithm):
mlzutils.ws_exist(wslist_norm, self.log())
# check sample logs, produce warnings if different
api.CompareSampleLogs(wslist, self.properties_to_compare, 5e-3, 'warning')
result = api.CompareSampleLogs(wslist, self.properties_to_compare, 5e-3)
if len(result) > 0:
self.log().warning("Sample logs " + result + " do not match!")
# apply correction
outws = self._vana_correct()
......
......@@ -148,7 +148,9 @@ class DNSFlippingRatioCorr(PythonAlgorithm):
self._flipper_valid()
# algorithm must warn if some properties_to_compare are different
api.CompareSampleLogs(self.input_workspaces.values(), self.properties_to_compare, 5e-3, 'warning')
result = api.CompareSampleLogs(self.input_workspaces.values(), self.properties_to_compare, 5e-3)
if len(result) > 0:
self.log().warning("Sample logs " + result + " do not match!")
return True
def _fr_correction(self):
......
......@@ -84,7 +84,9 @@ class DNSMergeRuns(PythonAlgorithm):
self._same_wavelength()
# algorithm must warn if some properties_to_compare are different
api.CompareSampleLogs(self.workspace_names, self.properties_to_compare, 5e-3, 'warning')
result = api.CompareSampleLogs(self.workspace_names, self.properties_to_compare, 5e-3)
if len(result) > 0:
self.log().warning("Sample logs " + result + " do not match!")
return True
......
......@@ -71,7 +71,9 @@ class TOFTOFMergeRuns(PythonAlgorithm):
Checks whether given workspaces can be merged
"""
# mandatory properties must be identical
api.CompareSampleLogs(wsnames, self.mandatory_properties, 0.01, 'error')
result = api.CompareSampleLogs(wsnames, self.mandatory_properties, 0.01)
if len(result) > 0:
raise RuntimeError("Sample logs " + result + " do not match!")
# timing (x-axis binning) must match
# is it possible to use WorkspaceHelpers::matchingBins from python?
......@@ -89,7 +91,10 @@ class TOFTOFMergeRuns(PythonAlgorithm):
raise RuntimeError(message)
# warnig if optional properties are not identical must be given
api.CompareSampleLogs(wsnames, self.optional_properties, 0.01, 'warning')
api.CompareSampleLogs(wsnames, self.optional_properties, 0.01)
if len(result) > 0:
self.log().warning("Sample logs " + result + " do not match!")
return True
def PyExec(self):
......
......@@ -13,22 +13,27 @@ class CompareSampleLogsTest(unittest.TestCase):
lognames = 'run_title,deterota,wavelength,polarisation,flipper'
logvalues = 'ws1,-10.0,4.2,x,ON'
AddSampleLogMultiple(Workspace=ws1, LogNames=lognames, LogValues=logvalues, ParseType=True)
logvalues = 'ws2,-10.0,4.2,x,OFF'
logvalues = 'ws2,-12.0,4.2,x,OFF'
AddSampleLogMultiple(Workspace=ws2, LogNames=lognames, LogValues=logvalues, ParseType=True)
def test_workspaces(self):
def test_workspaces_different_logs(self):
wslist = [self.ws1, self.ws2]
lognames = 'deterota,wavelength,polarisation,flipper'
lognames = 'deterota,wavelength,polarisation,flipper,qqq'
alg_test = run_algorithm("CompareSampleLogs", InputWorkspaces=wslist, SampleLogs=lognames,
Tolerance=0.01, DoNotMatchAction='warning')
Tolerance=0.01)
self.assertTrue(alg_test.isExecuted())
# check for the returned value
result = alg_test.getProperty('Result').value
self.assertEqual('deterota,flipper,qqq', result)
def test_groups(self):
def test_groups_same_logs(self):
GroupWorkspaces([self.ws1, self.ws2], OutputWorkspace='group')
lognames = 'deterota,wavelength,polarisation,flipper'
lognames = 'wavelength,polarisation'
alg_test = run_algorithm("CompareSampleLogs", InputWorkspaces='group', SampleLogs=lognames,
Tolerance=0.01, DoNotMatchAction='warning')
Tolerance=0.01)
self.assertTrue(alg_test.isExecuted())
result = alg_test.getProperty('Result').value
self.assertEqual('', result)
def tearDown(self):
if AnalysisDataService.doesExist('ws1'):
......
......@@ -9,30 +9,32 @@
Description
-----------
Utility algorithm. Compares specified sample logs for a given list of workspaces or workspace groups. If sample logs match, no output will be produced. If sample logs do not match or do not exist, one two actions on user's choice will be performed:
Utility algorithm. Compares specified sample logs for a given list of workspaces or workspace groups. If sample logs match, no output will be produced. If sample logs do not match or do not exist, comma separated list of these sample logs will be returned. This list can be used as an input for :ref:`algm-CreateLogPropertyTable` algorithm to get a TableWorkspace with not identical properties.
- **warning**: algorithm will throw a warning, containing run titles or run numbers of not identical properties. All specified sample logs will be checked for all input workspaces. This action may be utilized to warn the user about difference in optional sample logs.
- **error**: algorithm will terminate with an error message after first not matching property will be found or if one of specified sample logs does not exist. This action is useful for mandatory properties, which must be identical in the given list of workspaces.
For the moment, algorithm does not support comparison of the time series logs.
Usage
-----
**Example 1: compare identical sample logs**
.. testcode:: ExCompareSampleLogs
# create workspaces with some sample logs
ws1 = CreateSampleWorkspace()
ws2 = CreateSampleWorkspace()
lognames = 'run_title,deterota,wavelength,polarisation,flipper'
logvalues = 'ws1,-10.0,4.2,x,ON'
lognames = 'omega,wavelength,polarisation,flipper'
logvalues = '10.0,4.2,x,ON'
AddSampleLogMultiple(Workspace=ws1, LogNames=lognames, LogValues=logvalues, ParseType=True)
logvalues = 'ws2,-10.0,4.2,x,OFF'
logvalues = '10.0,4.2,x,ON'
AddSampleLogMultiple(Workspace=ws2, LogNames=lognames, LogValues=logvalues, ParseType=True)
# compare sample logs
CompareSampleLogs('ws1,ws2', 'deterota,wavelength,polarisation,flipper' , 0.01, 'warning')
result = CompareSampleLogs('ws1,ws2', 'omega,wavelength,polarisation,flipper' , 0.01)
if result == '':
print "All sample logs match!"
.. testcleanup:: ExCompareSampleLogs
......@@ -43,7 +45,46 @@ Output:
.. testoutput:: ExCompareSampleLogs
Property flipper does not match! ws1: ON, but ws2: OFF
All sample logs match!
**Example 2: create a table of not identical sample logs**
.. testcode:: ExCompareSampleLogs2
# create workspaces with some sample logs
ws1 = CreateSampleWorkspace()
ws2 = CreateSampleWorkspace()
lognames = 'run_title,omega,wavelength,polarisation,flipper'
logvalues = 'ws1,10.0,4.2,x,ON'
AddSampleLogMultiple(Workspace=ws1, LogNames=lognames, LogValues=logvalues, ParseType=True)
logvalues = 'ws2,12.0,4.2,x,OFF'
AddSampleLogMultiple(Workspace=ws2, LogNames=lognames, LogValues=logvalues, ParseType=True)
# compare sample logs
result = CompareSampleLogs('ws1,ws2', lognames , 0.01)
print "Following sample logs do not match: ", result
# create a table
table = CreateLogPropertyTable('ws1,ws2', result, GroupPolicy='All')
print "Column names are: ", table.getColumnNames()
print "The omega values are:", table.column(1)
print "The flipper values are:", table.column(2)
.. testcleanup:: ExCompareSampleLogs2
DeleteWorkspace('ws1')
DeleteWorkspace('ws2')
Output:
.. testoutput:: ExCompareSampleLogs2
Following sample logs do not match: run_title,omega,flipper
Column names are: ['run_title', 'omega', 'flipper']
The omega values are: ['10', '12']
The flipper values are: ['ON', 'OFF']
.. categories::
......
......@@ -98,7 +98,6 @@ Output:
.. testoutput:: ExTOFTOFMergeRuns2ws
Property temperature does not match! TOFTOFTestdata: 294.14, but TOFTOFTestdata2: 296.16
Temperature of experiment for 1st workspace (in K): 294.14
Temperature of experiment for 2nd workspace (in K): 296.16
Temperature of experiment for merged workspaces = average over workspaces (in K): 295.15
......@@ -141,7 +140,6 @@ Output:
.. testoutput:: ExTOFTOFMergeRunsGroup
Property temperature does not match! TOFTOFTestdata: 294.14, but TOFTOFTestdata2: 296.16
Monitor counts for 1st workspace: 136935
Monitor counts for 2nd workspace: 145145
Monitor counts for merged workspaces = sum over all workspaces: 282080
......
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