From 7d59f2982c3e839b3fd46766f1f63e73ca272d1c Mon Sep 17 00:00:00 2001 From: David Fairbrother <DavidFair@users.noreply.github.com> Date: Tue, 15 Nov 2016 16:52:09 +0000 Subject: [PATCH] Re #17949 Use Mantid to Load + move from dict to class for cal --- .../analysis/ISIS_PowderOldApiCalTest.py | 3 + .../tests/analysis/ISIS_PowderPolarisTest.py | 11 ++- scripts/Diffraction/isis_powder/RunDetails.py | 24 ++++++ .../Diffraction/isis_powder/abstract_inst.py | 30 ++------ scripts/Diffraction/isis_powder/calibrate.py | 29 ++++--- scripts/Diffraction/isis_powder/common.py | 28 +++---- scripts/Diffraction/isis_powder/focus.py | 16 ++-- .../isis_powder/mock_instrument.py | 4 +- scripts/Diffraction/isis_powder/pearl.py | 58 ++++++++++---- .../pearl_routines/fmode_output.py | 2 +- scripts/Diffraction/isis_powder/polaris.py | 76 +++++++++++-------- .../polaris_routines/polaris_calib_parser.py | 40 ++++++++-- .../polaris_routines/polaris_calibration.yaml | 22 +++++- scripts/PearlPowderISIS/pearl_routines.py | 4 +- scripts/test/ISIS_Powder_PearlTest.py | 4 +- 15 files changed, 220 insertions(+), 131 deletions(-) create mode 100644 scripts/Diffraction/isis_powder/RunDetails.py diff --git a/Testing/SystemTests/tests/analysis/ISIS_PowderOldApiCalTest.py b/Testing/SystemTests/tests/analysis/ISIS_PowderOldApiCalTest.py index 37173396f3f..e06d5211b58 100644 --- a/Testing/SystemTests/tests/analysis/ISIS_PowderOldApiCalTest.py +++ b/Testing/SystemTests/tests/analysis/ISIS_PowderOldApiCalTest.py @@ -14,6 +14,8 @@ DIRS = config['datasearch.directories'].split(';') class PowderDiffOldApiCalibrateTest(stresstesting.MantidStressTest): + _existing_config = None + def requiredFiles(self): filenames = [] @@ -49,6 +51,7 @@ class PowderDiffOldApiCalibrateTest(stresstesting.MantidStressTest): def runTest(self): self._success = False + self._existing_config = config['datasearch.directories'] pearl_routines.PEARL_startup("Calib", "15_3") diff --git a/Testing/SystemTests/tests/analysis/ISIS_PowderPolarisTest.py b/Testing/SystemTests/tests/analysis/ISIS_PowderPolarisTest.py index e1b8229a3de..f53d98b793d 100644 --- a/Testing/SystemTests/tests/analysis/ISIS_PowderPolarisTest.py +++ b/Testing/SystemTests/tests/analysis/ISIS_PowderPolarisTest.py @@ -14,6 +14,7 @@ DIRS = config['datasearch.directories'].split(';') class isis_powder_PolarisVanadiumCalTest(stresstesting.MantidStressTest): calibration_results = None + existing_config = config['datasearch.directories'] def requiredFiles(self): return _gen_required_files() @@ -26,12 +27,14 @@ class isis_powder_PolarisVanadiumCalTest(stresstesting.MantidStressTest): def cleanup(self): # TODO clean up reference files properly + config['datasearch.directories'] = self.existing_config _clean_up() class isis_powder_PolarisFocusTest(stresstesting.MantidStressTest): focus_results = None + existing_config = config['datasearch.directories'] def requiredFiles(self): return _gen_required_files() @@ -45,7 +48,7 @@ class isis_powder_PolarisFocusTest(stresstesting.MantidStressTest): return _calibration_validation(self, self.focus_results) def cleanup(self): - pass + config['datasearch.directories'] = self.existing_config # TODO @@ -115,11 +118,11 @@ def setup_polaris_instrument(): user_name = "Test" calibration_dir = _get_calibration_dir() - raw_data_dir = os.path.join(DIRS[0], "POLARIS") + path_to_add = os.path.join(DIRS[0], "POLARIS") + config['datasearch.directories'] += ";" + path_to_add output_dir = _get_output_dir() - polaris_obj = polaris.Polaris(user_name=user_name, calibration_dir=calibration_dir, raw_data_dir=raw_data_dir, - output_dir=output_dir) + polaris_obj = polaris.Polaris(user_name=user_name, calibration_dir=calibration_dir, output_dir=output_dir) return polaris_obj diff --git a/scripts/Diffraction/isis_powder/RunDetails.py b/scripts/Diffraction/isis_powder/RunDetails.py new file mode 100644 index 00000000000..e19c72251da --- /dev/null +++ b/scripts/Diffraction/isis_powder/RunDetails.py @@ -0,0 +1,24 @@ +from __future__ import (absolute_import, division, print_function) + + +class RunDetails(object): + """ + This class holds the full file paths associated with each run and various other useful attributes + """ + + def __init__(self, calibration_path, grouping_path, vanadium_name, run_number): + # Essential attributes + self.run_number = run_number + self.calibration = calibration_path + self.grouping = grouping_path + self.vanadium = vanadium_name + + # Optional Attributes + self.instrument_version = None + self.vanadium_absorption = None + self.splined_vanadium = None + self.sample_empty = None + + self.solid_angle_corr = None + + self.label = None diff --git a/scripts/Diffraction/isis_powder/abstract_inst.py b/scripts/Diffraction/isis_powder/abstract_inst.py index 8335e1fa3b0..d93e103be05 100644 --- a/scripts/Diffraction/isis_powder/abstract_inst.py +++ b/scripts/Diffraction/isis_powder/abstract_inst.py @@ -15,14 +15,13 @@ from isis_powder import calibrate @add_metaclass(ABCMeta) class AbstractInst(object): - def __init__(self, user_name=None, calibration_dir=None, raw_data_dir=None, output_dir=None, + def __init__(self, user_name=None, calibration_dir=None, output_dir=None, default_input_ext=".raw"): # ----- Properties common to ALL instruments -------- # if user_name is None: raise ValueError("A user name must be specified") self._user_name = user_name self._calibration_dir = calibration_dir - self._raw_data_dir = raw_data_dir self._output_dir = output_dir self._default_input_ext = _prefix_dot_to_ext(default_input_ext) self._focus_mode = None @@ -115,16 +114,6 @@ class AbstractInst(object): return out_file_names - def _generate_raw_data_cycle_dir(self, run_cycle): - if self._skip_appending_cycle_to_raw_dir(): - return self.raw_data_dir - str_run_cycle = str(run_cycle) - - # Append current cycle to raw data directory - generated_dir = os.path.join(self.raw_data_dir, str_run_cycle) - - return generated_dir - def _generate_input_full_path(self, run_number, input_dir): # Uses runtime polymorphism to generate the full run name file_name = self._generate_inst_file_name(run_number) @@ -162,7 +151,7 @@ class AbstractInst(object): # Instrument specific methods @abstractmethod - def _get_calibration_full_paths(self, run_number): + def _get_run_details(self, run_number): pass @staticmethod @@ -186,16 +175,6 @@ class AbstractInst(object): @return: The algorithm and save range in that order """ - @staticmethod - @abstractmethod - def _get_cycle_information(run_number): - """ - Gets all the information about this run for this cycle and returns it in a dictionary - @param run_number: The run to match the cycle to - @return: Dictionary with the following keys: "cycle", "instrument_version" - """ - pass - # --- Instrument optional hooks ----# # TODO cull some of these hooks once we unify the scripts @@ -262,7 +241,7 @@ class AbstractInst(object): def _subtract_sample_empty(self, input_sample): return input_sample - def _apply_solid_angle_efficiency_corr(self, ws_to_correct, vanadium_number=None, calibration_dict=None): + def _apply_solid_angle_efficiency_corr(self, ws_to_correct, vanadium_number=None, run_details=None): return ws_to_correct def _load_monitor(self, number, cycle): @@ -283,6 +262,9 @@ class AbstractInst(object): def calculate_focus_binning_params(self, sample): return None + def PEARL_populate_user_dirs(self, run_number): + return None + # ----- Private Implementation ----- # # These should only be called by the abstract instrument class diff --git a/scripts/Diffraction/isis_powder/calibrate.py b/scripts/Diffraction/isis_powder/calibrate.py index 690e1812ef3..116d573c6df 100644 --- a/scripts/Diffraction/isis_powder/calibrate.py +++ b/scripts/Diffraction/isis_powder/calibrate.py @@ -15,23 +15,23 @@ def create_van(instrument, van, empty, output_van_file_name, num_of_splines, abs common.remove_intermediate_workspace(input_empty_ws) common.remove_intermediate_workspace(input_van_ws) - calibration_full_paths = instrument._get_calibration_full_paths(run_number=van) + run_details = instrument._get_run_details(run_number=van) corrected_van_ws = instrument. _apply_van_calibration_tof_rebinning(vanadium_ws=corrected_van_ws, tof_rebin_pass=1, return_units="TOF") corrected_van_ws = mantid.AlignDetectors(InputWorkspace=corrected_van_ws, - CalibrationFile=calibration_full_paths["calibration"]) + CalibrationFile=run_details.calibration) corrected_van_ws = instrument._apply_solid_angle_efficiency_corr(ws_to_correct=corrected_van_ws, vanadium_number=van) if absorb: corrected_van_ws = _apply_absorb_corrections(instrument=instrument, - calibration_full_paths=calibration_full_paths, + run_details=run_details, corrected_van_ws=corrected_van_ws, gen_absorb=gen_absorb) focused_van_file = mantid.DiffractionFocussing(InputWorkspace=corrected_van_ws, - GroupingFileName=calibration_full_paths["grouping"]) + GroupingFileName=run_details.grouping) # Optional focused_van_file = instrument. _apply_van_calibration_tof_rebinning(vanadium_ws=focused_van_file, @@ -39,20 +39,19 @@ def create_van(instrument, van, empty, output_van_file_name, num_of_splines, abs common.remove_intermediate_workspace(corrected_van_ws) - cycle_information = instrument._get_cycle_information(run_number=van) + cycle_information = instrument._get_run_details(run_number=van) splined_ws_list = instrument._spline_background(focused_van_file, num_of_splines, - cycle_information["instrument_version"]) - + cycle_information.instrument_version) + # Figure out who will provide the path name if instrument._PEARL_filename_is_full_path(): out_van_file_path = output_van_file_name elif output_van_file_name: - # The user has manually specified the output file name + # The user has manually specified the output file out_van_file_path = os.path.join(instrument.calibration_dir, output_van_file_name) + elif run_details.splined_vanadium: + out_van_file_path = run_details.splined_vanadium else: - try: - out_van_file_path = calibration_full_paths["calibrated_vanadium"] - except KeyError: - raise ValueError("The output name must be manually specified for this instrument/run") + raise ValueError("The output name must be manually specified for this instrument/run") append = False for ws in splined_ws_list: @@ -64,13 +63,13 @@ def create_van(instrument, van, empty, output_van_file_name, num_of_splines, abs return output_ws -def _apply_absorb_corrections(instrument, calibration_full_paths, corrected_van_ws, gen_absorb): +def _apply_absorb_corrections(instrument, run_details, corrected_van_ws, gen_absorb): corrected_van_ws = mantid.ConvertUnits(InputWorkspace=corrected_van_ws, Target="Wavelength") if gen_absorb: - absorb_ws = instrument._generate_vanadium_absorb_corrections(calibration_full_paths, corrected_van_ws) + absorb_ws = instrument._generate_vanadium_absorb_corrections(run_details, corrected_van_ws) else: - absorb_ws = mantid.LoadNexus(Filename=calibration_full_paths["vanadium_absorption"]) + absorb_ws = mantid.LoadNexus(Filename=run_details.vanadium_absorption) # PEARL rebins whilst POLARIS does not as some of the older absorption files have different number of bins corrected_van_ws = instrument._calibration_rebin_to_workspace(ws_to_rebin=corrected_van_ws, ws_to_match=absorb_ws) diff --git a/scripts/Diffraction/isis_powder/common.py b/scripts/Diffraction/isis_powder/common.py index 4e37d557e7a..142d6254057 100644 --- a/scripts/Diffraction/isis_powder/common.py +++ b/scripts/Diffraction/isis_powder/common.py @@ -1,6 +1,8 @@ from __future__ import (absolute_import, division, print_function) -import mantid.simpleapi as mantid +from six.moves import xrange + +import mantid.simpleapi as mantid # --- Public API --- # @@ -56,7 +58,7 @@ def _load_monitor_sum_range(files, input_dir, instrument): # TODO refactor this - it probably doesn't work at the moment loop = 0 num = files.split("_") - frange = list(range(int(num[0]), int(num[1]) + 1)) + frange = xrange(int(num[0]), int(num[1]) + 1) mspectra = instrument._get_monitor_spectra(int(num[0])) for i in frange: file_path = instrument._generate_input_full_path(i, input_dir) @@ -79,26 +81,26 @@ def _load_monitor_sum_range(files, input_dir, instrument): def _load_raw_files(run_number, instrument): - cycle_information = instrument._get_cycle_information(run_number=run_number) - input_dir = instrument._generate_raw_data_cycle_dir(cycle_information["cycle"]) + run_name = instrument._generate_inst_file_name(run_number=run_number) + + instrument.PEARL_populate_user_dirs(run_number=run_number) if isinstance(run_number, int): - infile = instrument._generate_input_full_path(run_number=run_number, input_dir=input_dir) - load_raw_ws = mantid.LoadRaw(Filename=infile, LoadLogFiles="0") + load_raw_ws = mantid.Load(Filename=run_name, LoadLogFiles="0") else: - load_raw_ws = _load_raw_file_range(run_number, input_dir, instrument) + load_raw_ws = _load_raw_file_range(run_number, instrument) return load_raw_ws -def _load_raw_file_range(files, input_dir, instrument): +def _load_raw_file_range(files, instrument): loop = 0 num = files.split("_") - frange = list(range(int(num[0]), int(num[1]) + 1)) + frange = xrange(int(num[0]), int(num[1]) + 1) out_ws = None for i in frange: - file_path = instrument._generate_input_full_path(i, input_dir) + file_name = instrument._generate_inst_file_name(run_number=i) outwork = "run" + str(i) - mantid.LoadRaw(Filename=file_path, OutputWorkspace=outwork, LoadLogFiles="0") + mantid.Load(Filename=file_name, OutputWorkspace=outwork, LoadLogFiles="0") loop += 1 if loop == 2: firstwk = "run" + str(i - 1) @@ -118,8 +120,8 @@ def _load_current_normalised_ws(number, instrument): read_in_ws = _load_raw_files(run_number=number, instrument=instrument) - cycle_information = instrument._get_cycle_information(run_number=number) - load_monitor_ws = instrument._load_monitor(number=number, cycle=cycle_information["cycle"]) + run_information = instrument._get_run_details(run_number=number) + load_monitor_ws = instrument._load_monitor(number=number, cycle=run_information.label) read_ws = instrument._normalise_ws(ws_to_correct=read_in_ws, monitor_ws=load_monitor_ws, spline_terms=20) diff --git a/scripts/Diffraction/isis_powder/focus.py b/scripts/Diffraction/isis_powder/focus.py index da980a745a0..ff688ffe0fd 100644 --- a/scripts/Diffraction/isis_powder/focus.py +++ b/scripts/Diffraction/isis_powder/focus.py @@ -14,21 +14,20 @@ def _run_focus(instrument, run_number, perform_attenuation, perform_vanadium_nor read_ws = common._load_current_normalised_ws(number=run_number, instrument=instrument) input_workspace = instrument._do_tof_rebinning_focus(read_ws) # Rebins for PEARL - calibration_file_paths = instrument._get_calibration_full_paths(run_number=run_number) + calibration_file_paths = instrument._get_run_details(run_number=run_number) # Compensate for empty sample if specified input_workspace = instrument._subtract_sample_empty(input_workspace) # Align / Focus input_workspace = mantid.AlignDetectors(InputWorkspace=input_workspace, - CalibrationFile=calibration_file_paths["calibration"]) + CalibrationFile=calibration_file_paths.calibration) - # TODO fix this - maybe have it save solid angle corrections and just load/apply input_workspace = instrument._apply_solid_angle_efficiency_corr(ws_to_correct=input_workspace, - calibration_dict=calibration_file_paths) + run_details=calibration_file_paths) focused_ws = mantid.DiffractionFocussing(InputWorkspace=input_workspace, - GroupingFileName=calibration_file_paths["grouping"]) + GroupingFileName=calibration_file_paths.grouping) # Process rebinning_params = instrument.calculate_focus_binning_params(sample=focused_ws) @@ -56,14 +55,13 @@ def _run_focus(instrument, run_number, perform_attenuation, perform_vanadium_nor def _divide_sample_by_vanadium(instrument, run_number, input_workspace, perform_vanadium_norm): processed_spectra = [] - input_file_paths = instrument._get_calibration_full_paths(run_number=run_number) + run_details = instrument._get_run_details(run_number=run_number) - cycle_information = instrument._get_cycle_information(run_number=run_number) - alg_range, save_range = instrument._get_instrument_alg_save_ranges(cycle_information["instrument_version"]) + alg_range, save_range = instrument._get_instrument_alg_save_ranges(run_details.instrument_version) for index in range(0, alg_range): if perform_vanadium_norm: - vanadium_ws = mantid.LoadNexus(Filename=input_file_paths["calibrated_vanadium"], EntryNumber=index + 1) + vanadium_ws = mantid.LoadNexus(Filename=run_details.splined_vanadium, EntryNumber=index + 1) processed_spectra.append( instrument.correct_sample_vanadium(focused_ws=input_workspace, index=index, vanadium_ws=vanadium_ws)) diff --git a/scripts/Diffraction/isis_powder/mock_instrument.py b/scripts/Diffraction/isis_powder/mock_instrument.py index b7deba6bb45..e22ebecd6d1 100644 --- a/scripts/Diffraction/isis_powder/mock_instrument.py +++ b/scripts/Diffraction/isis_powder/mock_instrument.py @@ -21,7 +21,7 @@ class MockInstrument(AbstractInst): def _get_default_group_names(self): return None - def _get_calibration_full_paths(self, run_number): + def _get_run_details(self, run_number): # This is here to help remind people of the dict that is expected calibration_details = {"calibration": "cal", "grouping": "group", @@ -38,7 +38,7 @@ class MockInstrument(AbstractInst): return None @staticmethod - def _get_cycle_information(run_number): + def _get_label_information(run_number): # This is here to help remind people of the dict format cycle_information = {"cycle" : "123", "instrument_version": "test_v1"} diff --git a/scripts/Diffraction/isis_powder/pearl.py b/scripts/Diffraction/isis_powder/pearl.py index 567264f93a4..0c7c9a6a429 100644 --- a/scripts/Diffraction/isis_powder/pearl.py +++ b/scripts/Diffraction/isis_powder/pearl.py @@ -1,6 +1,8 @@ from __future__ import (absolute_import, division, print_function) import mantid.simpleapi as mantid +from mantid import config + import numpy as numpy import os @@ -10,6 +12,7 @@ import isis_powder.common as common from isis_powder import pearl_calib_factory from isis_powder import pearl_cycle_factory +from isis_powder.RunDetails import RunDetails from isis_powder.pearl_routines import fmode_output @@ -30,7 +33,7 @@ class Pearl(AbstractInst): def __init__(self, user_name=None, calibration_dir=None, raw_data_dir=None, output_dir=None, input_file_ext=".raw", tt_mode="TT88"): - super(Pearl, self).__init__(user_name=user_name, calibration_dir=calibration_dir, raw_data_dir=raw_data_dir, + super(Pearl, self).__init__(user_name=user_name, calibration_dir=calibration_dir, output_dir=output_dir, default_input_ext=input_file_ext) self._tt_mode = tt_mode @@ -41,7 +44,7 @@ class Pearl(AbstractInst): # Old API support self._old_atten_file = None - self._old_api_uses_full_paths = False + self._existing_config = None # File names pearl_mc_absorption_file_name = "PRL112_DC25_10MM_FF.OUT" # TODO @@ -63,11 +66,13 @@ class Pearl(AbstractInst): # Methods # - def _get_calibration_full_paths(self, run_number): - cycle_dict = self._get_cycle_information(run_number=run_number) + def _get_run_details(self, run_number): + # TODO once we migrate this to another format (i.e. not the if/elif/else) implement cached val + cycle_dict = self._get_label_information(run_number=run_number) calibration_file, grouping_file, van_absorb, van_file =\ pearl_calib_factory.get_calibration_filename(cycle=cycle_dict["cycle"], tt_mode=self._tt_mode) + cycle, instrument_version = pearl_cycle_factory.get_cycle_dir(run_number) calibration_dir = self.calibration_dir @@ -76,17 +81,19 @@ class Pearl(AbstractInst): van_absorb_full_path = os.path.join(calibration_dir, van_absorb) van_file_full_path = os.path.join(calibration_dir, van_file) - # TODO when we move PEARL to save out splined vanadium files support them below - calibration_details = {"calibration": calibration_full_path, - "grouping": grouping_full_path, - "vanadium_absorption": van_absorb_full_path, - "vanadium": van_file_full_path, - "calibrated_vanadium": van_file_full_path} + run_details = RunDetails(calibration_path=calibration_full_path, grouping_path=grouping_full_path, + vanadium_name=van_file_full_path, run_number=run_number) + run_details.vanadium_absorption = van_absorb_full_path + run_details.label = cycle + run_details.instrument_version = instrument_version - return calibration_details + # TODO remove this when we move to saving splined van ws on PEARL + run_details.splined_vanadium = run_details.vanadium - @staticmethod - def _get_cycle_information(run_number): + return run_details + + def _get_label_information(self, run_number): + # TODO remove this when we move to combining CAL/RUN factories run_input = "" if not run_number.isdigit(): # Only take first valid number as it is probably of the form 12345_12350 @@ -119,7 +126,7 @@ class Pearl(AbstractInst): def _create_calibration(self, calibration_runs, offset_file_name, grouping_file_name): input_ws = common._load_current_normalised_ws(number=calibration_runs, instrument=self) - cycle_information = self._get_cycle_information(calibration_runs) + cycle_information = self._get_label_information(calibration_runs) if cycle_information["instrument_version"] == "new" or cycle_information["instrument_version"] == "new2": input_ws = mantid.Rebin(InputWorkspace=input_ws, Params="100,-0.0006,19950") @@ -283,7 +290,7 @@ class Pearl(AbstractInst): def _do_silicon_calibration(self, runs_to_process, cal_file_name, grouping_file_name): # TODO fix all of this as the script is too limited to be useful create_si_ws = common._load_current_normalised_ws(number=runs_to_process, instrument=self) - cycle_details = self._get_cycle_information(runs_to_process) + cycle_details = self._get_label_information(runs_to_process) instrument_version = cycle_details["instrument_version"] if instrument_version == "new" or instrument_version == "new2": @@ -364,6 +371,17 @@ class Pearl(AbstractInst): mspectra = 1 return mspectra + def _generate_raw_data_cycle_dir(self, run_cycle): + if self._skip_appending_cycle_to_raw_dir(): + return self.raw_data_dir + str_run_cycle = str(run_cycle) + + # Append current cycle to raw data directory + generated_dir = os.path.join(self.raw_data_dir, str_run_cycle) + generated_dir += '/' + + return generated_dir + # Support for old API - This can be removed when PEARL_routines is removed def _old_api_constructor_set(self, user_name=None, calibration_dir=None, raw_data_dir=None, output_dir=None, input_file_ext=None, tt_mode=None): @@ -388,7 +406,7 @@ class Pearl(AbstractInst): self._calibration_dir = calib_dir def _old_api_set_raw_data_dir(self, raw_data_dir): - self._disable_appending_cycle_to_raw_dir = True + self._old_api_uses_full_paths = True self._raw_data_dir = raw_data_dir def _old_api_set_output_dir(self, output_dir): @@ -406,6 +424,14 @@ class Pearl(AbstractInst): def _PEARL_filename_is_full_path(self): return self._old_api_uses_full_paths + def PEARL_populate_user_dirs(self, run_number): + run_details = self._get_run_details(run_number=run_number) + generated_path = self._generate_raw_data_cycle_dir(run_cycle=run_details.label) + user_dirs = config['datasearch.directories'] + user_dirs_list = user_dirs.split(';') + if generated_path not in user_dirs_list: + config['datasearch.directories'] += ';' + generated_path + def _get_focus_tof_binning(self): return self._focus_tof_binning diff --git a/scripts/Diffraction/isis_powder/pearl_routines/fmode_output.py b/scripts/Diffraction/isis_powder/pearl_routines/fmode_output.py index 7beb0d4b84c..7eeb9ac9495 100644 --- a/scripts/Diffraction/isis_powder/pearl_routines/fmode_output.py +++ b/scripts/Diffraction/isis_powder/pearl_routines/fmode_output.py @@ -9,7 +9,7 @@ import isis_powder.common as common def generate_and_save_focus_output(instrument, processed_spectra, run_number, perform_attenuation, focus_mode=None,): output_file_paths = instrument._generate_out_file_paths(run_number, instrument.output_dir) - cycle_information = instrument._get_cycle_information(run_number) + cycle_information = instrument._get_label_information(run_number) unused, save_range = instrument._get_instrument_alg_save_ranges(cycle_information["instrument_version"]) if focus_mode == "all": diff --git a/scripts/Diffraction/isis_powder/polaris.py b/scripts/Diffraction/isis_powder/polaris.py index f7149f37e26..651dfe6513c 100644 --- a/scripts/Diffraction/isis_powder/polaris.py +++ b/scripts/Diffraction/isis_powder/polaris.py @@ -5,10 +5,10 @@ import os import mantid.simpleapi as mantid from isis_powder.abstract_inst import AbstractInst -from isis_powder.polaris_routines import polaris_calib_factory from isis_powder.polaris_routines import polaris_calib_parser import isis_powder.common as common +from isis_powder.RunDetails import RunDetails class Polaris(AbstractInst): @@ -25,13 +25,17 @@ class Polaris(AbstractInst): _number_of_banks = 5 def __init__(self, user_name=None, calibration_dir=None, raw_data_dir=None, output_dir=None, - input_file_ext=".raw", sample_empty_name=None): + input_file_ext=".raw", chopper_on=True): - super(Polaris, self).__init__(user_name=user_name, calibration_dir=calibration_dir, raw_data_dir=raw_data_dir, + super(Polaris, self).__init__(user_name=user_name, calibration_dir=calibration_dir, output_dir=output_dir, default_input_ext=input_file_ext) + self._chopper_on = chopper_on self._masking_file_name = "VanaPeaks.dat" - self._sample_empty = sample_empty_name + + # Caches the last dictionary to avoid us having to keep parsing the YAML + self._run_details_last_run_number = None + self._run_details_cached_obj = None # Abstract implementation def _get_lambda_range(self): @@ -43,26 +47,33 @@ class Polaris(AbstractInst): def _get_default_group_names(self): return self._calibration_grouping_names - def _get_calibration_full_paths(self, run_number): - # offset_file_name, grouping_file_name, vanadium_file_name = polaris_calib_factory.get_calibration_file(cycle) - cycle_dict = self._get_cycle_information(run_number=run_number) - configuration = polaris_calib_parser.get_calibration_dict(cycle_dict["cycle"]) - calibration_dir = self.calibration_dir + def _get_run_details(self, run_number): + # TODO rename this from get calibration to get run details + if self._run_details_last_run_number == run_number: + return self._run_details_cached_obj - # Assume the raw vanadium is with other raw files - vanadium_full_path = os.path.join(self.raw_data_dir, configuration["vanadium_file_name"]) + configuration = polaris_calib_parser.get_calibration_dict(run_number=run_number) + calibration_dir = self.calibration_dir + # Common to all runs calibration_full_path = os.path.join(calibration_dir, configuration["offset_file_name"]) grouping_full_path = os.path.join(calibration_dir, configuration["grouping_file_name"]) + if self._chopper_on: + chopper_config = configuration["chopper_on"] + else: + chopper_config = configuration["chopper_off"] + vanadium_file = self._generate_inst_file_name(run_number=chopper_config["vanadium_file_name"]) + splined_vanadium = os.path.join(calibration_dir, chopper_config["splined_vanadium_file_name"]) + solid_angle_file_path = os.path.join(calibration_dir, chopper_config["solid_angle_file_name"]) - calibrated_full_path = os.path.join(calibration_dir, configuration["calibrated_vanadium_file_name"]) - solid_angle_file_path = os.path.join(calibration_dir, configuration["solid_angle_file_name"]) + calibration_details = RunDetails(calibration_path=calibration_full_path, grouping_path=grouping_full_path, + vanadium_name=vanadium_file, run_number=run_number) + calibration_details.splined_vanadium = splined_vanadium + calibration_details.solid_angle_corr = solid_angle_file_path + calibration_details.label = configuration["label"] - calibration_details = {"calibration": calibration_full_path, - "grouping": grouping_full_path, - "vanadium": vanadium_full_path, - "calibrated_vanadium": calibrated_full_path, - "solid_angle_corr": solid_angle_file_path} + self._run_details_last_run_number = run_number + self._run_details_cached_obj = calibration_details return calibration_details @@ -75,11 +86,6 @@ class Polaris(AbstractInst): alg_range = 5 return alg_range, None - @staticmethod - def _get_cycle_information(run_number): - return {"cycle": "test", # TODO implement properly - "instrument_version": ""} - def _normalise_ws(self, ws_to_correct, monitor_ws=None, spline_terms=20): normalised_ws = mantid.NormaliseByCurrent(InputWorkspace=ws_to_correct) return normalised_ws @@ -112,6 +118,8 @@ class Polaris(AbstractInst): return corrections_ws def _subtract_sample_empty(self, input_sample): + # TODO when calibration mapping has sample.empty enable this + return input_sample if self._sample_empty is not None: empty_sample_path = os.path.join(self.calibration_dir, self._sample_empty) empty_sample = mantid.Load(Filename=empty_sample_path) @@ -120,13 +128,13 @@ class Polaris(AbstractInst): common.remove_intermediate_workspace(empty_sample) return input_sample - def _apply_solid_angle_efficiency_corr(self, ws_to_correct, vanadium_number=None, calibration_dict=None): - assert(vanadium_number or calibration_dict) + def _apply_solid_angle_efficiency_corr(self, ws_to_correct, vanadium_number=None, run_details=None): + assert(vanadium_number or run_details) - if not calibration_dict or not os.path.isfile(calibration_dict["solid_angle_corr"]): - corrections = self.generate_solid_angle_corrections(calibration_dict, vanadium_number) + if not run_details or not os.path.isfile(run_details.solid_angle_corr): + corrections = self.generate_solid_angle_corrections(run_details, vanadium_number) else: - corrections = mantid.Load(Filename=calibration_dict["solid_angle_corr"]) + corrections = mantid.Load(Filename=run_details.solid_angle_corr) corrected_ws = mantid.Divide(LHSWorkspace=ws_to_correct, RHSWorkspace=corrections) common.remove_intermediate_workspace(corrections) @@ -134,16 +142,18 @@ class Polaris(AbstractInst): ws_to_correct = corrected_ws return ws_to_correct - def generate_solid_angle_corrections(self, calibration_dict, vanadium_number): + def generate_solid_angle_corrections(self, run_details, vanadium_number): if vanadium_number: solid_angle_vanadium_ws = common._load_raw_files(run_number=vanadium_number, instrument=self) + elif run_details: + solid_angle_vanadium_ws = mantid.Load(Filename=run_details.vanadium) else: - solid_angle_vanadium_ws = mantid.Load(Filename=calibration_dict["vanadium"]) + raise RuntimeError("Got no run_details of vanadium_number in gen solid angle corrections") normalised_vanadium_ws = self._normalise_ws(solid_angle_vanadium_ws) corrections = self._calculate_solid_angle_efficiency_corrections(normalised_vanadium_ws) - if calibration_dict: - mantid.SaveNexusProcessed(InputWorkspace=corrections, Filename=calibration_dict["solid_angle_corr"]) + if run_details: + mantid.SaveNexusProcessed(InputWorkspace=corrections, Filename=run_details.solid_angle_corr) common.remove_intermediate_workspace(solid_angle_vanadium_ws) common.remove_intermediate_workspace(normalised_vanadium_ws) @@ -241,7 +251,7 @@ class Polaris(AbstractInst): def _read_masking_file(self): all_banks_masking_list = [] bank_masking_list = [] - mask_path = os.path.join(self.raw_data_dir, self._masking_file_name) + mask_path = os.path.join(self.calibration_dir, self._masking_file_name) ignore_line_prefixes = (' ', '\n', '\t', '#') # Matches whitespace or # symbol diff --git a/scripts/Diffraction/isis_powder/polaris_routines/polaris_calib_parser.py b/scripts/Diffraction/isis_powder/polaris_routines/polaris_calib_parser.py index 86589d2223c..42d54b3294e 100644 --- a/scripts/Diffraction/isis_powder/polaris_routines/polaris_calib_parser.py +++ b/scripts/Diffraction/isis_powder/polaris_routines/polaris_calib_parser.py @@ -1,16 +1,14 @@ from __future__ import (absolute_import, division, print_function) +from six.moves import xrange import os import yaml -def get_calibration_dict(cycle): +def get_calibration_dict(run_number): config_file = _open_yaml_file() - try: - output = config_file[str(cycle)] - except KeyError: - raise RuntimeError("Cycle " + str(cycle) + " not defined in calibration file") - return output + run_key = _get_dictionary_key(config_handle=config_file, run_number=run_number) + return config_file[run_key] def _open_yaml_file(): @@ -27,3 +25,33 @@ def _open_yaml_file(): raise RuntimeError("Failed to parse POLARIS calibration YAML file") return read_config + + +def _get_dictionary_key(config_handle, run_number): + + for key in config_handle: + run_generator = _parse_number_key(input_string=key) + for run_list in run_generator: + if run_number in run_list: + return key + + # If we hit this point the run_number isn't in any of the keys in the YAML file + raise ValueError("Run number " + str(run_number) + " not recognised in calibration mapping") + + +def _parse_number_key(input_string): + # Expands run numbers of the form 1-10, 12, 14-20, 23 to 1,2,3,..,8,9,10,12,14,15,16...,19,20,23 + + string_to_parse = str(input_string).strip() + + for entry in string_to_parse.split(','): + # Split between comma separated values + numbers = entry.split('-') + # Check if we are using a dash separator and return the range between those values + if len(numbers) == 1: + yield numbers + elif len(numbers) == 2: + # Add 1 so it includes the final number '-' range + yield xrange(int(numbers[0]), int(numbers[-1]) + 1) + else: + raise ValueError("The run number " + str(entry) + " is incorrect in calibration mapping") diff --git a/scripts/Diffraction/isis_powder/polaris_routines/polaris_calibration.yaml b/scripts/Diffraction/isis_powder/polaris_routines/polaris_calibration.yaml index 125f1d31298..03aace5d00e 100644 --- a/scripts/Diffraction/isis_powder/polaris_routines/polaris_calibration.yaml +++ b/scripts/Diffraction/isis_powder/polaris_routines/polaris_calibration.yaml @@ -7,9 +7,23 @@ # calibrated_vanadium_file_name : "calibrated_vanadium_name.nxs" # solid_angle_file_name : "solid_angle_corrections.nxs" -test: +#test: +# offset_file_name : "offsets_2011_cycle111b.cal" +# grouping_file_name : "offsets_2011_cycle111b.cal" +# vanadium_file_name : "POL78338.raw" +# calibrated_vanadium_file_name : "calibrated_vanadium_name.nxs" +# solid_angle_file_name : "solid_angle_corrections.nxs" +# + +78334-82415: offset_file_name : "offsets_2011_cycle111b.cal" grouping_file_name : "offsets_2011_cycle111b.cal" - vanadium_file_name : "POL78338.raw" - calibrated_vanadium_file_name : "calibrated_vanadium_name.nxs" - solid_angle_file_name : "solid_angle_corrections.nxs" + label : "15_2" + chopper_on: + vanadium_file_name : "78338" + splined_vanadium_file_name : "chopper_on_van_calib.nxs" + solid_angle_file_name : "chopper_on_sac.nxs" + chopper_off: + vanadium_file_name : "78338" + splined_vanadium_file_name : "chopper_off_van_calib.nxs" + solid_angle_file_name : "chopper_off_sac.nxs" diff --git a/scripts/PearlPowderISIS/pearl_routines.py b/scripts/PearlPowderISIS/pearl_routines.py index 0e1af82d14a..8092468d45c 100644 --- a/scripts/PearlPowderISIS/pearl_routines.py +++ b/scripts/PearlPowderISIS/pearl_routines.py @@ -100,7 +100,7 @@ def PEARL_getmonitorspectrum(runno): def PEARL_getcycle(number): pearl_obj = _pearl_obj_singleton() - cycle_information = pearl_obj._get_cycle_information(number) + cycle_information = pearl_obj._get_label_information(number) datadir = pearl_obj.output_dir updated_vals = {"cycle" : cycle_information["cycle"], "instver" : cycle_information["instrument_version"], @@ -124,7 +124,7 @@ def PEARL_getcalibfiles(): pearl_obj._old_api_set_tt_mode(g_oldParams["tt_mode"]) pearl_obj._old_api_set_calib_dir(g_oldParams["pearl_file_dir"]) - cal_dict = pearl_obj._get_calibration_full_paths(cycle=cycle) + cal_dict = pearl_obj._get_run_details(cycle=cycle) print ("Setting calibration for cycle", cycle) updated_vals = {"calfile" : cal_dict["calibration"], diff --git a/scripts/test/ISIS_Powder_PearlTest.py b/scripts/test/ISIS_Powder_PearlTest.py index 0e6e4384f57..265c5cb9e7d 100644 --- a/scripts/test/ISIS_Powder_PearlTest.py +++ b/scripts/test/ISIS_Powder_PearlTest.py @@ -13,7 +13,7 @@ class isis_powder_PearlTest(unittest.TestCase): def test_cycle_information_generates_correctly(self): # This checks that the cycle information generates using the correct keys for the dict - output = self._get_pearl_inst_defaults()._get_cycle_information(85500) + output = self._get_pearl_inst_defaults()._get_label_information(85500) expected_cycle = "14_1" expected_inst_vers = "new2" self.assertEquals(output["cycle"], expected_cycle) @@ -57,7 +57,7 @@ class isis_powder_PearlTest(unittest.TestCase): expected_calibration_dir = self.calibration_dir pearl_obj = self._get_pearl_inst_defaults() - output = pearl_obj._get_calibration_full_paths(input_cycle) + output = pearl_obj._get_run_details(input_cycle) self.assertEquals(output["calibration"], expected_calibration_dir + expected_calfile) self.assertEquals(output["grouping"], expected_calibration_dir + expected_grouping_file) -- GitLab