diff --git a/sohstationviewer/database/extract_data.py b/sohstationviewer/database/extract_data.py
index cf0ab6208f841629f618bd28260d617c2aa15fd2..afc16cc40306a3e882ef5597865f8fd625cbaaeb 100755
--- a/sohstationviewer/database/extract_data.py
+++ b/sohstationviewer/database/extract_data.py
@@ -18,18 +18,10 @@ def get_chan_plot_info(org_chan_id: str, data_type: str,
     :return info of channel read from DB which is used for plotting
     """
     chan = org_chan_id
-    if org_chan_id.startswith('EX'):
-        chan = 'EX?'
-    if org_chan_id.startswith('VM'):
-        chan = 'VM?'
-    if org_chan_id.startswith('MassPos'):
-        chan = 'MassPos?'
+    chan = get_question_channel(chan)
+
     if org_chan_id.startswith('DS'):
         chan = 'SEISMIC'
-    if org_chan_id.startswith('Event DS'):
-        chan = 'Event DS?'
-    if org_chan_id.startswith('Disk Usage'):
-        chan = 'Disk Usage?'
     if dbConf['seisRE'].match(chan):
         chan = 'SEISMIC'
     # The valueColors for each color mode is stored in a separate column.
@@ -74,7 +66,16 @@ def get_chan_plot_info(org_chan_id: str, data_type: str,
     return chan_db_info[0]
 
 
-def get_convert_factor(chan_id, data_type):
+def get_convert_factor(chan_id: str, data_type: str) -> float:
+    """
+    Get the convert factor to convert data from count (value read from file)
+    to actual value to display.
+
+    :param chan_id: actual channel name read from file
+    :param data_type: type of data in data set
+    :return: converting factor
+    """
+    chan_id = get_question_channel(chan_id)
     sql = f"SELECT convertFactor FROM Channels WHERE channel='{chan_id}' " \
           f"AND dataType='{data_type}'"
     ret = execute_db(sql)
@@ -84,6 +85,24 @@ def get_convert_factor(chan_id, data_type):
         return None
 
 
+def get_question_channel(chan_id: str) -> str:
+    """
+    The digit in channel end with a digit is represented with the question
+        mark '?' in DB. This function change the real channel name to DB
+        channel name with '?'.
+    :param chan_id: real channel name
+    :return chan_id: channel name with '?' at the end if available
+    """
+    sql = "SELECT * FROM Channels WHERE channel like '%?'"
+    ret = execute_db(sql)
+    question_channels = [c[0][:-1] for c in ret]
+    if any(chan_id.startswith(x) for x in question_channels):
+        if chan_id[-1].isdigit():
+            # to prevent the case prefix similar to prefix of channel w/o ?
+            chan_id = chan_id[:-1] + '?'
+    return chan_id
+
+
 def get_seismic_chan_label(chan_id):
     """
     Get label for chan_id in which data stream can use chan_id for label while
diff --git a/tests/database/test_extract_data.py b/tests/database/test_extract_data.py
index a8906f35ae997d558d0bb1644fe5ee461456fb0e..2c5a833bdbe2bb2961193e2241d969dd234dba6b 100644
--- a/tests/database/test_extract_data.py
+++ b/tests/database/test_extract_data.py
@@ -6,11 +6,13 @@ from sohstationviewer.database.extract_data import (
     get_signature_channels,
     get_color_def,
     get_color_ranges,
+    get_question_channel,
+    get_convert_factor
 )
 
 
-class TestExtractData(unittest.TestCase):
-    def test_get_chan_plot_info_good_soh_channel_and_data_type(self):
+class TestGetChanPlotInfo(unittest.TestCase):
+    def test_good_soh_channel_and_data_type(self):
         """
         Test basic functionality of get_chan_plot_info - channel and data type
         combination exists in database table `Channels`
@@ -27,7 +29,7 @@ class TestExtractData(unittest.TestCase):
         self.assertDictEqual(get_chan_plot_info('SOH/Data Def', 'RT130'),
                              expected_result)
 
-    def test_get_chan_plot_info_masspos_channel(self):
+    def test_masspos_channel(self):
         with self.subTest("Mass position 'VM'"):
             expected_result = {'channel': 'VM1',
                                'plotType': 'linesMasspos',
@@ -54,7 +56,7 @@ class TestExtractData(unittest.TestCase):
             self.assertDictEqual(get_chan_plot_info('MassPos1', 'RT130'),
                                  expected_result)
 
-    def test_get_chan_plot_info_seismic_channel(self):
+    def test_seismic_channel(self):
         with self.subTest("RT130 Seismic"):
             expected_result = {'channel': 'DS2',
                                'plotType': 'linesSRate',
@@ -81,7 +83,7 @@ class TestExtractData(unittest.TestCase):
             self.assertDictEqual(get_chan_plot_info('LHE', 'Q330'),
                                  expected_result)
 
-    def test_get_chan_plot_info_data_type_is_unknown(self):
+    def test_data_type_is_unknown(self):
         """
         Test basic functionality of get_chan_plot_info - data type is the
         string 'Unknown'.
@@ -113,7 +115,7 @@ class TestExtractData(unittest.TestCase):
             get_chan_plot_info('LCE', 'Unknown'),
             expected_result)
 
-    def test_get_chan_plot_info_bad_channel_or_data_type(self):
+    def test_bad_channel_or_data_type(self):
         """
         Test basic functionality of get_chan_plot_info - channel and data type
         combination does not exist in database table Channels and data type is
@@ -159,7 +161,9 @@ class TestExtractData(unittest.TestCase):
         self.assertDictEqual(get_chan_plot_info('SOH/Data Def', 'Q330'),
                              expected_result)
 
-    def test_get_seismic_chan_label_good_channel_id(self):
+
+class TestGetSeismicChanLabel(unittest.TestCase):
+    def test_good_channel_id(self):
         """
         Test basic functionality of get_seismic_chan_label - channel ID ends
         in one of the keys in conf.dbSettings.dbConf['seisLabel'] or
@@ -174,7 +178,7 @@ class TestExtractData(unittest.TestCase):
         self.assertEqual(get_seismic_chan_label('DS-TEST-CHANNEL'),
                          'DS-TEST-CHANNEL')
 
-    def test_get_chan_label_bad_channel_id(self):
+    def test_bad_channel_id(self):
         """
         Test basic functionality of get_seismic_chan_label - channel ID does
             not end in one of the keys in conf.dbSettings.dbConf['seisLabel']
@@ -182,16 +186,22 @@ class TestExtractData(unittest.TestCase):
         """
         self.assertRaises(IndexError, get_seismic_chan_label, '')
 
+
+class TestGetSignatureChannels(unittest.TestCase):
     def test_get_signature_channels(self):
         """Test basic functionality of get_signature_channels"""
         self.assertIsInstance(get_signature_channels(), dict)
 
+
+class TestGetColorDef(unittest.TestCase):
     def test_get_color_def(self):
         """Test basic functionality of get_color_def"""
         colors = get_color_def()
         expected_colors = ['K', 'U', 'C', 'G', 'Y', 'R', 'M', 'E']
         self.assertListEqual(colors, expected_colors)
 
+
+class TestGetColorRanges(unittest.TestCase):
     def test_get_color_ranges(self):
         """Test basic functionality of get_color_ranges"""
         names, all_counts, all_display_strings = get_color_ranges()
@@ -212,3 +222,23 @@ class TestExtractData(unittest.TestCase):
         # Check that each list of strings to display have enough items
         for display_strings in all_display_strings:
             self.assertEqual(len(display_strings), num_color_def + 1)
+
+
+class TestGetQuestionChannel(unittest.TestCase):
+    def test_question_channel(self):
+        ret = get_question_channel('VM1')
+        self.assertEqual(ret, 'VM?')
+
+    def test_non_question_channel(self):
+        ret = get_question_channel('VCO')
+        self.assertEqual(ret, 'VCO')
+
+
+class TestGetConvertFactor(unittest.TestCase):
+    def test_question_channel(self):
+        ret = get_convert_factor('VM1', 'Centaur')
+        self.assertEqual(ret, 10**(-6))
+
+    def test_non_question_channel(self):
+        ret = get_convert_factor('VEP', 'Q330')
+        self.assertEqual(ret, 0.15)