changeset 0:59e8b4328c82 draft

"planemo upload for repository https://github.com/bgruening/galaxytools/tree/master/tools/sklearn commit 208a8d348e7c7a182cfbe1b6f17868146428a7e2"
author bgruening
date Tue, 13 Apr 2021 22:40:10 +0000
parents
children f93f0cdbaf18
files README.rst fitted_model_eval.py keras_deep_learning.py keras_macros.xml 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 test-data/GridSearchCV.zip test-data/LinearRegression01.zip test-data/LinearRegression02.zip test-data/RF01704.fasta test-data/RFE.zip test-data/RandomForestClassifier.zip test-data/RandomForestRegressor01.zip test-data/StackingCVRegressor01.zip test-data/StackingCVRegressor02.zip test-data/StackingRegressor02.zip test-data/StackingVoting03.zip test-data/XGBRegressor01.zip test-data/abc_model01 test-data/abc_result01 test-data/abr_model01 test-data/abr_result01 test-data/accuracy_score.txt test-data/auc.txt test-data/average_precision_score.txt test-data/best_estimator_.zip test-data/best_params_.txt test-data/best_score_.tabular test-data/blobs.txt test-data/brier_score_loss.txt test-data/circles.txt test-data/class.txt test-data/classification_report.txt test-data/cluster_result01.txt test-data/cluster_result02.txt test-data/cluster_result03.txt test-data/cluster_result04.txt test-data/cluster_result05.txt test-data/cluster_result06.txt test-data/cluster_result07.txt test-data/cluster_result08.txt test-data/cluster_result09.txt test-data/cluster_result10.txt test-data/cluster_result11.txt test-data/cluster_result12.txt test-data/cluster_result13.txt test-data/cluster_result14.txt test-data/cluster_result15.txt test-data/cluster_result16.txt test-data/cluster_result17.txt test-data/cluster_result18.txt test-data/cluster_result19.txt test-data/cluster_result20.txt test-data/cluster_result21.txt test-data/confusion_matrix.txt test-data/converter_result01.json test-data/converter_result02.json test-data/csc_sparse1.mtx test-data/csc_sparse2.mtx test-data/csc_stack_result01.mtx test-data/csr_sparse1.mtx test-data/csr_sparse2.mtx test-data/csr_stack_result01.mtx test-data/deepsear_1feature.json test-data/empty_file.txt test-data/f1_score.txt test-data/fbeta_score.txt test-data/feature_importances_.tabular test-data/feature_selection_result01 test-data/feature_selection_result02 test-data/feature_selection_result03 test-data/feature_selection_result04 test-data/feature_selection_result05 test-data/feature_selection_result06 test-data/feature_selection_result07 test-data/feature_selection_result08 test-data/feature_selection_result09 test-data/feature_selection_result10 test-data/feature_selection_result11 test-data/feature_selection_result12 test-data/feature_selection_result13 test-data/final_estimator.zip test-data/fitted_keras_g_regressor01.zip test-data/fitted_model_eval01.tabular test-data/friedman1.txt test-data/friedman2.txt test-data/friedman3.txt test-data/gaus.txt test-data/gbc_model01 test-data/gbc_result01 test-data/gbr_model01 test-data/gbr_prediction_result01.tabular test-data/get_params.tabular test-data/get_params01.tabular test-data/get_params02.tabular test-data/get_params03.tabular test-data/get_params04.tabular test-data/get_params05.tabular test-data/get_params06.tabular test-data/get_params07.tabular test-data/get_params08.tabular test-data/get_params09.tabular test-data/get_params10.tabular test-data/get_params11.tabular test-data/get_params12.tabular test-data/glm_model01 test-data/glm_model02 test-data/glm_model03 test-data/glm_model04 test-data/glm_model05 test-data/glm_model06 test-data/glm_model07 test-data/glm_model08 test-data/glm_result01 test-data/glm_result02 test-data/glm_result03 test-data/glm_result04 test-data/glm_result05 test-data/glm_result06 test-data/glm_result07 test-data/glm_result08 test-data/grid_scores_.tabular test-data/hamming_loss.txt test-data/hastie.txt test-data/hinge_loss.txt test-data/imblearn_X.tabular test-data/imblearn_y.tabular test-data/jaccard_similarity_score.txt test-data/keras01.json test-data/keras02.json test-data/keras03.json test-data/keras04.json test-data/keras_batch_model01 test-data/keras_batch_model02 test-data/keras_batch_model03 test-data/keras_batch_model04 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/keras_prefitted01.zip test-data/keras_save_weights01.h5 test-data/keras_train_eval_y_true02.tabular test-data/lda_model01 test-data/lda_model02 test-data/lda_prediction_result01.tabular test-data/lda_prediction_result02.tabular test-data/lgb_class_model.txt test-data/lgb_prediction_result01.tabular test-data/lgb_regr_model.txt test-data/log_loss.txt test-data/matthews_corrcoef.txt test-data/ml_confusion_predicted.tabular test-data/ml_confusion_true.tabular test-data/ml_confusion_viz.png test-data/ml_vis01.html test-data/ml_vis02.html test-data/ml_vis03.html test-data/ml_vis04.html test-data/ml_vis05.html test-data/ml_vis05.png test-data/model_fit01 test-data/model_fit02 test-data/model_fit02.h5 test-data/model_pred01.tabular test-data/model_pred02.tabular test-data/moons.txt test-data/mv_result02.tabular test-data/mv_result03.tabular test-data/mv_result05.tabular test-data/named_steps.txt test-data/nn_model01 test-data/nn_model02 test-data/nn_model03 test-data/nn_prediction_result01.tabular test-data/nn_prediction_result02.tabular test-data/nn_prediction_result03.tabular test-data/numeric_values.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/pca_classical_header_names_output.dat test-data/pca_classical_output.dat test-data/pca_incremental_header_names_output.dat test-data/pca_incremental_output.dat test-data/pca_input.dat test-data/pca_input_with_headers.dat test-data/pickle_blacklist test-data/pipeline01 test-data/pipeline02 test-data/pipeline03 test-data/pipeline04 test-data/pipeline05 test-data/pipeline06 test-data/pipeline07 test-data/pipeline08 test-data/pipeline09 test-data/pipeline10 test-data/pipeline11 test-data/pipeline12 test-data/pipeline14 test-data/pipeline15 test-data/pipeline16 test-data/pipeline17 test-data/pipeline_params05.tabular test-data/pipeline_params18 test-data/precision_recall_curve.txt test-data/precision_recall_fscore_support.txt test-data/precision_score.txt test-data/predicted_header.tabular test-data/prp_model01 test-data/prp_model02 test-data/prp_model03 test-data/prp_model04 test-data/prp_model05 test-data/prp_model06 test-data/prp_model07 test-data/prp_model08 test-data/prp_model09 test-data/prp_result01 test-data/prp_result02 test-data/prp_result03 test-data/prp_result04 test-data/prp_result05 test-data/prp_result06 test-data/prp_result07 test-data/prp_result08 test-data/prp_result09 test-data/prp_result10 test-data/pw_metric01.tabular test-data/pw_metric02.tabular test-data/pw_metric03.tabular test-data/qda_model01 test-data/qda_prediction_result01.tabular test-data/ranking_.tabular test-data/recall_score.txt test-data/regression.txt test-data/regression_X.tabular test-data/regression_groups.tabular test-data/regression_metrics_result01 test-data/regression_metrics_result02 test-data/regression_metrics_result03 test-data/regression_metrics_result04 test-data/regression_metrics_result05 test-data/regression_metrics_result06 test-data/regression_test.tabular test-data/regression_test_X.tabular test-data/regression_test_y.tabular test-data/regression_train.tabular test-data/regression_y.tabular test-data/regression_y_split_test01.tabular test-data/rfc_model01 test-data/rfc_result01 test-data/rfc_result02 test-data/rfr_model01 test-data/rfr_result01 test-data/roc_auc_score.txt test-data/roc_curve.txt test-data/scurve.txt test-data/searchCV01 test-data/searchCV02 test-data/sparse.mtx test-data/sparse_u.txt test-data/svc_model01 test-data/svc_model02 test-data/svc_model03 test-data/svc_prediction_result01.tabular test-data/svc_prediction_result02.tabular test-data/svc_prediction_result03.tabular test-data/swiss_r.txt test-data/test.tabular test-data/test2.tabular test-data/test3.tabular test-data/test_set.tabular test-data/train.tabular test-data/train_set.tabular test-data/train_test_eval01.tabular test-data/train_test_eval03.tabular test-data/train_test_eval_model01 test-data/train_test_eval_weights01.h5 test-data/train_test_eval_weights02.h5 test-data/train_test_split_test01.tabular test-data/train_test_split_test02.tabular test-data/train_test_split_test03.tabular test-data/train_test_split_train01.tabular test-data/train_test_split_train02.tabular test-data/train_test_split_train03.tabular test-data/true_header.tabular test-data/vectorizer_result01.mtx test-data/vectorizer_result02.mtx test-data/vectorizer_result03.mtx test-data/vectorizer_result04.mtx test-data/y.tabular test-data/y_score.tabular test-data/y_true.tabular test-data/zero_one_loss.txt to_categorical.py to_categorical.xml train_test_eval.py train_test_split.py
diffstat 309 files changed, 253516 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README.rst	Tue Apr 13 22:40:10 2021 +0000
@@ -0,0 +1,146 @@
+Galaxy wrapper for scikit-learn library
+***************************************
+
+Contents
+========
+
+- `What is scikit-learn?`_
+	- `Scikit-learn main package groups`_
+	- `Tools offered by this wrapper`_
+
+- `Machine learning workflows`_
+	- `Supervised learning workflows`_
+	- `Unsupervised learning workflows`_
+
+
+____________________________
+
+
+.. _What is scikit-learn?:
+
+What is scikit-learn?
+=====================
+
+Scikit-learn is an open-source machine learning library for the Python programming language. It offers various algorithms for performing supervised and unsupervised learning as well as data preprocessing and transformation, model selection and evaluation, and dataset utilities. It is built upon SciPy (Scientific Python) library.
+
+Scikit-learn source code can be accessed at https://github.com/scikit-learn/scikit-learn.
+Detailed installation instructions can be found at http://scikit-learn.org/stable/install.html
+
+
+.. _Scikit-learn main package groups:
+
+Scikit-learn main package groups
+================================
+
+Scikit-learn provides the users with several main groups of related operations.
+These are:
+
+- Classification
+    - Identifying to which category an object belongs.
+- Regression
+    - Predicting a continuous-valued attribute associated with an object.
+- Clustering
+    - Automatic grouping of similar objects into sets.
+- Preprocessing
+    - Feature extraction and normalization.
+- Model selection and evaluation
+    - Comparing, validating and choosing parameters and models.
+- Dimensionality reduction
+    - Reducing the number of random variables to consider.
+
+Each group consists of a number of well-known algorithms from the category. For example, one can find hierarchical, spectral, kmeans, and other clustering methods in sklearn.cluster package.
+
+
+.. _Tools offered by this wrapper:
+
+Available tools in the current wrapper
+======================================
+
+The current release of the wrapper offers a subset of the packages from scikit-learn library. You can find:
+
+- A subset of classification metric functions
+- Linear and quadratic discriminant classifiers
+- Random forest and Ada boost classifiers and regressors
+- All the clustering methods
+- All support vector machine classifiers
+- A subset of data preprocessing estimator classes
+- Pairwise metric measurement functions
+
+In addition, several tools for performing matrix operations, generating problem-specific datasets, and encoding text and extracting features have been prepared to help the user with more advanced operations.
+
+.. _Machine learning workflows:
+
+Machine learning workflows
+==========================
+
+Machine learning is about processes. No matter what machine learning algorithm we use, we can apply typical workflows and dataflows to produce more robust models and better predictions.
+Here we discuss supervised and unsupervised learning workflows.
+
+.. _Supervised learning workflows:
+
+Supervised machine learning workflows
+=====================================
+
+**What is supervised learning?**
+
+In this machine learning task, given sample data which are labeled, the aim is to build a model which can predict the labels for new observations.
+In practice, there are five steps which we can go through to start from raw input data and end up getting reasonable predictions for new samples:
+
+1. Preprocess the data::
+
+    * Change the collected data into the proper format and datatype.
+    * Adjust the data quality by filling the missing values, performing
+    required scaling and normalizations, etc.
+    * Extract features which are the most meaningfull for the learning task.
+    * Split the ready dataset into training and test samples.
+
+2. Choose an algorithm::
+
+    * These factors help one to choose a learning algorithm:
+        - Nature of the data (e.g. linear vs. nonlinear data)
+        - Structure of the predicted output (e.g. binary vs. multilabel classification)
+        - Memory and time usage of the training
+        - Predictive accuracy on new data
+        - Interpretability of the predictions
+
+3. Choose a validation method
+
+	Every machine learning model should be evaluated before being put into practicical use.
+	There are numerous performance metrics to evaluate machine learning models.
+	For supervised learning, usually classification or regression metrics are used.
+
+	A validation method helps to evaluate the performance metrics of a trained model in order
+	to optimize its performance or ultimately switch to a more efficient model.
+	Cross-validation is a known validation method.
+
+4. Fit a model
+
+   Given the learning algorithm, validation method, and performance metric(s)
+   repeat the following steps::
+
+    * Train the model.
+    * Evaluate based on metrics.
+    * Optimize unitl satisfied.
+
+5. Use fitted model for prediction::
+
+	This is a final evaluation in which, the optimized model is used to make predictions
+	on unseen (here test) samples. After this, the model is put into production.
+
+.. _Unsupervised learning workflows:
+
+Unsupervised machine learning workflows
+=======================================
+
+**What is unsupervised learning?**
+
+Unlike supervised learning and more liklely in real life, here the initial data is not labeled.
+The task is to extract the structure from the data and group the samples based on their similarities.
+Clustering and dimensionality reduction are two famous examples of unsupervised learning tasks.
+
+In this case, the workflow is as follows::
+
+    * Preprocess the data (without splitting to train and test).
+    * Train a model.
+    * Evaluate and tune parameters.
+    * Analyse the model and test on real data.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fitted_model_eval.py	Tue Apr 13 22:40:10 2021 +0000
@@ -0,0 +1,174 @@
+import argparse
+import json
+import warnings
+
+import pandas as pd
+from galaxy_ml.utils import get_scoring, load_model, read_columns
+from scipy.io import mmread
+from sklearn.metrics.scorer import _check_multimetric_scoring
+from sklearn.model_selection._validation import _score
+from sklearn.pipeline import Pipeline
+
+
+def _get_X_y(params, infile1, infile2):
+    """read from inputs and output X and y
+
+    Parameters
+    ----------
+    params : dict
+        Tool inputs parameter
+    infile1 : str
+        File path to dataset containing features
+    infile2 : str
+        File path to dataset containing target values
+
+    """
+    # store read dataframe object
+    loaded_df = {}
+
+    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"]
+        else:
+            c = None
+
+        df_key = infile1 + repr(header)
+        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"))
+
+    # 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"]
+    else:
+        c = None
+
+    df_key = infile2 + repr(header)
+    if df_key in loaded_df:
+        infile2 = loaded_df[df_key]
+    else:
+        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)
+    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,
+):
+    """
+    Parameter
+    ---------
+    inputs : str
+        File path to galaxy tool parameter
+
+    infile_estimator : strgit
+        File path to trained estimator input
+
+    outfile_eval : str
+        File path to save the evalulation results, tabular
+
+    infile_weights : str
+        File path to weights input
+
+    infile1 : str
+        File path to dataset containing features
+
+    infile2 : str
+        File path to dataset containing target values
+    """
+    warnings.filterwarnings("ignore")
+
+    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:
+        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!"
+            )
+        main_est.load_weights(infile_weights)
+
+    # handle scorer, convert to scorer dict
+    # 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)
+    else:
+        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)
+
+
+if __name__ == "__main__":
+    aparser = argparse.ArgumentParser()
+    aparser.add_argument("-i", "--inputs", dest="inputs", required=True)
+    aparser.add_argument("-e", "--infile_estimator", dest="infile_estimator")
+    aparser.add_argument("-w", "--infile_weights", dest="infile_weights")
+    aparser.add_argument("-X", "--infile1", dest="infile1")
+    aparser.add_argument("-y", "--infile2", dest="infile2")
+    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,
+    )
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/keras_deep_learning.py	Tue Apr 13 22:40:10 2021 +0000
@@ -0,0 +1,372 @@
+import argparse
+import json
+import pickle
+import warnings
+from ast import literal_eval
+
+import keras
+import pandas as pd
+import six
+from galaxy_ml.utils import get_search_params, SafeEval, try_get_attr
+from keras.models import Model, Sequential
+
+
+safe_eval = SafeEval()
+
+
+def _handle_shape(literal):
+    """Eval integer or list/tuple of integers from string
+
+    Parameters:
+    -----------
+    literal : str.
+    """
+    literal = literal.strip()
+    if not literal:
+        return None
+    try:
+        return literal_eval(literal)
+    except NameError as e:
+        print(e)
+        return literal
+
+
+def _handle_regularizer(literal):
+    """Construct regularizer from string literal
+
+    Parameters
+    ----------
+    literal : str. E.g. '(0.1, 0)'
+    """
+    literal = literal.strip()
+    if not literal:
+        return None
+
+    l1, l2 = literal_eval(literal)
+
+    if not l1 and not l2:
+        return None
+
+    if l1 is None:
+        l1 = 0.
+    if l2 is None:
+        l2 = 0.
+
+    return keras.regularizers.l1_l2(l1=l1, l2=l2)
+
+
+def _handle_constraint(config):
+    """Construct constraint from galaxy tool parameters.
+    Suppose correct dictionary format
+
+    Parameters
+    ----------
+    config : dict. E.g.
+        "bias_constraint":
+            {"constraint_options":
+                {"max_value":1.0,
+                "min_value":0.0,
+                "axis":"[0, 1, 2]"
+                },
+            "constraint_type":
+                "MinMaxNorm"
+            }
+    """
+    constraint_type = config['constraint_type']
+    if constraint_type in ('None', ''):
+        return None
+
+    klass = getattr(keras.constraints, constraint_type)
+    options = config.get('constraint_options', {})
+    if 'axis' in options:
+        options['axis'] = literal_eval(options['axis'])
+
+    return klass(**options)
+
+
+def _handle_lambda(literal):
+    return None
+
+
+def _handle_layer_parameters(params):
+    """Access to handle all kinds of parameters
+    """
+    for key, value in six.iteritems(params):
+        if value in ('None', ''):
+            params[key] = None
+            continue
+
+        if type(value) in [int, float, bool]\
+                or (type(value) is str and value.isalpha()):
+            continue
+
+        if key in ['input_shape', 'noise_shape', 'shape', 'batch_shape',
+                   'target_shape', 'dims', 'kernel_size', 'strides',
+                   'dilation_rate', 'output_padding', 'cropping', 'size',
+                   'padding', 'pool_size', 'axis', 'shared_axes'] \
+                and isinstance(value, str):
+            params[key] = _handle_shape(value)
+
+        elif key.endswith('_regularizer') and isinstance(value, dict):
+            params[key] = _handle_regularizer(value)
+
+        elif key.endswith('_constraint') and isinstance(value, dict):
+            params[key] = _handle_constraint(value)
+
+        elif key == 'function':  # No support for lambda/function eval
+            params.pop(key)
+
+    return params
+
+
+def get_sequential_model(config):
+    """Construct keras Sequential model from Galaxy tool parameters
+
+    Parameters:
+    -----------
+    config : dictionary, galaxy tool parameters loaded by JSON
+    """
+    model = Sequential()
+    input_shape = _handle_shape(config['input_shape'])
+    layers = config['layers']
+    for layer in layers:
+        options = layer['layer_selection']
+        layer_type = options.pop('layer_type')
+        klass = getattr(keras.layers, layer_type)
+        kwargs = options.pop('kwargs', '')
+
+        # parameters needs special care
+        options = _handle_layer_parameters(options)
+
+        if kwargs:
+            kwargs = safe_eval('dict(' + kwargs + ')')
+            options.update(kwargs)
+
+        # add input_shape to the first layer only
+        if not getattr(model, '_layers') and input_shape is not None:
+            options['input_shape'] = input_shape
+
+        model.add(klass(**options))
+
+    return model
+
+
+def get_functional_model(config):
+    """Construct keras functional model from Galaxy tool parameters
+
+    Parameters
+    -----------
+    config : dictionary, galaxy tool parameters loaded by JSON
+    """
+    layers = config['layers']
+    all_layers = []
+    for layer in layers:
+        options = layer['layer_selection']
+        layer_type = options.pop('layer_type')
+        klass = getattr(keras.layers, layer_type)
+        inbound_nodes = options.pop('inbound_nodes', None)
+        kwargs = options.pop('kwargs', '')
+
+        # parameters needs special care
+        options = _handle_layer_parameters(options)
+
+        if kwargs:
+            kwargs = safe_eval('dict(' + kwargs + ')')
+            options.update(kwargs)
+
+        # merge layers
+        if 'merging_layers' in options:
+            idxs = literal_eval(options.pop('merging_layers'))
+            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])
+        # input layers
+        else:
+            new_layer = klass(**options)
+
+        all_layers.append(new_layer)
+
+    input_indexes = _handle_shape(config['input_layers'])
+    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]
+
+    return Model(inputs=input_layers, outputs=output_layers)
+
+
+def get_batch_generator(config):
+    """Construct keras online data generator from Galaxy tool parameters
+
+    Parameters
+    -----------
+    config : dictionary, galaxy tool parameters loaded by JSON
+    """
+    generator_type = config.pop('generator_type')
+    if generator_type == 'none':
+        return None
+
+    klass = try_get_attr('galaxy_ml.preprocessors', generator_type)
+
+    if generator_type == 'GenomicIntervalBatchGenerator':
+        config['ref_genome_path'] = 'to_be_determined'
+        config['intervals_path'] = 'to_be_determined'
+        config['target_path'] = 'to_be_determined'
+        config['features'] = 'to_be_determined'
+    else:
+        config['fasta_path'] = 'to_be_determined'
+
+    return klass(**config)
+
+
+def config_keras_model(inputs, outfile):
+    """ config keras model layers and output JSON
+
+    Parameters
+    ----------
+    inputs : dict
+        loaded galaxy tool parameters from `keras_model_config`
+        tool.
+    outfile : str
+        Path to galaxy dataset containing keras model JSON.
+    """
+    model_type = inputs['model_selection']['model_type']
+    layers_config = inputs['model_selection']
+
+    if model_type == 'sequential':
+        model = get_sequential_model(layers_config)
+    else:
+        model = get_functional_model(layers_config)
+
+    json_string = model.to_json()
+
+    with open(outfile, 'w') as f:
+        json.dump(json.loads(json_string), f, indent=2)
+
+
+def build_keras_model(inputs, outfile, model_json, infile_weights=None,
+                      batch_mode=False, outfile_params=None):
+    """ for `keras_model_builder` tool
+
+    Parameters
+    ----------
+    inputs : dict
+        loaded galaxy tool parameters from `keras_model_builder` tool.
+    outfile : str
+        Path to galaxy dataset containing the keras_galaxy model output.
+    model_json : str
+        Path to dataset containing keras model JSON.
+    infile_weights : str or None
+        If string, path to dataset containing model weights.
+    batch_mode : bool, default=False
+        Whether to build online batch classifier.
+    outfile_params : str, default=None
+        File path to search parameters output.
+    """
+    with open(model_json, 'r') as f:
+        json_model = json.load(f)
+
+    config = json_model['config']
+
+    options = {}
+
+    if json_model['class_name'] == 'Sequential':
+        options['model_type'] = 'sequential'
+        klass = Sequential
+    elif json_model['class_name'] == 'Model':
+        options['model_type'] = 'functional'
+        klass = Model
+    else:
+        raise ValueError("Unknow Keras model class: %s"
+                         % json_model['class_name'])
+
+    # load prefitted model
+    if inputs['mode_selection']['mode_type'] == 'prefitted':
+        estimator = klass.from_config(config)
+        estimator.load_weights(infile_weights)
+    # build train model
+    else:
+        cls_name = inputs['mode_selection']['learning_type']
+        klass = try_get_attr('galaxy_ml.keras_galaxy_models', cls_name)
+
+        options['loss'] = (inputs['mode_selection']
+                           ['compile_params']['loss'])
+        options['optimizer'] =\
+            (inputs['mode_selection']['compile_params']
+             ['optimizer_selection']['optimizer_type']).lower()
+
+        options.update((inputs['mode_selection']['compile_params']
+                        ['optimizer_selection']['optimizer_options']))
+
+        train_metrics = inputs['mode_selection']['compile_params']['metrics']
+        if train_metrics[-1] == 'none':
+            train_metrics = train_metrics[:-1]
+        options['metrics'] = train_metrics
+
+        options.update(inputs['mode_selection']['fit_params'])
+        options['seed'] = inputs['mode_selection']['random_seed']
+
+        if batch_mode:
+            generator = get_batch_generator(inputs['mode_selection']
+                                            ['generator_selection'])
+            options['data_batch_generator'] = generator
+            options['prediction_steps'] = \
+                inputs['mode_selection']['prediction_steps']
+            options['class_positive_factor'] = \
+                inputs['mode_selection']['class_positive_factor']
+        estimator = klass(config, **options)
+        if outfile_params:
+            hyper_params = get_search_params(estimator)
+            # TODO: remove this after making `verbose` tunable
+            for h_param in hyper_params:
+                if h_param[1].endswith('verbose'):
+                    h_param[0] = '@'
+            df = pd.DataFrame(hyper_params, columns=['', 'Parameter', 'Value'])
+            df.to_csv(outfile_params, sep='\t', index=False)
+
+    print(repr(estimator))
+    # save model by pickle
+    with open(outfile, 'wb') as f:
+        pickle.dump(estimator, f, pickle.HIGHEST_PROTOCOL)
+
+
+if __name__ == '__main__':
+    warnings.simplefilter('ignore')
+
+    aparser = argparse.ArgumentParser()
+    aparser.add_argument("-i", "--inputs", dest="inputs", required=True)
+    aparser.add_argument("-m", "--model_json", dest="model_json")
+    aparser.add_argument("-t", "--tool_id", dest="tool_id")
+    aparser.add_argument("-w", "--infile_weights", dest="infile_weights")
+    aparser.add_argument("-o", "--outfile", dest="outfile")
+    aparser.add_argument("-p", "--outfile_params", dest="outfile_params")
+    args = aparser.parse_args()
+
+    input_json_path = args.inputs
+    with open(input_json_path, 'r') as param_handler:
+        inputs = json.load(param_handler)
+
+    tool_id = args.tool_id
+    outfile = args.outfile
+    outfile_params = args.outfile_params
+    model_json = args.model_json
+    infile_weights = args.infile_weights
+
+    # for keras_model_config tool
+    if tool_id == 'keras_model_config':
+        config_keras_model(inputs, outfile)
+
+    # for keras_model_builder tool
+    else:
+        batch_mode = False
+        if tool_id == 'keras_batch_models':
+            batch_mode = True
+
+        build_keras_model(inputs=inputs,
+                          model_json=model_json,
+                          infile_weights=infile_weights,
+                          batch_mode=batch_mode,
+                          outfile=outfile,
+                          outfile_params=outfile_params)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/keras_macros.xml	Tue Apr 13 22:40:10 2021 +0000
@@ -0,0 +1,985 @@
+<macros>
+  <token name="@KERAS_VERSION@">0.5.0</token>
+
+  <xml name="macro_stdio">
+    <stdio>
+        <exit_code range="1:" level="fatal" description="Error occurred. Please check Tool Standard Error"/>
+    </stdio>
+  </xml>
+
+  <xml name="keras_optimizer_common" token_lr="0.01">
+    <section name="optimizer_options" title="Optimizer Advanced Options" expanded="false">
+      <param argument="lr" type="float" value="@LR@" optional="true" label="Learning rate" help="float >= 0"/>
+      <yield/>
+      <!--param argument="clipnorm" type="float" value="" optional="true" label="clipnorm" help="float >= 0"/-->
+      <!--param argument="clipvalue" type="float" value="" optional="true" label="clipvalue" help="float >= 0"/-->
+    </section>
+  </xml>
+
+  <xml name="keras_optimizer_common_more" token_lr="0.001">
+    <expand macro="keras_optimizer_common" lr="@LR@">
+      <!--param argument="epsilon" type="float" value="" label="epsilon" optional="true" help="Fuzz factor. If `None`, defaults to `K.epsilon()`"/>-->
+      <param argument="decay" type="float" value="0" optional="true" label="decay" help="Learning rate decay over each update."/>
+      <yield/>
+    </expand>
+  </xml>
+
+  <xml name="keras_activations" token_none="true" token_tanh="false">
+    <param argument="activation" type="select" label="Activation function">
+      <option value="linear" selected="@NONE@">None / linear (default)</option>
+      <option value="softmax">softmax</option>
+      <option value="elu">elu</option>
+      <option value="selu">selu</option>
+      <option value="softplus">softplus</option>
+      <option value="softsign">softsign</option>
+      <option value="relu">relu</option>
+      <option value="tanh" selected="@TANH@">tanh</option>
+      <option value="sigmoid">sigmoid</option>
+      <option value="hard_sigmoid">hard_sigmoid</option>
+      <option value="exponential">tanh</option>
+    </param>
+  </xml>
+
+  <xml name="keras_initializers" token_argument="kernel_initializer" token_default_glorot_uniform="false" token_default_zeros="false" token_default_random_uniform="false" token_default_ones="false">
+    <param argument="@ARGUMENT@" type="select" label="@ARGUMENT@">
+      <option value="zeros" selected="@DEFAULT_ZEROS@">zero / zeros / Zeros</option>
+      <option value="ones" selected="@DEFAULT_ONES@">one / ones / Ones</option>
+      <option value="constant">constant / Constant</option>
+      <option value="random_normal">normal / random_normal / RandomNormal</option>
+      <option value="random_uniform" selected="@DEFAULT_RANDOM_UNIFORM@">uniform / random_uniform / RandomUniform</option>
+      <option value="truncated_normal">truncated_normal / TruncatedNormal</option>
+      <option value="orthogonal">orthogonal / Orthogonal</option>
+      <option value="identity">identity / Identity</option>
+      <option value="glorot_normal">glorot_normal</option>
+      <option value="glorot_uniform" selected="@DEFAULT_GLOROT_UNIFORM@">glorot_uniform</option>
+      <option value="he_normal">he_normal</option>
+      <option value="he_uniform">he_uniform</option>
+      <option value="lecun_normal">lecun_normal</option>
+      <option value="lecun_uniform">lecun_uniform</option>
+    </param>
+  </xml>
+
+  <xml name="keras_regularizers" token_argument="kernel_regularizer">
+    <param argument="@ARGUMENT@" type="text" value="(0. , 0.)" optional="true" label="@ARGUMENT@"
+            help="(l1, l2). l1/l2: float; L1/l2 regularization factor. (0., 0.) is equivalent to `None`"/>
+  </xml>
+
+  <xml name="keras_constraints_options">
+    <section name="constraint_options" title="Constraint Advanced Options" expanded="false">
+      <yield/>
+      <param argument="axis" type="text" value="0" help="Integer or list of integers. axis along which to calculate weight norms">
+        <sanitizer>
+          <valid initial="default">
+            <add value="["/>
+            <add value="]"/>
+          </valid>
+        </sanitizer>
+      </param>
+    </section>
+  </xml>
+
+  <xml name="keras_constraints" token_argument="kernel_constraint">
+    <conditional name="@ARGUMENT@">
+      <param argument="constraint_type" type="select" label="@ARGUMENT@">
+        <option value="None" selected="true">None (default)</option>
+        <option value="MaxNorm">maxnorm / max_norm / MaxNorm</option>
+        <option value="NonNeg">nonneg / non_neg / NonNeg</option>
+        <option value="UnitNorm">unitnorm / unit_norm / UnitNorm</option>
+        <option value="MinMaxNorm">min_max_norm / MinMaxNorm</option>
+      </param>
+      <when value="None"/>
+      <when value="MaxNorm">
+        <expand macro="keras_constraints_options">
+          <param argument="max_value" type="float" value="2" help="the maximum norm for the incoming weights."/>
+        </expand>
+      </when>
+      <when value="NonNeg">
+      </when>
+      <when value="UnitNorm">
+        <expand macro="keras_constraints_options"/>
+      </when>
+      <when value="MinMaxNorm">
+        <expand macro="keras_constraints_options">
+          <param argument="min_value" type="float" value="0." help="the minimum norm for the incoming weights."/>
+          <param argument="max_value" type="float" value="1." help="the maximum norm for the incoming weights."/>
+          <param argument="max_value" type="float" value="1." help="rate for enforcing the constraint."/>
+        </expand>
+      </when>
+    </conditional>
+  </xml>
+
+  <xml name="keras_layer_types_core">
+    <option value="Dense">Core -- Dense</option>
+    <option value="Activation">Core -- Activation</option>
+    <option value="Dropout">Core -- Dropout</option>
+    <option value="Flatten">Core -- Flatten</option>
+    <option value="Reshape">Core -- Reshape</option>
+    <option value="Permute">Core -- Permute</option>
+    <option value="RepeatVector">Core -- RepeatVector</option>
+    <!--option value="Lambda">Lambda - Not supported</option-->
+    <option value="ActivityRegularization">Core -- ActivityRegularization</option>
+    <option value="Masking">Core -- Masking</option>
+    <option value="SpatialDropout1D">Core -- SpatialDropout1D</option>
+    <option value="SpatialDropout2D">Core -- SpatialDropout2D</option>
+    <option value="SpatialDropout3D">Core -- SpatialDropout3D</option>
+  </xml>
+
+  <xml name="keras_layer_types_Convolutional">
+    <option value="Conv1D">Convolutional -- Conv1D</option>
+    <option value="Conv2D">Convolutional -- Conv2D</option>
+    <option value="SeparableConv1D">Convolutional -- SeparableConv1D</option>
+    <option value="SeparableConv2D">Convolutional -- SeparableConv2D</option>
+    <option value="DepthwiseConv2D">Convolutional -- DepthwiseConv2D</option>
+    <option value="Conv2DTranspose">Convolutional -- Conv2DTranspose</option>
+    <option value="Conv3D">Convolutional -- Conv3D</option>
+    <option value="Conv3DTranspose">Convolutional -- Conv3DTranspose</option>
+    <option value="Cropping1D">Convolutional -- Cropping1D</option>
+    <option value="Cropping2D">Convolutional -- Cropping2D</option>
+    <option value="Cropping3D">Convolutional -- Cropping3D</option>
+    <option value="UpSampling1D">Convolutional -- UpSampling1D</option>
+    <option value="UpSampling2D">Convolutional -- UpSampling2D</option>
+    <option value="UpSampling3D">Convolutional -- UpSampling3D</option>
+    <option value="ZeroPadding1D">Convolutional -- ZeroPadding1D</option>
+    <option value="ZeroPadding2D">Convolutional -- ZeroPadding2D</option>
+    <option value="ZeroPadding3D">Convolutional -- ZeroPadding3D</option>
+  </xml>
+
+  <xml name="keras_layer_types_Pooling">
+    <option value="MaxPooling1D">Pooling -- MaxPooling1D</option>
+    <option value="MaxPooling2D">Pooling -- MaxPooling2D</option>
+    <option value="MaxPooling3D">Pooling -- MaxPooling3D</option>
+    <option value="AveragePooling1D">Pooling -- AveragePooling1D</option>
+    <option value="AveragePooling2D">Pooling -- AveragePooling2D</option>
+    <option value="AveragePooling3D">Pooling -- AveragePooling3D</option>
+    <option value="GlobalMaxPooling1D">Pooling -- GlobalMaxPooling1D</option>
+    <option value="GlobalAveragePooling1D">Pooling -- GlobalAveragePooling1D</option>
+    <option value="GlobalMaxPooling2D">Pooling -- GlobalMaxPooling2D</option>
+    <option value="GlobalAveragePooling2D">Pooling -- GlobalAveragePooling2D</option>
+    <option value="GlobalMaxPooling3D">Pooling -- GlobalMaxPooling3D</option>
+    <option value="GlobalAveragePooling3D">Pooling -- GlobalAveragePooling3D</option>
+  </xml>
+
+  <xml name="keras_layer_types_locally_connected">
+    <option value="LocallyConnected1D">Locally_connected -- LocallyConnected1D</option>
+    <option value="LocallyConnected2D">Locally_connected -- LocallyConnected2D</option>
+  </xml>
+
+  <xml name="keras_layer_types_recurrent">
+    <option value="SimpleRNN">Recurrent -- SimpleRNN</option>
+    <option value="GRU">Recurrent -- GRU</option>
+    <option value="LSTM">Recurrent -- LSTM</option>
+    <option value="ConvLSTM2D">Recurrent -- ConvLSTM2D</option>
+    <option value="ConvLSTM2DCell">Recurrent -- ConvLSTM2DCell</option>
+    <option value="SimpleRNNCell">Recurrent -- SimpleRNNCell</option>
+    <option value="GRUCell">Recurrent -- GRUCell</option>
+    <option value="LSTMCell">Recurrent -- LSTMCell</option>
+    <option value="CuDNNGRU">Recurrent -- CuDNNGRU</option>
+    <option value="CuDNNLSTM">Recurrent -- CuDNNLSTM</option>
+  </xml>
+
+  <xml name="keras_layer_types_embedding">
+    <option value="Embedding">Embedding -- Embedding</option>
+  </xml>
+
+  <xml name="keras_layer_types_advanced_activations">
+    <option value="LeakyReLU">Advanced activations -- LeakyReLU</option>
+    <option value="PReLU">Advanced activations -- PReLU</option>
+    <option value="ELU">Advanced activations -- ELU</option>
+    <option value="ThresholdedReLU">Advanced activations -- ThresholdedReLU</option>
+    <option value="Softmax">Advanced activations -- Softmax</option>
+    <option value="ReLU">Advanced activations -- ReLU</option>
+  </xml>
+
+  <xml name="keras_layer_types_normalization">
+    <option value="BatchNormalization">Normalization -- BatchNormalization</option>
+  </xml>
+
+  <xml name="keras_layer_types_noise">
+    <option value="GaussianNoise">Noise -- GaussianNoise</option>
+    <option value="GaussianDropout">Noise -- GaussianDropout</option>
+    <option value="AlphaDropout">Noise -- AlphaDropout</option>    
+  </xml>
+
+  <xml name="keras_layer_types_merge">
+    <option value="Add">Merge -- Add</option>
+    <option value="Subtract">Merge -- Subtract</option>
+    <option value="Multiply">Merge -- Multiply</option>
+    <option value="Average">Merge -- Average</option>
+    <option value="Maximum">Merge -- Maximum</option>
+    <option value="Minimum">Merge -- Minimum</option>
+    <option value="Concatenate">Merge -- Concatenate</option>
+    <option value="Dot">Merge -- Dot</option>
+  </xml>
+
+  <!--Core Layers-->
+
+  <xml name="layer_Dense">
+    <param argument="units" type="integer" value="" optional="false" label="units" help="Positive integer, dimensionality of the output space."/>
+    <expand macro="keras_activations"/>
+    <expand macro="simple_kwargs" help="For example: use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zeros', kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, bias_constraint=None. Leave blank for default."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_Dropout">
+    <param argument="rate" type="float" value="" min="0." max="1.0" help="Fraction of the input units to drop."/>
+    <expand macro="simple_kwargs" help="For example: noise_shape=None, seed=None. Leave blank for default."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_Flatten">
+    <param argument="data_format" type="select" help="The ordering of the dimensions in the inputs.">
+      <option value="channels_last">channels_last</option>
+      <option value="channels_first">channels_first</option>
+    </param>
+    <yield/>
+  </xml>
+
+  <xml name="layer_Input">
+    <param argument="shape" type="text" value="" help="A shape tuple (integer), not including the batch size.For instance, `shape=(32,)`"/>
+    <!--param argument="batch_shape" type="text" value="" optional="true" help="A shape tuple (integer), including the batch size.For instance, `batch_shape=(10, 32)`"/-->
+    <param argument="name" type="text" value="" optional="true" help="An optional string name for the layer. Unique. autogenerated if it isn't provided."/>
+    <param argument="dtype" type="select" help="The data type expected by the input">
+      <option value="float32" selected="true">float32</option>
+      <option value="float64">float64</option>
+      <option value="int32">int32</option>
+      <option value="int64">int64</option>
+      <!--TODO add more DTYPEs-->
+    </param>
+    <param argument="sparse" type="boolean" truevalue="booltrue" falsevalue="boolfalse" optional="true" checked="false" />
+    <!--param argument="tensor" type="data" format="zip" help="Optional existing tensor to wrap into the `Input` layer."/ -->
+    <yield/>
+  </xml>
+
+  <xml name="layer_Reshape">
+    <param argument="target_shape" type="text" value="" help="Tuple of integers. Does not include the batch axis."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_Permute">
+    <param argument="dims" type="text" value="" help="Tuple of integers. Permutation pattern, does not include the samples dimension. 
+            Indexing starts at 1. For instance, (2, 1) permutes the first and second dimension of the input."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_RepeatVector">
+    <param argument="n" type="integer" value="" help="repetition factor"/>
+  </xml>
+
+  <xml name="layer_Lambda">
+    <param argument="function" type="text" value="lambda x: " help="The function to be evaluated. Only lambda function is supported!"/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_ActivityRegularization">
+    <param argument="l1" type="float" value="0." min="0." help="L1 regularization factor (positive float)."/>
+    <param argument="l2" type="float" value="0." min="0." help="L2 regularization factor (positive float)."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_Masking">
+    <param argument="mask_value" type="float" value="0." help="Masks a sequence by using a mask value to skip timesteps."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_SpatialDropout1D">
+    <param argument="rate" type="float" value="" min="0." max="1." help="Fraction of the input units to drop."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_SpatialDropout2D">
+    <param argument="rate" type="float" value="" min="0." max="1." help="Fraction of the input units to drop."/>
+    <expand macro="simple_kwargs" help="For example: data_format=None. Leave blank for default."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_SpatialDropout3D">
+    <param argument="rate" type="float" value="" min="0." max="1." help="Fraction of the input units to drop."/>
+    <expand macro="simple_kwargs" help="For example: data_format=None. Leave blank for default."/>
+    <yield/>
+  </xml>
+
+  <!--Convolutional Layers-->
+
+  <xml name="layer_Conv1D">
+    <param argument="filters" type="integer" value="" min="0" help="the dimensionality of the output space (i.e. the number of output filters in the convolution)."/>
+    <param argument="kernel_size" type="text" value="" help="An integer or tuple/list of a single integer, specifying the length of the 1D convolution window."/>
+    <expand macro="keras_activations"/>
+    <expand macro="simple_kwargs" help="For example: strides=1, padding='valid', data_format='channels_last', dilation_rate=1, use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zeros', kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, bias_constraint=None. Leave blank for default."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_Conv2D">
+    <param argument="filters" type="integer" value="" min="0" help="the dimensionality of the output space (i.e. the number of output filters in the convolution)."/>
+    <param argument="kernel_size" type="text" value="" help="An integer or tuple/list of 2 integers, specifying the height and width of the 2D convolution window."/>
+    <expand macro="keras_activations"/>
+    <expand macro="simple_kwargs" help="For example: strides=(1, 1), padding='valid', data_format=None, dilation_rate=(1, 1), use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zeros', kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, bias_constraint=None. Leave blank for default."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_SeparableConv1D">
+    <param argument="filters" type="integer" value="" min="0" help="the dimensionality of the output space (i.e. the number of output filters in the convolution)."/>
+    <param argument="kernel_size" type="text" value="" help="An integer or tuple/list of a single integer, specifying the length of the 1D convolution window."/>
+    <expand macro="keras_activations"/>
+    <expand macro="simple_kwargs" help="For example: strides=1, padding='valid', data_format='channels_last', dilation_rate=1, depth_multiplier=1, use_bias=True, depthwise_initializer='glorot_uniform', pointwise_initializer='glorot_uniform', bias_initializer='zeros', depthwise_regularizer=None, pointwise_regularizer=None, bias_regularizer=None, activity_regularizer=None, depthwise_constraint=None, pointwise_constraint=None, bias_constraint=None. Leave blank for default."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_SeparableConv2D">
+    <param argument="filters" type="integer" value="" min="0" help="the dimensionality of the output space (i.e. the number of output filters in the convolution)."/>
+    <param argument="kernel_size" type="text" value="" help="An integer or tuple/list of 2 integers, specifying the height and width of the 2D convolution window."/>
+    <expand macro="keras_activations"/>
+    <expand macro="simple_kwargs" help="For example: strides=(1, 1), padding='valid', data_format=None, dilation_rate=(1, 1), depth_multiplier=1, use_bias=True, depthwise_initializer='glorot_uniform', pointwise_initializer='glorot_uniform', bias_initializer='zeros', depthwise_regularizer=None, pointwise_regularizer=None, bias_regularizer=None, activity_regularizer=None, depthwise_constraint=None, pointwise_constraint=None, bias_constraint=None. Leave blank for default."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_DepthwiseConv2D">
+    
+    <param argument="kernel_size" type="text" value="" help="An integer or tuple/list of 2 integers, specifying the height and width of the 2D convolution window."/>
+    <expand macro="keras_activations"/>
+    <expand macro="simple_kwargs" help="For example: strides=(1, 1), padding='valid', depth_multiplier=1, data_format=None, use_bias=True, depthwise_initializer='glorot_uniform', bias_initializer='zeros', depthwise_regularizer=None, bias_regularizer=None, activity_regularizer=None, depthwise_constraint=None, bias_constraint=None. Leave blank for default."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_Conv2DTranspose">
+    <param argument="filters" type="integer" value="" min="0" help="the dimensionality of the output space (i.e. the number of output filters in the convolution)."/>
+    <param argument="kernel_size" type="text" value="" help="An integer or tuple/list of 2 integers, specifying the height and width of the 2D convolution window."/>
+    <expand macro="keras_activations"/>
+    <expand macro="simple_kwargs" help="For example: strides=(1, 1), padding='valid', output_padding=None, data_format=None, dilation_rate=(1, 1), use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zeros', kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, bias_constraint=None. Leave blank for default."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_Conv3D">
+    <param argument="filters" type="integer" value="" min="0" help="the dimensionality of the output space (i.e. the number of output filters in the convolution)."/>
+    <param argument="kernel_size" type="text" value="" help="An integer or tuple/list of 3 integers, specifying the depth, height and width of the 3D convolution window."/>
+    <expand macro="keras_activations"/>
+    <expand macro="simple_kwargs" help="For example: strides=(1, 1, 1), padding='valid', data_format=None, dilation_rate=(1, 1, 1), use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zeros', kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, bias_constraint=None. Leave blank for default."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_Conv3DTranspose">
+    <param argument="filters" type="integer" value="" min="0" help="the dimensionality of the output space (i.e. the number of output filters in the convolution)."/>
+    <param argument="kernel_size" type="text" value="" help="An integer or tuple/list of 3 integers, specifying the depth, height and width of the 3D convolution window."/>
+    <expand macro="keras_activations"/>
+    <expand macro="simple_kwargs" help="For example: strides=(1, 1, 1), padding='valid', output_padding=None, data_format=None, activation=None, use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zeros', kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, bias_constraint=None. Leave blank for default."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_Cropping1D">
+    <param argument="cropping" type="text" value="(1, 1)" help="int or tuple of int (length 2) How many units should be trimmed off at the beginning and end of the cropping dimension (axis 1). If a single int is provided, the same value will be used for both."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_Cropping2D">
+    <param argument="cropping" type="text" value="((0, 0), (0, 0))" help="int, or tuple of 2 ints, or tuple of 2 tuples of 2 ints."/>
+    <expand macro="simple_kwargs" help="For example: data_format=None. Leave blank for default."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_Cropping3D">
+    <param argument="cropping" type="text" value="((1, 1), (1, 1), (1, 1))" help="int, or tuple of 3 ints, or tuple of 3 tuples of 2 ints."/>
+    <expand macro="simple_kwargs" help="For example: data_format=None. Leave blank for default."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_UpSampling1D">
+    <param argument="size" type="integer" value="2" min="0" help="integer. Upsampling factor."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_UpSampling2D">
+    <param argument="size" type="text" value="(2, 2)" help="int, or tuple of 2 integers. The upsampling factors for rows and columns."/>
+    <expand macro="simple_kwargs" help="For example: data_format=None, interpolation='nearest'. Leave blank for default."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_UpSampling3D">
+    <param argument="size" type="text" value="(2, 2, 2)" help="int, or tuple of 3 integers. The upsampling factors for dim1, dim2 and dim3."/>
+    <expand macro="simple_kwargs" help="For example: data_format=None, interpolation='nearest'. Leave blank for default."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_ZeroPadding1D">
+    <param argument="padding" type="text" value="1" help="int, or tuple of int (length 2)"/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_ZeroPadding2D">
+    <param argument="padding" type="text" value="(1, 1)" help="int, or tuple of 2 ints, or tuple of 2 tuples of 2 ints."/>
+    <expand macro="simple_kwargs" help="For example: data_format=None. Leave blank for default."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_ZeroPadding3D">
+    <param argument="padding" type="text" value="(1, 1, 1)" help="int, or tuple of 3 ints, or tuple of 3 tuples of 2 ints."/>
+    <expand macro="simple_kwargs" help="For example: data_format=None. Leave blank for default."/>
+    <yield/>
+  </xml>
+
+  <!--Pooling Layers-->
+
+  <xml name="layer_MaxPooling1D">
+    <param name="pool_size" type="integer" value="2" help="Integer, size of the max pooling windows."/>
+    <param name="strides" type="integer" value="" help="Integer, or None. Factor by which to downscale. E.g. 2 will halve the input. If None, it will default to pool_size."/>
+    <expand macro="simple_kwargs" help="For example: padding='valid', data_format='channels_last'. Leave blank for default."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_MaxPooling2D">
+    <param name="pool_size" type="text" value="(2, 2)" help="integer or tuple of 2 integers, factors by which to downscale (vertical, horizontal)"/>
+    <param name="strides" type="text" value="" help="Integer, tuple of 2 integers, or None. Strides values. If None, it will default to pool_size."/>
+    <expand macro="simple_kwargs" help="For example: padding='valid', data_format='channels_last'. Leave blank for default."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_MaxPooling3D">
+    <param name="pool_size" type="text" value="(2, 2, 2)" help="tuple of 3 integers, factors by which to downscale (dim1, dim2, dim3). 
+                                                                (2, 2, 2) will halve the size of the 3D input in each dimension."/>
+    <param name="strides" type="text" value="" help="tuple of 3 integers, or None. If None, it will default to pool_size."/>
+    <expand macro="simple_kwargs" help="For example: padding='valid', data_format='channels_last'. Leave blank for default."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_AveragePooling1D">
+    <param name="pool_size" type="integer" value="2" help="Integer, size of the max pooling windows."/>
+    <param name="strides" type="integer" value="" help="Integer, or None. Factor by which to downscale. E.g. 2 will halve the input. If None, it will default to pool_size."/>
+    <expand macro="simple_kwargs" help="For example: padding='valid', data_format='channels_last'. Leave blank for default."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_AveragePooling2D">
+    <param name="pool_size" type="text" value="(2, 2)" help="integer or tuple of 2 integers, factors by which to downscale (vertical, horizontal)"/>
+    <param name="strides" type="text" value="" help=" Integer, tuple of 2 integers, or None. Strides values. If None, it will default to pool_size."/>
+    <expand macro="simple_kwargs" help="For example: padding='valid', data_format='channels_last'. Leave blank for default."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_AveragePooling3D">
+    <param name="pool_size" type="text" value="(2, 2, 2)" help="tuple of 3 integers, factors by which to downscale (dim1, dim2, dim3). 
+                                                                (2, 2, 2) will halve the size of the 3D input in each dimension."/>
+    <param name="strides" type="text" value="" help="tuple of 3 integers, or None. If None, it will default to pool_size."/>
+    <expand macro="simple_kwargs" help="For example: padding='valid', data_format='channels_last'. Leave blank for default."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_GlobalMaxPooling1D">
+    <param argument="data_format" type="select" help="The ordering of the dimensions in the inputs.">
+      <option value="channels_last" selected="true">channels_last - inputs with shape  (batch, steps, channels)</option>
+      <option value="channels_first">channels_first - inputs with shape (batch, channels, steps)</option>
+    </param>
+    <yield/>
+  </xml>
+
+  <xml name="layer_GlobalMaxPooling2D">
+    <param argument="data_format" type="select" help="The ordering of the dimensions in the inputs.">
+        <option value="channels_last" selected="true">channels_last - inputs with shape (batch, height, width, channels)</option>
+        <option value="channels_first">channels_first - inputs with shape (batch, channels, height, width)</option>
+    </param>
+    <yield/>
+  </xml>
+
+  <xml name="layer_GlobalMaxPooling3D">
+    <param argument="data_format" type="select" help="The ordering of the dimensions in the inputs.">
+      <option value="channels_last" selected="true">channels_last - inputs with shape (batch, spatial_dim1, spatial_dim2, spatial_dim3, channels)</option>
+      <option value="channels_first">channels_first - inputs with shape (batch, channels, spatial_dim1, spatial_dim2, spatial_dim3)</option>
+    </param>
+    <yield/>
+  </xml>
+
+  <xml name="layer_GlobalAveragePooling1D">
+    <param argument="data_format" type="select" help="The ordering of the dimensions in the inputs.">
+      <option value="channels_last" selected="true">channels_last - inputs with shape  (batch, steps, channels)</option>
+      <option value="channels_first">channels_first - inputs with shape (batch, channels, steps)</option>
+    </param>
+    <yield/>
+  </xml>
+
+  <xml name="layer_GlobalAveragePooling2D">
+    <param argument="data_format" type="select" help="The ordering of the dimensions in the inputs.">
+        <option value="channels_last" selected="true">channels_last - inputs with shape (batch, height, width, channels)</option>
+        <option value="channels_first">channels_first - inputs with shape (batch, channels, height, width)</option>
+    </param>
+    <yield/>
+  </xml>
+
+  <xml name="layer_GlobalAveragePooling3D">
+    <param argument="data_format" type="select" help="The ordering of the dimensions in the inputs.">
+      <option value="channels_last" selected="true">channels_last - inputs with shape (batch, spatial_dim1, spatial_dim2, spatial_dim3, channels)</option>
+      <option value="channels_first">channels_first - inputs with shape (batch, channels, spatial_dim1, spatial_dim2, spatial_dim3)</option>
+    </param>
+    <yield/>
+  </xml>
+
+  <!--Locally-connected Layers-->
+
+  <xml name="layer_LocallyConnected1D">
+    <param argument="filters" type="integer" value="" min="0" help="the dimensionality of the output space (i.e. the number of output filters in the convolution)."/>
+    <param argument="kernel_size" type="text" value="" help="An integer or tuple/list of a single integer, specifying the length of the 1D convolution window."/>
+    <expand macro="keras_activations"/>
+    <expand macro="simple_kwargs" help="For example: strides=1, padding='valid', data_format=None, use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zeros', kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, bias_constraint=None. Leave blank for default."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_LocallyConnected2D">
+    <param argument="filters" type="integer" value="" min="0" help="the dimensionality of the output space (i.e. the number of output filters in the convolution)."/>
+    <param argument="kernel_size" type="text" value="" help="An integer or tuple/list of 2 integers, specifying the height and width of the 2D convolution window."/>
+    <expand macro="keras_activations"/>
+    <expand macro="simple_kwargs" help="For example: strides=(1, 1), padding='valid', data_format=None, use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zeros', kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, bias_constraint=None. Leave blank for default."/>
+    <yield/>
+  </xml>
+
+  <!--Recurrent Layers-->
+
+  <xml name="layer_SimpleRNN">
+    <param argument="units" type="integer" value="" min="1" help="Positive integer, dimensionality of the output space."/>
+    <expand macro="simple_kwargs" help="For example: activation='tanh', use_bias=True, kernel_initializer='glorot_uniform', recurrent_initializer='orthogonal', bias_initializer='zeros', kernel_regularizer=None, recurrent_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, recurrent_constraint=None, bias_constraint=None, dropout=0.0, recurrent_dropout=0.0, return_sequences=False, return_state=False, go_backwards=False, stateful=False, unroll=False. Leave blank for default."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_GRU">
+    <param argument="units" type="integer" value="" min="1" help="Positive integer, dimensionality of the output space."/>
+    <expand macro="simple_kwargs" help="For example: activation='tanh', recurrent_activation='hard_sigmoid', use_bias=True, kernel_initializer='glorot_uniform', recurrent_initializer='orthogonal', bias_initializer='zeros', kernel_regularizer=None, recurrent_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, recurrent_constraint=None, bias_constraint=None, dropout=0.0, recurrent_dropout=0.0, implementation=1, return_sequences=False, return_state=False, go_backwards=False, stateful=False, unroll=False, reset_after=False. Leave blank for default."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_LSTM">
+    <param argument="units" type="integer" value="" min="1" help="Positive integer, dimensionality of the output space."/>
+    <expand macro="simple_kwargs" help="For example: activation='tanh', recurrent_activation='hard_sigmoid', use_bias=True, kernel_initializer='glorot_uniform', recurrent_initializer='orthogonal', bias_initializer='zeros', unit_forget_bias=True, kernel_regularizer=None, recurrent_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, recurrent_constraint=None, bias_constraint=None, dropout=0.0, recurrent_dropout=0.0, implementation=1, return_sequences=False, return_state=False, go_backwards=False, stateful=False, unroll=False. Leave blank for default."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_ConvLSTM2D">
+    <param argument="filters" type="integer" value="" min="0" help="the dimensionality of the output space (i.e. the number of output filters in the convolution)."/>
+    <param argument="kernel_size" type="text" value="" help="An integer or tuple/list of n integers, specifying the dimensions of the convolution window."/>
+    <expand macro="simple_kwargs" help="For example: strides=(1, 1), padding='valid', data_format=None, dilation_rate=(1, 1), activation='tanh', recurrent_activation='hard_sigmoid', use_bias=True, kernel_initializer='glorot_uniform', recurrent_initializer='orthogonal', bias_initializer='zeros', unit_forget_bias=True, kernel_regularizer=None, recurrent_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, recurrent_constraint=None, bias_constraint=None, return_sequences=False, go_backwards=False, stateful=False, dropout=0.0, recurrent_dropout=0.0. Leave blank for default."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_ConvLSTM2DCell">
+    <param argument="filters" type="integer" value="" min="0" help="the dimensionality of the output space (i.e. the number of output filters in the convolution)."/>
+    <param argument="kernel_size" type="text" value="" help="An integer or tuple/list of n integers, specifying the dimensions of the convolution window."/>
+    <expand macro="simple_kwargs" help="For example: strides=(1, 1), padding='valid', data_format=None, dilation_rate=(1, 1), activation='tanh', recurrent_activation='hard_sigmoid', use_bias=True, kernel_initializer='glorot_uniform', recurrent_initializer='orthogonal', bias_initializer='zeros', unit_forget_bias=True, kernel_regularizer=None, recurrent_regularizer=None, bias_regularizer=None, kernel_constraint=None, recurrent_constraint=None, bias_constraint=None, dropout=0.0, recurrent_dropout=0.0. Leave blank for default."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_SimpleRNNCell">
+    <param argument="units" type="integer" value="" min="1" help="Positive integer, dimensionality of the output space."/>
+    <expand macro="simple_kwargs" help="For example: activation='tanh', use_bias=True, kernel_initializer='glorot_uniform', recurrent_initializer='orthogonal', bias_initializer='zeros', kernel_regularizer=None, recurrent_regularizer=None, bias_regularizer=None, kernel_constraint=None, recurrent_constraint=None, bias_constraint=None, dropout=0.0, recurrent_dropout=0.0. Leave blank for default."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_GRUCell">
+    <param argument="units" type="integer" value="" min="1" help="Positive integer, dimensionality of the output space."/>
+    <expand macro="simple_kwargs" help="For example: activation='tanh', recurrent_activation='hard_sigmoid', use_bias=True, kernel_initializer='glorot_uniform', recurrent_initializer='orthogonal', bias_initializer='zeros', kernel_regularizer=None, recurrent_regularizer=None, bias_regularizer=None, kernel_constraint=None, recurrent_constraint=None, bias_constraint=None, dropout=0.0, recurrent_dropout=0.0, implementation=1, reset_after=False. Leave blank for default."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_LSTMCell">
+    <param argument="units" type="integer" value="" min="1" help="Positive integer, dimensionality of the output space."/>
+    <expand macro="simple_kwargs" help="For example: activation='tanh', recurrent_activation='hard_sigmoid', use_bias=True, kernel_initializer='glorot_uniform', recurrent_initializer='orthogonal', bias_initializer='zeros', unit_forget_bias=True, kernel_regularizer=None, recurrent_regularizer=None, bias_regularizer=None, kernel_constraint=None, recurrent_constraint=None, bias_constraint=None, dropout=0.0, recurrent_dropout=0.0, implementation=1. Leave blank for default."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_CuDNNGRU">
+    <param argument="units" type="integer" value="" min="1" help="Positive integer, dimensionality of the output space."/>
+    <expand macro="simple_kwargs" help="For example: kernel_initializer='glorot_uniform', recurrent_initializer='orthogonal', bias_initializer='zeros', kernel_regularizer=None, recurrent_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, recurrent_constraint=None, bias_constraint=None, return_sequences=False, return_state=False, stateful=False. Leave blank for default."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_CuDNNLSTM">
+    <param argument="units" type="integer" value="" min="1" help="Positive integer, dimensionality of the output space."/>
+    <expand macro="simple_kwargs" help="For example: kernel_initializer='glorot_uniform', recurrent_initializer='orthogonal', bias_initializer='zeros', unit_forget_bias=True, kernel_regularizer=None, recurrent_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, recurrent_constraint=None, bias_constraint=None, return_sequences=False, return_state=False, stateful=False. Leave blank for default."/>
+    <yield/>
+  </xml>
+
+
+  <!--Embedding Layers-->
+
+  <xml name="layer_Embedding">
+    <param argument="input_dim" type="integer" value="" min="0" help="int > 0. Size of the vocabulary, i.e. maximum integer index + 1."/>
+    <param argument="output_dim" type="integer" value="" min="0" help="int >= 0. Dimension of the dense embedding."/>
+    <expand macro="simple_kwargs" help="For example: embeddings_initializer='uniform', embeddings_regularizer=None, activity_regularizer=None, embeddings_constraint=None, mask_zero=False, input_length=None. Leave blank for default."/>
+    <yield/>
+  </xml>
+
+  <!--Merge Layers-->
+
+  <xml name="layer_merge">
+    <param name="merging_layers" type="text" value="[ ]" label="Type the layer index numbers in a list" help="List of numbers">
+      <sanitizer>
+        <valid initial="default">
+          <add value="["/>
+          <add value="]"/>
+        </valid>
+      </sanitizer>
+    </param>
+    <yield/>
+  </xml>
+
+  <xml name="layer_Concatenate" token_type="integer" token_default_value="-1" token_help="Axis along which to concatenate.">
+    <expand macro="layer_merge">
+      <param argument="axis" type="@TYPE@" value="@DEFAULT_VALUE@" help="@HELP@"/>
+    </expand>
+    <yield/>
+  </xml>
+
+  <xml name="layer_Dot">
+    <expand macro="layer_Concatenate" type="text" default_value="" help="Integer or tuple of integers, axis or axes along which to take the dot product.">
+      <param argument="normalize" type="boolean" truevalue="booltrue" falsevalue="boolfalse" optional="true" checked="false" label="Whether to L2-normalize samples along the dot product axis before taking the dot product?"/>
+    </expand>
+    <yield/>
+  </xml>
+
+  <!--Advanced Activations Layers-->
+
+  <xml name="layer_LeakyReLU">
+    <param argument="alpha" type="float" value="0.3" min="0." help="float >= 0. Negative slope coefficient."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_PReLU">
+    <expand macro="keras_initializers" argument="alpha_initializer" default_zeros="true"/>
+    <expand macro="keras_regularizers" argument="alpha_regularizer"/>
+    <expand macro="keras_constraints" argument="alpha_constraint"/>
+    <param argument="shared_axes" type="text" value="" help="the axes along which to share learnable parameters for the activation function. E.g. [1, 2]">
+      <sanitizer>
+        <valid initial="default">
+          <add value="["/>
+          <add value="]"/>
+        </valid>
+      </sanitizer>
+    </param>
+    <yield/>
+  </xml>
+
+  <xml name="layer_ELU">
+    <param argument="alpha" type="float" value="1.0" help="scale for the negative factor."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_ThresholdedReLU">
+    <param argument="theta" type="float" value="1.0" help="float >= 0. Threshold location of activation."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_Softmax">
+    <param argument="axis" type="integer" value="-1" help="Integer, axis along which the softmax normalization is applied."/>
+    <yield/>
+  </xml>
+
+  <xml name="layer_ReLU">
+    <param argument="max_value" type="float" value="" min="0." help="float >= 0. Maximum activation value."/>
+    <param argument="negative_slope" type="float" value="0." min="0." help="float >= 0. Negative slope coefficient."/>
+    <param argument="max_value" type="float" value="0." help="float. Threshold value for thresholded activation."/>
+    <yield/>
+  </xml>
+
+  <!--Normalization Layers-->
+
+  <xml name="layer_BatchNormalization">
+    <expand macro="simple_kwargs" help="For example: axis=-1, momentum=0.99, epsilon=0.001, center=True, scale=True, beta_initializer='zeros', gamma_initializer='ones', moving_mean_initializer='zeros', moving_variance_initializer='ones', beta_regularizer=None, gamma_regularizer=None, beta_constraint=None, gamma_constraint=None. Leave blank for default."/>
+  </xml>
+
+  <!--Noise layers-->
+
+  <xml name="layer_GaussianNoise">
+    <param argument="stddev" type="float" value="" help="float, standard deviation of the noise distribution."/>
+  </xml>
+
+  <xml name="layer_GaussianDropout">
+    <param argument="rate" type="float" value="" help="drop probability, (as with `Dropout`). The multiplicative noise will have standard deviation `sqrt(rate / (1 - rate))`"/>
+  </xml>
+
+  <xml name="layer_AlphaDropout">
+    <expand macro="layer_Dropout"/>
+  </xml>
+
+  <xml name="inbound_nodes_index">
+    <param name="inbound_nodes" type="integer" value="" label="Type the index number of input layer"
+          help="Find the index number at the left top corner of layer configuration block"/>
+  </xml>
+
+  <!--Simple key words text parameters, conbined to reduce UI latency-->
+
+  <xml name="simple_kwargs" token_help="Leave blank for default.">
+    <param argument="kwargs" type="text" value="" label="Type in key words arguments if different from the default" help="@HELP@"/>
+  </xml>
+
+  <!-- Keras CallBacks -->
+
+  <xml name="keras_callbacks">
+    <repeat name="callbacks" min="1" max="5" title="callback">
+      <conditional name="callback_selection">
+        <param name="callback_type" type="select" label="Choose a callback">
+          <option value="None" selected="true">None</option>
+          <option value="EarlyStopping">EarlyStopping -- Stop training when a monitored quantity has stopped improving</option>
+          <!--option value="KerasTensorBoard">TensorBoard</option-->
+          <!--option value="KerasLearningRateScheduler">LearningRateScheduler</option-->
+          <!--option value="RemoteMonitor">RemoteMonitor - Stream events to a server</option> -->
+          <!--option value="ModelCheckpoint">ModelCheckpoint - Save the model after every epoch</option>-->
+          <option value="TerminateOnNaN">TerminateOnNaN -- Terminates training when a NaN loss is encountered.</option>
+          <option value="ReduceLROnPlateau">ReduceLROnPlateau -- Reduce learning rate when a metric has stopped improving</option>
+          <option value="CSVLogger">CSVLogger -- Streams epoch results to a csv file</option>
+        </param>
+        <when value="None"/>
+        <when value="EarlyStopping">
+          <expand macro="keras_callback_common_options">
+            <param argument="min_delta" type="float" value="0" optional="true" help="Minimum change in the monitored quantity to qualify as an improvement."/>
+            <param argument="patience" type="integer" value="0" min="0" help="Number of epochs with no improvement after which training will be stopped."/>
+            <param argument="baseline" type="float" value="" optional="true" help="Baseline value for the monitored quantity to reach. Training will stop if the model doesn't show improvement over the baseline."/>
+            <param argument="restore_best_weights" type="boolean" truevalue="booltrue" falsevalue="boolfalse" checked="false" help="Whether to restore model weights from the epoch with the best value of the monitored quantity"/>
+          </expand>
+        </when>
+        <!--when value="TensorBoard">
+          <param argument="histogram_freq" />
+          <param argument="batch_size" />
+          <param argument="write_graph" />
+          <param argument="write_grads" />
+          <param argument="write_images" />
+          <param argument="embeddings_layer_names" />
+          <param argument="embeddings_metadata" />
+          <param argument="embeddings_data" />
+          <param argument="update_freq" />
+        </when-->
+        <!--when value="RemoteMonitor">
+          <param argument="root" type="text" value="http://localhost:9000" help="Root url of the target server."/>
+          <param argument="path" type="text" value="/publish/epoch/end/" help="Path relative to root to which the events will be sent. E.g., root + '/publish/epoch/end/'"/>
+          <param argument="field" type="text" value="data" optional="true" help="JSON field under which the data will be stored. The field is used only if the payload is sent within a form (i.e. send_as_json is set to False)."/>
+          <param argument="headers" type="text" value="" optional="true" help="Dictionary; optional custom HTTP headers.">
+            <sanitizer>
+              <valid initial="default">
+                <add value="{"/>
+                <add value="}"/>
+              </valid>
+            </sanitizer>
+          </param>
+          <param argument="send_as_json" type="boolean" truevalue="booltrue" falsevalue="boolfalse" checked="false" help="Whether the request should be send as application/json."/>
+        </when>
+        <when value="ModelCheckpoint">
+          <expand macro="keras_callback_common_options">
+            <param argument="save_best_only" type="boolean" truevalue="booltrue" falsevalue="boolfalse" checked="false" help="If True, the latest best model according to the quantity monitored will not be overwritten."/>
+            <param argument="save_weights_only" type="boolean" truevalue="booltrue" falsevalue="boolfalse" checked="true" help="If True, then only the model's weights will be saved, else the full model is saved."/>
+            <param argument="period" type="integer" value="1" min="1" help="Interval (number of epochs) between checkpoints."/>
+          </expand>
+        </when>-->
+        <when value="TerminateOnNaN"/>
+        <when value="ReduceLROnPlateau">
+          <expand macro="keras_callback_common_options">
+            <param argument="factor" type="float" value="0.1" help="Factor by which the learning rate will be reduced. new_lr = lr * factor"/>
+            <param argument="patience" type="integer" value="10" help="Number of epochs with no improvement after which learning rate will be reduced."/>
+            <param argument="min_delta" type="float" value="0.0001" help="Threshold for measuring the new optimum, to only focus on significant changes."/>
+            <param argument="cooldown" type="integer" value="0" help="Number of epochs to wait before resuming normal operation after lr has been reduced."/>
+            <param argument="min_lr" type="float" value="0" help="Lower bound on the learning rate."/>
+          </expand>
+        </when>
+        <when value="CSVLogger"/>
+      </conditional>
+    </repeat>
+  </xml>
+
+  <xml name="keras_callback_common_options">
+    <param argument="monitor" type="select" help="Quantity to be monitored.">
+      <option value="val_loss" selected="true">val_loss</option>
+      <option value="loss">loss</option>
+    </param>
+    <param argument="mode" type="select">
+      <option value="auto" selected="true">auto -- the direction is automatically inferred from the name of the monitored quantity</option>
+      <option value="min">min -- training will stop when the quantity monitored has stopped decreasing</option>
+      <option value="max">max -- training will stop when the quantity monitored has stopped increasing</option>
+    </param>
+    <yield/>
+  </xml>
+
+  <!--Batch online data generators-->
+
+  <xml name="params_fasta_dna_batch_generator">
+    <param argument="seq_length" type="integer" value="1000" optional="true" help="Integer. Sequence length or number of bases."/>
+    <param argument="shuffle" type="boolean" truevalue="booltrue" falsevalue="boolfalse" optional="true" checked="true" help="Whether to shuffle the data between epochs."/>
+    <param argument="seed" type="integer" value="" optional="true" help="Integer, random seed for data shuffling"/>
+  </xml>
+
+  <xml name="params_fasta_protein_batch_generator">
+    <expand macro="params_fasta_dna_batch_generator"/>
+  </xml>
+
+  <xml name="params_genomic_interval_batch_generator">
+    <expand macro="params_fasta_dna_batch_generator"/>
+    <param argument="blacklist_regions" type="select" help="Tabix-indexed list of regions from which we should not output sequences">
+      <option value="hg38" selected="true">hg38</option>
+      <option value="hg19">hg19</option>
+    </param>
+    <param argument="center_bin_to_predict" type="integer" value="200" optional="true" help="Query the tabix-indexed file for a region of length."/>
+    <param argument="feature_thresholds" type="float" value="0.5"  optional="true" help="Threshold values to determine target value."/>
+    <param argument="random_state" type="integer" value="" optional="true" help="Random seed number, to control the sample position in each invertal."/>
+  </xml>
+
+  <xml name="params_image_batch_generator">
+  </xml>
+
+
+  <!--composite params macro-->
+
+  <xml name="keras_compile_params_section">
+    <section name="compile_params" title="Compile Parameters" expanded="true">
+      <param name="loss" type="select" label="Select a loss function">
+        <option value="binary_crossentropy" selected="true">binary_crossentropy</option>
+        <option value="mean_squared_error">mse / MSE/ mean_squared_error</option>
+        <option value="mean_absolute_error">mae / MAE / mean_absolute_error</option>
+        <option value="mean_absolute_percentage_error">mape / MAPE / mean_absolute_percentage_error</option>
+        <option value="mean_squared_logarithmic_error">msle / MSLE / mean_squared_logarithmic_error</option>
+        <option value="squared_hinge">squared_hinge</option>
+        <option value="hinge">hinge</option>
+        <option value="categorical_hinge">categorical_hinge</option>
+        <option value="logcosh">logcosh</option>
+        <option value="categorical_crossentropy">categorical_crossentropy</option>
+        <option value="sparse_categorical_crossentropy">sparse_categorical_crossentropy</option>
+        <option value="kullback_leibler_divergence">kld / KLD / kullback_leibler_divergence</option>
+        <option value="poisson">poisson</option>
+        <option value="cosine_proximity">cosine / cosine_proximity</option>
+      </param>
+      <conditional name="optimizer_selection">
+        <param name="optimizer_type" type="select" label="Select an optimizer">
+          <option value="SGD" selected="true">SGD - Stochastic gradient descent optimizer </option>
+          <option value="RMSprop">RMSprop - RMSProp optimizer </option>
+          <option value="Adagrad">Adagrad - Adagrad optimizer </option>
+          <option value="Adadelta">Adadelta - Adadelta optimizer </option>
+          <option value="Adam">Adam - Adam optimizer </option>
+          <option value="Adamax">Adamax - A variant of Adam based on the infinity norm </option>
+          <option value="Nadam">Nadam - Nesterov Adam optimizer </option>
+        </param>
+        <when value="SGD">
+          <expand macro="keras_optimizer_common">
+            <param argument="momentum" type="float" value="0" optional="true" label="Momentum"
+                help="float >= 0. Parameter that accelerates SGD in the relevant direction and dampens oscillations."/>
+            <param argument="decay" type="float" value="0" label="Decay" optional="true" help="float &gt;= 0. Learning rate decay over each update."/>
+            <param argument="nesterov" type="boolean" truevalue="booltrue" falsevalue="boolfalse" optional="true" checked="false" label="Whether to apply Nesterov momentum"/>
+          </expand>
+        </when>
+        <when value="RMSprop">
+          <expand macro="keras_optimizer_common_more" lr="0.001">
+            <param argument="rho" type="float" value="0.9" optional="true" label="rho" help="float &gt;= 0."/>
+          </expand>
+        </when>
+        <when value="Adagrad">
+          <expand macro="keras_optimizer_common_more" lr="0.001"/>
+        </when>
+        <when value="Adadelta">
+          <expand macro="keras_optimizer_common_more" lr="1.0">
+            <param argument="rho" type="float" value="0.95" optional="true" label="rho" help="float &gt;= 0."/>
+          </expand>
+        </when>
+        <when value="Adam">
+          <expand macro="keras_optimizer_common_more" lr="0.001">
+            <param argument="beta_1" type="float" value="0.9" optional="true" label="beta_1" help="float, 0 &lt; beta &lt; 1. Generally close to 1."/>
+            <param argument="beta_2" type="float" value="0.999" optional="true" label="beta_2" help="float, 0 &lt; beta &lt; 1. Generally close to 1."/>
+            <param argument="amsgrad" type="boolean" truevalue="booltrue" falsevalue="boolfalse" optional="true" checked="false" label="Whether to apply the AMSGrad variant?" 
+                help="Refer to paper `On the Convergence of Adam and Beyond`"/>
+          </expand>
+        </when>
+        <when value="Adamax">
+          <expand macro="keras_optimizer_common_more" lr="0.002">
+            <param argument="beta_1" type="float" value="0.9" optional="true" label="beta_1" help="float, 0 &lt; beta &lt; 1. Generally close to 1."/>
+            <param argument="beta_2" type="float" value="0.999" optional="true" label="beta_2" help="float, 0 &lt; beta &lt; 1. Generally close to 1."/>
+          </expand>
+        </when>
+        <when value="Nadam">
+          <expand macro="keras_optimizer_common" lr="0.002">
+            <param argument="beta_1" type="float" value="0.9" optional="true" label="beta_1" help="float, 0 &lt; beta &lt; 1. Generally close to 1."/>
+            <param argument="beta_2" type="float" value="0.999" optional="true" label="beta_2" help="float, 0 &lt; beta &lt; 1. Generally close to 1."/>
+            <!--param argument="epsilon" type="float" value="" label="epsilon" optional="true" help="Fuzz factor. If `None`, defaults to `K.epsilon()`"/>-->
+            <param argument="schedule_decay" type="float" value="0.004" optional="true" label="schedule_decay" help="float, 0 &lt; beta &lt; 1."/>
+          </expand>
+        </when>
+      </conditional>
+      <param name="metrics" type="select" optional="true" multiple="true" label="Select metrics">
+        <option value="acc" selected="true">acc / accruracy</option>
+        <option value="binary_accuracy">binary_accuracy</option>
+        <option value="categorical_accuracy">categorical_accuracy</option>
+        <option value="sparse_categorical_accuracy">sparse_categorical_accuracy</option>
+        <option value="mse">mse / MSE / mean_squared_error</option>
+        <option value="mae">mae / MAE / mean_absolute_error</option>
+        <option value="mae">mape / MAPE / mean_absolute_percentage_error</option>
+        <option value="cosine_proximity">cosine_proximity</option>
+        <option value="cosine">cosine</option>
+        <option value="none">none</option>
+      </param>
+    </section>
+  </xml>
+
+  <xml name="keras_fit_params_section">
+    <section name="fit_params" title="Fit Parameters" expanded="true">
+      <param name="epochs" type="integer" value="1" min="1" label="epochs"/>
+      <param name="batch_size" type="integer" value="32" optional="true" label="batch_size" help="Integer or blank for 32"/>
+      <param name="steps_per_epoch" type="integer" value="" optional="true" label="steps_per_epoch" help="The number of steps (batches of samples) before declaring one epoch finished and starting the next epoch. The default None is equal to the number of samples in your dataset divided by the batch size, or 1 if that cannot be determined."/>
+      <param name="validation_steps" type="integer" value="" optional="true" label="validation_steps" help="Default None. Total number of steps (batches of samples) to validate before stopping." />
+      <!--`validation_freq` will be available in next keras version-->
+      <!--param name="validation_freq" type="integer" value="1" optional="true" label="validation_freq" help="Integer only at current moment. If an integer, specifies how many training epochs to run before a new validation run is performed."/-->
+      <expand macro="keras_callbacks"/>
+    </section>
+  </xml>
+
+ <!--Citation-->
+  <xml name="keras_citation">
+    <citation type="bibtex">
+      @misc{chollet2015keras,
+        title={Keras},
+        url={https://keras.io},
+        author={Chollet, Fran\c{c}ois and others},
+        year={2015},
+        howpublished={https://keras.io},
+      }
+    </citation>
+  </xml>
+
+  <xml name="tensorflow_citation">
+    <citation type="bibtex">
+      @misc{tensorflow2015-whitepaper,
+        title={ {TensorFlow}: Large-Scale Machine Learning on Heterogeneous Systems},
+        url={https://www.tensorflow.org/},
+        note={Software available from tensorflow.org},
+        author={
+            Mart\'{\i}n~Abadi and
+            Ashish~Agarwal and
+            Paul~Barham and
+            Eugene~Brevdo and
+            Zhifeng~Chen and
+            Craig~Citro and
+            Greg~S.~Corrado and
+            Andy~Davis and
+            Jeffrey~Dean and
+            Matthieu~Devin and
+            Sanjay~Ghemawat and
+            Ian~Goodfellow and
+            Andrew~Harp and
+            Geoffrey~Irving and
+            Michael~Isard and
+            Yangqing Jia and
+            Rafal~Jozefowicz and
+            Lukasz~Kaiser and
+            Manjunath~Kudlur and
+            Josh~Levenberg and
+            Dandelion~Man\'{e} and
+            Rajat~Monga and
+            Sherry~Moore and
+            Derek~Murray and
+            Chris~Olah and
+            Mike~Schuster and
+            Jonathon~Shlens and
+            Benoit~Steiner and
+            Ilya~Sutskever and
+            Kunal~Talwar and
+            Paul~Tucker and
+            Vincent~Vanhoucke and
+            Vijay~Vasudevan and
+            Fernanda~Vi\'{e}gas and
+            Oriol~Vinyals and
+            Pete~Warden and
+            Martin~Wattenberg and
+            Martin~Wicke and
+            Yuan~Yu and
+            Xiaoqiang~Zheng},
+          year={2015},
+      }
+    </citation>
+  </xml>
+
+</macros>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/keras_train_and_eval.py	Tue Apr 13 22:40:10 2021 +0000
@@ -0,0 +1,521 @@
+import argparse
+import json
+import os
+import pickle
+import warnings
+from itertools import chain
+
+import joblib
+import numpy as np
+import pandas as pd
+from galaxy_ml.externals.selene_sdk.utils import compute_score
+from galaxy_ml.keras_galaxy_models import _predict_generator
+from galaxy_ml.model_validations import train_test_split
+from galaxy_ml.utils import (
+    clean_params,
+    get_main_estimator,
+    get_module,
+    get_scoring,
+    load_model,
+    read_columns,
+    SafeEval,
+    try_get_attr,
+)
+from scipy.io import mmread
+from sklearn.metrics.scorer import _check_multimetric_scoring
+from sklearn.model_selection import _search, _validation
+from sklearn.model_selection._validation import _score
+from sklearn.pipeline import Pipeline
+from sklearn.utils import indexable, safe_indexing
+
+
+_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")
+del os
+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 == "":
+            continue
+
+        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)
+            continue
+
+        if not swap_value.startswith(":"):
+            safe_eval = SafeEval(load_scipy=True, load_numpy=True)
+            ev = safe_eval(swap_value)
+        else:
+            # Have `:` before search list, asks for estimator evaluatio
+            safe_eval_es = SafeEval(load_estimators=True)
+            swap_value = swap_value[1:].strip()
+            # TODO maybe add regular express check
+            ev = safe_eval_es(swap_value)
+
+        swap_params[param_name] = ev
+
+    return swap_params
+
+
+def train_test_split_none(*arrays, **kwargs):
+    """extend train_test_split to take None arrays
+    and support split by group names.
+    """
+    nones = []
+    new_arrays = []
+    for idx, arr in enumerate(arrays):
+        if arr is None:
+            nones.append(idx)
+        else:
+            new_arrays.append(arr)
+
+    if kwargs["shuffle"] == "None":
+        kwargs["shuffle"] = 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(",")]
+        new_arrays = indexable(*new_arrays)
+        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))
+    else:
+        rval = train_test_split(*new_arrays, **kwargs)
+
+    for pos in nones:
+        rval[pos * 2: 2] = [None, None]
+
+    return rval
+
+
+def _evaluate(y_true, pred_probas, scorer, is_multimetric=True):
+    """output scores based on input scorer
+
+    Parameters
+    ----------
+    y_true : array
+        True label or target values
+    pred_probas : array
+        Prediction values, probability for classification problem
+    scorer : dict
+        dict of `sklearn.metrics.scorer.SCORER`
+    is_multimetric : bool, default is True
+    """
+    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")
+        if not is_multimetric:
+            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)
+                scores[name] = score
+
+    # TODO: multi-class metrics
+    # multi-label
+    else:
+        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)
+            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)
+                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,
+):
+    """
+    Parameter
+    ---------
+    inputs : str
+        File path to galaxy tool parameter
+
+    infile_estimator : str
+        File path to estimator
+
+    infile1 : str
+        File path to dataset containing features
+
+    infile2 : str
+        File path to dataset containing target values
+
+    outfile_result : str
+        File path to save the results, either cv_results or test result
+
+    outfile_object : str, optional
+        File path to save searchCV object
+
+    outfile_weights : str, optional
+        File path to save deep learning model weights
+
+    outfile_y_true : str, optional
+        File path to target values for prediction
+
+    outfile_y_preds : str, optional
+        File path to save deep learning model weights
+
+    groups : str
+        File path to dataset containing groups labels
+
+    ref_seq : str
+        File path to dataset containing genome sequence file
+
+    intervals : str
+        File path to dataset containing interval file
+
+    targets : str
+        File path to dataset compressed target bed file
+
+    fasta_path : str
+        File path to dataset containing fasta file
+    """
+    warnings.simplefilter("ignore")
+
+    with open(inputs, "r") as param_handler:
+        params = json.load(param_handler)
+
+    #  load estimator
+    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"]
+    swap_params = _eval_swap_params(swapping)
+    estimator.set_params(**swap_params)
+
+    estimator_params = estimator.get_params()
+
+    # store read dataframe object
+    loaded_df = {}
+
+    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"]
+        else:
+            c = None
+
+        df_key = infile1 + repr(header)
+        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"))
+
+    # fasta_file input
+    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})
+                break
+        else:
+            raise ValueError(
+                "The selected estimator doesn't support "
+                "fasta file input! Please consider using "
+                "KerasGBatchClassifier with "
+                "FastaDNABatchGenerator/FastaProteinBatchGenerator "
+                "or having GenomeOneHotEncoder/ProteinOneHotEncoder "
+                "in pipeline!"
+            )
+
+    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,
+        }
+        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"]
+    else:
+        c = None
+
+    df_key = infile2 + repr(header)
+    if df_key in loaded_df:
+        infile2 = loaded_df[df_key]
+    else:
+        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)
+    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())
+        y = None
+    # end y
+
+    # load groups
+    if groups:
+        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"]
+        else:
+            c = None
+
+        df_key = groups + repr(header)
+        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 = groups.ravel()
+
+    # del loaded_df
+    del loaded_df
+
+    # 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":
+        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"]
+
+    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
+        else:
+            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)
+
+    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 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
+            else:
+                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)
+
+    # 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))
+        else:
+            estimator.fit(X_train, y_train, validation_data=(X_test, y_test))
+    else:
+        estimator.fit(X_train, y_train)
+
+    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)
+        scores = _evaluate(y_true, predictions, scorer, is_multimetric=True)
+
+    else:
+        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)
+    if outfile_y_true:
+        try:
+            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,
+            )
+        except Exception as e:
+            print("Error in saving predictions: %s" % e)
+
+    # 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)
+
+    memory.clear(warn=False)
+
+    if outfile_object:
+        main_est = estimator
+        if isinstance(estimator, Pipeline):
+            main_est = estimator.steps[-1][-1]
+
+        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_
+            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)
+
+
+if __name__ == "__main__":
+    aparser = argparse.ArgumentParser()
+    aparser.add_argument("-i", "--inputs", dest="inputs", required=True)
+    aparser.add_argument("-e", "--estimator", dest="infile_estimator")
+    aparser.add_argument("-X", "--infile1", dest="infile1")
+    aparser.add_argument("-y", "--infile2", dest="infile2")
+    aparser.add_argument("-O", "--outfile_result", dest="outfile_result")
+    aparser.add_argument("-o", "--outfile_object", dest="outfile_object")
+    aparser.add_argument("-w", "--outfile_weights", dest="outfile_weights")
+    aparser.add_argument("-l", "--outfile_y_true", dest="outfile_y_true")
+    aparser.add_argument("-p", "--outfile_y_preds", dest="outfile_y_preds")
+    aparser.add_argument("-g", "--groups", dest="groups")
+    aparser.add_argument("-r", "--ref_seq", dest="ref_seq")
+    aparser.add_argument("-b", "--intervals", dest="intervals")
+    aparser.add_argument("-t", "--targets", dest="targets")
+    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,
+    )
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main_macros.xml	Tue Apr 13 22:40:10 2021 +0000
@@ -0,0 +1,2015 @@
+<macros>
+    <token name="@VERSION@">1.0.8.3</token>
+
+    <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>
+
+
+    <!--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="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>
+
+    <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="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="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="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="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>
+
+    <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_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="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="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="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="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="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="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>
+
+    <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_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>
+
+    <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="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="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="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="">
+    <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="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="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="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="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="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="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="beta">
+        <param argument="beta" type="float" value="1.0" label="The strength of recall versus precision in the F-score" help=" " />
+    </xml>
+
+
+    <!--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="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="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="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="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="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_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="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="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="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="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="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>
+    </xml>
+
+    <xml name="model_validation_common_options">
+        <expand macro="cv" />
+        <expand macro="verbose" />
+        <yield />
+    </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="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_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>
+    </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="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."/>
+      </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_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>
+        </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="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>
+
+    <!-- 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>
+
+    <!--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.
+                    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}
+          }
+            </citation>
+            <yield />
+        </citations>
+    </xml>
+
+    <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}},
+          year =      {2001--},
+          url = "http://www.scipy.org/",
+          note = {[Online; accessed 2016-04-09]}
+        }
+            </citation>
+        </citations>
+    </xml>
+
+    <xml name="skrebate_citation">
+        <citation type="bibtex">
+      @article{DBLP:journals/corr/abs-1711-08477,
+        author    = {Ryan J. Urbanowicz and
+                    Randal S. Olson and
+                    Peter Schmitt and
+                    Melissa Meeker and
+                    Jason H. Moore},
+        title     = {Benchmarking Relief-Based Feature Selection Methods},
+        journal   = {CoRR},
+        volume    = {abs/1711.08477},
+        year      = {2017},
+        url       = {http://arxiv.org/abs/1711.08477},
+        archivePrefix = {arXiv},
+        eprint    = {1711.08477},
+        timestamp = {Mon, 13 Aug 2018 16:46:04 +0200},
+        biburl    = {https://dblp.org/rec/bib/journals/corr/abs-1711-08477},
+        bibsource = {dblp computer science bibliography, https://dblp.org}
+      }
+        </citation>
+    </xml>
+
+    <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},
+        booktitle = {Proceedings of the 22nd ACM SIGKDD International Conference on Knowledge Discovery and Data Mining},
+        series = {KDD '16},
+        year = {2016},
+        isbn = {978-1-4503-4232-2},
+        location = {San Francisco, California, USA},
+        pages = {785--794},
+        numpages = {10},
+        url = {http://doi.acm.org/10.1145/2939672.2939785},
+        doi = {10.1145/2939672.2939785},
+        acmid = {2939785},
+        publisher = {ACM},
+        address = {New York, NY, USA},
+        keywords = {large-scale machine learning},
+      }
+        </citation>
+    </xml>
+
+    <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},
+        journal = {Journal of Machine Learning Research},
+        year    = {2017},
+        volume  = {18},
+        number  = {17},
+        pages   = {1-5},
+        url     = {http://jmlr.org/papers/v18/16-365.html}
+      }
+        </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}
+      }
+        </citation>
+    </xml>
+
+</macros>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ml_visualization_ex.py	Tue Apr 13 22:40:10 2021 +0000
@@ -0,0 +1,617 @@
+import argparse
+import json
+import os
+import warnings
+
+import matplotlib
+import matplotlib.pyplot as plt
+import numpy as np
+import pandas as pd
+import plotly
+import plotly.graph_objs as go
+from galaxy_ml.utils import load_model, read_columns, SafeEval
+from keras.models import model_from_json
+from keras.utils import plot_model
+from sklearn.feature_selection.base import SelectorMixin
+from sklearn.metrics import auc, average_precision_score, confusion_matrix, precision_recall_curve, roc_curve
+from sklearn.pipeline import Pipeline
+
+
+safe_eval = SafeEval()
+
+# 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
+]
+
+
+def visualize_pr_curve_plotly(df1, df2, pos_label, title=None):
+    """output pr-curve in html using plotly
+
+    df1 : pandas.DataFrame
+        Containing y_true
+    df2 : pandas.DataFrame
+        Containing y_score
+    pos_label : None
+        The label of positive class
+    title : str
+        Plot title
+    """
+    data = []
+    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)
+
+        trace = go.Scatter(
+            x=recall,
+            y=precision,
+            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),
+        title=dict(
+            text=title or "Precision-Recall Curve",
+            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)",
+    )
+    """
+    legend=dict(
+        x=0.95,
+        y=0,
+        traceorder="normal",
+        font=dict(
+            family="sans-serif",
+            size=9,
+            color="black"
+        ),
+        bgcolor="LightSteelBlue",
+        bordercolor="Black",
+        borderwidth=2
+    ),"""
+
+    fig = go.Figure(data=data, layout=layout)
+
+    plotly.offline.plot(fig, filename="output.html", auto_open=False)
+    # to be discovered by `from_work_dir`
+    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"""
+    backend = matplotlib.get_backend()
+    if "inline" not in backend:
+        matplotlib.use("SVG")
+    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)
+
+        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.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"))
+
+
+def visualize_roc_curve_plotly(df1, df2, pos_label, drop_intermediate=True, title=None):
+    """output roc-curve in html using plotly
+
+    df1 : pandas.DataFrame
+        Containing y_true
+    df2 : pandas.DataFrame
+        Containing y_score
+    pos_label : None
+        The label of positive class
+    drop_intermediate : bool
+        Whether to drop some suboptimal thresholds
+    title : str
+        Plot title
+    """
+    data = []
+    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)
+        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),
+        )
+        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),
+        title=dict(
+            text=title or "Receiver Operating Characteristic (ROC) Curve",
+            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)",
+    )
+    """
+    # legend=dict(
+            # x=0.95,
+            # y=0,
+            # traceorder="normal",
+            # font=dict(
+            #    family="sans-serif",
+            #    size=9,
+            #    color="black"
+            # ),
+            # bgcolor="LightSteelBlue",
+            # bordercolor="Black",
+            # borderwidth=2
+        # ),
+    """
+
+    fig = go.Figure(data=data, layout=layout)
+
+    plotly.offline.plot(fig, filename="output.html", auto_open=False)
+    # to be discovered by `from_work_dir`
+    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"""
+    backend = matplotlib.get_backend()
+    if "inline" not in backend:
+        matplotlib.use("SVG")
+    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)
+        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.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.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"))
+
+
+def get_dataframe(file_path, plot_selection, header_name, column_name):
+    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",
+    ]:
+        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)
+    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,
+):
+    """
+    Parameter
+    ---------
+    inputs : str
+        File path to galaxy tool parameter
+
+    infile_estimator : str, default is None
+        File path to estimator
+
+    infile1 : str, default is None
+        File path to dataset containing features or true labels.
+
+    infile2 : str, default is None
+        File path to dataset containing target values or predicted
+        probabilities.
+
+    outfile_result : str, default is None
+        File path to save the results, either cv_results or test result
+
+    outfile_object : str, default is None
+        File path to save searchCV object
+
+    groups : str, default is None
+        File path to dataset containing groups labels
+
+    ref_seq : str, default is None
+        File path to dataset containing genome sequence file
+
+    intervals : str, default is None
+        File path to dataset containing interval file
+
+    targets : str, default is None
+        File path to dataset compressed target bed file
+
+    fasta_path : str, default is None
+        File path to dataset containing fasta file
+
+    model_config : str, default is None
+        File path to dataset containing JSON config for neural networks
+
+    true_labels : str, default is None
+        File path to dataset containing true labels
+
+    predicted_labels : str, default is None
+        File path to dataset containing true predicted labels
+
+    plot_color : str, default is None
+        Color of the confusion matrix heatmap
+
+    title : str, default is None
+        Title of the confusion matrix heatmap
+    """
+    warnings.simplefilter("ignore")
+
+    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"]
+
+    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"]
+        else:
+            c = None
+
+        _, 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
+
+        if isinstance(estimator, Pipeline):
+            for st in estimator.steps[:-1]:
+                if isinstance(st[-1], SelectorMixin):
+                    mask = st[-1].get_support()
+                    feature_names = feature_names[mask]
+            estimator = estimator.steps[-1][-1]
+
+        if hasattr(estimator, "coef_"):
+            coefs = estimator.coef_
+        else:
+            coefs = getattr(estimator, "feature_importances_", None)
+        if coefs is None:
+            raise RuntimeError("The classifier does not expose " '"coef_" or "feature_importances_" ' "attributes")
+
+        threshold = params["plotting_selection"]["threshold"]
+        if threshold is not None:
+            mask = (coefs > threshold) | (coefs < -threshold)
+            coefs = coefs[mask]
+            feature_names = feature_names[mask]
+
+        # sort
+        indices = np.argsort(coefs)[::-1]
+
+        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)
+        # to be discovered by `from_work_dir`
+        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)
+
+        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
+
+        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:
+                visualize_roc_curve_matplotlib(
+                    df1,
+                    df2,
+                    pos_label,
+                    drop_intermediate=drop_intermediate,
+                    title=title,
+                )
+
+        return 0
+
+    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 = safe_eval(steps)
+
+        data = go.Scatter(
+            x=list(range(len(scores))),
+            y=scores,
+            text=[str(_) for _ in steps] if steps else None,
+            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),
+            # control backgroud colors
+            plot_bgcolor="rgba(255,255,255,0)",
+        )
+        """
+        # legend=dict(
+                # x=0.95,
+                # y=0,
+                # traceorder="normal",
+                # font=dict(
+                #    family="sans-serif",
+                #    size=9,
+                #    color="black"
+                # ),
+                # bgcolor="LightSteelBlue",
+                # bordercolor="Black",
+                # borderwidth=2
+            # ),
+        """
+
+        fig = go.Figure(data=[data], layout=layout)
+        plotly.offline.plot(fig, filename="output.html", auto_open=False)
+        # to be discovered by `from_work_dir`
+        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"]
+        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",
+            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",
+            name="Test Scores",
+        )
+        layout = dict(
+            xaxis=dict(title="No. of samples"),
+            yaxis=dict(title="Performance Score"),
+            # modify these configurations to customize image
+            title=dict(
+                text=title or "Learning Curve",
+                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)",
+        )
+        """
+        # legend=dict(
+                # x=0.95,
+                # y=0,
+                # traceorder="normal",
+                # font=dict(
+                #    family="sans-serif",
+                #    size=9,
+                #    color="black"
+                # ),
+                # bgcolor="LightSteelBlue",
+                # bordercolor="Black",
+                # borderwidth=2
+            # ),
+        """
+
+        fig = go.Figure(data=[data1, data2], layout=layout)
+        plotly.offline.plot(fig, filename="output.html", auto_open=False)
+        # to be discovered by `from_work_dir`
+        os.rename("output.html", "output")
+
+        return 0
+
+    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")
+
+        return 0
+
+    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)
+        true_classes = input_true.iloc[:, -1].copy()
+        predicted_classes = input_predicted.iloc[:, -1].copy()
+        axis_labels = list(set(true_classes))
+        c_matrix = confusion_matrix(true_classes, predicted_classes)
+        fig, ax = plt.subplots(figsize=(7, 7))
+        im = plt.imshow(c_matrix, cmap=plot_color)
+        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_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")
+
+        return 0
+
+    # save pdf file to disk
+    # fig.write_image("image.pdf", format='pdf')
+    # fig.write_image("image.pdf", format='pdf', width=340*2, height=226*2)
+
+
+if __name__ == "__main__":
+    aparser = argparse.ArgumentParser()
+    aparser.add_argument("-i", "--inputs", dest="inputs", required=True)
+    aparser.add_argument("-e", "--estimator", dest="infile_estimator")
+    aparser.add_argument("-X", "--infile1", dest="infile1")
+    aparser.add_argument("-y", "--infile2", dest="infile2")
+    aparser.add_argument("-O", "--outfile_result", dest="outfile_result")
+    aparser.add_argument("-o", "--outfile_object", dest="outfile_object")
+    aparser.add_argument("-g", "--groups", dest="groups")
+    aparser.add_argument("-r", "--ref_seq", dest="ref_seq")
+    aparser.add_argument("-b", "--intervals", dest="intervals")
+    aparser.add_argument("-t", "--targets", dest="targets")
+    aparser.add_argument("-f", "--fasta_path", dest="fasta_path")
+    aparser.add_argument("-c", "--model_config", dest="model_config")
+    aparser.add_argument("-tl", "--true_labels", dest="true_labels")
+    aparser.add_argument("-pl", "--predicted_labels", dest="predicted_labels")
+    aparser.add_argument("-pc", "--plot_color", dest="plot_color")
+    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,
+    )
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/model_prediction.py	Tue Apr 13 22:40:10 2021 +0000
@@ -0,0 +1,232 @@
+import argparse
+import json
+import warnings
+
+import numpy as np
+import pandas as pd
+from galaxy_ml.utils import get_module, load_model, read_columns, try_get_attr
+from scipy.io import mmread
+from sklearn.pipeline import Pipeline
+
+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,
+):
+    """
+    Parameter
+    ---------
+    inputs : str
+        File path to galaxy tool parameter
+
+    infile_estimator : strgit
+        File path to trained estimator input
+
+    outfile_predict : str
+        File path to save the prediction results, tabular
+
+    infile_weights : str
+        File path to weights input
+
+    infile1 : str
+        File path to dataset containing features
+
+    fasta_path : str
+        File path to dataset containing fasta file
+
+    ref_seq : str
+        File path to dataset containing the reference genome sequence.
+
+    vcf_path : str
+        File path to dataset containing variants info.
+    """
+    warnings.filterwarnings("ignore")
+
+    with open(inputs, "r") as param_handler:
+        params = json.load(param_handler)
+
+    # load model
+    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!"
+            )
+        main_est.load_weights(infile_weights)
+
+    # handle data 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"]
+        else:
+            c = None
+
+        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":
+            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":
+            preds = estimator.predict(X)
+        else:
+            preds = estimator.predict_proba(X)
+
+    # fasta input
+    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")
+        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)
+        steps = (n_seqs + batch_size - 1) // batch_size
+
+        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)
+
+        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)
+
+    # vcf input
+    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
+
+        pred_data_generator = klass(ref_genome_path=ref_seq, vcf_path=vcf_path, **options)
+
+        pred_data_generator.set_processing_attrs()
+
+        variants = pred_data_generator.variants
+
+        # 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.write(header_row)
+        header_done = False
+
+        steps_done = 0
+
+        # TODO: multiple threading
+        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)
+
+                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,
+                    )
+                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,
+                    )
+
+                if batch_preds.ndim == 1:
+                    batch_preds = batch_preds[:, np.newaxis]
+
+                batch_meta = variants[index_array]
+                batch_out = np.column_stack([batch_meta, batch_preds])
+
+                if not header_done:
+                    heads = np.arange(batch_preds.shape[-1]).astype(str)
+                    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)
+                    file_writer.write("%s\n" % row_str)
+
+                steps_done += 1
+
+        finally:
+            file_writer.close()
+            # TODO: make api `pred_data_generator.close()`
+            pred_data_generator.close()
+        return 0
+    # end input
+
+    # output
+    if len(preds.shape) == 1:
+        rval = pd.DataFrame(preds, columns=["Predicted"])
+    else:
+        rval = pd.DataFrame(preds)
+
+    rval.to_csv(outfile_predict, sep="\t", header=True, index=False)
+
+
+if __name__ == "__main__":
+    aparser = argparse.ArgumentParser()
+    aparser.add_argument("-i", "--inputs", dest="inputs", required=True)
+    aparser.add_argument("-e", "--infile_estimator", dest="infile_estimator")
+    aparser.add_argument("-w", "--infile_weights", dest="infile_weights")
+    aparser.add_argument("-X", "--infile1", dest="infile1")
+    aparser.add_argument("-O", "--outfile_predict", dest="outfile_predict")
+    aparser.add_argument("-f", "--fasta_path", dest="fasta_path")
+    aparser.add_argument("-r", "--ref_seq", dest="ref_seq")
+    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,
+    )
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pca.py	Tue Apr 13 22:40:10 2021 +0000
@@ -0,0 +1,186 @@
+import argparse
+
+import numpy as np
+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)."
+    )
+    args = parser.parse_args()
+
+    usecols = None
+    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":
+        usecols = args.column_indices
+
+    header = "infer" if args.header else None
+
+    pca_input = read_columns(
+        f=args.infile,
+        c=usecols,
+        c_option=args.columns,
+        sep="\t",
+        header=header,
+        parse_dates=True,
+        encoding=None,
+        index_col=None,
+    )
+
+    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})
+        pca = PCA()
+
+    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,
+            }
+        )
+
+        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})
+
+        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")
+
+
+if __name__ == "__main__":
+    main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/search_model_validation.py	Tue Apr 13 22:40:10 2021 +0000
@@ -0,0 +1,754 @@
+import argparse
+import collections
+import json
+import os
+import pickle
+import sys
+import warnings
+
+import imblearn
+import joblib
+import numpy as np
+import pandas as pd
+import skrebate
+from galaxy_ml.utils import (
+    clean_params,
+    get_cv,
+    get_main_estimator,
+    get_module,
+    get_scoring,
+    load_model,
+    read_columns,
+    SafeEval,
+    try_get_attr
+)
+from scipy.io import mmread
+from sklearn import (
+    cluster,
+    decomposition,
+    feature_selection,
+    kernel_approximation,
+    model_selection,
+    preprocessing,
+)
+from sklearn.exceptions import FitFailedWarning
+from sklearn.model_selection import _search, _validation
+from sklearn.model_selection._validation import _score, cross_validate
+
+
+_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))
+# handle  disk cache
+CACHE_DIR = os.path.join(os.getcwd(), "cached")
+del os
+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 == "":
+            continue
+
+        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)
+            continue
+
+        if not search_list.startswith(":"):
+            safe_eval = SafeEval(load_scipy=True, load_numpy=True)
+            ev = safe_eval(search_list)
+            search_params[param_name] = ev
+        else:
+            # Have `:` before search list, asks for estimator evaluatio
+            safe_eval_es = SafeEval(load_estimators=True)
+            search_list = search_list[1:].strip()
+            # TODO maybe add regular express check
+            ev = safe_eval_es(search_list)
+            preprocessings = (
+                preprocessing.StandardScaler(),
+                preprocessing.Binarizer(),
+                preprocessing.MaxAbsScaler(),
+                preprocessing.Normalizer(),
+                preprocessing.MinMaxScaler(),
+                preprocessing.PolynomialFeatures(),
+                preprocessing.RobustScaler(),
+                feature_selection.SelectKBest(),
+                feature_selection.GenericUnivariateSelect(),
+                feature_selection.SelectPercentile(),
+                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.NMF(random_state=0),
+                decomposition.PCA(random_state=0),
+                decomposition.SparsePCA(random_state=0, n_jobs=N_JOBS),
+                decomposition.TruncatedSVD(random_state=0),
+                kernel_approximation.Nystroem(random_state=0),
+                kernel_approximation.RBFSampler(random_state=0),
+                kernel_approximation.AdditiveChi2Sampler(),
+                kernel_approximation.SkewedChi2Sampler(random_state=0),
+                cluster.FeatureAgglomeration(),
+                skrebate.ReliefF(n_jobs=N_JOBS),
+                skrebate.SURF(n_jobs=N_JOBS),
+                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.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.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.combine.SMOTEENN(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":
+                    newlist.extend(preprocessings[0:35])
+                elif obj == "sk_prep_all":  # no KernalCenter()
+                    newlist.extend(preprocessings[0:7])
+                elif obj == "fs_all":
+                    newlist.extend(preprocessings[7:14])
+                elif obj == "decomp_all":
+                    newlist.extend(preprocessings[14:25])
+                elif obj == "k_appr_all":
+                    newlist.extend(preprocessings[25:29])
+                elif obj == "reb_all":
+                    newlist.extend(preprocessings[30:35])
+                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():
+                        newlist.append(obj.set_params(n_jobs=N_JOBS))
+                    else:
+                        newlist.append(obj)
+                else:
+                    sys.exit("Unsupported estimator type: %r" % (obj))
+
+            search_params[param_name] = newlist
+
+    return search_params
+
+
+def _handle_X_y(
+    estimator,
+    params,
+    infile1,
+    infile2,
+    loaded_df={},
+    ref_seq=None,
+    intervals=None,
+    targets=None,
+    fasta_path=None,
+):
+    """read inputs
+
+    Params
+    -------
+    estimator : estimator object
+    params : dict
+        Galaxy tool parameter inputs
+    infile1 : str
+        File path to dataset containing features
+    infile2 : str
+        File path to dataset containing target values
+    loaded_df : dict
+        Contains loaded DataFrame objects with file path as keys
+    ref_seq : str
+        File path to dataset containing genome sequence file
+    interval : str
+        File path to dataset containing interval file
+    targets : str
+        File path to dataset compressed target bed file
+    fasta_path : str
+        File path to dataset containing fasta file
+
+
+    Returns
+    -------
+    estimator : estimator object after setting new attributes
+    X : numpy array
+    y : numpy array
+    """
+    estimator_params = estimator.get_params()
+
+    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"]
+        else:
+            c = None
+
+        df_key = infile1 + repr(header)
+
+        if df_key in loaded_df:
+            infile1 = loaded_df[df_key]
+
+        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"))
+
+    # fasta_file input
+    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})
+                break
+        else:
+            raise ValueError(
+                "The selected estimator doesn't support "
+                "fasta file input! Please consider using "
+                "KerasGBatchClassifier with "
+                "FastaDNABatchGenerator/FastaProteinBatchGenerator "
+                "or having GenomeOneHotEncoder/ProteinOneHotEncoder "
+                "in pipeline!"
+            )
+
+    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,
+        }
+        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"]
+    else:
+        c = None
+
+    df_key = infile2 + repr(header)
+    if df_key in loaded_df:
+        infile2 = loaded_df[df_key]
+    else:
+        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)
+    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())
+        y = None
+    # end y
+
+    return estimator, X, y
+
+
+def _do_outer_cv(searcher, X, y, outer_cv, scoring, error_score="raise", outfile=None):
+    """Do outer cross-validation for nested CV
+
+    Parameters
+    ----------
+    searcher : object
+        SearchCV object
+    X : numpy array
+        Containing features
+    y : numpy array
+        Target values or labels
+    outer_cv : int or CV splitter
+        Control the cv splitting
+    scoring : object
+        Scorer
+    error_score: str, float or numpy float
+        Whether to raise fit error or return an value
+    outfile : str
+        File path to store the restuls
+    """
+    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,
+        )
+    else:
+        warnings.simplefilter("always", FitFailedWarning)
+        with warnings.catch_warnings(record=True) as w:
+            try:
+                rval = cross_validate(
+                    searcher,
+                    X,
+                    y,
+                    scoring=scoring,
+                    cv=outer_cv,
+                    n_jobs=N_JOBS,
+                    verbose=0,
+                    error_score=error_score,
+                )
+            except ValueError:
+                pass
+            for warning in w:
+                print(repr(warning.message))
+
+    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"):
+            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)
+
+
+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"]
+
+    # splits
+    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":
+        if groups is None:
+            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)
+        else:
+            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 error_score == "raise":
+        searcher.fit(X, y, groups=groups)
+    else:
+        warnings.simplefilter("always", FitFailedWarning)
+        with warnings.catch_warnings(record=True) as w:
+            try:
+                searcher.fit(X, y, groups=groups)
+            except ValueError:
+                pass
+            for warning in w:
+                print(repr(warning.message))
+
+    scorer_ = searcher.scorer_
+    if isinstance(scorer_, collections.Mapping):
+        is_multimetric = True
+    else:
+        is_multimetric = False
+
+    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)
+    else:
+        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)
+
+    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,
+):
+    """
+    Parameter
+    ---------
+    inputs : str
+        File path to galaxy tool parameter
+
+    infile_estimator : str
+        File path to estimator
+
+    infile1 : str
+        File path to dataset containing features
+
+    infile2 : str
+        File path to dataset containing target values
+
+    outfile_result : str
+        File path to save the results, either cv_results or test result
+
+    outfile_object : str, optional
+        File path to save searchCV object
+
+    outfile_weights : str, optional
+        File path to save model weights
+
+    groups : str
+        File path to dataset containing groups labels
+
+    ref_seq : str
+        File path to dataset containing genome sequence file
+
+    intervals : str
+        File path to dataset containing interval file
+
+    targets : str
+        File path to dataset compressed target bed file
+
+    fasta_path : str
+        File path to dataset containing fasta file
+    """
+    warnings.simplefilter("ignore")
+
+    # store read dataframe object
+    loaded_df = {}
+
+    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
+
+    with open(infile_estimator, "rb") as estimator_handler:
+        estimator = load_model(estimator_handler)
+
+    optimizer = params["search_schemes"]["selected_search_scheme"]
+    optimizer = getattr(model_selection, optimizer)
+
+    # handle gridsearchcv 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"]
+        else:
+            c = None
+
+        df_key = groups + repr(header)
+
+        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 = groups.ravel()
+        options["cv_selector"]["groups_selector"] = groups
+
+    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
+
+    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":
+        searcher = optimizer(estimator, param_grid, **options)
+        print(searcher)
+        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,
+    )
+
+    # 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":
+        main_est.set_params(memory=memory)
+
+    searcher = optimizer(estimator, param_grid, **options)
+
+    split_mode = params["outer_split"].pop("split_mode")
+
+    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")):
+            warnings.warn("Refit is change to `True` for nested validation!")
+            setattr(searcher, "refit", True)
+
+        outer_cv, _ = get_cv(params["outer_split"]["cv_selector"])
+        # nested CV, outer cv using cross_validate
+        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,
+            )
+        else:
+            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,
+                    )
+                except ValueError:
+                    pass
+                for warning in w:
+                    print(repr(warning.message))
+
+        fitted_searchers = rval.pop("estimator", [])
+        if fitted_searchers:
+            import os
+
+            pwd = os.getcwd()
+            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_path = os.path.join(pwd, save_dir, target_name)
+                    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)
+            except Exception as e:
+                print(e)
+            finally:
+                del os
+
+        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"):
+                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)
+        # deprecate train test split mode
+        """searcher = _do_train_test_split_val(
+            searcher, X, y, params,
+            primary_scoring=primary_scoring,
+            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":
+            searcher.fit(X, y, groups=groups)
+        else:
+            warnings.simplefilter("always", FitFailedWarning)
+            with warnings.catch_warnings(record=True) as w:
+                try:
+                    searcher.fit(X, y, groups=groups)
+                except ValueError:
+                    pass
+                for warning in w:
+                    print(repr(warning.message))
+
+        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)
+
+    memory.clear(warn=False)
+
+    # output best estimator, and weights if applicable
+    if outfile_object:
+        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!"
+            )
+            return
+
+        # clean prams
+        best_estimator_ = clean_params(best_estimator_)
+
+        main_est = get_main_estimator(best_estimator_)
+
+        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):
+                del main_est.data_generator_
+
+        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)
+
+
+if __name__ == "__main__":
+    aparser = argparse.ArgumentParser()
+    aparser.add_argument("-i", "--inputs", dest="inputs", required=True)
+    aparser.add_argument("-e", "--estimator", dest="infile_estimator")
+    aparser.add_argument("-X", "--infile1", dest="infile1")
+    aparser.add_argument("-y", "--infile2", dest="infile2")
+    aparser.add_argument("-O", "--outfile_result", dest="outfile_result")
+    aparser.add_argument("-o", "--outfile_object", dest="outfile_object")
+    aparser.add_argument("-w", "--outfile_weights", dest="outfile_weights")
+    aparser.add_argument("-g", "--groups", dest="groups")
+    aparser.add_argument("-r", "--ref_seq", dest="ref_seq")
+    aparser.add_argument("-b", "--intervals", dest="intervals")
+    aparser.add_argument("-t", "--targets", dest="targets")
+    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,
+    )
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple_model_fit.py	Tue Apr 13 22:40:10 2021 +0000
@@ -0,0 +1,194 @@
+import argparse
+import json
+import pickle
+
+import pandas as pd
+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))
+
+
+# TODO import from galaxy_ml.utils in future versions
+def clean_params(estimator, n_jobs=None):
+    """clean unwanted hyperparameter settings
+
+    If n_jobs is not None, set it into the estimator, if applicable
+
+    Return
+    ------
+    Cleaned estimator object
+    """
+    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"):
+            new_p = {name: None}
+            estimator.set_params(**new_p)
+        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"):
+            for cb in p:
+                cb_type = cb["callback_selection"]["callback_type"]
+                if cb_type not in ALLOWED_CALLBACKS:
+                    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
+
+    Parameters
+    ----------
+    params : dict
+        Tool inputs parameter
+    infile1 : str
+        File path to dataset containing features
+    infile2 : str
+        File path to dataset containing target values
+
+    """
+    # store read dataframe object
+    loaded_df = {}
+
+    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"]
+        else:
+            c = None
+
+        df_key = infile1 + repr(header)
+        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"))
+
+    # 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"]
+    else:
+        c = None
+
+    df_key = infile2 + repr(header)
+    if df_key in loaded_df:
+        infile2 = loaded_df[df_key]
+    else:
+        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)
+    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
+
+    Parameters
+    ----------
+    inputs : str
+        File path to galaxy tool parameter
+
+    infile_estimator : str
+        File paths of input estimator
+
+    infile1 : str
+        File path to dataset containing features
+
+    infile2 : str
+        File path to dataset containing target labels
+
+    out_object : str
+        File path for output of fitted model or skeleton
+
+    out_weights : str
+        File path for output of weights
+
+    """
+    with open(inputs, "r") as param_handler:
+        params = json.load(param_handler)
+
+    # load model
+    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 out_weights:
+            main_est.save_weights(out_weights)
+        del main_est.model_
+        del main_est.fit_params
+        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(out_object, "wb") as output_handler:
+        pickle.dump(estimator, output_handler, pickle.HIGHEST_PROTOCOL)
+
+
+if __name__ == "__main__":
+    aparser = argparse.ArgumentParser()
+    aparser.add_argument("-i", "--inputs", dest="inputs", required=True)
+    aparser.add_argument("-X", "--infile_estimator", dest="infile_estimator")
+    aparser.add_argument("-y", "--infile1", dest="infile1")
+    aparser.add_argument("-g", "--infile2", dest="infile2")
+    aparser.add_argument("-o", "--out_object", dest="out_object")
+    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,
+    )
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stacking_ensembles.py	Tue Apr 13 22:40:10 2021 +0000
@@ -0,0 +1,125 @@
+import argparse
+import ast
+import json
+import pickle
+import sys
+import warnings
+
+import mlxtend.classifier
+import mlxtend.regressor
+import pandas as pd
+from galaxy_ml.utils import get_cv, get_estimator, get_search_params, load_model
+
+
+warnings.filterwarnings("ignore")
+
+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):
+    """
+    Parameter
+    ---------
+    inputs_path : str
+        File path for Galaxy parameters
+
+    output_obj : str
+        File path for ensemble estimator ouput
+
+    base_paths : str
+        File path or paths concatenated by comma.
+
+    meta_path : str
+        File path
+
+    outfile_params : str
+        File path for params output
+    """
+    with open(inputs_path, "r") as param_handler:
+        params = json.load(param_handler)
+
+    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:
+                model = load_model(handler)
+        else:
+            estimator_json = params["base_est_builder"][idx]["estimator_selector"]
+            model = get_estimator(estimator_json)
+
+        if estimator_type.startswith("sklearn"):
+            named = model.__class__.__name__.lower()
+            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 meta_path:
+            with open(meta_path, "rb") as f:
+                meta_estimator = load_model(f)
+        else:
+            estimator_json = params["algo_selection"]["meta_estimator"]["estimator_selector"]
+            meta_estimator = get_estimator(estimator_json)
+
+    options = params["algo_selection"]["options"]
+
+    cv_selector = options.pop("cv_selector", None)
+    if cv_selector:
+        splitter, _groups = get_cv(cv_selector)
+        options["cv"] = splitter
+        # set n_jobs
+        options["n_jobs"] = N_JOBS
+
+    weights = options.pop("weights", None)
+    if weights:
+        weights = ast.literal_eval(weights)
+        if weights:
+            options["weights"] = weights
+
+    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
+        ensemble_estimator = klass(base_estimators, **options)
+
+    elif mod == mlxtend.classifier:
+        ensemble_estimator = klass(classifiers=base_estimators, meta_classifier=meta_estimator, **options)
+
+    else:
+        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:
+        pickle.dump(ensemble_estimator, out_handler, pickle.HIGHEST_PROTOCOL)
+
+    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)
+
+
+if __name__ == "__main__":
+    aparser = argparse.ArgumentParser()
+    aparser.add_argument("-b", "--bases", dest="bases")
+    aparser.add_argument("-m", "--meta", dest="meta")
+    aparser.add_argument("-i", "--inputs", dest="inputs")
+    aparser.add_argument("-o", "--outfile", dest="outfile")
+    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,
+    )
Binary file test-data/GridSearchCV.zip has changed
Binary file test-data/LinearRegression01.zip has changed
Binary file test-data/LinearRegression02.zip has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/RF01704.fasta	Tue Apr 13 22:40:10 2021 +0000
@@ -0,0 +1,4 @@
+>CP000097.1/1411351-1411410
+CAACGUUCACCUCACAUUUGUGAGGCGCAGACAACCCAGGCCAAGGAACGGGGACCUGGA
+>ACNY01000002.1/278641-278580
+GAUCGUUCACUUCGCAUCGCGCGAAGCGCAGUUCGCCUCAGGCCAUGGAACGGGGACCUGAG
Binary file test-data/RFE.zip has changed
Binary file test-data/RandomForestClassifier.zip has changed
Binary file test-data/RandomForestRegressor01.zip has changed
Binary file test-data/StackingCVRegressor01.zip has changed
Binary file test-data/StackingCVRegressor02.zip has changed
Binary file test-data/StackingRegressor02.zip has changed
Binary file test-data/StackingVoting03.zip has changed
Binary file test-data/XGBRegressor01.zip has changed
Binary file test-data/abc_model01 has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/abc_result01	Tue Apr 13 22:40:10 2021 +0000
@@ -0,0 +1,6 @@
+0	1	2	3	predicted
+3.68258022948	2.82110345641	-3.9901407239999998	-1.9523364774	1
+0.015942057224	-0.7119585943469999	0.125502976978	-0.972218263337	0
+2.0869076882499997	0.929399321468	-2.1292408448400004	-1.9971402218799998	1
+1.4132105208399999	0.523750660422	-1.4210539291	-1.49298569451	1
+0.7683140439399999	1.38267855169	-0.989045048734	0.649504257894	1
Binary file test-data/abr_model01 has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/abr_result01	Tue Apr 13 22:40:10 2021 +0000
@@ -0,0 +1,6 @@
+0	1	2	3	4	predicted
+86.97021227350001	1.00532111569	-1.01739601979	-0.613139481654	0.641846874331	0.323842059244
+91.2021798817	-0.6215229712070001	1.11914889596	0.390012184498	1.28956938152	1.1503117056799999
+-47.4101632272	-0.638416457964	-0.7327774684530001	-0.8640261049779999	-1.06109770116	-0.7191695359690001
+61.712804630200004	-1.0999480057700002	-0.739679672932	0.585657963012	1.4890682753600002	1.1503117056799999
+-206.998295124	0.130238853011	0.70574123041	1.3320656526399999	-1.3322092373799999	-0.7191695359690001
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/accuracy_score.txt	Tue Apr 13 22:40:10 2021 +0000
@@ -0,0 +1,2 @@
+accuracy_score : 
+0.8461538461538461
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/auc.txt	Tue Apr 13 22:40:10 2021 +0000
@@ -0,0 +1,2 @@
+auc : 
+2.5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/average_precision_score.txt	Tue Apr 13 22:40:10 2021 +0000
@@ -0,0 +1,2 @@
+average_precision_score : 
+1.0
Binary file test-data/best_estimator_.zip has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/best_params_.txt	Tue Apr 13 22:40:10 2021 +0000
@@ -0,0 +1,1 @@
+{'estimator__n_estimators': 100}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/best_score_.tabular	Tue Apr 13 22:40:10 2021 +0000
@@ -0,0 +1,2 @@
+best_score_
+0.7976348550293088
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/blobs.txt	Tue Apr 13 22:40:10 2021 +0000
@@ -0,0 +1,101 @@
+0	1	0
+0.33681845896740	-3.40287961299073	0
+-9.48324265575857	-8.66266051536995	2
+-1.93336328496076	5.70953908146890	1
+-10.03182405989413	-5.57834393458362	2
+0.54186077661701	-4.37693628326930	0
+-8.12962929067378	-7.05554320549807	2
+-0.73082578569427	7.32375551699482	1
+-1.84142532007015	6.20630466830832	1
+0.41007185031668	-3.99744881000119	0
+-8.73509589323240	-5.49090535208751	2
+1.84941962277054	-3.91839345672969	0
+-9.15256068848857	-9.17805648051067	2
+-3.21429939077830	5.75926163957071	1
+0.28450378549664	-3.61576522643830	0
+-0.92907484922306	5.79099955373578	1
+0.36692524194483	6.51861929622910	1
+1.59909917965412	-3.07105617297875	0
+-9.71270568435724	-7.91707651499009	2
+-10.08040443063205	-6.55135324108655	2
+1.10594345774293	-4.41906374949547	0
+2.48708049649457	-2.89100712361067	0
+0.00587148930883	-3.18314255539710	0
+1.61854359735349	-4.88855922559208	0
+-9.15856722108140	-7.13894114847511	2
+-3.07633571459573	7.80049676786476	1
+0.11174653022487	-3.61615828710479	0
+-9.43932350782336	-7.29863034570663	2
+-1.69466229591445	4.40837111117530	1
+1.05261752638325	-3.49553009701512	0
+-10.50560592102942	-5.99245086001851	2
+1.54081964152897	-4.53702344151471	0
+0.32228789680820	6.89854008042929	1
+0.61621969660610	-5.27504803637537	0
+-10.22545392329864	-8.71635918421430	2
+-10.61004107591557	-8.15999270542289	2
+-0.74547966700287	-2.96189843151195	0
+0.78848758990191	-5.32234377938911	0
+-10.42005276754933	-7.78467770434098	2
+-2.90664752997062	5.79835066175825	1
+-10.32143921202120	-8.92712052109752	2
+-0.21338559861828	7.84779827247996	1
+-0.07194732572546	-5.26054466248995	0
+-7.60696893546687	-7.73382713697845	2
+-1.37722038386856	6.91773657443747	1
+-3.21560019075551	7.26468660350508	1
+-10.36154489539457	-6.91944465708303	2
+-9.60457341239248	-9.25351754602290	2
+-2.72690231565835	6.73825747902294	1
+-2.80603999216749	6.99066208996353	1
+-0.81952671479263	7.58241271253648	1
+-2.08847400980833	5.69607144720414	1
+-0.31991876149841	-4.98235849165957	0
+-11.32066579703307	-8.20937750734829	2
+-7.96236061274655	-9.01605369665730	2
+2.16784691057462	-6.16570792177736	0
+1.89502027521910	-5.86480290918300	0
+-8.66871499099032	-7.79890226276482	2
+2.05772110384843	-6.12322912450768	0
+-9.31359960682017	-8.00568199998929	2
+-0.76743056356151	-5.47682217583339	0
+-3.46772941922521	6.76072133440808	1
+1.09049844437461	-5.87582929334941	0
+-0.11521126331032	-4.07510454495671	0
+1.08927850504071	-5.50265562869237	0
+-0.61505047925733	7.65521576624828	1
+0.42996321311489	-5.55093054437951	0
+-0.75919485469050	5.58853030731725	1
+-9.12599657251685	-8.00673850068656	2
+-9.77537442082784	-6.61925671967673	2
+-3.01723334528173	7.00340677720469	1
+-0.97308946436741	-4.06651907195677	0
+-0.48830021304200	-5.66504681203900	0
+-11.92081159330307	-7.64815817127183	2
+-9.38262507165980	-7.58496298709520	2
+0.07652275340590	7.58891330491466	1
+0.97696230365299	-3.92480270763176	0
+-7.83082970823398	-7.91191526652019	2
+-3.00736856610051	5.70163666960614	1
+-1.87511017769397	5.62449960555141	1
+-9.68323206673510	-8.25353931958495	2
+-9.30119933759135	-8.47564800181842	2
+0.32365967414684	-5.10078403493750	0
+-1.74836105433202	5.46645574794978	1
+-0.56064340851208	6.87612506043561	1
+0.67860300499613	-4.17761085385070	0
+-8.20199888805984	-8.29076835439347	2
+-3.05026420956995	8.94223661488021	1
+-8.81193622652183	-7.79813533757767	2
+-9.16862770716234	-7.13275033182281	2
+-4.48296365906822	6.92883992453694	1
+-10.52225224786374	-6.80543393827772	2
+-1.58567165074196	6.89948024038567	1
+-1.75853685207545	6.44534621138642	1
+-9.91452153947266	-8.11181559274489	2
+-1.40077619511942	6.92380628122115	1
+-1.19228020907627	6.14310846867304	1
+0.87541339904821	-5.04555103360224	0
+1.48113771750685	-3.69640708480025	0
+0.52495937648759	6.34480823448348	1
+-0.01369955366371	-4.41397334863602	0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/brier_score_loss.txt	Tue Apr 13 22:40:10 2021 +0000
@@ -0,0 +1,2 @@
+brier_score_loss : 
+0.24051282051282052
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/circles.txt	Tue Apr 13 22:40:10 2021 +0000
@@ -0,0 +1,101 @@
+0	1	0
+-0.06279051952931	-0.99802672842827	0
+0.05023241562345	0.79842138274262	1
+-0.99211470131448	-0.12533323356430	0
+0.42577929156507	-0.90482705246602	0
+-0.30901699437495	-0.95105651629515	0
+-1.00000000000000	-0.00000000000000	0
+-0.18738131458572	-0.98228725072869	0
+-0.53582679497900	-0.84432792550202	0
+-0.77486652890290	-0.19895190973188	1
+-0.87630668004386	0.48175367410172	0
+-0.24721359549996	-0.76084521303612	1
+0.80000000000000	0.00000000000000	1
+0.42866143598320	-0.67546234040161	1
+-0.58317490193713	0.54763768474295	1
+0.70104534403509	-0.38540293928137	1
+-0.74382118871060	-0.29449964214774	1
+-0.74382118871060	0.29449964214774	1
+0.80901699437495	0.58778525229247	0
+0.30901699437495	-0.95105651629515	0
+0.18738131458572	0.98228725072869	0
+-0.87630668004386	-0.48175367410172	0
+-0.42866143598320	-0.67546234040161	1
+-0.50993919179895	-0.61641059422063	1
+0.63742398974869	-0.77051324277579	0
+-0.92977648588825	-0.36812455268468	0
+-0.92977648588825	0.36812455268468	0
+-0.96858316112863	0.24868988716485	0
+0.24721359549996	-0.76084521303612	1
+-0.14990505166858	-0.78582980058295	1
+-0.80901699437495	0.58778525229247	0
+-0.63742398974869	-0.77051324277579	0
+0.72896862742141	0.68454710592869	0
+0.92977648588825	0.36812455268468	0
+0.06279051952931	0.99802672842827	0
+0.79369176105158	0.10026658685144	1
+-0.34062343325206	-0.72386164197282	1
+-0.77486652890290	0.19895190973188	1
+-0.14990505166858	0.78582980058295	1
+0.70104534403509	0.38540293928137	1
+-0.50993919179895	0.61641059422063	1
+-0.80000000000000	-0.00000000000000	1
+-0.79369176105158	0.10026658685144	1
+0.50993919179895	0.61641059422063	1
+0.53582679497900	-0.84432792550202	0
+-0.79369176105158	-0.10026658685144	1
+0.79369176105158	-0.10026658685144	1
+-0.53582679497900	0.84432792550201	0
+0.50993919179895	-0.61641059422063	1
+-0.05023241562345	0.79842138274262	1
+1.00000000000000	0.00000000000000	0
+-0.63742398974869	0.77051324277579	0
+0.72896862742141	-0.68454710592869	0
+0.06279051952931	-0.99802672842827	0
+0.80901699437495	-0.58778525229247	0
+0.18738131458573	-0.98228725072869	0
+-0.64721359549996	0.47022820183398	1
+0.58317490193713	-0.54763768474295	1
+-0.80901699437495	-0.58778525229247	0
+-0.70104534403509	0.38540293928137	1
+0.87630668004386	-0.48175367410172	0
+0.58317490193713	0.54763768474295	1
+-0.64721359549996	-0.47022820183398	1
+0.34062343325206	-0.72386164197282	1
+0.05023241562345	-0.79842138274262	1
+-0.72896862742141	0.68454710592869	0
+-0.58317490193713	-0.54763768474295	1
+0.64721359549996	0.47022820183398	1
+0.14990505166858	-0.78582980058295	1
+0.14990505166858	0.78582980058295	1
+-0.24721359549996	0.76084521303612	1
+0.92977648588825	-0.36812455268468	0
+0.99211470131448	-0.12533323356430	0
+0.63742398974869	0.77051324277579	0
+0.74382118871060	-0.29449964214774	1
+0.34062343325206	0.72386164197282	1
+0.64721359549996	-0.47022820183398	1
+-0.06279051952931	0.99802672842827	0
+0.99211470131448	0.12533323356430	0
+-0.72896862742141	-0.68454710592869	0
+0.87630668004386	0.48175367410172	0
+-0.96858316112863	-0.24868988716486	0
+0.96858316112863	0.24868988716485	0
+0.42577929156507	0.90482705246602	0
+-0.42577929156507	0.90482705246602	0
+0.42866143598320	0.67546234040161	1
+0.24721359549996	0.76084521303612	1
+-0.30901699437495	0.95105651629515	0
+0.77486652890290	-0.19895190973188	1
+-0.42577929156507	-0.90482705246602	0
+-0.18738131458572	0.98228725072869	0
+-0.34062343325206	0.72386164197282	1
+0.74382118871060	0.29449964214774	1
+0.77486652890290	0.19895190973188	1
+0.30901699437495	0.95105651629515	0
+0.96858316112863	-0.24868988716485	0
+-0.70104534403509	-0.38540293928137	1
+-0.05023241562345	-0.79842138274262	1
+-0.42866143598320	0.67546234040161	1
+-0.99211470131448	0.12533323356430	0
+0.53582679497900	0.84432792550202	0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/class.txt	Tue Apr 13 22:40:10 2021 +0000
@@ -0,0 +1,101 @@
+0	1	2	3	4	5	6	7	8	9	10	11	12	13	14	15	16	17	18	19	0
+1.103931098477063	1.1137324694427062	2.929660893432376	0.8263678474871072	-0.5024439301629023	-0.9778311716440287	-0.6702242261982462	-0.3783418745400049	-1.9100911341304148	0.41080891898717925	1.6359138753477174	-0.3544401787737543	-0.7776883945882607	-0.711126068648103	-1.1632958763488586	2.881523323585383	-0.3331610016599995	1.0249635446624175	-1.204722529676112	0.9686027151980944	1
+-0.5270034201986623	-2.4370266994140035	-0.46398126201591683	0.6724964425333426	0.32128693891873533	-1.4561055975293318	0.9733737109300644	1.2635448363305384	-0.9655190314614323	-0.30440284592936967	0.2928325635717791	-0.642481126749871	-0.17778292517384178	-0.23575096986827987	0.770818433376395	1.002493460919832	0.44402946209787597	0.38673364020325446	-1.0909759530149077	0.4374172416803542	1
+0.6343790937890923	-0.7044557030990274	-1.5479925634100813	-1.1375423986557498	0.7574995244231507	-0.2586895904715146	1.2113185073849615	0.8255591814670258	1.0488550790559334	-0.013557918030451043	-0.36824556412752163	-1.8422341740345995	0.9791413360462421	-0.23658235285975457	0.3758968273279556	-0.7379662029189028	-0.9558490082424093	-0.45167227065102006	-0.13587675227718632	-0.43481791249648283	0
+-0.2749398078895973	-0.602759369823714	-0.34817063773317436	1.2165805903649096	0.08822993442548502	-0.9828118947823061	1.1255554529825982	-0.5951138391567017	1.359567367140958	1.14745743851399	-2.2691569946862655	0.9270532988002531	-1.28390481061431	0.702184505359777	1.1599689740750685	-0.7022781266128805	-1.5820069707072104	-0.1640254026760564	-0.6268539047283007	-0.5343960171949464	0
+-0.8451664655381013	0.9592831641658773	0.29032122469609184	1.4456183940991385	-2.2668849557948265	0.49356800079005453	0.9973927328851383	-1.7077448427289017	-1.525140006218017	-0.2628130337984583	-0.6987088119151889	0.12372879270054708	-0.37829745272534815	-0.0010588423370812654	3.1974829539733727	1.7610392441369824	0.461991697252764	-0.8707192095484595	0.4949902726326138	0.7113500316301005	1
+-0.6479921130452116	-0.9442706004373587	0.20181386383006028	-1.0034745347115275	-0.9369221110721804	-1.003380717730042	-0.7275212508545039	-0.1820208348243829	0.869148773329888	-0.7855214383236936	0.1360612935062583	2.0654861372867295	-1.2399203282859266	-0.44615385943239716	1.7347311831934773	-0.6314619246803259	-0.76518919295205	1.2707549044789055	-0.7323378102483927	-0.3626096934734513	0
+-0.06451309551365764	-0.7249330776348837	0.5963143554325262	-1.379225616134922	1.1667980284973485	-2.274070053731467	0.7411405179848544	-0.6631329812615014	-1.567155162052582	-0.09527290234272089	-0.7316650418582739	-1.0020134142607244	-0.6953396335230776	1.5807860908438993	0.3379535699933314	1.8800551896643136	0.37962716233848903	0.5363444440333102	0.1390867505544731	0.7390508093906831	1
+0.7576049876525334	0.8726631262318649	0.8478637181249223	0.30198299200599726	1.0101338828657191	-1.3836221562341127	1.0376123351490436	1.0937481979752155	1.3929535047023875	0.8760511854123076	-1.2981174812942935	0.3025477016355275	-0.14253519602584672	1.2887025562956078	2.1562199933480133	-1.0111580468681463	-1.2275056029861684	-0.2688763993683175	-2.2719054986176683	-0.5810422898079113	0
+2.5394320331114613	0.46034921066168377	0.8315330299051433	-0.9396024430587621	-0.37614736761593637	-0.17996331764913345	1.455421460737774	1.5223077678776793	1.1770030840483332	0.40359841542535574	-0.03766667059723912	0.2415068878754467	-0.44558826380657596	1.2774520318648948	-1.8848343873195796	-0.23434224565939143	-1.8735210102773319	2.299369468755593	0.11182257854217889	-0.41968753568332984	0
+-1.1654317335035704	-0.23406889069910192	-1.3485118844184532	0.7912949804001552	-0.19206908223922012	-2.752037662677927	-1.6014139415281856	-0.5108631934878929	1.4041570989659866	0.5382460975045578	0.012866884184724063	0.7910261496852212	-0.5285056361126661	-2.874968879865529	-0.8428605517089753	-1.4276668142409976	-0.6865704170544349	0.8660591728218054	1.176952513690748	-0.6326584957221068	0
+0.9050654404010442	1.5248626005482613	0.0537117476660896	0.10714253527293145	0.5436279322698345	-0.9162199391704404	1.1974173477959238	-1.6813868155498577	0.465763145265903	1.6525856413988107	-2.023763530020729	-1.2225052973966217	0.48905360189011937	-0.06340532135397717	-0.8428196875999223	0.9810796287807456	-2.1897236651211855	-0.5362903624231383	0.6151521853927577	-0.042643618877945336	1
+0.2854489945462638	0.3530051834614323	0.1332902420274303	-2.066453723784956	-0.2645836803644654	0.5245478462345327	0.2238241190906629	-0.48256531456153773	0.13249140142592644	0.9127282586749043	2.6474189892831026	-0.37219899010144253	-1.548077411041423	0.662893215100046	-0.8853951972314839	1.183629012690877	-1.8429271907244553	0.8100978673990902	-0.3284080793917298	0.09184768542206719	1
+-1.3227165003614927	-0.7799983027126963	0.18479275551351085	-0.14231230753550203	-1.3945327153213618	-0.0758997670485449	0.6986307702990094	1.6282076357873105	0.18237029611060487	-0.7109024225989671	-0.2724518087709634	0.4729134646484038	0.5454540297228883	-1.0722422723792842	-0.606184110109761	0.8021132176384902	-1.4211379561267314	-0.3389835320929106	-1.44904592785806	0.031348504552504486	1
+-2.197691926666584	-1.7077148903852681	-0.6449885420999844	-0.06865025280146782	0.4202392504617797	0.968886848221698	-0.005924072251181685	-0.6511305169582245	0.3998134505861388	0.892257884749868	1.3521367585609907	-0.7404970062580767	-0.46898715506363886	1.275597323305137	0.14386099595965895	-1.838491122688009	1.7359354044223765	-0.1551428089500599	-0.43232000255589664	-0.3447470104944261	0
+-0.2670710335696844	1.7812245781622742	-1.1329343313282814	-0.24423451883692596	0.7548220931778789	-1.8862883675077626	0.6526294599846313	-0.3676598535224105	-0.2448455084452909	-0.6772836861850628	0.5942014265411584	0.2375037940405147	-1.1168006401508905	2.6256144457846546	-0.6716078230151616	-0.2989663691054665	0.8587286854080793	0.4974278727895833	1.0406815179638391	0.047335395957696466	0
+-0.4829965988829622	-0.8664172853019196	0.010536697447195188	-0.24957125769621874	-0.5053469214826972	-0.5661823837482267	1.397031114430776	0.9362535725466031	0.8494481273008917	-2.3689801750315524	-0.11515634319648775	-0.8619219742938617	0.5524984188665393	1.5190033138842483	-0.9215808226333405	-2.2309955927486342	1.4288742583770047	-0.5196163599941902	2.2436594507282206	-0.5399023920325723	0
+0.988208848486463	-2.585767588999438	-0.009847287471481413	0.30217682520827216	-2.221510823700524	0.9425068791712249	0.6889213621579444	-1.0110351209554707	1.3983331823298473	0.017600206923097966	-0.49772668445684926	0.041274574202699865	0.39315819224910903	0.687759695794799	0.8198061540197786	-1.6938202943901621	-0.31675443490083666	-0.5176603237193814	0.7734409975442094	-0.6613095000652233	0
+-1.6500251948243565	-0.5881887751399346	-0.008457486200020091	-1.0255372547670172	2.883969251775838	0.6841194893268114	0.36522540717596585	-0.4063786899313203	-0.4597632229684979	0.6689473090641462	0.5824042646735971	0.3231095013887879	0.59519151467352	0.40271751266444333	0.2803223035037342	1.1596486152072958	-0.7088028618998904	-1.7236514338073596	0.5349275937487872	0.28671842601834485	1
+0.30430567959512733	-0.6926221975020497	-0.3586531509541748	0.11220827271785544	-0.6418145875587414	0.40043811487947506	-0.5627558800719191	1.5870889370740489	-1.1979020496525155	0.9287687328933728	-0.9429787966287079	-0.4694866980716366	0.5476098176306101	0.9911844589581342	-1.890064241013992	0.810682748482377	1.135044917480963	0.5813591730005884	1.5988127102205738	0.4929116267678903	1
+0.40492907257520244	-0.6514435841992149	1.8847060544535634	0.25069797962239826	0.2098594845826785	-0.8699566545276876	0.7644150970416564	-0.5372191508425196	0.8513726693635947	-1.6024845301638289	-0.23003580655162623	-1.0594997311547119	0.1503781049950916	-0.697530591149039	-0.06048301501585981	-1.225374349155504	0.06893531119317442	-0.5498117799824236	0.2629482684151777	-0.42494833533236415	0
+-0.6938752020747251	-0.16425303413718284	-0.786824522255031	1.7668617516726024	0.1351177762474505	-0.6769151658288148	1.099720527820615	-0.2108673539727271	-0.09240517052244847	1.9753281712575461	1.0326537546555192	-0.5857366554551754	2.527070920782692	-1.1314983848532563	-1.2203869916654786	0.5386023310337225	-0.5545516579065658	1.617741961423047	0.026714277801613007	0.09274673011429316	1
+-1.2855738604138573	0.9527052435093047	-0.5393910228200474	0.1406950564673274	0.6278876784461687	2.2921936458109897	-0.8296277386100398	-0.8276017374999237	-0.5691114767876203	-0.7804341795136254	-0.3115251054922687	1.1604663708722944	-0.45823039827601697	0.096940343318409	-0.4661721263852442	0.7914638179665774	-0.008781526693367847	0.540432755366913	1.2382624131362387	0.2808835720014097	1
+0.01971106661270503	0.022725782621203446	-0.7171971284211488	-0.844608668797061	0.17759075527122256	0.32351256640857523	1.1092738552242762	0.8459134704189475	-1.0092620261375949	0.3312851879047735	0.8493202690407095	0.7463122829548583	2.2751079842809023	-0.365800592740796	1.392872207641418	0.2672220726832053	1.5171222642682722	0.6271956315522539	0.12548690045124972	0.3674941717644202	1
+-0.9272485993677742	-0.3992846345441018	1.0312821968019672	-1.0164811121806232	-0.5788411209471953	0.1621555997620361	1.4878944321336367	-2.305258151983712	1.0526886159889823	-1.1927713830291693	0.35643089395408944	-0.35781685235193555	0.24420707079596798	-0.7032369510661453	1.3748594175398903	-0.265531361494145	-1.6001897901099145	1.5225430928104695	1.1284147518659724	-0.38179068502908986	0
+0.8466872377493828	0.21453403707113433	0.6877174913431068	-0.4470343315836607	-0.9060867789442381	0.22357751470350606	-1.4313384494982322	0.7146958272683516	1.2868876187481681	0.6108180939736211	1.6680351279664263	-2.2704132021611114	-0.5699517962545901	-0.5390686415774785	-0.6652888855585158	-1.9249041040915857	0.2022499134735356	1.4692083028521956	0.9692133398427439	-0.650684739883086	0
+-0.601702497867707	0.03192366589002642	-1.0154893571166628	1.2277054932407083	-0.17345609362160444	1.3508013650170736	-0.8603704762851204	0.7158372997438407	0.609842377909055	0.26686482080895313	-0.21636159151507584	1.4178789398571483	0.07902571896854252	1.6204683987456092	-1.0280706824933712	-1.405364977188804	0.7610249189649491	-0.7259753124258116	-1.1264854630318841	-0.3650429101933015	0
+0.2407422845881994	2.8857517953922764	-0.023980761898605114	-0.45619206614093344	0.6177594707762792	-0.08768373982573438	1.7598211003608997	-0.031028697570925873	-0.49143266590475054	-0.05864391264016893	-2.2134606073911924	1.0913309075290665	0.9117965623133085	-0.12278570026442888	-0.8739999199474732	1.1171072920808645	-0.5925089707550872	1.2372535126873845	2.124745399513117	0.2923959583087956	1
+0.17584571165005292	-0.8511320881692872	-2.2051034645754948	-0.6116310759188245	-1.2047158798971238	0.66839521890313	0.8991245292770655	0.4741248277718854	0.1760900687774567	-0.6307555906525206	0.9535866516994639	0.9371915337062796	-1.4228495469631228	0.16029074988453906	1.8555455403701624	-1.869116730286061	2.1934384645923486	-2.281305792694086	2.8097011435732293	-0.2736139860084672	0
+0.5242236519537231	-0.06307879670506915	-1.3294456177962388	0.8242892015046335	-1.081258571215189	1.3449502719441988	-0.50356048600791	-0.38621990548929036	-0.05314119332051215	-0.45271329511708064	0.087257980752205	-2.050905763049373	1.1197161016785873	0.9167469515279244	0.687592786751324	0.8579972616602627	-1.0583875221093613	0.7563768879274201	0.37967322200031345	0.11635935179374274	1
+0.558346902284024	-0.9309696527726209	-2.0842708835548924	0.030877752980638058	1.0396388948858852	-0.3022844248616988	-1.277629080640249	-0.6294458606293386	1.238756470825371	0.13639753659343484	-0.3188074229604005	-0.9443200259389776	-0.41149095236240474	-1.337165050885127	-0.33733841113672913	-1.0953021286821771	-0.8271589650497895	1.2703115446925113	0.6531758521433048	-0.5392612125425414	0
+-0.7379887070817857	-1.2626042854762183	0.17912390469970796	0.32669169909966733	-0.5343938353030584	-0.8617991799058063	-1.0231988412194268	-2.38861407368411	-0.15825189124877934	1.3263448403293359	1.7165027742351253	0.5384660112416041	1.3283330921381156	0.21309224825039347	0.9270035239969678	0.9968859637509941	-1.0501783925356227	-0.4559683500449692	0.6819648840132921	0.16739862639293818	1
+1.4476040528943543	-0.6314322515594253	0.14853198602056514	0.1396675784886334	0.016672373423269438	0.16564178605539887	-1.0040158066788205	-0.5327923727826095	1.147051857581131	-1.1417786944082575	0.44682624679647864	-1.3120985315266447	0.7869814652437135	-0.46902780374760905	0.7464021537026985	-1.153959736241712	-0.5774434779881016	1.8363081603106133	-1.7651938506826501	-0.5154033311511862	0
+-0.694949123737318	1.4480014208760492	1.114733892631557	1.3552725615328403	0.32870245607283527	2.182275910834502	-0.43728724254382445	-0.32108899071015246	1.7059375939854156	-1.0144720406973653	-1.1268282836571295	0.9114744851303214	0.2876311214263635	-0.9194792276680201	0.8712160137184647	-1.6822107044034538	-0.9046542625496667	-1.2265674316518074	-0.08885766708388806	-0.7626183729066613	0
+-0.4951739548431622	3.075573893432424	0.7125389403746353	0.7127480011897636	3.85793967348964	-1.380114296433079	0.830819563694863	1.6659047027918155	1.692437606180482	0.132962280436304	0.13986220576101485	-0.8782681675417305	0.692696057131838	0.21421904746683115	-0.08289852500467178	-1.697739157869832	-0.8585956144545324	0.3596237434172795	1.0687856807518747	-0.7598986082131621	0
+-0.24659729953406678	0.48028838228527204	-0.021175774300496716	-0.3664962494470602	0.01003713940839754	-0.25227004044698087	-1.9569675522430627	-0.22013056376799153	1.0072449553370086	1.490533097267343	-1.163235822180662	-0.564484658307677	-0.6542808538079327	0.3252062923168107	-0.39939137701024663	-0.4953677656109705	-1.2056522392978473	0.33107168261445835	0.8604754069049109	-0.3930464701607799	0
+1.0901528926431487	-0.9453346120985947	-0.4729131940164531	1.443087583454784	-1.4130407277334363	0.24204583536789437	1.5221528599715186	-1.4925201736211136	-0.750070599045198	1.0925633619786013	-0.6563789851711918	2.000672024084738	1.9550554438780816	0.8237126081224749	-0.32415019818829954	0.3320842417897454	0.947459986817773	1.746256318275166	-0.9194491847633625	0.28846144012404507	0
+0.8621689184981023	0.07355255089438108	-0.8847286012386693	0.4796962084572591	0.5677535540962639	-2.5289475108846857	0.7483241867237762	2.288635291333243	-0.4638726726966315	-1.4726571262457677	1.2522315626273022	0.9146566431112833	1.3432368831212602	-0.1516899652786653	0.6523101983645719	0.8002795439355803	-0.2164492931029829	1.175609480746336	-0.5899674340661235	0.2467801870809084	1
+1.8327334301292564	2.7250208073497655	0.8850898918686639	2.02577923393804	1.1993328107538388	-0.6080810819389247	0.45076298555579936	-0.8695507065224324	1.4966446042512176	0.9689045577333327	-0.040195475275759104	-0.8394777244112416	1.3016102245353771	0.7079943796338916	0.170770931967963	-1.9468700714932357	-0.1583369501288343	1.5860651416439473	1.5303010308595233	-0.7232027745913409	0
+0.45675680055100876	1.6862402750755072	-0.3339099307005731	0.9727972485358709	1.5405555309799355	0.5095493726194038	-1.1769248912579864	0.14688445026802582	-1.8923413151325892	-0.3597035854371358	0.034288605346101064	-0.1895277822930986	-1.5451347924726995	1.2116386663488123	-0.8476549112820619	2.8325772842721397	-0.3001639683766244	-0.38212536558313037	0.30867526144867835	0.9570534912074047	1
+0.6675880922360743	0.061607686265927775	-0.5240201725381137	-0.2997158513385201	0.43035789354356024	0.36247267480026046	-2.8186530025073595	0.05633894424120396	-1.4240630471371363	0.9417552666999109	0.8621190134296215	0.827177562356735	1.276247945989341	2.297885578997527	-0.646962111575448	1.4674788351942492	0.6699042159445734	0.5558064722220939	-0.8570825503940438	0.6438772343953656	1
+-0.7230597875372071	0.7389509974901849	-1.93022327109422	-0.07844206283832174	-1.8155995691953226	0.4605439023890654	0.33409134205811086	0.27987375745446136	-2.1891803361957525	0.814324613537393	0.33687080618689497	-1.1366259127066474	0.38265856161425904	-1.6119503393696952	1.2140595171215174	3.690453997873541	-0.9050341895489411	0.9404548194318197	-0.6885408976578092	1.1547176268987822	1
+-0.20429550994058496	-0.7742446220627313	0.9314007484353164	2.565917360177608	-1.93736462781153	0.5384714676400842	0.9863681649066736	1.483178916134393	-0.9316097044806316	-0.5277830403219427	-1.328483968518206	1.1375377820834534	0.41535786515366985	-0.18726676450257188	-0.05624642393738156	0.046686315886620644	1.6701180226287295	0.4152987016284749	1.3110909185719273	0.31623204667724564	1
+-0.26759192177397656	1.2033205926353625	0.049037461548016935	-0.26722530141904327	0.9561499786482655	0.5229173631509835	-0.9762315218209106	-0.10777619396316224	1.6028516387787055	-0.4694062226879811	0.35280658284312694	-0.0751525704189141	1.3547691398570894	0.8054921061469411	-1.4257562814463445	-1.922437446100354	-0.38886964310660965	1.2860174671016282	1.3242380220962733	-0.7558340808429282	0
+-0.7430459223148423	-0.345025274037323	-0.6836501416815086	1.1810021618172988	0.4137586484133794	-1.0717355675879099	1.2401898182121198	0.7045354278052993	-0.9063430103781079	-0.8859252495127169	-2.1418516144035475	0.10342901781618742	-0.30175139488690217	0.527387687628702	-0.49581833514279516	1.0261169886240376	0.302080558087638	-1.1807980275906318	-1.0660552581621128	0.4203865372286456	1
+-0.8856978941958283	-0.5611773427197669	0.23925986087456783	0.0915712442891479	0.9195436457578192	-0.3182853136155345	-0.4101120092081721	-0.07936631605575531	0.5178580879150084	-1.645607964622266	-0.09891912036094928	0.06812570823584903	-0.07149411774529733	-0.1378586963310319	0.16979751913292426	0.9737023906726753	-2.2766864166854184	-1.2674959941594357	-0.16935301763051838	-0.06087500479564888	1
+-0.8347002345785401	-0.5852677365383244	-0.22290652406605962	-1.998282087632246	0.27650295204355396	-0.006598203487616498	2.2812721074024944	-0.7372621615773305	-0.5524691100306179	-0.8106258122291109	1.2972505366193468	1.1535198870555938	-0.9294976841312648	-0.2885403301648238	0.10382736210532115	-0.023326105815496323	1.059228248788412	0.34421346303858386	0.5515401814060694	0.1816700680401573	0
+-0.59892262579212	-1.6376756241371526	-0.378736298456714	-1.0418743710911664	2.5492856987737014	-0.6615569434901911	0.006317661817300752	-1.7976375781681988	0.046863996948282666	-0.3823403780460225	-0.13210003839031914	0.5417126512741955	-0.823533424001803	-1.3644765720109107	-0.9859808115749349	0.7527993867760319	-1.102540208655706	1.9406228046678644	-0.28559377932836866	0.07089647899954139	1
+1.3925260779906183	1.0778035873134737	0.07530237581078959	-1.6645104329617095	-0.05818985492234962	0.563949339433897	0.6791380636681086	0.5219979705833208	-0.6360766994468067	0.16841451395907342	-0.10405164557505987	0.49256225202705956	-0.5383113936858084	-0.30229931902300344	-0.3925687758796	-0.8161226282106238	2.2840703234313273	-0.38465598282466923	0.39058426076124503	0.11843675039187236	1
+1.1352016674683758	0.5648569127221107	2.397073067233959	-0.20268282272443056	-1.0917976649357448	-0.6601392708428152	-1.9445402822954807	-0.29178644639701495	0.2751710745518691	1.0097935422904265	1.5387536595031532	0.26393122365044175	-0.46273031364217426	-2.2292589330885986	-0.9134206948382958	0.8401731701415269	-1.645111014559415	1.5562083709832442	-0.1089062616381093	0.004757145532405901	1
+1.098875986566869	-0.4022899215971822	1.5175361283542563	-0.4806321621688906	-0.2984356710923274	0.6355011681954533	-0.5366404268123247	-1.2703180389254833	1.516758047371705	-2.132910373907718	0.025191903274544	0.8231244016664833	0.4804114112715212	-0.2851808701227014	0.7592043314019562	-1.6607300610426388	-0.5816933219806619	0.3696111506737348	1.0423327430213356	-0.6970225369060598	0
+0.8101916422542774	-0.6863958655184795	-0.5296495025503906	-2.593049387823186	1.3099523237532418	-0.5560681594651091	-1.1332472710708152	0.4487887875734142	1.3556075253585955	0.10193764725371153	1.0604911834109119	-0.16433173228337156	-0.24321111498677203	-0.5777727170864493	-0.2805096318513892	-2.591494319646014	0.9734907223316764	-0.4208166097429164	0.28768107786745795	-0.7502402390626048	0
+0.12340670941539608	-0.5283333516589073	-0.8105601159173703	-0.790472710889662	-0.4072015719616529	0.2499136810467275	0.7000452723146847	-0.7368148416525208	1.3152294000156877	-0.14471976544476078	-0.09180805144899466	0.07455981071053643	-1.7390992728519505	0.031047952046710476	0.06339992712334852	-2.68682916947328	1.1771921941427486	1.9998578404574014	1.2720349278692757	-0.7477253587693696	0
+-1.8463416145538356	0.9877470273404159	0.6090995914299342	-0.05454962931514019	1.5957629012804186	-0.7274708346047783	-0.4881110169164618	-0.10746411474278562	-0.22966924089385501	-0.41243382161399256	-0.4533996984310992	0.6296948056302356	-1.1360989745400003	-1.3017565892197434	-0.41546602951164513	1.0106305929502466	-0.9358580686121462	-0.8522489506584864	1.0907946273414781	0.1928095681182362	1
+-1.153885792720572	0.9710150739398405	1.2485130631114325	-0.922849593193101	0.40944806598520256	-1.2377573117811096	0.055893360103507414	-0.180323324487924	-0.9518528082448592	0.49790841207097386	-0.7935082792305357	-0.13442562190597213	0.6807164316349167	-0.7735959733304064	-2.338273386722357	0.09862297814391718	1.6377256011208965	-1.1446482896282357	-1.5573740255791648	0.32895701815399	1
+0.38416436496131556	-1.4737655176136435	0.09207904862564406	0.8282908984570213	-0.2281547965833843	-0.6788102101595077	-0.8116419957449114	-1.1963099714035128	-1.5560108513806363	0.7831220308214599	0.11250426233136833	-0.093173526942104	-0.22085148462505744	0.5748209312636592	-0.028677866459869465	1.8567762034490851	0.3902933933742653	-1.3867146526153864	0.009430420454783334	0.7326561834289222	1
+0.5333662646860791	1.2619572530223984	0.06886762106070753	0.8686502617410066	0.6091057104482803	-0.863695134710848	1.2455241795966359	-0.41089883250021403	-0.7780948095240008	0.2657401234141504	0.2092762944699149	-0.6045175428606584	1.1907316086258812	-0.6255334005329436	0.5106942988951843	-0.41078796254386396	2.001562705082795	0.920622863636502	0.11248681150043587	0.21241951185988145	1
+1.5038046653372112	-0.5482813446368637	-0.3641863572992026	-1.1327291781835451	-0.15806847832806897	-0.7192061272862257	-0.6950098823438737	-0.47009316461768835	-1.9377149832346678	-0.35779084437972	0.8451070985370979	-0.5080798628815741	0.5485566605075846	0.9761767931804848	0.43925107369417943	2.957596999924257	-0.3843783591548495	0.10415185780639113	0.9951843831205078	0.9865650926014994	1
+-1.9728640480783795	-0.584889332459948	-1.7115830531175702	2.1324867288289617	-0.5256451948154732	-0.13207671471324264	-0.9292471979014248	0.3506928143980163	1.3092760133267836	0.5398129189913056	-1.3559078555972999	0.39841641960968166	1.2537261342634507	0.9637445310773097	0.5431731800991407	-0.796177135299726	-1.3618004012670868	0.15859859636139104	2.7213336098665635	-0.5284081777192728	0
+0.41614597578860496	-0.1679131727874871	-0.18337459189215918	0.6847631554909649	1.4671555504106528	-1.0600082591583286	0.7597959068113311	-0.6926816136990898	0.5399648494662486	0.1429569524514458	-0.0482216355946755	-0.2086217318530937	0.6610574334671373	-0.31480674559033817	-0.06162756634039431	-0.7644973510153209	0.026631685382698556	1.2830307747086311	0.5078271760432795	-0.2680579423040609	0
+-0.012045236853271031	1.6925906279849425	-0.43238636618530835	-1.6847064151587414	2.2803112732391826	0.4504456177691022	0.8841718182048186	-1.1106346720321985	0.49231132027988483	-0.29108659019024025	-0.37667434221349183	-0.5384799446573829	0.2080936834521666	0.7315635547473112	0.5624562546330725	-1.0760533706627082	0.5355018164707845	1.580659829411814	2.135839579661295	-0.28797000142125845	0
+1.49961056170431	0.17185882517030615	-1.1299710458171193	-1.0986042355701349	0.2380742569517034	1.3281321131436516	1.1167682468088798	0.35564438892659067	-0.8928006143434813	0.14614254213307512	1.2829097566144694	-0.013688855208146944	-0.45706533906364627	-0.3062063943698761	1.9034164161920542	1.0929212167523317	0.1867834374796813	0.7587214440890531	-0.3029040483924579	0.42354677628115955	1
+-2.6545414330136725	1.8356854615940046	-0.5457976028267867	-0.9275320032879893	-1.3283248730961463	0.6232216740312264	0.596469164632437	-0.7210278452213854	-0.9118316286209408	-0.24928762363265858	0.952868090977543	1.11694972800202	0.5416161166668478	0.20604165648494577	-2.533714900686942	-0.016083961019089266	1.717987671558801	0.5450784715193229	0.5568882027647745	0.30241692371509693	1
+0.6668801993571806	-2.3053224234261527	0.48468627798385755	1.3546263068343696	0.11873192576862872	0.547052797574943	0.719991138685963	-0.524434980542717	-0.46901795027526905	-1.0137197024379423	1.3569787876682777	-1.2845045596199125	-1.5523887064375035	0.2108731700382351	0.19659506908435523	-0.953106011799891	2.1580484593930747	-0.2561154143302568	2.0759505803869307	0.04694527263670476	0
+1.1311811909202247	-0.6933878511104847	-1.265057694018798	0.5183435151558969	-0.07684033970519674	1.1988239385167685	-0.9469760525902353	0.5391724452767099	-0.23426383767301404	-0.1090739625676252	0.21359010083019977	-2.268619962246101	-0.7529456042925735	-0.8425159924738271	-0.05816611715256052	1.0977895592955997	-1.0448686711150859	0.9636968648987307	0.5900261263151266	0.2043616532143112	1
+0.3136974470241752	-0.8291825633597693	-1.0372415290485972	0.586065961267128	0.12771181052702799	-0.7640402478085184	-0.5004744114139862	1.6608354030583428	-1.5278423539544295	0.5708166717972424	1.5345529929213104	0.6876259510533493	-2.091922245950683	-0.3022998396168013	0.9114872277854996	1.766640084108124	0.4594646315912676	-1.1409669611458368	-0.7203819922636215	0.7128955852536363	1
+-0.0843840216296024	-1.3820347260227162	0.6397705674189378	1.0854940115848073	-0.8750993854125558	-0.5369047713298828	-2.6192806035910072	0.6701565503321437	-1.84641452901824	-0.10678367894303217	-0.7624907593835051	0.5861653271698655	-0.17704463664703687	0.7085263301324782	-0.8713026470236783	2.69143441504066	-0.19523201436527637	2.1560252861535147	-1.5795988238989795	0.9255039639597403	1
+0.6790203045104227	0.04209531864771717	-0.9611185195569437	-0.3493805390110045	0.3752751708285271	-0.28824269480756903	-0.0899568402734146	-0.7077880082031884	0.4219096981099068	-0.4093739891492758	-0.2055219060653654	1.3144282945889445	1.3487878682901	0.4293192866086668	-0.35331772809174306	-2.2826706845081164	2.29392855287745	-0.8770797047105753	0.6595634650916563	-0.4031787064662481	0
+0.6325447969724978	-1.5376848226493998	2.135545601595113	-0.7169675793179096	0.7929518975841817	-1.9315293250980572	1.3897142939008622	0.24930998597507595	-1.6440687479969183	-0.3704887551777182	-1.23787039502056	1.1836559269554183	-1.0938410824485512	-0.9895111468738925	-1.9260882651788052	2.109489705785208	0.21325468197813358	-0.1667210430129357	-0.4438538195629017	0.7910893416120955	1
+1.385783766454507	0.6443593624326104	-0.696350741910387	-0.823087860995007	-2.674354948547689	-0.49104596911569837	-0.14505356097389743	0.08649405653783686	0.32769430695483825	0.5845207431072055	-0.24481231922778438	0.8116910518786606	1.1430734254415746	0.32847783781427603	-0.24814981566368804	-2.8145262786887635	3.1865533860467052	0.44909883424446956	-0.402495596969506	-0.4328771627918769	0
+3.2529008023011587	-0.27166980167059496	-0.10473605798933078	-0.6534723222613076	-0.47729389928282157	0.19299500589830051	-0.24751855177125084	1.0219251961145952	-1.3171347334030596	-0.32230874972038603	-0.8110222905403106	-1.1322412716856916	-0.4661557022161254	-0.9471392661729446	-1.5958813690320397	1.160984081252255	0.8843769178013272	-0.035928362941471184	-0.8154578692172377	0.5729651158375776	1
+-0.9552158838227957	-0.3785028025591672	0.23351936921649144	-1.365343241823016	-0.6359698186412605	0.2872129861981349	0.01632286834064877	0.9912188508026412	-0.4305595490234799	-0.2605126207976518	0.3214442712943701	-0.20958795245614859	-1.4526406739111428	0.03730765585464991	-1.3274909827312888	1.1647254348024332	-0.769978389629172	1.0149522887472011	0.27653105409089324	0.27755713923924	1
+0.6551705283348923	-0.5615847942521986	-0.49519737438896855	0.23737629933432333	-0.4143994932544478	0.5167863504871545	0.3437170326220349	-0.7014811472600427	-1.6077015111257857	0.09451199914284816	0.5398998770150264	1.7475220863842662	-0.7767689612363475	-0.2216084475817371	1.183412573203491	2.0036214776598777	0.2883927875098986	0.46301689909689936	-0.5918632272605117	0.766784528636304	1
+-0.3361436284769567	0.1823427274870421	3.334203517597432	1.0128962309550167	-1.8811146489414055	-0.958168335581346	-0.5484922802752095	0.11760845626656423	1.1468147240921671	0.49875048880422795	3.1733905239619795	-0.0526349697724523	0.08652484860757291	0.5769340599430341	-1.0778260770671824	-0.8829578732735933	-0.9425233847712056	1.6033719963489919	1.8445232062556762	-0.48417251502812303	0
+0.9050528629328798	-0.012035767922212968	0.21306591909620448	1.0094897718684082	1.8398709351830922	-0.20939878024355807	1.544249561568332	-0.5558744255462802	-0.14830157676341127	-0.9129893226159165	-0.9052536407792096	-2.185153803257982	-0.7555250892846609	1.0407174952822522	-0.45036832301510676	0.8342667153934721	-0.849352027222355	-0.9657156624472774	-1.0122112207459872	0.1453852453196201	1
+1.178239159200306	-1.0652461548210312	0.32928250529485964	0.16713678370411497	0.12495397935004156	2.745117964775073	0.6030536979033265	-0.5722638992074314	0.9615416437730038	-0.44340798605665754	-1.5164304957203023	-1.0614676369216434	-0.08605564337254189	-0.15484845483449294	0.7389539007599524	0.7502907577776994	-2.800745114653922	-1.9836209428041778	-0.1788939995187421	-0.23460734202135813	0
+-0.022012467048051917	-0.2980589001770356	-0.9287657608462492	0.2022550669003972	1.3583611934492914	-0.3473542636872249	-0.08008290659022492	-1.094868489559057	0.3797735402439996	-1.9003696914644261	1.3733264119781319	0.49468129909971936	-0.5266982026448499	0.21506804700839205	-1.0239364192571805	0.08708817019212689	-0.8239609000108052	-1.0562806080043665	-0.6782509079000207	-0.11671445720024777	0
+-0.05535106725613376	1.897495684900051	-1.2961422703619865	-2.2362527882016288	0.6062782036825521	2.4944056179800698	-0.3652339819814644	-0.4307541449118705	-0.5320017432805376	0.42491286095294456	0.8968935558620045	-0.3501200079640903	-0.9035207258064066	-0.20458977846842988	0.6228215147539629	0.36595471824159787	0.4960995217769678	-0.7661022207718267	0.046327557310846944	0.21958825180654357	0
+0.4892337648335795	-0.887961134764646	-0.6575191404509574	-0.9041652092433549	-0.1504880604676619	-0.14829295739477777	0.28675094725200034	-0.5695736471796179	0.15975525591910827	-2.267876921091358	0.3074302518646544	0.2859729425182367	-0.12518243894874598	0.5923394212109696	-1.4363920287788075	-0.9059221277254496	0.9246917409852377	-0.1251848370827014	0.07971000908831376	-0.15744397774867594	0
+-1.7231933239653434	-0.24801134827199994	-1.9898222399382914	0.7656954261085819	-0.05483023725936617	1.6169399021897064	-0.3967249498631411	1.0323459107790158	0.9731895081194355	1.0303924263130786	1.0329180459160618	-0.033547027338664666	-1.0624411368884286	-0.9342158375564429	0.05971477069293665	0.25789653038454863	-2.1582838562759	-0.2780337171101295	0.7441495680026682	-0.2950948350858021	0
+0.16933309281863	-1.3713232471471188	-0.28145821900384405	-1.1300262257452833	0.5588657879489666	0.18393634027606567	-0.33064387147695085	-0.2728913561712938	-1.5796081028817355	-0.059698139612798386	-0.5305183143587244	0.4522332723500524	-0.35850443734187276	-0.6618912758728542	1.105836446597426	-0.8045286988938815	4.02369826067075	-0.6441278738693271	-1.1617665339422667	0.43461303247631455	0
+-1.8460295965152045	-0.255975214092637	1.0540424748134019	1.3190200056340993	-0.9984660716843727	0.1252126858419551	1.479116981117545	-0.07780687825586112	0.1755389386980704	-0.7247573669263252	-0.18580560212243427	0.4759463602670577	-1.079448951686073	0.5844426958957524	-0.013805770284701622	-1.7460392281016928	2.0284596495593634	-0.7858761582110539	-0.17228886477186073	-0.2592823117499626	0
+1.8771428706377922	1.954430088902813	-1.1616019467282765	0.5673334205644196	-0.08799540550164092	0.06644430233106957	0.5679433816499357	0.42441824827810354	0.1518278594250636	0.4306132751340653	0.0692509618345264	-0.1016379743818435	-0.5693165703158743	0.2262121311410064	-1.190784254860191	0.9589244192715091	-1.5758227297795224	0.32702615652721884	0.9015922583874204	0.05956556043266634	1
+0.15323002771333824	-0.3966186853856485	0.8421724903224964	-1.317627725338646	-0.33858048238968697	-0.4090657931046078	-1.4582418462866669	-0.6594840624629351	-0.4004108226455998	-0.7863950304118423	-0.7665729756746352	-0.010906592167949567	0.453194204359973	0.004008795533567026	1.3681052191345213	0.8285147180193451	-0.37259127080818166	0.7918792014178204	0.013153036557870796	0.22884946912013177	1
+-1.0926888646283135	0.7474034182399546	0.5070475019762871	-0.8560620219978579	2.019086116729861	2.7090019473659184	-0.5897085867477189	0.46800068820276425	1.1973925923016058	0.7580424981657605	-0.17689686434453186	-0.8134248245767957	-0.8757308415987771	0.1763704781550424	-1.199439969467994	-0.8989032076979058	-1.0151074498008397	-0.2667781642372559	1.5593148568891022	-0.5028825773221669	0
+-0.0696156591485477	-0.3955656348590421	-1.790003919076157	-3.209955381978046	1.7551741656764832	0.11653331605849324	-0.9325834567618385	-1.9081847831366037	1.5011366872997127	1.3655901991926498	0.714532047991697	-0.6735645547992268	2.4009183113212806	0.2753934759411781	-0.5586953357167566	-2.4248580602515304	0.4780055133333252	0.22430285295477725	1.5235848315795288	-0.779646482652198	0
+0.2383846452550063	-0.3130077315757537	1.0033975572213907	0.08864979057352633	1.6717911886146681	1.3347307577271426	0.12355262918532725	0.38378884838187516	1.0545758256277624	1.1966614601200112	-0.10788917679723521	1.5477291028255866	0.2484946248806814	-1.1366727112923867	-0.46484257027188	-0.6665072856921015	-1.062873534624194	0.8876717808262652	-1.3245780959402302	-0.4285126387910002	0
+-2.008942616762241	-0.8234988716333305	-0.15859132011071364	-0.5779462669917929	0.05687216122626013	-0.711741585516688	0.30663585257868975	-0.7322607097367665	-0.27918196650116295	0.23889598302964352	-2.89224040536514	-1.8338737352874381	-0.03502705018890768	-0.04826170379593097	-0.5084528851522548	1.0144555813357954	-0.8489078616442869	-1.5316018230959503	-1.9059055368464786	0.20977097201525036	1
+-0.1704564684096478	0.18971879197958597	-1.1844114274105708	-0.8546727892795731	0.09277642496734965	-0.1366293792823912	-2.048671922604096	-0.3357568385230854	1.4483592899951359	-1.0696662666401626	-0.2329845615794952	0.7837860781804775	0.41841523883774684	-0.8676594983663888	0.22583874577075078	-1.695720544464892	-0.4072557367301234	-0.1977972902611956	0.02359749586524577	-0.6782209637144826	0
+0.3239072506712229	0.7771447267055485	0.7529184295240164	-0.809273033397095	-0.5856061645692245	-0.6334300503835257	-0.7685061144460843	1.0110108162654712	-0.6307900736125656	1.0720688438114894	0.7375706675328788	-1.2970277152025405	-1.0622293344492408	0.12369973790391253	0.08645024003597679	-0.8294853204395023	2.2922588248961673	-2.306182941147614	-0.23693404546697278	0.11513663282079874	1
+-0.12031642840440407	-0.055598926892828825	0.29442208903978195	-0.08405908275243704	2.5707645107660437	-2.2724393778493805	-0.7091400944632673	-0.01527361681359736	-1.2630992116666893	-0.29672975912512006	-1.1604505895963486	-0.7448891733298583	-0.7216707082208504	1.6347076109296752	0.2543420370586476	0.9986464179201701	1.0028111182919377	-1.0099153635800724	0.6364125215344348	0.5362734706812686	1
+1.0759409181533681	0.6338708137850724	1.059455516811933	0.2736075032324234	-1.1004879462237114	0.8983820725024066	-0.9152704846639929	-0.8347039847535137	-1.3994538124984017	0.06937008395653746	-0.4322117530530746	-1.297471755359271	-0.9256383920977915	-1.5287869947378168	0.46665199638203264	1.3984163949968078	0.7172731124783118	-2.1595920504682318	0.2178924553288528	0.627726734926914	1
+1.1631257343736865	0.7161109143496656	1.165181781246556	-0.0970197604214342	1.770668260834617	0.09786380091576943	-0.25203469271235573	-0.07117035012372852	1.2621614052889216	-2.204226920077547	-0.833481645415412	1.668179441254334	0.6299876168291397	-0.4391047192362273	-0.12336287720355432	-2.4752753514344055	0.9905764766530935	0.16824138572933983	-1.108371640458861	-0.7056991628790823	0
+-0.4653767839296524	0.5706552646301977	-1.2510825198094822	-0.38542737502404606	0.5418393251037328	0.8696564647003973	-0.2677426807372017	1.3874400614164746	-1.6989225614176242	-0.8543980754353178	-0.7126300388983264	0.39242735549607893	0.7427861661062981	0.23731164772086588	0.17840259925316965	2.264950231927068	0.10561848543619334	1.7893962060023398	-0.33937719999794	0.8272635120183163	1
+1.0658262297925543	0.2245144207327693	1.9979515177687335	-1.3687162010707115	-1.1274591498928925	0.6453464430821444	0.10571095020938731	-0.04489492214522473	0.4070092579150457	-1.6549967992364703	-0.1861816445428681	-1.0013467840435817	0.13042091725382485	-0.9328609421342365	1.4771353822876396	1.0854915441340736	-2.221251309417225	0.5725567515972323	-1.1577200461261594	-0.011036089287608658	1
+-1.0583794427218747	2.576977679031155	-0.5895820679190702	0.13438281144361666	0.36102541634537905	1.5183620699261768	1.5873212424728582	-0.7273069057149364	0.4522026560345715	-0.02860552628379647	-0.018212347104613166	0.687677616154882	0.5422573331869172	0.10659762229930982	-1.2522775141080984	0.7277335248049872	-1.8227895144219035	-0.7301662802248373	0.9715535632493052	-0.0672408254641321	1
+-0.1099953959208559	1.6635363107373078	0.3272453529764515	-1.4246555886796946	1.2410820871966046	-0.15951736500333072	-0.661937714925914	0.4234572818376501	1.1246881843788494	0.9529594279919252	0.39143861927191975	3.465227148479317	-0.24134874955198468	-1.0945571896156956	-0.9833626436429376	-1.480187693017323	-0.09583127396217472	-0.31134706056867467	-0.6248721853412322	-0.5454408106982881	0
+0.9291001132966914	-0.1708304076874391	0.5364439368681257	0.2630766894332881	-0.1295965590136687	0.9929416493373554	0.7904280904722739	-0.01912275129904966	1.5057113544481104	-1.9314128569290476	-0.40508326392063543	1.0918159072154612	0.1881369570559398	-1.213691539345214	0.02421534060406341	-1.96631401509566	-0.14897841915958698	-2.1313146599852018	-1.2710579854942345	-0.7284633084773273	0
+0.6336131127287113	2.0333233170635046	-0.022356711144941453	-0.22007309599774338	0.9282123550423084	-0.787901129200937	0.5812629099886915	0.377426024051308	0.15067520175237897	-2.340925516401822	0.07371157701560777	1.560723423781778	-0.38910754054643126	1.0173191686261756	-0.4198460795464502	-0.4257545472403689	0.2939445657648525	0.6855820937261274	-2.068890495355913	-0.09921878204870066	0
+2.049778771444076	1.3048378295965286	1.563792608618236	-0.7047392202425459	0.5499305970570395	-0.04884518704139992	0.5223109585785488	-1.4893434370374596	1.3606389947395752	0.3899429971033616	0.055686488142052015	0.8438100462780511	1.6850310129308619	1.2652993760910154	-0.2279594058376745	-1.9365760629271713	0.0807919955941725	-0.6380407350109051	-1.0466273798176675	-0.6766362607223333	0
+0.630742979769623	-0.12660063112597814	-1.1219892377344292	-0.24320231504242704	-0.11846930012185257	0.35618373486097415	-0.35432027228237667	0.6830976831702715	-1.2988376519016114	-0.12917328933680922	0.4878147649765918	1.6226344780340827	0.46020710543895615	-0.9537377215409267	0.8308526010187456	1.1069055404414496	0.9232784698807094	-1.2718116679596179	-0.5666412777157238	0.5606432963172591	1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/classification_report.txt	Tue Apr 13 22:40:10 2021 +0000
@@ -0,0 +1,11 @@
+classification_report : 
+              precision    recall  f1-score   support
+
+           0       1.00      1.00      1.00        14
+           1       1.00      0.62      0.77        16
+           2       0.60      1.00      0.75         9
+
+    accuracy                           0.85        39
+   macro avg       0.87      0.88      0.84        39
+weighted avg       0.91      0.85      0.85        39
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/cluster_result01.txt	Tue Apr 13 22:40:10 2021 +0000
@@ -0,0 +1,48 @@
+0	44	64	-76	0
+0	51	48	-73	0
+0	58	65	-49	0
+0	43	61	-49	0
+0	45	43	-79	0
+0	42	60	-98	0
+0	50	55	-59	0
+0	53	53	-56	0
+0	45	44	-61	0
+0	43	65	-84	0
+0	35	52	-75	0
+0	56	56	-70	0
+1	-61	86	43	2
+1	-67	93	15	2
+1	-59	94	36	2
+1	-50	92	62	2
+1	-78	91	70	2
+1	-35	87	47	2
+1	-56	91	52	2
+1	-61	81	46	2
+1	-83	78	34	2
+1	-50	87	45	2
+1	-67	73	50	2
+1	-50	97	45	2
+1	-61	111	45	2
+2	-109	23	-92	1
+2	-94	20	-96	1
+2	-85	26	-88	1
+2	-90	33	-114	1
+2	-63	9	-106	1
+2	-79	9	-93	1
+2	-99	26	-108	1
+2	-81	19	-110	1
+2	-108	21	-108	1
+2	-92	27	-106	1
+2	-88	2	-106	1
+2	-88	15	-103	1
+3	54	-74	4	3
+3	42	-92	31	3
+3	39	-99	-7	3
+3	48	-115	-5	3
+3	39	-96	2	3
+3	31	-109	9	3
+3	33	-96	-8	3
+3	23	-102	4	3
+3	38	-90	21	3
+3	34	-107	1	3
+3	35	-78	18	3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/cluster_result02.txt	Tue Apr 13 22:40:10 2021 +0000
@@ -0,0 +1,48 @@
+0	44	64	-76	3
+0	51	48	-73	3
+0	58	65	-49	3
+0	43	61	-49	3
+0	45	43	-79	3
+0	42	60	-98	3
+0	50	55	-59	3
+0	53	53	-56	3
+0	45	44	-61	3
+0	43	65	-84	3
+0	35	52	-75	3
+0	56	56	-70	3
+1	-61	86	43	2
+1	-67	93	15	2
+1	-59	94	36	2
+1	-50	92	62	2
+1	-78	91	70	2
+1	-35	87	47	2
+1	-56	91	52	2
+1	-61	81	46	2
+1	-83	78	34	2
+1	-50	87	45	2
+1	-67	73	50	2
+1	-50	97	45	2
+1	-61	111	45	2
+2	-109	23	-92	0
+2	-94	20	-96	0
+2	-85	26	-88	0
+2	-90	33	-114	0
+2	-63	9	-106	0
+2	-79	9	-93	0
+2	-99	26	-108	0
+2	-81	19	-110	0
+2	-108	21	-108	0
+2	-92	27	-106	0
+2	-88	2	-106	0
+2	-88	15	-103	0
+3	54	-74	4	1
+3	42	-92	31	1
+3	39	-99	-7	1
+3	48	-115	-5	1
+3	39	-96	2	1
+3	31	-109	9	1
+3	33	-96	-8	1
+3	23	-102	4	1
+3	38	-90	21	1
+3	34	-107	1	1
+3	35	-78	18	1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/cluster_result03.txt	Tue Apr 13 22:40:10 2021 +0000
@@ -0,0 +1,48 @@
+0	44	64	-76	-1
+0	51	48	-73	-1
+0	58	65	-49	-1
+0	43	61	-49	-1
+0	45	43	-79	-1
+0	42	60	-98	-1
+0	50	55	-59	-1
+0	53	53	-56	-1
+0	45	44	-61	-1
+0	43	65	-84	-1
+0	35	52	-75	-1
+0	56	56	-70	-1
+1	-61	86	43	-1
+1	-67	93	15	-1
+1	-59	94	36	-1
+1	-50	92	62	-1
+1	-78	91	70	-1
+1	-35	87	47	-1
+1	-56	91	52	-1
+1	-61	81	46	-1
+1	-83	78	34	-1
+1	-50	87	45	-1
+1	-67	73	50	-1
+1	-50	97	45	-1
+1	-61	111	45	-1
+2	-109	23	-92	-1
+2	-94	20	-96	-1
+2	-85	26	-88	-1
+2	-90	33	-114	-1
+2	-63	9	-106	-1
+2	-79	9	-93	-1
+2	-99	26	-108	-1
+2	-81	19	-110	-1
+2	-108	21	-108	-1
+2	-92	27	-106	-1
+2	-88	2	-106	-1
+2	-88	15	-103	-1
+3	54	-74	4	-1
+3	42	-92	31	-1
+3	39	-99	-7	-1
+3	48	-115	-5	-1
+3	39	-96	2	-1
+3	31	-109	9	-1
+3	33	-96	-8	-1
+3	23	-102	4	-1
+3	38	-90	21	-1
+3	34	-107	1	-1
+3	35	-78	18	-1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/cluster_result04.txt	Tue Apr 13 22:40:10 2021 +0000
@@ -0,0 +1,48 @@
+0	44	64	-76	1
+0	51	48	-73	1
+0	58	65	-49	1
+0	43	61	-49	1
+0	45	43	-79	1
+0	42	60	-98	1
+0	50	55	-59	1
+0	53	53	-56	1
+0	45	44	-61	1
+0	43	65	-84	1
+0	35	52	-75	1
+0	56	56	-70	1
+1	-61	86	43	2
+1	-67	93	15	2
+1	-59	94	36	2
+1	-50	92	62	2
+1	-78	91	70	2
+1	-35	87	47	2
+1	-56	91	52	2
+1	-61	81	46	2
+1	-83	78	34	2
+1	-50	87	45	2
+1	-67	73	50	2
+1	-50	97	45	2
+1	-61	111	45	2
+2	-109	23	-92	3
+2	-94	20	-96	3
+2	-85	26	-88	3
+2	-90	33	-114	3
+2	-63	9	-106	3
+2	-79	9	-93	3
+2	-99	26	-108	3
+2	-81	19	-110	3
+2	-108	21	-108	3
+2	-92	27	-106	3
+2	-88	2	-106	3
+2	-88	15	-103	3
+3	54	-74	4	0
+3	42	-92	31	0
+3	39	-99	-7	0
+3	48	-115	-5	0
+3	39	-96	2	0
+3	31	-109	9	0
+3	33	-96	-8	0
+3	23	-102	4	0
+3	38	-90	21	0
+3	34	-107	1	0
+3	35	-78	18	0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/cluster_result05.txt	Tue Apr 13 22:40:10 2021 +0000
@@ -0,0 +1,48 @@
+0	44	64	-76	0
+0	51	48	-73	0
+0	58	65	-49	0
+0	43	61	-49	0
+0	45	43	-79	0
+0	42	60	-98	0
+0	50	55	-59	0
+0	53	53	-56	0
+0	45	44	-61	0
+0	43	65	-84	0
+0	35	52	-75	0
+0	56	56	-70	0
+1	-61	86	43	2
+1	-67	93	15	2
+1	-59	94	36	2
+1	-50	92	62	2
+1	-78	91	70	2
+1	-35	87	47	2
+1	-56	91	52	2
+1	-61	81	46	2
+1	-83	78	34	2
+1	-50	87	45	2
+1	-67	73	50	2
+1	-50	97	45	2
+1	-61	111	45	2
+2	-109	23	-92	0
+2	-94	20	-96	0
+2	-85	26	-88	0
+2	-90	33	-114	0
+2	-63	9	-106	0
+2	-79	9	-93	0
+2	-99	26	-108	0
+2	-81	19	-110	0
+2	-108	21	-108	0
+2	-92	27	-106	0
+2	-88	2	-106	0
+2	-88	15	-103	0
+3	54	-74	4	1
+3	42	-92	31	1
+3	39	-99	-7	1
+3	48	-115	-5	1
+3	39	-96	2	1
+3	31	-109	9	1
+3	33	-96	-8	1
+3	23	-102	4	1
+3	38	-90	21	1
+3	34	-107	1	1
+3	35	-78	18	1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/cluster_result06.txt	Tue Apr 13 22:40:10 2021 +0000
@@ -0,0 +1,48 @@
+0	44	64	-76	0
+0	51	48	-73	0
+0	58	65	-49	0
+0	43	61	-49	0
+0	45	43	-79	0
+0	42	60	-98	0
+0	50	55	-59	0
+0	53	53	-56	0
+0	45	44	-61	0
+0	43	65	-84	0
+0	35	52	-75	0
+0	56	56	-70	0
+1	-61	86	43	1
+1	-67	93	15	1
+1	-59	94	36	1
+1	-50	92	62	1
+1	-78	91	70	1
+1	-35	87	47	1
+1	-56	91	52	1
+1	-61	81	46	1
+1	-83	78	34	1
+1	-50	87	45	1
+1	-67	73	50	1
+1	-50	97	45	1
+1	-61	111	45	1
+2	-109	23	-92	2
+2	-94	20	-96	2
+2	-85	26	-88	2
+2	-90	33	-114	2
+2	-63	9	-106	2
+2	-79	9	-93	2
+2	-99	26	-108	2
+2	-81	19	-110	2
+2	-108	21	-108	2
+2	-92	27	-106	2
+2	-88	2	-106	2
+2	-88	15	-103	2
+3	54	-74	4	3
+3	42	-92	31	3
+3	39	-99	-7	3
+3	48	-115	-5	3
+3	39	-96	2	3
+3	31	-109	9	3
+3	33	-96	-8	3
+3	23	-102	4	3
+3	38	-90	21	3
+3	34	-107	1	3
+3	35	-78	18	3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/cluster_result07.txt	Tue Apr 13 22:40:10 2021 +0000
@@ -0,0 +1,48 @@
+0	44	64	-76	0
+0	51	48	-73	0
+0	58	65	-49	0
+0	43	61	-49	0
+0	45	43	-79	0
+0	42	60	-98	0
+0	50	55	-59	0
+0	53	53	-56	0
+0	45	44	-61	0
+0	43	65	-84	0
+0	35	52	-75	0
+0	56	56	-70	0
+1	-61	86	43	1
+1	-67	93	15	1
+1	-59	94	36	1
+1	-50	92	62	1
+1	-78	91	70	1
+1	-35	87	47	1
+1	-56	91	52	1
+1	-61	81	46	1
+1	-83	78	34	1
+1	-50	87	45	1
+1	-67	73	50	1
+1	-50	97	45	1
+1	-61	111	45	1
+2	-109	23	-92	2
+2	-94	20	-96	2
+2	-85	26	-88	2
+2	-90	33	-114	2
+2	-63	9	-106	2
+2	-79	9	-93	2
+2	-99	26	-108	2
+2	-81	19	-110	2
+2	-108	21	-108	2
+2	-92	27	-106	2
+2	-88	2	-106	2
+2	-88	15	-103	2
+3	54	-74	4	3
+3	42	-92	31	3
+3	39	-99	-7	3
+3	48	-115	-5	3
+3	39	-96	2	3
+3	31	-109	9	3
+3	33	-96	-8	3
+3	23	-102	4	3
+3	38	-90	21	3
+3	34	-107	1	3
+3	35	-78	18	3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/cluster_result08.txt	Tue Apr 13 22:40:10 2021 +0000
@@ -0,0 +1,48 @@
+0	44	64	-76	0
+0	51	48	-73	0
+0	58	65	-49	0
+0	43	61	-49	0
+0	45	43	-79	0
+0	42	60	-98	0
+0	50	55	-59	0
+0	53	53	-56	0
+0	45	44	-61	0
+0	43	65	-84	0
+0	35	52	-75	0
+0	56	56	-70	0
+1	-61	86	43	0
+1	-67	93	15	0
+1	-59	94	36	0
+1	-50	92	62	0
+1	-78	91	70	0
+1	-35	87	47	0
+1	-56	91	52	0
+1	-61	81	46	0
+1	-83	78	34	0
+1	-50	87	45	0
+1	-67	73	50	0
+1	-50	97	45	0
+1	-61	111	45	0
+2	-109	23	-92	0
+2	-94	20	-96	0
+2	-85	26	-88	0
+2	-90	33	-114	0
+2	-63	9	-106	0
+2	-79	9	-93	0
+2	-99	26	-108	0
+2	-81	19	-110	0
+2	-108	21	-108	0
+2	-92	27	-106	0
+2	-88	2	-106	0
+2	-88	15	-103	0
+3	54	-74	4	1
+3	42	-92	31	1
+3	39	-99	-7	1
+3	48	-115	-5	1
+3	39	-96	2	1
+3	31	-109	9	1
+3	33	-96	-8	1
+3	23	-102	4	1
+3	38	-90	21	1
+3	34	-107	1	1
+3	35	-78	18	1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/cluster_result09.txt	Tue Apr 13 22:40:10 2021 +0000
@@ -0,0 +1,48 @@
+0	44	64	-76	0
+0	51	48	-73	0
+0	58	65	-49	0
+0	43	61	-49	0
+0	45	43	-79	0
+0	42	60	-98	0
+0	50	55	-59	0
+0	53	53	-56	0
+0	45	44	-61	0
+0	43	65	-84	0
+0	35	52	-75	0
+0	56	56	-70	0
+1	-61	86	43	0
+1	-67	93	15	0
+1	-59	94	36	0
+1	-50	92	62	0
+1	-78	91	70	0
+1	-35	87	47	0
+1	-56	91	52	0
+1	-61	81	46	0
+1	-83	78	34	0
+1	-50	87	45	0
+1	-67	73	50	0
+1	-50	97	45	0
+1	-61	111	45	0
+2	-109	23	-92	0
+2	-94	20	-96	0
+2	-85	26	-88	0
+2	-90	33	-114	0
+2	-63	9	-106	0
+2	-79	9	-93	0
+2	-99	26	-108	0
+2	-81	19	-110	0
+2	-108	21	-108	0
+2	-92	27	-106	0
+2	-88	2	-106	0
+2	-88	15	-103	0
+3	54	-74	4	1
+3	42	-92	31	1
+3	39	-99	-7	1
+3	48	-115	-5	1
+3	39	-96	2	1
+3	31	-109	9	1
+3	33	-96	-8	1
+3	23	-102	4	1
+3	38	-90	21	1
+3	34	-107	1	1
+3	35	-78	18	1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/cluster_result10.txt	Tue Apr 13 22:40:10 2021 +0000
@@ -0,0 +1,48 @@
+0	44	64	-76	3
+0	51	48	-73	3
+0	58	65	-49	3
+0	43	61	-49	3
+0	45	43	-79	3
+0	42	60	-98	3
+0	50	55	-59	3
+0	53	53	-56	3