Skip to content
This repository was archived by the owner on Nov 14, 2022. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
213 changes: 180 additions & 33 deletions NDXINTER/reduce.py
Original file line number Diff line number Diff line change
@@ -1,41 +1,188 @@
import os
import shutil
import sys
sys.path.append("/isis/NDXMUSR/user/scripts/autoreduction")

AUTOREDUCTION_DIR = r"/autoreduce/data-archive/NDXINTER/user/scripts/autoreduction"
sys.path.append(AUTOREDUCTION_DIR)

# import mantid algorithms, numpy and matplotlib
from mantid.simpleapi import *
import matplotlib.pyplot as plt
import numpy as np
import reduce_vars as web_var
import os
import json
from shutil import copy

instrument='INTER'

# Main funcion that gets called by the reduction
def main(input_file, output_dir):
standard_params = web_var.standard_vars
advanced_params = web_var.advanced_vars
config['defaultsave.directory'] = output_dir

# Get the angle
angle, input_run = get_angle(input_file)
# Parse settings from JSON file
json_input = standard_params['path_to_json_settings_file']
params = parse_json_settings(json_input, angle)

# Run reduction
alg=AlgorithmManager.create("ReflectometryISISLoadAndProcess")
properties = {
"InputRunList" : input_run,
"FirstTransmissionRunList" : params.first_transmission_run_list,
"SecondTransmissionRunList" : params.second_transmission_run_list,
"ThetaIn" : angle,
"DetectorCorrectionType" : params.detector_correction_type,
"MonitorBackgroundWavelengthMin" : params.monitor_background_wavelength_min,
"MonitorBackgroundWavelengthMax" : params.monitor_background_wavelength_max,
"MonitorIntegrationWavelengthMin" : params.monitor_integration_wavelength_min,
"MonitorIntegrationWavelengthMax" : params.monitor_integration_wavelength_max,
"WavelengthMin" : params.wavelength_min,
"WavelengthMax" : params.wavelength_max,
"I0MonitorIndex" : params.i_zero_monitor_index,
"AnalysisMode" : params.analysis_mode,
"StartOverlap" : params.start_overlap,
"EndOverlap" : params.end_overlap,
"ScaleRHSWorkspace" : params.scale_rhs_workspace,
"TransmissionProcessingInstructions" : params.transmission_processing_instructions,
"ProcessingInstructions" : params.processing_instructions
}
alg.setProperties(properties)
alg.execute()

def validate(input_file, output_dir):
# Save reduced data as Nexus files
OutputWorkspace=alg.getPropertyValue("OutputWorkspace")
OutputWorkspaceBinned=alg.getPropertyValue("OutputWorkspaceBinned")
SaveNexus(OutputWorkspace, os.path.join(output_dir, OutputWorkspace+".nxs"))
SaveNexus(OutputWorkspaceBinned, os.path.join(output_dir, OutputWorkspaceBinned+".nxs"))

# Save a copy of the .json settings file
copy(json_input, output_dir)

def get_angle(input_file):
"""
Function to ensure that the files we want to use in reduction exist.
Please add any files/directories to the required_files/dirs lists.
Get the average angle from logs of motor position
:param input_file: The input Nexus file
:return: Average (mean) angle from motor position readback
"""
print("Running validation")
required_files = [input_file]
required_dirs = [output_dir]
for file_path in required_files:
if not os.path.isfile(file_path):
raise RuntimeError("Unable to find file: {}".format(file_path))
for dir in required_dirs:
if not os.path.isdir(dir):
raise RuntimeError("Unable to find directory: {}".format(dir))
print("Validation successful")

filename = os.path.basename(input_file)
run_str = filename.split("INTER")[1].split(".")[0].strip("0")
name=instrument+run_str
ws=Load(Filename=name, OutputWorkspace='TOF_'+run_str)
# Filter the logs for all angles starting from time 0 and use the average of the returned angles
(angle_list, average_angle) = FilterLogByTime(ws, 'Theta', StartTime=0)
return average_angle, name

def main(input_file, output_dir):
validate(input_file, output_dir)

# Example of printing some stuff which is captured in autoreduction
# output log file
print(web_var)
print("input_file = " + str(input_file))
print("output_dir = " + str(output_dir))

# Copy raw data to output dir.
# Note this should only be done if raw files are small and for specific
# purpose such as testing
shutil.copy(input_file, output_dir)

# And of course, here and below insert your reduction code!
def parse_json_settings(json_input, angle):
"""
Get experiment settings and instrument settings from JSON file
:param angle: Angle passed in and used to select "per angle defaults"
:return: Returns all of the parameters needed to do the reduction
"""
params = INTERParams()

with open(json_input, "r") as read_file:
data = json.load(read_file)

#========================================================================================
# Experiment Settings
#========================================================================================

experimentView = data["experimentView"]

# Set a string based on what integer value is found
if experimentView["analysisModeComboBox"] == 1:
params.analysis_mode = "MultiDetectorAnalysis"
elif experimentView["analysisModeComboBox"] == 0:
params.analysis_mode = "PointDetectorAnalysis"
else:
raise Exception # If the value isn't 1 or 0 then it isn't valid

perAngleDefaults = experimentView["perAngleDefaults"]
rows = perAngleDefaults["rows"]

# This looks for the run angle and set other parameters accordingly
# Using a tolerance of +-0.5% of the motor readback angle
min = angle * 0.995
max = angle * 1.005
angle_found = False
for row in rows:
# If the value is within -0.5% to +0.5% it is counted as a match
if min <= float(row[0]) <= max:
angle_found, params = get_per_angle_defaults_params(row, params)
break

# This is the default case
if not angle_found:
for row in rows:
if row[0] == "":
angle_found, params = get_per_angle_defaults_params(row, params)
break

if not angle_found:
raise Exception # Excpetion for if neither a pre-defined angle nor the default case are found

params.start_overlap = experimentView["startOverlapEdit"]
params.end_overlap = experimentView["endOverlapEdit"]
params.scale_rhs_workspace = experimentView["transScaleRHSCheckBox"]

#========================================================================================
# Instrument Settings
#========================================================================================

instrumentView = data["instrumentView"]

params.monitor_integration_wavelength_min = instrumentView["monIntMinEdit"]
params.monitor_integration_wavelength_max = instrumentView["monIntMaxEdit"]
params.monitor_background_wavelength_min = instrumentView["monBgMinEdit"]
params.monitor_background_wavelength_max = instrumentView["monBgMaxEdit"]
params.wavelength_min = instrumentView["lamMinEdit"]
params.wavelength_max = instrumentView["lamMaxEdit"]
params.i_zero_monitor_index = instrumentView["I0MonitorIndex"]

# Set a string based on what integer value is found
if instrumentView["detectorCorrectionTypeComboBox"] == 1:
params.detector_correction_type = "RotateAroundSample"
elif instrumentView["detectorCorrectionTypeComboBox"] == 0:
params.detector_correction_type = "VerticalShift"
else:
raise Exception # If the value isn't 1 or 0 then it isn't valid

return params

def get_per_angle_defaults_params(row, params):
"""
Get parameters that are dependant on the angle
:param row: The row for the angle that has been selected (or the row for the default case if no angle was matched)
:return: Returns all of the parameters that are dependant on the angle
"""
angle_found = True
params.first_transmission_run_list = instrument+row[1]
params.second_transmission_run_list = instrument+row[2]
params.transmission_processing_instructions = row[3]
# Skipping over parameters that are present in the JSON file but not currently used in the reduction
params.processing_instructions = row[8]
return angle_found, params

class INTERParams:
analysis_mode : str
first_transmission_run_list : str
second_transmission_run_list : str
transmission_processing_instructions : str
processing_instructions : str
start_overlap : str
end_overlap : str
scale_rhs_workspace : str
monitor_integration_wavelength_min : str
monitor_integration_wavelength_max : str
monitor_background_wavelength_min : str
monitor_background_wavelength_max : str
wavelength_min : str
wavelength_max : str
i_zero_monitor_index : str
detector_correction_type : str

if __name__ == "__main__":
main("test", "test")
main('','')

26 changes: 16 additions & 10 deletions NDXINTER/reduce_vars.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
standard_vars = {
'example standard var' : [1.0, 2.0, 3.0], # example comment
'path_to_json_settings_file' : '/autoreduce/scripts/settings.json'
# 'analysis_mode': "MultiDetectorAnalysis",
# 'first_transmission_run_list' : "INTER00061705",
# 'second_transmission_run_list' : "INTER00061669",
# 'transmission_processing_instructions': "76-85",
# 'processing_instructions': "80-84",
# 'start_overlap' : 10.0,
# 'end_overlap' : 12.0
}
advanced_vars = {
'example advanced var' : '5',
# 'monitor_integration_wavelength_min' : 4.0,
# 'monitor_integration_wavelength_max' : 10.0,
# 'monitor_background_wavelength_min': 17.0,
# 'monitor_background_wavelength_max': 18.0,
# 'wavelength_min' : 1.5,
# 'wavelength_max' : 17.0,
# 'i_zero_monitor_index' : 2,
# 'detector_correction_type': "VerticalShift"
}
variable_help = {
'standard_vars' : {
'example standard var' : "The list of a, b, c"
},
'advanced_vars' : {
'example advanced var' : "example comment"
},
}