diff --git a/.gitignore b/.gitignore
index 312a681c5e63e704ff86e4e9030f841dfd20c91b..ae878af4de378213b3aa88b306f0c10bd8b6689c 100755
--- a/.gitignore
+++ b/.gitignore
@@ -2,10 +2,6 @@
 /figures/
 /results/
 /logs/
-*.hdf5
-*.png
-*.eps
-*.mp4
 
 #jupyter checkpoints
 .ipynb_checkpoints/
diff --git a/MANIFEST.in b/MANIFEST.in
old mode 100644
new mode 100755
index 523902ae46b58a1345f8fb9541aa9d2c4c3b5f0b..273f97285be35932338beea1a8b651dc7a238e12
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,2 +1,6 @@
-global-include *.pyx
-global-include *.c
\ No newline at end of file
+graft tests
+graft pyrost/config
+graft pyrost/bin
+exclude dev.pyx
+global-exclude *.py[cod]
+global-exclude *.so
\ No newline at end of file
diff --git a/docs/conf.py b/docs/conf.py
index 656459407afa16be7eccdbafda3df3c587ad8bd9..786ec05d72bc032d7f39978906ab07f7ec4f5f4a 100755
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -12,8 +12,8 @@
 #
 import os
 import sys
-
-sys.path.insert(0, os.path.abspath('..'))
+import pyrost
+# sys.path.insert(0, os.path.abspath('..'))
 
 # -- Project information -----------------------------------------------------
 
@@ -22,7 +22,7 @@ copyright = '2020, Nikolay Ivanov'
 author = 'Nikolay Ivanov'
 
 # The full version, including alpha/beta/rc tags
-release = '0.1.2'
+release = '0.1.3'
 
 
 # -- General configuration ---------------------------------------------------
diff --git a/docs/figures/1d_sim_fits.png b/docs/figures/1d_sim_fits.png
new file mode 100755
index 0000000000000000000000000000000000000000..5cf4ce0369f204c5e5034c39fccfad31276ed9d5
Binary files /dev/null and b/docs/figures/1d_sim_fits.png differ
diff --git a/docs/figures/1d_sim_res.png b/docs/figures/1d_sim_res.png
new file mode 100755
index 0000000000000000000000000000000000000000..a2d550451abe9f50318a0026c74c23b6289c9e72
Binary files /dev/null and b/docs/figures/1d_sim_res.png differ
diff --git a/docs/figures/diatom_image.png b/docs/figures/diatom_image.png
new file mode 100755
index 0000000000000000000000000000000000000000..229d9e32776b90ddcd199241f7834dc0dfbf17bb
Binary files /dev/null and b/docs/figures/diatom_image.png differ
diff --git a/docs/figures/diatom_phase.png b/docs/figures/diatom_phase.png
new file mode 100755
index 0000000000000000000000000000000000000000..04ac51669270cc1dfd024c91c71e6d39b5314118
Binary files /dev/null and b/docs/figures/diatom_phase.png differ
diff --git a/docs/figures/phase_fit.png b/docs/figures/phase_fit.png
new file mode 100755
index 0000000000000000000000000000000000000000..8d0676a68d5daeb2c13eda805fe35cb859be43a5
Binary files /dev/null and b/docs/figures/phase_fit.png differ
diff --git a/docs/figures/ptychograph.png b/docs/figures/ptychograph.png
new file mode 100644
index 0000000000000000000000000000000000000000..c01f7623eb463b5b0cc41173d5a3091dfa4d7afa
Binary files /dev/null and b/docs/figures/ptychograph.png differ
diff --git a/docs/figures/sweep_scan.png b/docs/figures/sweep_scan.png
new file mode 100755
index 0000000000000000000000000000000000000000..966dfdfd1cf8acd1155e362c5e0b7609dad5a762
Binary files /dev/null and b/docs/figures/sweep_scan.png differ
diff --git a/pyrost/data_processing.py b/pyrost/data_processing.py
index 7a8a5307d96a01a21b806872966b4073a751f6a8..e9921a1b62e1b74b1774d9e845b1a6d88bf009ed 100755
--- a/pyrost/data_processing.py
+++ b/pyrost/data_processing.py
@@ -693,7 +693,8 @@ class SpeckleTracking(DataContainer):
             return {'pixel_map': pixel_map}
 
     def iter_update(self, sw_fs, sw_ss=0, ls_pm=3., ls_ri=10.,
-                    n_iter=5, f_tol=3e-3, verbose=True, method='search'):
+                    n_iter=5, f_tol=3e-3, verbose=True, method='search',
+                    return_errors=True):
         """Perform iterative Robust Speckle Tracking update. `ls_ri` and
         `ls_pm` define high frequency cut-off to supress the noise.
         Iterative update terminates when the difference between total
@@ -723,6 +724,8 @@ class SpeckleTracking(DataContainer):
             * 'newton' : Iterative Newton's method based on
               finite difference gradient approximation.
             * 'search' : Grid search along the search window.
+        return_errors : bool, optional
+            Return errors array if True.
 
         Returns
         -------
@@ -730,7 +733,8 @@ class SpeckleTracking(DataContainer):
             A new :class:`SpeckleTracking` object with the updated
             `pixel_map` and `reference_image`.
         list
-            List of total MSE values for each iteration.
+            List of total MSE values for each iteration.  Only if
+            `return_errors` is True.
         """
         obj = self.update_reference(ls_ri=ls_ri, sw_ss=sw_ss, sw_fs=sw_fs)
         errors = [obj.total_mse(ls_ri=ls_ri)]
@@ -759,7 +763,10 @@ class SpeckleTracking(DataContainer):
                 print('Iteration No. {:d}: Total MSE = {:.3f}'.format(it, errors[-1]))
             if errors[-2] - errors[-1] <= f_tol:
                 break
-        return obj, errors
+        if return_errors:
+            return obj, errors
+        else:
+            return obj
 
     def total_mse(self, ls_ri=3.):
         """Return average mean-squared-error (MSE) per pixel.
diff --git a/pyrost/simulation/__init__.py b/pyrost/simulation/__init__.py
index 52326949c39d0be0f3cf642aa51961c5bfa36eb9..ee6275bccc096b7fc6ede7a9023b242058b28207 100755
--- a/pyrost/simulation/__init__.py
+++ b/pyrost/simulation/__init__.py
@@ -3,4 +3,4 @@ Speckle Tracking scans. Wavefront propagation is based on
 the Fresnel diffraction theory.
 """
 from .st_sim_param import STParams, parameters
-from .st_sim import STSim, STConverter
\ No newline at end of file
+from .st_sim import STSim, STConverter, converter
diff --git a/pyrost/simulation/st_sim.py b/pyrost/simulation/st_sim.py
index 9887f9eb2f7b86f91c319ff1c1d0bd9cf70fb2b1..3cd9b9f5a6613aff6d7668fce2738b9103b687ac 100755
--- a/pyrost/simulation/st_sim.py
+++ b/pyrost/simulation/st_sim.py
@@ -90,6 +90,7 @@ from sys import stdout
 import h5py
 import numpy as np
 from ..protocol import cxi_protocol, ROOT_PATH
+from ..data_processing import STData
 from .st_sim_param import STParams, parameters
 from ..bin import aperture_wp, barcode_steps, barcode_profile, lens_wp
 from ..bin import make_frames, make_whitefield
@@ -117,14 +118,18 @@ class STSim:
 
     def __init__(self, st_params, bsteps=None):
         self.parameters = st_params
-        self.__dict__.update(**self.parameters.export_dict())
         self._init_logging()
         self._init_coord()
         self._init_lens()
         self._init_barcode(bsteps)
         self._init_detector()
 
+    def __getattr__(self, attr):
+        if attr in self.parameters:
+            return self.parameters.__getattr__(attr)
+
     def _init_logging(self):
+        os.makedirs(self.log_dir, exist_ok=True)
         self.logger = logging.getLogger(self.__class__.__name__)
         self.logger.level = logging.INFO
         filename = os.path.join(self.log_dir, datetime.datetime.now().strftime('%d-%m-%Y_%H-%M-%S.log'))
@@ -314,7 +319,8 @@ class STConverter:
 
     * basis_vectors : Detector basis vectors.
     * data : Measured intensity frames.
-    * defocus : Defocus distance.
+    * defocus_fs : Defocus distance along the fast detector axis.
+    * defocus_ss : Defocus distance along the slow detector axis.
     * distance : Sample-to-detector distance.
     * energy : Incoming beam photon energy [eV].
     * good_frames : An array of good frames' indices.
@@ -353,37 +359,88 @@ class STConverter:
         ini_parsers['protocol'] = self.protocol.export_ini()
         return ini_parsers
 
-    def _pixel_vector(self, st_params):
-        return self.crd_rat * np.array([st_params.pix_size, st_params.pix_size, 0])
+    def export_dict(self, data, st_params):
+        """Export simulated data `data` (fetched from :func:`STSim.frames`
+        or :func:`STSim.ptychograph`) and `st_params` to :class:`dict` object.
+
+        Parameters
+        ----------
+        data : numpy.ndarray
+            Simulated data.
+        st_params : STParams
+            Experimental parameters.
+
+        Returns
+        -------
+        data_dict : dict
+            Dictionary with all the data from `data` and `st_params`.
+
+        See Also
+        --------
+        STConverter - full list of the attributes stored in `data_dict`.
+        """
+        data_dict = {}
+
+        # Initialize basis vectors
+        pix_vec = self.crd_rat * np.array([st_params.pix_size, st_params.pix_size, 0])
+        data_dict['x_pixel_size'] = pix_vec[0]
+        data_dict['y_pixel_size'] = pix_vec[1]
+        vec_fs = np.tile(pix_vec * self.unit_vector_fs, (st_params.n_frames, 1))
+        vec_ss = np.tile(pix_vec * self.unit_vector_ss, (st_params.n_frames, 1))
+        data_dict['basis_vectors'] = np.stack((vec_ss, vec_fs), axis=1)
+
+        # Initialize data
+        data_dict['data'] = data
+        data_dict['good_frames'] = np.arange(data.shape[0],
+                                             dtype=self.protocol.get_dtype('good_frames'))
+        data_dict['mask'] = np.ones(data.shape[1:], dtype=self.protocol.get_dtype('mask'))
+        data_dict['whitefield'] = make_whitefield(mask=data_dict['mask'], data=data)
 
-    def _basis_vectors(self, st_params):
-        pix_vec = self._pixel_vector(st_params)
-        _vec_fs = np.tile(pix_vec * self.unit_vector_fs, (st_params.n_frames, 1))
-        _vec_ss = np.tile(pix_vec * self.unit_vector_ss, (st_params.n_frames, 1))
-        return np.stack((_vec_ss, _vec_fs), axis=1)
+        # Initialize defocus distances
+        data_dict['defocus_fs'] = self.crd_rat * st_params.defocus
+        data_dict['defocus_ss'] = self.crd_rat * st_params.defocus
 
-    def _defocus(self, st_params):
-        return self.crd_rat * st_params.defocus
+        # Initialize sample-to-detector distance
+        data_dict['distance'] = self.crd_rat * st_params.det_dist
 
-    def _distance(self, st_params):
-        return self.crd_rat * st_params.det_dist
+        # Initialize beam's wavelength and energy
+        data_dict['wavelength'] = self.crd_rat * st_params.wl
+        data_dict['energy'] = self.e_to_wl / data_dict['wavelength']
 
-    def _energy(self, st_params):
-        return self.e_to_wl / self._wavelength(st_params)
+        # Initialize region of interest
+        fs_lb, fs_ub = st_params.fs_roi()
+        data_dict['roi'] = np.array([0, data.shape[1], fs_lb, fs_ub])
 
-    def _translations(self, st_params):
-        t_arr = np.zeros((st_params.n_frames, 3), dtype=np.float64)
+        # Initialize sample translations
+        t_arr = np.zeros((st_params.n_frames, 3), dtype=self.protocol.get_dtype('translations'))
         t_arr[:, 0] = -np.arange(0, st_params.n_frames) * st_params.step_size
-        return self.crd_rat * t_arr
+        data_dict['translations'] = self.crd_rat * t_arr
 
-    def _wavelength(self, st_params):
-        return self.crd_rat * st_params.wl
+        for attr in data_dict:
+            data_dict[attr] = np.asarray(data_dict[attr], dtype=self.protocol.get_dtype(attr))
+        return data_dict
+
+    def export_data(self, data, st_params):
+        """Export simulated data `data` (fetched from :func:`STSim.frames`
+        or :func:`STSim.ptychograph`) and `st_params` to a data container.
+
+        Parameters
+        ----------
+        data : numpy.ndarray
+            Simulated data.
+        st_params : STParams
+            Experimental parameters.
 
-    def _x_pixel_size(self, st_params):
-        return self._pixel_vector(st_params)[0]
+        Returns
+        -------
+        STData
+            Data container with all the data from `data` and `st_params`.
 
-    def _y_pixel_size(self, st_params):
-        return self._pixel_vector(st_params)[1]
+        See Also
+        --------
+        STConverter - full list of the attributes stored in `data_dict`.
+        """
+        return STData(protocol=self.protocol, **self.export_dict(data, st_params))
 
     def save_sim(self, data, st_sim, dir_path):
         """Export simulated data `data` (fetched from :func:`STSim.frames`
@@ -409,14 +466,13 @@ class STConverter:
         * {'calc_error.ini', 'calculate_phase.ini', 'generate_pixel_map.ini',
           'make_reference.ini', 'speckle_gui.ini', 'update_pixel_map.ini',
           'update_translations.ini', 'zernike.ini'} : INI files to work with
-          Andrew's `speckle_tracking`_ GUI.
-
-        .. _speckle_tracking: https://github.com/andyofmelbourne/speckle-tracking
+          Andrew's `speckle_tracking <https://github.com/andyofmelbourne/speckle-tracking>`_
+          GUI.
         """
         self.save(data=data, st_params=st_sim.parameters,
                   dir_path=dir_path, logger=st_sim.logger)
 
-    def save(self, data, st_params, dir_path, logger=None, roi=None):
+    def save(self, data, st_params, dir_path, logger=None):
         """Export simulated data `data` (fetched from :func:`STSim.frames`
         or :func:`STSim.ptychograph`) and `st_params` to `dir_path` folder.
 
@@ -430,8 +486,6 @@ class STConverter:
             Path to the folder, where all the files are saved.
         logger : logging.Logger, optional
             Logging interface.
-        roi : numpy.ndarray, optional
-            Region of interest at the detector.
 
         See Also
         --------
@@ -451,23 +505,35 @@ class STConverter:
             logger.info("Making a cxi file...")
             logger.info("Using the following cxi protocol:")
             self.protocol.log(logger)
-        data_dict = {'data': data, 'mask': np.ones(data.shape[1:], dtype=np.uint8),
-                     'good_frames': np.arange(data.shape[0])}
-        data_dict['whitefield'] = make_whitefield(mask=data_dict['mask'], data=data)
-        if roi is None:
-            fs_lb, fs_ub = st_params.fs_roi()
-            roi = np.array([0, data.shape[1], fs_lb, fs_ub])
-        data_dict['roi'] = np.asarray(roi)
+        data_dict = self.export_dict(data, st_params)
         with h5py.File(os.path.join(dir_path, 'data.cxi'), 'w') as cxi_file:
-            for attr in self.write_attrs:
-                if attr in data_dict:
-                    self.protocol.write_cxi(attr, data_dict[attr], cxi_file)
-                else:
-                    dset = self.__getattribute__('_' + attr)(st_params)
-                    self.protocol.write_cxi(attr, dset, cxi_file)
+            for attr in data_dict:
+                self.protocol.write_cxi(attr, data_dict[attr], cxi_file)
         if logger:
             logger.info("{:s} saved".format(os.path.join(dir_path, 'data.cxi')))
 
+def converter(coord_ratio=1e-6, float_precision='float64'):
+    """Return the default simulation converter.
+
+    Parameters
+    ----------
+    coord_ratio : float, optional
+        Coordinates ratio between the simulated and saved data.
+    float_precision: {'float32', 'float64'}, optional
+        Floating point precision.
+
+    Returns
+    -------
+    STConverter
+        Default simulation data converter.
+
+    See Also
+    --------
+    STConverter : Full converter class description.
+    """
+    return STConverter(protocol=cxi_protocol(float_precision),
+                       coord_ratio=coord_ratio)
+
 def main():
     """Main fuction to run Speckle Tracking simulation and save the results to a CXI file.
     """
diff --git a/pyrost/simulation/st_sim_param.py b/pyrost/simulation/st_sim_param.py
index c6e0e3623ae3d9c8956bec68095d34669cb06b7d..590a2db87bc3b888bc514578eaa61752b4241949 100755
--- a/pyrost/simulation/st_sim_param.py
+++ b/pyrost/simulation/st_sim_param.py
@@ -126,6 +126,12 @@ class STParams(INIParser):
         super(STParams, self).__init__(**kwargs)
         self.__dict__['_lookup'] = self.lookup_dict()
 
+    def __iter__(self):
+        return self._lookup.__iter__()
+
+    def __contains__(self, attr):
+        return attr in self._lookup
+
     def __getattr__(self, attr):
         if attr in self._lookup:
             return self.__dict__[self._lookup[attr]][attr]
diff --git a/pytest.ini b/pytest.ini
index b30dddcd92a195a3dde59278db4f7f16d82c230a..6e7ae8f6073cc6bdfd5a6073298ccba274d18590 100644
--- a/pytest.ini
+++ b/pytest.ini
@@ -1,4 +1,5 @@
 [pytest]
 markers = 
     st_sim: test Speckle Tracking simulation package
-    rst: rest Robust Speckle Tracking package
\ No newline at end of file
+    rst: test Robust Speckle Tracking package
+    standalone: standalone test
\ No newline at end of file
diff --git a/setup.cfg b/setup.cfg
deleted file mode 100644
index 9af7e6f11bb01f7306f796faf7bfbe3e2955cd94..0000000000000000000000000000000000000000
--- a/setup.cfg
+++ /dev/null
@@ -1,2 +0,0 @@
-[aliases]
-test=pytest
\ No newline at end of file
diff --git a/setup.py b/setup.py
old mode 100644
new mode 100755
index fd2a4be6d6a3a7872b1effcabbecf10233882331..c4a850a8a034992851946031fb1208e2eb84db9f
--- a/setup.py
+++ b/setup.py
@@ -42,7 +42,7 @@ with open('README.md', 'r') as readme:
     long_description = readme.read()
 
 setup(name='pyrost',
-      version='0.1.2',
+      version='0.1.3',
       author='Nikolay Ivanov',
       author_email="nikolay.ivanov@desy.de",
       long_description=long_description,
@@ -50,11 +50,10 @@ setup(name='pyrost',
       url="https://github.com/simply-nicky/rst",
       packages=find_packages(),
       include_package_data=True,
-      package_data={'pyrost.bin': ['*.pyx']},
+      package_data={'pyrost.bin': ['*.pyx', '*.c'],
+                    'pyrost': ['config/*.ini']},
       install_requires=['Cython', 'CythonGSL', 'h5py', 'numpy', 'scipy',],
       extras_require={'interactive': ['matplotlib', 'jupyter', 'pyximport']},
-      setup_requires=['pytest-runner'],
-      tests_require=['pytest'],
       ext_modules=extensions,
       classifiers=[
           "Programming Language :: Python",
diff --git a/test_pyrost.py b/tests/test_pyrost.py
similarity index 80%
rename from test_pyrost.py
rename to tests/test_pyrost.py
index aa07065d61622d581fafaf4368f8f4a2a916bc25..0ed993abca8b7a37caaab6287caa27e38b0ecaa1 100755
--- a/test_pyrost.py
+++ b/tests/test_pyrost.py
@@ -4,9 +4,9 @@ import pyrost as rst
 import pyrost.simulation as st_sim
 import numpy as np
 
-@pytest.fixture(params=[{'det_dist': 5e5, 'n_frames': 10, 'ap_x': 5,
+@pytest.fixture(params=[{'det_dist': 5e5, 'n_frames': 10, 'ap_x': 4,
                          'ap_y': 1, 'focus': 3e3, 'defocus': 2e2},
-                        {'det_dist': 4.5e5, 'n_frames': 5, 'ap_x': 8,
+                        {'det_dist': 4.5e5, 'n_frames': 5, 'ap_x': 3,
                          'ap_y': 1.5, 'focus': 2e3, 'defocus': 1e2}])
 def st_params(request):
     """Return a default instance of simulation parameters.
@@ -45,10 +45,17 @@ def exp_data_2d(request):
 @pytest.fixture(params=['float32', 'float64'])
 def loader(request):
     """
-    Return a default cxi protocol
+    Return the default loader.
     """
     return rst.loader(request.param)
 
+@pytest.fixture(params=['float32', 'float64'])
+def converter(request):
+    """
+    Return the default loader.
+    """
+    return st_sim.converter(float_precision=request.param)
+
 @pytest.fixture(scope='function')
 def ini_path():
     """Return a path to the experimental speckle tracking data.
@@ -68,8 +75,8 @@ def test_st_params(st_params, ini_path):
 
 @pytest.mark.st_sim
 def test_st_sim(st_params):
-    sim = st_sim.STSim(st_params)
-    ptych = sim.ptychograph()
+    with st_sim.STSim(st_params) as sim_obj:
+        ptych = sim_obj.ptychograph()
     assert len(ptych.shape) == 3
     assert ptych.shape[0] == st_params.n_frames
 
@@ -95,6 +102,7 @@ def test_iter_update(sim_data, loader):
     data_path = os.path.join(sim_data, 'data.cxi')
     assert os.path.isfile(data_path)
     st_data = loader.load(data_path, roi=(0, 1, 400, 1450))
+    assert st_data.data.dtype == loader.protocol.known_types['float']
     st_obj = st_data.get_st()
     pixel_map0 = st_obj.pixel_map.copy()
     st_obj.iter_update(sw_ss=0, sw_fs=150, ls_pm=2.5, ls_ri=15,
@@ -108,3 +116,15 @@ def test_data_process_routines(exp_data_2d, loader):
     data = loader.load(**exp_data_2d)
     data = data.make_mask(method='eiger-bad')
     assert (data.get('whitefield') <= 65535).all()
+
+@pytest.mark.standalone
+def test_full(st_params, converter):
+    with st_sim.STSim(st_params) as sim_obj:
+        ptych = sim_obj.ptychograph()
+        data = converter.export_data(ptych, st_params)
+    assert data.data.dtype == converter.protocol.known_types['float']
+    st_obj = data.get_st()
+    st_res = st_obj.iter_update(sw_fs=20, ls_pm=3, ls_ri=5,
+                                verbose=True, n_iter=10, return_errors=False)
+    assert (st_obj.pixel_map != st_res.pixel_map).any()
+    assert st_res.pixel_map.dtype == converter.protocol.known_types['float']
\ No newline at end of file