From fdb9d5bdec354e532bbbc958aa419326760fc8ec Mon Sep 17 00:00:00 2001 From: Ian Bush Date: Wed, 18 Feb 2015 17:21:40 +0000 Subject: [PATCH] Refs #11116 - Moved methods into a MDReductionWrapper class. --- .../Inelastic/Direct/MDReductionWrapper.py | 95 ++++++++++++ .../test/MerlinAccumulateMDReduction.py | 146 ++++-------------- 2 files changed, 126 insertions(+), 115 deletions(-) create mode 100644 Code/Mantid/scripts/Inelastic/Direct/MDReductionWrapper.py diff --git a/Code/Mantid/scripts/Inelastic/Direct/MDReductionWrapper.py b/Code/Mantid/scripts/Inelastic/Direct/MDReductionWrapper.py new file mode 100644 index 000000000000..d1a20736cb94 --- /dev/null +++ b/Code/Mantid/scripts/Inelastic/Direct/MDReductionWrapper.py @@ -0,0 +1,95 @@ +from ReductionWrapper import * + +class MDReductionWrapper(ReductionWrapper): + """ A similar class to ReductionWrapper, but for reduction followed by accumulation + to a merged MD file + """ + def __init__(self, instrumentName, web_var = None): + super(MDReductionWrapper, self).__init__(instrumentName, web_var = None) + + # Create a file with the filename and path, with a '.lock' extension, to indicate file in use, + # unless this already exists, in which case do nothing and return False + def lock_obtained(self, fname): + if not os.path.isfile(fname + '.lock'): + lock_file = open(fname + '.lock', 'w') + lock_file.close() + return True + else: + return False + + # Remove lock file, exception will be thrown if this does not exist + def release_lock(self, fname): + os.remove(fname + '.lock') + + # The table below shows the valid combinations for controlling the run numbers. + # N = number of accumulated MD files to produce (e.g. Run Range Starts is a list of N integers). + # _______________ + # ____________________________|_1_|_2_|_3_|_4_| + # | 'Run Range Starts' | N | N | N | 1 | + # | 'Run Range Ends' | N | - | - | - | + # | 'Number of Runs to Merge' | - | N | 1 | 1 | + # --------------------------------------------- + # + # If file_run_number is between range_starts and range_ends return the range and MD file number (0...N-1), + # as a tuple or return -1, -1, -1 if the run number is not in a range asked for + def get_file_number(self, file_run_number, range_starts, range_ends): + for i in range(0, len(range_starts)): + if ((file_run_number >= range_starts[i]) and (file_run_number <= range_ends[i])): + return i, range_starts[i], range_ends[i] + return -1, -1, -1 + + # If number_of_runs_to_merge is given return the run range and MD file number (0...N-1) as a tuple, + # or return -1, -1, -1 if the range is not as asked for + def get_file_number_alternative(self, file_run_number, range_starts, number_of_runs_to_merge): + if (len(range_starts) == 1 and len(number_of_runs_to_merge) == 1): + if (file_run_number < range_starts[0]): + return -1, -1, -1 + file_number = file_run_number//number_of_runs_to_merge[0] - range_starts[0]//number_of_runs_to_merge[0] + return file_number + 1, file_number * number_of_runs_to_merge[0], (file_number + 1) * number_of_runs_to_merge[0] + elif (len(range_starts) > 1 and len(number_of_runs_to_merge) == 1): + for i in range(0, len(range_starts)): + if (file_run_number >= range_starts[i] and file_run_number < range_starts[i] + number_of_runs_to_merge[0]): + return i, range_starts[i], range_starts[i] + number_of_runs_to_merge[0] - 1 + return -1, -1, -1 + elif (len(range_starts) == len(number_of_runs_to_merge)): + for i in range(0, len(range_starts)): + if (file_run_number >= range_starts[i] and file_run_number < range_starts[i] + number_of_runs_to_merge[i]): + return i, range_starts[i], range_starts[i] + number_of_runs_to_merge[i] - 1 + return -1, -1, -1 + + raise Exception("Size of range_starts, ", len(range_starts), " and number_of_runs_to_merge, ", + len(number_of_runs_to_merge), " are incompatible") + + # If MD:Filenames is set return the appropriate filename, else return a filename such as 123_456_SQW.nxs + def get_file_name(self, file_number, start, end): + file_names = self._wvs.advanced_vars.get('MD:Filenames') + if (file_names is None or len(file_names) == 0): + return str(start) + '_' + str(end) + '_SQW.nxs' + else: + return file_names[file_number] + + # For psi allowed combinations are shown below + # N = number of accumulated MD files to produce (e.g. Psi Starts is a list of N integers). + # ___________ + # ___________________|_1_|_2_|_3_| + # | 'Psi Starts' | N | N | 1 | + # | 'Psi Increments' | 1 | N | 1 | + # -------------------------------- + # + def get_psi(self, file_number, file_run_number, start, end): + psi_starts = self._wvs.advanced_vars.get('MD:Psi Starts') + psi_increments = self._wvs.advanced_vars.get('MD:Psi Increments') + + if (len(psi_starts) == 1 and len(psi_increments) == 1): + return psi_starts[0] + (file_run_number - start) * psi_increments[0] + elif (len(psi_starts) == len(psi_increments)): + return psi_starts[file_number] + (file_run_number - start) * psi_increments[file_number] + elif (len(psi_starts) > 1 and len(psi_increments) == 1): + return psi_starts[file_number] + (file_run_number - start) * psi_increments[0] + else: + raise Exception("Size of psi_starts, ", len(psi_starts), " and psi_increments, ", + len(psi_increments), " are incompatible") + + + + diff --git a/Code/Mantid/scripts/test/MerlinAccumulateMDReduction.py b/Code/Mantid/scripts/test/MerlinAccumulateMDReduction.py index 88aeaa26231e..a68bde931b80 100644 --- a/Code/Mantid/scripts/test/MerlinAccumulateMDReduction.py +++ b/Code/Mantid/scripts/test/MerlinAccumulateMDReduction.py @@ -4,11 +4,11 @@ import os ### Only required for running locally ### -#import sys -#sys.path.insert(0,'/opt/Mantid/scripts/Inelastic') +import sys +sys.path.insert(0,'/home/whb43145/Mantid/mantid-develop/Code/Mantid/scripts/Inelastic') #sys.path.insert(0,'/home/whb43145/autoreduction_test_production') -from ReductionWrapper import * +from Direct.MDReductionWrapper import * try: import reduce_vars as web_var @@ -16,7 +16,7 @@ web_var = None -class ReduceMERLIN(ReductionWrapper): +class ReduceMERLIN(MDReductionWrapper): @MainProperties def def_main_properties(self, file_run_number=None): """ Define main properties used in reduction """ @@ -74,94 +74,26 @@ def main(self, input_file = None, output_directory = None, output_file = None): def __init__(self, web_var = None): """ sets properties defaults for the instrument with Name""" - ReductionWrapper.__init__(self,'MER',web_var) - -# Create a file with the filename and path, with a '.lock' extension, to indicate file in use, -# unless this already exists, in which case do nothing and return False -def lock_obtained(fname): - if not os.path.isfile(fname + '.lock'): - lock_file = open(fname + '.lock', 'w') - lock_file.close() - return True - else: - return False - -# Remove lock file, exception will be thrown if this does not exist -def release_lock(fname): - os.remove(fname + '.lock') - - -# The table below shows the valid combinations for controlling the run numbers. -# N = number of accumulated MD files to produce (e.g. Run Range Starts is a list of N integers). -# _______________ -# ____________________________|_1_|_2_|_3_|_4_| -# | 'Run Range Starts' | N | N | N | 1 | -# | 'Run Range Ends' | N | - | - | - | -# | 'Number of Runs to Merge' | - | N | 1 | 1 | -# --------------------------------------------- -# -# If file_run_number is between range_starts and range_ends return the range and MD file number (0...N-1), -# as a tuple or return -1, -1, -1 if the run number is not in a range asked for -def get_file_number(file_run_number, range_starts, range_ends): - for i in range(0, len(range_starts)): - if ((file_run_number >= range_starts[i]) and (file_run_number <= range_ends[i])): - return i, range_starts[i], range_ends[i] - return -1, -1, -1 - -# If number_of_runs_to_merge is given return the run range and MD file number (0...N-1) as a tuple, -# or return -1, -1, -1 if the range is not as asked for -def get_file_number_alternative(file_run_number, range_starts, number_of_runs_to_merge): - if (len(range_starts) == 1 and len(number_of_runs_to_merge) == 1): - if (file_run_number < range_starts[0]): - return -1, -1, -1 - file_number = file_run_number//number_of_runs_to_merge[0] - range_starts[0]//number_of_runs_to_merge[0] - return file_number + 1, file_number * number_of_runs_to_merge[0], (file_number + 1) * number_of_runs_to_merge[0] - elif (len(range_starts) > 1 and len(number_of_runs_to_merge) == 1): - for i in range(0, len(range_starts)): - if (file_run_number >= range_starts[i] and file_run_number < range_starts[i] + number_of_runs_to_merge[0]): - return i, range_starts[i], range_starts[i] + number_of_runs_to_merge[0] - 1 - return -1, -1, -1 - elif (len(range_starts) == len(number_of_runs_to_merge)): - for i in range(0, len(range_starts)): - if (file_run_number >= range_starts[i] and file_run_number < range_starts[i] + number_of_runs_to_merge[i]): - return i, range_starts[i], range_starts[i] + number_of_runs_to_merge[i] - 1 - return -1, -1, -1 - - raise Exception("Size of range_starts, ", len(range_starts), " and number_of_runs_to_merge, ", - len(number_of_runs_to_merge), " are incompatible") - -# If MD:Filenames is set return the appropriate filename, else return a filename such as 123_456_SQW.nxs -def get_file_name(file_number, start, end): - file_names = web_var.advanced_vars.get('MD:Filenames') - if (file_names is None or len(file_names) == 0): - return str(start) + '_' + str(end) + '_SQW.nxs' - else: - return file_names[file_number] - -# For psi allowed combinations are shown below -# N = number of accumulated MD files to produce (e.g. Psi Starts is a list of N integers). -# ___________ -# ___________________|_1_|_2_|_3_| -# | 'Psi Starts' | N | N | 1 | -# | 'Psi Increments' | 1 | N | 1 | -# -------------------------------- -# -def get_psi(file_number, file_run_number, start, end): - psi_starts = web_var.advanced_vars.get('MD:Psi Starts') - psi_increments = web_var.advanced_vars.get('MD:Psi Increments') - - if (len(psi_starts) == 1 and len(psi_increments) == 1): - return psi_starts[0] + (file_run_number - start) * psi_increments[0] - elif (len(psi_starts) == len(psi_increments)): - return psi_starts[file_number] + (file_run_number - start) * psi_increments[file_number] - elif (len(psi_starts) > 1 and len(psi_increments) == 1): - return psi_starts[file_number] + (file_run_number - start) * psi_increments[0] + super(ReduceMERLIN, self).__init__('MER',web_var) + +def convert_and_merge(rd, input_file, input_dir, file_run_number): + + # Process ranges to merge into something more useful + range_starts = web_var.advanced_vars.get('MD:Run Range Starts') + range_ends = web_var.advanced_vars.get('MD:Run Range Ends') + number_of_runs_to_merge = web_var.advanced_vars.get('MD:Number of Runs to Merge') + + if (len(range_ends) == 0): + file_number, start, end = rd.get_file_number_alternative(file_run_number, range_starts, number_of_runs_to_merge) else: - raise Exception("Size of psi_starts, ", len(psi_starts), " and psi_increments, ", - len(psi_increments), " are incompatible") + file_number, start, end = rd.get_file_number(file_run_number, range_starts, range_ends) + + merged_filename = input_dir + '/../' + rd.get_file_name(file_number, start, end) + psi = rd.get_psi(file_number, file_run_number, start, end) + + ub_matrix = web_var.advanced_vars.get('MD:UB Matrix') -def convert_and_merge(input_file, output_file, psi, ub_matrix, file_run_number): # Convert to an MD workspace and merge into the big file loaded_ws = Load(Filename = input_file) @@ -195,13 +127,13 @@ def convert_and_merge(input_file, output_file, psi, ub_matrix, file_run_number): # Get the lock on the output file. Can obtain this whether or not the file exists yet. # If lock is not obtained sleep for 10s. TODO: should this timeout? # In case of problems will need to delete the lock file manually. - while(not lock_obtained(output_file)): - print "Waiting for lock on ", output_file + while(not rd.lock_obtained(merged_filename)): + print "Waiting for lock on ", merged_filename time.sleep(10) # Load the output file if it exists, create it otherwise - if (os.path.exists(output_file)): - merged_ws = LoadMD(Filename = output_file, FileBackEnd = True) + if (os.path.exists(merged_filename)): + merged_ws = LoadMD(Filename = merged_filename, FileBackEnd = True) pars['OverwriteExisting'] = False else: pars['OverwriteExisting'] = True @@ -211,19 +143,19 @@ def convert_and_merge(input_file, output_file, psi, ub_matrix, file_run_number): # Save the file print output_file if pars.get('OverwriteExisting'): - SaveMD(merged_ws, Filename = output_file, MakeFileBacked = True) + SaveMD(merged_ws, Filename = merged_filename, MakeFileBacked = True) else: - SaveMD(merged_ws, Filename = output_file, UpdateFileBackEnd = True) + SaveMD(merged_ws, Filename = merged_filename, UpdateFileBackEnd = True) # Release the file lock now. - release_lock(output_file) + rd.release_lock(merged_filename) # This is called by the autoreduction script itself def reduce(input_file, output_dir): # Define any extra directories needed for maps files etc. (not needed for running through autoreduction server) ### Only required for running locally ### - #maps_dir = '/home/whb43145/autoreduction_test_russell/maps' + maps_dir = '/home/whb43145/Mantid/RAW_to_SPE/MERLIN/masks' input_path, input_filename = os.path.split(input_file) @@ -231,7 +163,7 @@ def reduce(input_file, output_dir): file_run_number = int(input_filename.split('MER')[1].split('.')[0]) ### Only required for running locally ### - #config.setDataSearchDirs('{0};{1};{2}'.format(input_path,output_dir,maps_dir)) + config.setDataSearchDirs('{0};{1};{2}'.format(input_path,output_dir,maps_dir)) config['defaultsave.directory'] = output_dir.encode('ascii','replace') # folder to save resulting spe/nxspe files rd = ReduceMERLIN(web_var) @@ -249,23 +181,7 @@ def reduce(input_file, output_dir): outWS = rd.reduce(input_file, output_dir) if (web_var.advanced_vars.get('MD:Accumulate to MD file')): - # Process ranges to merge into something more useful - range_starts = web_var.advanced_vars.get('MD:Run Range Starts') - range_ends = web_var.advanced_vars.get('MD:Run Range Ends') - number_of_runs_to_merge = web_var.advanced_vars.get('MD:Number of Runs to Merge') - - if (len(range_ends) == 0): - file_number, start, end = get_file_number_alternative(file_run_number, range_starts, number_of_runs_to_merge) - else: - file_number, start, end = get_file_number(file_run_number, range_starts, range_ends) - - merged_filename = output_dir + '/../' + get_file_name(file_number, start, end) - - psi = get_psi(file_number, file_run_number, start, end) - - ub_matrix = web_var.advanced_vars.get('MD:UB Matrix') - - convert_and_merge(output_filename, merged_filename, psi, ub_matrix, file_run_number) + convert_and_merge(rd, output_filename, output_dir, file_run_number) return None # Can make this an additional save directory