define([ 'css!vp_base/css/component/instanceEditor.css', 'vp_base/js/com/com_String', 'vp_base/js/com/com_util', 'vp_base/js/com/com_generatorV2', 'vp_base/js/com/component/Component', 'vp_base/js/com/component/SuggestInput' ], function(insCss, com_String, com_util, com_generator, Component, SuggestInput) { // temporary const const VP_INS_BOX = 'vp-ins-box'; const VP_INS_SELECT_CONTAINER = 'vp-ins-select-container'; const VP_INS_SELECT_TITLE = 'vp-ins-select-title'; const VP_INS_SEARCH = 'vp-ins-search'; const VP_INS_TYPE = 'vp-ins-type'; const VP_INS_SELECT_BOX = 'vp-ins-select-box'; const VP_INS_SELECT_LIST = 'vp-ins-select-list'; const VP_INS_SELECT_ITEM = 'vp-ins-select-item'; const VP_INS_PARAMETER_BOX = 'vp-ins-parameter-box'; const VP_INS_PARAMETER = 'vp-ins-parameter'; class ModelEditor extends Component { constructor(pageThis, targetId, containerId) { super(null, { pageThis: pageThis, targetId: targetId, containerId: containerId }); } _init() { super._init(); this.pageThis = this.state.pageThis; this.targetId = this.state.targetId; this.containerId = this.state.containerId; let modelEditorType = ''; let modelEditorName = ''; if (this.pageThis.state['modelEditorType'] == undefined) { modelEditorType = ''; } if (this.pageThis.state['modelEditorName'] == undefined) { modelEditorName = ''; } this.state = { modelEditorType: modelEditorType, modelEditorName: modelEditorName, action: {}, info: {}, config: {}, ...this.state } this.loaded = false; } render() { ; } getModelCategory(modelType) { let mlDict = vpConfig.getMLDataDict(); let keys = Object.keys(mlDict); let modelCategory = ''; for (let i = 0; i < keys.length; i++) { let key = keys[i]; if (mlDict[key].includes(modelType)) { modelCategory = key; break; } } return modelCategory; } getAction(modelType) { let category = this.getModelCategory(modelType); let defaultActions = { 'fit': { name: 'fit', label: 'Fit', code: '${model}.fit(${fit_featureData}, ${fit_targetData})', description: 'Perform modeling from features, or distance matrix.', options: [ { name: 'fit_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'X_train' }, { name: 'fit_targetData', label: 'Target Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'y_train' } ] }, 'predict': { name: 'predict', label: 'Predict', code: '${pred_allocate} = ${model}.predict(${pred_featureData})', description: 'Predict the closest target data X belongs to.', options: [ { name: 'pred_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'X_test' }, { name: 'pred_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'pred' } ] }, 'predict_proba': { name: 'predict_proba', label: 'Predict probability', code: '${pred_prob_allocate} = ${model}.predict_proba(${pred_prob_featureData})', description: 'Predict class probabilities for X.', options: [ { name: 'pred_prob_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'X_test' }, { name: 'pred_prob_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'pred' } ] }, 'transform': { name: 'transform', label: 'Transform', code: '${trans_allocate} = ${model}.transform(${trans_featureData})', description: 'Apply dimensionality reduction to X.', options: [ { name: 'trans_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'X' }, { name: 'trans_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'trans' } ] } }; let actions = {}; switch (category) { case 'Data Preparation': actions = { 'fit': { name: 'fit', label: 'Fit', code: '${model}.fit(${fit_featureData})', description: 'Fit Encoder/Scaler to X.', options: [ { name: 'fit_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'X' } ] }, 'fit_transform': { name: 'fit_transform', label: 'Fit and transform', code: '${fit_trans_allocate} = ${model}.fit_transform(${fit_trans_featureData})', description: 'Fit Encoder/Scaler to X, then transform X.', options: [ { name: 'fit_trans_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'X' }, { name: 'fit_trans_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'trans' } ] }, 'transform': { ...defaultActions['transform'], description: 'Transform labels to normalized encoding.' } } if (modelType != 'ColumnTransformer') { actions = { ...actions, 'inverse_transform': { name: 'inverse_transform', label: 'Inverse transform', code: '${inverse_allocate} = ${model}.inverse_transform(${inverse_featureData})', description: 'Transform binary labels back to multi-class labels.', options: [ { name: 'inverse_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'X' }, { name: 'inverse_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'inv_trans' } ] } } } break; case 'Regression': actions = { 'fit': defaultActions['fit'], 'predict': defaultActions['predict'] } break; case 'Classification': actions = { 'fit': defaultActions['fit'], 'predict': defaultActions['predict'], 'predict_proba': defaultActions['predict_proba'], } if (['LogisticRegression', 'SVC', 'GradientBoostingClassifier'].includes(modelType)) { actions = { ...actions, 'decision_function': { name: 'decision_function', label: 'Decision function', code: '${dec_allocate} = ${model}.decision_function(${dec_featureData})', description: 'Compute the decision function of X.', options: [ { name: 'dec_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'X' }, { name: 'dec_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable' } ] } } } break; case 'Auto ML': actions = { 'fit': defaultActions['fit'], 'predict': defaultActions['predict'], 'fit_predict': { name: 'fit_predict', label: 'Fit and predict', code: '${fit_pred_allocate} = ${model}.fit_predict(${fit_pred_featureData})', description: 'Fit and predict.', options: [ { name: 'fit_pred_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'X' }, { name: 'fit_pred_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'pred' } ] }, 'predict_proba': defaultActions['predict_proba'] } break; case 'Clustering': if (modelType == 'AgglomerativeClustering' || modelType == 'DBSCAN') { actions = { 'fit': { name: 'fit', label: 'Fit', code: '${model}.fit(${fit_featureData})', description: 'Perform clustering from features, or distance matrix.', options: [ { name: 'fit_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'X' } ] }, 'fit_predict': { name: 'fit_predict', label: 'Fit and predict', code: '${fit_pred_allocate} = ${model}.fit_predict(${fit_pred_featureData})', description: 'Compute clusters from a data or distance matrix and predict labels.', options: [ { name: 'fit_pred_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'X' }, { name: 'fit_pred_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'pred' } ] } } break; } actions = { 'fit': { name: 'fit', label: 'Fit', code: '${model}.fit(${fit_featureData})', description: 'Compute clustering.', options: [ { name: 'fit_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'X' } ] }, 'predict': { name: 'predict', label: 'Predict', code: '${pred_allocate} = ${model}.predict(${pred_featureData})', description: 'Predict the closest target data X belongs to.', options: [ { name: 'pred_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'X' }, { name: 'pred_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'pred' } ] }, 'fit_predict': { name: 'fit_predict', label: 'Fit and predict', code: '${fit_pred_allocate} = ${model}.fit_predict(${fit_pred_featureData})', description: 'Compute cluster centers and predict cluster index for each sample.', options: [ { name: 'fit_pred_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'X' }, { name: 'fit_pred_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'pred' } ] } } if (modelType == 'KMeans') { actions = { ...actions, 'fit_transform': { name: 'fit_transform', label: 'Fit and transform', code: '${fit_trans_allocate} = ${model}.fit_transform(${fit_trans_featureData})', description: 'Compute clustering and transform X to cluster-distance space.', options: [ { name: 'fit_trans_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'X' }, { name: 'fit_trans_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'trans' } ] }, 'transform': { name: 'transform', label: 'Transform', code: '${trans_allocate} = ${model}.transform(${trans_featureData})', description: 'Transform X to a cluster-distance space.', options: [ { name: 'trans_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'X' }, { name: 'trans_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'trans' } ] } } } break; case 'Dimension Reduction': if (modelType == 'TSNE') { actions = { 'fit': { name: 'fit', label: 'Fit', code: '${model}.fit(${fit_featureData})', description: 'Fit X into an embedded space.', options: [ { name: 'fit_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'X' } ] }, 'fit_transform': { name: 'fit_transform', label: 'Fit and transform', code: '${fit_trans_allocate} = ${model}.fit_transform(${fit_trans_featureData})', description: 'Fit X into an embedded space and return that transformed output.', options: [ { name: 'fit_trans_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'X' }, { name: 'fit_trans_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'trans' } ] } } break; } if (modelType == 'LinearDiscriminantAnalysis') { // LDA actions = { 'fit': { name: 'fit', label: 'Fit', code: '${model}.fit(${fit_featureData}, ${fit_targetData})', description: 'Fit the Linear Discriminant Analysis model.', options: [ { name: 'fit_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'X' }, { name: 'fit_targetData', label: 'Target Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'y' } ] }, 'fit_transform': { name: 'fit_transform', label: 'Fit and transform', code: '${fit_trans_allocate} = ${model}.fit_transform(${fit_trans_featureData}${fit_trans_targetData})', description: 'Fit to data, then transform it.', options: [ { name: 'fit_trans_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'X' }, { name: 'fit_trans_targetData', label: 'Target Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'y' }, { name: 'fit_trans_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'trans' } ] }, 'predict': { name: 'predict', label: 'Predict', code: '${pred_allocate} = ${model}.predict(${pred_featureData})', description: 'Predict class labels for samples in X.', options: [ { name: 'pred_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'X' }, { name: 'pred_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'pred' } ] }, 'transform': { name: 'transform', label: 'Transform', code: '${trans_allocate} = ${model}.transform(${trans_featureData})', description: 'Project data to maximize class separation.', options: [ { name: 'trans_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'X' }, { name: 'trans_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'trans' } ] } } break; } actions = { 'fit': { name: 'fit', label: 'Fit', code: '${model}.fit(${fit_featureData})', description: 'Fit X into an embedded space.', options: [ { name: 'fit_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'X' } ] }, 'fit_transform': { name: 'fit_transform', label: 'Fit and transform', code: '${fit_trans_allocate} = ${model}.fit_transform(${fit_trans_featureData})', description: 'Fit the model with X and apply the dimensionality reduction on X.', options: [ { name: 'fit_trans_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'X' }, { name: 'fit_trans_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'trans' } ] }, 'inverse_transform': { name: 'inverse_transform', label: 'Inverse transform', code: '${inverse_allocate} = ${model}.inverse_transform(${inverse_featureData})', description: 'Transform data back to its original space.', options: [ { name: 'inverse_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'X' }, { name: 'inverse_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'inv_trans' } ] }, 'transform': { name: 'transform', label: 'Transform', code: '${trans_allocate} = ${model}.transform(${trans_featureData})', description: 'Apply dimensionality reduction to X.', options: [ { name: 'trans_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'X' }, { name: 'trans_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'trans' } ] } } break; } return actions; } getInfo(modelType) { let category = this.getModelCategory(modelType); let infos = {}; let defaultInfos = { 'score': { name: 'score', label: 'Score', code: '${score_allocate} = ${model}.score(${score_featureData}, ${score_targetData})', description: '', options: [ { name: 'score_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'X' }, { name: 'score_targetData', label: 'Target Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'y' }, { name: 'score_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'scores' } ] }, 'get_params': { name: 'get_params', label: 'Get parameters', code: '${param_allocate} = ${model}.get_params(${deep})', description: 'Get parameters for this estimator.', options: [ { name: 'deep', component: ['bool_select'], default: 'True', usePair: true }, { name: 'param_allocate', label: 'Allocate to', component: ['input'], value: 'params' } ] }, 'permutation_importance': { name: 'permutation_importance', label: 'Permutation importance', import: 'from sklearn.inspection import permutation_importance', code: '${importance_allocate} = permutation_importance(${model}, ${importance_featureData}, ${importance_targetData}${scoring}${random_state}${etc})', description: 'Permutation importance for feature evaluation.', options: [ { name: 'importance_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'X_train' }, { name: 'importance_targetData', label: 'Target Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'y_train' }, { name: 'scoring', component: ['input'], usePair: true }, { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true }, { name: 'importance_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'importances' } ] } } switch (category) { case 'Data Preparation': if (modelType == 'OneHotEncoder') { infos = { 'categories_': { // TODO: name: 'categories_', label: 'Categories', code: '${categories_allocate} = ${model}.categories_', description: 'The categories of each feature determined during fitting', options: [ { name: 'categories_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'categories' } ] }, 'get_feature_names_out': { name: 'get_feature_names_out', label: 'Get feature names', code: '${feature_names_allocate} = ${model}.get_feature_names_out()', description: 'Get output feature names.', options: [ { name: 'feature_names_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'features' } ] } } } if (modelType == 'LabelEncoder') { infos = { 'classes_': { name: 'classes_', label: 'Classes', code: '${classes_allocate} = ${model}.classes_', description: 'Holds the label for each class.', options: [ { name: 'classes_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'classes' } ] } } } if (modelType == 'KBinsDiscretizer') { infos = { 'bin_edges': { // TODO: name: 'bin_edges', label: 'Bin edges', code: '${bin_edges_allocate} = ${model}.bin_edges_', description: 'The edges of each bin. Contain arrays of varying shapes', options: [ { name: 'bin_edges_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'bin_edges' } ] } } } if (modelType == 'ColumnTransformer') { infos = { 'transformers_': { name: 'transformers_', label: 'Transformers_', code: '${transformers_allocate} = ${model}.transformers_', description: 'The collection of fitted transformers as tuples of (name, fitted_transformer, column).', options: [ { name: 'transformers_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'classes' } ] }, 'get_feature_names_out': { name: 'get_feature_names_out', label: 'Get feature names', code: '${feature_names_allocate} = ${model}.get_feature_names_out()', description: 'Get output feature names.', options: [ { name: 'feature_names_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'features' } ] } } } infos = { ...infos, 'get_params': defaultInfos['get_params'] } break; case 'Regression': infos = { 'score': { ...defaultInfos['score'], description: 'Return the coefficient of determination of the prediction.' }, 'cross_val_score': { name: 'cross_val_score', label: 'Cross validation score', import: 'from sklearn.model_selection import cross_val_score', code: '${cvs_allocate} = cross_val_score(${model}, ${cvs_featureData}, ${cvs_targetData}${scoring}${cv})', description: 'Evaluate a score by cross-validation.', options: [ { name: 'cvs_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'X' }, { name: 'cvs_targetData', label: 'Target Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'y' }, { name: 'scoring', component: ['option_select'], usePair: true, type: 'text', options: [ '', 'explained_variance', 'max_error', 'neg_mean_absolute_error', 'neg_mean_squared_error', 'neg_root_mean_squared_error', 'neg_mean_squared_log_error', 'neg_median_absolute_error', 'r2', 'neg_mean_poisson_deviance', 'neg_mean_gamma_deviance', 'neg_mean_absolute_percentage_error' ] }, { name: 'cv', label: 'Cross Validation', component: ['input_number'], placeholder: '1 ~ 10', default: 5, usePair: true }, { name: 'cvs_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'scores' } ] }, 'permutation_importance': defaultInfos['permutation_importance'], 'Coefficient': { name: 'coef_', label: 'Coefficient', code: '${coef_allocate} = ${model}.coef_', description: 'Weights assigned to the features.', options: [ { name: 'coef_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'coef' } ] }, 'Intercept': { name: 'intercept_', label: 'Intercept', code: '${intercept_allocate} = ${model}.intercept_', description: 'Constants in decision function.', options: [ { name: 'intercept_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'intercepts' } ] } } break; case 'Classification': infos = { 'score': { ...defaultInfos['score'], description: 'Return the mean accuracy on the given test data and labels.' }, 'cross_val_score': { name: 'cross_val_score', label: 'Cross validation score', import: 'from sklearn.model_selection import cross_val_score', code: '${cvs_allocate} = cross_val_score(${model}, ${cvs_featureData}, ${cvs_targetData}${scoring}${cv})', description: 'Evaluate a score by cross-validation.', options: [ { name: 'cvs_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'X' }, { name: 'cvs_targetData', label: 'Target Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'y' }, { name: 'scoring', component: ['option_select'], usePair: true, type: 'text', options: [ '', 'accuracy', 'balanced_accuracy', 'top_k_accuracy', 'average_precision', 'neg_brier_score', 'f1', 'f1_micro', 'f1_macro', 'f1_weighted', 'f1_samples', 'neg_log_loss', 'precision', 'recall', 'jaccard', 'roc_auc', 'roc_auc_ovr', 'roc_auc_ovo', 'roc_auc_ovr_weighted', 'roc_auc_ovo_weighted' ] }, { name: 'cv', label: 'Cross Validation', component: ['input_number'], placeholder: '1 ~ 10', default: 5, usePair: true }, { name: 'cvs_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'scores' } ] }, 'permutation_importance': defaultInfos['permutation_importance'] } break; case 'Auto ML': infos = { 'score': { ...defaultInfos['score'], description: 'Return the mean accuracy on the given test data and labels.' }, 'get_params': { ...defaultInfos['get_params'] } } break; case 'Clustering': infos = { // 'Size of clusters': { // name: 'Size of clusters', // code: "print(f'Size of clusters: {np.bincount(pred)}')", // FIXME: model.cluster_centers_ / use model info or hide it // options: [] // } } if (modelType == 'KMeans') { infos = { ...infos, 'cluster_centers_': { name: 'cluster_centers', label: 'Cluster centers', code: '${centers_allocate} = ${model}.cluster_centers_', description: 'Coordinates of cluster centers.', options: [ { name: 'centers_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'cluster_centers' } ] } } } if (modelType == 'AgglomerativeClustering') { infos = { ...infos, 'Dendrogram': { // FIXME: name: 'dendrogram', label: 'Dendrogram', code: "# import\nfrom scipy.cluster.hierarchy import dendrogram, ward\n\nlinkage_array = ward(${dendro_data})\ndendrogram(linkage_array, p=3, truncate_mode='level', no_labels=True)\nplt.show()", description: 'Draw a dendrogram', options: [ { name: 'dendro_data', label: 'Data', component: ['var_select'], var_type: ['DataFrame'] } ] } } } break; case 'Dimension Reduction': if (modelType == 'LDA') { infos = { 'score': { name: 'score', label: 'Score', code: '${score_allocate} = ${model}.score(${score_featureData}, ${score_targetData})', description: 'Return the average log-likelihood of all samples.', options: [ { name: 'score_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'X' }, { name: 'score_targetData', label: 'Target Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'y' }, { name: 'score_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'scores' } ] } } break; } if (modelType == 'PCA') { infos = { 'explained_variance_ratio_': { name: 'explained_variance_ratio_', label: 'Explained variance ratio', code: '${ratio_allocate} = ${model}.explained_variance_ratio_', description: 'Percentage of variance explained by each of the selected components.', options: [ { name: 'ratio_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'ratio' } ] } } } infos = { ...infos, 'score': { name: 'score', label: 'Score', code: '${score_allocate} = ${model}.score(${score_featureData})', description: 'Return the average log-likelihood of all samples.', options: [ { name: 'score_featureData', label: 'Feature Data', component: ['var_select'], var_type: ['DataFrame', 'Series'], value: 'X' }, { name: 'score_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'scores' } ] } } break; } return infos; } renderPage() { var tag = new com_String(); tag.appendFormatLine('
', VP_INS_BOX, this.uuid); // vp-select-base // Model Editor State (Saved state) tag.appendFormatLine('', 'modelEditorType', this.state.modelEditorType); tag.appendFormatLine('', 'modelEditorName', this.state.modelEditorName); tag.appendFormatLine('
', VP_INS_SELECT_CONTAINER, 'action'); tag.appendFormatLine('
Action
', VP_INS_SELECT_TITLE); tag.appendFormatLine('
', 'position: relative;'); tag.appendFormatLine('', VP_INS_SEARCH, 'attr'); tag.appendFormatLine('', VP_INS_TYPE, 'action'); tag.appendFormatLine('', 'fa fa-search', 'vp-ins-search-icon'); tag.appendLine('
'); tag.appendFormatLine('
', VP_INS_SELECT_BOX, 'action'); tag.appendFormatLine('
    ', VP_INS_SELECT_LIST, 'action'); tag.appendLine('
'); tag.appendLine('
'); // VP_INS_SELECT_BOX tag.appendLine('
'); // VP_INS_SELECT_CONTAINER tag.appendFormatLine('
', VP_INS_SELECT_CONTAINER, 'info'); tag.appendFormatLine('
Information
', VP_INS_SELECT_TITLE); tag.appendFormatLine('
', 'position: relative;'); tag.appendFormatLine('', VP_INS_SEARCH, 'method'); tag.appendFormatLine('', VP_INS_TYPE, 'info'); tag.appendFormatLine('', 'fa fa-search', 'vp-ins-search-icon'); tag.appendLine('
'); tag.appendFormatLine('
', VP_INS_SELECT_BOX, 'info'); tag.appendFormatLine('
    ', VP_INS_SELECT_LIST, 'info'); tag.appendLine('
'); tag.appendLine('
'); // VP_INS_SELECT_BOX tag.appendLine('
'); // VP_INS_SELECT_CONTAINER tag.appendFormatLine('
Options
', VP_INS_SELECT_TITLE); tag.appendFormatLine('
', VP_INS_PARAMETER_BOX); tag.appendLine('
'); // VP_INS_BOX END $(this.pageThis.wrapSelector('#' + this.containerId)).html(tag.toString()); return tag.toString(); } reload() { this.renderPage(); let targetTag = $(this.pageThis.wrapSelector('#' + this.targetId)); let model = $(targetTag).val(); let modelType = $(targetTag).find('option:selected').data('type'); let actions = this.getAction(modelType); let infos = this.getInfo(modelType); this.state.action = { ...actions }; this.state.info = { ...infos }; var actListTag = new com_String(); var infoListTag = new com_String(); Object.keys(actions).forEach(actKey => { let titleText = actions[actKey].description; if (actions[actKey].name != actions[actKey].label) { titleText = actions[actKey].name + ': ' + titleText; } actListTag.appendFormatLine('
  • {4}
  • ', VP_INS_SELECT_ITEM, actKey, 'action', titleText, actions[actKey].label); }); Object.keys(infos).forEach(infoKey => { let titleText = infos[infoKey].description; if (infos[infoKey].name != infos[infoKey].label) { titleText = infos[infoKey].name + ': ' + titleText; } infoListTag.appendFormatLine('
  • {4}
  • ', VP_INS_SELECT_ITEM, infoKey, 'info', titleText, infos[infoKey].label); }); $(this.wrapSelector('.' + VP_INS_SELECT_LIST + '.action')).html(actListTag.toString()); $(this.wrapSelector('.' + VP_INS_SELECT_LIST + '.info')).html(infoListTag.toString()); let that = this; // action search suggest var suggestInput = new SuggestInput(); suggestInput.addClass('vp-input action'); suggestInput.addClass(VP_INS_SEARCH); suggestInput.setPlaceholder("Search Action"); suggestInput.setSuggestList(function () { return Object.keys(actions); }); suggestInput.setSelectEvent(function (value, item) { $(this.wrapSelector()).val(value); $(that.wrapSelector('.' + VP_INS_TYPE + '.action')).val(item.type); $(that.pageThis.wrapSelector('#' + that.targetId)).trigger({ type: "model_editor_selected", varName: value, varOptions: actions[value], isMethod: false }); }); $(that.wrapSelector('.' + VP_INS_SEARCH + '.action')).replaceWith(function () { return suggestInput.toTagString(); }); // info search suggest suggestInput = new SuggestInput(); suggestInput.addClass('vp-input info'); suggestInput.addClass(VP_INS_SEARCH); suggestInput.setPlaceholder("Search info"); suggestInput.setSuggestList(function () { return Object.keys(infos); }); suggestInput.setSelectEvent(function (value, item) { $(this.wrapSelector()).val(value); $(that.wrapSelector('.' + VP_INS_TYPE + '.info')).val(item.type); $(that.pageThis.wrapSelector('#' + that.targetId)).trigger({ type: "model_editor_selected", varName: value, varOptions: infos[value], isMethod: true }); }); $(that.wrapSelector('.' + VP_INS_SEARCH + '.info')).replaceWith(function () { return suggestInput.toTagString(); }); // bind event this._bindEvent(); // load once on initializing page if (this.loaded == false) { let { modelEditorType, modelEditorName } = this.pageThis.state; if (modelEditorType != '' && modelEditorName != '') { // render option page for saved state that.renderOptionPage(modelEditorType, modelEditorName); } // set loaded true this.loaded = true; } } renderOptionPage(type, name) { if (this.state[type] != undefined && this.state[type][name] != undefined) { let config = this.state[type][name]; let optBox = new com_String(); // render tag config && config.options && config.options.forEach(opt => { let label = opt.name; if (opt.label != undefined) { label = opt.label; } // fix label label = com_util.optionToLabel(label); optBox.appendFormatLine('' , opt.name, opt.name, label); let content = com_generator.renderContent(this, opt.component[0], opt, this.pageThis.state); optBox.appendLine(content[0].outerHTML); }); // replace option box $(this.wrapSelector('.' + VP_INS_PARAMETER_BOX)).html(optBox.toString()); this.state.config = config; // add selection $(this.wrapSelector('.' + VP_INS_SELECT_ITEM)).removeClass('selected'); let typeClass = '.' + VP_INS_SELECT_LIST + '.' + type; let nameClass = '.' + VP_INS_SELECT_ITEM + '[data-var-name="' + name + '"]'; $(this.wrapSelector(typeClass + ' ' + nameClass)).addClass('selected'); // set state $(this.wrapSelector('#modelEditorType')).val(type); $(this.wrapSelector('#modelEditorName')).val(name); this.pageThis.state.modelEditorType = type; this.pageThis.state.modelEditorName = name; } } _bindEvent() { super._bindEvent(); let that = this; $(this.wrapSelector('.' + VP_INS_SELECT_ITEM)).on('click', function() { let name = $(this).data('var-name'); let type = $(this).data('var-type'); that.renderOptionPage(type, name); }); } /** * Show Model Editor * @param {*} showType all / action / info */ show() { $(this.wrapSelector()).show(); this.reload(); } hide() { $(this.wrapSelector()).hide(); } getCode(replaceDict={}) { let code = new com_String(); if (this.state.config.import != undefined) { code.appendLine(this.state.config.import); code.appendLine(); } let modelCode = com_generator.vp_codeGenerator(this.pageThis, this.state.config, this.pageThis.state); Object.keys(replaceDict).forEach(key => { modelCode = modelCode.replace(key, replaceDict[key]); }); code.append(modelCode); let allocateIdx = modelCode.indexOf(' = '); if (allocateIdx >= 0) { let allocateCode = modelCode.substr(0, allocateIdx); code.appendLine(); code.append(allocateCode); } return code.toString(); } } return ModelEditor; });