Skip to content

Commit

Permalink
Grotrian Diagram Plot Appearance (#2313)
Browse files Browse the repository at this point in the history
* Grotrian diagram mockup 0

* Use atomic data to get energy levels

* Get line data from simulation object using LastLineInteraction class

* Remove transition where start and end (merged) levels is the same

* Refactor to GrotrianWidget class

* Add hovertext and colorbar

* Fix NUM_SHELLS variable

* Convert code into modular format

* Normalize wavelength by min and max value of the selected ion, instead of global min and max

* Create APIs for setting plot wavelength range manually

* Make y-axis linear in level_number instead of level_energy

* Rename num_electrons to standard_log_num_electrons while building plot

* Stardardize level population numbers

* Fix stardardization division by zero if only one element present in data

* Fix roman notation of ion number

* Display ground level too

* Change level populations to scientific notation in hovertext

* Put Angstrom symbol in colorbar instead of full name

* Standardize num_electrons using a common range for both excitation and de-excitation lines

* Fix the problem of arrows not touching the levels. (Used add_traces for arrows instead of add_annotation)

* Refactor duplicated code logic

* Put hoverinfo on transition arrows

* Put standardization logic into compute functions instead of draw functions

* Add width scale for level populations

* Format electron count to be an int instead of float in hovertext

* Wavelength range in colorbar should be confined to the displayed transitions only by default

* Set default colorscale to Rainbow for wavelengths

* Allow user to set atomic number and ion number simultaneously

* Handle ground state transitions correctly. Display dashed lines for levels with no level population

* Add basic docstrings

* Scientific formatting for level energies

* Display level populations based on supernova zone

* Put relative x-coordinate

* Add width scale for transition arrow widths

* Change y-axis from level number to log energies

* Minor margin changes

* Disable zooming

* Move width references to the left and colorbar to the right

* Refactor code. Remove duplication and hardcodings

* Add in/out last line interaction shell ids for real and virtual packets

* Add API for filtering data by supernova shell

* Add selected shell in plot title

* Do not handle last_line_interaction_in_shell_id and last_line_interaction_out_shell_id separately

* Do not reset custom wavelength range when the shell is changed

* Sync mockup notebook with master

* Fixed plot width and reference bars

* Added docstrings for remaining methods

* Added log option for y-scale

* Resolve Black issue

* Fix docstrings and make variable names more informative

* - Renamed 'colorscale' to 'cmapname'
- Allow 'colorscale' to be changed by user
- Fixed the access specifiers of editable attributes vs non-editable attributes

* Force user to set ion explicitly before plotting

* Add information for the configurable attributes in the class docstring

* Remove hardcoding in the unit conversion for level energies

* Fix arrowhead issue in VSCode

* Display info message that wavelengths will be reset when ion changes

* Add ability to change level_diff_threshold, max_levels, and filter_mode

* Added default parameter values in docstrings and updated comments

* Make all setters atomic operations
  • Loading branch information
AyushiDaksh authored Jul 18, 2023
1 parent dfa1366 commit bc367e6
Show file tree
Hide file tree
Showing 3 changed files with 2,425 additions and 12 deletions.
56 changes: 44 additions & 12 deletions tardis/analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import numpy as np
import pandas as pd

INVALID_ION_ERROR_MSG = "Atomic number, ion_number pair not present in model"


class LastLineInteraction(object):
@classmethod
Expand Down Expand Up @@ -86,26 +88,53 @@ def atomic_number(self):

@atomic_number.setter
def atomic_number(self, value):
self._atomic_number = value
self.update_last_interaction_filter()
old_atomic_number = self._atomic_number
try:
self._atomic_number = value
self.update_last_interaction_filter()
except:
self._atomic_number = old_atomic_number
raise ValueError(INVALID_ION_ERROR_MSG)

@property
def ion_number(self):
return self._ion_number

@ion_number.setter
def ion_number(self, value):
self._ion_number = value
self.update_last_interaction_filter()
old_ion_number = self._ion_number
try:
self._ion_number = value
self.update_last_interaction_filter()
except:
self._ion_number = old_ion_number
raise ValueError(INVALID_ION_ERROR_MSG)

def set_ion(self, atomic_number, ion_number):
old_atomic_number = self._atomic_number
old_ion_number = self._ion_number
try:
self._atomic_number = atomic_number
self._ion_number = ion_number
self.update_last_interaction_filter()
except:
self._atomic_number = old_atomic_number
self._ion_number = old_ion_number
raise ValueError(INVALID_ION_ERROR_MSG)

@property
def shell(self):
return self._shell

@shell.setter
def shell(self, value):
self._shell = value
self.update_last_interaction_filter()
old_shell = self._shell
try:
self._shell = value
self.update_last_interaction_filter()
except:
self._shell = old_shell
raise ValueError("Invalid shell number")

def update_last_interaction_filter(self):
if self.packet_filter_mode == "packet_out_nu":
Expand Down Expand Up @@ -137,29 +166,32 @@ def update_last_interaction_filter(self):
self.last_line_interaction_shell_id == self.shell
)

self.last_line_in = self.lines.iloc[
last_line_in = self.lines.iloc[
self.last_line_interaction_in_id[packet_filter]
]
self.last_line_out = self.lines.iloc[
last_line_out = self.lines.iloc[
self.last_line_interaction_out_id[packet_filter]
]

if self.atomic_number is not None:
self.last_line_in = self.last_line_in.xs(
last_line_in = last_line_in.xs(
self.atomic_number, level="atomic_number", drop_level=False
)
self.last_line_out = self.last_line_out.xs(
last_line_out = last_line_out.xs(
self.atomic_number, level="atomic_number", drop_level=False
)

if self.ion_number is not None:
self.last_line_in = self.last_line_in.xs(
last_line_in = last_line_in.xs(
self.ion_number, level="ion_number", drop_level=False
)
self.last_line_out = self.last_line_out.xs(
last_line_out = last_line_out.xs(
self.ion_number, level="ion_number", drop_level=False
)

self.last_line_in = last_line_in
self.last_line_out = last_line_out

last_line_in_count = self.last_line_in.line_id.value_counts()
last_line_out_count = self.last_line_out.line_id.value_counts()

Expand Down
Loading

0 comments on commit bc367e6

Please sign in to comment.