def test_analytic_integral(): class DistFunc3(zbasepdf.BasePDF): def _unnormalized_pdf(self, x, norm_range=False): return func3_2deps(x) mu_true = 1.4 sigma_true = 1.8 limits = -4.3, 1.9 mu = Parameter("mu_1414", mu_true, mu_true - 2., mu_true + 7.) sigma = Parameter("sigma_1414", sigma_true, sigma_true - 10., sigma_true + 5.) gauss_params1 = CustomGaussOLD(mu=mu, sigma=sigma, obs=obs1, name="gauss_params1") normal_params1 = Gauss(mu=mu, sigma=sigma, obs=obs1, name="gauss_params1") try: infinity = mt.inf except AttributeError: # py34 infinity = float('inf') gauss_integral_infs = gauss_params1.integrate(limits=(-infinity, infinity), norm_range=False) normal_integral_infs = normal_params1.integrate(limits=(-infinity, infinity), norm_range=False) DistFunc3.register_analytic_integral(func=func3_2deps_fully_integrated, limits=Space.from_axes(limits=limits3, axes=(0, 1))) dist_func3 = DistFunc3(obs=['obs1', 'obs2']) gauss_integral_infs = zfit.run(gauss_integral_infs) normal_integral_infs = zfit.run(normal_integral_infs) func3_integrated = zfit.run( ztf.convert_to_tensor( dist_func3.integrate(limits=Space.from_axes(limits=limits3, axes=(0, 1)), norm_range=False), dtype=tf.float64)) assert func3_integrated == func3_2deps_fully_integrated(limits=Space.from_axes(limits=limits3, axes=(0, 1))) assert gauss_integral_infs == pytest.approx(np.sqrt(np.pi * 2.) * sigma_true, rel=0.0001) assert normal_integral_infs == pytest.approx(1, rel=0.0001)
def test_mc_integration(chunksize): # simpel example zfit.run.chunking.active = True zfit.run.chunking.max_n_points = chunksize num_integral = zintegrate.mc_integrate(func=func1_5deps, limits=Space.from_axes( limits=limits_simple_5deps, axes=tuple(range(5))), n_axes=5) num_integral2 = zintegrate.mc_integrate(func=func2_1deps, limits=Space.from_axes( limits=limits2, axes=tuple(range(1))), n_axes=1) num_integral3 = zintegrate.mc_integrate(func=func3_2deps, limits=Space.from_axes( limits=limits3, axes=tuple(range(2))), n_axes=2) integral = num_integral.numpy() integral2 = num_integral2.numpy() integral3 = num_integral3.numpy() assert not hasattr(integral, "__len__") assert not hasattr(integral2, "__len__") assert not hasattr(integral3, "__len__") assert func1_5deps_fully_integrated(limits_simple_5deps) == pytest.approx( integral, rel=0.1) assert func2_1deps_fully_integrated(limits2) == pytest.approx(integral2, rel=0.03) assert func3_2deps_fully_integrated( Space.from_axes(limits=limits3, axes=(0, 1))).numpy() == pytest.approx(integral3, rel=0.03)
def test_sub_space(): sub_space2_true_axes = Space.from_axes(axes=sub_limit2_axes, limits=sub_limit2) assert sub_space2_true_axes == space2_subbed_axes sub_space2_true = Space(obs=sub_limit2_obs, limits=sub_limit2) space2_subbed = space2_obs.get_subspace(obs=sub_limit2_obs) assert space2_subbed == sub_space2_true
def test_mc_integration(): # simpel example num_integral = zintegrate.mc_integrate(func=func1_5deps, limits=Space.from_axes(limits=limits_simple_5deps, axes=tuple(range(5))), n_axes=5) num_integral2 = zintegrate.mc_integrate(func=func2_1deps, limits=Space.from_axes(limits=limits2, axes=tuple(range(1))), n_axes=1) num_integral3 = zintegrate.mc_integrate(func=func3_2deps, limits=Space.from_axes(limits=limits3, axes=tuple(range(2))), n_axes=2) integral = zfit.run(num_integral) integral2 = zfit.run(num_integral2) integral3 = zfit.run(num_integral3) assert not hasattr(integral, "__len__") assert not hasattr(integral2, "__len__") assert not hasattr(integral3, "__len__") assert func1_5deps_fully_integrated(limits_simple_5deps) == pytest.approx(integral, rel=0.1) assert func2_1deps_fully_integrated(limits2) == pytest.approx(integral2, rel=0.03) assert func3_2deps_fully_integrated( Space.from_axes(limits=limits3, axes=(0, 1))) == pytest.approx(integral3, rel=0.03)
def test_add(): param1 = zfit.Parameter("param1", 1.) param2 = zfit.Parameter("param2", 2.) pdfs = [0] * 4 pdfs[0] = Gauss(param1, 4, obs=obs1) pdfs[1] = Gauss(param2, 5, obs=obs1) pdfs[2] = Gauss(3, 6, obs=obs1) pdfs[3] = Gauss(4, 7, obs=obs1) datas = [0] * 4 datas[0] = z.constant(1.) datas[1] = z.constant(2.) datas[2] = z.constant(3.) datas[3] = z.constant(4.) ranges = [0] * 4 ranges[0] = (1, 4) ranges[1] = Space(limits=(2, 5), obs=obs1) ranges[2] = Space(limits=(3, 6), obs=obs1) ranges[3] = Space(limits=(4, 7), obs=obs1) constraint1 = zfit.constraint.nll_gaussian(params=param1, mu=1, sigma=0.5) constraint2 = zfit.constraint.nll_gaussian(params=param1, mu=2, sigma=0.25) merged_contraints = [constraint1, constraint2] nll1 = UnbinnedNLL(model=pdfs[0], data=datas[0], fit_range=ranges[0], constraints=constraint1) nll2 = UnbinnedNLL(model=pdfs[1], data=datas[1], fit_range=ranges[1], constraints=constraint2) nll3 = UnbinnedNLL(model=[pdfs[2], pdfs[3]], data=[datas[2], datas[3]], fit_range=[ranges[2], ranges[3]]) simult_nll = nll1 + nll2 + nll3 assert simult_nll.model == pdfs assert simult_nll.data == datas ranges[0] = Space._from_any( limits=ranges[0], obs=obs1, axes=(0, )) # for comparison, Space can only compare with Space ranges[1]._axes = (0, ) ranges[2]._axes = (0, ) ranges[3]._axes = (0, ) assert simult_nll.fit_range == ranges def eval_constraint(constraints): return z.reduce_sum([c.value() for c in constraints]).numpy() assert eval_constraint( simult_nll.constraints) == eval_constraint(merged_contraints)
def test_mc_partial_integration(): values = z.convert_to_tensor(func4_values) data1 = zfit.Data.from_tensor(obs='obs2', tensor=tf.expand_dims(values, axis=-1)) limits1 = Space(limits=limits4_2dim, obs=['obs1', 'obs3']) limits1._set_obs_axes({'obs1': 0, 'obs3': 2}) num_integral = zintegrate.mc_integrate(x=data1, func=func4_3deps, limits=limits1) vals_tensor = z.convert_to_tensor(func4_2values) vals_reshaped = tf.transpose(a=vals_tensor) data2 = zfit.Data.from_tensor(obs=['obs1', 'obs3'], tensor=vals_reshaped) limits2 = Space(limits=limits4_1dim, obs=['obs2']) limits2._set_obs_axes({'obs2': 1}) num_integral2 = zintegrate.mc_integrate(x=data2, func=func4_3deps, limits=limits2, draws_per_dim=100) integral = num_integral.numpy() integral2 = num_integral2.numpy() # print("DEBUG", value:", vals_reshaped) assert len(integral) == len(func4_values) assert len(integral2) == len(func4_2values[0]) assert func4_3deps_0and2_integrated( x=func4_values, limits=limits4_2dim) == pytest.approx(integral, rel=0.03) assert func4_3deps_1_integrated( x=func4_2values, limits=limits4_1dim) == pytest.approx(integral2, rel=0.03)
def test_multiple_limits(): gauss_params1 = create_gauss1() dims = (0, ) simple_limits = (-3.2, 9.1) multiple_limits_lower = ((-3.2, ), (1.1, ), (2.1, )) multiple_limits_upper = ((1.1, ), (2.1, ), (9.1, )) multiple_limits_range = Space.from_axes(limits=(multiple_limits_lower, multiple_limits_upper), axes=dims) integral_simp = gauss_params1.integrate(limits=simple_limits, norm_range=False) integral_mult = gauss_params1.integrate(limits=multiple_limits_range, norm_range=False) integral_simp_num = gauss_params1.numeric_integrate(limits=simple_limits, norm_range=False) integral_mult_num = gauss_params1.numeric_integrate( limits=multiple_limits_range, norm_range=False) integral_simp, integral_mult = zfit.run([integral_simp, integral_mult]) integral_simp_num, integral_mult_num = zfit.run( [integral_simp_num, integral_mult_num]) assert integral_simp == pytest.approx( integral_mult, rel=1e-2) # big tolerance as mc is used assert integral_simp == pytest.approx( integral_simp_num, rel=1e-2) # big tolerance as mc is used assert integral_simp_num == pytest.approx( integral_mult_num, rel=1e-2) # big tolerance as mc is used
def probs_4d(values): true_prob = [gauss1.pdf(values[:, 3])] true_prob += [gauss2.pdf(values[:, 0])] true_prob += [gauss3.pdf(values[:, 2])] true_prob += [prod_gauss_3d.pdf(values[:, 0:3], norm_range=Space(limits=(((-5,) * 3,), ((4,) * 3,)), obs=['a', 'b', 'c']))] return tf.math.reduce_prod(true_prob, axis=0)
def test_prod_gauss_nd_mixed(): norm_range = (-5, 4) low, high = norm_range test_values = np.random.uniform(low=low, high=high, size=(1000, 4)) obs4d = ['a', 'b', 'c', 'd'] test_values_data = Data.from_tensor(obs=obs4d, tensor=test_values) # prod_gauss_4d.update_integration_options(draws_per_dim=10) limits_4d = Space(limits=(((-5, ) * 4, ), ((4, ) * 4, )), obs=obs4d) prod_gauss_4d = product_gauss_4d() prod_gauss_4d.set_norm_range(limits_4d) probs = prod_gauss_4d.pdf(x=test_values_data, norm_range=limits_4d) gausses = create_gaussians() for gauss in (gausses): gauss.set_norm_range(norm_range) gauss1, gauss2, gauss3 = gausses prod_gauss_3d = product_gauss_3d() def probs_4d(values): true_prob = [gauss1.pdf(values[:, 3])] true_prob += [gauss2.pdf(values[:, 0])] true_prob += [gauss3.pdf(values[:, 2])] true_prob += [ prod_gauss_3d.pdf(values[:, (0, 1, 2)], norm_range=Space(limits=(((-5, ) * 3, ), ((4, ) * 3, )), obs=['a', 'b', 'c'])) ] return np.prod(true_prob, axis=0) true_unnormalized_probs = probs_4d(values=test_values) normalization_probs = limits_4d.area() * probs_4d( np.random.uniform(low=low, high=high, size=(40**4, 4))) true_probs = true_unnormalized_probs / tf.reduce_mean( input_tensor=normalization_probs) grad = tf.gradients(ys=probs, xs=list(prod_gauss_4d.get_dependents())) probs_np = zfit.run(probs) grad_np = zfit.run(grad) print("Gradients", grad_np) print(np.average(probs_np)) true_probs_np = zfit.run(true_probs) assert np.average(probs_np * limits_4d.area()) == pytest.approx( 1., rel=0.33) # low n mc np.testing.assert_allclose(true_probs_np, probs_np, rtol=2e-2)
def normalization_testing(pdf): with pdf.set_norm_range(Space(obs=obs1, limits=(low, high))): samples = tf.cast(np.random.uniform(low=low, high=high, size=(40000, pdf.n_obs)), dtype=tf.float64) samples = zfit.Data.from_tensor(obs=pdf.obs, tensor=samples) probs = pdf.pdf(samples) result = probs.numpy() result = np.average(result) * (high - low) assert pytest.approx(result, rel=0.07) == 1
def probs_4d(values): true_prob = [gauss1.pdf(values[:, 3], norm_range=norm_range)] true_prob += [gauss2.pdf(values[:, 0], norm_range=norm_range)] true_prob += [gauss3.pdf(values[:, 2], norm_range=norm_range)] true_prob += [ prod_gauss_3d.pdf(values[:, (0, 1, 2)], norm_range=Space(limits=(((-5, ) * 3, ), ((4, ) * 3, )), obs=['a', 'b', 'c'])) ] return np.prod(true_prob, axis=0)
def test_analytic_integral_selection(): class DistFuncInts(zbasepdf.BasePDF): def _unnormalized_pdf(self, x, norm_range=False): return x ** 2 int1 = lambda x: 1 # on purpose wrong signature but irrelevant (not called, only test bookkeeping) int2 = lambda x: 2 int22 = lambda x: 22 int3 = lambda x: 3 int4 = lambda x: 4 int5 = lambda x: 5 limits1 = (-1, 5) dims1 = (1,) limits1 = Space.from_axes(axes=dims1, limits=limits1) limits2 = (Space.ANY_LOWER, 5) dims2 = (1,) limits2 = Space.from_axes(axes=dims2, limits=limits2) limits3 = ((Space.ANY_LOWER, 1),), ((Space.ANY_UPPER, 5),) dims3 = (0, 1) limits3 = Space.from_axes(axes=dims3, limits=limits3) limits4 = (((Space.ANY_LOWER, 0, Space.ANY_LOWER),), ((Space.ANY_UPPER, 5, 42),)) dims4 = (0, 1, 2) limits4 = Space.from_axes(axes=dims4, limits=limits4) limits5 = (((Space.ANY_LOWER, 1),), ((10, Space.ANY_UPPER),)) dims5 = (1, 2) limits5 = Space.from_axes(axes=dims5, limits=limits5) DistFuncInts.register_analytic_integral(int1, limits=limits1) DistFuncInts.register_analytic_integral(int2, limits=limits2) DistFuncInts.register_analytic_integral(int22, limits=limits2, priority=60) DistFuncInts.register_analytic_integral(int3, limits=limits3) DistFuncInts.register_analytic_integral(int4, limits=limits4) DistFuncInts.register_analytic_integral(int5, limits=limits5) dims = DistFuncInts._analytic_integral.get_max_axes(limits=Space.from_axes(limits=(((-5, 1),), ((1, 5),)), axes=dims3)) assert dims3 == dims
def test_prod_gauss_nd(): test_values = np.random.random(size=(10, 3)) lower = ((-5, -5, -5),) upper = ((4, 4, 4),) obs1 = ['a', 'b', 'c'] norm_range_3d = Space(obs=obs1, limits=(lower, upper)) test_values_data = Data.from_tensor(obs=obs1, tensor=test_values) product_pdf = product_gauss_3d() probs = product_pdf.pdf(x=test_values_data, norm_range=norm_range_3d) true_probs = np.prod( [gauss.pdf(test_values[:, i], norm_range=(-5, 4)) for i, gauss in enumerate(create_gaussians())], axis=0) probs_np = probs.numpy() np.testing.assert_allclose(true_probs, probs_np, rtol=1e-2)
def test_prod_gauss_nd(): # return test_values = np.random.random(size=(10, 3)) lower = ((-5, -5, -5), ) upper = ((4, 4, 4), ) obs1 = ['a', 'b', 'c'] norm_range_3d = Space(obs=obs1, limits=(lower, upper)) test_values_data = Data.from_tensor(obs=obs1, tensor=test_values) probs = prod_gauss_3d.pdf(x=test_values_data, norm_range=norm_range_3d) true_probs = np.prod([ gauss.pdf(test_values[:, i], norm_range=(-5, 4)) for i, gauss in enumerate(gauss_dists) ]) probs_np = zfit.run(probs) np.testing.assert_allclose(zfit.run(true_probs), probs_np, rtol=1e-2)
def test_analytic_sampling(): class SampleGauss(TestGaussian): pass SampleGauss.register_analytic_integral(func=lambda limits, params, model: 2 * limits.upper[0][0], limits=Space.from_axes(limits=(-float("inf"), ANY_UPPER), axes=(0,))) # DUMMY! SampleGauss.register_inverse_analytic_integral(func=lambda x, params: x + 1000.) gauss1 = SampleGauss(obs=obs1) sample = gauss1.sample(n=10000, limits=(2., 5.)) sample = zfit.run(sample) assert 1004. <= min(sample[0]) assert 10010. >= max(sample[0])
def test_normalization(pdf_factory): test_yield = 1524.3 dist = pdf_factory() samples = tf.cast(np.random.uniform(low=low, high=high, size=100000), dtype=tf.float64) small_samples = tf.cast(np.random.uniform(low=low, high=high, size=10), dtype=tf.float64) with dist.set_norm_range(Space(obs1, limits=(low, high))): samples.limits = low, high probs = dist.pdf(samples) probs_small = dist.pdf(small_samples) log_probs = dist.log_pdf(small_samples) probs, log_probs = zfit.run([probs, log_probs]) probs = np.average(probs) * (high - low) assert probs == pytest.approx(1., rel=0.05) assert log_probs == pytest.approx(zfit.run(tf.log(probs_small)), rel=0.05) dist = dist.create_extended(ztf.constant(test_yield)) probs_extended = dist.pdf(samples) result_extended = zfit.run(probs_extended) result_extended = np.average(result_extended) * (high - low) assert result_extended == pytest.approx(1, rel=0.05)
def test_analytic_sampling(): class SampleGauss(TestGaussian): pass SampleGauss.register_analytic_integral( func=lambda limits, params, model: 2 * limits.upper[0][0], limits=Space.from_axes(limits=(-float("inf"), ANY_UPPER), axes=(0, ))) # DUMMY! SampleGauss.register_inverse_analytic_integral( func=lambda x, params: x + 1000.) mu, sigma = create_mu_sigma_true_params() gauss1 = SampleGauss(obs=obs1, mu=mu, sigma=sigma) sample = gauss1.sample(n=10000, limits=(2., 5.)) sample.set_data_range((1002, 1005)) sample = sample.numpy() assert 1004. <= min(sample[0]) assert 10010. >= max(sample[0])
def test_normalization(): test_yield = 1524.3 samples = tf.cast(np.random.uniform(low=low, high=high, size=100000), dtype=tf.float64) small_samples = tf.cast(np.random.uniform(low=low, high=high, size=10), dtype=tf.float64) for dist in gaussian_dists + [wrapped_gauss, wrapped_normal1]: with dist.set_norm_range(Space(obs1, limits=(low, high))): samples.limits = low, high print("Testing currently: ", dist.name) probs = dist.pdf(samples) probs_small = dist.pdf(small_samples) log_probs = dist.log_pdf(small_samples) probs, log_probs = zfit.run([probs, log_probs]) probs = np.average(probs) * (high - low) assert probs == pytest.approx(1., rel=0.05) assert log_probs == pytest.approx(zfit.run(tf.log(probs_small)), rel=0.05) dist = dist.create_extended(ztf.constant(test_yield)) probs_extended = dist.pdf(samples) result_extended = zfit.run(probs_extended) result_extended = np.average(result_extended) * (high - low) assert result_extended == pytest.approx(1, rel=0.05)
def test_exception(): invalid_obs = (1, 4) with pytest.raises(ValueError): Space(obs=invalid_obs) with pytest.raises(ObsNotSpecifiedError): Space(obs=None, limits=limit2) with pytest.raises(AxesNotSpecifiedError): Space.from_axes(axes=None, limits=limit2) with pytest.raises(ValueError): # one obs only, but two dims Space(obs='obs1', limits=(((1, 2), ), ((2, 3), ))) with pytest.raises(ValueError): # two obs but only 1 dim Space(obs=['obs1', 'obs2'], limits=(((1, ), ), ((2, ), ))) with pytest.raises(ValueError): # one axis but two dims Space.from_axes(axes=(1, ), limits=(((1, 2), ), ((2, 3), ))) with pytest.raises(ValueError): # two axes but only 1 dim Space.from_axes(axes=(1, 2), limits=(((1, ), ), ((2, ), ))) with pytest.raises( ValueError): # two obs, two limits but each one only 1 dim Space(obs=['obs1', 'obs2'], limits=(((1, ), (2, )), ((2, ), (3, ))))
sigma3_true = 1.8 fracs = [0.3, 0.15] def true_gaussian_sum(x): def norm(sigma): return np.sqrt(2 * np.pi) * sigma sum_gauss = fracs[0] * np.exp(- (x - mu1_true) ** 2 / (2 * sigma1_true ** 2)) / norm(sigma1_true) sum_gauss += fracs[1] * np.exp(- (x - mu2_true) ** 2 / (2 * sigma2_true ** 2)) / norm(sigma2_true) sum_gauss += (1. - sum(fracs)) * np.exp(- (x - mu3_true) ** 2 / (2 * sigma3_true ** 2)) / norm(sigma3_true) return sum_gauss obs1 = Space(obs='obs1') def create_params(name_add=""): mu1 = Parameter("mu1" + name_add, mu1_true) mu2 = Parameter("mu2" + name_add, mu2_true) mu3 = Parameter("mu3" + name_add, mu3_true) sigma1 = Parameter("sigma1" + name_add, sigma1_true) sigma2 = Parameter("sigma2" + name_add, sigma2_true) sigma3 = Parameter("sigma3" + name_add, sigma3_true) return mu1, mu2, mu3, sigma1, sigma2, sigma3 def create_gaussians() -> List[ZfitPDF]: # Gauss for sum, same axes mu1, mu2, mu3, sigma1, sigma2, sigma3 = create_params()
def test_dimensions(): lower1, lower2 = 1, 2 upper1, upper2 = 2, 3 space = Space(obs=['obs1', 'obs2'], limits=(((lower1, lower2), ), ((upper1, upper2), ))) assert space.n_obs == 2 assert space.n_limits == 1 low1, low2, up1, up2 = space.limit2d assert low1 == lower1 assert low2 == lower2 assert up1 == upper1 assert up2 == upper2 with pytest.raises(RuntimeError): space.limit1d space = Space(obs='obs1', limits=(((1, ), (2, )), ((2, ), (3, )))) assert space.n_obs == 1 assert space.n_limits == 2 with pytest.raises(RuntimeError): space.limit2d space = Space(obs=['obs1', 'obs2'], limits=(((1, 5), (2, 4)), ((2, 3), (3, 2)))) assert space.n_obs == 2 assert space.n_limits == 2 with pytest.raises(RuntimeError): space.limit2d space.limits1d space = Space(obs='obs1', limits=(((1, ), ), ((2, ), ))) assert space.n_obs == 1 assert space.n_limits == 1 space = Space(obs=['obs1', 'obs2'], limits=(((1, 5), (2, 4), (1, 5), (2, 4)), ((2, 3), (3, 2), (1, 5), (2, 4)))) assert space.n_obs == 2 assert space.n_limits == 4 space = Space(obs=['obs1', 'obs2', 'obs3', 'obs4'], limits=(((1, 5, 2, 4), (1, 5, 2, 4)), ((2, 3, 3, 2), (1, 5, 2, 4)))) assert space.n_obs == 4 assert space.n_limits == 2 lower1, lower2, upper1, upper2 = 1, 2, 2, 3 space = Space.from_axes(axes=(1, ), limits=(((lower1, ), (lower2, )), ((upper1, ), (upper2, )))) assert space.n_obs == 1 assert space.n_limits == 2 low1, low2, up1, up2 = space.limits1d with pytest.raises(RuntimeError): space.limit1d space = Space.from_axes(axes=(1, 2), limits=(((1, 5), (2, 4)), ((2, 3), (3, 2)))) assert space.n_obs == 2 assert space.n_limits == 2 with pytest.raises(RuntimeError): space.limit1d lower1 = 1 upper1 = 2 space = Space.from_axes(axes=(1, ), limits=(((lower1, ), ), ((upper1, ), ))) assert space.n_obs == 1 assert space.n_limits == 1 lower, upper = space.limit1d assert lower == lower1 assert upper == upper1 space = Space.from_axes(axes=(1, 2, 4, 5), limits=(((1, 5, 2, 4), (1, 5, 2, 4)), ((2, 3, 3, 2), (1, 5, 2, 4)))) assert space.n_obs == 4 assert space.n_limits == 2
import pytest from zfit.core.limits import Space, convert_to_space # noinspection PyUnresolvedReferences from zfit.core.testing import setup_function, teardown_function, tester from zfit.util.exception import ObsNotSpecifiedError, AxesNotSpecifiedError, LimitsUnderdefinedError lower1 = (1, ), (4, ) upper1 = (3, ), (7, ) limit1 = lower1, upper1 limit1_true = copy.deepcopy(limit1) limit1_areas = (2, 3) limit1_axes = (1, ) limit1_obs = ("obs1", ) limit1_axes_true = limit1_axes space1 = Space.from_axes(limits=limit1, axes=limit1_axes) space1_obs = Space(obs=limit1_obs, limits=limit1) arguments1 = (space1, lower1, upper1, limit1_true, limit1_axes, limit1_areas, 2) lower2 = (1, 2, 3), (-4, -5, 5) upper2 = (2, 4, 6), (-1, 5, 5.6) sub_lower2 = (1, 3), (-4, 5) sub_upper2 = (2, 6), (-1, 5.6) limit2 = lower2, upper2 sub_limit2 = sub_lower2, sub_upper2 limit2_areas = (6, 18) sub_limit2_areas = (3, 1.8) limit2_axes = (1, 5, 6) sub_limit2_axes = (1, 6) limit2_obs = ('obs1', 'obs2', 'obs3')