Skip to content

Commit

Permalink
Refs #11116 - Moved methods into a MDReductionWrapper class.
Browse files Browse the repository at this point in the history
  • Loading branch information
ianbush committed Feb 18, 2015
1 parent dda4dea commit fdb9d5b
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 115 deletions.
95 changes: 95 additions & 0 deletions 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")




146 changes: 31 additions & 115 deletions Code/Mantid/scripts/test/MerlinAccumulateMDReduction.py
Expand Up @@ -4,19 +4,19 @@
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
except:
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 """
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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
Expand All @@ -211,27 +143,27 @@ 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)

# Merlin data starts in the format: 'MERXXXXX.raw', where XXXXXX is the run number
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)
Expand All @@ -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

Expand Down

0 comments on commit fdb9d5b

Please sign in to comment.