diff --git a/Examples/python/fitting/ex11_ExternalMinimizer/lmfit_basics_new.py b/Examples/python/fitting/ex11_ExternalMinimizer/lmfit_basics_new.py
new file mode 100644
index 0000000000000000000000000000000000000000..2d2aab3a0c6de9e17a1b3de22b9d9ccc5fa2ceec
--- /dev/null
+++ b/Examples/python/fitting/ex11_ExternalMinimizer/lmfit_basics_new.py
@@ -0,0 +1,126 @@
+"""
+Example of using external minimizer to fit typical BornAgain simulation
+"""
+import numpy as np
+from matplotlib import pyplot as plt
+import bornagain as ba
+from bornagain import deg, angstrom, nm
+import lmfit
+
+
+real_data = None
+
+def get_sample(params):
+    """
+    Returns a sample with cylinders and pyramids on a substrate,
+    forming a hexagonal lattice.
+    """
+    radius = params['radius'].value
+    lattice_length = params['length'].value
+    print(radius, lattice_length)
+
+    m_air = ba.HomogeneousMaterial("Air", 0.0, 0.0)
+    m_substrate = ba.HomogeneousMaterial("Substrate", 6e-6, 2e-8)
+    m_particle = ba.HomogeneousMaterial("Particle", 6e-4, 2e-8)
+
+    sphere_ff = ba.FormFactorFullSphere(radius)
+    sphere = ba.Particle(m_particle, sphere_ff)
+    particle_layout = ba.ParticleLayout()
+    particle_layout.addParticle(sphere)
+
+    interference = ba.InterferenceFunction2DLattice.createHexagonal(lattice_length)
+    pdf = ba.FTDecayFunction2DCauchy(10*nm, 10*nm)
+    interference.setDecayFunction(pdf)
+
+    particle_layout.setInterferenceFunction(interference)
+
+    air_layer = ba.Layer(m_air)
+    air_layer.addLayout(particle_layout)
+    substrate_layer = ba.Layer(m_substrate, 0)
+    multi_layer = ba.MultiLayer()
+    multi_layer.addLayer(air_layer)
+    multi_layer.addLayer(substrate_layer)
+    return multi_layer
+
+
+def get_simulation(params):
+    """
+    Create and return GISAXS simulation with beam and detector defined
+    """
+    simulation = ba.GISASSimulation()
+    simulation.setDetectorParameters(100, -1.0*deg, 1.0*deg,
+                                     100, 0.0*deg, 2.0*deg)
+    simulation.setBeamParameters(1.0*angstrom, 0.2*deg, 0.0*deg)
+    simulation.setBeamIntensity(1e+08)
+    simulation.setSample(get_sample(params))
+    return simulation
+
+
+def create_real_data():
+    """
+    Generating "real" data by adding noise to the simulated data.
+    """
+    params = lmfit.Parameters()
+    params.add('radius', value=5*nm)
+    params.add('length', value=10*nm)
+    simulation = get_simulation(params)
+    simulation.runSimulation()
+
+    # retrieving simulated data in the form of numpy array
+    real_data = simulation.result().array()
+
+    # spoiling simulated data with noise to produce "real" data
+    np.random.seed(0)
+    noise_factor = 0.1
+    noisy = np.random.normal(real_data, noise_factor*np.sqrt(real_data))
+    noisy[noisy < 0.1] = 0.1
+    return noisy
+
+
+def residual(params):
+    simulation = get_simulation(params)
+    simulation.runSimulation()
+    result = simulation.result().array().flatten()
+    exp = real_data.flatten()
+    res = result-exp
+    return res
+
+
+def evaluate(params, objective, real_data):
+    bapars = ba.Parameters()
+    print(type(params))
+    for p in params:
+        print(type(p), type(params[p]))
+        bapars.add(p, params[p].value)
+
+    return objective.evaluate_residuals(bapars)
+
+
+
+def run_fitting():
+    """
+    main function to run fitting
+    """
+    global real_data
+    real_data = create_real_data()
+    print(real_data, real_data.shape)
+
+    fit_objective = ba.FitObjective()
+    fit_objective.addSimulationAndData(get_simulation, real_data, 1.0)
+
+    params = lmfit.Parameters()
+    params.add('radius', value=8*nm)
+    params.add('length', value=8*nm)
+
+    result = lmfit.minimize(evaluate, params, args=(fit_objective, real_data))
+
+    result.params.pretty_print()
+    print(lmfit.fit_report(result))
+    print("Done")
+
+
+if __name__ == '__main__':
+    run_fitting()
+    plt.show()
+
+