diff --git a/build.sh b/build.sh index 906b2c0c..f77324f7 100755 --- a/build.sh +++ b/build.sh @@ -11,8 +11,8 @@ #============================================================================= # Set version and replace it #============================================================================= -VP_ORG_VER=2.4.6 -VP_NEW_VER=2.4.7 +VP_ORG_VER=2.4.7 +VP_NEW_VER=2.4.8 # update version info grep -REil "VP_ORG_VER=.+$" colab/build.colab.sh jupyterlab/build.jupyterlab.sh jupyternotebook/build.jupyternotebook.sh | xargs sed -i "s/VP_ORG_VER=.\+$/VP_ORG_VER=${VP_ORG_VER}/g" diff --git a/colab/build.colab.sh b/colab/build.colab.sh index 014dfeb6..9a319753 100755 --- a/colab/build.colab.sh +++ b/colab/build.colab.sh @@ -11,8 +11,8 @@ #============================================================================= # Replace Version #============================================================================= -VP_ORG_VER=2.4.6 -VP_NEW_VER=2.4.7 +VP_ORG_VER=2.4.7 +VP_NEW_VER=2.4.8 # update version info # update manifest version with new numbering for new version diff --git a/colab/manifest.json b/colab/manifest.json index 007cc77c..e08ec7c0 100644 --- a/colab/manifest.json +++ b/colab/manifest.json @@ -1,7 +1,7 @@ { "name": "Visual Python for Colab", "description": "GUI-based Python code generator for Google Colab as an extension", - "version": "2.4.7", + "version": "2.4.8", "manifest_version": 3, "icons": { "48": "icon.png", diff --git a/jupyterlab/build.jupyterlab.sh b/jupyterlab/build.jupyterlab.sh index dcfee5a2..7bc6fa99 100755 --- a/jupyterlab/build.jupyterlab.sh +++ b/jupyterlab/build.jupyterlab.sh @@ -11,8 +11,8 @@ #============================================================================= # Replace Version and Basic Files #============================================================================= -VP_ORG_VER=2.4.6 -VP_NEW_VER=2.4.7 +VP_ORG_VER=2.4.7 +VP_NEW_VER=2.4.8 # update version info grep -REil "\"version\": \"${VP_ORG_VER}\"" package.json | xargs sed -i "s/\"version\": \"${VP_ORG_VER//\./\\.}\"/\"version\": \"${VP_NEW_VER}\"/g" diff --git a/jupyterlab/package-lock.json b/jupyterlab/package-lock.json index 7472a84d..63cbf276 100644 --- a/jupyterlab/package-lock.json +++ b/jupyterlab/package-lock.json @@ -1,12 +1,12 @@ { "name": "jupyterlab-visualpython", - "version": "2.4.6", + "version": "2.4.7", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "jupyterlab-visualpython", - "version": "2.4.6", + "version": "2.4.7", "license": "GPLv3 with Visual Python special exception", "dependencies": { "@jupyterlab/cells": "^3.5.2", diff --git a/jupyterlab/package.json b/jupyterlab/package.json index da347cc1..d3ce4a2d 100644 --- a/jupyterlab/package.json +++ b/jupyterlab/package.json @@ -1,6 +1,6 @@ { "name": "jupyterlab-visualpython", - "version": "2.4.7", + "version": "2.4.8", "description": "GUI-based Python code generator for Jupyter Lab as an extension", "keywords": [ "jupyter", diff --git a/jupyterlab/pyproject.toml b/jupyterlab/pyproject.toml index c32f299d..0fd04e6d 100644 --- a/jupyterlab/pyproject.toml +++ b/jupyterlab/pyproject.toml @@ -32,7 +32,7 @@ classifiers = [ "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", ] -version = "2.4.7" +version = "2.4.8" [project.license] file = "LICENSE" @@ -92,7 +92,7 @@ file = [ ] [tool.tbump.version] -current = "2.4.7" +current = "2.4.8" regex = "(?P\\d+)\\.(?P\\d+)\\.(?P\\d+)((?Pa|b|rc|.dev)(?P\\d+))?" [tool.tbump.git] diff --git a/jupyternotebook/build.jupyternotebook.sh b/jupyternotebook/build.jupyternotebook.sh index c56d37e7..f36ab453 100755 --- a/jupyternotebook/build.jupyternotebook.sh +++ b/jupyternotebook/build.jupyternotebook.sh @@ -11,8 +11,8 @@ #============================================================================= # Replace Version and Basic Files #============================================================================= -VP_ORG_VER=2.4.6 -VP_NEW_VER=2.4.7 +VP_ORG_VER=2.4.7 +VP_NEW_VER=2.4.8 # update version info grep -REil ${VP_ORG_VER//\./\\.} setup.py visualpython/js/com/com_Config.js visualpython/js/com/com_Const.js | xargs sed -i --follow-symlinks "s/${VP_ORG_VER//\./\\.}/${VP_NEW_VER}/g" diff --git a/jupyternotebook/setup.py b/jupyternotebook/setup.py index 2f141da0..b2a54870 100644 --- a/jupyternotebook/setup.py +++ b/jupyternotebook/setup.py @@ -10,7 +10,7 @@ setup( name = name, - version = '2.4.7', + version = '2.4.8', packages = find_packages(), package_data = {"": ["*"], 'visualpython' : ['visualpython.yaml', 'README.md']}, scripts = ['visualpython/bin/visualpy', 'visualpython/bin/visualpy.bat'], diff --git a/visualpython/css/m_ml/gridSearch.css b/visualpython/css/m_ml/gridSearch.css index dbe53854..a5579206 100644 --- a/visualpython/css/m_ml/gridSearch.css +++ b/visualpython/css/m_ml/gridSearch.css @@ -40,6 +40,7 @@ } .vp-param-set-add { cursor: pointer; + margin-bottom: 5px; } .vp-param-item > label { align-self: center; diff --git a/visualpython/css/m_ml/pipeline.css b/visualpython/css/m_ml/pipeline.css index 0bbe46c7..7e670421 100644 --- a/visualpython/css/m_ml/pipeline.css +++ b/visualpython/css/m_ml/pipeline.css @@ -15,7 +15,7 @@ } .vp-pp-right-box { display: grid; - grid-template-rows: 35px 10px calc(100% - 45px); + grid-template-rows: 35px 10px calc(100% - 80px) 35px; padding-left: 5px; overflow: auto; } @@ -45,7 +45,13 @@ position: absolute; transition: all 0.5s ease-in-out; } -.vp-pp-item:not(:last-child):before { +.vp-pp-item:last-child:before, +.vp-pp-item:last-child:after, +.vp-pp-item.vp-last-visible:before, +.vp-pp-item.vp-last-visible:after { + display: none; +} +.vp-pp-item:before { border: 0.25px solid var(--vp-gray-color); border-width: 0 4px 4px 0; display: inline-block; @@ -55,7 +61,7 @@ top: 47px; left: 100px; } -.vp-pp-item:not(:last-child):after { +.vp-pp-item:after { border: 0.25px solid var(--vp-gray-color); border-width: 0 4px 0 0; height: 15px; @@ -129,4 +135,48 @@ } .vp-pp-step-content:empty::after { content: 'Select the template and Follow the pipeline to generate simple ML code.' +} +.vp-pp-step-footer { + border-top: 0.25px solid var(--vp-border-gray-color); + width: 100%; + height: 35px; +} +.vp-pp-step-move-btn { + width: 70px; + height: 30px; + background-color: var(--vp-background-color); + border: 0.25px solid var(--vp-border-gray-color); + box-sizing: border-box; + box-shadow: 0.5px 0.5px 0.5px rgb(0 0 0 / 10%); + border-radius: 3px; + line-height: 30px; + vertical-align: middle; + font-family: 'AppleSDGothicNeo'; + font-size: 13px; + text-align: center; + color: var(--vp-font-primary); + cursor: pointer; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + + display: inline-block; + position: absolute; + bottom: 10px; +} +.vp-pp-step-move-btn:hover { + background-color: var(--vp-light-gray-color); +} +.vp-pp-step-move-btn.disabled { + background-color: var(--vp-gray-color); + cursor: not-allowed; +} +.vp-pp-step-prev { + left: 270px; +} +.vp-pp-step-next{ + right: 15px; } \ No newline at end of file diff --git a/visualpython/data/m_library/pandasLibrary.js b/visualpython/data/m_library/pandasLibrary.js index 8491177b..7ae4eb7e 100644 --- a/visualpython/data/m_library/pandasLibrary.js +++ b/visualpython/data/m_library/pandasLibrary.js @@ -1916,7 +1916,10 @@ define([ { "name": "by", "label": "Sort By", - "usePair": true + "usePair": true, + "component": [ + "col_multi" + ] }, { "name": "axis", @@ -2437,7 +2440,7 @@ define([ "name": "get data counts", "library": "pandas", "description": "get data value counts", - "code": "${o0} = ${i0}.value_counts()", + "code": "${o0} = ${i0}.value_counts(${bins}${sort}${ascending}${dropna}${etc})", "options": [ { "name": "i0", @@ -2454,7 +2457,39 @@ define([ "component": [ "input" ] - } + }, + { + "name": "bins", + "component": [ + "input_number" + ], + "help": "Only for Series object", + "usePair": true, + }, + { + "name": "sort", + "component": [ + "bool_select" + ], + "default": "True", + "usePair": true, + }, + { + "name": "ascending", + "component": [ + "bool_select" + ], + "default": "False", + "usePair": true, + }, + { + "name": "dropna", + "component": [ + "bool_select" + ], + "default": "True", + "usePair": true, + }, ] }, "pdIdt_info": { diff --git a/visualpython/data/m_ml/mlLibrary.js b/visualpython/data/m_ml/mlLibrary.js index 78528fed..e5bf2205 100644 --- a/visualpython/data/m_ml/mlLibrary.js +++ b/visualpython/data/m_ml/mlLibrary.js @@ -129,6 +129,7 @@ define([ name: 'OneHotEncoder', import: 'from sklearn.preprocessing import OneHotEncoder', code: 'OneHotEncoder(${sparse}${handle_unknown}${etc})', + returnType: 'OneHotEncoder', options: [ { name: 'sparse', component: ['bool_select'], default: 'False', usePair: true }, { name: 'handle_unknown', component: ['option_suggest'], usePair: true, @@ -139,6 +140,7 @@ define([ name: 'LabelEncoder', import: 'from sklearn.preprocessing import LabelEncoder', code: 'LabelEncoder()', + returnType: 'LabelEncoder', options: [ ] @@ -147,6 +149,7 @@ define([ name: 'OrdinalEncoder', import: 'from sklearn.preprocessing import OrdinalEncoder', code: 'OrdinalEncoder(${handle_unknown}${unknown_values}${etc})', + returnType: 'OrdinalEncoder', options: [ { name: 'handle_unknown', component: ['option_suggest'], usePair: true, options: ['error', 'use_encoded_value'], default: 'error' }, @@ -158,6 +161,7 @@ define([ install: '!pip install category_encoders', import: 'from category_encoders.target_encoder import TargetEncoder', code: 'TargetEncoder(${cols}${handle_missing}${handle_unknown}${smoothing}${etc})', + returnType: 'TargetEncoder', options: [ { name: 'cols', component: ['var_suggest', '1darr'], usePair: true }, { name: 'handle_missing', component: ['option_suggest'], usePair: true, @@ -172,6 +176,7 @@ define([ install: '!pip install imblearn', import: 'from imblearn.over_sampling import SMOTE', code: 'SMOTE(${random_state}${k_neighbors}${etc})', + returnType: 'SMOTE', options: [ { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true }, { name: 'k_neighbors', component: ['input_number'], default: 5, usePair: true } @@ -182,6 +187,7 @@ define([ name: 'StandardScaler', import: 'from sklearn.preprocessing import StandardScaler', code: 'StandardScaler(${with_mean}${with_std}${etc})', + returnType: 'StandardScaler', options: [ { name: 'with_mean', component: ['bool_select'], default: 'True', usePair: true }, { name: 'with_std', component: ['bool_select'], default: 'True', usePair: true } @@ -191,6 +197,7 @@ define([ name: 'RobustScaler', import: 'from sklearn.preprocessing import RobustScaler', code: 'RobustScaler(${with_centering}${with_scaling}${etc})', + returnType: 'RobustScaler', options: [ { name: 'with_centering', component: ['bool_select'], default: 'True', usePair: true }, { name: 'with_scaling', component: ['bool_select'], default: 'True', usePair: true } @@ -200,6 +207,7 @@ define([ name: 'MinMaxScaler', import: 'from sklearn.preprocessing import MinMaxScaler', code: 'MinMaxScaler(${feature_range}${etc})', + returnType: 'MinMaxScaler', options: [ { name: 'feature_range', component: ['input'], placeholder: '(min, max)', default: '(0, 1)', usePair: true } ] @@ -208,6 +216,7 @@ define([ name: 'Normalizer', import: 'from sklearn.preprocessing import Normalizer', code: 'Normalizer(${norm}${etc})', + returnType: 'Normalizer', options: [ { name: 'norm', component: ['option_suggest'], usePair: true, options: ['l1', 'l2', 'max'], default: 'l2' }, @@ -217,6 +226,7 @@ define([ name: 'Log Scaling', import: 'from sklearn.preprocessing import FunctionTransformer', code: 'FunctionTransformer(np.log1p${etc})', + returnType: 'FunctionTransformer', options: [ ] @@ -225,6 +235,7 @@ define([ name: 'Exponential Scaling', import: 'from sklearn.preprocessing import FunctionTransformer', code: 'FunctionTransformer(np.expm1${etc})', + returnType: 'FunctionTransformer', options: [ ] @@ -233,6 +244,7 @@ define([ name: 'Polynomial Features', import: 'from sklearn.preprocessing import PolynomialFeatures', code: 'PolynomialFeatures(${etc})', + returnType: 'PolynomialFeatures', options: [ ] @@ -241,6 +253,7 @@ define([ name: 'KBins Discretizer', import: 'from sklearn.preprocessing import KBinsDiscretizer', code: 'KBinsDiscretizer(${n_bins}${strategy}${encode}${etc})', + returnType: 'KBinsDiscretizer', options: [ { name: 'n_bins', component: ['input_number'], default: 5, usePair: true }, { name: 'strategy', component: ['option_select'], type: 'text', default: 'quantile', usePair: true, @@ -253,6 +266,7 @@ define([ name: 'SimpleImputer', import: 'from sklearn.impute import SimpleImputer', code: 'SimpleImputer(${missing_values}${strategy}${fill_value}${copy}${add_indicator}${etc})', + returnType: 'SimpleImputer', options: [ { name: 'missing_values', component: ['input'], placeholder: 'np.nan', usePair: true }, { name: 'strategy', component: ['option_select'], type: 'text', default: 'quantile', usePair: true, @@ -266,6 +280,7 @@ define([ name: 'MakeColumnTransformer', import: 'from sklearn.compose import make_column_transformer', code: 'make_column_transformer(${mct_code})', + returnType: 'ColumnTransformer', options: [ ] @@ -275,6 +290,7 @@ define([ name: 'LinearRegression', import: 'from sklearn.linear_model import LinearRegression', code: 'LinearRegression(${fit_intercept}${etc})', + returnType: 'LinearRegression', options: [ { name: 'fit_intercept', component: ['bool_select'], default: 'True', usePair: true } ] @@ -283,6 +299,7 @@ define([ name: 'Ridge', import: 'from sklearn.linear_model import Ridge', code: 'Ridge(${alpha}${etc})', + returnType: 'Ridge', options: [ { name: 'alpha', component: ['input_number'], default: 1.0, usePair: true } ] @@ -291,6 +308,7 @@ define([ name: 'Lasso', import: 'from sklearn.linear_model import Lasso', code: 'Lasso(${alpha}${etc})', + returnType: 'Lasso', options: [ { name: 'alpha', component: ['input_number'], default: 1.0, usePair: true } ] @@ -299,6 +317,7 @@ define([ name: 'ElasticNet', import: 'from sklearn.linear_model import ElasticNet', code: 'ElasticNet(${alpha}${l1_ratio}${etc})', + returnType: 'ElasticNet', options: [ { name: 'alpha', component: ['input_number'], default: 1.0, usePair: true }, { name: 'l1_ratio', component: ['input_number'], default: 0.5, usePair: true } @@ -308,6 +327,7 @@ define([ name: 'SVR', import: 'from sklearn.svm import SVR', code: 'SVR(${C}${kernel}${degree}${gamma}${coef0}${random_state}${etc})', + returnType: 'SVR', options: [ { name: 'C', component: ['input_number'], placeholder: '1.0', usePair: true, step: 0.1, min: 0 }, { name: 'kernel', component: ['option_select'], type: 'text', usePair: true, @@ -323,6 +343,7 @@ define([ name: 'DecisionTreeRegressor', import: 'from sklearn.tree import DecisionTreeRegressor', code: 'DecisionTreeRegressor(${criterion}${max_depth}${min_samples_split}${random_state}${etc})', + returnType: 'DecisionTreeRegressor', options: [ { name: 'criterion', component: ['option_select'], type: 'text', default: 'squared_error', type:'text', options: ['squared_error', 'friedman_mse', 'absolute_error', 'poisson'] }, @@ -335,6 +356,7 @@ define([ name: 'RandomForestRegressor', import: 'from sklearn.ensemble import RandomForestRegressor', code: 'RandomForestRegressor(${n_estimators}${criterion}${max_depth}${min_samples_split}${n_jobs}${random_state}${etc})', + returnType: 'RandomForestRegressor', options: [ { name: 'n_estimators', component: ['input_number'], default: 100, usePair: true }, { name: 'criterion', component: ['option_select'], type: 'text', default: 'squared_error', type:'text', usePair: true, @@ -349,6 +371,7 @@ define([ name: 'GradientBoostingRegressor', import: 'from sklearn.ensemble import GradientBoostingRegressor', code: 'GradientBoostingRegressor(${loss}${learning_rate}${n_estimators}${criterion}${random_state}${etc})', + returnType: 'GradientBoostingRegressor', options: [ { name: 'loss', component: ['option_select'], type: 'text', default: 'squared_error', type:'text', usePair: true, options: ['squared_error', 'absolute_error', 'huber', 'quantile'] }, @@ -364,6 +387,7 @@ define([ install: '!pip install xgboost', import: 'from xgboost import XGBRegressor', code: 'XGBRegressor(${n_estimators}${max_depth}${learning_rate}${gamma}${random_state}${etc})', + returnType: 'XGBRegressor', options: [ { name: 'n_estimators', component: ['input_number'], default: 100, usePair: true }, { name: 'max_depth', component: ['input_number'], placeholder: 'None', usePair: true }, @@ -377,6 +401,7 @@ define([ install: '!pip install lightgbm', import: 'from lightgbm import LGBMRegressor', code: 'LGBMRegressor(${boosting_type}${max_depth}${learning_rate}${n_estimators}${random_state}${etc})', + returnType: 'LGBMRegressor', options: [ { name: 'boosting_type', component: ['option_select'], type: 'text', default: 'gbdt', type: 'text', usePair: true, options: ['gbdt', 'dart', 'goss', 'rf']}, @@ -391,6 +416,7 @@ define([ install: '!pip install catboost', import: 'from catboost import CatBoostRegressor', code: 'CatBoostRegressor(${learning_rate}${loss_function}${task_type}${max_depth}${n_estimators}${random_state}${etc})', + returnType: 'CatBoostRegressor', options: [ { name: 'learning_rate', component: ['input_number'], placeholder: 'None', usePair: true }, { name: 'loss_function', component: ['option_select'], type: 'text', default: 'RMSE', type:'text', usePair: true, @@ -407,6 +433,7 @@ define([ name: 'LogisticRegression', import: 'from sklearn.linear_model import LogisticRegression', code: 'LogisticRegression(${penalty}${C}${random_state}${etc})', + returnType: 'LogisticRegression', options: [ { name: 'penalty', component: ['option_select'], type: 'text', default: 'l2', usePair: true, options: ['l1', 'l2', 'elasticnet', 'none']}, { name: 'C', component: ['input_number'], placeholder: '1.0', usePair: true, step: 0.1, min: 0 }, @@ -417,6 +444,7 @@ define([ name: 'BernoulliNB', import: 'from sklearn.naive_bayes import BernoulliNB', code: 'BernoulliNB(${etc})', + returnType: 'BernoulliNB', options: [ //TODO: ] @@ -425,6 +453,7 @@ define([ name: 'MultinomialNB', import: 'from sklearn.naive_bayes import MultinomialNB', code: 'MultinomialNB(${etc})', + returnType: 'MultinomialNB', options: [ //TODO: ] @@ -433,6 +462,7 @@ define([ name: 'GaussianNB', import: 'from sklearn.naive_bayes import GaussianNB', code: 'GaussianNB(${etc})', + returnType: 'GaussianNB', options: [ //TODO: ] @@ -441,6 +471,7 @@ define([ name: 'SVC', import: 'from sklearn.svm import SVC', code: 'SVC(${C}${kernel}${degree}${gamma}${coef0}${random_state}${etc})', + returnType: 'SVC', options: [ { name: 'C', component: ['input_number'], placeholder: '1.0', usePair: true, step: 0.1, min: 0 }, { name: 'kernel', component: ['option_select'], type: 'text', usePair: true, @@ -456,6 +487,7 @@ define([ name: 'DecisionTreeClassifier', import: 'from sklearn.tree import DecisionTreeClassifier', code: 'DecisionTreeClassifier(${criterion}${max_depth}${min_samples_split}${random_state}${etc})', + returnType: 'DecisionTreeClassifier', options: [ { name: 'criterion', component: ['option_select'], type: 'text', default: 'squared_error', type:'text', options: ['squared_error', 'friedman_mse', 'absolute_error', 'poisson'], usePair: true }, @@ -468,6 +500,7 @@ define([ name: 'RandomForestClassifier', import: 'from sklearn.ensemble import RandomForestClassifier', code: 'RandomForestClassifier(${n_estimators}${criterion}${max_depth}${min_samples_split}${n_jobs}${random_state}${etc})', + returnType: 'RandomForestClassifier', options: [ { name: 'n_estimators', component: ['input_number'], default: 100, usePair: true }, { name: 'criterion', component: ['option_select'], type: 'text', default: 'gini', type:'text', usePair: true, @@ -482,6 +515,7 @@ define([ name: 'GradientBoostingClassifier', import: 'from sklearn.ensemble import GradientBoostingClassifier', code: 'GradientBoostingClassifier(${loss}${learning_rate}${n_estimators}${criterion}${random_state}${etc})', + returnType: 'GradientBoostingClassifier', options: [ { name: 'loss', component: ['option_select'], type: 'text', default: 'deviance', type: 'text', usePair: true, options: ['deviance', 'exponential'] }, @@ -497,6 +531,7 @@ define([ install: '!pip install xgboost', import: 'from xgboost import XGBClassifier', code: 'XGBClassifier(${n_estimators}${max_depth}${learning_rate}${gamma}${random_state}${etc})', + returnType: 'XGBClassifier', options: [ { name: 'n_estimators', component: ['input_number'], default: 100, usePair: true }, { name: 'max_depth', component: ['input_number'], placeholder: 'None', usePair: true }, @@ -510,6 +545,7 @@ define([ install: '!pip install lightgbm', import: 'from lightgbm import LGBMClassifier', code: 'LGBMClassifier(${boosting_type}${max_depth}${learning_rate}${n_estimators}${random_state}${etc})', + returnType: 'LGBMClassifier', options: [ { name: 'boosting_type', component: ['option_select'], type: 'text', default: 'gbdt', type: 'text', usePair: true, options: ['gbdt', 'dart', 'goss', 'rf']}, @@ -524,6 +560,7 @@ define([ install: '!pip install catboost', import: 'from catboost import CatBoostClassifier', code: 'CatBoostClassifier(${learning_rate}${loss_function}${task_type}${max_depth}${n_estimators}${random_state}${etc})', + returnType: 'CatBoostClassifier', options: [ { name: 'learning_rate', component: ['input_number'], placeholder: 'None', usePair: true }, { name: 'loss_function', component: ['option_select'], type: 'text', default: 'RMSE', type:'text', usePair: true, @@ -542,6 +579,7 @@ define([ import: 'from autosklearn.regression import AutoSklearnRegressor', link: 'https://automl.github.io/auto-sklearn/master/api.html#regression', code: 'AutoSklearnRegressor(${etc})', + returnType: 'AutoSklearnRegressor', options: [ ] @@ -551,6 +589,7 @@ define([ install: '!pip install tpot', import: 'from tpot import TPOTRegressor', code: 'TPOTRegressor(${generation}${population_size}${cv}${random_state}${etc})', + returnType: 'TPOTRegressor', options: [ { name: 'generation', component: ['input_number'], default: 100, usePair: true }, { name: 'population_size', component: ['input_number'], default: 100, usePair: true }, @@ -564,6 +603,7 @@ define([ import: 'from autosklearn.classification import AutoSklearnClassifier', link: 'https://automl.github.io/auto-sklearn/master/api.html#classification', code: 'AutoSklearnClassifier(${etc})', + returnType: 'AutoSklearnClassifier', options: [ ] @@ -573,6 +613,7 @@ define([ install: '!pip install tpot', import: 'from tpot import TPOTClassifier', code: 'TPOTClassifier(${generation}${population_size}${cv}${random_state}${etc})', + returnType: 'TPOTClassifier', options: [ { name: 'generation', component: ['input_number'], default: 100, usePair: true }, { name: 'population_size', component: ['input_number'], default: 100, usePair: true }, @@ -585,6 +626,7 @@ define([ name: 'KMeans', import: 'from sklearn.cluster import KMeans', code: 'KMeans(${n_clusters}${random_state}${etc})', + returnType: 'KMeans', options: [ { name: 'n_clusters', component: ['input_number'], default: 8, usePair: true }, { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true } @@ -594,6 +636,7 @@ define([ name: 'AgglomerativeClustering', import: 'from sklearn.cluster import AgglomerativeClustering', code: 'AgglomerativeClustering(${n_clusters}${random_state}${etc})', + returnType: 'AgglomerativeClustering', options: [ { name: 'n_clusters', component: ['input_number'], default: 2, usePair: true }, { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true } @@ -603,6 +646,7 @@ define([ name: 'GaussianMixture', import: 'from sklearn.mixture import GaussianMixture', code: 'GaussianMixture(${n_components}${random_state}${etc})', + returnType: 'GaussianMixture', options: [ { name: 'n_components', component: ['input_number'], default: 1, usePair: true }, { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true } @@ -612,6 +656,7 @@ define([ name: 'DBSCAN', import: 'from sklearn.cluster import DBSCAN', code: 'DBSCAN(${eps}${min_samples}${etc})', + returnType: 'DBSCAN', options: [ { name: 'eps', component: ['input_number'], default: 0.5, usePair: true }, { name: 'min_samples', component: ['input_number'], default: 5, usePair: true } @@ -622,6 +667,7 @@ define([ name: 'PCA(Principal Component Analysis)', import: 'from sklearn.decomposition import PCA', code: 'PCA(${n_components}${random_state}${etc})', + returnType: 'PCA', options: [ { name: 'n_components', component: ['input_number'], placeholder: 'None', usePair: true }, { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true } @@ -631,6 +677,7 @@ define([ name: 'LDA(Linear Discriminant Analysis)', import: 'from sklearn.discriminant_analysis import LinearDiscriminantAnalysis', code: 'LinearDiscriminantAnalysis(${n_components}${etc})', + returnType: 'LinearDiscriminantAnalysis', options: [ { name: 'n_components', component: ['input_number'], placeholder: 'None', usePair: true } ] @@ -639,6 +686,7 @@ define([ name: 'Truncated SVD', import: 'from sklearn.decomposition import TruncatedSVD', code: 'TruncatedSVD(${n_components}${random_state}${etc})', + returnType: 'TruncatedSVD', options: [ { name: 'n_components', component: ['input_number'], default: 2, usePair: true }, { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true } @@ -648,6 +696,7 @@ define([ name: 'NMF(Non-Negative Matrix Factorization)', import: 'from sklearn.decomposition import NMF', code: 'NMF(${n_components}${random_state}${etc})', + returnType: 'NMF', options: [ { name: 'n_components', component: ['input_number'], placeholder: 'None', usePair: true }, { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true } @@ -657,6 +706,7 @@ define([ name: 'TSNE(T-distributed Stochastic Neighbor Embedding)', import: 'from sklearn.manifold import TSNE', code: 'TSNE(${n_components}${learning_rate}${random_state}${etc})', + returnType: 'TSNE', options: [ { name: 'n_components', component: ['input_number'], placeholder: 'None', usePair: true }, { name: 'learning_rate', component: ['input_number'], default: 200.0, usePair: true }, @@ -667,10 +717,12 @@ define([ 'grid-search': { name: 'GridSearch', import: 'from sklearn.model_selection import GridSearchCV', - code: 'GridSearchCV(${estimator}, ${param_grid}${n_jobs}${cv}${verbose}${etc})', + code: 'GridSearchCV(${estimator}, ${param_grid}${scoring}${n_jobs}${cv}${verbose}${etc})', + returnType: 'GridSearchCV', options: [ { name: 'estimator', component: ['data_select'], placeholder: 'Select model'}, { name: 'param_grid', component: ['input'], placeholder: 'Enter parameters'}, + { name: 'scoring', component: ['input'], placeholder: 'None', usePair: true }, // https://scikit-learn.org/stable/modules/model_evaluation.html#scoring-parameter { name: 'n_jobs', component: ['input'], placeholder: 'None', usePair: true }, { name: 'cv', component: ['input'], placeholder: 'None', usePair: true }, { name: 'verbose', component: ['input_number'], placeholder: 'Input number', usePair: true } @@ -680,19 +732,19 @@ define([ 'model_save': { name: 'Save model', import: 'import joblib', - code: "joblib.dump(${target}, ${savePath}${etc})", + code: "joblib.dump(${target}, ${save_path}${etc})", options: [ - { name: 'target', component: ['data_select'], placeholder: 'Select model'}, - { name: 'savePath', component: ['file-save'], placeholder: 'Select path'} + { name: 'target', component: ['data_select'], comp_type: 'ml', placeholder: 'Select model'}, + { name: 'save_path', component: ['file-save'], placeholder: 'Select path'} ] }, 'model_load': { name: 'Load model', import: 'import joblib', - code: "${allocateTo} = joblib.load(${loadPath}${etc})", + code: "${allocate_to} = joblib.load(${load_path}${etc})", options: [ - { name: 'loadPath', component: ['file-open'], placeholder: 'Select path'}, - { name: 'allocateTo', component: ['data_select'], placeholder: 'New variable to load'} + { name: 'load_path', component: ['file-open'], placeholder: 'Select path'}, + { name: 'allocate_to', component: ['input'], placeholder: 'New variable to load'} ] } } diff --git a/visualpython/data/m_stats/statsLibrary.js b/visualpython/data/m_stats/statsLibrary.js index e43e6695..891953e9 100644 --- a/visualpython/data/m_stats/statsLibrary.js +++ b/visualpython/data/m_stats/statsLibrary.js @@ -35,6 +35,7 @@ define([ import: 'from scipy import stats', code: '_rv = stats.binom(${n}${p})', description: 'A binomial discrete random variable.', + help: '_vp_stats.binom', options: [ { name: 'n', component: ['input_number'], value: 10, required: true, usePair: true }, { name: 'p', component: ['input_number'], value: 0.6, required: true, usePair: true }, @@ -45,6 +46,7 @@ define([ import: 'from scipy import stats', code: '_rv = stats.multinomial(${n}${p})', description: 'A multinomial random variable.', + help: '_vp_stats.multinomial', options: [ { name: 'n', component: ['input_number'], value: 10, required: true, usePair: true }, { name: 'p', component: ['data_select'], value: '[0.4, 0.6]', required: true, usePair: true }, @@ -56,6 +58,7 @@ define([ import: 'from scipy import stats', code: '_rv = stats.uniform()', description: 'A uniform continuous random variable.', + help: '_vp_stats.uniform', options: [ ] }, @@ -64,6 +67,7 @@ define([ import: 'from scipy import stats', code: '_rv = stats.norm(${loc}${scale})', description: 'A normal continuous random variable.', + help: '_vp_stats.norm', options: [ { name: 'loc', component: ['input_number'], value: 0, usePair: true }, { name: 'scale', component: ['input_number'], value: 1, usePair: true }, @@ -74,6 +78,7 @@ define([ import: 'from scipy import stats', code: '_rv = stats.beta(${a}${b})', description: 'A beta continuous random variable.', + help: '_vp_stats.beta', options: [ { name: 'a', component: ['input_number'], required: true, usePair: true }, { name: 'b', component: ['input_number'], required: true, usePair: true }, @@ -84,6 +89,7 @@ define([ import: 'from scipy import stats', code: '_rv = stats.gamma(${a})', description: 'A gamma continuous random variable.', + help: '_vp_stats.gamma', options: [ { name: 'a', component: ['input_number'], required: true, usePair: true }, ] @@ -93,6 +99,7 @@ define([ import: 'from scipy import stats', code: '_rv = stats.t(${df})', description: "A Student's t continuous random variable.", + help: '_vp_stats.t', options: [ { name: 'df', component: ['input_number'], required: true, usePair: true }, ] @@ -102,6 +109,7 @@ define([ import: 'from scipy import stats', code: '_rv = stats.chi2(${df})', description: 'A chi-squared continuous random variable.', + help: '_vp_stats.chi2', options: [ { name: 'df', component: ['input_number'], required: true, usePair: true }, ] @@ -111,6 +119,7 @@ define([ import: 'from scipy import stats', code: '_rv = stats.f(${dfn}${dfd})', description: 'An F continuous random variable.', + help: '_vp_stats.f', options: [ { name: 'dfn', component: ['input_number'], required: true, usePair: true }, { name: 'dfd', component: ['input_number'], required: true, usePair: true }, @@ -121,8 +130,9 @@ define([ import: 'from scipy import stats', code: '_rv = stats.dirichlet(${alpha}${seed})', description: 'A Dirichlet random variable.', + help: '_vp_stats.dirichlet', options: [ - { name: 'alpha', component: ['input_number'], required: true, usePair: true }, + { name: 'alpha', component: ['input'], required: true, usePair: true, value: '(3,5,2)', placeholder: '(x, y, z)' }, { name: 'seed', component: ['input_number'], usePair: true }, ] }, @@ -131,6 +141,7 @@ define([ import: 'from scipy import stats', code: '_rv = stats.multivariate_normal(${mean}${cov}${allow_singular})', description: 'A multivariate normal random variable.', + help: '_vp_stats.multivariate_normal', options: [ { name: 'mean', component: ['data_select'], value: '[0]', usePair: true }, { name: 'cov', component: ['data_select'], value: '[1]', usePair: true }, diff --git a/visualpython/html/component/popupComponent.html b/visualpython/html/component/popupComponent.html index 825a51c9..4c1ddec2 100644 --- a/visualpython/html/component/popupComponent.html +++ b/visualpython/html/component/popupComponent.html @@ -91,11 +91,11 @@ \ No newline at end of file diff --git a/visualpython/html/m_stats/anova.html b/visualpython/html/m_stats/anova.html index 17b356bd..582cd58c 100644 --- a/visualpython/html/m_stats/anova.html +++ b/visualpython/html/m_stats/anova.html @@ -50,8 +50,8 @@
- -
+ +
diff --git a/visualpython/html/m_stats/studentstTest.html b/visualpython/html/m_stats/studentstTest.html index c250b06d..d1244cb5 100644 --- a/visualpython/html/m_stats/studentstTest.html +++ b/visualpython/html/m_stats/studentstTest.html @@ -40,9 +40,15 @@
- +
+ + +
- +
+ + +
diff --git a/visualpython/js/com/com_Config.js b/visualpython/js/com/com_Config.js index b94ec7aa..3097dea1 100644 --- a/visualpython/js/com/com_Config.js +++ b/visualpython/js/com/com_Config.js @@ -197,7 +197,7 @@ define([ code: 'import joblib', type: 'package' }, - 'scipy.stats': { + 'stats': { code: 'from scipy import stats', type: 'package' }, @@ -205,7 +205,7 @@ define([ code: 'import scipy', type: 'package' }, - 'statsmodels.api': { + 'sm': { code: 'import statsmodels.api as sm', type: 'package' } @@ -1052,7 +1052,7 @@ define([ /** * Version */ - Config.version = "2.4.7"; + Config.version = "2.4.8"; /** * Type of mode diff --git a/visualpython/js/com/com_Const.js b/visualpython/js/com/com_Const.js index b0ed00fa..7832fdc0 100644 --- a/visualpython/js/com/com_Const.js +++ b/visualpython/js/com/com_Const.js @@ -19,7 +19,7 @@ define ([ class Constants { } Constants.TOOLBAR_BTN_INFO = { - HELP: "Visual Python 2.4.7" + HELP: "Visual Python 2.4.8" , ICON: "vp-main-icon" , ID: "vpBtnToggle" , NAME: "toggle-vp" diff --git a/visualpython/js/com/com_generatorV2.js b/visualpython/js/com/com_generatorV2.js index 13cce5e5..d8cb8cf8 100644 --- a/visualpython/js/com/com_generatorV2.js +++ b/visualpython/js/com/com_generatorV2.js @@ -14,8 +14,9 @@ define([ 'vp_base/js/com/component/SuggestInput', 'vp_base/js/com/component/VarSelector2', 'vp_base/js/com/component/DataSelector', + 'vp_base/js/com/component/MultiSelector', 'vp_base/js/com/component/FileNavigation' -], function (com_util, com_makeDom, SuggestInput, VarSelector2, DataSelector, FileNavigation) { +], function (com_util, com_makeDom, SuggestInput, VarSelector2, DataSelector, MultiSelector, FileNavigation) { /** * show result after code executed */ @@ -39,6 +40,7 @@ define([ 'var_select': 'Select Variable', 'var_multi': 'Select N-Variables', 'col_select': 'Select Column', + 'col_multi': 'Select Columns', 'textarea': 'Input textarea', 'input_number': 'Input number', 'input_text': 'Input text', @@ -149,6 +151,7 @@ define([ } + bindMultiSelector(pageThis); bindAutoComponentEvent(pageThis); } @@ -174,7 +177,7 @@ define([ } else if (output === true) { requiredFontStyle = 'vp-bold'; } - var lblTag = $(``).attr({ + var lblTag = $(``).attr({ 'for': name, 'class': requiredFontStyle, 'title': '(' + name + ')' @@ -315,7 +318,8 @@ define([ case 'option_select': var optSlct = $('').attr({ 'class':'vp-select option-select vp-state', - 'id':obj.name + 'id':obj.name, + 'title': (obj.help==undefined?'':obj.help), }); obj.options.forEach((opt, idx, arr) => { var label = (obj.options_label != undefined? obj.options_label[idx]:opt); @@ -368,6 +372,7 @@ define([ let dataSelector = new DataSelector({ pageThis: pageThis, id: obj.name, + type: obj.comp_type || 'data', allowDataType: obj.var_type, placeholder: obj.placeholder || 'Select data', value: value, @@ -382,7 +387,8 @@ define([ id: obj.name, class: 'vp-input vp-state', placeholder: obj.placeholder || 'Select data', - required: obj.required === true + required: obj.required === true, + title: (obj.help==undefined?'':obj.help), }); vp_generateVarSuggestInput(pageThis.wrapSelector(), obj); content = tag; @@ -393,7 +399,8 @@ define([ 'id': obj.name, 'class': 'vp-select var-multi vp-state', // multiple selection true - 'multiple': true + 'multiple': true, + 'title': (obj.help==undefined?'':obj.help), }); vp_generateVarSelect(tag, obj.var_type, obj.value); content = tag; @@ -402,10 +409,28 @@ define([ var tag = $('').attr({ 'type': 'text', 'id': obj.name, - 'class': 'vp-input vp-state' + 'class': 'vp-input vp-state', + 'title': (obj.help==undefined?'':obj.help), }); content = tag; break; + case 'col_multi': + var tag1 = $('
').attr({ + 'id': obj.name + '_auto_comp', + 'class': 'vp-auto-multi-column', + 'data-id': obj.name, + 'data-target': obj.comp_target || 'i0', + 'style': 'height: 150px;', + 'title': (obj.help==undefined?'':obj.help), + }); + var tag2 = $('').attr({ + type: 'hidden', + id: obj.name, + class: 'vp-input vp-state', + }) + var tag = $('
').append(tag1).append(tag2); + content = tag; + break; case 'textarea': var textarea = $(``); // cell metadata test @@ -710,6 +735,12 @@ define([ case 'dtype': value = $(pageThis.wrapSelector(parent + ' #'+obj.name)).val(); break; + case 'col_multi': + let colList = pageThis.autoGen[obj.name].getDataList(); + pageThis.state[obj.name] = colList.map(data => { return data.code }); + value = colList.map(data => { return data.code }).join(','); + $(pageThis.wrapSelector('#'+obj.name)).val(value); + break; case 'file-open': case 'file-save': case 'table': @@ -1236,6 +1267,50 @@ define([ return $(''); } + var bindMultiSelector = function(pageThis) { + //==================================================================== + // for column multi selector + //==================================================================== + $(pageThis.wrapSelector('.vp-auto-multi-column')).each((idx, tag) => { + let compId = tag.id; + let id = $(tag).data('id'); + let targetId = $(tag).data('target'); + let colSelector = new MultiSelector( + pageThis.wrapSelector('#' + compId), + { mode: 'columns', parent: (pageThis.state[targetId] || ''), selectedList: pageThis.state[compId] } + ); + pageThis.autoGen = { + [id]: colSelector, + ...pageThis.autoGen + }; + $(pageThis.wrapSelector('#' + targetId)).on('change', function() { + let targetVariable = $(this).val(); + let colSelector = new MultiSelector( + pageThis.wrapSelector('#' + compId), + { + mode: 'columns', parent: targetVariable, selectedList: pageThis.state[compId], + change: function(type, list) { + let value = list.map(data => { return data.code }).join(','); + if (list.length == 0) { + value = ''; + } else if (list.length > 1) { + value = '[' + value + ']'; + } + pageThis.state[compId] = list.map(data => { return data.code }); + pageThis.state[id] = value; + $(pageThis.wrapSelector('#'+id)).val(value); + } + }, + ); + pageThis.autoGen = { + [id]: colSelector, + ...pageThis.autoGen + }; + }); + + }); + } + var bindAutoComponentEvent = function(pageThis) { let selector = pageThis.wrapSelector(); // Auto-component selector @@ -1499,7 +1574,6 @@ define([ $(pageThis.wrapSelector('#'+id)).val(code); }); - //==================================================================== // Event for tabBlock //==================================================================== diff --git a/visualpython/js/com/component/DataSelector.js b/visualpython/js/com/component/DataSelector.js index d6d34108..7439a7e9 100644 --- a/visualpython/js/com/component/DataSelector.js +++ b/visualpython/js/com/component/DataSelector.js @@ -50,7 +50,7 @@ define([ super._init(); this.prop = { - type: 'data', // selector type : data / column + type: 'data', // selector type : data / column / ml pageThis: null, // target's page object id: '', // target id value: null, // pre-defined value @@ -58,6 +58,7 @@ define([ finish: null, // callback after selection (value, dtype) select: null, // callback after selection from suggestInput (value, dtype) allowDataType: null, // list of allowed data types + dataCategory: null, // list of data category (use it for ml categories) // additional options boxClasses: '', classes: '', @@ -71,9 +72,20 @@ define([ // If null, define default allow data type if (!this.prop.allowDataType) { // default allow data types - this.prop.allowDataType = [ - 'DataFrame', 'Series', 'ndarray', 'list', 'dict' - ] + if (this.prop.type === 'ml') { + this.prop.allowDataType = vpConfig.getMLDataTypes(); + } else { + this.prop.allowDataType = [ + 'DataFrame', 'Series', 'ndarray', 'list', 'dict' + ] + } + } + if (!this.prop.dataCategory) { + if (this.prop.type === 'ml') { + this.prop.dataCategory = vpConfig.getMLCategories(); + } else { + this.prop.dataCategory = this.prop.allowDataType; + } } this.state = { @@ -282,7 +294,11 @@ define([ that.renderVariableBox(that._varList.filter(obj => !that.prop.allowDataType.includes(obj.dtype))); } else { // filter variable list - that.renderVariableBox(that._varList.filter(obj => obj.dtype == type)); + if (that.prop.type === 'ml') { + that.renderVariableBox(that._varList.filter(obj => vpConfig.getMLDataDict(type).includes(obj.dtype))); + } else { + that.renderVariableBox(that._varList.filter(obj => obj.dtype == type)); + } } }); @@ -530,7 +546,7 @@ define([ let varTags = new com_String(); let types = [ 'All', - ...this.prop.allowDataType, + ...this.prop.dataCategory, 'Others' ]; // Add Data Types to filter @@ -551,10 +567,17 @@ define([ let that = this; let varTags = new com_String(); varTags = new com_String(); - varList && varList.forEach((obj, idx) => { - varTags.appendFormatLine('
{4}
' - , 'vp-ds-var-item', (that.state.data == obj.value?'selected':''), obj.dtype, obj.dtype, obj.label); - }); + if (this.prop.type === 'ml') { + varList && varList.forEach((obj, idx) => { + varTags.appendFormatLine('
{4} | {5}
' + , 'vp-ds-var-item', (that.state.data == obj.value?'selected':''), obj.dtype, obj.dtype, obj.label, obj.dtype); + }); + } else { + varList && varList.forEach((obj, idx) => { + varTags.appendFormatLine('
{4}
' + , 'vp-ds-var-item', (that.state.data == obj.value?'selected':''), obj.dtype, obj.dtype, obj.label); + }); + } $(this.wrapSelector('.vp-ds-variable-box')).html(varTags.toString()); // focus on selected item diff --git a/visualpython/js/com/component/HelpViewer.js b/visualpython/js/com/component/HelpViewer.js index ac8a8e68..84ccfe44 100644 --- a/visualpython/js/com/component/HelpViewer.js +++ b/visualpython/js/com/component/HelpViewer.js @@ -167,14 +167,18 @@ define([ return sbSelector.toString(); } - open(content, useHelp=true) { + open(content, useHelp=true, importCode='') { this.show(); let that = this; let code = content; if (useHelp === true) { - code = `print(help(${content}))`; + if (importCode !== '') { + code = importCode + '\n' + `print(help(${content}))`; + } else { + code = `print(help(${content}))`; + } } let loadingSpinner = new LoadingSpinner($(this.wrapSelector('.vp-popup-body'))); diff --git a/visualpython/js/com/component/MultiSelector.js b/visualpython/js/com/component/MultiSelector.js index 516365f8..9ec8ae02 100644 --- a/visualpython/js/com/component/MultiSelector.js +++ b/visualpython/js/com/component/MultiSelector.js @@ -90,7 +90,7 @@ define([ var that = this; - if (parent === '') { + if (parent == null || parent === '' || (Array.isArray(parent) && parent.length == 0)) { this._executeCallback([]); return; } diff --git a/visualpython/js/com/component/PackageManager.js b/visualpython/js/com/component/PackageManager.js index 884b76a6..00afe14c 100644 --- a/visualpython/js/com/component/PackageManager.js +++ b/visualpython/js/com/component/PackageManager.js @@ -17,11 +17,12 @@ define([ 'vp_base/js/com/com_util', 'vp_base/js/com/com_Const', 'vp_base/js/com/com_String', + 'vp_base/js/com/com_interface', 'vp_base/js/com/component/SuggestInput', 'vp_base/js/com/component/PopupComponent', 'vp_base/js/com/component/FileNavigation', 'vp_base/js/com/component/LoadingSpinner' -], function(ifHtml, ifCss, com_util, com_Const, com_String, SuggestInput, PopupComponent, FileNavigation, LoadingSpinner) { +], function(ifHtml, ifCss, com_util, com_Const, com_String, com_interface, SuggestInput, PopupComponent, FileNavigation, LoadingSpinner) { /** * PackageManager @@ -51,19 +52,19 @@ define([ 'plotly': { pipName: 'plotly' }, 'wordcloud': { pipName: 'wordcloud' }, 'sklearn': { pipName: 'scikit-learn' }, - 'scikit-posthocs': { pipName: 'scikit-posthocs' }, + 'scikit_posthocs': { pipName: 'scikit-posthocs' }, 'scipy': { pipName: 'scipy' }, 'statsmodels': { pipName: 'statsmodels' }, - 'factor-analyzer': { pipName: 'factor-analyzer' }, + 'factor_analyzer': { pipName: 'factor-analyzer' }, 'pingouin': { pipName: 'pingouin' }, 'category_encoders': { pipName: 'category_encoders' }, 'imblearn': { pipName: 'imblearn' }, 'xgboost': { pipName: 'xgboost' }, 'lightgbm': { pipName: 'lightgbm' }, 'catboost': { pipName: 'catboost' }, - 'auto-sklearn': { pipName: 'auto-sklearn' }, + 'autosklearn': { pipName: 'auto-sklearn' }, 'tpot': { pipName: 'tpot' }, - 'PyMuPDF': { pipName: 'PyMuPDF' }, + 'pymupdf': { pipName: 'pymupdf' }, 'sweetviz': { pipName: 'sweetviz' }, } @@ -75,16 +76,16 @@ define([ 'seaborn': { pipName: 'seaborn' }, 'plotly': { pipName: 'plotly' }, 'sklearn': { pipName: 'scikit-learn' }, - 'scikit-posthocs': { pipName: 'scikit-posthocs' }, + 'scikit_posthocs': { pipName: 'scikit-posthocs' }, 'scipy': { pipName: 'scipy' }, 'statsmodels': { pipName: 'statsmodels' }, - 'factor-analyzer': { pipName: 'factor-analyzer' }, + 'factor_analyzer': { pipName: 'factor-analyzer' }, 'category_encoders': { pipName: 'category_encoders' }, 'imblearn': { pipName: 'imblearn' }, 'xgboost': { pipName: 'xgboost' }, 'lightgbm': { pipName: 'lightgbm' }, 'catboost': { pipName: 'catboost' }, - 'auto-sklearn': { pipName: 'auto-sklearn' }, + 'autosklearn': { pipName: 'auto-sklearn' }, 'sweetviz': { pipName: 'sweetviz' }, } } @@ -197,33 +198,40 @@ define([ if (vpConfig.extensionType === 'lite') { code = com_util.formatString("%pip uninstall {0}", pipName); } + // DEPRECATED: no longer save to block as default // create block and run it - $('#vp_wrapper').trigger({ - type: 'create_option_page', - blockType: 'block', - menuId: 'lgExe_code', - menuState: { taskState: { code: code } }, - afterAction: 'run' - }); + // $('#vp_wrapper').trigger({ + // type: 'create_option_page', + // blockType: 'block', + // menuId: 'lgExe_code', + // menuState: { taskState: { code: code } }, + // afterAction: 'run' + // }); + com_interface.insertCell('code', code, true, 'Package Manager'); + that.loadPackageList(); } else if (menu === 'upgrade') { var pipName = that.packageLib[key].pipName; var code = com_util.formatString("!pip install --upgrade {0}", pipName); if (vpConfig.extensionType === 'lite') { code = com_util.formatString("%pip install {0}", pipName); } + // DEPRECATED: no longer save to block as default // create block and run it - $('#vp_wrapper').trigger({ - type: 'create_option_page', - blockType: 'block', - menuId: 'lgExe_code', - menuState: { taskState: { code: code } }, - afterAction: 'run' - }); + // $('#vp_wrapper').trigger({ + // type: 'create_option_page', + // blockType: 'block', + // menuId: 'lgExe_code', + // menuState: { taskState: { code: code } }, + // afterAction: 'run' + // }); + com_interface.insertCell('code', code, true, 'Package Manager'); + that.loadPackageList(); } else if (menu === 'delete') { $(item).remove(); delete that.packageLib[key]; vpConfig.removeData('packageList', 'vppackman').then(function() { vpConfig.setData({ 'packageList': that.packageLib }, 'vppackman'); + that.loadPackageList(); }); } evt.stopPropagation(); @@ -331,14 +339,19 @@ define([ return false; } } + // DEPRECATED: no longer save to block as default // create block and run it - $('#vp_wrapper').trigger({ - type: 'create_option_page', - blockType: 'block', - menuId: 'lgExe_code', - menuState: { taskState: { code: code } }, - afterAction: 'run' - }); + // $('#vp_wrapper').trigger({ + // type: 'create_option_page', + // blockType: 'block', + // menuId: 'lgExe_code', + // menuState: { taskState: { code: code } }, + // afterAction: 'run' + // }); + com_interface.insertCell('code', code, true, 'Package Manager'); + + // load package list + this.loadPackageList(); break; } diff --git a/visualpython/js/com/component/PopupComponent.js b/visualpython/js/com/component/PopupComponent.js index ff48a5bd..d0d2d5c0 100644 --- a/visualpython/js/com/component/PopupComponent.js +++ b/visualpython/js/com/component/PopupComponent.js @@ -122,8 +122,9 @@ define([ checkModules: [], // module aliases or function names docs: 'https://visual-python.gitbook.io/docs/getting-started/welcome-to-visual-python', helpInfo: { - content: '', // method to show using help() ex) pd.DataFrame - useHelp: true // custom text to show on help viewer + content: '', // method to show using help() ex) pd.DataFrame + useHelp: true, // custom text to show on help viewer + importCode: '' // import code for help }, ...restConfig }; @@ -308,6 +309,22 @@ define([ _bindEvent() { var that = this; + // Popup click / focus event + $(this.wrapSelector()).on('click focus', function(evt) { + // Close on blur + if ($(that.wrapSelector('.vp-popup-button')).find(evt.target).length == 0) { + if (!$(evt.target).hasClass('vp-popup-codeview-box') + && $(that.wrapSelector('.vp-popup-codeview-box')).find(evt.target).length == 0) { + that.closeView('code'); + } + } + if ($(that.wrapSelector('.vp-popup-button')).find(evt.target).length == 0) { + if (!$(evt.target).hasClass('vp-popup-dataview-box') + && $(that.wrapSelector('.vp-popup-dataview-box')).find(evt.target).length == 0) { + that.closeView('data'); + } + } + }); // Close popup event $(this.wrapSelector('.vp-popup-close')).on('click', function(evt) { if (that.getTaskType() === 'task') { @@ -326,10 +343,7 @@ define([ // Toggle operation (minimize) $(this.wrapSelector('.vp-popup-toggle')).on('click', function(evt) { evt.stopPropagation(); - $(that.eventTarget).trigger({ - type: 'close_option_page', - component: that - }); + that.hide(); }); // Maximize operation $(this.wrapSelector('.vp-popup-maximize')).on('click', function(evt) { @@ -514,6 +528,14 @@ define([ } }); + // blur on code, dataview + $(this.wrapSelector('.vp-popup-codeview-box')).on('hide', function() { + that.closeView('code'); + }); + $(this.wrapSelector('.vp-popup-dataview-box')).on('hide', function() { + that.closeView('data'); + }); + // focus on data selector input $(this.wrapSelector('.vp-data-selector')).on('focus', function(evt) { @@ -1025,7 +1047,7 @@ define([ this._bindCodemirror(); - if (targetFrame !== undefined) { + if (targetFrame == undefined) { $(this.eventTarget).trigger({ type: 'focus_option_page', component: this @@ -1047,7 +1069,15 @@ define([ close() { vpLog.display(VP_LOG_TYPE.DEVELOP, 'close popup', this); this.saveState(); - this.hide(); + if (this.getTaskType() === 'task') { + $(this.eventTarget).trigger({ + type: 'remove_option_page', + component: this + }); + } else { + // if it's block, just hide it + this.hide(); + } } save() { @@ -1083,6 +1113,10 @@ define([ blur() { $(this.wrapSelector()).removeClass('vp-focused'); + // blur on its block + if (this.taskItem) { + this.taskItem.blurItem(); + } } show() { @@ -1154,20 +1188,36 @@ define([ setTimeout(function() { that.cmCodeview.refresh(); }, 1); - $(this.wrapSelector('.vp-popup-dataview-box')).hide(); + this.closeView('data'); $(this.wrapSelector('.vp-popup-codeview-box')).show(); } else if (viewType === 'data') { this.renderDataView(); - $(this.wrapSelector('.vp-popup-codeview-box')).hide(); + this.closeView('code'); $(this.wrapSelector('.vp-popup-dataview-box')).show(); } else if (viewType === 'help') { - $(this.wrapSelector('.vp-popup-codeview-box')).hide(); - $(this.wrapSelector('.vp-popup-dataview-box')).hide(); + this.closeView('code'); + this.closeView('data'); this.openHelpView(); } } closeView(viewType) { + if (viewType === 'code') { + // reset codeview + if (this.cmCodeview) { + this.cmCodeview.setValue(''); + this.cmCodeview.save(); + + var that = this; + setTimeout(function() { + that.cmCodeview.refresh(); + }, 1); + } + } else if (viewType === 'data') { + // reset dataview + $(this.wrapSelector('.vp-popup-dataview-box')).html(''); + } + // hide view $(this.wrapSelector('.vp-popup-'+viewType+'view-box')).hide(); } @@ -1178,7 +1228,7 @@ define([ openHelpView() { this.closeHelpView(); this.helpViewer = new HelpViewer(); - this.helpViewer.open(this.config.helpInfo.content, this.config.helpInfo.useHelp); + this.helpViewer.open(this.config.helpInfo.content, this.config.helpInfo.useHelp, this.config.helpInfo.importCode); } /** @@ -1194,11 +1244,13 @@ define([ * Set HelpViewer content * @param {string} content * @param {boolean} useHelp + * @param {string} importCode */ - setHelpContent(content, useHelp=true) { + setHelpContent(content, useHelp=true, importCode='') { this.config.helpInfo = { content: content, - useHelp: useHelp + useHelp: useHelp, + importCode: importCode }; } diff --git a/visualpython/js/m_apps/Frame.js b/visualpython/js/m_apps/Frame.js index d2e27d3f..b2f16431 100644 --- a/visualpython/js/m_apps/Frame.js +++ b/visualpython/js/m_apps/Frame.js @@ -21,8 +21,9 @@ define([ 'vp_base/js/com/component/PopupComponent', 'vp_base/js/com/component/SuggestInput', 'vp_base/js/com/component/DataSelector', + 'vp_base/js/com/component/MultiSelector', 'vp_base/js/m_apps/Subset' -], function(frameHtml, frameCss, com_Const, com_String, com_util, PopupComponent, SuggestInput, DataSelector, Subset) { +], function(frameHtml, frameCss, com_Const, com_String, com_util, PopupComponent, SuggestInput, DataSelector, MultiSelector, Subset) { /** * Frame @@ -1427,6 +1428,7 @@ define([ content.appendLine(''); content.appendFormatLine('', 'vp-inner-popup-stats-method'); + let methodList = [ + 'sum', 'mean', 'median', 'max', 'min', 'std', 'var' + ]; + methodList.forEach(method => { + content.appendFormatLine('', + method, method, method); + }); + content.appendLine(''); + + content.appendLine('
'); + content.appendLine('
'); + + // tab 3. replace content.appendFormatLine(''); - // tab 3. condition + // tab 4. condition // replace page - 2. condition content.appendFormatLine(''); - // tab 4. apply + // tab 5. apply content.appendFormatLine('