Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix LOQ Batch reduction issues #18888

Merged
merged 7 commits into from Feb 23, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion docs/source/release/v3.10.0/sans.rst
Expand Up @@ -8,7 +8,9 @@ SANS Changes
Bug Fixes
---------
- Fixed wrong first spectrum number for LARMOR. The first non-monitor spectrum number is 11, but it had been set to 10.

- Fixed LOQ Batch mode bug where geometry information was not saved out when using SaveCanSAS1D.
- Fixed LOQ Batch mode bug where custom user file without a .txt ending was not being picked up.
- Fixed Batch mode bug where the output name suffix was hardcoded to SANS2D. It now takes the individual instruments into account.
|

`Full list of changes on github <http://github.com/mantidproject/mantid/pulls?q=is%3Apr+milestone%3A%22Release+3.10%22+is%3Amerged+label%3A%22Component%3A+SANS%22>`__
112 changes: 91 additions & 21 deletions scripts/SANS/SANSBatchMode.py
Expand Up @@ -140,6 +140,44 @@ def get_transmission_properties(workspace):
return transmission_properties


def get_geometry_properties(reducer):
"""
This extracts geometry properties from the ReductionSingleton. They are saved in the CanSAS1D format.

@param reducer: a handle to the redcution singleton
@return: a dict with geometry properties
"""
def _add_property(key, element, props):
if element is None:
raise RuntimeError("Could not extract value for {0}.".format(key))
props.update({key: element})

geometry_properties = {}
geometry = reducer.get_sample().geometry

# Get the shape
shape = geometry.shape
if shape == 'cylinder-axis-up':
shape_to_save = "Cylinder"
elif shape == 'cuboid':
shape_to_save = "Flat plate"
elif shape == 'cylinder-axis-along':
shape_to_save = 'Disc'
else:
raise RuntimeError("Unknown shape {0}. Cannot extract property".format(shape))
geometry_properties.update({"Geometry": shape_to_save})

# Get the Height
_add_property("SampleHeight", geometry.height, geometry_properties)

# Get the Width
_add_property("SampleWidth", geometry.width, geometry_properties)

# Get the thickness
_add_property("SampleThickness", geometry.thickness, geometry_properties)
return geometry_properties


def BatchReduce(filename, format, plotresults=False, saveAlgs={'SaveRKH':'txt'},verbose=False,
centreit=False, reducer=None, combineDet=None, save_as_zero_error_free=False):
"""
Expand Down Expand Up @@ -197,14 +235,21 @@ def BatchReduce(filename, format, plotresults=False, saveAlgs={'SaveRKH':'txt'},
original_user_file=original_user_file,
original_settings = settings,
original_prop_man_settings = prop_man_settings)
except (RunTimeError, ValueError) as e:
# When we set a new user file, that means that the combineDet feature could be invalid,
# ie if the detector under investigation changed in the user file. We need to change this
# here too. But only if it is not None.
if combineDet is not None:
new_combineDet = ReductionSingleton().instrument.get_detector_selection()
combineDet = su.get_correct_combinDet_setting(ins_name, new_combineDet)
except (RuntimeError, ValueError) as e:
sanslog.warning("Error in Batchmode user files: Could not reset the specified user file %s. More info: %s" %(
str(run['user_file']),str(e)))
str(run['user_file']), str(e)))

local_settings = copy.deepcopy(ReductionSingleton().reference())
local_prop_man_settings = ReductionSingleton().settings.clone("TEMP_SETTINGS")

raw_workspaces = []
geometry_properties = {}
try:
# Load in the sample runs specified in the csv file
raw_workspaces.append(read_run(run, 'sample_sans', format))
Expand All @@ -222,6 +267,12 @@ def BatchReduce(filename, format, plotresults=False, saveAlgs={'SaveRKH':'txt'},
if verbose == 1:
FindBeamCentre(50.,170.,12)

try:
geometry_properties = get_geometry_properties(ReductionSingleton())
except RuntimeError as e:
message = "Could not extract geometry properties from the reducer: {0}".format(str(e))
sanslog.warning(message)

# WavRangeReduction runs the reduction for the specified
# wavelength range where the final argument can either be
# DefaultTrans or CalcTrans:
Expand Down Expand Up @@ -254,34 +305,42 @@ def BatchReduce(filename, format, plotresults=False, saveAlgs={'SaveRKH':'txt'},
final_name = sanitize_name(final_name)

#convert the names from the default one, to the agreement
# This caused a renaming with the following logic
# | combinDet | Name HAB | Name LAB | Name Merged |
# | rear | +_rear | - | - |
# | front | - | +_front | - |
# | both | +_rear | +_front | - |
# | merged | +_rear | +_front | +_merged |
# This is not great since it uses SANS2D terminology for all instruments

names = [final_name]
if combineDet == 'rear':
names = [final_name+'_rear']
RenameWorkspace(InputWorkspace=reduced,OutputWorkspace= final_name+'_rear')
new_name = su.rename_workspace_correctly(ins_name, su.ReducedType.LAB, final_name, reduced)
names = [new_name]
elif combineDet == 'front':
names = [final_name+'_front']
RenameWorkspace(InputWorkspace=reduced,OutputWorkspace= final_name+'_front')
new_name = su.rename_workspace_correctly(ins_name, su.ReducedType.HAB, final_name, reduced)
names = [new_name]
elif combineDet == 'both':
names = [final_name+'_front', final_name+'_rear']
if ins_name == 'SANS2D':
rear_reduced = reduced.replace('front','rear')
rear_reduced = reduced.replace('front', 'rear')
else: #if ins_name == 'lOQ':
rear_reduced = reduced.replace('HAB','main')
RenameWorkspace(InputWorkspace=reduced,OutputWorkspace=final_name+'_front')
RenameWorkspace(InputWorkspace=rear_reduced,OutputWorkspace=final_name+'_rear')
rear_reduced = reduced.replace('HAB', 'main')
new_name_HAB = su.rename_workspace_correctly(ins_name, su.ReducedType.HAB, final_name, reduced)
new_name_LAB = su.rename_workspace_correctly(ins_name, su.ReducedType.LAB, final_name, rear_reduced)
names = [new_name_HAB, new_name_LAB]
elif combineDet == 'merged':
names = [final_name + '_merged', final_name + '_rear', final_name+'_front']
if ins_name == 'SANS2D':
rear_reduced = reduced.replace('merged','rear')
front_reduced = reduced.replace('merged','front')
rear_reduced = reduced.replace('merged', 'rear')
front_reduced = reduced.replace('merged', 'front')
else:
rear_reduced = reduced.replace('_merged','')
front_reduced = rear_reduced.replace('main','HAB')
RenameWorkspace(InputWorkspace=reduced,OutputWorkspace= final_name + '_merged')
RenameWorkspace(InputWorkspace=rear_reduced,OutputWorkspace= final_name + '_rear')
RenameWorkspace(InputWorkspace=front_reduced,OutputWorkspace= final_name+'_front')
rear_reduced = reduced.replace('_merged', '')
front_reduced = rear_reduced.replace('main', 'HAB')
new_name_Merged = su.rename_workspace_correctly(ins_name, su.ReducedType.Merged, final_name, reduced)
new_name_LAB = su.rename_workspace_correctly(ins_name, su.ReducedType.LAB, final_name, rear_reduced)
new_name_HAB = su.rename_workspace_correctly(ins_name, su.ReducedType.HAB, final_name, front_reduced)
names = [new_name_Merged, new_name_LAB, new_name_HAB]
else:
RenameWorkspace(InputWorkspace=reduced,OutputWorkspace=final_name)
RenameWorkspace(InputWorkspace=reduced, OutputWorkspace=final_name)

file = run['output_as']
#saving if optional and doesn't happen if the result workspace is left blank. Is this feature used?
Expand Down Expand Up @@ -310,6 +369,11 @@ def BatchReduce(filename, format, plotresults=False, saveAlgs={'SaveRKH':'txt'},
# sample logs.
_ws = mtd[workspace_name]
transmission_properties = get_transmission_properties(_ws)

# Add the geometry properties if they exist
if geometry_properties:
transmission_properties.update(geometry_properties)

# Call the SaveCanSAS1D with the Transmission and TransmissionCan if they are
# available
SaveCanSAS1D(save_names_dict[workspace_name], workspace_name+ext, DetectorNames=detnames,
Expand Down Expand Up @@ -496,7 +560,13 @@ def setUserFileInBatchMode(new_user_file, current_user_file, original_user_file,

# Try to find the user file in the default paths
if not os.path.isfile(new_user_file):
user_file = FileFinder.getFullPath(new_user_file)
# Find the user file in the Mantid path. we make sure that the user file has a txt extension.
user_file_names_with_extension = su.get_user_file_name_options_with_txt_extension(new_user_file)
for user_file_name_with_extension in user_file_names_with_extension:
user_file = FileFinder.getFullPath(user_file_name_with_extension)
if user_file:
break

if not os.path.isfile(user_file):
user_file_to_set = original_user_file
else:
Expand Down
106 changes: 106 additions & 0 deletions scripts/SANS/SANSUtility.py
Expand Up @@ -1962,6 +1962,112 @@ def get_unfitted_transmission_workspace_name(workspace_name):
return unfitted_workspace_name


def get_user_file_name_options_with_txt_extension(user_file_name):
"""
A user file is a .txt file. The user file can be specified without the .txt ending. Which will prevent the
FileFinder from picking it up.

@param user_file_name: the name of the user file
@return: either the original user file name or a list of user file names with .txt and .TXT extensions
"""
capitalized_user_file = user_file_name.upper()
if capitalized_user_file.endswith('.TXT'):
user_file_with_extension = [user_file_name]
else:
user_file_with_extension = [user_file_name + ".txt", user_file_name + ".TXT"]
return user_file_with_extension


def get_correct_combinDet_setting(instrument_name, detector_selection):
"""
We want to get the correct combinDet variable for batch reductions from a new detector selection.

@param instrument_name: the name of the intrument
@param detector_selection: a detector selection comes directly from the reducer
@return: a combinedet option
"""
if detector_selection is None:
return None

instrument_name = instrument_name.upper()
# If we are dealing with LARMOR, then the correct combineDet selection is None
if instrument_name == "LARMOR":
return None

detector_selection = detector_selection.upper()
# If we are dealing with LOQ, then the correct combineDet selection is
if instrument_name == "LOQ":
if detector_selection == "MAIN":
new_combine_detector_selection = 'rear'
elif detector_selection == "HAB":
new_combine_detector_selection = 'front'
elif detector_selection == "MERGED":
new_combine_detector_selection = 'merged'
elif detector_selection == "BOTH":
new_combine_detector_selection = 'both'
else:
raise RuntimeError("SANSBatchReduce: Unknown detector {0} for conversion "
"to combineDet.".format(detector_selection))
return new_combine_detector_selection

# If we are dealing with SANS2D, then the correct combineDet selection is
if instrument_name == "SANS2D":
if detector_selection == "REAR":
new_combine_detector_selection = 'rear'
elif detector_selection == "FRONT":
new_combine_detector_selection = 'front'
elif detector_selection == "MERGED":
new_combine_detector_selection = 'merged'
elif detector_selection == "BOTH":
new_combine_detector_selection = 'both'
else:
raise RuntimeError("SANSBatchReduce: Unknown detector {0} for conversion "
"to combineDet.".format(detector_selection))
return new_combine_detector_selection
raise RuntimeError("SANSBatchReduce: Unknown instrument {0}.".format(instrument_name))


class ReducedType(object):
class LAB(object):
pass

class HAB(object):
pass

class Merged(object):
pass


def rename_workspace_correctly(instrument_name, reduced_type, final_name, workspace):
def get_suffix(inst_name, red_type):
if inst_name == "SANS2D":
if red_type is ReducedType.LAB:
suffix = "_rear"
elif red_type is ReducedType.HAB:
suffix = "_front"
elif red_type is ReducedType.Merged:
suffix = "_merged"
else:
raise RuntimeError("Unknown reduction type {0}.".format(red_type))
return suffix
elif inst_name == "LOQ":
if red_type is ReducedType.LAB:
suffix = "_main"
elif red_type is ReducedType.HAB:
suffix = "_hab"
elif red_type is ReducedType.Merged:
suffix = "_merged"
else:
raise RuntimeError("Unknown reduction type {0}.".format(red_type))
return suffix
else:
return ""
final_suffix = get_suffix(instrument_name, reduced_type)
complete_name = final_name + final_suffix
RenameWorkspace(InputWorkspace=workspace, OutputWorkspace=complete_name)
return complete_name


###############################################################################
######################### Start of Deprecated Code ############################
###############################################################################
Expand Down
17 changes: 17 additions & 0 deletions scripts/test/SANSBatchModeTest.py
Expand Up @@ -142,5 +142,22 @@ def test_reducer_is_not_reset_if_file_to_set_is_original_and_current(self):
# Clean up
self._delete_minimal_user_files(user_files)


class TestGeometrySettings(unittest.TestCase):
def test_that_can_get_geometry_properties(self):
LOQ()
reducer = ReductionSingleton()
geometry_settings = bm.get_geometry_properties(reducer)
self.assertTrue("Geometry" in geometry_settings)
self.assertTrue("SampleHeight" in geometry_settings)
self.assertTrue("SampleWidth" in geometry_settings)
self.assertTrue("SampleThickness" in geometry_settings)

self.assertTrue(geometry_settings["Geometry"] == "Disc")
self.assertTrue(geometry_settings["SampleHeight"] == 1.)
self.assertTrue(geometry_settings["SampleWidth"] == 1.)
self.assertTrue(geometry_settings["SampleThickness"] == 1.)


if __name__ == "__main__":
unittest.main()