Skip to content

Commit

Permalink
Fix minor bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
yuyizheng1112 authored and James Gillanders committed Aug 20, 2021
1 parent 4e9acec commit 21d74e1
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 67 deletions.
1 change: 1 addition & 0 deletions tardis/visualization/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@
shell_info_from_hdf,
)
from tardis.visualization.widgets.line_info import LineInfoWidget
from tardis.visualization.widgets.custom_abundance import CustomAbundanceWidget
from tardis.visualization.tools.sdec_plot import SDECPlotter
149 changes: 82 additions & 67 deletions tardis/visualization/widgets/custom_abundance.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,32 +220,33 @@ def create_widgets(self):
value=1,
layout=ipw.Layout(width="160px")
)
self.dpd_shell_no.observe(self.dpd_shell_no_eventhandler, "name")
self.dpd_shell_no.observe(self.dpd_shell_no_eventhandler, "value")
self.btn_prev = ipw.Button(icon="chevron-left",
disabled=True,
layout=ipw.Layout(width="30px", height="30px")
)
self.btn_prev.on_click(self.on_btn_prev)
self.btn_next = ipw.Button(icon="chevron-right",
layout=ipw.Layout(width="30px", height="30px")
)
self.btn_next.on_click(self.on_btn_next)

self.checks = [
ipw.Checkbox(
indent=False,
layout=ipw.Layout(
width="30px",
margin="0 0 0 5px"
)
) for element in self.elements]
self.input_items = [ipw.BoundedFloatText(min=0,
max=1,
step=0.01,
description=element)
for element in self.elements]
for i in self.no_of_elements:
for i in range(self.no_of_elements):
self.input_items[i].observe(self.input_item_eventhandler, "value")
self.input_items[i].index = i
self.checks[i].observe(self.check_handler, "value")
self.checks[i].observe(self.check_eventhandler, "value")
self.checks[i].index = i

self.btn_norm = ipw.Button(description="Normalize",
Expand All @@ -269,7 +270,7 @@ def create_widgets(self):
description="Element: ",
style={"description_width": "initial"},
placeholder="symbol",
layout=ipw.Layout(width="120px"),
layout=ipw.Layout(width="125px"),
)
self.input_symb.observe(self.input_symb_eventhandler, "value")
self.btn_add_element = ipw.Button(
Expand Down Expand Up @@ -302,17 +303,20 @@ def create_widgets(self):

self.btn_add_shell = ipw.Button(
icon="plus-square",
description=" Add New Shell",
description="Add",
disabled=True,
layout=ipw.Layout(margin="0 0 0 10px")
layout=ipw.Layout(
width="90px",
# margin="0 0 0 10px"
)
)
self.btn_add_shell.on_click(self.on_btn_add_shell)
self.input_v_start = ipw.FloatText(
min=0,
description="Velocity range (km/s): ",
description="Add shell(s) with velocity range (km/s): ",
style={"description_width": "initial"},
layout=ipw.Layout(
width="230px"
width="330px",
)
)
self.input_v_end = ipw.FloatText(
Expand Down Expand Up @@ -357,7 +361,7 @@ def create_widgets(self):
style={"description_width": "initial"},
value="Linear"
)
self.tbs_scale.observe(self.tbs_scale_handler, "value")
self.tbs_scale.observe(self.tbs_scale_eventhandler, "value")


def update_input_item_value(self, index, value):
Expand Down Expand Up @@ -387,23 +391,24 @@ def read_abundance(self):
# Ensure the sum of locked elements less than 1
def bound_locked_sum_to_1(self, index):
"""Ensure the sum of locked abundances is no more than 1. If the
locked sum is more than 1, adjust the changed value to the maximum
with the sum is no more than 1.
locked sum is more than 1, calculate the maximum with the sum no
more than 1 and return it.
Parameters
----------
index : int
The index of the widget in `input_items` widget list.
"""
locked_mask = np.array(self.checked_list)
back_value = self.abundance[index, self.shell_no-1] # abundance value in back end (DataFrame)
back_value = self.abundance.iloc[index, self.shell_no-1] # abundance value in back end (DataFrame)
front_value = self.input_items[index].value # abundance value in front end (widget)
locked_sum = self.abundance.loc[locked_mask, self.shell_no-1].sum() - back_value + front_value

if locked_sum > 1:
new = 1 - (locked_sum - back_value)
self.abundance[index, self.shell_no-1] = new
self.update_input_item_value(self, index, new)
new = 1 - (locked_sum - front_value)
self.abundance.iloc[index, self.shell_no-1] = new
self.update_input_item_value(index, new)
self.fig.data[index+2].y = self.abundance.iloc[index]

def update_front(self):
"""Update checkbox widgets, input widgets and plot in the front
Expand All @@ -416,8 +421,7 @@ def update_front(self):
self.density_editor.read_density()
with self.fig.batch_update():
# Change line diagonal
self.fig.layout.shapes[0].x0 = self.velocity[self.shell_no].value
self.fig.layout.shapes[0].x1 = self.velocity[self.shell_no].value
self.fig.data[0].x = [self.velocity[self.shell_no].value]*2

def overwrite_existing_shells(self, v_0, v_1):
"""Judge whether the existing shell(s) will be overwritten when
Expand Down Expand Up @@ -446,8 +450,13 @@ def overwrite_existing_shells(self, v_0, v_1):
else:
return False

def add_shell(self):
def on_btn_add_shell(self, obj):
"""Add new shell with given boundary velocities.
Parameters
----------
obj : ipywidgets.widgets.widget_button.Button
The clicked button instance.
"""
v_start = self.input_v_start.value
v_end = self.input_v_end.value
Expand Down Expand Up @@ -495,11 +504,11 @@ def add_shell(self):

# Update data and x axis in plot.
with self.fig.batch_update():
self.fig.data[0].x = self.velocity[1:]
self.fig.data[0].y = self.density[1:]
self.fig.data[1].x = self.velocity[1:]
self.fig.data[1].y = self.density[1:]
for i in range(self.no_of_elements):
self.fig.data[i+1].x = self.velocity[1:]
self.fig.data[i+1].y = self.abundance.iloc[i]
self.fig.data[i+2].x = self.velocity[1:]
self.fig.data[i+2].y = self.abundance.iloc[i]

self.dpd_shell_no.options = list(range(1, self.no_of_shells+1))
self.shell_no = start_index + 1
Expand Down Expand Up @@ -552,16 +561,16 @@ def input_item_eventhandler(self, obj):

if is_locked:
self.bound_locked_sum_to_1(item_index)

self.abundance.iloc[item_index, self.shell_no-1] = obj.new

if math.isclose(self.abundance.iloc[:, self.shell_no-1].sum(), 1):
self.norm_warning.layout.visibility = "hidden"
else:
self.norm_warning.layout.visibility = "visible"

self.abundance.iloc[item_index, self.shell_no-1] = obj.owner.value

# Update plot
self.fig.data[item_index+1].y = self.abundance.iloc[item_index]
self.fig.data[item_index+2].y = self.abundance.iloc[item_index]

def check_eventhandler(self, obj):
"""The callback for the item in `checks` widget list.
Expand Down Expand Up @@ -657,6 +666,12 @@ def input_symb_eventhandler(self, obj):
self.btn_add_element.disabled = True
return

if element_symbol_string in self.elements:
self.symb_warning.layout.visibility = "visible"
self.btn_add_element.disabled = True
self.symb_warning.readout = "Already exists!"
return

try:
if nucname.iselement(element_symbol_string) or nucname.isnuclide(element_symbol_string):
self.symb_warning.layout.visibility = "hidden"
Expand All @@ -668,11 +683,7 @@ def input_symb_eventhandler(self, obj):

self.symb_warning.layout.visibility = "visible"
self.btn_add_element.disabled = True

if element_symbol_string in self.elements:
self.symb_warning.readout = "Already exists!"
else:
self.symb_warning.readout = "invalid"
self.symb_warning.readout = "invalid"

def on_btn_add_element(self, obj):
"""The callback for `btn_add_element` button. Add new element and
Expand Down Expand Up @@ -749,7 +760,7 @@ def on_btn_apply(self, obj):
# update plot
update_list = np.where(applied_mask == True)[0]
for i in update_list:
self.fig.data[i+1].y = self.abundance.iloc[i]
self.fig.data[i+2].y = self.abundance.iloc[i]

def input_v_eventhandler(self, obj):
"""The callback for `input_v` widget. Judge whether the input
Expand Down Expand Up @@ -796,6 +807,20 @@ def generate_abundance_density_plot(self):
self.fig = go.FigureWidget()
title = "Abundance/Density vs Velocity"
data = self.abundance.T

# Line Diagonal
self.fig.add_trace(
go.Scatter(
x=[self.velocity[1].value]*2,
y=(0, 1),
mode="lines",
name="Selected shell",
line=dict(
color="Red",
dash="dot",
)
)
)

self.fig.add_trace(
go.Scatter(
Expand Down Expand Up @@ -832,20 +857,6 @@ def generate_abundance_density_plot(self):
exponentformat="e",
overlaying="y",
side="right"),
shapes=[ # Line Diagonal
dict(
type="line",
yref="y",
y0=0,
y1=1,
xref="x",
x0=self.velocity[1].value,
x1=self.velocity[1].value,
line=dict(
color="Red",
dash="dot",
)
)],
height=500,
title=title,
hovermode="closest",
Expand All @@ -864,13 +875,15 @@ def display(self):
ipywidgets.widgets.widget_box.VBox
A box that contains all the widgets in the GUI.
"""
box_head = ipw.HBox([self.dpd_shell_no, self.btn_prev, self.btn_next])
box_editor = ipw.HBox([ipw.VBox(self.input_items), ipw.VBox(self.checks, layout=ipw.Layout(margin="0 0 0 10px"))])

box_editor = ipw.HBox([ipw.VBox(self.input_items), ipw.VBox(self.checks)])

box_add_shell = ipw.HBox([self.input_v_start, self.input_v_end, self.btn_add_shell, self.overwrite_warning])
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])

box_add_element = ipw.VBox([ipw.HBox([self.input_symb, self.btn_add_element]), self.symb_warning], layout=ipw.Layout(margin="0 0 0 100px"))
box_add_element = ipw.HBox([self.input_symb, self.btn_add_element, self.symb_warning], layout=ipw.Layout(margin="0 0 0 80px"))

help_note = ipw.HTML(
value="<p style=\"text-indent: 40px\"><b>Click the checkbox</b> to </p> <p style=\"text-indent: 40px\"> 1) lock the abundance you don't want to normalize </p> <p style=\"text-indent: 40px\"> 2) apply the abundance to other shells.</p>",
Expand All @@ -883,22 +896,22 @@ def display(self):
layout=ipw.Layout(margin="5px 0 0 50px"))

box_features = ipw.VBox([help_note, box_norm, box_apply])
box_abundance = ipw.VBox([box_add_element, ipw.HBox([box_editor, box_features])])
box_abundance = ipw.VBox([ipw.HBox([box_editor, box_features]), box_add_element])
box_density = self.density_editor.display()

main_tab = ipw.Tab([box_abundance, box_density])
main_tab.set_title(0, "Edit Abundance")
main_tab.set_title(1, "Edit Density")

box_output = ipw.VBox([self.input_i_time_0, self.input_d_time_0, ipw.HBox([self.input_path, self.btn_output, self.ckb_overwrite])])
hint = ipw.HTML(value="<b><font size='3'>Save model as file: </font></b>")
box_output = ipw.VBox([hint, self.input_i_time_0, self.input_d_time_0, ipw.HBox([self.input_path, self.btn_output, self.ckb_overwrite])])
self.read_abundance()
self.density_editor.read_density()

return ipw.VBox([
self.tbs_scale,
self.fig,
box_head,
box_add_shell,
main_tab,
box_output,
self.error_view
Expand All @@ -920,7 +933,7 @@ def to_csvy(self, path, overwrite):
"The file already exists. Click the 'overwrite' checkbox to overwrite it."
)
else:
self.self.write_yaml_portion(path)
self.write_yaml_portion(path)
self.write_csv_portion(path)

@error_view.capture(clear_output=True)
Expand Down Expand Up @@ -1087,8 +1100,8 @@ def from_yml(cls, fpath):

velocity = model.velocity
density = model.homologous_density.density_0
abundance = model.abundance
isotope_abundance = model.isotope_abundance
abundance = model.raw_abundance
isotope_abundance = model.raw_isotope_abundance

# Combine elements and isotopes to one DataFrame
abundance["mass_number"] = ""
Expand Down Expand Up @@ -1250,12 +1263,12 @@ def create_widgets(self):

# Formula to compute density profile
form_exp = ipw.HTMLMath(
description="Exponential: ",
value=r"$$\rho = \rho_0 \times \exp \left( -\frac{v}{v_0} \right)$$"
value=r"$$\rho = \rho_0 \times \exp \left( -\frac{v}{v_0} \right)$$",
layout=ipw.Layout(margin="0 0 0 100px")
)
form_pow = ipw.HTMLMath(
description="Power Law: ",
value=r"$$\rho = \rho_0 \times \left( \frac{v}{v_0} \right)^n$$"
value=r"$$\rho = \rho_0 \times \left( \frac{v}{v_0} \right)^n$$",
layout=ipw.Layout(margin="0 0 0 100px")
)

self.exp_box = ipw.VBox([
Expand Down Expand Up @@ -1289,10 +1302,10 @@ def input_d_eventhandler(self, obj):
"""
if self._trigger:
new_value = obj.new
self.d[self.shell_no] = new_value
self.d[self.shell_no] = new_value * self.d.unit

# update plot
self.fig.data[0].y = self.d[1:]
self.fig.data[1].y = self.d[1:]

dtype_out = ipw.Output()

Expand All @@ -1313,11 +1326,11 @@ def dpd_dtype_eventhandler(self, obj):
type parameters.
"""
if obj.new == "uniform":
return self.uniform_box
display(self.uniform_box)
elif obj.new == "exponential":
return self.exp_box
display(self.exp_box)
elif obj.new == "power_law":
return self.pow_box
display(self.pow_box)

def on_btn_calculate(self, obj):
"""The callback for `btn_calculate` button. Calculate density
Expand Down Expand Up @@ -1368,8 +1381,10 @@ def display(self):
ipywidgets.widgets.widget_box.VBox
A box that contains all the widgets in the GUI.
"""
hint1 = ipw.HTML(value="<font size='3'>1) Edit density of the selected shell:</font>")
hint2 = ipw.HTML(value="<font size='3'>2) Edit densities for all shells:</font>")
d_box = ipw.HBox(
[self.input_d, ipw.Label(value="g/cm^3")],
layout=ipw.Layout(margin="0 0 20px 0")
)
return ipw.VBox([d_box, self.dpd_dtype, self.dtype_out, self.btn_calculate])
return ipw.VBox([hint1, d_box, hint2, self.dpd_dtype, self.dtype_out, self.btn_calculate])

0 comments on commit 21d74e1

Please sign in to comment.