Skip to content

Commit

Permalink
refs #5960. More robust cal generation.
Browse files Browse the repository at this point in the history
Can mask workspaces that are of type MaskingWorkspace. Updated to new python API. Unit test provided to cover new and existing functionality.
  • Loading branch information
OwenArnold committed Oct 17, 2012
1 parent 3b2eb30 commit 93424d9
Show file tree
Hide file tree
Showing 4 changed files with 174 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@ class InstrumentDefinitionParserTest : public CxxTest::TestSuite
std::string _instName;
};

ScopedFile createIDFFileObject(const std::string& idf_filename, const std::string& idf_file_contents)
{
const std::string instrument_dir = ConfigService::Instance().getInstrumentDirectory() + "/IDFs_for_UNIT_TESTING/";

return ScopedFile(idf_file_contents, idf_filename, instrument_dir);
}

/**
Helper method to create a pair of corresponding resource managed, IDF and VTP files.
*/
Expand Down Expand Up @@ -678,6 +685,41 @@ class InstrumentDefinitionParserTest : public CxxTest::TestSuite
remove( path.toString().c_str() );
}


void testIDFFile()
{
const std::string instrumentName = "Minimal_Definition";
const std::string idfFilename = instrumentName + ".xml";

const std::string idfFileContents = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
"<instrument name=\"" + instrumentName + "\" valid-from =\"1900-01-31 23:59:59\" valid-to=\"2100-01-31 23:59:59\" last-modified=\"2012-10-05 11:00:00\">"
"<defaults/>"
"<component type=\"cylinder-right\" idlist=\"cylinder-right\">"
"<location/>"
"</component>"
"<type name=\"cylinder-right\" is=\"detector\">"
"<cylinder id=\"some-shape\">"
" <centre-of-bottom-base r=\"0.0\" t=\"0.0\" p=\"0.0\" />"
" <axis x=\"0.0\" y=\"0.0\" z=\"1.0\" />"
" <radius val=\"0.01\" />"
" <height val=\"0.03\" />"
"</cylinder>"
"</type>"
"<idlist idname=\"cylinder-right\">"
"<id val=\"1\" />"
"</idlist>"
"</instrument>";

ScopedFile idfFile = createIDFFileObject(idfFilename, idfFileContents);


InstrumentDefinitionParser parser;
parser.initialize(idfFile.getFileName(), instrumentName, idfFileContents);
parser.parseXML(NULL);

// Do your tests here.
}

};

class InstrumentDefinitionParserTestPerformance : public CxxTest::TestSuite
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,19 @@
Creates a cal file from a mask workspace: the masked out detectors (Y == 0 in mask workspace) will be combined into group 0.
*WIKI*"""

import sys
from MantidFramework import *
from mantid.simpleapi import *
from mantid.api import *
#from mantid.kernel import *

class QueryFlag:
def isMasked(self, detector, yValue):
return detector.isMasked()

class QueryValue:
def isMasked(self, detector, yValue):
return yValue == 1

class MaskWorkspaceToCalFile(PythonAlgorithm):

Expand All @@ -16,20 +27,22 @@ def name(self):


def PyInit(self):
self.declareWorkspaceProperty("InputWorkspace", "", Direction = Direction.Input, Description = 'Input mask workspace')
self.declareFileProperty("OutputFile","", FileAction.Save, ['cal'],Description="The file to contain the results")
self.declareProperty(MatrixWorkspaceProperty("InputWorkspace", "", Direction.Input), "Input mask workspace")
self.declareProperty(FileProperty(name="OutputFile",defaultValue="",action=FileAction.Save,extensions=['cal']), "The file to contain the results")

self.declareProperty("Invert", False, Description="If True, masking is inverted in the input workspace. Default: False")

self.declareProperty("Invert", False, "If True, masking is inverted in the input workspace. Default: False")

def PyExec(self):
#extract settings
inputWorkspace = self.getProperty("InputWorkspace")
outputFileName = self.getProperty("OutputFile")
invert = self.getProperty("Invert")

inputWorkspace = mtd[self.getPropertyValue("InputWorkspace")]
outputFileName = self.getProperty("OutputFile").value
invert = self.getProperty("Invert").value
mask_query = QueryFlag()
if inputWorkspace.id() == "MaskWorkspace":
mask_query = QueryValue()

#check for consistency
if inputWorkspace.getNumberBins() < 1:
if len(inputWorkspace.readX(0)) < 1:
raise RuntimeError('The input workspace is empty.')

#define flags for masking and not-masking
Expand All @@ -48,7 +61,8 @@ def PyExec(self):
for i in range(inputWorkspace.getNumberHistograms()):
try:
det = inputWorkspace.getDetector(i)
if (det.isMasked()): #check if masked
y_value = inputWorkspace.readY(i)[0]
if (mask_query.isMasked(det, y_value)): #check if masked
group = masking_flag
else:
group = not_masking_flag
Expand All @@ -70,4 +84,4 @@ def FormatLine(self,number,UDET,offset,select,group):

#############################################################################################

mtd.registerPyAlgorithm(MaskWorkspaceToCalFile())
registerAlgorithm(MaskWorkspaceToCalFile())
19 changes: 18 additions & 1 deletion Code/Mantid/Framework/PythonAPI/src/api_exports.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#include <string>
#include <ostream>

// Kernel
#include "MantidKernel/DataItem.h"
// API
#include "MantidAPI/AlgorithmProperty.h"
#include "MantidAPI/FileFinder.h"
Expand Down Expand Up @@ -275,13 +277,26 @@ using namespace boost::python;
// Overloads for createSubAlgorithm function which has 1 optional argument
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(Workspace_isDirtyOverloader, API::Workspace::isDirty, 0, 1)

void export_dataitem()
{
REGISTER_SHARED_PTR_TO_PYTHON(Kernel::DataItem);

class_<Kernel::DataItem,boost::noncopyable>("DataItem", no_init)
.def("id", &Kernel::DataItem::id, "The string ID of the class")
.def("name", &Kernel::DataItem::name, "The name of the object")
.def("threadSafe", &Kernel::DataItem::threadSafe, "Returns true if the object can be accessed safely from multiple threads")
.def("__str__", &Kernel::DataItem::toString, "Returns a serialised version of the object")
;
}


//-----------------------------------------------------------------------------------------------
void export_workspace()
{
/// Shared pointer registration
register_ptr_to_python<boost::shared_ptr<Workspace> >();

class_<API::Workspace, boost::noncopyable>("Workspace", no_init)
class_<API::Workspace, bases<Kernel::DataItem>, boost::noncopyable>("Workspace", no_init)
.def("getTitle", &API::Workspace::getTitle,
return_value_policy< return_by_value >())
.def("setTitle", &API::Workspace::setTitle)
Expand All @@ -292,6 +307,7 @@ using namespace boost::python;
.def("getName", &API::Workspace::getName, return_value_policy< copy_const_reference >())
.def("__str__", &API::Workspace::getName, return_value_policy< copy_const_reference >())
.def("getHistory", &API::Workspace::getHistory, return_internal_reference<>())
.def("id", &API::Workspace::id)
;
}

Expand Down Expand Up @@ -964,6 +980,7 @@ using namespace boost::python;
{
export_frameworkmanager();
export_ialgorithm();
export_dataitem();
export_workspace();
export_matrixworkspace();
export_eventworkspace();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import unittest
import os
from mantid.kernel import *
from mantid.api import *
from mantid.simpleapi import *
from testhelpers import run_algorithm

class MaskWorkspaceToCalFileTest(unittest.TestCase):

def get_masking_for_index(self, cal_file, requested_index):
while True:
line = cal_file.readline()
if line == "":
raise LookupError
line_contents = line.split()
try:
index = int(line_contents[0].strip())
select = int(line_contents[3].strip())
group = int(line_contents[4].strip())
if(index == requested_index):
return select
except ValueError:
continue

def do_test_cal_file(self, masked_workspace, should_invert, expected_masking_identifier, expected_not_masking_identifier, masking_edge):
cal_filename = 'wish_masking_system_test_temp.cal'
cal_file_alg = run_algorithm('MaskWorkspaceToCalFile',InputWorkspace=masked_workspace.name(), OutputFile=cal_filename, Invert=should_invert, rethrow=True)

cal_file_full_path = str(cal_file_alg.getPropertyValue('OutputFile'))
file = open(cal_file_full_path, 'r')
try:
mask_boundary_inside = self.get_masking_for_index(file, masking_edge)
mask_boundary_outside = self.get_masking_for_index(file, masking_edge+1)
self.assertTrue(mask_boundary_inside == expected_masking_identifier)
self.assertTrue(mask_boundary_outside == expected_not_masking_identifier)
except LookupError:
print "Could not find the requested index"
self.assertTrue(False)
finally:
file.close()
os.remove(cal_file_full_path)

# Test creating a cal file from a masked MatrixWorkspace directly
def test_calfile_from_masked_workspace(self):
run_algorithm('Load', Filename='LOQ49886.nxs', OutputWorkspace='LOQ49886', rethrow=True)
run_algorithm('MaskDetectors', Workspace='LOQ49886',WorkspaceIndexList='0-700', MaskedWorkspace='LOQ49886', rethrow=True)
masked_workspace = mtd['LOQ49886']
should_invert = False
masking_identifier = 0
not_masking_identifier = 1
self.do_test_cal_file(masked_workspace, should_invert, masking_identifier, not_masking_identifier, 700)

# Test creating a cal file from a MaskWorkspace
def test_calfile_from_extracted_masking_workspace(self):
run_algorithm('Load', Filename='LOQ49886.nxs', OutputWorkspace='LOQ49886', rethrow=True)
run_algorithm('MaskDetectors', Workspace='LOQ49886',WorkspaceIndexList='0-700', MaskedWorkspace='LOQ49886', rethrow=True)
run_algorithm('ExtractMask', InputWorkspace='LOQ49886', OutputWorkspace='ExtractedWorkspace', rethrow=True)
extracted_workspace = mtd['ExtractedWorkspace']
should_invert = False
masking_identifier = 0
not_masking_identifier = 1
self.do_test_cal_file(extracted_workspace, should_invert, masking_identifier, not_masking_identifier, 700)

# Test creating a cal file from a MatrixWorkspace directly with masking inverted
def test_calfile_from_masked_workspace_inverse(self):
run_algorithm('Load', Filename='LOQ49886.nxs', OutputWorkspace='LOQ49886', rethrow=True)
run_algorithm('MaskDetectors', Workspace='LOQ49886',WorkspaceIndexList='0-700', MaskedWorkspace='LOQ49886', rethrow=True)
masked_workspace = mtd['LOQ49886']
should_invert = True
masking_identifier = 1
not_masking_identifier = 0
self.do_test_cal_file(masked_workspace, should_invert, masking_identifier, not_masking_identifier, 700)

# Test creating a cal file from a MaskWorkspace with masking inverted
def test_calfile_from_extracted_masking_workspace_inverse(self):
run_algorithm('Load', Filename='LOQ49886.nxs', OutputWorkspace='LOQ49886', rethrow=True)
run_algorithm('MaskDetectors', Workspace='LOQ49886',WorkspaceIndexList='0-700', MaskedWorkspace='LOQ49886', rethrow=True)
run_algorithm('ExtractMask', InputWorkspace='LOQ49886', OutputWorkspace='ExtractedWorkspace', rethrow=True)
extracted_workspace = mtd['ExtractedWorkspace']
should_invert = True
masking_identifier = 1
not_masking_identifier = 0
self.do_test_cal_file(extracted_workspace, should_invert, masking_identifier, not_masking_identifier, 700)



if __name__ == '__main__':
unittest.main()

0 comments on commit 93424d9

Please sign in to comment.