Skip to content
Snippets Groups Projects
Commit 2d122ca6 authored by Pospelov, Gennady's avatar Pospelov, Gennady
Browse files

New NumpyUtils to return vector of doubles as Numpy array

parent 5307c20e
No related branches found
No related tags found
No related merge requests found
Showing
with 411 additions and 36 deletions
// ************************************************************************** //
//
// BornAgain: simulate and fit scattering at grazing incidence
//
//! @file PythonAPI/inc/NumpyUtils.h
//! @brief Defines various functions to interact from numpy on Python side
//!
//! @homepage http://bornagainproject.org
//! @license GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2015
//! @authors Scientific Computing Group at MLZ Garching
//! @authors C. Durniak, M. Ganeva, G. Pospelov, W. Van Herck, J. Wuttke
//
// ************************************************************************** //
#ifndef NUMPYUTILS_H
#define NUMPYUTILS_H
#ifdef BORNAGAIN_PYTHON
#ifndef PyObject_HEAD
struct _object;
typedef _object PyObject;
#endif
#endif
#include <vector>
namespace Utils
{
#ifdef BORNAGAIN_PYTHON
PyObject *createNumpyArray(const std::vector<double> &data);
#endif
} // namespace Utils
#endif
...@@ -102,34 +102,31 @@ void register_Histogram1D_class(){ ...@@ -102,34 +102,31 @@ void register_Histogram1D_class(){
, "Increment bin with abscissa x with a weight." ); , "Increment bin with abscissa x with a weight." );
} }
{ //::Histogram1D::getBinCenters { //::Histogram1D::getBinCentersNumpy
typedef ::std::vector< double > ( ::Histogram1D::*getBinCenters_function_type)( ) const; typedef ::PyObject * ( ::Histogram1D::*getBinCenters_function_type)( ) const;
Histogram1D_exposer.def( Histogram1D_exposer.def(
"getBinCenters" "getBinCenters"
, getBinCenters_function_type( &::Histogram1D::getBinCenters ) , getBinCenters_function_type( &::Histogram1D::getBinCentersNumpy ) );
, "returns vector of histogram bin centers." );
} }
{ //::Histogram1D::getBinErrors { //::Histogram1D::getBinErrorsNumpy
typedef ::std::vector< double > ( ::Histogram1D::*getBinErrors_function_type)( ) const; typedef ::PyObject * ( ::Histogram1D::*getBinErrors_function_type)( ) const;
Histogram1D_exposer.def( Histogram1D_exposer.def(
"getBinErrors" "getBinErrors"
, getBinErrors_function_type( &::Histogram1D::getBinErrors ) , getBinErrors_function_type( &::Histogram1D::getBinErrorsNumpy ) );
, "returns vector of bin errors." );
} }
{ //::Histogram1D::getBinValues { //::Histogram1D::getBinValuesNumpy
typedef ::std::vector< double > ( ::Histogram1D::*getBinValues_function_type)( ) const; typedef ::PyObject * ( ::Histogram1D::*getBinValues_function_type)( ) const;
Histogram1D_exposer.def( Histogram1D_exposer.def(
"getBinValues" "getBinValues"
, getBinValues_function_type( &::Histogram1D::getBinValues ) , getBinValues_function_type( &::Histogram1D::getBinValuesNumpy ) );
, "returns vector of bin content (the value accumulated by bins)." );
} }
{ //::Histogram1D::getRank { //::Histogram1D::getRank
......
// ************************************************************************** //
//
// BornAgain: simulate and fit scattering at grazing incidence
//
//! @file PythonAPI/inc/NumpyUtils.h
//! @brief Implements various functions to interact from numpy on Python side
//!
//! @homepage http://bornagainproject.org
//! @license GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2015
//! @authors Scientific Computing Group at MLZ Garching
//! @authors C. Durniak, M. Ganeva, G. Pospelov, W. Van Herck, J. Wuttke
//
// ************************************************************************** //
#include "NumpyUtils.h"
#include "Exceptions.h"
#ifdef BORNAGAIN_PYTHON
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#include <boost/python/detail/wrap_python.hpp>
#define PY_ARRAY_UNIQUE_SYMBOL BORNAGAIN_PYTHONAPI_ARRAY
#define NO_IMPORT_ARRAY
#include "numpy/arrayobject.h"
PyObject *Utils::createNumpyArray(const std::vector<double> &data)
{
const size_t ndim(1);
npy_int ndim_numpy = ndim;
npy_intp *ndimsizes_numpy = new npy_intp[ndim];
ndimsizes_numpy[0] = data.size();
// creating standalone numpy array
PyObject *pyarray = PyArray_SimpleNew(ndim_numpy, ndimsizes_numpy, NPY_DOUBLE);
delete [] ndimsizes_numpy;
if(pyarray == NULL ) {
throw RuntimeErrorException(
"ExportOutputData() -> Panic in PyArray_SimpleNew");
}
Py_INCREF(pyarray);
// getting pointer to data buffer of numpy array
double *array_buffer = (double *)PyArray_DATA((PyArrayObject*)pyarray);
for(size_t index=0; index<data.size(); ++index) {
*array_buffer++ = data[index];
}
return pyarray;
}
#endif
...@@ -58,8 +58,16 @@ public: ...@@ -58,8 +58,16 @@ public:
//! returns vector of bin errors //! returns vector of bin errors
std::vector<double> getBinErrors() const; std::vector<double> getBinErrors() const;
#ifdef BORNAGAIN_PYTHON
PyObject *getBinCentersNumpy() const;
PyObject *getBinValuesNumpy() const;
PyObject *getBinErrorsNumpy() const;
#endif
//! Create new histogram by applying crop on axis. //! Create new histogram by applying crop on axis.
Histogram1D *crop(double xmin, double xmax); Histogram1D *crop(double xmin, double xmax);
}; };
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "Histogram1D.h" #include "Histogram1D.h"
#include "FixedBinAxis.h" #include "FixedBinAxis.h"
#include "VariableBinAxis.h" #include "VariableBinAxis.h"
#include "NumpyUtils.h"
#include <boost/scoped_ptr.hpp> #include <boost/scoped_ptr.hpp>
...@@ -67,6 +68,21 @@ std::vector<double> Histogram1D::getBinErrors() const ...@@ -67,6 +68,21 @@ std::vector<double> Histogram1D::getBinErrors() const
return IHistogram::getDataVector(IHistogram::ERROR); return IHistogram::getDataVector(IHistogram::ERROR);
} }
PyObject *Histogram1D::getBinCentersNumpy() const
{
return Utils::createNumpyArray(getBinCenters());
}
PyObject *Histogram1D::getBinValuesNumpy() const
{
return Utils::createNumpyArray(getBinValues());
}
PyObject *Histogram1D::getBinErrorsNumpy() const
{
return Utils::createNumpyArray(getBinErrors());
}
Histogram1D *Histogram1D::crop(double xmin, double xmax) Histogram1D *Histogram1D::crop(double xmin, double xmax)
{ {
boost::scoped_ptr<IAxis > xaxis(getXaxis()->createClippedAxis(xmin, xmax)); boost::scoped_ptr<IAxis > xaxis(getXaxis()->createClippedAxis(xmin, xmax));
......
...@@ -14,15 +14,18 @@ ...@@ -14,15 +14,18 @@
// ************************************************************************** // // ************************************************************************** //
#include "RealParameterWrapper.h" #include "RealParameterWrapper.h"
#include <sstream>
RealParameterWrapper::RealParameterWrapper(double *par, const AttLimits &limits) RealParameterWrapper::RealParameterWrapper(double *par, const AttLimits &limits)
: m_data(par) : m_data(par)
, m_limits(limits) , m_limits(limits)
{ {
if(par && !m_limits.isInRange(getValue())) { if(par && !m_limits.isInRange(getValue())) {
throw OutOfBoundsException( std::ostringstream message;
"RealParameterWrapper::RealParameterWrapper() -> Error. Initial value is out of bounds" message << "RealParameterWrapper::RealParameterWrapper() -> Error. "
); << "Initial value " << getValue() << " is out of bounds "
<< limits << std::endl;
throw OutOfBoundsException(message.str());
} }
} }
......
...@@ -43,8 +43,7 @@ def get_simulation(): ...@@ -43,8 +43,7 @@ def get_simulation():
simulation = GISASSimulation() simulation = GISASSimulation()
simulation.setDetectorParameters(100, -1.0*degree, 1.0*degree, 100, 0.0*degree, 2.0*degree) simulation.setDetectorParameters(100, -1.0*degree, 1.0*degree, 100, 0.0*degree, 2.0*degree)
simulation.setBeamParameters(1.0*angstrom, 0.2*degree, 0.0*degree) simulation.setBeamParameters(1.0*angstrom, 0.2*degree, 0.0*degree)
return simulation
return simulation;
def create_real_data(): def create_real_data():
...@@ -83,6 +82,7 @@ def run_fitting(): ...@@ -83,6 +82,7 @@ def run_fitting():
real_data = create_real_data() real_data = create_real_data()
fit_suite = FitSuite() fit_suite = FitSuite()
fit_suite.setMinimizer("GSLLMA")
fit_suite.addSimulationAndRealData(simulation, real_data) fit_suite.addSimulationAndRealData(simulation, real_data)
fit_suite.initPrint(10) fit_suite.initPrint(10)
...@@ -97,7 +97,6 @@ def run_fitting(): ...@@ -97,7 +97,6 @@ def run_fitting():
fit_suite.runFit() fit_suite.runFit()
print "Fitting completed." print "Fitting completed."
fit_suite.printResults()
print "chi2:", fit_suite.getChi2() print "chi2:", fit_suite.getChi2()
fitpars = fit_suite.getFitParameters() fitpars = fit_suite.getFitParameters()
for i in range(0, fitpars.size()): for i in range(0, fitpars.size()):
......
...@@ -96,12 +96,13 @@ def run_fitting(): ...@@ -96,12 +96,13 @@ def run_fitting():
simulation = get_simulation() simulation = get_simulation()
sample_builder = MySampleBuilder() sample_builder = MySampleBuilder()
simulation.setSampleBuilder(sample_builder) simulation.setSampleBuilder(sample_builder)
simulation.printParameters()
real_data = create_real_data() real_data = create_real_data()
fit_suite = FitSuite() fit_suite = FitSuite()
fit_suite.addSimulationAndRealData(simulation, real_data) fit_suite.addSimulationAndRealData(simulation, real_data)
fit_suite.initPrint(10) fit_suite.initPrint(1)
draw_observer = DefaultFitObserver(draw_every_nth=10) draw_observer = DefaultFitObserver(draw_every_nth=10)
fit_suite.attachObserver(draw_observer) fit_suite.attachObserver(draw_observer)
...@@ -114,7 +115,6 @@ def run_fitting(): ...@@ -114,7 +115,6 @@ def run_fitting():
fit_suite.runFit() fit_suite.runFit()
print "Fitting completed." print "Fitting completed."
fit_suite.printResults()
print "chi2:", fit_suite.getChi2() print "chi2:", fit_suite.getChi2()
fitpars = fit_suite.getFitParameters() fitpars = fit_suite.getFitParameters()
for i in range(0, fitpars.size()): for i in range(0, fitpars.size()):
......
...@@ -83,20 +83,24 @@ def add_mask_to_simulation(simulation): ...@@ -83,20 +83,24 @@ def add_mask_to_simulation(simulation):
# mask all detector (put mask=True to all detector channels) # mask all detector (put mask=True to all detector channels)
simulation.maskAll() simulation.maskAll()
# set mask to simulate pacman's head # # set mask to simulate pacman's head
simulation.addMask(Ellipse(0.0*deg, 1.0*deg, 0.5*deg, 0.5*deg), False) # simulation.addMask(Ellipse(0.0*deg, 1.0*deg, 0.5*deg, 0.5*deg), False)
#
# # set mask for pacman's eye
# simulation.addMask(Ellipse(0.11*deg, 1.25*deg, 0.05*deg, 0.05*deg), True)
#
# # set mask for pacman's mouth
# points = [[0.0*deg, 1.0*deg], [0.5*deg, 1.2*deg], [0.5*deg, 0.8*deg], [0.0*deg, 1.0*deg]]
# simulation.addMask(Polygon(points), True)
#
# # giving pacman something to eat
# simulation.addMask(Rectangle(0.45*deg, 0.95*deg, 0.55*deg, 1.05*deg), False)
# simulation.addMask(Rectangle(0.61*deg, 0.95*deg, 0.71*deg, 1.05*deg), False)
# simulation.addMask(Rectangle(0.75*deg, 0.95*deg, 0.85*deg, 1.05*deg), False)
simulation.addMask(HorizontalLine(1.0*deg), False)
simulation.addMask(VerticalLine(0.0*deg), False)
# set mask for pacman's eye
simulation.addMask(Ellipse(0.11*deg, 1.25*deg, 0.05*deg, 0.05*deg), True)
# set mask for pacman's mouth
points = [[0.0*deg, 1.0*deg], [0.5*deg, 1.2*deg], [0.5*deg, 0.8*deg], [0.0*deg, 1.0*deg]]
simulation.addMask(Polygon(points), True)
# giving pacman something to eat
simulation.addMask(Rectangle(0.45*deg, 0.95*deg, 0.55*deg, 1.05*deg), False)
simulation.addMask(Rectangle(0.61*deg, 0.95*deg, 0.71*deg, 1.05*deg), False)
simulation.addMask(Rectangle(0.75*deg, 0.95*deg, 0.85*deg, 1.05*deg), False)
# other mask's shapes are possible too # other mask's shapes are possible too
# simulation.removeMasks() # simulation.removeMasks()
......
"""
Fitting example
This is more detailed version of FitCylindersPrisms.py.
We show how to generate "real" data and how to draw fit progress.
Please take a note, that performance here is determined by poor performance of matplotlib drawing routines.
"""
import matplotlib
from matplotlib import pyplot as plt
import math
from bornagain import *
import numpy
phi_slice_value = 0.0*deg # position of vertical slice
alpha_slice_value = 0.2*deg # position of horizontal slice
# conditions = [
# {'title': "Small cylinders, analytical calculations", 'scale': 1, 'integration': False, 'max': 1e+08},
# {'title': "Small cylinders, Monte-Carlo integration", 'scale': 1, 'integration': True, 'max': 1e+08},
# {'title': "Large cylinders, analytical calculations", 'scale': 100, 'integration': False, 'max': 1e+12},
# {'title': "Large cylinders, Monte-Carlo integration", 'scale': 100, 'integration': True, 'max': 1e+12}
# ]
def get_sample(radius=5*nanometer, height=10*nanometer):
"""
Build the sample representing cylinders and pyramids on top of
substrate without interference.
"""
m_air = HomogeneousMaterial("Air", 0.0, 0.0)
m_substrate = HomogeneousMaterial("Substrate", 6e-6, 2e-8)
m_particle = HomogeneousMaterial("Particle", 6e-4, 2e-8)
cylinder_ff = FormFactorCylinder(radius, height)
cylinder = Particle(m_particle, cylinder_ff)
particle_layout = ParticleLayout()
particle_layout.addParticle(cylinder)
air_layer = Layer(m_air)
air_layer.addLayout(particle_layout)
substrate_layer = Layer(m_substrate, 0)
multi_layer = MultiLayer()
multi_layer.addLayer(air_layer)
multi_layer.addLayer(substrate_layer)
return multi_layer
def get_simulation():
"""
Create and return GISAXS simulation with beam and detector defined
"""
simulation = GISASSimulation()
simulation.setDetectorParameters(100, -1.0*degree, 1.0*degree, 100, 0.0*degree, 2.0*degree)
simulation.setBeamParameters(1.0*angstrom, 0.2*degree, 0.0*degree)
return simulation
def create_real_data():
"""
Generating "real" data by adding noise to the simulated data.
"""
sample = get_sample(5.0*nanometer, 10.0*nanometer)
simulation = get_simulation()
simulation.setSample(sample)
simulation.runSimulation()
real_data = simulation.getIntensityData()
# spoiling simulated data with the noise to produce "real" data
noise_factor = 1.0
for i in range(0, real_data.getTotalNumberOfBins()):
amplitude = real_data.getBinContent(i)
sigma = noise_factor*math.sqrt(amplitude)
noisy_amplitude = GenerateNormalRandom(amplitude, sigma)
if noisy_amplitude < 0.0:
noisy_amplitude = 0.0
real_data.setBinContent(i, noisy_amplitude)
return real_data
class DrawObserver(IFitObserver):
"""
Draws fit progress every nth iteration. This class has to be attached to FitSuite via attachObserver method.
FitSuite kernel will call DrawObserver's update() method every n'th iteration.
It is up to the user what to do here.
"""
def __init__(self, draw_every_nth=10):
IFitObserver.__init__(self, draw_every_nth)
self.fig = plt.figure(figsize=(10.25, 7.69))
self.fig.canvas.draw()
plt.ion()
def plot_colormap(self, data, title, min=1, max=1e6):
plt.subplot(2, 2, 1)
plt.subplots_adjust(wspace=0.2, hspace=0.2)
im = plt.imshow(data.getArray(),
norm=matplotlib.colors.LogNorm(min, max),
extent=[data.getXmin()/deg, data.getXmax()/deg, data.getYmin()/deg, data.getYmax()/deg])
plt.colorbar(im)
plt.title(title)
def plot_horizontal_slices(self, real_data, simul_data):
plt.subplot(2, 2, 2)
plt.subplots_adjust(wspace=0.2, hspace=0.2)
real_slice = real_data.projectionX(alpha_slice_value)
simul_slice = simul_data.projectionX(alpha_slice_value)
plt.semilogy(real_slice.getBinCenters()/deg, real_slice.getBinValues(), label="real")
plt.semilogy(simul_slice.getBinCenters()/deg, simul_slice.getBinValues(), label="simul")
plt.ylim(1.0, real_slice.getMaximum()*10.0)
plt.xlim(real_slice.getXmin()/deg, real_slice.getXmax()/deg)
plt.legend(loc='upper right')
plt.title("Horizontal slice at alpha =" + '{:3.1f}'.format(alpha_slice_value/deg))
def plot_vertical_slices(self, real_data, simul_data):
plt.subplot(2, 2, 3)
plt.subplots_adjust(wspace=0.2, hspace=0.2)
real_slice = real_data.projectionY(phi_slice_value)
simul_slice = simul_data.projectionY(phi_slice_value)
plt.semilogy(real_slice.getBinCenters()/deg, real_slice.getBinValues(), label="real")
plt.semilogy(simul_slice.getBinCenters()/deg, simul_slice.getBinValues(), label="simul")
plt.ylim(1.0, real_slice.getMaximum()*10.0)
plt.xlim(real_slice.getXmin()/deg, real_slice.getXmax()/deg)
plt.legend(loc='upper right')
plt.title("Vertical slice at phi =" + '{:3.1f}'.format(phi_slice_value/deg))
def plot_slices(self, slices, title):
for slice in slices:
plt.semilogy(slice.getBinCenters()/deg, slice.getBinValues(), label="real")
plt.xlim(slice.getXmin()/deg, slice.getXmax()/deg)
plt.ylim(1.0, slice.getMaximum()*10.0)
plt.legend(loc='upper right')
plt.title(title)
def update(self, fit_suite):
self.fig.clf()
real_data = fit_suite.getRealData()
simulated_data = fit_suite.getSimulationData()
self.plot_colormap(real_data, "\"Real\" data", min=1.0, max=real_data.getMaximum())
self.plot_horizontal_slices(real_data, simulated_data)
self.plot_vertical_slices(real_data, simulated_data)
# real_hslice = real_data.projectionX(alpha_slice_value)
# simul_hslice = simulated_data.projectionX(alpha_slice_value)
# plt.subplot(2, 2, 2)
# slices = []
# slices.append(real_data.projectionX(alpha_slice_value))
# slices.append(simulated_data.projectionX(alpha_slice_value))
# self.plot_slices(slices, "Horizontal slice at alpha =" + '{:3.1f}'.format(alpha_slice_value/deg))
# self.plot_horizontal_slices(real_data, simulated_data)
# self.plot_slice(real_hslice, nplot=2, min=1.0, max=real_hslice.getMaximum())
# self.plot_slice(simul_hslice, nplot=2, min=1.0, max=real_hslice.getMaximum())
# plt.title("Horizontal slice")
# plt.legend("Real", "Simulated", loc='upper right')
# real_vslice = real_data.projectionY(phi_slice_value)
# simul_vslice = simulated_data.projectionY(phi_slice_value)
# self.plot(fit_suite.getSimulationData(), "Simulated data", nplot=2, min=1.0, max=real_data.getMaximum())
# self.plot(fit_suite.getChiSquaredMap(), "Chi2 map", nplot=3, min=0.001, max=10.0)
plt.subplot(2, 2, 4)
plt.title('Parameters')
plt.axis('off')
plt.text(0.01, 0.85, "Iteration " + '{:d} {:s}'.
format(fit_suite.getNumberOfIterations(), fit_suite.getMinimizer().getMinimizerName()))
plt.text(0.01, 0.75, "Chi2 " + '{:8.4f}'.format(fit_suite.getChi2()))
fitpars = fit_suite.getFitParameters()
for i in range(0, fitpars.size()):
plt.text(0.01, 0.55 - i*0.1, '{:30.30s}: {:6.3f}'.format(fitpars[i].getName(), fitpars[i].getValue()))
plt.draw()
plt.pause(0.01)
if fit_suite.isLastIteration():
plt.ioff()
def run_fitting():
"""
main function to run fitting
"""
real_data = create_real_data()
sample = get_sample()
simulation = get_simulation()
simulation.setSample(sample)
# At this point we mask all the detector and then unmask two areas corresponding to the vertical
# and horizontal lines.
simulation.maskAll()
simulation.addMask(HorizontalLine(alpha_slice_value), False)
simulation.addMask(VerticalLine(phi_slice_value), False)
fit_suite = FitSuite()
fit_suite.addSimulationAndRealData(simulation, real_data)
fit_suite.initPrint(10)
draw_observer = DrawObserver(draw_every_nth=10)
fit_suite.attachObserver(draw_observer)
# setting fitting parameters with starting values
fit_suite.addFitParameter("*/FormFactorCylinder/radius", 6.*nanometer, AttLimits.limited(4., 8.))
fit_suite.addFitParameter("*/FormFactorCylinder/height", 9.*nanometer, AttLimits.limited(8., 12.))
# running fit
fit_suite.runFit()
print "Fitting completed."
print "chi2:", fit_suite.getChi2()
fitpars = fit_suite.getFitParameters()
for i in range(0, fitpars.size()):
print fitpars[i].getName(), fitpars[i].getValue(), fitpars[i].getError()
if __name__ == '__main__':
run_fitting()
plt.show()
...@@ -199,6 +199,9 @@ bool FitKernel::check_prerequisites() const ...@@ -199,6 +199,9 @@ bool FitKernel::check_prerequisites() const
"FitSuite::check_prerequisites() -> Error! No simulation/data description defined"); "FitSuite::check_prerequisites() -> Error! No simulation/data description defined");
if( !m_fit_parameters.size() ) throw LogicErrorException( if( !m_fit_parameters.size() ) throw LogicErrorException(
"FitSuite::check_prerequisites() -> Error! No fit parameters defined"); "FitSuite::check_prerequisites() -> Error! No fit parameters defined");
if( m_fit_objects.getSizeOfDataSet() == 0) throw LogicErrorException(
"FitSuite::check_prerequisites() -> Error! No elements to fit. "
"Looks like whole detector is masked.");
return true; return true;
} }
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "FitSuiteObjects.h" #include "FitSuiteObjects.h"
#include "FitObject.h" #include "FitObject.h"
#include "ChiSquaredModule.h" #include "ChiSquaredModule.h"
#include <sstream>
FitSuiteObjects::FitSuiteObjects() FitSuiteObjects::FitSuiteObjects()
: m_total_weight(0) : m_total_weight(0)
...@@ -52,9 +53,6 @@ size_t FitSuiteObjects::getSizeOfDataSet() const ...@@ -52,9 +53,6 @@ size_t FitSuiteObjects::getSizeOfDataSet() const
m_fit_objects.begin(); it!= m_fit_objects.end(); ++it) { m_fit_objects.begin(); it!= m_fit_objects.end(); ++it) {
result += (*it)->getSizeOfData(); result += (*it)->getSizeOfData();
} }
if(result == 0) {
throw LogicErrorException("Panic, zero dataset size");
}
return result; return result;
} }
...@@ -90,6 +88,12 @@ OutputData<double> *FitSuiteObjects::getChiSquaredMap(size_t i_item) const ...@@ -90,6 +88,12 @@ OutputData<double> *FitSuiteObjects::getChiSquaredMap(size_t i_item) const
//! loop through all defined simulations and run them //! loop through all defined simulations and run them
void FitSuiteObjects::runSimulations() void FitSuiteObjects::runSimulations()
{ {
if(getSizeOfDataSet() == 0) {
std::ostringstream message;
message << "FitSuiteObjects::runSimulations() -> Error. Zero size of dataset.";
throw LogicErrorException(message.str());
}
m_fit_elements.clear(); m_fit_elements.clear();
m_fit_elements.reserve(getSizeOfDataSet()); m_fit_elements.reserve(getSizeOfDataSet());
......
...@@ -378,6 +378,18 @@ def ManualClassTunings(mb): ...@@ -378,6 +378,18 @@ def ManualClassTunings(mb):
cl.member_function("getXaxis").call_policies = call_policies.return_internal_reference() cl.member_function("getXaxis").call_policies = call_policies.return_internal_reference()
cl.member_function("getYaxis").call_policies = call_policies.return_internal_reference() cl.member_function("getYaxis").call_policies = call_policies.return_internal_reference()
cl = mb.class_("Histogram1D")
cl.member_function("getBinCenters").exclude()
cl.member_function("getBinValues").exclude()
cl.member_function("getBinErrors").exclude()
cl.member_function("getBinCentersNumpy").call_policies = call_policies.custom_call_policies("")
cl.member_function("getBinValuesNumpy").call_policies = call_policies.custom_call_policies("")
cl.member_function("getBinErrorsNumpy").call_policies = call_policies.custom_call_policies("")
cl.member_function("getBinCentersNumpy").alias = "getBinCenters"
cl.member_function("getBinValuesNumpy").alias = "getBinValues"
cl.member_function("getBinErrorsNumpy").alias = "getBinErrors"
# #
cl = mb.class_("Histogram2D") cl = mb.class_("Histogram2D")
for fun in cl.member_functions(): for fun in cl.member_functions():
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment