grnsight 4.0.0 → 6.0.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/.travis.yml +3 -1
- package/GRNsight - Beta.html +194 -0
- package/Gemfile.lock +259 -0
- package/README.md +2 -2
- 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/lcov.info +1847 -1142
- package/database/README.md +1 -0
- package/database/network-database/README.md +44 -0
- package/database/network-database/schema.sql +24 -0
- package/database/network-database/scripts/filter_genes.py +76 -0
- package/database/network-database/scripts/generate_network.py +199 -0
- package/database/network-database/scripts/generate_sgd_network_from_yeastract_network.py +120 -0
- package/database/network-database/scripts/loader.py +78 -0
- package/package.json +20 -11
- package/server/app.js +7 -2
- package/server/config/config.js +12 -3
- package/server/controllers/additional-sheet-parser.js +292 -55
- package/server/controllers/constants.js +4 -37
- package/server/controllers/custom-workbook-controller.js +66 -0
- package/server/controllers/demo-workbooks.js +5973 -0
- package/server/controllers/export-constants.js +78 -0
- package/server/controllers/export-controller.js +4 -3
- package/server/controllers/exporters/graphml.js +15 -15
- package/server/controllers/exporters/sif.js +7 -7
- package/server/controllers/exporters/xlsx.js +110 -34
- package/server/controllers/expression-database-controller.js +19 -0
- package/server/controllers/expression-sheet-parser.js +170 -0
- 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-database-controller.js +18 -0
- 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 -425
- package/server/controllers/workbook-constants.js +521 -0
- package/server/dals/expression-dal.js +122 -0
- package/server/dals/network-dal.js +96 -0
- package/test/additional-sheet-parser-tests.js +147 -38
- package/test/api-tests.js +3 -6
- package/test/errors-adjacency-matrix-modifications.js +30 -29
- package/test/errors-graph-tests.js +4 -4
- package/test/errors-sheet-modifications.js +10 -2
- package/test/export-tests.js +187 -60
- package/test/expression-data-import-tests.js +113 -0
- package/test/grnstate-tests.js +8 -2
- package/test/import-graphml-tests.js +59 -40
- package/test/import-sif-tests.js +50 -37
- package/test/test.js +554 -91
- 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/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/controllers/main.js +1 -1
- package/web-client/public/favicon.ico +0 -0
- package/web-client/public/gene/api.js +76 -14
- package/web-client/public/gene/info.js +19 -8
- package/web-client/public/js/api/grnsight-api.js +124 -0
- package/web-client/public/js/constants.js +90 -17
- package/web-client/public/js/createNetwork.js +195 -0
- package/web-client/public/js/graph-statistics.js +7 -7
- package/web-client/public/js/graph.js +369 -324
- package/web-client/public/js/grnsight.js +2 -2
- package/web-client/public/js/grnsight.min.js +128 -59
- package/web-client/public/js/grnstate.js +54 -30
- package/web-client/public/js/iframe-coordination.js +55 -0
- package/web-client/public/js/setup-handlers.js +358 -18
- package/web-client/public/js/setup-load-and-import-handlers.js +105 -66
- package/web-client/public/js/update-app.js +483 -93
- package/web-client/public/js/upload.js +349 -32
- package/web-client/public/js/warnings.js +13 -51
- package/web-client/public/lib/iframeSizer.contentWindow.min.js +10 -0
- package/web-client/public/stylesheets/grnsight.styl +323 -28
- package/web-client/views/components/demo.pug +10 -0
- package/web-client/views/{graph.jade → graph.pug} +0 -0
- package/web-client/views/{info.jade → info.pug} +1 -5
- package/web-client/views/upload.pug +580 -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/SDF/CMSI_402/spring_2018/writtenStatusReport4 +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/Samdarshi_GRNsight_SoCalSysBio_Abstract_2019.docx +0 -0
- package/documents/abstracts/Varshneya_Samdarshi_Southern-California-Systems-Biology_2017_abstract.docx +0 -0
- package/documents/abstracts/~$mdarshi_SoCalSysBio_Abstract_2019.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 -496
- 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_CMSI402_2017.pptx +0 -0
- package/documents/posters/Anguiano_Varshneya_LMU-Symposium_2015.pptx +0 -0
- package/documents/posters/Anguiano_Varshneya_SCCUR_2014.pptx +0 -0
- package/documents/posters/Choe_Shin_CMSI402_2018.pptx +0 -0
- package/documents/posters/Dahlquist-et-al_BOSC_ISMB_2016_poster.pptx +0 -0
- package/documents/posters/Lopez_Filler_LMU_Symposium_2019.pdf +0 -0
- package/documents/posters/Lopez_Filler_LMU_Symposium_2019.pptx +0 -0
- package/documents/posters/Samdarshi-et-al_LMU-Symposium_2017.pptx +0 -0
- package/documents/posters/Samdarshi-et-al_LMU-Symposium_2018.pptx +0 -0
- package/documents/posters/Samdarshi-et-al_SoCalSysBio_2019.pptx +0 -0
- package/documents/posters/Shin-et-al_SCCUR_2017.pptx +0 -0
- package/documents/posters/Southwick_CMSI402_2014.pptx +0 -0
- package/documents/posters/Varshneya_Samdarshi_LMU-Symposium_2016.pptx +0 -0
- package/documents/posters/Varshneya_Samdarshi_SoCalSysBio_2017.pptx +0 -0
- package/documents/presentations/Anguiano_402_Final_Presentation.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_LMU-Symposium_20190323_talk.pdf +0 -0
- package/documents/presentations/Samdarshi_LMU-Symposium_20190323_talk.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_talk.pptx +0 -0
- package/documents/reports/Samdarshi_Mihir_2019/Samdarshi_2019_Final.docx +0 -0
- package/documents/reports/Samdarshi_Mihir_2019/Samdarshi_Mihir_2019_AnnotatedBibliography.docx +0 -0
- package/documents/reports/Samdarshi_Mihir_2019/Samdarshi_Mihir_2019_Outline.docx +0 -0
- package/documents/reports/Samdarshi_Mihir_2019/~$mdarshi_2019_Draft.docx +0 -0
- package/documents/reports/Samdarshi_Mihir_2019/~$mdarshi_2019_Final_Paper_Draft.docx +0 -0
- package/documents/reports/Varshneya_Anu_2017/Varshneya-201701-AnnotatedBibliography.docx +0 -0
- package/documents/reports/Varshneya_Anu_2017/Varshneya-201702-Introduction.docx +0 -0
- package/documents/reports/Varshneya_Anu_2017/Varshneya-201702-Outline.docx +0 -0
- package/documents/reports/Varshneya_Anu_2017/Varshneya-201703-Discussion.docx +0 -0
- package/documents/reports/Varshneya_Anu_2017/Varshneya-201703-MMResults.docx +0 -0
- package/documents/reports/Varshneya_Anu_2017/Varshneya-201704-Draft-1.docx +0 -0
- package/documents/reports/Varshneya_Anu_2017/Varshneya-201704-Final.docx +0 -0
- package/onlysidebar.html +0 -8
- 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/views/upload.jade +0 -464
|
@@ -3,10 +3,14 @@ import { grnState } from "./grnstate";
|
|
|
3
3
|
import { modifyChargeParameter, modifyLinkDistanceParameter, valueValidator } from "./update-app";
|
|
4
4
|
import {
|
|
5
5
|
ENDS_IN_EXPRESSION_REGEXP,
|
|
6
|
-
|
|
6
|
+
VIEWPORT_FIT,
|
|
7
7
|
ZOOM_INPUT,
|
|
8
8
|
ZOOM_PERCENT,
|
|
9
|
-
ZOOM_SLIDER
|
|
9
|
+
ZOOM_SLIDER,
|
|
10
|
+
ZOOM_DISPLAY_MINIMUM_VALUE,
|
|
11
|
+
ZOOM_DISPLAY_MAXIMUM_VALUE,
|
|
12
|
+
ZOOM_DISPLAY_MIDDLE,
|
|
13
|
+
ZOOM_ADAPTIVE_MAX_SCALE,
|
|
10
14
|
} from "./constants";
|
|
11
15
|
|
|
12
16
|
/* globals d3 */
|
|
@@ -25,6 +29,17 @@ import {
|
|
|
25
29
|
/* eslint no-unused-vars: [2, {"varsIgnorePattern": "text|getMappedValue|manualZoom"}] */
|
|
26
30
|
/* eslint-disable no-unused-vars */
|
|
27
31
|
|
|
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
|
+
|
|
28
43
|
export var updaters = {
|
|
29
44
|
setNodesToGrid: () => {},
|
|
30
45
|
setNodesToForceGraph: () => {},
|
|
@@ -32,7 +47,7 @@ export var updaters = {
|
|
|
32
47
|
removeNodeColoring: () => {},
|
|
33
48
|
};
|
|
34
49
|
|
|
35
|
-
export var drawGraph = function (
|
|
50
|
+
export var drawGraph = function (workbook) {
|
|
36
51
|
/* eslint-enable no-unused-vars */
|
|
37
52
|
var $container = $(".grnsight-container");
|
|
38
53
|
d3.selectAll("svg").remove();
|
|
@@ -48,9 +63,7 @@ export var drawGraph = function (network) {
|
|
|
48
63
|
|
|
49
64
|
var CURSOR_CLASSES = "cursorGrab cursorGrabbing";
|
|
50
65
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
$("#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." : "");
|
|
54
67
|
|
|
55
68
|
var getNodeWidth = function (node) {
|
|
56
69
|
return node.name.length * 12 + 5;
|
|
@@ -58,12 +71,31 @@ export var drawGraph = function (network) {
|
|
|
58
71
|
|
|
59
72
|
var adaptive = !$("input[name='viewport']").prop("checked");
|
|
60
73
|
|
|
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);
|
|
87
|
+
|
|
88
|
+
const MIN_DISPLAY = ZOOM_DISPLAY_MINIMUM_VALUE;
|
|
89
|
+
const ADAPTIVE_MAX_DISPLAY = ZOOM_DISPLAY_MAXIMUM_VALUE;
|
|
61
90
|
const MIN_SCALE = 0.25;
|
|
62
|
-
const ADAPTIVE_MAX_SCALE = 4;
|
|
63
91
|
const MIDDLE_SCALE = 1;
|
|
64
92
|
|
|
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);
|
|
96
|
+
|
|
65
97
|
// Create an array of all the network weights
|
|
66
|
-
var allWeights =
|
|
98
|
+
var allWeights = workbook.positiveWeights.concat(workbook.negativeWeights);
|
|
67
99
|
// Assign the entire array weights of 1, if color edges turned off
|
|
68
100
|
if (!grnState.colorOptimal) {
|
|
69
101
|
for (var i = 0; i < allWeights.length; i++) {
|
|
@@ -77,12 +109,15 @@ export var drawGraph = function (network) {
|
|
|
77
109
|
}
|
|
78
110
|
}
|
|
79
111
|
|
|
112
|
+
const maxWeight = Math.max(Math.abs(d3.max(allWeights)), Math.abs(d3.min(allWeights)));
|
|
113
|
+
|
|
80
114
|
// Get the largest magnitude weight and set that as the default normalization factor
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
115
|
+
if (grnState.newWorkbook) {
|
|
116
|
+
grnState.normalizationMax = maxWeight;
|
|
117
|
+
grnState.resetNormalizationMax = maxWeight;
|
|
118
|
+
}
|
|
84
119
|
|
|
85
|
-
|
|
120
|
+
// Normalize all weights b/w 2-14
|
|
86
121
|
var normMax = +$("#normalization-max").val();
|
|
87
122
|
var totalScale = d3.scaleLinear()
|
|
88
123
|
.domain([0, normMax > 0 ? normMax : maxWeight])
|
|
@@ -91,8 +126,8 @@ export var drawGraph = function (network) {
|
|
|
91
126
|
|
|
92
127
|
var unweighted = false;
|
|
93
128
|
|
|
94
|
-
|
|
95
|
-
if (
|
|
129
|
+
// if unweighted, all weights are 2
|
|
130
|
+
if (workbook.sheetType === "unweighted") {
|
|
96
131
|
totalScale = d3.scaleQuantile()
|
|
97
132
|
.domain([d3.extent(allWeights)])
|
|
98
133
|
.range(["2"]);
|
|
@@ -162,7 +197,8 @@ export var drawGraph = function (network) {
|
|
|
162
197
|
|
|
163
198
|
var svg = d3.select($container[0]).append("svg")
|
|
164
199
|
.attr("width", width)
|
|
165
|
-
.attr("height", height)
|
|
200
|
+
.attr("height", height)
|
|
201
|
+
.attr("id", "exportContainer");
|
|
166
202
|
|
|
167
203
|
var zoomContainer = svg.append("g") // required for zoom to work
|
|
168
204
|
.attr("class", "boundingBox")
|
|
@@ -172,10 +208,12 @@ export var drawGraph = function (network) {
|
|
|
172
208
|
var boundingBoxContainer = zoomContainer.append("g"); // appended another g here...
|
|
173
209
|
|
|
174
210
|
var zoom = d3.zoom()
|
|
175
|
-
.scaleExtent([
|
|
211
|
+
.scaleExtent([MIN_SCALE, ZOOM_ADAPTIVE_MAX_SCALE])
|
|
176
212
|
.on("zoom", zoomed);
|
|
177
213
|
|
|
178
|
-
svg.style("pointer-events", "all").call(zoomDrag)
|
|
214
|
+
svg.style("pointer-events", "all").call(zoomDrag)
|
|
215
|
+
.style("font-family", "sans-serif");
|
|
216
|
+
|
|
179
217
|
|
|
180
218
|
function zoomed () {
|
|
181
219
|
zoomContainer.attr("transform", d3.event.transform);
|
|
@@ -183,14 +221,14 @@ export var drawGraph = function (network) {
|
|
|
183
221
|
|
|
184
222
|
d3.select("svg").on("dblclick.zoom", null); // disables double click zooming
|
|
185
223
|
|
|
186
|
-
|
|
187
|
-
|
|
224
|
+
// This rectangle catches all of the mousewheel and pan events, without letting
|
|
225
|
+
// them bubble up to the body.
|
|
188
226
|
boundingBoxContainer.append("rect")
|
|
189
227
|
.attr("width", width)
|
|
190
228
|
.attr("height", height)
|
|
191
229
|
.style("fill", "none")
|
|
192
230
|
.style("pointer-events", "all")
|
|
193
|
-
.attr("stroke",
|
|
231
|
+
.attr("stroke", "none" )
|
|
194
232
|
.append("g");
|
|
195
233
|
|
|
196
234
|
d3.selectAll(".scrollBtn").on("click", null); // Remove event handlers, if there were any.
|
|
@@ -212,114 +250,77 @@ export var drawGraph = function (network) {
|
|
|
212
250
|
zoom.scaleTo(container, zoomScale);
|
|
213
251
|
};
|
|
214
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;
|
|
258
|
+
|
|
215
259
|
const updateAppBasedOnZoomValue = () => {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
if (currentPoint <= leftPoints) {
|
|
220
|
-
equivalentScale = MIN_SCALE;
|
|
221
|
-
equivalentScale += scaleIncreasePerLeftPoint * currentPoint;
|
|
222
|
-
} else {
|
|
223
|
-
currentPoint = currentPoint - leftPoints;
|
|
224
|
-
equivalentScale = MIDDLE_SCALE;
|
|
225
|
-
equivalentScale += scaleIncreasePerRightPoint * currentPoint;
|
|
226
|
-
}
|
|
227
|
-
zoomSliderScale = equivalentScale;
|
|
228
|
-
setGraphZoom(equivalentScale);
|
|
229
|
-
} else {
|
|
230
|
-
// Prohibits zooming past 100% if (!adaptive && grnState.zoomValue >= ADAPTIVE_MAX_SCALE)
|
|
231
|
-
grnState.zoomValue = ADAPTIVE_MAX_SCALE;
|
|
232
|
-
setGraphZoom(MIDDLE_SCALE);
|
|
260
|
+
|
|
261
|
+
if (!adaptive) {
|
|
262
|
+
grnState.zoomValue = 100.0;
|
|
233
263
|
}
|
|
234
264
|
|
|
235
|
-
|
|
265
|
+
const zoomDisplay = grnState.zoomValue;
|
|
266
|
+
setGraphZoom((zoomDisplay <= ZOOM_DISPLAY_MIDDLE ? zoomScaleLeft : zoomScaleRight)(zoomDisplay));
|
|
236
267
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
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);
|
|
240
276
|
}
|
|
241
277
|
|
|
242
|
-
$(
|
|
243
|
-
|
|
278
|
+
$(ZOOM_SLIDER).val((finalDisplay <= ZOOM_DISPLAY_MIDDLE ? zoomScaleSliderLeft : zoomScaleSliderRight)
|
|
279
|
+
.invert(finalDisplay));
|
|
244
280
|
};
|
|
245
281
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
// Get the value that, if multiplied by the minScale value, would return 1. (ex: 0.25 * 4 = 1)
|
|
269
|
-
// This gives us the equivalent value of this minimum scale, should it be treated
|
|
270
|
-
// as a scale increase. This mostly allows us to treat this minimum scale as a non-decimal value,
|
|
271
|
-
// but it also provides a way to compare the total effect this minimum scale would have
|
|
272
|
-
// in a way that is easier to understand.
|
|
273
|
-
var minScaleReversed = 100 / (minScale * 100);
|
|
274
|
-
|
|
275
|
-
// Number of points required to display the minimum scale, now that's it's been transformed. These
|
|
276
|
-
// are the points that represent everything on the scale less than one.
|
|
277
|
-
leftPoints = minScaleReversed * NUMBER_POINTS_PER_INT;
|
|
278
|
-
|
|
279
|
-
// We want to end up with a total increase that, once we've gone through all the
|
|
280
|
-
// left points, produces 1 when added to minscale. So for scale 0.25 with 400
|
|
281
|
-
// left points, we need to know what we could add to 0.25 400 times to produce 1.
|
|
282
|
-
// We divide 0.75 by 400 to get that result.
|
|
283
|
-
scaleIncreasePerLeftPoint = (1 - minScale) / leftPoints;
|
|
284
|
-
|
|
285
|
-
// Points representing scales greater than 1.
|
|
286
|
-
rightPoints = maxScale * NUMBER_POINTS_PER_INT;
|
|
287
|
-
|
|
288
|
-
// For the same concept as above, we need to figure out what to add to 1 so
|
|
289
|
-
// so that we can end up with maxScale. Note that we start at 1 and not 0 because
|
|
290
|
-
// the scale is beginning at 1.
|
|
291
|
-
scaleIncreasePerRightPoint = (maxScale - MIDDLE_SCALE) / rightPoints;
|
|
292
|
-
var totalPoints = leftPoints + rightPoints;
|
|
293
|
-
|
|
294
|
-
// Returns the x that we're mapping to. Now we can set up the range slider.
|
|
295
|
-
var maxRangeValue = totalPoints / 100;
|
|
296
|
-
|
|
297
|
-
$(ZOOM_SLIDER).attr("min", 0);
|
|
298
|
-
$(ZOOM_SLIDER).attr("max", maxRangeValue);
|
|
299
|
-
if (grnState.newNetwork) {
|
|
300
|
-
grnState.zoomValue = 0.01 * leftPoints;
|
|
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;
|
|
301
303
|
}
|
|
302
304
|
|
|
303
305
|
updateAppBasedOnZoomValue();
|
|
304
306
|
};
|
|
305
307
|
|
|
306
|
-
setupZoomSlider(
|
|
307
|
-
|
|
308
|
-
var ZOOM_SLIDER_MAX_VAL = 8;
|
|
309
|
-
var ZOOM_RANGE = 200;
|
|
308
|
+
setupZoomSlider();
|
|
310
309
|
|
|
311
310
|
var zoomInputValidator = function (value) {
|
|
312
|
-
return valueValidator(
|
|
311
|
+
return valueValidator(MIN_DISPLAY, ADAPTIVE_MAX_DISPLAY, value);
|
|
313
312
|
};
|
|
314
313
|
|
|
315
314
|
$(ZOOM_INPUT).on("input", () => {
|
|
316
|
-
|
|
317
|
-
grnState.zoomValue = zoomAsPercent * (ZOOM_SLIDER_MAX_VAL / ZOOM_RANGE);
|
|
315
|
+
grnState.zoomValue = zoomInputValidator(+$(ZOOM_INPUT).val());
|
|
318
316
|
updateAppBasedOnZoomValue();
|
|
319
|
-
});
|
|
317
|
+
}).blur(() => $(ZOOM_INPUT).val(grnState.zoomValue));
|
|
320
318
|
|
|
321
319
|
d3.select(ZOOM_SLIDER).on("input", function () {
|
|
322
|
-
|
|
320
|
+
const sliderValue = +$(this).val();
|
|
321
|
+
grnState.zoomValue = Math.floor(
|
|
322
|
+
(sliderValue <= sliderMidpoint ? zoomScaleSliderLeft : zoomScaleSliderRight)(sliderValue)
|
|
323
|
+
);
|
|
323
324
|
updateAppBasedOnZoomValue();
|
|
324
325
|
}).on("mousedown", function () {
|
|
325
326
|
manualZoom = true;
|
|
@@ -327,11 +328,11 @@ export var drawGraph = function (network) {
|
|
|
327
328
|
manualZoom = false;
|
|
328
329
|
});
|
|
329
330
|
|
|
330
|
-
if (!grnState.
|
|
331
|
+
if (!grnState.newWorkbook) {
|
|
331
332
|
updateAppBasedOnZoomValue();
|
|
332
333
|
}
|
|
333
334
|
|
|
334
|
-
|
|
335
|
+
const adjustGraphSize = () => {
|
|
335
336
|
var newWidth = $container.width();
|
|
336
337
|
var newHeight = $container.height();
|
|
337
338
|
|
|
@@ -343,29 +344,39 @@ export var drawGraph = function (network) {
|
|
|
343
344
|
height = newHeight;
|
|
344
345
|
}
|
|
345
346
|
|
|
346
|
-
|
|
347
|
-
|
|
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...
|
|
348
349
|
d3.select("svg").attr("width", newWidth)
|
|
349
|
-
.attr("height", $(".grnsight-container").hasClass(
|
|
350
|
+
.attr("height", $(".grnsight-container").hasClass(VIEWPORT_FIT) ? newHeight : newHeight);
|
|
350
351
|
d3.select("rect").attr("width", width).attr("height", height);
|
|
351
352
|
d3.select(".boundingBox").attr("width", width).attr("height", height);
|
|
352
|
-
}
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
mutationCallback = adjustGraphSize;
|
|
356
|
+
resizeObserver.disconnect();
|
|
357
|
+
resizeObserver.observe($container.get(0), { attributes: true });
|
|
353
358
|
|
|
354
359
|
var restrictGraphToViewport = function (fixed) {
|
|
355
360
|
if (!fixed) {
|
|
356
361
|
$("#restrict-graph-to-viewport span").removeClass("glyphicon-ok");
|
|
362
|
+
$(document).ready(function () {
|
|
363
|
+
$(".scale-and-scroll").show();
|
|
364
|
+
});
|
|
357
365
|
$("input[name=viewport]").removeProp("checked");
|
|
358
|
-
$container.addClass("
|
|
366
|
+
$container.addClass("cursorGrabbing");
|
|
359
367
|
adaptive = true;
|
|
360
368
|
d3.select("rect").attr("stroke", "none");
|
|
361
369
|
center();
|
|
362
370
|
} else if (fixed) {
|
|
363
371
|
$("#restrict-graph-to-viewport span").addClass("glyphicon-ok");
|
|
364
372
|
$("input[name=viewport]").prop("checked", "checked");
|
|
373
|
+
$(document).ready(function () {
|
|
374
|
+
$(".scale-and-scroll").hide();
|
|
375
|
+
});
|
|
365
376
|
adaptive = false;
|
|
366
377
|
$container.removeClass(CURSOR_CLASSES);
|
|
367
|
-
if (
|
|
368
|
-
grnState.zoomValue =
|
|
378
|
+
if (grnState.zoomValue > ZOOM_DISPLAY_MIDDLE) {
|
|
379
|
+
grnState.zoomValue = ZOOM_DISPLAY_MIDDLE;
|
|
369
380
|
updateAppBasedOnZoomValue();
|
|
370
381
|
$container.removeClass(CURSOR_CLASSES);
|
|
371
382
|
}
|
|
@@ -377,6 +388,7 @@ export var drawGraph = function (network) {
|
|
|
377
388
|
$(".boundingBox").attr("width", width).attr("height", height);
|
|
378
389
|
center();
|
|
379
390
|
}
|
|
391
|
+
updateAppBasedOnZoomValue(); // Update zoom value within bounds
|
|
380
392
|
};
|
|
381
393
|
|
|
382
394
|
d3.select("#restrict-graph-to-viewport").on("click", function () {
|
|
@@ -389,22 +401,15 @@ export var drawGraph = function (network) {
|
|
|
389
401
|
restrictGraphToViewport(fixed);
|
|
390
402
|
});
|
|
391
403
|
|
|
392
|
-
$(window).on("resize", function () {
|
|
393
|
-
if ($container.hasClass("containerFit")) {
|
|
394
|
-
$(".boundBoxSize").trigger("click");
|
|
395
|
-
}
|
|
396
|
-
});
|
|
397
|
-
|
|
398
404
|
function center () {
|
|
399
405
|
var viewportWidth = $container.width();
|
|
400
406
|
var viewportHeight = $container.height();
|
|
401
407
|
zoom.translateTo(zoomContainer, viewportWidth / 2, viewportHeight / 2);
|
|
402
|
-
simulation.alphaTarget(0.3).restart();
|
|
403
408
|
}
|
|
404
409
|
|
|
405
410
|
function move (direction) {
|
|
406
|
-
var width = direction === "left" ? 50 : (direction === "right" ?
|
|
407
|
-
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);
|
|
408
413
|
zoom.translateBy(zoomContainer, width, height);
|
|
409
414
|
}
|
|
410
415
|
|
|
@@ -415,18 +420,18 @@ export var drawGraph = function (network) {
|
|
|
415
420
|
var weight = boundingBoxContainer.selectAll(".weight");
|
|
416
421
|
|
|
417
422
|
simulation
|
|
418
|
-
.nodes(
|
|
423
|
+
.nodes(workbook.genes)
|
|
419
424
|
.on("tick", tick);
|
|
420
425
|
|
|
421
426
|
simulation.force("link")
|
|
422
|
-
.links(
|
|
427
|
+
.links(workbook.links);
|
|
423
428
|
|
|
424
|
-
link = link.data(
|
|
429
|
+
link = link.data(workbook.links)
|
|
425
430
|
.enter().append("g")
|
|
426
431
|
.attr("class", "link")
|
|
427
432
|
.attr("strokeWidth", getEdgeThickness);
|
|
428
433
|
|
|
429
|
-
node = node.data(
|
|
434
|
+
node = node.data(workbook.genes)
|
|
430
435
|
.enter().append("g")
|
|
431
436
|
.attr("class", "node")
|
|
432
437
|
.attr("id", function (d) {
|
|
@@ -437,13 +442,14 @@ export var drawGraph = function (network) {
|
|
|
437
442
|
.call(drag)
|
|
438
443
|
.on("dblclick", dblclick);
|
|
439
444
|
|
|
440
|
-
if (
|
|
445
|
+
if (workbook.sheetType === "weighted") {
|
|
441
446
|
link.append("path")
|
|
442
447
|
.attr("class", "mousezone")
|
|
443
448
|
.style("stroke-width", function (d) {
|
|
444
449
|
var baseThickness = getEdgeThickness(d);
|
|
445
450
|
return Math.max(baseThickness, 7);
|
|
446
|
-
})
|
|
451
|
+
})
|
|
452
|
+
.attr("stroke-opacity", "0");
|
|
447
453
|
}
|
|
448
454
|
|
|
449
455
|
link.append("path")
|
|
@@ -480,7 +486,7 @@ export var drawGraph = function (network) {
|
|
|
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,9 +499,9 @@ export var drawGraph = function (network) {
|
|
|
493
499
|
return "url(#" + d.type + selfRef + "_StrokeWidth" + d.strokeWidth + minimum + ")";
|
|
494
500
|
} else {
|
|
495
501
|
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
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.
|
|
499
505
|
if (d.value < 0 && grnState.colorOptimal) {
|
|
500
506
|
defs.append("marker")
|
|
501
507
|
.attr("id", "repressor" + selfRef + "_StrokeWidth" + d.strokeWidth + minimum)
|
|
@@ -522,22 +528,22 @@ export var drawGraph = function (network) {
|
|
|
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,11 +638,11 @@ export var drawGraph = function (network) {
|
|
|
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")
|
|
@@ -655,25 +661,29 @@ export var drawGraph = function (network) {
|
|
|
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) {
|
|
|
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) {
|
|
|
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) {
|
|
|
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) {
|
|
|
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,7 +780,7 @@ export var drawGraph = function (network) {
|
|
|
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
786
|
if (d.value < 0 && grnState.colorOptimal) {
|
|
@@ -777,62 +789,62 @@ export var drawGraph = function (network) {
|
|
|
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) {
|
|
|
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) {
|
|
|
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) {
|
|
|
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
|
})
|
|
@@ -935,8 +948,12 @@ export var drawGraph = function (network) {
|
|
|
935
948
|
.attr({
|
|
936
949
|
href: "info?" + $.param({
|
|
937
950
|
symbol: gene.name,
|
|
938
|
-
species: grnState.species,
|
|
939
|
-
|
|
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
|
+
}),
|
|
940
957
|
target: "_blank"
|
|
941
958
|
});
|
|
942
959
|
$("body").append(tempLink);
|
|
@@ -960,129 +977,152 @@ export var drawGraph = function (network) {
|
|
|
960
977
|
return self.indexOf(value) === index;
|
|
961
978
|
}
|
|
962
979
|
|
|
963
|
-
|
|
964
|
-
|
|
980
|
+
const getExpressionData = (gene, strain, average) => {
|
|
981
|
+
const strainData = grnState.workbook.expression[strain];
|
|
965
982
|
if (average) {
|
|
966
|
-
|
|
967
|
-
|
|
983
|
+
const uniqueTimePoints = strainData.timePoints.filter(onlyUnique);
|
|
984
|
+
let avgMap = {};
|
|
968
985
|
uniqueTimePoints.forEach(function (key) {
|
|
969
986
|
avgMap[key] = [];
|
|
970
987
|
});
|
|
971
|
-
strainData.
|
|
988
|
+
strainData.timePoints.forEach(function (time, index) {
|
|
972
989
|
avgMap[time].push(strainData.data[gene][index]);
|
|
973
990
|
});
|
|
974
|
-
|
|
991
|
+
let avgs = [];
|
|
975
992
|
Object.keys(avgMap).forEach(function (key) {
|
|
976
|
-
|
|
977
|
-
|
|
993
|
+
const length = avgMap[key].length;
|
|
994
|
+
const sum = avgMap[key].reduce(function (partialSum, currentValue) {
|
|
978
995
|
return partialSum + currentValue;
|
|
979
996
|
}, 0);
|
|
980
997
|
avgs.push(sum / length);
|
|
981
998
|
});
|
|
982
999
|
return {data: avgs, timePoints: uniqueTimePoints};
|
|
983
1000
|
}
|
|
984
|
-
return {data: strainData.data[gene], timePoints: strainData.
|
|
1001
|
+
return {data: strainData.data[gene], timePoints: strainData.timePoints};
|
|
985
1002
|
};
|
|
986
1003
|
|
|
987
1004
|
var colorNodes = function (position, dataset, average, logFoldChangeMaxValue) {
|
|
988
1005
|
var timePoints = [];
|
|
989
1006
|
node.each(function (p) {
|
|
990
1007
|
d3.select(this)
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
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
|
+
});
|
|
1022
1043
|
});
|
|
1023
1044
|
};
|
|
1024
1045
|
|
|
1025
1046
|
var renderNodeColoringLegend = function (logFoldChangeMaxValue) {
|
|
1026
1047
|
var $nodeColoringLegend = $(".node-coloring-legend");
|
|
1027
1048
|
d3.select($nodeColoringLegend[0]).selectAll("svg").remove();
|
|
1028
|
-
var
|
|
1029
|
-
var
|
|
1030
|
-
var width = 200;
|
|
1049
|
+
var yMargin = 20;
|
|
1050
|
+
var width = 203;
|
|
1031
1051
|
var height = 10;
|
|
1032
1052
|
var textYOffset = 10;
|
|
1033
|
-
var increment = 0.1;
|
|
1034
1053
|
|
|
1035
1054
|
var svg = d3.select($nodeColoringLegend[0])
|
|
1036
1055
|
.append("svg")
|
|
1037
|
-
.attr("width",
|
|
1056
|
+
.attr("width", "100%")
|
|
1038
1057
|
.attr("height", height + yMargin)
|
|
1039
1058
|
.append("g")
|
|
1040
|
-
.attr("transform", "translate(
|
|
1041
|
-
|
|
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.
|
|
1042
1073
|
var gradientValues = d3.range(-logFoldChangeMaxValue, logFoldChangeMaxValue, increment);
|
|
1074
|
+
var scale = d3.scaleLinear()
|
|
1075
|
+
.domain([-logFoldChangeMaxValue, logFoldChangeMaxValue])
|
|
1076
|
+
.range([0, 1]);
|
|
1043
1077
|
|
|
1044
|
-
|
|
1078
|
+
linearGradient.selectAll("stop")
|
|
1045
1079
|
.data(gradientValues)
|
|
1046
|
-
.
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
.attr("width", width / gradientValues.length + "px")
|
|
1050
|
-
.attr("height", height + "px")
|
|
1051
|
-
.attr("transform", function (d, i) {
|
|
1052
|
-
return "translate(" + (i * (width / gradientValues.length)) + "," + 0 + ")";
|
|
1080
|
+
.enter().append("stop")
|
|
1081
|
+
.attr("offset", function (d, i) {
|
|
1082
|
+
return i / (gradientValues.length - 1);
|
|
1053
1083
|
})
|
|
1054
|
-
.
|
|
1055
|
-
var scale = d3.scaleLinear()
|
|
1056
|
-
.domain([-logFoldChangeMaxValue, logFoldChangeMaxValue])
|
|
1057
|
-
.range([0, 1]);
|
|
1058
|
-
|
|
1059
|
-
// We negate d because we actually want red to be on the right.
|
|
1084
|
+
.attr("stop-color", function (d) {
|
|
1060
1085
|
return d3.interpolateRdBu(scale(-d));
|
|
1061
1086
|
});
|
|
1062
1087
|
|
|
1088
|
+
svg.append("rect")
|
|
1089
|
+
.attr("width", `${width}px`)
|
|
1090
|
+
.attr("height", `${height}px`)
|
|
1091
|
+
.style("fill", `url(#${linearGradientId})`);
|
|
1092
|
+
|
|
1063
1093
|
var legendLabels = {
|
|
1064
|
-
|
|
1065
|
-
"
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
"center": {
|
|
1069
|
-
"textContent": "0",
|
|
1070
|
-
"x": width / 2
|
|
1094
|
+
left: {
|
|
1095
|
+
textAnchor: "start",
|
|
1096
|
+
textContent: (-logFoldChangeMaxValue).toFixed(2),
|
|
1097
|
+
x: 0
|
|
1071
1098
|
},
|
|
1072
|
-
|
|
1073
|
-
"
|
|
1074
|
-
"
|
|
1099
|
+
center: {
|
|
1100
|
+
textAnchor: "middle",
|
|
1101
|
+
textContent: "0",
|
|
1102
|
+
x: width / 2
|
|
1075
1103
|
},
|
|
1104
|
+
right: {
|
|
1105
|
+
textAnchor: "end",
|
|
1106
|
+
textContent: (logFoldChangeMaxValue).toFixed(2),
|
|
1107
|
+
x: width
|
|
1108
|
+
}
|
|
1076
1109
|
};
|
|
1077
|
-
|
|
1110
|
+
/* eslint-disable max-len */
|
|
1111
|
+
var g = document.getElementById("nodeColoringLegendId");
|
|
1112
|
+
/* eslint-enable max-len */
|
|
1113
|
+
|
|
1078
1114
|
for (var key in legendLabels) {
|
|
1079
1115
|
var label = document.createElementNS("http://www.w3.org/2000/svg", "text");
|
|
1080
1116
|
label.textContent = legendLabels[key].textContent;
|
|
1081
1117
|
label.setAttribute("font-size", "8px");
|
|
1118
|
+
label.setAttribute("text-anchor", legendLabels[key].textAnchor);
|
|
1082
1119
|
label.setAttribute("x", legendLabels[key].x);
|
|
1083
1120
|
label.setAttribute("y", height + textYOffset + "px");
|
|
1121
|
+
label.setAttribute("fill", "rgb(0,0,0)");
|
|
1122
|
+
|
|
1084
1123
|
g.appendChild(label);
|
|
1085
1124
|
}
|
|
1125
|
+
|
|
1086
1126
|
};
|
|
1087
1127
|
|
|
1088
1128
|
updaters.removeNodeColoring = function () {
|
|
@@ -1093,9 +1133,9 @@ export var drawGraph = function (network) {
|
|
|
1093
1133
|
updaters.renderNodeColoring = function () {
|
|
1094
1134
|
if (grnState.nodeColoring.nodeColoringEnabled) {
|
|
1095
1135
|
colorNodes("top", grnState.nodeColoring.topDataset, grnState.nodeColoring.averageTopDataset,
|
|
1096
|
-
|
|
1136
|
+
grnState.nodeColoring.logFoldChangeMaxValue);
|
|
1097
1137
|
colorNodes("bottom", grnState.nodeColoring.bottomDataset, grnState.nodeColoring.averageBottomDataset,
|
|
1098
|
-
|
|
1138
|
+
grnState.nodeColoring.logFoldChangeMaxValue);
|
|
1099
1139
|
renderNodeLabels();
|
|
1100
1140
|
renderNodeColoringLegend(grnState.nodeColoring.logFoldChangeMaxValue);
|
|
1101
1141
|
}
|
|
@@ -1110,7 +1150,7 @@ export var drawGraph = function (network) {
|
|
|
1110
1150
|
return false;
|
|
1111
1151
|
};
|
|
1112
1152
|
|
|
1113
|
-
if (!$.isEmptyObject(
|
|
1153
|
+
if (!$.isEmptyObject(workbook.expression) && hasExpressionData(workbook.expression) &&
|
|
1114
1154
|
grnState.nodeColoring.topDataset !== undefined) {
|
|
1115
1155
|
updaters.renderNodeColoring();
|
|
1116
1156
|
}
|
|
@@ -1131,7 +1171,7 @@ export var drawGraph = function (network) {
|
|
|
1131
1171
|
|
|
1132
1172
|
var currentWeightVisibilitySetting = null;
|
|
1133
1173
|
|
|
1134
|
-
if (
|
|
1174
|
+
if (workbook.sheetType === "weighted") {
|
|
1135
1175
|
if ($(".weightedGraphOptions").hasClass("hidden")) {
|
|
1136
1176
|
$(".weightedGraphOptions").removeClass("hidden");
|
|
1137
1177
|
}
|
|
@@ -1235,7 +1275,7 @@ export var drawGraph = function (network) {
|
|
|
1235
1275
|
updaters.setNodesToGrid = () => { // eslint-disable-line no-unused-vars
|
|
1236
1276
|
const margin = 10;
|
|
1237
1277
|
const grid = Grid() // eslint-disable-line no-undef
|
|
1238
|
-
.data(
|
|
1278
|
+
.data(workbook.genes)
|
|
1239
1279
|
.bands(true)
|
|
1240
1280
|
.padding([0.2, 0])
|
|
1241
1281
|
.size([$container.width() - margin, $container.height() - margin]); // set size of container
|
|
@@ -1257,8 +1297,8 @@ export var drawGraph = function (network) {
|
|
|
1257
1297
|
}
|
|
1258
1298
|
};
|
|
1259
1299
|
|
|
1260
|
-
|
|
1261
|
-
|
|
1300
|
+
// Tick only runs while the graph physics are still running.
|
|
1301
|
+
// (I.e. when the graph is completely relaxed, tick stops running.)
|
|
1262
1302
|
function tick () {
|
|
1263
1303
|
var getSelfReferringEdge = function (node) {
|
|
1264
1304
|
return link.select("path")["_groups"][0].map(function (path) {
|
|
@@ -1282,7 +1322,7 @@ export var drawGraph = function (network) {
|
|
|
1282
1322
|
|
|
1283
1323
|
var selfReferringEdgeWidth = (selfReferringEdge ? getSelfReferringRadius(selfReferringEdge) +
|
|
1284
1324
|
selfReferringEdge.strokeWidth + 2 : 0);
|
|
1285
|
-
var rightBoundary = width - d.textWidth - BOUNDARY_MARGIN - selfReferringEdgeWidth;
|
|
1325
|
+
var rightBoundary = width - (d.textWidth + OFFSET_VALUE) - BOUNDARY_MARGIN - selfReferringEdgeWidth;
|
|
1286
1326
|
var currentXPos = Math.max(BOUNDARY_MARGIN, Math.min(rightBoundary, d.x));
|
|
1287
1327
|
if (adaptive && width < MAX_WIDTH &&
|
|
1288
1328
|
(currentXPos === BOUNDARY_MARGIN || currentXPos === rightBoundary)) {
|
|
@@ -1349,7 +1389,7 @@ export var drawGraph = function (network) {
|
|
|
1349
1389
|
var dy = y2 - y1;
|
|
1350
1390
|
var dr = Math.sqrt(dx * dx + dy * dy);
|
|
1351
1391
|
|
|
1352
|
-
|
|
1392
|
+
// Defaults for normal edge.
|
|
1353
1393
|
var drx = dr;
|
|
1354
1394
|
var dry = dr;
|
|
1355
1395
|
var xRotation = 0; // degrees
|
|
@@ -1357,33 +1397,34 @@ export var drawGraph = function (network) {
|
|
|
1357
1397
|
var sweep = 1; // 1 or 0
|
|
1358
1398
|
var offset = parseFloat(d.strokeWidth);
|
|
1359
1399
|
|
|
1360
|
-
|
|
1400
|
+
// Edge adjustment values when long self-node edges get hidden behind the node.
|
|
1361
1401
|
var DEFAULT_NODE_SHIFT = 1.033;
|
|
1362
1402
|
var SHORT_NODE_LIMIT = 135;
|
|
1363
1403
|
var ADDITIONAL_SHIFT = 0.07;
|
|
1364
1404
|
var END_POINT_ADJUSTMENT = 1.2;
|
|
1365
1405
|
|
|
1366
1406
|
|
|
1367
|
-
|
|
1407
|
+
// Self edge.
|
|
1368
1408
|
if (x1 === x2 && y1 === y2) {
|
|
1369
|
-
|
|
1409
|
+
// Move the position of the loop.
|
|
1370
1410
|
x1 = d.source.x + (d.source.textWidth) * DEFAULT_NODE_SHIFT;
|
|
1371
1411
|
y1 = d.source.y + (nodeHeight / 2) + SELF_REFERRING_Y_OFFSET;
|
|
1372
1412
|
|
|
1373
|
-
|
|
1413
|
+
// Fiddle with this angle to get loop oriented.
|
|
1414
|
+
// (Future: This doesn't appear to change anything?)
|
|
1374
1415
|
xRotation = 45;
|
|
1375
1416
|
|
|
1376
|
-
|
|
1417
|
+
// Needs to be 1.
|
|
1377
1418
|
largeArc = 1;
|
|
1378
1419
|
|
|
1379
|
-
|
|
1420
|
+
// Change sweep to change orientation of loop.
|
|
1380
1421
|
sweep = 1;
|
|
1381
1422
|
|
|
1382
1423
|
drx = getSelfReferringRadius(d);
|
|
1383
1424
|
dry = getSelfReferringRadius(d);
|
|
1384
1425
|
|
|
1385
|
-
|
|
1386
|
-
|
|
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.
|
|
1387
1428
|
if (d.source.textWidth > SHORT_NODE_LIMIT) {
|
|
1388
1429
|
DEFAULT_NODE_SHIFT += ADDITIONAL_SHIFT;
|
|
1389
1430
|
}
|
|
@@ -1395,11 +1436,12 @@ export var drawGraph = function (network) {
|
|
|
1395
1436
|
}
|
|
1396
1437
|
}
|
|
1397
1438
|
|
|
1398
|
-
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)};
|
|
1399
1441
|
|
|
1400
1442
|
return "M" + x1 + "," + y1 +
|
|
1401
|
-
|
|
1402
|
-
|
|
1443
|
+
"A" + drx + "," + dry + " " + xRotation + "," + largeArc + "," + sweep + " " +
|
|
1444
|
+
x2 + "," + (y2 + offset);
|
|
1403
1445
|
} else {
|
|
1404
1446
|
return moveTo(d) + lineTo(d);
|
|
1405
1447
|
}
|
|
@@ -1445,7 +1487,7 @@ export var drawGraph = function (network) {
|
|
|
1445
1487
|
}
|
|
1446
1488
|
|
|
1447
1489
|
function normalize (d) {
|
|
1448
|
-
return Math.abs(d.value / maxWeight);
|
|
1490
|
+
return Math.abs(d.value / maxWeight).toPrecision(4);
|
|
1449
1491
|
}
|
|
1450
1492
|
|
|
1451
1493
|
function dragstart (d) {
|
|
@@ -1463,6 +1505,9 @@ export var drawGraph = function (network) {
|
|
|
1463
1505
|
|
|
1464
1506
|
grnState.simulation = simulation;
|
|
1465
1507
|
|
|
1508
|
+
// The restrict graph state is sometimes carried over across reloads
|
|
1509
|
+
restrictGraphToViewport( $("input[name=viewport]").prop("checked"));
|
|
1510
|
+
|
|
1466
1511
|
modifyChargeParameter(grnState.chargeSlider.currentVal);
|
|
1467
1512
|
modifyLinkDistanceParameter(grnState.linkDistanceSlider.currentVal);
|
|
1468
1513
|
|