Interactive web-based user interface for the CMB-S4 reference simulation tool
See the Documentation
If your browser doesn't visualize the widget input boxes, try reloading the page and disable your adblocker.
For support requests, open an issue on the s4_design_sim_tool
repository
import ipywidgets as widgets
from IPython.display import display
w = {}
for emission in ["foreground_emission", "CMB_unlensed", "CMB_lensing_signal"]:
w[emission] = widgets.BoundedFloatText(
value=1,
min=0,
max=1,
step=0.01,
description='Weight:',
disabled=False
)
emission = "CMB_tensor_to_scalar_ratio"
w[emission] = widgets.BoundedFloatText(
value=3e-3,
min=0,
max=1,
step=1e-5,
description=f'r:',
disabled=False
)
display(w["foreground_emission"])
display(w["CMB_unlensed"])
CMB lensing signal
CMB lensed - CMB unlensed:
- 1 for lensed CMB
- 0 for unlensed CMB
>0, <1
for residual after de-lensing
For the case of partial de-lensing, consider that lensing is a non-linear and this is a very rough approximation, still it could be useful in same cases, for example low-ell BB modes.
display(w["CMB_lensing_signal"])
display(w["CMB_tensor_to_scalar_ratio"])
w["total_experiment_length_years"] = widgets.BoundedFloatText(
value=7,
min=0,
max=15,
step=0.1,
description='Years:',
disabled=False
)
display(w["total_experiment_length_years"])
w["observing_efficiency"] = widgets.BoundedFloatText(
value=0.2,
min=0,
max=1,
step=0.01,
description='Efficiency:',
disabled=False
)
display(w["observing_efficiency"])
w["number_of_splits"] = widgets.BoundedIntText(
value=1,
min=1,
max=7,
step=1,
description='Splits:',
disabled=False
)
display(w["number_of_splits"])
import toml
config = toml.load("s4_design.toml")
def define_check_sum(telescope_widgets, max_tubes):
def check_sum(_):
total_tubes = sum([w.value for w in telescope_widgets[1:1+4]])
telescope_widgets[0].value = total_tubes == max_tubes
return check_sum
telescopes = {"SAT":{}, "LAT":{}}
for telescope, tubes in config["telescopes"]["SAT"].items():
telescopes["SAT"][telescope] = [widgets.Valid(
value=True, description=telescope, layout=widgets.Layout(width='120px')
)]
telescope_check = define_check_sum(telescopes["SAT"][telescope], 3)
for k,v in tubes.items():
if k == "site":
wid = widgets.Dropdown(
options=['Pole', 'Chile'],
value=v,
description=k,
disabled=False, layout=widgets.Layout(width='150px')
)
elif k == "years":
wid = widgets.BoundedFloatText(
value=v,
min=0,
max=20,
step=0.1,
description='years',
disabled=False, layout=widgets.Layout(width='130px')
)
else:
wid = widgets.BoundedIntText(
value=v,
min=0,
max=3,
step=1,
description=k,
disabled=False, layout=widgets.Layout(width='130px')
)
wid.observe(telescope_check)
telescopes["SAT"][telescope].append(wid)
for k, v in telescopes["SAT"].items():
display(widgets.HBox(v))
for telescope, tubes in config["telescopes"]["LAT"].items():
telescopes["LAT"][telescope] = [widgets.Valid(
value=True, description=telescope, layout=widgets.Layout(width='120px')
)]
telescope_check = define_check_sum(telescopes["LAT"][telescope], 19)
for k,v in tubes.items():
if k == "site":
wid = widgets.Dropdown(
options=['Pole', 'Chile'],
value=v,
description=k,
disabled=False, layout=widgets.Layout(width='150px')
)
elif k == "years":
wid = widgets.BoundedFloatText(
value=v,
min=0,
max=20,
step=0.1,
description='years',
disabled=False, layout=widgets.Layout(width='130px')
)
else:
wid = widgets.BoundedIntText(
value=v,
min=0,
max=19,
step=1,
description=k,
disabled=False, layout=widgets.Layout(width='130px')
)
wid.observe(telescope_check)
telescopes["LAT"][telescope].append(wid)
for k, v in telescopes["LAT"].items():
display(widgets.HBox(v))
import toml
toml_decoder = toml.decoder.TomlDecoder()
toml_encoder = toml.TomlPreserveInlineDictEncoder()
def generate_toml():
output_config = {}
for section in ["sky_emission", "experiment"]:
output_config[section] = {}
for k in config[section]:
output_config[section][k] = w[k].value
output_config["telescopes"] = {"SAT":{}, "LAT":{}}
for t in ["SAT", "LAT"]:
for telescope, tubes in telescopes[t].items():
output_config["telescopes"][t][telescope] = toml_decoder.get_empty_inline_table()
for tube_type in tubes[1:]:
output_config["telescopes"][t][telescope][tube_type.description] = tube_type.value
if tube_type.description == "years":
output_config["telescopes"][t][telescope][tube_type.description] = int(tube_type.value)
return toml.dumps(output_config, encoder=toml_encoder)
from s4_design_sim_tool.cli import md5sum_string, S4RefSimTool
from pathlib import Path
import os
output_location = os.environ.get("S4REFSIMTOOL_OUTPUT_URL", "")
button = widgets.Button(
description='Generate TOML',
disabled=False,
button_style='info', # 'success', 'info', 'warning', 'danger' or ''
tooltip='Click me',
icon='check'
)
output_label = widgets.HTML(value="")
output = widgets.Output(layout={'border': '1px solid black'})
display(button, output_label, output)
def on_button_clicked(b):
output.clear_output()
toml_string = generate_toml()
md5sum = md5sum_string(toml_string)
output_path = Path("output") / md5sum
output_label.value = ""
if output_path.exists():
output_label.value = "This exact CMB-S4 configuration has <b>already been executed</b><br />" + \
f"<a href='{output_location}/output/{md5sum}' target='blank'><button class='p-Widget jupyter-widgets jupyter-button widget-button mod-success'>Access the maps </button></a>"
output_label.value += "<p>TOML file preview:</p>"
with output:
print(toml_string)
button.on_click(on_button_clicked)
import ipywidgets as widgets
import logging
class OutputWidgetHandler(logging.Handler):
""" Custom logging handler sending logs to an output widget """
def __init__(self, *args, **kwargs):
super(OutputWidgetHandler, self).__init__(*args, **kwargs)
layout = {
'width': '100%',
'height': '500px',
'border': '1px solid black'
}
self.out = widgets.Output(layout=layout)
def emit(self, record):
""" Overload of logging.Handler method """
formatted_record = self.format(record)
new_output = {
'name': 'stdout',
'output_type': 'stream',
'text': formatted_record+'\n'
}
self.out.outputs = (new_output, ) + self.out.outputs
def show_logs(self):
""" Show the logs """
display(self.out)
def clear_logs(self):
""" Clear the current logs """
self.out.clear_output()
logger = logging.root
handler = OutputWidgetHandler()
handler.setFormatter(logging.Formatter('%(asctime)s - [%(levelname)s] %(message)s'))
logger.addHandler(handler)
logger.setLevel(logging.INFO)
def run_simulation(toml_filename, md5sum):
output_path = toml_filename.parents[0]
sim = S4RefSimTool(toml_filename, output_folder=output_path)
sim.run(channels="all", sites=["Pole", "Chile"])
logger.info("Create the wget script")
create_wget_script(output_path, output_location)
run_button = widgets.Button(
description='Create the maps',
disabled=False,
button_style='danger', # 'success', 'info', 'warning', 'danger' or ''
tooltip='Click me',
icon='check'
)
run_output_label = widgets.HTML(value="")
handler.clear_logs()
display(run_button, run_output_label, handler.out)
def on_run_button_clicked(_):
run_button.disabled = True
toml_string = generate_toml()
md5sum = md5sum_string(toml_string)
output_path = Path("output") / md5sum
if output_path.exists():
logger.error("This configuration has already been executed")
run_button.disabled = False
return
output_path.mkdir(parents=True, exist_ok=True)
toml_filename = output_path / "config.toml"
with open(toml_filename, "w") as f:
f.write(toml_string)
run_output_label.value = "<p> The simulation has been launched, see the logs below, access the TOML configuration file and the maps as they are created clicking on the button </p>" + \
f"<a href='{output_location}/output/{md5sum}' target='blank'><button class='p-Widget jupyter-widgets jupyter-button widget-button mod-success'>Access the maps </button></a>"
run_simulation(toml_filename, md5sum)
run_button.disabled = False
run_button.on_click(on_run_button_clicked)