diff --git a/env.d.ts b/env.d.ts index c1321fe6fef0779b5ceac3f592597fd8bd27f19c..e955ccfb3b567884184daede71782b4770d72ad9 100644 --- a/env.d.ts +++ b/env.d.ts @@ -1,6 +1 @@ -declare module '@metabohub/viz-core'; -declare module 'dagrejs'; -declare module '@metabohub/viz-context-menu'; declare module 'line-intersect'; -// declare module 'dagrejs/dist/dagre.js'; -// declare module 'cytoscape'; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 6b1f97e7c1506dd17b54de46c40169fe76f6d51b..e720393f253a2addf25b10b924ff93142c586526 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,13 +10,9 @@ "license": "Apache-2.0", "dependencies": { "@mdi/font": "^7.4.47", - "@metabohub/viz-context-menu": "^0.0.2", - "@metabohub/viz-core": "^0.6.1", "@types/d3": "^7.4.3", - "cytoscape": "^3.30.2", "d3": "^7.9.0", - "line-intersect": "^3.0.0", - "xml2js": "^0.6.2" + "line-intersect": "^3.0.0" }, "devDependencies": { "@eslint/js": "^9.10.0", @@ -24,12 +20,7 @@ "@types/jest": "^29.5.12", "@types/jsdom": "^21.1.6", "@types/node": "^20.11.14", - "@types/xml2js": "^0.4.14", "@viz-js/viz": "^3.4.0", - "cytoscape": "^3.30.2", - "cytoscape-cose-bilkent": "^3.0.0", - "cytoscape-fcose": "^2.2.0", - "dagrejs": "^0.2.1", "eslint": "^9.10.0", "graph-data-structure": "^3.5.0", "jest": "^29.7.0", @@ -205,6 +196,7 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "dev": true, "engines": { "node": ">=6.9.0" } @@ -213,6 +205,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "dev": true, "engines": { "node": ">=6.9.0" } @@ -330,6 +323,7 @@ "version": "7.25.6", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.6.tgz", "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", + "dev": true, "dependencies": { "@babel/types": "^7.25.6" }, @@ -553,6 +547,7 @@ "version": "7.25.6", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz", "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", + "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.24.8", "@babel/helper-validator-identifier": "^7.24.7", @@ -1569,7 +1564,7 @@ "version": "0.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "devOptional": true, + "dev": true, "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -1583,7 +1578,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "devOptional": true, + "dev": true, "engines": { "node": ">=6.0.0" } @@ -1592,32 +1587,22 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "devOptional": true, + "dev": true, "engines": { "node": ">=6.0.0" } }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", - "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", - "optional": true, - "peer": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "devOptional": true, + "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -1628,30 +1613,6 @@ "resolved": "https://registry.npmjs.org/@mdi/font/-/font-7.4.47.tgz", "integrity": "sha512-43MtGpd585SNzHZPcYowu/84Vz2a2g31TvPMTm9uTiCSWzaheQySUcSyUH/46fPnuPQWof2yd0pGBtzee/IQWw==" }, - "node_modules/@metabohub/viz-context-menu": { - "version": "0.0.2", - "resolved": "https://forgemia.inra.fr/api/v4/projects/11129/packages/npm/@metabohub/viz-context-menu/-/@metabohub/viz-context-menu-0.0.2.tgz", - "integrity": "sha1-851aHxYa7Y9LimYhpJEgXdatdkQ=", - "dependencies": { - "@mdi/font": "^7.4.47", - "roboto-fontface": "*", - "vue": "^3.4.15", - "vuetify": "^3.5.2", - "webfontloader": "^1.6.28" - } - }, - "node_modules/@metabohub/viz-core": { - "version": "0.6.1", - "resolved": "https://forgemia.inra.fr/api/v4/projects/8209/packages/npm/@metabohub/viz-core/-/@metabohub/viz-core-0.6.1.tgz", - "integrity": "sha1-OtkeLt1AEBpOMOIT8gszu3tftyQ=", - "dependencies": { - "@vueuse/core": "^10.7.0", - "d3": "^7.8.5", - "lodash-es": "^4.17.21", - "uuid": "^9.0.1", - "vue": "^3.3.4" - } - }, "node_modules/@microsoft/api-extractor": { "version": "7.43.0", "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.43.0.tgz", @@ -2578,7 +2539,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "devOptional": true + "dev": true }, "node_modules/@types/geojson": { "version": "7946.0.14", @@ -2649,7 +2610,7 @@ "version": "20.12.12", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz", "integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==", - "devOptional": true, + "dev": true, "dependencies": { "undici-types": "~5.26.4" } @@ -2666,20 +2627,6 @@ "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", "dev": true }, - "node_modules/@types/web-bluetooth": { - "version": "0.0.20", - "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz", - "integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==" - }, - "node_modules/@types/xml2js": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/@types/xml2js/-/xml2js-0.4.14.tgz", - "integrity": "sha512-4YnrRemBShWRO2QjvUin8ESA41rH+9nQGLUGZV/1IDhi3SL9OhdpNC/MrulTWuptXKwhx/aDxE7toV0f/ypIXQ==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/yargs": { "version": "17.0.32", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", @@ -2907,209 +2854,11 @@ "integrity": "sha512-xbqbRanQCG06yfpnv2hsgX43G26q0JCSjcYSpvmUlx1VRCzA0ngi7zsPn0jW9K2ITchpjQiC1tyO6+zFgS/IyA==", "dev": true }, - "node_modules/@vue/compiler-core": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.4.tgz", - "integrity": "sha512-oNwn+BAt3n9dK9uAYvI+XGlutwuTq/wfj4xCBaZCqwwVIGtD7D6ViihEbyYZrDHIHTDE3Q6oL3/hqmAyFEy9DQ==", - "dependencies": { - "@babel/parser": "^7.25.3", - "@vue/shared": "3.5.4", - "entities": "^4.5.0", - "estree-walker": "^2.0.2", - "source-map-js": "^1.2.0" - } - }, - "node_modules/@vue/compiler-core/node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" - }, - "node_modules/@vue/compiler-dom": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.4.tgz", - "integrity": "sha512-yP9RRs4BDLOLfldn6ah+AGCNovGjMbL9uHvhDHf5wan4dAHLnFGOkqtfE7PPe4HTXIqE7l/NILdYw53bo1C8jw==", - "dependencies": { - "@vue/compiler-core": "3.5.4", - "@vue/shared": "3.5.4" - } - }, - "node_modules/@vue/compiler-sfc": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.4.tgz", - "integrity": "sha512-P+yiPhL+NYH7m0ZgCq7AQR2q7OIE+mpAEgtkqEeH9oHSdIRvUO+4X6MPvblJIWcoe4YC5a2Gdf/RsoyP8FFiPQ==", - "dependencies": { - "@babel/parser": "^7.25.3", - "@vue/compiler-core": "3.5.4", - "@vue/compiler-dom": "3.5.4", - "@vue/compiler-ssr": "3.5.4", - "@vue/shared": "3.5.4", - "estree-walker": "^2.0.2", - "magic-string": "^0.30.11", - "postcss": "^8.4.44", - "source-map-js": "^1.2.0" - } - }, - "node_modules/@vue/compiler-sfc/node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" - }, - "node_modules/@vue/compiler-ssr": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.4.tgz", - "integrity": "sha512-acESdTXsxPnYr2C4Blv0ggx5zIFMgOzZmYU2UgvIff9POdRGbRNBHRyzHAnizcItvpgerSKQbllUc9USp3V7eg==", - "dependencies": { - "@vue/compiler-dom": "3.5.4", - "@vue/shared": "3.5.4" - } - }, - "node_modules/@vue/reactivity": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.4.tgz", - "integrity": "sha512-HKKbEuP7tYSGCq4e4nK6ZW6l5hyG66OUetefBp4budUyjvAYsnQDf+bgFzg2RAgnH0CInyqXwD9y47jwJEHrQw==", - "dependencies": { - "@vue/shared": "3.5.4" - } - }, - "node_modules/@vue/runtime-core": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.4.tgz", - "integrity": "sha512-f3ek2sTA0AFu0n+w+kCtz567Euqqa3eHewvo4klwS7mWfSj/A+UmYTwsnUFo35KeyAFY60JgrCGvEBsu1n/3LA==", - "dependencies": { - "@vue/reactivity": "3.5.4", - "@vue/shared": "3.5.4" - } - }, - "node_modules/@vue/runtime-dom": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.4.tgz", - "integrity": "sha512-ofyc0w6rbD5KtjhP1i9hGOKdxGpvmuB1jprP7Djlj0X7R5J/oLwuNuE98GJ8WW31Hu2VxQHtk/LYTAlW8xrJdw==", - "dependencies": { - "@vue/reactivity": "3.5.4", - "@vue/runtime-core": "3.5.4", - "@vue/shared": "3.5.4", - "csstype": "^3.1.3" - } - }, - "node_modules/@vue/server-renderer": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.4.tgz", - "integrity": "sha512-FbjV6DJLgKRetMYFBA1UXCroCiED/Ckr53/ba9wivyd7D/Xw9fpo0T6zXzCnxQwyvkyrL7y6plgYhWhNjGxY5g==", - "dependencies": { - "@vue/compiler-ssr": "3.5.4", - "@vue/shared": "3.5.4" - }, - "peerDependencies": { - "vue": "3.5.4" - } - }, - "node_modules/@vue/shared": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.4.tgz", - "integrity": "sha512-L2MCDD8l7yC62Te5UUyPVpmexhL9ipVnYRw9CsWfm/BGRL5FwDX4a25bcJ/OJSD3+Hx+k/a8LDKcG2AFdJV3BA==" - }, - "node_modules/@vuetify/loader-shared": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@vuetify/loader-shared/-/loader-shared-2.0.3.tgz", - "integrity": "sha512-Ss3GC7eJYkp2SF6xVzsT7FAruEmdihmn4OCk2+UocREerlXKWgOKKzTN5PN3ZVN5q05jHHrsNhTuWbhN61Bpdg==", - "optional": true, - "peer": true, - "dependencies": { - "upath": "^2.0.1" - }, - "peerDependencies": { - "vue": "^3.0.0", - "vuetify": "^3.0.0" - } - }, - "node_modules/@vueuse/core": { - "version": "10.11.1", - "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.11.1.tgz", - "integrity": "sha512-guoy26JQktXPcz+0n3GukWIy/JDNKti9v6VEMu6kV2sYBsWuGiTU8OWdg+ADfUbHg3/3DlqySDe7JmdHrktiww==", - "dependencies": { - "@types/web-bluetooth": "^0.0.20", - "@vueuse/metadata": "10.11.1", - "@vueuse/shared": "10.11.1", - "vue-demi": ">=0.14.8" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/@vueuse/core/node_modules/vue-demi": { - "version": "0.14.10", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", - "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", - "hasInstallScript": true, - "bin": { - "vue-demi-fix": "bin/vue-demi-fix.js", - "vue-demi-switch": "bin/vue-demi-switch.js" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "@vue/composition-api": "^1.0.0-rc.1", - "vue": "^3.0.0-0 || ^2.6.0" - }, - "peerDependenciesMeta": { - "@vue/composition-api": { - "optional": true - } - } - }, - "node_modules/@vueuse/metadata": { - "version": "10.11.1", - "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.11.1.tgz", - "integrity": "sha512-IGa5FXd003Ug1qAZmyE8wF3sJ81xGLSqTqtQ6jaVfkeZ4i5kS2mwQF61yhVqojRnenVew5PldLyRgvdl4YYuSw==", - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/@vueuse/shared": { - "version": "10.11.1", - "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.11.1.tgz", - "integrity": "sha512-LHpC8711VFZlDaYUXEBbFBCQ7GS3dVU9mjOhhMhXP6txTV4EhYQg/KGnQuvt/sPAtoUKq7VVUnL6mVtFoL42sA==", - "dependencies": { - "vue-demi": ">=0.14.8" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/@vueuse/shared/node_modules/vue-demi": { - "version": "0.14.10", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", - "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", - "hasInstallScript": true, - "bin": { - "vue-demi-fix": "bin/vue-demi-fix.js", - "vue-demi-switch": "bin/vue-demi-switch.js" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "@vue/composition-api": "^1.0.0-rc.1", - "vue": "^3.0.0-0 || ^2.6.0" - }, - "peerDependenciesMeta": { - "@vue/composition-api": { - "optional": true - } - } - }, "node_modules/acorn": { "version": "8.12.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", - "devOptional": true, + "dev": true, "bin": { "acorn": "bin/acorn" }, @@ -3454,7 +3203,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "devOptional": true + "dev": true }, "node_modules/bundle-require": { "version": "4.1.0", @@ -3757,15 +3506,6 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true }, - "node_modules/cose-base": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-2.2.0.tgz", - "integrity": "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==", - "dev": true, - "dependencies": { - "layout-base": "^2.0.0" - } - }, "node_modules/create-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", @@ -3819,44 +3559,6 @@ "node": ">=18" } }, - "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" - }, - "node_modules/cytoscape": { - "version": "3.30.2", - "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.30.2.tgz", - "integrity": "sha512-oICxQsjW8uSaRmn4UK/jkczKOqTrVqt5/1WL0POiJUT2EKNc9STM4hYFHv917yu55aTBMFNRzymlJhVAiWPCxw==", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/cytoscape-cose-bilkent": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-3.0.4.tgz", - "integrity": "sha512-oAh/ga1fxJ7j9bBjjfGRlpTAKVFddYu+HfwJaebLpZTc0LUnnnHe/Ng3aiWj1Ammc301+RDTSXT6ecpIz4dSMQ==", - "dev": true, - "dependencies": { - "linkedlist-js": "1.3.0" - }, - "peerDependencies": { - "cytoscape": "^2.4.0 || ^3.0.0" - } - }, - "node_modules/cytoscape-fcose": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz", - "integrity": "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==", - "dev": true, - "dependencies": { - "cose-base": "^2.2.0" - }, - "peerDependencies": { - "cytoscape": "^3.2.0" - } - }, "node_modules/d3": { "version": "7.9.0", "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz", @@ -4246,16 +3948,6 @@ "node": ">=12" } }, - "node_modules/dagrejs": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/dagrejs/-/dagrejs-0.2.1.tgz", - "integrity": "sha512-4bb1y+4aM1xtkK7ieP0V7Xn/34GQfnCapl0yubrOMX8Qb/PIwM1Dii2uUBv/KtuzrQtxPliSP4r5MQBsnP6gNg==", - "dev": true, - "dependencies": { - "graphlib": "^2.1.8", - "lodash": "^4.17.19" - } - }, "node_modules/data-urls": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", @@ -4307,7 +3999,7 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "devOptional": true, + "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -4445,6 +4137,7 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, "engines": { "node": ">=0.12" }, @@ -4997,6 +4690,7 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, "hasInstallScript": true, "optional": true, "os": [ @@ -5135,15 +4829,6 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, - "node_modules/graphlib": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz", - "integrity": "sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==", - "dev": true, - "dependencies": { - "lodash": "^4.17.15" - } - }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -6367,12 +6052,6 @@ "node": ">=6" } }, - "node_modules/layout-base": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-2.0.1.tgz", - "integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==", - "dev": true - }, "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -6418,12 +6097,6 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, - "node_modules/linkedlist-js": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/linkedlist-js/-/linkedlist-js-1.3.0.tgz", - "integrity": "sha512-YwgG4Et8dJF04nsn9YuyrydUJvwmJHOQo7PzxvkT09NTgQ1yC+vXHGBolo48rTjAItIYR7YWIXh6xZsavCBSvQ==", - "dev": true - }, "node_modules/load-tsconfig": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/load-tsconfig/-/load-tsconfig-0.2.5.tgz", @@ -6449,12 +6122,9 @@ "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash-es": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", - "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + "dev": true, + "optional": true, + "peer": true }, "node_modules/lodash.get": { "version": "4.4.2", @@ -6499,14 +6169,6 @@ "node": "14 || >=16.14" } }, - "node_modules/magic-string": { - "version": "0.30.11", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", - "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" - } - }, "node_modules/make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", @@ -6635,7 +6297,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "devOptional": true + "dev": true }, "node_modules/mz": { "version": "2.7.0", @@ -6652,12 +6314,15 @@ "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/ai" } ], + "optional": true, + "peer": true, "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -6914,7 +6579,8 @@ "node_modules/picocolors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "dev": true }, "node_modules/picomatch": { "version": "2.3.1", @@ -6953,6 +6619,7 @@ "version": "8.4.45", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.45.tgz", "integrity": "sha512-7KTLTdzdZZYscUc65XmjFiB73vBhBfbPztCYdUNvlaso9PrzjzcmjqBPR0lNGkcVlcO4BjiO5rK/qNz+XAen1Q==", + "dev": true, "funding": [ { "type": "opencollective", @@ -6967,6 +6634,8 @@ "url": "https://github.com/sponsors/ai" } ], + "optional": true, + "peer": true, "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.0.1", @@ -7221,11 +6890,6 @@ "node": ">=0.10.0" } }, - "node_modules/roboto-fontface": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/roboto-fontface/-/roboto-fontface-0.10.0.tgz", - "integrity": "sha512-OlwfYEgA2RdboZohpldlvJ1xngOins5d7ejqnIBWr9KaMxsnBqotpptRXTyfNRLnFpqzX6sTDt+X+a+6udnU8g==" - }, "node_modules/robust-predicates": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", @@ -7235,7 +6899,7 @@ "version": "4.21.2", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.2.tgz", "integrity": "sha512-e3TapAgYf9xjdLvKQCkQTnbTKd4a6jwlpQSJJFokHGaX2IVjoEqkIIhiQfqsi0cdwlOD+tQGuOd5AJkc5RngBw==", - "devOptional": true, + "dev": true, "dependencies": { "@types/estree": "1.0.5" }, @@ -7308,7 +6972,8 @@ "node_modules/sax": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", - "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==" + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", + "dev": true }, "node_modules/saxes": { "version": "6.0.0", @@ -7389,6 +7054,9 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">=0.10.0" } @@ -7653,53 +7321,6 @@ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "dev": true }, - "node_modules/terser": { - "version": "5.32.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.32.0.tgz", - "integrity": "sha512-v3Gtw3IzpBJ0ugkxEX8U0W6+TnPKRRCWGh1jC/iM/e3Ki5+qvO1L1EAZ56bZasc64aXHwRHNIQEzm6//i5cemQ==", - "optional": true, - "peer": true, - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "optional": true, - "peer": true - }, - "node_modules/terser/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "optional": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/terser/node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "optional": true, - "peer": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -7793,6 +7414,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, "engines": { "node": ">=4" } @@ -8053,7 +7675,7 @@ "version": "5.6.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", - "devOptional": true, + "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -8089,18 +7711,7 @@ "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "devOptional": true - }, - "node_modules/upath": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/upath/-/upath-2.0.1.tgz", - "integrity": "sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==", - "optional": true, - "peer": true, - "engines": { - "node": ">=4", - "yarn": "*" - } + "dev": true }, "node_modules/update-browserslist-db": { "version": "1.1.0", @@ -8151,18 +7762,6 @@ "requires-port": "^1.0.0" } }, - "node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -8194,549 +7793,13 @@ "node": ">= 0.10" } }, - "node_modules/vite": { - "version": "5.4.3", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.3.tgz", - "integrity": "sha512-IH+nl64eq9lJjFqU+/yrRnrHPVTlgy42/+IzbOdaFDVlyLgI/wDlf+FCobXLX1cT0X5+7LMyH1mIy2xJdLfo8Q==", - "optional": true, - "peer": true, + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "dev": true, "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - }, - "node_modules/vite-plugin-vuetify": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/vite-plugin-vuetify/-/vite-plugin-vuetify-2.0.4.tgz", - "integrity": "sha512-A4cliYUoP/u4AWSRVRvAPKgpgR987Pss7LpFa7s1GvOe8WjgDq92Rt3eVXrvgxGCWvZsPKziVqfHHdCMqeDhfw==", - "optional": true, - "peer": true, - "dependencies": { - "@vuetify/loader-shared": "^2.0.3", - "debug": "^4.3.3", - "upath": "^2.0.1" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "peerDependencies": { - "vite": ">=5", - "vue": "^3.0.0", - "vuetify": "^3.0.0" - } - }, - "node_modules/vite/node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "cpu": [ - "ppc64" - ], - "optional": true, - "os": [ - "aix" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "android" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "android" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "android" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "freebsd" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "freebsd" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "cpu": [ - "loong64" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "cpu": [ - "mips64el" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "cpu": [ - "ppc64" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "cpu": [ - "riscv64" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "cpu": [ - "s390x" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "netbsd" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "openbsd" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "sunos" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "hasInstallScript": true, - "optional": true, - "peer": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" - } - }, - "node_modules/vue": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.4.tgz", - "integrity": "sha512-3yAj2gkmiY+i7+22A1PWM+kjOVXjU74UPINcTiN7grIVPyFFI0lpGwHlV/4xydDmobaBn7/xmi+YG8HeSlCTcg==", - "dependencies": { - "@vue/compiler-dom": "3.5.4", - "@vue/compiler-sfc": "3.5.4", - "@vue/runtime-dom": "3.5.4", - "@vue/server-renderer": "3.5.4", - "@vue/shared": "3.5.4" - }, - "peerDependencies": { - "typescript": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/vuetify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/vuetify/-/vuetify-3.7.1.tgz", - "integrity": "sha512-N1XlczbgeGt/O+JUk72QPrqcDaRIXUdptUciJqGyTvZ9cfMoSlEWs6TZO+dOOfXbKvmIMFMycYg4dgSHDpCPhg==", - "engines": { - "node": "^12.20 || >=14.13" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/johnleider" - }, - "peerDependencies": { - "typescript": ">=4.7", - "vite-plugin-vuetify": ">=1.0.0", - "vue": "^3.3.0", - "webpack-plugin-vuetify": ">=2.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - }, - "vite-plugin-vuetify": { - "optional": true - }, - "webpack-plugin-vuetify": { - "optional": true - } - } - }, - "node_modules/w3c-xmlserializer": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", - "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", - "dev": true, - "dependencies": { - "xml-name-validator": "^5.0.0" + "xml-name-validator": "^5.0.0" }, "engines": { "node": ">=18" @@ -8760,11 +7823,6 @@ "makeerror": "1.0.12" } }, - "node_modules/webfontloader": { - "version": "1.6.28", - "resolved": "https://registry.npmjs.org/webfontloader/-/webfontloader-1.6.28.tgz", - "integrity": "sha512-Egb0oFEga6f+nSgasH3E0M405Pzn6y3/9tOVanv/DLfa1YBIgcv90L18YyWnvXkRbIM17v5Kv6IT2N6g1x5tvQ==" - }, "node_modules/webidl-conversions": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", @@ -8982,26 +8040,6 @@ "xml-js": "bin/cli.js" } }, - "node_modules/xml2js": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", - "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", - "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", - "engines": { - "node": ">=4.0" - } - }, "node_modules/xmlchars": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", diff --git a/package.json b/package.json index 4e94f435278eac9ab6452f5580adc89887bcb52d..852486561b6b4a7b9542cf5598dc27da704ba42b 100644 --- a/package.json +++ b/package.json @@ -8,13 +8,9 @@ }, "dependencies": { "@mdi/font": "^7.4.47", - "@metabohub/viz-context-menu": "^0.0.2", - "@metabohub/viz-core": "^0.6.1", "@types/d3": "^7.4.3", - "cytoscape": "^3.30.2", "d3": "^7.9.0", - "line-intersect": "^3.0.0", - "xml2js": "^0.6.2" + "line-intersect": "^3.0.0" }, "devDependencies": { "@eslint/js": "^9.10.0", @@ -22,12 +18,7 @@ "@types/jest": "^29.5.12", "@types/jsdom": "^21.1.6", "@types/node": "^20.11.14", - "@types/xml2js": "^0.4.14", "@viz-js/viz": "^3.4.0", - "cytoscape": "^3.30.2", - "cytoscape-cose-bilkent": "^3.0.0", - "cytoscape-fcose": "^2.2.0", - "dagrejs": "^0.2.1", "eslint": "^9.10.0", "graph-data-structure": "^3.5.0", "jest": "^29.7.0", diff --git a/src/composables/AlgorithmDFS.ts b/src/composables/AlgorithmDFS.ts index 04fb29f65fbf0789e4fa3909276a2be0eaf72f6d..1748b83d6ac29af7db9c01cf437a2ac3e511e31b 100644 --- a/src/composables/AlgorithmDFS.ts +++ b/src/composables/AlgorithmDFS.ts @@ -66,18 +66,19 @@ export async function DFSWithSources(network:Network, sources:Array<string>|Star * @param sources to use as staring node for DFS * @returns the reverse dfs order (topological sort) and a graph object without the cycles accessible from the sources */ -export async function DFSsourceDAG(network:Network, sources:Array<string>):Promise<{dfs:Array<string>, graph:{[key:string]:Function} }> { +export async function DFSsourceDAG(network:Network, sources:Array<string>):Promise<{dfs:Array<string>, graph:{[key:string]:Function}}> { let DFS:DFS=await createGraphForDFS(network); - sources.forEach(async sourceID =>{ - const nodesID:string[]=DFS.nodesID; - if (nodesID.length===0) return; // no nodes + const nodesID:string[]=DFS.nodesID; + if (nodesID.length===0) return { dfs:[],graph:DFS.GDSgraph }; // no nodes + + for (const sourceID of sources){ const sourceIndex=nodesID.indexOf(sourceID); // if the source exist in the network and it's not already visited : dfs from this source if (sourceIndex!==-1 && !DFS.visited[sourceIndex]){ DFS= await nodeDagDFS(DFS,sourceIndex,[]); } - }); + }; return { dfs:DFS.dfsOrder.reverse(),graph:DFS.GDSgraph }; } @@ -115,8 +116,8 @@ async function nodeDagDFS(DFS:DFS,nodeIndex:number,currentPath:number[]):Promise path.push(nodeIndex) // loop through the children of the node - DFS.GDSgraph.adjacent(DFS.nodesID[nodeIndex]).sort().forEach(async (childID:string) => { - + const childrenOfNode=DFS.GDSgraph.adjacent(DFS.nodesID[nodeIndex]).sort(); + for (const childID of childrenOfNode){ // get the index of the child const childIndex = DFS.nodesID.indexOf(childID); if(childIndex!==-1){ @@ -136,7 +137,7 @@ async function nodeDagDFS(DFS:DFS,nodeIndex:number,currentPath:number[]):Promise } } - }); + }; // add the node to the dfs order DFS.dfsOrder.push(DFS.nodesID[nodeIndex]); diff --git a/src/composables/CalculateOverlaps.ts b/src/composables/CalculateOverlaps.ts index f7e09f05b02929a51f32b62f7ffa3efe42a439fc..973b7348b835c37a3790390b0a901fc7f564a9bd 100644 --- a/src/composables/CalculateOverlaps.ts +++ b/src/composables/CalculateOverlaps.ts @@ -318,259 +318,3 @@ function nodeEdgeOverlap(centerCoordNode: Coordinate, sizeNode:Size, posLink1: C function isPointInsideRect(point: Coordinate, rectangle:{left:number,right:number,top:number,bottom:number}):boolean{ return point.x >= rectangle.left && point.x <= rectangle.right && point.y >= rectangle.top && point.y <= rectangle.bottom; } - - - -// CHNAGE THE CODE : SEE METRICSNETWORK (for end of internship : keep this one) - -// /** -// * Check if the coordinates (x, y) are the same as the node's coordinates -// * @param node the node -// * @param x coordinate -// * @param y coordinate -// * @returns a boolean -// */ -// function isNodeCoord(node: {x:number,y:number}, x: number, y: number): boolean { -// return (node.x == x && node.y == y); -// } - - - -//______________________Intersection in the network______________________ -/** - * Check if the 2 edges are crossing. - * Coming from the same node or going to the same node doesn't count as crossing. - * @param link1 an edge - * @param link2 an edge - * @returns a boolean - */ -// function edgesIntersectionLink(link1: Link, link2: Link,style:GraphStyleProperties): boolean { - -// // case of common node -// if (commonNodeBetween2Links(link1,link2)) { -// return false; -// } - -// let x1: Node = link1.source; -// const x1Center=AdjustCoordNodeToCenter(x1,style); -// let x2: Node = link1.target; -// const x2Center=AdjustCoordNodeToCenter(x2,style); -// let x3: Node = link2.source; -// const x3Center=AdjustCoordNodeToCenter(x3,style); -// let x4: Node = link2.target; -// const x4Center=AdjustCoordNodeToCenter(x4,style); - -// const result = checkIntersection(x1Center.x, x1Center.y, x2Center.x, x2Center.y, x3Center.x, x3Center.y, x4Center.x, x4Center.y); -// if (result.type == "intersecting") { -// return true; -// } else { -// return false; -// } - -// } - -// function commonNodeBetween2Links(link1: Link,link2: Link): boolean { -// if (link1.source==link2.source || link1.source==link2.target || link1.target==link2.source || link1.target==link2.target) { -// return true; -// }else { -// return false; -// } -// } - -// function sameAngleBetween2ConnectedLinks(link1: Link,link2: Link,style:GraphStyleProperties): boolean { - -// // get nodes information -// let commonNode: Node; -// let node1: Node; // node from link 1 that is not in link 2 -// let node2: Node; // node from link 2 that is not in link 1 - -// // if link 1 source is the common node : -// if (link1.source==link2.source || link1.source==link2.target){ -// commonNode=link1.source; -// node1=link1.target; -// // if link 1 target is the common node : -// }else if (link1.target==link2.source || link1.target==link2.target){ -// commonNode=link1.target; -// node1=link1.source; -// } -// // get node 2 -// if (link2.source==commonNode){ -// node2=link2.target; -// }else{ -// node2=link2.source; -// } - -// // adjust coord -// const commonNodeCenter=AdjustCoordNodeToCenter(commonNode,style); -// const node1Center=AdjustCoordNodeToCenter(node1,style); -// const node2Center=AdjustCoordNodeToCenter(node2,style); -// // get angle between the 2 edges -// const angle1=adjustAngle(Math.atan2(node1Center.y-commonNodeCenter.y,node1Center.x-commonNodeCenter.x)); -// const angle2=adjustAngle(Math.atan2(node2Center.y-commonNodeCenter.y,node2Center.x-commonNodeCenter.x)); - -// // same angles ? -// return angle1==angle2; - -// } - -// function adjustAngle(angle: number): number { -// return (angle + 2 * Math.PI) % (2 * Math.PI); -// } - -// function AdjustCoordNodeToCenter(node:Node,style:GraphStyleProperties):{x:number,y:number}{ -// const size = getSizeNodePixel(node,style); -// return {x:node.x-size.width/2,y:node.y-size.height/2} -// } - -// /** -// * Counts how many crossings are in a network -// * @param network the network -// * @returns the number of crossings -// */ -// export function countIntersection(network: Network,style:GraphStyleProperties): number { -// let nb: number = 0; -// for (let i=0 ; i<network.links.length ; i++) { -// for (let j=i+1 ; j<network.links.length ; j++) { -// const link1=network.links[i]; -// const link2=network.links[j]; -// if (edgesIntersectionLink(link1, link2,style)){ -// nb++; -// } -// } -// } -// return nb; -// } - - -//______________________Intersection in another format of graph______________________ - -////CLEAN CODE : CHANGE FORMAT TO NETWORK AND USE THE OTHER FUNCTIONS FOR CYCLE - -// function AdjustCoordNodeToCenter2(node:Node,nodeCoord:{x:number,y:number},style:GraphStyleProperties):{x:number,y:number}{ -// const size = getSizeNodePixel(node,style); -// return {x:nodeCoord.x-size.width/2,y:nodeCoord.y-size.height/2} -// } - - - -// function commonNodeBetween2EdgesID(link1: {source:string,target:string},link2: {source:string,target:string}): boolean { -// if (link1.source==link2.source || link1.source==link2.target || link1.target==link2.source || link1.target==link2.target) { -// return true; -// }else { -// return false; -// } -// } - - - -// function intersection2ConnectedLinks(node1Link1:{x:number,y:number},node2Link1:{x:number,y:number},node1Link2:{x:number,y:number},node2Link2:{x:number,y:number}): boolean { - -// // get nodes information -// let commonNode: {x:number,y:number}; -// let node1: {x:number,y:number}; // node from link 1 that is not in link 2 -// let node2: {x:number,y:number}; // node from link 2 that is not in link 1 - -// // if link 1 node 1 is the common node : -// if (sameNode(node1Link1,node1Link2) || sameNode(node1Link1,node2Link2)){ -// commonNode=node1Link1; -// node1=node2Link1; -// // if link 1 node 2 is the common node : -// }else if (sameNode(node2Link1,node1Link2) || sameNode(node2Link1,node2Link2)){ -// commonNode=node2Link1; -// node1=node1Link1; -// } -// // get node 2 -// if (sameNode(node1Link2,commonNode)){ -// node2=node2Link2; -// }else{ -// node2=node1Link2; -// } - -// // get angle between the 2 edges -// const angle1=adjustAngle(Math.atan2(node1.y-commonNode.y,node1.x-commonNode.x)); -// const angle2=adjustAngle(Math.atan2(node2.y-commonNode.y,node2.x-commonNode.x)); - -// // same angles ? -// return angle1==angle2; - -// } - -// export function countIntersectionGraph(nodes: {[key:string]:{x:number,y:number}},links:{source:string,target:string}[],network:Network,style:GraphStyleProperties): number { -// let nb: number = 0; -// for (let i=0 ; i<links.length ; i++) { -// for (let j=i+1 ; j<links.length ; j++) { -// const link1=links[i]; -// const link2=links[j]; -// // check if intersection -// let node1Link1=nodes[link1.source]; -// //node1Link1=AdjustCoordNodeToCenter2(network.nodes[link1.source],node1Link1,style); -// let node2Link1=nodes[link1.target]; -// //node2Link1=AdjustCoordNodeToCenter2(network.nodes[link1.target],node2Link1,style); -// let node1Link2=nodes[link2.source]; -// //node1Link2=AdjustCoordNodeToCenter2(network.nodes[link2.source],node1Link2,style); -// let node2Link2=nodes[link2.target]; -// //node2Link2=AdjustCoordNodeToCenter2(network.nodes[link2.target],node2Link2,style); -// if (edgesIntersection(node1Link1,node2Link1,node1Link2,node2Link2)){ -// nb++; -// } -// } -// } -// return nb; -// } - -//______________________Nodes overlap for graph______________________ - -// export function countOverlapNodes(nodesPosition: {[key:string]:Coordinate},network:Network,networkStyle:GraphStyleProperties):number{ -// let nb=0; -// const nodesID=Object.keys(nodesPosition); -// for (let i=0 ; i<nodesID.length ; i++) { -// for (let j=i+1 ; j<nodesID.length ; j++) { -// // info about node1 -// const node1=network.nodes[nodesID[i]]; -// const posNode1=nodesPosition[nodesID[i]]; -// const sizeNode1=getSizeNodePixel(node1,networkStyle); -// // info about node2 -// const node2=network.nodes[nodesID[j]]; -// const posNode2=nodesPosition[nodesID[j]]; -// const sizeNode2=getSizeNodePixel(node2,networkStyle); - -// if (nodeOverlap(posNode1,sizeNode1,posNode2,sizeNode2)){ -// nb+=1; -// } - -// } -// } -// return nb; -// } - -//______________________Nodes overlap with edges for graph______________________ - -// export function countOverlapNodesEdges(nodesPosition: {[key:string]:{x:number,y:number}},links:{source:string,target:string}[],network:Network,networkStyle:GraphStyleProperties):number{ -// let nb=0; -// const nodesID=Object.keys(nodesPosition); -// for (let i=0 ; i<nodesID.length ; i++) { -// // info about node -// const node=network.nodes[nodesID[i]]; -// const posNode=nodesPosition[nodesID[i]]; -// const sizeNode=getSizeNodePixel(node,networkStyle); - -// for (let j=0 ; j<links.length ; j++) { -// // info about link -// const link=links[j]; -// // if node is linked to the edge : continue -// if(link.source==nodesID[i] || link.target==nodesID[i]){ -// continue; -// }else{ -// let posLink1=nodesPosition[link.source]; -// let posLink2=nodesPosition[link.target]; -// //posLink1=AdjustCoordNodeToCenter2(network.nodes[link.source],posLink1,networkStyle); -// //posLink2=AdjustCoordNodeToCenter2(network.nodes[link.target],posLink2,networkStyle); -// if (nodeEdgeOverlap(posNode,sizeNode,posLink1,posLink2)){ -// nb+=1; -// } -// } - -// } -// } -// return nb; -// } diff --git a/src/composables/CalculateRelationCycle.ts b/src/composables/CalculateRelationCycle.ts index 99f9167467de99a642dceb5f3d99932cd085bcdf..805295cfd63bd5a7404986d075172e8e60322912 100644 --- a/src/composables/CalculateRelationCycle.ts +++ b/src/composables/CalculateRelationCycle.ts @@ -252,7 +252,6 @@ export function getNodesPlacedInGroupCycleAsArray(subgraphNetwork:SubgraphNetwor * If the group cycle ID is not found or the precalculated node positions are not available, null is returned. */ export function getNodesPlacedInGroupCycleAsObject(subgraphNetwork:SubgraphNetwork,groupCycleID:string):{[key:string]:Coordinate}{ - console.log(JSON.stringify(subgraphNetwork)); if (subgraphNetwork[TypeSubgraph.CYCLEGROUP] && groupCycleID in subgraphNetwork[TypeSubgraph.CYCLEGROUP]){ const groupCycle =subgraphNetwork[TypeSubgraph.CYCLEGROUP][groupCycleID]; if (groupCycle.precalculatedNodesPosition){ @@ -333,7 +332,8 @@ export async function sortLinksWithAllGroupCycle(subgraphNetwork:SubgraphNetwork // change ordre with group cycle if (orderChange && subgraphNetwork[TypeSubgraph.CYCLEGROUP]){ // adding edge in right order for each group cycle - for (const groupCycle of Object.keys(subgraphNetwork[TypeSubgraph.CYCLEGROUP])) { + const allGroupCycle=Object.keys(subgraphNetwork[TypeSubgraph.CYCLEGROUP]); + for (const groupCycle of allGroupCycle) { const resultSorting = await sortLinksWithGroupCycle(subgraphNetwork, groupCycle); subgraphNetwork = resultSorting.subgraphNetwork; links = links.concat(resultSorting.linksOrdered); @@ -385,7 +385,7 @@ async function sortLinksWithGroupCycle(subgraphNetwork:SubgraphNetwork,groupCycl } // get links between the parent (or children) and the group cycle in the right order - nodeOrder.forEach(async (nodeId) => { + for (const nodeId of nodeOrder){ // get links for each node const newLinksOrder = await getLinksNodeGroupCycle(subgraphNetwork,nodeId,groupCycle,source); // add links @@ -393,7 +393,7 @@ async function sortLinksWithGroupCycle(subgraphNetwork:SubgraphNetwork,groupCycl links.push(newLink); }); - }); + }; return { subgraphNetwork:subgraphNetwork,linksOrdered:links }; }else{ return { subgraphNetwork:subgraphNetwork,linksOrdered:[] }; diff --git a/src/composables/CalculateSize.ts b/src/composables/CalculateSize.ts index 742e8c2a1f61fe4b8203cc7e847ea8b456418540..5ecd8154ed53a603cf93b99f82a853b42eca5612 100644 --- a/src/composables/CalculateSize.ts +++ b/src/composables/CalculateSize.ts @@ -7,9 +7,6 @@ import { Coordinate, Size } from "../types/CoordinatesSize"; // Composable imports import { inCycle, isSideCompound } from "./GetSetAttributsNodes"; -// General imports - - /** * This file contains functions to calculate the size of nodes, edges and subgraphs. Anf function to shift coordinates depending on node size. @@ -386,7 +383,7 @@ function getSizeGroupCycles(subgraphNetwork:SubgraphNetwork,groupCycle:Subgraph) * @param style - The style properties used to calculate the top left coordinate. * @param moveCycleToo - Optional parameter indicating whether to move nodes in cycles as well. Defaults to true. */ -export function shiftAllToGetTopLeftCoord(network:Network,style:GraphStyleProperties,moveCycleToo:boolean=true) { +export function shiftAllToGetTopLeftCoord(network:Network,style:GraphStyleProperties,moveCycleToo:boolean=true):void { Object.values(network.nodes).forEach(node=>{ if( moveCycleToo || !inCycle(network,node.id)){ const {x,y}=getTopLeftCoordFromCenter(node,style); diff --git a/src/composables/ConvertFromNetwork.ts b/src/composables/ConvertFromNetwork.ts index c50043c4d1a3a50412132a3747515438fea4b221..861e6448369075b490f239412f29aaaa123165d7 100644 --- a/src/composables/ConvertFromNetwork.ts +++ b/src/composables/ConvertFromNetwork.ts @@ -40,12 +40,6 @@ import * as GDS from 'graph-data-structure'; * ********************************* * 1. Layout library * - * -> networkToDagre - * take a network object and return a dagre.graphlib.Graph object containing the same nodes and edge - * - * -> networkToCytoscape - * take a network object and return a cytoscape object containing the same nodes and edge - * * -> networkToDOT * take a network object and return a DOT string representation * @@ -160,88 +154,6 @@ export function networkToAdjacentObject(network:Network):{[key : string]:string[ //___________________________________________________1. Layout library __________________________________________________________________________ - -/** - * Take a network object and return a dagre.graphlib.Graph object containing the same nodes and edge - * @param {Network} Network object - * @param graphAttributes for dagre layout (see https://github.com/dagrejs/dagre/wiki) - * @returns {dagre.graphlib.Graph} Return dagre.graphlib.Graph object - */ -// export function networkToDagre(network: Network,graphAttributes={}): dagre.graphlib.Graph{ - -// // initialisation dagre graph -// var g = new dagre.graphlib.Graph(); -// g.setGraph(graphAttributes); -// g.setDefaultEdgeLabel(() => ({})); - -// // insert nodes into graph -// Object.values(network.nodes).forEach((node) => { -// const { id, label, x, y } = node; -// g.setNode(id, { label, width: 100, height: 100, x, y }); -// }); - -// // insert edges into graph -// network.links.forEach((link) => { -// const { source, target } = link; -// g.setEdge(source.id, target.id); -// }); - -// return g; - -// } - - - -/** - * Converts a network object to a Cytoscape object. - * - * @param network - The network object to convert. - * @param initialPosition - Optional. Specifies whether to initialize the position of the nodes. Default is false. - * @returns The converted Cytoscape object. - */ -// export function networkToCytoscape(network: Network, initialPosition:boolean=false): cytoscape.Core { - -// // Convert nodes -// const nodes: ElementDefinition[] = Object.values(network.nodes).map(node => ({ -// data: { -// id: node.id, -// }, -// position: { -// x: node.x, -// y: node.y, -// }, -// })); - -// // Convert links -// const edges: ElementDefinition[] = []; -// network.links.forEach(link => { -// edges.push({ -// data: { -// id: link.id, -// source: link.source.id, -// target: link.target.id, -// } -// }); -// }); - - -// if (initialPosition){ -// return cytoscape({ -// container: undefined, -// elements: {nodes:nodes, edges:edges}, -// layout: { -// name: 'preset', // to initialize the position of the nodes -// }, -// }); -// }else{ -// return cytoscape({ -// container: undefined, -// elements: {nodes:nodes, edges:edges}, -// }); -// } -// } - - /** * Converts a SubgraphNetwork object to a DOT string representation. * @@ -464,7 +376,7 @@ export function graphVizToDot(vizGraph:Graph, subgraphFirst:boolean=true):string * @param obj - The object to convert. * @returns A string representation of the object with attribute-value pairs. */ -function customStringify(obj:AttributesViz|undefined) { +function customStringify(obj:AttributesViz|undefined):string{ if (!obj || Object.keys(obj).length === 0) { return "[]"; } diff --git a/src/composables/ConvertToNetwork.ts b/src/composables/ConvertToNetwork.ts index 79e679a60cbc1c4048bd048238765097a3b5e5d8..995f66dd03fc03463bda6a7604764c560aae9f7c 100644 --- a/src/composables/ConvertToNetwork.ts +++ b/src/composables/ConvertToNetwork.ts @@ -17,9 +17,6 @@ import { assignRankOrder } from './CalculateStartNodes'; * -> networkLayoutToNetwork : * Convert a network layout object (network with information to calculate layout) into a network object * - * -> changeNetworkFromDagre : - * Take dagre.graphlib.Graph object and the network associated (with the graph) : change the position and metadata (rank and order) of network's node by the one of the graph. - * * -> changeNetworkFromViz : * Take a json of a viz graph and the network associated (with the json) : change the position and metadata (rank and order) of network's node by the one of the json. * @@ -48,33 +45,6 @@ export function networkLayoutToNetwork(networkLayout: NetworkLayout): Network { } -// /** -// * Take dagre.graphlib.Graph object and the network associated (with the graph) : change the position and metadata (rank and order) of network's node by the one of the graph. -// * The graph and network need to have the same nodes ! -// * @param {dagre.graphlib.Graph} dagre.graphlib.Graph object -// * @param {Network} Network object (value of pointer) -// */ -// export async function changeNetworkFromDagre(graph: dagre.graphlib.Graph,network: NetworkLayout): Promise<void>{ -// Object.entries(graph["_nodes"]).forEach(([node, nodeData]:[string, dagre.graphlib.Node]) => { -// if (!network.nodes[node].metadataLayout) { -// network.nodes[node].metadataLayout = {}; -// } -// const { x, y, _order,_rank } = nodeData; -// // if there is some position x and y : network is updated -// if (x !== undefined && y !== undefined){ -// if (network.nodes[node]) { -// network.nodes[node].x = x; -// network.nodes[node].y = y; -// } else { -// throw new Error(`Node '${node}' not found in the network.`); -// } -// network.nodes[node].metadataLayout.order = _order; -// network.nodes[node].metadataLayout.rank = _rank / 2; // because rank 0 is 0, and the next is 2, 4, ... -// } -// }); -// } - - /** * Take a json of a viz graph and the network associated (with the json) : change the position and metadata (rank and order) of network's node by the one of the json. * The json and network need to have the same nodes ! @@ -124,24 +94,5 @@ export async function changeNetworkFromViz(json: JsonViz, subgraphNetwork: Subgr } -// /** -// * Updates the positions of nodes in the network based on the provided Cytoscape JSON. -// * -// * @param jsonCytoscape - The Cytoscape JSON containing the elements and their positions. -// * @param network - The network to update. -// */ -// export function changeNetworkFromCytoscape(jsonCytoscape: {elements: { nodes:ElementDefinition[] } }, network:Network) : void { - -// jsonCytoscape.elements.nodes.forEach((node: any) => { -// const idNode= node.data.id; -// if (Object.keys(network.nodes).includes(idNode)) { -// network.nodes[idNode].x = node.position.x; -// network.nodes[idNode].y = node.position.y; -// }else{ -// throw new Error(`Node '${idNode}' not found in the network.`); -// } -// }); -// } - diff --git a/src/composables/GetSetAttributsNodes.ts b/src/composables/GetSetAttributsNodes.ts index 70387517162a8efebf2b407bf026742155df6a4a..2861b941461e4cf70d8c7af6f5303df60bf17881 100644 --- a/src/composables/GetSetAttributsNodes.ts +++ b/src/composables/GetSetAttributsNodes.ts @@ -26,9 +26,6 @@ import { NetworkLayout } from "../types/NetworkLayout"; * ********************************* * 2. Reversible * - * -> addMetadataReversibleWithClass : - * Adds the reversible attribute to the given node in the network. - * * -> addReversibleNetwork : * Adds the reversible attribute to the given node in the network. * @@ -51,6 +48,8 @@ import { NetworkLayout } from "../types/NetworkLayout"; * ********************************* * 3. Cycle * + * -> inCycle : + * Checks if a node is part of a cycle in the network. * */ @@ -112,19 +111,6 @@ export const classReversible="reversible"; export const reversibleAttribute="reversible"; export const reactionClass="reaction"; -/** - * Checks if a node in the network is reversible by checking its classes. - * => done for my type of file, not necessaty if reversible information already in the metadata - * @param network - The network object. - */ -export async function addMetadataReversibleWithClass(network:Network):Promise<void>{ - Object.values(network.nodes).forEach((node) => { - if(node.classes && node.classes.includes(classReversible)){ - addReversibleNetwork(network,node.id); - } - }); - } - /** * Adds the reversible attribute to the given node in the network. diff --git a/src/composables/LayoutDrawCycle.ts b/src/composables/LayoutDrawCycle.ts index 6351d3c29e8a2b06a6bfa11c8297f877b0a29d2b..958977730ddc2bc18b981de473a17929d730eb75 100644 --- a/src/composables/LayoutDrawCycle.ts +++ b/src/composables/LayoutDrawCycle.ts @@ -398,7 +398,7 @@ async function lineCycleCoordinates(subgraphNetwork:SubgraphNetwork,cycleToDrawI let cycleAsLine:string[]=[]; - unfixedInterval.forEach(async interval=>{ + for (const interval of unfixedInterval){ const startNode=cycleNodes[(interval[0]-1+ cycleNodes.length) % cycleNodes.length]; const endNode=cycleNodes[(interval[1]+1+ cycleNodes.length) % cycleNodes.length]; @@ -420,7 +420,7 @@ async function lineCycleCoordinates(subgraphNetwork:SubgraphNetwork,cycleToDrawI subgraphNetwork=lineCoord.subgraphNetwork; const positionBefore=lineCoord.positionBefore; subgraphNetwork=undoIfCreateOverlap(subgraphNetwork,groupCycleName,positionBefore); - }); + }; return subgraphNetwork; } @@ -556,9 +556,6 @@ async function forceGroupCycle(subgraphNetwork:SubgraphNetwork, groupCycleName:s const simulation = d3.forceSimulation(graph.nodes) .force('link', d3.forceLink().id((d: any) => {return d.id;}).links(graph.links).distance(distanceLinks).strength(0.3)) .force('charge', d3.forceManyBody().strength(strengthManyBody)) - //.force("collide", d3.forceCollide(distanceLinks/2)) - //.force('center', d3.forceCenter(0,0)) - //.force("radial", d3.forceRadial(0,0)) .alphaMin(0.4) .stop(); @@ -1162,500 +1159,3 @@ function drawCycleGroup(cycleGroup:string,subgraphNetwork:SubgraphNetwork):void{ } } - -// ________________________Method 2________________________________________________________ - -// export function coordinateAllCycles(subgraphNetwork:SubgraphNetwork):Promise<SubgraphNetwork>{ -// return new Promise((resolve) => { -// // creation of group cycle and placement of first cycle -// subgraphNetwork=firstStepGroupCycles(subgraphNetwork); -// // if there are group cycle : continue to place the other cycles -// if (subgraphNetwork.cyclesGroup && Object.keys(subgraphNetwork.cyclesGroup).length>0){ -// Promise.all( -// Object.keys(subgraphNetwork.cyclesGroup).map(groupCycleName => { -// forceGroupCycle(subgraphNetwork, groupCycleName) -// }) -// ).then(() => { -// subgraphNetwork=getSizeAllGroupCycles(subgraphNetwork); -// resolve(subgraphNetwork); -// }); -// } -// }); -// } - -// function firstStepGroupCycles(subgraphNetwork:SubgraphNetwork):SubgraphNetwork { -// let cycles = subgraphNetwork.cycles? Object.values(subgraphNetwork.cycles):undefined; -// let i=0; -// let group=-1; -// let groupName:string=""; -// let newGroup=true; - -// while (cycles && cycles.length > 0) { - -// if (newGroup){ -// // if first cycle of a group cycle -// // creation of a new group cycle -// group+=1; -// groupName=cycleGroupName(String(group)); -// subgraphNetwork=addNewCycleGroup(subgraphNetwork,groupName); -// // find biggest cycle, or the one with most constraint -// // cycles that are not subgraph of a cycle -// const parentCycles = cycles.filter(cycle => !cycle.forSubgraph || cycle.forSubgraph.type !== TypeSubgraph.CYCLE); -// if (parentCycles.length === 0) { -// console.error("No cycle found without a forSubgraph of type cycle"); -// return; -// } -// parentCycles.sort((a, b) => sortCycleSizeRelation(subgraphNetwork,a,b,true)); -// const largestParentCycle = parentCycles[0]; - -// // add it to the group cycle and remove it from the list of cycle to process -// subgraphNetwork.cyclesGroup[groupName].nodes.push(largestParentCycle.name); -// cycles = cycles.filter(cycle => cycle.name !== largestParentCycle.name); -// // give it coordinates -// subgraphNetwork=coordinateCycle(subgraphNetwork, largestParentCycle.name,groupName,true); - -// }else{ -// // if not first cycle of a group cycle -// // find all cycles with common nodes (fixed nodes) -// const dependantCyclesList=dependantCycles(cycles,subgraphNetwork); - -// dependantCyclesList.forEach(dependantCycle => { -// // add them to the group cycle -// subgraphNetwork.cyclesGroup[groupName].nodes.push(dependantCycle); -// // fix the nodes (to (0,0)) -// const nodes=subgraphNetwork.cycles[dependantCycle].nodes; -// subgraphNetwork=coordinateCycle(subgraphNetwork, dependantCycle,groupName,false); -// }); - -// // remove them from the list of cycle to process -// cycles = cycles.filter(cycle => !dependantCyclesList.includes(cycle.name)); - -// } - -// // check all cycles of the group cycle are processed -// newGroup=isRemainingCycleIndepOfDrawing(cycles, subgraphNetwork); - -// } - -// return subgraphNetwork; -// } - - - - -// function coordinateCycle(subgraphNetwork:SubgraphNetwork, cycleToDrawID:string,groupCycleName:string,asCircle:boolean=true):SubgraphNetwork{ -// const network = subgraphNetwork.network.value; -// let centroidX :number=0; -// let centroidY :number=0; - -// // Get nodes to place -// let cycle:string[]=[]; -// if (cycleToDrawID in subgraphNetwork.cycles){ -// cycle=subgraphNetwork.cycles[cycleToDrawID].nodes; -// subgraphNetwork.cycles[cycleToDrawID].metadata={}; -// }else{ -// console.log('cycle not in subgraph network'); -// } - -// // Check existence of all nodes -// const cycleExist = cycle.every(node => node in network.nodes); - - -// // If cycle exist: place his nodes -// if (cycleExist && cycle.length>0){ - -// // Update node metadata to place them in cycleGroup -// cycle.forEach(node=>{ -// network.nodes[node].metadata[TypeSubgraph.CYCLEGROUP]=groupCycleName; -// }); - -// // if the cycle has to be drawn as a circle -// if (asCircle){ -// // radius and centroid -// const radius = getRadiusSize(cycle,network,subgraphNetwork.networkStyle.value); -// subgraphNetwork.cycles[cycleToDrawID].metadata.radius=radius; -// subgraphNetwork.cycles[cycleToDrawID].metadata.centroid={x:centroidX,y:centroidY}; - -// // Shift cycle -// const topIndex = findTopCycleNode(subgraphNetwork,cycle); // first node of list is the top -// const cycleCopy= cycle.slice(); -// const shiftedCycle = cycleCopy.splice(topIndex).concat(cycleCopy); - -// // Give position to each node -// subgraphNetwork=cycleNodesCoordinates(cycleToDrawID,shiftedCycle,centroidX,centroidY,radius,subgraphNetwork,-Math.PI/2,groupCycleName); -// } else { -// subgraphNetwork=fixedCycleNodesToOrigin(cycle,subgraphNetwork,groupCycleName); -// } -// } - -// return subgraphNetwork; -// } - - -// function sortCycleSizeRelation(subgraphNetwork:SubgraphNetwork,a:Subgraph,b:Subgraph,byRelation:boolean=false):number{ -// // sort by size -// if ( !byRelation || b.nodes.length !== a.nodes.length ){ -// return b.nodes.length - a.nodes.length; -// }else{ -// // then by number of parent nodes -// const totalParentNodesA = parentNodeNotInCycle(subgraphNetwork, a.nodes) -// .flat().length; -// const totalParentNodesB = parentNodeNotInCycle(subgraphNetwork, b.nodes) -// .flat().length; -// if (totalParentNodesA !== totalParentNodesB){ -// return totalParentNodesB - totalParentNodesA; -// }else{ -// // then by number of child nodes -// const totalChildNodesA = childNodeNotInCycle(subgraphNetwork, a.nodes) -// .flat().length; -// const totalChildNodesB = childNodeNotInCycle(subgraphNetwork, b.nodes) -// .flat().length; - -// return totalChildNodesB - totalChildNodesA; -// } -// } -// } - - - - - - -// function fixedCycleNodesToOrigin(cycle:string[],subgraphNetwork:SubgraphNetwork,groupcycle:string,):SubgraphNetwork{ -// const network=subgraphNetwork.network.value; -// cycle.forEach((node) => { -// const nodeNetwork=network.nodes[node]; -// // Give position if not fixed -// if(network.nodes[node].metadata && !network.nodes[node].metadata.fixedCycle){ -// if (groupcycle in subgraphNetwork.cyclesGroup){ -// if (!subgraphNetwork.cyclesGroup[groupcycle].metadata[node]){ -// subgraphNetwork.cyclesGroup[groupcycle].metadata[node] = {}; -// } -// subgraphNetwork.cyclesGroup[groupcycle].metadata[node]["x"]=0; -// subgraphNetwork.cyclesGroup[groupcycle].metadata[node]["y"]=0; - -// // Fix the nodes -// if (!nodeNetwork.metadata) nodeNetwork.metadata={}; -// nodeNetwork.metadata.fixedInCycle= true; -// } else { -// console.error("CycleGroup not in subgraphNetwork"); -// } -// } -// }); - -// return subgraphNetwork; -// } - - -// function dependantCycles(remainingCycles:Subgraph[], subgraphNetwork:SubgraphNetwork):Array<string>{ - -// const network = subgraphNetwork.network.value; - -// const fixedCycleIds = remainingCycles.filter(cycle => -// cycle.nodes.some(node => -// network.nodes[node].metadata && network.nodes[node].metadata.fixedInCycle -// ) -// ).map(cycle => cycle.name); - -// return fixedCycleIds; -// } - - -// function centroidFromNodes(nodesList:string[],subgraphNetwork:SubgraphNetwork):{x:number,y:number}{ -// if (nodesList.length>0){ -// const network=subgraphNetwork.network.value; -// let centroid={x:0,y:0} -// nodesList.forEach(node=> { -// if ("x" in network.nodes[node] && "y" in network.nodes[node]){ -// centroid.x += network.nodes[node].x; -// centroid.y += network.nodes[node].y; -// } -// }); -// return {x:centroid.x/nodesList.length,y:centroid.y/nodesList.length}; -// } -// return {x:0,y:0}; -// } - - - -// function euclideanDistance(point1: {x: number, y: number}, point2: {x: number, y: number}): number { -// let dx = point2.x - point1.x; -// let dy = point2.y - point1.y; -// return Math.sqrt(dx * dx + dy * dy); -// } - - -// function totalIntervals(startArc: {x: number, y: number}, endArc: {x: number, y: number}, centroidArc: {x: number, y: number}, nodesInArc: number): number { -// // Calculate distances -// let a = euclideanDistance(startArc, endArc); -// let b = euclideanDistance(startArc, centroidArc); -// let c = euclideanDistance(endArc, centroidArc); - -// // Calculate angle of arc using law of cosines -// let angle = Math.acos((b*b + c*c - a*a) / (2 * b * c)); - -// // Calculate total intervals in full circle -// let totalIntervals = Math.round(2 * Math.PI / angle) * nodesInArc; - -// return totalIntervals; -// } - -// function centroidOneFixedCycleNode(subgraphNetwork:SubgraphNetwork,nodeFixedID:string,radius:number):{x:number,y:number}{ -// const nodeFixed=subgraphNetwork.network.value.nodes[nodeFixedID]; -// const radiusFixedCycle=subgraphNetwork.cycles[nodeFixed.metadata.fixedCycle as string].metadata.radius as number; -// const centroidFixedCycle=subgraphNetwork.cycles[nodeFixed.metadata.fixedCycle as string].metadata.centroid; -// const fixedAngle = Math.atan2(nodeFixed.y - centroidFixedCycle["y"], nodeFixed.x - centroidFixedCycle["x"]); -// const d = radius + radiusFixedCycle; -// const centroidX = centroidFixedCycle["x"] + d * Math.cos(fixedAngle); -// const centroidY = centroidFixedCycle["y"] + d * Math.sin(fixedAngle); -// return {x:centroidX,y:centroidY} -// } - - - -// function pushFromIndepGroupCycles(subgraphNetwork:SubgraphNetwork, groupCyclesID:string[],allGroupCycleDrawn:string[][]):void{ - -// console.log('--------------------------------------------------------------------'); -// // nodes in the group of cycle that won't move (others nodes will be pushed deprending on their positions) -// const nodesCycles = groupCyclesID -// .filter(cycleID => cycleID in subgraphNetwork.cycles) // Check if cycleID exists -// .flatMap(cycleID => subgraphNetwork.cycles[cycleID].nodes) // get all nodes from all cycles -// .reduce((unique, item) => unique.includes(item) ? unique : [...unique, item], []); // remove duplicates - -// // centroid of the group -// const centroid = centroidFromNodes(nodesCycles,subgraphNetwork); - -// const radius=subgraphNetwork.cycles[groupCyclesID[0]].metadata.radius as number; // TO CHANGE when several nodes - -// // get list of nodes to push : all but the cycle with its shortcut -// // and group of cycle already draw considered as a node -// const network = subgraphNetwork.network.value; -// const nodesNetwork = Object.keys(network.nodes).filter(node => !nodesCycles.includes(node)); -// const nodesGroupCycleDrawn=allGroupCycleDrawn.flatMap(groupCycle=>groupCycle) -// .flatMap(cycleID=>subgraphNetwork.cycles[cycleID].nodes) // get all nodes from all cycles -// .reduce((unique, item) => unique.includes(item) ? unique : [...unique, item], []); // remove duplicates -// const nodesNotInDrawCycle=nodesNetwork.filter(node => !nodesGroupCycleDrawn.includes(node)); -// let nodeToPush=nodesNotInDrawCycle.filter(node => !nodesGroupCycleDrawn.includes(node)); -// allGroupCycleDrawn.forEach(groupCycle=>{ -// nodeToPush.push(groupCycle[0]); // metanode of cycle group -// }); - - -// // Need to push ? - -// const needPush=nodesInsideMetanode(groupCyclesID,nodesNetwork,subgraphNetwork); -// console.log(needPush); - -// // push nodes - -// if (needPush){ -// nodeToPush.forEach(nodeID =>{ - -// if (nodeID in subgraphNetwork.cycles){ // if in a cycle -// // get connected cycle group -// const fullGroupCycle=allGroupCycleDrawn.filter(groupCycle=> groupCycle.includes(nodeID))[0]; -// const nodesAsMetanode=fullGroupCycle.flatMap(cycleID=>subgraphNetwork.cycles[cycleID].nodes) -// .reduce((unique, item) => unique.includes(item) ? unique : [...unique, item], []); // remove duplicates -// const metanodeCentroid=centroidFromNodes(nodesAsMetanode,subgraphNetwork); - -// const distanceCentroidToMetanode=euclideanDistance(centroid,metanodeCentroid); -// const distanceToMoveCentroid=(distanceCentroidToMetanode/radius+1)*radius; -// pushMetanode(nodesAsMetanode,centroid,distanceToMoveCentroid,subgraphNetwork); - - -// }else if (nodeID in network.nodes){ // if classic node - -// const distanceCentroidToNode=euclideanDistance(centroid,network.nodes[nodeID]); -// const distanceToMove=(distanceCentroidToNode/radius+1)*radius; -// pushMetanode([nodeID],centroid,distanceToMove,subgraphNetwork); - -// } - -// }); -// } - -// } - -// function pushMetanode(metanode:string[],centroidToPushfrom:{x:number,y:number},radius:number=1,subgraphNetwork:SubgraphNetwork):void{ -// const network = subgraphNetwork.network.value; -// if (metanode.length===1){ -// const node=network.nodes[metanode[0]]; -// let dx = node.x - centroidToPushfrom.x; -// let dy = node.y - centroidToPushfrom.y; -// let angle = Math.atan2(dy, dx); -// node.x = centroidToPushfrom.x + radius * Math.cos(angle); -// node.y = centroidToPushfrom.y + radius * Math.sin(angle); -// }else{ - -// // MARCHE PAS - -// // const centroidMetanode=centroidFromNodes(metanode,subgraphNetwork); -// // let dx = centroidMetanode.x - centroidToPushfrom.x; -// // let dy = centroidMetanode.y - centroidToPushfrom.y; -// // let angle = Math.atan2(dy, dx); -// // const newCentroid={x : centroidToPushfrom.x + radius * Math.cos(angle), -// // y : centroidToPushfrom.y + radius * Math.sin(angle)}; - -// // metanode.forEach(nodeID=>{ -// // const node=network.nodes[nodeID]; -// // node.x += newCentroid.x - centroidMetanode.x; -// // node.y += newCentroid.y - centroidMetanode.y; -// // }); -// } -// } - -// function nodesInsideMetanode(groupCyclesID:string[],nodeToCheck:string[],subgraphNetwork:SubgraphNetwork):boolean{ - - -// const cycles=groupCyclesID.filter(cycleID => cycleID in subgraphNetwork.cycles && subgraphNetwork.cycles[cycleID].metadata -// && "radius" in subgraphNetwork.cycles[cycleID].metadata && subgraphNetwork.cycles[cycleID].metadata.radius !== undefined -// && "centroid" in subgraphNetwork.cycles[cycleID].metadata && subgraphNetwork.cycles[cycleID].metadata.centroid -// && subgraphNetwork.cycles[cycleID].metadata.centroid["x"] !== undefined -// && typeof subgraphNetwork.cycles[cycleID].metadata.centroid["y"] !== undefined -// ) - -// let i=0; -// let flag=true; -// while (flag && i<cycles.length){ -// flag=!nodesInsideCircle(cycles[i],nodeToCheck,subgraphNetwork); -// i++; -// } -// return !flag; -// } - -// function nodesInsideCircle(cycleID:string,nodeToCheck:string[],subgraphNetwork:SubgraphNetwork):boolean{ -// const centroid=subgraphNetwork.cycles[cycleID].metadata.centroid as {x:number,y:number}; -// const radius=subgraphNetwork.cycles[cycleID].metadata.radius as number; - - -// let i=-1; -// let flag=true; -// while (flag && i<nodeToCheck.length){ -// i++; -// if( nodeToCheck[i] && Object.keys(subgraphNetwork.network.value.nodes).includes(nodeToCheck[i]) ){ - -// const node=subgraphNetwork.network.value.nodes[nodeToCheck[i]]; -// const distance=euclideanDistance(node,centroid); -// if (distance<=radius){ -// flag=false; -// } - -// }else{ -// //console.log('node '+nodeToCheck[i]+' not in network'); // PROBLEM !!! -// } - - -// } -// return !flag; -// } - - - -// function drawCycle(subgraphNetwork:SubgraphNetwork,cycleToDrawID:string,radius:number|undefined=undefined,radiusFactor:number=15):void { - -// console.log('drawing '+cycleToDrawID); - -// let cycle:string[]=[]; -// let centroidX :number; -// let centroidY :number; -// if (!subgraphNetwork.cycles[cycleToDrawID].metadata) subgraphNetwork.cycles[cycleToDrawID].metadata={}; -// subgraphNetwork.cycles[cycleToDrawID].metadata["radius"]=undefined; -// subgraphNetwork.cycles[cycleToDrawID].metadata["centroid"]=undefined; - - -// if (cycleToDrawID in subgraphNetwork.cycles){ -// cycle=subgraphNetwork.cycles[cycleToDrawID].nodes; -// }else{ -// console.log('argument cycleToDraw invalid'); -// } - -// // Check if the node are present in the graph, and see if position is fixed in another cycle -// const network = subgraphNetwork.network.value; -// let cycleExist = true; -// const nodesFixed:string[]=[]; -// cycle.forEach(node=>{ -// if (!(node in network.nodes)){ -// cycleExist=false; -// } else if (network.nodes[node].metadata && network.nodes[node].metadata.fixedInCycle){ -// nodesFixed.push(node); -// } -// }); - - -// if (cycleExist && cycle.length>0){ - -// if (nodesFixed.length===0){ // if independant cycle ---------------------------------------------------------------------------------- - -// // radius -// if (radius === undefined){ -// radius = getRadiusSize(cycle,radiusFactor); -// } -// subgraphNetwork.cycles[cycleToDrawID].metadata.radius=radius; - -// // centroid -// if (subgraphNetwork.cycles[cycleToDrawID].metadata && subgraphNetwork.cycles[cycleToDrawID].metadata["x"] && subgraphNetwork.cycles[cycleToDrawID].metadata["y"]){ -// centroidX=subgraphNetwork.cycles[cycleToDrawID].metadata["x"] as number; -// centroidY=subgraphNetwork.cycles[cycleToDrawID].metadata["y"] as number; -// }else { -// const centroid=centroidFromNodes(cycle,subgraphNetwork); -// centroidX=centroid.x; -// centroidY=centroid.y; -// } -// subgraphNetwork.cycles[cycleToDrawID].metadata.centroid={x:centroidX,y:centroidY}; - - -// // Shift cycle -// const topIndex = findTopCycleNode(subgraphNetwork,cycle); // first node of list is the top - -// const cycleCopy= cycle.slice(); -// const shiftedCycle = cycleCopy.splice(topIndex).concat(cycleCopy); - -// // Give position to each node -// cycleNodesCoordinates(cycleToDrawID,shiftedCycle,centroidX,centroidY,radius,subgraphNetwork,-Math.PI/2); - -// } else if (nodesFixed.length===1){ // if cycle linked to another cycle by one node ---------------------------------------------------------------------------------- -// const nodeFixed=network.nodes[nodesFixed[0]]; - -// // first node is the one fixed : -// const cycleCopy= cycle.slice(); -// const firstIndex=cycle.indexOf(nodesFixed[0]); -// const shiftedCycle = cycleCopy.splice(firstIndex).concat(cycleCopy); - -// // radius -// if (radius === undefined){ -// radius = getRadiusSize(cycle,radiusFactor); -// } -// subgraphNetwork.cycles[cycleToDrawID].metadata.radius=radius; - -// //centroid depending on fixed cycle -// const radiusFixedCycle=subgraphNetwork.cycles[nodeFixed.metadata.fixedCycle as string].metadata.radius as number; -// const centroidFixedCycle=subgraphNetwork.cycles[nodeFixed.metadata.fixedCycle as string].metadata.centroid; -// const fixedAngle = Math.atan2(nodeFixed.y - centroidFixedCycle["y"], nodeFixed.x - centroidFixedCycle["x"]); -// const d = radius + radiusFixedCycle; -// const centroidX = centroidFixedCycle["x"] + d * Math.cos(fixedAngle); -// const centroidY = centroidFixedCycle["y"] + d * Math.sin(fixedAngle); -// subgraphNetwork.cycles[cycleToDrawID].metadata.centroid={x:centroidX,y:centroidY}; - - -// // shift of start angle (default:pi/2) : angle of fixed node in the new cycle (with centroid calculted before) -// const shiftAngle = Math.atan2(nodeFixed.y - centroidY, nodeFixed.x - centroidX); - -// // drawing : -// cycleNodesCoordinates(cycleToDrawID,shiftedCycle,centroidX,centroidY,radius,subgraphNetwork,shiftAngle); - -// } else { // several node in common with other cycle(s) ---------------------------------------------------------------------------------- - -// const unfixedInterval=getUnfixedIntervals(cycle,subgraphNetwork); -// unfixedInterval.forEach(interval=>{ - -// const startNode=cycle[(interval[0]-1+ cycle.length) % cycle.length]; -// const endNode=cycle[(interval[1]+1+ cycle.length) % cycle.length]; -// lineNodesCoordinates(network.nodes[startNode],network.nodes[endNode],cycle.slice(interval[0],interval[1]+1),subgraphNetwork); - -// }); - -// } -// } - -// } - diff --git a/src/composables/LayoutFindCycle.ts b/src/composables/LayoutFindCycle.ts index 646b378fb22c519c4e61872ed3aafada93b30c8e..8159995846ab2d370e92e11e61f3491db77999b6 100644 --- a/src/composables/LayoutFindCycle.ts +++ b/src/composables/LayoutFindCycle.ts @@ -101,17 +101,9 @@ export function addDirectedCycleToSubgraphNetwork(subgraphNetwork:SubgraphNetwor if (sizeCycle<=sizeCommonCycle){ // if sorting worked : it is supposed to always be the case subgraphNetwork[TypeSubgraph.CYCLE][cycle[0]].parentSubgraph={name:networkCycles[i].name,type:TypeSubgraph.CYCLE}; updateParentSubgraphOf(subgraphNetwork,subgraphNetwork[TypeSubgraph.CYCLE][cycle[0]]); - // if(! subgraphNetwork[TypeSubgraph.CYCLE][networkCycles[i].name].childrenSubgraphs){ - // subgraphNetwork[TypeSubgraph.CYCLE][networkCycles[i].name].childrenSubgraphs=[]; - // } - // subgraphNetwork[TypeSubgraph.CYCLE][networkCycles[i].name].childrenSubgraphs.push({name:cycle[0],type:TypeSubgraph.CYCLE}); }else{ subgraphNetwork[TypeSubgraph.CYCLE][networkCycles[i].name].parentSubgraph={name:cycle[0],type:TypeSubgraph.CYCLE}; updateParentSubgraphOf(subgraphNetwork,subgraphNetwork[TypeSubgraph.CYCLE][networkCycles[i].name]); - // if(! subgraphNetwork[TypeSubgraph.CYCLE] [cycle[0]].childrenSubgraphs){ - // subgraphNetwork[TypeSubgraph.CYCLE] [cycle[0]].childrenSubgraphs=[]; - // } - // subgraphNetwork[TypeSubgraph.CYCLE] [cycle[0]].childrenSubgraphs.push({name:networkCycles[i].name,type:TypeSubgraph.CYCLE}); } } } @@ -311,9 +303,7 @@ function JohnsonAlgorithm(graph: number[][], list_nodes:string[],flag: "Single" } start = 0; - // for (let i = 0; i < nVertices; i++) { - // console.log(String(i)+" "+String(list_nodes[i])); - // } + while (start < nbNodeToRun) { for (let i = 0; i < nVertices; i++) { blocked[i] = false; diff --git a/src/composables/LayoutMain.ts b/src/composables/LayoutMain.ts index f1decc2ac50e601acb7a8e02abd9dd5bbb8ed763..879a4d79796c6b5c35f21bdd93fe69218fa1326e 100644 --- a/src/composables/LayoutMain.ts +++ b/src/composables/LayoutMain.ts @@ -215,13 +215,8 @@ export async function allSteps(subgraphNetwork: SubgraphNetwork,parameters:Param shiftAllToGetTopLeftCoord(network,networkStyle); } } - ).then( - () => { - // add color to link (optional : for debug) - //subgraphNetwork = addBoldLinkMainChain(subgraphNetwork); - //subgraphNetwork=addRedLinkcycleGroup(subgraphNetwork); - } ); + return subgraphNetwork; } diff --git a/src/composables/LayoutMainChain.ts b/src/composables/LayoutMainChain.ts index 491995d0200354655a6c96a4fd470e1c47b3675f..f0b06da29112eeeb377bed7f16d362d08d9c4156 100644 --- a/src/composables/LayoutMainChain.ts +++ b/src/composables/LayoutMainChain.ts @@ -5,12 +5,12 @@ import {TypeSubgraph, type Subgraph} from "../types/Subgraph"; import { Network } from "../types/TypeVizCore"; // Composable imports -import { DFSWithSources, DFSsourceDAG } from "./AlgorithmDFS"; +import { DFSsourceDAG } from "./AlgorithmDFS"; import { networkToGDSGraph } from "./ConvertFromNetwork"; import { getStartNodes } from "./CalculateStartNodes"; import { BFS } from "./AlgorithmBFS"; import { addSubgraphToNetwork, createSubgraph } from './SubgraphForSubgraphNetwork'; -import { path } from "d3"; + /** * This file contains functions find and add main chains and mini-branch (form main chain) in a subgraphNetwork. @@ -168,20 +168,16 @@ export async function getPathSourcesToTargetNode(network:Network, sources:string const {dfs,graph}=await DFSsourceDAG(network,[source]); // get max distance from source node for all nodes, and by which parent nodes the node had been accessed const {distances, parents}=await DistanceFromSourceDAG(graph,dfs,pathType); - console.log('distances',distances); // get the farthest node from source (node with max distance) const targetNodes=findMaxKeys(distances); // for each target node : (if several path wanted) if (pathType==PathType.ALL_LONGEST || pathType==PathType.ALL){ for (const target of targetNodes.key){ // get the parents that goes from source to target node - console.log('parents',parents); - console.log('target',target); const nodesBetweenSourceTarget=BFS(parents,target); // merge with an existing path if node in common // height is the max distance +1 pathsFromSources=await mergeNewPath(source,{nodes:nodesBetweenSourceTarget, height:targetNodes.max+1},pathsFromSources,merge); - console.log('pathsFromSources',pathsFromSources); }; } else if(pathType==PathType.LONGEST){ // if only one path wanted : take the first // get the parents that goes from source to target node @@ -290,16 +286,12 @@ async function mergeNewPath(source:string,newPath:{nodes:Array<string>, height:n // for each path in the object keys.forEach(key=>{ const pathNodes = pathsFromSources[key].nodes; - console.log('pathNodes',pathNodes); // Check for common nodes const commonNodes = pathNodes.find(node => newPath.nodes.includes(node)); - console.log('commonNodes',commonNodes); if (commonNodes && commonNodes.length>0){ - console.log('commonNodes',commonNodes); if(merge){ // Merge paths const mergedPath = Array.from(new Set(pathNodes.concat(newPath.nodes))); - console.log('mergedPath',mergedPath); // Create new key if necessary let newKey:string = key; const sourceAlreadyInKey=key.split('__').includes(source); @@ -330,123 +322,3 @@ async function mergeNewPath(source:string,newPath:{nodes:Array<string>, height:n return pathsFromSources; } - - -// // ---------------------------------------------------------------------------------------------------------------------------------------------- -// // ---------------------------------------------- Method 1 of getCluster for main chains --------------------------------------------------------- -// // ---------------------------------------------------------------------------------------------------------------------------------------------- - - -// /** -// * Get a long path from sources using a DFS. The path isn't the longest if there some undirected cycle. -// * @param network -// * @param sources to use for DFS -// * @returns some node clusters with id -// */ -// export function getLongPathDFS(network:Network,sources:string[]):{[key:string]:{nodes:Array<string>, height:number}}{ -// //console.log('DFS long path'); -// // create graph for library from network -// const graph=networkToGDSGraph(network); -// // DFS -// const dfs=DFSWithSources(network, sources); -// // get new clusters : 'longest' paths from sources with DFS -// return longestPathFromDFS(graph,dfs,sources as string[]); -// } - - -// /** -// * The 'longest' (not the longest if undirected or directed cycle) path associated with each source with the DFS is found. BEWARE : the order of the id can change the result. -// * @param graph object for graph-data-structure library -// * @param dfs the return string (of nodes id) of a dfs (logically obtained with same sources as the sources for this functions) -// * @param sources array of node ID or a type of method to get sources automatically -// * RANK_ONLY : sources are nodes of rank 0 -// * SOURCE_ONLY : sources are topological sources of the network (nul indegree) -// * RANK_SOURCE : sources are node of rank 0, then source nodes -// * ALL : sources are all nodes -// * SOURCE_ALL : sources are topological sources, then all the others nodes -// * RANK_SOURCE_ALL : sources are node of rank 0, then topological sources, then all the other nodes -// * For this function, the advised choice is either RANK_ONLY, SOURCE_ONLY or RANK_SOURCE. -// * -// * @returns an object for the different path, the key is the source of the path -// */ -// function longestPathFromDFS(graph:{[key:string]:Function},DFSreversed:Array<string>,sources:Array<string>):{[key:string]:{nodes:Array<string>, height:number}}{ -// let dfs = Array.from(DFSreversed).reverse(); // the code has been done whith a backward reading of dfs - -// let longestPaths:{[key:string]:{nodes:Array<string>, height:number}}={}; -// let path:Array<string>; -// let source:string=undefined; -// let i=dfs.length-1; // index of node in dfs array -// let add=false; - -// while( i !== -1 ){ // dfs nodes are read backwards -// const visitedNode=dfs[i]; -// const previousNode: string = (dfs.length - 1 >= i + 1) ? dfs[i + 1] : undefined; - -// // if visited node is source -// if( sources.includes(visitedNode) ){ - -// if (source!==undefined){ -// // end the path (of the previous source, if one) -// longestPaths=endPath(source,longestPaths,path); -// // suppress nodes after the current node (those already analysed in while loop, because backward reading) -// dfs.splice(i + 1); -// } - -// // define new source and add to path -// source = visitedNode; -// longestPaths[source]={nodes:[source],height:1}; -// add=true; -// path=[source]; - -// // if there is a previous node -// } else if (previousNode){ -// // if visited node is child of the previous visited node in dfs : add to path -// if (nodeIsChildOf(graph,visitedNode,previousNode)){ -// add=true; -// path.push(visitedNode); -// }else{ -// // end the path if a node has been added in the last pass of the loop -// if (add && source!==undefined){ -// longestPaths=endPath(source,longestPaths,path); -// } -// // remove previous visited node if this node is not the parent of current node -// dfs.splice(i+1,1); -// path.splice(path.length-1); -// i++; // next loop pass will be on the same visited node (because the parent of the visited node wasn't found) -// add=false; // no node has been added -// } -// } - -// i--; //backward reading -// } -// return longestPaths; -// } - -// /** -// * Is the node a child of the parent node ? -// * @param graph object that contains function to get children of a node -// * @param node is this node a child of the parent? -// * @param parentNode the parent node -// * @returns boolean -// */ -// function nodeIsChildOf(graph:{[key:string]:Function},node:string, parentNode:string):boolean{ -// return graph.adjacent(parentNode).includes(node); -// } - -// /** -// * Check if the given path is longer than the one in the longest, if it is : update the path to keep the longest of the two -// * @param source source of the path (first node) -// * @param longestPaths -// * @param path the path to check -// * @returns the new longest paths -// */ -// function endPath(source:string, longestPaths:{[key:string]:{nodes:Array<string>, height:number}},path:Array<string>):{[key:string]:{nodes:Array<string>, height:number}}{ -// if (source in longestPaths){ -// if(longestPaths[source].height < path.length){ -// longestPaths[source]={nodes:path.slice(),height:path.length}; -// } -// }else{ -// console.error("source key not in object") -// } -// return longestPaths; -// } diff --git a/src/composables/LayoutManageSideCompounds.ts b/src/composables/LayoutManageSideCompounds.ts index 5b51fde891450e47d478cbb5554dbe8a61722ba2..680cdbb1b19cb654f64ba373ea5a1ec406bc33f1 100644 --- a/src/composables/LayoutManageSideCompounds.ts +++ b/src/composables/LayoutManageSideCompounds.ts @@ -13,33 +13,14 @@ import { sideCompoundAttribute,isDuplicate, isSideCompound, setAsSideCompound } - - /******************************************************************************************************************************************************* * * This file contains the functions to manage side compounds. - * - * ********************************* - * - * 0. Declare side compounds - * - * -> addSideCompoundAttributeFromList : - * add attribute of side compound to all nodes in network from a list - * - * -> getIDSideCompoundsInNetworkFromFile : - * return the list of id of side compounds in the network - * - * -> getIDSideCompoundsFromFile : - * return the list of id of side compounds from a file - * - * -> getContentFromURL : - * fetch url to return data - * - * + * ********************************** * * - * 1. Duplicate and remove side compounds + * 0. Duplicate and remove side compounds * * * -> putDuplicatedSideCompoundAside : @@ -58,7 +39,7 @@ import { sideCompoundAttribute,isDuplicate, isSideCompound, setAsSideCompound } * ********************************* * * - * 2. Reinsert side compounds + * 1. Reinsert side compounds * * -> reinsertionSideCompounds : * reinsert side compounds in the network @@ -72,6 +53,8 @@ import { sideCompoundAttribute,isDuplicate, isSideCompound, setAsSideCompound } * -> motifStampSideCompound : * applies a motif stamp to place side compound for a reaction * + ****** 1.0 Stamp motif : initialization + * * -> initializeReactionSideCompounds : * initializes a reaction for side compounds motif * @@ -81,6 +64,8 @@ import { sideCompoundAttribute,isDuplicate, isSideCompound, setAsSideCompound } * -> angleRadianSegment : * calculates the angle in radians between two points * + * ***** 1.1 Stamp motif : find intervals + * * -> addSideCompoundsIntervals : * finds the cofactor intervals for a given reaction * @@ -96,9 +81,13 @@ import { sideCompoundAttribute,isDuplicate, isSideCompound, setAsSideCompound } * -> sizeInterval : * calculates the size of an interval (between two metabolites) in a reaction * + * ***** 1.2 Stamp motif : find spacing + * * -> findSpacingSideCompounds : * finds spacing between side compounds * + * ***** 1.3 Stamp motif : give coordinates + * * -> giveCoordAllSideCompounds : * calculates the coordinates for all side compounds in a subgraph network * @@ -114,6 +103,7 @@ import { sideCompoundAttribute,isDuplicate, isSideCompound, setAsSideCompound } * -> giveCoordSideCompound : * calculates the coordinates for a side compound * + * ***** 1.4 Stamp motif : insert side compounds * -> insertAllSideCompoundsInNetwork : * inserts all side compounds in the network * @@ -121,93 +111,13 @@ import { sideCompoundAttribute,isDuplicate, isSideCompound, setAsSideCompound } * inserts a side compound in the network * * - * * * *******************************************************************************************************************************************************/ - - -/*******************************************************************************************************************************************************/ -//___________________________________________________0. Declare side compounds__________________________________________________________________________ - - - - -// /** -// * Add attribute of side compound to all nodes in network from a list -// * @param network -// * @param pathListSideCompounds path to the list of id of side compounds -// */ -// export async function addSideCompoundAttributeFromList(subgraphNetwork:SubgraphNetwork, pathListSideCompounds:string):Promise<void>{ -// const listIDSideCompounds = await getIDSideCompoundsInNetworkFromFile(subgraphNetwork,pathListSideCompounds); -// listIDSideCompounds.forEach((sideCompoundID) => { -// setAsSideCompound(subgraphNetwork.network,sideCompoundID); -// }); -// } - -// /** -// * Return the list of id of side compounds in the network -// * @param subgraphNetwork -// * @param pathListSideCompounds path to the list of id of side compounds -// * @returns list of id of side compounds in the network -// */ -// async function getIDSideCompoundsInNetworkFromFile(subgraphNetwork:SubgraphNetwork,pathListSideCompounds:string):Promise<string[]>{ -// let listIDSideCompounds:string[]; -// const network = subgraphNetwork.network; -// try { -// listIDSideCompounds = await getIDSideCompoundsFromFile(pathListSideCompounds); -// const sideCompoundInNetwork = Object.keys(network.nodes).filter(id => listIDSideCompounds.includes(id)); -// return sideCompoundInNetwork; -// } catch (error) { -// throw error; -// } -// } - -// /** -// * Return the list of id of side compounds from a file -// * @param pathListSideCompounds path to the list of id of side compounds -// * @returns list of id of side compounds -// */ -// async function getIDSideCompoundsFromFile(pathListSideCompounds:string):Promise<string[]>{ -// try { -// const sideCompoundsFile=pathListSideCompounds; -// const sideCompoundsString = await getContentFromURL(sideCompoundsFile); -// const lines = sideCompoundsString.split('\n'); -// const listId: Array<string> = []; -// lines.forEach((line: string) => { -// listId.push(line.split('\t')[0]); -// }) -// return listId; -// }catch (error) { -// throw error; -// } -// } - -// /** -// * Fetch url to return data -// * @param url URL to fetch -// * @returns Return response -// */ -// export async function getContentFromURL(url: string): Promise<string> { -// try { -// const response = await fetch(url); -// if (!response.ok) { -// throw new Error('La requête a échoué avec le statut ' + response.status); -// } -// const content = await response.text(); -// return content; -// } catch (error) { -// console.error('Une erreur s\'est produite lors de la récupération du contenu du fichier :', error); -// throw error; -// } -// } - - - /*******************************************************************************************************************************************************/ -//___________________________________________________1. Duplicate and remove side compounds__________________________________________________________________________ +//___________________________________________________0. Duplicate and remove side compounds__________________________________________________________________________ @@ -222,10 +132,6 @@ import { sideCompoundAttribute,isDuplicate, isSideCompound, setAsSideCompound } */ export async function putDuplicatedSideCompoundAside(subgraphNetwork:SubgraphNetwork, doDuplicateSideCompounds:boolean,doPutAsideSideCompounds:boolean):Promise<SubgraphNetwork>{ try { - // finding side compounds in network - // if (addSideCompoundAttribute){ - // await addSideCompoundAttributeFromList(subgraphNetwork,pathListSideCompounds); - // } // duplication of side compounds if (doDuplicateSideCompounds){ await duplicateSideCompound(subgraphNetwork); @@ -315,7 +221,7 @@ function removeSideCompoundsFromNetwork(subgraphNetwork:SubgraphNetwork): Subgra } /*******************************************************************************************************************************************************/ -//___________________________________________________2. Reinsert side compounds__________________________________________________________________________ +//___________________________________________________1. Reinsert side compounds__________________________________________________________________________ /** @@ -435,7 +341,7 @@ async function motifStampSideCompound(subgraphNetwork:SubgraphNetwork,reactionID /***********************************************************************/ -//______________2.1 Stamp motif : initialization +//______________1.0 Stamp motif : initialization /** @@ -531,7 +437,7 @@ function angleRadianSegment(x1:number,y1:number,x2:number,y2:number,clockwise:bo } /***********************************************************************/ -//______________2.2 Stamp motif : find intervals +//______________1.1 Stamp motif : find intervals @@ -708,7 +614,7 @@ function sizeInterval(reaction:Reaction,intervalIndex:number):number{ } /***********************************************************************/ -//______________2.3 Stamp motif : find spacing +//______________1.2 Stamp motif : find spacing async function findSpacingSideCompounds(reaction:Reaction,sizeInterval:number):Promise<{reactant:number|undefined,product:number|undefined}>{ @@ -722,7 +628,7 @@ async function findSpacingSideCompounds(reaction:Reaction,sizeInterval:number):P } /***********************************************************************/ -//______________2.4 Stamp motif : give coordinates +//______________1.3 Stamp motif : give coordinates /** @@ -838,7 +744,7 @@ function giveCoordSideCompound(sideCompound:Node,angle:number,center:{x:number,y /***********************************************************************/ -//______________2.4 Stamp motif : insertion in network +//______________1.4 Stamp motif : insertion in network /** diff --git a/src/composables/LayoutReversibleReactions.ts b/src/composables/LayoutReversibleReactions.ts index f801da831e58a7b3ae565d05e2b86bbef9ba864e..cc326725ede5fff81d54773965e117514b5bc114 100644 --- a/src/composables/LayoutReversibleReactions.ts +++ b/src/composables/LayoutReversibleReactions.ts @@ -8,8 +8,7 @@ import { NetworkLayout, NodeLayout } from "../types/NetworkLayout"; // Composable imports import { removeAllSelectedNodes } from "./VizCoreFunctions"; import { BFSWithSources } from "./AlgorithmBFS"; -import { addLinkClassReversible, addMetadataReversibleWithClass, isReaction, isReversible } from "./GetSetAttributsNodes"; - +import { addLinkClassReversible, isReaction, isReversible } from "./GetSetAttributsNodes"; @@ -72,9 +71,6 @@ import { addLinkClassReversible, addMetadataReversibleWithClass, isReaction, isR export async function duplicateReversibleReactions(networkLayout:NetworkLayout):Promise<void> { try { - // add metadata "reversible" to nodes - console.warn("add metadata reversible if in the class. Not necessary if file with correct format (done bcs of the file I have) => to remove ?"); - await addMetadataReversibleWithClass(networkLayout); const newLinks: Array<Link> = []; //links associated with new reactions nodes @@ -191,25 +187,9 @@ async function reversibleNodeReaction(node: NodeLayout, suffix: string = "_rev") newNodeReversed=true; } - //const newLabel = label.endsWith(suffix) ? label.slice(0, -suffix.length) : label + suffix; - - //const newClasses: string[] = []; - // add classes of original reaction, - // and add class reversibleVersion if not present, removed if present - // classes.forEach(item =>{ - // newClasses.push(item) - // }); - // const revIndex = newClasses.indexOf("reversibleVersion"); - // if (revIndex !== -1) { - // newClasses.splice(revIndex, 1); - // }else{ - // newClasses.push("reversibleVersion"); - // } - const newNode: NodeLayout = { ...node, id: newId, - //metadata: {...node.metadata, reversibleVersion: id}, // to remove : doest work metadataLayout: {reversibleNodeVersion:id,isReversedVersion:newNodeReversed}, }; return newNode; @@ -321,7 +301,7 @@ export function keepFirstReversibleNode(subgraphNetwork:SubgraphNetwork,nodeOrde // remove one version of the reaction removeAllSelectedNodes(reactionToRemove,network); // rename the other if it was the reversible version that is keeped - console.warn("need to check if subgraph still exist ?") + if(doRename){ const subgraphNetworkRename=renameAllIDNode(subgraphNetwork,nodeToRename); return subgraphNetworkRename// return object renamed @@ -353,16 +333,6 @@ export function renameAllIDNode(subgraphNetwork:SubgraphNetwork,nodesToRename:{[ } }); - // Modify edges -> not necessary because pointer for links (not id of node) - // network.links.forEach(link => { - // if (nodesToRename[link.source.id]) { - // link.source = network.nodes[nodesToRename[link.source.id]]; - // } - // if (nodesToRename[link.target.id]) { - // link.target = network.nodes[nodesToRename[link.target.id]]; - // } - // }); - // Modify subgraphs // in cycles renameAllInSubgraph(subgraphNetwork,TypeSubgraph.CYCLE,nodesToRename); @@ -383,77 +353,15 @@ export function renameAllIDNode(subgraphNetwork:SubgraphNetwork,nodesToRename:{[ * @param typeSubgraph - The type of subgraph. * @param nodesToRename - The mapping of nodes to their new names. */ -function renameAllInSubgraph(subgraphNetwork:SubgraphNetwork, typeSubgraph:TypeSubgraph, nodesToRename:{[key: string]: string}){ +function renameAllInSubgraph(subgraphNetwork:SubgraphNetwork, typeSubgraph:TypeSubgraph, nodesToRename:{[key: string]: string}):void{ const subgraphs = subgraphNetwork[typeSubgraph] ? subgraphNetwork[typeSubgraph] : {}; Object.entries(subgraphs).forEach(([ID, subgraph]) => { subgraph.nodes = subgraph.nodes.map(node => { if(nodesToRename[node]){ - // change metadata of node to know in which subgraph it is - //console.warn("pk fonction ici ?"); - //updateNodeMetadataSubgraph(subgraphNetwork.network.value, nodesToRename[node], ID, typeSubgraph); // change the name of the node in the subgraph return nodesToRename[node]; } return node; }); }); -} - - - - -// export function renameIDNode(subgraphNetwork:SubgraphNetwork,oldName:string,newName:string):SubgraphNetwork{ -// const network = subgraphNetwork.network.value; -// if(oldName in network.nodes && !(newName in network.nodes)){ - -// // modify node : -// // insert new node with new name -// network.nodes[newName]=network.nodes[oldName]; -// const newNode=network.nodes[newName]; -// newNode.id=newName; -// // delete old node -// delete network.nodes[oldName]; - -// // modify edges : -// // when the node is source -// const linksOldNodeAsSource = Object.values(network.links).filter((link) => { -// return link.source.id === oldName; -// }); -// linksOldNodeAsSource.forEach((link) => { -// link.source = newNode; -// }); -// // when the node is target -// const linksOldNodeAsTarget = Object.values(network.links).filter((link) => { -// return link.target.id === oldName; -// }); -// linksOldNodeAsTarget.forEach((link) => { -// link.target = newNode; -// }); - -// // modify subgraphs : -// // in cycles -// renameInSubgraph(subgraphNetwork,TypeSubgraph.CYCLE,oldName,newName); -// // in main chains -// renameInSubgraph(subgraphNetwork,TypeSubgraph.MAIN_CHAIN,oldName,newName); -// // in secondary chains -// renameInSubgraph(subgraphNetwork,TypeSubgraph.SECONDARY_CHAIN,oldName,newName); - -// return subgraphNetwork; - -// }else{ -// console.log("Error : impossible to rename node "+oldName+" to "+newName+", node already exist or not found in network."); -// } -// } - -// function renameInSubgraph(subgraphNetwork:SubgraphNetwork,typeSubgraph:TypeSubgraph,oldName:string,newName:string){ -// const subgraphs = subgraphNetwork[typeSubgraph]? subgraphNetwork[typeSubgraph]:{}; -// Object.entries(subgraphs).forEach(([ID,subgraph])=>{ -// if(subgraph.nodes.includes(oldName)){ -// // change the name of the node in the subgraph -// subgraph.nodes = subgraph.nodes.map(node => node === oldName ? newName : node); -// // change metadata of node to know in which subgraph it is -// updateNodeMetadataSubgraph(subgraphNetwork.network.value, newName, ID,typeSubgraph); //newName because the node has been renamed -// } -// }); -// } - +} \ No newline at end of file diff --git a/src/composables/LayoutSugiyama.ts b/src/composables/LayoutSugiyama.ts index 117ff68305d1f7247f11602eece3fada55daa481..ca42c17508feb9dc650e3a0ed9a7830ec2509764 100644 --- a/src/composables/LayoutSugiyama.ts +++ b/src/composables/LayoutSugiyama.ts @@ -14,9 +14,6 @@ import { instance } from "@viz-js/viz"; /** * This file contains functions to apply layout algorithms to a network. * - * -> dagreLayout : - * Take a network object and change the (x,y) position of the node with dagre lib - * * -> vizLayout : * Take a network object and change the (x,y) position of the node with viz lib * @@ -26,26 +23,6 @@ import { instance } from "@viz-js/viz"; - -/** - * Take a network object and change the (x,y) position of the node with dagre lib - * @param {Network} Network object - * @param graphAttributes for dagre layout (see https://github.com/dagrejs/dagre/wiki) - * @param [callbackFunction=() => {}] function to do after the layout is done - */ -// export function dagreLayout(network: Network,graphAttributes={},callbackFunction = () => {}):void { - -// setTimeout(async function() { -// let graphDagre = networkToDagre(network,graphAttributes); -// dagre.layout(graphDagre); -// changeNetworkFromDagre(graphDagre, network).then(() => { -// callbackFunction(); -// }); -// }, 1); - -// } - - /** * Take a network object and change the (x,y) position of the node with viz lib * @param {Network} Network object @@ -69,146 +46,3 @@ export async function vizLayout(subgraphNetwork:SubgraphNetwork,assignRank:boole }); return subgraphNetwork; } - - - -/** - * Applies the force-directed layout algorithm to the given network. - * Use cytoscapes' cose-bilkent layout. - * - * @param network - The network to apply the layout to. - * @param networkStyle - The style properties of the network. - * @param shiftCoord - Optional. Specifies whether to shift the coordinates of the nodes to the top-left corner. Defaults to false. - * @returns A Promise that resolves to the updated network after applying the layout. - */ -// export async function forceLayout(network: Network, networkStyle:GraphStyleProperties, shiftCoord: boolean = false): Promise<Network> { - -// //cytoscape.use(fcose); -// cytoscape.use(cosebilkent); - -// const size=await getMeanNodesSizePixel(Object.values(network.nodes), networkStyle,false); -// const edgeFactor=3; -// const edgeLength = Math.max(size.height, size.width) * edgeFactor; - -// const layout ={ -// name:"cose-bilkent", //fcose -// animate: false, -// randomize: false, -// idealEdgeLength: edgeLength, -// nodeRepulsion: 70000, // high number if randomize = false -// gravity : 0.001, -// numIter: 3000 - -// } - -// let cyto = networkToCytoscape(network,true); - -// await new Promise<void>((resolve) => { -// cyto.ready(function () { -// setTimeout(function () { -// cyto.elements().layout(layout).run(); -// resolve(); -// }, 5000); -// }); -// }); - -// if (shiftCoord) { -// shiftAllToGetTopLeftCoord(network, networkStyle); -// } - -// const json = cyto.json(); -// changeNetworkFromCytoscape(json, network); - -// return network; -// } - - - - -// /** -// * Take a network and apply a d3 force layout algorithm on WITHOUT simulation -// * @param network Network object -// * @returns {Network} Network object with d3 force layout apply on -// */ -// export async function forceLayout3(network: Network, autoRescale: Boolean = false): Promise<Network> { -// const seuil = 0.04; -// const maxiter = 1000; -// const minMovement = 0.01; -// const listNodesID=Object.keys(network.nodes); -// let svgHeight = screen.height; -// let svgWidth = screen.width; - -// const simulation = d3.forceSimulation(Object.values(network.nodes)) -// .force('link', d3.forceLink() -// .id((d: any) => d.id) -// .links(network.links) -// ) -// .force('charge', d3.forceManyBody()) -// .velocityDecay(0.1) -// .force('center', d3.forceCenter(svgWidth / 2, svgHeight / 2)) -// .stop(); - -// await sendTick(); - -// async function sendTick() { -// let iter=0; -// let lastPositions = new Map(Object.values(network.nodes).map(node => [node.id, { x: node.x, y: node.y }])); -// while (iter < maxiter) { -// iter++; -// simulation.tick(); - -// let maxMovement = 0; -// for (let nodeID of listNodesID) { -// const node=network.nodes[nodeID]; -// const lastPos = lastPositions.get(nodeID); -// const dx = node.x - lastPos.x; -// const dy = node.y - lastPos.y; -// const distance = Math.sqrt(dx * dx + dy * dy); - -// if (distance > maxMovement) { -// maxMovement = distance; -// } - -// lastPositions.set(node.id, { x: node.x, y: node.y }); -// } - -// if (maxMovement < minMovement) { -// console.log('Force layout converged after ' + iter + ' iterations'); -// break; -// }else{ -// console.log(iter); -// } -// } -// } - -// return network; -// } - - -// export async function forceLayout2(network: Network, autoRescale: Boolean = false): Promise<Network> { -// let svgHeight = screen.height; -// let svgWidth = screen.width; - -// const simulation = d3.forceSimulation(Object.values(network.nodes)) -// .force('link', d3.forceLink() -// .id((d: any) => { -// return d.id; -// }) -// .links(network.links) -// ) -// .force('charge', d3.forceManyBody()) -// .force('center', d3.forceCenter(svgWidth / 2, svgHeight / 2)) -// .alphaMin(0.4) -// .stop(); - -// await sendTick(); - -// async function sendTick() { -// for (let i = simulation.alpha(); i > 0.4; i = simulation.alpha()) { -// simulation.tick(); -// } -// } - -// return network; - -// } diff --git a/src/composables/MetricsApplication.ts b/src/composables/MetricsApplication.ts deleted file mode 100644 index 7a6b41be71e258815596a333117dcd2e4b367701..0000000000000000000000000000000000000000 --- a/src/composables/MetricsApplication.ts +++ /dev/null @@ -1,329 +0,0 @@ -// import { ref } from "vue"; -// import { getContentFromURL, importNetworkFromURL } from "./importNetwork"; -// import { Network } from "@metabohub/viz-core/src/types/Network"; -// import { GraphStyleProperties } from "@metabohub/viz-core/src/types/GraphStyleProperties"; -// import { SubgraphNetwork } from "../types/SubgraphNetwork"; -// import { addSideCompoundAttributeFromList, duplicateSideCompound, putDuplicatedSideCompoundAside } from "./LayoutManageSideCompounds"; -// import { createStaticForceLayout } from "@metabohub/viz-core"; -// import { Parameters,defaultParameters } from "../types/Parameters"; -// import { forceLayout, vizLayout } from "./LayoutSugiyamaForce"; -// import { Algo, PathType } from "../types/EnumArgs"; -// import { countIntersectionEdgeNetwork, countOverlapNodeNetwork, countOverlapNodeEdgeNetwork, countDifferentCoordinatesNodeNetwork, countNodes, countEdges, coefficientOfVariationEdgeLength, analyseDirectorVector } from "./MetricsCalculation"; -// import { TypeSubgraph } from "../types/Subgraph"; -// import { networkToGDSGraph } from "./ConvertFromNetwork"; -// import { allSteps } from "./LayoutMain"; - - -// export async function analyseAllJSON(pathListJSON: string,algo:Algo=Algo.DEFAULT,metricGraph:boolean=true): Promise<void> { -// const jsonFileString = await getContentFromURL(pathListJSON); -// const allJson = jsonFileString.split('\n'); -// let resultGraphAllJSON: Array<Array<number>> = []; -// let resultLayoutAllJSON: Array<Array<number>> = []; -// let nameMetrics:{graph:string[],layout:string[]}= {graph:[],layout:[]}; -// let nameFile: string[] = []; - -// // which layout to apply -// let applyLayout: (subgraph: SubgraphNetwork) => Promise<SubgraphNetwork> =defaultApplyLayout; -// switch (algo) { -// case Algo.FORCE: -// console.log('apply Force'); -// applyLayout = applyForceLayout; -// console.warn('Use of timeout so exec time is not accurate (no comparison possible)'); -// break; -// case Algo.VIZ: -// console.log('apply Viz'); -// applyLayout = applyVizLayout; -// break; -// case Algo.ALGO: -// console.log('applyAlgo : default'); -// applyLayout = applyAlgo; -// break; -// case Algo.ALGO_V0: -// console.log('applyAlgo_V0: no main chain'); -// applyLayout = applyAlgo_V0; -// break; -// case Algo.ALGO_V1: -// console.log('applyAlgo_V1 : longuest'); -// applyLayout = applyAlgo_V1; -// break; -// case Algo.ALGO_V3: -// console.log('applyAlgo_V3 : all'); -// applyLayout = applyAlgo_V3; -// break; -// default: -// console.log('no change'); -// applyLayout = defaultApplyLayout; -// break; -// } -// let firstJSON=true; -// for (const json of allJson) { -// console.log(json); -// const resultJSON= await analyseJSON(json,metricGraph,applyLayout,false); -// if (firstJSON){ -// nameMetrics.graph=resultJSON.graph.nameMetrics; -// nameMetrics.layout=resultJSON.layout.nameMetrics; -// firstJSON=false; -// } -// if (resultJSON.graph !== undefined){ -// resultGraphAllJSON.push(resultJSON.graph.result); -// } -// if (resultJSON.layout !== undefined){ -// nameFile.push(json); -// resultLayoutAllJSON.push(resultJSON.layout.result); -// } - -// } - -// if (metricGraph){ -// print1DArray(nameMetrics.graph); -// print2DArray(resultGraphAllJSON); -// } -// print1DArray(nameMetrics.layout); -// print2DArray(resultLayoutAllJSON); - -// console.warn("If apply metrics on another layout : refresh the page, else results are the same than last time (idk why)"); -// console.warn('Some metrics are calculated without side compounds'); -// } - - -// async function analyseJSON(json: string, metricGraph:boolean=true, applyLayout: (subgraph: SubgraphNetwork) => Promise<SubgraphNetwork> =defaultApplyLayout,printColumnName:boolean=true): -// Promise<{graph:{nameMetrics:string[],result:number[]},layout:{nameMetrics:string[],result:number[]}} | undefined> { - -// // initialize objects -// const networkForJSON = ref<Network>({ id: '', nodes: {}, links: [] }); -// const networkStyleforJSON = ref<GraphStyleProperties>({ -// nodeStyles: {}, -// linkStyles: {} -// }); -// let startTime:number; -// let endTime:number; -// let subgraphNetwork:SubgraphNetwork; -// let resultGraph: {nameMetrics:string[],result:number[]}= {nameMetrics:[],result:[]}; -// let resultLayout:{nameMetrics:string[],result:number[]}= {nameMetrics:[],result:[]}; - -// // import network from JSON, and process it -// try { -// await new Promise<void>((resolve, reject) => { -// try { -// importNetworkFromURL(json, networkForJSON, networkStyleforJSON, () => { -// //// Callback function (after network imported) : - -// // set style (same for all) -// changeNodeStyles(networkStyleforJSON.value); -// // create subgraphNetwork object -// subgraphNetwork={network:networkForJSON,networkStyle:networkStyleforJSON,attributs:{},mainChains:{}}; -// // duplicate side compounds -// addSideCompoundAttributeFromList(subgraphNetwork,"/sideCompounds.txt").then( -// ()=>{ -// duplicateSideCompound(subgraphNetwork); -// } -// ).then( -// ()=>{ -// // calculate metrics of graph -// if (metricGraph) { -// const metricsGraph=applyMetricsGraph(subgraphNetwork.network.value,printColumnName); -// resultGraph.result=metricsGraph.metrics -// resultGraph.nameMetrics=metricsGraph.nameMetrics; -// } -// } -// ).then( -// ()=>{ -// startTime = performance.now(); -// } -// ).then( -// async ()=>{ -// // apply layout -// subgraphNetwork=await applyLayout(subgraphNetwork); -// } -// ).then( -// ()=>{ -// endTime = performance.now(); -// } -// ).then( -// ()=>{ -// // calculate metrics on resulting layout -// const metricsLayout=applyMetricsLayout(subgraphNetwork,true,printColumnName); -// resultLayout.result= metricsLayout.metrics; -// resultLayout.nameMetrics=metricsLayout.nameMetrics; -// resolve(); -// } -// ); - -// }); -// } catch (error) { -// reject(error); -// } -// }); -// } catch (error) { -// console.error("error file : " + json + "\n" + error); -// return undefined; -// } -// // add execution time of layout only (not duplication side compounds) -// const executionTime = parseFloat((endTime - startTime).toFixed(3)); -// if (executionTime) { -// resultLayout.result.push(executionTime); -// resultLayout.nameMetrics.push('execution time (ms)'); -// } - -// return {graph:resultGraph,layout:resultLayout}; -// } - - -// function changeNodeStyles(networkStyle:GraphStyleProperties):void{ -// networkStyle.nodeStyles = { -// metabolite: { -// width: 25, -// height: 25, -// fill: '#FFFFFF', -// shape: 'circle' -// }, -// sideCompound: { -// width: 12, -// height: 12, -// fill: '#f0e3e0', -// shape: 'circle' -// }, -// reaction: { -// width: 15, -// height: 15, -// fill: "grey", -// shape: 'rect' -// }, -// // reversible : { -// // fill : "green", -// // shape:"inverseTriangle" -// // }, -// // reversibleVersion:{ -// // fill:"red", -// // shape: "triangle" -// // } - -// } -// } - -// function print1DArray(data: Array<string|number|boolean>): void { -// const stringData = data.join(','); -// console.log(stringData); -// } - -// function print2DArray(data: Array<Array<string|number|boolean>>): void { -// const stringData = data.map(row => row.join(',')).join('\n'); -// console.log(stringData); -// } - - - -// const defaultApplyLayout = async (subgraphNetwork: SubgraphNetwork): Promise<SubgraphNetwork> => { -// return subgraphNetwork; -// }; - -// const applyForceLayout = (subgraphNetwork: SubgraphNetwork): Promise<SubgraphNetwork> => { -// const network=subgraphNetwork.network.value; -// const styleNetwork= subgraphNetwork.networkStyle.value; -// const subgraphNetworkPromise = new Promise<SubgraphNetwork>(async (resolve, reject) => { -// try { -// await forceLayout(network, styleNetwork, false); -// resolve(subgraphNetwork); -// } catch (error) { -// reject(error); -// } -// }); -// return subgraphNetworkPromise; -// }; - -// const applyVizLayout = async (subgraphNetwork: SubgraphNetwork): Promise<SubgraphNetwork> => { -// let parameters: Parameters = defaultParameters; -// const subgraphNetworkPromise = new Promise<SubgraphNetwork>((resolve, reject) => { -// resolve(vizLayout(subgraphNetwork, false, false, parameters.addNodes, parameters.groupOrCluster, false, false, parameters.dpi, parameters.numberNodeOnEdge)) -// }) -// return subgraphNetworkPromise; -// }; - -// const applyAlgo = async (subgraphNetwork: SubgraphNetwork): Promise<SubgraphNetwork> => { -// let parameters: Parameters=defaultParameters; -// const subgraphNetworkPromise = new Promise<SubgraphNetwork>((resolve, reject) => { -// resolve(allSteps(subgraphNetwork,parameters,false)); -// }) -// return subgraphNetworkPromise; -// }; - -// const applyAlgo_V0 = async (subgraphNetwork: SubgraphNetwork): Promise<SubgraphNetwork> => { -// let parameters: Parameters=defaultParameters; -// parameters.doMainChain=false; -// const subgraphNetworkPromise = new Promise<SubgraphNetwork>((resolve, reject) => { -// resolve(allSteps(subgraphNetwork,parameters,false)); -// }) -// return subgraphNetworkPromise; -// }; - -// const applyAlgo_V1 = async (subgraphNetwork: SubgraphNetwork): Promise<SubgraphNetwork> => { -// let parameters: Parameters=defaultParameters; -// parameters.pathType=PathType.LONGEST; -// const subgraphNetworkPromise = new Promise<SubgraphNetwork>((resolve, reject) => { -// resolve(allSteps(subgraphNetwork,parameters,false)); -// }) -// return subgraphNetworkPromise; -// }; - -// const applyAlgo_V3 = async (subgraphNetwork: SubgraphNetwork): Promise<SubgraphNetwork> => { -// let parameters: Parameters=defaultParameters; -// parameters.pathType=PathType.ALL; -// const subgraphNetworkPromise = new Promise<SubgraphNetwork>((resolve, reject) => { -// resolve(allSteps(subgraphNetwork,parameters,false)); -// }) -// return subgraphNetworkPromise; -// }; - - - - -// export function applyMetricsGraph(network: Network,printColumnName:boolean=true): {nameMetrics:string[],metrics:number[]} { -// const networkGDS=networkToGDSGraph(network); -// const result: number[]=[]; - -// const nameColumnGraph: string[] = ['nodes', 'node not side compound','edges','edge not side compound', 'hasDirectedCycle' ]; -// if (printColumnName) print1DArray(nameColumnGraph); - -// // number of nodes -// result.push(countNodes(network,true)); -// // number of nodes not side compounds -// result.push(countNodes(network,false)); -// // number of edges -// result.push(countEdges(network,true)); -// // number of edges not side compounds -// result.push(countEdges(network,false)); -// // has directed cycle -// result.push(Number(networkGDS.hasCycle())); - -// return {nameMetrics:nameColumnGraph,metrics:result}; -// } - -// export function applyMetricsLayout(subgraphNetwork: SubgraphNetwork, coordAreCenter:boolean=true, printColumnName:boolean=true): {nameMetrics:string[],metrics:number[]} { -// const network=subgraphNetwork.network.value; -// const networkStyle=subgraphNetwork.networkStyle.value; -// const networkGDS=networkToGDSGraph(network); -// const result: number[]=[]; - -// const nameColumnLayout: string[] = ['node overlap', 'edge node overlap', 'different x (not SD)' ,'different y (not SD)','edge intersections','coef var edge length (no SD)','% colineat axis (not SD)', 'coef var vect dir (not SD)']; -// if (printColumnName) print1DArray(nameColumnLayout); - - -// //number of node overlap -// result.push(countOverlapNodeNetwork(network,networkStyle,coordAreCenter)); -// // number of edge node overlap -// result.push(countOverlapNodeEdgeNetwork(network,networkStyle,coordAreCenter)); -// // number of different x and y coordinates (without side compounds) -// const countDiffCoord=countDifferentCoordinatesNodeNetwork(network,networkStyle,coordAreCenter,false); -// result.push(countDiffCoord.x); -// result.push(countDiffCoord.y); -// // number of edges intersections -// result.push(countIntersectionEdgeNetwork(network,networkStyle,coordAreCenter)); -// // variance edge length (without side compounds?) -// result.push(coefficientOfVariationEdgeLength(network,networkStyle,coordAreCenter,false)); -// // direction edge : % of edge colinear to axis and coef of variaton of angle -// const resultDirection=analyseDirectorVector(network,networkStyle,coordAreCenter,true,false); -// result.push(resultDirection.colinearAxis) -// result.push(resultDirection.coefVariation) - -// return {nameMetrics:nameColumnLayout,metrics:result}; -// } diff --git a/src/composables/MetricsCalculation.ts b/src/composables/MetricsCalculation.ts deleted file mode 100644 index 522a6d35cd721be8544dae2f33c46497d2a712d7..0000000000000000000000000000000000000000 --- a/src/composables/MetricsCalculation.ts +++ /dev/null @@ -1,448 +0,0 @@ -// import { Link } from "@metabohub/viz-core/src/types/Link"; -// import { Network } from "@metabohub/viz-core/src/types/Network"; -// import { Node } from "@metabohub/viz-core/src/types/Node"; -// import { getTopLeftCoordFromCenter, getSizeNodePixel, getCenterCoordFromTopLeft } from "./CalculateSize"; -// import { checkIntersection } from "line-intersect"; -// import { Coordinate,Size } from "../types/CoordinatesSize"; -// import { GraphStyleProperties } from "@metabohub/viz-core/src/types/GraphStyleProperties"; - -// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// //---------------------------------------------------- Utilitary Functions -----------------------------------------------------------// -// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - -// export function getCenterNode(node: Node,networkStyle:GraphStyleProperties,coordAreCenter:boolean=false): Coordinate { -// let nodeCenter: {x:number,y:number}; - -// if (coordAreCenter) { -// nodeCenter={x:node.x,y:node.y}; -// }else{ -// nodeCenter=getCenterCoordFromTopLeft(node,networkStyle); -// } -// return nodeCenter; -// } - - -// function commonNodeBetween2Links(link1: Link,link2: Link): boolean { -// if (link1.source==link2.source || link1.source==link2.target || link1.target==link2.source || link1.target==link2.target) { -// return true; -// }else { -// return false; -// } -// } - -// export function countNodes(network: Network, countSideCompound: boolean = true): number { -// if (countSideCompound) { -// return Object.keys(network.nodes).length; -// } else { -// let nodes = 0; -// Object.keys(network.nodes).forEach((nodeID) => { -// const node = network.nodes[nodeID]; -// if (!(node.metadata && node.metadata["isSideCompound"])) { -// nodes += 1; -// } -// }); -// return nodes; -// } -// } - -// export function countEdges(network: Network, countSideCompound: boolean = true): number { -// if (countSideCompound) { -// return network.links.length; -// } else { -// let links = 0; -// network.links.forEach(link => { -// if (!(link.source.metadata && link.source.metadata["isSideCompound"]) && !(link.target.metadata && link.target.metadata["isSideCompound"])) { -// links += 1; -// } -// }); -// return links; -// } -// } - -// function getNormalizedDirectorVector(link: Link, style: GraphStyleProperties, coordAreCenter: boolean = false): Coordinate { - -// const sourceCenter = getCenterNode(link.source, style, coordAreCenter); -// const targetCenter = getCenterNode(link.target, style, coordAreCenter); - -// const dx = targetCenter.x - sourceCenter.x; -// const dy = targetCenter.y - sourceCenter.y; - -// const length = edgeLength(link, style, coordAreCenter); - -// if (length === 0) { -// return { x: 0, y: 0 }; // Handle case with zero length -// } - -// return { -// x: parseFloat((dx / length).toFixed(2)), -// y: parseFloat((dy / length).toFixed(2)) -// }; -// } - -// function linkOfSideCompound(link:Link):boolean{ -// return (link.source.metadata && (link.source.metadata["isSideCompound"]) as boolean) || (link.target.metadata && (link.target.metadata["isSideCompound"]) as boolean); -// } - - -// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// //-------------------------------------------------------- Node Metrics --------------------------------------------------------------// -// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - - -// ///////////////////////////////////////////////////// -// // ------------------------- Node overlap - - -// export function countOverlapNodeNetwork(network: Network,networkStyle:GraphStyleProperties,coordAreCenter:boolean=false): number { -// let nb=0; -// const nodesID=Object.keys(network.nodes); - -// for (let i=0 ; i<nodesID.length ; i++) { -// for (let j=i+1 ; j<nodesID.length ; j++) { -// // node1 -// const node1=network.nodes[nodesID[i]]; -// const coordNode1=getCenterNode(node1,networkStyle,coordAreCenter); -// const sizeNode1=getSizeNodePixel(node1,networkStyle); -// // node2 -// const node2=network.nodes[nodesID[j]]; -// const coordNode2=getCenterNode(node2,networkStyle,coordAreCenter); -// const sizeNode2=getSizeNodePixel(node2,networkStyle); - -// if (nodesOverlap(coordNode1,sizeNode1,coordNode2,sizeNode2)){ -// nb+=1; -// } -// } -// } -// return nb; -// } - - - -// function nodesOverlap(coord1: Coordinate, size1: Size, coord2: Coordinate, size2: Size): boolean { - -// // coordinate are center - -// if ( !size1.width || !size1.height || !size2.width || !size2.height || !coord1.x || !coord1.y || !coord2.x || !coord2.y) { -// // Handle null or undefined inputs appropriately -// return false; -// } - -// // rectangle 1 -// const left1 = coord1.x - size1.width / 2; -// const right1 = coord1.x + size1.width / 2; -// const top1 = coord1.y - size1.height / 2; -// const bottom1 = coord1.y + size1.height / 2; - -// // rectangle 2 -// const left2 = coord2.x - size2.width / 2; -// const right2 = coord2.x + size2.width / 2; -// const top2 = coord2.y - size2.height / 2; -// const bottom2 = coord2.y + size2.height / 2; - -// // overlap? -// const overlapX = left1 < right2 && right1 > left2; -// const overlapY = top1 < bottom2 && bottom1 > top2; - -// return overlapX && overlapY; -// } - - -// ///////////////////////////////////////////////////// -// // ------------------------- Node on edge - - - -// export function countOverlapNodeEdgeNetwork(network: Network,networkStyle:GraphStyleProperties,coordAreCenter:boolean=false): number { -// let nb=0; -// const nodesID=Object.keys(network.nodes); -// nodesID.forEach( (nodeID) =>{ - -// const node=network.nodes[nodeID]; -// const coordNode1=getCenterNode(node,networkStyle,coordAreCenter); -// const sizeNode=getSizeNodePixel(node,networkStyle); -// nb += countOverlapEdgeForNode(network,networkStyle,nodeID,coordNode1,sizeNode,coordAreCenter); - -// }); - -// return nb; -// } - -// function countOverlapEdgeForNode(network:Network,networkStyle:GraphStyleProperties,nodeID:string,coordNode:Coordinate,sizeNode:Size,coordAreCenter:boolean=false): number { -// let nb=0; - -// network.links.forEach(link => { -// // if node not linked to the edge : check if it is on the edge -// if(!(link.source.id==nodeID || link.target.id==nodeID)){ - -// let coordSource=getCenterNode(link.source,networkStyle,coordAreCenter); -// let coordTarget=getCenterNode(link.target,networkStyle,coordAreCenter); - -// if (nodeEdgeOverlap(coordNode,sizeNode,coordSource,coordTarget)){ -// nb+=1; -// } -// } -// }); -// return nb; -// } - - -// function nodeEdgeOverlap(centerCoordNode: Coordinate, sizeNode: Size, coordSource: Coordinate, coordTarget: Coordinate): boolean { // CORRIGER !!!!! - -// // Treat the node as a rectangle (coordinates are center of node) -// const rect = { -// left: centerCoordNode.x - sizeNode.width / 2, -// right: centerCoordNode.x + sizeNode.width / 2, -// top: centerCoordNode.y - sizeNode.height / 2, -// bottom: centerCoordNode.y + sizeNode.height / 2 -// }; - -// // Check if any of the edge's endpoints is inside the rectangle => same as node overlap (to suppress ?) -// const isPointInsideRect = (point: Coordinate) => -// point.x >= rect.left && point.x <= rect.right && point.y >= rect.top && point.y <= rect.bottom; - -// if (isPointInsideRect(coordSource) || isPointInsideRect(coordTarget)) { -// return true; // One of the endpoints is inside the rectangle -// } - -// // Check for overlap between the edge and the sides of the rectangle -// // Convert the sides of the rectangle into line segments -// const rectangleEdges = [ -// { start: { x: rect.left, y: rect.top }, end: { x: rect.right, y: rect.top } }, // Top -// { start: { x: rect.right, y: rect.top }, end: { x: rect.right, y: rect.bottom } }, // Right -// { start: { x: rect.left, y: rect.bottom }, end: { x: rect.right, y: rect.bottom } }, // Bottom -// { start: { x: rect.left, y: rect.top }, end: { x: rect.left, y: rect.bottom } } // Left -// ]; - -// // Use checkIntersection function to check if two line segments intersect -// for (const edge of rectangleEdges) { -// const result = checkIntersection(edge.start.x,edge.start.y, edge.end.x,edge.end.y, coordSource.x, coordSource.y,coordTarget.x,coordTarget.y); -// if (result.type === "intersecting") { -// return true; // There is an overlap -// } -// } - -// return false; // No overlap detected -// } - - -// ///////////////////////////////////////////////////// -// // ------------------------- Node different coordinates - -// export function countDifferentCoordinatesNodeNetwork(network: Network, networkStyle: GraphStyleProperties, coordAreCenter: boolean = false, countSideCompound:boolean=true,roundAt: number = 2): { x: number, y: number } { -// let uniqueX = new Set<number>(); -// let uniqueY = new Set<number>(); - -// Object.keys(network.nodes).forEach((nodeID) => { -// const node = network.nodes[nodeID]; -// // Do not count side compounds if countSideCompound is false -// if (countSideCompound || !(node.metadata && node.metadata["isSideCompound"])) { -// const coordNode = getCenterNode(node, networkStyle, coordAreCenter); - -// // Round the coordinates based on roundAt -// const roundedX = parseFloat(coordNode.x.toFixed(roundAt)); -// const roundedY = parseFloat(coordNode.y.toFixed(roundAt)); - -// uniqueX.add(roundedX); -// uniqueY.add(roundedY); -// } -// }); - -// return { x: uniqueX.size, y: uniqueY.size }; -// } - -// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// //-------------------------------------------------------- Edge Metrics --------------------------------------------------------------// -// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - - -// ///////////////////////////////////////////////////// -// // ------------------------- Edge intersection -// // (overlap not taken into account) - - -// /** -// * Counts how many crossings are in a network -// * @param network the network -// * @returns the number of crossings -// */ -// export function countIntersectionEdgeNetwork(network: Network,style:GraphStyleProperties,coordAreCenter:boolean=false): number { -// let nb: number = 0; -// for (let i=0 ; i<network.links.length ; i++) { -// for (let j=i+1 ; j<network.links.length ; j++) { -// const link1=network.links[i]; -// const link2=network.links[j]; -// if (edgesIntersect(link1, link2,style,coordAreCenter)){ -// nb++; -// } -// } -// } -// return nb; -// } - -// function edgesIntersect(link1: Link, link2: Link,style:GraphStyleProperties,coordAreCenter:boolean=false): boolean { - -// // Case of common node -// if (commonNodeBetween2Links(link1,link2)) { -// return false; -// } - -// // Get center of node : where the link is attached -// const node1Center=getCenterNode(link1.source,style,coordAreCenter); -// const node2Center=getCenterNode(link1.target,style,coordAreCenter); -// const node3Center=getCenterNode(link2.source,style,coordAreCenter); -// const node4Center=getCenterNode(link2.target,style,coordAreCenter); - - -// // Check intersection -// const result = checkIntersection(node1Center.x, node1Center.y, node2Center.x, node2Center.y, node3Center.x, node3Center.y, node4Center.x, node4Center.y); -// if (result.type == "intersecting") { -// return true; -// } else { -// return false; -// } - -// } - -// ///////////////////////////////////////////////////// -// // ------------------------- Edge length - - -// export function coefficientOfVariationEdgeLength(network: Network,style:GraphStyleProperties,coordAreCenter:boolean=false,includeSideCompounds:boolean=true): number { - -// let links = network.links; - -// if (!includeSideCompounds) { -// links = links.filter(link => -// !(link.source.metadata && link.source.metadata["isSideCompound"]) && -// !(link.target.metadata && link.target.metadata["isSideCompound"]) -// ); -// } - -// if (links.length === 0) { -// return 0; // Handle case with no edge -// } - -// const lengths = links.map(link => edgeLength(link, style, coordAreCenter)); - -// const mean = lengths.reduce((a, b) => a + b, 0) / lengths.length; -// if (mean === 0) { -// return 0; // Handle case with no edge lengths -// } -// const variance = lengths.reduce((a, b) => a + Math.pow(b - mean, 2), 0) / lengths.length; -// const stdDeviation = Math.sqrt(variance); -// const coefVariation = stdDeviation / Math.abs(mean); -// return parseFloat(coefVariation.toFixed(3)); -// } - -// function edgeLength(link: Link,style:GraphStyleProperties,coordAreCenter:boolean=false): number { -// const sourceCenter=getCenterNode(link.source,style,coordAreCenter); -// const targetCenter=getCenterNode(link.target,style,coordAreCenter); - -// const dx = sourceCenter.x - targetCenter.x; -// const dy = sourceCenter.y - targetCenter.y; -// return Math.sqrt(dx * dx + dy * dy); -// } - - - -// ///////////////////////////////////////////////////// -// // ------------------------- Edge colinear with axis -// // => function used with edge direction - -// function calculateNormalizedDirectorVectors(links: Link[], style: GraphStyleProperties, coordAreCenter: boolean = false,includeSideCompounds:boolean=true): Coordinate[] { -// const vectors: Coordinate[] = []; - -// links.forEach(link => { -// if (includeSideCompounds || !linkOfSideCompound(link)){ -// const normalizedVector = getNormalizedDirectorVector(link, style, coordAreCenter); -// vectors.push(normalizedVector); -// } - -// }); - -// return vectors; -// } - -// function isColinearAxisNetwork(vector:Coordinate): boolean { -// return vector.x === 0 || vector.y === 0; -// } - -// function countEdgeColinearAxisNetwork(vectors:Coordinate[], pourcentage:boolean=false): number { - -// if (vectors.length === 0) { -// return 0; -// } - -// let count = 0; -// vectors.forEach(vector => { -// if (isColinearAxisNetwork(vector)) { -// count += 1; -// } -// }); -// if (pourcentage) { -// return parseFloat((count / vectors.length).toFixed(2)); -// } -// return count; -// } - - -// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// //-------------------------------------------------------- Domain Metrics --------------------------------------------------------------// -// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - -// // WHEN CLEAN : fonction that said if sidecompound or not - -// ///////////////////////////////////////////////////// -// // ------------------------- Edge direction - -// export function analyseDirectorVector(network: Network, style: GraphStyleProperties, coordAreCenter: boolean = false, pourcentageColinearAxis:boolean=false, includeSideCompounds:boolean=true):{colinearAxis:number,coefVariation:number} { - -// const result: { colinearAxis: number, coefVariation: number } = { colinearAxis: undefined, coefVariation: undefined }; - -// let links = network.links; - -// if (!includeSideCompounds) { -// links = links.filter(link => -// !(link.source.metadata && link.source.metadata["isSideCompound"]) && -// !(link.target.metadata && link.target.metadata["isSideCompound"]) -// ); -// } - -// // get all normalized director vectors -// const vectors = calculateNormalizedDirectorVectors(links, style, coordAreCenter,includeSideCompounds); -// if (vectors.length==0) return { colinearAxis: 0, coefVariation: 0 } - -// // count colinear with axis -// result.colinearAxis = countEdgeColinearAxisNetwork(vectors,pourcentageColinearAxis); - -// // coeficient of variation of angle - -// // calculate angles of vectors -// const angles = vectors.map(vector => Math.atan2(vector.y, vector.x)); - -// // calculate mean of angles -// const mean = angles.reduce((a, b) => a + b, 0) / angles.length; -// if (mean === 0) { -// result.coefVariation = 0; // Handle case with no angles -// return result; -// } - -// // calculate variance of angles -// const variance = angles.reduce((a, b) => a + Math.pow(b - mean, 2), 0) / angles.length; - -// // calculate standard deviation -// const stdDeviation = Math.sqrt(variance); - -// // calculate coefficient of variation -// const coefVariation = stdDeviation / mean; -// result.coefVariation = parseFloat(coefVariation.toFixed(2)); - -// return result; - -// } - - diff --git a/src/composables/SBMLtoJSON.ts b/src/composables/SBMLtoJSON.ts deleted file mode 100644 index 4a16b9f44e1b8c9f6b7aef8516e35d670a040e66..0000000000000000000000000000000000000000 --- a/src/composables/SBMLtoJSON.ts +++ /dev/null @@ -1,160 +0,0 @@ -// import { parseString } from 'xml2js'; -// import type { JSONGraphFormat, XMLSpecies, XMLReactions } from '../types/JSONGraphFormat'; - -// /** -// * Return a number between min (inclusive) and max (inclusive) -// * @param min -// * @param max -// * @returns a number -// */ -// function getRandomInt(min: number, max: number): number { -// min = Math.ceil(min); -// max = Math.floor(max); -// return Math.floor(Math.random() * (max - min + 1)) + min; -// } - -// /** -// * Convert an xml graph into a JSON graph format -// * @param sbmlString the xml file as a string -// * @returns the graph as a Promise -// */ -// export async function sbml2json(sbmlString: string): Promise<JSONGraphFormat> { -// return new Promise((resolve, reject) => { -// parseString(sbmlString, { explicitArray: false }, (err, result) => { -// if (err) { -// console.log("Error during the parsing of the file"); -// console.log(err); -// reject(err); -// } else { -// const model = result.sbml.model; -// // graph to return -// const graph: JSONGraphFormat = { -// graph: { -// id: model.$.id, -// type: 'metabolic', -// metadata: { -// style: { -// nodeStyles: { -// metabolite: { -// width: 25, -// height: 25, -// strokeWidth: 1, -// shape: 'circle' -// }, -// reaction: { -// width: 15, -// height: 15, -// strokeWidth: 0.5, -// shape: 'rect', -// fill: 'grey' -// }, -// reversible: { -// fill: 'green', -// shape: 'inverseTriangle' -// }, -// reversibleVersion: { -// fill: 'red', -// shape: 'triangle' -// } -// } -// } -// }, -// nodes: {}, -// edges: [] -// } -// }; - -// // Transform species to nodes -// const speciesList = model.listOfSpecies.species; -// // add a metabolite node for each species -// speciesList.forEach((species: XMLSpecies) => { -// graph.graph.nodes[species.$.id] = { -// id: species.$.id, -// metadata: { -// classes: ['metabolite'], -// position: { -// x: getRandomInt(0, 100), -// y: getRandomInt(0, 100) -// } -// }, -// label: species.$.name -// }; -// }); - -// // Transform reactions to nodes and edges -// const reactions = model.listOfReactions.reaction; -// reactions.forEach((reaction: XMLReactions) => { -// const reactionId = reaction.$.id; - -// let classReversible :string; -// const isReversible=reaction.$.reversible; -// if (isReversible==="true"){ -// classReversible = "reversible"; -// }else{ -// classReversible = "irreversible"; -// } - -// // get the reactants and products for every reaction -// const reactants: string[] = []; -// if (reaction.listOfReactants.speciesReference != undefined && (reaction.listOfReactants.speciesReference as Partial<XMLSpecies>[]).length != undefined) { -// // type : array -// (reaction.listOfReactants.speciesReference as Partial<XMLSpecies>[]).forEach((ref: Partial<XMLSpecies>) => { -// reactants.push(ref.$.species); -// }); -// } else if (reaction.listOfReactants.speciesReference != undefined) { -// // type : object -// reactants.push((reaction.listOfReactants.speciesReference as Partial<XMLSpecies>).$.species); -// } -// const products: string[] = []; -// if (reaction.listOfProducts.speciesReference != undefined && (reaction.listOfProducts.speciesReference as Partial<XMLSpecies>[]).length != undefined) { -// // type : array -// (reaction.listOfProducts.speciesReference as Partial<XMLSpecies>[]).forEach((ref: Partial<XMLSpecies>) => { -// products.push(ref.$.species); -// }); -// } else if (reaction.listOfProducts.speciesReference != undefined) { -// // type : object -// products.push((reaction.listOfProducts.speciesReference as Partial<XMLSpecies>).$.species); -// } - -// // add the reaction as a node -// graph.graph.nodes[reactionId] = { -// id: reactionId, -// metadata: { -// classes: ['reaction',classReversible], -// position: { -// x: getRandomInt(0, 100), -// y: getRandomInt(0, 100) -// } -// }, -// label: reaction.$.name -// }; - -// // add the edges for the reaction and its reactants and products -// reactants.forEach((reactant: string) => { -// graph.graph.edges.push({ -// id: `${reactant}--${reactionId}`, -// source: reactant, -// target: reactionId, -// metadata: { -// classes: [classReversible] -// } -// }); -// }); -// products.forEach((product: string) => { -// graph.graph.edges.push({ -// id: `${reactionId}--${product}`, -// source: reactionId, -// target: product, -// metadata: { -// classes: [classReversible] -// } -// }); -// }); -// }); - -// // return the graph object -// resolve(graph); -// } -// }); -// }); -// } diff --git a/src/composables/SubgraphForViz.ts b/src/composables/SubgraphForViz.ts index d2d19e53a4bb232c832ce21826fd268f52c7a039..b479d2ac771c0c2042c6252f28eff6ddb3567f0b 100644 --- a/src/composables/SubgraphForViz.ts +++ b/src/composables/SubgraphForViz.ts @@ -97,7 +97,6 @@ function changeCycleMetanodes(subgraphNetwork:SubgraphNetwork,listNodeBefore:str let cycle:string; if (network.nodes[node].metadataLayout && network.nodes[node].metadataLayout[TypeSubgraph.CYCLEGROUP]){ cycle = network.nodes[node].metadataLayout[TypeSubgraph.CYCLEGROUP]; - //cycle=inBiggerCycle(cycle,subgraphNetwork) if(!(listNodeAfter.includes(cycle))){ // push node cycle listNodeAfter.push(cycle); diff --git a/src/composables/__tests__/AlgorithmDFS.test.ts b/src/composables/__tests__/AlgorithmDFS.test.ts index 232c795106e4fe3a2ee1de92756462f29cbc2070..203d358715ef6aa7517affa104ea8af3cf4edd2c 100644 --- a/src/composables/__tests__/AlgorithmDFS.test.ts +++ b/src/composables/__tests__/AlgorithmDFS.test.ts @@ -100,6 +100,7 @@ describe('AlgorithmDFS', () => { it('should return a DFS order, when no directed cycle', async () => { // MOCK + const removeEdgeMock = jest.fn(); const networkToGDSGraphMock = jest.spyOn(ConvertFromNetwork, 'networkToGDSGraph'); networkToGDSGraphMock.mockImplementation(async () => { return Promise.resolve({ @@ -124,7 +125,7 @@ describe('AlgorithmDFS', () => { return []; } }), - removeEdge: jest.fn() + removeEdge: removeEdgeMock }); }); @@ -147,9 +148,7 @@ describe('AlgorithmDFS', () => { // EXPECT expect(result.dfs).toEqual([ 'A', 'C', 'E', 'B', 'D' ]); - //expect(true).toBe(false); // need to check if no edge removed - console.warn('need to check if edge removed : modify test'); - + expect(removeEdgeMock).not.toHaveBeenCalled(); }); diff --git a/src/composables/__tests__/CalculateRelationCycle.test.ts b/src/composables/__tests__/CalculateRelationCycle.test.ts index 8c633ee17fee6583dda6f3718bcf749d1b96f99b..6ad6e6ead41a2aec7608c0a18b2165ec4b72b628 100644 --- a/src/composables/__tests__/CalculateRelationCycle.test.ts +++ b/src/composables/__tests__/CalculateRelationCycle.test.ts @@ -525,7 +525,6 @@ describe('CalculateRelationCycle', () => { // TEST const result=await CalculateRelationCycle.sortLinksWithAllGroupCycle(subgraphNetwork,true); - //console.log(result.linksOrdered); // EXPECT expect(result.subgraphNetwork).toEqual(expectedSubgraphNetwork); @@ -579,7 +578,6 @@ describe('CalculateRelationCycle', () => { // TEST const result=await CalculateRelationCycle.sortLinksWithAllGroupCycle(subgraphNetwork,true); - //console.log(result.linksOrdered); // EXPECT expect(result.subgraphNetwork).toEqual(expectedSubgraphNetwork); diff --git a/src/composables/__tests__/GetSetAttributsNodes.test.ts b/src/composables/__tests__/GetSetAttributsNodes.test.ts index c871d470294dbbdc8e1e529d1873c1f2458b2b74..a0ec06ab11ccfa5071e0d042d713c5525771264b 100644 --- a/src/composables/__tests__/GetSetAttributsNodes.test.ts +++ b/src/composables/__tests__/GetSetAttributsNodes.test.ts @@ -291,81 +291,6 @@ describe('Duplicate', () => { // 2. Reversible ***************************************************************** describe('Reversible', () => { - test("addMetadataReversibleWithClass", async () => { - - const addReversibleNetworkMock = jest.spyOn(GetSetAttributsNodes, 'addReversibleNetwork'); - // DATA - - let network:Network = { - id:"networkTest", - nodes: { - node1 :{ - id: "node1", - x: 10, - y: 10, - }, - node2: { - id: "node2", - x: 20, - y: 20, - classes: [GetSetAttributsNodes.classReversible+"_test"] - }, - node3: { - id: "node3", - x: 30, - y: 30, - classes: [GetSetAttributsNodes.classReversible] - }, - node4: { - id: "node4", - x: 40, - y: 40, - classes: [GetSetAttributsNodes.classReversible+"_test",GetSetAttributsNodes.classReversible] - } - }, - links: [] - }; - - let networkExpected:Network = { - id:"networkTest", - nodes: { - node1 :{ - id: "node1", - x: 10, - y: 10, - }, - node2: { - id: "node2", - x: 20, - y: 20, - classes: [GetSetAttributsNodes.classReversible+"_test"] - }, - node3: { - id: "node3", - x: 30, - y: 30, - classes: [GetSetAttributsNodes.classReversible], - metadata: {[GetSetAttributsNodes.reversibleAttribute]:true} - }, - node4: { - id: "node4", - x: 40, - y: 40, - classes: [GetSetAttributsNodes.classReversible+"_test",GetSetAttributsNodes.classReversible], - metadata: {[GetSetAttributsNodes.reversibleAttribute]:true} - } - }, - links: [] - }; - - // TEST - await GetSetAttributsNodes.addMetadataReversibleWithClass(network); - - // EXPECT - //expect(addReversibleNetworkMock).toHaveBeenCalled(); - expect(network).toEqual(networkExpected); - - }); test("addReversibleNetwork", () => { // DATA diff --git a/src/composables/__tests__/LayoutReversibleReactions.test.ts b/src/composables/__tests__/LayoutReversibleReactions.test.ts index 00fd0ecf404b1ee208892dd08c30e62d4208bf06..aa65c0f3e4246b1d357d89a92af31fe7b25eb55b 100644 --- a/src/composables/__tests__/LayoutReversibleReactions.test.ts +++ b/src/composables/__tests__/LayoutReversibleReactions.test.ts @@ -34,7 +34,7 @@ describe('LayoutReversibleReactions', () => { nodeA: {id:"nodeA", x:0, y:0, classes:["metabolite"]}, nodeB: {id:"nodeB", x:0, y:0, classes:["reaction"]}, nodeC: {id:"nodeC", x:0, y:0, classes:["metabolite"]}, - nodeD: {id:"nodeD", x:0, y:0, classes:["reaction"]}, + nodeD: {id:"nodeD", x:0, y:0, classes:["reaction"],"metadata": {"reversible": true}}, nodeE: {id:"nodeE", x:0, y:0, classes:["metabolite"]}, nodeF: {id:"nodeF", x:0, y:0, classes:["metabolite"]}, } @@ -80,14 +80,6 @@ describe('LayoutReversibleReactions', () => { } // MOCK - addMetadataReversibleWithClassMock = jest.spyOn(GetSetAttributsNodes, 'addMetadataReversibleWithClass'); - addMetadataReversibleWithClassMock.mockImplementation( - async (network) =>{ - network.nodes.nodeD.metadata={}; - network.nodes.nodeD.metadata[reversibleAttribute]=true; - } - ) - addLinkClassReversibleMock = jest.spyOn(GetSetAttributsNodes, 'addLinkClassReversible'); addLinkClassReversibleMock.mockImplementation( (link:Link) => { link.classes=[classReversible]; diff --git a/src/composables/importNetwork.ts b/src/composables/importNetwork.ts deleted file mode 100644 index ec7117c21656f862a1216c080419a47bf3c10444..0000000000000000000000000000000000000000 --- a/src/composables/importNetwork.ts +++ /dev/null @@ -1,93 +0,0 @@ -// import type { Ref } from "vue"; -// import type { Network } from "@metabohub/viz-core/src/types/Network"; -// import type { GraphStyleProperties } from "@metabohub/viz-core/src//types/GraphStyleProperties"; - -// //import { readJsonGraph } from "./readJson"; -// import { readJsonGraph } from "@metabohub/viz-core"; -// import { sbml2json } from "./SBMLtoJSON"; - - - -// /** -// * Import network at JSONGraph format from an URL. -// * @param url URL to get network data -// * @param network Reference to network object -// * @param networkStyle Reference to networkStyle object -// * @param callbackFunction Function to call after network load (opt) -// */ -// export function importNetworkFromURL(url: string, network: Ref<Network>, networkStyle: Ref<GraphStyleProperties>, callbackFunction = () => {}): void { -// setTimeout(async function() { -// let data:string = await getContentFromURL(url); -// // Check if the data is XML -// if (data.startsWith('<?xml')) { -// // Convert XML to JSON -// data = JSON.stringify(await sbml2json(data)); -// } -// const graphData = readJsonGraph(data); -// networkStyle.value = graphData.networkStyle; -// loadNetwork(graphData.network, network).then(() => { -// callbackFunction(); -// }); -// }, 1); -// } - - -// /** -// * Import network at JSONGraph format from a file. -// * @param file File to get network data -// * @param network Reference to network object -// * @param networkStyle Reference to networkStyle object -// * @param callbackFunction Function to call after network load (opt) -// */ - -// export function importNetworkFromFile(file: File, network: Ref<Network>, networkStyle: Ref<GraphStyleProperties>, callbackFunction = () => {}): void { -// const reader = new FileReader(); -// reader.onload = async function () { -// let data = reader.result as string; -// if (data.startsWith('<?xml')) { -// // Convert XML to JSON -// data = JSON.stringify(await sbml2json(data)); -// } -// const networkData = readJsonGraph(data); -// networkStyle.value = networkData.networkStyle; -// loadNetwork(networkData.network, network).then(() => { -// callbackFunction(); -// }); -// } - -// reader.readAsText(file); -// } - - -// /** -// * Make async the step where the data are put in network reference. -// * That permit to chain with another function like rescale. -// * @param data network data -// * @param network Reference to network object -// */ -// async function loadNetwork(data: Network, network: Ref<Network>): Promise<void> { -// network.value = data; -// } - - -// /** -// * Fetch url to return data -// * @param url URL to fetch -// * @returns Return response -// */ -// export async function getContentFromURL(url: string): Promise<string> { -// try { -// const response = await fetch(url); -// if (!response.ok) { -// throw new Error('La requête a échoué avec le statut ' + response.status); -// } -// const content = await response.text(); -// return content; -// } catch (error) { -// console.error('Une erreur s\'est produite lors de la récupération du contenu du fichier :', error); -// throw error; -// } -// } - - - diff --git a/src/types/FormatJSONGraphXML.ts b/src/types/FormatJSONGraphXML.ts deleted file mode 100644 index 3b279426c36d032d4f6ca1b72aa8b6914b6345cb..0000000000000000000000000000000000000000 --- a/src/types/FormatJSONGraphXML.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { GraphStyleProperties } from "../types/TypeVizCore"; - -export interface JSONGraphFormat { - graph: { - id: any; - type: string; - metadata: { - style:GraphStyleProperties; - }; - nodes: { - [x: string]: { - id: string; - metadata: { - classes?: string[]; - position?: { - x: number; - y: number; - - }; - }; - label: string; - }; - }; - edges: { - id: string; - source: string; - target: string; - metadata: { - classes?: string[]; - }; - }[]; - }; -} - -export interface XMLSpecies { - $: { - compartment: string; - id: string; - name: string; - species: string - } -} - -export interface XMLReactions { - $: { - id: string; - name: string; - reversible:string; - }, - listOfReactants: { - speciesReference: any[]|{} - }, - listOfProducts: { - speciesReference: Partial<XMLSpecies>[]|Partial<XMLSpecies> - } -} - - diff --git a/src/types/FormatJsonStyle.ts b/src/types/FormatJsonStyle.ts deleted file mode 100644 index 9d54eb7d7e56d76ff968af38f4f422f94b98a86a..0000000000000000000000000000000000000000 --- a/src/types/FormatJsonStyle.ts +++ /dev/null @@ -1,8 +0,0 @@ - -export interface JsonStyle { - biosource?: {[key:string]:string|number}, - generalStyle?:{[key:string]:string|number|boolean}, - linkStyle?:{[key:string]:string|number|boolean}, - metaboliteStyle?:{[key:string]:string|number|boolean}, - reactionStyle?:{[key:string]:string|number|boolean}, -} diff --git a/src/types/Parameters.ts b/src/types/Parameters.ts index fac8eb813e421231b0f2ce530b469d340de7a8a2..cce9be9adbdaee9c87218a97e2aba2768fe66ae3 100644 --- a/src/types/Parameters.ts +++ b/src/types/Parameters.ts @@ -35,9 +35,6 @@ export interface Parameters { factorLengthSideCompounds: number; // % of the lenght of minimal edge to use as lenght of side compounds edges shiftCoord?: boolean; // shift coordinates : center is at the previous coord (because of top left corner) - - //userSources: string[]; - //onlyUserSources: boolean; } export let defaultParameters: Parameters = { @@ -66,7 +63,4 @@ export let defaultParameters: Parameters = { factorLengthSideCompounds: 1/2, // user can change this parameter shiftCoord: true, - - //userSources: [], - //onlyUserSources: false, }; \ No newline at end of file diff --git a/src/types/Reaction.ts b/src/types/Reaction.ts index cf90a30e4c2440973be11a73e422105364e7bf56..2688d6d174e957d4ecaefad0f71bb5a06915f90e 100644 --- a/src/types/Reaction.ts +++ b/src/types/Reaction.ts @@ -8,18 +8,11 @@ export enum MetaboliteType { PRODUCT='product', } -// export enum MinMedianMax { -// MEDIAN='median', -// MIN='min', -// MAX='max' -// } - export interface Reaction { id:string sideCompoundsReactants: Array<string> sideCompoundsProducts:Array<string> metabolitesAngles:{[key:string]:{angle:number,type:MetaboliteType}} - //linkMedianMinMaxLength?:{median:number,min:number,max:number} intervalsAvailables?: ReactionInterval[] angleSpacingReactant?:number angleSpacingProduct?:number diff --git a/src/types/SubgraphNetwork.ts b/src/types/SubgraphNetwork.ts index 12e9f06a56ebff854bbb856b507bcc59ade052ca..9da2c08757ef7e8ac12645bce23e1a6427e766f1 100644 --- a/src/types/SubgraphNetwork.ts +++ b/src/types/SubgraphNetwork.ts @@ -1,9 +1,6 @@ -import { Network } from "@metabohub/viz-core/src/types/Network"; -import { Node } from "@metabohub/viz-core/src/types/Node"; import { Subgraph, TypeSubgraph } from "./Subgraph"; -import { Ref } from "vue"; -import { GraphStyleProperties } from "@metabohub/viz-core/src/types/GraphStyleProperties"; -import { NetworkLayout } from "./NetworkLayout"; +import { GraphStyleProperties } from "../types/TypeVizCore"; +import { NetworkLayout, NodeLayout } from "./NetworkLayout"; import { AttributesViz } from "./TypeViz"; /** @@ -33,6 +30,6 @@ export interface SubgraphNetwork { } sideCompounds?:{ - [key:string]:{reactants:Array<Node>,products:Array<Node>} + [key:string]:{reactants:Array<NodeLayout>,products:Array<NodeLayout>} } } \ No newline at end of file diff --git a/src/types/TypeViz.ts b/src/types/TypeViz.ts index 72b18ecd732297c2e573c0e686d514583de94fee..9c9532e4eda3b85afd4a90f62a6e2311850ecd1f 100644 --- a/src/types/TypeViz.ts +++ b/src/types/TypeViz.ts @@ -1,15 +1,3 @@ -// Graph already accessible (see the format below, but implemented in library), but the other interface can't be exported so there are duplicated here -// export interface Graph { -// name?: string -// strict?: boolean -// directed?: boolean -// graphAttributes?: Attributes -// nodeAttributes?: Attributes -// edgeAttributes?: Attributes -// nodes?: Node[] -// edges?: Edge[] -// subgraphs?: Subgraph[] -// } export interface AttributesViz { [name: string]: string | number | boolean