diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/CorrectLogTimes.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/CorrectLogTimes.py new file mode 100644 index 000000000000..b45b8f0b0a37 --- /dev/null +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/CorrectLogTimes.py @@ -0,0 +1,69 @@ +""" +Sometimes the clocks controlling different sample environments or other experimental log values are not synchronized. +This algorithm attempts to make all (some) time series property logs start at the same time as the first time in the proton charge log. +""" + +import mantid.simpleapi +import mantid.api +import mantid.kernel +import numpy + +class CorrectLogTimes(mantid.api.PythonAlgorithm): + """ Class to shift log times to match proton charge + """ + + def category(self): + """ Mantid required + """ + return "PythonAlgorithms;DataHandling\\Logs" + + def name(self): + """ Mantid required + """ + return "CorrectLogTimes" + + + def PyInit(self): + self.declareProperty(mantid.api.WorkspaceProperty("Workspace", "",direction=mantid.kernel.Direction.InOut), "Input workspace") + self.declareProperty("LogNames","",doc="Experimental og values to be shifted. If empty, will attempt to shift all logs") + + def PyExec(self): + self.ws = self.getProperty("Workspace").value + logNames = self.getProperty("LogNames").value + + logList=[] + + #check for parameters and build the result string + for value in logNames.split(','): + value=value.strip() + if len(value)>0: + if not self.ws.run().hasProperty(value): + err = 'Property '+value+' not found' + raise ValueError(err) + else: + logList.append(value) + + + if len(logList)==0: + logList=self.ws.getRun().keys() + + for x in logList: + if x not in ['duration','proton_charge','start_time','run_title','run_start','run_number','gd_prtn_chrg','end_time']: + try: + self.ShiftTime(x) + except: + pass + + + def ShiftTime(self, logName): + """ + shift the time in a given log to match the time in the proton charge log" + """ + PC = self.ws.getRun()['proton_charge'].firstTime() + P = self.ws.getRun()[logName].firstTime() + Tdiff = PC-P + Tdiff_num = Tdiff.total_milliseconds()*1E-3 + mantid.simpleapi.ChangeLogTime(InputWorkspace=self.ws, OutputWorkspace = self.ws, LogName = logName, TimeOffset = Tdiff_num) + + +mantid.api.AlgorithmFactory.subscribe(CorrectLogTimes) diff --git a/Code/Mantid/Framework/PythonInterface/plugins/algorithms/MaskBTP.py b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/MaskBTP.py new file mode 100644 index 000000000000..b003f3f06077 --- /dev/null +++ b/Code/Mantid/Framework/PythonInterface/plugins/algorithms/MaskBTP.py @@ -0,0 +1,171 @@ +""" +Algorithm to mask detectors in particular banks, tube, or pixels. It applies to the following instruments only: ARCS, CNCS, HYSPEC, SEQUOIA. +If one of Bank, Tube, Pixel entries is left blank, it will apply to all elements of that type. For example: + +MaskBTP(w,Bank = "1") will completely mask all tubes and pixels in bank 1. +MaskBTP(w,Pixel = "1,2") will mask all pixels 1 and 2, in all tubes, in all banks. + +The algorithm allows ranged inputs: Pixel = "1-8,121-128" is equivalent to Pixel = "1,2,3,4,5,6,7,8,121,122,123,124,125,126,127,128" + +Either the input workspace or the instrument must be set + +""" + +import mantid.simpleapi +import mantid.api +import mantid.kernel +import numpy + +class MaskBTP(mantid.api.PythonAlgorithm): + """ Class to generate grouping file + """ + + def category(self): + """ Mantid required + """ + return "PythonAlgorithms;Transforms\\Masking;Inelastic" + + def name(self): + """ Mantid require + """ + return "MaskBTP" + + + def PyInit(self): + self.declareProperty(mantid.api.WorkspaceProperty("Workspace", "",direction=mantid.kernel.Direction.InOut, optional = mantid.api.PropertyMode.Optional), "Input workspace (optional)") + allowedInstrumentList=mantid.kernel.StringListValidator(["","ARCS","CNCS","HYSPEC","SEQUOIA"]) + self.declareProperty("Instrument","",validator=allowedInstrumentList,doc="One of the following instruments: ARCS, CNCS, HYSPEC, SEQUOIA") + self.declareProperty("Bank","",doc="Bank(s) to be masked. If empty, will apply to all banks") + self.declareProperty("Tube","",doc="Tube(s) to be masked. If empty, will apply to all tubes") + self.declareProperty("Pixel","",doc="Pixel(s) to be masked. If empty, will apply to all pixels") + self.declareProperty(mantid.kernel.IntArrayProperty(name="MaskedDetectors", direction=mantid.kernel.Direction.Output), doc="List of masked detectors") + + + def PyExec(self): + ws = self.getProperty("Workspace").value + self.instrument=None + self.instname = self.getProperty("Instrument").value + bankString = self.getProperty("Bank").value + tubeString = self.getProperty("Tube").value + pixelString = self.getProperty("Pixel").value + + if self.instname == "" and ws == None: + raise ValueError("No workspace or instrument were selected" ) + + if ws != None: + self.instrument = ws.getInstrument() + self.instname = self.instrument.getName() + + instrumentList=["ARCS","CNCS","HYSPEC","SEQUOIA"] + try: + instrumentList.index(self.instname) + except: + raise ValueError("Instrument "+self.instname+" not in the allowed list") + + if (self.instrument==None): + IDF=mantid.api.ExperimentInfo.getInstrumentFilename(self.instname) + ws=mantid.simpleapi.LoadEmptyInstrument(IDF,OutputWorkspace=self.instname+"MaskBTP") + self.instrument=ws.getInstrument() + + if (bankString == ""): + if (self.instname == "ARCS"): + banks=numpy.arange(115)+1 + elif (self.instname == "CNCS"): + banks=numpy.arange(50)+1 + elif (self.instname == "HYSPEC"): + banks=numpy.arange(20)+1 + elif (self.instname == "SEQUOIA"): + banks=numpy.arange(113)+38 + else: + banks=self._parseBTPlist(bankString) + + if (tubeString == ""): + tubes=numpy.arange(8)+1 + else: + tubes=self._parseBTPlist(tubeString) + + if(pixelString == ""): + pixels=numpy.arange(128)+1 + else: + pixels=self._parseBTPlist(pixelString) + + + + detlist=[] + for b in banks: + ep=self._getEightPackHandle(b) + for t in tubes: + if ((t<1) or (t>8)): + raise ValueError("Out of range index for tube number") + else: + for p in pixels: + if ((p<1) or (p>128)): + raise ValueError("Out of range index for pixel number") + else: + pid=ep[int(t-1)][int(p-1)].getID() + detlist.append(pid) + if len(detlist)> 0: + mantid.simpleapi.MaskDetectors(Workspace=ws,DetectorList=detlist) + else: + self.log().information("no detectors within this range") + self.setProperty("MaskedDetectors", numpy.array(detlist)) + + def _parseBTPlist(self,value): + """ + Helper function to transform a string into a list of integers + For example "1,2-4,8-10" will become [1,2,3,4,8,9,10] + It will deal with lists as well, so range(1,4) will still be [1,2,3] + """ + parsed = [] + #split the commas + parts = str(value).strip(']').strip('[').split(',') + #now deal with the hyphens + for p in parts: + if len(p) > 0: + elem = p.split("-") + if len(elem) == 1: + parsed.append(int(elem[0])) + if len(elem) == 2: + startelem = int(elem[0]) + endelem = int(elem[1]) + if endelem < startelem: + raise ValueError("The element after the hyphen needs to be greater or equal than the first element") + elemlist = range(startelem,endelem+1) + parsed.extend(elemlist) + return parsed + + def _getEightPackHandle(self,banknum): + """ + Helper function to return the handle to a given eightpack + """ + banknum=int(banknum) + if self.instname=="ARCS": + if (1<=banknum<= 38): + return self.instrument[3][banknum-1][0] + elif(39<=banknum<= 77): + return self.instrument[4][banknum-39][0] + elif(78<=banknum<=115): + return self.instrument[5][banknum-78][0] + else: + raise ValueError("Out of range index for ARCS instrument bank numbers") + elif self.instname=="CNCS": + if (1<=banknum<= 50): + return self.instrument[3][banknum-1][0] + else: + raise ValueError("Out of range index for CNCS instrument bank numbers") + elif self.instname=="HYSPEC": + if (1<=banknum<= 20): + return self.instrument[3][banknum-1][0] + else: + raise ValueError("Out of range index for HYSPEC instrument bank numbers") + elif self.instname=="SEQUOIA": + if (38<=banknum<= 74): + return self.instrument[3][banknum-38][0] + elif(75<=banknum<= 113): + return self.instrument[4][banknum-75][0] + elif(114<=banknum<=150): + return self.instrument[5][banknum-114][0] + else: + raise ValueError("Out of range index for SEQUOIA instrument bank numbers") + +mantid.api.AlgorithmFactory.subscribe(MaskBTP) diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt index 786892b0038d..a8a3f3299356 100644 --- a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt @@ -5,6 +5,7 @@ set ( TEST_PY_FILES CheckForSampleLogsTest.py ConjoinSpectraTest.py + CorrectLogTimesTest.py CreateLeBailFitInputTest.py CreateWorkspaceTest.py CreateTransmissionWorkspaceTest.py @@ -16,6 +17,7 @@ set ( TEST_PY_FILES LoadLogPropertyTableTest.py LoadMultipleGSSTest.py MaskAngleTest.py + MaskBTPTest.py MaskWorkspaceToCalFileTest.py MeanTest.py MergeCalFilesTest.py diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CorrectLogTimesTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CorrectLogTimesTest.py new file mode 100644 index 000000000000..bfef172f442f --- /dev/null +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/CorrectLogTimesTest.py @@ -0,0 +1,36 @@ +import unittest +from mantid.simpleapi import * +from mantid.api import * +from testhelpers import * +from numpy import * + +class CorrectLogTimesTest(unittest.TestCase): + + def testCLTWrongLog(self): + w=Load('CNCS_7860_event.nxs') + + try: + CorrectLogTimes(Workspace=w,LogNames="s1") + self.fail("Should not have got here. Should throw because wrong instrument.") + except RuntimeError: + pass + finally: + DeleteWorkspace(w) + + def testCLTsingle(self): + w=Load('CNCS_7860_event.nxs') + self.assertFalse(w.getRun()['proton_charge'].firstTime()==w.getRun()['Speed4'].firstTime()) + CorrectLogTimes(Workspace=w,LogNames="Speed4") + self.assertTrue(w.getRun()['proton_charge'].firstTime()==w.getRun()['Speed4'].firstTime()) + self.assertFalse(w.getRun()['proton_charge'].firstTime()==w.getRun()['Speed5'].firstTime()) + DeleteWorkspace(w) + + def testCLTall(self): + w=Load('CNCS_7860_event.nxs') + self.assertFalse(w.getRun()['proton_charge'].firstTime()==w.getRun()['Speed4'].firstTime()) + CorrectLogTimes(Workspace=w,LogNames="") + self.assertTrue(w.getRun()['proton_charge'].firstTime()==w.getRun()['Speed4'].firstTime()) + self.assertTrue(w.getRun()['proton_charge'].firstTime()==w.getRun()['Speed5'].firstTime()) + DeleteWorkspace(w) +if __name__ == '__main__': + unittest.main() diff --git a/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/MaskBTPTest.py b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/MaskBTPTest.py new file mode 100644 index 000000000000..6189f4931421 --- /dev/null +++ b/Code/Mantid/Framework/PythonInterface/test/python/plugins/algorithms/MaskBTPTest.py @@ -0,0 +1,65 @@ +import unittest +from mantid.simpleapi import * +from mantid.api import * +from testhelpers import * +from numpy import * + +class MaskBTPTest(unittest.TestCase): + + def testMaskBTPWrongInstrument(self): + w=WorkspaceCreationHelper.create2DWorkspaceWithFullInstrument(30,5,False,False) + AnalysisDataService.add('w',w) + try: + masklist = MaskBTP(Workspace=w,Pixel="1") + self.fail("Should not have got here. Should throw because wrong instrument.") + except RuntimeError: + pass + finally: + DeleteWorkspace(w) + + def testMaskBTPWrongLimits(self): + try: + MaskBTP(Instrument='ARCS', Pixel="129") + self.fail("Should not have got here.") + except RuntimeError: + pass + try: + MaskBTP(Instrument='SEQUOIA', Bank="1") + self.fail("Should not have got here.") + except RuntimeError: + pass + try: + MaskBTP(Instrument='HYSPEC', Tube="18") + self.fail("Should not have got here.") + except RuntimeError: + pass + DeleteWorkspace("ARCSMaskBTP") + DeleteWorkspace("HYSPECMaskBTP") + DeleteWorkspace("SEQUOIAMaskBTP") + + def testMaskBTP(self): + m1=MaskBTP(Instrument='CNCS', Pixel="1-3,5") + m2=MaskBTP(Workspace='CNCSMaskBTP', Bank="1-2") + m3=MaskBTP(Workspace='CNCSMaskBTP', Bank='5-7', Tube='3') + p1=arange(400)*128 + m1p=sort(concatenate((p1,p1+1,p1+2,p1+4))) + self.assertTrue(array_equal(m1,m1p)) + self.assertTrue(array_equal(m2,arange(2048))) + b5t3=arange(128)+4*1024+2*128 + self.assertTrue(array_equal(m3,concatenate((b5t3,b5t3+1024,b5t3+2048)))) + #check whether some pixels are masked when they should + w=mtd['CNCSMaskBTP'] + self.assertTrue(w.getInstrument().getDetector(29696).isMasked()) #pixel1 + self.assertTrue(w.getInstrument().getDetector(29697).isMasked()) #pixel2 + self.assertTrue(w.getInstrument().getDetector(29698).isMasked()) #pixel3 + self.assertTrue(not w.getInstrument().getDetector(29699).isMasked()) #pixel4 + self.assertTrue(w.getInstrument().getDetector(29700).isMasked()) #pixel5 + + self.assertTrue(w.getInstrument().getDetector(1020).isMasked()) #bank 1 + self.assertTrue(not w.getInstrument().getDetector(3068).isMasked()) #bank3, tube 8 + + self.assertTrue(w.getInstrument().getDetector(4400).isMasked()) #bank5, tube 3 + DeleteWorkspace(w) + +if __name__ == '__main__': + unittest.main()