Show and select branches for a branched trace.
        - [*] signifies the current branch that is selected
        - will prompt for branch selection if called with no argument
        - will automatically select a branch if called with an argument

        Parameters (optional):
            selected_number: int    branch number from expand output

        Example output:

        Suppose we have the trace output:
             ⎇  [callable]            [port]    [location]
         --> +2 leaf                  source    module/main.py:26|4|8
                module.main           root      module/helper.py:76|5|10
                module.helper.process root      module/helper.py:76|5|10
             +3 leaf                  sink      module/main.py:74|1|9

        Calling expand will result in the output:
        [*] leaf
                [0 hops: source]
                [module/main.py:26|4|8]
        [1] module.helper.preprocess
                [1 hops: source]
                [module/main.py:21|4|8]

def branch(self, selected_number: Optional[int] = None) -> None:
        """Show and select branches for a branched trace.
        - [*] signifies the current branch that is selected
        - will prompt for branch selection if called with no argument
        - will automatically select a branch if called with an argument

        Parameters (optional):
            selected_number: int    branch number from expand output

        Example output:

        Suppose we have the trace output:
             ⎇  [callable]            [port]    [location]
         --> +2 leaf                  source    module/main.py:26|4|8
                module.main           root      module/helper.py:76|5|10
                module.helper.process root      module/helper.py:76|5|10
             +3 leaf                  sink      module/main.py:74|1|9

        Calling expand will result in the output:
        [*] leaf
                [0 hops: source]
                [module/main.py:26|4|8]
        [1] module.helper.preprocess
                [1 hops: source]
                [module/main.py:21|4|8]
        """
        self._verify_entrypoint_selected()
        self._verify_multiple_branches()

        with self.db.make_session() as session:
            branches, leaves_strings = self._get_branch_options(session)

            if selected_number is None:
                selected_number = self._select_branch_trace_frame(
                    branches, leaves_strings
                )

            if (
                not isinstance(selected_number, int)
                or selected_number < 1
                or selected_number > len(branches)
            ):
                raise UserError(
                    "Branch number invalid "
                    f"(expected 1-{len(branches)} but got {selected_number})."
                )

            new_navigation = self._navigate_trace_frames(
                session, branches, selected_number - 1
            )

        new_trace_tuples = self._create_trace_tuples(new_navigation)

        if self._is_before_root():
            new_trace_tuples.reverse()
            self.trace_tuples = (
                new_trace_tuples
                + self.trace_tuples[self.current_trace_frame_index + 1 :]
            )

            # If length of prefix changes, it will change some indices
            trace_frame_index_delta = (
                len(new_navigation) - self.current_trace_frame_index - 1
            )
            self.current_trace_frame_index += trace_frame_index_delta
        else:
            self.trace_tuples = (
                self.trace_tuples[: self.current_trace_frame_index] + new_trace_tuples
            )

        self.trace()