bifurcation-explorer 0.1.0__tar.gz

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.
Files changed (115) hide show
  1. bifurcation_explorer-0.1.0/LICENSE +0 -0
  2. bifurcation_explorer-0.1.0/PKG-INFO +14 -0
  3. bifurcation_explorer-0.1.0/README.md +1 -0
  4. bifurcation_explorer-0.1.0/pyproject.toml +53 -0
  5. bifurcation_explorer-0.1.0/setup.cfg +4 -0
  6. bifurcation_explorer-0.1.0/src/bifurcation_explorer/__init__.py +0 -0
  7. bifurcation_explorer-0.1.0/src/bifurcation_explorer/__main__.py +20 -0
  8. bifurcation_explorer-0.1.0/src/bifurcation_explorer/callbacks/__init__.py +7 -0
  9. bifurcation_explorer-0.1.0/src/bifurcation_explorer/callbacks/change_resolution.py +97 -0
  10. bifurcation_explorer-0.1.0/src/bifurcation_explorer/callbacks/select_network_compartments.py +52 -0
  11. bifurcation_explorer-0.1.0/src/bifurcation_explorer/callbacks/select_parameter_type.py +29 -0
  12. bifurcation_explorer-0.1.0/src/bifurcation_explorer/callbacks/update_eigenvalue_spectrum_index_alternative.py +26 -0
  13. bifurcation_explorer-0.1.0/src/bifurcation_explorer/callbacks/update_eigenvalue_spectrum_index_empirical.py +34 -0
  14. bifurcation_explorer-0.1.0/src/bifurcation_explorer/callbacks/update_fixed_parameter_value.py +30 -0
  15. bifurcation_explorer-0.1.0/src/bifurcation_explorer/callbacks/update_graphs.py +146 -0
  16. bifurcation_explorer-0.1.0/src/bifurcation_explorer/common/__init__.py +0 -0
  17. bifurcation_explorer-0.1.0/src/bifurcation_explorer/common/config.py +130 -0
  18. bifurcation_explorer-0.1.0/src/bifurcation_explorer/common/drawing_options.py +150 -0
  19. bifurcation_explorer-0.1.0/src/bifurcation_explorer/common/exceptions.py +14 -0
  20. bifurcation_explorer-0.1.0/src/bifurcation_explorer/common/glob.py +23 -0
  21. bifurcation_explorer-0.1.0/src/bifurcation_explorer/common/redraw.py +101 -0
  22. bifurcation_explorer-0.1.0/src/bifurcation_explorer/data/__init__.py +0 -0
  23. bifurcation_explorer-0.1.0/src/bifurcation_explorer/data/bifurcation_data.py +241 -0
  24. bifurcation_explorer-0.1.0/src/bifurcation_explorer/data/branch_data.py +224 -0
  25. bifurcation_explorer-0.1.0/src/bifurcation_explorer/data/envelope_data.py +145 -0
  26. bifurcation_explorer-0.1.0/src/bifurcation_explorer/data/plot_data.py +230 -0
  27. bifurcation_explorer-0.1.0/src/bifurcation_explorer/data/shape_data.py +104 -0
  28. bifurcation_explorer-0.1.0/src/bifurcation_explorer/data/ternary_line.py +96 -0
  29. bifurcation_explorer-0.1.0/src/bifurcation_explorer/enums/__init__.py +0 -0
  30. bifurcation_explorer-0.1.0/src/bifurcation_explorer/enums/check_box.py +7 -0
  31. bifurcation_explorer-0.1.0/src/bifurcation_explorer/enums/drawing_traces.py +35 -0
  32. bifurcation_explorer-0.1.0/src/bifurcation_explorer/enums/font.py +9 -0
  33. bifurcation_explorer-0.1.0/src/bifurcation_explorer/enums/graph_palette.py +26 -0
  34. bifurcation_explorer-0.1.0/src/bifurcation_explorer/enums/labels.py +54 -0
  35. bifurcation_explorer-0.1.0/src/bifurcation_explorer/enums/network_data.py +73 -0
  36. bifurcation_explorer-0.1.0/src/bifurcation_explorer/enums/numbers_float.py +11 -0
  37. bifurcation_explorer-0.1.0/src/bifurcation_explorer/enums/numbers_integer.py +13 -0
  38. bifurcation_explorer-0.1.0/src/bifurcation_explorer/enums/resolutions.py +13 -0
  39. bifurcation_explorer-0.1.0/src/bifurcation_explorer/enums/static_options.py +3 -0
  40. bifurcation_explorer-0.1.0/src/bifurcation_explorer/enums/styles.py +176 -0
  41. bifurcation_explorer-0.1.0/src/bifurcation_explorer/enums/symbols.py +12 -0
  42. bifurcation_explorer-0.1.0/src/bifurcation_explorer/enums/types/__init__.py +0 -0
  43. bifurcation_explorer-0.1.0/src/bifurcation_explorer/enums/types/area_types.py +9 -0
  44. bifurcation_explorer-0.1.0/src/bifurcation_explorer/enums/types/bifurcation_types.py +21 -0
  45. bifurcation_explorer-0.1.0/src/bifurcation_explorer/enums/types/branch_types.py +9 -0
  46. bifurcation_explorer-0.1.0/src/bifurcation_explorer/enums/types/parameter_types.py +10 -0
  47. bifurcation_explorer-0.1.0/src/bifurcation_explorer/enums/types/plot_types.py +9 -0
  48. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/__init__.py +0 -0
  49. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/bifurcations/__init__.py +0 -0
  50. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/bifurcations/hopf/__init__.py +0 -0
  51. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/bifurcations/hopf/envelope_alternative.py +37 -0
  52. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/bifurcations/hopf/envelope_empirical.py +38 -0
  53. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/bifurcations/hopf/hopf_alternative.py +37 -0
  54. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/bifurcations/hopf/hopf_empirical.py +38 -0
  55. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/bifurcations/saddlenode/__init__.py +0 -0
  56. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/bifurcations/saddlenode/saddlenode_alternative.py +38 -0
  57. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/bifurcations/saddlenode/saddlenode_empirical.py +37 -0
  58. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/bifurcations/transcritical/__init__.py +0 -0
  59. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/bifurcations/transcritical/transcritical_alternative.py +43 -0
  60. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/bifurcations/transcritical/transcritical_empirical.py +37 -0
  61. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/biomass_compartment/__init__.py +0 -0
  62. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/biomass_compartment/biomass_compartment_first.py +47 -0
  63. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/biomass_compartment/biomass_compartment_second.py +38 -0
  64. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/draw/__init__.py +0 -0
  65. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/draw/branch_alternative.py +16 -0
  66. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/draw/branch_empirical.py +17 -0
  67. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/draw/lines.py +16 -0
  68. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/draw/points.py +16 -0
  69. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/eigenvalue_spectrum/__init__.py +0 -0
  70. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/eigenvalue_spectrum/eigenvalue_spectrum_centered_alternative.py +21 -0
  71. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/eigenvalue_spectrum/eigenvalue_spectrum_centered_empirical.py +16 -0
  72. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/eigenvalue_spectrum/eigenvalue_spectrum_index_alternative.py +43 -0
  73. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/eigenvalue_spectrum/eigenvalue_spectrum_index_empirical.py +37 -0
  74. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/equilibria/__init__.py +0 -0
  75. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/equilibria/area.py +58 -0
  76. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/equilibria/over_information.py +31 -0
  77. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/equilibria/stable.py +42 -0
  78. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/equilibria/unstable.py +42 -0
  79. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/general/__init__.py +0 -0
  80. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/general/network_selector.py +21 -0
  81. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/general/resolution_selector.py +21 -0
  82. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/ids.py +71 -0
  83. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/layout.py +347 -0
  84. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/others/__init__.py +0 -0
  85. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/others/eigenvalue_spectrum_index.py +37 -0
  86. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/others/extinct.py +37 -0
  87. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/others/internal_error.py +37 -0
  88. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/parameters/__init__.py +0 -0
  89. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/parameters/fixed_parameter_type.py +38 -0
  90. bifurcation_explorer-0.1.0/src/bifurcation_explorer/frontend/parameters/fixed_parameter_value.py +37 -0
  91. bifurcation_explorer-0.1.0/src/bifurcation_explorer/graph/__init__.py +0 -0
  92. bifurcation_explorer-0.1.0/src/bifurcation_explorer/graph/bifurcation_diagram/__init__.py +0 -0
  93. bifurcation_explorer-0.1.0/src/bifurcation_explorer/graph/bifurcation_diagram/build.py +289 -0
  94. bifurcation_explorer-0.1.0/src/bifurcation_explorer/graph/bifurcation_diagram/update.py +466 -0
  95. bifurcation_explorer-0.1.0/src/bifurcation_explorer/graph/eigenvalue_spectrum/__init__.py +0 -0
  96. bifurcation_explorer-0.1.0/src/bifurcation_explorer/graph/eigenvalue_spectrum/build.py +41 -0
  97. bifurcation_explorer-0.1.0/src/bifurcation_explorer/graph/eigenvalue_spectrum/update.py +147 -0
  98. bifurcation_explorer-0.1.0/src/bifurcation_explorer/graph/figures.py +49 -0
  99. bifurcation_explorer-0.1.0/src/bifurcation_explorer/graph/phase_portrait/__init__.py +0 -0
  100. bifurcation_explorer-0.1.0/src/bifurcation_explorer/graph/phase_portrait/build.py +41 -0
  101. bifurcation_explorer-0.1.0/src/bifurcation_explorer/graph/phase_portrait/update.py +81 -0
  102. bifurcation_explorer-0.1.0/src/bifurcation_explorer/graph/ternary/__init__.py +0 -0
  103. bifurcation_explorer-0.1.0/src/bifurcation_explorer/graph/ternary/build.py +191 -0
  104. bifurcation_explorer-0.1.0/src/bifurcation_explorer/graph/ternary/update_data.py +395 -0
  105. bifurcation_explorer-0.1.0/src/bifurcation_explorer/graph/ternary/update_traces.py +96 -0
  106. bifurcation_explorer-0.1.0/src/bifurcation_explorer/graph/ternary/write.py +12 -0
  107. bifurcation_explorer-0.1.0/src/bifurcation_explorer/graph/time_serie/__init__.py +0 -0
  108. bifurcation_explorer-0.1.0/src/bifurcation_explorer/graph/time_serie/build.py +41 -0
  109. bifurcation_explorer-0.1.0/src/bifurcation_explorer/graph/time_serie/update.py +12 -0
  110. bifurcation_explorer-0.1.0/src/bifurcation_explorer.egg-info/PKG-INFO +14 -0
  111. bifurcation_explorer-0.1.0/src/bifurcation_explorer.egg-info/SOURCES.txt +113 -0
  112. bifurcation_explorer-0.1.0/src/bifurcation_explorer.egg-info/dependency_links.txt +1 -0
  113. bifurcation_explorer-0.1.0/src/bifurcation_explorer.egg-info/entry_points.txt +2 -0
  114. bifurcation_explorer-0.1.0/src/bifurcation_explorer.egg-info/requires.txt +3 -0
  115. bifurcation_explorer-0.1.0/src/bifurcation_explorer.egg-info/top_level.txt +1 -0
File without changes
@@ -0,0 +1,14 @@
1
+ Metadata-Version: 2.4
2
+ Name: bifurcation-explorer
3
+ Version: 0.1.0
4
+ Summary: A tool for exploring bifurcations in a set of food-web networks
5
+ Author-email: Pablo Alvarez Lopez <pablo@alvarezlopez.com>
6
+ Requires-Python: >=3.9
7
+ Description-Content-Type: text/markdown
8
+ License-File: LICENSE
9
+ Requires-Dist: dash
10
+ Requires-Dist: numpy
11
+ Requires-Dist: scipy
12
+ Dynamic: license-file
13
+
14
+ # Bifurcation Explorer
@@ -0,0 +1 @@
1
+ # Bifurcation Explorer
@@ -0,0 +1,53 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "bifurcation-explorer"
7
+ version = "0.1.0"
8
+ description = "A tool for exploring bifurcations in a set of food-web networks"
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ authors = [
12
+ { name = "Pablo Alvarez Lopez", email = "pablo@alvarezlopez.com" }
13
+ ]
14
+
15
+ dependencies = [
16
+ "dash",
17
+ "numpy",
18
+ "scipy"
19
+ ]
20
+
21
+ [project.scripts]
22
+ bifurcation-explorer = "bifurcation_explorer.__main__:run"
23
+
24
+ [tool.setuptools.packages.find]
25
+ where = ["src"]
26
+
27
+ [tool.setuptools.package-data]
28
+ "*" = ["*.css", "*.html", "*.png", "*.jpg"]
29
+
30
+ # tools configuration
31
+
32
+ [tool.black]
33
+ line-length = 150
34
+
35
+ [tool.pytest.ini_options]
36
+ testpaths = ["tests"]
37
+ pythonpath = ["src"]
38
+
39
+ [tool.mypy]
40
+ python_version = "3.9"
41
+ warn_return_any = true
42
+ warn_unused_configs = true
43
+ disallow_untyped_defs = true
44
+ #ignore_missing_imports = true
45
+
46
+ [tool.pylint."MESSAGES CONTROL"]
47
+ max-line-length = 150
48
+ disable = [
49
+ "R0903", # Too few public methods
50
+ ]
51
+
52
+ [tool.pylint.FORMAT]
53
+ expected-line-ending-format = "CRLF"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,20 @@
1
+ from threading import Timer
2
+ import webbrowser
3
+ import pathlib
4
+
5
+ # project imports
6
+ from bifurcation_explorer.common import glob
7
+ from bifurcation_explorer.enums.static_options import StaticOptions
8
+ from bifurcation_explorer.frontend.layout import html_layout
9
+ from bifurcation_explorer.callbacks import *
10
+
11
+ # main
12
+ if __name__ == "__main__":
13
+ # set main folder
14
+ glob.config.main_folder = pathlib.Path(__file__).parent.resolve()
15
+ # open browser after 1 second
16
+ Timer(1, lambda: webbrowser.open_new("http://127.0.0.1:8050/")).start()
17
+ # set layout
18
+ glob.app.layout = html_layout
19
+ # run app
20
+ glob.app.run(debug=StaticOptions.DEBUG)
@@ -0,0 +1,7 @@
1
+ from .change_resolution import change_resolution
2
+ from .select_network_compartments import select_network_compartments
3
+ from .select_parameter_type import select_parameter_type
4
+ from .update_eigenvalue_spectrum_index_alternative import update_eigenvalue_spectrum_index_alternative
5
+ from .update_eigenvalue_spectrum_index_empirical import update_eigenvalue_spectrum_index_empirical
6
+ from .update_fixed_parameter_value import update_fixed_parameter_value
7
+ from .update_graphs import update_graphs
@@ -0,0 +1,97 @@
1
+ from dash import Input, Output, Patch, callback
2
+
3
+ from bifurcation_explorer.common import glob
4
+ from bifurcation_explorer.enums.styles import Styles
5
+ from bifurcation_explorer.frontend.ids import IDs
6
+
7
+ # callback to change resolution
8
+ @callback(
9
+ # outputs
10
+ Output(IDs.DROPDOWN_SIZE, "value"),
11
+ Output(IDs.FIG_TERNARY_GRAPH, "figure", allow_duplicate=True),
12
+ Output(IDs.FIG_BIFURCATION_DIAGRAMM_FIRST, "figure", allow_duplicate=True),
13
+ Output(IDs.FIG_BIFURCATION_DIAGRAMM_SECOND, "figure", allow_duplicate=True),
14
+ Output(IDs.FIG_EIGENVALUE_SPECTRUM_EMPIRICAL, "figure", allow_duplicate=True),
15
+ Output(IDs.FIG_EIGENVALUE_SPECTRUM_ALTERNATIVE, "figure", allow_duplicate=True),
16
+ Output(IDs.FIG_TIME_SERIES_FIRST, "figure", allow_duplicate=True),
17
+ Output(IDs.FIG_TIME_SERIES_SECOND, "figure", allow_duplicate=True),
18
+ Output(IDs.FIG_PHASE_PORTRAIT_FIRST, "figure", allow_duplicate=True),
19
+ Output(IDs.FIG_PHASE_PORTRAIT_SECOND, "figure", allow_duplicate=True),
20
+ Output(IDs.DIV_GRAPH_PLOT_01, "style"),
21
+ Output(IDs.DIV_GRAPH_PLOT_02, "style"),
22
+ Output(IDs.DIV_GRAPH_PLOT_03, "style"),
23
+ Output(IDs.DIV_GRAPH_PLOT_04, "style"),
24
+ Output(IDs.DIV_GRAPH_PLOT_05, "style"),
25
+ Output(IDs.DIV_GRAPH_PLOT_06, "style"),
26
+ Output(IDs.DIV_GRAPH_PLOT_07, "style"),
27
+ Output(IDs.DIV_GRAPH_PLOT_08, "style"),
28
+ Output(IDs.DIV_GRAPHS, "style"),
29
+ Output(IDs.DIV_RIGH_PANEL, "style"),
30
+ Output(IDs.DIV_SMALL_ROW_01, "style"),
31
+ Output(IDs.DIV_SMALL_ROW_02, "style"),
32
+ Output(IDs.DIV_SMALL_ROW_03, "style"),
33
+ Output(IDs.DIV_SMALL_ROW_04, "style"),
34
+ Output(IDs.DIV_GRAPH_TERNARY, "style"),
35
+ # inputs
36
+ Input(IDs.DROPDOWN_SIZE, "value"),
37
+ # we don't need an initial call
38
+ prevent_initial_call=True,
39
+ )
40
+
41
+ # change resolution
42
+ def change_resolution(size: int):
43
+ # update resolution in config
44
+ glob.config.resolution = size
45
+ # declare patch for ternary
46
+ patched_ternary = Patch()
47
+ patched_ternary["layout"]["width"] = size * 2
48
+ patched_ternary["layout"]["height"] = size * 2
49
+ # declare patch for plots
50
+ patched_plot = Patch()
51
+ patched_plot["layout"]["width"] = size * 2
52
+ patched_plot["layout"]["height"] = size
53
+ # get div styles
54
+ div_graph_plot = Styles.DIV_GRAPH_PLOT
55
+ div_graphs = Styles.DIV_GRAPHS
56
+ div_right_panel = Styles.DIV_RIGHT_PANEL
57
+ div_small_row = Styles.DIV_SMALL_ROW
58
+ div_ternary_graph = Styles.DIV_GRAPH_TERNARY
59
+ # update styles
60
+ div_graph_plot["width"] = f"{size * 2}px"
61
+ div_graph_plot["height"] = f"{size}px"
62
+ div_graphs["width"] = f"{size * 4}px"
63
+ div_graphs["height"] = f"{size * 2}px"
64
+ div_right_panel["width"] = f"{size * 2}px"
65
+ div_right_panel["height"] = f"{size * 4}px"
66
+ div_small_row["width"] = f"{size * 2}px"
67
+ div_small_row["height"] = f"{size}px"
68
+ div_ternary_graph["width"] = f"{size * 2}px"
69
+ div_ternary_graph["height"] = f"{size * 2}px"
70
+ # return values
71
+ return (
72
+ size,
73
+ patched_ternary,
74
+ patched_plot,
75
+ patched_plot,
76
+ patched_plot,
77
+ patched_plot,
78
+ patched_plot,
79
+ patched_plot,
80
+ patched_plot,
81
+ patched_plot,
82
+ div_graph_plot,
83
+ div_graph_plot,
84
+ div_graph_plot,
85
+ div_graph_plot,
86
+ div_graph_plot,
87
+ div_graph_plot,
88
+ div_graph_plot,
89
+ div_graph_plot,
90
+ div_graphs,
91
+ div_right_panel,
92
+ div_small_row,
93
+ div_small_row,
94
+ div_small_row,
95
+ div_small_row,
96
+ div_ternary_graph
97
+ )
@@ -0,0 +1,52 @@
1
+ from dash import Input, Output, callback
2
+
3
+ from bifurcation_explorer.common import glob
4
+ from bifurcation_explorer.frontend.ids import IDs
5
+ from bifurcation_explorer.graph.ternary.build import build_ternary
6
+ from bifurcation_explorer.graph.ternary.update_traces import update_traces
7
+
8
+
9
+ # callback to select network
10
+ @callback(
11
+ # outputs
12
+ Output(IDs.DROPDOWN_NETWORK, "value"),
13
+ Output(IDs.DROPDOWN_COMPARTMENT_FIRST, "options"),
14
+ Output(IDs.DROPDOWN_COMPARTMENT_FIRST, "value"),
15
+ Output(IDs.DROPDOWN_COMPARTMENT_SECOND, "options"),
16
+ Output(IDs.DROPDOWN_COMPARTMENT_SECOND, "value"),
17
+ # inputs
18
+ Input(IDs.DROPDOWN_NETWORK, "value"),
19
+ Input(IDs.DROPDOWN_COMPARTMENT_FIRST, "value"),
20
+ Input(IDs.DROPDOWN_COMPARTMENT_SECOND, "value"),
21
+ )
22
+
23
+ # select network and compartments
24
+ def select_network_compartments(network: str, compartment_value_a: str, compartment_value_b: str):
25
+ # check if update network
26
+ if glob.config.network != network:
27
+ # update network
28
+ glob.config.update_network(network)
29
+ # reset ternary
30
+ glob.figures.ternary = build_ternary()
31
+ # load ternary data
32
+ glob.plot_data.load_ternary_data()
33
+ # update compartments
34
+ glob.config.update_comparment_first(compartment_value_a)
35
+ glob.config.update_comparment_second(compartment_value_b)
36
+ # get the list of new compartments
37
+ new_compartments = glob.config.get_current_compartments()
38
+ # update branch datas
39
+ glob.plot_data.load_branch_datas()
40
+ # update ternary traces
41
+ update_traces()
42
+ # redraw bifurcation diagrams
43
+ glob.config.drawing_options.redraw_bifurcation_diagrams_first.redraw_all()
44
+ glob.config.drawing_options.redraw_bifurcation_diagrams_second.redraw_all()
45
+ # return network and new list of compartments
46
+ return (
47
+ network,
48
+ new_compartments,
49
+ glob.config.compartment_first,
50
+ new_compartments,
51
+ glob.config.compartment_second,
52
+ )
@@ -0,0 +1,29 @@
1
+ from dash import Input, Output, callback
2
+
3
+ from bifurcation_explorer.common import glob
4
+ from bifurcation_explorer.enums.types.parameter_types import ParameterTypes
5
+ from bifurcation_explorer.frontend.ids import IDs
6
+
7
+
8
+ # callback to sync parameter checkboxes
9
+ @callback(
10
+ # outputs
11
+ Output(IDs.DROPDOWN_PARAMETER_TYPE, "value"),
12
+ # inputs
13
+ Input(IDs.DROPDOWN_PARAMETER_TYPE, "value"),
14
+ # we don't need an initial call
15
+ prevent_initial_call=True,
16
+ )
17
+
18
+ # select parameter type
19
+ def select_parameter_type(parameter_type_str: str):
20
+ # set new parameter type
21
+ try:
22
+ glob.config.update_fixed_parameter_type(ParameterTypes(parameter_type_str))
23
+ except ValueError:
24
+ print(f"Error: invalid parameter '{parameter_type_str}'.")
25
+ # force redraw ternaries and bifurcation diagrams
26
+ glob.config.drawing_options.redraw_ternary.redraw_all()
27
+ glob.config.drawing_options.redraw_bifurcation_diagrams_first.redraw_all()
28
+ glob.config.drawing_options.redraw_bifurcation_diagrams_second.redraw_all()
29
+ return parameter_type_str
@@ -0,0 +1,26 @@
1
+ from dash import Input, Output, callback
2
+
3
+ from bifurcation_explorer.common import glob
4
+ from bifurcation_explorer.enums.types.branch_types import BranchTypes
5
+ from bifurcation_explorer.frontend.ids import IDs
6
+
7
+
8
+ # callback to update analyzed value
9
+ @callback(
10
+ # outputs
11
+ Output(IDs.TEXTFIELD_EIGENVALUE_SPECTRUM_INDEX_ALTERNATIVE, "value"),
12
+ # inputs
13
+ Input(IDs.TEXTFIELD_EIGENVALUE_SPECTRUM_INDEX_ALTERNATIVE, "value"),
14
+ # we don't need an initial call
15
+ prevent_initial_call=True,
16
+ )
17
+
18
+ # update analyzed value
19
+ def update_eigenvalue_spectrum_index_alternative(eigenvalue_spectrum_index: int):
20
+ # check that we introduced a valid number
21
+ if eigenvalue_spectrum_index is not None:
22
+ # update index
23
+ glob.config.update_eigenvalue_spectrum_index(
24
+ eigenvalue_spectrum_index, BranchTypes.ALTERNATIVE
25
+ )
26
+ return eigenvalue_spectrum_index
@@ -0,0 +1,34 @@
1
+ from dash import Input, Output, callback
2
+
3
+ from bifurcation_explorer.common import glob
4
+ from bifurcation_explorer.enums.types.branch_types import BranchTypes
5
+ from bifurcation_explorer.frontend.ids import IDs
6
+
7
+
8
+ # callback to update analyzed value
9
+ @callback(
10
+ # outputs
11
+ Output(IDs.TEXTFIELD_EIGENVALUE_SPECTRUM_INDEX_EMPIRICAL, "value"),
12
+ # inputs
13
+ Input(IDs.TEXTFIELD_EIGENVALUE_SPECTRUM_INDEX_EMPIRICAL, "value"),
14
+ # we don't need an initial call
15
+ prevent_initial_call=True,
16
+ )
17
+
18
+
19
+ def update_eigenvalue_spectrum_index_empirical(eigenvalue_spectrum_index: int):
20
+ """Update the eigenvalue spectrum index for empirical data.
21
+
22
+ Args:
23
+ eigenvalue_spectrum_index: The index value to set for the eigenvalue spectrum.
24
+
25
+ Returns:
26
+ The eigenvalue spectrum index value.
27
+ """
28
+ # check that we introduced a valid number
29
+ if eigenvalue_spectrum_index is not None:
30
+ # update index
31
+ glob.config.update_eigenvalue_spectrum_index(
32
+ eigenvalue_spectrum_index, BranchTypes.EMPIRICAL
33
+ )
34
+ return eigenvalue_spectrum_index
@@ -0,0 +1,30 @@
1
+ from dash import Input, Output, callback
2
+
3
+ from bifurcation_explorer.common import glob
4
+ from bifurcation_explorer.frontend.ids import IDs
5
+
6
+
7
+ # callback to update fixed value
8
+ @callback(
9
+ # outputs
10
+ Output(IDs.TEXTFIELD_FIXED_PARAMETER_VALUE, "value"),
11
+ # inputs
12
+ Input(IDs.TEXTFIELD_FIXED_PARAMETER_VALUE, "value"),
13
+ # we don't need an initial call
14
+ prevent_initial_call=True,
15
+ )
16
+
17
+ # update fixed value
18
+ def update_fixed_parameter_value(fixed_parameter_value: float):
19
+ # check that we introduced a valid number
20
+ if fixed_parameter_value is not None:
21
+ # set new value
22
+ fixed_parameter_value = glob.config.update_fixed_parameter_value(fixed_parameter_value)
23
+ # read branch datas
24
+ glob.plot_data.load_branch_datas()
25
+ # update only ternary branches
26
+ glob.config.drawing_options.redraw_ternary.branches = True
27
+ # redraw full bifurcation diagrams
28
+ glob.config.drawing_options.redraw_bifurcation_diagrams_first.redraw_all()
29
+ glob.config.drawing_options.redraw_bifurcation_diagrams_second.redraw_all()
30
+ return fixed_parameter_value
@@ -0,0 +1,146 @@
1
+ from dash import Input, Output, callback
2
+
3
+ from bifurcation_explorer.common import glob
4
+ from bifurcation_explorer.enums.types.branch_types import BranchTypes
5
+ from bifurcation_explorer.enums.types.plot_types import PlotTypes
6
+ from bifurcation_explorer.frontend.ids import IDs
7
+ from bifurcation_explorer.graph.bifurcation_diagram.update import update_bifurcation_diagram
8
+ from bifurcation_explorer.graph.eigenvalue_spectrum.update import update_eigenvalue_spectrum
9
+ from bifurcation_explorer.graph.ternary.update_data import update_ternary_data
10
+
11
+
12
+ # callback to update graphs
13
+ @callback(
14
+ # outputs
15
+ [
16
+ Output(IDs.FIG_TERNARY_GRAPH, "figure"),
17
+ Output(IDs.FIG_BIFURCATION_DIAGRAMM_FIRST, "figure"),
18
+ Output(IDs.FIG_BIFURCATION_DIAGRAMM_SECOND, "figure"),
19
+ Output(IDs.FIG_EIGENVALUE_SPECTRUM_EMPIRICAL, "figure"),
20
+ Output(IDs.FIG_EIGENVALUE_SPECTRUM_ALTERNATIVE, "figure"),
21
+ Output(IDs.ERROR_MESSAGE, "children"),
22
+ ],
23
+ # inputs
24
+ [
25
+ # general
26
+ Input(IDs.DROPDOWN_NETWORK, "value"),
27
+ Input(IDs.DROPDOWN_PARAMETER_TYPE, "value"),
28
+ Input(IDs.DROPDOWN_COMPARTMENT_FIRST, "value"),
29
+ Input(IDs.DROPDOWN_COMPARTMENT_SECOND, "value"),
30
+ Input(IDs.TEXTFIELD_FIXED_PARAMETER_VALUE, "value"),
31
+ # branches
32
+ Input(IDs.CHECKBOX_EQUILIBRIA_AREA, "value"),
33
+ Input(IDs.CHECKBOX_EQUILIBRIA_STABLE, "value"),
34
+ Input(IDs.CHECKBOX_EQUILIBRIA_UNSTABLE, "value"),
35
+ Input(IDs.CHECKBOX_EQUILIBRIA_OVERINFORMATION, "value"),
36
+ # bifurcations
37
+ Input(IDs.CHECKBOX_BIFURCATIONS_SADDLENODE_EMPIRICAL, "value"),
38
+ Input(IDs.CHECKBOX_BIFURCATIONS_SADDLENODE_ALTERNATIVE, "value"),
39
+ Input(IDs.CHECKBOX_BIFURCATIONS_TRANSCRITICAL_EMPIRICAL, "value"),
40
+ Input(IDs.CHECKBOX_BIFURCATIONS_TRANSCRITICAL_ALTERNATIVE, "value"),
41
+ Input(IDs.CHECKBOX_BIFURCATIONS_HOPF_EMPIRICAL, "value"),
42
+ Input(IDs.CHECKBOX_BIFURCATIONS_ENVELOPE_EMPIRICAL, "value"),
43
+ Input(IDs.CHECKBOX_BIFURCATIONS_HOPF_ALTERNATIVE, "value"),
44
+ Input(IDs.CHECKBOX_BIFURCATIONS_ENVELOPE_ALTERNATIVE, "value"),
45
+ # others
46
+ Input(IDs.CHECKBOX_OTHERS_EXTINCT, "value"),
47
+ Input(IDs.CHECKBOX_OTHERS_INTERNALERROR, "value"),
48
+ Input(IDs.CHECKBOX_OTHERS_EIGENVALUE_SPECTRUM_INDEX, "value"),
49
+ # draw options
50
+ Input(IDs.CHECKBOX_DRAW_BRANCH_EMPIRICAL, "value"),
51
+ Input(IDs.CHECKBOX_DRAW_BRANCH_ALTERNATIVE, "value"),
52
+ Input(IDs.CHECKBOX_DRAW_LINES, "value"),
53
+ Input(IDs.CHECKBOX_DRAW_POINTS, "value"),
54
+ # eigen values spectrum
55
+ Input(IDs.TEXTFIELD_EIGENVALUE_SPECTRUM_INDEX_EMPIRICAL, "value"),
56
+ Input(IDs.TEXTFIELD_EIGENVALUE_SPECTRUM_INDEX_ALTERNATIVE, "value"),
57
+ # eigen values centering
58
+ Input(IDs.CHECKBOX_EIGENVALUE_SPECTRUM_CENTERED_EMPIRICAL, "value"),
59
+ Input(IDs.CHECKBOX_EIGENVALUE_SPECTRUM_CENTERED_ALTERNATIVE, "value"),
60
+ ],
61
+ )
62
+
63
+ # update graph
64
+ def update_graphs(
65
+ _network: str,
66
+ _parameter_type: str,
67
+ _compartment_a: str,
68
+ _compartment_b: str,
69
+ _fixed_parameter_value: float,
70
+ # equilibria
71
+ equilibria_area: bool,
72
+ equilibria_stable: bool,
73
+ equilibria_unstable: bool,
74
+ equilibria_over_information: bool,
75
+ # bifurcations
76
+ bifurcations_saddlenode_empirical: bool,
77
+ bifurcations_saddlenode_alternative: bool,
78
+ bifurcations_transcritical_empirical: bool,
79
+ bifurcations_transcritical_alternative: bool,
80
+ bifurcations_hopf_empirical: bool,
81
+ bifurcations_envelope_empirical: bool,
82
+ bifurcations_hopf_alternative: bool,
83
+ bifurcations_envelope_alternative: bool,
84
+ # others
85
+ others_extinct: bool,
86
+ others_internal_error: bool,
87
+ others_eigenvalue_spectrum_index: bool,
88
+ # drawing options
89
+ draw_branch_empirical: bool,
90
+ draw_branch_alternative: bool,
91
+ draw_lines: bool,
92
+ draw_points: bool,
93
+ # eigenvalue spectrum
94
+ _eigenvalue_spectrum_index_empirical: float,
95
+ _eigenvalue_spectrum_index_alternative: float,
96
+ # eigenvalue spectrum (centering)
97
+ eigenvalue_spectrum_centered_empirical: bool,
98
+ eigenvalue_spectrum_centered_alternative: bool,
99
+ ):
100
+ # update drawing config
101
+ glob.config.drawing_options.update_flags(
102
+ equilibria_area,
103
+ equilibria_stable,
104
+ equilibria_unstable,
105
+ equilibria_over_information,
106
+ bifurcations_saddlenode_empirical,
107
+ bifurcations_saddlenode_alternative,
108
+ bifurcations_transcritical_empirical,
109
+ bifurcations_transcritical_alternative,
110
+ bifurcations_hopf_empirical,
111
+ bifurcations_envelope_empirical,
112
+ bifurcations_hopf_alternative,
113
+ bifurcations_envelope_alternative,
114
+ others_extinct,
115
+ others_internal_error,
116
+ others_eigenvalue_spectrum_index,
117
+ draw_branch_empirical,
118
+ draw_branch_alternative,
119
+ draw_lines,
120
+ draw_points,
121
+ eigenvalue_spectrum_centered_empirical,
122
+ eigenvalue_spectrum_centered_alternative,
123
+ )
124
+ # update both bifurcation diagrams
125
+ glob.figures.bifurcation_diagram_first = update_bifurcation_diagram(
126
+ glob.figures.bifurcation_diagram_first, PlotTypes.FIRST
127
+ )
128
+ glob.figures.bifurcation_diagram_second = update_bifurcation_diagram(
129
+ glob.figures.bifurcation_diagram_second, PlotTypes.SECOND
130
+ )
131
+ # update both bifurcation diagrams
132
+ glob.figures.eigenvalue_spectrum_empirical = update_eigenvalue_spectrum(
133
+ glob.figures.eigenvalue_spectrum_empirical, BranchTypes.EMPIRICAL
134
+ )
135
+ glob.figures.eigenvalue_spectrum_alternative = update_eigenvalue_spectrum(
136
+ glob.figures.eigenvalue_spectrum_alternative, BranchTypes.ALTERNATIVE
137
+ )
138
+ # return both figure and the empty error message
139
+ return (
140
+ update_ternary_data(),
141
+ glob.figures.bifurcation_diagram_first,
142
+ glob.figures.bifurcation_diagram_second,
143
+ glob.figures.eigenvalue_spectrum_empirical,
144
+ glob.figures.eigenvalue_spectrum_alternative,
145
+ "",
146
+ )
@@ -0,0 +1,130 @@
1
+ import os
2
+
3
+ from bifurcation_explorer.common.drawing_options import DrawingOptions
4
+ from bifurcation_explorer.common.exceptions import ParameterTypeError
5
+ from bifurcation_explorer.enums.types.branch_types import BranchTypes
6
+ from bifurcation_explorer.enums.network_data import NetworkData
7
+ from bifurcation_explorer.enums.types.parameter_types import ParameterTypes
8
+ from bifurcation_explorer.enums.resolutions import Resolutions
9
+
10
+
11
+ # config file
12
+ class Config:
13
+
14
+ def __init__(self):
15
+ # main folder
16
+ self.main_folder = "."
17
+ # current dynamic options
18
+ self.network: str = None
19
+ self.resolution: Resolutions = int(Resolutions.DEFAULT)
20
+ self.compartment_first_index: int = 0
21
+ self.compartment_first: str = None
22
+ self.compartment_second_index: int = 1
23
+ self.compartment_second: str = None
24
+ self.fixed_parameter_type: ParameterTypes = ParameterTypes.LOTKAVOLTERRA
25
+ self.dynamic_paramameter_type: ParameterTypes = ParameterTypes.RECIPIENT
26
+ self.fixed_parameter_value: float = 0.4
27
+ self.fixed_parameter_value_str: str = f"{self.fixed_parameter_value:.5f}"
28
+ # eigenValues spectrum options
29
+ self.eigenvalue_spectrum_index: dict[BranchTypes, int] = {}
30
+ for branch_type in BranchTypes:
31
+ self.eigenvalue_spectrum_index[branch_type] = 0
32
+ # drawing options
33
+ self.drawing_options: DrawingOptions = DrawingOptions()
34
+
35
+ def get_current_compartments(self):
36
+ """Return the list of current compartments for the selected network."""
37
+ if self.network is not None:
38
+ return NetworkData.VALUES[self.network]
39
+ # return empty list
40
+ return []
41
+
42
+ def get_pseudoarc_result_folder_data(self):
43
+ """Return the path to the result pseudo-arc data folder."""
44
+ return "D:/OIST/foodweb-dynamics/matlab_pablo/branches/13-continuation-pseudoArc/results"
45
+
46
+ def get_envelope_result_folder_data(self):
47
+ """Return the path to the result envelope data folder."""
48
+ return "D:/OIST/foodweb-dynamics/matlab_pablo/branches/16-hopf-bifurcation-envelope/results"
49
+
50
+ def get_pickle_cache_folder(self):
51
+ """Return the path to the pickle cache folder."""
52
+ return os.path.join(self.main_folder, "cache")
53
+
54
+ def get_pickle_network_folder(self):
55
+ """Return the path to the pickle network folder."""
56
+ return os.path.join(self.get_pickle_cache_folder(), self.network)
57
+
58
+ def get_pickle_plot_data(self):
59
+ """Return the path to the bifurcations pickle file."""
60
+ return os.path.join(self.get_pickle_network_folder(), "plot_data.pkl")
61
+
62
+ def get_continuation_zip_file(self, fixed_parameter_value_str: str):
63
+ """Return the path to the continuation zip file."""
64
+ return os.path.join(self.get_pseudoarc_result_folder_data(), self.network, fixed_parameter_value_str + ".zip")
65
+
66
+ def get_envelope_zip_file(self, fixed_parameter_value_str: str):
67
+ """Return the path to the envelope zip file."""
68
+ return os.path.join(self.get_envelope_result_folder_data(), self.network, fixed_parameter_value_str + ".zip")
69
+
70
+ def get_pickle_branch_file(self, fixed_parameter_value: str):
71
+ """Return the path to the branch pickle file."""
72
+ return os.path.join(self.get_pickle_network_folder(), fixed_parameter_value + ".pkl")
73
+
74
+ def update_network(self, network: str):
75
+ """Update the current network and adjust compartment indices if necessary."""
76
+ self.network = network
77
+ # adjust compartments
78
+ num_compartments: int = len(self.get_current_compartments())
79
+ if self.compartment_first_index >= num_compartments:
80
+ self.compartment_first_index = 0
81
+ if self.compartment_second_index >= num_compartments:
82
+ self.compartment_second_index = 0
83
+
84
+ def update_fixed_parameter_type(self, fixed_parameter_type: ParameterTypes):
85
+ """Update the type of the fixed parameter."""
86
+ self.fixed_parameter_type = fixed_parameter_type
87
+ # set dynamic parameter
88
+ if self.fixed_parameter_type == ParameterTypes.DONOR:
89
+ self.dynamic_paramameter_type = ParameterTypes.LOTKAVOLTERRA
90
+ elif self.fixed_parameter_type == ParameterTypes.RECIPIENT:
91
+ self.dynamic_paramameter_type = ParameterTypes.DONOR
92
+ elif self.fixed_parameter_type == ParameterTypes.LOTKAVOLTERRA:
93
+ self.dynamic_paramameter_type = ParameterTypes.RECIPIENT
94
+ else:
95
+ raise ParameterTypeError("invalid parameter")
96
+
97
+ def update_fixed_parameter_value(self, fixed_parameter_value: float):
98
+ """Update the value of the fixed parameter and its string representation."""
99
+ self.fixed_parameter_value = fixed_parameter_value
100
+ self.fixed_parameter_value_str = f"{fixed_parameter_value:.5f}"
101
+ # return new value
102
+ return self.fixed_parameter_value
103
+
104
+ def update_eigenvalue_spectrum_index(
105
+ self, eigenvalue_spectrum_index: int, branch_type: BranchTypes
106
+ ):
107
+ """Update the eigenvalue spectrum index for a given branch type."""
108
+ self.eigenvalue_spectrum_index[branch_type] = eigenvalue_spectrum_index
109
+
110
+ def update_comparment_first(self, compartment_first: str):
111
+ """Update first compartment to the specified value if it exists, otherwise set to the first compartment."""
112
+ compartments: list[str] = self.get_current_compartments()
113
+ # continue depending if value exist in the current compartments
114
+ if compartment_first in compartments:
115
+ self.compartment_first = compartment_first
116
+ self.compartment_first_index = compartments.index(compartment_first)
117
+ else:
118
+ self.compartment_first = compartments[0]
119
+ self.compartment_first_index = 0
120
+
121
+ def update_comparment_second(self, compartment_second: str):
122
+ """Update second compartment to the specified value if it exists, otherwise set to the second compartment."""
123
+ compartments: list[str] = self.get_current_compartments()
124
+ # continue depending if value exist in the current compartments
125
+ if compartment_second in compartments:
126
+ self.compartment_second = compartment_second
127
+ self.compartment_second_index = compartments.index(compartment_second)
128
+ else:
129
+ self.compartment_second = compartments[1]
130
+ self.compartment_second_index = 1