diff --git a/Pipfile b/Pipfile index 60af9c6..e61611c 100644 --- a/Pipfile +++ b/Pipfile @@ -18,6 +18,7 @@ pyworkflow = {path = "./pyworkflow",editable = true} djangorestframework = "*" drf-yasg = "*" click = "*" +altair = "~=4.1.0" cli = {path = "./CLI",editable = true} [requires] diff --git a/Pipfile.lock b/Pipfile.lock index 3a19a29..afca2c0 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "dce2012d65e3fe72d898cc6effffb73c3a37eeb894bfe86f1dd216d65352cc13" + "sha256": "4c72a9b43eac720e3134c042fa24b920a44591c05c5280481cb67ac4791c680c" }, "pipfile-spec": 6, "requires": { @@ -16,6 +16,14 @@ ] }, "default": { + "altair": { + "hashes": [ + "sha256:3edd30d4f4bb0a37278b72578e7e60bc72045a8e6704179e2f4738e35bc12931", + "sha256:7748841a1bea8354173d1140bef6d3b58bea21d201f562528e9599ea384feb7f" + ], + "index": "pypi", + "version": "==4.1.0" + }, "asgiref": { "hashes": [ "sha256:8036f90603c54e93521e5777b2b9a39ba1bad05773fcf2d208f0299d1df58ce5", @@ -23,6 +31,13 @@ ], "version": "==3.2.7" }, + "attrs": { + "hashes": [ + "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c", + "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72" + ], + "version": "==19.3.0" + }, "autopep8": { "hashes": [ "sha256:152fd8fe47d02082be86e05001ec23d6f420086db56b17fc883f3f965fb34954" @@ -50,11 +65,11 @@ }, "click": { "hashes": [ - "sha256:8a18b4ea89d8820c5d0c7da8a64b2c324b4dabb695804dbfea19b9be9d88c0cc", - "sha256:e345d143d80bf5ee7534056164e5e112ea5e22716bbb1ce727941f4c8b471b9a" + "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a", + "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc" ], "index": "pypi", - "version": "==7.1.1" + "version": "==7.1.2" }, "coreapi": { "hashes": [ @@ -101,6 +116,13 @@ "index": "pypi", "version": "==1.17.1" }, + "entrypoints": { + "hashes": [ + "sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19", + "sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451" + ], + "version": "==0.3" + }, "idna": { "hashes": [ "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb", @@ -129,6 +151,13 @@ ], "version": "==2.11.2" }, + "jsonschema": { + "hashes": [ + "sha256:4e5b3cf8216f577bee9ce139cbe72eca3ea4f292ec60928ff24758ce626cd163", + "sha256:c8a85b28d377cc7737e46e2d9f2b4f44ee3c0e1deac6bf46ddefc7187d30797a" + ], + "version": "==3.2.0" + }, "markupsafe": { "hashes": [ "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", @@ -244,6 +273,12 @@ ], "version": "==2.4.7" }, + "pyrsistent": { + "hashes": [ + "sha256:28669905fe725965daa16184933676547c5bb40a5153055a8dee2a4bd7933ad3" + ], + "version": "==0.16.0" + }, "python-dateutil": { "hashes": [ "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c", @@ -261,10 +296,10 @@ }, "pytz": { "hashes": [ - "sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d", - "sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be" + "sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed", + "sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048" ], - "version": "==2019.3" + "version": "==2020.1" }, "pyworkflow": { "editable": true, @@ -323,6 +358,12 @@ ], "version": "==0.3.1" }, + "toolz": { + "hashes": [ + "sha256:08fdd5ef7c96480ad11c12d472de21acd32359996f69a5259299b540feba4560" + ], + "version": "==0.10.0" + }, "uritemplate": { "hashes": [ "sha256:07620c3f3f8eed1f12600845892b0e036a2420acf513c53f7de0abd911a5894f", diff --git a/front-end/package-lock.json b/front-end/package-lock.json index 4288ba8..7b30060 100644 --- a/front-end/package-lock.json +++ b/front-end/package-lock.json @@ -1820,6 +1820,11 @@ "@babel/types": "^7.3.0" } }, + "@types/clone": { + "version": "0.1.30", + "resolved": "https://registry.npmjs.org/@types/clone/-/clone-0.1.30.tgz", + "integrity": "sha1-5zZWSMG0ITalnH1QQGN7O1yDthQ=" + }, "@types/color-name": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", @@ -1835,6 +1840,11 @@ "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==" }, + "@types/fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha512-mky/O83TXmGY39P1H9YbUpjV6l6voRYlufqfFCvel8l1phuy8HRjdWc1rrPuN53ITBJlbyMSV6z3niOySO5pgQ==" + }, "@types/glob": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", @@ -2563,6 +2573,11 @@ "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=" }, + "array-flat-polyfill": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-flat-polyfill/-/array-flat-polyfill-1.0.1.tgz", + "integrity": "sha512-hfJmKupmQN0lwi0xG6FQ5U8Rd97RnIERplymOv/qpq8AoNKPPAnxJadjFA23FNWm88wykh9HmpLJUUwUtNU/iw==" + }, "array-flatten": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", @@ -3687,6 +3702,11 @@ "wrap-ansi": "^5.1.0" } }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" + }, "clone-deep": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-0.2.4.tgz", @@ -4381,6 +4401,148 @@ "type": "^1.0.1" } }, + "d3-array": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.4.0.tgz", + "integrity": "sha512-KQ41bAF2BMakf/HdKT865ALd4cgND6VcIztVQZUTt0+BH3RWy6ZYnHghVXf6NFjt2ritLr8H1T8LreAAlfiNcw==" + }, + "d3-color": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.1.tgz", + "integrity": "sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q==" + }, + "d3-delaunay": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-5.2.1.tgz", + "integrity": "sha512-ZZdeJl6cKRyqYVFYK+/meXvWIrAvZsZTD7WSxl4OPXCmuXNgDyACAClAJHD63zL25TA+IJGURUNO7rFseNFCYw==", + "requires": { + "delaunator": "4" + } + }, + "d3-dispatch": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.6.tgz", + "integrity": "sha512-fVjoElzjhCEy+Hbn8KygnmMS7Or0a9sI2UzGwoB7cCtvI1XpVN9GpoYlnb3xt2YV66oXYb1fLJ8GMvP4hdU1RA==" + }, + "d3-dsv": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.2.0.tgz", + "integrity": "sha512-9yVlqvZcSOMhCYzniHE7EVUws7Fa1zgw+/EAV2BxJoG3ME19V6BQFBwI855XQDsxyOuG7NibqRMTtiF/Qup46g==", + "requires": { + "commander": "2", + "iconv-lite": "0.4", + "rw": "1" + } + }, + "d3-force": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-2.0.1.tgz", + "integrity": "sha512-zh73/N6+MElRojiUG7vmn+3vltaKon7iD5vB/7r9nUaBeftXMzRo5IWEG63DLBCto4/8vr9i3m9lwr1OTJNiCg==", + "requires": { + "d3-dispatch": "1", + "d3-quadtree": "1", + "d3-timer": "1" + } + }, + "d3-format": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.4.4.tgz", + "integrity": "sha512-TWks25e7t8/cqctxCmxpUuzZN11QxIA7YrMbram94zMQ0PXjE4LVIMe/f6a4+xxL8HQ3OsAFULOINQi1pE62Aw==" + }, + "d3-geo": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.12.0.tgz", + "integrity": "sha512-NalZVW+6/SpbKcnl+BCO67m8gX+nGeJdo6oGL9H6BRUGUL1e+AtPcP4vE4TwCQ/gl8y5KE7QvBzrLn+HsKIl+w==", + "requires": { + "d3-array": "1" + }, + "dependencies": { + "d3-array": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz", + "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==" + } + } + }, + "d3-geo-projection": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/d3-geo-projection/-/d3-geo-projection-2.9.0.tgz", + "integrity": "sha512-ZULvK/zBn87of5rWAfFMc9mJOipeSo57O+BBitsKIXmU4rTVAnX1kSsJkE0R+TxY8pGNoM1nbyRRE7GYHhdOEQ==", + "requires": { + "commander": "2", + "d3-array": "1", + "d3-geo": "^1.12.0", + "resolve": "^1.1.10" + }, + "dependencies": { + "d3-array": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz", + "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==" + } + } + }, + "d3-hierarchy": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.1.9.tgz", + "integrity": "sha512-j8tPxlqh1srJHAtxfvOUwKNYJkQuBFdM1+JAUfq6xqH5eAqf93L7oG1NVqDa4CpFZNvnNKtCYEUC8KY9yEn9lQ==" + }, + "d3-interpolate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.4.0.tgz", + "integrity": "sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA==", + "requires": { + "d3-color": "1" + } + }, + "d3-path": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", + "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==" + }, + "d3-quadtree": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.7.tgz", + "integrity": "sha512-RKPAeXnkC59IDGD0Wu5mANy0Q2V28L+fNe65pOCXVdVuTJS3WPKaJlFHer32Rbh9gIo9qMuJXio8ra4+YmIymA==" + }, + "d3-scale": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-3.2.1.tgz", + "integrity": "sha512-huz5byJO/6MPpz6Q8d4lg7GgSpTjIZW/l+1MQkzKfu2u8P6hjaXaStOpmyrD6ymKoW87d2QVFCKvSjLwjzx/rA==", + "requires": { + "d3-array": "1.2.0 - 2", + "d3-format": "1", + "d3-interpolate": "^1.2.0", + "d3-time": "1", + "d3-time-format": "2" + } + }, + "d3-shape": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", + "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", + "requires": { + "d3-path": "1" + } + }, + "d3-time": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.1.0.tgz", + "integrity": "sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA==" + }, + "d3-time-format": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.2.3.tgz", + "integrity": "sha512-RAHNnD8+XvC4Zc4d2A56Uw0yJoM7bsvOlJR33bclxq399Rak/b9bhvu/InjxdWhPtkgU53JJcleJTGkNRnN6IA==", + "requires": { + "d3-time": "1" + } + }, + "d3-timer": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.10.tgz", + "integrity": "sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw==" + }, "dagre": { "version": "0.8.5", "resolved": "https://registry.npmjs.org/dagre/-/dagre-0.8.5.tgz", @@ -4565,6 +4727,11 @@ } } }, + "delaunator": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-4.0.1.tgz", + "integrity": "sha512-WNPWi1IRKZfCt/qIDMfERkDp93+iZEmOxN2yy4Jg+Xhv8SLk2UTqqbe1sfiipn0and9QrE914/ihdx82Y/Giag==" + }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -5767,6 +5934,11 @@ } } }, + "fast-json-patch": { + "version": "3.0.0-1", + "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-3.0.0-1.tgz", + "integrity": "sha512-6pdFb07cknxvPzCeLsFHStEy+MysPJPgZQ9LbQ/2O67unQF93SNqfdSqnPPl71YMHX+AD8gbl7iuoGFzHEdDuw==" + }, "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -8383,6 +8555,11 @@ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=" }, + "json-stringify-pretty-compact": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-2.0.0.tgz", + "integrity": "sha512-WRitRfs6BGq4q8gTgOy4ek7iPFXjbra0H3PmDLKm2xnZ+Gh1HUhiKGgCZkSPNULlP7mvfu6FV/mOLhCarspADQ==" + }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -9161,6 +9338,11 @@ "tslib": "^1.10.0" } }, + "node-fetch": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", + "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==" + }, "node-forge": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.0.tgz", @@ -11594,6 +11776,16 @@ "prop-types": "^15.6.2" } }, + "react-vega": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/react-vega/-/react-vega-7.3.0.tgz", + "integrity": "sha512-Gqkc3HKocbHgSYA054dxhI9NdJffqfW1l4rkRzWB809W1GRKfw48K/65fLRO435DBnx3CajgMP/KIEbboTbswA==", + "requires": { + "@types/react": "^16.9.19", + "fast-deep-equal": "^3.1.1", + "vega-embed": "^6.5.1" + } + }, "react-window": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/react-window/-/react-window-1.8.5.tgz", @@ -12083,6 +12275,11 @@ "aproba": "^1.1.1" } }, + "rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q=" + }, "rxjs": { "version": "6.5.5", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.5.tgz", @@ -13415,6 +13612,14 @@ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" }, + "topojson-client": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/topojson-client/-/topojson-client-3.1.0.tgz", + "integrity": "sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw==", + "requires": { + "commander": "2" + } + }, "tough-cookie": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", @@ -13751,6 +13956,512 @@ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" }, + "vega": { + "version": "5.11.1", + "resolved": "https://registry.npmjs.org/vega/-/vega-5.11.1.tgz", + "integrity": "sha512-Ihmaoh52nMO5k6SwUIKl5n1jJKkGPiWNSNPneyq7jHqpIGRvlE6AP5jdWXrtIWumRzEJ1TZqmSfuPOOvF1yq0A==", + "requires": { + "vega-crossfilter": "~4.0.2", + "vega-dataflow": "~5.5.1", + "vega-encode": "~4.6.0", + "vega-event-selector": "~2.0.3", + "vega-expression": "~2.6.4", + "vega-force": "~4.0.4", + "vega-functions": "~5.6.0", + "vega-geo": "~4.3.1", + "vega-hierarchy": "~4.0.5", + "vega-loader": "~4.2.2", + "vega-parser": "~5.14.0", + "vega-projection": "~1.4.1", + "vega-regression": "~1.0.6", + "vega-runtime": "~5.0.3", + "vega-scale": "~6.1.0", + "vega-scenegraph": "~4.7.1", + "vega-statistics": "~1.7.5", + "vega-time": "~1.1.0", + "vega-transforms": "~4.7.2", + "vega-typings": "~0.16.0", + "vega-util": "~1.13.2", + "vega-view": "~5.6.0", + "vega-view-transforms": "~4.5.4", + "vega-voronoi": "~4.1.2", + "vega-wordcloud": "~4.0.5" + } + }, + "vega-canvas": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/vega-canvas/-/vega-canvas-1.2.2.tgz", + "integrity": "sha512-39h8/fZp4kDwSeDGIEoyEiIgtP3mgY3D08InD1Ldm0FntePpSe1tXzC1zcvoLe/+f7Qprl6Jfwux/ksOXvpj2w==" + }, + "vega-crossfilter": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vega-crossfilter/-/vega-crossfilter-4.0.2.tgz", + "integrity": "sha512-wlKpqBEUpDd/Y3aaC1u91lebXR+sS7LElYv2jGDDG5pA+RS8lRo3NmSClKVBM5NcY80IeMywG+0a/ogzVeBrPQ==", + "requires": { + "d3-array": "^2.4.0", + "vega-dataflow": "^5.5.1", + "vega-util": "^1.13.2" + } + }, + "vega-dataflow": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/vega-dataflow/-/vega-dataflow-5.5.1.tgz", + "integrity": "sha512-l8lIopoWl6q8L7TSg5YS2c2uBniPDgf5CuCzLyREbFR5Xp4+ZR/ioV6Ayzwn5+p3DyujyotngNOZ1FrVsrhz5g==", + "requires": { + "vega-loader": "^4.2.2", + "vega-util": "^1.13.2" + } + }, + "vega-embed": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/vega-embed/-/vega-embed-6.7.0.tgz", + "integrity": "sha512-M910tRLCjAh1Elc/+weMx7Q6cL8BMG5w+xIU0d9GQv24L6iBo5LLG4NyIhrXvx1FvrjLRJMTRTqvMmuBST2LJA==", + "requires": { + "fast-json-patch": "^3.0.0-1", + "json-stringify-pretty-compact": "^2.0.0", + "semver": "^7.3.2", + "vega-schema-url-parser": "^1.1.0", + "vega-themes": "^2.8.3", + "vega-tooltip": "^0.22.1" + }, + "dependencies": { + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==" + } + } + }, + "vega-encode": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/vega-encode/-/vega-encode-4.6.0.tgz", + "integrity": "sha512-nXUpjoh3WMg5dPJLAFQd+L4Nx91ZDSctyaOzM6ap5+zAeyGPHulL/gdglBXMfiJvAU5lT4JPhY0riRBvHx6j3A==", + "requires": { + "d3-array": "^2.4.0", + "d3-interpolate": "^1.4.0", + "vega-dataflow": "^5.5.1", + "vega-scale": "^6.1.0", + "vega-util": "^1.13.2" + } + }, + "vega-event-selector": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/vega-event-selector/-/vega-event-selector-2.0.3.tgz", + "integrity": "sha512-rUnAvBSy5tkk+0MELY7qICTgjMNjH/DDNIH603q3GRi+bBRCd4MlJxWrPYBhwZIYpmr6XCe130lZ90/F5SgVfA==" + }, + "vega-expression": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/vega-expression/-/vega-expression-2.6.4.tgz", + "integrity": "sha512-wVpXbvRUUHKAsJIXQmiu4EAA3DvN0uXbGpGR+lg0y9kaFQIiiLzpouioGNgP6slyKmrjrLRty571etvlhsOm7A==", + "requires": { + "vega-util": "^1.13.2" + } + }, + "vega-force": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/vega-force/-/vega-force-4.0.4.tgz", + "integrity": "sha512-ETTezb3lpQIbrk8pdmv4WpoNlChWdIK1Hv5CHL8Q/oOT/lIop/NHnI+JZO4yuzaYv+o3UqNWPcjiY0U5/i51dw==", + "requires": { + "d3-force": "^2.0.1", + "vega-dataflow": "^5.5.1", + "vega-util": "^1.13.2" + } + }, + "vega-functions": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/vega-functions/-/vega-functions-5.6.0.tgz", + "integrity": "sha512-9OHdAohz428LkAK2+CeBjZ6WgsLGGcVsWNFqoTJhEOuBJNliOa9Jq6V+5QfriYEHZBk48ppLPRlYgKibz7dthQ==", + "requires": { + "d3-array": "^2.4.0", + "d3-color": "^1.4.1", + "d3-format": "^1.4.4", + "d3-geo": "^1.12.0", + "d3-time-format": "^2.2.3", + "vega-dataflow": "^5.5.1", + "vega-expression": "^2.6.4", + "vega-scale": "^6.1.0", + "vega-scenegraph": "^4.7.0", + "vega-selections": "^5.1.1", + "vega-statistics": "^1.7.4", + "vega-time": "^1.1.0", + "vega-util": "^1.13.2" + } + }, + "vega-geo": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/vega-geo/-/vega-geo-4.3.1.tgz", + "integrity": "sha512-bQQB6UgFM1NUSKeCMeb3an3cTEGqEj+DV+gE1/zq/5H7/iYJGY2tI/URy+pgBIaxwyhxUSm0QpzU+JXzh2CW8g==", + "requires": { + "d3-array": "^2.4.0", + "d3-color": "^1.4.1", + "d3-geo": "^1.12.0", + "vega-canvas": "^1.2.2", + "vega-dataflow": "^5.5.1", + "vega-projection": "^1.4.1", + "vega-statistics": "^1.7.4", + "vega-util": "^1.13.2" + } + }, + "vega-hierarchy": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/vega-hierarchy/-/vega-hierarchy-4.0.5.tgz", + "integrity": "sha512-MLXbYq0GncfBLtd4A6zTXjE7Nh+dPQAbKyNghSZbHus2hiSjEC2uBECCaCiKidBxDsTcJBISaopSNFGVRFxJuw==", + "requires": { + "d3-hierarchy": "^1.1.9", + "vega-dataflow": "^5.5.1", + "vega-util": "^1.13.2" + } + }, + "vega-lite": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/vega-lite/-/vega-lite-4.11.0.tgz", + "integrity": "sha512-S+sMBlFnRIplwPDEidfkrXm4rj6n8Ep1p6I2gRRCqTD2i8h2rZeLViycKZXMcheA1hRtfGxXOAaHXdb902TwTA==", + "requires": { + "@types/clone": "~0.1.30", + "@types/fast-json-stable-stringify": "^2.0.0", + "array-flat-polyfill": "^1.0.1", + "clone": "~2.1.2", + "fast-deep-equal": "~3.1.1", + "fast-json-stable-stringify": "~2.1.0", + "json-stringify-pretty-compact": "~2.0.0", + "tslib": "~1.11.1", + "vega-event-selector": "~2.0.2", + "vega-expression": "~2.6.3", + "vega-util": "~1.13.1", + "yargs": "~15.3.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "yargs": { + "version": "15.3.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz", + "integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==", + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.1" + } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "vega-loader": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/vega-loader/-/vega-loader-4.2.2.tgz", + "integrity": "sha512-W5/Wd//W0E5b6TM+CQc2Ha7JkGIqXlPqL95H4QKdX8e7urm9OL+fKBvY7YoWld/h1IIbD0z/EnXYzYfWXaNXOA==", + "requires": { + "d3-dsv": "^1.2.0", + "d3-time-format": "^2.2.3", + "node-fetch": "^2.6.0", + "topojson-client": "^3.1.0", + "vega-util": "^1.13.2" + } + }, + "vega-parser": { + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/vega-parser/-/vega-parser-5.14.0.tgz", + "integrity": "sha512-9/327Mju6n38IDmlJX98R/kbIKB10MghmQ41rNvv/0x6aRV+tCPN02bEALf8GR7FnQSxt+CvftSb7RB7Qc6Dfg==", + "requires": { + "vega-dataflow": "^5.5.1", + "vega-event-selector": "^2.0.3", + "vega-expression": "^2.6.4", + "vega-functions": "^5.6.0", + "vega-scale": "^6.1.0", + "vega-util": "^1.13.2" + } + }, + "vega-projection": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/vega-projection/-/vega-projection-1.4.1.tgz", + "integrity": "sha512-6Rfv/6gqhuEjWGoti9YNqCYLWXb3st+bytqIyiYMmTS8nEQLhH8UyOHwbq5eYOCT4Sn7Q4nsLz+i2I5vgIfUAw==", + "requires": { + "d3-geo": "^1.12.0", + "d3-geo-projection": "^2.9.0" + } + }, + "vega-regression": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/vega-regression/-/vega-regression-1.0.6.tgz", + "integrity": "sha512-s4kjsKp23WvDJDHkpIrGNUaLI3/95k6nTURj9RDtM4C6CbUgO2snIaEfki4JfOCnBYtvotwDuZgXKmJInu9hVw==", + "requires": { + "d3-array": "^2.4.0", + "vega-dataflow": "^5.5.1", + "vega-statistics": "^1.7.4", + "vega-util": "^1.13.2" + } + }, + "vega-runtime": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/vega-runtime/-/vega-runtime-5.0.3.tgz", + "integrity": "sha512-VHSM68yR+Bf+fY0hmDsMk4Qu4NH0pcpJXDJ2SDgUJozbTTAgWvLXPYYDVSLFZIyaQ7JFLCdYJdzMZuds5WFPjQ==", + "requires": { + "vega-dataflow": "^5.5.1", + "vega-util": "^1.13.2" + } + }, + "vega-scale": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/vega-scale/-/vega-scale-6.1.0.tgz", + "integrity": "sha512-gpe+5JmVSloj70jJNw2aE1OES6+xERFjorRawk9xfD521AgThoFt1Dgs/afQwy/hz2mUG1t4MkpDKJ/Q3EAmIA==", + "requires": { + "d3-array": "^2.4.0", + "d3-format": "^1.4.4", + "d3-interpolate": "^1.4.0", + "d3-scale": "^3.2.1", + "vega-time": "^1.1.0", + "vega-util": "^1.13.2" + } + }, + "vega-scenegraph": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/vega-scenegraph/-/vega-scenegraph-4.7.1.tgz", + "integrity": "sha512-rO/7GshzgKR8vaPluN2wJqjNAu7EBejWDfGfytG/IJrpJ+z/MzvkeH6+VnCjh7cSFeiIIXzYAoyr2iSLFcWKfQ==", + "requires": { + "d3-path": "^1.0.9", + "d3-shape": "^1.3.7", + "vega-canvas": "^1.2.1", + "vega-loader": "^4.2.2", + "vega-scale": "^6.1.0", + "vega-util": "^1.13.2" + } + }, + "vega-schema-url-parser": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vega-schema-url-parser/-/vega-schema-url-parser-1.1.0.tgz", + "integrity": "sha512-Tc85J2ofMZZOsxiqDM9sbvfsa+Vdo3GwNLjEEsPOsCDeYqsUHKAlc1IpbbhPLZ6jusyM9Lk0e1izF64GGklFDg==" + }, + "vega-selections": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/vega-selections/-/vega-selections-5.1.1.tgz", + "integrity": "sha512-ztZUMfDicuIGJHZimSdVvMGzMvaa37ICzUHHvwxS51OhYv096dzKgoSypjx+tsmR7wnhY7ZL+iQgpT1/O29jlA==", + "requires": { + "vega-expression": "^2.6.4", + "vega-util": "^1.13.2" + } + }, + "vega-statistics": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/vega-statistics/-/vega-statistics-1.7.5.tgz", + "integrity": "sha512-6yj2V8l7rU123RIvXKiXDMC6ZCJOuToeZcqzTv4VZCRBXilVQeYzam9/nhIVROzh+4KtRW1I5oayMQqrHzIIfw==", + "requires": { + "d3-array": "^2.4.0" + } + }, + "vega-themes": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/vega-themes/-/vega-themes-2.8.3.tgz", + "integrity": "sha512-BzV/gC2ZAhnv20qpQVtyQW6CYXAGQKjArSdxky1UB1RnR5WMRzPsC+g8ak4k0txTwqhkvMAlDXUMaBgDMTOhQg==" + }, + "vega-time": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vega-time/-/vega-time-1.1.0.tgz", + "integrity": "sha512-yQ4co3hN0/NiuPWHKm3uCIGMjzYBJFM5glhME8mb5mrrKnBUsany+HL/9a6aU/HBeLDsDPEhna/lFpj1Y5cW8A==", + "requires": { + "d3-array": "^2.4.0", + "d3-time": "^1.1.0", + "d3-time-format": "^2.2.3", + "vega-util": "^1.13.2" + } + }, + "vega-tooltip": { + "version": "0.22.1", + "resolved": "https://registry.npmjs.org/vega-tooltip/-/vega-tooltip-0.22.1.tgz", + "integrity": "sha512-mPmzxwvi6+2ZgbZ/+mNC7XbSu5I6Ckon8zdgUfH9neb+vV7CKlV/FYypMdVN/9iDMFUqGzybYdqNOiSPPIxFEQ==", + "requires": { + "vega-util": "^1.13.1" + } + }, + "vega-transforms": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/vega-transforms/-/vega-transforms-4.7.2.tgz", + "integrity": "sha512-nV1r53Zs1a+zaMcInVZTIXqPdKzlwscVxkYgR8TcXxQ1VpfJreetDTmvCl89STC6GPHlDZqkn7KRGvSoXgyNbA==", + "requires": { + "d3-array": "^2.4.0", + "vega-dataflow": "^5.5.1", + "vega-statistics": "^1.7.4", + "vega-time": "^1.1.0", + "vega-util": "^1.13.2" + } + }, + "vega-typings": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/vega-typings/-/vega-typings-0.16.0.tgz", + "integrity": "sha512-cRvEt2JicJs17eDlL8Dr+Wh55gvtTuyyWiBjp37/ewR8i3tZ9ZZEg7bTS600Z27jX9Ylkc4zINz5FibbrhWvng==", + "requires": { + "vega-util": "^1.13.1" + } + }, + "vega-util": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/vega-util/-/vega-util-1.13.2.tgz", + "integrity": "sha512-cN/VaO8CjPb3ELfQb+IVi5NGoQpYhWSUFfH7K2ibwagO8obZlUFa9ze8fYiexi2Txf78HFgWm9MXNdV6PROrkw==" + }, + "vega-view": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/vega-view/-/vega-view-5.6.0.tgz", + "integrity": "sha512-/w3R46lw11SXGRwuhZTvhDtQCPBPf21Svh1wiEjQ/f6M1DMhJySaPhdVdh9kIAucYAQtlrBJe1U82PG9j2wAdQ==", + "requires": { + "d3-array": "^2.4.0", + "d3-timer": "^1.0.10", + "vega-dataflow": "^5.5.1", + "vega-functions": "^5.6.0", + "vega-runtime": "^5.0.3", + "vega-scenegraph": "^4.7.0", + "vega-util": "^1.13.2" + } + }, + "vega-view-transforms": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/vega-view-transforms/-/vega-view-transforms-4.5.4.tgz", + "integrity": "sha512-sO7a160cEWjNTLACZVGIxnRcxC2suTOn6mxbKIVtk62Ce/Z93qITdwq05IsZ7JLDVQ9G+Az9rU5Se2Je4mxGwA==", + "requires": { + "vega-dataflow": "^5.5.1", + "vega-scenegraph": "^4.7.0", + "vega-util": "^1.13.2" + } + }, + "vega-voronoi": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/vega-voronoi/-/vega-voronoi-4.1.2.tgz", + "integrity": "sha512-XXp2UChi4/6jkEqWkLFbjDBVLMizQICWDv4RUkfMeDNhWmhEY/3kPHCU6taqfTVkbxfA7aN20ivbakJzoywiAQ==", + "requires": { + "d3-delaunay": "^5.2.1", + "vega-dataflow": "^5.5.1", + "vega-util": "^1.13.2" + } + }, + "vega-wordcloud": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/vega-wordcloud/-/vega-wordcloud-4.0.5.tgz", + "integrity": "sha512-k+EvuJuoxdfuHYiHdpj4AWi7T3gQO0M7p4NFLHjq6oOEzFBmivnvjfGGXoFZmh4uooF2djAVxtmCeuzUxG3qJg==", + "requires": { + "vega-canvas": "^1.2.1", + "vega-dataflow": "^5.5.1", + "vega-scale": "^6.1.0", + "vega-statistics": "^1.7.4", + "vega-util": "^1.13.2" + } + }, "vendors": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.4.tgz", diff --git a/front-end/package.json b/front-end/package.json index c5a94d7..5cd81a3 100644 --- a/front-end/package.json +++ b/front-end/package.json @@ -23,9 +23,12 @@ "react-dom": "^16.13.0", "react-scripts": "3.4.1", "react-spinners-css": "^1.1.7", + "react-vega": "^7.3.0", "react-window": "^1.8.5", "regenerator-runtime": "^0.13.5", - "resize-observer-polyfill": "^1.5.1" + "resize-observer-polyfill": "^1.5.1", + "vega": "^5.11.1", + "vega-lite": "^4.11.0" }, "scripts": { "start": "react-scripts start", diff --git a/front-end/src/components/CustomNode/GraphView.js b/front-end/src/components/CustomNode/GraphView.js index f299792..e872a86 100644 --- a/front-end/src/components/CustomNode/GraphView.js +++ b/front-end/src/components/CustomNode/GraphView.js @@ -1,4 +1,5 @@ import React from 'react'; +import { VegaLite } from 'react-vega'; import { Roller } from 'react-spinners-css'; import { Modal, Button } from 'react-bootstrap'; import propTypes from 'prop-types'; @@ -87,6 +88,19 @@ export default class GraphView extends React.Component { .catch(err => console.error(err)); }; + loadGraph = async () => { + this.setState({loading: true}); + API.retrieveData(this.key_id) + .then(json => { + this.setState({ + data: json, + loading: false, + }); + }) + .catch(err => console.log(err)); + + }; + Cell = ({ columnIndex, rowIndex, style }) => { const className = (rowIndex % 2 === 0) ? 'GridItemEven' : 'GridItemOdd'; const column = this.state.columns[columnIndex]; @@ -107,36 +121,58 @@ export default class GraphView extends React.Component { // Print loading spinner body = (); } else if (this.state.data.length < 1) { - // Print instructions about loading - body = "Loading the data might take a while depending on how big the data is."; - footer = ( - - - - - ); + // Print message to load respective table/graph + if (this.props.node.options.node_type === "visualization") { + // Print instructions about loading + body = "Loading the graph might take a while depending on how big the data is."; + footer = ( + + + + + ); + } else { + // Print instructions about loading + body = "Loading the data might take a while depending on how big the data is."; + footer = ( + + + + + ); + } } else { - // Display the grid - let displayHeight = this.state.rows.length * 20; - let displayWidth = this.state.maxWidth; - - body = ( - this.columnWidths(index)} - height={displayHeight < 600 ? displayHeight + 5 : 600} - rowCount={this.state.rows.length} - rowHeight={index => 20} - width={displayWidth < 900 ? displayWidth : 900} - > - {this.Cell} - - ); + // Display the visualization + if (this.props.node.options.node_type === "visualization") { + // Display the graph + body = (); + } else { + // Display the grid + let displayHeight = this.state.rows.length * 20; + let displayWidth = this.state.maxWidth; + + body = ( + this.columnWidths(index)} + height={displayHeight < 600 ? displayHeight + 5 : 600} + rowCount={this.state.rows.length} + rowHeight={index => 20} + width={displayWidth < 900 ? displayWidth : 900} + > + {this.Cell} + + ); + } + } return ( diff --git a/front-end/src/components/CustomNode/NodeConfig.js b/front-end/src/components/CustomNode/NodeConfig.js index a12181a..1bbc41c 100644 --- a/front-end/src/components/CustomNode/NodeConfig.js +++ b/front-end/src/components/CustomNode/NodeConfig.js @@ -101,10 +101,14 @@ function OptionInput(props) { inputComp = } else if (props.type === "string") { inputComp = + } else if (props.type === "text") { + inputComp = } else if (props.type === "int") { inputComp = } else if (props.type === "boolean") { inputComp = + } else if (props.type === "select") { + inputComp = } else { return (<>) } @@ -199,11 +203,20 @@ function SimpleInput(props) { }, [value, keyName, onChange, type]); - return ( - - ) + if (props.type === "textarea") { + return ( + + ) + + } else { + return ( + + ) + } } @@ -227,3 +240,29 @@ function BooleanInput(props) { onChange={handleChange} /> ) } + + +function SelectInput(props) { + + const [value, setValue] = useState(props.value); + const handleChange = (event) => { + setValue(event.target.value); + }; + + const {keyName, onChange} = props; + // whenever value changes, fire callback to update config form + useEffect(() => { + onChange(keyName, value); + }, + [value, keyName, onChange]); + + return ( + + {props.options.map(opt => + + )} + + ) +} diff --git a/pyworkflow/pyworkflow/node.py b/pyworkflow/pyworkflow/node.py index c59c521..8ccc6ec 100644 --- a/pyworkflow/pyworkflow/node.py +++ b/pyworkflow/pyworkflow/node.py @@ -132,6 +132,14 @@ def execute(self, predecessor_data, flow_vars): raise NotImplementedError() +class VizNode(Node): + """VizNodes deal with graphical display of data.""" + color = "red" + + def execute(self, predecessor_data, flow_vars): + raise NotImplementedError() + + class NodeException(Exception): def __init__(self, action: str, reason: str): self.action = action diff --git a/pyworkflow/pyworkflow/node_factory.py b/pyworkflow/pyworkflow/node_factory.py index 4db6845..ecf1a8a 100644 --- a/pyworkflow/pyworkflow/node_factory.py +++ b/pyworkflow/pyworkflow/node_factory.py @@ -14,6 +14,8 @@ def node_factory(node_info): new_node = manipulation_node(node_key, node_info) elif node_type == 'flow_control': new_node = flow_node(node_key, node_info) + elif node_type == 'visualization': + new_node = visualization_node(node_key, node_info) else: new_node = custom_node(node_key, node_info) @@ -49,6 +51,13 @@ def manipulation_node(node_key, node_info): return None +def visualization_node(node_key, node_info): + if node_key == 'GraphNode': + return GraphNode(node_info) + else: + return None + + def custom_node(node_key, node_info): try: filename = node_info.get('filename') diff --git a/pyworkflow/pyworkflow/nodes/__init__.py b/pyworkflow/pyworkflow/nodes/__init__.py index 31d80d9..23853aa 100644 --- a/pyworkflow/pyworkflow/nodes/__init__.py +++ b/pyworkflow/pyworkflow/nodes/__init__.py @@ -1,3 +1,4 @@ +from .flow_control import * from .io import * from .manipulation import * -from .flow_control import * +from .visualization import * diff --git a/pyworkflow/pyworkflow/nodes/custom_nodes/table_creator.py b/pyworkflow/pyworkflow/nodes/custom_nodes/table_creator.py new file mode 100644 index 0000000..a10634c --- /dev/null +++ b/pyworkflow/pyworkflow/nodes/custom_nodes/table_creator.py @@ -0,0 +1,48 @@ +from pyworkflow.node import IONode, NodeException +from pyworkflow.parameters import * + +import pandas as pd +import io + + +class TableCreatorNode(IONode): + """Accepts raw-text CSV input to create data tables. + + Raises: + NodeException: any error reading CSV file, converting + to DataFrame. + """ + name = "Table Creator" + num_in = 0 + num_out = 1 + + OPTIONS = { + "input": TextParameter( + "Input", + default="", + docstring="Text input" + ), + "sep": StringParameter( + "Delimiter", + default=",", + docstring="Column delimiter" + ), + # user-specified headers are probably integers, but haven't figured out + # arguments with multiple possible types + "header": StringParameter( + "Header Row", + default="infer", + docstring="Row number containing column names (0-indexed)" + ), + } + + def execute(self, predecessor_data, flow_vars): + try: + df = pd.read_csv( + io.StringIO(flow_vars["input"].get_value()), + sep=flow_vars["sep"].get_value(), + header=flow_vars["header"].get_value() + ) + return df.to_json() + except Exception as e: + raise NodeException('read csv', str(e)) diff --git a/pyworkflow/pyworkflow/nodes/visualization/__init__.py b/pyworkflow/pyworkflow/nodes/visualization/__init__.py new file mode 100644 index 0000000..ab0c8d6 --- /dev/null +++ b/pyworkflow/pyworkflow/nodes/visualization/__init__.py @@ -0,0 +1 @@ +from .graph import GraphNode diff --git a/pyworkflow/pyworkflow/nodes/visualization/graph.py b/pyworkflow/pyworkflow/nodes/visualization/graph.py new file mode 100644 index 0000000..eb922a3 --- /dev/null +++ b/pyworkflow/pyworkflow/nodes/visualization/graph.py @@ -0,0 +1,94 @@ +from pyworkflow.node import VizNode, NodeException +from pyworkflow.parameters import * + +import pandas as pd +import altair as alt + + +class GraphNode(VizNode): + """Displays a pandas DataFrame in a visual graph. + + Raises: + NodeException: any error generating Altair Chart. + """ + name = "Graph Node" + num_in = 1 + num_out = 0 + + OPTIONS = { + "graph_type": SelectParameter( + "Graph Type", + options=["area", "bar", "line", "point"], + default="bar", + docstring="Graph viz type" + ), + "mark_options": BooleanParameter( + "Specify mark options", + default=False, + docstring="Specify mark options" + ), + "width": IntegerParameter( + "Mark width", + default=10, + docstring="Width of marks" + ), + "height": IntegerParameter( + "Mark height", + default=10, + docstring="Height of marks" + ), + "encode_options": BooleanParameter( + "Specify encoding options", + default=True, + docstring="Specify encoding options" + ), + "x_axis": StringParameter( + "X-Axis", + default="a", + docstring="X-axis values" + ), + "y_axis": StringParameter( + "Y-Axis", + default="average(b)", + docstring="Y-axis values" + ) + } + + def execute(self, predecessor_data, flow_vars): + try: + df = pd.DataFrame.from_dict(predecessor_data[0]) + + if flow_vars["mark_options"].get_value(): + mark_options = { + "height": flow_vars["height"].get_value(), + "width": flow_vars["width"].get_value(), + } + else: + mark_options = {} + + if flow_vars["encode_options"].get_value(): + encode_options = { + "x": flow_vars["x_axis"].get_value(), + "y": flow_vars["y_axis"].get_value(), + } + else: + encode_options = {} + + graph_type = flow_vars["graph_type"].get_value() + + # Generate requested chart with options + if graph_type == "area": + chart = alt.Chart(df).mark_area(**mark_options).encode(**encode_options) + elif graph_type == "bar": + chart = alt.Chart(df).mark_bar(**mark_options).encode(**encode_options) + elif graph_type == "line": + chart = alt.Chart(df).mark_line(**mark_options).encode(**encode_options) + elif graph_type == "point": + chart = alt.Chart(df).mark_point(**mark_options).encode(**encode_options) + else: + chart = None + + return chart.to_json() + except Exception as e: + print(e) + raise NodeException('graph node', str(e)) diff --git a/pyworkflow/pyworkflow/parameters.py b/pyworkflow/pyworkflow/parameters.py index 8e67c73..364eb30 100644 --- a/pyworkflow/pyworkflow/parameters.py +++ b/pyworkflow/pyworkflow/parameters.py @@ -101,6 +101,15 @@ def validate(self): raise ParameterValidationError(self) +class TextParameter(Parameter): + type = "text" + + def validate(self): + value = self.get_value() + if not isinstance(value, str): + raise ParameterValidationError(self) + + class IntegerParameter(Parameter): type = "int" @@ -119,6 +128,24 @@ def validate(self): raise ParameterValidationError(self) +class SelectParameter(Parameter): + type = "select" + + def __init__(self, label="", options=None, default=None, docstring=None): + super().__init__(label, default, docstring) + self.options = options or [] + + def to_json(self): + out = super().to_json() + out["options"] = self.options + return out + + def validate(self): + value = self.get_value() + if not isinstance(value, str): + raise ParameterValidationError(self) + + class ParameterValidationError(Exception): def __init__(self, parameter): diff --git a/pyworkflow/pyworkflow/tests/test_workflow.py b/pyworkflow/pyworkflow/tests/test_workflow.py index 098f151..18a755a 100644 --- a/pyworkflow/pyworkflow/tests/test_workflow.py +++ b/pyworkflow/pyworkflow/tests/test_workflow.py @@ -46,7 +46,7 @@ def test_workflow_filename(self): ########################## def test_workflow_packaged_nodes(self): nodes = self.workflow.get_packaged_nodes() - self.assertEqual(len(nodes), 4) + self.assertEqual(len(nodes), 5) def test_get_flow_variables(self): flow_var_options = self.workflow.get_all_flow_var_options("1")