changeset 10:ac40a2fe5750 draft

"planemo upload for repository https://github.com/bgruening/galaxytools/tree/master/tools/sklearn commit e2a5eade6d0e5ddf3a47630381a0ad90d80e8a04"
author bgruening
date Tue, 13 Apr 2021 17:21:05 +0000
parents b78007bf1cb8
children 2b679bb676be
files fitted_model_eval.py keras_deep_learning.py keras_train_and_eval.py main_macros.xml ml_visualization_ex.py model_prediction.py pca.py search_model_validation.py simple_model_fit.py stacking_ensembles.py stacking_ensembles.xml test-data/keras_batch_params01.tabular test-data/keras_batch_params04.tabular test-data/keras_model01 test-data/keras_model02 test-data/keras_model04 test-data/keras_params04.tabular test-data/ohe_in_w_header.tabular test-data/ohe_in_wo_header.tabular test-data/ohe_out_4.tabular test-data/ohe_out_5.tabular test-data/pipeline_params05.tabular test-data/pipeline_params18 test-data/train_test_eval_model01 test-data/train_test_eval_weights01.h5 test-data/train_test_eval_weights02.h5 to_categorical.py train_test_eval.py train_test_split.py
diffstat 29 files changed, 3382 insertions(+), 3085 deletions(-) [+]
line wrap: on
line diff
--- a/fitted_model_eval.py	Thu Oct 01 19:54:05 2020 +0000
+++ b/fitted_model_eval.py	Tue Apr 13 17:21:05 2021 +0000
@@ -11,7 +11,7 @@
 
 
 def _get_X_y(params, infile1, infile2):
-    """ read from inputs and output X and y
+    """read from inputs and output X and y
 
     Parameters
     ----------
@@ -26,35 +26,40 @@
     # store read dataframe object
     loaded_df = {}
 
-    input_type = params['input_options']['selected_input']
+    input_type = params["input_options"]["selected_input"]
     # tabular input
-    if input_type == 'tabular':
-        header = 'infer' if params['input_options']['header1'] else None
-        column_option = (params['input_options']['column_selector_options_1']
-                         ['selected_column_selector_option'])
-        if column_option in ['by_index_number', 'all_but_by_index_number',
-                             'by_header_name', 'all_but_by_header_name']:
-            c = params['input_options']['column_selector_options_1']['col1']
+    if input_type == "tabular":
+        header = "infer" if params["input_options"]["header1"] else None
+        column_option = params["input_options"]["column_selector_options_1"]["selected_column_selector_option"]
+        if column_option in [
+            "by_index_number",
+            "all_but_by_index_number",
+            "by_header_name",
+            "all_but_by_header_name",
+        ]:
+            c = params["input_options"]["column_selector_options_1"]["col1"]
         else:
             c = None
 
         df_key = infile1 + repr(header)
-        df = pd.read_csv(infile1, sep='\t', header=header,
-                         parse_dates=True)
+        df = pd.read_csv(infile1, sep="\t", header=header, parse_dates=True)
         loaded_df[df_key] = df
 
         X = read_columns(df, c=c, c_option=column_option).astype(float)
     # sparse input
-    elif input_type == 'sparse':
-        X = mmread(open(infile1, 'r'))
+    elif input_type == "sparse":
+        X = mmread(open(infile1, "r"))
 
     # Get target y
-    header = 'infer' if params['input_options']['header2'] else None
-    column_option = (params['input_options']['column_selector_options_2']
-                     ['selected_column_selector_option2'])
-    if column_option in ['by_index_number', 'all_but_by_index_number',
-                         'by_header_name', 'all_but_by_header_name']:
-        c = params['input_options']['column_selector_options_2']['col2']
+    header = "infer" if params["input_options"]["header2"] else None
+    column_option = params["input_options"]["column_selector_options_2"]["selected_column_selector_option2"]
+    if column_option in [
+        "by_index_number",
+        "all_but_by_index_number",
+        "by_header_name",
+        "all_but_by_header_name",
+    ]:
+        c = params["input_options"]["column_selector_options_2"]["col2"]
     else:
         c = None
 
@@ -62,26 +67,24 @@
     if df_key in loaded_df:
         infile2 = loaded_df[df_key]
     else:
-        infile2 = pd.read_csv(infile2, sep='\t',
-                              header=header, parse_dates=True)
+        infile2 = pd.read_csv(infile2, sep="\t", header=header, parse_dates=True)
         loaded_df[df_key] = infile2
 
-    y = read_columns(
-            infile2,
-            c=c,
-            c_option=column_option,
-            sep='\t',
-            header=header,
-            parse_dates=True)
+    y = read_columns(infile2, c=c, c_option=column_option, sep="\t", header=header, parse_dates=True)
     if len(y.shape) == 2 and y.shape[1] == 1:
         y = y.ravel()
 
     return X, y
 
 
-def main(inputs, infile_estimator, outfile_eval,
-         infile_weights=None, infile1=None,
-         infile2=None):
+def main(
+    inputs,
+    infile_estimator,
+    outfile_eval,
+    infile_weights=None,
+    infile1=None,
+    infile2=None,
+):
     """
     Parameter
     ---------
@@ -103,49 +106,55 @@
     infile2 : str
         File path to dataset containing target values
     """
-    warnings.filterwarnings('ignore')
+    warnings.filterwarnings("ignore")
 
-    with open(inputs, 'r') as param_handler:
+    with open(inputs, "r") as param_handler:
         params = json.load(param_handler)
 
     X_test, y_test = _get_X_y(params, infile1, infile2)
 
     # load model
-    with open(infile_estimator, 'rb') as est_handler:
+    with open(infile_estimator, "rb") as est_handler:
         estimator = load_model(est_handler)
 
     main_est = estimator
     if isinstance(estimator, Pipeline):
         main_est = estimator.steps[-1][-1]
-    if hasattr(main_est, 'config') and hasattr(main_est, 'load_weights'):
-        if not infile_weights or infile_weights == 'None':
-            raise ValueError("The selected model skeleton asks for weights, "
-                             "but no dataset for weights was provided!")
+    if hasattr(main_est, "config") and hasattr(main_est, "load_weights"):
+        if not infile_weights or infile_weights == "None":
+            raise ValueError(
+                "The selected model skeleton asks for weights, " "but no dataset for weights was provided!"
+            )
         main_est.load_weights(infile_weights)
 
     # handle scorer, convert to scorer dict
-    scoring = params['scoring']
+    # Check if scoring is specified
+    scoring = params["scoring"]
+    if scoring is not None:
+        # get_scoring() expects secondary_scoring to be a comma separated string (not a list)
+        # Check if secondary_scoring is specified
+        secondary_scoring = scoring.get("secondary_scoring", None)
+        if secondary_scoring is not None:
+            # If secondary_scoring is specified, convert the list into comman separated string
+            scoring["secondary_scoring"] = ",".join(scoring["secondary_scoring"])
+
     scorer = get_scoring(scoring)
     scorer, _ = _check_multimetric_scoring(estimator, scoring=scorer)
 
-    if hasattr(estimator, 'evaluate'):
-        scores = estimator.evaluate(X_test, y_test=y_test,
-                                    scorer=scorer,
-                                    is_multimetric=True)
+    if hasattr(estimator, "evaluate"):
+        scores = estimator.evaluate(X_test, y_test=y_test, scorer=scorer, is_multimetric=True)
     else:
-        scores = _score(estimator, X_test, y_test, scorer,
-                        is_multimetric=True)
+        scores = _score(estimator, X_test, y_test, scorer, is_multimetric=True)
 
     # handle output
     for name, score in scores.items():
         scores[name] = [score]
     df = pd.DataFrame(scores)
     df = df[sorted(df.columns)]
-    df.to_csv(path_or_buf=outfile_eval, sep='\t',
-              header=True, index=False)
+    df.to_csv(path_or_buf=outfile_eval, sep="\t", header=True, index=False)
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     aparser = argparse.ArgumentParser()
     aparser.add_argument("-i", "--inputs", dest="inputs", required=True)
     aparser.add_argument("-e", "--infile_estimator", dest="infile_estimator")
@@ -155,6 +164,11 @@
     aparser.add_argument("-O", "--outfile_eval", dest="outfile_eval")
     args = aparser.parse_args()
 
-    main(args.inputs, args.infile_estimator, args.outfile_eval,
-         infile_weights=args.infile_weights, infile1=args.infile1,
-         infile2=args.infile2)
+    main(
+        args.inputs,
+        args.infile_estimator,
+        args.outfile_eval,
+        infile_weights=args.infile_weights,
+        infile1=args.infile1,
+        infile2=args.infile2,
+    )
--- a/keras_deep_learning.py	Thu Oct 01 19:54:05 2020 +0000
+++ b/keras_deep_learning.py	Tue Apr 13 17:21:05 2021 +0000
@@ -177,11 +177,11 @@
         # merge layers
         if 'merging_layers' in options:
             idxs = literal_eval(options.pop('merging_layers'))
-            merging_layers = [all_layers[i-1] for i in idxs]
+            merging_layers = [all_layers[i - 1] for i in idxs]
             new_layer = klass(**options)(merging_layers)
         # non-input layers
         elif inbound_nodes is not None:
-            new_layer = klass(**options)(all_layers[inbound_nodes-1])
+            new_layer = klass(**options)(all_layers[inbound_nodes - 1])
         # input layers
         else:
             new_layer = klass(**options)
@@ -189,10 +189,10 @@
         all_layers.append(new_layer)
 
     input_indexes = _handle_shape(config['input_layers'])
-    input_layers = [all_layers[i-1] for i in input_indexes]
+    input_layers = [all_layers[i - 1] for i in input_indexes]
 
     output_indexes = _handle_shape(config['output_layers'])
-    output_layers = [all_layers[i-1] for i in output_indexes]
+    output_layers = [all_layers[i - 1] for i in output_indexes]
 
     return Model(inputs=input_layers, outputs=output_layers)
 
@@ -300,8 +300,7 @@
         options.update((inputs['mode_selection']['compile_params']
                         ['optimizer_selection']['optimizer_options']))
 
-        train_metrics = (inputs['mode_selection']['compile_params']
-                         ['metrics']).split(',')
+        train_metrics = inputs['mode_selection']['compile_params']['metrics']
         if train_metrics[-1] == 'none':
             train_metrics = train_metrics[:-1]
         options['metrics'] = train_metrics
--- a/keras_train_and_eval.py	Thu Oct 01 19:54:05 2020 +0000
+++ b/keras_train_and_eval.py	Tue Apr 13 17:21:05 2021 +0000
@@ -10,7 +10,6 @@
 from scipy.io import mmread
 from sklearn.pipeline import Pipeline
 from sklearn.metrics.scorer import _check_multimetric_scoring
-from sklearn import model_selection
 from sklearn.model_selection._validation import _score
 from sklearn.model_selection import _search, _validation
 from sklearn.utils import indexable, safe_indexing
@@ -18,39 +17,49 @@
 from galaxy_ml.externals.selene_sdk.utils import compute_score
 from galaxy_ml.model_validations import train_test_split
 from galaxy_ml.keras_galaxy_models import _predict_generator
-from galaxy_ml.utils import (SafeEval, get_scoring, load_model,
-                             read_columns, try_get_attr, get_module,
-                             clean_params, get_main_estimator)
+from galaxy_ml.utils import (
+    SafeEval,
+    get_scoring,
+    load_model,
+    read_columns,
+    try_get_attr,
+    get_module,
+    clean_params,
+    get_main_estimator,
+)
 
 
-_fit_and_score = try_get_attr('galaxy_ml.model_validations', '_fit_and_score')
-setattr(_search, '_fit_and_score', _fit_and_score)
-setattr(_validation, '_fit_and_score', _fit_and_score)
+_fit_and_score = try_get_attr("galaxy_ml.model_validations", "_fit_and_score")
+setattr(_search, "_fit_and_score", _fit_and_score)
+setattr(_validation, "_fit_and_score", _fit_and_score)
 
-N_JOBS = int(os.environ.get('GALAXY_SLOTS', 1))
-CACHE_DIR = os.path.join(os.getcwd(), 'cached')
+N_JOBS = int(os.environ.get("GALAXY_SLOTS", 1))
+CACHE_DIR = os.path.join(os.getcwd(), "cached")
 del os
-NON_SEARCHABLE = ('n_jobs', 'pre_dispatch', 'memory', '_path',
-                  'nthread', 'callbacks')
-ALLOWED_CALLBACKS = ('EarlyStopping', 'TerminateOnNaN', 'ReduceLROnPlateau',
-                     'CSVLogger', 'None')
+NON_SEARCHABLE = ("n_jobs", "pre_dispatch", "memory", "_path", "nthread", "callbacks")
+ALLOWED_CALLBACKS = (
+    "EarlyStopping",
+    "TerminateOnNaN",
+    "ReduceLROnPlateau",
+    "CSVLogger",
+    "None",
+)
 
 
 def _eval_swap_params(params_builder):
     swap_params = {}
 
-    for p in params_builder['param_set']:
-        swap_value = p['sp_value'].strip()
-        if swap_value == '':
+    for p in params_builder["param_set"]:
+        swap_value = p["sp_value"].strip()
+        if swap_value == "":
             continue
 
-        param_name = p['sp_name']
+        param_name = p["sp_name"]
         if param_name.lower().endswith(NON_SEARCHABLE):
-            warnings.warn("Warning: `%s` is not eligible for search and was "
-                          "omitted!" % param_name)
+            warnings.warn("Warning: `%s` is not eligible for search and was " "omitted!" % param_name)
             continue
 
-        if not swap_value.startswith(':'):
+        if not swap_value.startswith(":"):
             safe_eval = SafeEval(load_scipy=True, load_numpy=True)
             ev = safe_eval(swap_value)
         else:
@@ -77,34 +86,31 @@
         else:
             new_arrays.append(arr)
 
-    if kwargs['shuffle'] == 'None':
-        kwargs['shuffle'] = None
+    if kwargs["shuffle"] == "None":
+        kwargs["shuffle"] = None
 
-    group_names = kwargs.pop('group_names', None)
+    group_names = kwargs.pop("group_names", None)
 
     if group_names is not None and group_names.strip():
-        group_names = [name.strip() for name in
-                       group_names.split(',')]
+        group_names = [name.strip() for name in group_names.split(",")]
         new_arrays = indexable(*new_arrays)
-        groups = kwargs['labels']
+        groups = kwargs["labels"]
         n_samples = new_arrays[0].shape[0]
         index_arr = np.arange(n_samples)
         test = index_arr[np.isin(groups, group_names)]
         train = index_arr[~np.isin(groups, group_names)]
-        rval = list(chain.from_iterable(
-            (safe_indexing(a, train),
-             safe_indexing(a, test)) for a in new_arrays))
+        rval = list(chain.from_iterable((safe_indexing(a, train), safe_indexing(a, test)) for a in new_arrays))
     else:
         rval = train_test_split(*new_arrays, **kwargs)
 
     for pos in nones:
-        rval[pos * 2: 2] = [None, None]
+        rval[pos * 2 : 2] = [None, None]
 
     return rval
 
 
 def _evaluate(y_true, pred_probas, scorer, is_multimetric=True):
-    """ output scores based on input scorer
+    """output scores based on input scorer
 
     Parameters
     ----------
@@ -118,52 +124,55 @@
     """
     if y_true.ndim == 1 or y_true.shape[-1] == 1:
         pred_probas = pred_probas.ravel()
-        pred_labels = (pred_probas > 0.5).astype('int32')
-        targets = y_true.ravel().astype('int32')
+        pred_labels = (pred_probas > 0.5).astype("int32")
+        targets = y_true.ravel().astype("int32")
         if not is_multimetric:
-            preds = pred_labels if scorer.__class__.__name__ == \
-                '_PredictScorer' else pred_probas
+            preds = pred_labels if scorer.__class__.__name__ == "_PredictScorer" else pred_probas
             score = scorer._score_func(targets, preds, **scorer._kwargs)
 
             return score
         else:
             scores = {}
             for name, one_scorer in scorer.items():
-                preds = pred_labels if one_scorer.__class__.__name__\
-                    == '_PredictScorer' else pred_probas
-                score = one_scorer._score_func(targets, preds,
-                                               **one_scorer._kwargs)
+                preds = pred_labels if one_scorer.__class__.__name__ == "_PredictScorer" else pred_probas
+                score = one_scorer._score_func(targets, preds, **one_scorer._kwargs)
                 scores[name] = score
 
     # TODO: multi-class metrics
     # multi-label
     else:
-        pred_labels = (pred_probas > 0.5).astype('int32')
-        targets = y_true.astype('int32')
+        pred_labels = (pred_probas > 0.5).astype("int32")
+        targets = y_true.astype("int32")
         if not is_multimetric:
-            preds = pred_labels if scorer.__class__.__name__ == \
-                '_PredictScorer' else pred_probas
-            score, _ = compute_score(preds, targets,
-                                     scorer._score_func)
+            preds = pred_labels if scorer.__class__.__name__ == "_PredictScorer" else pred_probas
+            score, _ = compute_score(preds, targets, scorer._score_func)
             return score
         else:
             scores = {}
             for name, one_scorer in scorer.items():
-                preds = pred_labels if one_scorer.__class__.__name__\
-                    == '_PredictScorer' else pred_probas
-                score, _ = compute_score(preds, targets,
-                                         one_scorer._score_func)
+                preds = pred_labels if one_scorer.__class__.__name__ == "_PredictScorer" else pred_probas
+                score, _ = compute_score(preds, targets, one_scorer._score_func)
                 scores[name] = score
 
     return scores
 
 
-def main(inputs, infile_estimator, infile1, infile2,
-         outfile_result, outfile_object=None,
-         outfile_weights=None, outfile_y_true=None,
-         outfile_y_preds=None, groups=None,
-         ref_seq=None, intervals=None, targets=None,
-         fasta_path=None):
+def main(
+    inputs,
+    infile_estimator,
+    infile1,
+    infile2,
+    outfile_result,
+    outfile_object=None,
+    outfile_weights=None,
+    outfile_y_true=None,
+    outfile_y_preds=None,
+    groups=None,
+    ref_seq=None,
+    intervals=None,
+    targets=None,
+    fasta_path=None,
+):
     """
     Parameter
     ---------
@@ -209,19 +218,19 @@
     fasta_path : str
         File path to dataset containing fasta file
     """
-    warnings.simplefilter('ignore')
+    warnings.simplefilter("ignore")
 
-    with open(inputs, 'r') as param_handler:
+    with open(inputs, "r") as param_handler:
         params = json.load(param_handler)
 
     #  load estimator
-    with open(infile_estimator, 'rb') as estimator_handler:
+    with open(infile_estimator, "rb") as estimator_handler:
         estimator = load_model(estimator_handler)
 
     estimator = clean_params(estimator)
 
     # swap hyperparameter
-    swapping = params['experiment_schemes']['hyperparams_swapping']
+    swapping = params["experiment_schemes"]["hyperparams_swapping"]
     swap_params = _eval_swap_params(swapping)
     estimator.set_params(**swap_params)
 
@@ -230,38 +239,39 @@
     # store read dataframe object
     loaded_df = {}
 
-    input_type = params['input_options']['selected_input']
+    input_type = params["input_options"]["selected_input"]
     # tabular input
-    if input_type == 'tabular':
-        header = 'infer' if params['input_options']['header1'] else None
-        column_option = (params['input_options']['column_selector_options_1']
-                         ['selected_column_selector_option'])
-        if column_option in ['by_index_number', 'all_but_by_index_number',
-                             'by_header_name', 'all_but_by_header_name']:
-            c = params['input_options']['column_selector_options_1']['col1']
+    if input_type == "tabular":
+        header = "infer" if params["input_options"]["header1"] else None
+        column_option = params["input_options"]["column_selector_options_1"]["selected_column_selector_option"]
+        if column_option in [
+            "by_index_number",
+            "all_but_by_index_number",
+            "by_header_name",
+            "all_but_by_header_name",
+        ]:
+            c = params["input_options"]["column_selector_options_1"]["col1"]
         else:
             c = None
 
         df_key = infile1 + repr(header)
-        df = pd.read_csv(infile1, sep='\t', header=header,
-                         parse_dates=True)
+        df = pd.read_csv(infile1, sep="\t", header=header, parse_dates=True)
         loaded_df[df_key] = df
 
         X = read_columns(df, c=c, c_option=column_option).astype(float)
     # sparse input
-    elif input_type == 'sparse':
-        X = mmread(open(infile1, 'r'))
+    elif input_type == "sparse":
+        X = mmread(open(infile1, "r"))
 
     # fasta_file input
-    elif input_type == 'seq_fasta':
-        pyfaidx = get_module('pyfaidx')
+    elif input_type == "seq_fasta":
+        pyfaidx = get_module("pyfaidx")
         sequences = pyfaidx.Fasta(fasta_path)
         n_seqs = len(sequences.keys())
         X = np.arange(n_seqs)[:, np.newaxis]
         for param in estimator_params.keys():
-            if param.endswith('fasta_path'):
-                estimator.set_params(
-                    **{param: fasta_path})
+            if param.endswith("fasta_path"):
+                estimator.set_params(**{param: fasta_path})
                 break
         else:
             raise ValueError(
@@ -270,25 +280,29 @@
                 "KerasGBatchClassifier with "
                 "FastaDNABatchGenerator/FastaProteinBatchGenerator "
                 "or having GenomeOneHotEncoder/ProteinOneHotEncoder "
-                "in pipeline!")
+                "in pipeline!"
+            )
 
-    elif input_type == 'refseq_and_interval':
+    elif input_type == "refseq_and_interval":
         path_params = {
-            'data_batch_generator__ref_genome_path': ref_seq,
-            'data_batch_generator__intervals_path': intervals,
-            'data_batch_generator__target_path': targets
+            "data_batch_generator__ref_genome_path": ref_seq,
+            "data_batch_generator__intervals_path": intervals,
+            "data_batch_generator__target_path": targets,
         }
         estimator.set_params(**path_params)
         n_intervals = sum(1 for line in open(intervals))
         X = np.arange(n_intervals)[:, np.newaxis]
 
     # Get target y
-    header = 'infer' if params['input_options']['header2'] else None
-    column_option = (params['input_options']['column_selector_options_2']
-                     ['selected_column_selector_option2'])
-    if column_option in ['by_index_number', 'all_but_by_index_number',
-                         'by_header_name', 'all_but_by_header_name']:
-        c = params['input_options']['column_selector_options_2']['col2']
+    header = "infer" if params["input_options"]["header2"] else None
+    column_option = params["input_options"]["column_selector_options_2"]["selected_column_selector_option2"]
+    if column_option in [
+        "by_index_number",
+        "all_but_by_index_number",
+        "by_header_name",
+        "all_but_by_header_name",
+    ]:
+        c = params["input_options"]["column_selector_options_2"]["col2"]
     else:
         c = None
 
@@ -296,37 +310,35 @@
     if df_key in loaded_df:
         infile2 = loaded_df[df_key]
     else:
-        infile2 = pd.read_csv(infile2, sep='\t',
-                              header=header, parse_dates=True)
+        infile2 = pd.read_csv(infile2, sep="\t", header=header, parse_dates=True)
         loaded_df[df_key] = infile2
 
-    y = read_columns(
-            infile2,
-            c=c,
-            c_option=column_option,
-            sep='\t',
-            header=header,
-            parse_dates=True)
+    y = read_columns(infile2,
+                     c=c,
+                     c_option=column_option,
+                     sep='\t',
+                     header=header,
+                     parse_dates=True)
     if len(y.shape) == 2 and y.shape[1] == 1:
         y = y.ravel()
-    if input_type == 'refseq_and_interval':
-        estimator.set_params(
-            data_batch_generator__features=y.ravel().tolist())
+    if input_type == "refseq_and_interval":
+        estimator.set_params(data_batch_generator__features=y.ravel().tolist())
         y = None
     # end y
 
     # load groups
     if groups:
-        groups_selector = (params['experiment_schemes']['test_split']
-                                 ['split_algos']).pop('groups_selector')
+        groups_selector = (params["experiment_schemes"]["test_split"]["split_algos"]).pop("groups_selector")
 
-        header = 'infer' if groups_selector['header_g'] else None
-        column_option = \
-            (groups_selector['column_selector_options_g']
-                            ['selected_column_selector_option_g'])
-        if column_option in ['by_index_number', 'all_but_by_index_number',
-                             'by_header_name', 'all_but_by_header_name']:
-            c = groups_selector['column_selector_options_g']['col_g']
+        header = "infer" if groups_selector["header_g"] else None
+        column_option = groups_selector["column_selector_options_g"]["selected_column_selector_option_g"]
+        if column_option in [
+            "by_index_number",
+            "all_but_by_index_number",
+            "by_header_name",
+            "all_but_by_header_name",
+        ]:
+            c = groups_selector["column_selector_options_g"]["col_g"]
         else:
             c = None
 
@@ -334,13 +346,12 @@
         if df_key in loaded_df:
             groups = loaded_df[df_key]
 
-        groups = read_columns(
-                groups,
-                c=c,
-                c_option=column_option,
-                sep='\t',
-                header=header,
-                parse_dates=True)
+        groups = read_columns(groups,
+                              c=c,
+                              c_option=column_option,
+                              sep='\t',
+                              header=header,
+                              parse_dates=True)
         groups = groups.ravel()
 
     # del loaded_df
@@ -349,86 +360,99 @@
     # cache iraps_core fits could increase search speed significantly
     memory = joblib.Memory(location=CACHE_DIR, verbose=0)
     main_est = get_main_estimator(estimator)
-    if main_est.__class__.__name__ == 'IRAPSClassifier':
+    if main_est.__class__.__name__ == "IRAPSClassifier":
         main_est.set_params(memory=memory)
 
     # handle scorer, convert to scorer dict
     scoring = params['experiment_schemes']['metrics']['scoring']
+    if scoring is not None:
+        # get_scoring() expects secondary_scoring to be a comma separated string (not a list)
+        # Check if secondary_scoring is specified
+        secondary_scoring = scoring.get("secondary_scoring", None)
+        if secondary_scoring is not None:
+            # If secondary_scoring is specified, convert the list into comman separated string
+            scoring["secondary_scoring"] = ",".join(scoring["secondary_scoring"])
+
     scorer = get_scoring(scoring)
     scorer, _ = _check_multimetric_scoring(estimator, scoring=scorer)
 
     # handle test (first) split
-    test_split_options = (params['experiment_schemes']
-                                ['test_split']['split_algos'])
+    test_split_options = params["experiment_schemes"]["test_split"]["split_algos"]
 
-    if test_split_options['shuffle'] == 'group':
-        test_split_options['labels'] = groups
-    if test_split_options['shuffle'] == 'stratified':
+    if test_split_options["shuffle"] == "group":
+        test_split_options["labels"] = groups
+    if test_split_options["shuffle"] == "stratified":
         if y is not None:
-            test_split_options['labels'] = y
+            test_split_options["labels"] = y
         else:
-            raise ValueError("Stratified shuffle split is not "
-                             "applicable on empty target values!")
+            raise ValueError("Stratified shuffle split is not " "applicable on empty target values!")
 
-    X_train, X_test, y_train, y_test, groups_train, groups_test = \
-        train_test_split_none(X, y, groups, **test_split_options)
+    (
+        X_train,
+        X_test,
+        y_train,
+        y_test,
+        groups_train,
+        _groups_test,
+    ) = train_test_split_none(X, y, groups, **test_split_options)
 
-    exp_scheme = params['experiment_schemes']['selected_exp_scheme']
+    exp_scheme = params["experiment_schemes"]["selected_exp_scheme"]
 
     # handle validation (second) split
-    if exp_scheme == 'train_val_test':
-        val_split_options = (params['experiment_schemes']
-                                   ['val_split']['split_algos'])
+    if exp_scheme == "train_val_test":
+        val_split_options = params["experiment_schemes"]["val_split"]["split_algos"]
 
-        if val_split_options['shuffle'] == 'group':
-            val_split_options['labels'] = groups_train
-        if val_split_options['shuffle'] == 'stratified':
+        if val_split_options["shuffle"] == "group":
+            val_split_options["labels"] = groups_train
+        if val_split_options["shuffle"] == "stratified":
             if y_train is not None:
-                val_split_options['labels'] = y_train
+                val_split_options["labels"] = y_train
             else:
-                raise ValueError("Stratified shuffle split is not "
-                                 "applicable on empty target values!")
+                raise ValueError("Stratified shuffle split is not " "applicable on empty target values!")
 
-        X_train, X_val, y_train, y_val, groups_train, groups_val = \
-            train_test_split_none(X_train, y_train, groups_train,
-                                  **val_split_options)
+        (
+            X_train,
+            X_val,
+            y_train,
+            y_val,
+            groups_train,
+            _groups_val,
+        ) = train_test_split_none(X_train, y_train, groups_train, **val_split_options)
 
     # train and eval
-    if hasattr(estimator, 'validation_data'):
-        if exp_scheme == 'train_val_test':
-            estimator.fit(X_train, y_train,
-                          validation_data=(X_val, y_val))
+    if hasattr(estimator, "validation_data"):
+        if exp_scheme == "train_val_test":
+            estimator.fit(X_train, y_train, validation_data=(X_val, y_val))
         else:
-            estimator.fit(X_train, y_train,
-                          validation_data=(X_test, y_test))
+            estimator.fit(X_train, y_train, validation_data=(X_test, y_test))
     else:
         estimator.fit(X_train, y_train)
 
-    if hasattr(estimator, 'evaluate'):
+    if hasattr(estimator, "evaluate"):
         steps = estimator.prediction_steps
         batch_size = estimator.batch_size
-        generator = estimator.data_generator_.flow(X_test, y=y_test,
-                                                   batch_size=batch_size)
-        predictions, y_true = _predict_generator(estimator.model_, generator,
-                                                 steps=steps)
+        generator = estimator.data_generator_.flow(X_test, y=y_test, batch_size=batch_size)
+        predictions, y_true = _predict_generator(estimator.model_, generator, steps=steps)
         scores = _evaluate(y_true, predictions, scorer, is_multimetric=True)
 
     else:
-        if hasattr(estimator, 'predict_proba'):
+        if hasattr(estimator, "predict_proba"):
             predictions = estimator.predict_proba(X_test)
         else:
             predictions = estimator.predict(X_test)
 
         y_true = y_test
-        scores = _score(estimator, X_test, y_test, scorer,
-                        is_multimetric=True)
+        scores = _score(estimator, X_test, y_test, scorer, is_multimetric=True)
     if outfile_y_true:
         try:
-            pd.DataFrame(y_true).to_csv(outfile_y_true, sep='\t',
-                                        index=False)
+            pd.DataFrame(y_true).to_csv(outfile_y_true, sep="\t", index=False)
             pd.DataFrame(predictions).astype(np.float32).to_csv(
-                outfile_y_preds, sep='\t', index=False,
-                float_format='%g', chunksize=10000)
+                outfile_y_preds,
+                sep="\t",
+                index=False,
+                float_format="%g",
+                chunksize=10000,
+            )
         except Exception as e:
             print("Error in saving predictions: %s" % e)
 
@@ -437,8 +461,7 @@
         scores[name] = [score]
     df = pd.DataFrame(scores)
     df = df[sorted(df.columns)]
-    df.to_csv(path_or_buf=outfile_result, sep='\t',
-              header=True, index=False)
+    df.to_csv(path_or_buf=outfile_result, sep="\t", header=True, index=False)
 
     memory.clear(warn=False)
 
@@ -447,23 +470,22 @@
         if isinstance(estimator, Pipeline):
             main_est = estimator.steps[-1][-1]
 
-        if hasattr(main_est, 'model_') \
-                and hasattr(main_est, 'save_weights'):
+        if hasattr(main_est, "model_") and hasattr(main_est, "save_weights"):
             if outfile_weights:
                 main_est.save_weights(outfile_weights)
             del main_est.model_
             del main_est.fit_params
             del main_est.model_class_
-            del main_est.validation_data
-            if getattr(main_est, 'data_generator_', None):
+            if getattr(main_est, "validation_data", None):
+                del main_est.validation_data
+            if getattr(main_est, "data_generator_", None):
                 del main_est.data_generator_
 
-        with open(outfile_object, 'wb') as output_handler:
-            pickle.dump(estimator, output_handler,
-                        pickle.HIGHEST_PROTOCOL)
+        with open(outfile_object, "wb") as output_handler:
+            pickle.dump(estimator, output_handler, pickle.HIGHEST_PROTOCOL)
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     aparser = argparse.ArgumentParser()
     aparser.add_argument("-i", "--inputs", dest="inputs", required=True)
     aparser.add_argument("-e", "--estimator", dest="infile_estimator")
@@ -481,11 +503,19 @@
     aparser.add_argument("-f", "--fasta_path", dest="fasta_path")
     args = aparser.parse_args()
 
-    main(args.inputs, args.infile_estimator, args.infile1, args.infile2,
-         args.outfile_result, outfile_object=args.outfile_object,
-         outfile_weights=args.outfile_weights,
-         outfile_y_true=args.outfile_y_true,
-         outfile_y_preds=args.outfile_y_preds,
-         groups=args.groups,
-         ref_seq=args.ref_seq, intervals=args.intervals,
-         targets=args.targets, fasta_path=args.fasta_path)
+    main(
+        args.inputs,
+        args.infile_estimator,
+        args.infile1,
+        args.infile2,
+        args.outfile_result,
+        outfile_object=args.outfile_object,
+        outfile_weights=args.outfile_weights,
+        outfile_y_true=args.outfile_y_true,
+        outfile_y_preds=args.outfile_y_preds,
+        groups=args.groups,
+        ref_seq=args.ref_seq,
+        intervals=args.intervals,
+        targets=args.targets,
+        fasta_path=args.fasta_path,
+    )
--- a/main_macros.xml	Thu Oct 01 19:54:05 2020 +0000
+++ b/main_macros.xml	Tue Apr 13 17:21:05 2021 +0000
@@ -1,1952 +1,1940 @@
 <macros>
-  <token name="@VERSION@">1.0.8.2</token>
+    <token name="@VERSION@">1.0.8.3</token>
 
-  <xml name="python_requirements">
-      <requirements>
-          <requirement type="package" version="3.6">python</requirement>
-          <requirement type="package" version="0.8.1">Galaxy-ML</requirement>
-          <yield/>
-      </requirements>
-  </xml>
+    <xml name="python_requirements">
+        <requirements>
+            <requirement type="package" version="0.8.3">Galaxy-ML</requirement>
+            <yield />
+        </requirements>
+    </xml>
 
-  <xml name="macro_stdio">
-    <stdio>
-        <exit_code range="1:" level="fatal" description="Error occurred. Please check Tool Standard Error"/>
-    </stdio>
-  </xml>
+    <xml name="macro_stdio">
+        <stdio>
+            <exit_code range="1:" level="fatal" description="Error occurred. Please check Tool Standard Error" />
+        </stdio>
+    </xml>
 
 
-  <!--Generic interface-->
+    <!--Generic interface-->
 
-  <xml name="sl_Conditional" token_train="tabular" token_data="tabular" token_model="txt">
-    <conditional name="selected_tasks">
-        <param name="selected_task" type="select" label="Select a Classification Task">
-            <option value="train" selected="true">Train a model</option>
-            <option value="load">Load a model and predict</option>
-        </param>
-        <when value="load">
-            <param name="infile_model" type="data" format="@MODEL@" label="Models" help="Select a model file."/>
-            <param name="infile_data" type="data" format="@DATA@" label="Data (tabular)" help="Select the dataset you want to classify."/>
-            <param name="header" type="boolean" optional="True" truevalue="booltrue" falsevalue="boolfalse" checked="False" label="Does the dataset contain header:" />
-            <conditional name="prediction_options">
-                <param name="prediction_option" type="select" label="Select the type of prediction">
-                    <option value="predict">Predict class labels</option>
-                    <option value="advanced">Include advanced options</option>
-                </param>
-                <when value="predict">
-                </when>
-                <when value="advanced">
-                </when>
-            </conditional>
-        </when>
-        <when value="train">
-            <conditional name="selected_algorithms">
-                <yield />
-            </conditional>
-        </when>
-    </conditional>
-  </xml>
+    <xml name="sl_Conditional" token_train="tabular" token_data="tabular" token_model="txt">
+        <conditional name="selected_tasks">
+            <param name="selected_task" type="select" label="Select a Classification Task">
+                <option value="train" selected="true">Train a model</option>
+                <option value="load">Load a model and predict</option>
+            </param>
+            <when value="load">
+                <param name="infile_model" type="data" format="@MODEL@" label="Models" help="Select a model file." />
+                <param name="infile_data" type="data" format="@DATA@" label="Data (tabular)" help="Select the dataset you want to classify." />
+                <param name="header" type="boolean" optional="True" truevalue="booltrue" falsevalue="boolfalse" checked="False" label="Does the dataset contain header:" />
+                <conditional name="prediction_options">
+                    <param name="prediction_option" type="select" label="Select the type of prediction">
+                        <option value="predict">Predict class labels</option>
+                        <option value="advanced">Include advanced options</option>
+                    </param>
+                    <when value="predict">
+                    </when>
+                    <when value="advanced">
+                    </when>
+                </conditional>
+            </when>
+            <when value="train">
+                <conditional name="selected_algorithms">
+                    <yield />
+                </conditional>
+            </when>
+        </conditional>
+    </xml>
 
-  <xml name="advanced_section">
-    <section name="options" title="Advanced Options" expanded="False">
-      <yield />
-    </section>
-  </xml>
+    <xml name="advanced_section">
+        <section name="options" title="Advanced Options" expanded="False">
+            <yield />
+        </section>
+    </xml>
 
 
-  <!--Generalized Linear Models-->
-  <xml name="loss" token_help=" " token_select="false">
-    <param argument="loss" type="select" label="Loss function"  help="@HELP@">
-        <option value="squared_loss" selected="@SELECT@">squared loss</option>
-        <option value="huber">huber</option>
-        <option value="epsilon_insensitive">epsilon insensitive</option>
-        <option value="squared_epsilon_insensitive">squared epsilon insensitive</option>
-        <yield/>
-    </param>
-  </xml>
+    <!--Generalized Linear Models-->
+    <xml name="loss" token_help=" " token_select="false">
+        <param argument="loss" type="select" label="Loss function" help="@HELP@">
+            <option value="squared_loss" selected="@SELECT@">squared loss</option>
+            <option value="huber">huber</option>
+            <option value="epsilon_insensitive">epsilon insensitive</option>
+            <option value="squared_epsilon_insensitive">squared epsilon insensitive</option>
+            <yield />
+        </param>
+    </xml>
 
-  <xml name="penalty" token_help=" ">
-    <param argument="penalty" type="select" label="Penalty (regularization term)"  help="@HELP@">
-        <option value="l2" selected="true">l2</option>
-        <option value="l1">l1</option>
-        <option value="elasticnet">elastic net</option>
-        <option value="none">none</option>
-        <yield/>
-    </param>
-  </xml>
+    <xml name="penalty" token_help=" ">
+        <param argument="penalty" type="select" label="Penalty (regularization term)" help="@HELP@">
+            <option value="l2" selected="true">l2</option>
+            <option value="l1">l1</option>
+            <option value="elasticnet">elastic net</option>
+            <option value="none">none</option>
+            <yield />
+        </param>
+    </xml>
 
-  <xml name="l1_ratio" token_default_value="0.15" token_help=" ">
-    <param argument="l1_ratio" type="float" value="@DEFAULT_VALUE@" label="Elastic Net mixing parameter" help="@HELP@"/>
-  </xml>
+    <xml name="l1_ratio" token_default_value="0.15" token_help=" ">
+        <param argument="l1_ratio" type="float" value="@DEFAULT_VALUE@" label="Elastic Net mixing parameter" help="@HELP@" />
+    </xml>
 
-  <xml name="epsilon" token_default_value="0.1" token_help="Used if loss is ‘huber’, ‘epsilon_insensitive’, or ‘squared_epsilon_insensitive’. ">
-    <param argument="epsilon" type="float" value="@DEFAULT_VALUE@" label="Epsilon (epsilon-sensitive loss functions only)" help="@HELP@"/>
-  </xml>
+    <xml name="epsilon" token_default_value="0.1" token_help="Used if loss is ‘huber’, ‘epsilon_insensitive’, or ‘squared_epsilon_insensitive’. ">
+        <param argument="epsilon" type="float" value="@DEFAULT_VALUE@" label="Epsilon (epsilon-sensitive loss functions only)" help="@HELP@" />
+    </xml>
 
-  <xml name="learning_rate_s" token_help=" " token_selected1="false" token_selected2="false">
-    <param argument="learning_rate" type="select" optional="true" label="Learning rate schedule"  help="@HELP@">
-        <option value="optimal" selected="@SELECTED1@">optimal</option>
-        <option value="constant">constant</option>
-        <option value="invscaling" selected="@SELECTED2@">inverse scaling</option>
-        <yield/>
-    </param>
-  </xml>
+    <xml name="learning_rate_s" token_help=" " token_selected1="false" token_selected2="false">
+        <param argument="learning_rate" type="select" optional="true" label="Learning rate schedule" help="@HELP@">
+            <option value="optimal" selected="@SELECTED1@">optimal</option>
+            <option value="constant">constant</option>
+            <option value="invscaling" selected="@SELECTED2@">inverse scaling</option>
+            <yield />
+        </param>
+    </xml>
 
-  <xml name="eta0" token_default_value="0.0" token_help="Used with ‘constant’ or ‘invscaling’ schedules. ">
-    <param argument="eta0" type="float" value="@DEFAULT_VALUE@" label="Initial learning rate" help="@HELP@"/>
-  </xml>
+    <xml name="eta0" token_default_value="0.0" token_help="Used with ‘constant’ or ‘invscaling’ schedules. ">
+        <param argument="eta0" type="float" value="@DEFAULT_VALUE@" label="Initial learning rate" help="@HELP@" />
+    </xml>
 
-  <xml name="power_t" token_default_value="0.5" token_help=" ">
-    <param argument="power_t" type="float" value="@DEFAULT_VALUE@" label="Exponent for inverse scaling learning rate" help="@HELP@"/>
-  </xml>
+    <xml name="power_t" token_default_value="0.5" token_help=" ">
+        <param argument="power_t" type="float" value="@DEFAULT_VALUE@" label="Exponent for inverse scaling learning rate" help="@HELP@" />
+    </xml>
 
-  <xml name="normalize" token_checked="false" token_help=" ">
-    <param argument="normalize" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="@CHECKED@" label="Normalize samples before training" help=" "/>
-  </xml>
+    <xml name="normalize" token_checked="false" token_help=" ">
+        <param argument="normalize" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="@CHECKED@" label="Normalize samples before training" help=" " />
+    </xml>
 
-  <xml name="copy_X" token_checked="true" token_help=" ">
-    <param argument="copy_X" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="@CHECKED@" label="Use a copy of samples" help="If false, samples would be overwritten. "/>
-  </xml>
+    <xml name="copy_X" token_checked="true" token_help=" ">
+        <param argument="copy_X" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="@CHECKED@" label="Use a copy of samples" help="If false, samples would be overwritten. " />
+    </xml>
 
-  <xml name="ridge_params">
-    <expand macro="normalize"/>
-    <expand macro="alpha" default_value="1.0"/>
-    <expand macro="fit_intercept"/>
-    <expand macro="max_iter" default_value=""/>
-    <expand macro="tol" default_value="0.001" help_text="Precision of the solution. "/>
-    <!--class_weight-->
-    <expand macro="copy_X"/>
-    <param argument="solver" type="select" value="" label="Solver to use in the computational routines" help=" ">
-        <option value="auto" selected="true">auto</option>
-        <option value="svd">svd</option>
-        <option value="cholesky">cholesky</option>
-        <option value="lsqr">lsqr</option>
-        <option value="sparse_cg">sparse_cg</option>
-        <option value="sag">sag</option>
-    </param>
-    <expand macro="random_state"/>
-  </xml>
+    <xml name="ridge_params">
+        <expand macro="normalize" />
+        <expand macro="alpha" default_value="1.0" />
+        <expand macro="fit_intercept" />
+        <expand macro="max_iter" default_value="" />
+        <expand macro="tol" default_value="0.001" help_text="Precision of the solution. " />
+        <!--class_weight-->
+        <expand macro="copy_X" />
+        <param argument="solver" type="select" value="" label="Solver to use in the computational routines" help=" ">
+            <option value="auto" selected="true">auto</option>
+            <option value="svd">svd</option>
+            <option value="cholesky">cholesky</option>
+            <option value="lsqr">lsqr</option>
+            <option value="sparse_cg">sparse_cg</option>
+            <option value="sag">sag</option>
+        </param>
+        <expand macro="random_state" />
+    </xml>
 
-  <!--Ensemble methods-->
-  <xml name="n_estimators" token_default_value="10" token_help=" ">
-    <param argument="n_estimators" type="integer" optional="true" value="@DEFAULT_VALUE@" label="Number of trees in the forest" help="@HELP@"/>
-  </xml>
+    <!--Ensemble methods-->
+    <xml name="n_estimators" token_default_value="10" token_help=" ">
+        <param argument="n_estimators" type="integer" optional="true" value="@DEFAULT_VALUE@" label="Number of trees in the forest" help="@HELP@" />
+    </xml>
 
-  <xml name="max_depth" token_default_value="" token_help=" ">
-    <param argument="max_depth" type="integer" optional="true" value="@DEFAULT_VALUE@" label="Maximum depth of the tree" help="@HELP@"/>
-  </xml>
+    <xml name="max_depth" token_default_value="" token_help=" ">
+        <param argument="max_depth" type="integer" optional="true" value="@DEFAULT_VALUE@" label="Maximum depth of the tree" help="@HELP@" />
+    </xml>
 
-  <xml name="min_samples_split" token_type="integer" token_default_value="2" token_help=" ">
-    <param argument="min_samples_split" type="@TYPE@" optional="true" value="@DEFAULT_VALUE@" label="Minimum number of samples required to split an internal node" help="@HELP@"/>
-  </xml>
+    <xml name="min_samples_split" token_type="integer" token_default_value="2" token_help=" ">
+        <param argument="min_samples_split" type="@TYPE@" optional="true" value="@DEFAULT_VALUE@" label="Minimum number of samples required to split an internal node" help="@HELP@" />
+    </xml>
 
-  <xml name="min_samples_leaf" token_type="integer" token_default_value="1" token_label="Minimum number of samples in newly created leaves" token_help=" ">
-    <param argument="min_samples_leaf" type="@TYPE@" optional="true" value="@DEFAULT_VALUE@" label="@LABEL@" help="@HELP@"/>
-  </xml>
+    <xml name="min_samples_leaf" token_type="integer" token_default_value="1" token_label="Minimum number of samples in newly created leaves" token_help=" ">
+        <param argument="min_samples_leaf" type="@TYPE@" optional="true" value="@DEFAULT_VALUE@" label="@LABEL@" help="@HELP@" />
+    </xml>
 
-  <xml name="min_weight_fraction_leaf" token_default_value="0.0" token_help=" ">
-    <param argument="min_weight_fraction_leaf" type="float" optional="true" value="@DEFAULT_VALUE@" label="Minimum weighted fraction of the input samples required to be at a leaf node" help="@HELP@"/>
-  </xml>
+    <xml name="min_weight_fraction_leaf" token_default_value="0.0" token_help=" ">
+        <param argument="min_weight_fraction_leaf" type="float" optional="true" value="@DEFAULT_VALUE@" label="Minimum weighted fraction of the input samples required to be at a leaf node" help="@HELP@" />
+    </xml>
 
-  <xml name="max_leaf_nodes" token_default_value="" token_help=" ">
-    <param argument="max_leaf_nodes" type="integer" optional="true" value="@DEFAULT_VALUE@" label="Maximum number of leaf nodes in best-first method" help="@HELP@"/>
-  </xml>
+    <xml name="max_leaf_nodes" token_default_value="" token_help=" ">
+        <param argument="max_leaf_nodes" type="integer" optional="true" value="@DEFAULT_VALUE@" label="Maximum number of leaf nodes in best-first method" help="@HELP@" />
+    </xml>
 
-  <xml name="min_impurity_decrease" token_default_value="0" token_help=" ">
-    <param argument="min_impurity_decrease" type="float" value="@DEFAULT_VALUE@" optional="true" label="The threshold value of impurity for stopping node splitting" help="@HELP@"/>
-  </xml>
+    <xml name="min_impurity_decrease" token_default_value="0" token_help=" ">
+        <param argument="min_impurity_decrease" type="float" value="@DEFAULT_VALUE@" optional="true" label="The threshold value of impurity for stopping node splitting" help="@HELP@" />
+    </xml>
 
-  <xml name="bootstrap" token_checked="true" token_help=" ">
-    <param argument="bootstrap" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolflase" checked="@CHECKED@" label="Use bootstrap samples for building trees." help="@HELP@"/>
-  </xml>
+    <xml name="bootstrap" token_checked="true" token_help=" ">
+        <param argument="bootstrap" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolflase" checked="@CHECKED@" label="Use bootstrap samples for building trees." help="@HELP@" />
+    </xml>
 
-  <xml name="criterion" token_help=" ">
-    <param argument="criterion" type="select" label="Function to measure the quality of a split"  help=" ">
-        <option value="gini" selected="true">Gini impurity</option>
-        <option value="entropy">Information gain</option>
-        <yield/>
-    </param>
-  </xml>
+    <xml name="criterion" token_help=" ">
+        <param argument="criterion" type="select" label="Function to measure the quality of a split" help=" ">
+            <option value="gini" selected="true">Gini impurity</option>
+            <option value="entropy">Information gain</option>
+            <yield />
+        </param>
+    </xml>
 
-  <xml name="criterion2" token_help="">
-    <param argument="criterion" type="select" label="Function to measure the quality of a split" >
-      <option value="mse">mse - mean squared error</option>
-      <option value="mae">mae - mean absolute error</option>
-      <yield/>
-    </param>
-  </xml>
+    <xml name="criterion2" token_help="">
+        <param argument="criterion" type="select" label="Function to measure the quality of a split">
+            <option value="mse">mse - mean squared error</option>
+            <option value="mae">mae - mean absolute error</option>
+            <yield />
+        </param>
+    </xml>
 
-  <xml name="oob_score" token_checked="false" token_help=" ">
-    <param argument="oob_score" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="@CHECKED@" label="Use out-of-bag samples to estimate the generalization error" help="@HELP@"/>
-  </xml>
+    <xml name="oob_score" token_checked="false" token_help=" ">
+        <param argument="oob_score" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="@CHECKED@" label="Use out-of-bag samples to estimate the generalization error" help="@HELP@" />
+    </xml>
 
-  <xml name="max_features">
-    <conditional name="select_max_features">
-      <param argument="max_features" type="select" label="max_features">
-        <option value="auto" selected="true">auto - max_features=n_features</option>
-        <option value="sqrt">sqrt - max_features=sqrt(n_features)</option>
-        <option value="log2">log2 - max_features=log2(n_features)</option>
-        <option value="number_input">I want to type the number in or input None type</option>
-      </param>
-      <when value="auto">
-      </when>
-      <when value="sqrt">
-      </when>
-      <when value="log2">
-      </when>
-      <when value="number_input">
-        <param name="num_max_features" type="float" value="" optional="true" label="Input max_features number:" help="If int, consider the number of features at each split; If float, then max_features is a percentage and int(max_features * n_features) features are considered at each split."/>
-      </when>
-    </conditional>
-  </xml>
+    <xml name="max_features">
+        <conditional name="select_max_features">
+            <param argument="max_features" type="select" label="max_features">
+                <option value="auto" selected="true">auto - max_features=n_features</option>
+                <option value="sqrt">sqrt - max_features=sqrt(n_features)</option>
+                <option value="log2">log2 - max_features=log2(n_features)</option>
+                <option value="number_input">I want to type the number in or input None type</option>
+            </param>
+            <when value="auto">
+            </when>
+            <when value="sqrt">
+            </when>
+            <when value="log2">
+            </when>
+            <when value="number_input">
+                <param name="num_max_features" type="float" value="" optional="true" label="Input max_features number:" help="If int, consider the number of features at each split; If float, then max_features is a percentage and int(max_features * n_features) features are considered at each split." />
+            </when>
+        </conditional>
+    </xml>
 
-  <xml name="verbose" token_default_value="0" token_help="If 1 then it prints progress and performance once in a while. If greater than 1 then it prints progress and performance for every tree.">
-    <param argument="verbose" type="integer" value="@DEFAULT_VALUE@" optional="true" label="Enable verbose output" help="@HELP@"/>
-  </xml>
+    <xml name="verbose" token_default_value="0" token_help="If 1 then it prints progress and performance once in a while. If greater than 1 then it prints progress and performance for every tree.">
+        <param argument="verbose" type="integer" value="@DEFAULT_VALUE@" optional="true" label="Enable verbose output" help="@HELP@" />
+    </xml>
 
-  <xml name="learning_rate" token_default_value="1.0" token_help=" ">
-    <param argument="learning_rate" type="float" optional="true" value="@DEFAULT_VALUE@" label="Learning rate" help="@HELP@"/>
-  </xml>
+    <xml name="learning_rate" token_default_value="1.0" token_help=" ">
+        <param argument="learning_rate" type="float" optional="true" value="@DEFAULT_VALUE@" label="Learning rate" help="@HELP@" />
+    </xml>
 
-  <xml name="subsample" token_help=" ">
-    <param argument="subsample" type="float" value="1.0" optional="true" label="The fraction of samples to be used for fitting the individual base learners" help="@HELP@"/>
-  </xml>
+    <xml name="subsample" token_help=" ">
+        <param argument="subsample" type="float" value="1.0" optional="true" label="The fraction of samples to be used for fitting the individual base learners" help="@HELP@" />
+    </xml>
 
-  <xml name="presort">
-    <param argument="presort" type="select" label="Whether to presort the data to speed up the finding of best splits in fitting" >
-      <option value="auto" selected="true">auto</option>
-      <option value="true">true</option>
-      <option value="false">false</option>
-    </param>
-  </xml>
+    <xml name="presort">
+        <param argument="presort" type="select" label="Whether to presort the data to speed up the finding of best splits in fitting">
+            <option value="auto" selected="true">auto</option>
+            <option value="true">true</option>
+            <option value="false">false</option>
+        </param>
+    </xml>
 
-  <!-- LightGBM -->
-  <xml name="feature_fraction" token_help="LightGBM will randomly select part of the features for each iteration (tree) if feature_fraction is smaller than 1.0. For example, if you set it to 0.8, LightGBM will select 80% of features before training each tree.">
-    <param argument="feature_fraction" type="float" value="1.0" label="Proportion of features to train each tree" help="@HELP@"/>
-  </xml>
-  
-  <xml name="lambda_l1" token_help=" ">
-    <param argument="lambda_l1" type="float" value="0.0" label="L1 regularization" help="@HELP@"/>
-  </xml>
+    <!-- LightGBM -->
+    <xml name="feature_fraction" token_help="LightGBM will randomly select part of the features for each iteration (tree) if feature_fraction is smaller than 1.0. For example, if you set it to 0.8, LightGBM will select 80% of features before training each tree.">
+        <param argument="feature_fraction" type="float" value="1.0" label="Proportion of features to train each tree" help="@HELP@" />
+    </xml>
+
+    <xml name="lambda_l1" token_help=" ">
+        <param argument="lambda_l1" type="float" value="0.0" label="L1 regularization" help="@HELP@" />
+    </xml>
 
-  <xml name="lambda_l2" token_help=" ">
-    <param argument="lambda_l2" type="float" value="0.0" label="L1 regularization" help="@HELP@"/>
-  </xml>
+    <xml name="lambda_l2" token_help=" ">
+        <param argument="lambda_l2" type="float" value="0.0" label="L1 regularization" help="@HELP@" />
+    </xml>
 
-  <xml name="min_gain_to_split" token_help=" ">
-    <param argument="min_gain_to_split" type="float" value="0.0" label="Minimal gain to perform split" help="@HELP@"/>
-  </xml>
+    <xml name="min_gain_to_split" token_help=" ">
+        <param argument="min_gain_to_split" type="float" value="0.0" label="Minimal gain to perform split" help="@HELP@" />
+    </xml>
 
-  <xml name="min_child_weight" token_help="Minimal sum hessian in one leaf. It can be used to deal with over-fitting.">
-    <param argument="min_child_weight" type="float" value="0.0" label="Minimal sum hessian in one leaf" help="@HELP@"/>
-  </xml>
+    <xml name="min_child_weight" token_help="Minimal sum hessian in one leaf. It can be used to deal with over-fitting.">
+        <param argument="min_child_weight" type="float" value="0.0" label="Minimal sum hessian in one leaf" help="@HELP@" />
+    </xml>
 
 
-  <!--Parameters-->
-  <xml name="tol" token_default_value="0.0" token_help_text="Early stopping heuristics based on the relative center changes. Set to default (0.0) to disable this convergence detection.">
-        <param argument="tol" type="float" optional="true" value="@DEFAULT_VALUE@" label="Tolerance" help="@HELP_TEXT@"/>
-  </xml>
+    <!--Parameters-->
+    <xml name="tol" token_default_value="0.0" token_help_text="Early stopping heuristics based on the relative center changes. Set to default (0.0) to disable this convergence detection.">
+        <param argument="tol" type="float" optional="true" value="@DEFAULT_VALUE@" label="Tolerance" help="@HELP_TEXT@" />
+    </xml>
 
-  <xml name="n_clusters" token_default_value="8">
-    <param argument="n_clusters" type="integer" optional="true" value="@DEFAULT_VALUE@" label="Number of clusters" help=" "/>
-  </xml>
+    <xml name="n_clusters" token_default_value="8">
+        <param argument="n_clusters" type="integer" optional="true" value="@DEFAULT_VALUE@" label="Number of clusters" help=" " />
+    </xml>
 
-  <xml name="fit_intercept" token_checked="true">
-    <param argument="fit_intercept" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="@CHECKED@" label="Estimate the intercept" help="If false, the data is assumed to be already centered."/>
-  </xml>
+    <xml name="fit_intercept" token_checked="true">
+        <param argument="fit_intercept" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="@CHECKED@" label="Estimate the intercept" help="If false, the data is assumed to be already centered." />
+    </xml>
 
-  <xml name="n_iter_no_change" token_default_value="5" token_help_text="Number of iterations with no improvement to wait before early stopping. ">
-    <param argument="n_iter_no_change" type="integer" optional="true" value="@DEFAULT_VALUE@" label="Number of iterations" help="@HELP_TEXT@"/>
-  </xml>
+    <xml name="n_iter_no_change" token_default_value="5" token_help_text="Number of iterations with no improvement to wait before early stopping. ">
+        <param argument="n_iter_no_change" type="integer" optional="true" value="@DEFAULT_VALUE@" label="Number of iterations" help="@HELP_TEXT@" />
+    </xml>
 
-  <xml name="shuffle" token_checked="true" token_help_text=" " token_label="Shuffle data after each iteration">
-    <param argument="shuffle" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="@CHECKED@" label="@LABEL@" help="@HELP_TEXT@"/>
-  </xml>
+    <xml name="shuffle" token_checked="true" token_help_text=" " token_label="Shuffle data after each iteration">
+        <param argument="shuffle" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="@CHECKED@" label="@LABEL@" help="@HELP_TEXT@" />
+    </xml>
 
-  <xml name="random_state" token_default_value="" token_help_text="Integer number. The seed of the pseudo random number generator to use when shuffling the data. A fixed seed allows reproducible results. default=None.">
-    <param argument="random_state" type="integer" optional="true" value="@DEFAULT_VALUE@" label="Random seed number" help="@HELP_TEXT@"/>
-  </xml>
+    <xml name="random_state" token_default_value="" token_help_text="Integer number. The seed of the pseudo random number generator to use when shuffling the data. A fixed seed allows reproducible results. default=None.">
+        <param argument="random_state" type="integer" optional="true" value="@DEFAULT_VALUE@" label="Random seed number" help="@HELP_TEXT@" />
+    </xml>
 
-  <xml name="warm_start" token_checked="true" token_help_text="When set to True, reuse the solution of the previous call to fit as initialization,otherwise, just erase the previous solution.">
-    <param argument="warm_start" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="@CHECKED@" label="Perform warm start" help="@HELP_TEXT@"/>
-  </xml>
+    <xml name="warm_start" token_checked="true" token_help_text="When set to True, reuse the solution of the previous call to fit as initialization,otherwise, just erase the previous solution.">
+        <param argument="warm_start" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="@CHECKED@" label="Perform warm start" help="@HELP_TEXT@" />
+    </xml>
 
-  <xml name="C" token_default_value="1.0" token_help_text="Penalty parameter C of the error term.">
-    <param argument="C" type="float" optional="true" value="@DEFAULT_VALUE@" label="Penalty parameter" help="@HELP_TEXT@"/>
-  </xml>
+    <xml name="C" token_default_value="1.0" token_help_text="Penalty parameter C of the error term.">
+        <param argument="C" type="float" optional="true" value="@DEFAULT_VALUE@" label="Penalty parameter" help="@HELP_TEXT@" />
+    </xml>
 
-  <!--xml name="class_weight" token_default_value="" token_help_text="">
+    <!--xml name="class_weight" token_default_value="" token_help_text="">
     <param argument="class_weight" type="" optional="true" value="@DEFAULT_VALUE@" label="" help="@HELP_TEXT@"/>
   </xml-->
 
-  <xml name="alpha" token_default_value="0.0001" token_help_text="Constant that multiplies the regularization term if regularization is used. ">
-    <param argument="alpha" type="float" optional="true" value="@DEFAULT_VALUE@" label="Regularization coefficient" help="@HELP_TEXT@"/>
-  </xml>
+    <xml name="alpha" token_default_value="0.0001" token_help_text="Constant that multiplies the regularization term if regularization is used. ">
+        <param argument="alpha" type="float" optional="true" value="@DEFAULT_VALUE@" label="Regularization coefficient" help="@HELP_TEXT@" />
+    </xml>
 
-  <xml name="n_samples" token_default_value="100" token_help_text="The total number of points equally divided among clusters.">
-    <param argument="n_samples" type="integer" optional="true" value="@DEFAULT_VALUE@" label="Number of samples" help="@HELP_TEXT@"/>
-  </xml>
+    <xml name="n_samples" token_default_value="100" token_help_text="The total number of points equally divided among clusters.">
+        <param argument="n_samples" type="integer" optional="true" value="@DEFAULT_VALUE@" label="Number of samples" help="@HELP_TEXT@" />
+    </xml>
 
-  <xml name="n_features" token_default_value="2" token_help_text="Number of different numerical properties produced for each sample.">
-    <param argument="n_features" type="integer" optional="true" value="@DEFAULT_VALUE@" label="Number of features" help="@HELP_TEXT@"/>
-  </xml>
+    <xml name="n_features" token_default_value="2" token_help_text="Number of different numerical properties produced for each sample.">
+        <param argument="n_features" type="integer" optional="true" value="@DEFAULT_VALUE@" label="Number of features" help="@HELP_TEXT@" />
+    </xml>
 
-  <xml name="noise" token_default_value="0.0" token_help_text="Floating point number. ">
-    <param argument="noise" type="float" optional="true" value="@DEFAULT_VALUE@" label="Standard deviation of the Gaussian noise added to the data" help="@HELP_TEXT@"/>
-  </xml>
+    <xml name="noise" token_default_value="0.0" token_help_text="Floating point number. ">
+        <param argument="noise" type="float" optional="true" value="@DEFAULT_VALUE@" label="Standard deviation of the Gaussian noise added to the data" help="@HELP_TEXT@" />
+    </xml>
 
-  <xml name="C" token_default_value="1.0" token_help_text="Penalty parameter C of the error term. ">
-      <param argument="C" type="float" optional="true" value="@DEFAULT_VALUE@" label="Penalty parameter" help="@HELP_TEXT@"/>
-  </xml>
+    <xml name="C" token_default_value="1.0" token_help_text="Penalty parameter C of the error term. ">
+        <param argument="C" type="float" optional="true" value="@DEFAULT_VALUE@" label="Penalty parameter" help="@HELP_TEXT@" />
+    </xml>
 
-  <xml name="max_iter" token_default_value="300" token_label="Maximum number of iterations per single run" token_help_text=" ">
-      <param argument="max_iter" type="integer" optional="true" value="@DEFAULT_VALUE@" label="@LABEL@" help="@HELP_TEXT@"/>
-  </xml>
+    <xml name="max_iter" token_default_value="300" token_label="Maximum number of iterations per single run" token_help_text=" ">
+        <param argument="max_iter" type="integer" optional="true" value="@DEFAULT_VALUE@" label="@LABEL@" help="@HELP_TEXT@" />
+    </xml>
 
-  <xml name="n_init" token_default_value="10" >
-      <param argument="n_init" type="integer" optional="true" value="@DEFAULT_VALUE@" label="Number of runs with different centroid seeds" help=" "/>
-  </xml>
+    <xml name="n_init" token_default_value="10">
+        <param argument="n_init" type="integer" optional="true" value="@DEFAULT_VALUE@" label="Number of runs with different centroid seeds" help=" " />
+    </xml>
 
-  <xml name="init">
-      <param argument="init" type="select" label="Centroid initialization method"  help="''k-means++'' selects initial cluster centers that speed up convergence. ''random'' chooses k observations (rows) at random from data as initial centroids.">
-          <option value="k-means++">k-means++</option>
-          <option value="random">random</option>
-      </param>
-  </xml>
+    <xml name="init">
+        <param argument="init" type="select" label="Centroid initialization method" help="''k-means++'' selects initial cluster centers that speed up convergence. ''random'' chooses k observations (rows) at random from data as initial centroids.">
+            <option value="k-means++">k-means++</option>
+            <option value="random">random</option>
+        </param>
+    </xml>
 
-  <xml name="gamma" token_default_value="1.0" token_label="Scaling parameter" token_help_text=" ">
-    <param argument="gamma" type="float" optional="true" value="@DEFAULT_VALUE@" label="@LABEL@" help="@HELP_TEXT@"/>
-  </xml>
+    <xml name="gamma" token_default_value="1.0" token_label="Scaling parameter" token_help_text=" ">
+        <param argument="gamma" type="float" optional="true" value="@DEFAULT_VALUE@" label="@LABEL@" help="@HELP_TEXT@" />
+    </xml>
 
-  <xml name="degree" token_default_value="3" token_label="Degree of the polynomial" token_help_text=" ">
-    <param argument="degree" type="integer" optional="true" value="@DEFAULT_VALUE@" label="@LABEL@" help="@HELP_TEXT@"/>
-  </xml>
+    <xml name="degree" token_default_value="3" token_label="Degree of the polynomial" token_help_text=" ">
+        <param argument="degree" type="integer" optional="true" value="@DEFAULT_VALUE@" label="@LABEL@" help="@HELP_TEXT@" />
+    </xml>
 
-  <xml name="coef0" token_default_value="1" token_label="Zero coefficient" token_help_text=" ">
-    <param argument="coef0" type="integer" optional="true" value="@DEFAULT_VALUE@" label="@LABEL@" help="@HELP_TEXT@"/>
-  </xml>
+    <xml name="coef0" token_default_value="1" token_label="Zero coefficient" token_help_text=" ">
+        <param argument="coef0" type="integer" optional="true" value="@DEFAULT_VALUE@" label="@LABEL@" help="@HELP_TEXT@" />
+    </xml>
 
-  <xml name="pos_label" token_default_value="">
-    <param argument="pos_label" type="integer" optional="true" value="@DEFAULT_VALUE@" label="Label of the positive class" help=" "/>
-  </xml>
+    <xml name="pos_label" token_default_value="">
+        <param argument="pos_label" type="integer" optional="true" value="@DEFAULT_VALUE@" label="Label of the positive class" help=" " />
+    </xml>
 
-  <xml name="average">
-    <param argument="average" type="select" optional="true" label="Averaging type" help=" ">
-      <option value="micro">Calculate metrics globally by counting the total true positives, false negatives and false positives. (micro)</option>
-      <option value="samples">Calculate metrics for each instance, and find their average. Only meaningful for multilabel. (samples)</option>
-      <option value="macro">Calculate metrics for each label, and find their unweighted mean. This does not take label imbalance into account. (macro)</option>
-      <option value="weighted">Calculate metrics for each label, and find their average, weighted by support (the number of true instances for each label). This alters ‘macro’ to account for label imbalance; it can result in an F-score that is not between precision and recall. (weighted)</option>
-      <option value="None">None</option>
-      <yield/>
-    </param>
-  </xml>
+    <xml name="average">
+        <param argument="average" type="select" optional="true" label="Averaging type" help=" ">
+            <option value="micro">Calculate metrics globally by counting the total true positives, false negatives and false positives. (micro)</option>
+            <option value="samples">Calculate metrics for each instance, and find their average. Only meaningful for multilabel. (samples)</option>
+            <option value="macro">Calculate metrics for each label, and find their unweighted mean. This does not take label imbalance into account. (macro)</option>
+            <option value="weighted">Calculate metrics for each label, and find their average, weighted by support (the number of true instances for each label). This alters ‘macro’ to account for label imbalance; it can result in an F-score that is not between precision and recall. (weighted)</option>
+            <option value="None">None</option>
+            <yield />
+        </param>
+    </xml>
 
-  <xml name="beta">
-    <param argument="beta" type="float" value="1.0" label="The strength of recall versus precision in the F-score" help=" "/>
-  </xml>
+    <xml name="beta">
+        <param argument="beta" type="float" value="1.0" label="The strength of recall versus precision in the F-score" help=" " />
+    </xml>
 
 
-  <!--Data interface-->
+    <!--Data interface-->
+
+    <xml name="samples_tabular" token_label1="Training samples dataset:" token_multiple1="false" token_multiple2="false">
+        <param name="infile1" type="data" format="tabular" label="@LABEL1@" />
+        <param name="header1" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="False" label="Does the dataset contain header:" />
+        <conditional name="column_selector_options_1">
+            <expand macro="samples_column_selector_options" multiple="@MULTIPLE1@" />
+        </conditional>
+        <param name="infile2" type="data" format="tabular" label="Dataset containing class labels or target values:" />
+        <param name="header2" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="False" label="Does the dataset contain header:" />
+        <conditional name="column_selector_options_2">
+            <expand macro="samples_column_selector_options" column_option="selected_column_selector_option2" col_name="col2" multiple="@MULTIPLE2@" infile="infile2" />
+        </conditional>
+        <yield />
+    </xml>
+
+    <xml name="samples_column_selector_options" token_column_option="selected_column_selector_option" token_col_name="col1" token_multiple="False" token_infile="infile1">
+        <param name="@COLUMN_OPTION@" type="select" label="Choose how to select data by column:">
+            <option value="by_index_number" selected="true">Select columns by column index number(s)</option>
+            <option value="all_but_by_index_number">All columns EXCLUDING some by column index number(s)</option>
+            <option value="by_header_name">Select columns by column header name(s)</option>
+            <option value="all_but_by_header_name">All columns EXCLUDING some by column header name(s)</option>
+            <option value="all_columns">All columns</option>
+        </param>
+        <when value="by_index_number">
+            <param name="@COL_NAME@" multiple="@MULTIPLE@" type="data_column" use_header_names="true" data_ref="@INFILE@" label="Select target column(s):" />
+        </when>
+        <when value="all_but_by_index_number">
+            <param name="@COL_NAME@" multiple="@MULTIPLE@" type="data_column" use_header_names="true" data_ref="@INFILE@" label="Select target column(s):" />
+        </when>
+        <when value="by_header_name">
+            <param name="@COL_NAME@" type="text" value="" label="Type header name(s):" help="Comma-separated string. For example: target1,target2" />
+        </when>
+        <when value="all_but_by_header_name">
+            <param name="@COL_NAME@" type="text" value="" label="Type header name(s):" help="Comma-separated string. For example: target1,target2" />
+        </when>
+        <when value="all_columns">
+        </when>
+    </xml>
 
-  <xml name="samples_tabular" token_label1="Training samples dataset:" token_multiple1="false" token_multiple2="false">
-    <param name="infile1" type="data" format="tabular" label="@LABEL1@"/>
-    <param name="header1" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="False" label="Does the dataset contain header:" />
-    <conditional name="column_selector_options_1">
-      <expand macro="samples_column_selector_options" multiple="@MULTIPLE1@"/>
-    </conditional>
-    <param name="infile2" type="data" format="tabular" label="Dataset containing class labels or target values:"/>
-    <param name="header2" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="False" label="Does the dataset contain header:" />
-    <conditional name="column_selector_options_2">
-      <expand macro="samples_column_selector_options" column_option="selected_column_selector_option2" col_name="col2" multiple="@MULTIPLE2@" infile="infile2"/>
-    </conditional>
-    <yield/>
-  </xml>
+    <xml name="clf_inputs_extended" token_label1=" " token_label2=" " token_multiple="False">
+        <conditional name="true_columns">
+            <param name="selected_input1" type="select" label="Select the input type of true labels dataset:">
+                <option value="tabular" selected="true">Tabular</option>
+                <option value="sparse">Sparse</option>
+            </param>
+            <when value="tabular">
+                <param name="infile1" type="data" label="@LABEL1@" />
+                <param name="col1" type="data_column" data_ref="infile1" label="Select the target column:" />
+            </when>
+            <when value="sparse">
+                <param name="infile1" type="data" format="txt" label="@LABEL1@" />
+            </when>
+        </conditional>
+        <conditional name="predicted_columns">
+            <param name="selected_input2" type="select" label="Select the input type of predicted labels dataset:">
+                <option value="tabular" selected="true">Tabular</option>
+                <option value="sparse">Sparse</option>
+            </param>
+            <when value="tabular">
+                <param name="infile2" type="data" label="@LABEL2@" />
+                <param name="col2" multiple="@MULTIPLE@" type="data_column" data_ref="infile2" label="Select target column(s):" />
+            </when>
+            <when value="sparse">
+                <param name="infile2" type="data" format="txt" label="@LABEL1@" />
+            </when>
+        </conditional>
+    </xml>
+
+    <xml name="clf_inputs" token_label1="Dataset containing true labels (tabular):" token_label2="Dataset containing predicted values (tabular):" token_multiple1="False" token_multiple="False">
+        <param name="infile1" type="data" format="tabular" label="@LABEL1@" />
+        <param name="header1" type="boolean" optional="True" truevalue="booltrue" falsevalue="boolfalse" checked="False" label="Does the dataset contain header:" />
+        <conditional name="column_selector_options_1">
+            <expand macro="samples_column_selector_options" multiple="@MULTIPLE1@" />
+        </conditional>
+        <param name="infile2" type="data" format="tabular" label="@LABEL2@" />
+        <param name="header2" type="boolean" optional="True" truevalue="booltrue" falsevalue="boolfalse" checked="False" label="Does the dataset contain header:" />
+        <conditional name="column_selector_options_2">
+            <expand macro="samples_column_selector_options" column_option="selected_column_selector_option2" col_name="col2" multiple="@MULTIPLE@" infile="infile2" />
+        </conditional>
+    </xml>
+
+    <xml name="multiple_input" token_name="input_files" token_max_num="10" token_format="txt" token_label="Sparse matrix file (.mtx, .txt)" token_help_text="Specify a sparse matrix file in .txt format.">
+        <repeat name="@NAME@" min="1" max="@MAX_NUM@" title="Select input file(s):">
+            <param name="input" type="data" format="@FORMAT@" label="@LABEL@" help="@HELP_TEXT@" />
+        </repeat>
+    </xml>
+
+    <xml name="sparse_target" token_label1="Select a sparse matrix:" token_label2="Select the tabular containing true labels:" token_multiple="False" token_format1="txt" token_format2="tabular" token_help1="" token_help2="">
+        <param name="infile1" type="data" format="@FORMAT1@" label="@LABEL1@" help="@HELP1@" />
+        <expand macro="input_tabular_target" />
+    </xml>
+
+    <xml name="sl_mixed_input">
+        <conditional name="input_options">
+            <expand macro="data_input_options" />
+            <expand macro="data_input_whens" />
+        </conditional>
+    </xml>
+
+    <xml name="sl_mixed_input_plus_sequence">
+        <conditional name="input_options">
+            <expand macro="data_input_options">
+                <option value="seq_fasta">sequnences in a fasta file</option>
+                <option value="refseq_and_interval">reference genome and intervals</option>
+            </expand>
+            <expand macro="data_input_whens">
+                <when value="seq_fasta">
+                    <expand macro="inputs_seq_fasta" />
+                </when>
+                <when value="refseq_and_interval">
+                    <expand macro="inputs_refseq_and_interval" />
+                </when>
+            </expand>
+        </conditional>
+    </xml>
+
+    <xml name="data_input_options">
+        <param name="selected_input" type="select" label="Select input type:">
+            <option value="tabular" selected="true">tabular data</option>
+            <option value="sparse">sparse matrix</option>
+            <yield />
+        </param>
+    </xml>
 
-  <xml name="samples_column_selector_options" token_column_option="selected_column_selector_option" token_col_name="col1" token_multiple="False" token_infile="infile1">
-    <param name="@COLUMN_OPTION@" type="select" label="Choose how to select data by column:">
-      <option value="by_index_number" selected="true">Select columns by column index number(s)</option>
-      <option value="all_but_by_index_number">All columns EXCLUDING some by column index number(s)</option>
-      <option value="by_header_name">Select columns by column header name(s)</option>
-      <option value="all_but_by_header_name">All columns EXCLUDING some by column header name(s)</option>
-      <option value="all_columns">All columns</option>
-    </param>
-    <when value="by_index_number">
-      <param name="@COL_NAME@" multiple="@MULTIPLE@" type="data_column" use_header_names="true" data_ref="@INFILE@" label="Select target column(s):"/>
-    </when>
-    <when value="all_but_by_index_number">
-      <param name="@COL_NAME@" multiple="@MULTIPLE@" type="data_column" use_header_names="true" data_ref="@INFILE@" label="Select target column(s):"/>
-    </when>
-    <when value="by_header_name">
-      <param name="@COL_NAME@" type="text" value="" label="Type header name(s):" help="Comma-separated string. For example: target1,target2"/>
-    </when>
-    <when value="all_but_by_header_name">
-      <param name="@COL_NAME@" type="text" value="" label="Type header name(s):" help="Comma-separated string. For example: target1,target2"/>
-    </when>
-    <when value="all_columns">
-    </when>
-  </xml>
+    <xml name="data_input_whens">
+        <when value="tabular">
+            <expand macro="samples_tabular" multiple1="true" multiple2="false" />
+        </when>
+        <when value="sparse">
+            <expand macro="sparse_target" />
+        </when>
+        <yield />
+    </xml>
+
+    <xml name="input_tabular_target">
+        <param name="infile2" type="data" format="tabular" label="Dataset containing class labels or target values:" />
+        <param name="header2" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="false" label="Does the dataset contain header:" />
+        <conditional name="column_selector_options_2">
+            <expand macro="samples_column_selector_options" column_option="selected_column_selector_option2" col_name="col2" multiple="false" infile="infile2" />
+        </conditional>
+    </xml>
+
+    <xml name="inputs_seq_fasta">
+        <param name="fasta_path" type="data" format="fasta" label="Dataset containing fasta genomic/protein sequences" help="Sequences will be one-hot encoded to arrays." />
+        <expand macro="input_tabular_target" />
+    </xml>
+
+    <xml name="inputs_refseq_and_interval">
+        <param name="ref_genome_file" type="data" format="fasta" label="Dataset containing reference genomic sequence" />
+        <param name="interval_file" type="data" format="interval" label="Dataset containing sequence intervals for training" help="interval. Sequences will be retrieved from the reference genome and one-hot encoded to training arrays." />
+        <param name="target_file" type="data" format="bed" label="Dataset containing positions and features for target values." help="bed. The file will be compressed with `bgzip` and then indexed using `tabix`." />
+        <param name="infile2" type="data" format="tabular" label="Dataset containing the feature list for prediction" />
+        <param name="header2" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="false" label="Does the dataset contain header:" />
+        <conditional name="column_selector_options_2">
+            <expand macro="samples_column_selector_options" column_option="selected_column_selector_option2" col_name="col2" multiple="true" infile="infile2" />
+        </conditional>
+    </xml>
+
+    <!--Advanced options-->
+    <xml name="nn_advanced_options">
+        <section name="options" title="Advanced Options" expanded="False">
+            <yield />
+            <param argument="weights" type="select" label="Weight function" help="Used in prediction.">
+                <option value="uniform" selected="true">Uniform weights. All points in each neighborhood are weighted equally. (Uniform)</option>
+                <option value="distance">Weight points by the inverse of their distance. (Distance)</option>
+            </param>
+            <param argument="algorithm" type="select" label="Neighbor selection algorithm" help=" ">
+                <option value="auto" selected="true">Auto</option>
+                <option value="ball_tree">BallTree</option>
+                <option value="kd_tree">KDTree</option>
+                <option value="brute">Brute-force</option>
+            </param>
+            <param argument="leaf_size" type="integer" value="30" label="Leaf size" help="Used with BallTree and KDTree. Affects the time and memory usage of the constructed tree." />
+            <!--param name="metric"-->
+            <!--param name="p"-->
+            <!--param name="metric_params"-->
+        </section>
+    </xml>
+
+    <xml name="svc_advanced_options">
+        <section name="options" title="Advanced Options" expanded="False">
+            <yield />
+            <param argument="kernel" type="select" optional="true" label="Kernel type" help="Kernel type to be used in the algorithm. If none is given, ‘rbf’ will be used.">
+                <option value="rbf" selected="true">rbf</option>
+                <option value="linear">linear</option>
+                <option value="poly">poly</option>
+                <option value="sigmoid">sigmoid</option>
+                <option value="precomputed">precomputed</option>
+            </param>
+            <param argument="degree" type="integer" optional="true" value="3" label="Degree of the polynomial (polynomial kernel only)" help="Ignored by other kernels. dafault : 3 " />
+            <!--TODO: param argument="gamma" float, optional (default=’auto’) -->
+            <param argument="coef0" type="float" optional="true" value="0.0" label="Zero coefficient (polynomial and sigmoid kernels only)" help="Independent term in kernel function. dafault: 0.0 " />
+            <param argument="shrinking" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="true" label="Use the shrinking heuristic" help=" " />
+            <param argument="probability" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="false" label="Enable probability estimates. " help="This must be enabled prior to calling fit, and will slow down that method." />
+            <!-- param argument="cache_size"-->
+            <!--expand macro="class_weight"/-->
+            <expand macro="tol" default_value="0.001" help_text="Tolerance for stopping criterion. " />
+            <expand macro="max_iter" default_value="-1" label="Solver maximum number of iterations" help_text="Hard limit on iterations within solver, or -1 for no limit." />
+            <!--param argument="decision_function_shape"-->
+            <expand macro="random_state" help_text="Integer number. The seed of the pseudo random number generator to use when shuffling the data for probability estimation. A fixed seed allows reproducible results." />
+        </section>
+    </xml>
+
+    <xml name="spectral_clustering_advanced_options">
+        <section name="options" title="Advanced Options" expanded="False">
+            <expand macro="n_clusters" />
+            <param argument="eigen_solver" type="select" value="" label="Eigen solver" help="The eigenvalue decomposition strategy to use.">
+                <option value="arpack" selected="true">arpack</option>
+                <option value="lobpcg">lobpcg</option>
+                <option value="amg">amg</option>
+                <!--None-->
+            </param>
+            <expand macro="random_state" />
+            <expand macro="n_init" />
+            <param argument="gamma" type="float" optional="true" value="1.0" label="Kernel scaling factor" help="Scaling factor of RBF, polynomial, exponential chi^2 and sigmoid affinity kernel. Ignored for affinity=''nearest_neighbors''." />
+            <param argument="affinity" type="select" label="Affinity" help="Affinity kernel to use. ">
+                <option value="rbf" selected="true">RBF</option>
+                <option value="precomputed">precomputed</option>
+                <option value="nearest_neighbors">Nearset neighbors</option>
+            </param>
+            <param argument="n_neighbors" type="integer" optional="true" value="10" label="Number of neighbors" help="Number of neighbors to use when constructing the affinity matrix using the nearest neighbors method. Ignored for affinity=''rbf''" />
+            <!--param argument="eigen_tol"-->
+            <param argument="assign_labels" type="select" label="Assign labels" help="The strategy to use to assign labels in the embedding space.">
+                <option value="kmeans" selected="true">kmeans</option>
+                <option value="discretize">discretize</option>
+            </param>
+            <param argument="degree" type="integer" optional="true" value="3" label="Degree of the polynomial (polynomial kernel only)" help="Ignored by other kernels. dafault : 3 " />
+            <param argument="coef0" type="integer" optional="true" value="1" label="Zero coefficient (polynomial and sigmoid kernels only)" help="Ignored by other kernels. dafault : 1 " />
+            <!--param argument="kernel_params"-->
+        </section>
+    </xml>
+
+    <xml name="minibatch_kmeans_advanced_options">
+        <section name="options" title="Advanced Options" expanded="False">
+            <expand macro="n_clusters" />
+            <expand macro="init" />
+            <expand macro="n_init" default_value="3" />
+            <expand macro="max_iter" default_value="100" />
+            <expand macro="tol" help_text="Early stopping heuristics based on normalized center change. To disable set to 0.0 ." />
+            <expand macro="random_state" />
+            <param argument="batch_size" type="integer" optional="true" value="100" label="Batch size" help="Size of the mini batches." />
+            <!--param argument="compute_labels"-->
+            <param argument="max_no_improvement" type="integer" optional="true" value="10" label="Maximum number of improvement attempts" help="
+        Convergence detection based on inertia (the consecutive number of mini batches that doe not yield an improvement on the smoothed inertia).
+        To disable, set max_no_improvement to None. " />
+            <param argument="init_size" type="integer" optional="true" value="" label="Number of random initialization samples" help="Number of samples to randomly sample for speeding up the initialization . ( default: 3 * batch_size )" />
+            <param argument="reassignment_ratio" type="float" optional="true" value="0.01" label="Re-assignment ratio" help="Controls the fraction of the maximum number of counts for a center to be reassigned. Higher values yield better clustering results." />
+        </section>
+    </xml>
+
+    <xml name="kmeans_advanced_options">
+        <section name="options" title="Advanced Options" expanded="False">
+            <expand macro="n_clusters" />
+            <expand macro="init" />
+            <expand macro="n_init" />
+            <expand macro="max_iter" />
+            <expand macro="tol" default_value="0.0001" help_text="Relative tolerance with regards to inertia to declare convergence." />
+            <!--param argument="precompute_distances"/-->
+            <expand macro="random_state" />
+            <param argument="copy_x" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="true" label="Use a copy of data for precomputing distances" help="Mofifying the original data introduces small numerical differences caused by subtracting and then adding the data mean." />
+            <expand macro="kmeans_algorithm" />
+        </section>
+    </xml>
 
-  <xml name="clf_inputs_extended" token_label1=" " token_label2=" " token_multiple="False">
-    <conditional name="true_columns">
-      <param name="selected_input1" type="select" label="Select the input type of true labels dataset:">
-          <option value="tabular" selected="true">Tabular</option>
-          <option value="sparse">Sparse</option>
-      </param>
-      <when value="tabular">
-        <param name="infile1" type="data" label="@LABEL1@"/>
-        <param name="col1" type="data_column" data_ref="infile1" label="Select the target column:"/>
-      </when>
-      <when value="sparse">
-          <param name="infile1" type="data" format="txt" label="@LABEL1@"/>
-      </when>
-    </conditional>
-    <conditional name="predicted_columns">
-      <param name="selected_input2" type="select" label="Select the input type of predicted labels dataset:">
-          <option value="tabular" selected="true">Tabular</option>
-          <option value="sparse">Sparse</option>
-      </param>
-      <when value="tabular">
-        <param name="infile2" type="data" label="@LABEL2@"/>
-        <param name="col2" multiple="@MULTIPLE@" type="data_column" data_ref="infile2" label="Select target column(s):"/>
-      </when>
-      <when value="sparse">
-          <param name="infile2" type="data" format="txt" label="@LABEL1@"/>
-      </when>
-    </conditional>
-  </xml>
+    <xml name="kmeans_algorithm">
+        <param argument="algorithm" type="select" label="K-means algorithm to use:">
+            <option value="auto" selected="true">auto</option>
+            <option value="full">full</option>
+            <option value="elkan">elkan</option>
+        </param>
+    </xml>
+
+    <xml name="birch_advanced_options">
+        <section name="options" title="Advanced Options" expanded="False">
+            <param argument="threshold" type="float" optional="true" value="0.5" label="Subcluster radius threshold" help="The radius of the subcluster obtained by merging a new sample; the closest subcluster should be less than the threshold to avoid a new subcluster." />
+            <param argument="branching_factor" type="integer" optional="true" value="50" label="Maximum number of subclusters per branch" help="Maximum number of CF subclusters in each node." />
+            <expand macro="n_clusters" default_value="3" />
+            <!--param argument="compute_labels"/-->
+        </section>
+    </xml>
+
+    <xml name="dbscan_advanced_options">
+        <section name="options" title="Advanced Options" expanded="False">
+            <param argument="eps" type="float" optional="true" value="0.5" label="Maximum neighborhood distance" help="The maximum distance between two samples for them to be considered as in the same neighborhood." />
+            <param argument="min_samples" type="integer" optional="true" value="5" label="Minimal core point density" help="The number of samples (or total weight) in a neighborhood for a point (including the point itself) to be considered as a core point." />
+            <param argument="metric" type="text" optional="true" value="euclidean" label="Metric" help="The metric to use when calculating distance between instances in a feature array." />
+            <param argument="algorithm" type="select" label="Pointwise distance computation algorithm" help="The algorithm to be used by the NearestNeighbors module to compute pointwise distances and find nearest neighbors.">
+                <option value="auto" selected="true">auto</option>
+                <option value="ball_tree">ball_tree</option>
+                <option value="kd_tree">kd_tree</option>
+                <option value="brute">brute</option>
+            </param>
+            <param argument="leaf_size" type="integer" optional="true" value="30" label="Leaf size" help="Leaf size passed to BallTree or cKDTree. Memory and time efficieny factor in tree constrution and querying." />
+        </section>
+    </xml>
+
+    <xml name="clustering_algorithms_options">
+        <conditional name="algorithm_options">
+            <param name="selected_algorithm" type="select" label="Clustering Algorithm">
+                <option value="KMeans" selected="true">KMeans</option>
+                <option value="SpectralClustering">Spectral Clustering</option>
+                <option value="MiniBatchKMeans">Mini Batch KMeans</option>
+                <option value="DBSCAN">DBSCAN</option>
+                <option value="Birch">Birch</option>
+            </param>
+            <when value="KMeans">
+                <expand macro="kmeans_advanced_options" />
+            </when>
+            <when value="DBSCAN">
+                <expand macro="dbscan_advanced_options" />
+            </when>
+            <when value="Birch">
+                <expand macro="birch_advanced_options" />
+            </when>
+            <when value="SpectralClustering">
+                <expand macro="spectral_clustering_advanced_options" />
+            </when>
+            <when value="MiniBatchKMeans">
+                <expand macro="minibatch_kmeans_advanced_options" />
+            </when>
+        </conditional>
+    </xml>
+
+    <xml name="distance_metrics">
+        <param argument="metric" type="select" label="Distance metric" help=" ">
+            <option value="euclidean" selected="true">euclidean</option>
+            <option value="cityblock">cityblock</option>
+            <option value="cosine">cosine</option>
+            <option value="l1">l1</option>
+            <option value="l2">l2</option>
+            <option value="manhattan">manhattan</option>
+            <yield />
+        </param>
+    </xml>
+
+    <xml name="distance_nonsparse_metrics">
+        <option value="braycurtis">braycurtis</option>
+        <option value="canberra">canberra</option>
+        <option value="chebyshev">chebyshev</option>
+        <option value="correlation">correlation</option>
+        <option value="dice">dice</option>
+        <option value="hamming">hamming</option>
+        <option value="jaccard">jaccard</option>
+        <option value="kulsinski">kulsinski</option>
+        <option value="mahalanobis">mahalanobis</option>
+        <option value="matching">matching</option>
+        <option value="minkowski">minkowski</option>
+        <option value="rogerstanimoto">rogerstanimoto</option>
+        <option value="russellrao">russellrao</option>
+        <option value="seuclidean">seuclidean</option>
+        <option value="sokalmichener">sokalmichener</option>
+        <option value="sokalsneath">sokalsneath</option>
+        <option value="sqeuclidean">sqeuclidean</option>
+        <option value="yule">yule</option>
+    </xml>
+
+    <xml name="pairwise_kernel_metrics">
+        <param argument="metric" type="select" label="Pirwise Kernel metric" help=" ">
+            <option value="rbf" selected="true">rbf</option>
+            <option value="sigmoid">sigmoid</option>
+            <option value="polynomial">polynomial</option>
+            <option value="linear" selected="true">linear</option>
+            <option value="chi2">chi2</option>
+            <option value="additive_chi2">additive_chi2</option>
+        </param>
+    </xml>
+
+    <xml name="sparse_pairwise_metric_functions">
+        <param name="selected_metric_function" type="select" label="Select the pairwise metric you want to compute:">
+            <option value="euclidean_distances" selected="true">Euclidean distance matrix</option>
+            <option value="pairwise_distances">Distance matrix</option>
+            <option value="pairwise_distances_argmin">Minimum distances between one point and a set of points</option>
+            <yield />
+        </param>
+    </xml>
+
+    <xml name="pairwise_metric_functions">
+        <option value="additive_chi2_kernel">Additive chi-squared kernel</option>
+        <option value="chi2_kernel">Exponential chi-squared kernel</option>
+        <option value="linear_kernel">Linear kernel</option>
+        <option value="manhattan_distances">L1 distances</option>
+        <option value="pairwise_kernels">Kernel</option>
+        <option value="polynomial_kernel">Polynomial kernel</option>
+        <option value="rbf_kernel">Gaussian (rbf) kernel</option>
+        <option value="laplacian_kernel">Laplacian kernel</option>
+    </xml>
 
-  <xml name="clf_inputs" token_label1="Dataset containing true labels (tabular):" token_label2="Dataset containing predicted values (tabular):" token_multiple1="False" token_multiple="False">
-    <param name="infile1" type="data" format="tabular" label="@LABEL1@"/>
-    <param name="header1" type="boolean" optional="True" truevalue="booltrue" falsevalue="boolfalse" checked="False" label="Does the dataset contain header:" />
-    <conditional name="column_selector_options_1">
-      <expand macro="samples_column_selector_options" multiple="@MULTIPLE1@"/>
-    </conditional>
-    <param name="infile2" type="data" format="tabular" label="@LABEL2@"/>
-    <param name="header2" type="boolean" optional="True" truevalue="booltrue" falsevalue="boolfalse" checked="False" label="Does the dataset contain header:" />
-    <conditional name="column_selector_options_2">
-      <expand macro="samples_column_selector_options" column_option="selected_column_selector_option2" col_name="col2" multiple="@MULTIPLE@" infile="infile2"/>
-    </conditional>
-  </xml>
+    <xml name="sparse_pairwise_condition">
+        <when value="pairwise_distances">
+            <section name="options" title="Advanced Options" expanded="False">
+                <expand macro="distance_metrics">
+                    <yield />
+                </expand>
+            </section>
+        </when>
+        <when value="euclidean_distances">
+            <section name="options" title="Advanced Options" expanded="False">
+                <param argument="squared" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="false" label="Return squared Euclidean distances" help=" " />
+            </section>
+        </when>
+    </xml>
 
-  <xml name="multiple_input" token_name="input_files" token_max_num="10" token_format="txt" token_label="Sparse matrix file (.mtx, .txt)" token_help_text="Specify a sparse matrix file in .txt format.">
-    <repeat name="@NAME@" min="1" max="@MAX_NUM@" title="Select input file(s):">
-        <param name="input" type="data" format="@FORMAT@" label="@LABEL@" help="@HELP_TEXT@"/>
-    </repeat>
-  </xml>
+    <xml name="argmin_distance_condition">
+        <when value="pairwise_distances_argmin">
+            <section name="options" title="Advanced Options" expanded="False">
+                <param argument="axis" type="integer" optional="true" value="1" label="Axis" help="Axis along which the argmin and distances are to be computed." />
+                <expand macro="distance_metrics">
+                    <yield />
+                </expand>
+                <param argument="batch_size" type="integer" optional="true" value="500" label="Batch size" help="Number of rows to be processed in each batch run." />
+            </section>
+        </when>
+    </xml>
+
+    <xml name="sparse_preprocessors">
+        <param name="selected_pre_processor" type="select" label="Select a preprocessor:">
+            <option value="StandardScaler" selected="true">Standard Scaler (Standardizes features by removing the mean and scaling to unit variance)</option>
+            <option value="Binarizer">Binarizer (Binarizes data)</option>
+            <option value="MaxAbsScaler">Max Abs Scaler (Scales features by their maximum absolute value)</option>
+            <option value="Normalizer">Normalizer (Normalizes samples individually to unit norm)</option>
+            <yield />
+        </param>
+    </xml>
+
+    <xml name="sparse_preprocessors_ext">
+        <expand macro="sparse_preprocessors">
+            <option value="KernelCenterer">Kernel Centerer (Centers a kernel matrix)</option>
+            <option value="MinMaxScaler">Minmax Scaler (Scales features to a range)</option>
+            <option value="PolynomialFeatures">Polynomial Features (Generates polynomial and interaction features)</option>
+            <option value="RobustScaler">Robust Scaler (Scales features using outlier-invariance statistics)</option>
+            <option value="QuantileTransformer">QuantileTransformer (Transform features using quantiles information)</option>
+            <option value="PowerTransformer">PowerTransformer (Apply a power transform featurewise to make data more Gaussian-like)</option>
+            <option value="KBinsDiscretizer">KBinsDiscretizer (Bin continuous data into intervals.)</option>
+        </expand>
+    </xml>
 
-  <xml name="sparse_target" token_label1="Select a sparse matrix:" token_label2="Select the tabular containing true labels:" token_multiple="False" token_format1="txt" token_format2="tabular" token_help1="" token_help2="">
-    <param name="infile1" type="data" format="@FORMAT1@" label="@LABEL1@" help="@HELP1@"/>
-    <expand macro="input_tabular_target"/>
-  </xml>
-
-  <xml name="sl_mixed_input">
-    <conditional name="input_options">
-        <expand macro="data_input_options"/>
-        <expand macro="data_input_whens"/>
-    </conditional>
-  </xml>
+    <xml name="sparse_preprocessor_options">
+        <when value="Binarizer">
+            <section name="options" title="Advanced Options" expanded="False">
+                <param argument="copy" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="true" label="Use a copy of data for precomputing binarization" help=" " />
+                <param argument="threshold" type="float" optional="true" value="0.0" label="Threshold" help="Feature values below or equal to this are replaced by 0, above it by 1. Threshold may not be less than 0 for operations on sparse matrices. " />
+            </section>
+        </when>
+        <when value="StandardScaler">
+            <section name="options" title="Advanced Options" expanded="False">
+                <param argument="copy" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="true" label="Use a copy of data for performing inplace scaling" help=" " />
+                <param argument="with_mean" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="true" label="Center the data before scaling" help=" " />
+                <param argument="with_std" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="true" label="Scale the data to unit variance (or unit standard deviation)" help=" " />
+            </section>
+        </when>
+        <when value="MaxAbsScaler">
+            <section name="options" title="Advanced Options" expanded="False">
+                <param argument="copy" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="true" label="Use a copy of data for precomputing scaling" help=" " />
+            </section>
+        </when>
+        <when value="Normalizer">
+            <section name="options" title="Advanced Options" expanded="False">
+                <param argument="norm" type="select" optional="true" label="The norm to use to normalize non zero samples" help=" ">
+                    <option value="l1" selected="true">l1</option>
+                    <option value="l2">l2</option>
+                    <option value="max">max</option>
+                </param>
+                <param argument="copy" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="true" label="Use a copy of data for precomputing row normalization" help=" " />
+            </section>
+        </when>
+        <yield />
+    </xml>
 
-  <xml name="sl_mixed_input_plus_sequence">
-    <conditional name="input_options">
-        <expand macro="data_input_options">
-            <option value="seq_fasta">sequnences in a fasta file</option>
-            <option value="refseq_and_interval">reference genome and intervals</option>
-        </expand>
-        <expand macro="data_input_whens">
-            <when value="seq_fasta">
-                <expand macro="inputs_seq_fasta"/>
+    <xml name="sparse_preprocessor_options_ext">
+        <expand macro="sparse_preprocessor_options">
+            <when value="KernelCenterer">
+                <section name="options" title="Advanced Options" expanded="False">
+                </section>
+            </when>
+            <when value="MinMaxScaler">
+                <section name="options" title="Advanced Options" expanded="False">
+                    <param argument="feature_range" type="text" value="(0, 1)" optional="true" help="Desired range of transformed data. None or tuple (min, max). None equals to (0, 1)" />
+                    <param argument="copy" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolflase" checked="true" label="Use a copy of data for precomputing normalization" help=" " />
+                </section>
+            </when>
+            <when value="PolynomialFeatures">
+                <section name="options" title="Advanced Options" expanded="False">
+                    <param argument="degree" type="integer" optional="true" value="2" label="The degree of the polynomial features " help="" />
+                    <param argument="interaction_only" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolflase" checked="false" label="Produce interaction features only" help="(Features that are products of at most degree distinct input features) " />
+                    <param argument="include_bias" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolflase" checked="true" label="Include a bias column" help="Feature in which all polynomial powers are zero " />
+                </section>
+            </when>
+            <when value="RobustScaler">
+                <section name="options" title="Advanced Options" expanded="False">
+                    <!--=True, =True, copy=True-->
+                    <param argument="with_centering" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolflase" checked="true" label="Center the data before scaling" help=" " />
+                    <param argument="with_scaling" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolflase" checked="true" label="Scale the data to interquartile range" help=" " />
+                    <param argument="copy" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolflase" checked="true" label="Use a copy of data for inplace scaling" help=" " />
+                </section>
             </when>
-            <when value="refseq_and_interval">
-                <expand macro="inputs_refseq_and_interval"/>
+            <when value="QuantileTransformer">
+                <section name="options" title="Advanced Options" expanded="False">
+                    <param name="n_quantiles" type="integer" value="1000" min="0" label="Number of quantiles to be computed" />
+                    <param name="output_distribution" type="select" label="Marginal distribution for the transformed data">
+                        <option value="uniform" selected="true">uniform</option>
+                        <option value="normal">normal</option>
+                    </param>
+                    <param name="ignore_implicit_zeros" type="boolean" truevalue="booltrue" falsevalue="boolfalse" checked="false" label="Whether to discard sparse entries" help="Only applies to sparse matrices. If False, sparse entries are treated as zeros" />
+                    <param name="subsample" type="integer" value="100000" label="Maximum number of samples used to estimate the quantiles for computational efficiency" help="Note that the subsampling procedure may differ for value-identical sparse and dense matrices." />
+                    <expand macro="random_state" help_text="This is used by subsampling and smoothing noise" />
+                </section>
+            </when>
+            <when value="PowerTransformer">
+                <section name="options" title="Advanced Options" expanded="False">
+                    <param name="method" type="select" label="The power transform method">
+                        <option value="yeo-johnson" selected="true">yeo-johnson (works with positive and negative values)</option>
+                        <option value="box-cox">box-cox (might perform better, but only works with strictly positive values)</option>
+                    </param>
+                    <param name="standardize" type="boolean" truevalue="booltrue" falsevalue="boolfalse" checked="true" label="Whether to apply zero-mean, unit-variance normalization to the transformed output." />
+                </section>
+            </when>
+            <when value="KBinsDiscretizer">
+                <section name="options" title="Advanced Options" expanded="False">
+                    <param name="n_bins" type="integer" value="5" min="2" label="The number of bins to produce" />
+                    <param name="encode" type="select" label="Method used to encode the transformed result">
+                        <option value="onehot" selected="true">onehot (encode the transformed result with one-hot encoding and return a sparse matrix)</option>
+                        <option value="onehot-dense">onehot-dense (encode the transformed result with one-hot encoding and return a dense array)</option>
+                        <option value="ordinal">ordinal (return the bin identifier encoded as an integer value)</option>
+                    </param>
+                    <param name="strategy" type="select" label="Strategy used to define the widths of the bins">
+                        <option value="uniform">uniform (all bins in each feature have identical widths)</option>
+                        <option value="quantile" selected="true">quantile (all bins in each feature have the same number of points)</option>
+                        <option value="kmeans">kmeans (values in each bin have the same nearest center of a 1D k-means cluster)</option>
+                    </param>
+                </section>
             </when>
         </expand>
-    </conditional>
-  </xml>
-
-  <xml name="data_input_options">
-    <param name="selected_input" type="select" label="Select input type:">
-        <option value="tabular" selected="true">tabular data</option>
-        <option value="sparse">sparse matrix</option>
-        <yield/>
-    </param>
-  </xml>
+    </xml>
 
-  <xml name="data_input_whens">
-    <when value="tabular">
-        <expand macro="samples_tabular" multiple1="true" multiple2="false"/>
-    </when>
-    <when value="sparse">
-        <expand macro="sparse_target"/>
-    </when>
-    <yield/>
-  </xml>
-
-  <xml name="input_tabular_target">
-    <param name="infile2" type="data" format="tabular" label="Dataset containing class labels or target values:"/>
-    <param name="header2" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="false" label="Does the dataset contain header:" />
-    <conditional name="column_selector_options_2">
-      <expand macro="samples_column_selector_options" column_option="selected_column_selector_option2" col_name="col2" multiple="false" infile="infile2"/>
-    </conditional>
-  </xml>
+    <xml name="cv_splitter">
+        <option value="default" selected="true">default splitter</option>
+        <option value="KFold">KFold</option>
+        <option value="StratifiedKFold">StratifiedKFold</option>
+        <option value="LeaveOneOut">LeaveOneOut</option>
+        <option value="LeavePOut">LeavePOut</option>
+        <option value="RepeatedKFold">RepeatedKFold</option>
+        <option value="RepeatedStratifiedKFold">RepeatedStratifiedKFold</option>
+        <option value="ShuffleSplit">ShuffleSplit</option>
+        <option value="StratifiedShuffleSplit">StratifiedShuffleSplit</option>
+        <option value="TimeSeriesSplit">TimeSeriesSplit</option>
+        <option value="PredefinedSplit">PredefinedSplit</option>
+        <option value="OrderedKFold">OrderedKFold</option>
+        <option value="RepeatedOrderedKFold">RepeatedOrderedKFold</option>
+        <yield />
+    </xml>
 
-  <xml name="inputs_seq_fasta">
-    <param name="fasta_path" type="data" format="fasta" label="Dataset containing fasta genomic/protein sequences" help="Sequences will be one-hot encoded to arrays."/>
-    <expand macro="input_tabular_target"/>
-  </xml>
-
-  <xml name="inputs_refseq_and_interval">
-    <param name="ref_genome_file" type="data" format="fasta" label="Dataset containing reference genomic sequence"/>
-    <param name="interval_file" type="data" format="interval" label="Dataset containing sequence intervals for training" help="interval. Sequences will be retrieved from the reference genome and one-hot encoded to training arrays."/>
-    <param name="target_file" type="data" format="bed" label="Dataset containing positions and features for target values." help="bed. The file will be compressed with `bgzip` and then indexed using `tabix`."/>
-    <param name="infile2" type="data" format="tabular" label="Dataset containing the feature list for prediction"/>
-    <param name="header2" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="false" label="Does the dataset contain header:" />
-    <conditional name="column_selector_options_2">
-      <expand macro="samples_column_selector_options" column_option="selected_column_selector_option2" col_name="col2" multiple="true" infile="infile2"/>
-    </conditional>
-  </xml>
-
-  <!--Advanced options-->
-  <xml name="nn_advanced_options">
-    <section name="options" title="Advanced Options" expanded="False">
-      <yield/>
-      <param argument="weights" type="select" label="Weight function" help="Used in prediction.">
-          <option value="uniform" selected="true">Uniform weights. All points in each neighborhood are weighted equally. (Uniform)</option>
-          <option value="distance">Weight points by the inverse of their distance. (Distance)</option>
-      </param>
-      <param argument="algorithm" type="select" label="Neighbor selection algorithm" help=" ">
-          <option value="auto" selected="true">Auto</option>
-          <option value="ball_tree">BallTree</option>
-          <option value="kd_tree">KDTree</option>
-          <option value="brute">Brute-force</option>
-      </param>
-      <param argument="leaf_size" type="integer" value="30" label="Leaf size" help="Used with BallTree and KDTree. Affects the time and memory usage of the constructed tree."/>
-      <!--param name="metric"-->
-      <!--param name="p"-->
-      <!--param name="metric_params"-->
-    </section>
-  </xml>
+    <xml name="cv_splitter_options">
+        <when value="default">
+            <expand macro="cv_n_splits" />
+        </when>
+        <when value="KFold">
+            <expand macro="cv_n_splits" />
+            <expand macro="cv_shuffle" />
+            <expand macro="random_state" />
+        </when>
+        <when value="StratifiedKFold">
+            <expand macro="cv_n_splits" />
+            <expand macro="cv_shuffle" />
+            <expand macro="random_state" />
+        </when>
+        <when value="LeaveOneOut">
+        </when>
+        <when value="LeavePOut">
+            <param argument="p" type="integer" value="" label="p" help="Integer. Size of the test sets." />
+        </when>
+        <when value="RepeatedKFold">
+            <expand macro="cv_n_splits" value="5" />
+            <param argument="n_repeats" type="integer" value="10" label="n_repeats" help="Number of times cross-validator needs to be repeated." />
+            <expand macro="random_state" />
+        </when>
+        <when value="RepeatedStratifiedKFold">
+            <expand macro="cv_n_splits" value="5" />
+            <param argument="n_repeats" type="integer" value="10" label="n_repeats" help="Number of times cross-validator needs to be repeated." />
+            <expand macro="random_state" />
+        </when>
+        <when value="ShuffleSplit">
+            <expand macro="cv_n_splits" value="10" help="Number of re-shuffling and splitting iterations." />
+            <expand macro="cv_test_size" value="0.1" />
+            <expand macro="random_state" />
+        </when>
+        <when value="StratifiedShuffleSplit">
+            <expand macro="cv_n_splits" value="10" help="Number of re-shuffling and splitting iterations." />
+            <expand macro="cv_test_size" value="0.1" />
+            <expand macro="random_state" />
+        </when>
+        <when value="TimeSeriesSplit">
+            <expand macro="cv_n_splits" />
+            <param argument="max_train_size" type="integer" value="" optional="true" label="Maximum size of the training set" help="Maximum size for a single training set." />
+        </when>
+        <when value="PredefinedSplit">
+            <param argument="test_fold" type="text" value="" area="true" label="test_fold" help="List, e.g., [0, 1, -1, 1], represents two test sets, [X[0]] and [X[1], X[3]], X[2] is excluded from any test set due to '-1'." />
+        </when>
+        <when value="OrderedKFold">
+            <expand macro="cv_n_splits" />
+            <expand macro="cv_shuffle" />
+            <expand macro="random_state" />
+        </when>
+        <when value="RepeatedOrderedKFold">
+            <expand macro="cv_n_splits" />
+            <param argument="n_repeats" type="integer" value="5" />
+            <expand macro="random_state" />
+        </when>
+        <yield />
+    </xml>
 
-  <xml name="svc_advanced_options">
-    <section name="options" title="Advanced Options" expanded="False">
-        <yield/>
-        <param argument="kernel" type="select" optional="true" label="Kernel type" help="Kernel type to be used in the algorithm. If none is given, ‘rbf’ will be used.">
-            <option value="rbf" selected="true">rbf</option>
-            <option value="linear">linear</option>
-            <option value="poly">poly</option>
-            <option value="sigmoid">sigmoid</option>
-            <option value="precomputed">precomputed</option>
-        </param>
-        <param argument="degree" type="integer" optional="true" value="3" label="Degree of the polynomial (polynomial kernel only)" help="Ignored by other kernels. dafault : 3 "/>
-        <!--TODO: param argument="gamma" float, optional (default=’auto’) -->
-        <param argument="coef0" type="float" optional="true" value="0.0" label="Zero coefficient (polynomial and sigmoid kernels only)"
-            help="Independent term in kernel function. dafault: 0.0 "/>
-        <param argument="shrinking" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="true"
-            label="Use the shrinking heuristic" help=" "/>
-        <param argument="probability" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="false"
-            label="Enable probability estimates. " help="This must be enabled prior to calling fit, and will slow down that method."/>
-        <!-- param argument="cache_size"-->
-        <!--expand macro="class_weight"/-->
-        <expand macro="tol" default_value="0.001" help_text="Tolerance for stopping criterion. "/>
-        <expand macro="max_iter" default_value="-1" label="Solver maximum number of iterations" help_text="Hard limit on iterations within solver, or -1 for no limit."/>
-        <!--param argument="decision_function_shape"-->
-        <expand macro="random_state" help_text="Integer number. The seed of the pseudo random number generator to use when shuffling the data for probability estimation. A fixed seed allows reproducible results."/>
-    </section>
-  </xml>
+    <xml name="cv">
+        <conditional name="cv_selector">
+            <param name="selected_cv" type="select" label="Select the cv splitter:">
+                <expand macro="cv_splitter">
+                    <option value="GroupKFold">GroupKFold</option>
+                    <option value="GroupShuffleSplit">GroupShuffleSplit</option>
+                    <option value="LeaveOneGroupOut">LeaveOneGroupOut</option>
+                    <option value="LeavePGroupsOut">LeavePGroupsOut</option>
+                </expand>
+            </param>
+            <expand macro="cv_splitter_options">
+                <when value="GroupKFold">
+                    <expand macro="cv_n_splits" />
+                    <expand macro="cv_groups" />
+                </when>
+                <when value="GroupShuffleSplit">
+                    <expand macro="cv_n_splits" value="5" />
+                    <expand macro="cv_test_size" />
+                    <expand macro="random_state" />
+                    <expand macro="cv_groups" />
+                </when>
+                <when value="LeaveOneGroupOut">
+                    <expand macro="cv_groups" />
+                </when>
+                <when value="LeavePGroupsOut">
+                    <param argument="n_groups" type="integer" value="" label="n_groups" help="Number of groups (p) to leave out in the test split." />
+                    <expand macro="cv_groups" />
+                </when>
+            </expand>
+        </conditional>
+    </xml>
+
+    <xml name="cv_reduced" token_label="Select the cv splitter">
+        <conditional name="cv_selector">
+            <param name="selected_cv" type="select" label="@LABEL@">
+                <expand macro="cv_splitter" />
+            </param>
+            <expand macro="cv_splitter_options" />
+        </conditional>
+    </xml>
+
+    <xml name="cv_n_splits" token_value="3" token_help="Number of folds. Must be at least 2.">
+        <param argument="n_splits" type="integer" value="@VALUE@" min="1" label="n_splits" help="@HELP@" />
+    </xml>
+
+    <xml name="cv_shuffle">
+        <param argument="shuffle" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="false" label="Whether to shuffle data before splitting" />
+    </xml>
+
+    <xml name="cv_test_size" token_value="0.2">
+        <param argument="test_size" type="float" value="@VALUE@" min="0.0" label="Portion or number of the test set" help="0.0-1.0, proportion of the dataset to include in the test split; >1, integer only, the absolute number of test samples " />
+    </xml>
 
-  <xml name="spectral_clustering_advanced_options">
-    <section name="options" title="Advanced Options" expanded="False">
-        <expand macro="n_clusters"/>
-        <param argument="eigen_solver" type="select" value="" label="Eigen solver" help="The eigenvalue decomposition strategy to use.">
-            <option value="arpack" selected="true">arpack</option>
-            <option value="lobpcg">lobpcg</option>
-            <option value="amg">amg</option>
-            <!--None-->
-        </param>
-        <expand macro="random_state"/>
-        <expand macro="n_init"/>
-        <param argument="gamma" type="float" optional="true" value="1.0" label="Kernel scaling factor" help="Scaling factor of RBF, polynomial, exponential chi^2 and sigmoid affinity kernel. Ignored for affinity=''nearest_neighbors''."/>
-        <param argument="affinity" type="select" label="Affinity" help="Affinity kernel to use. ">
-            <option value="rbf" selected="true">RBF</option>
-            <option value="precomputed">precomputed</option>
-            <option value="nearest_neighbors">Nearset neighbors</option>
-        </param>
-        <param argument="n_neighbors" type="integer" optional="true" value="10" label="Number of neighbors" help="Number of neighbors to use when constructing the affinity matrix using the nearest neighbors method. Ignored for affinity=''rbf''"/>
-        <!--param argument="eigen_tol"-->
-        <param argument="assign_labels" type="select" label="Assign labels" help="The strategy to use to assign labels in the embedding space.">
-            <option value="kmeans" selected="true">kmeans</option>
-            <option value="discretize">discretize</option>
-        </param>
-        <param argument="degree" type="integer" optional="true" value="3"
-            label="Degree of the polynomial (polynomial kernel only)" help="Ignored by other kernels. dafault : 3 "/>
-        <param argument="coef0" type="integer" optional="true" value="1"
-            label="Zero coefficient (polynomial and sigmoid kernels only)" help="Ignored by other kernels. dafault : 1 "/>
-        <!--param argument="kernel_params"-->
-    </section>
-  </xml>
+    <xml name="cv_groups">
+        <section name="groups_selector" title="Groups column selector" expanded="true">
+            <param name="infile_g" type="data" format="tabular" label="Choose dataset containing groups info:" />
+            <param name="header_g" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="False" label="Does the dataset contain header:" />
+            <conditional name="column_selector_options_g">
+                <expand macro="samples_column_selector_options" column_option="selected_column_selector_option_g" col_name="col_g" multiple="False" infile="infile_g" />
+            </conditional>
+        </section>
+    </xml>
 
-  <xml name="minibatch_kmeans_advanced_options">
-    <section name="options" title="Advanced Options" expanded="False">
-        <expand macro="n_clusters"/>
-        <expand macro="init"/>
-        <expand macro="n_init" default_value="3"/>
-        <expand macro="max_iter" default_value="100"/>
-        <expand macro="tol" help_text="Early stopping heuristics based on normalized center change. To disable set to 0.0 ."/>
-        <expand macro="random_state"/>
-        <param argument="batch_size" type="integer" optional="true" value="100" label="Batch size" help="Size of the mini batches."/>
-        <!--param argument="compute_labels"-->
-        <param argument="max_no_improvement" type="integer" optional="true" value="10" label="Maximum number of improvement attempts" help="
-        Convergence detection based on inertia (the consecutive number of mini batches that doe not yield an improvement on the smoothed inertia).
-        To disable, set max_no_improvement to None. "/>
-        <param argument="init_size" type="integer" optional="true" value="" label="Number of random initialization samples" help="Number of samples to randomly sample for speeding up the initialization . ( default: 3 * batch_size )"/>
-        <param argument="reassignment_ratio" type="float" optional="true" value="0.01" label="Re-assignment ratio" help="Controls the fraction of the maximum number of counts for a center to be reassigned. Higher values yield better clustering results."/>
-    </section>
-  </xml>
+    <xml name="train_test_split_params">
+        <conditional name="split_algos">
+            <param name="shuffle" type="select" label="Select the splitting method">
+                <option value="None">No shuffle</option>
+                <option value="simple" selected="true">ShuffleSplit</option>
+                <option value="stratified">StratifiedShuffleSplit -- target values serve as class labels</option>
+                <option value="group">GroupShuffleSplit or split by group names</option>
+            </param>
+            <when value="None">
+                <expand macro="train_test_split_test_size" />
+            </when>
+            <when value="simple">
+                <expand macro="train_test_split_test_size" />
+                <expand macro="random_state" />
+            </when>
+            <when value="stratified">
+                <expand macro="train_test_split_test_size" />
+                <expand macro="random_state" />
+            </when>
+            <when value="group">
+                <expand macro="train_test_split_test_size" optional="true" />
+                <expand macro="random_state" />
+                <param argument="group_names" type="text" value="" optional="true" label="Type in group names instead" help="For example: chr6, chr7. This parameter is optional. If used, it will override the holdout size and random seed." />
+                <yield />
+            </when>
+        </conditional>
+        <!--param argument="train_size" type="float" optional="True" value="" label="Train size:"/>-->
+    </xml>
 
-  <xml name="kmeans_advanced_options">
-    <section name="options" title="Advanced Options" expanded="False">
-      <expand macro="n_clusters"/>
-      <expand macro="init"/>
-      <expand macro="n_init"/>
-      <expand macro="max_iter"/>
-      <expand macro="tol" default_value="0.0001" help_text="Relative tolerance with regards to inertia to declare convergence."/>
-      <!--param argument="precompute_distances"/-->
-      <expand macro="random_state"/>
-      <param argument="copy_x" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="true" label="Use a copy of data for precomputing distances" help="Mofifying the original data introduces small numerical differences caused by subtracting and then adding the data mean."/>
-      <expand macro="kmeans_algorithm"/>
-    </section>
-  </xml>
+    <xml name="train_test_split_test_size" token_optional="false">
+        <param name="test_size" type="float" value="0.2" optional="@OPTIONAL@" label="Holdout size" help="Leass than 1, for preportion; greater than 1 (integer), for number of samples." />
+    </xml>
 
-  <xml name="kmeans_algorithm">
-    <param argument="algorithm" type="select" label="K-means algorithm to use:">
-      <option value="auto" selected="true">auto</option>
-      <option value="full">full</option>
-      <option value="elkan">elkan</option>
-    </param>
-  </xml>
-
-  <xml name="birch_advanced_options">
-    <section name="options" title="Advanced Options" expanded="False">
-      <param argument="threshold" type="float" optional="true" value="0.5" label="Subcluster radius threshold" help="The radius of the subcluster obtained by merging a new sample; the closest subcluster should be less than the threshold to avoid a new subcluster."/>
-      <param argument="branching_factor" type="integer" optional="true" value="50" label="Maximum number of subclusters per branch" help="Maximum number of CF subclusters in each node."/>
-      <expand macro="n_clusters" default_value="3"/>
-      <!--param argument="compute_labels"/-->
-    </section>
-  </xml>
+    <xml name="feature_selection_algorithms">
+        <option value="SelectKBest" selected="true">SelectKBest - Select features according to the k highest scores</option>
+        <option value="GenericUnivariateSelect">GenericUnivariateSelect - Univariate feature selector with configurable strategy</option>
+        <option value="SelectPercentile">SelectPercentile - Select features according to a percentile of the highest scores</option>
+        <option value="SelectFpr">SelectFpr - Filter: Select the p-values below alpha based on a FPR test</option>
+        <option value="SelectFdr">SelectFdr - Filter: Select the p-values for an estimated false discovery rate</option>
+        <option value="SelectFwe">SelectFwe - Filter: Select the p-values corresponding to Family-wise error rate</option>
+        <option value="VarianceThreshold">VarianceThreshold - Feature selector that removes all low-variance features</option>
+        <option value="SelectFromModel">SelectFromModel - Meta-transformer for selecting features based on importance weights</option>
+        <option value="RFE">RFE - Feature ranking with recursive feature elimination</option>
+        <option value="RFECV">RFECV - Feature ranking with recursive feature elimination and cross-validated selection of the best number of features</option>
+        <yield />
+    </xml>
 
-  <xml name="dbscan_advanced_options">
-    <section name="options" title="Advanced Options" expanded="False">
-      <param argument="eps" type="float" optional="true" value="0.5" label="Maximum neighborhood distance" help="The maximum distance between two samples for them to be considered as in the same neighborhood."/>
-      <param argument="min_samples" type="integer" optional="true" value="5" label="Minimal core point density" help="The number of samples (or total weight) in a neighborhood for a point (including the point itself) to be considered as a core point."/>
-      <param argument="metric" type="text" optional="true" value="euclidean" label="Metric" help="The metric to use when calculating distance between instances in a feature array."/>
-      <param argument="algorithm" type="select" label="Pointwise distance computation algorithm" help="The algorithm to be used by the NearestNeighbors module to compute pointwise distances and find nearest neighbors.">
-          <option value="auto" selected="true">auto</option>
-          <option value="ball_tree">ball_tree</option>
-          <option value="kd_tree">kd_tree</option>
-          <option value="brute">brute</option>
-      </param>
-      <param argument="leaf_size" type="integer" optional="true" value="30" label="Leaf size" help="Leaf size passed to BallTree or cKDTree. Memory and time efficieny factor in tree constrution and querying."/>
-    </section>
-  </xml>
-
-  <xml name="clustering_algorithms_options">
-    <conditional name="algorithm_options">
-      <param name="selected_algorithm" type="select" label="Clustering Algorithm">
-          <option value="KMeans" selected="true">KMeans</option>
-          <option value="SpectralClustering">Spectral Clustering</option>
-          <option value="MiniBatchKMeans">Mini Batch KMeans</option>
-          <option value="DBSCAN">DBSCAN</option>
-          <option value="Birch">Birch</option>
-      </param>
-      <when value="KMeans">
-          <expand macro="kmeans_advanced_options"/>
-      </when>
-      <when value="DBSCAN">
-          <expand macro="dbscan_advanced_options"/>
-      </when>
-      <when value="Birch">
-          <expand macro="birch_advanced_options"/>
-      </when>
-      <when value="SpectralClustering">
-          <expand macro="spectral_clustering_advanced_options"/>
-      </when>
-      <when value="MiniBatchKMeans">
-          <expand macro="minibatch_kmeans_advanced_options"/>
-      </when>
-    </conditional>
-  </xml>
+    <xml name="feature_selection_algorithm_details">
+        <when value="GenericUnivariateSelect">
+            <expand macro="feature_selection_score_function" />
+            <section name="options" title="Advanced Options" expanded="False">
+                <param argument="mode" type="select" label="Feature selection mode">
+                    <option value="percentile">percentile</option>
+                    <option value="k_best">k_best</option>
+                    <option value="fpr">fpr</option>
+                    <option value="fdr">fdr</option>
+                    <option value="fwe">fwe</option>
+                </param>
+                <param argument="param" type="float" value="" optional="true" label="Parameter of the corresponding mode" help="float or int depending on the feature selection mode" />
+            </section>
+        </when>
+        <when value="SelectPercentile">
+            <expand macro="feature_selection_score_function" />
+            <section name="options" title="Advanced Options" expanded="False">
+                <param argument="percentile" type="integer" value="10" optional="True" label="Percent of features to keep" />
+            </section>
+        </when>
+        <when value="SelectKBest">
+            <expand macro="feature_selection_score_function" />
+            <section name="options" title="Advanced Options" expanded="False">
+                <param argument="k" type="integer" value="10" optional="True" label="Number of top features to select" help="No 'all' option is supported." />
+            </section>
+        </when>
+        <when value="SelectFpr">
+            <expand macro="feature_selection_score_function" />
+            <section name="options" title="Advanced Options" expanded="False">
+                <param argument="alpha" type="float" value="" optional="True" label="Alpha" help="The highest p-value for features to be kept." />
+            </section>
+        </when>
+        <when value="SelectFdr">
+            <expand macro="feature_selection_score_function" />
+            <section name="options" title="Advanced Options" expanded="False">
+                <param argument="alpha" type="float" value="" optional="True" label="Alpha" help="The highest uncorrected p-value for features to keep." />
+            </section>
+        </when>
+        <when value="SelectFwe">
+            <expand macro="feature_selection_score_function" />
+            <section name="options" title="Advanced Options" expanded="False">
+                <param argument="alpha" type="float" value="" optional="True" label="Alpha" help="The highest uncorrected p-value for features to keep." />
+            </section>
+        </when>
+        <when value="VarianceThreshold">
+            <section name="options" title="Options" expanded="False">
+                <param argument="threshold" type="float" value="0.0" optional="True" label="Threshold" help="Features with a training-set variance lower than this threshold will be removed." />
+            </section>
+        </when>
+    </xml>
 
-  <xml name="distance_metrics">
-    <param argument="metric" type="select" label="Distance metric" help=" ">
-      <option value="euclidean" selected="true">euclidean</option>
-      <option value="cityblock">cityblock</option>
-      <option value="cosine">cosine</option>
-      <option value="l1">l1</option>
-      <option value="l2">l2</option>
-      <option value="manhattan">manhattan</option>
-      <yield/>
-    </param>
-  </xml>
+    <xml name="feature_selection_SelectFromModel">
+        <when value="SelectFromModel">
+            <conditional name="model_inputter">
+                <param name="input_mode" type="select" label="Construct a new estimator from a selection list?">
+                    <option value="new" selected="true">Yes</option>
+                    <option value="prefitted">No. Load a prefitted estimator</option>
+                </param>
+                <when value="new">
+                    <expand macro="estimator_selector_fs" />
+                </when>
+                <when value="prefitted">
+                    <param name="fitted_estimator" type="data" format='zip' label="Load a prefitted estimator" />
+                </when>
+            </conditional>
+            <expand macro="feature_selection_SelectFromModel_options" />
+        </when>
+    </xml>
 
-  <xml name="distance_nonsparse_metrics">
-    <option value="braycurtis">braycurtis</option>
-    <option value="canberra">canberra</option>
-    <option value="chebyshev">chebyshev</option>
-    <option value="correlation">correlation</option>
-    <option value="dice">dice</option>
-    <option value="hamming">hamming</option>
-    <option value="jaccard">jaccard</option>
-    <option value="kulsinski">kulsinski</option>
-    <option value="mahalanobis">mahalanobis</option>
-    <option value="matching">matching</option>
-    <option value="minkowski">minkowski</option>
-    <option value="rogerstanimoto">rogerstanimoto</option>
-    <option value="russellrao">russellrao</option>
-    <option value="seuclidean">seuclidean</option>
-    <option value="sokalmichener">sokalmichener</option>
-    <option value="sokalsneath">sokalsneath</option>
-    <option value="sqeuclidean">sqeuclidean</option>
-    <option value="yule">yule</option>
-  </xml>
+    <xml name="feature_selection_SelectFromModel_no_prefitted">
+        <when value="SelectFromModel">
+            <conditional name="model_inputter">
+                <param name="input_mode" type="select" label="Construct a new estimator from a selection list?">
+                    <option value="new" selected="true">Yes</option>
+                </param>
+                <when value="new">
+                    <expand macro="estimator_selector_all" />
+                </when>
+            </conditional>
+            <expand macro="feature_selection_SelectFromModel_options" />
+        </when>
+    </xml>
 
-  <xml name="pairwise_kernel_metrics">
-    <param argument="metric" type="select" label="Pirwise Kernel metric" help=" ">
-      <option value="rbf" selected="true">rbf</option>
-      <option value="sigmoid">sigmoid</option>
-      <option value="polynomial">polynomial</option>
-      <option value="linear" selected="true">linear</option>
-      <option value="chi2">chi2</option>
-      <option value="additive_chi2">additive_chi2</option>
-    </param>
-  </xml>
+    <xml name="feature_selection_SelectFromModel_options">
+        <section name="options" title="Advanced Options" expanded="False">
+            <param argument="threshold" type="text" value="" optional="true" label="threshold" help="The threshold value to use for feature selection. e.g. 'mean', 'median', '1.25*mean'." />
+            <param argument="norm_order" type="integer" value="1" label="norm_order" help="Order of the norm used to filter the vectors of coefficients below threshold in the case where the coef_ attribute of the estimator is of dimension 2. " />
+            <param argument="max_features" type="integer" value="" optional="true" label="The maximum number of features selected scoring above threshold" help="To disable threshold and only select based on max_features, set threshold=-np.inf." />
+        </section>
+    </xml>
 
-  <xml name="sparse_pairwise_metric_functions">
-    <param name="selected_metric_function" type="select" label="Select the pairwise metric you want to compute:">
-      <option value="euclidean_distances" selected="true">Euclidean distance matrix</option>
-      <option value="pairwise_distances">Distance matrix</option>
-      <option value="pairwise_distances_argmin">Minimum distances between one point and a set of points</option>
-      <yield/>
-    </param>
-  </xml>
-
-  <xml name="pairwise_metric_functions">
-    <option value="additive_chi2_kernel" >Additive chi-squared kernel</option>
-    <option value="chi2_kernel">Exponential chi-squared kernel</option>
-    <option value="linear_kernel">Linear kernel</option>
-    <option value="manhattan_distances">L1 distances</option>
-    <option value="pairwise_kernels">Kernel</option>
-    <option value="polynomial_kernel">Polynomial kernel</option>
-    <option value="rbf_kernel">Gaussian (rbf) kernel</option>
-    <option value="laplacian_kernel">Laplacian kernel</option>
-  </xml>
+    <xml name="feature_selection_RFE">
+        <when value="RFE">
+            <yield />
+            <section name="options" title="Advanced Options" expanded="False">
+                <param argument="n_features_to_select" type="integer" value="" optional="true" label="n_features_to_select" help="The number of features to select. If None, half of the features are selected." />
+                <param argument="step" type="float" value="1" label="step" optional="true" help="Default = 1. " />
+                <param argument="verbose" type="integer" value="0" label="verbose" help="Controls verbosity of output." />
+            </section>
+        </when>
+    </xml>
 
-  <xml name="sparse_pairwise_condition">
-    <when value="pairwise_distances">
-      <section name="options" title="Advanced Options" expanded="False">
-          <expand macro="distance_metrics">
-              <yield/>
-          </expand>
-      </section>
-    </when>
-    <when value="euclidean_distances">
-      <section name="options" title="Advanced Options" expanded="False">
-          <param argument="squared" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="false"
-            label="Return squared Euclidean distances" help=" "/>
-      </section>
-    </when>
-  </xml>
+    <xml name="feature_selection_RFECV_fs">
+        <when value="RFECV">
+            <yield />
+            <section name="options" title="Advanced Options" expanded="False">
+                <param argument="step" type="float" value="1" label="step" optional="true" help="Default = 1. " />
+                <param argument="min_features_to_select" type="integer" value="1" optional="true" label="The minimum number of features to be selected" />
+                <expand macro="cv" />
+                <expand macro="scoring_selection" />
+                <param argument="verbose" type="integer" value="0" label="verbose" help="Controls verbosity of output." />
+            </section>
+        </when>
+    </xml>
 
-  <xml name="argmin_distance_condition">
-    <when value="pairwise_distances_argmin">
-      <section name="options" title="Advanced Options" expanded="False">
-          <param argument="axis" type="integer" optional="true" value="1" label="Axis" help="Axis along which the argmin and distances are to be computed."/>
-          <expand macro="distance_metrics">
-              <yield/>
-          </expand>
-          <param argument="batch_size" type="integer" optional="true" value="500" label="Batch size" help="Number of rows to be processed in each batch run."/>
-      </section>
-    </when>
-  </xml>
+    <xml name="feature_selection_RFECV_pipeline">
+        <when value="RFECV">
+            <yield />
+            <section name="options" title="Advanced Options" expanded="False">
+                <param argument="step" type="float" value="1" label="step" optional="true" help="Default = 1. " />
+                <param argument="min_features_to_select" type="integer" value="1" optional="true" label="The minimum number of features to be selected" />
+                <expand macro="cv_reduced" />
+                <!-- TODO: group splitter support-->
+                <expand macro="scoring_selection" />
+                <param argument="verbose" type="integer" value="0" label="verbose" help="Controls verbosity of output." />
+            </section>
+        </when>
+    </xml>
 
-  <xml name="sparse_preprocessors">
-    <param name="selected_pre_processor" type="select" label="Select a preprocessor:">
-      <option value="StandardScaler" selected="true">Standard Scaler (Standardizes features by removing the mean and scaling to unit variance)</option>
-      <option value="Binarizer">Binarizer (Binarizes data)</option>
-      <option value="MaxAbsScaler">Max Abs Scaler (Scales features by their maximum absolute value)</option>
-      <option value="Normalizer">Normalizer (Normalizes samples individually to unit norm)</option>
-      <yield/>
-    </param>
-  </xml>
-
-  <xml name="sparse_preprocessors_ext">
-    <expand macro="sparse_preprocessors">
-      <option value="KernelCenterer">Kernel Centerer (Centers a kernel matrix)</option>
-      <option value="MinMaxScaler">Minmax Scaler (Scales features to a range)</option>
-      <option value="PolynomialFeatures">Polynomial Features (Generates polynomial and interaction features)</option>
-      <option value="RobustScaler">Robust Scaler (Scales features using outlier-invariance statistics)</option>
-      <option value="QuantileTransformer">QuantileTransformer (Transform features using quantiles information)</option>
-      <option value="PowerTransformer">PowerTransformer (Apply a power transform featurewise to make data more Gaussian-like)</option>
-      <option value="KBinsDiscretizer">KBinsDiscretizer (Bin continuous data into intervals.)</option>
-    </expand>
-  </xml>
+    <xml name="feature_selection_DyRFECV_fs">
+        <when value="DyRFECV">
+            <yield />
+            <section name="options" title="Advanced Options" expanded="False">
+                <param argument="step" type="text" size="30" value="1" label="step" optional="true" help="Default = 1. Support float, int and list.">
+                    <sanitizer>
+                        <valid initial="default">
+                            <add value="[" />
+                            <add value="]" />
+                        </valid>
+                    </sanitizer>
+                </param>
+                <param argument="min_features_to_select" type="integer" value="1" optional="true" label="The minimum number of features to be selected" />
+                <expand macro="cv" />
+                <expand macro="scoring_selection" />
+                <param argument="verbose" type="integer" value="0" label="verbose" help="Controls verbosity of output." />
+            </section>
+        </when>
+    </xml>
 
-  <xml name="sparse_preprocessor_options">
-    <when value="Binarizer">
-        <section name="options" title="Advanced Options" expanded="False">
-            <param argument="copy" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="true"
-                label="Use a copy of data for precomputing binarization" help=" "/>
-            <param argument="threshold" type="float" optional="true" value="0.0"
-                label="Threshold"
-                help="Feature values below or equal to this are replaced by 0, above it by 1. Threshold may not be less than 0 for operations on sparse matrices. "/>
-        </section>
-    </when>
-    <when value="StandardScaler">
-      <section name="options" title="Advanced Options" expanded="False">
-        <param argument="copy" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="true"
-            label="Use a copy of data for performing inplace scaling" help=" "/>
-        <param argument="with_mean" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="true"
-            label="Center the data before scaling" help=" "/>
-        <param argument="with_std" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="true"
-            label="Scale the data to unit variance (or unit standard deviation)" help=" "/>
-      </section>
-    </when>
-    <when value="MaxAbsScaler">
-      <section name="options" title="Advanced Options" expanded="False">
-        <param argument="copy" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="true"
-            label="Use a copy of data for precomputing scaling" help=" "/>
-      </section>
-    </when>
-    <when value="Normalizer">
-      <section name="options" title="Advanced Options" expanded="False">
-        <param argument="norm" type="select" optional="true" label="The norm to use to normalize non zero samples" help=" ">
-          <option value="l1" selected="true">l1</option>
-          <option value="l2">l2</option>
-          <option value="max">max</option>
+    <xml name="feature_selection_pipeline">
+        <!--compare to `feature_selection_fs`, no fitted estimator for SelectFromModel and no custom estimator for RFE and RFECV-->
+        <conditional name="fs_algorithm_selector">
+            <param name="selected_algorithm" type="select" label="Select a feature selection algorithm">
+                <expand macro="feature_selection_algorithms" />
+            </param>
+            <expand macro="feature_selection_algorithm_details" />
+            <expand macro="feature_selection_SelectFromModel_no_prefitted" />
+            <expand macro="feature_selection_RFE">
+                <expand macro="estimator_selector_all" />
+            </expand>
+            <expand macro="feature_selection_RFECV_pipeline">
+                <expand macro="estimator_selector_all" />
+            </expand>
+            <!-- TODO: add DyRFECV to pipeline-->
+        </conditional>
+    </xml>
+
+    <xml name="feature_selection_fs">
+        <conditional name="fs_algorithm_selector">
+            <param name="selected_algorithm" type="select" label="Select a feature selection algorithm">
+                <expand macro="feature_selection_algorithms">
+                    <option value="DyRFECV">DyRFECV - Extended RFECV with changeable steps</option>
+                </expand>
+            </param>
+            <expand macro="feature_selection_algorithm_details" />
+            <expand macro="feature_selection_SelectFromModel" />
+            <expand macro="feature_selection_RFE">
+                <expand macro="estimator_selector_fs" />
+            </expand>
+            <expand macro="feature_selection_RFECV_fs">
+                <expand macro="estimator_selector_fs" />
+            </expand>
+            <expand macro="feature_selection_DyRFECV_fs">
+                <expand macro="estimator_selector_fs" />
+            </expand>
+        </conditional>
+    </xml>
+
+    <xml name="feature_selection_score_function">
+        <param argument="score_func" type="select" label="Select a score function">
+            <option value="chi2">chi2 - Compute chi-squared stats between each non-negative feature and class</option>
+            <option value="f_classif">f_classif - Compute the ANOVA F-value for the provided sample</option>
+            <option value="f_regression">f_regression - Univariate linear regression tests</option>
+            <option value="mutual_info_classif">mutual_info_classif - Estimate mutual information for a discrete target variable</option>
+            <option value="mutual_info_regression">mutual_info_regression - Estimate mutual information for a continuous target variable</option>
         </param>
-        <param argument="copy" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="true"
-            label="Use a copy of data for precomputing row normalization" help=" "/>
-      </section>
-    </when>
-    <yield/>
-  </xml>
+    </xml>
 
-  <xml name="sparse_preprocessor_options_ext">
-    <expand macro="sparse_preprocessor_options">
-      <when value="KernelCenterer">
-        <section name="options" title="Advanced Options" expanded="False">
-        </section>
-      </when>
-      <when value="MinMaxScaler">
-          <section name="options" title="Advanced Options" expanded="False">
-              <param argument="feature_range" type="text" value="(0, 1)" optional="true" help="Desired range of transformed data. None or tuple (min, max). None equals to (0, 1)"/>
-              <param argument="copy" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolflase" checked="true"
-                  label="Use a copy of data for precomputing normalization" help=" "/>
-          </section>
-      </when>
-      <when value="PolynomialFeatures">
-          <section name="options" title="Advanced Options" expanded="False">
-              <param argument="degree" type="integer" optional="true" value="2" label="The degree of the polynomial features " help=""/>
-              <param argument="interaction_only" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolflase" checked="false" label="Produce interaction features only" help="(Features that are products of at most degree distinct input features) "/>
-              <param argument="include_bias" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolflase" checked="true" label="Include a bias column" help="Feature in which all polynomial powers are zero "/>
-          </section>
-      </when>
-      <when value="RobustScaler">
-          <section name="options" title="Advanced Options" expanded="False">
-              <!--=True, =True, copy=True-->
-              <param argument="with_centering" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolflase" checked="true"
-                  label="Center the data before scaling" help=" "/>
-              <param argument="with_scaling" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolflase" checked="true"
-                  label="Scale the data to interquartile range" help=" "/>
-              <param argument="copy" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolflase" checked="true"
-                  label="Use a copy of data for inplace scaling" help=" "/>
-          </section>
-      </when>
-      <when value="QuantileTransformer">
-          <section name="options" title="Advanced Options" expanded="False">
-              <param name="n_quantiles" type="integer" value="1000" min="0" label="Number of quantiles to be computed" />
-              <param name="output_distribution" type="select" label="Marginal distribution for the transformed data">
-                  <option value="uniform" selected="true">uniform</option>
-                  <option value="normal">normal</option>
-              </param>
-              <param name="ignore_implicit_zeros" type="boolean" truevalue="booltrue" falsevalue="boolfalse" checked="false" label="Whether to discard sparse entries" help="Only applies to sparse matrices. If False, sparse entries are treated as zeros"/>
-              <param name="subsample" type="integer" value="100000" label="Maximum number of samples used to estimate the quantiles for computational efficiency" help="Note that the subsampling procedure may differ for value-identical sparse and dense matrices."/>
-              <expand macro="random_state" help_text="This is used by subsampling and smoothing noise"/>
-          </section>
-      </when>
-      <when value="PowerTransformer">
-          <section name="options" title="Advanced Options" expanded="False">
-              <param name="method" type="select" label="The power transform method">
-                  <option value="yeo-johnson" selected="true">yeo-johnson (works with positive and negative values)</option>
-                  <option value="box-cox">box-cox (might perform better, but only works with strictly positive values)</option>
-              </param>
-              <param name="standardize" type="boolean" truevalue="booltrue" falsevalue="boolfalse" checked="true" label="Whether to apply zero-mean, unit-variance normalization to the transformed output."/>
-          </section>
-      </when>
-      <when value="KBinsDiscretizer">
-          <section name="options" title="Advanced Options" expanded="False">
-              <param name="n_bins" type="integer" value="5" min="2" label="The number of bins to produce"/>
-              <param name="encode" type="select" label="Method used to encode the transformed result">
-                  <option value="onehot" selected="true">onehot (encode the transformed result with one-hot encoding and return a sparse matrix)</option>
-                  <option value="onehot-dense">onehot-dense (encode the transformed result with one-hot encoding and return a dense array)</option>
-                  <option value="ordinal">ordinal (return the bin identifier encoded as an integer value)</option>
-              </param>
-              <param name="strategy" type="select" label="Strategy used to define the widths of the bins">
-                  <option value="uniform">uniform (all bins in each feature have identical widths)</option>
-                  <option value="quantile" selected="true">quantile (all bins in each feature have the same number of points)</option>
-                  <option value="kmeans">kmeans (values in each bin have the same nearest center of a 1D k-means cluster)</option>
-              </param>
-          </section>
-      </when>
-    </expand>
-  </xml>
-
-  <xml name="cv_splitter">
-    <option value="default" selected="true">default splitter</option>
-    <option value="KFold">KFold</option>
-    <option value="StratifiedKFold">StratifiedKFold</option>
-    <option value="LeaveOneOut">LeaveOneOut</option>
-    <option value="LeavePOut">LeavePOut</option>
-    <option value="RepeatedKFold">RepeatedKFold</option>
-    <option value="RepeatedStratifiedKFold">RepeatedStratifiedKFold</option>
-    <option value="ShuffleSplit">ShuffleSplit</option>
-    <option value="StratifiedShuffleSplit">StratifiedShuffleSplit</option>
-    <option value="TimeSeriesSplit">TimeSeriesSplit</option>
-    <option value="PredefinedSplit">PredefinedSplit</option>
-    <option value="OrderedKFold">OrderedKFold</option>
-    <option value="RepeatedOrderedKFold">RepeatedOrderedKFold</option>
-    <yield/>
-  </xml>
-
-  <xml name="cv_splitter_options">
-    <when value="default">
-      <expand macro="cv_n_splits"/>
-    </when>
-    <when value="KFold">
-      <expand macro="cv_n_splits"/>
-      <expand macro="cv_shuffle"/>
-      <expand macro="random_state"/>
-    </when>
-    <when value="StratifiedKFold">
-      <expand macro="cv_n_splits"/>
-      <expand macro="cv_shuffle"/>
-      <expand macro="random_state"/>
-    </when>
-    <when value="LeaveOneOut">
-    </when>
-    <when value="LeavePOut">
-      <param argument="p" type="integer" value="" label="p" help="Integer. Size of the test sets."/>
-    </when>
-    <when value="RepeatedKFold">
-      <expand macro="cv_n_splits" value="5"/>
-      <param argument="n_repeats" type="integer" value="10" label="n_repeats" help="Number of times cross-validator needs to be repeated." />
-      <expand macro="random_state" />
-    </when>
-    <when value="RepeatedStratifiedKFold">
-      <expand macro="cv_n_splits" value="5"/>
-      <param argument="n_repeats" type="integer" value="10" label="n_repeats" help="Number of times cross-validator needs to be repeated." />
-      <expand macro="random_state" />
-    </when>
-    <when value="ShuffleSplit">
-      <expand macro="cv_n_splits" value="10" help="Number of re-shuffling and splitting iterations."/>
-      <expand macro="cv_test_size" value="0.1" />
-      <expand macro="random_state"/>
-    </when>
-    <when value="StratifiedShuffleSplit">
-      <expand macro="cv_n_splits" value="10" help="Number of re-shuffling and splitting iterations."/>
-      <expand macro="cv_test_size" value="0.1" />
-      <expand macro="random_state"/>
-    </when>
-    <when value="TimeSeriesSplit">
-      <expand macro="cv_n_splits"/>
-      <param argument="max_train_size" type="integer" value="" optional="true" label="Maximum size of the training set" help="Maximum size for a single training set." />
-    </when>
-    <when value="PredefinedSplit">
-      <param argument="test_fold" type="text" value="" area="true" label="test_fold" help="List, e.g., [0, 1, -1, 1], represents two test sets, [X[0]] and [X[1], X[3]], X[2] is excluded from any test set due to '-1'."/>
-    </when>
-    <when value="OrderedKFold">
-      <expand macro="cv_n_splits"/>
-      <expand macro="cv_shuffle"/>
-      <expand macro="random_state"/>
-    </when>
-    <when value="RepeatedOrderedKFold">
-      <expand macro="cv_n_splits"/>
-      <param argument="n_repeats" type="integer" value="5"/>
-      <expand macro="random_state"/>
-    </when>
-    <yield/>
-  </xml>
+    <xml name="model_validation_common_options">
+        <expand macro="cv" />
+        <expand macro="verbose" />
+        <yield />
+    </xml>
 
-  <xml name="cv">
-    <conditional name="cv_selector">
-      <param name="selected_cv" type="select" label="Select the cv splitter:">
-        <expand macro="cv_splitter">
-          <option value="GroupKFold">GroupKFold</option>
-          <option value="GroupShuffleSplit">GroupShuffleSplit</option>
-          <option value="LeaveOneGroupOut">LeaveOneGroupOut</option>
-          <option value="LeavePGroupsOut">LeavePGroupsOut</option>
-        </expand>
-      </param>
-      <expand macro="cv_splitter_options">
-        <when value="GroupKFold">
-          <expand macro="cv_n_splits"/>
-          <expand macro="cv_groups" />
-        </when>
-        <when value="GroupShuffleSplit">
-          <expand macro="cv_n_splits" value="5"/>
-          <expand macro="cv_test_size"/>
-          <expand macro="random_state"/>
-          <expand macro="cv_groups"/>
-        </when>
-        <when value="LeaveOneGroupOut">
-          <expand macro="cv_groups"/>
-        </when>
-        <when value="LeavePGroupsOut">
-          <param argument="n_groups" type="integer" value="" label="n_groups" help="Number of groups (p) to leave out in the test split." />
-          <expand macro="cv_groups"/>
-        </when>
-      </expand>
-    </conditional>
-  </xml>
-
-  <xml name="cv_reduced" token_label="Select the cv splitter">
-    <conditional name="cv_selector">
-      <param name="selected_cv" type="select" label="@LABEL@">
-        <expand macro="cv_splitter"/>
-      </param>
-      <expand macro="cv_splitter_options"/>
-    </conditional>
-  </xml>
-
-  <xml name="cv_n_splits" token_value="3" token_help="Number of folds. Must be at least 2.">
-    <param argument="n_splits" type="integer" value="@VALUE@" min="1" label="n_splits" help="@HELP@"/>
-  </xml>
-
-  <xml name="cv_shuffle">
-    <param argument="shuffle" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="false" label="Whether to shuffle data before splitting" />
-  </xml>
-
-  <xml name="cv_test_size" token_value="0.2">
-    <param argument="test_size" type="float" value="@VALUE@" min="0.0" label="Portion or number of the test set" help="0.0-1.0, proportion of the dataset to include in the test split; >1, integer only, the absolute number of test samples "/>
-  </xml>
-
-  <xml name="cv_groups" >
-    <section name="groups_selector" title="Groups column selector" expanded="true">
-      <param name="infile_g" type="data" format="tabular" label="Choose dataset containing groups info:"/>
-      <param name="header_g" type="boolean" optional="true" truevalue="booltrue" falsevalue="boolfalse" checked="False" label="Does the dataset contain header:" />
-      <conditional name="column_selector_options_g">
-        <expand macro="samples_column_selector_options" column_option="selected_column_selector_option_g" col_name="col_g" multiple="False" infile="infile_g"/>
-      </conditional>
-    </section>
-  </xml>
-
-  <xml name="train_test_split_params">
-    <conditional name="split_algos">
-      <param name="shuffle" type="select" label="Select the splitting method">
-        <option value="None">No shuffle</option>
-        <option value="simple" selected="true">ShuffleSplit</option>
-        <option value="stratified">StratifiedShuffleSplit -- target values serve as class labels</option>
-        <option value="group">GroupShuffleSplit or split by group names</option>
-      </param>
-      <when value="None">
-        <expand macro="train_test_split_test_size"/>
-      </when>
-      <when value="simple">
-        <expand macro="train_test_split_test_size"/>
-        <expand macro="random_state"/>
-      </when>
-      <when value="stratified">
-        <expand macro="train_test_split_test_size"/>
-        <expand macro="random_state"/>
-      </when>
-      <when value="group">
-        <expand macro="train_test_split_test_size" optional="true"/>
-        <expand macro="random_state"/>
-        <param argument="group_names" type="text" value="" optional="true" label="Type in group names instead"
-        help="For example: chr6, chr7. This parameter is optional. If used, it will override the holdout size and random seed."/>
-        <yield/>
-      </when>
-    </conditional>
-    <!--param argument="train_size" type="float" optional="True" value="" label="Train size:"/>-->
-  </xml>
-
-  <xml name="train_test_split_test_size" token_optional="false">
-    <param name="test_size" type="float" value="0.2" optional="@OPTIONAL@" label="Holdout size" help="Leass than 1, for preportion; greater than 1 (integer), for number of samples."/>
-  </xml>
-
-  <xml name="feature_selection_algorithms">
-    <option value="SelectKBest" selected="true">SelectKBest - Select features according to the k highest scores</option>
-    <option value="GenericUnivariateSelect">GenericUnivariateSelect - Univariate feature selector with configurable strategy</option>
-    <option value="SelectPercentile">SelectPercentile - Select features according to a percentile of the highest scores</option>
-    <option value="SelectFpr">SelectFpr - Filter: Select the p-values below alpha based on a FPR test</option>
-    <option value="SelectFdr">SelectFdr - Filter: Select the p-values for an estimated false discovery rate</option>
-    <option value="SelectFwe">SelectFwe - Filter: Select the p-values corresponding to Family-wise error rate</option>
-    <option value="VarianceThreshold">VarianceThreshold - Feature selector that removes all low-variance features</option>
-    <option value="SelectFromModel">SelectFromModel - Meta-transformer for selecting features based on importance weights</option>
-    <option value="RFE">RFE - Feature ranking with recursive feature elimination</option>
-    <option value="RFECV">RFECV - Feature ranking with recursive feature elimination and cross-validated selection of the best number of features</option>
-    <yield/>
-  </xml>
-
-  <xml name="feature_selection_algorithm_details">
-    <when value="GenericUnivariateSelect">
-      <expand macro="feature_selection_score_function" />
-      <section name="options" title="Advanced Options" expanded="False">
-        <param argument="mode" type="select" label="Feature selection mode">
-          <option value="percentile">percentile</option>
-          <option value="k_best">k_best</option>
-          <option value="fpr">fpr</option>
-          <option value="fdr">fdr</option>
-          <option value="fwe">fwe</option>
-        </param>
-        <param argument="param" type="float" value="" optional="true" label="Parameter of the corresponding mode" help="float or int depending on the feature selection mode" />
-      </section>
-    </when>
-    <when value="SelectPercentile">
-      <expand macro="feature_selection_score_function" />
-      <section name="options" title="Advanced Options" expanded="False">
-        <param argument="percentile" type="integer" value="10" optional="True" label="Percent of features to keep" />
-      </section>
-    </when>
-    <when value="SelectKBest">
-      <expand macro="feature_selection_score_function" />
-      <section name="options" title="Advanced Options" expanded="False">
-        <param argument="k" type="integer" value="10" optional="True" label="Number of top features to select" help="No 'all' option is supported." />
-      </section>
-    </when>
-    <when value="SelectFpr">
-      <expand macro="feature_selection_score_function" />
-      <section name="options" title="Advanced Options" expanded="False">
-        <param argument="alpha" type="float" value="" optional="True" label="Alpha" help="The highest p-value for features to be kept."/>
-      </section>
-    </when>
-    <when value="SelectFdr">
-      <expand macro="feature_selection_score_function" />
-      <section name="options" title="Advanced Options" expanded="False">
-        <param argument="alpha" type="float" value="" optional="True" label="Alpha" help="The highest uncorrected p-value for features to keep."/>
-      </section>
-    </when>
-    <when value="SelectFwe">
-      <expand macro="feature_selection_score_function" />
-      <section name="options" title="Advanced Options" expanded="False">
-        <param argument="alpha" type="float" value="" optional="True" label="Alpha" help="The highest uncorrected p-value for features to keep."/>
-      </section>
-    </when>
-    <when value="VarianceThreshold">
-      <section name="options" title="Options" expanded="False">
-        <param argument="threshold" type="float" value="0.0" optional="True" label="Threshold" help="Features with a training-set variance lower than this threshold will be removed."/>
-      </section>
-    </when>
-  </xml>
-
-  <xml name="feature_selection_SelectFromModel">
-    <when value="SelectFromModel">
-      <conditional name="model_inputter">
-        <param name="input_mode" type="select" label="Construct a new estimator from a selection list?" >
-          <option value="new" selected="true">Yes</option>
-          <option value="prefitted">No. Load a prefitted estimator</option>
-        </param>
-        <when value="new">
-          <expand macro="estimator_selector_fs"/>
-        </when>
-        <when value="prefitted">
-          <param name="fitted_estimator" type="data" format='zip' label="Load a prefitted estimator" />
-        </when>
-      </conditional>
-      <expand macro="feature_selection_SelectFromModel_options"/>
-    </when>
-  </xml>
-
-  <xml name="feature_selection_SelectFromModel_no_prefitted">
-    <when value="SelectFromModel">
-      <conditional name="model_inputter">
-        <param name="input_mode" type="select" label="Construct a new estimator from a selection list?" >
-          <option value="new" selected="true">Yes</option>
-        </param>
-        <when value="new">
-          <expand macro="estimator_selector_all"/>
-        </when>
-      </conditional>
-      <expand macro="feature_selection_SelectFromModel_options"/>
-    </when>
-  </xml>
-
-  <xml name="feature_selection_SelectFromModel_options">
-    <section name="options" title="Advanced Options" expanded="False">
-      <param argument="threshold" type="text" value="" optional="true" label="threshold" help="The threshold value to use for feature selection. e.g. 'mean', 'median', '1.25*mean'." />
-      <param argument="norm_order" type="integer" value="1" label="norm_order" help="Order of the norm used to filter the vectors of coefficients below threshold in the case where the coef_ attribute of the estimator is of dimension 2. " />
-      <param argument="max_features" type="integer" value="" optional="true" label="The maximum number of features selected scoring above threshold" help="To disable threshold and only select based on max_features, set threshold=-np.inf."/>
-    </section>
-  </xml>
-
-  <xml name="feature_selection_RFE">
-    <when value="RFE">
-      <yield/>
-      <section name="options" title="Advanced Options" expanded="False">
-        <param argument="n_features_to_select" type="integer" value="" optional="true" label="n_features_to_select" help="The number of features to select. If None, half of the features are selected." />
-        <param argument="step" type="float" value="1" label="step" optional="true" help="Default = 1. " />
-        <param argument="verbose" type="integer" value="0" label="verbose" help="Controls verbosity of output." />
-      </section>
-    </when>
-  </xml>
+    <xml name="scoring_selection">
+        <conditional name="scoring">
+            <param name="primary_scoring" type="select" multiple="false" label="Select the primary metric (scoring):" help="Metric to refit the best estimator.">
+                <option value="default" selected="true">default with estimator</option>
+                <option value="accuracy">Classification -- 'accuracy'</option>
+                <option value="balanced_accuracy">Classification -- 'balanced_accuracy'</option>
+                <option value="average_precision">Classification -- 'average_precision'</option>
+                <option value="f1">Classification -- 'f1'</option>
+                <option value="f1_micro">Classification -- 'f1_micro'</option>
+                <option value="f1_macro">Classification -- 'f1_macro'</option>
+                <option value="f1_weighted">Classification -- 'f1_weighted'</option>
+                <option value="f1_samples">Classification -- 'f1_samples'</option>
+                <option value="neg_log_loss">Classification -- 'neg_log_loss'</option>
+                <option value="precision">Classification -- 'precision'</option>
+                <option value="precision_micro">Classification -- 'precision_micro'</option>
+                <option value="precision_macro">Classification -- 'precision_macro'</option>
+                <option value="precision_wighted">Classification -- 'precision_wighted'</option>
+                <option value="precision_samples">Classification -- 'precision_samples'</option>
+                <option value="recall">Classification -- 'recall'</option>
+                <option value="recall_micro">Classification -- 'recall_micro'</option>
+                <option value="recall_macro">Classification -- 'recall_macro'</option>
+                <option value="recall_wighted">Classification -- 'recall_wighted'</option>
+                <option value="recall_samples">Classification -- 'recall_samples'</option>
+                <option value="roc_auc">Classification -- 'roc_auc'</option>
+                <option value="explained_variance">Regression -- 'explained_variance'</option>
+                <option value="neg_mean_absolute_error">Regression -- 'neg_mean_absolute_error'</option>
+                <option value="neg_mean_squared_error">Regression -- 'neg_mean_squared_error'</option>
+                <option value="neg_mean_squared_log_error">Regression -- 'neg_mean_squared_log_error'</option>
+                <option value="neg_median_absolute_error">Regression -- 'neg_median_absolute_error'</option>
+                <option value="r2">Regression -- 'r2'</option>
+                <option value="max_error">Regression -- 'max_error'</option>
+                <option value="binarize_auc_scorer">anomaly detection -- binarize_auc_scorer</option>
+                <option value="binarize_average_precision_scorer">anomaly detection -- binarize_average_precision_scorer</option>
+            </param>
+            <when value="default" />
+            <when value="accuracy">
+                <expand macro="secondary_scoring_selection_classification" />
+            </when>
+            <when value="balanced_accuracy">
+                <expand macro="secondary_scoring_selection_classification" />
+            </when>
+            <when value="average_precision">
+                <expand macro="secondary_scoring_selection_classification" />
+            </when>
+            <when value="f1">
+                <expand macro="secondary_scoring_selection_classification" />
+            </when>
+            <when value="f1_micro">
+                <expand macro="secondary_scoring_selection_classification" />
+            </when>
+            <when value="f1_macro">
+                <expand macro="secondary_scoring_selection_classification" />
+            </when>
+            <when value="f1_weighted">
+                <expand macro="secondary_scoring_selection_classification" />
+            </when>
+            <when value="f1_samples">
+                <expand macro="secondary_scoring_selection_classification" />
+            </when>
+            <when value="neg_log_loss">
+                <expand macro="secondary_scoring_selection_classification" />
+            </when>
+            <when value="precision">
+                <expand macro="secondary_scoring_selection_classification" />
+            </when>
+            <when value="precision_micro">
+                <expand macro="secondary_scoring_selection_classification" />
+            </when>
+            <when value="precision_macro">
+                <expand macro="secondary_scoring_selection_classification" />
+            </when>
+            <when value="precision_wighted">
+                <expand macro="secondary_scoring_selection_classification" />
+            </when>
+            <when value="precision_samples">
+                <expand macro="secondary_scoring_selection_classification" />
+            </when>
+            <when value="recall">
+                <expand macro="secondary_scoring_selection_classification" />
+            </when>
+            <when value="recall_micro">
+                <expand macro="secondary_scoring_selection_classification" />
+            </when>
+            <when value="recall_macro">
+                <expand macro="secondary_scoring_selection_classification" />
+            </when>
+            <when value="recall_wighted">
+                <expand macro="secondary_scoring_selection_classification" />
+            </when>
+            <when value="recall_samples">
+                <expand macro="secondary_scoring_selection_classification" />
+            </when>
+            <when value="roc_auc">
+                <expand macro="secondary_scoring_selection_classification" />
+            </when>
+            <when value="explained_variance">
+                <expand macro="secondary_scoring_selection_regression" />
+            </when>
+            <when value="neg_mean_absolute_error">
+                <expand macro="secondary_scoring_selection_regression" />
+            </when>
+            <when value="neg_mean_squared_error">
+                <expand macro="secondary_scoring_selection_regression" />
+            </when>
+            <when value="neg_mean_squared_log_error">
+                <expand macro="secondary_scoring_selection_regression" />
+            </when>
+            <when value="neg_median_absolute_error">
+                <expand macro="secondary_scoring_selection_regression" />
+            </when>
+            <when value="r2">
+                <expand macro="secondary_scoring_selection_regression" />
+            </when>
+            <when value="max_error">
+                <expand macro="secondary_scoring_selection_regression" />
+            </when>
+            <when value="binarize_auc_scorer">
+                <expand macro="secondary_scoring_selection_anormaly" />
+            </when>
+            <when value="binarize_average_precision_scorer">
+                <expand macro="secondary_scoring_selection_anormaly" />
+            </when>
+        </conditional>
+    </xml>
 
-  <xml name="feature_selection_RFECV_fs">
-    <when value="RFECV">
-      <yield/>
-      <section name="options" title="Advanced Options" expanded="False">
-        <param argument="step" type="float" value="1" label="step" optional="true" help="Default = 1. " />
-        <param argument="min_features_to_select" type="integer" value="1" optional="true" label="The minimum number of features to be selected"/>
-        <expand macro="cv"/>
-        <expand macro="scoring_selection"/>
-        <param argument="verbose" type="integer" value="0" label="verbose" help="Controls verbosity of output." />
-      </section>
-    </when>
-  </xml>
-
-  <xml name="feature_selection_RFECV_pipeline">
-    <when value="RFECV">
-      <yield/>
-      <section name="options" title="Advanced Options" expanded="False">
-        <param argument="step" type="float" value="1" label="step" optional="true" help="Default = 1. " />
-        <param argument="min_features_to_select" type="integer" value="1" optional="true" label="The minimum number of features to be selected"/>
-        <expand macro="cv_reduced"/>
-        <!-- TODO: group splitter support-->
-        <expand macro="scoring_selection"/>
-        <param argument="verbose" type="integer" value="0" label="verbose" help="Controls verbosity of output." />
-      </section>
-    </when>
-  </xml>
+    <xml name="secondary_scoring_selection_classification">
+        <param name="secondary_scoring" type="select" multiple="true" label="Additional scoring used in multi-metric mode:" help="If the same metric with the primary is chosen, the metric will be ignored.">
+            <option value="accuracy">Classification -- 'accuracy'</option>
+            <option value="balanced_accuracy">Classification -- 'balanced_accuracy'</option>
+            <option value="average_precision">Classification -- 'average_precision'</option>
+            <option value="f1">Classification -- 'f1'</option>
+            <option value="f1_micro">Classification -- 'f1_micro'</option>
+            <option value="f1_macro">Classification -- 'f1_macro'</option>
+            <option value="f1_weighted">Classification -- 'f1_weighted'</option>
+            <option value="f1_samples">Classification -- 'f1_samples'</option>
+            <option value="neg_log_loss">Classification -- 'neg_log_loss'</option>
+            <option value="precision">Classification -- 'precision'</option>
+            <option value="precision_micro">Classification -- 'precision_micro'</option>
+            <option value="precision_macro">Classification -- 'precision_macro'</option>
+            <option value="precision_wighted">Classification -- 'precision_wighted'</option>
+            <option value="precision_samples">Classification -- 'precision_samples'</option>
+            <option value="recall">Classification -- 'recall'</option>
+            <option value="recall_micro">Classification -- 'recall_micro'</option>
+            <option value="recall_macro">Classification -- 'recall_macro'</option>
+            <option value="recall_wighted">Classification -- 'recall_wighted'</option>
+            <option value="recall_samples">Classification -- 'recall_samples'</option>
+            <option value="roc_auc">Classification -- 'roc_auc'</option>
+        </param>
+    </xml>
 
-  <xml name="feature_selection_DyRFECV_fs">
-    <when value="DyRFECV">
-      <yield/>
-      <section name="options" title="Advanced Options" expanded="False">
-        <param argument="step" type="text" size="30" value="1" label="step" optional="true" help="Default = 1. Support float, int and list." >
-          <sanitizer>
-            <valid initial="default">
-              <add value="["/>
-              <add value="]"/>
-            </valid>
-          </sanitizer>
+    <xml name="secondary_scoring_selection_regression">
+        <param name="secondary_scoring" type="select" multiple="true" label="Additional scoring used in multi-metric mode:" help="If the same metric with the primary is chosen, the metric will be ignored.">
+            <option value="explained_variance">Regression -- 'explained_variance'</option>
+            <option value="neg_mean_absolute_error">Regression -- 'neg_mean_absolute_error'</option>
+            <option value="neg_mean_squared_error">Regression -- 'neg_mean_squared_error'</option>
+            <option value="neg_mean_squared_log_error">Regression -- 'neg_mean_squared_log_error'</option>
+            <option value="neg_median_absolute_error">Regression -- 'neg_median_absolute_error'</option>
+            <option value="r2">Regression -- 'r2'</option>
+            <option value="max_error">Regression -- 'max_error'</option>
         </param>
-        <param argument="min_features_to_select" type="integer" value="1" optional="true" label="The minimum number of features to be selected"/>
-        <expand macro="cv"/>
-        <expand macro="scoring_selection"/>
-        <param argument="verbose" type="integer" value="0" label="verbose" help="Controls verbosity of output." />
-      </section>
-    </when>
-  </xml>
+    </xml>
 
-  <xml name="feature_selection_pipeline">
-    <!--compare to `feature_selection_fs`, no fitted estimator for SelectFromModel and no custom estimator for RFE and RFECV-->
-    <conditional name="fs_algorithm_selector">
-      <param name="selected_algorithm" type="select" label="Select a feature selection algorithm">
-        <expand macro="feature_selection_algorithms"/>
-      </param>
-      <expand macro="feature_selection_algorithm_details"/>
-      <expand macro="feature_selection_SelectFromModel_no_prefitted"/>
-      <expand macro="feature_selection_RFE">
-        <expand macro="estimator_selector_all"/>
-      </expand>  
-      <expand macro="feature_selection_RFECV_pipeline">
-        <expand macro="estimator_selector_all"/>
-      </expand>
-      <!-- TODO: add DyRFECV to pipeline-->
-    </conditional>
-  </xml>
+    <xml name="secondary_scoring_selection_anormaly">
+        <param name="secondary_scoring" type="select" multiple="true" label="Additional scoring used in multi-metric mode:" help="If the same metric with the primary is chosen, the metric will be ignored.">
+            <option value="binarize_auc_scorer">anomaly detection -- binarize_auc_scorer</option>
+            <option value="binarize_average_precision_scorer">anomaly detection -- binarize_average_precision_scorer</option>
+        </param>
+    </xml>
 
-  <xml name="feature_selection_fs">
-    <conditional name="fs_algorithm_selector">
-      <param name="selected_algorithm" type="select" label="Select a feature selection algorithm">
-        <expand macro="feature_selection_algorithms">
-          <option value="DyRFECV">DyRFECV - Extended RFECV with changeable steps</option>
-        </expand>
-      </param>
-      <expand macro="feature_selection_algorithm_details"/>
-      <expand macro="feature_selection_SelectFromModel"/>
-      <expand macro="feature_selection_RFE">
-        <expand macro="estimator_selector_fs"/>
-      </expand>  
-      <expand macro="feature_selection_RFECV_fs">
-        <expand macro="estimator_selector_fs"/>
-      </expand>
-      <expand macro="feature_selection_DyRFECV_fs">
-        <expand macro="estimator_selector_fs"/>
-      </expand>
-    </conditional>
-  </xml>
-
-  <xml name="feature_selection_score_function">
-    <param argument="score_func" type="select" label="Select a score function">
-      <option value="chi2">chi2 - Compute chi-squared stats between each non-negative feature and class</option>
-      <option value="f_classif">f_classif - Compute the ANOVA F-value for the provided sample</option>
-      <option value="f_regression">f_regression - Univariate linear regression tests</option>
-      <option value="mutual_info_classif">mutual_info_classif - Estimate mutual information for a discrete target variable</option>
-      <option value="mutual_info_regression">mutual_info_regression - Estimate mutual information for a continuous target variable</option>
-    </param>
-  </xml>
-
-  <xml name="model_validation_common_options">
-    <expand macro="cv"/>
-    <expand macro="verbose"/>
-    <yield/>
-  </xml>
+    <xml name="pre_dispatch" token_type="hidden" token_default_value="all" token_help="Number of predispatched jobs for parallel execution">
+        <param argument="pre_dispatch" type="@TYPE@" value="@DEFAULT_VALUE@" optional="true" label="pre_dispatch" help="@HELP@" />
+    </xml>
 
-  <xml name="scoring_selection">
-    <conditional name="scoring">
-      <param name="primary_scoring" type="select" multiple="false" label="Select the primary metric (scoring):" help="Metric to refit the best estimator.">
-        <option value="default" selected="true">default with estimator</option>
-        <option value="accuracy">Classification -- 'accuracy'</option>
-        <option value="balanced_accuracy">Classification -- 'balanced_accuracy'</option>
-        <option value="average_precision">Classification -- 'average_precision'</option>
-        <option value="f1">Classification -- 'f1'</option>
-        <option value="f1_micro">Classification -- 'f1_micro'</option>
-        <option value="f1_macro">Classification -- 'f1_macro'</option>
-        <option value="f1_weighted">Classification -- 'f1_weighted'</option>
-        <option value="f1_samples">Classification -- 'f1_samples'</option>
-        <option value="neg_log_loss">Classification -- 'neg_log_loss'</option>
-        <option value="precision">Classification -- 'precision'</option>
-        <option value="precision_micro">Classification -- 'precision_micro'</option>
-        <option value="precision_macro">Classification -- 'precision_macro'</option>
-        <option value="precision_wighted">Classification -- 'precision_wighted'</option>
-        <option value="precision_samples">Classification -- 'precision_samples'</option>
-        <option value="recall">Classification -- 'recall'</option>
-        <option value="recall_micro">Classification -- 'recall_micro'</option>
-        <option value="recall_macro">Classification -- 'recall_macro'</option>
-        <option value="recall_wighted">Classification -- 'recall_wighted'</option>
-        <option value="recall_samples">Classification -- 'recall_samples'</option>
-        <option value="roc_auc">Classification -- 'roc_auc'</option>
-        <option value="explained_variance">Regression -- 'explained_variance'</option>
-        <option value="neg_mean_absolute_error">Regression -- 'neg_mean_absolute_error'</option>
-        <option value="neg_mean_squared_error">Regression -- 'neg_mean_squared_error'</option>
-        <option value="neg_mean_squared_log_error">Regression -- 'neg_mean_squared_log_error'</option>
-        <option value="neg_median_absolute_error">Regression -- 'neg_median_absolute_error'</option>
-        <option value="r2">Regression -- 'r2'</option>
-        <option value="max_error">Regression -- 'max_error'</option>
-        <option value="binarize_auc_scorer">anomaly detection -- binarize_auc_scorer</option>
-        <option value="binarize_average_precision_scorer">anomaly detection -- binarize_average_precision_scorer</option>
-      </param>
-      <when value="default"/>
-      <when value="accuracy"><expand macro="secondary_scoring_selection_classification"/></when>
-      <when value="balanced_accuracy"><expand macro="secondary_scoring_selection_classification"/></when>
-      <when value="average_precision"><expand macro="secondary_scoring_selection_classification"/></when>
-      <when value="f1"><expand macro="secondary_scoring_selection_classification"/></when>
-      <when value="f1_micro"><expand macro="secondary_scoring_selection_classification"/></when>
-      <when value="f1_macro"><expand macro="secondary_scoring_selection_classification"/></when>
-      <when value="f1_weighted"><expand macro="secondary_scoring_selection_classification"/></when>
-      <when value="f1_samples"><expand macro="secondary_scoring_selection_classification"/></when>
-      <when value="neg_log_loss"><expand macro="secondary_scoring_selection_classification"/></when>
-      <when value="precision"><expand macro="secondary_scoring_selection_classification"/></when>
-      <when value="precision_micro"><expand macro="secondary_scoring_selection_classification"/></when>
-      <when value="precision_macro"><expand macro="secondary_scoring_selection_classification"/></when>
-      <when value="precision_wighted"><expand macro="secondary_scoring_selection_classification"/></when>
-      <when value="precision_samples"><expand macro="secondary_scoring_selection_classification"/></when>
-      <when value="recall"><expand macro="secondary_scoring_selection_classification"/></when>
-      <when value="recall_micro"><expand macro="secondary_scoring_selection_classification"/></when>
-      <when value="recall_macro"><expand macro="secondary_scoring_selection_classification"/></when>
-      <when value="recall_wighted"><expand macro="secondary_scoring_selection_classification"/></when>
-      <when value="recall_samples"><expand macro="secondary_scoring_selection_classification"/></when>
-      <when value="roc_auc"><expand macro="secondary_scoring_selection_classification"/></when>
-      <when value="explained_variance"><expand macro="secondary_scoring_selection_regression"/></when>
-      <when value="neg_mean_absolute_error"><expand macro="secondary_scoring_selection_regression"/></when>
-      <when value="neg_mean_squared_error"><expand macro="secondary_scoring_selection_regression"/></when>
-      <when value="neg_mean_squared_log_error"><expand macro="secondary_scoring_selection_regression"/></when>
-      <when value="neg_median_absolute_error"><expand macro="secondary_scoring_selection_regression"/></when>
-      <when value="r2"><expand macro="secondary_scoring_selection_regression"/></when>
-      <when value="max_error"><expand macro="secondary_scoring_selection_regression"/></when>
-      <when value="binarize_auc_scorer"><expand macro="secondary_scoring_selection_anormaly"/></when>
-      <when value="binarize_average_precision_scorer"><expand macro="secondary_scoring_selection_anormaly"/></when>
-    </conditional>
-  </xml>
+    <xml name="estimator_and_hyperparameter">
+        <param name="infile_estimator" type="data" format="zip" label="Choose the dataset containing pipeline/estimator object" />
+        <section name="hyperparams_swapping" title="Hyperparameter Swapping" expanded="false">
+            <param name="infile_params" type="data" format="tabular" optional="true" label="Choose the dataset containing hyperparameters for the pipeline/estimator above" help="This dataset could be the output of `get_params` in the `Estimator Attributes` tool." />
+            <repeat name="param_set" min="1" max="30" title="New hyperparameter setting">
+                <param name="sp_name" type="select" optional="true" label="Choose a parameter name (with current value)">
+                    <options from_dataset="infile_params" startswith="@">
+                        <column name="name" index="2" />
+                        <column name="value" index="1" />
+                        <filter type="unique_value" name="unique_param" column="1" />
+                    </options>
+                </param>
+                <param name="sp_value" type="text" value="" optional="true" label="New value" help="Supports int, float, boolean, single quoted string, and selected object constructor. Similar to the `Parameter settings for search` section in `searchcv` tool except that only single value is expected here.">
+                    <sanitizer>
+                        <valid initial="default">
+                            <add value="&apos;" />
+                            <add value="&quot;" />
+                        </valid>
+                    </sanitizer>
+                </param>
+            </repeat>
+        </section>
+    </xml>
+
+    <xml name="search_cv_options">
+        <expand macro="scoring_selection" />
+        <expand macro="model_validation_common_options" />
+        <!--expand macro="pre_dispatch" default_value="2*n_jobs" help="Controls the number of jobs that get dispatched during parallel execution"/-->
+        <param argument="iid" type="boolean" truevalue="booltrue" falsevalue="boolfalse" checked="true" label="iid" help="If True, data is identically distributed across the folds" />
+        <!--param argument="refit" type="boolean" truevalue="booltrue" falsevalue="boolfalse" checked="true" label="refit" help="Refit an estimator using the best found parameters on the whole dataset. Be aware that `refit=True` invokes extra computation, but it's REQUIRED for outputting the best estimator!"/> -->
+        <param argument="error_score" type="boolean" truevalue="booltrue" falsevalue="boolfalse" checked="true" label="Raise fit error:" help="If false, the metric score is assigned to NaN if an error occurs in estimator fitting and FitFailedWarning is raised." />
+        <param argument="return_train_score" type="boolean" truevalue="booltrue" falsevalue="boolfalse" checked="false" label="return_train_score" help="" />
+    </xml>
+
+    <xml name="estimator_module_options">
+        <option value="svm" selected="true">sklearn.svm</option>
+        <option value="linear_model">sklearn.linear_model</option>
+        <option value="ensemble">sklearn.ensemble</option>
+        <option value="naive_bayes">sklearn.naive_bayes</option>
+        <option value="tree">sklearn.tree</option>
+        <option value="neighbors">sklearn.neighbors</option>
+        <option value="xgboost">xgboost</option>
+        <yield />
+    </xml>
 
-  <xml name="secondary_scoring_selection_classification">
-    <param name="secondary_scoring" type="select" multiple="true" label="Additional scoring used in multi-metric mode:" help="If the same metric with the primary is chosen, the metric will be ignored.">
-      <option value="accuracy">Classification -- 'accuracy'</option>
-      <option value="balanced_accuracy">Classification -- 'balanced_accuracy'</option>
-      <option value="average_precision">Classification -- 'average_precision'</option>
-      <option value="f1">Classification -- 'f1'</option>
-      <option value="f1_micro">Classification -- 'f1_micro'</option>
-      <option value="f1_macro">Classification -- 'f1_macro'</option>
-      <option value="f1_weighted">Classification -- 'f1_weighted'</option>
-      <option value="f1_samples">Classification -- 'f1_samples'</option>
-      <option value="neg_log_loss">Classification -- 'neg_log_loss'</option>
-      <option value="precision">Classification -- 'precision'</option>
-      <option value="precision_micro">Classification -- 'precision_micro'</option>
-      <option value="precision_macro">Classification -- 'precision_macro'</option>
-      <option value="precision_wighted">Classification -- 'precision_wighted'</option>
-      <option value="precision_samples">Classification -- 'precision_samples'</option>
-      <option value="recall">Classification -- 'recall'</option>
-      <option value="recall_micro">Classification -- 'recall_micro'</option>
-      <option value="recall_macro">Classification -- 'recall_macro'</option>
-      <option value="recall_wighted">Classification -- 'recall_wighted'</option>
-      <option value="recall_samples">Classification -- 'recall_samples'</option>
-      <option value="roc_auc">Classification -- 'roc_auc'</option>
-    </param>
-  </xml>
-
-  <xml name="secondary_scoring_selection_regression">
-    <param name="secondary_scoring" type="select" multiple="true" label="Additional scoring used in multi-metric mode:" help="If the same metric with the primary is chosen, the metric will be ignored.">
-      <option value="explained_variance">Regression -- 'explained_variance'</option>
-      <option value="neg_mean_absolute_error">Regression -- 'neg_mean_absolute_error'</option>
-      <option value="neg_mean_squared_error">Regression -- 'neg_mean_squared_error'</option>
-      <option value="neg_mean_squared_log_error">Regression -- 'neg_mean_squared_log_error'</option>
-      <option value="neg_median_absolute_error">Regression -- 'neg_median_absolute_error'</option>
-      <option value="r2">Regression -- 'r2'</option>
-      <option value="max_error">Regression -- 'max_error'</option>
-    </param>
-  </xml>
-
-  <xml name="secondary_scoring_selection_anormaly">
-    <param name="secondary_scoring" type="select" multiple="true" label="Additional scoring used in multi-metric mode:" help="If the same metric with the primary is chosen, the metric will be ignored.">
-      <option value="binarize_auc_scorer">anomaly detection -- binarize_auc_scorer</option>
-      <option value="binarize_average_precision_scorer">anomaly detection -- binarize_average_precision_scorer</option>
-    </param>
-  </xml>
-
-  <xml name="pre_dispatch" token_type="hidden" token_default_value="all" token_help="Number of predispatched jobs for parallel execution">
-    <param argument="pre_dispatch" type="@TYPE@" value="@DEFAULT_VALUE@" optional="true" label="pre_dispatch" help="@HELP@"/>
-  </xml>
-
-  <xml name="estimator_and_hyperparameter">
-    <param name="infile_estimator" type="data" format="zip" label="Choose the dataset containing pipeline/estimator object"/>
-    <section name="hyperparams_swapping" title="Hyperparameter Swapping" expanded="false">
-      <param name="infile_params" type="data" format="tabular" optional="true" label="Choose the dataset containing hyperparameters for the pipeline/estimator above" help="This dataset could be the output of `get_params` in the `Estimator Attributes` tool."/>
-      <repeat name="param_set" min="1" max="30" title="New hyperparameter setting">
-          <param name="sp_name" type="select" optional="true" label="Choose a parameter name (with current value)">
-            <options from_dataset="infile_params" startswith="@">
-              <column name="name" index="2"/>
-              <column name="value" index="1"/>
-              <filter type="unique_value" name="unique_param" column="1"/>
-            </options>
-          </param>
-          <param name="sp_value" type="text" value="" optional="true" label="New value" help="Supports int, float, boolean, single quoted string, and selected object constructor. Similar to the `Parameter settings for search` section in `searchcv` tool except that only single value is expected here.">
-            <sanitizer>
-              <valid initial="default">
-                <add value="&apos;"/>
-                <add value="&quot;"/>
-              </valid>
-            </sanitizer>
-          </param>
-      </repeat>
-    </section>
-  </xml>
-
-  <xml name="search_cv_options">
-      <expand macro="scoring_selection"/>
-      <expand macro="model_validation_common_options"/>
-      <!--expand macro="pre_dispatch" default_value="2*n_jobs" help="Controls the number of jobs that get dispatched during parallel execution"/-->
-      <param argument="iid" type="boolean" truevalue="booltrue" falsevalue="boolfalse" checked="true" label="iid" help="If True, data is identically distributed across the folds"/>
-      <!--param argument="refit" type="boolean" truevalue="booltrue" falsevalue="boolfalse" checked="true" label="refit" help="Refit an estimator using the best found parameters on the whole dataset. Be aware that `refit=True` invokes extra computation, but it's REQUIRED for outputting the best estimator!"/> -->
-      <param argument="error_score" type="boolean" truevalue="booltrue" falsevalue="boolfalse" checked="true" label="Raise fit error:" help="If false, the metric score is assigned to NaN if an error occurs in estimator fitting and FitFailedWarning is raised."/>
-      <param argument="return_train_score" type="boolean" truevalue="booltrue" falsevalue="boolfalse" checked="false" label="return_train_score" help=""/>
-  </xml>
-
-  <xml name="estimator_module_options">
-      <option value="svm" selected="true">sklearn.svm</option>
-      <option value="linear_model">sklearn.linear_model</option>
-      <option value="ensemble">sklearn.ensemble</option>
-      <option value="naive_bayes">sklearn.naive_bayes</option>
-      <option value="tree">sklearn.tree</option>
-      <option value="neighbors">sklearn.neighbors</option>
-      <option value="xgboost">xgboost</option>
-      <yield/>
-  </xml>
+    <xml name="estimator_suboptions">
+        <when value="svm">
+            <param name="selected_estimator" type="select" label="Choose estimator class:">
+                <option value="LinearSVC" selected="true">LinearSVC</option>
+                <option value="LinearSVR">LinearSVR</option>
+                <option value="NuSVC">NuSVC</option>
+                <option value="NuSVR">NuSVR</option>
+                <option value="OneClassSVM">OneClassSVM</option>
+                <option value="SVC">SVC</option>
+                <option value="SVR">SVR</option>
+            </param>
+            <expand macro="estimator_params_text" />
+        </when>
+        <when value="linear_model">
+            <param name="selected_estimator" type="select" label="Choose estimator class:">
+                <option value="ARDRegression" selected="true">ARDRegression</option>
+                <option value="BayesianRidge">BayesianRidge</option>
+                <option value="ElasticNet">ElasticNet</option>
+                <option value="ElasticNetCV">ElasticNetCV</option>
+                <option value="HuberRegressor">HuberRegressor</option>
+                <option value="Lars">Lars</option>
+                <option value="LarsCV">LarsCV</option>
+                <option value="Lasso">Lasso</option>
+                <option value="LassoCV">LassoCV</option>
+                <option value="LassoLars">LassoLars</option>
+                <option value="LassoLarsCV">LassoLarsCV</option>
+                <option value="LassoLarsIC">LassoLarsIC</option>
+                <option value="LinearRegression">LinearRegression</option>
+                <option value="LogisticRegression">LogisticRegression</option>
+                <option value="LogisticRegressionCV">LogisticRegressionCV</option>
+                <option value="MultiTaskLasso">MultiTaskLasso</option>
+                <option value="MultiTaskElasticNet">MultiTaskElasticNet</option>
+                <option value="MultiTaskLassoCV">MultiTaskLassoCV</option>
+                <option value="MultiTaskElasticNetCV">MultiTaskElasticNetCV</option>
+                <option value="OrthogonalMatchingPursuit">OrthogonalMatchingPursuit</option>
+                <option value="OrthogonalMatchingPursuitCV">OrthogonalMatchingPursuitCV</option>
+                <option value="PassiveAggressiveClassifier">PassiveAggressiveClassifier</option>
+                <option value="PassiveAggressiveRegressor">PassiveAggressiveRegressor</option>
+                <option value="Perceptron">Perceptron</option>
+                <option value="RANSACRegressor">RANSACRegressor</option>
+                <option value="Ridge">Ridge</option>
+                <option value="RidgeClassifier">RidgeClassifier</option>
+                <option value="RidgeClassifierCV">RidgeClassifierCV</option>
+                <option value="RidgeCV">RidgeCV</option>
+                <option value="SGDClassifier">SGDClassifier</option>
+                <option value="SGDRegressor">SGDRegressor</option>
+                <option value="TheilSenRegressor">TheilSenRegressor</option>
+            </param>
+            <expand macro="estimator_params_text" />
+        </when>
+        <when value="ensemble">
+            <param name="selected_estimator" type="select" label="Choose estimator class:">
+                <option value="AdaBoostClassifier" selected="true">AdaBoostClassifier</option>
+                <option value="AdaBoostRegressor">AdaBoostRegressor</option>
+                <option value="BaggingClassifier">BaggingClassifier</option>
+                <option value="BaggingRegressor">BaggingRegressor</option>
+                <option value="ExtraTreesClassifier">ExtraTreesClassifier</option>
+                <option value="ExtraTreesRegressor">ExtraTreesRegressor</option>
+                <option value="GradientBoostingClassifier">GradientBoostingClassifier</option>
+                <option value="GradientBoostingRegressor">GradientBoostingRegressor</option>
+                <option value="IsolationForest">IsolationForest</option>
+                <option value="HistGradientBoostingClassifier">HistGradientBoostingClassifier</option>
+                <option value="HistGradientBoostingRegressor">HistGradientBoostingRegressor</option>
+                <option value="RandomForestClassifier">RandomForestClassifier</option>
+                <option value="RandomForestRegressor">RandomForestRegressor</option>
+                <option value="RandomTreesEmbedding">RandomTreesEmbedding</option>
+                <!--option value="VotingClassifier">VotingClassifier</option-->
+            </param>
+            <expand macro="estimator_params_text" />
+        </when>
+        <when value="naive_bayes">
+            <param name="selected_estimator" type="select" label="Choose estimator class:">
+                <option value="BernoulliNB" selected="true">BernoulliNB</option>
+                <option value="GaussianNB">GaussianNB</option>
+                <option value="MultinomialNB">MultinomialNB</option>
+            </param>
+            <expand macro="estimator_params_text" />
+        </when>
+        <when value="tree">
+            <param name="selected_estimator" type="select" label="Choose estimator class:">
+                <option value="DecisionTreeClassifier" selected="true">DecisionTreeClassifier</option>
+                <option value="DecisionTreeRegressor">DecisionTreeRegressor</option>
+                <option value="ExtraTreeClassifier">ExtraTreeClassifier</option>
+                <option value="ExtraTreeRegressor">ExtraTreeRegressor</option>
+            </param>
+            <expand macro="estimator_params_text" />
+        </when>
+        <when value="neighbors">
+            <param name="selected_estimator" type="select" label="Choose estimator class:">
+                <option value="KNeighborsClassifier" selected="true">KNeighborsClassifier</option>
+                <option value="KNeighborsRegressor">KNeighborsRegressor</option>
+                <!--option value="BallTree">BallTree</option-->
+                <!--option value="KDTree">KDTree</option-->
+                <option value="KernelDensity">KernelDensity</option>
+                <option value="LocalOutlierFactor">LocalOutlierFactor</option>
+                <option value="RadiusNeighborsClassifier">RadiusNeighborsClassifier</option>
+                <option value="RadiusNeighborsRegressor">RadiusNeighborsRegressor</option>
+                <option value="NearestCentroid">NearestCentroid</option>
+                <option value="NearestNeighbors">NearestNeighbors</option>
+            </param>
+            <expand macro="estimator_params_text" />
+        </when>
+        <when value="xgboost">
+            <param name="selected_estimator" type="select" label="Choose estimator class:">
+                <option value="XGBRegressor" selected="true">XGBRegressor</option>
+                <option value="XGBClassifier">XGBClassifier</option>
+            </param>
+            <expand macro="estimator_params_text" />
+        </when>
+        <yield />
+    </xml>
 
-  <xml name="estimator_suboptions">
-      <when value="svm">
-        <param name="selected_estimator" type="select" label="Choose estimator class:">
-          <option value="LinearSVC" selected="true">LinearSVC</option>
-          <option value="LinearSVR">LinearSVR</option>
-          <option value="NuSVC">NuSVC</option>
-          <option value="NuSVR">NuSVR</option>
-          <option value="OneClassSVM">OneClassSVM</option>
-          <option value="SVC">SVC</option>
-          <option value="SVR">SVR</option>
-        </param>
-        <expand macro="estimator_params_text"/>
-      </when>
-      <when value="linear_model">
-        <param name="selected_estimator" type="select" label="Choose estimator class:">
-          <option value="ARDRegression" selected="true">ARDRegression</option>
-          <option value="BayesianRidge">BayesianRidge</option>
-          <option value="ElasticNet">ElasticNet</option>
-          <option value="ElasticNetCV">ElasticNetCV</option>
-          <option value="HuberRegressor">HuberRegressor</option>
-          <option value="Lars">Lars</option>
-          <option value="LarsCV">LarsCV</option>
-          <option value="Lasso">Lasso</option>
-          <option value="LassoCV">LassoCV</option>
-          <option value="LassoLars">LassoLars</option>
-          <option value="LassoLarsCV">LassoLarsCV</option>
-          <option value="LassoLarsIC">LassoLarsIC</option>
-          <option value="LinearRegression">LinearRegression</option>
-          <option value="LogisticRegression">LogisticRegression</option>
-          <option value="LogisticRegressionCV">LogisticRegressionCV</option>
-          <option value="MultiTaskLasso">MultiTaskLasso</option>
-          <option value="MultiTaskElasticNet">MultiTaskElasticNet</option>
-          <option value="MultiTaskLassoCV">MultiTaskLassoCV</option>
-          <option value="MultiTaskElasticNetCV">MultiTaskElasticNetCV</option>
-          <option value="OrthogonalMatchingPursuit">OrthogonalMatchingPursuit</option>
-          <option value="OrthogonalMatchingPursuitCV">OrthogonalMatchingPursuitCV</option>
-          <option value="PassiveAggressiveClassifier">PassiveAggressiveClassifier</option>
-          <option value="PassiveAggressiveRegressor">PassiveAggressiveRegressor</option>
-          <option value="Perceptron">Perceptron</option>
-          <option value="RANSACRegressor">RANSACRegressor</option>
-          <option value="Ridge">Ridge</option>
-          <option value="RidgeClassifier">RidgeClassifier</option>
-          <option value="RidgeClassifierCV">RidgeClassifierCV</option>
-          <option value="RidgeCV">RidgeCV</option>
-          <option value="SGDClassifier">SGDClassifier</option>
-          <option value="SGDRegressor">SGDRegressor</option>
-          <option value="TheilSenRegressor">TheilSenRegressor</option>
-        </param>
-        <expand macro="estimator_params_text"/>
-      </when>
-      <when value="ensemble">
-        <param name="selected_estimator" type="select" label="Choose estimator class:">
-          <option value="AdaBoostClassifier" selected="true">AdaBoostClassifier</option>
-          <option value="AdaBoostRegressor">AdaBoostRegressor</option>
-          <option value="BaggingClassifier">BaggingClassifier</option>
-          <option value="BaggingRegressor">BaggingRegressor</option>
-          <option value="ExtraTreesClassifier">ExtraTreesClassifier</option>
-          <option value="ExtraTreesRegressor">ExtraTreesRegressor</option>
-          <option value="GradientBoostingClassifier">GradientBoostingClassifier</option>
-          <option value="GradientBoostingRegressor">GradientBoostingRegressor</option>
-          <option value="IsolationForest">IsolationForest</option>
-          <option value="HistGradientBoostingClassifier">HistGradientBoostingClassifier</option>
-          <option value="HistGradientBoostingRegressor">HistGradientBoostingRegressor</option>
-          <option value="RandomForestClassifier">RandomForestClassifier</option>
-          <option value="RandomForestRegressor">RandomForestRegressor</option>
-          <option value="RandomTreesEmbedding">RandomTreesEmbedding</option>
-          <!--option value="VotingClassifier">VotingClassifier</option-->
-        </param>
-        <expand macro="estimator_params_text"/>
-      </when>
-      <when value="naive_bayes">
-        <param name="selected_estimator" type="select" label="Choose estimator class:">
-          <option value="BernoulliNB" selected="true">BernoulliNB</option>
-          <option value="GaussianNB">GaussianNB</option>
-          <option value="MultinomialNB">MultinomialNB</option>
-        </param>
-        <expand macro="estimator_params_text"/>
-      </when>
-      <when value="tree">
-        <param name="selected_estimator" type="select" label="Choose estimator class:">
-          <option value="DecisionTreeClassifier" selected="true">DecisionTreeClassifier</option>
-          <option value="DecisionTreeRegressor">DecisionTreeRegressor</option>
-          <option value="ExtraTreeClassifier">ExtraTreeClassifier</option>
-          <option value="ExtraTreeRegressor">ExtraTreeRegressor</option>
-        </param>
-        <expand macro="estimator_params_text"/>
-      </when>
-      <when value="neighbors">
-        <param name="selected_estimator" type="select" label="Choose estimator class:">
-          <option value="KNeighborsClassifier" selected="true">KNeighborsClassifier</option>
-          <option value="KNeighborsRegressor">KNeighborsRegressor</option>
-          <!--option value="BallTree">BallTree</option-->
-          <!--option value="KDTree">KDTree</option-->
-          <option value="KernelDensity">KernelDensity</option>
-          <option value="LocalOutlierFactor">LocalOutlierFactor</option>
-          <option value="RadiusNeighborsClassifier">RadiusNeighborsClassifier</option>
-          <option value="RadiusNeighborsRegressor">RadiusNeighborsRegressor</option>
-          <option value="NearestCentroid">NearestCentroid</option>
-          <option value="NearestNeighbors">NearestNeighbors</option>
-        </param>
-        <expand macro="estimator_params_text"/>
-      </when>
-      <when value="xgboost">
-        <param name="selected_estimator" type="select" label="Choose estimator class:">
-          <option value="XGBRegressor" selected="true">XGBRegressor</option>
-          <option value="XGBClassifier">XGBClassifier</option>
+    <xml name="estimator_selector_all">
+        <conditional name="estimator_selector">
+            <param name="selected_module" type="select" label="Choose the module that contains target estimator:">
+                <expand macro="estimator_module_options" />
+            </param>
+            <expand macro="estimator_suboptions" />
+        </conditional>
+    </xml>
+
+    <xml name="estimator_selector_fs">
+        <conditional name="estimator_selector">
+            <param name="selected_module" type="select" label="Choose the module that contains target estimator:">
+                <expand macro="estimator_module_options">
+                    <option value="custom_estimator">Load a custom estimator</option>
+                </expand>
+            </param>
+            <expand macro="estimator_suboptions">
+                <when value="custom_estimator">
+                    <param name="c_estimator" type="data" format="zip" label="Choose the dataset containing the custom estimator or pipeline:" />
+                </when>
+            </expand>
+        </conditional>
+    </xml>
+
+    <xml name="estimator_params_text" token_label="Type in parameter settings if different from default:" token_default_value='' token_help="Dictionary-capable, e.g., C=1, kernel='linear'. No double quotes. Leave this box blank for default estimator.">
+        <param name="text_params" type="text" value="@DEFAULT_VALUE@" optional="true" label="@LABEL@" help="@HELP@">
+            <sanitizer>
+                <valid initial="default">
+                    <add value="&apos;" />
+                </valid>
+            </sanitizer>
         </param>
-        <expand macro="estimator_params_text"/>
-      </when>
-      <yield/>
-  </xml>
-
-  <xml name="estimator_selector_all">
-    <conditional name="estimator_selector">
-      <param name="selected_module" type="select" label="Choose the module that contains target estimator:" >
-        <expand macro="estimator_module_options"/>
-      </param>
-      <expand macro="estimator_suboptions"/>
-    </conditional>
-  </xml>
-
-  <xml name="estimator_selector_fs">
-    <conditional name="estimator_selector">
-      <param name="selected_module" type="select" label="Choose the module that contains target estimator:" >
-        <expand macro="estimator_module_options">
-            <option value="custom_estimator">Load a custom estimator</option>
-        </expand>
-      </param>
-      <expand macro="estimator_suboptions">
-        <when value="custom_estimator">
-            <param name="c_estimator" type="data" format="zip" label="Choose the dataset containing the custom estimator or pipeline:"/>
-        </when>
-      </expand>
-    </conditional>
-  </xml>
+    </xml>
 
-  <xml name="estimator_params_text" token_label="Type in parameter settings if different from default:" token_default_value=''
-        token_help="Dictionary-capable, e.g., C=1, kernel='linear'. No double quotes. Leave this box blank for default estimator.">
-    <param name="text_params" type="text" value="@DEFAULT_VALUE@" optional="true" label="@LABEL@" help="@HELP@">
-      <sanitizer>
-        <valid initial="default">
-          <add value="&apos;"/>
-        </valid>
-      </sanitizer>
-    </param>
-  </xml>
-
-  <xml name="kernel_approximation_all">
-    <conditional name="kernel_approximation_selector">
-      <param name="select_algorithm" type="select" label="Choose a kernel approximation algorithm:">
-        <option value="Nystroem" selected="true">Nystroem</option>
-        <option value="RBFSampler">RBFSampler</option>
-        <option value="AdditiveChi2Sampler">AdditiveChi2Sampler</option>
-        <option value="SkewedChi2Sampler">SkewedChi2Sampler</option>
-      </param>
-      <when value="Nystroem">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): coef0=None, degree=None, gamma=None, kernel='rbf', kernel_params=None, n_components=100, random_state=None. No double quotes"/>
-      </when>
-      <when value="RBFSampler">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): gamma=1.0, n_components=100, random_state=None."/>
-      </when>
-      <when value="AdditiveChi2Sampler">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): sample_interval=None, sample_steps=2."/>
-      </when>
-      <when value="SkewedChi2Sampler">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): n_components=100, random_state=None, skewedness=1.0."/>
-      </when>
-    </conditional>
-  </xml>
+    <xml name="kernel_approximation_all">
+        <conditional name="kernel_approximation_selector">
+            <param name="select_algorithm" type="select" label="Choose a kernel approximation algorithm:">
+                <option value="Nystroem" selected="true">Nystroem</option>
+                <option value="RBFSampler">RBFSampler</option>
+                <option value="AdditiveChi2Sampler">AdditiveChi2Sampler</option>
+                <option value="SkewedChi2Sampler">SkewedChi2Sampler</option>
+            </param>
+            <when value="Nystroem">
+                <expand macro="estimator_params_text" help="Default(=blank): coef0=None, degree=None, gamma=None, kernel='rbf', kernel_params=None, n_components=100, random_state=None. No double quotes" />
+            </when>
+            <when value="RBFSampler">
+                <expand macro="estimator_params_text" help="Default(=blank): gamma=1.0, n_components=100, random_state=None." />
+            </when>
+            <when value="AdditiveChi2Sampler">
+                <expand macro="estimator_params_text" help="Default(=blank): sample_interval=None, sample_steps=2." />
+            </when>
+            <when value="SkewedChi2Sampler">
+                <expand macro="estimator_params_text" help="Default(=blank): n_components=100, random_state=None, skewedness=1.0." />
+            </when>
+        </conditional>
+    </xml>
 
-  <xml name="matrix_decomposition_all">
-    <conditional name="matrix_decomposition_selector">
-      <param name="select_algorithm" type="select" label="Choose a matrix decomposition algorithm:">
-        <option value="DictionaryLearning" selected="true">DictionaryLearning</option>
-        <option value="FactorAnalysis">FactorAnalysis</option>
-        <option value="FastICA">FastICA</option>
-        <option value="IncrementalPCA">IncrementalPCA</option>
-        <option value="KernelPCA">KernelPCA</option>
-        <option value="LatentDirichletAllocation">LatentDirichletAllocation</option>
-        <option value="MiniBatchDictionaryLearning">MiniBatchDictionaryLearning</option>
-        <option value="MiniBatchSparsePCA">MiniBatchSparsePCA</option>
-        <option value="NMF">NMF</option>
-        <option value="PCA">PCA</option>
-        <option value="SparsePCA">SparsePCA</option>
-        <!--option value="SparseCoder">SparseCoder</option-->
-        <option value="TruncatedSVD">TruncatedSVD</option>
-      </param>
-      <when value="DictionaryLearning">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): alpha=1, code_init=None, dict_init=None, fit_algorithm='lars', max_iter=1000, n_components=None, random_state=None, split_sign=False, tol=1e-08, transform_algorithm='omp', transform_alpha=None, transform_n_nonzero_coefs=None, verbose=False."/>
-      </when>
-      <when value="FactorAnalysis">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): copy=True, iterated_power=3, max_iter=1000, n_components=None, noise_variance_init=None, random_state=0, svd_method='randomized', tol=0.01."/>
-      </when>
-      <when value="FastICA">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): algorithm='parallel', fun='logcosh', fun_args=None, max_iter=200, n_components=None, random_state=None, tol=0.0001, w_init=None, whiten=True. No double quotes."/>
-      </when>
-      <when value="IncrementalPCA">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): batch_size=None, copy=True, n_components=None, whiten=False."/>
-      </when>
-      <when value="KernelPCA">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): alpha=1.0, coef0=1, copy_X=True, degree=3, eigen_solver='auto', fit_inverse_transform=False, gamma=None, kernel='linear', kernel_params=None, max_iter=None, n_components=None, random_state=None, remove_zero_eig=False, tol=0. No double quotes."/>
-      </when>
-      <when value="LatentDirichletAllocation">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): batch_size=128, doc_topic_prior=None, evaluate_every=-1, learning_decay=0.7, learning_method=None, learning_offset=10.0, max_doc_update_iter=100, max_iter=10, mean_change_tol=0.001, n_components=10, n_topics=None, perp_tol=0.1, random_state=None, topic_word_prior=None, total_samples=1000000.0, verbose=0."/>
-      </when>
-      <when value="MiniBatchDictionaryLearning">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): alpha=1, batch_size=3, dict_init=None, fit_algorithm='lars', n_components=None, n_iter=1000, random_state=None, shuffle=True, split_sign=False, transform_algorithm='omp', transform_alpha=None, transform_n_nonzero_coefs=None, verbose=False."/>
-      </when>
-      <when value="MiniBatchSparsePCA">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): alpha=1, batch_size=3, callback=None, method='lars', n_components=None, n_iter=100, random_state=None, ridge_alpha=0.01, shuffle=True, verbose=False."/>
-      </when>
-      <when value="NMF">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): alpha=0.0, beta_loss='frobenius', init=None, l1_ratio=0.0, max_iter=200, n_components=None, random_state=None, shuffle=False, solver='cd', tol=0.0001, verbose=0."/>
-      </when>
-      <when value="PCA">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): copy=True, iterated_power='auto', n_components=None, random_state=None, svd_solver='auto', tol=0.0, whiten=False."/>
-      </when>
-      <when value="SparsePCA">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): U_init=None, V_init=None, alpha=1, max_iter=1000, method='lars', n_components=None, random_state=None, ridge_alpha=0.01, tol=1e-08, verbose=False."/>
-      </when>
-      <when value="TruncatedSVD">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): algorithm='randomized', n_components=2, n_iter=5, random_state=None, tol=0.0."/>
-      </when>
-    </conditional>
-  </xml>
+    <xml name="matrix_decomposition_all">
+        <conditional name="matrix_decomposition_selector">
+            <param name="select_algorithm" type="select" label="Choose a matrix decomposition algorithm:">
+                <option value="DictionaryLearning" selected="true">DictionaryLearning</option>
+                <option value="FactorAnalysis">FactorAnalysis</option>
+                <option value="FastICA">FastICA</option>
+                <option value="IncrementalPCA">IncrementalPCA</option>
+                <option value="KernelPCA">KernelPCA</option>
+                <option value="LatentDirichletAllocation">LatentDirichletAllocation</option>
+                <option value="MiniBatchDictionaryLearning">MiniBatchDictionaryLearning</option>
+                <option value="MiniBatchSparsePCA">MiniBatchSparsePCA</option>
+                <option value="NMF">NMF</option>
+                <option value="PCA">PCA</option>
+                <option value="SparsePCA">SparsePCA</option>
+                <!--option value="SparseCoder">SparseCoder</option-->
+                <option value="TruncatedSVD">TruncatedSVD</option>
+            </param>
+            <when value="DictionaryLearning">
+                <expand macro="estimator_params_text" help="Default(=blank): alpha=1, code_init=None, dict_init=None, fit_algorithm='lars', max_iter=1000, n_components=None, random_state=None, split_sign=False, tol=1e-08, transform_algorithm='omp', transform_alpha=None, transform_n_nonzero_coefs=None, verbose=False." />
+            </when>
+            <when value="FactorAnalysis">
+                <expand macro="estimator_params_text" help="Default(=blank): copy=True, iterated_power=3, max_iter=1000, n_components=None, noise_variance_init=None, random_state=0, svd_method='randomized', tol=0.01." />
+            </when>
+            <when value="FastICA">
+                <expand macro="estimator_params_text" help="Default(=blank): algorithm='parallel', fun='logcosh', fun_args=None, max_iter=200, n_components=None, random_state=None, tol=0.0001, w_init=None, whiten=True. No double quotes." />
+            </when>
+            <when value="IncrementalPCA">
+                <expand macro="estimator_params_text" help="Default(=blank): batch_size=None, copy=True, n_components=None, whiten=False." />
+            </when>
+            <when value="KernelPCA">
+                <expand macro="estimator_params_text" help="Default(=blank): alpha=1.0, coef0=1, copy_X=True, degree=3, eigen_solver='auto', fit_inverse_transform=False, gamma=None, kernel='linear', kernel_params=None, max_iter=None, n_components=None, random_state=None, remove_zero_eig=False, tol=0. No double quotes." />
+            </when>
+            <when value="LatentDirichletAllocation">
+                <expand macro="estimator_params_text" help="Default(=blank): batch_size=128, doc_topic_prior=None, evaluate_every=-1, learning_decay=0.7, learning_method=None, learning_offset=10.0, max_doc_update_iter=100, max_iter=10, mean_change_tol=0.001, n_components=10, n_topics=None, perp_tol=0.1, random_state=None, topic_word_prior=None, total_samples=1000000.0, verbose=0." />
+            </when>
+            <when value="MiniBatchDictionaryLearning">
+                <expand macro="estimator_params_text" help="Default(=blank): alpha=1, batch_size=3, dict_init=None, fit_algorithm='lars', n_components=None, n_iter=1000, random_state=None, shuffle=True, split_sign=False, transform_algorithm='omp', transform_alpha=None, transform_n_nonzero_coefs=None, verbose=False." />
+            </when>
+            <when value="MiniBatchSparsePCA">
+                <expand macro="estimator_params_text" help="Default(=blank): alpha=1, batch_size=3, callback=None, method='lars', n_components=None, n_iter=100, random_state=None, ridge_alpha=0.01, shuffle=True, verbose=False." />
+            </when>
+            <when value="NMF">
+                <expand macro="estimator_params_text" help="Default(=blank): alpha=0.0, beta_loss='frobenius', init=None, l1_ratio=0.0, max_iter=200, n_components=None, random_state=None, shuffle=False, solver='cd', tol=0.0001, verbose=0." />
+            </when>
+            <when value="PCA">
+                <expand macro="estimator_params_text" help="Default(=blank): copy=True, iterated_power='auto', n_components=None, random_state=None, svd_solver='auto', tol=0.0, whiten=False." />
+            </when>
+            <when value="SparsePCA">
+                <expand macro="estimator_params_text" help="Default(=blank): U_init=None, V_init=None, alpha=1, max_iter=1000, method='lars', n_components=None, random_state=None, ridge_alpha=0.01, tol=1e-08, verbose=False." />
+            </when>
+            <when value="TruncatedSVD">
+                <expand macro="estimator_params_text" help="Default(=blank): algorithm='randomized', n_components=2, n_iter=5, random_state=None, tol=0.0." />
+            </when>
+        </conditional>
+    </xml>
 
-  <xml name="FeatureAgglomeration">
-    <conditional name="FeatureAgglomeration_selector">
-      <param name="select_algorithm" type="select" label="Choose the algorithm:">
-        <option value="FeatureAgglomeration" selected="true">FeatureAgglomeration</option>
-      </param>
-      <when value="FeatureAgglomeration">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): affinity='euclidean', compute_full_tree='auto', connectivity=None, linkage='ward', memory=None, n_clusters=2, pooling_func=np.mean."/>
-      </when>
-    </conditional>
-  </xml>
+    <xml name="FeatureAgglomeration">
+        <conditional name="FeatureAgglomeration_selector">
+            <param name="select_algorithm" type="select" label="Choose the algorithm:">
+                <option value="FeatureAgglomeration" selected="true">FeatureAgglomeration</option>
+            </param>
+            <when value="FeatureAgglomeration">
+                <expand macro="estimator_params_text" help="Default(=blank): affinity='euclidean', compute_full_tree='auto', connectivity=None, linkage='ward', memory=None, n_clusters=2, pooling_func=np.mean." />
+            </when>
+        </conditional>
+    </xml>
 
-  <xml name="skrebate">
-    <conditional name="skrebate_selector">
-      <param name="select_algorithm" type="select" label="Choose the algorithm:">
-        <option value="ReliefF">ReliefF</option>
-        <option value="SURF">SURF</option>
-        <option value="SURFstar">SURFstar</option>
-        <option value="MultiSURF">MultiSURF</option>
-        <option value="MultiSURFstar">MultiSURFstar</option>
-        <!--option value="TuRF">TuRF</option> -->
-      </param>
-      <when value="ReliefF">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): discrete_threshold=10, n_features_to_select=10, n_neighbors=100, verbose=False."/>
-      </when>
-      <when value="SURF">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): discrete_threshold=10, n_features_to_select=10, verbose=False."/>
-      </when>
-      <when value="SURFstar">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): discrete_threshold=10, n_features_to_select=10, verbose=False."/>
-      </when>
-      <when value="MultiSURF">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): discrete_threshold=10, n_features_to_select=10, verbose=False."/>
-      </when>
-      <when value="MultiSURFstar">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): discrete_threshold=10, n_features_to_select=10, verbose=False."/>
-      </when>
-      <!--when value="TuRF">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): core_algorithm='ReliefF', discrete_threshold=10, n_features_to_select=10, n_neighbors=100, pct=0.5, verbose=False."/>
+    <xml name="skrebate">
+        <conditional name="skrebate_selector">
+            <param name="select_algorithm" type="select" label="Choose the algorithm:">
+                <option value="ReliefF">ReliefF</option>
+                <option value="SURF">SURF</option>
+                <option value="SURFstar">SURFstar</option>
+                <option value="MultiSURF">MultiSURF</option>
+                <option value="MultiSURFstar">MultiSURFstar</option>
+                <!--option value="TuRF">TuRF</option> -->
+            </param>
+            <when value="ReliefF">
+                <expand macro="estimator_params_text" help="Default(=blank): discrete_threshold=10, n_features_to_select=10, n_neighbors=100, verbose=False." />
+            </when>
+            <when value="SURF">
+                <expand macro="estimator_params_text" help="Default(=blank): discrete_threshold=10, n_features_to_select=10, verbose=False." />
+            </when>
+            <when value="SURFstar">
+                <expand macro="estimator_params_text" help="Default(=blank): discrete_threshold=10, n_features_to_select=10, verbose=False." />
+            </when>
+            <when value="MultiSURF">
+                <expand macro="estimator_params_text" help="Default(=blank): discrete_threshold=10, n_features_to_select=10, verbose=False." />
+            </when>
+            <when value="MultiSURFstar">
+                <expand macro="estimator_params_text" help="Default(=blank): discrete_threshold=10, n_features_to_select=10, verbose=False." />
+            </when>
+            <!--when value="TuRF">
+        <expand macro="estimator_params_text" help="Default(=blank): core_algorithm='ReliefF', discrete_threshold=10, n_features_to_select=10, n_neighbors=100, pct=0.5, verbose=False."/>
       </when> -->
-    </conditional>
-  </xml>
+        </conditional>
+    </xml>
 
-  <xml name="imbalanced_learn_sampling">
-    <conditional name="imblearn_selector">
-      <param name="select_algorithm" type="select" label="Choose the algorithm:">
-        <option value="under_sampling.ClusterCentroids" selected="true">under_sampling.ClusterCentroids</option>
-        <option value="under_sampling.CondensedNearestNeighbour">under_sampling.CondensedNearestNeighbour</option>
-        <option value="under_sampling.EditedNearestNeighbours">under_sampling.EditedNearestNeighbours</option>
-        <option value="under_sampling.RepeatedEditedNearestNeighbours">under_sampling.RepeatedEditedNearestNeighbours</option>
-        <option value="under_sampling.AllKNN">under_sampling.AllKNN</option>
-        <option value="under_sampling.InstanceHardnessThreshold">under_sampling.InstanceHardnessThreshold</option>
-        <option value="under_sampling.NearMiss">under_sampling.NearMiss</option>
-        <option value="under_sampling.NeighbourhoodCleaningRule">under_sampling.NeighbourhoodCleaningRule</option>
-        <option value="under_sampling.OneSidedSelection">under_sampling.OneSidedSelection</option>
-        <option value="under_sampling.RandomUnderSampler">under_sampling.RandomUnderSampler</option>
-        <option value="under_sampling.TomekLinks">under_sampling.TomekLinks</option>
-        <option value="over_sampling.ADASYN">over_sampling.ADASYN</option>
-        <option value="over_sampling.RandomOverSampler">over_sampling.RandomOverSampler</option>
-        <option value="over_sampling.SMOTE">over_sampling.SMOTE</option>
-        <option value="over_sampling.SVMSMOTE">over_sampling.SVMSMOTE</option>
-        <option value="over_sampling.BorderlineSMOTE">over_sampling.BorderlineSMOTE</option>
-        <option value="over_sampling.SMOTENC">over_sampling.SMOTENC</option>
-        <option value="combine.SMOTEENN">combine.SMOTEENN</option>
-        <option value="combine.SMOTETomek">combine.SMOTETomek</option>
-        <option value="Z_RandomOverSampler">Z_RandomOverSampler - for regression</option>
-      </param>
-      <when value="under_sampling.ClusterCentroids">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): sampling_strategy='auto', random_state=None, estimator=None, voting='auto'."/>
-      </when>
-      <when value="under_sampling.CondensedNearestNeighbour">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): sampling_strategy='auto', random_state=None, n_neighbors=None, n_seeds_S=1."/>
-      </when>
-      <when value="under_sampling.EditedNearestNeighbours">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): sampling_strategy='auto', random_state=None, n_neighbors=3, max_iter=100, kind_sel='all'."/>
-      </when>
-      <when value="under_sampling.RepeatedEditedNearestNeighbours">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): sampling_strategy='auto', random_state=None, n_neighbors=3, max_iter=100, kind_sel='all'."/>
-      </when>
-      <when value="under_sampling.AllKNN">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): sampling_strategy='auto', random_state=None, n_neighbors=3, kind_sel='all', allow_minority=False."/>
-      </when>
-      <when value="under_sampling.InstanceHardnessThreshold">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): estimator=None, sampling_strategy='auto', random_state=None, cv=5."/>
-      </when>
-      <when value="under_sampling.NearMiss">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): sampling_strategy='auto', random_state=None, version=1, n_neighbors=3, n_neighbors_ver3=3."/>
-      </when>
-      <when value="under_sampling.NeighbourhoodCleaningRule">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): sampling_strategy='auto', random_state=None, n_neighbors=3, kind_sel='all', threshold_cleaning=0.5."/>
-      </when>
-      <when value="under_sampling.OneSidedSelection">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): sampling_strategy='auto', random_state=None, n_neighbors=None, n_seeds_S=1."/>
-      </when>
-      <when value="under_sampling.RandomUnderSampler">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): sampling_strategy='auto', random_state=None, replacement=False."/>
-      </when>
-      <when value="under_sampling.TomekLinks">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): sampling_strategy='auto', random_state=None."/>
-      </when>
-      <when value="over_sampling.ADASYN">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): sampling_strategy='auto', random_state=None, n_neighbors=5."/>
-      </when>
-      <when value="over_sampling.RandomOverSampler">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): sampling_strategy='auto', random_state=None."/>
-      </when>
-      <when value="over_sampling.SMOTE">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): sampling_strategy='auto', random_state=None, k_neighbors=5."/>
-      </when>
-      <when value="over_sampling.SVMSMOTE">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): sampling_strategy='auto', k_neighbors=5, m_neighbors=10, out_step=0.5, random_state=None, svm_estimator=None."/>
-      </when>
-      <when value="over_sampling.BorderlineSMOTE">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): sampling_strategy='auto', k_neighbors=5, kind='borderline-1', m_neighbors=10, random_state=None."/>
-      </when>
-      <when value="over_sampling.SMOTENC">
-        <expand macro="estimator_params_text"
-              help="Default: categorical_features=[], sampling_strategy='auto', random_state=None, k_neighbors=5."/>
-      </when>
-      <when value="combine.SMOTEENN">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): sampling_strategy='auto', random_state=None, smote=None, enn=None."/>
-      </when>
-      <when value="combine.SMOTETomek">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): sampling_strategy='auto', random_state=None, smote=None, tomek=None."/>
-      </when>
-      <when value="Z_RandomOverSampler">
-        <expand macro="estimator_params_text"
-              help="Default(=blank): sampling_strategy='auto', random_state=None, negative_thres=0, positive_thres=-1."/>
-      </when>
-    </conditional>
-  </xml>
+    <xml name="imbalanced_learn_sampling">
+        <conditional name="imblearn_selector">
+            <param name="select_algorithm" type="select" label="Choose the algorithm:">
+                <option value="under_sampling.ClusterCentroids" selected="true">under_sampling.ClusterCentroids</option>
+                <option value="under_sampling.CondensedNearestNeighbour">under_sampling.CondensedNearestNeighbour</option>
+                <option value="under_sampling.EditedNearestNeighbours">under_sampling.EditedNearestNeighbours</option>
+                <option value="under_sampling.RepeatedEditedNearestNeighbours">under_sampling.RepeatedEditedNearestNeighbours</option>
+                <option value="under_sampling.AllKNN">under_sampling.AllKNN</option>
+                <option value="under_sampling.InstanceHardnessThreshold">under_sampling.InstanceHardnessThreshold</option>
+                <option value="under_sampling.NearMiss">under_sampling.NearMiss</option>
+                <option value="under_sampling.NeighbourhoodCleaningRule">under_sampling.NeighbourhoodCleaningRule</option>
+                <option value="under_sampling.OneSidedSelection">under_sampling.OneSidedSelection</option>
+                <option value="under_sampling.RandomUnderSampler">under_sampling.RandomUnderSampler</option>
+                <option value="under_sampling.TomekLinks">under_sampling.TomekLinks</option>
+                <option value="over_sampling.ADASYN">over_sampling.ADASYN</option>
+                <option value="over_sampling.RandomOverSampler">over_sampling.RandomOverSampler</option>
+                <option value="over_sampling.SMOTE">over_sampling.SMOTE</option>
+                <option value="over_sampling.SVMSMOTE">over_sampling.SVMSMOTE</option>
+                <option value="over_sampling.BorderlineSMOTE">over_sampling.BorderlineSMOTE</option>
+                <option value="over_sampling.SMOTENC">over_sampling.SMOTENC</option>
+                <option value="combine.SMOTEENN">combine.SMOTEENN</option>
+                <option value="combine.SMOTETomek">combine.SMOTETomek</option>
+                <option value="Z_RandomOverSampler">Z_RandomOverSampler - for regression</option>
+            </param>
+            <when value="under_sampling.ClusterCentroids">
+                <expand macro="estimator_params_text" help="Default(=blank): sampling_strategy='auto', random_state=None, estimator=None, voting='auto'." />
+            </when>
+            <when value="under_sampling.CondensedNearestNeighbour">
+                <expand macro="estimator_params_text" help="Default(=blank): sampling_strategy='auto', random_state=None, n_neighbors=None, n_seeds_S=1." />
+            </when>
+            <when value="under_sampling.EditedNearestNeighbours">
+                <expand macro="estimator_params_text" help="Default(=blank): sampling_strategy='auto', random_state=None, n_neighbors=3, max_iter=100, kind_sel='all'." />
+            </when>
+            <when value="under_sampling.RepeatedEditedNearestNeighbours">
+                <expand macro="estimator_params_text" help="Default(=blank): sampling_strategy='auto', random_state=None, n_neighbors=3, max_iter=100, kind_sel='all'." />
+            </when>
+            <when value="under_sampling.AllKNN">
+                <expand macro="estimator_params_text" help="Default(=blank): sampling_strategy='auto', random_state=None, n_neighbors=3, kind_sel='all', allow_minority=False." />
+            </when>
+            <when value="under_sampling.InstanceHardnessThreshold">
+                <expand macro="estimator_params_text" help="Default(=blank): estimator=None, sampling_strategy='auto', random_state=None, cv=5." />
+            </when>
+            <when value="under_sampling.NearMiss">
+                <expand macro="estimator_params_text" help="Default(=blank): sampling_strategy='auto', random_state=None, version=1, n_neighbors=3, n_neighbors_ver3=3." />
+            </when>
+            <when value="under_sampling.NeighbourhoodCleaningRule">
+                <expand macro="estimator_params_text" help="Default(=blank): sampling_strategy='auto', random_state=None, n_neighbors=3, kind_sel='all', threshold_cleaning=0.5." />
+            </when>
+            <when value="under_sampling.OneSidedSelection">
+                <expand macro="estimator_params_text" help="Default(=blank): sampling_strategy='auto', random_state=None, n_neighbors=None, n_seeds_S=1." />
+            </when>
+            <when value="under_sampling.RandomUnderSampler">
+                <expand macro="estimator_params_text" help="Default(=blank): sampling_strategy='auto', random_state=None, replacement=False." />
+            </when>
+            <when value="under_sampling.TomekLinks">
+                <expand macro="estimator_params_text" help="Default(=blank): sampling_strategy='auto', random_state=None." />
+            </when>
+            <when value="over_sampling.ADASYN">
+                <expand macro="estimator_params_text" help="Default(=blank): sampling_strategy='auto', random_state=None, n_neighbors=5." />
+            </when>
+            <when value="over_sampling.RandomOverSampler">
+                <expand macro="estimator_params_text" help="Default(=blank): sampling_strategy='auto', random_state=None." />
+            </when>
+            <when value="over_sampling.SMOTE">
+                <expand macro="estimator_params_text" help="Default(=blank): sampling_strategy='auto', random_state=None, k_neighbors=5." />
+            </when>
+            <when value="over_sampling.SVMSMOTE">
+                <expand macro="estimator_params_text" help="Default(=blank): sampling_strategy='auto', k_neighbors=5, m_neighbors=10, out_step=0.5, random_state=None, svm_estimator=None." />
+            </when>
+            <when value="over_sampling.BorderlineSMOTE">
+                <expand macro="estimator_params_text" help="Default(=blank): sampling_strategy='auto', k_neighbors=5, kind='borderline-1', m_neighbors=10, random_state=None." />
+            </when>
+            <when value="over_sampling.SMOTENC">
+                <expand macro="estimator_params_text" help="Default: categorical_features=[], sampling_strategy='auto', random_state=None, k_neighbors=5." />
+            </when>
+            <when value="combine.SMOTEENN">
+                <expand macro="estimator_params_text" help="Default(=blank): sampling_strategy='auto', random_state=None, smote=None, enn=None." />
+            </when>
+            <when value="combine.SMOTETomek">
+                <expand macro="estimator_params_text" help="Default(=blank): sampling_strategy='auto', random_state=None, smote=None, tomek=None." />
+            </when>
+            <when value="Z_RandomOverSampler">
+                <expand macro="estimator_params_text" help="Default(=blank): sampling_strategy='auto', random_state=None, negative_thres=0, positive_thres=-1." />
+            </when>
+        </conditional>
+    </xml>
 
-  <xml name="stacking_ensemble_inputs">
-    <section name="options" title="Advanced Options" expanded="false">
-        <yield/>
-        <param argument="use_features_in_secondary" type="boolean" truevalue="booltrue" falsevalue="boolfalse" checked="false"/>
-        <param argument="store_train_meta_features" type="boolean" truevalue="booltrue" falsevalue="boolfalse" checked="false"/>
-    </section>
-  </xml>
+    <xml name="stacking_ensemble_inputs">
+        <section name="options" title="Advanced Options" expanded="false">
+            <yield />
+            <param argument="use_features_in_secondary" type="boolean" truevalue="booltrue" falsevalue="boolfalse" checked="false" />
+            <param argument="store_train_meta_features" type="boolean" truevalue="booltrue" falsevalue="boolfalse" checked="false" />
+        </section>
+    </xml>
 
-  <xml name="stacking_base_estimator">
-    <conditional name="estimator_selector">
-        <param name="selected_module" type="select" label="Choose the module that contains target estimator:" >
-            <expand macro="estimator_module_options">
-                <option value="custom_estimator">Load a custom estimator</option>
+    <xml name="stacking_base_estimator">
+        <conditional name="estimator_selector">
+            <param name="selected_module" type="select" label="Choose the module that contains target estimator:">
+                <expand macro="estimator_module_options">
+                    <option value="custom_estimator">Load a custom estimator</option>
+                </expand>
+            </param>
+            <expand macro="estimator_suboptions">
+                <when value="custom_estimator">
+                    <param name="c_estimator" type="data" format="zip" label="Choose the dataset containing the custom estimator or pipeline" />
+                </when>
             </expand>
-        </param>
-        <expand macro="estimator_suboptions">
-            <when value="custom_estimator">
-                <param name="c_estimator" type="data" format="zip" label="Choose the dataset containing the custom estimator or pipeline"/>
-            </when>
-        </expand>
-    </conditional>
-  </xml>
+        </conditional>
+    </xml>
 
-  <xml name="stacking_voting_weights">
-    <section name="options" title="Advanced Options" expanded="false">
-        <param argument="weights" type="text" value="[]" optional="true" help="Sequence of weights (float or int). Uses uniform weights if None (`[]`).">
-          <sanitizer>
-            <valid initial="default">
-              <add value="["/>
-              <add value="]"/>
-            </valid>
-          </sanitizer>
-        </param>
-        <yield/>
-    </section>
-  </xml>
+    <xml name="stacking_voting_weights">
+        <section name="options" title="Advanced Options" expanded="false">
+            <param argument="weights" type="text" value="[]" optional="true" help="Sequence of weights (float or int). Uses uniform weights if None (`[]`).">
+                <sanitizer>
+                    <valid initial="default">
+                        <add value="[" />
+                        <add value="]" />
+                    </valid>
+                </sanitizer>
+            </param>
+            <yield />
+        </section>
+    </xml>
 
-  <xml name="preprocessors_sequence_encoders">
-    <conditional name="encoder_selection">
-        <param name="encoder_type" type="select" label="Choose the sequence encoder class">
-            <option value="GenomeOneHotEncoder">GenomeOneHotEncoder</option>
-            <option value="ProteinOneHotEncoder">ProteinOneHotEncoder</option>
-        </param>
-        <when value="GenomeOneHotEncoder">
-            <expand macro="preprocessors_sequence_encoder_arguments"/>
-        </when>
-        <when value="ProteinOneHotEncoder">
-            <expand macro="preprocessors_sequence_encoder_arguments"/>
-        </when>
-    </conditional>
-  </xml>
+    <xml name="preprocessors_sequence_encoders">
+        <conditional name="encoder_selection">
+            <param name="encoder_type" type="select" label="Choose the sequence encoder class">
+                <option value="GenomeOneHotEncoder">GenomeOneHotEncoder</option>
+                <option value="ProteinOneHotEncoder">ProteinOneHotEncoder</option>
+            </param>
+            <when value="GenomeOneHotEncoder">
+                <expand macro="preprocessors_sequence_encoder_arguments" />
+            </when>
+            <when value="ProteinOneHotEncoder">
+                <expand macro="preprocessors_sequence_encoder_arguments" />
+            </when>
+        </conditional>
+    </xml>
 
-  <xml name="preprocessors_sequence_encoder_arguments">
-    <param argument="seq_length" type="integer" value="" min="0" optional="true" help="Integer. Sequence length"/>
-    <param argument="padding" type="boolean" truevalue="booltrue" falsevalue="boolfalse" checked="true" help="Whether to pad or truncate sequence to meet the sequence length."/>
-  </xml>
+    <xml name="preprocessors_sequence_encoder_arguments">
+        <param argument="seq_length" type="integer" value="" min="0" optional="true" help="Integer. Sequence length" />
+        <param argument="padding" type="boolean" truevalue="booltrue" falsevalue="boolfalse" checked="true" help="Whether to pad or truncate sequence to meet the sequence length." />
+    </xml>
 
-  <!-- Outputs -->
+    <!-- Outputs -->
 
-  <xml name="output">
-    <outputs>
-      <data format="tabular" name="outfile_predict">
-          <filter>selected_tasks['selected_task'] == 'load'</filter>
-      </data>
-      <data format="zip" name="outfile_fit" label="${tool.name}.${selected_tasks.selected_algorithms.selected_algorithm}">
-          <filter>selected_tasks['selected_task'] == 'train'</filter>
-      </data>
-    </outputs>
-  </xml>
+    <xml name="output">
+        <outputs>
+            <data format="tabular" name="outfile_predict">
+                <filter>selected_tasks['selected_task'] == 'load'</filter>
+            </data>
+            <data format="zip" name="outfile_fit" label="${tool.name}.${selected_tasks.selected_algorithms.selected_algorithm}">
+                <filter>selected_tasks['selected_task'] == 'train'</filter>
+            </data>
+        </outputs>
+    </xml>
 
-  <!--Citations-->
-  <xml name="eden_citation">
-    <citations>
-        <citation type="doi">10.5281/zenodo.15094</citation>
-    </citations>
-  </xml>
+    <!--Citations-->
+    <xml name="eden_citation">
+        <citations>
+            <citation type="doi">10.5281/zenodo.15094</citation>
+        </citations>
+    </xml>
 
-  <xml name="sklearn_citation">
-    <citations>
-        <citation type="bibtex">
-          @article{scikit-learn,
-            title={Scikit-learn: Machine Learning in {P}ython},
-            author={Pedregosa, F. and Varoquaux, G. and Gramfort, A. and Michel, V.
+    <xml name="sklearn_citation">
+        <citations>
+            <citation type="bibtex">
+          @article{scikit-learn, title={Scikit-learn: Machine Learning in {P}ython}, author={Pedregosa, F. and Varoquaux, G. and Gramfort, A. and Michel, V.
                     and Thirion, B. and Grisel, O. and Blondel, M. and Prettenhofer, P.
                     and Weiss, R. and Dubourg, V. and Vanderplas, J. and Passos, A. and
-                    Cournapeau, D. and Brucher, M. and Perrot, M. and Duchesnay, E.},
-            journal={Journal of Machine Learning Research},
-            volume={12},
-            pages={2825--2830},
-            year={2011}
+                    Cournapeau, D. and Brucher, M. and Perrot, M. and Duchesnay, E.}, journal={Journal of Machine Learning Research}, volume={12}, pages={2825--2830}, year={2011}
           }
-        </citation>
-        <yield/>
-    </citations>
-  </xml>
+            </citation>
+            <yield />
+        </citations>
+    </xml>
 
-  <xml name="scipy_citation">
-    <citations>
-        <citation type="bibtex">
+    <xml name="scipy_citation">
+        <citations>
+            <citation type="bibtex">
           @Misc{,
           author =    {Eric Jones and Travis Oliphant and Pearu Peterson and others},
           title =     {{SciPy}: Open source scientific tools for {Python}},
@@ -1954,12 +1942,12 @@
           url = "http://www.scipy.org/",
           note = {[Online; accessed 2016-04-09]}
         }
-        </citation>
-    </citations>
-  </xml>
+            </citation>
+        </citations>
+    </xml>
 
-  <xml name="skrebate_citation">
-    <citation type="bibtex">
+    <xml name="skrebate_citation">
+        <citation type="bibtex">
       @article{DBLP:journals/corr/abs-1711-08477,
         author    = {Ryan J. Urbanowicz and
                     Randal S. Olson and
@@ -1977,11 +1965,11 @@
         biburl    = {https://dblp.org/rec/bib/journals/corr/abs-1711-08477},
         bibsource = {dblp computer science bibliography, https://dblp.org}
       }
-    </citation>
-  </xml>
+        </citation>
+    </xml>
 
-  <xml name="xgboost_citation">
-    <citation type="bibtex">
+    <xml name="xgboost_citation">
+        <citation type="bibtex">
       @inproceedings{Chen:2016:XST:2939672.2939785,
         author = {Chen, Tianqi and Guestrin, Carlos},
         title = {{XGBoost}: A Scalable Tree Boosting System},
@@ -1999,11 +1987,11 @@
         address = {New York, NY, USA},
         keywords = {large-scale machine learning},
       }
-    </citation>
-  </xml>
+        </citation>
+    </xml>
 
-  <xml name="imblearn_citation">
-    <citation type="bibtex">
+    <xml name="imblearn_citation">
+        <citation type="bibtex">
       @article{JMLR:v18:16-365,
         author  = {Guillaume  Lema{{\^i}}tre and Fernando Nogueira and Christos K. Aridas},
         title   = {Imbalanced-learn: A Python Toolbox to Tackle the Curse of Imbalanced Datasets in Machine Learning},
@@ -2014,22 +2002,14 @@
         pages   = {1-5},
         url     = {http://jmlr.org/papers/v18/16-365.html}
       }
-    </citation>
-  </xml>
+        </citation>
+    </xml>
 
-  <xml name="selene_citation">
-    <citation type="bibtex">
-      @article{chen2019selene,
-        title={Selene: a PyTorch-based deep learning library for sequence data},
-        author={Chen, Kathleen M and Cofer, Evan M and Zhou, Jian and Troyanskaya, Olga G},
-        journal={Nature methods},
-        volume={16},
-        number={4},
-        pages={315},
-        year={2019},
-        publisher={Nature Publishing Group}
+    <xml name="selene_citation">
+        <citation type="bibtex">
+      @article{chen2019selene, title={Selene: a PyTorch-based deep learning library for sequence data}, author={Chen, Kathleen M and Cofer, Evan M and Zhou, Jian and Troyanskaya, Olga G}, journal={Nature methods}, volume={16}, number={4}, pages={315}, year={2019}, publisher={Nature Publishing Group}
       }
-    </citation>
-  </xml>
+        </citation>
+    </xml>
 
 </macros>
--- a/ml_visualization_ex.py	Thu Oct 01 19:54:05 2020 +0000
+++ b/ml_visualization_ex.py	Tue Apr 13 17:21:05 2021 +0000
@@ -22,16 +22,16 @@
 
 # plotly default colors
 default_colors = [
-    '#1f77b4',  # muted blue
-    '#ff7f0e',  # safety orange
-    '#2ca02c',  # cooked asparagus green
-    '#d62728',  # brick red
-    '#9467bd',  # muted purple
-    '#8c564b',  # chestnut brown
-    '#e377c2',  # raspberry yogurt pink
-    '#7f7f7f',  # middle gray
-    '#bcbd22',  # curry yellow-green
-    '#17becf'   # blue-teal
+    "#1f77b4",  # muted blue
+    "#ff7f0e",  # safety orange
+    "#2ca02c",  # cooked asparagus green
+    "#d62728",  # brick red
+    "#9467bd",  # muted purple
+    "#8c564b",  # chestnut brown
+    "#e377c2",  # raspberry yogurt pink
+    "#7f7f7f",  # middle gray
+    "#bcbd22",  # curry yellow-green
+    "#17becf",  # blue-teal
 ]
 
 
@@ -52,46 +52,31 @@
         y_true = df1.iloc[:, idx].values
         y_score = df2.iloc[:, idx].values
 
-        precision, recall, _ = precision_recall_curve(
-            y_true, y_score, pos_label=pos_label)
-        ap = average_precision_score(
-            y_true, y_score, pos_label=pos_label or 1)
+        precision, recall, _ = precision_recall_curve(y_true, y_score, pos_label=pos_label)
+        ap = average_precision_score(y_true, y_score, pos_label=pos_label or 1)
 
         trace = go.Scatter(
             x=recall,
             y=precision,
-            mode='lines',
-            marker=dict(
-                color=default_colors[idx % len(default_colors)]
-            ),
-            name='%s (area = %.3f)' % (idx, ap)
+            mode="lines",
+            marker=dict(color=default_colors[idx % len(default_colors)]),
+            name="%s (area = %.3f)" % (idx, ap),
         )
         data.append(trace)
 
     layout = go.Layout(
-        xaxis=dict(
-            title='Recall',
-            linecolor='lightslategray',
-            linewidth=1
-        ),
-        yaxis=dict(
-            title='Precision',
-            linecolor='lightslategray',
-            linewidth=1
-        ),
+        xaxis=dict(title="Recall", linecolor="lightslategray", linewidth=1),
+        yaxis=dict(title="Precision", linecolor="lightslategray", linewidth=1),
         title=dict(
-            text=title or 'Precision-Recall Curve',
+            text=title or "Precision-Recall Curve",
             x=0.5,
             y=0.92,
-            xanchor='center',
-            yanchor='top'
+            xanchor="center",
+            yanchor="top",
         ),
-        font=dict(
-            family="sans-serif",
-            size=11
-        ),
+        font=dict(family="sans-serif", size=11),
         # control backgroud colors
-        plot_bgcolor='rgba(255,255,255,0)'
+        plot_bgcolor="rgba(255,255,255,0)",
     )
     """
     legend=dict(
@@ -112,45 +97,47 @@
 
     plotly.offline.plot(fig, filename="output.html", auto_open=False)
     # to be discovered by `from_work_dir`
-    os.rename('output.html', 'output')
+    os.rename("output.html", "output")
 
 
 def visualize_pr_curve_matplotlib(df1, df2, pos_label, title=None):
-    """visualize pr-curve using matplotlib and output svg image
-    """
+    """visualize pr-curve using matplotlib and output svg image"""
     backend = matplotlib.get_backend()
     if "inline" not in backend:
         matplotlib.use("SVG")
-    plt.style.use('seaborn-colorblind')
+    plt.style.use("seaborn-colorblind")
     plt.figure()
 
     for idx in range(df1.shape[1]):
         y_true = df1.iloc[:, idx].values
         y_score = df2.iloc[:, idx].values
 
-        precision, recall, _ = precision_recall_curve(
-            y_true, y_score, pos_label=pos_label)
-        ap = average_precision_score(
-            y_true, y_score, pos_label=pos_label or 1)
+        precision, recall, _ = precision_recall_curve(y_true, y_score, pos_label=pos_label)
+        ap = average_precision_score(y_true, y_score, pos_label=pos_label or 1)
 
-        plt.step(recall, precision, 'r-', color="black", alpha=0.3,
-                 lw=1, where="post", label='%s (area = %.3f)' % (idx, ap))
+        plt.step(
+            recall,
+            precision,
+            "r-",
+            color="black",
+            alpha=0.3,
+            lw=1,
+            where="post",
+            label="%s (area = %.3f)" % (idx, ap),
+        )
 
     plt.xlim([0.0, 1.0])
     plt.ylim([0.0, 1.05])
-    plt.xlabel('Recall')
-    plt.ylabel('Precision')
-    title = title or 'Precision-Recall Curve'
+    plt.xlabel("Recall")
+    plt.ylabel("Precision")
+    title = title or "Precision-Recall Curve"
     plt.title(title)
     folder = os.getcwd()
     plt.savefig(os.path.join(folder, "output.svg"), format="svg")
-    os.rename(os.path.join(folder, "output.svg"),
-              os.path.join(folder, "output"))
+    os.rename(os.path.join(folder, "output.svg"), os.path.join(folder, "output"))
 
 
-def visualize_roc_curve_plotly(df1, df2, pos_label,
-                               drop_intermediate=True,
-                               title=None):
+def visualize_roc_curve_plotly(df1, df2, pos_label, drop_intermediate=True, title=None):
     """output roc-curve in html using plotly
 
     df1 : pandas.DataFrame
@@ -169,45 +156,31 @@
         y_true = df1.iloc[:, idx].values
         y_score = df2.iloc[:, idx].values
 
-        fpr, tpr, _ = roc_curve(y_true, y_score, pos_label=pos_label,
-                                drop_intermediate=drop_intermediate)
+        fpr, tpr, _ = roc_curve(y_true, y_score, pos_label=pos_label, drop_intermediate=drop_intermediate)
         roc_auc = auc(fpr, tpr)
 
         trace = go.Scatter(
             x=fpr,
             y=tpr,
-            mode='lines',
-            marker=dict(
-                color=default_colors[idx % len(default_colors)]
-            ),
-            name='%s (area = %.3f)' % (idx, roc_auc)
+            mode="lines",
+            marker=dict(color=default_colors[idx % len(default_colors)]),
+            name="%s (area = %.3f)" % (idx, roc_auc),
         )
         data.append(trace)
 
     layout = go.Layout(
-        xaxis=dict(
-            title='False Positive Rate',
-            linecolor='lightslategray',
-            linewidth=1
-        ),
-        yaxis=dict(
-            title='True Positive Rate',
-            linecolor='lightslategray',
-            linewidth=1
-        ),
+        xaxis=dict(title="False Positive Rate", linecolor="lightslategray", linewidth=1),
+        yaxis=dict(title="True Positive Rate", linecolor="lightslategray", linewidth=1),
         title=dict(
-            text=title or 'Receiver Operating Characteristic (ROC) Curve',
+            text=title or "Receiver Operating Characteristic (ROC) Curve",
             x=0.5,
             y=0.92,
-            xanchor='center',
-            yanchor='top'
+            xanchor="center",
+            yanchor="top",
         ),
-        font=dict(
-            family="sans-serif",
-            size=11
-        ),
+        font=dict(family="sans-serif", size=11),
         # control backgroud colors
-        plot_bgcolor='rgba(255,255,255,0)'
+        plot_bgcolor="rgba(255,255,255,0)",
     )
     """
     # legend=dict(
@@ -229,66 +202,84 @@
 
     plotly.offline.plot(fig, filename="output.html", auto_open=False)
     # to be discovered by `from_work_dir`
-    os.rename('output.html', 'output')
+    os.rename("output.html", "output")
 
 
-def visualize_roc_curve_matplotlib(df1, df2, pos_label,
-                                   drop_intermediate=True,
-                                   title=None):
-    """visualize roc-curve using matplotlib and output svg image
-    """
+def visualize_roc_curve_matplotlib(df1, df2, pos_label, drop_intermediate=True, title=None):
+    """visualize roc-curve using matplotlib and output svg image"""
     backend = matplotlib.get_backend()
     if "inline" not in backend:
         matplotlib.use("SVG")
-    plt.style.use('seaborn-colorblind')
+    plt.style.use("seaborn-colorblind")
     plt.figure()
 
     for idx in range(df1.shape[1]):
         y_true = df1.iloc[:, idx].values
         y_score = df2.iloc[:, idx].values
 
-        fpr, tpr, _ = roc_curve(y_true, y_score, pos_label=pos_label,
-                                drop_intermediate=drop_intermediate)
+        fpr, tpr, _ = roc_curve(y_true, y_score, pos_label=pos_label, drop_intermediate=drop_intermediate)
         roc_auc = auc(fpr, tpr)
 
-        plt.step(fpr, tpr, 'r-', color="black", alpha=0.3, lw=1,
-                 where="post", label='%s (area = %.3f)' % (idx, roc_auc))
+        plt.step(
+            fpr,
+            tpr,
+            "r-",
+            color="black",
+            alpha=0.3,
+            lw=1,
+            where="post",
+            label="%s (area = %.3f)" % (idx, roc_auc),
+        )
 
     plt.xlim([0.0, 1.0])
     plt.ylim([0.0, 1.05])
-    plt.xlabel('False Positive Rate')
-    plt.ylabel('True Positive Rate')
-    title = title or 'Receiver Operating Characteristic (ROC) Curve'
+    plt.xlabel("False Positive Rate")
+    plt.ylabel("True Positive Rate")
+    title = title or "Receiver Operating Characteristic (ROC) Curve"
     plt.title(title)
     folder = os.getcwd()
     plt.savefig(os.path.join(folder, "output.svg"), format="svg")
-    os.rename(os.path.join(folder, "output.svg"),
-              os.path.join(folder, "output"))
+    os.rename(os.path.join(folder, "output.svg"), os.path.join(folder, "output"))
 
 
 def get_dataframe(file_path, plot_selection, header_name, column_name):
-    header = 'infer' if plot_selection[header_name] else None
+    header = "infer" if plot_selection[header_name] else None
     column_option = plot_selection[column_name]["selected_column_selector_option"]
-    if column_option in ["by_index_number", "all_but_by_index_number", "by_header_name", "all_but_by_header_name"]:
+    if column_option in [
+        "by_index_number",
+        "all_but_by_index_number",
+        "by_header_name",
+        "all_but_by_header_name",
+    ]:
         col = plot_selection[column_name]["col1"]
     else:
         col = None
     _, input_df = read_columns(file_path, c=col,
-                                   c_option=column_option,
-                                   return_df=True,
-                                   sep='\t', header=header,
-                                   parse_dates=True)
+                               c_option=column_option,
+                               return_df=True,
+                               sep='\t', header=header,
+                               parse_dates=True)
     return input_df
 
 
-def main(inputs, infile_estimator=None, infile1=None,
-         infile2=None, outfile_result=None,
-         outfile_object=None, groups=None,
-         ref_seq=None, intervals=None,
-         targets=None, fasta_path=None,
-         model_config=None, true_labels=None,
-         predicted_labels=None, plot_color=None,
-         title=None):
+def main(
+    inputs,
+    infile_estimator=None,
+    infile1=None,
+    infile2=None,
+    outfile_result=None,
+    outfile_object=None,
+    groups=None,
+    ref_seq=None,
+    intervals=None,
+    targets=None,
+    fasta_path=None,
+    model_config=None,
+    true_labels=None,
+    predicted_labels=None,
+    plot_color=None,
+    title=None,
+):
     """
     Parameter
     ---------
@@ -341,34 +332,39 @@
     title : str, default is None
         Title of the confusion matrix heatmap
     """
-    warnings.simplefilter('ignore')
+    warnings.simplefilter("ignore")
 
-    with open(inputs, 'r') as param_handler:
+    with open(inputs, "r") as param_handler:
         params = json.load(param_handler)
 
-    title = params['plotting_selection']['title'].strip()
-    plot_type = params['plotting_selection']['plot_type']
-    plot_format = params['plotting_selection']['plot_format']
+    title = params["plotting_selection"]["title"].strip()
+    plot_type = params["plotting_selection"]["plot_type"]
+    plot_format = params["plotting_selection"]["plot_format"]
 
-    if plot_type == 'feature_importances':
-        with open(infile_estimator, 'rb') as estimator_handler:
+    if plot_type == "feature_importances":
+        with open(infile_estimator, "rb") as estimator_handler:
             estimator = load_model(estimator_handler)
 
-        column_option = (params['plotting_selection']
-                               ['column_selector_options']
-                               ['selected_column_selector_option'])
-        if column_option in ['by_index_number', 'all_but_by_index_number',
-                             'by_header_name', 'all_but_by_header_name']:
-            c = (params['plotting_selection']
-                       ['column_selector_options']['col1'])
+        column_option = params["plotting_selection"]["column_selector_options"]["selected_column_selector_option"]
+        if column_option in [
+            "by_index_number",
+            "all_but_by_index_number",
+            "by_header_name",
+            "all_but_by_header_name",
+        ]:
+            c = params["plotting_selection"]["column_selector_options"]["col1"]
         else:
             c = None
 
-        _, input_df = read_columns(infile1, c=c,
-                                   c_option=column_option,
-                                   return_df=True,
-                                   sep='\t', header='infer',
-                                   parse_dates=True)
+        _, input_df = read_columns(
+            infile1,
+            c=c,
+            c_option=column_option,
+            return_df=True,
+            sep="\t",
+            header="infer",
+            parse_dates=True,
+        )
 
         feature_names = input_df.columns.values
 
@@ -379,16 +375,14 @@
                     feature_names = feature_names[mask]
             estimator = estimator.steps[-1][-1]
 
-        if hasattr(estimator, 'coef_'):
+        if hasattr(estimator, "coef_"):
             coefs = estimator.coef_
         else:
-            coefs = getattr(estimator, 'feature_importances_', None)
+            coefs = getattr(estimator, "feature_importances_", None)
         if coefs is None:
-            raise RuntimeError('The classifier does not expose '
-                               '"coef_" or "feature_importances_" '
-                               'attributes')
+            raise RuntimeError("The classifier does not expose " '"coef_" or "feature_importances_" ' "attributes")
 
-        threshold = params['plotting_selection']['threshold']
+        threshold = params["plotting_selection"]["threshold"]
         if threshold is not None:
             mask = (coefs > threshold) | (coefs < -threshold)
             coefs = coefs[mask]
@@ -397,80 +391,74 @@
         # sort
         indices = np.argsort(coefs)[::-1]
 
-        trace = go.Bar(x=feature_names[indices],
-                       y=coefs[indices])
+        trace = go.Bar(x=feature_names[indices], y=coefs[indices])
         layout = go.Layout(title=title or "Feature Importances")
         fig = go.Figure(data=[trace], layout=layout)
 
-        plotly.offline.plot(fig, filename="output.html",
-                            auto_open=False)
+        plotly.offline.plot(fig, filename="output.html", auto_open=False)
         # to be discovered by `from_work_dir`
-        os.rename('output.html', 'output')
+        os.rename("output.html", "output")
 
         return 0
 
-    elif plot_type in ('pr_curve', 'roc_curve'):
-        df1 = pd.read_csv(infile1, sep='\t', header='infer')
-        df2 = pd.read_csv(infile2, sep='\t', header='infer').astype(np.float32)
+    elif plot_type in ("pr_curve", "roc_curve"):
+        df1 = pd.read_csv(infile1, sep="\t", header="infer")
+        df2 = pd.read_csv(infile2, sep="\t", header="infer").astype(np.float32)
 
-        minimum = params['plotting_selection']['report_minimum_n_positives']
+        minimum = params["plotting_selection"]["report_minimum_n_positives"]
         # filter out columns whose n_positives is beblow the threhold
         if minimum:
             mask = df1.sum(axis=0) >= minimum
             df1 = df1.loc[:, mask]
             df2 = df2.loc[:, mask]
 
-        pos_label = params['plotting_selection']['pos_label'].strip() \
-            or None
+        pos_label = params["plotting_selection"]["pos_label"].strip() or None
 
-        if plot_type == 'pr_curve':
-            if plot_format == 'plotly_html':
+        if plot_type == "pr_curve":
+            if plot_format == "plotly_html":
                 visualize_pr_curve_plotly(df1, df2, pos_label, title=title)
             else:
                 visualize_pr_curve_matplotlib(df1, df2, pos_label, title)
-        else:          # 'roc_curve'
-            drop_intermediate = (params['plotting_selection']
-                                       ['drop_intermediate'])
-            if plot_format == 'plotly_html':
-                visualize_roc_curve_plotly(df1, df2, pos_label,
-                                           drop_intermediate=drop_intermediate,
-                                           title=title)
+        else:  # 'roc_curve'
+            drop_intermediate = params["plotting_selection"]["drop_intermediate"]
+            if plot_format == "plotly_html":
+                visualize_roc_curve_plotly(
+                    df1,
+                    df2,
+                    pos_label,
+                    drop_intermediate=drop_intermediate,
+                    title=title,
+                )
             else:
                 visualize_roc_curve_matplotlib(
-                    df1, df2, pos_label,
+                    df1,
+                    df2,
+                    pos_label,
                     drop_intermediate=drop_intermediate,
-                    title=title)
+                    title=title,
+                )
 
         return 0
 
-    elif plot_type == 'rfecv_gridscores':
-        input_df = pd.read_csv(infile1, sep='\t', header='infer')
+    elif plot_type == "rfecv_gridscores":
+        input_df = pd.read_csv(infile1, sep="\t", header="infer")
         scores = input_df.iloc[:, 0]
-        steps = params['plotting_selection']['steps'].strip()
+        steps = params["plotting_selection"]["steps"].strip()
         steps = safe_eval(steps)
 
         data = go.Scatter(
             x=list(range(len(scores))),
             y=scores,
             text=[str(_) for _ in steps] if steps else None,
-            mode='lines'
+            mode="lines",
         )
         layout = go.Layout(
             xaxis=dict(title="Number of features selected"),
             yaxis=dict(title="Cross validation score"),
-            title=dict(
-                text=title or None,
-                x=0.5,
-                y=0.92,
-                xanchor='center',
-                yanchor='top'
-            ),
-            font=dict(
-                family="sans-serif",
-                size=11
-            ),
+            title=dict(text=title or None, x=0.5, y=0.92, xanchor="center", yanchor="top"),
+            font=dict(family="sans-serif", size=11),
             # control backgroud colors
-            plot_bgcolor='rgba(255,255,255,0)'
+            plot_bgcolor="rgba(255,255,255,0)",
         )
         """
         # legend=dict(
@@ -489,55 +477,43 @@
         """
 
         fig = go.Figure(data=[data], layout=layout)
-        plotly.offline.plot(fig, filename="output.html",
-                            auto_open=False)
+        plotly.offline.plot(fig, filename="output.html", auto_open=False)
         # to be discovered by `from_work_dir`
-        os.rename('output.html', 'output')
+        os.rename("output.html", "output")
 
         return 0
 
-    elif plot_type == 'learning_curve':
-        input_df = pd.read_csv(infile1, sep='\t', header='infer')
-        plot_std_err = params['plotting_selection']['plot_std_err']
+    elif plot_type == "learning_curve":
+        input_df = pd.read_csv(infile1, sep="\t", header="infer")
+        plot_std_err = params["plotting_selection"]["plot_std_err"]
         data1 = go.Scatter(
-            x=input_df['train_sizes_abs'],
-            y=input_df['mean_train_scores'],
-            error_y=dict(
-                array=input_df['std_train_scores']
-            ) if plot_std_err else None,
-            mode='lines',
+            x=input_df["train_sizes_abs"],
+            y=input_df["mean_train_scores"],
+            error_y=dict(array=input_df["std_train_scores"]) if plot_std_err else None,
+            mode="lines",
             name="Train Scores",
         )
         data2 = go.Scatter(
-            x=input_df['train_sizes_abs'],
-            y=input_df['mean_test_scores'],
-            error_y=dict(
-                array=input_df['std_test_scores']
-            ) if plot_std_err else None,
-            mode='lines',
+            x=input_df["train_sizes_abs"],
+            y=input_df["mean_test_scores"],
+            error_y=dict(array=input_df["std_test_scores"]) if plot_std_err else None,
+            mode="lines",
             name="Test Scores",
         )
         layout = dict(
-            xaxis=dict(
-                title='No. of samples'
-            ),
-            yaxis=dict(
-                title='Performance Score'
-            ),
+            xaxis=dict(title="No. of samples"),
+            yaxis=dict(title="Performance Score"),
             # modify these configurations to customize image
             title=dict(
-                text=title or 'Learning Curve',
+                text=title or "Learning Curve",
                 x=0.5,
                 y=0.92,
-                xanchor='center',
-                yanchor='top'
+                xanchor="center",
+                yanchor="top",
             ),
-            font=dict(
-                family="sans-serif",
-                size=11
-            ),
+            font=dict(family="sans-serif", size=11),
             # control backgroud colors
-            plot_bgcolor='rgba(255,255,255,0)'
+            plot_bgcolor="rgba(255,255,255,0)",
         )
         """
         # legend=dict(
@@ -556,27 +532,26 @@
         """
 
         fig = go.Figure(data=[data1, data2], layout=layout)
-        plotly.offline.plot(fig, filename="output.html",
-                            auto_open=False)
+        plotly.offline.plot(fig, filename="output.html", auto_open=False)
         # to be discovered by `from_work_dir`
-        os.rename('output.html', 'output')
+        os.rename("output.html", "output")
 
         return 0
 
-    elif plot_type == 'keras_plot_model':
-        with open(model_config, 'r') as f:
+    elif plot_type == "keras_plot_model":
+        with open(model_config, "r") as f:
             model_str = f.read()
         model = model_from_json(model_str)
         plot_model(model, to_file="output.png")
-        os.rename('output.png', 'output')
+        os.rename("output.png", "output")
 
         return 0
 
-    elif plot_type == 'classification_confusion_matrix':
+    elif plot_type == "classification_confusion_matrix":
         plot_selection = params["plotting_selection"]
         input_true = get_dataframe(true_labels, plot_selection, "header_true", "column_selector_options_true")
-        header_predicted = 'infer' if plot_selection["header_predicted"] else None
-        input_predicted = pd.read_csv(predicted_labels, sep='\t', parse_dates=True, header=header_predicted)
+        header_predicted = "infer" if plot_selection["header_predicted"] else None
+        input_predicted = pd.read_csv(predicted_labels, sep="\t", parse_dates=True, header=header_predicted)
         true_classes = input_true.iloc[:, -1].copy()
         predicted_classes = input_predicted.iloc[:, -1].copy()
         axis_labels = list(set(true_classes))
@@ -586,15 +561,15 @@
         for i in range(len(c_matrix)):
             for j in range(len(c_matrix)):
                 ax.text(j, i, c_matrix[i, j], ha="center", va="center", color="k")
-        ax.set_ylabel('True class labels')
-        ax.set_xlabel('Predicted class labels')
+        ax.set_ylabel("True class labels")
+        ax.set_xlabel("Predicted class labels")
         ax.set_title(title)
         ax.set_xticks(axis_labels)
         ax.set_yticks(axis_labels)
         fig.colorbar(im, ax=ax)
         fig.tight_layout()
         plt.savefig("output.png", dpi=125)
-        os.rename('output.png', 'output')
+        os.rename("output.png", "output")
 
         return 0
 
@@ -603,7 +578,7 @@
     # fig.write_image("image.pdf", format='pdf', width=340*2, height=226*2)
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     aparser = argparse.ArgumentParser()
     aparser.add_argument("-i", "--inputs", dest="inputs", required=True)
     aparser.add_argument("-e", "--estimator", dest="infile_estimator")
@@ -623,11 +598,21 @@
     aparser.add_argument("-pt", "--title", dest="title")
     args = aparser.parse_args()
 
-    main(args.inputs, args.infile_estimator, args.infile1, args.infile2,
-         args.outfile_result, outfile_object=args.outfile_object,
-         groups=args.groups, ref_seq=args.ref_seq, intervals=args.intervals,
-         targets=args.targets, fasta_path=args.fasta_path,
-         model_config=args.model_config, true_labels=args.true_labels,
-         predicted_labels=args.predicted_labels,
-         plot_color=args.plot_color,
-         title=args.title)
+    main(
+        args.inputs,
+        args.infile_estimator,
+        args.infile1,
+        args.infile2,
+        args.outfile_result,
+        outfile_object=args.outfile_object,
+        groups=args.groups,
+        ref_seq=args.ref_seq,
+        intervals=args.intervals,
+        targets=args.targets,
+        fasta_path=args.fasta_path,
+        model_config=args.model_config,
+        true_labels=args.true_labels,
+        predicted_labels=args.predicted_labels,
+        plot_color=args.plot_color,
+        title=args.title,
+    )
--- a/model_prediction.py	Thu Oct 01 19:54:05 2020 +0000
+++ b/model_prediction.py	Tue Apr 13 17:21:05 2021 +0000
@@ -1,23 +1,29 @@
 import argparse
 import json
+import warnings
+
 import numpy as np
 import pandas as pd
-import warnings
-
 from scipy.io import mmread
 from sklearn.pipeline import Pipeline
 
-from galaxy_ml.utils import (load_model, read_columns,
-                             get_module, try_get_attr)
+from galaxy_ml.utils import (get_module, load_model,
+                             read_columns, try_get_attr)
+
+
+N_JOBS = int(__import__("os").environ.get("GALAXY_SLOTS", 1))
 
 
-N_JOBS = int(__import__('os').environ.get('GALAXY_SLOTS', 1))
-
-
-def main(inputs, infile_estimator, outfile_predict,
-         infile_weights=None, infile1=None,
-         fasta_path=None, ref_seq=None,
-         vcf_path=None):
+def main(
+    inputs,
+    infile_estimator,
+    outfile_predict,
+    infile_weights=None,
+    infile1=None,
+    fasta_path=None,
+    ref_seq=None,
+    vcf_path=None,
+):
     """
     Parameter
     ---------
@@ -45,96 +51,94 @@
     vcf_path : str
         File path to dataset containing variants info.
     """
-    warnings.filterwarnings('ignore')
+    warnings.filterwarnings("ignore")
 
-    with open(inputs, 'r') as param_handler:
+    with open(inputs, "r") as param_handler:
         params = json.load(param_handler)
 
     # load model
-    with open(infile_estimator, 'rb') as est_handler:
+    with open(infile_estimator, "rb") as est_handler:
         estimator = load_model(est_handler)
 
     main_est = estimator
     if isinstance(estimator, Pipeline):
         main_est = estimator.steps[-1][-1]
-    if hasattr(main_est, 'config') and hasattr(main_est, 'load_weights'):
-        if not infile_weights or infile_weights == 'None':
-            raise ValueError("The selected model skeleton asks for weights, "
-                             "but dataset for weights wan not selected!")
+    if hasattr(main_est, "config") and hasattr(main_est, "load_weights"):
+        if not infile_weights or infile_weights == "None":
+            raise ValueError(
+                "The selected model skeleton asks for weights, " "but dataset for weights wan not selected!"
+            )
         main_est.load_weights(infile_weights)
 
     # handle data input
-    input_type = params['input_options']['selected_input']
+    input_type = params["input_options"]["selected_input"]
     # tabular input
-    if input_type == 'tabular':
-        header = 'infer' if params['input_options']['header1'] else None
-        column_option = (params['input_options']
-                               ['column_selector_options_1']
-                               ['selected_column_selector_option'])
-        if column_option in ['by_index_number', 'all_but_by_index_number',
-                             'by_header_name', 'all_but_by_header_name']:
-            c = params['input_options']['column_selector_options_1']['col1']
+    if input_type == "tabular":
+        header = "infer" if params["input_options"]["header1"] else None
+        column_option = params["input_options"]["column_selector_options_1"]["selected_column_selector_option"]
+        if column_option in [
+            "by_index_number",
+            "all_but_by_index_number",
+            "by_header_name",
+            "all_but_by_header_name",
+        ]:
+            c = params["input_options"]["column_selector_options_1"]["col1"]
         else:
             c = None
 
-        df = pd.read_csv(infile1, sep='\t', header=header, parse_dates=True)
+        df = pd.read_csv(infile1, sep="\t", header=header, parse_dates=True)
 
         X = read_columns(df, c=c, c_option=column_option).astype(float)
 
-        if params['method'] == 'predict':
+        if params["method"] == "predict":
             preds = estimator.predict(X)
         else:
             preds = estimator.predict_proba(X)
 
     # sparse input
-    elif input_type == 'sparse':
-        X = mmread(open(infile1, 'r'))
-        if params['method'] == 'predict':
+    elif input_type == "sparse":
+        X = mmread(open(infile1, "r"))
+        if params["method"] == "predict":
             preds = estimator.predict(X)
         else:
             preds = estimator.predict_proba(X)
 
     # fasta input
-    elif input_type == 'seq_fasta':
-        if not hasattr(estimator, 'data_batch_generator'):
+    elif input_type == "seq_fasta":
+        if not hasattr(estimator, "data_batch_generator"):
             raise ValueError(
                 "To do prediction on sequences in fasta input, "
                 "the estimator must be a `KerasGBatchClassifier`"
-                "equipped with data_batch_generator!")
-        pyfaidx = get_module('pyfaidx')
+                "equipped with data_batch_generator!"
+            )
+        pyfaidx = get_module("pyfaidx")
         sequences = pyfaidx.Fasta(fasta_path)
         n_seqs = len(sequences.keys())
         X = np.arange(n_seqs)[:, np.newaxis]
         seq_length = estimator.data_batch_generator.seq_length
-        batch_size = getattr(estimator, 'batch_size', 32)
+        batch_size = getattr(estimator, "batch_size", 32)
         steps = (n_seqs + batch_size - 1) // batch_size
 
-        seq_type = params['input_options']['seq_type']
-        klass = try_get_attr(
-            'galaxy_ml.preprocessors', seq_type)
+        seq_type = params["input_options"]["seq_type"]
+        klass = try_get_attr("galaxy_ml.preprocessors", seq_type)
 
-        pred_data_generator = klass(
-            fasta_path, seq_length=seq_length)
+        pred_data_generator = klass(fasta_path, seq_length=seq_length)
 
-        if params['method'] == 'predict':
-            preds = estimator.predict(
-                X, data_generator=pred_data_generator, steps=steps)
+        if params["method"] == "predict":
+            preds = estimator.predict(X, data_generator=pred_data_generator, steps=steps)
         else:
-            preds = estimator.predict_proba(
-                X, data_generator=pred_data_generator, steps=steps)
+            preds = estimator.predict_proba(X, data_generator=pred_data_generator, steps=steps)
 
     # vcf input
-    elif input_type == 'variant_effect':
-        klass = try_get_attr('galaxy_ml.preprocessors',
-                             'GenomicVariantBatchGenerator')
+    elif input_type == "variant_effect":
+        klass = try_get_attr("galaxy_ml.preprocessors", "GenomicVariantBatchGenerator")
 
-        options = params['input_options']
-        options.pop('selected_input')
-        if options['blacklist_regions'] == 'none':
-            options['blacklist_regions'] = None
+        options = params["input_options"]
+        options.pop("selected_input")
+        if options["blacklist_regions"] == "none":
+            options["blacklist_regions"] = None
 
-        pred_data_generator = klass(
-            ref_genome_path=ref_seq, vcf_path=vcf_path, **options)
+        pred_data_generator = klass(ref_genome_path=ref_seq, vcf_path=vcf_path, **options)
 
         pred_data_generator.set_processing_attrs()
 
@@ -143,9 +147,8 @@
         # predict 1600 sample at once then write to file
         gen_flow = pred_data_generator.flow(batch_size=1600)
 
-        file_writer = open(outfile_predict, 'w')
-        header_row = '\t'.join(['chrom', 'pos', 'name', 'ref',
-                                'alt', 'strand'])
+        file_writer = open(outfile_predict, "w")
+        header_row = "\t".join(["chrom", "pos", "name", "ref", "alt", "strand"])
         file_writer.write(header_row)
         header_done = False
 
@@ -155,23 +158,24 @@
         try:
             while steps_done < len(gen_flow):
                 index_array = next(gen_flow.index_generator)
-                batch_X = gen_flow._get_batches_of_transformed_samples(
-                    index_array)
+                batch_X = gen_flow._get_batches_of_transformed_samples(index_array)
 
-                if params['method'] == 'predict':
+                if params["method"] == "predict":
                     batch_preds = estimator.predict(
                         batch_X,
                         # The presence of `pred_data_generator` below is to
                         # override model carrying data_generator if there
                         # is any.
-                        data_generator=pred_data_generator)
+                        data_generator=pred_data_generator,
+                    )
                 else:
                     batch_preds = estimator.predict_proba(
                         batch_X,
                         # The presence of `pred_data_generator` below is to
                         # override model carrying data_generator if there
                         # is any.
-                        data_generator=pred_data_generator)
+                        data_generator=pred_data_generator,
+                    )
 
                 if batch_preds.ndim == 1:
                     batch_preds = batch_preds[:, np.newaxis]
@@ -181,12 +185,12 @@
 
                 if not header_done:
                     heads = np.arange(batch_preds.shape[-1]).astype(str)
-                    heads_str = '\t'.join(heads)
+                    heads_str = "\t".join(heads)
                     file_writer.write("\t%s\n" % heads_str)
                     header_done = True
 
                 for row in batch_out:
-                    row_str = '\t'.join(row)
+                    row_str = "\t".join(row)
                     file_writer.write("%s\n" % row_str)
 
                 steps_done += 1
@@ -200,14 +204,14 @@
 
     # output
     if len(preds.shape) == 1:
-        rval = pd.DataFrame(preds, columns=['Predicted'])
+        rval = pd.DataFrame(preds, columns=["Predicted"])
     else:
         rval = pd.DataFrame(preds)
 
-    rval.to_csv(outfile_predict, sep='\t', header=True, index=False)
+    rval.to_csv(outfile_predict, sep="\t", header=True, index=False)
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     aparser = argparse.ArgumentParser()
     aparser.add_argument("-i", "--inputs", dest="inputs", required=True)
     aparser.add_argument("-e", "--infile_estimator", dest="infile_estimator")
@@ -219,7 +223,13 @@
     aparser.add_argument("-v", "--vcf_path", dest="vcf_path")
     args = aparser.parse_args()
 
-    main(args.inputs, args.infile_estimator, args.outfile_predict,
-         infile_weights=args.infile_weights, infile1=args.infile1,
-         fasta_path=args.fasta_path, ref_seq=args.ref_seq,
-         vcf_path=args.vcf_path)
+    main(
+        args.inputs,
+        args.infile_estimator,
+        args.outfile_predict,
+        infile_weights=args.infile_weights,
+        infile1=args.infile1,
+        fasta_path=args.fasta_path,
+        ref_seq=args.ref_seq,
+        vcf_path=args.vcf_path,
+    )
--- a/pca.py	Thu Oct 01 19:54:05 2020 +0000
+++ b/pca.py	Tue Apr 13 17:21:05 2021 +0000
@@ -1,98 +1,185 @@
 import argparse
+
 import numpy as np
-from sklearn.decomposition import PCA, IncrementalPCA, KernelPCA
 from galaxy_ml.utils import read_columns
+from sklearn.decomposition import IncrementalPCA, KernelPCA, PCA
+
 
 def main():
-    parser = argparse.ArgumentParser(description='RDKit screen')
-    parser.add_argument('-i', '--infile',
-                        help="Input file")
-    parser.add_argument('--header', action='store_true', help="Include the header row or skip it")
-    parser.add_argument('-c', '--columns', type=str.lower, default='all', choices=['by_index_number', 'all_but_by_index_number',\
-                        'by_header_name', 'all_but_by_header_name', 'all_columns'],
-                        help="Choose to select all columns, or exclude/include some")
-    parser.add_argument('-ci', '--column_indices', type=str.lower,
-                        help="Choose to select all columns, or exclude/include some")
-    parser.add_argument('-n', '--number', nargs='?', type=int, default=None,\
-                        help="Number of components to keep. If not set, all components are kept")
-    parser.add_argument('--whiten', action='store_true', help="Whiten the components")
-    parser.add_argument('-t', '--pca_type', type=str.lower, default='classical', choices=['classical', 'incremental', 'kernel'],
-                        help="Choose which flavour of PCA to use")
-    parser.add_argument('-s', '--svd_solver', type=str.lower, default='auto', choices=['auto', 'full', 'arpack', 'randomized'],
-                        help="Choose the type of svd solver.")
-    parser.add_argument('-b', '--batch_size', nargs='?', type=int, default=None,\
-                        help="The number of samples to use for each batch")
-    parser.add_argument('-k', '--kernel', type=str.lower, default='linear',\
-                        choices=['linear', 'poly', 'rbf', 'sigmoid', 'cosine', 'precomputed'],
-                        help="Choose the type of kernel.")
-    parser.add_argument('-g', '--gamma', nargs='?', type=float, default=None,
-                        help='Kernel coefficient for rbf, poly and sigmoid kernels. Ignored by other kernels')
-    parser.add_argument('-tol', '--tolerance', type=float, default=0.0,
-                        help='Convergence tolerance for arpack. If 0, optimal value will be chosen by arpack')
-    parser.add_argument('-mi', '--max_iter', nargs='?', type=int, default=None,\
-                        help="Maximum number of iterations for arpack")
-    parser.add_argument('-d', '--degree', type=int, default=3,\
-                        help="Degree for poly kernels. Ignored by other kernels")
-    parser.add_argument('-cf', '--coef0', type=float, default=1.0,
-                        help='Independent term in poly and sigmoid kernels')
-    parser.add_argument('-e', '--eigen_solver', type=str.lower, default='auto', choices=['auto', 'dense', 'arpack'],
-                        help="Choose the type of eigen solver.")
-    parser.add_argument('-o', '--outfile',
-                        help="Base name for output file (no extension).")
+    parser = argparse.ArgumentParser(description="RDKit screen")
+    parser.add_argument("-i", "--infile", help="Input file")
+    parser.add_argument(
+        "--header", action="store_true", help="Include the header row or skip it"
+    )
+    parser.add_argument(
+        "-c",
+        "--columns",
+        type=str.lower,
+        default="all",
+        choices=[
+            "by_index_number",
+            "all_but_by_index_number",
+            "by_header_name",
+            "all_but_by_header_name",
+            "all_columns",
+        ],
+        help="Choose to select all columns, or exclude/include some",
+    )
+    parser.add_argument(
+        "-ci",
+        "--column_indices",
+        type=str.lower,
+        help="Choose to select all columns, or exclude/include some",
+    )
+    parser.add_argument(
+        "-n",
+        "--number",
+        nargs="?",
+        type=int,
+        default=None,
+        help="Number of components to keep. If not set, all components are kept",
+    )
+    parser.add_argument("--whiten", action="store_true", help="Whiten the components")
+    parser.add_argument(
+        "-t",
+        "--pca_type",
+        type=str.lower,
+        default="classical",
+        choices=["classical", "incremental", "kernel"],
+        help="Choose which flavour of PCA to use",
+    )
+    parser.add_argument(
+        "-s",
+        "--svd_solver",
+        type=str.lower,
+        default="auto",
+        choices=["auto", "full", "arpack", "randomized"],
+        help="Choose the type of svd solver.",
+    )
+    parser.add_argument(
+        "-b",
+        "--batch_size",
+        nargs="?",
+        type=int,
+        default=None,
+        help="The number of samples to use for each batch",
+    )
+    parser.add_argument(
+        "-k",
+        "--kernel",
+        type=str.lower,
+        default="linear",
+        choices=["linear", "poly", "rbf", "sigmoid", "cosine", "precomputed"],
+        help="Choose the type of kernel.",
+    )
+    parser.add_argument(
+        "-g",
+        "--gamma",
+        nargs="?",
+        type=float,
+        default=None,
+        help="Kernel coefficient for rbf, poly and sigmoid kernels. Ignored by other kernels",
+    )
+    parser.add_argument(
+        "-tol",
+        "--tolerance",
+        type=float,
+        default=0.0,
+        help="Convergence tolerance for arpack. If 0, optimal value will be chosen by arpack",
+    )
+    parser.add_argument(
+        "-mi",
+        "--max_iter",
+        nargs="?",
+        type=int,
+        default=None,
+        help="Maximum number of iterations for arpack",
+    )
+    parser.add_argument(
+        "-d",
+        "--degree",
+        type=int,
+        default=3,
+        help="Degree for poly kernels. Ignored by other kernels",
+    )
+    parser.add_argument(
+        "-cf",
+        "--coef0",
+        type=float,
+        default=1.0,
+        help="Independent term in poly and sigmoid kernels",
+    )
+    parser.add_argument(
+        "-e",
+        "--eigen_solver",
+        type=str.lower,
+        default="auto",
+        choices=["auto", "dense", "arpack"],
+        help="Choose the type of eigen solver.",
+    )
+    parser.add_argument(
+        "-o", "--outfile", help="Base name for output file (no extension)."
+    )
     args = parser.parse_args()
 
     usecols = None
-    cols = []
     pca_params = {}
 
-    if args.columns == 'by_index_number' or args.columns == 'all_but_by_index_number':
-        usecols = [int(i) for i in args.column_indices.split(',')]
-    elif args.columns == 'by_header_name' or args.columns == 'all_but_by_header_name':
+    if args.columns == "by_index_number" or args.columns == "all_but_by_index_number":
+        usecols = [int(i) for i in args.column_indices.split(",")]
+    elif args.columns == "by_header_name" or args.columns == "all_but_by_header_name":
         usecols = args.column_indices
 
-    header = 'infer' if args.header else None
+    header = "infer" if args.header else None
 
     pca_input = read_columns(
         f=args.infile,
         c=usecols,
         c_option=args.columns,
-        sep='\t',
+        sep="\t",
         header=header,
         parse_dates=True,
         encoding=None,
-        index_col=None)
+        index_col=None,
+    )
 
-    pca_params.update({'n_components': args.number})
+    pca_params.update({"n_components": args.number})
 
-    if args.pca_type == 'classical':
-        pca_params.update({'svd_solver': args.svd_solver, 'whiten': args.whiten})
-        if args.svd_solver == 'arpack':
-            pca_params.update({'tol': args.tolerance})
+    if args.pca_type == "classical":
+        pca_params.update({"svd_solver": args.svd_solver, "whiten": args.whiten})
+        if args.svd_solver == "arpack":
+            pca_params.update({"tol": args.tolerance})
         pca = PCA()
 
-    elif args.pca_type == 'incremental':
-        pca_params.update({'batch_size': args.batch_size, 'whiten': args.whiten})
+    elif args.pca_type == "incremental":
+        pca_params.update({"batch_size": args.batch_size, "whiten": args.whiten})
         pca = IncrementalPCA()
 
-    elif args.pca_type == 'kernel':
-        pca_params.update({'kernel': args.kernel, 'eigen_solver': args.eigen_solver, 'gamma': args.gamma})
+    elif args.pca_type == "kernel":
+        pca_params.update(
+            {
+                "kernel": args.kernel,
+                "eigen_solver": args.eigen_solver,
+                "gamma": args.gamma,
+            }
+        )
 
-        if args.kernel == 'poly':
-            pca_params.update({'degree': args.degree, 'coef0': args.coef0})
-        elif args.kernel == 'sigmoid':
-            pca_params.update({'coef0': args.coef0})
-        elif args.kernel == 'precomputed':
+        if args.kernel == "poly":
+            pca_params.update({"degree": args.degree, "coef0": args.coef0})
+        elif args.kernel == "sigmoid":
+            pca_params.update({"coef0": args.coef0})
+        elif args.kernel == "precomputed":
             pca_input = np.dot(pca_input, pca_input.T)
 
-        if args.eigen_solver == 'arpack':
-            pca_params.update({'tol': args.tolerance, 'max_iter': args.max_iter})
+        if args.eigen_solver == "arpack":
+            pca_params.update({"tol": args.tolerance, "max_iter": args.max_iter})
 
         pca = KernelPCA()
 
     print(pca_params)
     pca.set_params(**pca_params)
     pca_output = pca.fit_transform(pca_input)
-    np.savetxt(fname=args.outfile, X=pca_output, fmt='%.4f', delimiter='\t')
+    np.savetxt(fname=args.outfile, X=pca_output, fmt="%.4f", delimiter="\t")
 
 
 if __name__ == "__main__":
--- a/search_model_validation.py	Thu Oct 01 19:54:05 2020 +0000
+++ b/search_model_validation.py	Tue Apr 13 17:21:05 2021 +0000
@@ -11,45 +11,57 @@
 import sys
 import warnings
 from scipy.io import mmread
-from sklearn import (cluster, decomposition, feature_selection,
-                     kernel_approximation, model_selection, preprocessing)
+from sklearn import (
+    cluster,
+    decomposition,
+    feature_selection,
+    kernel_approximation,
+    model_selection,
+    preprocessing,
+)
 from sklearn.exceptions import FitFailedWarning
 from sklearn.model_selection._validation import _score, cross_validate
 from sklearn.model_selection import _search, _validation
 from sklearn.pipeline import Pipeline
 
-from galaxy_ml.utils import (SafeEval, get_cv, get_scoring, load_model,
-                             read_columns, try_get_attr, get_module,
-                             clean_params, get_main_estimator)
+from galaxy_ml.utils import (
+    SafeEval,
+    get_cv,
+    get_scoring,
+    load_model,
+    read_columns,
+    try_get_attr,
+    get_module,
+    clean_params,
+    get_main_estimator,
+)
 
 
-_fit_and_score = try_get_attr('galaxy_ml.model_validations', '_fit_and_score')
-setattr(_search, '_fit_and_score', _fit_and_score)
-setattr(_validation, '_fit_and_score', _fit_and_score)
+_fit_and_score = try_get_attr("galaxy_ml.model_validations", "_fit_and_score")
+setattr(_search, "_fit_and_score", _fit_and_score)
+setattr(_validation, "_fit_and_score", _fit_and_score)
 
-N_JOBS = int(os.environ.get('GALAXY_SLOTS', 1))
+N_JOBS = int(os.environ.get("GALAXY_SLOTS", 1))
 # handle  disk cache
-CACHE_DIR = os.path.join(os.getcwd(), 'cached')
+CACHE_DIR = os.path.join(os.getcwd(), "cached")
 del os
-NON_SEARCHABLE = ('n_jobs', 'pre_dispatch', 'memory', '_path',
-                  'nthread', 'callbacks')
+NON_SEARCHABLE = ("n_jobs", "pre_dispatch", "memory", "_path", "nthread", "callbacks")
 
 
 def _eval_search_params(params_builder):
     search_params = {}
 
-    for p in params_builder['param_set']:
-        search_list = p['sp_list'].strip()
-        if search_list == '':
+    for p in params_builder["param_set"]:
+        search_list = p["sp_list"].strip()
+        if search_list == "":
             continue
 
-        param_name = p['sp_name']
+        param_name = p["sp_name"]
         if param_name.lower().endswith(NON_SEARCHABLE):
-            print("Warning: `%s` is not eligible for search and was "
-                  "omitted!" % param_name)
+            print("Warning: `%s` is not eligible for search and was " "omitted!" % param_name)
             continue
 
-        if not search_list.startswith(':'):
+        if not search_list.startswith(":"):
             safe_eval = SafeEval(load_scipy=True, load_numpy=True)
             ev = safe_eval(search_list)
             search_params[param_name] = ev
@@ -60,26 +72,27 @@
             # TODO maybe add regular express check
             ev = safe_eval_es(search_list)
             preprocessings = (
-                preprocessing.StandardScaler(), preprocessing.Binarizer(),
+                preprocessing.StandardScaler(),
+                preprocessing.Binarizer(),
                 preprocessing.MaxAbsScaler(),
-                preprocessing.Normalizer(), preprocessing.MinMaxScaler(),
+                preprocessing.Normalizer(),
+                preprocessing.MinMaxScaler(),
                 preprocessing.PolynomialFeatures(),
-                preprocessing.RobustScaler(), feature_selection.SelectKBest(),
+                preprocessing.RobustScaler(),
+                feature_selection.SelectKBest(),
                 feature_selection.GenericUnivariateSelect(),
                 feature_selection.SelectPercentile(),
-                feature_selection.SelectFpr(), feature_selection.SelectFdr(),
+                feature_selection.SelectFpr(),
+                feature_selection.SelectFdr(),
                 feature_selection.SelectFwe(),
                 feature_selection.VarianceThreshold(),
                 decomposition.FactorAnalysis(random_state=0),
                 decomposition.FastICA(random_state=0),
                 decomposition.IncrementalPCA(),
                 decomposition.KernelPCA(random_state=0, n_jobs=N_JOBS),
-                decomposition.LatentDirichletAllocation(
-                    random_state=0, n_jobs=N_JOBS),
-                decomposition.MiniBatchDictionaryLearning(
-                    random_state=0, n_jobs=N_JOBS),
-                decomposition.MiniBatchSparsePCA(
-                    random_state=0, n_jobs=N_JOBS),
+                decomposition.LatentDirichletAllocation(random_state=0, n_jobs=N_JOBS),
+                decomposition.MiniBatchDictionaryLearning(random_state=0, n_jobs=N_JOBS),
+                decomposition.MiniBatchSparsePCA(random_state=0, n_jobs=N_JOBS),
                 decomposition.NMF(random_state=0),
                 decomposition.PCA(random_state=0),
                 decomposition.SparsePCA(random_state=0, n_jobs=N_JOBS),
@@ -94,59 +107,48 @@
                 skrebate.SURFstar(n_jobs=N_JOBS),
                 skrebate.MultiSURF(n_jobs=N_JOBS),
                 skrebate.MultiSURFstar(n_jobs=N_JOBS),
-                imblearn.under_sampling.ClusterCentroids(
-                    random_state=0, n_jobs=N_JOBS),
-                imblearn.under_sampling.CondensedNearestNeighbour(
-                    random_state=0, n_jobs=N_JOBS),
-                imblearn.under_sampling.EditedNearestNeighbours(
-                    random_state=0, n_jobs=N_JOBS),
-                imblearn.under_sampling.RepeatedEditedNearestNeighbours(
-                    random_state=0, n_jobs=N_JOBS),
+                imblearn.under_sampling.ClusterCentroids(random_state=0, n_jobs=N_JOBS),
+                imblearn.under_sampling.CondensedNearestNeighbour(random_state=0, n_jobs=N_JOBS),
+                imblearn.under_sampling.EditedNearestNeighbours(random_state=0, n_jobs=N_JOBS),
+                imblearn.under_sampling.RepeatedEditedNearestNeighbours(random_state=0, n_jobs=N_JOBS),
                 imblearn.under_sampling.AllKNN(random_state=0, n_jobs=N_JOBS),
-                imblearn.under_sampling.InstanceHardnessThreshold(
-                    random_state=0, n_jobs=N_JOBS),
-                imblearn.under_sampling.NearMiss(
-                    random_state=0, n_jobs=N_JOBS),
-                imblearn.under_sampling.NeighbourhoodCleaningRule(
-                    random_state=0, n_jobs=N_JOBS),
-                imblearn.under_sampling.OneSidedSelection(
-                    random_state=0, n_jobs=N_JOBS),
-                imblearn.under_sampling.RandomUnderSampler(
-                    random_state=0),
-                imblearn.under_sampling.TomekLinks(
-                    random_state=0, n_jobs=N_JOBS),
+                imblearn.under_sampling.InstanceHardnessThreshold(random_state=0, n_jobs=N_JOBS),
+                imblearn.under_sampling.NearMiss(random_state=0, n_jobs=N_JOBS),
+                imblearn.under_sampling.NeighbourhoodCleaningRule(random_state=0, n_jobs=N_JOBS),
+                imblearn.under_sampling.OneSidedSelection(random_state=0, n_jobs=N_JOBS),
+                imblearn.under_sampling.RandomUnderSampler(random_state=0),
+                imblearn.under_sampling.TomekLinks(random_state=0, n_jobs=N_JOBS),
                 imblearn.over_sampling.ADASYN(random_state=0, n_jobs=N_JOBS),
                 imblearn.over_sampling.RandomOverSampler(random_state=0),
                 imblearn.over_sampling.SMOTE(random_state=0, n_jobs=N_JOBS),
                 imblearn.over_sampling.SVMSMOTE(random_state=0, n_jobs=N_JOBS),
-                imblearn.over_sampling.BorderlineSMOTE(
-                    random_state=0, n_jobs=N_JOBS),
-                imblearn.over_sampling.SMOTENC(
-                    categorical_features=[], random_state=0, n_jobs=N_JOBS),
+                imblearn.over_sampling.BorderlineSMOTE(random_state=0, n_jobs=N_JOBS),
+                imblearn.over_sampling.SMOTENC(categorical_features=[], random_state=0, n_jobs=N_JOBS),
                 imblearn.combine.SMOTEENN(random_state=0),
-                imblearn.combine.SMOTETomek(random_state=0))
+                imblearn.combine.SMOTETomek(random_state=0),
+            )
             newlist = []
             for obj in ev:
                 if obj is None:
                     newlist.append(None)
-                elif obj == 'all_0':
+                elif obj == "all_0":
                     newlist.extend(preprocessings[0:35])
-                elif obj == 'sk_prep_all':      # no KernalCenter()
+                elif obj == "sk_prep_all":  # no KernalCenter()
                     newlist.extend(preprocessings[0:7])
-                elif obj == 'fs_all':
+                elif obj == "fs_all":
                     newlist.extend(preprocessings[7:14])
-                elif obj == 'decomp_all':
+                elif obj == "decomp_all":
                     newlist.extend(preprocessings[14:25])
-                elif obj == 'k_appr_all':
+                elif obj == "k_appr_all":
                     newlist.extend(preprocessings[25:29])
-                elif obj == 'reb_all':
+                elif obj == "reb_all":
                     newlist.extend(preprocessings[30:35])
-                elif obj == 'imb_all':
+                elif obj == "imb_all":
                     newlist.extend(preprocessings[35:54])
                 elif type(obj) is int and -1 < obj < len(preprocessings):
                     newlist.append(preprocessings[obj])
-                elif hasattr(obj, 'get_params'):       # user uploaded object
-                    if 'n_jobs' in obj.get_params():
+                elif hasattr(obj, "get_params"):  # user uploaded object
+                    if "n_jobs" in obj.get_params():
                         newlist.append(obj.set_params(n_jobs=N_JOBS))
                     else:
                         newlist.append(obj)
@@ -158,9 +160,17 @@
     return search_params
 
 
-def _handle_X_y(estimator, params, infile1, infile2, loaded_df={},
-                ref_seq=None, intervals=None, targets=None,
-                fasta_path=None):
+def _handle_X_y(
+    estimator,
+    params,
+    infile1,
+    infile2,
+    loaded_df={},
+    ref_seq=None,
+    intervals=None,
+    targets=None,
+    fasta_path=None,
+):
     """read inputs
 
     Params
@@ -192,15 +202,18 @@
     """
     estimator_params = estimator.get_params()
 
-    input_type = params['input_options']['selected_input']
+    input_type = params["input_options"]["selected_input"]
     # tabular input
-    if input_type == 'tabular':
-        header = 'infer' if params['input_options']['header1'] else None
-        column_option = (params['input_options']['column_selector_options_1']
-                         ['selected_column_selector_option'])
-        if column_option in ['by_index_number', 'all_but_by_index_number',
-                             'by_header_name', 'all_but_by_header_name']:
-            c = params['input_options']['column_selector_options_1']['col1']
+    if input_type == "tabular":
+        header = "infer" if params["input_options"]["header1"] else None
+        column_option = params["input_options"]["column_selector_options_1"]["selected_column_selector_option"]
+        if column_option in [
+            "by_index_number",
+            "all_but_by_index_number",
+            "by_header_name",
+            "all_but_by_header_name",
+        ]:
+            c = params["input_options"]["column_selector_options_1"]["col1"]
         else:
             c = None
 
@@ -209,25 +222,23 @@
         if df_key in loaded_df:
             infile1 = loaded_df[df_key]
 
-        df = pd.read_csv(infile1, sep='\t', header=header,
-                         parse_dates=True)
+        df = pd.read_csv(infile1, sep="\t", header=header, parse_dates=True)
         loaded_df[df_key] = df
 
         X = read_columns(df, c=c, c_option=column_option).astype(float)
     # sparse input
-    elif input_type == 'sparse':
-        X = mmread(open(infile1, 'r'))
+    elif input_type == "sparse":
+        X = mmread(open(infile1, "r"))
 
     # fasta_file input
-    elif input_type == 'seq_fasta':
-        pyfaidx = get_module('pyfaidx')
+    elif input_type == "seq_fasta":
+        pyfaidx = get_module("pyfaidx")
         sequences = pyfaidx.Fasta(fasta_path)
         n_seqs = len(sequences.keys())
         X = np.arange(n_seqs)[:, np.newaxis]
         for param in estimator_params.keys():
-            if param.endswith('fasta_path'):
-                estimator.set_params(
-                    **{param: fasta_path})
+            if param.endswith("fasta_path"):
+                estimator.set_params(**{param: fasta_path})
                 break
         else:
             raise ValueError(
@@ -236,25 +247,29 @@
                 "KerasGBatchClassifier with "
                 "FastaDNABatchGenerator/FastaProteinBatchGenerator "
                 "or having GenomeOneHotEncoder/ProteinOneHotEncoder "
-                "in pipeline!")
+                "in pipeline!"
+            )
 
-    elif input_type == 'refseq_and_interval':
+    elif input_type == "refseq_and_interval":
         path_params = {
-            'data_batch_generator__ref_genome_path': ref_seq,
-            'data_batch_generator__intervals_path': intervals,
-            'data_batch_generator__target_path': targets
+            "data_batch_generator__ref_genome_path": ref_seq,
+            "data_batch_generator__intervals_path": intervals,
+            "data_batch_generator__target_path": targets,
         }
         estimator.set_params(**path_params)
         n_intervals = sum(1 for line in open(intervals))
         X = np.arange(n_intervals)[:, np.newaxis]
 
     # Get target y
-    header = 'infer' if params['input_options']['header2'] else None
-    column_option = (params['input_options']['column_selector_options_2']
-                     ['selected_column_selector_option2'])
-    if column_option in ['by_index_number', 'all_but_by_index_number',
-                         'by_header_name', 'all_but_by_header_name']:
-        c = params['input_options']['column_selector_options_2']['col2']
+    header = "infer" if params["input_options"]["header2"] else None
+    column_option = params["input_options"]["column_selector_options_2"]["selected_column_selector_option2"]
+    if column_option in [
+        "by_index_number",
+        "all_but_by_index_number",
+        "by_header_name",
+        "all_but_by_header_name",
+    ]:
+        c = params["input_options"]["column_selector_options_2"]["col2"]
     else:
         c = None
 
@@ -262,30 +277,21 @@
     if df_key in loaded_df:
         infile2 = loaded_df[df_key]
     else:
-        infile2 = pd.read_csv(infile2, sep='\t',
-                              header=header, parse_dates=True)
+        infile2 = pd.read_csv(infile2, sep="\t", header=header, parse_dates=True)
         loaded_df[df_key] = infile2
 
-    y = read_columns(
-            infile2,
-            c=c,
-            c_option=column_option,
-            sep='\t',
-            header=header,
-            parse_dates=True)
+    y = read_columns(infile2, c=c, c_option=column_option, sep="\t", header=header, parse_dates=True)
     if len(y.shape) == 2 and y.shape[1] == 1:
         y = y.ravel()
-    if input_type == 'refseq_and_interval':
-        estimator.set_params(
-            data_batch_generator__features=y.ravel().tolist())
+    if input_type == "refseq_and_interval":
+        estimator.set_params(data_batch_generator__features=y.ravel().tolist())
         y = None
     # end y
 
     return estimator, X, y
 
 
-def _do_outer_cv(searcher, X, y, outer_cv, scoring, error_score='raise',
-                 outfile=None):
+def _do_outer_cv(searcher, X, y, outer_cv, scoring, error_score="raise", outfile=None):
     """Do outer cross-validation for nested CV
 
     Parameters
@@ -305,21 +311,31 @@
     outfile : str
         File path to store the restuls
     """
-    if error_score == 'raise':
+    if error_score == "raise":
         rval = cross_validate(
-            searcher, X, y, scoring=scoring,
-            cv=outer_cv, n_jobs=N_JOBS, verbose=0,
-            error_score=error_score)
+            searcher,
+            X,
+            y,
+            scoring=scoring,
+            cv=outer_cv,
+            n_jobs=N_JOBS,
+            verbose=0,
+            error_score=error_score,
+        )
     else:
-        warnings.simplefilter('always', FitFailedWarning)
+        warnings.simplefilter("always", FitFailedWarning)
         with warnings.catch_warnings(record=True) as w:
             try:
                 rval = cross_validate(
-                    searcher, X, y,
+                    searcher,
+                    X,
+                    y,
                     scoring=scoring,
-                    cv=outer_cv, n_jobs=N_JOBS,
+                    cv=outer_cv,
+                    n_jobs=N_JOBS,
                     verbose=0,
-                    error_score=error_score)
+                    error_score=error_score,
+                )
             except ValueError:
                 pass
             for warning in w:
@@ -327,55 +343,57 @@
 
     keys = list(rval.keys())
     for k in keys:
-        if k.startswith('test'):
-            rval['mean_' + k] = np.mean(rval[k])
-            rval['std_' + k] = np.std(rval[k])
-        if k.endswith('time'):
+        if k.startswith("test"):
+            rval["mean_" + k] = np.mean(rval[k])
+            rval["std_" + k] = np.std(rval[k])
+        if k.endswith("time"):
             rval.pop(k)
     rval = pd.DataFrame(rval)
     rval = rval[sorted(rval.columns)]
-    rval.to_csv(path_or_buf=outfile, sep='\t', header=True, index=False)
+    rval.to_csv(path_or_buf=outfile, sep="\t", header=True, index=False)
 
 
-def _do_train_test_split_val(searcher, X, y, params, error_score='raise',
-                             primary_scoring=None, groups=None,
-                             outfile=None):
-    """ do train test split, searchCV validates on the train and then use
+def _do_train_test_split_val(
+    searcher,
+    X,
+    y,
+    params,
+    error_score="raise",
+    primary_scoring=None,
+    groups=None,
+    outfile=None,
+):
+    """do train test split, searchCV validates on the train and then use
     the best_estimator_ to evaluate on the test
 
     Returns
     --------
     Fitted SearchCV object
     """
-    train_test_split = try_get_attr(
-        'galaxy_ml.model_validations', 'train_test_split')
-    split_options = params['outer_split']
+    train_test_split = try_get_attr("galaxy_ml.model_validations", "train_test_split")
+    split_options = params["outer_split"]
 
     # splits
-    if split_options['shuffle'] == 'stratified':
-        split_options['labels'] = y
+    if split_options["shuffle"] == "stratified":
+        split_options["labels"] = y
         X, X_test, y, y_test = train_test_split(X, y, **split_options)
-    elif split_options['shuffle'] == 'group':
+    elif split_options["shuffle"] == "group":
         if groups is None:
-            raise ValueError("No group based CV option was choosen for "
-                             "group shuffle!")
-        split_options['labels'] = groups
+            raise ValueError("No group based CV option was choosen for " "group shuffle!")
+        split_options["labels"] = groups
         if y is None:
-            X, X_test, groups, _ =\
-                train_test_split(X, groups, **split_options)
+            X, X_test, groups, _ = train_test_split(X, groups, **split_options)
         else:
-            X, X_test, y, y_test, groups, _ =\
-                train_test_split(X, y, groups, **split_options)
+            X, X_test, y, y_test, groups, _ = train_test_split(X, y, groups, **split_options)
     else:
-        if split_options['shuffle'] == 'None':
-            split_options['shuffle'] = None
-        X, X_test, y, y_test =\
-            train_test_split(X, y, **split_options)
+        if split_options["shuffle"] == "None":
+            split_options["shuffle"] = None
+        X, X_test, y, y_test = train_test_split(X, y, **split_options)
 
-    if error_score == 'raise':
+    if error_score == "raise":
         searcher.fit(X, y, groups=groups)
     else:
-        warnings.simplefilter('always', FitFailedWarning)
+        warnings.simplefilter("always", FitFailedWarning)
         with warnings.catch_warnings(record=True) as w:
             try:
                 searcher.fit(X, y, groups=groups)
@@ -390,33 +408,38 @@
     else:
         is_multimetric = False
 
-    best_estimator_ = getattr(searcher, 'best_estimator_')
+    best_estimator_ = getattr(searcher, "best_estimator_")
 
     # TODO Solve deep learning models in pipeline
-    if best_estimator_.__class__.__name__ == 'KerasGBatchClassifier':
-        test_score = best_estimator_.evaluate(
-            X_test, scorer=scorer_, is_multimetric=is_multimetric)
+    if best_estimator_.__class__.__name__ == "KerasGBatchClassifier":
+        test_score = best_estimator_.evaluate(X_test, scorer=scorer_, is_multimetric=is_multimetric)
     else:
-        test_score = _score(best_estimator_, X_test,
-                            y_test, scorer_,
-                            is_multimetric=is_multimetric)
+        test_score = _score(best_estimator_, X_test, y_test, scorer_, is_multimetric=is_multimetric)
 
     if not is_multimetric:
         test_score = {primary_scoring: test_score}
     for key, value in test_score.items():
         test_score[key] = [value]
     result_df = pd.DataFrame(test_score)
-    result_df.to_csv(path_or_buf=outfile, sep='\t', header=True,
-                     index=False)
+    result_df.to_csv(path_or_buf=outfile, sep="\t", header=True, index=False)
 
     return searcher
 
 
-def main(inputs, infile_estimator, infile1, infile2,
-         outfile_result, outfile_object=None,
-         outfile_weights=None, groups=None,
-         ref_seq=None, intervals=None, targets=None,
-         fasta_path=None):
+def main(
+    inputs,
+    infile_estimator,
+    infile1,
+    infile2,
+    outfile_result,
+    outfile_object=None,
+    outfile_weights=None,
+    groups=None,
+    ref_seq=None,
+    intervals=None,
+    targets=None,
+    fasta_path=None,
+):
     """
     Parameter
     ---------
@@ -456,154 +479,174 @@
     fasta_path : str
         File path to dataset containing fasta file
     """
-    warnings.simplefilter('ignore')
+    warnings.simplefilter("ignore")
 
     # store read dataframe object
     loaded_df = {}
 
-    with open(inputs, 'r') as param_handler:
+    with open(inputs, "r") as param_handler:
         params = json.load(param_handler)
 
     # Override the refit parameter
-    params['search_schemes']['options']['refit'] = True \
-        if params['save'] != 'nope' else False
+    params["search_schemes"]["options"]["refit"] = True if params["save"] != "nope" else False
 
-    with open(infile_estimator, 'rb') as estimator_handler:
+    with open(infile_estimator, "rb") as estimator_handler:
         estimator = load_model(estimator_handler)
 
-    optimizer = params['search_schemes']['selected_search_scheme']
+    optimizer = params["search_schemes"]["selected_search_scheme"]
     optimizer = getattr(model_selection, optimizer)
 
     # handle gridsearchcv options
-    options = params['search_schemes']['options']
+    options = params["search_schemes"]["options"]
 
     if groups:
-        header = 'infer' if (options['cv_selector']['groups_selector']
-                                    ['header_g']) else None
-        column_option = (options['cv_selector']['groups_selector']
-                                ['column_selector_options_g']
-                                ['selected_column_selector_option_g'])
-        if column_option in ['by_index_number', 'all_but_by_index_number',
-                             'by_header_name', 'all_but_by_header_name']:
-            c = (options['cv_selector']['groups_selector']
-                        ['column_selector_options_g']['col_g'])
+        header = "infer" if (options["cv_selector"]["groups_selector"]["header_g"]) else None
+        column_option = options["cv_selector"]["groups_selector"]["column_selector_options_g"][
+            "selected_column_selector_option_g"
+        ]
+        if column_option in [
+            "by_index_number",
+            "all_but_by_index_number",
+            "by_header_name",
+            "all_but_by_header_name",
+        ]:
+            c = options["cv_selector"]["groups_selector"]["column_selector_options_g"]["col_g"]
         else:
             c = None
 
         df_key = groups + repr(header)
 
-        groups = pd.read_csv(groups, sep='\t', header=header,
-                             parse_dates=True)
+        groups = pd.read_csv(groups, sep="\t", header=header, parse_dates=True)
         loaded_df[df_key] = groups
 
         groups = read_columns(
-                groups,
-                c=c,
-                c_option=column_option,
-                sep='\t',
-                header=header,
-                parse_dates=True)
+            groups,
+            c=c,
+            c_option=column_option,
+            sep="\t",
+            header=header,
+            parse_dates=True,
+        )
         groups = groups.ravel()
-        options['cv_selector']['groups_selector'] = groups
+        options["cv_selector"]["groups_selector"] = groups
 
-    splitter, groups = get_cv(options.pop('cv_selector'))
-    options['cv'] = splitter
-    primary_scoring = options['scoring']['primary_scoring']
-    options['scoring'] = get_scoring(options['scoring'])
-    if options['error_score']:
-        options['error_score'] = 'raise'
+    splitter, groups = get_cv(options.pop("cv_selector"))
+    options["cv"] = splitter
+    primary_scoring = options["scoring"]["primary_scoring"]
+    # get_scoring() expects secondary_scoring to be a comma separated string (not a list)
+    # Check if secondary_scoring is specified
+    secondary_scoring = options["scoring"].get("secondary_scoring", None)
+    if secondary_scoring is not None:
+        # If secondary_scoring is specified, convert the list into comman separated string
+        options["scoring"]["secondary_scoring"] = ",".join(options["scoring"]["secondary_scoring"])
+    options["scoring"] = get_scoring(options["scoring"])
+    if options["error_score"]:
+        options["error_score"] = "raise"
     else:
-        options['error_score'] = np.NaN
-    if options['refit'] and isinstance(options['scoring'], dict):
-        options['refit'] = primary_scoring
-    if 'pre_dispatch' in options and options['pre_dispatch'] == '':
-        options['pre_dispatch'] = None
+        options["error_score"] = np.NaN
+    if options["refit"] and isinstance(options["scoring"], dict):
+        options["refit"] = primary_scoring
+    if "pre_dispatch" in options and options["pre_dispatch"] == "":
+        options["pre_dispatch"] = None
 
-    params_builder = params['search_schemes']['search_params_builder']
+    params_builder = params["search_schemes"]["search_params_builder"]
     param_grid = _eval_search_params(params_builder)
 
     estimator = clean_params(estimator)
 
     # save the SearchCV object without fit
-    if params['save'] == 'save_no_fit':
+    if params["save"] == "save_no_fit":
         searcher = optimizer(estimator, param_grid, **options)
         print(searcher)
-        with open(outfile_object, 'wb') as output_handler:
-            pickle.dump(searcher, output_handler,
-                        pickle.HIGHEST_PROTOCOL)
+        with open(outfile_object, "wb") as output_handler:
+            pickle.dump(searcher, output_handler, pickle.HIGHEST_PROTOCOL)
         return 0
 
     # read inputs and loads new attributes, like paths
-    estimator, X, y = _handle_X_y(estimator, params, infile1, infile2,
-                                  loaded_df=loaded_df, ref_seq=ref_seq,
-                                  intervals=intervals, targets=targets,
-                                  fasta_path=fasta_path)
+    estimator, X, y = _handle_X_y(
+        estimator,
+        params,
+        infile1,
+        infile2,
+        loaded_df=loaded_df,
+        ref_seq=ref_seq,
+        intervals=intervals,
+        targets=targets,
+        fasta_path=fasta_path,
+    )
 
     # cache iraps_core fits could increase search speed significantly
     memory = joblib.Memory(location=CACHE_DIR, verbose=0)
     main_est = get_main_estimator(estimator)
-    if main_est.__class__.__name__ == 'IRAPSClassifier':
+    if main_est.__class__.__name__ == "IRAPSClassifier":
         main_est.set_params(memory=memory)
 
     searcher = optimizer(estimator, param_grid, **options)
 
-    split_mode = params['outer_split'].pop('split_mode')
+    split_mode = params["outer_split"].pop("split_mode")
 
-    if split_mode == 'nested_cv':
+    if split_mode == "nested_cv":
         # make sure refit is choosen
         # this could be True for sklearn models, but not the case for
         # deep learning models
-        if not options['refit'] and \
-                not all(hasattr(estimator, attr)
-                        for attr in ('config', 'model_type')):
+        if not options["refit"] and not all(hasattr(estimator, attr) for attr in ("config", "model_type")):
             warnings.warn("Refit is change to `True` for nested validation!")
-            setattr(searcher, 'refit', True)
+            setattr(searcher, "refit", True)
 
-        outer_cv, _ = get_cv(params['outer_split']['cv_selector'])
+        outer_cv, _ = get_cv(params["outer_split"]["cv_selector"])
         # nested CV, outer cv using cross_validate
-        if options['error_score'] == 'raise':
+        if options["error_score"] == "raise":
             rval = cross_validate(
-                searcher, X, y, scoring=options['scoring'],
-                cv=outer_cv, n_jobs=N_JOBS,
-                verbose=options['verbose'],
-                return_estimator=(params['save'] == 'save_estimator'),
-                error_score=options['error_score'],
-                return_train_score=True)
+                searcher,
+                X,
+                y,
+                scoring=options["scoring"],
+                cv=outer_cv,
+                n_jobs=N_JOBS,
+                verbose=options["verbose"],
+                return_estimator=(params["save"] == "save_estimator"),
+                error_score=options["error_score"],
+                return_train_score=True,
+            )
         else:
-            warnings.simplefilter('always', FitFailedWarning)
+            warnings.simplefilter("always", FitFailedWarning)
             with warnings.catch_warnings(record=True) as w:
                 try:
                     rval = cross_validate(
-                        searcher, X, y,
-                        scoring=options['scoring'],
-                        cv=outer_cv, n_jobs=N_JOBS,
-                        verbose=options['verbose'],
-                        return_estimator=(params['save'] == 'save_estimator'),
-                        error_score=options['error_score'],
-                        return_train_score=True)
+                        searcher,
+                        X,
+                        y,
+                        scoring=options["scoring"],
+                        cv=outer_cv,
+                        n_jobs=N_JOBS,
+                        verbose=options["verbose"],
+                        return_estimator=(params["save"] == "save_estimator"),
+                        error_score=options["error_score"],
+                        return_train_score=True,
+                    )
                 except ValueError:
                     pass
                 for warning in w:
                     print(repr(warning.message))
 
-        fitted_searchers = rval.pop('estimator', [])
+        fitted_searchers = rval.pop("estimator", [])
         if fitted_searchers:
             import os
+
             pwd = os.getcwd()
-            save_dir = os.path.join(pwd, 'cv_results_in_folds')
+            save_dir = os.path.join(pwd, "cv_results_in_folds")
             try:
                 os.mkdir(save_dir)
                 for idx, obj in enumerate(fitted_searchers):
-                    target_name = 'cv_results_' + '_' + 'split%d' % idx
+                    target_name = "cv_results_" + "_" + "split%d" % idx
                     target_path = os.path.join(pwd, save_dir, target_name)
-                    cv_results_ = getattr(obj, 'cv_results_', None)
+                    cv_results_ = getattr(obj, "cv_results_", None)
                     if not cv_results_:
                         print("%s is not available" % target_name)
                         continue
                     cv_results_ = pd.DataFrame(cv_results_)
                     cv_results_ = cv_results_[sorted(cv_results_.columns)]
-                    cv_results_.to_csv(target_path, sep='\t', header=True,
-                                       index=False)
+                    cv_results_.to_csv(target_path, sep="\t", header=True, index=False)
             except Exception as e:
                 print(e)
             finally:
@@ -611,18 +654,14 @@
 
         keys = list(rval.keys())
         for k in keys:
-            if k.startswith('test'):
-                rval['mean_' + k] = np.mean(rval[k])
-                rval['std_' + k] = np.std(rval[k])
-            if k.endswith('time'):
+            if k.startswith("test"):
+                rval["mean_" + k] = np.mean(rval[k])
+                rval["std_" + k] = np.std(rval[k])
+            if k.endswith("time"):
                 rval.pop(k)
         rval = pd.DataFrame(rval)
         rval = rval[sorted(rval.columns)]
-        rval.to_csv(path_or_buf=outfile_result, sep='\t', header=True,
-                    index=False)
-
-        return 0
-
+        rval.to_csv(path_or_buf=outfile_result, sep="\t", header=True, index=False)
         # deprecate train test split mode
         """searcher = _do_train_test_split_val(
             searcher, X, y, params,
@@ -630,14 +669,15 @@
             error_score=options['error_score'],
             groups=groups,
             outfile=outfile_result)"""
+        return 0
 
     # no outer split
     else:
         searcher.set_params(n_jobs=N_JOBS)
-        if options['error_score'] == 'raise':
+        if options["error_score"] == "raise":
             searcher.fit(X, y, groups=groups)
         else:
-            warnings.simplefilter('always', FitFailedWarning)
+            warnings.simplefilter("always", FitFailedWarning)
             with warnings.catch_warnings(record=True) as w:
                 try:
                     searcher.fit(X, y, groups=groups)
@@ -648,18 +688,19 @@
 
         cv_results = pd.DataFrame(searcher.cv_results_)
         cv_results = cv_results[sorted(cv_results.columns)]
-        cv_results.to_csv(path_or_buf=outfile_result, sep='\t',
-                          header=True, index=False)
+        cv_results.to_csv(path_or_buf=outfile_result, sep="\t", header=True, index=False)
 
     memory.clear(warn=False)
 
     # output best estimator, and weights if applicable
     if outfile_object:
-        best_estimator_ = getattr(searcher, 'best_estimator_', None)
+        best_estimator_ = getattr(searcher, "best_estimator_", None)
         if not best_estimator_:
-            warnings.warn("GridSearchCV object has no attribute "
-                          "'best_estimator_', because either it's "
-                          "nested gridsearch or `refit` is False!")
+            warnings.warn(
+                "GridSearchCV object has no attribute "
+                "'best_estimator_', because either it's "
+                "nested gridsearch or `refit` is False!"
+            )
             return
 
         # clean prams
@@ -667,24 +708,22 @@
 
         main_est = get_main_estimator(best_estimator_)
 
-        if hasattr(main_est, 'model_') \
-                and hasattr(main_est, 'save_weights'):
+        if hasattr(main_est, "model_") and hasattr(main_est, "save_weights"):
             if outfile_weights:
                 main_est.save_weights(outfile_weights)
             del main_est.model_
             del main_est.fit_params
             del main_est.model_class_
             del main_est.validation_data
-            if getattr(main_est, 'data_generator_', None):
+            if getattr(main_est, "data_generator_", None):
                 del main_est.data_generator_
 
-        with open(outfile_object, 'wb') as output_handler:
+        with open(outfile_object, "wb") as output_handler:
             print("Best estimator is saved: %s " % repr(best_estimator_))
-            pickle.dump(best_estimator_, output_handler,
-                        pickle.HIGHEST_PROTOCOL)
+            pickle.dump(best_estimator_, output_handler, pickle.HIGHEST_PROTOCOL)
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     aparser = argparse.ArgumentParser()
     aparser.add_argument("-i", "--inputs", dest="inputs", required=True)
     aparser.add_argument("-e", "--estimator", dest="infile_estimator")
@@ -700,8 +739,17 @@
     aparser.add_argument("-f", "--fasta_path", dest="fasta_path")
     args = aparser.parse_args()
 
-    main(args.inputs, args.infile_estimator, args.infile1, args.infile2,
-         args.outfile_result, outfile_object=args.outfile_object,
-         outfile_weights=args.outfile_weights, groups=args.groups,
-         ref_seq=args.ref_seq, intervals=args.intervals,
-         targets=args.targets, fasta_path=args.fasta_path)
+    main(
+        args.inputs,
+        args.infile_estimator,
+        args.infile1,
+        args.infile2,
+        args.outfile_result,
+        outfile_object=args.outfile_object,
+        outfile_weights=args.outfile_weights,
+        groups=args.groups,
+        ref_seq=args.ref_seq,
+        intervals=args.intervals,
+        targets=args.targets,
+        fasta_path=args.fasta_path,
+    )
--- a/simple_model_fit.py	Thu Oct 01 19:54:05 2020 +0000
+++ b/simple_model_fit.py	Tue Apr 13 17:21:05 2021 +0000
@@ -4,10 +4,11 @@
 import pickle
 
 from galaxy_ml.utils import load_model, read_columns
+from scipy.io import mmread
 from sklearn.pipeline import Pipeline
 
 
-N_JOBS = int(__import__('os').environ.get('GALAXY_SLOTS', 1))
+N_JOBS = int(__import__("os").environ.get("GALAXY_SLOTS", 1))
 
 
 # TODO import from galaxy_ml.utils in future versions
@@ -20,33 +21,35 @@
     ------
     Cleaned estimator object
     """
-    ALLOWED_CALLBACKS = ('EarlyStopping', 'TerminateOnNaN',
-                         'ReduceLROnPlateau', 'CSVLogger', 'None')
+    ALLOWED_CALLBACKS = (
+        "EarlyStopping",
+        "TerminateOnNaN",
+        "ReduceLROnPlateau",
+        "CSVLogger",
+        "None",
+    )
 
     estimator_params = estimator.get_params()
 
     for name, p in estimator_params.items():
         # all potential unauthorized file write
-        if name == 'memory' or name.endswith('__memory') \
-                or name.endswith('_path'):
+        if name == "memory" or name.endswith("__memory") or name.endswith("_path"):
             new_p = {name: None}
             estimator.set_params(**new_p)
-        elif n_jobs is not None and (name == 'n_jobs' or
-                                     name.endswith('__n_jobs')):
+        elif n_jobs is not None and (name == 'n_jobs' or name.endswith('__n_jobs')):
             new_p = {name: n_jobs}
             estimator.set_params(**new_p)
-        elif name.endswith('callbacks'):
+        elif name.endswith("callbacks"):
             for cb in p:
-                cb_type = cb['callback_selection']['callback_type']
+                cb_type = cb["callback_selection"]["callback_type"]
                 if cb_type not in ALLOWED_CALLBACKS:
-                    raise ValueError(
-                        "Prohibited callback type: %s!" % cb_type)
+                    raise ValueError("Prohibited callback type: %s!" % cb_type)
 
     return estimator
 
 
 def _get_X_y(params, infile1, infile2):
-    """ read from inputs and output X and y
+    """read from inputs and output X and y
 
     Parameters
     ----------
@@ -61,35 +64,40 @@
     # store read dataframe object
     loaded_df = {}
 
-    input_type = params['input_options']['selected_input']
+    input_type = params["input_options"]["selected_input"]
     # tabular input
-    if input_type == 'tabular':
-        header = 'infer' if params['input_options']['header1'] else None
-        column_option = (params['input_options']['column_selector_options_1']
-                         ['selected_column_selector_option'])
-        if column_option in ['by_index_number', 'all_but_by_index_number',
-                             'by_header_name', 'all_but_by_header_name']:
-            c = params['input_options']['column_selector_options_1']['col1']
+    if input_type == "tabular":
+        header = "infer" if params["input_options"]["header1"] else None
+        column_option = params["input_options"]["column_selector_options_1"]["selected_column_selector_option"]
+        if column_option in [
+            "by_index_number",
+            "all_but_by_index_number",
+            "by_header_name",
+            "all_but_by_header_name",
+        ]:
+            c = params["input_options"]["column_selector_options_1"]["col1"]
         else:
             c = None
 
         df_key = infile1 + repr(header)
-        df = pd.read_csv(infile1, sep='\t', header=header,
-                         parse_dates=True)
+        df = pd.read_csv(infile1, sep="\t", header=header, parse_dates=True)
         loaded_df[df_key] = df
 
         X = read_columns(df, c=c, c_option=column_option).astype(float)
     # sparse input
-    elif input_type == 'sparse':
-        X = mmread(open(infile1, 'r'))
+    elif input_type == "sparse":
+        X = mmread(open(infile1, "r"))
 
     # Get target y
-    header = 'infer' if params['input_options']['header2'] else None
-    column_option = (params['input_options']['column_selector_options_2']
-                     ['selected_column_selector_option2'])
-    if column_option in ['by_index_number', 'all_but_by_index_number',
-                         'by_header_name', 'all_but_by_header_name']:
-        c = params['input_options']['column_selector_options_2']['col2']
+    header = "infer" if params["input_options"]["header2"] else None
+    column_option = params["input_options"]["column_selector_options_2"]["selected_column_selector_option2"]
+    if column_option in [
+        "by_index_number",
+        "all_but_by_index_number",
+        "by_header_name",
+        "all_but_by_header_name",
+    ]:
+        c = params["input_options"]["column_selector_options_2"]["col2"]
     else:
         c = None
 
@@ -97,26 +105,23 @@
     if df_key in loaded_df:
         infile2 = loaded_df[df_key]
     else:
-        infile2 = pd.read_csv(infile2, sep='\t',
-                              header=header, parse_dates=True)
+        infile2 = pd.read_csv(infile2, sep="\t", header=header, parse_dates=True)
         loaded_df[df_key] = infile2
 
-    y = read_columns(
-            infile2,
-            c=c,
-            c_option=column_option,
-            sep='\t',
-            header=header,
-            parse_dates=True)
+    y = read_columns(infile2,
+                     c=c,
+                     c_option=column_option,
+                     sep='\t',
+                     header=header,
+                     parse_dates=True)
     if len(y.shape) == 2 and y.shape[1] == 1:
         y = y.ravel()
 
     return X, y
 
 
-def main(inputs, infile_estimator, infile1, infile2, out_object,
-         out_weights=None):
-    """ main
+def main(inputs, infile_estimator, infile1, infile2, out_object, out_weights=None):
+    """main
 
     Parameters
     ----------
@@ -139,38 +144,37 @@
         File path for output of weights
 
     """
-    with open(inputs, 'r') as param_handler:
+    with open(inputs, "r") as param_handler:
         params = json.load(param_handler)
 
     # load model
-    with open(infile_estimator, 'rb') as est_handler:
+    with open(infile_estimator, "rb") as est_handler:
         estimator = load_model(est_handler)
     estimator = clean_params(estimator, n_jobs=N_JOBS)
 
     X_train, y_train = _get_X_y(params, infile1, infile2)
 
     estimator.fit(X_train, y_train)
-    
+
     main_est = estimator
     if isinstance(main_est, Pipeline):
         main_est = main_est.steps[-1][-1]
-    if hasattr(main_est, 'model_') \
-            and hasattr(main_est, 'save_weights'):
+    if hasattr(main_est, "model_") and hasattr(main_est, "save_weights"):
         if out_weights:
             main_est.save_weights(out_weights)
         del main_est.model_
         del main_est.fit_params
         del main_est.model_class_
-        del main_est.validation_data
-        if getattr(main_est, 'data_generator_', None):
+        if getattr(main_est, "validation_data", None):
+            del main_est.validation_data
+        if getattr(main_est, "data_generator_", None):
             del main_est.data_generator_
 
-    with open(out_object, 'wb') as output_handler:
-        pickle.dump(estimator, output_handler,
-                    pickle.HIGHEST_PROTOCOL)
+    with open(out_object, "wb") as output_handler:
+        pickle.dump(estimator, output_handler, pickle.HIGHEST_PROTOCOL)
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     aparser = argparse.ArgumentParser()
     aparser.add_argument("-i", "--inputs", dest="inputs", required=True)
     aparser.add_argument("-X", "--infile_estimator", dest="infile_estimator")
@@ -180,5 +184,11 @@
     aparser.add_argument("-t", "--out_weights", dest="out_weights")
     args = aparser.parse_args()
 
-    main(args.inputs, args.infile_estimator, args.infile1,
-         args.infile2, args.out_object, args.out_weights)
+    main(
+        args.inputs,
+        args.infile_estimator,
+        args.infile1,
+        args.infile2,
+        args.out_object,
+        args.out_weights,
+    )
--- a/stacking_ensembles.py	Thu Oct 01 19:54:05 2020 +0000
+++ b/stacking_ensembles.py	Tue Apr 13 17:21:05 2021 +0000
@@ -5,22 +5,17 @@
 import mlxtend.classifier
 import pandas as pd
 import pickle
-import sklearn
 import sys
 import warnings
-from sklearn import ensemble
-
-from galaxy_ml.utils import (load_model, get_cv, get_estimator,
-                             get_search_params)
+from galaxy_ml.utils import load_model, get_cv, get_estimator, get_search_params
 
 
-warnings.filterwarnings('ignore')
+warnings.filterwarnings("ignore")
 
-N_JOBS = int(__import__('os').environ.get('GALAXY_SLOTS', 1))
+N_JOBS = int(__import__("os").environ.get("GALAXY_SLOTS", 1))
 
 
-def main(inputs_path, output_obj, base_paths=None, meta_path=None,
-         outfile_params=None):
+def main(inputs_path, output_obj, base_paths=None, meta_path=None, outfile_params=None):
     """
     Parameter
     ---------
@@ -39,87 +34,79 @@
     outfile_params : str
         File path for params output
     """
-    with open(inputs_path, 'r') as param_handler:
+    with open(inputs_path, "r") as param_handler:
         params = json.load(param_handler)
 
-    estimator_type = params['algo_selection']['estimator_type']
+    estimator_type = params["algo_selection"]["estimator_type"]
     # get base estimators
     base_estimators = []
-    for idx, base_file in enumerate(base_paths.split(',')):
-        if base_file and base_file != 'None':
-            with open(base_file, 'rb') as handler:
+    for idx, base_file in enumerate(base_paths.split(",")):
+        if base_file and base_file != "None":
+            with open(base_file, "rb") as handler:
                 model = load_model(handler)
         else:
-            estimator_json = (params['base_est_builder'][idx]
-                              ['estimator_selector'])
+            estimator_json = params["base_est_builder"][idx]["estimator_selector"]
             model = get_estimator(estimator_json)
 
-        if estimator_type.startswith('sklearn'):
+        if estimator_type.startswith("sklearn"):
             named = model.__class__.__name__.lower()
-            named = 'base_%d_%s' % (idx, named)
+            named = "base_%d_%s" % (idx, named)
             base_estimators.append((named, model))
         else:
             base_estimators.append(model)
 
     # get meta estimator, if applicable
-    if estimator_type.startswith('mlxtend'):
+    if estimator_type.startswith("mlxtend"):
         if meta_path:
-            with open(meta_path, 'rb') as f:
+            with open(meta_path, "rb") as f:
                 meta_estimator = load_model(f)
         else:
-            estimator_json = (params['algo_selection']
-                              ['meta_estimator']['estimator_selector'])
+            estimator_json = params["algo_selection"]["meta_estimator"]["estimator_selector"]
             meta_estimator = get_estimator(estimator_json)
 
-    options = params['algo_selection']['options']
+    options = params["algo_selection"]["options"]
 
-    cv_selector = options.pop('cv_selector', None)
+    cv_selector = options.pop("cv_selector", None)
     if cv_selector:
-        splitter, groups = get_cv(cv_selector)
-        options['cv'] = splitter
+        splitter, _groups = get_cv(cv_selector)
+        options["cv"] = splitter
         # set n_jobs
-        options['n_jobs'] = N_JOBS
+        options["n_jobs"] = N_JOBS
 
-    weights = options.pop('weights', None)
+    weights = options.pop("weights", None)
     if weights:
         weights = ast.literal_eval(weights)
         if weights:
-            options['weights'] = weights
+            options["weights"] = weights
 
-    mod_and_name = estimator_type.split('_')
+    mod_and_name = estimator_type.split("_")
     mod = sys.modules[mod_and_name[0]]
     klass = getattr(mod, mod_and_name[1])
 
-    if estimator_type.startswith('sklearn'):
-        options['n_jobs'] = N_JOBS
+    if estimator_type.startswith("sklearn"):
+        options["n_jobs"] = N_JOBS
         ensemble_estimator = klass(base_estimators, **options)
 
     elif mod == mlxtend.classifier:
-        ensemble_estimator = klass(
-            classifiers=base_estimators,
-            meta_classifier=meta_estimator,
-            **options)
+        ensemble_estimator = klass(classifiers=base_estimators, meta_classifier=meta_estimator, **options)
 
     else:
-        ensemble_estimator = klass(
-            regressors=base_estimators,
-            meta_regressor=meta_estimator,
-            **options)
+        ensemble_estimator = klass(regressors=base_estimators, meta_regressor=meta_estimator, **options)
 
     print(ensemble_estimator)
     for base_est in base_estimators:
         print(base_est)
 
-    with open(output_obj, 'wb') as out_handler:
+    with open(output_obj, "wb") as out_handler:
         pickle.dump(ensemble_estimator, out_handler, pickle.HIGHEST_PROTOCOL)
 
-    if params['get_params'] and outfile_params:
+    if params["get_params"] and outfile_params:
         results = get_search_params(ensemble_estimator)
-        df = pd.DataFrame(results, columns=['', 'Parameter', 'Value'])
-        df.to_csv(outfile_params, sep='\t', index=False)
+        df = pd.DataFrame(results, columns=["", "Parameter", "Value"])
+        df.to_csv(outfile_params, sep="\t", index=False)
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     aparser = argparse.ArgumentParser()
     aparser.add_argument("-b", "--bases", dest="bases")
     aparser.add_argument("-m", "--meta", dest="meta")
@@ -128,5 +115,10 @@
     aparser.add_argument("-p", "--outfile_params", dest="outfile_params")
     args = aparser.parse_args()
 
-    main(args.inputs, args.outfile, base_paths=args.bases,
-         meta_path=args.meta, outfile_params=args.outfile_params)
+    main(
+        args.inputs,
+        args.outfile,
+        base_paths=args.bases,
+        meta_path=args.meta,
+        outfile_params=args.outfile_params,
+    )
--- a/stacking_ensembles.xml	Thu Oct 01 19:54:05 2020 +0000
+++ b/stacking_ensembles.xml	Tue Apr 13 17:21:05 2021 +0000
@@ -1,10 +1,10 @@
-<tool id="sklearn_stacking_ensemble_models" name="Stacking Ensembles" version="@VERSION@">
+<tool id="sklearn_stacking_ensemble_models" name="Stacking Ensembles" version="@VERSION@" profile="20.05">
     <description>builds stacking, voting ensemble models with numerous base options</description>
     <macros>
         <import>main_macros.xml</import>
     </macros>
-    <expand macro="python_requirements"/>
-    <expand macro="macro_stdio"/>
+    <expand macro="python_requirements" />
+    <expand macro="macro_stdio" />
     <version_command>echo "$ENSEMBLE_VERSION"</version_command>
     <command>
         <![CDATA[
@@ -54,63 +54,62 @@
                         <option value="hard" selected="true">hard</option>
                         <option value="soft">soft</option>
                     </param>
-                    <param argument="flatten_transform" type="boolean" truevalue="booltrue" falsevalue="boolfalse" checked="true" help=""/>
+                    <param argument="flatten_transform" type="boolean" truevalue="booltrue" falsevalue="boolfalse" checked="true" help="" />
                 </expand>
             </when>
             <when value="sklearn.ensemble_VotingRegressor">
-                <expand macro="stacking_voting_weights"/>
+                <expand macro="stacking_voting_weights" />
             </when>
             <when value="mlxtend.classifier_StackingCVClassifier">
                 <expand macro="stacking_ensemble_inputs">
-                    <expand macro="cv_reduced"/>
-                    <expand macro="shuffle" label="shuffle"/>
-                    <expand macro="random_state" default_value="" help_text="Integer number. The seed of the pseudo random number generator to use when shuffling the data."/>
-                    <param argument="use_probas" type="boolean" truevalue="booltrue" falsevalue="boolfalse" checked="false"/>
+                    <expand macro="cv_reduced" />
+                    <expand macro="shuffle" label="shuffle" />
+                    <expand macro="random_state" default_value="" help_text="Integer number. The seed of the pseudo random number generator to use when shuffling the data." />
+                    <param argument="use_probas" type="boolean" truevalue="booltrue" falsevalue="boolfalse" checked="false" />
                 </expand>
                 <section name="meta_estimator" title="Meta Estimator" expanded="true">
-                    <expand macro="stacking_base_estimator"/>
+                    <expand macro="stacking_base_estimator" />
                 </section>
             </when>
             <when value="mlxtend.classifier_StackingClassifier">
                 <expand macro="stacking_ensemble_inputs">
-                    <param argument="use_probas" type="boolean" truevalue="booltrue" falsevalue="boolfalse" checked="false"/>
-                    <param argument="average_probas" type="boolean" truevalue="booltrue" falsevalue="boolfalse" checked="false"/>
+                    <param argument="use_probas" type="boolean" truevalue="booltrue" falsevalue="boolfalse" checked="false" />
+                    <param argument="average_probas" type="boolean" truevalue="booltrue" falsevalue="boolfalse" checked="false" />
                 </expand>
                 <section name="meta_estimator" title="Meta Estimator" expanded="true">
-                    <expand macro="stacking_base_estimator"/>
+                    <expand macro="stacking_base_estimator" />
                 </section>
             </when>
             <when value="mlxtend.regressor_StackingCVRegressor">
                 <expand macro="stacking_ensemble_inputs">
-                    <expand macro="cv_reduced"/>
+                    <expand macro="cv_reduced" />
                     <!--TODO support group splitters. Hint: `groups` is a fit_param-->
-                    <expand macro="shuffle" label="shuffle"/>
-                    <expand macro="random_state" default_value="" help_text="Integer number. The seed of the pseudo random number generator to use when shuffling the data."/>
-                    <param argument="refit" type="boolean" truevalue="booltrue" falsevalue="boolfalse" checked="true"/>
+                    <expand macro="shuffle" label="shuffle" />
+                    <expand macro="random_state" default_value="" help_text="Integer number. The seed of the pseudo random number generator to use when shuffling the data." />
+                    <param argument="refit" type="boolean" truevalue="booltrue" falsevalue="boolfalse" checked="true" />
                 </expand>
                 <section name="meta_estimator" title="Meta Estimator" expanded="true">
-                    <expand macro="stacking_base_estimator"/>
+                    <expand macro="stacking_base_estimator" />
                 </section>
             </when>
             <when value="mlxtend.regressor_StackingRegressor">
                 <expand macro="stacking_ensemble_inputs">
-                    <param argument="refit" type="boolean" truevalue="booltrue" falsevalue="boolfalse" checked="true"/>
+                    <param argument="refit" type="boolean" truevalue="booltrue" falsevalue="boolfalse" checked="true" />
                 </expand>
                 <section name="meta_estimator" title="Meta Estimator" expanded="true">
-                    <expand macro="stacking_base_estimator"/>
+                    <expand macro="stacking_base_estimator" />
                 </section>
             </when>
         </conditional>
         <repeat name="base_est_builder" min="1" max="20" title="Base Estimator">
-            <expand macro="stacking_base_estimator"/>
+            <expand macro="stacking_base_estimator" />
             <!--param name="base_estimator" type="data" format="zip,json" label="Select the dataset containing base estimator" help="One estimator at a time."/-->
         </repeat>
         <!--param name="meta_estimator" type="data" format="zip,json" label="Select the dataset containing the Meta estimator"/-->
-        <param name="get_params" type="boolean" truevalue="booltrue" falsevalue="boolfalse" checked="true" label="Output parameters for searchCV?"
-                help="Optional. Tunable parameters could be obtained through `estimator_attributes` tool."/>
+        <param name="get_params" type="boolean" truevalue="booltrue" falsevalue="boolfalse" checked="true" label="Output parameters for searchCV?" help="Optional. Tunable parameters could be obtained through `estimator_attributes` tool." />
     </inputs>
     <outputs>
-        <data format="zip" name="outfile" label="${algo_selection.estimator_type} on ${on_string}"/>
+        <data format="zip" name="outfile" label="${algo_selection.estimator_type} on ${on_string}" />
         <data format="tabular" name="outfile_params" label="get_params for ${algo_selection.estimator_type}">
             <filter>get_params</filter>
         </data>
@@ -118,75 +117,75 @@
     <tests>
         <test>
             <conditional name="algo_selection">
-                <param name="estimator_type" value="sklearn.ensemble_VotingClassifier"/>
+                <param name="estimator_type" value="sklearn.ensemble_VotingClassifier" />
                 <section name="options">
-                    <param name="weights" value="[1, 2]"/>
+                    <param name="weights" value="[1, 2]" />
                 </section>
             </conditional>
             <repeat name="base_est_builder">
                 <conditional name="estimator_selector">
-                    <param name="selected_module" value="svm"/>
-                    <param name="selected_estimator" value="SVC"/>
+                    <param name="selected_module" value="svm" />
+                    <param name="selected_estimator" value="SVC" />
                 </conditional>
             </repeat>
             <repeat name="base_est_builder">
                 <conditional name="estimator_selector">
-                    <param name="selected_module" value="xgboost"/>
-                    <param name="selected_estimator" value="XGBClassifier"/>
+                    <param name="selected_module" value="xgboost" />
+                    <param name="selected_estimator" value="XGBClassifier" />
                 </conditional>
             </repeat>
-            <param name="get_params" value="false"/>
-            <output name="outfile" file="StackingVoting03.zip" compare="sim_size" delta="5"/>
+            <param name="get_params" value="false" />
+            <output name="outfile" file="StackingVoting03.zip" compare="sim_size" delta="5" />
         </test>
         <test>
             <conditional name="algo_selection">
-                <param name="estimator_type" value="mlxtend.regressor_StackingCVRegressor"/>
+                <param name="estimator_type" value="mlxtend.regressor_StackingCVRegressor" />
                 <section name="meta_estimator">
                     <conditional name="estimator_selector">
-                        <param name="selected_module" value="custom_estimator"/>
-                        <param name="c_estimator" value="LinearRegression01.zip" ftype="zip"/>
+                        <param name="selected_module" value="custom_estimator" />
+                        <param name="c_estimator" value="LinearRegression01.zip" ftype="zip" />
                     </conditional>
                 </section>
             </conditional>
             <repeat name="base_est_builder">
                 <conditional name="estimator_selector">
-                    <param name="selected_module" value="custom_estimator"/>
-                    <param name="c_estimator" value="RandomForestRegressor01.zip" ftype="zip"/>
+                    <param name="selected_module" value="custom_estimator" />
+                    <param name="c_estimator" value="RandomForestRegressor01.zip" ftype="zip" />
                 </conditional>
             </repeat>
             <repeat name="base_est_builder">
                 <conditional name="estimator_selector">
-                    <param name="selected_module" value="custom_estimator"/>
-                    <param name="c_estimator" value="XGBRegressor01.zip" ftype="zip"/>
+                    <param name="selected_module" value="custom_estimator" />
+                    <param name="c_estimator" value="XGBRegressor01.zip" ftype="zip" />
                 </conditional>
             </repeat>
-            <param name="get_params" value="false"/>
-            <output name="outfile" file="StackingCVRegressor01.zip" compare="sim_size" delta="5"/>
+            <param name="get_params" value="false" />
+            <output name="outfile" file="StackingCVRegressor01.zip" compare="sim_size" delta="5" />
         </test>
         <test>
             <conditional name="algo_selection">
-                <param name="estimator_type" value="mlxtend.regressor_StackingRegressor"/>
+                <param name="estimator_type" value="mlxtend.regressor_StackingRegressor" />
                 <section name="meta_estimator">
                     <conditional name="estimator_selector">
-                        <param name="selected_module" value="svm"/>
-                        <param name="selected_estimator" value="SVR"/>
+                        <param name="selected_module" value="svm" />
+                        <param name="selected_estimator" value="SVR" />
                     </conditional>
                 </section>
             </conditional>
             <repeat name="base_est_builder">
                 <conditional name="estimator_selector">
-                    <param name="selected_module" value="custom_estimator"/>
-                    <param name="c_estimator" value="RandomForestRegressor01.zip" ftype="zip"/>
+                    <param name="selected_module" value="custom_estimator" />
+                    <param name="c_estimator" value="RandomForestRegressor01.zip" ftype="zip" />
                 </conditional>
             </repeat>
             <repeat name="base_est_builder">
                 <conditional name="estimator_selector">
-                    <param name="selected_module" value="xgboost"/>
-                    <param name="selected_estimator" value="XGBRegressor"/>
+                    <param name="selected_module" value="xgboost" />
+                    <param name="selected_estimator" value="XGBRegressor" />
                 </conditional>
             </repeat>
-            <param name="get_params" value="false"/>
-            <output name="outfile" file="StackingRegressor02.zip" compare="sim_size" delta="5"/>
+            <param name="get_params" value="false" />
+            <output name="outfile" file="StackingRegressor02.zip" compare="sim_size" delta="5" />
         </test>
     </tests>
     <help>
@@ -202,9 +201,9 @@
         ]]>
     </help>
     <expand macro="sklearn_citation">
-        <expand macro="skrebate_citation"/>
-        <expand macro="xgboost_citation"/>
-        <expand macro="imblearn_citation"/>
+        <expand macro="skrebate_citation" />
+        <expand macro="xgboost_citation" />
+        <expand macro="imblearn_citation" />
         <citation type="bibtex">
             @article{raschkas_2018_mlxtend,
                 author       = {Sebastian Raschka},
--- a/test-data/keras_batch_params01.tabular	Thu Oct 01 19:54:05 2020 +0000
+++ b/test-data/keras_batch_params01.tabular	Tue Apr 13 17:21:05 2021 +0000
@@ -27,7 +27,7 @@
 @	schedule_decay	schedule_decay: None
 @	seed	seed: None
 @	steps_per_epoch	steps_per_epoch: None
-@	validation_data	validation_data: None
+@	validation_fraction	validation_fraction: 0.1
 @	validation_steps	validation_steps: None
 @	verbose	verbose: 0
 *	data_batch_generator__fasta_path	data_batch_generator__fasta_path: 'to_be_determined'
--- a/test-data/keras_batch_params04.tabular	Thu Oct 01 19:54:05 2020 +0000
+++ b/test-data/keras_batch_params04.tabular	Tue Apr 13 17:21:05 2021 +0000
@@ -26,7 +26,7 @@
 @	schedule_decay	schedule_decay: None
 @	seed	seed: None
 @	steps_per_epoch	steps_per_epoch: None
-@	validation_data	validation_data: None
+@	validation_fraction	validation_fraction: 0.1
 @	validation_steps	validation_steps: None
 @	verbose	verbose: 0
 *	layers_0_Dense__class_name	layers_0_Dense__class_name: 'Dense'
Binary file test-data/keras_model01 has changed
Binary file test-data/keras_model02 has changed
Binary file test-data/keras_model04 has changed
--- a/test-data/keras_params04.tabular	Thu Oct 01 19:54:05 2020 +0000
+++ b/test-data/keras_params04.tabular	Tue Apr 13 17:21:05 2021 +0000
@@ -22,7 +22,7 @@
 @	schedule_decay	schedule_decay: None
 @	seed	seed: 42
 @	steps_per_epoch	steps_per_epoch: None
-@	validation_data	validation_data: None
+@	validation_fraction	validation_fraction: 0.1
 @	validation_steps	validation_steps: None
 @	verbose	verbose: 0
 *	layers_0_Dense__class_name	layers_0_Dense__class_name: 'Dense'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/ohe_in_w_header.tabular	Tue Apr 13 17:21:05 2021 +0000
@@ -0,0 +1,9 @@
+Label
+0
+1
+2
+3
+3
+2
+1
+0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/ohe_in_wo_header.tabular	Tue Apr 13 17:21:05 2021 +0000
@@ -0,0 +1,8 @@
+0
+1
+2
+3
+3
+2
+1
+0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/ohe_out_4.tabular	Tue Apr 13 17:21:05 2021 +0000
@@ -0,0 +1,8 @@
+1	0	0	0
+0	1	0	0
+0	0	1	0
+0	0	0	1
+0	0	0	1
+0	0	1	0
+0	1	0	0
+1	0	0	0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/ohe_out_5.tabular	Tue Apr 13 17:21:05 2021 +0000
@@ -0,0 +1,8 @@
+1	0	0	0	0
+0	1	0	0	0
+0	0	1	0	0
+0	0	0	1	0
+0	0	0	1	0
+0	0	1	0	0
+0	1	0	0	0
+1	0	0	0	0
--- a/test-data/pipeline_params05.tabular	Thu Oct 01 19:54:05 2020 +0000
+++ b/test-data/pipeline_params05.tabular	Tue Apr 13 17:21:05 2021 +0000
@@ -13,6 +13,6 @@
 *	n_jobs	n_jobs: 1
 @	oob_score	oob_score: False
 @	random_state	random_state: 42
-*	verbose	verbose: 0
+@	verbose	verbose: 0
 @	warm_start	warm_start: False
 	Note:	@, params eligible for search in searchcv tool.
--- a/test-data/pipeline_params18	Thu Oct 01 19:54:05 2020 +0000
+++ b/test-data/pipeline_params18	Tue Apr 13 17:21:05 2021 +0000
@@ -47,7 +47,7 @@
                                                            output_distribution='uniform',
                                                            random_state=10,
                                                            subsample=100000))"
-*	verbose	verbose: False
+@	verbose	verbose: False
 @	powertransformer__copy	powertransformer__copy: True
 @	powertransformer__method	powertransformer__method: 'yeo-johnson'
 @	powertransformer__standardize	powertransformer__standardize: True
@@ -75,7 +75,7 @@
 *	transformedtargetregressor__regressor__n_jobs	transformedtargetregressor__regressor__n_jobs: 1
 @	transformedtargetregressor__regressor__oob_score	transformedtargetregressor__regressor__oob_score: False
 @	transformedtargetregressor__regressor__random_state	transformedtargetregressor__regressor__random_state: 10
-*	transformedtargetregressor__regressor__verbose	transformedtargetregressor__regressor__verbose: 0
+@	transformedtargetregressor__regressor__verbose	transformedtargetregressor__regressor__verbose: 0
 @	transformedtargetregressor__regressor__warm_start	transformedtargetregressor__regressor__warm_start: False
 @	transformedtargetregressor__transformer	"transformedtargetregressor__transformer: QuantileTransformer(copy=True, ignore_implicit_zeros=False, n_quantiles=1000,
                     output_distribution='uniform', random_state=10,
Binary file test-data/train_test_eval_model01 has changed
Binary file test-data/train_test_eval_weights01.h5 has changed
Binary file test-data/train_test_eval_weights02.h5 has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/to_categorical.py	Tue Apr 13 17:21:05 2021 +0000
@@ -0,0 +1,50 @@
+import argparse
+import json
+import warnings
+
+import numpy as np
+import pandas as pd
+from keras.utils import to_categorical
+
+
+def main(inputs, infile, outfile, num_classes=None):
+    """
+    Parameter
+    ---------
+    input : str
+        File path to galaxy tool parameter
+
+    infile : str
+        File paths of input vector
+
+    outfile : str
+        File path to output matrix
+
+    num_classes : str
+        Total number of classes. If None, this would be inferred as the (largest number in y) + 1
+
+    """
+    warnings.simplefilter("ignore")
+
+    with open(inputs, "r") as param_handler:
+        params = json.load(param_handler)
+
+    input_header = params["header0"]
+    header = "infer" if input_header else None
+
+    input_vector = pd.read_csv(infile, sep="\t", header=header)
+
+    output_matrix = to_categorical(input_vector, num_classes=num_classes)
+
+    np.savetxt(outfile, output_matrix, fmt="%d", delimiter="\t")
+
+
+if __name__ == "__main__":
+    aparser = argparse.ArgumentParser()
+    aparser.add_argument("-i", "--inputs", dest="inputs", required=True)
+    aparser.add_argument("-y", "--infile", dest="infile")
+    aparser.add_argument("-n", "--num_classes", dest="num_classes", type=int, default=None)
+    aparser.add_argument("-o", "--outfile", dest="outfile")
+    args = aparser.parse_args()
+
+    main(args.inputs, args.infile, args.outfile, args.num_classes)
--- a/train_test_eval.py	Thu Oct 01 19:54:05 2020 +0000
+++ b/train_test_eval.py	Tue Apr 13 17:21:05 2021 +0000
@@ -1,59 +1,66 @@
 import argparse
-import joblib
 import json
-import numpy as np
 import os
-import pandas as pd
 import pickle
 import warnings
+
 from itertools import chain
+
+import joblib
+import numpy as np
+import pandas as pd
+from galaxy_ml.model_validations import train_test_split
+from galaxy_ml.utils import (
+    get_module,
+    get_scoring,
+    load_model,
+    read_columns,
+    SafeEval,
+    try_get_attr,
+)
 from scipy.io import mmread
-from sklearn.base import clone
-from sklearn import (cluster, compose, decomposition, ensemble,
-                     feature_extraction, feature_selection,
-                     gaussian_process, kernel_approximation, metrics,
-                     model_selection, naive_bayes, neighbors,
-                     pipeline, preprocessing, svm, linear_model,
-                     tree, discriminant_analysis)
-from sklearn.exceptions import FitFailedWarning
+from sklearn import pipeline
 from sklearn.metrics.scorer import _check_multimetric_scoring
-from sklearn.model_selection._validation import _score, cross_validate
+from sklearn.model_selection._validation import _score
 from sklearn.model_selection import _search, _validation
+from sklearn.model_selection._validation import _score
 from sklearn.utils import indexable, safe_indexing
 
-from galaxy_ml.model_validations import train_test_split
-from galaxy_ml.utils import (SafeEval, get_scoring, load_model,
-                             read_columns, try_get_attr, get_module)
 
+_fit_and_score = try_get_attr("galaxy_ml.model_validations", "_fit_and_score")
+setattr(_search, "_fit_and_score", _fit_and_score)
+setattr(_validation, "_fit_and_score", _fit_and_score)
 
-_fit_and_score = try_get_attr('galaxy_ml.model_validations', '_fit_and_score')
-setattr(_search, '_fit_and_score', _fit_and_score)
-setattr(_validation, '_fit_and_score', _fit_and_score)
-
-N_JOBS = int(os.environ.get('GALAXY_SLOTS', 1))
-CACHE_DIR = os.path.join(os.getcwd(), 'cached')
+N_JOBS = int(os.environ.get("GALAXY_SLOTS", 1))
+CACHE_DIR = os.path.join(os.getcwd(), "cached")
 del os
-NON_SEARCHABLE = ('n_jobs', 'pre_dispatch', 'memory', '_path',
-                  'nthread', 'callbacks')
-ALLOWED_CALLBACKS = ('EarlyStopping', 'TerminateOnNaN', 'ReduceLROnPlateau',
-                     'CSVLogger', 'None')
+NON_SEARCHABLE = ("n_jobs", "pre_dispatch", "memory", "_path", "nthread", "callbacks")
+ALLOWED_CALLBACKS = (
+    "EarlyStopping",
+    "TerminateOnNaN",
+    "ReduceLROnPlateau",
+    "CSVLogger",
+    "None",
+)
 
 
 def _eval_swap_params(params_builder):
     swap_params = {}
 
-    for p in params_builder['param_set']:
-        swap_value = p['sp_value'].strip()
-        if swap_value == '':
+    for p in params_builder["param_set"]:
+        swap_value = p["sp_value"].strip()
+        if swap_value == "":
             continue
 
-        param_name = p['sp_name']
+        param_name = p["sp_name"]
         if param_name.lower().endswith(NON_SEARCHABLE):
-            warnings.warn("Warning: `%s` is not eligible for search and was "
-                          "omitted!" % param_name)
+            warnings.warn(
+                "Warning: `%s` is not eligible for search and was "
+                "omitted!" % param_name
+            )
             continue
 
-        if not swap_value.startswith(':'):
+        if not swap_value.startswith(":"):
             safe_eval = SafeEval(load_scipy=True, load_numpy=True)
             ev = safe_eval(swap_value)
         else:
@@ -80,23 +87,24 @@
         else:
             new_arrays.append(arr)
 
-    if kwargs['shuffle'] == 'None':
-        kwargs['shuffle'] = None
+    if kwargs["shuffle"] == "None":
+        kwargs["shuffle"] = None
 
-    group_names = kwargs.pop('group_names', None)
+    group_names = kwargs.pop("group_names", None)
 
     if group_names is not None and group_names.strip():
-        group_names = [name.strip() for name in
-                       group_names.split(',')]
+        group_names = [name.strip() for name in group_names.split(",")]
         new_arrays = indexable(*new_arrays)
-        groups = kwargs['labels']
+        groups = kwargs["labels"]
         n_samples = new_arrays[0].shape[0]
         index_arr = np.arange(n_samples)
         test = index_arr[np.isin(groups, group_names)]
         train = index_arr[~np.isin(groups, group_names)]
-        rval = list(chain.from_iterable(
-            (safe_indexing(a, train),
-             safe_indexing(a, test)) for a in new_arrays))
+        rval = list(
+            chain.from_iterable(
+                (safe_indexing(a, train), safe_indexing(a, test)) for a in new_arrays
+            )
+        )
     else:
         rval = train_test_split(*new_arrays, **kwargs)
 
@@ -106,11 +114,20 @@
     return rval
 
 
-def main(inputs, infile_estimator, infile1, infile2,
-         outfile_result, outfile_object=None,
-         outfile_weights=None, groups=None,
-         ref_seq=None, intervals=None, targets=None,
-         fasta_path=None):
+def main(
+    inputs,
+    infile_estimator,
+    infile1,
+    infile2,
+    outfile_result,
+    outfile_object=None,
+    outfile_weights=None,
+    groups=None,
+    ref_seq=None,
+    intervals=None,
+    targets=None,
+    fasta_path=None,
+):
     """
     Parameter
     ---------
@@ -150,17 +167,17 @@
     fasta_path : str
         File path to dataset containing fasta file
     """
-    warnings.simplefilter('ignore')
+    warnings.simplefilter("ignore")
 
-    with open(inputs, 'r') as param_handler:
+    with open(inputs, "r") as param_handler:
         params = json.load(param_handler)
 
     #  load estimator
-    with open(infile_estimator, 'rb') as estimator_handler:
+    with open(infile_estimator, "rb") as estimator_handler:
         estimator = load_model(estimator_handler)
 
     # swap hyperparameter
-    swapping = params['experiment_schemes']['hyperparams_swapping']
+    swapping = params["experiment_schemes"]["hyperparams_swapping"]
     swap_params = _eval_swap_params(swapping)
     estimator.set_params(**swap_params)
 
@@ -169,38 +186,41 @@
     # store read dataframe object
     loaded_df = {}
 
-    input_type = params['input_options']['selected_input']
+    input_type = params["input_options"]["selected_input"]
     # tabular input
-    if input_type == 'tabular':
-        header = 'infer' if params['input_options']['header1'] else None
-        column_option = (params['input_options']['column_selector_options_1']
-                         ['selected_column_selector_option'])
-        if column_option in ['by_index_number', 'all_but_by_index_number',
-                             'by_header_name', 'all_but_by_header_name']:
-            c = params['input_options']['column_selector_options_1']['col1']
+    if input_type == "tabular":
+        header = "infer" if params["input_options"]["header1"] else None
+        column_option = params["input_options"]["column_selector_options_1"][
+            "selected_column_selector_option"
+        ]
+        if column_option in [
+            "by_index_number",
+            "all_but_by_index_number",
+            "by_header_name",
+            "all_but_by_header_name",
+        ]:
+            c = params["input_options"]["column_selector_options_1"]["col1"]
         else:
             c = None
 
         df_key = infile1 + repr(header)
-        df = pd.read_csv(infile1, sep='\t', header=header,
-                         parse_dates=True)
+        df = pd.read_csv(infile1, sep="\t", header=header, parse_dates=True)
         loaded_df[df_key] = df
 
         X = read_columns(df, c=c, c_option=column_option).astype(float)
     # sparse input
-    elif input_type == 'sparse':
-        X = mmread(open(infile1, 'r'))
+    elif input_type == "sparse":
+        X = mmread(open(infile1, "r"))
 
     # fasta_file input
-    elif input_type == 'seq_fasta':
-        pyfaidx = get_module('pyfaidx')
+    elif input_type == "seq_fasta":
+        pyfaidx = get_module("pyfaidx")
         sequences = pyfaidx.Fasta(fasta_path)
         n_seqs = len(sequences.keys())
         X = np.arange(n_seqs)[:, np.newaxis]
         for param in estimator_params.keys():
-            if param.endswith('fasta_path'):
-                estimator.set_params(
-                    **{param: fasta_path})
+            if param.endswith("fasta_path"):
+                estimator.set_params(**{param: fasta_path})
                 break
         else:
             raise ValueError(
@@ -209,25 +229,31 @@
                 "KerasGBatchClassifier with "
                 "FastaDNABatchGenerator/FastaProteinBatchGenerator "
                 "or having GenomeOneHotEncoder/ProteinOneHotEncoder "
-                "in pipeline!")
+                "in pipeline!"
+            )
 
-    elif input_type == 'refseq_and_interval':
+    elif input_type == "refseq_and_interval":
         path_params = {
-            'data_batch_generator__ref_genome_path': ref_seq,
-            'data_batch_generator__intervals_path': intervals,
-            'data_batch_generator__target_path': targets
+            "data_batch_generator__ref_genome_path": ref_seq,
+            "data_batch_generator__intervals_path": intervals,
+            "data_batch_generator__target_path": targets,
         }
         estimator.set_params(**path_params)
         n_intervals = sum(1 for line in open(intervals))
         X = np.arange(n_intervals)[:, np.newaxis]
 
     # Get target y
-    header = 'infer' if params['input_options']['header2'] else None
-    column_option = (params['input_options']['column_selector_options_2']
-                     ['selected_column_selector_option2'])
-    if column_option in ['by_index_number', 'all_but_by_index_number',
-                         'by_header_name', 'all_but_by_header_name']:
-        c = params['input_options']['column_selector_options_2']['col2']
+    header = "infer" if params["input_options"]["header2"] else None
+    column_option = params["input_options"]["column_selector_options_2"][
+        "selected_column_selector_option2"
+    ]
+    if column_option in [
+        "by_index_number",
+        "all_but_by_index_number",
+        "by_header_name",
+        "all_but_by_header_name",
+    ]:
+        c = params["input_options"]["column_selector_options_2"]["col2"]
     else:
         c = None
 
@@ -235,37 +261,39 @@
     if df_key in loaded_df:
         infile2 = loaded_df[df_key]
     else:
-        infile2 = pd.read_csv(infile2, sep='\t',
-                              header=header, parse_dates=True)
+        infile2 = pd.read_csv(infile2, sep="\t", header=header, parse_dates=True)
         loaded_df[df_key] = infile2
 
-    y = read_columns(
-            infile2,
-            c=c,
-            c_option=column_option,
-            sep='\t',
-            header=header,
-            parse_dates=True)
+    y = read_columns(infile2,
+                     c=c,
+                     c_option=column_option,
+                     sep='\t',
+                     header=header,
+                     parse_dates=True)
     if len(y.shape) == 2 and y.shape[1] == 1:
         y = y.ravel()
-    if input_type == 'refseq_and_interval':
-        estimator.set_params(
-            data_batch_generator__features=y.ravel().tolist())
+    if input_type == "refseq_and_interval":
+        estimator.set_params(data_batch_generator__features=y.ravel().tolist())
         y = None
     # end y
 
     # load groups
     if groups:
-        groups_selector = (params['experiment_schemes']['test_split']
-                                 ['split_algos']).pop('groups_selector')
+        groups_selector = (
+            params["experiment_schemes"]["test_split"]["split_algos"]
+        ).pop("groups_selector")
 
-        header = 'infer' if groups_selector['header_g'] else None
-        column_option = \
-            (groups_selector['column_selector_options_g']
-                            ['selected_column_selector_option_g'])
-        if column_option in ['by_index_number', 'all_but_by_index_number',
-                             'by_header_name', 'all_but_by_header_name']:
-            c = groups_selector['column_selector_options_g']['col_g']
+        header = "infer" if groups_selector["header_g"] else None
+        column_option = groups_selector["column_selector_options_g"][
+            "selected_column_selector_option_g"
+        ]
+        if column_option in [
+            "by_index_number",
+            "all_but_by_index_number",
+            "by_header_name",
+            "all_but_by_header_name",
+        ]:
+            c = groups_selector["column_selector_options_g"]["col_g"]
         else:
             c = None
 
@@ -273,13 +301,12 @@
         if df_key in loaded_df:
             groups = loaded_df[df_key]
 
-        groups = read_columns(
-                groups,
-                c=c,
-                c_option=column_option,
-                sep='\t',
-                header=header,
-                parse_dates=True)
+        groups = read_columns(groups,
+                              c=c,
+                              c_option=column_option,
+                              sep='\t',
+                              header=header,
+                              parse_dates=True)
         groups = groups.ravel()
 
     # del loaded_df
@@ -288,15 +315,15 @@
     # handle memory
     memory = joblib.Memory(location=CACHE_DIR, verbose=0)
     # cache iraps_core fits could increase search speed significantly
-    if estimator.__class__.__name__ == 'IRAPSClassifier':
+    if estimator.__class__.__name__ == "IRAPSClassifier":
         estimator.set_params(memory=memory)
     else:
         # For iraps buried in pipeline
         new_params = {}
         for p, v in estimator_params.items():
-            if p.endswith('memory'):
+            if p.endswith("memory"):
                 # for case of `__irapsclassifier__memory`
-                if len(p) > 8 and p[:-8].endswith('irapsclassifier'):
+                if len(p) > 8 and p[:-8].endswith("irapsclassifier"):
                     # cache iraps_core fits could increase search
                     # speed significantly
                     new_params[p] = memory
@@ -305,88 +332,98 @@
                 elif v:
                     new_params[p] = None
             # handle n_jobs
-            elif p.endswith('n_jobs'):
+            elif p.endswith("n_jobs"):
                 # For now, 1 CPU is suggested for iprasclassifier
-                if len(p) > 8 and p[:-8].endswith('irapsclassifier'):
+                if len(p) > 8 and p[:-8].endswith("irapsclassifier"):
                     new_params[p] = 1
                 else:
                     new_params[p] = N_JOBS
             # for security reason, types of callback are limited
-            elif p.endswith('callbacks'):
+            elif p.endswith("callbacks"):
                 for cb in v:
-                    cb_type = cb['callback_selection']['callback_type']
+                    cb_type = cb["callback_selection"]["callback_type"]
                     if cb_type not in ALLOWED_CALLBACKS:
-                        raise ValueError(
-                            "Prohibited callback type: %s!" % cb_type)
+                        raise ValueError("Prohibited callback type: %s!" % cb_type)
 
         estimator.set_params(**new_params)
 
     # handle scorer, convert to scorer dict
-    scoring = params['experiment_schemes']['metrics']['scoring']
+    # Check if scoring is specified
+    scoring = params["experiment_schemes"]["metrics"].get("scoring", None)
+    if scoring is not None:
+        # get_scoring() expects secondary_scoring to be a comma separated string (not a list)
+        # Check if secondary_scoring is specified
+        secondary_scoring = scoring.get("secondary_scoring", None)
+        if secondary_scoring is not None:
+            # If secondary_scoring is specified, convert the list into comman separated string
+            scoring["secondary_scoring"] = ",".join(scoring["secondary_scoring"])
     scorer = get_scoring(scoring)
     scorer, _ = _check_multimetric_scoring(estimator, scoring=scorer)
 
     # handle test (first) split
-    test_split_options = (params['experiment_schemes']
-                                ['test_split']['split_algos'])
+    test_split_options = params["experiment_schemes"]["test_split"]["split_algos"]
 
-    if test_split_options['shuffle'] == 'group':
-        test_split_options['labels'] = groups
-    if test_split_options['shuffle'] == 'stratified':
+    if test_split_options["shuffle"] == "group":
+        test_split_options["labels"] = groups
+    if test_split_options["shuffle"] == "stratified":
         if y is not None:
-            test_split_options['labels'] = y
+            test_split_options["labels"] = y
         else:
-            raise ValueError("Stratified shuffle split is not "
-                             "applicable on empty target values!")
+            raise ValueError(
+                "Stratified shuffle split is not " "applicable on empty target values!"
+            )
 
-    X_train, X_test, y_train, y_test, groups_train, groups_test = \
-        train_test_split_none(X, y, groups, **test_split_options)
+    X_train, X_test, y_train, y_test, groups_train, _groups_test = train_test_split_none(
+        X, y, groups, **test_split_options
+    )
 
-    exp_scheme = params['experiment_schemes']['selected_exp_scheme']
+    exp_scheme = params["experiment_schemes"]["selected_exp_scheme"]
 
     # handle validation (second) split
-    if exp_scheme == 'train_val_test':
-        val_split_options = (params['experiment_schemes']
-                                   ['val_split']['split_algos'])
+    if exp_scheme == "train_val_test":
+        val_split_options = params["experiment_schemes"]["val_split"]["split_algos"]
 
-        if val_split_options['shuffle'] == 'group':
-            val_split_options['labels'] = groups_train
-        if val_split_options['shuffle'] == 'stratified':
+        if val_split_options["shuffle"] == "group":
+            val_split_options["labels"] = groups_train
+        if val_split_options["shuffle"] == "stratified":
             if y_train is not None:
-                val_split_options['labels'] = y_train
+                val_split_options["labels"] = y_train
             else:
-                raise ValueError("Stratified shuffle split is not "
-                                 "applicable on empty target values!")
+                raise ValueError(
+                    "Stratified shuffle split is not "
+                    "applicable on empty target values!"
+                )
 
-        X_train, X_val, y_train, y_val, groups_train, groups_val = \
-            train_test_split_none(X_train, y_train, groups_train,
-                                  **val_split_options)
+        (
+            X_train,
+            X_val,
+            y_train,
+            y_val,
+            groups_train,
+            _groups_val,
+        ) = train_test_split_none(X_train, y_train, groups_train, **val_split_options)
 
     # train and eval
-    if hasattr(estimator, 'validation_data'):
-        if exp_scheme == 'train_val_test':
-            estimator.fit(X_train, y_train,
-                          validation_data=(X_val, y_val))
+    if hasattr(estimator, "validation_data"):
+        if exp_scheme == "train_val_test":
+            estimator.fit(X_train, y_train, validation_data=(X_val, y_val))
         else:
-            estimator.fit(X_train, y_train,
-                          validation_data=(X_test, y_test))
+            estimator.fit(X_train, y_train, validation_data=(X_test, y_test))
     else:
         estimator.fit(X_train, y_train)
 
-    if hasattr(estimator, 'evaluate'):
-        scores = estimator.evaluate(X_test, y_test=y_test,
-                                    scorer=scorer,
-                                    is_multimetric=True)
+    if hasattr(estimator, "evaluate"):
+        scores = estimator.evaluate(
+            X_test, y_test=y_test, scorer=scorer, is_multimetric=True
+        )
     else:
-        scores = _score(estimator, X_test, y_test, scorer,
-                        is_multimetric=True)
+        scores = _score(estimator, X_test, y_test, scorer, is_multimetric=True)
     # handle output
     for name, score in scores.items():
         scores[name] = [score]
     df = pd.DataFrame(scores)
     df = df[sorted(df.columns)]
-    df.to_csv(path_or_buf=outfile_result, sep='\t',
-              header=True, index=False)
+    df.to_csv(path_or_buf=outfile_result, sep="\t", header=True, index=False)
 
     memory.clear(warn=False)
 
@@ -395,23 +432,25 @@
         if isinstance(estimator, pipeline.Pipeline):
             main_est = estimator.steps[-1][-1]
 
-        if hasattr(main_est, 'model_') \
-                and hasattr(main_est, 'save_weights'):
+        if hasattr(main_est, "model_") and hasattr(main_est, "save_weights"):
             if outfile_weights:
                 main_est.save_weights(outfile_weights)
-            del main_est.model_
-            del main_est.fit_params
-            del main_est.model_class_
-            del main_est.validation_data
-            if getattr(main_est, 'data_generator_', None):
+            if getattr(main_est, "model_", None):
+                del main_est.model_
+            if getattr(main_est, "fit_params", None):
+                del main_est.fit_params
+            if getattr(main_est, "model_class_", None):
+                del main_est.model_class_
+            if getattr(main_est, "validation_data", None):
+                del main_est.validation_data
+            if getattr(main_est, "data_generator_", None):
                 del main_est.data_generator_
 
-        with open(outfile_object, 'wb') as output_handler:
-            pickle.dump(estimator, output_handler,
-                        pickle.HIGHEST_PROTOCOL)
+        with open(outfile_object, "wb") as output_handler:
+            pickle.dump(estimator, output_handler, pickle.HIGHEST_PROTOCOL)
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     aparser = argparse.ArgumentParser()
     aparser.add_argument("-i", "--inputs", dest="inputs", required=True)
     aparser.add_argument("-e", "--estimator", dest="infile_estimator")
@@ -427,8 +466,17 @@
     aparser.add_argument("-f", "--fasta_path", dest="fasta_path")
     args = aparser.parse_args()
 
-    main(args.inputs, args.infile_estimator, args.infile1, args.infile2,
-         args.outfile_result, outfile_object=args.outfile_object,
-         outfile_weights=args.outfile_weights, groups=args.groups,
-         ref_seq=args.ref_seq, intervals=args.intervals,
-         targets=args.targets, fasta_path=args.fasta_path)
+    main(
+        args.inputs,
+        args.infile_estimator,
+        args.infile1,
+        args.infile2,
+        args.outfile_result,
+        outfile_object=args.outfile_object,
+        outfile_weights=args.outfile_weights,
+        groups=args.groups,
+        ref_seq=args.ref_seq,
+        intervals=args.intervals,
+        targets=args.targets,
+        fasta_path=args.fasta_path,
+    )
--- a/train_test_split.py	Thu Oct 01 19:54:05 2020 +0000
+++ b/train_test_split.py	Tue Apr 13 17:21:05 2021 +0000
@@ -7,9 +7,8 @@
 from galaxy_ml.utils import get_cv, read_columns
 
 
-def _get_single_cv_split(params, array, infile_labels=None,
-                         infile_groups=None):
-    """ output (train, test) subset from a cv splitter
+def _get_single_cv_split(params, array, infile_labels=None, infile_groups=None):
+    """output (train, test) subset from a cv splitter
 
     Parameters
     ----------
@@ -25,45 +24,50 @@
     y = None
     groups = None
 
-    nth_split = params['mode_selection']['nth_split']
+    nth_split = params["mode_selection"]["nth_split"]
 
     # read groups
     if infile_groups:
-        header = 'infer' if (params['mode_selection']['cv_selector']
-                             ['groups_selector']['header_g']) else None
-        column_option = (params['mode_selection']['cv_selector']
-                         ['groups_selector']['column_selector_options_g']
-                         ['selected_column_selector_option_g'])
-        if column_option in ['by_index_number', 'all_but_by_index_number',
-                             'by_header_name', 'all_but_by_header_name']:
-            c = (params['mode_selection']['cv_selector']['groups_selector']
-                 ['column_selector_options_g']['col_g'])
+        header = "infer" if (params["mode_selection"]["cv_selector"]["groups_selector"]["header_g"]) else None
+        column_option = params["mode_selection"]["cv_selector"]["groups_selector"]["column_selector_options_g"][
+            "selected_column_selector_option_g"
+        ]
+        if column_option in [
+            "by_index_number",
+            "all_but_by_index_number",
+            "by_header_name",
+            "all_but_by_header_name",
+        ]:
+            c = params["mode_selection"]["cv_selector"]["groups_selector"]["column_selector_options_g"]["col_g"]
         else:
             c = None
 
-        groups = read_columns(infile_groups, c=c, c_option=column_option,
-                              sep='\t', header=header, parse_dates=True)
+        groups = read_columns(
+            infile_groups,
+            c=c,
+            c_option=column_option,
+            sep="\t",
+            header=header,
+            parse_dates=True,
+        )
         groups = groups.ravel()
 
-        params['mode_selection']['cv_selector']['groups_selector'] = groups
+        params["mode_selection"]["cv_selector"]["groups_selector"] = groups
 
     # read labels
     if infile_labels:
-        target_input = (params['mode_selection']
-                        ['cv_selector'].pop('target_input'))
-        header = 'infer' if target_input['header1'] else None
-        col_index = target_input['col'][0] - 1
-        df = pd.read_csv(infile_labels, sep='\t', header=header,
-                         parse_dates=True)
+        target_input = params["mode_selection"]["cv_selector"].pop("target_input")
+        header = "infer" if target_input["header1"] else None
+        col_index = target_input["col"][0] - 1
+        df = pd.read_csv(infile_labels, sep="\t", header=header, parse_dates=True)
         y = df.iloc[:, col_index].values
 
     # construct the cv splitter object
-    splitter, groups = get_cv(params['mode_selection']['cv_selector'])
+    splitter, groups = get_cv(params["mode_selection"]["cv_selector"])
 
     total_n_splits = splitter.get_n_splits(array.values, y=y, groups=groups)
     if nth_split > total_n_splits:
-        raise ValueError("Total number of splits is {}, but got `nth_split` "
-                         "= {}".format(total_n_splits, nth_split))
+        raise ValueError("Total number of splits is {}, but got `nth_split` " "= {}".format(total_n_splits, nth_split))
 
     i = 1
     for train_index, test_index in splitter.split(array.values, y=y, groups=groups):
@@ -79,8 +83,14 @@
     return train, test
 
 
-def main(inputs, infile_array, outfile_train, outfile_test,
-         infile_labels=None, infile_groups=None):
+def main(
+    inputs,
+    infile_array,
+    outfile_train,
+    outfile_test,
+    infile_labels=None,
+    infile_groups=None,
+):
     """
     Parameter
     ---------
@@ -102,45 +112,41 @@
     outfile_test : str
         File path to dataset containing test split
     """
-    warnings.simplefilter('ignore')
+    warnings.simplefilter("ignore")
 
-    with open(inputs, 'r') as param_handler:
+    with open(inputs, "r") as param_handler:
         params = json.load(param_handler)
 
-    input_header = params['header0']
-    header = 'infer' if input_header else None
-    array = pd.read_csv(infile_array, sep='\t', header=header,
-                        parse_dates=True)
+    input_header = params["header0"]
+    header = "infer" if input_header else None
+    array = pd.read_csv(infile_array, sep="\t", header=header, parse_dates=True)
 
     # train test split
-    if params['mode_selection']['selected_mode'] == 'train_test_split':
-        options = params['mode_selection']['options']
-        shuffle_selection = options.pop('shuffle_selection')
-        options['shuffle'] = shuffle_selection['shuffle']
+    if params["mode_selection"]["selected_mode"] == "train_test_split":
+        options = params["mode_selection"]["options"]
+        shuffle_selection = options.pop("shuffle_selection")
+        options["shuffle"] = shuffle_selection["shuffle"]
         if infile_labels:
-            header = 'infer' if shuffle_selection['header1'] else None
-            col_index = shuffle_selection['col'][0] - 1
-            df = pd.read_csv(infile_labels, sep='\t', header=header,
-                             parse_dates=True)
+            header = "infer" if shuffle_selection["header1"] else None
+            col_index = shuffle_selection["col"][0] - 1
+            df = pd.read_csv(infile_labels, sep="\t", header=header, parse_dates=True)
             labels = df.iloc[:, col_index].values
-            options['labels'] = labels
+            options["labels"] = labels
 
         train, test = train_test_split(array, **options)
 
     # cv splitter
     else:
-        train, test = _get_single_cv_split(params, array,
-                                           infile_labels=infile_labels,
-                                           infile_groups=infile_groups)
+        train, test = _get_single_cv_split(params, array, infile_labels=infile_labels, infile_groups=infile_groups)
 
     print("Input shape: %s" % repr(array.shape))
     print("Train shape: %s" % repr(train.shape))
     print("Test shape: %s" % repr(test.shape))
-    train.to_csv(outfile_train, sep='\t', header=input_header, index=False)
-    test.to_csv(outfile_test, sep='\t', header=input_header, index=False)
+    train.to_csv(outfile_train, sep="\t", header=input_header, index=False)
+    test.to_csv(outfile_test, sep="\t", header=input_header, index=False)