Skip to content

Commit

Permalink
MaskBTP and CorrectLogTimes algorithms. Refs #8626
Browse files Browse the repository at this point in the history
  • Loading branch information
AndreiSavici committed Dec 23, 2013
1 parent bfc883e commit f46c7b2
Show file tree
Hide file tree
Showing 5 changed files with 343 additions and 0 deletions.
@@ -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)
171 changes: 171 additions & 0 deletions 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)
Expand Up @@ -5,6 +5,7 @@
set ( TEST_PY_FILES
CheckForSampleLogsTest.py
ConjoinSpectraTest.py
CorrectLogTimesTest.py
CreateLeBailFitInputTest.py
CreateWorkspaceTest.py
CreateTransmissionWorkspaceTest.py
Expand All @@ -16,6 +17,7 @@ set ( TEST_PY_FILES
LoadLogPropertyTableTest.py
LoadMultipleGSSTest.py
MaskAngleTest.py
MaskBTPTest.py
MaskWorkspaceToCalFileTest.py
MeanTest.py
MergeCalFilesTest.py
Expand Down
@@ -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()
@@ -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()

0 comments on commit f46c7b2

Please sign in to comment.