From d02eef983588d9c832e4459794d5d28b1dbacbb4 Mon Sep 17 00:00:00 2001 From: Shreyas Singh Date: Thu, 23 Mar 2023 02:27:30 +0530 Subject: [PATCH 1/5] Add a check to display the widgets in a notebook only --- .../visualization/widgets/custom_abundance.py | 191 +++++++++--------- tardis/visualization/widgets/line_info.py | 129 ++++++------ tardis/visualization/widgets/shell_info.py | 89 ++++---- 3 files changed, 211 insertions(+), 198 deletions(-) diff --git a/tardis/visualization/widgets/custom_abundance.py b/tardis/visualization/widgets/custom_abundance.py index 033f303ddac..2c39a4867e9 100644 --- a/tardis/visualization/widgets/custom_abundance.py +++ b/tardis/visualization/widgets/custom_abundance.py @@ -12,7 +12,7 @@ import tardis from tardis.io.model.readers.generic_readers import read_uniform_abundances -from tardis.util.base import quantity_linspace, is_valid_nuclide_or_elem +from tardis.util.base import quantity_linspace, is_valid_nuclide_or_elem, is_notebook from tardis.io.configuration.config_reader import Configuration from tardis.model import SimulationState from tardis.io.model.parse_density_configuration import ( @@ -1284,109 +1284,112 @@ def display(self, cmap="jet"): ipywidgets.widgets.widget_box.VBox A box that contains all the widgets in the GUI. """ - # --------------Combine widget components-------------- - self.box_editor = ipw.HBox( - [ - ipw.VBox(self.input_items), - ipw.VBox(self.checks, layout=ipw.Layout(margin="0 0 0 10px")), - ] - ) - - box_add_shell = ipw.HBox( - [ - self.input_v_start, - self.input_v_end, - self.btn_add_shell, - self.overwrite_warning, - ], - layout=ipw.Layout(margin="0 0 0 50px"), - ) - - box_head = ipw.HBox( - [self.dpd_shell_no, self.btn_prev, self.btn_next, box_add_shell] - ) + if not is_notebook(): + print("Please use a notebook to display the widget") + else: + # --------------Combine widget components-------------- + self.box_editor = ipw.HBox( + [ + ipw.VBox(self.input_items), + ipw.VBox(self.checks, layout=ipw.Layout(margin="0 0 0 10px")), + ] + ) - box_add_element = ipw.HBox( - [self.input_symb, self.btn_add_element, self.symb_warning], - layout=ipw.Layout(margin="0 0 0 80px"), - ) + box_add_shell = ipw.HBox( + [ + self.input_v_start, + self.input_v_end, + self.btn_add_shell, + self.overwrite_warning, + ], + layout=ipw.Layout(margin="0 0 0 50px"), + ) - help_note = ipw.HTML( - value="

* Select a checkbox " - "to lock the abundance of corresponding element.

" - "

On clicking the 'Normalize' " - "button, the locked abundance(s) will not be normalized." - "

", - indent=True, - ) + box_head = ipw.HBox( + [self.dpd_shell_no, self.btn_prev, self.btn_next, box_add_shell] + ) - self.abundance_note = ipw.HTML( - description="(The following abundances are for the innermost " - "shell in selected range.)", - layout=ipw.Layout(visibility="hidden"), - style={"description_width": "initial"}, - ) + box_add_element = ipw.HBox( + [self.input_symb, self.btn_add_element, self.symb_warning], + layout=ipw.Layout(margin="0 0 0 80px"), + ) - box_norm = ipw.HBox([self.btn_norm, self.norm_warning]) + help_note = ipw.HTML( + value="

* Select a checkbox " + "to lock the abundance of corresponding element.

" + "

On clicking the 'Normalize' " + "button, the locked abundance(s) will not be normalized." + "

", + indent=True, + ) - box_apply = ipw.VBox( - [ - ipw.Label(value="Apply abundance(s) to:"), - self.rbs_single_apply, - ipw.HBox( - [ - self.rbs_multi_apply, - self.irs_shell_range, - self.abundance_note, - ] - ), - ], - layout=ipw.Layout(margin="0 0 15px 50px"), - ) + self.abundance_note = ipw.HTML( + description="(The following abundances are for the innermost " + "shell in selected range.)", + layout=ipw.Layout(visibility="hidden"), + style={"description_width": "initial"}, + ) - box_features = ipw.VBox([box_norm, help_note]) - box_abundance = ipw.VBox( - [ - box_apply, - ipw.HBox([self.box_editor, box_features]), - box_add_element, - ] - ) - box_density = self.density_editor.display() + box_norm = ipw.HBox([self.btn_norm, self.norm_warning]) + + box_apply = ipw.VBox( + [ + ipw.Label(value="Apply abundance(s) to:"), + self.rbs_single_apply, + ipw.HBox( + [ + self.rbs_multi_apply, + self.irs_shell_range, + self.abundance_note, + ] + ), + ], + layout=ipw.Layout(margin="0 0 15px 50px"), + ) - main_tab = ipw.Tab([box_abundance, box_density]) - main_tab.set_title(0, "Edit Abundance") - main_tab.set_title(1, "Edit Density") + box_features = ipw.VBox([box_norm, help_note]) + box_abundance = ipw.VBox( + [ + box_apply, + ipw.HBox([self.box_editor, box_features]), + box_add_element, + ] + ) + box_density = self.density_editor.display() - hint = ipw.HTML( - value="Save model as file: " - ) - box_output = ipw.VBox( - [ - hint, - self.input_i_time_0, - ipw.HBox( - [self.input_path, self.btn_output, self.ckb_overwrite] - ), - ] - ) + main_tab = ipw.Tab([box_abundance, box_density]) + main_tab.set_title(0, "Edit Abundance") + main_tab.set_title(1, "Edit Density") - # Initialize the widget and plot colormap - self.plot_cmap = cmap - self.update_line_color() - self.read_abundance() - self.density_editor.read_density() + hint = ipw.HTML( + value="Save model as file: " + ) + box_output = ipw.VBox( + [ + hint, + self.input_i_time_0, + ipw.HBox( + [self.input_path, self.btn_output, self.ckb_overwrite] + ), + ] + ) - return ipw.VBox( - [ - self.tbs_scale, - self.fig, - box_head, - main_tab, - box_output, - self.error_view, - ] - ) + # Initialize the widget and plot colormap + self.plot_cmap = cmap + self.update_line_color() + self.read_abundance() + self.density_editor.read_density() + + return ipw.VBox( + [ + self.tbs_scale, + self.fig, + box_head, + main_tab, + box_output, + self.error_view, + ] + ) @error_view.capture(clear_output=True) def to_csvy(self, path, overwrite): diff --git a/tardis/visualization/widgets/line_info.py b/tardis/visualization/widgets/line_info.py index 7ae2d483c0f..e605e4e1679 100644 --- a/tardis/visualization/widgets/line_info.py +++ b/tardis/visualization/widgets/line_info.py @@ -10,7 +10,11 @@ import ipywidgets as ipw from tardis.analysis import LastLineInteraction -from tardis.util.base import species_tuple_to_string, species_string_to_tuple +from tardis.util.base import ( + species_tuple_to_string, + species_string_to_tuple, + is_notebook, +) from tardis.visualization.widgets.util import ( create_table_widget, TableSummaryLabel, @@ -668,68 +672,71 @@ def display(self): ipywidgets.Box Line info widget containing all component widgets """ - # Set widths of widgets - self.species_interactions_table.layout.width = "350px" - self.last_line_counts_table.layout.width = "450px" - self.total_packets_label.update_and_resize(0) - self.group_mode_dropdown.layout.width = "auto" - - # Attach event listeners to widgets - spectrum_trace = self.figure_widget.data[0] - spectrum_trace.on_selection(self._spectrum_selection_handler) - self.filter_mode_buttons.observe( - self._filter_mode_toggle_handler, names="index" - ) - self.species_interactions_table.on( - "selection_changed", self._species_intrctn_selection_handler - ) - self.group_mode_dropdown.observe( - self._group_mode_dropdown_handler, names="index" - ) + if not is_notebook(): + print("Please use a notebook to display the widget") + else: + # Set widths of widgets + self.species_interactions_table.layout.width = "350px" + self.last_line_counts_table.layout.width = "450px" + self.total_packets_label.update_and_resize(0) + self.group_mode_dropdown.layout.width = "auto" - selection_box_symbol = ( - "" - ) + # Attach event listeners to widgets + spectrum_trace = self.figure_widget.data[0] + spectrum_trace.on_selection(self._spectrum_selection_handler) + self.filter_mode_buttons.observe( + self._filter_mode_toggle_handler, names="index" + ) + self.species_interactions_table.on( + "selection_changed", self._species_intrctn_selection_handler + ) + self.group_mode_dropdown.observe( + self._group_mode_dropdown_handler, names="index" + ) - table_container_left = ipw.VBox( - [ - self.ui_control_description( - "Filter selected wavelength range " - f"( {selection_box_symbol} ) by" - ), - self.filter_mode_buttons, - self.species_interactions_table, - ], - layout=dict(margin="0px 15px"), - ) + selection_box_symbol = ( + "" + ) - table_container_right = ipw.VBox( - [ - self.ui_control_description("Group packet counts by"), - self.group_mode_dropdown, - self.last_line_counts_table, - self.total_packets_label.widget, - ], - layout=dict(margin="0px 15px"), - ) + table_container_left = ipw.VBox( + [ + self.ui_control_description( + "Filter selected wavelength range " + f"( {selection_box_symbol} ) by" + ), + self.filter_mode_buttons, + self.species_interactions_table, + ], + layout=dict(margin="0px 15px"), + ) - return ipw.VBox( - [ - self.figure_widget, - ipw.Box( - [ - table_container_left, - table_container_right, - ], - layout=dict( - display="flex", - align_items="flex-start", - justify_content="center", - height="420px", + table_container_right = ipw.VBox( + [ + self.ui_control_description("Group packet counts by"), + self.group_mode_dropdown, + self.last_line_counts_table, + self.total_packets_label.widget, + ], + layout=dict(margin="0px 15px"), + ) + + return ipw.VBox( + [ + self.figure_widget, + ipw.Box( + [ + table_container_left, + table_container_right, + ], + layout=dict( + display="flex", + align_items="flex-start", + justify_content="center", + height="420px", + ), ), - ), - ] - ) + ] + ) diff --git a/tardis/visualization/widgets/shell_info.py b/tardis/visualization/widgets/shell_info.py index 205d727d037..b71c8bb34db 100644 --- a/tardis/visualization/widgets/shell_info.py +++ b/tardis/visualization/widgets/shell_info.py @@ -2,7 +2,7 @@ from tardis.io.atom_data.atom_web_download import download_atom_data from tardis.util.base import ( atomic_number2element_symbol, - species_tuple_to_string, + species_tuple_to_string, is_notebook, ) from tardis.visualization.widgets.util import create_table_widget @@ -438,53 +438,56 @@ def display( ipywidgets.Box Shell info widget containing all component widgets """ - # CSS properties of the layout of shell info tables container - tables_container_layout = dict( - display="flex", - align_items="flex-start", - justify_content="space-between", - ) - tables_container_layout.update(layout_kwargs) + if not is_notebook(): + print("Please use a notebook to display the widget") + else: + # CSS properties of the layout of shell info tables container + tables_container_layout = dict( + display="flex", + align_items="flex-start", + justify_content="space-between", + ) + tables_container_layout.update(layout_kwargs) - # Setting tables' widths - self.shells_table.layout.width = shells_table_width - self.element_count_table.layout.width = element_count_table_width - self.ion_count_table.layout.width = ion_count_table_width - self.level_count_table.layout.width = level_count_table_width + # Setting tables' widths + self.shells_table.layout.width = shells_table_width + self.element_count_table.layout.width = element_count_table_width + self.ion_count_table.layout.width = ion_count_table_width + self.level_count_table.layout.width = level_count_table_width - # Attach event listeners to table widgets - self.shells_table.on( - "selection_changed", self.update_element_count_table - ) - self.element_count_table.on( - "selection_changed", self.update_ion_count_table - ) - self.ion_count_table.on( - "selection_changed", self.update_level_count_table - ) + # Attach event listeners to table widgets + self.shells_table.on( + "selection_changed", self.update_element_count_table + ) + self.element_count_table.on( + "selection_changed", self.update_ion_count_table + ) + self.ion_count_table.on( + "selection_changed", self.update_level_count_table + ) - # Putting all table widgets in a container styled with tables_container_layout - shell_info_tables_container = ipw.Box( - [ - self.shells_table, - self.element_count_table, - self.ion_count_table, - self.level_count_table, - ], - layout=ipw.Layout(**tables_container_layout), - ) - self.shells_table.change_selection([1]) + # Putting all table widgets in a container styled with tables_container_layout + shell_info_tables_container = ipw.Box( + [ + self.shells_table, + self.element_count_table, + self.ion_count_table, + self.level_count_table, + ], + layout=ipw.Layout(**tables_container_layout), + ) + self.shells_table.change_selection([1]) - # Notes text explaining how to interpret tables widgets' data - text = ipw.HTML( - "Frac. Ab. denotes Fractional Abundances (i.e all " - "values sum to 1)
W denotes Dilution Factor and " - "Rad. Temp. is Radiative Temperature (in K)" - ) + # Notes text explaining how to interpret tables widgets' data + text = ipw.HTML( + "Frac. Ab. denotes Fractional Abundances (i.e all " + "values sum to 1)
W denotes Dilution Factor and " + "Rad. Temp. is Radiative Temperature (in K)" + ) - # Put text horizontally before shell info container - shell_info_widget = ipw.VBox([text, shell_info_tables_container]) - return shell_info_widget + # Put text horizontally before shell info container + shell_info_widget = ipw.VBox([text, shell_info_tables_container]) + return shell_info_widget def shell_info_from_simulation(sim_model): From d2e1637862d7a7cb0be81337613a34bcbd93984e Mon Sep 17 00:00:00 2001 From: Shreyas Singh Date: Thu, 23 Mar 2023 02:28:37 +0530 Subject: [PATCH 2/5] Add mock objects in the tests for the function is_notebook --- tardis/tests/test_util.py | 9 +++++++++ tardis/visualization/widgets/custom_abundance.py | 4 +++- tardis/visualization/widgets/shell_info.py | 3 ++- .../visualization/widgets/tests/test_custom_abundance.py | 7 ++++++- tardis/visualization/widgets/tests/test_line_info.py | 6 +++++- tardis/visualization/widgets/tests/test_shell_info.py | 6 +++++- 6 files changed, 30 insertions(+), 5 deletions(-) diff --git a/tardis/tests/test_util.py b/tardis/tests/test_util.py index 8e5b7bdbd26..335f9442d14 100644 --- a/tardis/tests/test_util.py +++ b/tardis/tests/test_util.py @@ -30,6 +30,15 @@ def artis_abundances_fname(example_model_file_dir): return example_model_file_dir / "artis_abundances.dat" +@pytest.fixture(scope="session") +def monkeysession(): + """ + Creates a session-scoped fixture to be used to mock functions dependent on the user. + """ + with pytest.MonkeyPatch.context() as mp: + yield mp + + def test_malformed_species_error(): malformed_species_error = MalformedSpeciesError("He") assert malformed_species_error.malformed_element_symbol == "He" diff --git a/tardis/visualization/widgets/custom_abundance.py b/tardis/visualization/widgets/custom_abundance.py index 2c39a4867e9..51f76aee8ee 100644 --- a/tardis/visualization/widgets/custom_abundance.py +++ b/tardis/visualization/widgets/custom_abundance.py @@ -1291,7 +1291,9 @@ def display(self, cmap="jet"): self.box_editor = ipw.HBox( [ ipw.VBox(self.input_items), - ipw.VBox(self.checks, layout=ipw.Layout(margin="0 0 0 10px")), + ipw.VBox( + self.checks, layout=ipw.Layout(margin="0 0 0 10px") + ), ] ) diff --git a/tardis/visualization/widgets/shell_info.py b/tardis/visualization/widgets/shell_info.py index b71c8bb34db..811386be4ae 100644 --- a/tardis/visualization/widgets/shell_info.py +++ b/tardis/visualization/widgets/shell_info.py @@ -2,7 +2,8 @@ from tardis.io.atom_data.atom_web_download import download_atom_data from tardis.util.base import ( atomic_number2element_symbol, - species_tuple_to_string, is_notebook, + species_tuple_to_string, + is_notebook, ) from tardis.visualization.widgets.util import create_table_widget diff --git a/tardis/visualization/widgets/tests/test_custom_abundance.py b/tardis/visualization/widgets/tests/test_custom_abundance.py index bf467e283cd..d05586c8d4e 100644 --- a/tardis/visualization/widgets/tests/test_custom_abundance.py +++ b/tardis/visualization/widgets/tests/test_custom_abundance.py @@ -5,6 +5,7 @@ import numpy as np import numpy.testing as npt +from tardis.tests.test_util import monkeysession from tardis.visualization.widgets.custom_abundance import ( CustomAbundanceWidgetData, CustomYAML, @@ -30,7 +31,7 @@ def yml_data(example_configuration_dir: Path, atomic_dataset): @pytest.fixture(scope="module") -def caw(yml_data): +def caw(yml_data, monkeysession): """Fixture to contain a CustomAbundanceWidget instance generated from a YAML file tardis_configv1_verysimple.yml. @@ -40,6 +41,10 @@ def caw(yml_data): CustomAbundanceWidget generated from a YAML """ caw = CustomAbundanceWidget(yml_data) + monkeysession.setattr( + "tardis.visualization.widgets.custom_abundance.is_notebook", + lambda: True, + ) caw.display() return caw diff --git a/tardis/visualization/widgets/tests/test_line_info.py b/tardis/visualization/widgets/tests/test_line_info.py index 112ca1ee191..87686c3af29 100644 --- a/tardis/visualization/widgets/tests/test_line_info.py +++ b/tardis/visualization/widgets/tests/test_line_info.py @@ -4,6 +4,7 @@ from plotly.callbacks import Points, BoxSelector from tardis.visualization.widgets.line_info import LineInfoWidget from tardis.util.base import species_string_to_tuple +from tardis.tests.test_util import monkeysession @pytest.fixture(scope="class") @@ -141,12 +142,15 @@ class TestLineInfoWidgetEvents: None, # No selection of wavelength range ], ) - def liw_with_selection(self, simulation_verysimple, request): + def liw_with_selection(self, simulation_verysimple, request, monkeysession): """ Makes different wavelength range selection on figure (specified by params) after creating a LineInfoWidget object. """ liw = LineInfoWidget.from_simulation(simulation_verysimple) + monkeysession.setattr( + "tardis.visualization.widgets.line_info.is_notebook", lambda: True + ) # To attach event listeners to component widgets of line_info_widget _ = liw.display() diff --git a/tardis/visualization/widgets/tests/test_shell_info.py b/tardis/visualization/widgets/tests/test_shell_info.py index 0afefc5e854..7a99374dbc5 100644 --- a/tardis/visualization/widgets/tests/test_shell_info.py +++ b/tardis/visualization/widgets/tests/test_shell_info.py @@ -2,6 +2,7 @@ import numpy as np import pandas.testing as pdt +from tardis.tests.test_util import monkeysession from tardis.visualization.widgets.shell_info import ( BaseShellInfo, SimulationShellInfo, @@ -138,8 +139,11 @@ class TestShellInfoWidget: select_ion_num = 3 @pytest.fixture(scope="class") - def shell_info_widget(self, base_shell_info): + def shell_info_widget(self, base_shell_info, monkeysession): shell_info_widget = ShellInfoWidget(base_shell_info) + monkeysession.setattr( + "tardis.visualization.widgets.shell_info.is_notebook", lambda: True + ) # To attach event listeners to table widgets of shell_info_widget _ = shell_info_widget.display() return shell_info_widget From 5e16805463a643aecce28da8295a2a80dc04b0f9 Mon Sep 17 00:00:00 2001 From: shreyas3156 Date: Sat, 22 Apr 2023 14:09:22 +0530 Subject: [PATCH 3/5] Add test to raise for command-line calls and set default show_convergence_plots to False --- tardis/simulation/base.py | 39 +++++++++++-------- .../tools/tests/test_convergence_plot.py | 20 ++++++++++ 2 files changed, 43 insertions(+), 16 deletions(-) diff --git a/tardis/simulation/base.py b/tardis/simulation/base.py index 72abba91498..23e1df81daa 100644 --- a/tardis/simulation/base.py +++ b/tardis/simulation/base.py @@ -172,22 +172,29 @@ def __init__( ) if show_convergence_plots: - self.convergence_plots = ConvergencePlots( - iterations=self.iterations, **convergence_plots_kwargs - ) - - if "export_convergence_plots" in convergence_plots_kwargs: - if not isinstance( - convergence_plots_kwargs["export_convergence_plots"], bool - ): - raise TypeError( - "Expected bool in export_convergence_plots argument" - ) - self.export_convergence_plots = convergence_plots_kwargs[ - "export_convergence_plots" - ] + if not is_notebook(): + raise RuntimeError( + "Convergence Plots cannot be displayed in command-line. Set show_convergence_plots " + "to False." + ) else: - self.export_convergence_plots = False + self.convergence_plots = ConvergencePlots( + iterations=self.iterations, **convergence_plots_kwargs + ) + + if "export_convergence_plots" in convergence_plots_kwargs: + if not isinstance( + convergence_plots_kwargs["export_convergence_plots"], + bool, + ): + raise TypeError( + "Expected bool in export_convergence_plots argument" + ) + self.export_convergence_plots = convergence_plots_kwargs[ + "export_convergence_plots" + ] + else: + self.export_convergence_plots = False self._callbacks = OrderedDict() self._cb_next_id = 0 @@ -633,7 +640,7 @@ def from_config( config, packet_source=None, virtual_packet_logging=False, - show_convergence_plots=True, + show_convergence_plots=False, show_progress_bars=True, **kwargs, ): diff --git a/tardis/visualization/tools/tests/test_convergence_plot.py b/tardis/visualization/tools/tests/test_convergence_plot.py index 00043cb7837..e62bb0e988c 100644 --- a/tardis/visualization/tools/tests/test_convergence_plot.py +++ b/tardis/visualization/tools/tests/test_convergence_plot.py @@ -1,5 +1,9 @@ """Tests for Convergence Plots.""" +from copy import deepcopy + import pytest + +from tardis import run_tardis from tardis.visualization.tools.convergence_plot import ( ConvergencePlots, transition_colors, @@ -205,3 +209,19 @@ def test_override_plot_parameters(convergence_plots): assert ( convergence_plots.plasma_plot["layout"]["xaxis2"]["showgrid"] == False ) + + +def test_convergence_plot_command_line( + config_verysimple, atomic_dataset, monkeysession +): + monkeysession.setattr( + "tardis.simulation.base.is_notebook", + lambda: False, + ) + atomic_data = deepcopy(atomic_dataset) + with pytest.raises(RuntimeError): + run_tardis( + config_verysimple, + atom_data=atomic_data, + show_convergence_plots=True, + ) From ed823716a4d843514eee13cd6b5dc16e8c254f15 Mon Sep 17 00:00:00 2001 From: shreyas3156 Date: Sun, 23 Apr 2023 16:46:25 +0530 Subject: [PATCH 4/5] Add import statement --- tardis/visualization/tools/tests/test_convergence_plot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tardis/visualization/tools/tests/test_convergence_plot.py b/tardis/visualization/tools/tests/test_convergence_plot.py index e62bb0e988c..79751b15c72 100644 --- a/tardis/visualization/tools/tests/test_convergence_plot.py +++ b/tardis/visualization/tools/tests/test_convergence_plot.py @@ -2,7 +2,7 @@ from copy import deepcopy import pytest - +from tardis.tests.test_util import monkeysession from tardis import run_tardis from tardis.visualization.tools.convergence_plot import ( ConvergencePlots, From 6adf924808d81247ad4b19583b4edf9c60d37aa0 Mon Sep 17 00:00:00 2001 From: Atharva Arya Date: Wed, 13 Mar 2024 19:07:47 +0530 Subject: [PATCH 5/5] Format file using black --- tardis/visualization/widgets/custom_abundance.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tardis/visualization/widgets/custom_abundance.py b/tardis/visualization/widgets/custom_abundance.py index 51f76aee8ee..8d6d3b6c952 100644 --- a/tardis/visualization/widgets/custom_abundance.py +++ b/tardis/visualization/widgets/custom_abundance.py @@ -12,7 +12,11 @@ import tardis from tardis.io.model.readers.generic_readers import read_uniform_abundances -from tardis.util.base import quantity_linspace, is_valid_nuclide_or_elem, is_notebook +from tardis.util.base import ( + quantity_linspace, + is_valid_nuclide_or_elem, + is_notebook, +) from tardis.io.configuration.config_reader import Configuration from tardis.model import SimulationState from tardis.io.model.parse_density_configuration import (