@@ -0,0 +1,333 @@
/*WIKI*
TODO: Enter a full wiki-markup description of your algorithm here. You can then use the Build/wiki_maker.py script to generate your full wiki page.
*WIKI*/

#include "MantidAPI/IMDEventWorkspace.h"
#include "MantidAPI/IMDWorkspace.h"
#include "MantidKernel/Strings.h"
#include "MantidKernel/System.h"
#include "MantidMDAlgorithms/CompareMDWorkspaces.h"
#include "MantidMDEvents/MDHistoWorkspace.h"
#include "MantidGeometry/MDGeometry/IMDDimension.h"
#include "MantidMDEvents/MDEventFactory.h"

using namespace Mantid::Kernel;
using namespace Mantid::API;
using namespace Mantid::MDEvents;
using namespace Mantid::Geometry;

/** Custom exception class to signal a failure
* in the comparison
*/
class CompareFailsException
{
public:
CompareFailsException(const std::string& msg) : msg_(msg) {}
~CompareFailsException( ) {}
std::string getMessage( ) const {return(msg_);}
private:
std::string msg_;
};


namespace Mantid
{
namespace MDAlgorithms
{

// Register the algorithm into the AlgorithmFactory
DECLARE_ALGORITHM(CompareMDWorkspaces)



//----------------------------------------------------------------------------------------------
/** Constructor
*/
CompareMDWorkspaces::CompareMDWorkspaces()
{
}

//----------------------------------------------------------------------------------------------
/** Destructor
*/
CompareMDWorkspaces::~CompareMDWorkspaces()
{
}


//----------------------------------------------------------------------------------------------
/// Algorithm's name for identification. @see Algorithm::name
const std::string CompareMDWorkspaces::name() const { return "CompareMDWorkspaces";};

/// Algorithm's version for identification. @see Algorithm::version
int CompareMDWorkspaces::version() const { return 1;};

/// Algorithm's category for identification. @see Algorithm::category
const std::string CompareMDWorkspaces::category() const { return "MDAlgorithms";}

//----------------------------------------------------------------------------------------------
/// Sets documentation strings for this algorithm
void CompareMDWorkspaces::initDocs()
{
this->setWikiSummary("Compare two MDWorkspaces for equality.");
this->setOptionalMessage("Compare two MDWorkspaces for equality.");
}

//----------------------------------------------------------------------------------------------
/** Initialize the algorithm's properties.
*/
void CompareMDWorkspaces::init()
{
declareProperty(new WorkspaceProperty<IMDWorkspace>("Workspace1","",Direction::Input),
"First MDWorkspace to compare.");
declareProperty(new WorkspaceProperty<IMDWorkspace>("Workspace2","",Direction::Output),
"Second MDWorkspace to compare.");

declareProperty("Tolerance",0.0,
"The maximum amount by which values may differ between the workspaces.");
declareProperty("CheckEvents",true,
"Whether to compare each MDEvent. If False, will only look at the box structure.");

declareProperty(new PropertyWithValue<std::string>("Result","",Direction::Output),
"String describing the difference found between the workspaces");
declareProperty(new PropertyWithValue<bool>("Equals",false,Direction::Output),
"Boolean set to true if the workspaces match.");
}

//----------------------------------------------------------------------------------------------
/** Return a string "(a vs b)". */
template<typename T>
std::string versus(T a, T b)
{
return "(" + Strings::toString(a) + " vs " + Strings::toString(b) + ")";
}

//----------------------------------------------------------------------------------------------
/** Compare a and b. Throw if they dont match
*
* @param a :: any type
* @param b :: any type
* @param message :: message for result
* @throw CompareFailsException if the two DONT match
*/
template<typename T>
void CompareMDWorkspaces::compare(T a, T b, const std::string & message)
{
if (a != b)
throw CompareFailsException(message + " " + versus(a,b) );
}

//----------------------------------------------------------------------------------------------
/** Compare a and b. Throw if they dont match within Tolerance
*
* @param a :: double
* @param b :: double
* @param message :: message for result
* @throw CompareFailsException if the two DONT match
*/
void CompareMDWorkspaces::compareTol(double a, double b, const std::string & message)
{
double diff = fabs(a-b);
if (diff > m_tolerance)
throw CompareFailsException(message + " " + versus(a,b) );
}


//----------------------------------------------------------------------------------------------
/** Compare the dimensions etc. of two MDWorkspaces
*/
void CompareMDWorkspaces::compareMDGeometry(Mantid::API::IMDWorkspace_sptr ws1, Mantid::API::IMDWorkspace_sptr ws2)
{
compare(ws1->getNumDims(), ws2->getNumDims(), "Workspaces have a different number of dimensions");
for (size_t d=0; d<ws1->getNumDims(); d++)
{
IMDDimension_const_sptr dim1 = ws1->getDimension(d);
IMDDimension_const_sptr dim2 = ws2->getDimension(d);
compare(dim1->getName(), dim2->getName(), "Dimension #" + Strings::toString(d) + " has a different name");
compare(dim1->getUnits(), dim2->getUnits(), "Dimension #" + Strings::toString(d) + " has different units");
compare(dim1->getNBins(), dim2->getNBins(), "Dimension #" + Strings::toString(d) + " has a different number of bins");
compareTol(dim1->getMinimum(), dim2->getMinimum(), "Dimension #" + Strings::toString(d) + " has a different minimum");
compareTol(dim1->getMaximum(), dim2->getMaximum(), "Dimension #" + Strings::toString(d) + " has a different maximum");
// TODO? Compare origin and transforms?
}
}

//----------------------------------------------------------------------------------------------
/** Compare the dimensions etc. of two MDWorkspaces
*/
void CompareMDWorkspaces::compareMDHistoWorkspaces(Mantid::MDEvents::MDHistoWorkspace_sptr ws1, Mantid::MDEvents::MDHistoWorkspace_sptr ws2)
{
compare(ws1->getNumDims(), ws2->getNumDims(), "Workspaces have a different number of dimensions");
compare(ws1->getNPoints(), ws2->getNPoints(), "Workspaces have a different number of points");
for (size_t i = 0; i < ws1->getNPoints(); i++)
{
double diff = fabs(ws1->getSignalAt(i)- ws2->getSignalAt(i));
if (diff > m_tolerance)
throw CompareFailsException("MDHistoWorkspaces have a different signal at index "
+ Strings::toString(i) + " " + versus(ws1->getSignalAt(i), ws2->getSignalAt(i)) );

double diffErr = fabs(ws1->getErrorAt(i)- ws2->getErrorAt(i));
if (diffErr > m_tolerance)
throw CompareFailsException("MDHistoWorkspaces have a different error at index "
+ Strings::toString(i) + " " + versus(ws1->getErrorAt(i), ws2->getErrorAt(i)) );
}
}


//----------------------------------------------------------------------------------------------
/** Perform the comparison on MDEventWorkspaces
*
* @param ws :: MDEventWorkspace to compare
*/
template<typename MDE, size_t nd>
void CompareMDWorkspaces::compareMDWorkspaces(typename MDEventWorkspace<MDE, nd>::sptr ws)
{
typename MDEventWorkspace<MDE, nd>::sptr ws1 = ws;
typename MDEventWorkspace<MDE, nd>::sptr ws2 = boost::dynamic_pointer_cast<MDEventWorkspace<MDE, nd> >(inWS2);
if (!ws1 || !ws2)
throw std::runtime_error("Incompatible workspace types passed to PlusMD.");

std::vector<IMDBox<MDE,nd>*> boxes1;
std::vector<IMDBox<MDE,nd>*> boxes2;

ws1->getBox()->getBoxes(boxes1, 1000, false);
ws2->getBox()->getBoxes(boxes2, 1000, false);

this->compare(boxes1.size(), boxes2.size(), "Workspaces do not have the same number of boxes");

for (size_t j=0; j<boxes1.size(); j++)
{
IMDBox<MDE,nd>* box1 = boxes1[j];
IMDBox<MDE,nd>* box2 = boxes2[j];

this->compare( box1->getId(), box2->getId(), "Boxes have different ID" );
this->compare( box1->getDepth(), box2->getDepth(), "Boxes are at a different depth" );
this->compare( box1->getNumChildren(), box2->getNumChildren(), "Boxes do not have the same number of children");
for (size_t i=0; i<box1->getNumChildren(); i++)
this->compare( box1->getChild(i)->getId(), box2->getChild(i)->getId(), "Child of boxes do not match IDs" );

for (size_t d=0; d<nd; d++)
{
this->compareTol( box1->getExtents(d).min, box2->getExtents(d).min, "Extents of box do not match");
this->compareTol( box1->getExtents(d).max, box2->getExtents(d).max, "Extents of box do not match");
}
this->compareTol( box1->getVolume(), box2->getVolume(), "Box volume does not match");
this->compareTol( box1->getSignal(), box2->getSignal(), "Box signal does not match");
this->compareTol( box1->getErrorSquared(), box2->getErrorSquared(), "Box error squared does not match");
if (m_CheckEvents)
this->compare( box1->getNPoints(), box2->getNPoints(), "Number of points in box does not match" );

// Are both MDGridBoxes ?
MDGridBox<MDE,nd>* gridbox1 = dynamic_cast<MDGridBox<MDE,nd>*>(box1);
MDGridBox<MDE,nd>* gridbox2 = dynamic_cast<MDGridBox<MDE,nd>*>(box2);
if (gridbox1)
{
for (size_t d=0; d<nd; d++)
this->compareTol( gridbox1->getBoxSize(d), gridbox2->getBoxSize(d), "Box sizes do not match");
}

// Are both MDBoxes (with events)
MDBox<MDE,nd>* mdbox1 = dynamic_cast<MDBox<MDE,nd>*>(box1);
MDBox<MDE,nd>* mdbox2 = dynamic_cast<MDBox<MDE,nd>*>(box2);
if (mdbox1 && mdbox2)
{
if (m_CheckEvents)
{
const std::vector<MDE > & events1 = mdbox1->getConstEvents();
const std::vector<MDE > & events2 = mdbox2->getConstEvents();
this->compare( events1.size(), events2.size(), "Box event vectors are not the same length" );
if (events1.size() == events2.size() && events1.size() > 2)
{
// Check first and last event
for (size_t i=0; i<events1.size(); i+=events1.size()-1)
{
for (size_t d=0; d<nd; d++)
{
this->compareTol( events1[i].getCenter(d), events2[i].getCenter(d), "Event center does not match");
}
this->compareTol( events1[i].getSignal(), events2[i].getSignal(), "Event signal does not match");
this->compareTol( events1[i].getErrorSquared(), events2[i].getErrorSquared(), "Event error does not match");
}
}
mdbox1->releaseEvents();
mdbox2->releaseEvents();
}// Don't compare if BoxStructureOnly
} // is mdbox1
}


}

//----------------------------------------------------------------------------------------------
/** Perform comparison, set m_result if not matching.
*/
void CompareMDWorkspaces::doComparison()
{
m_tolerance = getProperty("Tolerance");
m_CheckEvents = getProperty("CheckEvents");

IMDWorkspace_sptr ws1 = getProperty("Workspace1");
IMDWorkspace_sptr ws2 = getProperty("Workspace2");
inWS2 = ws2;
if (!ws1 || !ws2)
throw std::invalid_argument("Invalid workspace given.");

MatrixWorkspace_sptr mws1 = boost::dynamic_pointer_cast<MatrixWorkspace>(ws1);
MatrixWorkspace_sptr mws2 = boost::dynamic_pointer_cast<MatrixWorkspace>(ws2);
if (mws1 || mws2)
throw std::invalid_argument("Cannot compare MatrixWorkspaces. Please use CheckWorkspacesMatch algorithm instead.");

MDHistoWorkspace_sptr histo1 = boost::dynamic_pointer_cast<MDHistoWorkspace>(ws1);
MDHistoWorkspace_sptr histo2 = boost::dynamic_pointer_cast<MDHistoWorkspace>(ws2);
IMDEventWorkspace_sptr event1 = boost::dynamic_pointer_cast<IMDEventWorkspace>(ws1);
IMDEventWorkspace_sptr event2 = boost::dynamic_pointer_cast<IMDEventWorkspace>(ws2);

try
{
compare(ws1->id(), ws2->id(), "Workspaces are of different types");

this->compareMDGeometry(ws1, ws2);

if (histo1 && histo2)
{
this->compareMDHistoWorkspaces(histo1, histo2);
}
else if (event1 && event2)
{
CALL_MDEVENT_FUNCTION(this->compareMDWorkspaces, event1);
}
else
m_result = "Workspaces are of different types.";
}
catch (CompareFailsException & e)
{
m_result = e.getMessage();
}
}

//----------------------------------------------------------------------------------------------
/** Execute the algorithm.
*/
void CompareMDWorkspaces::exec()
{
m_result.clear();
this->doComparison();

if ( m_result != "")
{
g_log.notice() << "The workspaces did not match: " << m_result << std::endl;
this->setProperty("Equals", false);
}
else
{
m_result = "Success!";
this->setProperty("Equals", true);
}
setProperty("Result",m_result);

}



} // namespace Mantid
} // namespace MDAlgorithms
@@ -189,8 +189,10 @@ ConvertToMDEvents::init()


declareProperty(new ArrayProperty<std::string>("OtherDimensions",Direction::Input),
" List(comma separated) of additional to Q (orthogonal) dimensions in the target workspace.\n"
" The names of these dimensions have to coinside with the log names in the source workspace");
" List(comma separated) of additional to Q and DeltaE variables which form additional (orthogonal) to Q dimensions"
" in the target workspace (e.g. Temperature or Magnetic field).\n"
" These variables had to be logged during experiment and the names of these variables "
" have to coincide with the log names for the records of these variables in the source workspace");

// this property is mainly for subalgorithms to set-up as they have to identify if they use the same instrument.
declareProperty(new PropertyWithValue<bool>("UsePreprocessedDetectors", true, Direction::Input),
@@ -223,7 +225,15 @@ ConvertToMDEvents::init()

// Box controller properties. These are the defaults
this->initBoxControllerProps("5" /*SplitInto*/, 1500 /*SplitThreshold*/, 20 /*MaxRecursionDepth*/);
// additional box controller settings property.
declareProperty(
new PropertyWithValue<int>("MinRecursionDepth", 0),
"Optional. If specified, then all the boxes will be split to this minimum recursion depth. 0 = no splitting, 1 = one level of splitting, etc.\n"
"Be careful using this since it can quickly create a huge number of boxes = (SplitInto ^ (MinRercursionDepth * NumDimensions)).\n"
"But setting this property equal to MaxRecursionDepth property is necessary if one wants to generate multiple file based workspaces in order to merge them later\n");
setPropertyGroup("MinRecursionDepth", getBoxSettingsGroupName());


}

//----------------------------------------------------------------------------------------------
@@ -315,7 +325,11 @@ void ConvertToMDEvents::exec()
// Build up the box controller, using the properties in BoxControllerSettingsAlgorithm
this->setBoxController(bc);
// split boxes;
pWSWrapper->pWorkspace()->splitBox();
spws->splitBox();
// Do we split more due to MinRecursionDepth?
int minDepth = this->getProperty("MinRecursionDepth");
if (minDepth<0) throw std::invalid_argument("MinRecursionDepth must be >= 0.");
spws->setMinRecursionDepth(size_t(minDepth));
}

// call selected algorithm
@@ -655,6 +669,7 @@ ConvertToMDEvents::identifyTheAlg(API::MatrixWorkspace_const_sptr inWS,const std
TargWSDescription.dim_names = dim_IDs_requested;
TargWSDescription.dim_IDs = dim_IDs_requested;
TargWSDescription.dim_units = dim_units_requested;
TargWSDescription.AlgID = the_algID;

// build meaningfull dimension names for Q-transformation if it is Q-transformation indeed
this->buildDimNames(TargWSDescription);
@@ -751,7 +766,7 @@ void ConvertToMDEvents::buildDimNames(MDEvents::MDWSDescription &TargWSDescripti
if(TargWSDescription.emode<0)return;

// Q3D mode needs special treatment for dimension names:
if(TargWSDescription.dim_IDs[0].find(Q_modes[Q3D])!=std::string::npos){
if(TargWSDescription.AlgID.find(Q_modes[Q3D])!=std::string::npos){
std::vector<Kernel::V3D> dim_directions(3);
dim_directions[0]=TargWSDescription.u;
dim_directions[1]=TargWSDescription.v;
@@ -21,6 +21,7 @@ See also: [[MergeMDFiles]], for merging when system memory is too small to keep
#include "MantidGeometry/MDGeometry/MDHistoDimension.h"
#include "MantidKernel/ArrayProperty.h"
#include "MantidMDEvents/MDBoxIterator.h"
#include "MantidKernel/CPUTimer.h"

using namespace Mantid::Kernel;
using namespace Mantid::API;
@@ -179,6 +180,7 @@ namespace MDAlgorithms
template<typename MDE, size_t nd>
void MergeMD::doPlus(typename MDEventWorkspace<MDE, nd>::sptr ws)
{
//CPUTimer tim;
typename MDEventWorkspace<MDE, nd>::sptr ws1 = boost::dynamic_pointer_cast<MDEventWorkspace<MDE, nd> >(out);
typename MDEventWorkspace<MDE, nd>::sptr ws2 = ws;
if (!ws1 || !ws2)
@@ -191,10 +193,19 @@ namespace MDAlgorithms
size_t initial_numEvents = ws1->getNPoints();

// Make a leaf-only iterator through all boxes with events in the RHS workspace
MDBoxIterator<MDE,nd> it2(box2, 1000, true);
do
std::vector<IMDBox<MDE,nd> *> boxes;
box2->getBoxes(boxes, 1000, true);
int numBoxes = int(boxes.size());

// Add the boxes in parallel. They should be spread out enough on each
// core to avoid stepping on each other.
//PRAGMA_OMP( parallel for if (!ws2->isFileBacked()) schedule(dynamic, PARALLEL_GET_MAX_THREADS*2) )
//PRAGMA_OMP( parallel for if (!ws2->isFileBacked()) schedule(dynamic) )
PRAGMA_OMP( parallel for if (!ws2->isFileBacked()) )
for (int i=0; i<numBoxes; i++)
{
MDBox<MDE,nd> * box = dynamic_cast<MDBox<MDE,nd> *>(it2.getBox());
PARALLEL_START_INTERUPT_REGION
MDBox<MDE,nd> * box = dynamic_cast<MDBox<MDE,nd> *>(boxes[i]);
if (box)
{
// Copy the events from WS2 and add them into WS1
@@ -203,7 +214,10 @@ namespace MDAlgorithms
box1->addEvents(events);
box->releaseEvents();
}
} while (it2.next());
PARALLEL_END_INTERUPT_REGION
}
PARALLEL_CHECK_INTERUPT_REGION


//Progress * prog2 = new Progress(this, 0.4, 0.9, 100);
Progress * prog2 = NULL;
@@ -217,6 +231,8 @@ namespace MDAlgorithms
if (ws1->getNPoints() != initial_numEvents)
ws1->setFileNeedsUpdating(true);

//std::cout << tim << " to add workspace " << ws2->name() << std::endl;

}


@@ -225,6 +241,7 @@ namespace MDAlgorithms
*/
void MergeMD::exec()
{
CPUTimer tim;
// Check that all input workspaces exist and match in certain important ways
const std::vector<std::string> inputs_orig = getProperty("InputWorkspaces");

@@ -269,6 +286,8 @@ namespace MDAlgorithms
// Add to data service
AnalysisDataService::Instance().addOrReplace(this->getPropertyValue("OutputWorkspace"), out);
this->setProperty("OutputWorkspace", out);

g_log.debug() << tim << " to merge all workspaces." << std::endl;
}


@@ -83,7 +83,7 @@ namespace MDAlgorithms
*
* Will do m_out_event += m_operand_event
*
* @param ws :: MDEventWorkspace to clone
* @param ws :: MDEventWorkspace being added to
*/
template<typename MDE, size_t nd>
void PlusMD::doPlus(typename MDEventWorkspace<MDE, nd>::sptr ws)
@@ -0,0 +1,90 @@
#ifndef MANTID_MDALGORITHMS_COMPAREMDWORKSPACESTEST_H_
#define MANTID_MDALGORITHMS_COMPAREMDWORKSPACESTEST_H_

#include "MantidKernel/System.h"
#include "MantidKernel/Timer.h"
#include "MantidMDAlgorithms/CompareMDWorkspaces.h"
#include "MantidTestHelpers/MDEventsTestHelper.h"
#include <cxxtest/TestSuite.h>
#include <iomanip>
#include <iostream>
#include "MantidMDEvents/MDHistoWorkspace.h"

using namespace Mantid;
using namespace Mantid::MDAlgorithms;
using namespace Mantid::API;
using namespace Mantid::MDEvents;
using namespace Mantid::MDEvents::MDEventsTestHelper;
using Mantid::MDEvents::MDHistoWorkspace_sptr;

class CompareMDWorkspacesTest : public CxxTest::TestSuite
{
public:
void test_Init()
{
CompareMDWorkspaces alg;
TS_ASSERT_THROWS_NOTHING( alg.initialize() )
TS_ASSERT( alg.isInitialized() )
}

void doTest(std::string ws1, std::string ws2, std::string resultExpected="Success!",
bool CheckEvents = true)
{

CompareMDWorkspaces alg;
TS_ASSERT_THROWS_NOTHING( alg.initialize() )
TS_ASSERT( alg.isInitialized() )
TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("Workspace1", ws1) );
TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("Workspace2", ws2) );
TS_ASSERT_THROWS_NOTHING( alg.setProperty("CheckEvents", CheckEvents) );
TS_ASSERT_THROWS_NOTHING( alg.setProperty("Tolerance", 1e-5) );
TS_ASSERT_THROWS_NOTHING( alg.execute(); );
TS_ASSERT( alg.isExecuted() );

std::string result = alg.getPropertyValue("Result");
std::cout << result << std::endl;
TSM_ASSERT( result.c_str(), boost::starts_with(result, resultExpected));
}

void test_histo()
{
MDHistoWorkspace_sptr A = makeFakeMDHistoWorkspace(1.56, 3, 10, 10.0, 1.57, "A");
MDHistoWorkspace_sptr B = makeFakeMDHistoWorkspace(1.56, 3, 10, 10.0, 1.57, "B");
doTest("A", "B");
B->setSignalAt(123, 2.34);
doTest("A", "B", "MDHistoWorkspaces have a different signal at index 123");
B->setSignalAt(123, 1.56);
B->setErrorSquaredAt(123, 2.34);
doTest("A", "B", "MDHistoWorkspaces have a different error at index 123");

MDHistoWorkspace_sptr C = makeFakeMDHistoWorkspace(1.56, 3, 9, 10.0, 1.57, "C");
doTest("A", "C", "Dimension #0 has a different number of bins");
MDHistoWorkspace_sptr C2 = makeFakeMDHistoWorkspace(1.56, 3, 10, 20.0, 1.57, "C2");
doTest("A", "C2", "Dimension #0 has a different maximum");

MDHistoWorkspace_sptr D = makeFakeMDHistoWorkspace(1.56, 2, 10, 10.0, 1.57, "D");
doTest("A", "D", "Workspaces have a different number of dimensions");

}


void test_md()
{
makeAnyMDEW<MDEvent<3>, 3>(2, 0., 10., 1, "A");
makeAnyMDEW<MDLeanEvent<3>, 3>(2, 0., 10., 1, "mdle3");
doTest("A", "mdle3", "Workspaces are of different types");

makeAnyMDEW<MDEvent<3>, 3>(2, 0., 10., 2, "B");
doTest("A", "B", "Box signal does not match");

makeAnyMDEW<MDEvent<3>, 3>(3, 0., 10., 1, "C");
doTest("A", "C", "Workspaces do not have the same number of boxes");


}


};


#endif /* MANTID_MDALGORITHMS_COMPAREMDWORKSPACESTEST_H_ */
@@ -129,7 +129,7 @@ void testInit(){
TS_ASSERT_THROWS_NOTHING( pAlg->initialize() )
TS_ASSERT( pAlg->isInitialized() )

TSM_ASSERT_EQUALS("algortithm should have 13 propeties",13,(size_t)(pAlg->getProperties().size()));
TSM_ASSERT_EQUALS("algortithm should have 14 propeties",14,(size_t)(pAlg->getProperties().size()));
}
// TEST QMode
void testParseQMode_WrongThrows()
@@ -346,19 +346,19 @@ void testParseConv_ByTOF()
void testNeedsNumericAxis(){
Mantid::API::MatrixWorkspace_sptr ws2D =WorkspaceCreationHelper::Create2DWorkspace(4,10);
ws2D->replaceAxis(0,new API::TextAxis(3));
std::vector<std::string> dim_names;
std::vector<std::string> dim_ID;
std::vector<std::string> dim_units;
TS_ASSERT_THROWS(pAlg->identifyMatrixAlg(ws2D,"QhQkQl","",dim_names,dim_units),std::invalid_argument);
TS_ASSERT_THROWS(pAlg->identifyMatrixAlg(ws2D,"QhQkQl","",dim_ID,dim_units),std::invalid_argument);
}
void testGetWS4DimIDFine(){
Mantid::API::MatrixWorkspace_sptr ws2D =WorkspaceCreationHelper::createProcessedWorkspaceWithCylComplexInstrument(4,10,true);

std::vector<std::string> dim_names;
std::vector<std::string> dim_ID;
std::vector<std::string> dim_units;
std::string Alg_ID;
TS_ASSERT_THROWS_NOTHING(Alg_ID=pAlg->identifyMatrixAlg(ws2D,"QhQkQl","Direct",dim_names,dim_units));
TS_ASSERT_THROWS_NOTHING(Alg_ID=pAlg->identifyMatrixAlg(ws2D,"QhQkQl","Direct",dim_ID,dim_units));

TSM_ASSERT_EQUALS("Inelastic workspace will produce 4 dimensions",4,dim_names.size());
TSM_ASSERT_EQUALS("Inelastic workspace will produce 4 dimensions",4,dim_ID.size());
TSM_ASSERT_EQUALS("Last dimension of Inelastic transformation should be DeltaE","DeltaE",dim_units[3]);
TSM_ASSERT_EQUALS("Alg ID would be: ","WS2DQhQkQlDirectCnvNo",Alg_ID);
}
@@ -370,12 +370,12 @@ void testGetWS3DimIDFine(){
ws2D->replaceAxis(0,pAx);


std::vector<std::string> dim_names;
std::vector<std::string> dim_ID;
std::vector<std::string> dim_units;
std::string Alg_ID;
TS_ASSERT_THROWS_NOTHING(Alg_ID=pAlg->identifyMatrixAlg(ws2D,"QhQkQl","Elastic",dim_names,dim_units));
TS_ASSERT_THROWS_NOTHING(Alg_ID=pAlg->identifyMatrixAlg(ws2D,"QhQkQl","Elastic",dim_ID,dim_units));

TSM_ASSERT_EQUALS("Inelastic workspace will produce 3 dimensions",3,dim_names.size());
TSM_ASSERT_EQUALS("Inelastic workspace will produce 3 dimensions",3,dim_ID.size());
TSM_ASSERT_EQUALS("Last dimension of Elastic transformation should be ","Momentum",dim_units[2]);
TSM_ASSERT_EQUALS("Alg ID would be: ","WS2DQhQkQlElasticCnvByTOF",Alg_ID);

@@ -393,14 +393,14 @@ void testGetWSDimNames2AxisNoQ(){
pAx->setUnit("QSquared");
ws2D->replaceAxis(1,pAx);

std::vector<std::string> dim_names;
std::vector<std::string> dim_ID;
std::vector<std::string> dim_units;
std::string AlgID;
TS_ASSERT_THROWS_NOTHING(AlgID=pAlg->identifyMatrixAlg(ws2D,"","",dim_names,dim_units));
TS_ASSERT_THROWS_NOTHING(AlgID=pAlg->identifyMatrixAlg(ws2D,"","",dim_ID,dim_units));

TS_ASSERT_EQUALS(2,dim_names.size());
TS_ASSERT_EQUALS("Dim1",dim_names[0]);
TS_ASSERT_EQUALS("Dim2",dim_names[1]);
TS_ASSERT_EQUALS(2,dim_ID.size());
TS_ASSERT_EQUALS("Dim1",dim_ID[0]);
TS_ASSERT_EQUALS("Dim2",dim_ID[1]);

TS_ASSERT_EQUALS(2,dim_units.size());
TS_ASSERT_EQUALS("dSpacing",dim_units[0]);
@@ -33,8 +33,7 @@ void testInit(){

TS_ASSERT_THROWS_NOTHING( pAlg->initialize() )
TS_ASSERT( pAlg->isInitialized() )

TSM_ASSERT_EQUALS("algortithm should have 13 propeties",13,(size_t)(pAlg->getProperties().size()));

}

void testExecThrow(){
@@ -86,12 +86,14 @@ namespace MDEvents

virtual void splitAllIfNeeded(Kernel::ThreadScheduler * ts);

virtual void splitBox();
virtual void splitBox();

virtual void refreshCache();
virtual void refreshCache();

std::string getEventTypeName() const;

virtual void setMinRecursionDepth(size_t minDepth);

//------------------------ (END) IMDEventWorkspace Methods -----------------------------------------

Mantid::API::ITableWorkspace_sptr makeBoxTable(size_t start, size_t num);
@@ -73,6 +73,8 @@ namespace MDEvents
void checkMinMaxNdimConsistent(Mantid::Kernel::Logger& log)const;
/// the vector of default names for Q-directrions in reciprocal space;
std::vector<std::string> defailt_qNames;
/// the string which describes subalgorithm, used to convert source ws to target MD ws.
std::string AlgID;

};
/** function to build mslice-like axis name from the vector, which describes crystallographic direction along this axis*/
@@ -126,35 +126,8 @@ namespace MDEvents

// Do we split more due to MinRecursionDepth?
int minDepth = this->getProperty("MinRecursionDepth");
double numBoxes = pow(double(bc->getNumSplit()), double(minDepth));
double memoryToUse = numBoxes * double(sizeof(MDBox<MDE,nd>)) / 1024.0;
MemoryStats stats;
if (double(stats.availMem()) < memoryToUse)
{
g_log.error() << "MinRecursionDepth is set to " << minDepth << ", which would create " << numBoxes << " boxes using " << memoryToUse << " kB of memory."
<< " You have " << stats.availMem() << " kB available." << std::endl;
throw std::runtime_error("Not enough memory available for the given MinRecursionDepth!");
}

for (int depth = 1; depth < minDepth; depth++)
{
// Get all the MDGridBoxes in the workspace
std::vector<IMDBox<MDE,nd>*> boxes;
boxes.clear();
ws->getBox()->getBoxes(boxes, depth-1, false);
for (size_t i=0; i<boxes.size(); i++)
{
IMDBox<MDE,nd> * box = boxes[i];
MDGridBox<MDE,nd>* gbox = dynamic_cast<MDGridBox<MDE,nd>*>(box);
if (gbox)
{
// Split ALL the contents.
for (size_t j=0; j<gbox->getNumChildren(); j++)
gbox->splitContents(j, NULL);
}
}
}

if (minDepth<0) throw std::invalid_argument("MinRecursionDepth must be >= 0.");
ws->setMinRecursionDepth(size_t(minDepth));
}


@@ -18,6 +18,7 @@
#include <iomanip>
#include <functional>
#include "MantidMDEvents/MDBoxIterator.h"
#include "MantidKernel/Memory.h"

using namespace Mantid;
using namespace Mantid::Kernel;
@@ -123,6 +124,56 @@ namespace MDEvents
return data->getNPoints();
}

//-----------------------------------------------------------------------------------------------
/** Recurse box structure down to a minimum depth.
*
* This will split all boxes so that all MDBoxes are at the depth indicated.
* 0 = no splitting, 1 = one level of splitting, etc.
*
* WARNING! This should ONLY be called before adding any events to a workspace.
*
* WARNING! Be careful using this since it can quickly create a huge
* number of boxes = (SplitInto ^ (MinRercursionDepth * NumDimensions))
*
* @param minDepth :: minimum recursion depth.
* @throw std::runtime_error if there is not enough memory for the boxes.
*/
TMDE(
void MDEventWorkspace)::setMinRecursionDepth(size_t minDepth)
{
BoxController_sptr bc = this->getBoxController();
double numBoxes = pow(double(bc->getNumSplit()), double(minDepth));
double memoryToUse = numBoxes * double(sizeof(MDBox<MDE,nd>)) / 1024.0;
MemoryStats stats;
if (double(stats.availMem()) < memoryToUse)
{
std::ostringstream mess;
mess << "Not enough memory available for the given MinRecursionDepth! "
<< "MinRecursionDepth is set to " << minDepth << ", which would create " << numBoxes << " boxes using " << memoryToUse << " kB of memory."
<< " You have " << stats.availMem() << " kB available." << std::endl;
throw std::runtime_error(mess.str());
}

for (size_t depth = 1; depth < minDepth; depth++)
{
// Get all the MDGridBoxes in the workspace
std::vector<IMDBox<MDE,nd>*> boxes;
boxes.clear();
this->getBox()->getBoxes(boxes, depth-1, false);
for (size_t i=0; i<boxes.size(); i++)
{
IMDBox<MDE,nd> * box = boxes[i];
MDGridBox<MDE,nd>* gbox = dynamic_cast<MDGridBox<MDE,nd>*>(box);
if (gbox)
{
// Split ALL the contents.
for (size_t j=0; j<gbox->getNumChildren(); j++)
gbox->splitContents(j, NULL);
}
}
}
}


//-----------------------------------------------------------------------------------------------
/// Set the number of bins in each dimension to something corresponding to the estimated resolution of the finest binning
@@ -25,7 +25,7 @@ class MDWSDescriptionTest : public CxxTest::TestSuite
TS_ASSERT_THROWS_NOTHING(name=makeAxisName(dir1,descr.defailt_qNames));
TS_ASSERT_EQUALS("[Qh,0,0]",name);

/* TS_ASSERT_THROWS_NOTHING(name=makeAxisName(V3D(-1,0.99,-1.001),descr.defailt_qNames));
TS_ASSERT_THROWS_NOTHING(name=makeAxisName(V3D(-1,0.99,-1.001),descr.defailt_qNames));
TS_ASSERT_EQUALS("[-Qh,0.99Qk,-Ql]",name);

TS_ASSERT_THROWS_NOTHING(name=makeAxisName(V3D(-1,0.9999,-1.001),descr.defailt_qNames));
@@ -35,7 +35,7 @@ class MDWSDescriptionTest : public CxxTest::TestSuite
TS_ASSERT_EQUALS("[-Qh,0.999Qk,-1.01Ql]",name);

TS_ASSERT_THROWS_NOTHING(name=makeAxisName(V3D(2.01,0.9,-1.01),descr.defailt_qNames));
TS_ASSERT_EQUALS("[2.01Qh,0.9Qk,-1.01Ql]",name);*/
TS_ASSERT_EQUALS("[2.01Qh,0.9Qk,-1.01Ql]",name);



@@ -41,11 +41,11 @@ def PyExec(self):
# All distances in mm
wvl = None
if input_ws.getRun().hasProperty("wavelength"):
wvl = input_ws.getRun().hasProperty("wavelength")
wvl = input_ws.getRun().getProperty("wavelength").value

d_wvl = None
if input_ws.getRun().hasProperty("wavelength-spread"):
d_wvl = input_ws.getRun().hasProperty("wavelength-spread")
d_wvl = input_ws.getRun().getProperty("wavelength-spread").value

source_apert_radius = None
if input_ws.getRun().hasProperty("source-aperture-diameter"):
@@ -74,7 +74,7 @@ def PyExec(self):
res_factor += math.pow(k*pixel_size_x/sample_detector_distance, 2)/12.0

for i in range(len(output_ws.readX(0))):
output_ws.dataDx(0)[i] = math.sqrt(res_factor+math.pow((output_ws.readX(0)[i]*d_wvl/wvl), 2)/6.0)
output_ws.dataDx(0)[i] = math.sqrt(res_factor+math.pow((output_ws.readX(0)[i]*d_wvl), 2)/6.0)
else:
raise RuntimeError, "ReactorSANSResolution could not find all the run parameters needed to compute the resolution."

@@ -11,6 +11,9 @@ def category(self):

def name(self):
return "RefLReduction"

def version(self):
return 1

def PyInit(self):
self.declareListProperty("RunNumbers", [0], Validator=ArrayBoundedValidator(Lower=0))
@@ -23,12 +26,10 @@ def PyInit(self):
self.declareListProperty("TOFRange", [9000., 23600.], Validator=ArrayBoundedValidator(Lower=0))
self.declareListProperty("Binning", [0,200,200000],
Description="Positive is linear bins, negative is logorithmic")
# Output workspace to put the transmission histo into
self.declareWorkspaceProperty("OutputWorkspace", "", Direction.Output)

def PyExec(self):
# temporary hack for getting python algorithms working
import mantidsimple
globals()["FindSNSNeXus"] = mantidsimple.FindSNSNeXus

self._binning = self.getProperty("Binning")
if len(self._binning) != 1 and len(self._binning) != 3:
raise RuntimeError("Can only specify (width) or (start,width,stop) for binning. Found %d values." % len(self._binning))
@@ -256,6 +257,10 @@ def PyExec(self):
RHSWorkspace='NormWks',
OutputWorkspace='NormalizedWks')
ReplaceSpecialValues("NormalizedWks",NaNValue=0,NaNError=0, OutputWorkspace="NormalizedWks")
SumSpectra(InputWorkspace="NormalizedWks", OutputWorkspace="Reflectivity")

output_ws = self.getPropertyValue("OutputWorkspace")

SumSpectra(InputWorkspace="NormalizedWks", OutputWorkspace=output_ws)
self.setProperty("OutputWorkspace", mtd[output_ws])

mtd.registerPyAlgorithm(RefLReduction())
@@ -78,9 +78,11 @@ def _loadPreNeXusData(self, runnumber, extension):
def _loadNeXusData(self, filename, name, bank, extension, **kwargs):
alg = LoadEventNexus(Filename=filename, OutputWorkspace=name, BankName=bank, SingleBankPixelsOnly=1, FilterByTofMin=self._binning[0], FilterByTofMax=self._binning[2], LoadMonitors=True, MonitorsAsEvents=True, **kwargs)
wksp = alg['OutputWorkspace']
LoadIsawDetCal(InputWorkspace=wksp,Filename=self._DetCalfile)
if self._DetCalfile is not None:
LoadIsawDetCal(InputWorkspace=wksp,Filename=self._DetCalfile)
#Normalise by sum of counts in upstream monitor
Integration(InputWorkspace=mtd[str(name)+'_monitors'], OutputWorkspace='Mon', RangeLower=self._binning[0], RangeUpper=self._binning[2], EndWorkspaceIndex=0)
NormaliseToMonitor(InputWorkspace=wksp,OutputWorkspace=wksp,MonitorWorkspace=mtd[str(name)+'_monitors'],IntegrationRangeMin=self._binning[0],IntegrationRangeMax=self._binning[2])
wksp *= 1e8
mtd.deleteWorkspace(str(name)+'_monitors')
mtd.releaseFreeMemory()
# take care of filtering events
@@ -221,18 +223,7 @@ def PyExec(self):
if bkgRun > 0:
temp = mtd["%s_%d" % (self._instrument, bkgRun)]
if temp is None:
vanMon = mtd['Mon']
RenameWorkspace(InputWorkspace=vanMon,OutputWorkspace="vanMon")
vanMon = mtd['vanMon']
bkgRun = self._loadData(bkgRun, "", SUFFIX, (0., 0.))
temp = mtd['Mon']
vanMon /= temp
# Keep units of Counts
vanMon.setYUnit("")
Multiply(LHSWorkspace=bkgRun, RHSWorkspace=vanMon, OutputWorkspace=bkgRun, AllowDifferentNumberSpectra=1)
mtd.deleteWorkspace('Mon')
mtd.deleteWorkspace('vanMon')
mtd.releaseFreeMemory()
else:
bkgRun = temp
else:
@@ -266,23 +257,13 @@ def PyExec(self):
for bank in Banks:
# first round of processing the sample
samRun = self._loadData(samRunnum, bank, SUFFIX, filterWall)
samMon = mtd['Mon']
RenameWorkspace(InputWorkspace=samMon,OutputWorkspace="samMon")
samMon = mtd['samMon']

# process the background
bkgRun = self.getProperty("BackgroundNumber")
if bkgRun > 0 and self._SubtractBkg:
temp = mtd["%s_%d" % (self._instrument, bkgRun)]
if temp is None:
bkgRun = self._loadData(bkgRun, bank, SUFFIX, (0., 0.))
temp = mtd['Mon']
temp /= samMon
# Keep units of Counts
temp.setYUnit("")
Divide(LHSWorkspace=bkgRun, RHSWorkspace=temp, OutputWorkspace=bkgRun, AllowDifferentNumberSpectra=1)
mtd.deleteWorkspace('Mon')
mtd.releaseFreeMemory()
else:
bkgRun = temp
else:
@@ -310,14 +291,11 @@ def PyExec(self):

# write out the files
# scale data so fitting routines do not run out of memory
samMon /= 1e8
samRun /= samMon
samRun = self._bin(samRun)
mtd.releaseFreeMemory()
self._save(samRun, normalized)
if self._outTypes is not '':
mtd.deleteWorkspace(str(samRun))
mtd.deleteWorkspace('samMon')
mtd.releaseFreeMemory()
peaksWS = mtd['Peaks']
try:
@@ -44,7 +44,7 @@ namespace MDEventsTestHelper

/// Make a fake n-dimensional MDHistoWorkspace
Mantid::MDEvents::MDHistoWorkspace_sptr makeFakeMDHistoWorkspace(double signal, size_t numDims, size_t numBins = 10, double max = 10.0,
double errorSquared=1.0);
double errorSquared=1.0, std::string name="");


//-------------------------------------------------------------------------------------
@@ -202,10 +202,11 @@ namespace MDEventsTestHelper
* @param numBins :: bins in each dimensions
* @param max :: max position in each dimension
* @param errorSquared :: error squared in every point
* @param name :: optional name
* @return the MDHisto
*/
Mantid::MDEvents::MDHistoWorkspace_sptr makeFakeMDHistoWorkspace(double signal, size_t numDims, size_t numBins,
double max, double errorSquared)
double max, double errorSquared, std::string name)
{
Mantid::MDEvents::MDHistoWorkspace * ws = NULL;
if (numDims ==1)
@@ -237,6 +238,8 @@ namespace MDEventsTestHelper
}
Mantid::MDEvents::MDHistoWorkspace_sptr ws_sptr(ws);
ws_sptr->setTo(signal, errorSquared);
if (!name.empty())
AnalysisDataService::Instance().addOrReplace(name, ws_sptr);
return ws_sptr;
}

@@ -810,6 +810,11 @@ add_custom_command ( TARGET MantidPlot POST_BUILD
${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}/ipython_plugin
)

###########################################################################
# Documentation targets
###########################################################################
add_subdirectory( docs )

###########################################################################
# MantidPlot Python Unit Tests
###########################################################################
@@ -0,0 +1,4 @@
###########################################################################
# Add each directory
###########################################################################
add_subdirectory( python )
@@ -6,30 +6,41 @@
find_package ( Sphinx )

if ( SPHINX_FOUND )
# Fill in the config file and autogen file
configure_file ( conf.py.in conf.py @ONLY )
# Fill in the config file and autogen file with build information
configure_file ( source/conf.py.in source/conf.py @ONLY )
configure_file ( autogen_api.py.in autogen_api.py @ONLY )

# These files need to be relative to the conf.py file
add_custom_command ( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/index.rst
COMMAND ${CMAKE_COMMAND} ARGS -E copy
${CMAKE_CURRENT_SOURCE_DIR}/index.rst ${CMAKE_CURRENT_BINARY_DIR}/index.rst
COMMAND ${CMAKE_COMMAND} ARGS -E copy_directory
${CMAKE_CURRENT_SOURCE_DIR}/api ${CMAKE_CURRENT_BINARY_DIR}/api
COMMAND ${CMAKE_COMMAND} ARGS -E copy_directory
${CMAKE_CURRENT_SOURCE_DIR}/_static ${CMAKE_CURRENT_BINARY_DIR}/_static
COMMAND ${CMAKE_COMMAND} ARGS -E copy_directory
${CMAKE_CURRENT_SOURCE_DIR}/_templates ${CMAKE_CURRENT_BINARY_DIR}/_templates
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/conf.py
configure_file ( runsphinx.py.in runsphinx.py @ONLY )

# Sphinx seems to require the config file to be next to the rest of the source
# files meaning we need to copy everything over to the build directory
set ( SPHINX_SOURCE
source/index.rst
source/api/mantid.rst
source/api/mantidplot.rst
source/_templates/indexcontent.html
source/_templates/indexsidebar.html
source/_templates/layout.html
)

# The destination for the copied files
set ( SPHINX_CONF_DIR ${CMAKE_CURRENT_BINARY_DIR} )
set ( SPHINX_CONF_FILES )
foreach( file ${SPHINX_SOURCE} )
set ( out_file ${SPHINX_CONF_DIR}/${file} )
add_custom_command ( OUTPUT ${out_file}
COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/${file} ${out_file}
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${file}
)
set ( SPHINX_CONF_FILES ${SPHINX_CONF_FILES} ${out_file} )
endforeach()

set ( SPHINX_HTML_BUILD ${CMAKE_CURRENT_BINARY_DIR}/../../../python-sphinx/html )
# Sphinx is run as '${SPHINX_EXECUTABLE} -b sourcedir builddir'
set ( OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/../../../python-sphinx/html )
add_custom_target ( python-sphinx
COMMAND python autogen_api.py
COMMAND ${SPHINX_EXECUTABLE} -b html ${CMAKE_CURRENT_BINARY_DIR} ${OUTPUT_DIR}
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/index.rst
COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/MantidPlot -xq autogen_api.py
COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/MantidPlot -xq runsphinx.py
DEPENDS ${SPHINX_CONF_FILES}
COMMENT "Build Python Sphinx API documentation"
)
)

endif ()
@@ -5,9 +5,8 @@ import sys
import os
import inspect

# Append the path to the mantid library
# Append the path to the mantid/mantidplot library
sys.path.append("@CMAKE_RUNTIME_OUTPUT_DIRECTORY@")
import mantid

#------------------------------------------------------------------------------

@@ -27,7 +26,6 @@ class ClassAPIWriter(object):
:inherited-members:
"""

def __init__(self, cls, outputdir, extension):
if not inspect.isclass(cls):
raise TypeError("Expected class type, found %s" % str(type(cls)))
@@ -41,6 +39,11 @@ class ClassAPIWriter(object):

# FQL name could contain '_cmodule' aswell, strip this off
modname = self._cls.__module__

# Hack for replaceing qti reference with mantidplot ref
if 'qti' in modname:
modname = modname.replace('_qti','mantidplot')
# Build up the module name and don't reference the "private" modules
pieces = modname.split('.')
fqlmod = ''
for p in pieces:
@@ -55,26 +58,89 @@ class ClassAPIWriter(object):

def filename(self):
return self._filename

class FunctionAPIWriter(object):
"""Writes a Sphinx documentation file
for a given function
"""

_doc_template = \
"""%(title)s
%(underline)s
if __name__ == '__main__':
extension = '.rst'
apidir = os.path.join(os.path.dirname(__file__), 'api')
output_dir = os.path.join(apidir,'generated')
if not os.path.exists(output_dir):
os.mkdir(output_dir)
.. module:`%(modulename)s`
.. autofunction:: %(modulename)s.%(function)s
"""

def __init__(self, func, outputdir, extension):
if not inspect.isfunction(func):
raise TypeError("Expected function type, found %s" % str(type(cls)))
self._filename = os.path.join(outputdir, func.__name__ + extension)
self._func = func

def write(self):
rstfile = open(self._filename, 'w')
funcname = self._func.__name__
underline = '='*len(funcname) # Sphinx doesn't like the title underline being incorrect
# FQL name could contain '_cmodule' aswell, strip this off
modname = self._func.__module__
# Hack for replaceing qti reference with mantidplot ref
if 'qti' in modname:
modname = modname.replace('_qti','mantidplot')

# Write the file
rstfile.write(self._doc_template % {'title':funcname, 'underline':underline,\
'modulename':modname,'function':funcname})
rstfile.close()

def filename(self):
return self._filename


def generate_api_doc(module, indexfilename):
"""Write the sphinx doc files for a given module
@param module - The module object
@param indexfilename - A file that will contain an index list of the given files
"""

indexfilename = os.path.join(apidir, 'autogen.txt')
indexfile = open(indexfilename, 'w')
indexfile.write(".. AUTO-GENERATED FILE -- DO NOT EDIT!\n\n")
indexfile.write(".. toctree::\n\n")

print "Generating API docs"
for name, member in inspect.getmembers(mantid):
print "Generating %s API docs" % module.__name__
for name, member in inspect.getmembers(module):
if name.startswith("_"): continue
if inspect.isclass(member):
apiwriter = ClassAPIWriter(member, output_dir, extension)
elif inspect.isfunction(member):
apiwriter = FunctionAPIWriter(member, output_dir, extension)
else:
continue
apiwriter.write()
indexfile.write(" generated/" + os.path.basename(apiwriter.filename()) + "\n")
indexfile.close()
print "Completed autogenerating API docs"
print "Done generating API %s docs" % module.__name__

if __name__ == '__main__':
extension = '.rst'
apidir = os.path.join(os.path.dirname(__file__), 'source','api')
output_dir = os.path.join(apidir,'generated')
if not os.path.exists(output_dir):
os.mkdir(output_dir)

import mantid
indexfilename = os.path.join(apidir, 'automantid.txt')
generate_api_doc(mantid, indexfilename)
try:
import mantidplot
indexfilename = os.path.join(apidir, 'automantidplot.txt')
generate_api_doc(mantidplot, indexfilename)
except:
import warnings
warnings.warn("Unable to import mantidplot. No api documentation will be generated for MantidPlot")



@@ -0,0 +1,21 @@
"""We need to run Sphinx inside MantidPlot to document the internal
module. This script calls the sphinx entry point with the necessary
arguments
"""

__requires__ = 'Sphinx==1.1.2'
import sys
import os
from pkg_resources import load_entry_point

mantidplot = "@CMAKE_RUNTIME_OUTPUT_DIRECTORY@/MantidPlot"
builder = "html"
src_dir = "@CMAKE_CURRENT_BINARY_DIR@/source"
output_dir = "@CMAKE_CURRENT_BINARY_DIR@/../../../python-sphinx/" + builder
argv = [mantidplot,'-b', builder, src_dir, output_dir]

if __name__ == '__main__':
sys.exit(
load_entry_point('Sphinx==1.1.2', 'console_scripts', 'sphinx-build')(argv)
)

Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@@ -0,0 +1,45 @@
{% extends "defindex.html" %}
{% block tables %}

<p><strong>Contents:</strong></p>
<table class="contentstable" align="center"><tr>
<td width="50%">
<p class="biglink"><a class="biglink" href="http://www.mantidproject.org/Python_in_Mantid_Training">Introductary training</a><br/>
<span class="linkdescr">An introduction to Python in Mantid</span></p>
</td><td width="50%">
<p class="biglink"><a class="biglink" href="{{ pathto("api/mantid") }}">Mantid Framework Reference</a><br/>
<span class="linkdescr">Documents the classes and functions of the Mantid framework</span></p>
<p class="biglink"><a class="biglink" href="{{ pathto("api/mantidplot") }}">MantidPlot Reference</a><br/>
<span class="linkdescr">Documents the classes and functions of MantidPlot</span></p>
</td></tr>
</table>

<p><strong>Indices and tables:</strong></p>
<table class="contentstable" align="center"><tr>
<td width="50%">
<p class="biglink"><a class="biglink" href="{{ pathto("py-modindex") }}">Module Index</a><br/>
<span class="linkdescr">quick access to all modules</span></p>
<p class="biglink"><a class="biglink" href="{{ pathto("genindex") }}">General Index</a><br/>
<span class="linkdescr">all functions, classes, terms</span></p>
<p class="biglink"><a class="biglink" href="{{ pathto("glossary") }}">Glossary</a><br/>
<span class="linkdescr">the most important terms explained</span></p>
</td><td width="50%">
<p class="biglink"><a class="biglink" href="{{ pathto("search") }}">Search page</a><br/>
<span class="linkdescr">search this documentation</span></p>
<p class="biglink"><a class="biglink" href="{{ pathto("contents") }}">Complete Table of Contents</a><br/>
<span class="linkdescr">lists all sections and subsections</span></p>
</td></tr>
</table>

<p><strong>Useful links:</strong></p>
<table class="contentstable" align="center"><tr>
<td width="50%">
<p class="biglink"><a class="biglink" href="http://www.mantidproject.org" }}">Mantid project wiki</a><br/>
<span class="linkdescr">Mantid wiki</span></p>
</td><td width="50%">
<p class="biglink"><a class="biglink" href="http://docs.scipy.org/doc/numpy-1.5.x/user/" }}">Numpy Tutorial</a><br/>
<span class="linkdescr">An introduction to numpy</span></p>
</td></tr>
</table>

{% endblock %}
@@ -0,0 +1,6 @@
<h3>Resources</h3>
<ul>
<li><a href="http://www.mantidproject.org/">Mantid wiki</a></li>
<li>&nbsp;</li>
<li><a href="http://docs.python.org/">Python manual</a></li>
</ul>
@@ -0,0 +1,10 @@
{% extends "default/layout.html" %}

{%- block sidebarlogo %}
{%- if logo %}
<p class="logo"><a href="{{ pathto(master_doc) }}">
<img class="logo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo" width=220 height=110/>
</a></p>
{%- endif %}
{%- endblock %}

@@ -1,13 +1,9 @@
.. _mantid:

#################################
Mantid Python Class Reference
#################################
##################################
Mantid Framework class reference
##################################

.. module:: mantid

Some lovely wording here...

and probably more structure

.. include:: autogen.txt
.. include:: automantid.txt
@@ -0,0 +1,9 @@
.. _mantidplot:

##########################
MantidPlot API reference
##########################

.. module:: mantidplot

.. include:: automantidplot.txt
@@ -107,14 +107,15 @@ html_theme = 'default'

# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
html_title = "%s v%s Python Manual" % ("Mantid", version)

# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None

# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None

html_logo = os.path.relpath('@CMAKE_HOME_DIRECTORY@/Images/Mantid_Logo_Transparent.png')

# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
@@ -135,11 +136,15 @@ html_static_path = ['_static']
#html_use_smartypants = True

# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
html_sidebars = {
'index':'indexsidebar.html'
}

# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
html_additional_pages = {
'index':'indexcontent.html'
}

# If false, no module index is generated.
#html_domain_indices = True
@@ -168,7 +173,7 @@ html_use_index = True
#html_file_suffix = None

# Output file base name for HTML help builder.
htmlhelp_basename = 'Mantiddoc'
htmlhelp_basename = 'mantid'


# -- Options for LaTeX output --------------------------------------------------
@@ -16,6 +16,7 @@ Contents
:maxdepth: 1

api/mantid.rst
api/mantidplot.rst

Indices and tables
==================
@@ -10,7 +10,7 @@
# Imports
#-----------------------------------------------------------------------------

from IPython.lib.kernel import connect_qtconsole
from IPython.lib.kernel import connect_qtconsole, find_connection_file
from IPython.zmq.ipkernel import IPKernelApp

#-----------------------------------------------------------------------------
@@ -21,11 +21,7 @@ def pylab_kernel(gui):
"""Launch and return an IPython kernel with pylab support for the desired gui
"""
kernel = IPKernelApp.instance()
# Notes: pylab command seems to be needed for event loop to behave nicely
# IPython needs additional mantidsimple import (even if started from a command line)
# - added this to mantidplotrc.py
# Can only %run one file. I think qtiplotrc should go away anyway.
# Weird things happen if I run this under a debug build
# Note: pylab command seems to be needed for event loop to behave nicely
kernel.initialize(['python', '--pylab=%s' % gui,
"--c='%run -m mantidplotrc'"])
return kernel
@@ -52,6 +48,20 @@ def init_ipkernel(self, backend):

def new_qt_console(self, evt=None):
"""start a new qtconsole connected to our kernel"""

import sys
# We have to step in and cannibalise connect_qtconsole if we're on windows because
# it launches sys.executable assuming it'll be python, when in fact it's MantidPlot
if sys.platform == 'win32':
argv = []
cf = find_connection_file(self.ipkernel.connection_file, profile=self.ipkernel.profile)
cmd = ';'.join([
"from IPython.frontend.qt.console import qtconsoleapp",
"qtconsoleapp.main()"
])
from subprocess import Popen, PIPE
return Popen([sys.exec_prefix+'\pythonw.exe', '-c', cmd, '--existing', cf] + argv, stdout=PIPE, stderr=PIPE)

return connect_qtconsole(self.ipkernel.connection_file, profile=self.ipkernel.profile)

def cleanup_consoles(self, evt=None):
@@ -10,7 +10,7 @@
#import resources # Initialize Qt resources from file resources.py

IPYTHON_LOADED = False
import IPython, pygments
import IPython, pygments, matplotlib
from internal_ipkernel import InternalIPKernel
IPYTHON_LOADED = True

@@ -21,7 +21,7 @@
#-------------------------- Mantid Python access functions----------------
# Grab a few Mantid things so that we can recognise workspace variables
# While we have 2 APIs we need to figure out which to use so add a little bit of indirection
def get_analysis_data_service():
def _get_analysis_data_service():
"""Returns an object that can be used to get a workspace by name from Mantid
Returns:
@@ -44,7 +44,7 @@ def workspace(name):
Args:
name: The name of the workspace in the Analysis Data Service.
"""
return get_analysis_data_service()[name]
return _get_analysis_data_service()[name]

def table(name):
"""Get a handle on a table.
@@ -217,8 +217,7 @@ def stemPlot(source, index, power=None, startPoint=None, endPoint=None):
Args:
source: A reference to a workspace or a table.
index: For a table, the column number or name. For a workspace, the workspace index.
power: The stem unit as a power of 10. If not provided, a dialog will appear with a
suggested value.
power: The stem unit as a power of 10. If not provided, a dialog will appear with a suggested value.
startPoint: The first point (row or bin) to use (Default: the first one).
endPoint: The last point (row or bin) to use (Default: the last one).
@@ -457,26 +456,17 @@ def plotSlice(source, label="", xydim=None, slicepoint=None,
Optional Keyword Args:
label :: label for the window title
xydim :: indexes or names of the dimensions to plot,
as an (X,Y) list or tuple.
See SliceViewer::setXYDim()
slicepoint :: list with the slice point in each dimension. Must be the
same length as the number of dimensions of the workspace.
See SliceViewer::setSlicePoint()
colormin :: value of the minimum color in the scale
See SliceViewer::setColorScaleMin()
colormax :: value of the maximum color in the scale
See SliceViewer::setColorScaleMax()
colorscalelog :: value of the maximum color in the scale
See SliceViewer::setColorScaleLog()
limits :: list with the (xleft, xright, ybottom, ytop) limits
to the view to show.
See SliceViewer::setXYLimits()
xydim :: indexes or names of the dimensions to plot, as an (X,Y) list or tuple. See SliceViewer::setXYDim()
slicepoint :: list with the slice point in each dimension. Must be the same length as the number of dimensions of the workspace. See SliceViewer::setSlicePoint()
colormin :: value of the minimum color in the scale. See SliceViewer::setColorScaleMin()
colormax :: value of the maximum color in the scale. See SliceViewer::setColorScaleMax()
colorscalelog :: value of the maximum color in the scale. See SliceViewer::setColorScaleLog()
limits :: list with the (xleft, xright, ybottom, ytop) limits to the view to show. See SliceViewer::setXYLimits()
Returns:
a (list of) handle(s) to the SliceViewerWindow widgets that were open.
Use SliceViewerWindow.getSlicer() to get access to the functions of the
SliceViewer, e.g. setting the view and slice point.
Use SliceViewerWindow.getSlicer() to get access to the functions of the
SliceViewer, e.g. setting the view and slice point.
"""
workspace_names = __getWorkspaceNames(source)
try:
@@ -563,10 +553,6 @@ def closeAllSliceViewers():
Layer.Bottom = _qti.GraphOptions.Bottom
Layer.Top = _qti.GraphOptions.Top





#-----------------------------------------------------------------------------
#--------------------------- "Private" functions -----------------------------
#-----------------------------------------------------------------------------
@@ -604,7 +590,7 @@ def __getWorkspaceNames(source):
else:
ws_names.append(wspace.getName())
elif isinstance(source,str):
w = get_analysis_data_service()[source]
w = _get_analysis_data_service()[source]
if w != None:
names = __getWorkspaceNames(w)
for n in names:
@@ -10008,7 +10008,7 @@ void ApplicationWindow::addFunctionCurve()

Graph* g = plot->activeGraph();
if ( g ) {
FunctionDialog* fd = functionDialog(g);
functionDialog(g);
}
}

@@ -14445,6 +14445,8 @@ void ApplicationWindow::parseCommandLineArguments(const QStringList& args)
{
exec = true;
quit = true;
// Minimize ourselves
this->showMinimized();
}
else if (str.startsWith("-") || str.startsWith("--"))
{
@@ -15935,13 +15937,20 @@ void ApplicationWindow::goToColumn()
}
}

void ApplicationWindow::showScriptWindow(bool forceVisible)
/**
* Show the script window, creating it if necessary
* @param forceVisible - If true the window is forced to visible rather than toggling
* @param quitting - If true then it is assumed MantidPlot will exit automatically so stdout redirect
* from scripts is disabled.
*/
void ApplicationWindow::showScriptWindow(bool forceVisible, bool quitting)
{
if( !scriptingWindow )
{
// MG 09/02/2010 : Removed parent from scripting window. If it has one then it doesn't respect the always on top
// flag, it is treated as a sub window of its parent
scriptingWindow = new ScriptingWindow(scriptingEnv(), NULL);
const bool capturePrint = !quitting;
scriptingWindow = new ScriptingWindow(scriptingEnv(),capturePrint, NULL);
scriptingWindow->setObjectName("ScriptingWindow");
scriptingWindow->setAttribute(Qt::WA_DeleteOnClose, false);
connect(scriptingWindow, SIGNAL(closeMe()), this, SLOT(saveScriptWindowGeometry()));
@@ -15954,7 +15963,14 @@ void ApplicationWindow::showScriptWindow(bool forceVisible)
{
scriptingWindow->resize(d_script_win_size);
scriptingWindow->move(d_script_win_pos);
scriptingWindow->show();
if( quitting )
{
scriptingWindow->showMinimized();
}
else
{
scriptingWindow->show();
}
scriptingWindow->setFocus();
}
else
@@ -16121,7 +16137,7 @@ ApplicationWindow * ApplicationWindow::loadScript(const QString& fn, bool execut
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
setScriptingLanguage("Python");
restoreApplicationGeometry();
showScriptWindow();
showScriptWindow(false, quit);
scriptingWindow->open(fn, false);
QApplication::restoreOverrideCursor();
if (execute)
@@ -728,7 +728,7 @@ public slots:
//! Connected to the context menu signal from lv; it's called when there are no items selected in the list
void showListViewPopupMenu(const QPoint &p);

void showScriptWindow(bool forceVisible = false);
void showScriptWindow(bool forceVisible = false, bool quitting = false);
void saveScriptWindowGeometry();
void showScriptInterpreter();
bool testForIPython();
@@ -96,6 +96,12 @@ PythonScript::PythonScript(PythonScripting *env, const QString &code, QObject *c
GILHolder gil;
PyObject *pymodule = PyImport_AddModule("__main__");
localDict = PyDict_Copy(PyModule_GetDict(pymodule));
if( QFileInfo(Name).exists() )
{
QString scriptPath = QFileInfo(Name).absoluteFilePath();
// Make sure the __file__ variable is set
PyDict_SetItem(localDict,PyString_FromString("__file__"), PyString_FromString(scriptPath.toAscii().data()));
}
setQObject(Context, "self");
updatePath(Name, true);

@@ -675,6 +681,7 @@ void PythonScript::beginStdoutRedirect()
*/
void PythonScript::endStdoutRedirect()
{

GILHolder gil; // Aqcuire the GIL
PyDict_SetItemString(env()->sysDict(), "stdout", stdoutSave);
Py_XDECREF(stdoutSave);
@@ -184,7 +184,6 @@ bool PythonScripting::start()

//Get the refresh protection flag
Mantid::Kernel::ConfigService::Instance().getValue("pythonalgorithms.refresh.allowed", refresh_allowed);

if( loadInitFile(mantidbin.absoluteFilePath("mantidplotrc.py")) )
{
d_initialized = true;
@@ -193,18 +192,22 @@ bool PythonScripting::start()
{
d_initialized = false;
}
return d_initialized;
}
catch(std::exception & ex)
{
std::cerr << "Exception in PythonScripting.cpp: " << ex.what() << std::endl;
return false;
d_initialized = false;
}
catch(...)
{
std::cerr << "Exception in PythonScripting.cpp" << std::endl;
return false;
d_initialized = false;
}
// Reset the stdout/err printers
PyDict_SetItemString(m_sys, "stdout",PyDict_GetItemString(m_sys, "__stdout__"));
PyDict_SetItemString(m_sys, "stderr",PyDict_GetItemString(m_sys, "__stderr__"));

return d_initialized;
}

/**
@@ -40,10 +40,10 @@
/**
* Constructor
*/
ScriptManagerWidget::ScriptManagerWidget(ScriptingEnv *env, QWidget *parent, bool interpreter_mode)
ScriptManagerWidget::ScriptManagerWidget(ScriptingEnv *env, QWidget *parent, bool interpreter_mode, bool capturePrint)
: QTabWidget(parent), Scripted(env), m_last_dir(""), m_script_runners(),
m_cursor_pos(), m_findrep_dlg(NULL),
m_interpreter_mode(interpreter_mode)
m_interpreter_mode(interpreter_mode), m_recentScriptList(), m_capturePrint(capturePrint)
{
//Create actions for this widget
initActions();
@@ -1062,11 +1062,18 @@ void ScriptManagerWidget::open(bool newtab, const QString & filename)
Script * ScriptManagerWidget::createScriptRunner(ScriptEditor *editor)
{
Script *script = scriptingEnv()->newScript("", this, editor->fileName(), true,
m_toggle_progress->isChecked());
// Connect the signals that print output and error messages to the formatting functions
connect(script, SIGNAL(print(const QString &)), this, SLOT(displayOutput(const QString &)));
connect(script, SIGNAL(error(const QString &, const QString&, int)), this,
SLOT(displayError(const QString &)));
m_toggle_progress->isChecked());
if( m_capturePrint )
{
// Connect the signals that print output and error messages to the formatting functions
connect(script, SIGNAL(print(const QString &)), this, SLOT(displayOutput(const QString &)));
connect(script, SIGNAL(error(const QString &, const QString&, int)), this,
SLOT(displayError(const QString &)));
}
else
{
script->redirectStdOut(false);
}
if( editor )
{
connect(script, SIGNAL(keywordsChanged(const QStringList&)), editor,
@@ -62,7 +62,7 @@ class ScriptManagerWidget : public QTabWidget, Scripted

public:
/// Constructor
ScriptManagerWidget(ScriptingEnv *env, QWidget *parent, bool interpreter_mode = false);
ScriptManagerWidget(ScriptingEnv *env, QWidget *parent, bool interpreter_mode = false, bool capturePrint = true);
///Destructor
~ScriptManagerWidget();
///Save settings applicable to the manager
@@ -244,6 +244,8 @@ private slots:
bool m_interpreter_mode;
///list storing the recent scripts
QStringList m_recentScriptList;
/// Flag to indicate whether stdout should be redirected
bool m_capturePrint;
/// enum used for maximum of recent scripts size
enum {MaxRecentScripts = 5};
};
@@ -314,7 +316,6 @@ private slots:

/// If a find is in progress
bool m_find_inprogress;

};


@@ -257,12 +257,13 @@ void ScriptOutputDock::resetFont()
* @param parent :: The parent widget
* @param flags :: Window flags passed to the base class
*/
ScriptingWindow::ScriptingWindow(ScriptingEnv *env,QWidget *parent, Qt::WindowFlags flags) :
ScriptingWindow::ScriptingWindow(ScriptingEnv *env, bool capturePrint, QWidget *parent, Qt::WindowFlags flags) :
QMainWindow(parent, flags), m_acceptClose(false)
{
setObjectName("MantidScriptWindow");
// Sub-widgets
m_manager = new ScriptManagerWidget(env, this);
const bool interpreterMode(false);
m_manager = new ScriptManagerWidget(env, this, interpreterMode, capturePrint);
setCentralWidget(m_manager);
m_output_dock = new ScriptOutputDock(QString(), m_manager, this);
m_output_dock->setScriptIsRunning(false);
@@ -279,7 +280,7 @@ ScriptingWindow::ScriptingWindow(ScriptingEnv *env,QWidget *parent, Qt::WindowFl
QSettings settings;
settings.beginGroup("/ScriptWindow");
QString lastdir = settings.value("LastDirectoryVisited", "").toString();
// If nothgin, set the last directory to the Mantid scripts directory (if present)
// If nothing, set the last directory to the Mantid scripts directory (if present)
if( lastdir.isEmpty() )
{
lastdir = QString::fromStdString(Mantid::Kernel::ConfigService::Instance().getString("pythonscripts.directory"));
@@ -107,13 +107,13 @@ class ScriptingWindow : public QMainWindow

public:
///Constructor
ScriptingWindow(ScriptingEnv *env,QWidget *parent = 0, Qt::WindowFlags flags = 0);
ScriptingWindow(ScriptingEnv *env,bool capturePrint = true,QWidget *parent = 0, Qt::WindowFlags flags = 0);
///Destructor
~ScriptingWindow();
/// Override the closeEvent
void closeEvent(QCloseEvent *event);
/// Override the showEvent
void showEvent(QShowEvent *event);
void showEvent(QShowEvent *event);
/// Is a script running?
bool isScriptRunning() const;
///Save the current state of the script window for next time
@@ -177,7 +177,6 @@ private slots:
QAction *m_scripting_lang;
/// Flag to define whether we should accept a close event
bool m_acceptClose;

};

#endif //SCRIPTINGWINDOW_H_
@@ -5,7 +5,6 @@ set ( SRC_FILES src/CreateSampleShapeDialog.cpp
src/LoadRawDialog.cpp
src/LOQScriptInputDialog.cpp
src/MantidGLWidget.cpp
src/PeakIntegrationDialog.cpp
src/PlotAsymmetryByLogValueDialog.cpp
src/SampleShapeHelpers.cpp
)
@@ -20,7 +19,6 @@ set ( INC_FILES inc/MantidQtCustomDialogs/CreateSampleShapeDialog.h
inc/MantidQtCustomDialogs/LoadRawDialog.h
inc/MantidQtCustomDialogs/LOQScriptInputDialog.h
inc/MantidQtCustomDialogs/MantidGLWidget.h
inc/MantidQtCustomDialogs/PeakIntegrationDialog.h
inc/MantidQtCustomDialogs/PlotAsymmetryByLogValueDialog.h
inc/MantidQtCustomDialogs/SampleShapeHelpers.h
)
@@ -32,7 +30,6 @@ set ( MOC_FILES inc/MantidQtCustomDialogs/CreateSampleShapeDialog.h
inc/MantidQtCustomDialogs/LoadRawDialog.h
inc/MantidQtCustomDialogs/LOQScriptInputDialog.h
inc/MantidQtCustomDialogs/MantidGLWidget.h
inc/MantidQtCustomDialogs/PeakIntegrationDialog.h
inc/MantidQtCustomDialogs/PlotAsymmetryByLogValueDialog.h
inc/MantidQtCustomDialogs/SampleShapeHelpers.h
)

This file was deleted.

This file was deleted.

@@ -67,6 +67,8 @@ namespace MantidQt

void setLogValueClicked();

void helpClicked();

private:
Ui::CreateMDWorkspace m_uiForm;
WorkspaceMementoCollection m_data;
@@ -79,6 +79,13 @@
</property>
</widget>
</item>
<item>
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_remove_workspace">
<property name="sizePolicy">
@@ -138,7 +145,7 @@
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<layout class="QVBoxLayout" name="verticalLayout_3" stretch="4,1,1,4">
<layout class="QVBoxLayout" name="verticalLayout_3" stretch="4,1,1,0,4">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
@@ -356,6 +363,51 @@
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="btn_help">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>30</width>
<height>30</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>30</width>
<height>30</height>
</size>
</property>
<property name="toolTip">
<string>Help</string>
</property>
<property name="text">
<string>?</string>
</property>
</widget>
</item>
<item>
<spacer name="helpSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="spacerLayout">
<property name="sizeConstraint">
@@ -42,6 +42,8 @@
#include <QFileDialog>
#include <QRadioButton>
#include <QCheckBox>
#include <QDesktopServices>
#include <QUrl>
#include <strstream>
#include <boost/regex.hpp>
#include <boost/algorithm/string.hpp>
@@ -105,6 +107,7 @@ void CreateMDWorkspace::initLayout()
connect(m_uiForm.btn_find_ub_matrix, SIGNAL(clicked()), this, SLOT(findUBMatrixClicked()));
connect(m_uiForm.btn_set_goniometer, SIGNAL(clicked()), this, SLOT(setGoniometerClicked()));
connect(m_uiForm.btn_add_logs, SIGNAL(clicked()), this, SLOT(setLogValueClicked()));
connect(m_uiForm.btn_help, SIGNAL(clicked()), this, SLOT(helpClicked()));

//Set MVC Model
m_uiForm.tableView->setModel(m_model);
@@ -626,6 +629,15 @@ void CreateMDWorkspace::createMDWorkspaceClicked()
runConfirmation(msg);
}

/**
* Event handler for the help request. Launches browser to obtain help.
*/
void CreateMDWorkspace::helpClicked()
{
QDesktopServices::openUrl(QUrl(QString("http://www.mantidproject.org/") +
"Create_MD_Workspace_GUI"));
}


/// Destructor
CreateMDWorkspace::~CreateMDWorkspace()
@@ -1471,6 +1471,9 @@ void MuonAnalysis::normalise(const std::vector<double>& x, const std::vector<dou
*/
void MuonAnalysis::plotGroup(const std::string& plotType)
{
if (plotToTime() <= plotFromTime())
return;

m_updating = true;

QString plotTypeTitle("");
@@ -1663,6 +1666,9 @@ void MuonAnalysis::plotGroup(const std::string& plotType)
*/
void MuonAnalysis::plotPair(const std::string& plotType)
{
if (plotToTime() <= plotFromTime())
return;

m_updating = true;

QString plotTypeTitle("");
@@ -2934,12 +2940,13 @@ void MuonAnalysis::groupFittedWorkspaces(QString workspaceName)
void MuonAnalysis::connectAutoUpdate()
{
// Home tab Auto Updates
connect(m_uiForm.firstGoodBinFront, SIGNAL(textChanged(const QString&)), this, SLOT(homeTabUpdatePlot()));
connect(m_uiForm.firstGoodBinFront, SIGNAL(editingFinished ()), this, SLOT(homeTabUpdatePlot()));
connect(m_uiForm.frontGroupGroupPairComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(homeTabUpdatePlot()));
connect(m_uiForm.homePeriodBox1, SIGNAL(currentIndexChanged(int)), this, SLOT(homeTabUpdatePlot()));
connect(m_uiForm.homePeriodBoxMath, SIGNAL(currentIndexChanged(int)), this, SLOT(homeTabUpdatePlot()));
connect(m_uiForm.homePeriodBox2, SIGNAL(currentIndexChanged(int)), this, SLOT(homeTabUpdatePlot()));
connect(m_uiForm.frontPlotFuncs, SIGNAL(currentIndexChanged(int)), this, SLOT(homeTabUpdatePlot()));
connect(m_uiForm.frontAlphaNumber, SIGNAL(editingFinished ()), this, SLOT(homeTabUpdatePlot()));

// Grouping tab Auto Updates
// Group Table
@@ -70,11 +70,11 @@ void MuonAnalysisOptionTab::initLayout()
////////////// Auto Update /////////////////
connect(m_uiForm.connectPlotType, SIGNAL(currentIndexChanged(int)), this, SIGNAL(settingsTabUpdatePlot()));
connect(m_uiForm.timeComboBox, SIGNAL(currentIndexChanged(int)), this, SIGNAL(settingsTabUpdatePlot()));
connect(m_uiForm.timeAxisStartAtInput, SIGNAL(textChanged(const QString&)), this, SIGNAL(settingsTabUpdatePlot()));
connect(m_uiForm.timeAxisFinishAtInput, SIGNAL(textChanged(const QString&)), this, SIGNAL(settingsTabUpdatePlot()));
connect(m_uiForm.yAxisMinimumInput, SIGNAL(textChanged(const QString&)), this, SIGNAL(settingsTabUpdatePlot()));
connect(m_uiForm.yAxisMaximumInput, SIGNAL(textChanged(const QString&)), this, SIGNAL(settingsTabUpdatePlot()));
connect(m_uiForm.optionStepSizeText, SIGNAL(textChanged(const QString&)), this, SIGNAL(settingsTabUpdatePlot()));
connect(m_uiForm.timeAxisStartAtInput, SIGNAL(editingFinished ()), this, SIGNAL(settingsTabUpdatePlot()));
connect(m_uiForm.timeAxisFinishAtInput, SIGNAL(editingFinished ()), this, SIGNAL(settingsTabUpdatePlot()));
connect(m_uiForm.yAxisMinimumInput, SIGNAL(editingFinished ()), this, SIGNAL(settingsTabUpdatePlot()));
connect(m_uiForm.yAxisMaximumInput, SIGNAL(editingFinished ()), this, SIGNAL(settingsTabUpdatePlot()));
connect(m_uiForm.optionStepSizeText, SIGNAL(editingFinished ()), this, SIGNAL(settingsTabUpdatePlot()));
connect(m_uiForm.rebinComboBox, SIGNAL(currentIndexChanged(int)), this, SIGNAL(settingsTabUpdatePlot()));
connect(m_uiForm.showErrorBars, SIGNAL(clicked()), this, SIGNAL(settingsTabUpdatePlot()));
}
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@@ -1,6 +1,4 @@
from numpy import zeros, arctan2
from pylab import *
import matplotlib.pyplot as plt
from mantidsimple import *
import math