grnsight 3.0.0 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintignore +1 -0
- package/.travis.yml +1 -1
- package/GRNsight - Beta.html +194 -0
- package/Gemfile.lock +259 -0
- package/README.md +1 -1
- package/_gh_pages/about.html +360 -45
- package/_gh_pages/assets/css/footer.css +3 -0
- package/_gh_pages/assets/css/main.css +28 -14
- package/_gh_pages/assets/images/21-genes_31-edges_Schade-data_estimation_output_binary-no-targetless-genes_sif.png +0 -0
- package/_gh_pages/assets/images/21-genes_31-edges_Schade-data_estimation_output_binary_sif.png +0 -0
- package/_gh_pages/assets/images/21-genes_31-edges_Schade-data_graphml_3-edges-and-footer.png +0 -0
- package/_gh_pages/assets/images/21-genes_31-edges_Schade-data_graphml_header-and-3-nodes.png +0 -0
- package/_gh_pages/assets/images/21-genes_31-edges_Schade-data_graphml_output_3-edges-and-footer.png +0 -0
- package/_gh_pages/assets/images/21-genes_31-edges_Schade-data_graphml_output_header-and-3-nodes.png +0 -0
- package/_gh_pages/assets/images/21-genes_31-edges_Schade-data_input_binary-no-targetless-genes_sif.png +0 -0
- package/_gh_pages/assets/images/21-genes_31-edges_Schade-data_input_binary_sif.png +0 -0
- package/_gh_pages/assets/images/21-genes_31-edges_Schade-data_input_concatenated-no-targetless-genes_sif.png +0 -0
- package/_gh_pages/assets/images/21-genes_31-edges_Schade-data_input_concatenated_sif.png +0 -0
- package/_gh_pages/assets/images/Choe-Shin_CMSI402-poster-session_20180430.jpg +0 -0
- package/_gh_pages/assets/images/Choe_SCCUR_2017.jpg +0 -0
- package/_gh_pages/assets/images/Dahlquist-Choe-Shin_CMSI402-poster-session_20180430.jpg +0 -0
- package/_gh_pages/assets/images/Dionisio-Dahlquist_GRNsight-shades_20170506.jpg +0 -0
- package/_gh_pages/assets/images/Klein_Samdarshi_TriBeta_2018_20180317.jpg +0 -0
- package/_gh_pages/assets/images/Shin_SCCUR_2017.jpg +0 -0
- package/{documents/manuscripts/peerj-computerscience-2016/figures/submitted-versions/Figure1_zoom145_900pix-wide.png → _gh_pages/assets/images/demo-3_network-sheet.png} +0 -0
- package/{documents/manuscripts/peerj-computerscience-2016/figures/submitted-versions/Figure2_zoom145_900pix-wide.png → _gh_pages/assets/images/demo-4_network-optimized-weights-sheet.png} +0 -0
- package/_gh_pages/assets/images/gene-pages-0.png +0 -0
- package/_gh_pages/assets/images/gene-pages-1.png +0 -0
- package/_gh_pages/assets/images/gene-pages-2.png +0 -0
- package/_gh_pages/assets/images/gene-pages-3.png +0 -0
- package/_gh_pages/assets/images/grnsight2020.png +0 -0
- package/_gh_pages/assets/images/v3demo2-grid+nodecoloring.png +0 -0
- package/_gh_pages/assets/images/v3demo2-nodecoloring.png +0 -0
- package/_gh_pages/assets/images/v3demo2.png +0 -0
- package/_gh_pages/assets/js/ga-report.js +11 -11
- package/_gh_pages/assets/js/iframeResizer.min.js +9 -0
- package/_gh_pages/assets/js/main.js +43 -43
- package/_gh_pages/beta.html +29 -24
- package/_gh_pages/contact.html +31 -31
- package/_gh_pages/coverage/coverage.json +1 -0
- package/_gh_pages/coverage/coverage.raw.json +1 -0
- package/_gh_pages/coverage/lcov-report/base.css +223 -0
- package/_gh_pages/coverage/lcov-report/block-navigation.js +63 -0
- package/_gh_pages/coverage/lcov-report/controllers/additional-sheet-parser.js.html +330 -0
- package/_gh_pages/coverage/lcov-report/controllers/constants.js.html +243 -0
- package/_gh_pages/coverage/lcov-report/controllers/export-controller.js.html +285 -0
- package/_gh_pages/coverage/lcov-report/controllers/exporters/graphml.js.html +405 -0
- package/_gh_pages/coverage/lcov-report/controllers/exporters/index.html +110 -0
- package/_gh_pages/coverage/lcov-report/controllers/exporters/sif.js.html +150 -0
- package/_gh_pages/coverage/lcov-report/controllers/helpers.js.html +114 -0
- package/_gh_pages/coverage/lcov-report/controllers/import-controller.js.html +233 -0
- package/_gh_pages/coverage/lcov-report/controllers/importers/graphml.js.html +716 -0
- package/_gh_pages/coverage/lcov-report/controllers/importers/index.html +106 -0
- package/_gh_pages/coverage/lcov-report/controllers/importers/sif.js.html +488 -0
- package/_gh_pages/coverage/lcov-report/controllers/index.html +162 -0
- package/_gh_pages/coverage/lcov-report/controllers/semantic-checker.js.html +810 -0
- package/_gh_pages/coverage/lcov-report/controllers/spreadsheet-controller.js.html +1779 -0
- package/_gh_pages/coverage/lcov-report/index.html +136 -0
- package/_gh_pages/coverage/lcov-report/prettify.css +1 -0
- package/_gh_pages/coverage/lcov-report/prettify.js +1 -0
- package/_gh_pages/coverage/lcov-report/server/controllers/additional-sheet-parser.js.html +330 -0
- package/_gh_pages/coverage/lcov-report/server/controllers/constants.js.html +243 -0
- package/_gh_pages/coverage/lcov-report/server/controllers/export-controller.js.html +285 -0
- package/_gh_pages/coverage/lcov-report/server/controllers/exporters/graphml.js.html +405 -0
- package/_gh_pages/coverage/lcov-report/server/controllers/exporters/index.html +110 -0
- package/_gh_pages/coverage/lcov-report/server/controllers/exporters/sif.js.html +150 -0
- package/_gh_pages/coverage/lcov-report/server/controllers/graphml-constants.js.html +585 -0
- package/_gh_pages/coverage/lcov-report/server/controllers/helpers.js.html +114 -0
- package/_gh_pages/coverage/lcov-report/server/controllers/import-controller.js.html +237 -0
- package/_gh_pages/coverage/lcov-report/server/controllers/importers/graphml.js.html +585 -0
- package/_gh_pages/coverage/lcov-report/server/controllers/importers/index.html +110 -0
- package/_gh_pages/coverage/lcov-report/server/controllers/importers/sif.js.html +492 -0
- package/_gh_pages/coverage/lcov-report/server/controllers/index.html +188 -0
- package/_gh_pages/coverage/lcov-report/server/controllers/semantic-checker.js.html +810 -0
- package/_gh_pages/coverage/lcov-report/server/controllers/spreadsheet-controller.js.html +1779 -0
- package/_gh_pages/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/_gh_pages/coverage/lcov-report/sorter.js +158 -0
- package/_gh_pages/coverage/lcov-report/web-client/public/js/grnstate.js.html +225 -0
- package/_gh_pages/coverage/lcov-report/web-client/public/js/index.html +97 -0
- package/_gh_pages/coverage/lcov.info +49 -0
- package/_gh_pages/documentation.html +998 -320
- package/_gh_pages/documents/abstracts/SIGGRAPH 2017 Abstract/siggraph-abstract-review.aux +47 -0
- package/_gh_pages/documents/abstracts/SIGGRAPH 2017 Abstract/siggraph-abstract-review.bbl +73 -0
- package/_gh_pages/documents/abstracts/SIGGRAPH 2017 Abstract/siggraph-abstract-review.blg +52 -0
- package/_gh_pages/documents/abstracts/SIGGRAPH 2017 Abstract/siggraph-abstract-review.log +1056 -0
- package/_gh_pages/documents/abstracts/SIGGRAPH 2017 Abstract/siggraph-abstract-review.out +7 -0
- package/_gh_pages/documents/abstracts/SIGGRAPH 2017 Abstract/siggraph-abstract-review.synctex.gz +0 -0
- package/_gh_pages/documents/manuscripts/peerj-computerscience-2016/revisions/GRNsight_PeerJ-CS_manuscript_2016_text-only_revised-Dondi.docx +0 -0
- package/_gh_pages/encryption/server.cert +21 -0
- package/_gh_pages/encryption/server.key +28 -0
- package/_gh_pages/favicon.ico +0 -0
- package/_gh_pages/index.html +45 -22
- package/_gh_pages/links.html +47 -28
- package/_gh_pages/news.html +103 -21
- package/_gh_pages/onlyfooter.html +78 -0
- package/_gh_pages/onlyheader.html +64 -0
- package/_gh_pages/onlysidebar.html +73 -0
- package/_gh_pages/package-lock.json +14048 -0
- package/_gh_pages/people.html +129 -40
- package/_gh_pages/privacy.html +23 -17
- package/_gh_pages/publications.html +75 -33
- package/_gh_pages/robots.txt +1 -0
- package/_gh_pages/sitemap.xml +87 -74
- package/_gh_pages/test-files/import-samples/attributes.graphml +40 -0
- package/_gh_pages/test-files/import-samples/port.graphml +32 -0
- package/_gh_pages/test-files/import-samples/simple.graphml +31 -0
- package/_gh_pages/web-client/public/js/grnsight.min.js +2347 -0
- package/_gh_pages/web-client/public/stylesheets/grnsight.css +443 -0
- package/coverage/coverage.json +1 -1
- package/coverage/coverage.raw.json +1 -0
- package/coverage/lcov-report/base.css +18 -8
- package/coverage/lcov-report/block-navigation.js +63 -0
- package/coverage/lcov-report/controllers/additional-sheet-parser.js.html +330 -0
- package/coverage/lcov-report/controllers/constants.js.html +65 -61
- package/coverage/lcov-report/controllers/export-controller.js.html +96 -92
- package/coverage/lcov-report/controllers/exporters/graphml.js.html +168 -164
- package/coverage/lcov-report/controllers/exporters/index.html +36 -32
- package/coverage/lcov-report/controllers/exporters/sif.js.html +65 -61
- package/coverage/lcov-report/controllers/helpers.js.html +25 -21
- package/coverage/lcov-report/controllers/index.html +49 -45
- package/coverage/lcov-report/controllers/semantic-checker.js.html +403 -396
- package/coverage/lcov-report/controllers/spreadsheet-controller.js.html +973 -879
- package/coverage/lcov-report/index.html +45 -28
- package/coverage/lcov-report/server/controllers/additional-sheet-parser.js.html +330 -0
- package/coverage/lcov-report/server/controllers/constants.js.html +243 -0
- package/coverage/lcov-report/server/controllers/export-controller.js.html +285 -0
- package/coverage/lcov-report/server/controllers/exporters/graphml.js.html +405 -0
- package/coverage/lcov-report/server/controllers/exporters/index.html +110 -0
- package/coverage/lcov-report/server/controllers/exporters/sif.js.html +150 -0
- package/coverage/lcov-report/server/controllers/graphml-constants.js.html +585 -0
- package/coverage/lcov-report/server/controllers/helpers.js.html +114 -0
- package/coverage/lcov-report/server/controllers/import-controller.js.html +237 -0
- package/coverage/lcov-report/server/controllers/importers/graphml.js.html +585 -0
- package/coverage/lcov-report/server/controllers/importers/index.html +110 -0
- package/coverage/lcov-report/server/controllers/importers/sif.js.html +492 -0
- package/coverage/lcov-report/server/controllers/index.html +188 -0
- package/coverage/lcov-report/server/controllers/semantic-checker.js.html +810 -0
- package/coverage/lcov-report/server/controllers/spreadsheet-controller.js.html +1779 -0
- package/coverage/lcov-report/web-client/public/js/grnstate.js.html +225 -0
- package/coverage/lcov-report/web-client/public/js/index.html +97 -0
- package/coverage/lcov.info +1758 -876
- package/encryption/server.cert +21 -0
- package/encryption/server.key +28 -0
- package/package.json +46 -22
- package/server/app.js +6 -2
- package/server/config/config.js +16 -7
- package/server/controllers/additional-sheet-parser.js +292 -55
- package/server/controllers/api-controllers.js +36 -0
- package/server/controllers/constants.js +4 -37
- package/server/controllers/database-controller.js +129 -0
- package/server/controllers/demo-workbooks.js +5973 -0
- package/server/controllers/export-constants.js +78 -0
- package/server/controllers/export-controller.js +25 -3
- package/server/controllers/exporters/graphml.js +15 -15
- package/server/controllers/exporters/sif.js +7 -7
- package/server/controllers/exporters/xlsx.js +183 -0
- package/server/controllers/expression-sheet-parser.js +170 -0
- package/server/controllers/ga-controller.js +1 -1
- package/server/controllers/graphml-constants.js +0 -17
- package/server/controllers/helpers.js +25 -1
- package/server/controllers/import-controller.js +2 -2
- package/server/controllers/importers/graphml.js +17 -20
- package/server/controllers/importers/sif.js +22 -18
- package/server/controllers/network-sheet-parser.js +307 -0
- package/server/controllers/semantic-checker.js +30 -162
- package/server/controllers/sif-constants.js +36 -0
- package/server/controllers/spreadsheet-controller.js +277 -424
- package/server/controllers/workbook-constants.js +521 -0
- package/test/additional-sheet-parser-tests.js +147 -38
- package/test/api-tests.js +245 -0
- package/test/errors-adjacency-matrix-modifications.js +30 -29
- package/test/errors-gene-name-modifications.js +9 -0
- package/test/errors-graph-tests.js +4 -4
- package/test/errors-sheet-modifications.js +10 -2
- package/test/export-tests.js +431 -24
- package/test/expression-data-import-tests.js +113 -0
- package/test/grnstate-tests.js +29 -0
- package/test/import-graphml-tests.js +59 -40
- package/test/import-sif-tests.js +50 -37
- package/test/test.js +557 -93
- package/test/warnings-adjacency-matrix-modifications.js +8 -7
- package/test-files/additional-sheet-test-files/optimization-diagnostics-default.xlsx +0 -0
- package/test-files/additional-sheet-test-files/optimization-diagnostics-extraneous-data.xlsx +0 -0
- package/test-files/additional-sheet-test-files/optimization-diagnostics-incorrect-MSE-gene-header.xlsx +0 -0
- package/test-files/additional-sheet-test-files/optimization-diagnostics-incorrect-MSE-header.xlsx +0 -0
- package/test-files/additional-sheet-test-files/optimization-diagnostics-incorrect-column-headers.xlsx +0 -0
- package/test-files/additional-sheet-test-files/optimization-diagnostics-invalid-MSE-data.xlsx +0 -0
- package/test-files/additional-sheet-test-files/optimization-diagnostics-invalid-value.xlsx +0 -0
- package/test-files/additional-sheet-test-files/optimization-diagnostics-missing-MSE-data.xlsx +0 -0
- package/test-files/additional-sheet-test-files/optimization-diagnostics-missing-column-headers.xlsx +0 -0
- package/test-files/additional-sheet-test-files/optimization-diagnostics-missing-header.xlsx +0 -0
- package/test-files/additional-sheet-test-files/optimization-diagnostics-unknown-parameter.xlsx +0 -0
- package/test-files/additional-sheet-test-files/optimization-parameters-default.xlsx +0 -0
- package/test-files/additional-sheet-test-files/optimization-parameters-incorrect-headers.xlsx +0 -0
- package/test-files/additional-sheet-test-files/optimization-parameters-invalid-optimization-parameter.xlsx +0 -0
- package/test-files/additional-sheet-test-files/optimization-parameters-missing-headers.xlsx +0 -0
- package/test-files/additional-sheet-test-files/optimization-parameters-unknown-parameter.xlsx +0 -0
- package/test-files/additional-sheet-test-files/two-column-sheets-extraneous-data.xlsx +0 -0
- package/test-files/additional-sheet-test-files/two-column-sheets-incorrect-cell-A1.xlsx +0 -0
- package/test-files/additional-sheet-test-files/two-column-sheets-incorrect-column-header.xlsx +0 -0
- package/test-files/additional-sheet-test-files/two-column-sheets-invalid-gene-length.xlsx +0 -0
- package/test-files/additional-sheet-test-files/two-column-sheets-invalid-gene-type.xlsx +0 -0
- package/test-files/additional-sheet-test-files/two-column-sheets-invalid-value.xlsx +0 -0
- package/test-files/additional-sheet-test-files/two-column-sheets-missing-column-header.xlsx +0 -0
- package/test-files/additional-sheet-test-files/two-column-sheets-special-character.xlsx +0 -0
- package/test-files/adjacency-matrix-modifications/asymmetric-gene-order-input.xlsx +0 -0
- package/test-files/adjacency-matrix-modifications/asymmetric-gene-order-output.xlsx +0 -0
- package/test-files/adjacency-matrix-modifications/extra-column-adjacent-input.xlsx +0 -0
- package/test-files/adjacency-matrix-modifications/extra-column-adjacent-output.xlsx +0 -0
- package/test-files/adjacency-matrix-modifications/extra-column-end-of-sheet-input.xlsx +0 -0
- package/test-files/adjacency-matrix-modifications/extra-column-end-of-sheet-output.xlsx +0 -0
- package/test-files/adjacency-matrix-modifications/extra-data-random-cell-both-output.xlsx +0 -0
- package/test-files/adjacency-matrix-modifications/extra-data-random-cell-network-only-input.xlsx +0 -0
- package/test-files/adjacency-matrix-modifications/extra-data-random-cell-network-only-output.xlsx +0 -0
- package/test-files/adjacency-matrix-modifications/extra-data-random-cell-network-optimized-only-output.xlsx +0 -0
- package/test-files/adjacency-matrix-modifications/extra-row-end-of-sheet-input.xlsx +0 -0
- package/test-files/adjacency-matrix-modifications/extra-row-end-of-sheet-output.xlsx +0 -0
- package/test-files/adjacency-matrix-modifications/incorrect-network-cell-A1.xlsx +0 -0
- package/test-files/adjacency-matrix-modifications/missing-column-end-input.xlsx +0 -0
- package/test-files/adjacency-matrix-modifications/missing-column-end-output.xlsx +0 -0
- package/test-files/adjacency-matrix-modifications/missing-data-input.xlsx +0 -0
- package/test-files/adjacency-matrix-modifications/missing-data-output.xlsx +0 -0
- package/test-files/adjacency-matrix-modifications/missing-row-end-input.xlsx +0 -0
- package/test-files/adjacency-matrix-modifications/missing-row-end-output.xlsx +0 -0
- package/test-files/adjacency-matrix-modifications/missing-row-middle-input.xlsx +0 -0
- package/test-files/adjacency-matrix-modifications/missing-row-middle-output.xlsx +0 -0
- package/test-files/adjacency-matrix-modifications/missing-value-bottom-corner-input.xlsx +0 -0
- package/test-files/adjacency-matrix-modifications/missing-value-bottom-corner-output.xlsx +0 -0
- package/test-files/adjacency-matrix-modifications/value-replaced-w-spaces-both-output.xlsx +0 -0
- package/test-files/adjacency-matrix-modifications/value-replaced-w-spaces-net-only-input.xlsx +0 -0
- package/test-files/adjacency-matrix-modifications/value-replaced-w-spaces-net-op-only-output.xlsx +0 -0
- package/test-files/adjacency-matrix-modifications/value-replaced/342/200/223w-spaces-net-only-output.xlsx +0 -0
- package/test-files/demo-files/15-genes_28-edges_db5_Dahlquist-data_estimation_output.xlsx +0 -0
- package/test-files/demo-files/15-genes_28-edges_db5_Dahlquist-data_input.xlsx +0 -0
- package/test-files/expression-data-test-sheets/expression_sheet_correct_numbering.xlsx +0 -0
- package/test-files/expression-data-test-sheets/expression_sheet_different_number_of_columns.xlsx +0 -0
- package/test-files/expression-data-test-sheets/expression_sheet_empty_column.xlsx +0 -0
- package/test-files/expression-data-test-sheets/expression_sheet_empty_row.xlsx +0 -0
- package/test-files/expression-data-test-sheets/expression_sheet_erroneous_data.xlsx +0 -0
- package/test-files/expression-data-test-sheets/expression_sheet_extra_gene_name.xlsx +0 -0
- package/test-files/expression-data-test-sheets/expression_sheet_incorrectly_ordered_time_points.xlsx +0 -0
- package/test-files/expression-data-test-sheets/expression_sheet_mismatched_case_gene_names.xlsx +0 -0
- package/test-files/expression-data-test-sheets/expression_sheet_mismatched_gene_names.xlsx +0 -0
- package/test-files/expression-data-test-sheets/expression_sheet_missing_column_header.xlsx +0 -0
- package/test-files/expression-data-test-sheets/expression_sheet_missing_data_error.xlsx +0 -0
- package/test-files/expression-data-test-sheets/expression_sheet_missing_data_ok.xlsx +0 -0
- package/test-files/expression-data-test-sheets/expression_sheet_missing_data_ok_export_exact.xlsx +0 -0
- package/test-files/expression-data-test-sheets/expression_sheet_missing_gene_name.xlsx +0 -0
- package/test-files/expression-data-test-sheets/expression_sheet_name_not_in_optparams.xlsx +0 -0
- package/test-files/expression-data-test-sheets/expression_sheet_name_not_present.xlsx +0 -0
- package/test-files/expression-data-test-sheets/expression_sheet_negative_time_points.xlsx +0 -0
- package/test-files/expression-data-test-sheets/expression_sheet_non_numerical_time_points.xlsx +0 -0
- package/test-files/expression-data-test-sheets/expression_sheet_not_existing.xlsx +0 -0
- package/test-files/expression-data-test-sheets/expression_sheet_wrong_id_label.xlsx +0 -0
- package/test-files/expression-data-test-sheets/expression_sheet_wrong_order_gene_names.xlsx +0 -0
- package/test-files/expression-data-test-sheets/expression_sheet_wrong_sheet_name_case.xlsx +0 -0
- package/test-files/expression-data-test-sheets/expression_sheet_wrong_sheet_name_convention.xlsx +0 -0
- package/test-files/gene-name-modifications/NaN-as-gene-name-input.xlsx +0 -0
- package/test-files/gene-name-modifications/NaN-as-gene-name-output.xlsx +0 -0
- package/test-files/gene-name-modifications/mismatched-case-related-input.xlsx +0 -0
- package/test-files/gene-name-modifications/mismatched-case-related-output.xlsx +0 -0
- package/test-files/gene-name-modifications/mismatched-case-unrelated-input.xlsx +0 -0
- package/test-files/gene-name-modifications/mismatched-case-unrelated-output.xlsx +0 -0
- package/test-files/gene-name-modifications/numbers-as-gene-name-related-input.xlsx +0 -0
- package/test-files/gene-name-modifications/numbers-as-gene-name-related-output.xlsx +0 -0
- package/test-files/gene-name-modifications/numbers-as-gene-name-unrelated-input.xlsx +0 -0
- package/test-files/gene-name-modifications/numbers-as-gene-name-unrelated-output.xlsx +0 -0
- package/test-files/graph-tests/different-sized-networks/{80-genes-0-edges.xlsx → 134-genes-0-edges.xlsx} +0 -0
- package/test-files/graph-tests/different-sized-networks/{45-genes-max-edges.xlsx → 44-source-genes-45-target-genes-max-edges.xlsx} +0 -0
- package/test-files/graph-tests/different-sized-networks/{1-gene-0-edges.xlsx → unused-files/1-gene-0-edges.xlsx} +0 -0
- package/test-files/graph-tests/different-sized-networks/{1-gene-1-edges.xlsx → unused-files/1-gene-1-edges.xlsx} +0 -0
- package/test-files/graph-tests/different-sized-networks/{10-genes-50-edges.xlsx → unused-files/10-genes-50-edges.xlsx} +0 -0
- package/test-files/graph-tests/different-sized-networks/{10-genes-90-edges.xlsx → unused-files/10-genes-90-edges.xlsx} +0 -0
- package/test-files/graph-tests/different-sized-networks/{100-genes-0-edges.xlsx → unused-files/100-genes-0-edges.xlsx} +0 -0
- package/test-files/graph-tests/different-sized-networks/{110-genes-0-edges.xlsx → unused-files/110-genes-0-edges.xlsx} +0 -0
- package/test-files/graph-tests/different-sized-networks/{120-genes-0-edges.xlsx → unused-files/120-genes-0-edges.xlsx} +0 -0
- package/test-files/graph-tests/different-sized-networks/{130-genes-0-edges.xlsx → unused-files/130-genes-0-edges.xlsx} +0 -0
- package/test-files/graph-tests/different-sized-networks/{140-genes-0-edges.xlsx → unused-files/140-genes-0-edges.xlsx} +0 -0
- package/test-files/graph-tests/different-sized-networks/{150-genes-10000-edges.xlsx → unused-files/150-genes-10000-edges.xlsx} +0 -0
- package/test-files/graph-tests/different-sized-networks/{150-genes-20000-edges.xlsx → unused-files/150-genes-20000-edges.xlsx} +0 -0
- package/test-files/graph-tests/different-sized-networks/{150-genes-max-edges.xlsx → unused-files/150-genes-max-edges.xlsx} +0 -0
- package/test-files/graph-tests/different-sized-networks/{160-genes-max-edges.xlsx → unused-files/160-genes-max-edges.xlsx} +0 -0
- package/test-files/graph-tests/different-sized-networks/{20-genes-max-edges.xlsx → unused-files/20-genes-max-edges.xlsx} +0 -0
- package/test-files/graph-tests/different-sized-networks/{25-genes-max-edges.xlsx → unused-files/25-genes-max-edges.xlsx} +0 -0
- package/test-files/graph-tests/different-sized-networks/{30-genes-max-edges.xlsx → unused-files/30-genes-max-edges.xlsx} +0 -0
- package/test-files/graph-tests/different-sized-networks/{34-genes-0-edges.xlsx → unused-files/34-genes-0-edges.xlsx} +0 -0
- package/test-files/graph-tests/different-sized-networks/{34-genes-40-edges.xlsx → unused-files/34-genes-40-edges.xlsx} +0 -0
- package/test-files/graph-tests/different-sized-networks/{34-genes-65-edges.xlsx → unused-files/34-genes-65-edges.xlsx} +0 -0
- package/test-files/graph-tests/different-sized-networks/{34-genes-90-edges.xlsx → unused-files/34-genes-90-edges.xlsx} +0 -0
- package/test-files/graph-tests/different-sized-networks/{5-genes-max-edges.xlsx → unused-files/5-genes-max-edges.xlsx} +0 -0
- package/test-files/graph-tests/different-sized-networks/{51-genes-max-edges.xlsx → unused-files/51-genes-max-edges.xlsx} +0 -0
- package/test-files/graph-tests/different-sized-networks/{52-genes-max-edges.xlsx → unused-files/52-genes-max-edges.xlsx} +0 -0
- package/test-files/graph-tests/different-sized-networks/{55-genes-0-edges.xlsx → unused-files/55-genes-0-edges.xlsx} +0 -0
- package/test-files/graph-tests/different-sized-networks/{55-genes-max-edges.xlsx → unused-files/55-genes-max-edges.xlsx} +0 -0
- package/test-files/graph-tests/different-sized-networks/{65-genes-0-edges.xlsx → unused-files/65-genes-0-edges.xlsx} +0 -0
- package/test-files/graph-tests/different-sized-networks/{7-genes-max-edges.xlsx → unused-files/7-genes-max-edges.xlsx} +0 -0
- package/test-files/graph-tests/different-sized-networks/{70-genes-0-edges.xlsx → unused-files/70-genes-0-edges.xlsx} +0 -0
- package/test-files/graph-tests/different-sized-networks/{9-genes-max-edges.xlsx → unused-files/9-genes-max-edges.xlsx} +0 -0
- package/test-files/graph-tests/different-sized-networks/{90-genes-0-edges.xlsx → unused-files/90-genes-0-edges.xlsx} +0 -0
- package/test-files/graph-tests/different-sized-networks/{regulation-matrix-documented-20140709-AllTF-all-targets.xlsx → unused-files/regulation-matrix-documented-20140709-AllTF-all-targets.xlsx} +0 -0
- package/test-files/node-tests/long-gene-name-no-spaces-first.xlsx +0 -0
- package/test-files/node-tests/long-gene-name-no-spaces-second.xlsx +0 -0
- package/test-files/node-tests/long-gene-name-spaces.xlsx +0 -0
- package/test-files/species-test-data/15-genes_28-edges_db5_Dahlquist-data_input_no-species.xlsx +0 -0
- package/test-files/species-test-data/15-genes_28-edges_db5_Dahlquist-data_input_with-species.xlsx +0 -0
- package/test-files/species-test-data/3-gene_7-edge_elegans.xlsx +0 -0
- package/test-files/species-test-data/3-gene_7-edge_melanogaster.xlsx +0 -0
- package/test-files/species-test-data/3-gene_7-edge_musculus.xlsx +0 -0
- package/test-files/species-test-data/3-gene_7-edge_sapiens.xlsx +0 -0
- package/test-files/species-test-data/kev-fake-data-sapiens-no-exp-data.xlsx +0 -0
- package/test-files/spreadsheet-controller-test-files/sheet-name-capitalized-network-optimized-weights.xlsx +0 -0
- package/test-files/spreadsheet-controller-test-files/sheet-name-capitalized-network.xlsx +0 -0
- package/web-client/app.js +1 -1
- package/web-client/config/config.js +5 -5
- package/web-client/controllers/main.js +5 -1
- package/web-client/public/favicon.ico +0 -0
- package/web-client/public/gene/GRNSight.svg +689 -0
- package/web-client/public/gene/PageDesignREADME.md +1 -0
- package/web-client/public/gene/api.js +442 -0
- package/web-client/public/gene/info.css +181 -0
- package/web-client/public/gene/info.js +334 -0
- package/web-client/public/gene/integrationREADME.md +52 -0
- package/web-client/public/js/constants.js +182 -0
- package/web-client/public/js/getGeneInformationREADME.md +4 -0
- package/web-client/public/js/graph-statistics.js +7 -7
- package/web-client/public/js/graph.js +480 -476
- package/web-client/public/js/grnsight.js +10 -9
- package/web-client/public/js/grnsight.min.js +2335 -0
- package/web-client/public/js/grnstate.js +147 -0
- package/web-client/public/js/iframe-coordination.js +55 -0
- package/web-client/public/js/setup-handlers.js +617 -0
- package/web-client/public/js/setup-load-and-import-handlers.js +180 -0
- package/web-client/public/js/update-app.js +980 -0
- package/web-client/public/js/upload.js +352 -578
- package/web-client/public/js/warnings.js +60 -0
- package/web-client/public/lib/iframeSizer.contentWindow.min.js +10 -0
- package/{documents/SDF/CMSI_402/spring_2018/writtenStatusReport4 → web-client/public/lib/jaspar-front.html} +0 -0
- package/web-client/public/stylesheets/grnsight.styl +176 -26
- package/web-client/public/stylesheets/print.styl +10 -4
- package/web-client/views/{graph.jade → graph.pug} +1 -3
- package/web-client/views/info.pug +215 -0
- package/web-client/views/upload.pug +587 -0
- package/_gh_pages/Gemfile +0 -7
- package/_gh_pages/Gemfile.lock +0 -129
- package/documents/SDF/CMSI_402/spring_2014/Southwick_CMSI402_Spring2014_software-development-plan.md +0 -71
- package/documents/SDF/CMSI_402/spring_2014/Southwick_CMSI402_Spring2014_software-requirements-specification.md +0 -71
- package/documents/SDF/CMSI_402/spring_2014/use-case-diagram-spring-2014.jpg +0 -0
- package/documents/SDF/CMSI_402/spring_2017/Anguiano_402_Final_Presentation.pptx +0 -0
- package/documents/SDF/CMSI_402/spring_2017/Anguiano_402_Presentation_Final_Poster.pdf +0 -0
- package/documents/SDF/CMSI_402/spring_2017/Anguiano_CMSI402_Spring2017_project-proposal-presentation.pptx +0 -0
- package/documents/SDF/CMSI_402/spring_2017/Anguiano_CMSI402_Spring2017_project-proposal.docx +0 -0
- package/documents/SDF/CMSI_402/spring_2017/Anguiano_CMSI402_Spring2017_software-development-plan.docx +0 -0
- package/documents/SDF/CMSI_402/spring_2017/Anguiano_CMSI402_Spring2017_software-requirements-specification.docx +0 -0
- package/documents/SDF/CMSI_402/spring_2017/Design Review Presentation.pptx +0 -0
- package/documents/SDF/CMSI_402/spring_2018/0402report.docx +0 -0
- package/documents/SDF/CMSI_402/spring_2018/0409report.docx +0 -0
- package/documents/SDF/CMSI_402/spring_2018/402-gantt.png +0 -0
- package/documents/SDF/CMSI_402/spring_2018/402SRS_GRNSightFeedback01.txt +0 -28
- package/documents/SDF/CMSI_402/spring_2018/402_SPD.md +0 -223
- package/documents/SDF/CMSI_402/spring_2018/ChoeShinCMSI402_Final.pptx +0 -0
- package/documents/SDF/CMSI_402/spring_2018/ProjectProposal.md +0 -22
- package/documents/SDF/CMSI_402/spring_2018/SoftwareRequirementsSpecification.md +0 -88
- package/documents/SDF/CMSI_402/spring_2018/homework/choe_eileen/Choe_Eileen_CMSI 402_HW1.pdf +0 -0
- package/documents/SDF/CMSI_402/spring_2018/homework/choe_eileen/Choe_Eileen_CMSI402_HW2.pdf +0 -0
- package/documents/SDF/CMSI_402/spring_2018/homework/shin_jen/402hw2.docx +0 -0
- package/documents/SDF/CMSI_402/spring_2018/homework/shin_jen/Jen - 402Hw1.docx +0 -0
- package/documents/SDF/CMSI_402/spring_2018/homework/shin_jen/Jen - hw3.docx +0 -0
- package/documents/SDF/CMSI_402/spring_2018/writtenStatusReport.docx +0 -0
- package/documents/Varshneya_Samdarshi_LMU_Symposium_2016.pptx +0 -0
- package/documents/abstracts/Anguiano_Varshneya_Undergraduate-Research-Symposium_2017_abstract.pdf +0 -0
- package/documents/abstracts/SIGGRAPH 2017 Abstract/ACM-Reference-Format.bst +0 -3478
- package/documents/abstracts/SIGGRAPH 2017 Abstract/Figure1_zoom100.png +0 -0
- package/documents/abstracts/SIGGRAPH 2017 Abstract/acmart.cls +0 -2352
- package/documents/abstracts/SIGGRAPH 2017 Abstract/acmart.ins +0 -29
- package/documents/abstracts/SIGGRAPH 2017 Abstract/always-weights.png +0 -0
- package/documents/abstracts/SIGGRAPH 2017 Abstract/auto.png +0 -0
- package/documents/abstracts/SIGGRAPH 2017 Abstract/networkA.png +0 -0
- package/documents/abstracts/SIGGRAPH 2017 Abstract/networkB-normalized.png +0 -0
- package/documents/abstracts/SIGGRAPH 2017 Abstract/networkB.png +0 -0
- package/documents/abstracts/SIGGRAPH 2017 Abstract/never-weights.png +0 -0
- package/documents/abstracts/SIGGRAPH 2017 Abstract/representative-image/screenshot.jpg +0 -0
- package/documents/abstracts/SIGGRAPH 2017 Abstract/representative-image/screenshot3x2.png +0 -0
- package/documents/abstracts/SIGGRAPH 2017 Abstract/representative-image/withweights3x2.png +0 -0
- package/documents/abstracts/SIGGRAPH 2017 Abstract/screenshot-auto.png +0 -0
- package/documents/abstracts/SIGGRAPH 2017 Abstract/siggraph-abstract-review.bib +0 -85
- package/documents/abstracts/SIGGRAPH 2017 Abstract/siggraph-abstract-review.pdf +0 -0
- package/documents/abstracts/SIGGRAPH 2017 Abstract/siggraph-abstract-review.tex +0 -235
- package/documents/abstracts/SWE Collegiate Competition 2017.md +0 -9
- package/documents/abstracts/Varshneya_Samdarshi_Southern-California-Systems-Biology_2017_abstract.docx +0 -0
- package/documents/developer_documents/State Diagram.graphml +0 -3525
- package/documents/developer_documents/graphml/State Diagram.graphml +0 -3115
- package/documents/developer_documents/older_versions/GRNsight State Diagram old.png +0 -0
- package/documents/developer_documents/older_versions/GRNsight State Diagram.png +0 -0
- package/documents/developer_documents/testing_script_generator/GRNsightTestingDocument.md +0 -998
- package/documents/developer_documents/testing_script_generator/featureList.json +0 -486
- package/documents/developer_documents/testing_script_generator/testing-script-generator.js +0 -149
- package/documents/manuscripts/peerj-computerscience-2016/GRNsight_PeerJ-CS_conference-presentations_2016.docx +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/GRNsight_PeerJ-CS_manuscript_2016.docx +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/GRNsight_PeerJ-CS_manuscript_2016_Table1.docx +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/GRNsight_PeerJ-CS_manuscript_2016_references.rtf +0 -264
- package/documents/manuscripts/peerj-computerscience-2016/GRNsight_PeerJ-CS_manuscript_2016_text-only.docx +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/figures/other-versions/21-genes_31-edges_Schade-data_for-screenshots.xlsx +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/figures/other-versions/Figure1_zoom100.jpg +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/figures/other-versions/Figure1_zoom100.png +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/figures/other-versions/Figure1_zoom100.psd +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/figures/other-versions/Figure1_zoom145.jpg +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/figures/other-versions/Figure1_zoom145.png +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/figures/other-versions/Figure1_zoom145.psd +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/figures/other-versions/Figure1_zoom145_900pix-wide.psd +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/figures/other-versions/Figure2_zoom100.jpg +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/figures/other-versions/Figure2_zoom100.png +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/figures/other-versions/Figure2_zoom100.psd +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/figures/other-versions/Figure2_zoom145.jpg +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/figures/other-versions/Figure2_zoom145.png +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/figures/other-versions/Figure2_zoom145.psd +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/figures/other-versions/Figure2_zoom145_900pix-wide.psd +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/figures/other-versions/Figure5A.pdf +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/figures/other-versions/Figure5B.pdf +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/figures/other-versions/Figure5C.eps +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/figures/other-versions/Figure5D.pdf +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/figures/other-versions/Figure5E.pdf +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/figures/other-versions/Figure5F.eps +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/figures/other-versions/Figure5_compiled.png +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/figures/submitted-versions/Figure3_GRNsight-Architecture.pdf +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/figures/submitted-versions/Figure4_GRNsight-Screenshot.pdf +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/figures/submitted-versions/Figure5_compiled.pdf +12 -5383
- package/documents/manuscripts/peerj-computerscience-2016/peerj-reviewing-10823-v0.pdf +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/revisions/GRNsight_PeerJ-CS_conference-presentations_2016_revised.docx +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/revisions/GRNsight_PeerJ-CS_cover-letter-and-response_2016.pdf +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/revisions/GRNsight_PeerJ-CS_cover-letter_2016.docx +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/revisions/GRNsight_PeerJ-CS_cover-letter_2016.pdf +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/revisions/GRNsight_PeerJ-CS_manuscript_2016_Table1.docx +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/revisions/GRNsight_PeerJ-CS_manuscript_2016_references_revised.rtf +0 -385
- package/documents/manuscripts/peerj-computerscience-2016/revisions/GRNsight_PeerJ-CS_manuscript_2016_text-only_revised.docx +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/revisions/GRNsight_PeerJ-CS_manuscript_2016_text-only_revised_marked.docx +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/revisions/GRNsight_PeerJ-CS_response-to-reviewers_2016.docx +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/revisions/GRNsight_PeerJ-CS_response-to-reviewers_2016.pdf +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/revisions/figures/Figure3_GRNsight-Architecture.pdf +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/revisions/figures/Figure4_GRNsight-Screenshot-auto.pdf +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/revisions/figures/Figure4_GRNsight-Screenshot.pdf +0 -0
- package/documents/manuscripts/peerj-computerscience-2016/revisions/peerj-reviewing-10823-v1.pdf +0 -0
- package/documents/posters/Anguiano_402_Presentation_Draft_Poster.pdf +0 -0
- package/documents/posters/Anguiano_402_Presentation_Draft_Poster.pptx +0 -0
- package/documents/posters/Anguiano_Varshneya_LMU-Symposium_2015_poster.pptx +0 -0
- package/documents/posters/Anguiano_Varshneya_SCCUR-Poster_20141122_poster.pptx +0 -0
- package/documents/posters/ChoeShinCMSI402-2.pptx +0 -0
- package/documents/posters/ChoeShinCMSI402.pptx +0 -0
- package/documents/posters/ChoeShinCMSI402Final.pptx +0 -0
- package/documents/posters/Dahlquist-et-al_BOSC_ISMB_2016_poster.pptx +0 -0
- package/documents/posters/Samdarshi et al. LMU Symposium 2017-finalDraft.pptx +0 -0
- package/documents/posters/Samdarshi et al. LMU Symposium 2018-firstDraft.pptx +0 -0
- package/documents/posters/Shin et al. SCCUR 2017 FinalDraft.pptx +0 -0
- package/documents/posters/Southwick_CMSI402_2014_poster.pptx +0 -0
- package/documents/posters/Varshneya_Samdarshi_LMU-Symposium_2016_poster.pptx +0 -0
- package/documents/posters/Varshneya_Samdarshi_Southern-California-Systems-Biology-Conference_2017_poster.pptx +0 -0
- package/documents/posters/~$Samdarshi et al. LMU Symposium 2018-firstDraft.pptx +0 -0
- package/documents/presentations/Anguiano_402_Final_Presentation.pptx +0 -0
- package/documents/presentations/Choe_SCCUR2017.pptx +0 -0
- package/documents/presentations/Choe_SWERapidFire2017_final.pptx +0 -0
- package/documents/presentations/Dahlquist_BOSC_20160709.pptx +0 -0
- package/documents/presentations/Dahlquist_ExperimentalBiology_20160404_talk.pptx +0 -0
- package/documents/presentations/Dahlquist_SoCalSysBio_20150131_talk.pptx +0 -0
- package/documents/presentations/Samdarshi et al. LMU Symposium 2017-draft.pptx +0 -0
- package/documents/presentations/Southwick_Anguiano_LMU-Symposium_20140329_talk.pptx +0 -0
- package/documents/presentations/Southwick_CMSI402_Presentation_20140508_talk.pptx +0 -0
- package/documents/presentations/Varshneya-Anguiano-LMU Symposium-201703.pptx +0 -0
- package/documents/presentations/~$Choe_SWERapidFire2017_final.pptx +0 -0
- package/documents/reports/Varshneya-201701-AnnotatedBibliography.docx +0 -0
- package/documents/reports/Varshneya-201702-Introduction.docx +0 -0
- package/documents/reports/Varshneya-201702-Outline.docx +0 -0
- package/documents/reports/Varshneya-201703-Discussion.docx +0 -0
- package/documents/reports/Varshneya-201703-MMResults.docx +0 -0
- package/documents/reports/Varshneya-201704-Draft-1.docx +0 -0
- package/documents/reports/Varshneya-201704-Final.docx +0 -0
- package/test/graph-library-tests.js +0 -165
- package/test-files/demo-files/21-genes_50-edges_Dahlquist-data_estimation_output.xlsx +0 -0
- package/test-files/demo-files/21-genes_50-edges_Dahlquist-data_input.xlsx +0 -0
- package/test-files/graph-tests/different-sized-networks/10-genes-max-edges.xlsx +0 -0
- package/test-files/graph-tests/different-sized-networks/12-genes-max-edges.xlsx +0 -0
- package/test-files/graph-tests/different-sized-networks/35-genes-max-edges.xlsx +0 -0
- package/test-files/graph-tests/different-sized-networks/40-genes-0-edges.xlsx +0 -0
- package/test-files/graph-tests/different-sized-networks/40-genes-max-edges.xlsx +0 -0
- package/test-files/graph-tests/different-sized-networks/42-genes-max-edges.xlsx +0 -0
- package/test-files/graph-tests/different-sized-networks/50-genes-max-edges.xlsx +0 -0
- package/test-files/graph-tests/different-sized-networks/75-genes-150-edges.xlsx +0 -0
- package/web-client/public/js/container.js +0 -121
- package/web-client/public/js/node-coloring.js +0 -306
- package/web-client/public/js/sliders.js +0 -197
- package/web-client/views/upload.jade +0 -458
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
import Grid from "d3-v4-grid";
|
|
2
|
-
|
|
2
|
+
import { grnState } from "./grnstate";
|
|
3
|
+
import { modifyChargeParameter, modifyLinkDistanceParameter, valueValidator } from "./update-app";
|
|
4
|
+
import {
|
|
5
|
+
ENDS_IN_EXPRESSION_REGEXP,
|
|
6
|
+
VIEWPORT_FIT,
|
|
7
|
+
ZOOM_INPUT,
|
|
8
|
+
ZOOM_PERCENT,
|
|
9
|
+
ZOOM_SLIDER,
|
|
10
|
+
ZOOM_DISPLAY_MINIMUM_VALUE,
|
|
11
|
+
ZOOM_DISPLAY_MAXIMUM_VALUE,
|
|
12
|
+
ZOOM_DISPLAY_MIDDLE,
|
|
13
|
+
ZOOM_ADAPTIVE_MAX_SCALE,
|
|
14
|
+
} from "./constants";
|
|
3
15
|
|
|
4
16
|
/* globals d3 */
|
|
5
17
|
/* eslint-disable no-use-before-define, func-style */
|
|
@@ -17,7 +29,25 @@ const hasExpressionData = require("./node-coloring").hasExpressionData;
|
|
|
17
29
|
/* eslint no-unused-vars: [2, {"varsIgnorePattern": "text|getMappedValue|manualZoom"}] */
|
|
18
30
|
/* eslint-disable no-unused-vars */
|
|
19
31
|
|
|
20
|
-
|
|
32
|
+
/**
|
|
33
|
+
* Resize detection logic: to avoid "listener leaks," this is set up a single time here, with an assignable
|
|
34
|
+
* updateFunction being set when needed.
|
|
35
|
+
*/
|
|
36
|
+
let mutationCallback = null;
|
|
37
|
+
const resizeObserver = new MutationObserver((mutationsList, observer) => {
|
|
38
|
+
if (typeof(mutationCallback) === "function") {
|
|
39
|
+
mutationCallback(mutationsList, observer);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
export var updaters = {
|
|
44
|
+
setNodesToGrid: () => {},
|
|
45
|
+
setNodesToForceGraph: () => {},
|
|
46
|
+
renderNodeColoring: () => {},
|
|
47
|
+
removeNodeColoring: () => {},
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export var drawGraph = function (workbook) {
|
|
21
51
|
/* eslint-enable no-unused-vars */
|
|
22
52
|
var $container = $(".grnsight-container");
|
|
23
53
|
d3.selectAll("svg").remove();
|
|
@@ -27,39 +57,47 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
27
57
|
var width = $container.width();
|
|
28
58
|
var height = $container.height();
|
|
29
59
|
var nodeHeight = 30;
|
|
30
|
-
var colorOptimal = true;
|
|
31
60
|
var grayThreshold = +$("#grayThresholdInput").val();
|
|
32
61
|
|
|
33
62
|
var dashedLine = $("#dashedGrayLineButton").prop("checked");
|
|
34
63
|
|
|
35
64
|
var CURSOR_CLASSES = "cursorGrab cursorGrabbing";
|
|
36
65
|
|
|
37
|
-
|
|
38
|
-
$("#zoomPercent").html(100 + "%"); // initalize zoom percentage value
|
|
39
|
-
|
|
40
|
-
$("#warningMessage").html(network.warnings.length !== 0 ? "Click here in order to view warnings." : "");
|
|
66
|
+
$("#warningMessage").html(workbook.warnings.length !== 0 ? "Click here in order to view warnings." : "");
|
|
41
67
|
|
|
42
68
|
var getNodeWidth = function (node) {
|
|
43
69
|
return node.name.length * 12 + 5;
|
|
44
70
|
};
|
|
45
71
|
|
|
46
|
-
// If colorOptimal is false, then weighting is ignored, and the lines are all drawn as if it was an unweighted sheet
|
|
47
|
-
if (!$("#colorEdges").hasClass("active")) {
|
|
48
|
-
colorOptimal = false;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
72
|
var adaptive = !$("input[name='viewport']").prop("checked");
|
|
52
73
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
74
|
+
/**
|
|
75
|
+
* The *_SCALE values represent the actual zoom values used to transform the graph.
|
|
76
|
+
* The *_DISPLAY values represent the value that is shown in the user interface.
|
|
77
|
+
*
|
|
78
|
+
* Separating these values allows for flexible configuration of what the user sees vs. the actual scale factor
|
|
79
|
+
* used in transformations. This "distortion" is done so that "actual size" or 100% can be shown as the midpoint
|
|
80
|
+
* on the zoom slider, even if the numeric ranges to the left and right of the midpoint are asymmetric (as they
|
|
81
|
+
* are here).
|
|
82
|
+
*/
|
|
83
|
+
const createZoomScale = (domainMin, domainMax, rangeMin, rangeMax) => d3.scaleLinear()
|
|
84
|
+
.domain([domainMin, domainMax])
|
|
85
|
+
.range([rangeMin, rangeMax])
|
|
86
|
+
.clamp(true);
|
|
57
87
|
|
|
58
|
-
|
|
88
|
+
const MIN_DISPLAY = ZOOM_DISPLAY_MINIMUM_VALUE;
|
|
89
|
+
const ADAPTIVE_MAX_DISPLAY = ZOOM_DISPLAY_MAXIMUM_VALUE;
|
|
90
|
+
const MIN_SCALE = 0.25;
|
|
91
|
+
const MIDDLE_SCALE = 1;
|
|
59
92
|
|
|
60
|
-
|
|
93
|
+
const zoomScaleLeft = createZoomScale(MIN_DISPLAY, ZOOM_DISPLAY_MIDDLE, MIN_SCALE, MIDDLE_SCALE);
|
|
94
|
+
const zoomScaleRight = createZoomScale(
|
|
95
|
+
ZOOM_DISPLAY_MIDDLE, ADAPTIVE_MAX_DISPLAY, MIDDLE_SCALE, ZOOM_ADAPTIVE_MAX_SCALE);
|
|
61
96
|
|
|
62
|
-
|
|
97
|
+
// Create an array of all the network weights
|
|
98
|
+
var allWeights = workbook.positiveWeights.concat(workbook.negativeWeights);
|
|
99
|
+
// Assign the entire array weights of 1, if color edges turned off
|
|
100
|
+
if (!grnState.colorOptimal) {
|
|
63
101
|
for (var i = 0; i < allWeights.length; i++) {
|
|
64
102
|
if ( allWeights[i] !== 0 ) {
|
|
65
103
|
allWeights[i] = 1;
|
|
@@ -71,18 +109,25 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
71
109
|
}
|
|
72
110
|
}
|
|
73
111
|
|
|
74
|
-
|
|
112
|
+
const maxWeight = Math.max(Math.abs(d3.max(allWeights)), Math.abs(d3.min(allWeights)));
|
|
113
|
+
|
|
114
|
+
// Get the largest magnitude weight and set that as the default normalization factor
|
|
115
|
+
if (grnState.newWorkbook) {
|
|
116
|
+
grnState.normalizationMax = maxWeight;
|
|
117
|
+
grnState.resetNormalizationMax = maxWeight;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Normalize all weights b/w 2-14
|
|
75
121
|
var normMax = +$("#normalization-max").val();
|
|
76
122
|
var totalScale = d3.scaleLinear()
|
|
77
|
-
.domain([0, normMax > 0 ? normMax :
|
|
123
|
+
.domain([0, normMax > 0 ? normMax : maxWeight])
|
|
78
124
|
.range([2, 14])
|
|
79
125
|
.clamp(true);
|
|
80
126
|
|
|
81
127
|
var unweighted = false;
|
|
82
128
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
if (network.sheetType === "unweighted") {
|
|
129
|
+
// if unweighted, all weights are 2
|
|
130
|
+
if (workbook.sheetType === "unweighted") {
|
|
86
131
|
totalScale = d3.scaleQuantile()
|
|
87
132
|
.domain([d3.extent(allWeights)])
|
|
88
133
|
.range(["2"]);
|
|
@@ -90,13 +135,12 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
90
135
|
$(".normalization-form").append("placeholder='unweighted'");
|
|
91
136
|
document.getElementById("edge-weight-normalization-factor-menu").setAttribute("placeholder", "");
|
|
92
137
|
} else {
|
|
93
|
-
var maxWeight = d3.max(allWeights);
|
|
94
138
|
document.getElementById("normalization-max").setAttribute("placeholder", maxWeight);
|
|
95
139
|
document.getElementById("edge-weight-normalization-factor-menu").setAttribute("placeholder", maxWeight);
|
|
96
140
|
}
|
|
97
141
|
|
|
98
142
|
var getEdgeThickness = function (edge) {
|
|
99
|
-
return Math.
|
|
143
|
+
return Math.floor(totalScale(Math.abs(edge.value)));
|
|
100
144
|
};
|
|
101
145
|
|
|
102
146
|
var simulation = d3.forceSimulation()
|
|
@@ -153,7 +197,8 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
153
197
|
|
|
154
198
|
var svg = d3.select($container[0]).append("svg")
|
|
155
199
|
.attr("width", width)
|
|
156
|
-
.attr("height", height)
|
|
200
|
+
.attr("height", height)
|
|
201
|
+
.attr("id", "exportContainer");
|
|
157
202
|
|
|
158
203
|
var zoomContainer = svg.append("g") // required for zoom to work
|
|
159
204
|
.attr("class", "boundingBox")
|
|
@@ -163,10 +208,12 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
163
208
|
var boundingBoxContainer = zoomContainer.append("g"); // appended another g here...
|
|
164
209
|
|
|
165
210
|
var zoom = d3.zoom()
|
|
166
|
-
.scaleExtent([
|
|
211
|
+
.scaleExtent([MIN_SCALE, ZOOM_ADAPTIVE_MAX_SCALE])
|
|
167
212
|
.on("zoom", zoomed);
|
|
168
213
|
|
|
169
|
-
svg.style("pointer-events", "all").call(zoomDrag)
|
|
214
|
+
svg.style("pointer-events", "all").call(zoomDrag)
|
|
215
|
+
.style("font-family", "sans-serif");
|
|
216
|
+
|
|
170
217
|
|
|
171
218
|
function zoomed () {
|
|
172
219
|
zoomContainer.attr("transform", d3.event.transform);
|
|
@@ -174,14 +221,14 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
174
221
|
|
|
175
222
|
d3.select("svg").on("dblclick.zoom", null); // disables double click zooming
|
|
176
223
|
|
|
177
|
-
|
|
178
|
-
|
|
224
|
+
// This rectangle catches all of the mousewheel and pan events, without letting
|
|
225
|
+
// them bubble up to the body.
|
|
179
226
|
boundingBoxContainer.append("rect")
|
|
180
227
|
.attr("width", width)
|
|
181
228
|
.attr("height", height)
|
|
182
229
|
.style("fill", "none")
|
|
183
230
|
.style("pointer-events", "all")
|
|
184
|
-
.attr("stroke",
|
|
231
|
+
.attr("stroke", "none" )
|
|
185
232
|
.append("g");
|
|
186
233
|
|
|
187
234
|
d3.selectAll(".scrollBtn").on("click", null); // Remove event handlers, if there were any.
|
|
@@ -193,146 +240,99 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
193
240
|
});
|
|
194
241
|
d3.select(".center").on("click", center);
|
|
195
242
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
without transformations will have 1 at the very far left. However, that's
|
|
205
|
-
an inaccurate way to represent what's actually happening. So this function
|
|
206
|
-
maps the scale from 0 to some x, with that x being calculated based on the
|
|
207
|
-
input scales.
|
|
208
|
-
*/
|
|
209
|
-
var setupZoomSlider = function (minScale) {
|
|
210
|
-
// If the maximumScale is 1, we won't need to calculate any values from 1 to maxScale.
|
|
211
|
-
// So we'll just treat it as 0.
|
|
212
|
-
|
|
213
|
-
var maxScale = ADAPTIVE_MAX_SCALE;
|
|
214
|
-
|
|
215
|
-
// Each integer on the zoom is equivalent to 100 steps.
|
|
216
|
-
var NUMBER_POINTS_PER_INT = 100;
|
|
217
|
-
|
|
218
|
-
// Get the value that, if multiplied by the minScale value, would return 1. (ex: 0.25 * 4 = 1)
|
|
219
|
-
// This gives us the equivalent value of this minimum scale, should it be treated
|
|
220
|
-
// as a scale increase. This mostly allows us to treat this minimum scale as a non-decimal value,
|
|
221
|
-
// but it also provides a way to compare the total effect this minimum scale would have
|
|
222
|
-
// in a way that is easier to understand.
|
|
223
|
-
var minScaleReversed = 100 / (minScale * 100);
|
|
224
|
-
|
|
225
|
-
// Number of points required to display the minimum scale, now that's it's been transformed. These
|
|
226
|
-
// are the points that represent everything on the scale less than one.
|
|
227
|
-
leftPoints = minScaleReversed * NUMBER_POINTS_PER_INT;
|
|
228
|
-
|
|
229
|
-
// We want to end up with a total increase that, once we've gone through all the
|
|
230
|
-
// left points, produces 1 when added to minscale. So for scale 0.25 with 400
|
|
231
|
-
// left points, we need to know what we could add to 0.25 400 times to produce 1.
|
|
232
|
-
// We divide 0.75 by 400 to get that result.
|
|
233
|
-
scaleIncreasePerLeftPoint = (1 - minScale) / leftPoints;
|
|
234
|
-
|
|
235
|
-
// Points representing scales greater than 1.
|
|
236
|
-
rightPoints = maxScale * NUMBER_POINTS_PER_INT;
|
|
237
|
-
|
|
238
|
-
// For the same concept as above, we need to figure out what to add to 1 so
|
|
239
|
-
// so that we can end up with maxScale. Note that we start at 1 and not 0 because
|
|
240
|
-
// the scale is beginning at 1.
|
|
241
|
-
scaleIncreasePerRightPoint = (maxScale - MIDDLE_SCALE) / rightPoints;
|
|
242
|
-
var totalPoints = leftPoints + rightPoints;
|
|
243
|
-
|
|
244
|
-
// Returns the x that we're mapping to. Now we can set up the range slider.
|
|
245
|
-
var maxRangeValue = totalPoints / 100;
|
|
246
|
-
|
|
247
|
-
$(".zoomSlider").attr("min", 0);
|
|
248
|
-
$(".zoomSlider").attr("max", maxRangeValue);
|
|
249
|
-
$(".zoomSlider").val(0.01 * leftPoints);
|
|
243
|
+
const setGraphZoom = zoomScale => {
|
|
244
|
+
if (zoomScale < MIDDLE_SCALE) {
|
|
245
|
+
$container.removeClass(CURSOR_CLASSES).addClass("cursorGrab");
|
|
246
|
+
} else if (!adaptive && zoomScale >= MIDDLE_SCALE) {
|
|
247
|
+
$container.removeClass(CURSOR_CLASSES);
|
|
248
|
+
}
|
|
249
|
+
var container = zoomContainer;
|
|
250
|
+
zoom.scaleTo(container, zoomScale);
|
|
250
251
|
};
|
|
251
252
|
|
|
252
|
-
|
|
253
|
+
// See setupZoomElements below to see how these are initialized. They are declared here because
|
|
254
|
+
// updateAppBasedOnZoomValue uses them (lexical positioning is chosen here for better context).
|
|
255
|
+
let sliderMidpoint;
|
|
256
|
+
let zoomScaleSliderLeft;
|
|
257
|
+
let zoomScaleSliderRight;
|
|
253
258
|
|
|
254
|
-
|
|
255
|
-
var ZOOM_RANGE = 200;
|
|
259
|
+
const updateAppBasedOnZoomValue = () => {
|
|
256
260
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
value = value === 0 ? MIDDLE_SCALE : value;
|
|
260
|
-
$("#zoomPercent").html(value + "%");
|
|
261
|
-
$("#zoomInput").val(value);
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
function getMappedValue (scale) {
|
|
265
|
-
// Reverse the calculations from setupZoomSlider to get value from equivalentScale
|
|
266
|
-
var equivalentPoint;
|
|
267
|
-
if (scale <= MIDDLE_SCALE) {
|
|
268
|
-
equivalentPoint = (scale - minimumScale) / (scaleIncreasePerLeftPoint * 100);
|
|
269
|
-
} else {
|
|
270
|
-
equivalentPoint = (scale - 1) / scaleIncreasePerRightPoint + leftPoints;
|
|
271
|
-
equivalentPoint /= 100;
|
|
261
|
+
if (!adaptive) {
|
|
262
|
+
grnState.zoomValue = 100.0;
|
|
272
263
|
}
|
|
273
|
-
$(".zoomSlider").val(equivalentPoint.toFixed(2));
|
|
274
|
-
}
|
|
275
264
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
}
|
|
288
|
-
zoomSliderScale = equivalentScale;
|
|
289
|
-
manualZoomFunction(equivalentScale);
|
|
290
|
-
} else {
|
|
291
|
-
// Prohibits zooming past 100% if (!adaptive && value >= ADAPTIVE_MAX_SCALE)
|
|
292
|
-
$(".zoomSlider").val(ADAPTIVE_MAX_SCALE);
|
|
293
|
-
manualZoomFunction(MIDDLE_SCALE);
|
|
294
|
-
updateZoomValue();
|
|
265
|
+
const zoomDisplay = grnState.zoomValue;
|
|
266
|
+
setGraphZoom((zoomDisplay <= ZOOM_DISPLAY_MIDDLE ? zoomScaleLeft : zoomScaleRight)(zoomDisplay));
|
|
267
|
+
|
|
268
|
+
const finalDisplay = grnState.zoomValue;
|
|
269
|
+
$(ZOOM_PERCENT).text(`${finalDisplay}%`);
|
|
270
|
+
|
|
271
|
+
// Special handling for zoom input field: the user might be in the middle of typing a value that is
|
|
272
|
+
// _temporarily_ out of range (e.g., "1" while typing "100") and we don’t want to overwrite that.
|
|
273
|
+
// The special case can be detected if the input element currently has focus.
|
|
274
|
+
if (document.activeElement !== document.querySelector(ZOOM_INPUT)) {
|
|
275
|
+
$(ZOOM_INPUT).val(finalDisplay);
|
|
295
276
|
}
|
|
277
|
+
|
|
278
|
+
$(ZOOM_SLIDER).val((finalDisplay <= ZOOM_DISPLAY_MIDDLE ? zoomScaleSliderLeft : zoomScaleSliderRight)
|
|
279
|
+
.invert(finalDisplay));
|
|
296
280
|
};
|
|
297
281
|
|
|
298
|
-
|
|
299
|
-
|
|
282
|
+
/**
|
|
283
|
+
* To eliminate coupling between how the zoom slider element is defined in markup and how zoom values are
|
|
284
|
+
* calculated and displayed, we define this function to read the zoom slider for its minimum, maximum, and
|
|
285
|
+
* midpoint. The slider’s minimum will be shown as MIN_DISPLAY, the slider’s maximum will be shown as
|
|
286
|
+
* ADAPTIVE_MAX_DISPLAY, and the slider’s midpoint will be shown as ZOOM_DISPLAY_MIDDLE.
|
|
287
|
+
*
|
|
288
|
+
* Elements showing minimum and maximum display values are also updated here so that they are consistent
|
|
289
|
+
* with these constants. This way, all zoom calculations are based on these constants, and changing these
|
|
290
|
+
* constants should be all that is needed to adjust displayed and actual zoom values.
|
|
291
|
+
*/
|
|
292
|
+
var setupZoomSlider = () => {
|
|
293
|
+
const sliderMin = +$(ZOOM_SLIDER).attr("min");
|
|
294
|
+
const sliderMax = +$(ZOOM_SLIDER).attr("max");
|
|
295
|
+
sliderMidpoint = (sliderMin + sliderMax) / 2;
|
|
296
|
+
|
|
297
|
+
zoomScaleSliderLeft = createZoomScale(sliderMin, sliderMidpoint, MIN_DISPLAY, ZOOM_DISPLAY_MIDDLE);
|
|
298
|
+
zoomScaleSliderRight = createZoomScale(sliderMidpoint, sliderMax, ZOOM_DISPLAY_MIDDLE, ADAPTIVE_MAX_DISPLAY);
|
|
299
|
+
|
|
300
|
+
// Reset the zoom value to the midpoint whenever we load a new workbook.
|
|
301
|
+
if (grnState.newWorkbook) {
|
|
302
|
+
grnState.zoomValue = ZOOM_DISPLAY_MIDDLE;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
updateAppBasedOnZoomValue();
|
|
300
306
|
};
|
|
301
307
|
|
|
308
|
+
setupZoomSlider();
|
|
309
|
+
|
|
302
310
|
var zoomInputValidator = function (value) {
|
|
303
|
-
return valueValidator(
|
|
311
|
+
return valueValidator(MIN_DISPLAY, ADAPTIVE_MAX_DISPLAY, value);
|
|
304
312
|
};
|
|
305
313
|
|
|
306
|
-
$(
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
314
|
+
$(ZOOM_INPUT).on("input", () => {
|
|
315
|
+
grnState.zoomValue = zoomInputValidator(+$(ZOOM_INPUT).val());
|
|
316
|
+
updateAppBasedOnZoomValue();
|
|
317
|
+
}).blur(() => $(ZOOM_INPUT).val(grnState.zoomValue));
|
|
318
|
+
|
|
319
|
+
d3.select(ZOOM_SLIDER).on("input", function () {
|
|
320
|
+
const sliderValue = +$(this).val();
|
|
321
|
+
grnState.zoomValue = Math.floor(
|
|
322
|
+
(sliderValue <= sliderMidpoint ? zoomScaleSliderLeft : zoomScaleSliderRight)(sliderValue)
|
|
323
|
+
);
|
|
324
|
+
updateAppBasedOnZoomValue();
|
|
317
325
|
}).on("mousedown", function () {
|
|
318
326
|
manualZoom = true;
|
|
319
327
|
}).on("mouseup", function () {
|
|
320
328
|
manualZoom = false;
|
|
321
329
|
});
|
|
322
330
|
|
|
331
|
+
if (!grnState.newWorkbook) {
|
|
332
|
+
updateAppBasedOnZoomValue();
|
|
333
|
+
}
|
|
323
334
|
|
|
324
|
-
|
|
325
|
-
if (zoomScale < MIDDLE_SCALE) {
|
|
326
|
-
$container.removeClass(CURSOR_CLASSES).addClass("cursorGrab");
|
|
327
|
-
} else if (!adaptive && zoomScale >= MIDDLE_SCALE) {
|
|
328
|
-
$container.removeClass(CURSOR_CLASSES);
|
|
329
|
-
}
|
|
330
|
-
updateZoomValue();
|
|
331
|
-
var container = zoomContainer;
|
|
332
|
-
zoom.scaleTo(container, zoomScale);
|
|
333
|
-
};
|
|
334
|
-
|
|
335
|
-
d3.selectAll(".boundBoxSize").on("click", function () {
|
|
335
|
+
const adjustGraphSize = () => {
|
|
336
336
|
var newWidth = $container.width();
|
|
337
337
|
var newHeight = $container.height();
|
|
338
338
|
|
|
@@ -344,30 +344,40 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
344
344
|
height = newHeight;
|
|
345
345
|
}
|
|
346
346
|
|
|
347
|
-
|
|
348
|
-
|
|
347
|
+
// Subtract 1 from SVG height if we are fitting to window so as to prevent scrollbars from showing up
|
|
348
|
+
// Is inconsistent, but I'm tired of fighting with it...
|
|
349
349
|
d3.select("svg").attr("width", newWidth)
|
|
350
|
-
.attr("height", $(".grnsight-container").hasClass(
|
|
350
|
+
.attr("height", $(".grnsight-container").hasClass(VIEWPORT_FIT) ? newHeight : newHeight);
|
|
351
351
|
d3.select("rect").attr("width", width).attr("height", height);
|
|
352
352
|
d3.select(".boundingBox").attr("width", width).attr("height", height);
|
|
353
|
-
}
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
mutationCallback = adjustGraphSize;
|
|
356
|
+
resizeObserver.disconnect();
|
|
357
|
+
resizeObserver.observe($container.get(0), { attributes: true });
|
|
354
358
|
|
|
355
359
|
var restrictGraphToViewport = function (fixed) {
|
|
356
360
|
if (!fixed) {
|
|
357
361
|
$("#restrict-graph-to-viewport span").removeClass("glyphicon-ok");
|
|
362
|
+
$(document).ready(function () {
|
|
363
|
+
$(".scale-and-scroll").show();
|
|
364
|
+
});
|
|
358
365
|
$("input[name=viewport]").removeProp("checked");
|
|
359
|
-
$container.addClass("
|
|
366
|
+
$container.addClass("cursorGrabbing");
|
|
360
367
|
adaptive = true;
|
|
361
368
|
d3.select("rect").attr("stroke", "none");
|
|
362
369
|
center();
|
|
363
370
|
} else if (fixed) {
|
|
364
371
|
$("#restrict-graph-to-viewport span").addClass("glyphicon-ok");
|
|
365
372
|
$("input[name=viewport]").prop("checked", "checked");
|
|
373
|
+
$(document).ready(function () {
|
|
374
|
+
$(".scale-and-scroll").hide();
|
|
375
|
+
});
|
|
366
376
|
adaptive = false;
|
|
367
377
|
$container.removeClass(CURSOR_CLASSES);
|
|
368
|
-
if (
|
|
369
|
-
|
|
370
|
-
|
|
378
|
+
if (grnState.zoomValue > ZOOM_DISPLAY_MIDDLE) {
|
|
379
|
+
grnState.zoomValue = ZOOM_DISPLAY_MIDDLE;
|
|
380
|
+
updateAppBasedOnZoomValue();
|
|
371
381
|
$container.removeClass(CURSOR_CLASSES);
|
|
372
382
|
}
|
|
373
383
|
width = $container.width();
|
|
@@ -378,6 +388,7 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
378
388
|
$(".boundingBox").attr("width", width).attr("height", height);
|
|
379
389
|
center();
|
|
380
390
|
}
|
|
391
|
+
updateAppBasedOnZoomValue(); // Update zoom value within bounds
|
|
381
392
|
};
|
|
382
393
|
|
|
383
394
|
d3.select("#restrict-graph-to-viewport").on("click", function () {
|
|
@@ -390,22 +401,15 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
390
401
|
restrictGraphToViewport(fixed);
|
|
391
402
|
});
|
|
392
403
|
|
|
393
|
-
$(window).on("resize", function () {
|
|
394
|
-
if ($container.hasClass("containerFit")) {
|
|
395
|
-
$(".boundBoxSize").trigger("click");
|
|
396
|
-
}
|
|
397
|
-
});
|
|
398
|
-
|
|
399
404
|
function center () {
|
|
400
405
|
var viewportWidth = $container.width();
|
|
401
406
|
var viewportHeight = $container.height();
|
|
402
407
|
zoom.translateTo(zoomContainer, viewportWidth / 2, viewportHeight / 2);
|
|
403
|
-
simulation.alphaTarget(0.3).restart();
|
|
404
408
|
}
|
|
405
409
|
|
|
406
410
|
function move (direction) {
|
|
407
|
-
var width = direction === "left" ? 50 : (direction === "right" ?
|
|
408
|
-
var height = direction === "up" ? 50 : (direction === "down" ?
|
|
411
|
+
var width = direction === "left" ? -50 : (direction === "right" ? 50 : 0);
|
|
412
|
+
var height = direction === "up" ? -50 : (direction === "down" ? 50 : 0);
|
|
409
413
|
zoom.translateBy(zoomContainer, width, height);
|
|
410
414
|
}
|
|
411
415
|
|
|
@@ -416,18 +420,18 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
416
420
|
var weight = boundingBoxContainer.selectAll(".weight");
|
|
417
421
|
|
|
418
422
|
simulation
|
|
419
|
-
.nodes(
|
|
423
|
+
.nodes(workbook.genes)
|
|
420
424
|
.on("tick", tick);
|
|
421
425
|
|
|
422
426
|
simulation.force("link")
|
|
423
|
-
.links(
|
|
427
|
+
.links(workbook.links);
|
|
424
428
|
|
|
425
|
-
link = link.data(
|
|
429
|
+
link = link.data(workbook.links)
|
|
426
430
|
.enter().append("g")
|
|
427
431
|
.attr("class", "link")
|
|
428
432
|
.attr("strokeWidth", getEdgeThickness);
|
|
429
433
|
|
|
430
|
-
node = node.data(
|
|
434
|
+
node = node.data(workbook.genes)
|
|
431
435
|
.enter().append("g")
|
|
432
436
|
.attr("class", "node")
|
|
433
437
|
.attr("id", function (d) {
|
|
@@ -438,13 +442,14 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
438
442
|
.call(drag)
|
|
439
443
|
.on("dblclick", dblclick);
|
|
440
444
|
|
|
441
|
-
if (
|
|
445
|
+
if (workbook.sheetType === "weighted") {
|
|
442
446
|
link.append("path")
|
|
443
447
|
.attr("class", "mousezone")
|
|
444
448
|
.style("stroke-width", function (d) {
|
|
445
449
|
var baseThickness = getEdgeThickness(d);
|
|
446
450
|
return Math.max(baseThickness, 7);
|
|
447
|
-
})
|
|
451
|
+
})
|
|
452
|
+
.attr("stroke-opacity", "0");
|
|
448
453
|
}
|
|
449
454
|
|
|
450
455
|
link.append("path")
|
|
@@ -452,9 +457,10 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
452
457
|
.attr("id", function (d) {
|
|
453
458
|
return "path" + d.source.index + "_" + d.target.index;
|
|
454
459
|
}).style("stroke-width", function (d) {
|
|
455
|
-
|
|
460
|
+
d.strokeWidth = grnState.colorOptimal ? getEdgeThickness(d) : 2;
|
|
461
|
+
return d.strokeWidth;
|
|
456
462
|
}).style("stroke-dasharray", function (d) {
|
|
457
|
-
if (unweighted || !colorOptimal) {
|
|
463
|
+
if (unweighted || !grnState.colorOptimal) {
|
|
458
464
|
return "0";
|
|
459
465
|
} else if (normalize(d) <= grayThreshold && dashedLine === true) {
|
|
460
466
|
return "6, 9";
|
|
@@ -462,7 +468,7 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
462
468
|
return "0";
|
|
463
469
|
}
|
|
464
470
|
}).style("stroke", function (d) {
|
|
465
|
-
if (unweighted || !colorOptimal) {
|
|
471
|
+
if (unweighted || !grnState.colorOptimal) {
|
|
466
472
|
return "black";
|
|
467
473
|
} else if (normalize(d) <= grayThreshold) {
|
|
468
474
|
return "gray";
|
|
@@ -480,7 +486,7 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
480
486
|
var xOffsets;
|
|
481
487
|
var color;
|
|
482
488
|
|
|
483
|
-
if (
|
|
489
|
+
if (normalize(d) <= grayThreshold) {
|
|
484
490
|
minimum = "gray";
|
|
485
491
|
}
|
|
486
492
|
if ( x1 === x2 && y1 === y2 ) {
|
|
@@ -493,10 +499,10 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
493
499
|
return "url(#" + d.type + selfRef + "_StrokeWidth" + d.strokeWidth + minimum + ")";
|
|
494
500
|
} else {
|
|
495
501
|
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
if (d.value < 0 && colorOptimal) {
|
|
502
|
+
// If negative, you need one bar for horizontal and one for vertical.
|
|
503
|
+
// If the user is not coloring the weighted
|
|
504
|
+
// sheets, then we make all of the markers arrowheads.
|
|
505
|
+
if (d.value < 0 && grnState.colorOptimal) {
|
|
500
506
|
defs.append("marker")
|
|
501
507
|
.attr("id", "repressor" + selfRef + "_StrokeWidth" + d.strokeWidth + minimum)
|
|
502
508
|
.attr("refX", function () {
|
|
@@ -522,22 +528,22 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
522
528
|
})
|
|
523
529
|
.attr("orient", 180)
|
|
524
530
|
.append("rect")
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
531
|
+
.attr("width", function () {
|
|
532
|
+
return d.strokeWidth;
|
|
533
|
+
})
|
|
534
|
+
.attr("height", function () {
|
|
535
|
+
return 25 + d.strokeWidth;
|
|
536
|
+
})
|
|
537
|
+
.attr("rx", 10)
|
|
538
|
+
.attr("ry", 10)
|
|
539
|
+
.attr("style", function () {
|
|
540
|
+
if ( normalize(d) <= grayThreshold) {
|
|
541
|
+
color = "gray";
|
|
542
|
+
} else {
|
|
543
|
+
color = d.stroke;
|
|
544
|
+
}
|
|
545
|
+
return "stroke:" + color + "; fill: " + color + "; stroke-width: 0";
|
|
546
|
+
});
|
|
541
547
|
|
|
542
548
|
defs.append("marker")
|
|
543
549
|
.attr("id", "repressorHorizontal" + selfRef + "_StrokeWidth" + d.strokeWidth + minimum)
|
|
@@ -632,16 +638,16 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
632
638
|
})
|
|
633
639
|
.attr("orient", function () {
|
|
634
640
|
return (x1 === x2 && y1 === y2) ?
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
641
|
+
{
|
|
642
|
+
2: 270, 3: 270, 4: 268, 5: 264, 6: 268, 7: 252,
|
|
643
|
+
8: 248, 9: 243, 10: 240, 11: 240, 12: 235, 13: 233,
|
|
644
|
+
14: 232
|
|
645
|
+
}[d.strokeWidth] : "auto";
|
|
640
646
|
})
|
|
641
647
|
.append("path")
|
|
642
648
|
.attr("d", "M 0 0 L 14 5 L 0 10 Q 6 5 0 0")
|
|
643
649
|
.attr("style", function () {
|
|
644
|
-
if (unweighted || !colorOptimal) {
|
|
650
|
+
if (unweighted || !grnState.colorOptimal) {
|
|
645
651
|
color = "black";
|
|
646
652
|
} else if ( normalize(d) <= grayThreshold) {
|
|
647
653
|
color = "gray";
|
|
@@ -655,25 +661,29 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
655
661
|
return "url(#" + d.type + selfRef + "_StrokeWidth" + d.strokeWidth + minimum + ")";
|
|
656
662
|
});
|
|
657
663
|
|
|
658
|
-
if (
|
|
664
|
+
if (workbook.sheetType === "weighted") {
|
|
659
665
|
link.append("text")
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
+
.attr("class", "weight")
|
|
667
|
+
.attr("text-anchor", "middle")
|
|
668
|
+
.attr("text-anchor", "middle")
|
|
669
|
+
.attr("fill", "rgb(0,0,0)")
|
|
670
|
+
.style("font-family", "sans-serif")
|
|
671
|
+
.text(function (d) {
|
|
672
|
+
return d.value.toPrecision(4);
|
|
673
|
+
});
|
|
666
674
|
|
|
667
|
-
weight = weight.data(
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
675
|
+
weight = weight.data(workbook.links)
|
|
676
|
+
.enter().append("text")
|
|
677
|
+
.attr("class", "weight")
|
|
678
|
+
.attr("text-anchor", "middle")
|
|
679
|
+
.attr("fill", "rgb(0,0,0)")
|
|
680
|
+
.style("font-family", "sans-serif")
|
|
681
|
+
.text(function (d) {
|
|
682
|
+
return d.value.toPrecision(4);
|
|
683
|
+
})
|
|
684
|
+
.each(function (d) {
|
|
685
|
+
d.weightElement = d3.select(this);
|
|
686
|
+
});
|
|
677
687
|
|
|
678
688
|
}
|
|
679
689
|
|
|
@@ -693,6 +703,7 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
693
703
|
};
|
|
694
704
|
|
|
695
705
|
var CURVE_THRESHOLD = 200;
|
|
706
|
+
var EDGE_OFFSET = 20;
|
|
696
707
|
var lineTo = function (d) {
|
|
697
708
|
var node = d3.select("#node" + d.target.index);
|
|
698
709
|
var w = +node.attr("width");
|
|
@@ -705,14 +716,14 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
705
716
|
d.target.centerX = d.target.x + (w / 2);
|
|
706
717
|
d.target.centerY = d.target.y + (h / 2);
|
|
707
718
|
|
|
708
|
-
|
|
719
|
+
// This function calculates the newX and newY.
|
|
709
720
|
smartPathEnd(d, w, h);
|
|
710
721
|
x1 = d.source.newX;
|
|
711
722
|
y1 = d.source.newY;
|
|
712
723
|
x2 = d.target.newX;
|
|
713
724
|
y2 = d.target.newY;
|
|
714
725
|
|
|
715
|
-
|
|
726
|
+
// Unit vectors.
|
|
716
727
|
var ux = x2 - x1;
|
|
717
728
|
var uy = y2 - y1;
|
|
718
729
|
var umagnitude = Math.sqrt(ux * ux + uy * uy);
|
|
@@ -725,7 +736,7 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
725
736
|
vx /= vmagnitude;
|
|
726
737
|
vy /= vmagnitude;
|
|
727
738
|
|
|
728
|
-
|
|
739
|
+
// Check for vector direction.
|
|
729
740
|
if (((d.target.newX > d.source.x) && (d.target.newY > d.source.y)) ||
|
|
730
741
|
((d.target.newX < d.source.x) && (d.target.newY < d.source.y))) {
|
|
731
742
|
vx = -vx; vy = -vy;
|
|
@@ -739,15 +750,16 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
739
750
|
var cp2x = x2 - inlineOffset * ux + vx * orthoOffset;
|
|
740
751
|
var cp2y = y2 - inlineOffset * uy + vy * orthoOffset;
|
|
741
752
|
|
|
742
|
-
d.label = {
|
|
743
|
-
x: (x1 + cp1x + cp2x + x2) / 4,
|
|
744
|
-
y: (y1 + cp1y + cp2y + y2) / 4
|
|
745
|
-
};
|
|
746
|
-
|
|
747
753
|
cp1x = Math.min(Math.max(0, cp1x), width);
|
|
748
754
|
cp1y = Math.min(Math.max(0, cp1y), height);
|
|
749
755
|
cp2x = Math.min(Math.max(0, cp2x), width);
|
|
750
756
|
cp2y = Math.min(Math.max(0, cp2y), height);
|
|
757
|
+
|
|
758
|
+
d.label = {
|
|
759
|
+
x: Math.min(Math.max((x1 + cp1x + cp2x + x2) / 4, EDGE_OFFSET), width - 2 * EDGE_OFFSET),
|
|
760
|
+
y: Math.min(Math.max((y1 + cp1y + cp2y + y2) / 4, EDGE_OFFSET), height - EDGE_OFFSET)
|
|
761
|
+
};
|
|
762
|
+
|
|
751
763
|
return "C" + cp1x + " " + cp1y + ", " +
|
|
752
764
|
cp2x + " " + cp2y + ", " +
|
|
753
765
|
x2 + " " + y2;
|
|
@@ -768,71 +780,71 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
768
780
|
MINIMUM_DISTANCE = d.strokeWidth > 11 ? 16.5 : 15;
|
|
769
781
|
}
|
|
770
782
|
|
|
771
|
-
|
|
783
|
+
// Set an offset if the edge is a repressor to make room for the flat arrowhead
|
|
772
784
|
var globalOffset = parseFloat(d.strokeWidth);
|
|
773
785
|
|
|
774
|
-
if (d.value < 0 && colorOptimal) {
|
|
786
|
+
if (d.value < 0 && grnState.colorOptimal) {
|
|
775
787
|
globalOffset = Math.max(globalOffset, MINIMUM_DISTANCE);
|
|
776
788
|
}
|
|
777
789
|
|
|
778
790
|
var thicknessAdjustment = globalOffset > MINIMUM_DISTANCE ? 1 : 0;
|
|
779
791
|
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
792
|
+
// We need to work out the (tan of the) angle between the
|
|
793
|
+
// imaginary horizontal line running through the center of the
|
|
794
|
+
// target node and the imaginary line connecting the center of
|
|
795
|
+
// the target node with the top-left corner of the same
|
|
796
|
+
// node. Of course, this angle is fixed.
|
|
785
797
|
d.tanRatioFixed = (d.target.centerY - d.target.y) / (d.target.centerX - d.target.x);
|
|
786
798
|
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
799
|
+
// We also need to work out the (tan of the) angle between the
|
|
800
|
+
// imaginary horizontal line running through the center of the
|
|
801
|
+
// target node and the imaginary line connecting the center of
|
|
802
|
+
// the target node with the center of the source node. This
|
|
803
|
+
// angle changes as the nodes move around the screen.
|
|
792
804
|
d.tanRatioMoveable = Math.abs(d.target.centerY - d.source.newY) / Math.abs(d.target.centerX - d.source.newX);
|
|
793
805
|
// Note, JavaScript handles division-by-zero by returning
|
|
794
806
|
// Infinity, which in this case is useful, especially
|
|
795
807
|
// since it handles the subsequent Infinity arithmetic
|
|
796
808
|
// correctly.
|
|
797
809
|
|
|
798
|
-
|
|
810
|
+
// Now work out the intersection point
|
|
799
811
|
if (d.tanRatioMoveable === d.tanRatioFixed) {
|
|
800
|
-
|
|
801
|
-
|
|
812
|
+
// Then path is intersecting at corner of textbox so draw
|
|
813
|
+
// path to that point
|
|
802
814
|
|
|
803
|
-
|
|
815
|
+
// By default assume path intersects a left-side corner
|
|
804
816
|
d.target.newX = d.target.x - globalOffset;
|
|
805
817
|
|
|
806
|
-
|
|
818
|
+
// But...
|
|
807
819
|
if (d.target.centerX < d.source.newX) {
|
|
808
|
-
|
|
809
|
-
|
|
820
|
+
// i.e. if target node is to left of the source node
|
|
821
|
+
// then path intersects a right-side corner
|
|
810
822
|
d.target.newX = d.target.x + w + globalOffset;
|
|
811
823
|
}
|
|
812
824
|
|
|
813
|
-
|
|
825
|
+
// By default assume path intersects a top corner
|
|
814
826
|
d.target.newY = d.target.y - globalOffset;
|
|
815
827
|
|
|
816
|
-
|
|
828
|
+
// But...
|
|
817
829
|
if (d.target.centerY < d.source.newY) {
|
|
818
|
-
|
|
819
|
-
|
|
830
|
+
// i.e. if target node is above the source node
|
|
831
|
+
// then path intersects a bottom corner
|
|
820
832
|
d.target.newY = d.target.y + h + globalOffset;
|
|
821
833
|
}
|
|
822
834
|
}
|
|
823
835
|
|
|
824
836
|
if (d.tanRatioMoveable < d.tanRatioFixed) {
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
837
|
+
// Then path is intersecting on a vertical side of the
|
|
838
|
+
// textbox, which means we know the x-coordinate of the
|
|
839
|
+
// path endpoint but we need to work out the y-coordinate
|
|
828
840
|
|
|
829
|
-
|
|
841
|
+
// By default assume path intersects left vertical side
|
|
830
842
|
d.target.newX = d.target.x - globalOffset;
|
|
831
843
|
|
|
832
|
-
|
|
844
|
+
// But...
|
|
833
845
|
if (d.target.centerX < d.source.newX) {
|
|
834
|
-
|
|
835
|
-
|
|
846
|
+
// i.e. if target node is to left of the source node
|
|
847
|
+
// then path intersects right vertical side
|
|
836
848
|
if (d.type !== "arrowhead") {
|
|
837
849
|
d.target.newX = d.target.x + w + globalOffset + 0.25 * d.strokeWidth - thicknessAdjustment;
|
|
838
850
|
} else {
|
|
@@ -840,31 +852,31 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
840
852
|
}
|
|
841
853
|
}
|
|
842
854
|
|
|
843
|
-
|
|
855
|
+
// Now use a bit of trigonometry to work out the y-coord.
|
|
844
856
|
|
|
845
|
-
|
|
857
|
+
// By default assume path intersects towards top of node
|
|
846
858
|
d.target.newY = d.target.centerY - ((d.target.centerX - d.target.x) * d.tanRatioMoveable);
|
|
847
859
|
|
|
848
|
-
|
|
860
|
+
// But...
|
|
849
861
|
if (d.target.centerY < d.source.newY) {
|
|
850
|
-
|
|
851
|
-
|
|
862
|
+
// i.e. if target node is above the source node
|
|
863
|
+
// then path intersects towards bottom of the node
|
|
852
864
|
d.target.newY = (2 * d.target.y) - d.target.newY + h;
|
|
853
865
|
}
|
|
854
866
|
}
|
|
855
867
|
|
|
856
868
|
if (d.tanRatioMoveable > d.tanRatioFixed) {
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
869
|
+
// Then path is intersecting on a horizontal side of the
|
|
870
|
+
// textbox, which means we know the y-coordinate of the
|
|
871
|
+
// path endpoint but we need to work out the x-coordinate
|
|
860
872
|
|
|
861
|
-
|
|
873
|
+
// By default assume path intersects top horizontal side
|
|
862
874
|
d.target.newY = d.target.y - globalOffset;
|
|
863
875
|
|
|
864
|
-
|
|
876
|
+
// But...
|
|
865
877
|
if (d.target.centerY < d.source.newY) {
|
|
866
|
-
|
|
867
|
-
|
|
878
|
+
// i.e. if target node is above the source node
|
|
879
|
+
// then path intersects bottom horizontal side
|
|
868
880
|
if (d.type !== "arrowhead") {
|
|
869
881
|
d.target.newY = d.target.y + h + globalOffset + 0.25 * d.strokeWidth - thicknessAdjustment;
|
|
870
882
|
} else {
|
|
@@ -872,15 +884,15 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
872
884
|
}
|
|
873
885
|
}
|
|
874
886
|
|
|
875
|
-
|
|
887
|
+
// Now use a bit of trigonometry to work out the x-coord.
|
|
876
888
|
|
|
877
|
-
|
|
889
|
+
// By default assume path intersects towards lefthand side
|
|
878
890
|
d.target.newX = d.target.centerX - ((d.target.centerY - d.target.y) / d.tanRatioMoveable);
|
|
879
891
|
|
|
880
|
-
|
|
892
|
+
// But...
|
|
881
893
|
if (d.target.centerX < d.source.newX) {
|
|
882
|
-
|
|
883
|
-
|
|
894
|
+
// i.e. if target node is to left of the source node
|
|
895
|
+
// then path intersects towards the righthand side
|
|
884
896
|
d.target.newX = (2 * d.target.x) - d.target.newX + w;
|
|
885
897
|
}
|
|
886
898
|
}
|
|
@@ -914,11 +926,12 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
914
926
|
node.selectAll(".nodeText").remove();
|
|
915
927
|
var text = node.append("text")
|
|
916
928
|
.attr("dy", NODE_HEIGHT)
|
|
917
|
-
.attr("text-anchor", "middle")
|
|
918
929
|
.attr("class", "nodeText")
|
|
930
|
+
.attr("fill", "rgb(0, 0, 0)")
|
|
931
|
+
.style("text-anchor", "middle")
|
|
919
932
|
.style("font-size", "18px")
|
|
920
933
|
.style("stroke-width", "0")
|
|
921
|
-
.style("
|
|
934
|
+
.style("font-family", "sans-serif")
|
|
922
935
|
.text(function (d) {
|
|
923
936
|
return d.name;
|
|
924
937
|
})
|
|
@@ -927,7 +940,27 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
927
940
|
d.textWidth = textWidth < MINIMUM_NODE_WIDTH ? MINIMUM_NODE_WIDTH : textWidth;
|
|
928
941
|
return d.textWidth / 2 + NODE_MARGIN;
|
|
929
942
|
})
|
|
930
|
-
.on("dblclick", nodeTextDblclick)
|
|
943
|
+
.on("dblclick", nodeTextDblclick)
|
|
944
|
+
|
|
945
|
+
// this function triggers the gene page
|
|
946
|
+
.on("contextmenu", function (gene) {
|
|
947
|
+
const tempLink = $("<a></a>")
|
|
948
|
+
.attr({
|
|
949
|
+
href: "info?" + $.param({
|
|
950
|
+
symbol: gene.name,
|
|
951
|
+
species: grnState.genePageData.species,
|
|
952
|
+
jaspar: grnState.genePageData.taxonJaspar,
|
|
953
|
+
uniprot: grnState.genePageData.taxonUniprot,
|
|
954
|
+
ensembl: grnState.genePageData.ensembl,
|
|
955
|
+
mine: grnState.genePageData.mine
|
|
956
|
+
}),
|
|
957
|
+
target: "_blank"
|
|
958
|
+
});
|
|
959
|
+
$("body").append(tempLink);
|
|
960
|
+
tempLink.get(0).click();
|
|
961
|
+
tempLink.remove();
|
|
962
|
+
d3.event.preventDefault();
|
|
963
|
+
});
|
|
931
964
|
|
|
932
965
|
rect
|
|
933
966
|
.attr("width", function (d) {
|
|
@@ -944,149 +977,182 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
944
977
|
return self.indexOf(value) === index;
|
|
945
978
|
}
|
|
946
979
|
|
|
947
|
-
|
|
948
|
-
|
|
980
|
+
const getExpressionData = (gene, strain, average) => {
|
|
981
|
+
const strainData = grnState.workbook.expression[strain];
|
|
949
982
|
if (average) {
|
|
950
|
-
|
|
951
|
-
|
|
983
|
+
const uniqueTimePoints = strainData.timePoints.filter(onlyUnique);
|
|
984
|
+
let avgMap = {};
|
|
952
985
|
uniqueTimePoints.forEach(function (key) {
|
|
953
986
|
avgMap[key] = [];
|
|
954
987
|
});
|
|
955
|
-
strainData.
|
|
988
|
+
strainData.timePoints.forEach(function (time, index) {
|
|
956
989
|
avgMap[time].push(strainData.data[gene][index]);
|
|
957
990
|
});
|
|
958
|
-
|
|
991
|
+
let avgs = [];
|
|
959
992
|
Object.keys(avgMap).forEach(function (key) {
|
|
960
|
-
|
|
961
|
-
|
|
993
|
+
const length = avgMap[key].length;
|
|
994
|
+
const sum = avgMap[key].reduce(function (partialSum, currentValue) {
|
|
962
995
|
return partialSum + currentValue;
|
|
963
996
|
}, 0);
|
|
964
997
|
avgs.push(sum / length);
|
|
965
998
|
});
|
|
966
999
|
return {data: avgs, timePoints: uniqueTimePoints};
|
|
967
1000
|
}
|
|
968
|
-
return {data: strainData.data[gene], timePoints: strainData.
|
|
1001
|
+
return {data: strainData.data[gene], timePoints: strainData.timePoints};
|
|
969
1002
|
};
|
|
970
1003
|
|
|
971
1004
|
var colorNodes = function (position, dataset, average, logFoldChangeMaxValue) {
|
|
972
1005
|
var timePoints = [];
|
|
973
1006
|
node.each(function (p) {
|
|
974
1007
|
d3.select(this)
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1008
|
+
.append("g")
|
|
1009
|
+
.selectAll(".coloring")
|
|
1010
|
+
.data(function () {
|
|
1011
|
+
if (grnState.workbook.expression[dataset].data[p.name]) {
|
|
1012
|
+
const result = getExpressionData(p.name, dataset, average);
|
|
1013
|
+
timePoints = result.timePoints;
|
|
1014
|
+
return result.data;
|
|
1015
|
+
} else {
|
|
1016
|
+
return 0;
|
|
1017
|
+
}
|
|
1018
|
+
})
|
|
1019
|
+
.attr("class", "coloring")
|
|
1020
|
+
.enter().append("rect")
|
|
1021
|
+
.attr("width", function () {
|
|
1022
|
+
var width = (p.textWidth + (2 * NODE_MARGIN)) / timePoints.length;
|
|
1023
|
+
return width + "px";
|
|
1024
|
+
})
|
|
1025
|
+
.attr("class", "coloring")
|
|
1026
|
+
.attr("height", rect.attr("height") / 2 + "px")
|
|
1027
|
+
.attr("transform", function (d, i) {
|
|
1028
|
+
var yOffset = position === "top" ? 0 : rect.attr("height") / 2;
|
|
1029
|
+
var xOffset = i * ((p.textWidth + (2 * NODE_MARGIN)) / timePoints.length);
|
|
1030
|
+
return "translate(" + xOffset + "," + yOffset + ")";
|
|
1031
|
+
})
|
|
1032
|
+
.attr("stroke-width", "0px")
|
|
1033
|
+
.style("fill", function (d) {
|
|
1034
|
+
d = d || 0; // missing values are changed to 0
|
|
1035
|
+
var scale = d3.scaleLinear()
|
|
1036
|
+
.domain([-logFoldChangeMaxValue, logFoldChangeMaxValue])
|
|
1037
|
+
.range([0, 1]);
|
|
1038
|
+
return d3.interpolateRdBu(scale(-d));
|
|
1039
|
+
})
|
|
1040
|
+
.text(function (d) {
|
|
1041
|
+
return "data " + JSON.stringify(d) + " of " + p.name;
|
|
1042
|
+
});
|
|
1006
1043
|
});
|
|
1007
1044
|
};
|
|
1008
1045
|
|
|
1009
1046
|
var renderNodeColoringLegend = function (logFoldChangeMaxValue) {
|
|
1010
1047
|
var $nodeColoringLegend = $(".node-coloring-legend");
|
|
1011
1048
|
d3.select($nodeColoringLegend[0]).selectAll("svg").remove();
|
|
1012
|
-
var
|
|
1013
|
-
var
|
|
1014
|
-
var width = 200;
|
|
1049
|
+
var yMargin = 20;
|
|
1050
|
+
var width = 203;
|
|
1015
1051
|
var height = 10;
|
|
1016
1052
|
var textYOffset = 10;
|
|
1017
|
-
var increment = 0.1;
|
|
1018
1053
|
|
|
1019
1054
|
var svg = d3.select($nodeColoringLegend[0])
|
|
1020
1055
|
.append("svg")
|
|
1021
|
-
.attr("width",
|
|
1056
|
+
.attr("width", "100%")
|
|
1022
1057
|
.attr("height", height + yMargin)
|
|
1023
1058
|
.append("g")
|
|
1024
|
-
.attr("transform", "translate(
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
var
|
|
1031
|
-
|
|
1032
|
-
|
|
1059
|
+
.attr("transform", "translate(0, 5)")
|
|
1060
|
+
.attr("id", "nodeColoringLegendId");
|
|
1061
|
+
|
|
1062
|
+
// Thank you https://www.visualcinnamon.com/2016/05/smooth-color-legend-d3-svg-gradient.html
|
|
1063
|
+
const linearGradientId = "node-coloring-color-scale";
|
|
1064
|
+
var defs = svg.append("defs");
|
|
1065
|
+
var linearGradient = defs.append("linearGradient")
|
|
1066
|
+
.attr("id", linearGradientId)
|
|
1067
|
+
.attr("x1", "0%")
|
|
1068
|
+
.attr("y1", "0%")
|
|
1069
|
+
.attr("x2", "100%")
|
|
1070
|
+
.attr("y2", "0%");
|
|
1071
|
+
|
|
1072
|
+
const increment = Math.abs(logFoldChangeMaxValue) / 50; // Guarantee 50 steps regardless of the range.
|
|
1073
|
+
var gradientValues = d3.range(-logFoldChangeMaxValue, logFoldChangeMaxValue, increment);
|
|
1074
|
+
var scale = d3.scaleLinear()
|
|
1075
|
+
.domain([-logFoldChangeMaxValue, logFoldChangeMaxValue])
|
|
1076
|
+
.range([0, 1]);
|
|
1077
|
+
|
|
1078
|
+
linearGradient.selectAll("stop")
|
|
1033
1079
|
.data(gradientValues)
|
|
1034
|
-
.
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
.attr("width", width / gradientValues.length + "px")
|
|
1038
|
-
.attr("height", height + "px")
|
|
1039
|
-
.attr("transform", function (d, i) {
|
|
1040
|
-
return "translate(" + (i * (width / gradientValues.length)) + "," + 0 + ")";
|
|
1080
|
+
.enter().append("stop")
|
|
1081
|
+
.attr("offset", function (d, i) {
|
|
1082
|
+
return i / (gradientValues.length - 1);
|
|
1041
1083
|
})
|
|
1042
|
-
.
|
|
1043
|
-
|
|
1044
|
-
.domain([-logFoldChangeMaxValue, logFoldChangeMaxValue])
|
|
1045
|
-
.range([0, 1]);
|
|
1046
|
-
return d3.interpolateRdBu(scale(flippedScale ? d : -d));
|
|
1084
|
+
.attr("stop-color", function (d) {
|
|
1085
|
+
return d3.interpolateRdBu(scale(-d));
|
|
1047
1086
|
});
|
|
1048
1087
|
|
|
1088
|
+
svg.append("rect")
|
|
1089
|
+
.attr("width", `${width}px`)
|
|
1090
|
+
.attr("height", `${height}px`)
|
|
1091
|
+
.style("fill", `url(#${linearGradientId})`);
|
|
1092
|
+
|
|
1049
1093
|
var legendLabels = {
|
|
1050
|
-
|
|
1051
|
-
"
|
|
1052
|
-
|
|
1094
|
+
left: {
|
|
1095
|
+
textAnchor: "start",
|
|
1096
|
+
textContent: (-logFoldChangeMaxValue).toFixed(2),
|
|
1097
|
+
x: 0
|
|
1053
1098
|
},
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
"
|
|
1057
|
-
|
|
1058
|
-
"right": {
|
|
1059
|
-
"textContent": (flippedScale ? -logFoldChangeMaxValue : +logFoldChangeMaxValue).toFixed(0),
|
|
1060
|
-
"x": width - xMargin / 2
|
|
1099
|
+
center: {
|
|
1100
|
+
textAnchor: "middle",
|
|
1101
|
+
textContent: "0",
|
|
1102
|
+
x: width / 2
|
|
1061
1103
|
},
|
|
1104
|
+
right: {
|
|
1105
|
+
textAnchor: "end",
|
|
1106
|
+
textContent: (logFoldChangeMaxValue).toFixed(2),
|
|
1107
|
+
x: width
|
|
1108
|
+
}
|
|
1062
1109
|
};
|
|
1063
|
-
|
|
1110
|
+
/* eslint-disable max-len */
|
|
1111
|
+
var g = document.getElementById("nodeColoringLegendId");
|
|
1112
|
+
/* eslint-enable max-len */
|
|
1113
|
+
|
|
1064
1114
|
for (var key in legendLabels) {
|
|
1065
1115
|
var label = document.createElementNS("http://www.w3.org/2000/svg", "text");
|
|
1066
1116
|
label.textContent = legendLabels[key].textContent;
|
|
1067
1117
|
label.setAttribute("font-size", "8px");
|
|
1118
|
+
label.setAttribute("text-anchor", legendLabels[key].textAnchor);
|
|
1068
1119
|
label.setAttribute("x", legendLabels[key].x);
|
|
1069
1120
|
label.setAttribute("y", height + textYOffset + "px");
|
|
1121
|
+
label.setAttribute("fill", "rgb(0,0,0)");
|
|
1122
|
+
|
|
1070
1123
|
g.appendChild(label);
|
|
1071
1124
|
}
|
|
1125
|
+
|
|
1072
1126
|
};
|
|
1073
1127
|
|
|
1074
|
-
|
|
1075
|
-
|
|
1128
|
+
updaters.removeNodeColoring = function () {
|
|
1129
|
+
grnState.nodeColoring.nodeColoringEnabled = false;
|
|
1076
1130
|
node.selectAll(".coloring").remove();
|
|
1077
1131
|
};
|
|
1078
1132
|
|
|
1079
|
-
|
|
1080
|
-
if (
|
|
1081
|
-
colorNodes("top",
|
|
1082
|
-
|
|
1133
|
+
updaters.renderNodeColoring = function () {
|
|
1134
|
+
if (grnState.nodeColoring.nodeColoringEnabled) {
|
|
1135
|
+
colorNodes("top", grnState.nodeColoring.topDataset, grnState.nodeColoring.averageTopDataset,
|
|
1136
|
+
grnState.nodeColoring.logFoldChangeMaxValue);
|
|
1137
|
+
colorNodes("bottom", grnState.nodeColoring.bottomDataset, grnState.nodeColoring.averageBottomDataset,
|
|
1138
|
+
grnState.nodeColoring.logFoldChangeMaxValue);
|
|
1083
1139
|
renderNodeLabels();
|
|
1084
|
-
renderNodeColoringLegend(
|
|
1140
|
+
renderNodeColoringLegend(grnState.nodeColoring.logFoldChangeMaxValue);
|
|
1141
|
+
}
|
|
1142
|
+
};
|
|
1143
|
+
|
|
1144
|
+
const hasExpressionData = sheets => {
|
|
1145
|
+
for (var property in sheets) {
|
|
1146
|
+
if (property.match(ENDS_IN_EXPRESSION_REGEXP)) {
|
|
1147
|
+
return true;
|
|
1148
|
+
}
|
|
1085
1149
|
}
|
|
1150
|
+
return false;
|
|
1086
1151
|
};
|
|
1087
1152
|
|
|
1088
|
-
if (!$.isEmptyObject(
|
|
1089
|
-
|
|
1153
|
+
if (!$.isEmptyObject(workbook.expression) && hasExpressionData(workbook.expression) &&
|
|
1154
|
+
grnState.nodeColoring.topDataset !== undefined) {
|
|
1155
|
+
updaters.renderNodeColoring();
|
|
1090
1156
|
}
|
|
1091
1157
|
|
|
1092
1158
|
$(".node").css({
|
|
@@ -1105,7 +1171,7 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
1105
1171
|
|
|
1106
1172
|
var currentWeightVisibilitySetting = null;
|
|
1107
1173
|
|
|
1108
|
-
if (
|
|
1174
|
+
if (workbook.sheetType === "weighted") {
|
|
1109
1175
|
if ($(".weightedGraphOptions").hasClass("hidden")) {
|
|
1110
1176
|
$(".weightedGraphOptions").removeClass("hidden");
|
|
1111
1177
|
}
|
|
@@ -1178,7 +1244,6 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
1178
1244
|
}
|
|
1179
1245
|
|
|
1180
1246
|
// resets graph options so when new graph is loaded, initial layout is always force graph
|
|
1181
|
-
$("#forceGraph").trigger("click");
|
|
1182
1247
|
|
|
1183
1248
|
const getMarginWidth = function (gridNodes, row) {
|
|
1184
1249
|
const containerWidth = $container.width();
|
|
@@ -1206,52 +1271,34 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
1206
1271
|
return name1 > name2 ? 1 : -1;
|
|
1207
1272
|
};
|
|
1208
1273
|
|
|
1209
|
-
let
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
let nodeGroup = node._groups[0].sort(sortNode);
|
|
1215
|
-
if (!layout) {
|
|
1216
|
-
$("#gridLayout")
|
|
1217
|
-
.addClass("called")
|
|
1218
|
-
.trigger("click")
|
|
1219
|
-
.removeClass("called");
|
|
1220
|
-
this.value = "Force Graph";
|
|
1221
|
-
layout = true;
|
|
1222
|
-
const margin = 10;
|
|
1223
|
-
const grid = Grid() // create new grid layout
|
|
1224
|
-
.data(network.genes)
|
|
1274
|
+
let nodeGroup = node._groups[0].sort(sortNode);
|
|
1275
|
+
updaters.setNodesToGrid = () => { // eslint-disable-line no-unused-vars
|
|
1276
|
+
const margin = 10;
|
|
1277
|
+
const grid = Grid() // eslint-disable-line no-undef
|
|
1278
|
+
.data(workbook.genes)
|
|
1225
1279
|
.bands(true)
|
|
1226
1280
|
.padding([0.2, 0])
|
|
1227
1281
|
.size([$container.width() - margin, $container.height() - margin]); // set size of container
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
nodeGroup[i].__data__.fy = marginHeight + gridNodes[i].y;
|
|
1237
|
-
}
|
|
1238
|
-
} else {
|
|
1239
|
-
$("#forceGraph")
|
|
1240
|
-
.addClass("called")
|
|
1241
|
-
.trigger("click")
|
|
1242
|
-
.removeClass("called");
|
|
1243
|
-
this.value = "Grid Layout";
|
|
1244
|
-
layout = false;
|
|
1245
|
-
for (i in nodeGroup) {
|
|
1246
|
-
nodeGroup[i].__data__.fx = null;
|
|
1247
|
-
nodeGroup[i].__data__.fy = null;
|
|
1248
|
-
}
|
|
1282
|
+
grid.layout();
|
|
1283
|
+
let gridNodes = grid.nodes();
|
|
1284
|
+
let gridNumRow = grid.cols();
|
|
1285
|
+
let marginWidth = getMarginWidth(gridNodes, gridNumRow);
|
|
1286
|
+
let marginHeight = getMarginHeight(gridNodes);
|
|
1287
|
+
for (var i in nodeGroup) {
|
|
1288
|
+
nodeGroup[i].__data__.fx = marginWidth + gridNodes[i].x;
|
|
1289
|
+
nodeGroup[i].__data__.fy = marginHeight + gridNodes[i].y;
|
|
1249
1290
|
}
|
|
1250
|
-
|
|
1251
|
-
|
|
1291
|
+
};
|
|
1292
|
+
|
|
1293
|
+
updaters.setNodesToForceGraph = () => { // eslint-disable-line no-unused-vars
|
|
1294
|
+
for (var i in nodeGroup) {
|
|
1295
|
+
nodeGroup[i].__data__.fx = null;
|
|
1296
|
+
nodeGroup[i].__data__.fy = null;
|
|
1297
|
+
}
|
|
1298
|
+
};
|
|
1252
1299
|
|
|
1253
|
-
|
|
1254
|
-
|
|
1300
|
+
// Tick only runs while the graph physics are still running.
|
|
1301
|
+
// (I.e. when the graph is completely relaxed, tick stops running.)
|
|
1255
1302
|
function tick () {
|
|
1256
1303
|
var getSelfReferringEdge = function (node) {
|
|
1257
1304
|
return link.select("path")["_groups"][0].map(function (path) {
|
|
@@ -1275,7 +1322,7 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
1275
1322
|
|
|
1276
1323
|
var selfReferringEdgeWidth = (selfReferringEdge ? getSelfReferringRadius(selfReferringEdge) +
|
|
1277
1324
|
selfReferringEdge.strokeWidth + 2 : 0);
|
|
1278
|
-
var rightBoundary = width - d.textWidth - BOUNDARY_MARGIN - selfReferringEdgeWidth;
|
|
1325
|
+
var rightBoundary = width - (d.textWidth + OFFSET_VALUE) - BOUNDARY_MARGIN - selfReferringEdgeWidth;
|
|
1279
1326
|
var currentXPos = Math.max(BOUNDARY_MARGIN, Math.min(rightBoundary, d.x));
|
|
1280
1327
|
if (adaptive && width < MAX_WIDTH &&
|
|
1281
1328
|
(currentXPos === BOUNDARY_MARGIN || currentXPos === rightBoundary)) {
|
|
@@ -1301,15 +1348,14 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
1301
1348
|
}).attr("y", function (d) {
|
|
1302
1349
|
var selfReferringEdge = getSelfReferringEdge(d);
|
|
1303
1350
|
var selfReferringEdgeHeight = (selfReferringEdge ? getSelfReferringRadius(selfReferringEdge) +
|
|
1304
|
-
|
|
1351
|
+
selfReferringEdge.strokeWidth + SELF_REFERRING_Y_OFFSET + 0.5 : 0);
|
|
1305
1352
|
var bottomBoundary = height - nodeHeight - BOUNDARY_MARGIN - selfReferringEdgeHeight;
|
|
1306
1353
|
var currentYPos = Math.max(BOUNDARY_MARGIN, Math.min(bottomBoundary, d.y));
|
|
1307
1354
|
if (adaptive && height < MAX_HEIGHT &&
|
|
1308
|
-
|
|
1355
|
+
(currentYPos === BOUNDARY_MARGIN || currentYPos === bottomBoundary)) {
|
|
1309
1356
|
if (!d3.select(this).classed("fixed")) {
|
|
1310
1357
|
height += OFFSET_VALUE;
|
|
1311
1358
|
boundingBoxContainer.attr("height", height);
|
|
1312
|
-
|
|
1313
1359
|
link
|
|
1314
1360
|
.attr("y1", function (d) {
|
|
1315
1361
|
return d.source.y;
|
|
@@ -1343,7 +1389,7 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
1343
1389
|
var dy = y2 - y1;
|
|
1344
1390
|
var dr = Math.sqrt(dx * dx + dy * dy);
|
|
1345
1391
|
|
|
1346
|
-
|
|
1392
|
+
// Defaults for normal edge.
|
|
1347
1393
|
var drx = dr;
|
|
1348
1394
|
var dry = dr;
|
|
1349
1395
|
var xRotation = 0; // degrees
|
|
@@ -1351,49 +1397,51 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
1351
1397
|
var sweep = 1; // 1 or 0
|
|
1352
1398
|
var offset = parseFloat(d.strokeWidth);
|
|
1353
1399
|
|
|
1354
|
-
|
|
1400
|
+
// Edge adjustment values when long self-node edges get hidden behind the node.
|
|
1355
1401
|
var DEFAULT_NODE_SHIFT = 1.033;
|
|
1356
1402
|
var SHORT_NODE_LIMIT = 135;
|
|
1357
1403
|
var ADDITIONAL_SHIFT = 0.07;
|
|
1358
1404
|
var END_POINT_ADJUSTMENT = 1.2;
|
|
1359
1405
|
|
|
1360
1406
|
|
|
1361
|
-
|
|
1407
|
+
// Self edge.
|
|
1362
1408
|
if (x1 === x2 && y1 === y2) {
|
|
1363
|
-
|
|
1409
|
+
// Move the position of the loop.
|
|
1364
1410
|
x1 = d.source.x + (d.source.textWidth) * DEFAULT_NODE_SHIFT;
|
|
1365
1411
|
y1 = d.source.y + (nodeHeight / 2) + SELF_REFERRING_Y_OFFSET;
|
|
1366
1412
|
|
|
1367
|
-
|
|
1413
|
+
// Fiddle with this angle to get loop oriented.
|
|
1414
|
+
// (Future: This doesn't appear to change anything?)
|
|
1368
1415
|
xRotation = 45;
|
|
1369
1416
|
|
|
1370
|
-
|
|
1417
|
+
// Needs to be 1.
|
|
1371
1418
|
largeArc = 1;
|
|
1372
1419
|
|
|
1373
|
-
|
|
1420
|
+
// Change sweep to change orientation of loop.
|
|
1374
1421
|
sweep = 1;
|
|
1375
1422
|
|
|
1376
1423
|
drx = getSelfReferringRadius(d);
|
|
1377
1424
|
dry = getSelfReferringRadius(d);
|
|
1378
1425
|
|
|
1379
|
-
|
|
1380
|
-
|
|
1426
|
+
// For whatever reason the arc collapses to a point if the beginning
|
|
1427
|
+
// and ending points of the arc are the same, so kludge it.
|
|
1381
1428
|
if (d.source.textWidth > SHORT_NODE_LIMIT) {
|
|
1382
1429
|
DEFAULT_NODE_SHIFT += ADDITIONAL_SHIFT;
|
|
1383
1430
|
}
|
|
1384
1431
|
x2 = d.source.x + d.source.textWidth / END_POINT_ADJUSTMENT * DEFAULT_NODE_SHIFT;
|
|
1385
1432
|
y2 = d.source.y + nodeHeight;
|
|
1386
1433
|
|
|
1387
|
-
if (d.value < 0 && colorOptimal) {
|
|
1434
|
+
if (d.value < 0 && grnState.colorOptimal) {
|
|
1388
1435
|
offset = Math.max(10, parseFloat(d.strokeWidth));
|
|
1389
1436
|
}
|
|
1390
1437
|
}
|
|
1391
1438
|
|
|
1392
|
-
d.label = { x: x1,
|
|
1439
|
+
d.label = { x: Math.min(width - (13 * offset), x1), // For 4 decimal places
|
|
1440
|
+
y: Math.min(height - offset, y1 + dry * 3)};
|
|
1393
1441
|
|
|
1394
1442
|
return "M" + x1 + "," + y1 +
|
|
1395
|
-
|
|
1396
|
-
|
|
1443
|
+
"A" + drx + "," + dry + " " + xRotation + "," + largeArc + "," + sweep + " " +
|
|
1444
|
+
x2 + "," + (y2 + offset);
|
|
1397
1445
|
} else {
|
|
1398
1446
|
return moveTo(d) + lineTo(d);
|
|
1399
1447
|
}
|
|
@@ -1415,7 +1463,7 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
1415
1463
|
selfRef = "_SelfReferential";
|
|
1416
1464
|
}
|
|
1417
1465
|
|
|
1418
|
-
if (d.type === "repressor" && colorOptimal) {
|
|
1466
|
+
if (d.type === "repressor" && grnState.colorOptimal) {
|
|
1419
1467
|
if ((d.tanRatioMoveable > d.tanRatioFixed) || (d.target === d.source)) { // if horizontal repressor
|
|
1420
1468
|
return "url(#repressorHorizontal" + selfRef + "_StrokeWidth" + d.strokeWidth + minimum + ")";
|
|
1421
1469
|
} else { // otherwise vertical repressor
|
|
@@ -1439,7 +1487,7 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
1439
1487
|
}
|
|
1440
1488
|
|
|
1441
1489
|
function normalize (d) {
|
|
1442
|
-
return Math.abs(d.value /
|
|
1490
|
+
return Math.abs(d.value / maxWeight).toPrecision(4);
|
|
1443
1491
|
}
|
|
1444
1492
|
|
|
1445
1493
|
function dragstart (d) {
|
|
@@ -1455,57 +1503,13 @@ export var drawGraph = function (network, sliderController, nodeColoring) {
|
|
|
1455
1503
|
d.fy = d3.event.y;
|
|
1456
1504
|
}
|
|
1457
1505
|
|
|
1458
|
-
|
|
1459
|
-
sliderController.addForce(simulation);
|
|
1460
|
-
sliderController.configureForceHandlers();
|
|
1461
|
-
sliderController.initializeDefaultForces();
|
|
1462
|
-
|
|
1463
|
-
var changeSliderValue = function (slider, item) {
|
|
1464
|
-
var value = slider === "link" ? linkDistValidator($(item).val()) :
|
|
1465
|
-
chargeValidator($(item).val());
|
|
1466
|
-
sliderController.modifyForceParameter(slider, value);
|
|
1467
|
-
if (slider === "link") {
|
|
1468
|
-
$(LINK_DISTANCE_VALUE).text(value);
|
|
1469
|
-
$(LINK_DISTANCE_INPUT).val(value);
|
|
1470
|
-
$(LINK_DISTANCE_MENU).val(value);
|
|
1471
|
-
} else {
|
|
1472
|
-
$(CHARGE_VALUE).text(value);
|
|
1473
|
-
$(CHARGE_INPUT).val(value);
|
|
1474
|
-
$(CHARGE_MENU).val(value);
|
|
1475
|
-
}
|
|
1476
|
-
};
|
|
1477
|
-
|
|
1478
|
-
var LINK_DISTANCE_MENU = "#link-distance-menu";
|
|
1479
|
-
var LINK_DISTANCE_INPUT = "#linkDistInput";
|
|
1480
|
-
var LINK_DISTANCE_VALUE = "#linkDistVal";
|
|
1481
|
-
|
|
1482
|
-
$(LINK_DISTANCE_MENU).on("change", function () {
|
|
1483
|
-
changeSliderValue("link", LINK_DISTANCE_MENU);
|
|
1484
|
-
});
|
|
1485
|
-
|
|
1486
|
-
$(LINK_DISTANCE_INPUT).on("change", function () {
|
|
1487
|
-
changeSliderValue("link", LINK_DISTANCE_INPUT);
|
|
1488
|
-
});
|
|
1506
|
+
grnState.simulation = simulation;
|
|
1489
1507
|
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
var CHARGE_VALUE = "#chargeVal";
|
|
1508
|
+
// The restrict graph state is sometimes carried over across reloads
|
|
1509
|
+
restrictGraphToViewport( $("input[name=viewport]").prop("checked"));
|
|
1493
1510
|
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
});
|
|
1497
|
-
|
|
1498
|
-
$(CHARGE_INPUT).on("change", function () {
|
|
1499
|
-
changeSliderValue("charge", CHARGE_INPUT);
|
|
1500
|
-
});
|
|
1501
|
-
|
|
1502
|
-
var linkDistValidator = function (value) {
|
|
1503
|
-
return valueValidator(1, 1000, value);
|
|
1504
|
-
};
|
|
1505
|
-
|
|
1506
|
-
var chargeValidator = function (value) {
|
|
1507
|
-
return valueValidator(-2000, 0, value);
|
|
1508
|
-
};
|
|
1511
|
+
modifyChargeParameter(grnState.chargeSlider.currentVal);
|
|
1512
|
+
modifyLinkDistanceParameter(grnState.linkDistanceSlider.currentVal);
|
|
1509
1513
|
|
|
1510
1514
|
$(".startDisabled").removeClass("disabled");
|
|
1511
1515
|
};
|