From e957d946a15b84052da37844a68ba9c70ce04ae8 Mon Sep 17 00:00:00 2001
From: Gemma Guest <gemma.guest@stfc.ac.uk>
Date: Wed, 7 Nov 2018 11:31:27 +0000
Subject: [PATCH] Add new INTER system test

---
 .../INTER/INTERReductionTestRuns.nxs.md5      |   1 +
 .../tests/analysis/INTERReductionTest.py      | 285 ++++++++++++++++++
 .../reference/INTERReductionResult.nxs.md5    |   1 +
 3 files changed, 287 insertions(+)
 create mode 100644 Testing/Data/SystemTest/INTER/INTERReductionTestRuns.nxs.md5
 create mode 100644 Testing/SystemTests/tests/analysis/INTERReductionTest.py
 create mode 100644 Testing/SystemTests/tests/analysis/reference/INTERReductionResult.nxs.md5

diff --git a/Testing/Data/SystemTest/INTER/INTERReductionTestRuns.nxs.md5 b/Testing/Data/SystemTest/INTER/INTERReductionTestRuns.nxs.md5
new file mode 100644
index 00000000000..fb8487afde9
--- /dev/null
+++ b/Testing/Data/SystemTest/INTER/INTERReductionTestRuns.nxs.md5
@@ -0,0 +1 @@
+e50c38cd8fb906ab71f1e6e93911d988
diff --git a/Testing/SystemTests/tests/analysis/INTERReductionTest.py b/Testing/SystemTests/tests/analysis/INTERReductionTest.py
new file mode 100644
index 00000000000..9c6f95251f6
--- /dev/null
+++ b/Testing/SystemTests/tests/analysis/INTERReductionTest.py
@@ -0,0 +1,285 @@
+# Mantid Repository : https://github.com/mantidproject/mantid
+#
+# Copyright &copy; 2018 ISIS Rutherford Appleton Laboratory UKRI,
+#     NScD Oak Ridge National Laboratory, European Spallation Source
+#     & Institut Laue - Langevin
+# SPDX - License - Identifier: GPL - 3.0 +
+"""
+System Test for ISIS Reflectometry reduction
+Adapted from scripts provided by Max Skoda.
+"""
+from __future__ import (print_function)
+import systemtesting
+from mantid.simpleapi import *
+from mantid import ConfigService
+
+
+class INTERReductionTest(systemtesting.MantidSystemTest):
+    '''
+    Mantid Test Script for INTER:
+
+    Tests:
+    1. Event data time-slicing
+    2. "Quickref" - used when the autoreduction unwantedly sums runs together.
+    3. Scripted fitting of reduced data for NRW
+    4. Linear detector reduction
+    '''
+    # Note: you may find the regenerate functions useful.
+
+    event_run_numbers = [45222]
+    run_numbers = [45222, 45223, 45224, 44984, 44985, 44990, 44991]
+    first_transmission_run_names = ['45226', '44988', '44986']
+    second_transmission_run_names = ['45227', '44989', '44987']
+    transmission_workspace_names = ['TRANS', 'TRANS_SM', 'TRANS_NoSM']
+    runs_file = 'INTERReductionTestRuns.nxs'
+    runs_workspace = 'Runs'
+    reference_result_file = 'INTERReductionResult.nxs'
+    result_workspace = 'Result'
+
+    def __init__(self):
+        super(INTERReductionTest, self).__init__()
+        self.tolerance = 0.00000001
+
+    def requiredFiles(self):
+        return [self.reference_result_file, self.runs_file]
+
+    def validate(self):
+        return (self.result_workspace, self.reference_result_file)
+
+    def runTest(self):
+        SetupInstrument()
+        Load(self.runs_file, OutputWorkspace=self.runs_workspace)
+        workspaces_to_exclude_from_result = AnalysisDataService.Instance().getObjectNames()
+        CreateTransmissionWorkspaces(self.first_transmission_run_names,
+                                     self.second_transmission_run_names,
+                                     self.transmission_workspace_names)
+
+        TestEventDataTimeSlicing(self.event_run_numbers)
+        TestReductionOfThreeAngleFringedSolidLiquidExample()
+        TestReductionOfTwoAngleAirLiquidExample()
+        TestFittingOfReducedData()
+
+        RemoveWorkspaces(workspaces_to_exclude_from_result)
+        GroupWorkspaces(InputWorkspaces=AnalysisDataService.Instance().getObjectNames(),
+                        OutputWorkspace=self.result_workspace)
+        mtd[self.result_workspace].sortByName()
+
+    @staticmethod
+    def regenerateRunsFile():
+        SetupInstrument()
+        RegenerateRunsFile(INTERReductionTest.first_transmission_run_names +
+                           INTERReductionTest.second_transmission_run_names,
+                           INTERReductionTest.run_numbers,
+                           INTERReductionTest.event_run_numbers)
+
+    @staticmethod
+    def regenerateReferenceFileByReducing():
+        SetupInstrument()
+        test = INTERReductionTest()
+        test.runTest()
+        SaveNexus(InputWorkspace=INTERReductionTest.result_workspace,
+                  Filename=INTERReductionTest.reference_result_file)
+
+    @staticmethod
+    def regenerateReferenceFileFromDirectory(reference_file_directory):
+        SetupInstrument()
+        RegenerateReferenceFile(reference_file_directory, INTERReductionTest.reference_result_file)
+
+
+def SetupInstrument():
+    configI = ConfigService.Instance()
+    configI.setString("default.instrument", "INTER")
+    configI.setString("default.facility", "ISIS")
+
+
+def RemoveWorkspaces(to_remove):
+    for workspace_name in to_remove:
+        AnalysisDataService.Instance().remove(workspace_name)
+
+
+def WorkspaceName(file_path):
+    return os.path.splitext(os.path.basename(file_path))[0]
+
+
+def RegenerateReferenceFile(reference_file_directory, output_filename):
+    files = os.listdir(reference_file_directory)
+    workspace_names = []
+    for file in files:
+        workspace_name = WorkspaceName(file)
+        Load(file, OutputWorkspace=workspace_name)
+        workspace_names.append(workspace_name)
+
+    output_workspace_name = 'Output'
+    GroupWorkspaces(InputWorkspaces=workspace_names, OutputWorkspace=output_workspace_name)
+    mtd[output_workspace_name].sortByName()
+    SaveNexus(InputWorkspace=output_workspace_name, Filename=output_filename)
+
+
+def RegenerateRunsFile(transmission_run_names, run_numbers, event_run_numbers):
+    "This is used to generate the test input file from a range of run numbers"
+    "and transmission runs."
+    # Load transmission runs
+    for run in transmission_run_names:
+        Load('{}.raw'.format(run), OutputWorkspace=run)
+    # Load raw run files
+    run_names = [str(run_number)+'.raw' for run_number in run_numbers]
+    for run_name in run_names:
+        Load(run_name, OutputWorkspace=run_name)
+    # Load event workspaces
+    event_run_names = [str(event_run_number) for event_run_number in event_run_numbers]
+    for event_run_name in event_run_names:
+        LoadEventNexus(event_run_name, OutputWorkspace=event_run_name, LoadMonitors=True)
+    event_monitor_names = [str(run_number)+'_monitors' for run_number in event_run_numbers]
+    # Group and save
+    GroupWorkspaces(InputWorkspaces=run_names + transmission_run_names + event_run_names +
+                    event_monitor_names,
+                    OutputWorkspace='Input')
+    SaveNexus(InputWorkspace='Input', Filename='INTERReductionTestRuns.nxs')
+
+
+def CreateTransmissionWorkspaces(runs1, runs2, output_names):
+    for run1, run2, name in zip(runs1, runs2, output_names):
+        CreateTransmissionWorkspaceAuto(
+            FirstTransmissionRun=run1,
+            SecondTransmissionRun=run2,
+            OutputWorkspace=name,
+            StartOverlap=10,
+            EndOverlap=12)
+        # Delete debug workspaces
+        DeleteWorkspace('TRANS_LAM_'+run1)
+        DeleteWorkspace('TRANS_LAM_'+run2)
+
+
+def EventRef(runno,angle,stop=0,start=0,DB='TRANS'):
+    '''Event data time-slicing'''
+    runno=str(runno)
+    w1=mtd[runno]
+    total = w1.getRun().getLogData('gd_prtn_chrg').value
+    end = w1.getRun().getLogData('duration').value
+    if stop==0:
+        stoptime=end
+    else:
+        stoptime=stop
+    FilterByTime(InputWorkspace=runno, OutputWorkspace=runno+'_filter', StartTime=start, StopTime=stoptime)
+    wt=mtd[runno+'_filter']
+    slice = wt.getRun().getLogData('gd_prtn_chrg').value
+    fraction = slice/total
+    duration = wt.getRun().getLogData('duration').value
+    print('Fraction:',fraction)
+    print('Slice:',slice)
+    print('Duration:',duration)
+
+    Scale(InputWorkspace=runno+'_monitors',Factor=fraction,OutputWorkspace='mon_slice')
+    Rebin(InputWorkspace=runno+'_filter', OutputWorkspace=runno+'_'+str(start)+'_'+str(stop), Params='0,100,100000', PreserveEvents=False)
+    Rebin(InputWorkspace='mon_slice', OutputWorkspace='mon_rebin', Params='0,100,100000', PreserveEvents=False)
+    AppendSpectra(InputWorkspace1='mon_rebin', InputWorkspace2=runno+'_'+str(start)+'_'+str(stop),
+                  OutputWorkspace=runno+'_'+str(start)+'_'+str(stop), MergeLogs=False)
+    ReflectometryReductionOneAuto(InputWorkspace=runno+'_'+str(start)+'_'+str(stop), FirstTransmissionRun=DB,
+                                  OutputWorkspaceBinned=runno+'_'+str(start)+'_'+str(stop)+'_ref_binned',
+                                  OutputWorkspace=runno+'_'+str(start)+'_'+str(stop)+'_ref',
+                                  OutputWorkspaceWavelength=runno+'_'+str(start)+'_'+str(stop)+'_lam',Debug=True)
+
+
+def QuickRef(runs=[], trans=[], angles=[]):
+    '''Use of "QuickRef" - scripted reduction'''
+    list=''
+    if not angles:
+        for i in range(len(runs)):
+            run1=runs[i]
+            trans1=trans[i]
+            ReflectometryReductionOneAuto(InputWorkspace=str(run1)+'.raw', FirstTransmissionRun=str(trans1),
+                                          OutputWorkspaceBinned=str(run1)+'_IvsQ_binned', OutputWorkspace=str(run1)+'_IvsQ',
+                                          OutputWorkspaceWavelength=str(run1)+'_IvsLam',Debug=True)
+            list=list+str(run1)+'_IvsQ_binned'+','
+    else:
+        for i in range(len(runs)):
+            run1=runs[i]
+            trans1=trans[i]
+            theta=angles[i]
+            if theta == 0.8:
+                ReflectometryReductionOneAuto(InputWorkspace=str(run1)+'.raw', FirstTransmissionRun=str(trans1),
+                                              OutputWorkspaceBinned=str(run1)+'_IvsQ_binned', OutputWorkspace=str(run1)+'_IvsQ',
+                                              OutputWorkspaceWavelength=str(run1)+'_IvsLam', ThetaIn=theta, WavelengthMin=2.6,Debug=True)
+            else:
+                ReflectometryReductionOneAuto(InputWorkspace=str(run1)+'.raw', FirstTransmissionRun=str(trans1),
+                                              OutputWorkspaceBinned=str(run1)+'_IvsQ_binned', OutputWorkspace=str(run1)+'_IvsQ',
+                                              OutputWorkspaceWavelength=str(run1)+'_IvsLam', ThetaIn=theta,Debug=True)
+            if i == len(runs)-1:
+                list=list+str(run1)+'_IvsQ_binned'
+            else:
+                list=list+str(run1)+'_IvsQ_binned'+','
+    runno2=str(runs[-1])
+    runno2=runno2[-2:]
+    dqq = NRCalculateSlitResolution(Workspace=str(runs[0])+'_IvsQ')
+    Stitch1DMany(InputWorkspaces=list, OutputWorkspace=str(runs[0])+'_'+str(runno2), Params='-'+str(dqq), ScaleRHSWorkspace=1)
+
+
+def twoangfit(run1,run2,scalefactor):
+    runno=str(run2)
+    runno=runno[-2:]
+    Scale(InputWorkspace=str(run1)+'_'+str(runno), OutputWorkspace=str(run1)+'_'+str(runno)+'_scaled', Factor=(1.0/scalefactor))
+    function_name='name=ReflectivityMulf,nlayer=1,Theta=2.3,ScaleFactor=1,AirSLD=0,BulkSLD=0,Roughness=0,BackGround=6.8e-06,'\
+        'Resolution=5.0,SLD_Layer0=1.0e-6,d_Layer0=20.0,Rough_Layer0=0.0,constraints=(0<SLD_Layer0,0<d_Layer0),'\
+        'ties=(Theta=2.3,AirSLD=0,BulkSLD=0,Resolution=5.0,ScaleFactor=1.0,Roughness=0,Rough_Layer0=0)'
+    Fit(Function=function_name,
+        InputWorkspace=str(run1)+'_'+str(runno)+'_scaled',IgnoreInvalidData='1',
+        Output=str(run1)+'_'+str(runno)+'_fit',OutputCompositeMembers='1',ConvolveMembers='1')
+    sld=round(mtd[str(run1)+'_'+str(runno)+'_fit_Parameters'].cell(7,1),9)
+    thick=round(mtd[str(run1)+'_'+str(runno)+'_fit_Parameters'].cell(8,1),2)
+    dNb=sld*thick
+    print('run ',str(run1))
+    print('dNb ',dNb)
+    print('SLD ',sld)
+    print('Thick ',thick)
+    print('-----------')
+
+
+def GenerateTimeSlices(run):
+    '''Generate 60sec time slices'''
+    grouped=''
+    for ii in range(5):
+        slice_name = str(run) + '_' + str(60*ii) + '_' + str(60*(ii+1))
+        EventRef(run,0.5,(ii+1)*60,ii*60,DB='TRANS')
+        grouped=grouped+', ' + slice_name + '_ref_binned'
+        DeleteWorkspace(slice_name+'_lam')
+        DeleteWorkspace(slice_name)
+        DeleteWorkspace(slice_name+'_ref')
+        DeleteWorkspace('mon_slice')
+        DeleteWorkspace('mon_rebin')
+
+
+def TestEventDataTimeSlicing(event_run_numbers):
+    for run in event_run_numbers:
+        GenerateTimeSlices(run)
+
+
+def TestReductionOfThreeAngleFringedSolidLiquidExample():
+    QuickRef([45222,45223,45224],['TRANS','TRANS','TRANS'])
+
+
+def TestReductionOfTwoAngleAirLiquidExample():
+    QuickRef([44984,44985],['TRANS_SM','TRANS_noSM'], angles=[0.8,2.3])
+
+
+def TestFittingOfReducedData():
+    #D2O run:
+    CloneWorkspace(InputWorkspace='44984_85', OutputWorkspace='D2O_IvsQ_binned')
+    #fit d2o to get scalefactor
+    function_name='name=ReflectivityMulf,nlayer=0,Theta=2.3,ScaleFactor=1.0,AirSLD=0,BulkSLD=6.35e-6,Roughness=2.5,'\
+        'BackGround=3.0776e-06,Resolution=5.0,ties=(Theta=2.3,AirSLD=0,BulkSLD=6.35e-6,Resolution=5.0,Roughness=2.5)'
+    Fit(Function=function_name,
+        InputWorkspace='D2O_IvsQ_binned',IgnoreInvalidData='1',Minimizer='Simplex',Output='D2O_fit',
+        OutputCompositeMembers='1',ConvolveMembers='1',StartX='0.0015',EndX='0.3359')
+    scalefactor=round(mtd['D2O_fit_Parameters'].cell(1,1),3)
+    #Create reduced workspace for test:
+    QuickRef([44990,44991],['TRANS_SM','TRANS_noSM'], angles=[0.8,2.3])
+    #Test fitting:
+    twoangfit(44990,44991,scalefactor)
+
+
+# If you want to re-run the test and save the result as a reference...
+#   INTERReductionTest.regenerateReferenceFileByReducing()
+
+# or
+# If you have workspaces in a folder to use as a reference...
+#   INTERReductionTest.regenerateReferenceFileFromDirectory("Path/To/Folder")
diff --git a/Testing/SystemTests/tests/analysis/reference/INTERReductionResult.nxs.md5 b/Testing/SystemTests/tests/analysis/reference/INTERReductionResult.nxs.md5
new file mode 100644
index 00000000000..c650cdee60d
--- /dev/null
+++ b/Testing/SystemTests/tests/analysis/reference/INTERReductionResult.nxs.md5
@@ -0,0 +1 @@
+5e6d14841469249a4754ca6c930a76f1
-- 
GitLab