diff --git a/sohstationviewer/view/plotting/plotting_widget/plotting_widget_helper.py b/sohstationviewer/view/plotting/plotting_widget/plotting_widget_helper.py
new file mode 100644
index 0000000000000000000000000000000000000000..5bfedc4f89ece72802b86ffc5dd90580ceee5828
--- /dev/null
+++ b/sohstationviewer/view/plotting/plotting_widget/plotting_widget_helper.py
@@ -0,0 +1,59 @@
+from typing import Dict, Optional
+import numpy as np
+
+from matplotlib.axes import Axes
+
+from sohstationviewer.controller.plotting_data import format_time
+
+
+def get_data_point_info(click_index: int,
+                        ax: Axes,
+                        chan_data: Dict,
+                        date_mode: str) -> str:
+    """
+    Get info of the clicked data point to display
+    :param click_index: index of data point being clicked
+    :param ax: axes of channel's plot
+    :param chan_data: data info of a channel as a dict
+    :param date_mode: the format of date, time
+    :return info_str: info of data point as text
+    """
+
+    clicked_time = chan_data['times'][0][click_index]
+    clicked_data = chan_data['data'][0][click_index]
+    if hasattr(ax, 'unit_bw'):
+        clicked_data = ax.unit_bw.format(clicked_data)
+    formatted_clicked_time = format_time(
+        clicked_time, date_mode, 'HH:MM:SS')
+    info_str = (f"<pre>Channel: {ax.chan}   "
+                f"Point:{click_index + 1}   "
+                f"Time: {formatted_clicked_time}   "
+                f"Value: {clicked_data}</pre>")
+    return info_str
+
+
+def get_total_miny_maxy(
+        x: np.ndarray, y: Optional[np.ndarray],
+        min_x: float, max_x: float) -> (int, Optional[float], Optional[float]):
+    """
+    Identify total points in channel and y_min, y_max to reset the info and
+        ylim
+    :param x: x list of the plot
+    :param y: y list of the plot
+    :param min_x: Under limit of x
+    :param max_x: Upper limit of x
+
+    :return: total points, new under limit of y, new upper limit of y
+    """
+    new_x_indexes = np.where((x >= min_x) & (x <= max_x))[0]
+
+    new_x = x[new_x_indexes]
+    if new_x.size == 0:
+        return 0, None, None
+
+    new_min_x_index = min(new_x_indexes)
+    new_max_x_index = max(new_x_indexes)
+    new_y = y[new_min_x_index:new_max_x_index + 1]
+    new_min_y = min(new_y)
+    new_max_y = max(new_y)
+    return new_x_indexes.size, new_min_y, new_max_y
diff --git a/sohstationviewer/view/util/functions.py b/sohstationviewer/view/util/functions.py
index 1a70f2fac011c174cbf8113c06ae8b33aae06f2f..72846da567b407fd2e2a53024394c27964a385cd 100644
--- a/sohstationviewer/view/util/functions.py
+++ b/sohstationviewer/view/util/functions.py
@@ -1,7 +1,6 @@
 import re
 from pathlib import Path
-from typing import Dict, List, Tuple, Union, Optional
-import numpy as np
+from typing import Dict, List, Tuple, Union
 
 from sohstationviewer.view.util.enums import LogType
 from sohstationviewer.conf import constants as const
@@ -235,33 +234,6 @@ def check_masspos(mp_data: Dict[str, Dict], sel_key: Union[tuple, str],
                         f"{','.join(not_included_mp)}")
 
 
-def get_total_miny_maxy(
-        x: np.ndarray, y: Optional[np.ndarray],
-        min_x: float, max_x: float) -> (int, Optional[float], Optional[float]):
-    """
-    Identify total points in channel and y_min, y_max to reset the info and
-        ylim
-    :param x: x list of the plot
-    :param y: y list of the plot
-    :param min_x: Under limit of x
-    :param max_x: Upper limit of x
-
-    :return: total points, new under limit of y, new upper limit of y
-    """
-    new_x_indexes = np.where((x >= min_x) & (x <= max_x))[0]
-
-    new_x = x[new_x_indexes]
-    if new_x.size == 0:
-        return 0, None, None
-
-    new_min_x_index = min(new_x_indexes)
-    new_max_x_index = max(new_x_indexes)
-    new_y = y[new_min_x_index:new_max_x_index + 1]
-    new_min_y = min(new_y)
-    new_max_y = max(new_y)
-    return new_x_indexes.size, new_min_y, new_max_y
-
-
 def extract_netcodes(data_obj):
     """
     Extract information about network codes from data_obj.nets_by_sta which
@@ -291,39 +263,6 @@ def extract_netcodes(data_obj):
     return '\n\t'.join(net_info_list)
 
 
-def get_index_from_time(chan_data: List[np.ndarray], tm: float, val: float) \
-        -> Tuple[int, int]:
-    """
-    Get index of tm in chan_data['time'] which is a list of np.ndarray
-    :param chan_data: dict of data to plot that includes 'times' key
-    :param tm: epoch time of a clicked point
-    :param val: data value of a clicked point
-    :return list_idx: index of the np.ndarray in the list
-    :return section_idx: index of tm inside np.ndarray found
-    """
-    list_idx = None
-    section_idx = None
-    for i in range(len(chan_data['times'])):
-        section_indexes = np.where(chan_data['times'][i] == tm)[0]
-        if len(section_indexes) != 0:
-            if (chan_data['chan_db_info']['plotType'] not in
-                    ['linesDots', 'linesSRate']):
-                # don't check val because the plotting value of some plot
-                # is for displaying only, not actual value. And this type
-                # of data isn't under the effect of overlap.
-                section_idx = section_indexes[0]
-                list_idx = i
-                break
-            else:
-                # to prevent 2 values with the same times in case of overlap
-                for j in section_indexes:
-                    if chan_data['data'][i][j] == val:
-                        list_idx = i
-                        section_idx = j
-                        break
-    return list_idx, section_idx
-
-
 def remove_not_found_chans(
         chan_order: List[str], actual_chans: List[str],
         processing_log: List[Tuple[str, LogType]]) -> List[str]: