def auto_alien1(data, config, data_dir=None):
    "\n    Removes aliens from experimental CDI data using iterative algorithm and returns the result.\n    \n    The algorithm follows the steps:\n    1. Initialization:\n    - initialize variables with the configuration parameters\n    - crop the data array around maximum element to it's biggest size\n    - sets points below threshold value to 0\n    - finds non-zero elements of the data array and keeps them as tuples of indices\n    2. Iteration loop, runs until number of clasters remains unchanged\n    - runs DBSCAN algorithm on the non-zero and returns clasters labels\n    - analyzes the results to find relative clusters sizes, and clusters average asymmetry, and other characteristics\n    - removes alien clusters, i.e. the ones with relative cluster size below configured size threshold and with average asymmetry over configured asymmetry threshold\n    - go back to the loop using the non-zero elements of alien removed array to the DBSCAN\n    3. If configured, add final step to apply gaussian convolusion to the result and use it as a filter with configured sigma as threshold\n    \n    Parameters\n    ----------\n    data : ndarray\n        an array with experiment data\n    config : Object\n        configuration object providing access to configuration parameters\n    data_dir : str\n        a directory where 'alien_analysis' subdirectory will be created to save results of analysis if configured\n\n    Returns\n    -------\n    cuboid : ndarray\n        data array with removed aliens\n    "
    try:
        size_threshold = config.AA1_size_threshold
    except AttributeError:
        size_threshold = 0.01
    except Exception as e:
        print('error parsing AA1_size_threshold ', str(e))
    try:
        asym_threshold = config.AA1_asym_threshold
    except AttributeError:
        asym_threshold = 1.75
    except Exception as e:
        print('error parsing AA1_asym_threshold ', str(e))
    try:
        min_pts = config.AA1_min_pts
    except AttributeError:
        min_pts = 5
    except Exception as e:
        print('error parsing AA1_min_pts ', str(e))
    try:
        eps = config.AA1_eps
    except AttributeError:
        eps = 1.1
    except Exception as e:
        print('error parsing AA1_eps ', str(e))
    try:
        threshold = config.AA1_amp_threshold
    except AttributeError:
        print('AA1_amp_threshold parameter not configured, not removing aliens')
        return data
    except Exception as e:
        print('error parsing AA1_amp_threshold ', str(e))
    try:
        save_arrs = config.AA1_save_arrs
        if save_arrs:
            save_dir = os.path.join(data_dir, 'alien_analysis')
            if (not os.path.exists(save_dir)):
                os.makedirs(save_dir)
    except AttributeError:
        save_arrs = False
    except Exception as e:
        print('error parsing save_arrs ', str(e))
    try:
        expandcleanedsig = config.AA1_expandcleanedsigma
    except AttributeError:
        expandcleanedsig = 0.0
    except Exception as e:
        print('error parsing expandcleanedsig ', str(e))
    cuboid = crop_center(data)
    cuboid = np.where((cuboid >= threshold), cuboid, 0)
    if save_arrs:
        save_arr(cuboid, save_dir, ('db%3.2f_cuboid%3.2f.tif' % (threshold, eps)))
        save_arr(cuboid[::(- 1), ::(- 1), ::(- 1)], save_dir, ('db%3.2f_cuboidrev%3.2f.tif' % (threshold, eps)))
    non_zero = cuboid.nonzero()
    iter = 0
    nclusters = 0
    finished = False
    while (not finished):
        non_zero = cuboid.nonzero()
        labels = DBSCAN(eps=eps, metric='euclidean', min_samples=min_pts, n_jobs=(- 1)).fit_predict(np.array(non_zero).transpose().astype(np.float32))
        arrs = analyze_clusters(cuboid, labels, non_zero)
        if save_arrs:
            save_arrays(arrs, iter, threshold, eps, save_dir)
        if (nclusters == arrs[0]):
            finished = True
        nclusters = arrs[0]
        if (iter == 0):
            rel_cluster_size = arrs[2]
            cluster_avg_asym = arrs[7]
        cuboid = np.where(np.logical_and((rel_cluster_size < size_threshold), (cluster_avg_asym > asym_threshold)), 0.0, cuboid)
        iter += 1
    if (expandcleanedsig > 0):
        cuboid = np.where((cuboid > 0), 1.0, 0.0)
        sig = [expandcleanedsig, expandcleanedsig, 1.0]
        cuboid = ut.gauss_conv_fft(cuboid, sig)
        no_thresh_cuboid = crop_center(data)
        cuboid = np.where((cuboid > 0.1), no_thresh_cuboid, 0.0)
    return cuboid
Removes aliens from experimental CDI data using iterative algorithm and returns the result.

The algorithm follows the steps:
1. Initialization:
- initialize variables with the configuration parameters
- crop the data array around maximum element to it's biggest size
- sets points below threshold value to 0
- finds non-zero elements of the data array and keeps them as tuples of indices
2. Iteration loop, runs until number of clasters remains unchanged
- runs DBSCAN algorithm on the non-zero and returns clasters labels
- analyzes the results to find relative clusters sizes, and clusters average asymmetry, and other characteristics
- removes alien clusters, i.e. the ones with relative cluster size below configured size threshold and with average asymmetry over configured asymmetry threshold
- go back to the loop using the non-zero elements of alien removed array to the DBSCAN
3. If configured, add final step to apply gaussian convolusion to the result and use it as a filter with configured sigma as threshold

Parameters
----------
data : ndarray
    an array with experiment data
config : Object
    configuration object providing access to configuration parameters
data_dir : str
    a directory where 'alien_analysis' subdirectory will be created to save results of analysis if configured

Returns
-------
cuboid : ndarray
    data array with removed aliens
def auto_alien1(data, config, data_dir=None):
    "\n    Removes aliens from experimental CDI data using iterative algorithm and returns the result.\n    \n    The algorithm follows the steps:\n    1. Initialization:\n    - initialize variables with the configuration parameters\n    - crop the data array around maximum element to it's biggest size\n    - sets points below threshold value to 0\n    - finds non-zero elements of the data array and keeps them as tuples of indices\n    2. Iteration loop, runs until number of clasters remains unchanged\n    - runs DBSCAN algorithm on the non-zero and returns clasters labels\n    - analyzes the results to find relative clusters sizes, and clusters average asymmetry, and other characteristics\n    - removes alien clusters, i.e. the ones with relative cluster size below configured size threshold and with average asymmetry over configured asymmetry threshold\n    - go back to the loop using the non-zero elements of alien removed array to the DBSCAN\n    3. If configured, add final step to apply gaussian convolusion to the result and use it as a filter with configured sigma as threshold\n    \n    Parameters\n    ----------\n    data : ndarray\n        an array with experiment data\n    config : Object\n        configuration object providing access to configuration parameters\n    data_dir : str\n        a directory where 'alien_analysis' subdirectory will be created to save results of analysis if configured\n\n    Returns\n    -------\n    cuboid : ndarray\n        data array with removed aliens\n    "
    try:
        size_threshold = config.AA1_size_threshold
    except AttributeError:
        size_threshold = 0.01
    except Exception as e:
        print('error parsing AA1_size_threshold ', str(e))
    try:
        asym_threshold = config.AA1_asym_threshold
    except AttributeError:
        asym_threshold = 1.75
    except Exception as e:
        print('error parsing AA1_asym_threshold ', str(e))
    try:
        min_pts = config.AA1_min_pts
    except AttributeError:
        min_pts = 5
    except Exception as e:
        print('error parsing AA1_min_pts ', str(e))
    try:
        eps = config.AA1_eps
    except AttributeError:
        eps = 1.1
    except Exception as e:
        print('error parsing AA1_eps ', str(e))
    try:
        threshold = config.AA1_amp_threshold
    except AttributeError:
        print('AA1_amp_threshold parameter not configured, not removing aliens')
        return data
    except Exception as e:
        print('error parsing AA1_amp_threshold ', str(e))
    try:
        save_arrs = config.AA1_save_arrs
        if save_arrs:
            save_dir = os.path.join(data_dir, 'alien_analysis')
            if (not os.path.exists(save_dir)):
                os.makedirs(save_dir)
    except AttributeError:
        save_arrs = False
    except Exception as e:
        print('error parsing save_arrs ', str(e))
    try:
        expandcleanedsig = config.AA1_expandcleanedsigma
    except AttributeError:
        expandcleanedsig = 0.0
    except Exception as e:
        print('error parsing expandcleanedsig ', str(e))
    cuboid = crop_center(data)
    cuboid = np.where((cuboid >= threshold), cuboid, 0)
    if save_arrs:
        save_arr(cuboid, save_dir, ('db%3.2f_cuboid%3.2f.tif' % (threshold, eps)))
        save_arr(cuboid[::(- 1), ::(- 1), ::(- 1)], save_dir, ('db%3.2f_cuboidrev%3.2f.tif' % (threshold, eps)))
    non_zero = cuboid.nonzero()
    iter = 0
    nclusters = 0
    finished = False
    while (not finished):
        non_zero = cuboid.nonzero()
        labels = DBSCAN(eps=eps, metric='euclidean', min_samples=min_pts, n_jobs=(- 1)).fit_predict(np.array(non_zero).transpose().astype(np.float32))
        arrs = analyze_clusters(cuboid, labels, non_zero)
        if save_arrs:
            save_arrays(arrs, iter, threshold, eps, save_dir)
        if (nclusters == arrs[0]):
            finished = True
        nclusters = arrs[0]
        if (iter == 0):
            rel_cluster_size = arrs[2]
            cluster_avg_asym = arrs[7]
        cuboid = np.where(np.logical_and((rel_cluster_size < size_threshold), (cluster_avg_asym > asym_threshold)), 0.0, cuboid)
        iter += 1
    if (expandcleanedsig > 0):
        cuboid = np.where((cuboid > 0), 1.0, 0.0)
        sig = [expandcleanedsig, expandcleanedsig, 1.0]
        cuboid = ut.gauss_conv_fft(cuboid, sig)
        no_thresh_cuboid = crop_center(data)
        cuboid = np.where((cuboid > 0.1), no_thresh_cuboid, 0.0)
    return cuboid