예제 #1
0
    def ion_count(self, atomic_num, shell_num):
        """Generates fractional abundance of ions of a specific element and
        shell, in a form that can be used by a table widget

        Parameters
        ----------
        atomic_num : int
            Atomic number of element
        shell_num : int
            Shell number (note: starts from 1, not 0 which is what simulation
            model use)

        Returns
        -------
        pandas.DataFrame
            Dataframe containing ion specie and fractional abundance for a
            specific element, against each ion number
        """
        ion_num_density = self.ion_number_density[shell_num - 1].loc[atomic_num]
        element_num_density = self.number_density.loc[atomic_num, shell_num - 1]
        ion_count_data = ion_num_density / element_num_density  # Normalization
        ion_count_data.index.name = "Ion"
        ion_count_data.fillna(0, inplace=True)
        return pd.DataFrame(
            {
                "Species": ion_count_data.index.map(
                    lambda x: species_tuple_to_string((atomic_num, x))
                ),
                "Frac. Ab. (Z={})".format(atomic_num): ion_count_data.map(
                    "{:.6e}".format
                ),
            }
        )
예제 #2
0
    def get_last_line_counts(
        self,
        selected_species,
        filter_mode=FILTER_MODES[0],
        group_mode=GROUP_MODES[0],
    ):
        """
        Get packet counts of each last line interaction of a species.

        Parameters
        ----------
        selected_species : str
            Valid symbol of a species (e.g Si II) selected from the species
            data returned by :code:`get_species_interactions` (see Notes section)
        filter_mode : str, optional
            Filter mode of the LastLineInteraction object to use for fetching
            the data of last lines interacted (more details in Notes section).
            Allowed values are given by the class variable :code:`FILTER_MODES`
            (default value is :code:`FILTER_MODES[0]`)
        group_mode : str, optional
            Group mode to use for grouping last line interactions by excitation
            lines, de-excitation lines or both. Allowed values are given by the
            class variable :code:`GROUP_MODES` (default value is
            :code:`GROUP_MODES[0]` i.e. both)

        Returns
        -------
        pd.DataFrame
            DataFrame containing last line interactions and corresponding
            packet counts.

        Notes
        -----
        This method depends on tardis.analysis.LastLineInteraction object for
        doing computations. So there is a member variable in this class -
        :code:`line_interaction_analysis` which is a dictionary of such objects
        (each of them differ in how they filter the selected wavelength range).
        Thus we have to specify which object to use by specifying the
        filter_mode parameter.

        This method should always be called after calling
        :code:`get_species_interactions` method which sets a wavelength
        range on LastLineInteraction object. So selected_species should
        be one present within that range, otherwise it will result an error.
        """
        if selected_species:
            selected_species_tuple = species_string_to_tuple(selected_species)

            try:
                # Get selected species' rows from last_line_in dataframe
                current_last_lines_in = (
                    self.line_interaction_analysis[filter_mode].last_line_in.
                    xs(
                        key=selected_species_tuple,
                        level=["atomic_number", "ion_number"],
                        drop_level=False,
                    ).reset_index())

                # Get selected species' rows from last_line_out dataframe
                current_last_lines_out = (
                    self.line_interaction_analysis[filter_mode].last_line_out.
                    xs(
                        key=selected_species_tuple,
                        level=["atomic_number", "ion_number"],
                        drop_level=False,
                    ).reset_index())

                assert (current_last_lines_in.empty
                        & current_last_lines_out.empty == False)

            except (KeyError, AssertionError):  # selected_species is invalid
                allowed_species = [
                    species_tuple_to_string(species)
                    for species in self.line_interaction_analysis[filter_mode].
                    last_line_in.groupby(["atomic_number", "ion_number"
                                          ]).groups.keys()
                ]
                raise ValueError(
                    "Invalid value of selected_species, it must be one present "
                    "within the currently selected wavelength range in your "
                    f"LineInfoWidget instance, which are {allowed_species}")

            last_line_interaction_string = []
            interacting_packets_count = []

            if group_mode == "both":
                # Group by both exc. line ids and de-exc. line ids
                current_last_lines_in[
                    "line_id_out"] = current_last_lines_out.line_id
                grouped_line_interactions = current_last_lines_in.groupby(
                    ["line_id", "line_id_out"])

                # Iterate over each group's key and size and append them to list
                for (
                        line_id,
                        count,
                ) in grouped_line_interactions.size().iteritems():
                    current_line_in = self.lines_data.loc[line_id[0]]
                    current_line_out = self.lines_data.loc[line_id[1]]
                    last_line_interaction_string.append(
                        f"exc. {int(current_line_in.level_number_lower):02d}-"
                        f"{int(current_line_in.level_number_upper):02d} "
                        f"({current_line_in.wavelength:.2f} A) "
                        f"de-exc. {int(current_line_out.level_number_upper):02d}-"
                        f"{int(current_line_out.level_number_lower):02d} "
                        f"({current_line_out.wavelength:.2f} A)")
                    interacting_packets_count.append(count)

            elif group_mode == "exc":
                grouped_line_interactions = current_last_lines_in.groupby(
                    "line_id")

                # Iterate over each group's key and size and append them to list
                for (
                        line_id,
                        count,
                ) in grouped_line_interactions.size().iteritems():
                    current_line_in = self.lines_data.loc[line_id]
                    last_line_interaction_string.append(
                        f"exc. {int(current_line_in.level_number_lower):02d}-"
                        f"{int(current_line_in.level_number_upper):02d} "
                        f"({current_line_in.wavelength:.2f} A)")
                    interacting_packets_count.append(count)

            elif group_mode == "de-exc":
                grouped_line_interactions = current_last_lines_out.groupby(
                    "line_id")

                # Iterate over each group's key and size and append them to list
                for (
                        line_id,
                        count,
                ) in grouped_line_interactions.size().iteritems():
                    current_line_out = self.lines_data.loc[line_id]
                    last_line_interaction_string.append(
                        f"de-exc. {int(current_line_out.level_number_upper):02d}-"
                        f"{int(current_line_out.level_number_lower):02d} "
                        f"({current_line_out.wavelength:.2f} A)")
                    interacting_packets_count.append(count)

            else:
                raise ValueError(
                    "Invalid value passed to group_mode argument. "
                    f"Allowed values are {self.GROUP_MODES}")

        else:  # species_selected is None
            # qgrid cannot show empty dataframe properly,
            # so create one row with empty strings
            interacting_packets_count = [""]
            last_line_interaction_string = [""]

        last_line_counts = pd.Series(interacting_packets_count)
        last_line_counts.name = "No. of packets"
        last_line_counts.index = pd.Index(last_line_interaction_string,
                                          name="Last Line Interaction")
        return last_line_counts.sort_values(ascending=False).to_frame()
예제 #3
0
    def get_species_interactions(self,
                                 wavelength_range,
                                 filter_mode=FILTER_MODES[0]):
        """
        Get fractional species interactions in specified wavelength range.

        Fractional species interactions means fraction of packets present in
        the specified wavelength range which experienced their last interaction
        with a species. The packets to consider are filtered by the specified
        filter mode.

        Parameters
        ----------
        wavelength_range : list-like or None
            A list of two float values to specify the wavelength range - first
            for the range start and second for the range end. None specifies
            that no wavelength range is selected and will return empty dataframe
        filter_mode : str, optional
            Filter mode of the LastLineInteraction object to use for filtering
            the selected wavelength range (more details in Notes section).
            Allowed values are given by the class variable :code:`FILTER_MODES`
            (default value is :code:`FILTER_MODES[0]`)

        Returns
        -------
        pandas.DataFrame
            Dataframe containing species symbols and corresponding fractions
            of packets interacting with them

        Notes
        -----
        This method depends on tardis.analysis.LastLineInteraction object for
        doing computations. So there is a member variable in this class -
        :code:`line_interaction_analysis` which is a dictionary of such objects
        (each of them differ in how they filter the selected wavelength range).
        Thus we have to specify which object to use by specifying the
        filter_mode parameter.
        """
        if wavelength_range:
            self.line_interaction_analysis[filter_mode].wavelength_start = (
                wavelength_range[0] * u.AA)
            self.line_interaction_analysis[filter_mode].wavelength_end = (
                wavelength_range[1] * u.AA)

            # Obtain species group from last_line_in dataframe
            selected_species_group = self.line_interaction_analysis[
                filter_mode].last_line_in.groupby(
                    ["atomic_number", "ion_number"])

            if selected_species_group.groups:
                selected_species_symbols = [
                    species_tuple_to_string(item)
                    for item in selected_species_group.groups.keys()
                ]

                # Normalize each group's count to find fractions of interactions
                fractional_species_interactions = (
                    selected_species_group.size() /
                    self.line_interaction_analysis[filter_mode].last_line_in.
                    shape[0])

            else:  # No species could be selected in specified wavelength_range
                # qgrid cannot show empty dataframe properly,
                # so create one row with empty strings
                selected_species_symbols = [""]
                fractional_species_interactions = pd.Series([""])

        else:  # wavelength_range is None
            selected_species_symbols = [""]
            fractional_species_interactions = pd.Series([""])

        fractional_species_interactions.index = pd.Index(
            selected_species_symbols, name="Species")
        fractional_species_interactions.name = "Fraction of packets interacting"
        return fractional_species_interactions.sort_values(
            ascending=False).to_frame()
예제 #4
0
파일: test_util.py 프로젝트: zdy0903/tardis
def test_species_tuple_to_string(species_tuple, roman_numerals,
                                 species_string):
    assert species_tuple_to_string(
        species_tuple, roman_numerals=roman_numerals) == species_string
예제 #5
0
def test_species_tuple_to_string(species_tuple, roman_numerals, species_string):
    assert species_tuple_to_string(species_tuple, roman_numerals=roman_numerals) == species_string