diff --git a/my_flask_app/__pycache__/main.cpython-39.pyc b/my_flask_app/__pycache__/main.cpython-39.pyc
index 197f3a0c6f0b12d1beee27123df9ba4302797d1b..870e9cbe212add277a10cf6075c2b75ab29566f5 100644
Binary files a/my_flask_app/__pycache__/main.cpython-39.pyc and b/my_flask_app/__pycache__/main.cpython-39.pyc differ
diff --git a/my_flask_app/main.py b/my_flask_app/main.py
index 5ad81ab1297e18cdcb0039722521c3ef3107b47e..3a3f7ba6ea91600f1a9958e870465fe1e27705a8 100644
--- a/my_flask_app/main.py
+++ b/my_flask_app/main.py
@@ -1,14 +1,16 @@
+from datetime import datetime
 import pandas as pd
 from my_flask_app import app
 from .models.models import CustomTable, CustomColumn, Theme, CompressedDataType, Observation_Spec, RegType, RegRole
 from flask_sqlalchemy import SQLAlchemy
 from flask import jsonify, redirect, render_template, request, session, url_for, json
-from sqlalchemy import ARRAY, BIGINT, BOOLEAN, DOUBLE_PRECISION, FLOAT, INTEGER, JSON, NUMERIC, SMALLINT, TIMESTAMP, UUID, VARCHAR, MetaData, String, create_engine, text, inspect
+from sqlalchemy import ARRAY, BIGINT, BOOLEAN, DOUBLE_PRECISION, FLOAT, INT, INTEGER, JSON, NUMERIC, SMALLINT, TIMESTAMP, UUID, VARCHAR, MetaData, String, create_engine, text, inspect
 import pydot, base64, os, logging
 from sqlalchemy.orm import scoped_session, sessionmaker
 from sqlalchemy.dialects.postgresql.base import ischema_names
 from sqlalchemy.dialects.postgresql import JSONB, TSTZRANGE, INTERVAL, BYTEA, JSON, UUID, DOUBLE_PRECISION, BYTEA, ARRAY, REAL, TSTZRANGE, UUID, BYTEA, JSONB, JSON, ARRAY, FLOAT, INTEGER, TIMESTAMP, TEXT, BOOLEAN, VARCHAR, NUMERIC, REAL
 from sqlalchemy.dialects.sqlite import JSON, FLOAT, INTEGER, TIMESTAMP, TEXT, BOOLEAN, VARCHAR, NUMERIC, REAL
+from bs4 import BeautifulSoup
 
 # Set up database (call db.engine)
 app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
@@ -49,7 +51,9 @@ def index():
                     session['self_defined_labels'] = []
                     session['schema_selected'] = ''
                     session['show_all'] = False
+                    session['object_name'] = {}
                     session['data_header']={'event':[], 'measurement':[], 'segment':[], 'segmentData':[]}
+                    session['current_data_header'] = {'tablename': '', 'type': '', 'label': [], 'features_name': []}
                     print("4")
                 # Initialize inspector here, outside the inner if-else
                 print("4.5")
@@ -98,6 +102,9 @@ def index():
                 image2 = generate_erd(graph_DOT2)
                 print("222")
 
+
+            extract_ME_table(engine, 'event_data', 'E', 'time', ['col', 'machine_id'], [' col ', ' name ', ' Z_ACTUAL_ZERO_POINT '], ['value(fine, coarse)'], datetime(2022, 11, 1, 17, 5), datetime(2022, 11, 3, 0, 0))
+
             return render_template('app.html', database=database, schemas=schemas, show_all=show_all, schema_Selected=schema_Selected, tables=tables1, image1=image1, image2=image2, dropped_items=dropped_items, self_labels=self_labels)
         
         else:
@@ -108,8 +115,6 @@ def index():
         return f"An error occurred: {str(e)}", 400
     
 
-
-
 @app.route('/handle-drop', methods=['POST'])
 def handle_drop():
     data = request.json
@@ -222,32 +227,189 @@ def add_label():
 @app.route('/add-data-header', methods=['POST'])
 def add_data_header():
     data_header = session.get('data_header', {'event':[], 'measurement':[], 'segment':[], 'segmentData':[]})
+    
     data = request.json
     type = data.get('type') if data.get('type') != None else ''
-    label = data.get('label') if data.get('label') != None else ''
+    label_list = eval(data.get('label'))if data.get('label') != None else ['','','']
     object_column = data.get('object_column') if data.get('object_column') != None else ''
     value_list = data.get('value_list') if data.get('value_list') != None else []
 
+    current_table = session.get('target_table_name', '')
+
     if type == 'event':
-        observation = Observation_Spec(type, label, value_list)
-        data_header['event'].append(observation.to_dict())
+        observation = Observation_Spec(current_table, 'E', label_list, value_list)
+        if observation.to_dict() not in data_header['event']:
+            data_header['event'].append(observation.to_dict())
     elif type == 'measurement':
-        observation = Observation_Spec(type, label, value_list)
-        data_header['measurement'].append(observation.to_dict())
+        observation = Observation_Spec(current_table, 'M', label_list, value_list)
+        if observation.to_dict() not in data_header['measurement']:
+            data_header['measurement'].append(observation.to_dict())
     elif type == 'segment':
-        observation = Observation_Spec(type, label, value_list)
-        data_header['segment'].append(observation.to_dict())
+        observation = Observation_Spec(current_table, 'S', label_list, [])
+        if observation.to_dict() not in data_header['segment']:
+            data_header['segment'].append(observation.to_dict())
     elif type == 'segmentData':
-        observation = Observation_Spec(type, label, value_list)
-        data_header['segmentData'].append(observation.to_dict())
-    
+        observation = Observation_Spec(current_table, 'SD', label_list, value_list)
+        if observation.to_dict() not in data_header['segmentData']:
+            data_header['segmentData'].append(observation.to_dict())
+    elif type == 'object':
+        obj = session.get('object_name', {})
+        obj[current_table] = object_column
+        session['object_name'] = obj
+        return jsonify()
+
+    print(observation.to_dict())
     print("88888")
     print(data_header)
     session['data_header'] = data_header
 
-    return jsonify({'data_header': data_header})
+    data_header_table = generate_html_header_table()
+
+    return jsonify({'data_header': data_header, 'data_header_table': data_header_table})
+
+
+@app.route('/reset-data-header-table', methods=['POST'])
+def reset_data_header_table():
+    session['data_header'] = {'event':[], 'measurement':[], 'segment':[], 'segmentData':[]}
+    data_header_table = generate_html_header_table()
+
+    return jsonify({'data_header_table': data_header_table})
+
+
+@app.route('/init-data-header-table', methods=['POST'])
+def init_data_header_table():
+    data_header_table = generate_html_header_table()
+    return jsonify({'data_header_table': data_header_table})
+
+
+@app.route('/delete-data-header', methods=['POST'])
+def delete_data_header():
+    data_header = session.get('data_header', {'event':[], 'measurement':[], 'segment':[], 'segmentData':[]})
+    if data_header == {'event':[], 'measurement':[], 'segment':[], 'segmentData':[]}:
+        data_header_table = generate_html_header_table()
+        return jsonify({'data_header_table': data_header_table})
+    
+    data = request.json
+    str = data['value']
+    res = readHeaderHTML(str)
+    type = res['type']
+
+    if type == 'M':
+        print(data_header['measurement'])
+        data_header['measurement'].remove(res) 
+    elif type == 'E':
+        data_header['event'].remove(res)
+    elif type == 'S':
+        data_header['segment'].remove(res)
+    elif type == 'SD':
+        data_header['segmentData'].remove(res)
+    session['data_header'] = data_header
+
+    data_header_table = generate_html_header_table()
+    return jsonify({'data_header_table': data_header_table})
+
+
+@app.route('/get-MD-info', methods=['POST'])
+def get_MD_info():
+    data = request.json
+    str = data['value']
+    soup = BeautifulSoup(str, 'html.parser')
+    tds = soup.find_all('td')
+    res = readHeaderHTML(str)  # res = {'tablename': '', 'type': '', 'label': [], 'features_name': []}
+    type = res['type']
+    label_column = res['label'][0]
+    session['current_data_header'] = res
+    print(res)
+
+    if type == 'E' or type == 'M':
+        time = getTimeColumns(res['tablename'])           # list
+        object = getObjectColumns(res['tablename'])       # list
+        if res['label'][0] == 'col' and res['label'][1] in object:
+            object.remove(res['label'][1])
+
+        return jsonify({'time': time, 'object': object})
+    elif type == 'S':
+        time = getTimeColumns(res['tablename'])          # list
+        object = getObjectColumns(res['tablename'])      # list
+        # index = 
+        return jsonify({'time': time, 'object': object})
+    elif type == 'SD':
+        time = getTimeColumns(res['tablename'])          # list
+        object = getObjectColumns(res['tablename'])
+        # index = 
+        return jsonify({'time': time, 'object': object})
+
+
+@app.route('/get-ME-table', methods=['POST'])
+def get_ME_table():
+    engine = create_engine(session.get('db_uri', ''))
+    data = request.json
+    current_data_header = session.get('current_data_header', {'tablename': '', 'type': '', 'label': [], 'features_name': []})
+    table_name = current_data_header['tablename']
+    type = current_data_header['type']
+    time_column = data['time_column']
+    object_column = data['object_column']
+    optgroupLabel = data['optgroupLabel']
+    object_list = [optgroupLabel, object_column]
+    label_list = current_data_header['label']
+    features = []
+    for feature in current_data_header['features_name']:
+        if '(' in feature and ')' in feature:         # "value('coarse', 'fine')"
+            feature = feature.replace("'", "")
+            features.append(feature)
+        else:
+            features.append(feature)
+    start_time = datetime.strptime(data['minDatetime'], '%Y-%m-%d %H:%M:%S') if 'minDatetime' in data else None
+    end_time = datetime.strptime(data['maxDatetime'], '%Y-%m-%d %H:%M:%S') if 'maxDatetime' in data else None
+
+    print(table_name)
+    print(type)
+    print(time_column)
+    print(object_list)
+    print(label_list)
+    print(features)
+
+    query_result = extract_ME_table(engine, table_name, type, time_column, object_list, label_list, features, start_time, end_time)
+    table_HTML = get_ME_table_HTML(query_result)
+
+    if start_time == None and end_time == None:
+        min_datetime, max_datetime = get_min_max_datetime(engine, table_name, time_column)
+        return jsonify({'table_HTML': table_HTML, 'min_datetime': min_datetime, 'max_datetime': max_datetime})
+
+    return jsonify({'table_HTML': table_HTML})
+
+
+def readHeaderHTML(str):
+    soup = BeautifulSoup(str, 'html.parser')
+    tds = soup.find_all('td')
+
+    res = {'tablename': '', 'type': '', 'label': [], 'features_name': []}
+    res['tablename'] = tds[1].get_text()
+    res['type'] = tds[2].get_text()
+    res['label'] = json.loads(tds[3]['data-value'])
+    features = []
+    for td in tds[4:]:
+        data_value = td['data-value']
+        value_list = json.loads(data_value)
+        if value_list[0] == '':
+            a = value_list[1]
+            features.append(a)
+        else:
+            a = value_list[0] + '(' 
+            for i in range(len(value_list)-1):
+                a += "'" + value_list[i+1] + "', "
+            a = a[:len(a)-2]
+            a += ')'
+            if a not in features:
+                features.append(a)
+    res['features_name'] = features   # ['machine_id', "value('coarse', 'fine')"]
+
+    print(features)
+
+    return res
 
-def check_json_column(engine, table_name):
+
+def check_json_column(engine, table_name) -> list:
     insp = inspect(engine)
     schema = getTableSchema(table_name) if insp.dialect.name == 'postgresql' else insp.default_schema_name
     json_column_names = []
@@ -297,6 +459,81 @@ def database_name_from_uri(engine, database_uri: str):
         return 'Unknown'
 
 
+def count_feature_columns(data_header) -> int:
+    max_count = 0
+    for key in data_header.keys():
+        for dict_item in data_header[key]:
+            count = 0
+            for value in dict_item.get('features_name', []):
+                num = tuple(value.split('(')[1].split(')')[0].replace("'","").split(', ')) if '(' in value and ')' in value else 1
+                count += len(num) if type(num) == tuple else 1
+            if count > max_count:
+                max_count = count
+
+    return max_count
+
+
+def count_data_header(data_header):
+    count = 0
+    for key in data_header.keys():
+        count += len(data_header[key])
+
+    return count
+
+
+def generate_html_header_table():
+    # session['data_header'] = {'event':[], 'measurement':[], 'segment':[], 'segmentData':[]}
+    content = session.get('data_header', {'event':[], 'measurement':[], 'segment':[], 'segmentData':[]})
+    count_f_columns= count_feature_columns(content)
+    count_d_headers = count_data_header(content)
+
+    # Generate column headers
+    table_html = "<table class='uk-table uk-table-small uk-table-hover uk-table-divider uk-table-striped' style='cursor: pointer;'><thead><tr>"
+    table_html += "<th></th>"
+    table_html += "<th class='uk-table-expand'>Table name</th>"
+    table_html += "<th>Type</th>"
+    table_html += "<th class='uk-table-expand'>Label</th>"
+    for i in range(count_f_columns):
+        table_html += f"<th>F_{i+1}</th>"
+    table_html += "</tr></thead><tbody>"
+
+    # Generate table rows
+    index = 0
+    for key in content.keys():
+        for dict_item in content[key]:
+            table_html += f"<tr onclick='getRowData(this)'>"
+            table_html += "<td><button type='button' class='btn-close'  aria-label='Close' data-bs-dismiss='modal' onclick='deleteRow1(event, this)'></button></td>"
+            table_html += f"<td>{dict_item.get('tablename', '')}</td>"
+            table_html += f"<td data-id>{dict_item.get('type', '')}</td>"
+            print("723723")
+            print(dict_item.get('label', ''))
+            label_value = json.dumps(dict_item.get('label', ''))
+            table_html += f"<td data-value='{label_value}'>{dict_item.get('label', '')[2]}</td>"
+            print("823823")
+            for value in dict_item.get('features_name', []):
+                if '(' in value and ')' in value:
+                    feature_cloumn = value.split('(')[0]
+                    print(feature_cloumn)
+                    multiple_columns = tuple(value.split('(')[1].split(')')[0].replace("'","").split(', '))
+                    print(multiple_columns)
+                    for column in multiple_columns:
+                        print("624624")
+                        tmp = [feature_cloumn]
+                        for col in multiple_columns:
+                            tmp.append(col)
+                            print(tmp)
+                        data_value = json.dumps(tmp)
+                        table_html += f"<td data-value='{data_value}'>{column}</td>"
+                else:
+                    data_value = json.dumps(["", value])
+                    table_html += f"<td data-value='{data_value}'>{value}</td>"
+            index += 1
+            table_html += "</tr>"
+    table_html += "</tbody></table>"
+    print(table_html)
+    return table_html
+
+
 def generate_html_table(content):
     if not content:
         return "No data found."
@@ -318,7 +555,29 @@ def generate_html_table(content):
     return table_html
 
 
-def query_database_for_table_content(engine, table_name, number=20):
+def getTimeColumns(table_name:str) -> list:
+    engine = create_engine(session.get('db_uri', ''))
+    insp = inspect(engine)
+    schema = getTableSchema(table_name) if insp.dialect.name == 'postgresql' else insp.default_schema_name
+    columns = insp.get_columns(table_name, schema)
+    timestamp_columns = [column['name'] for column in columns if str(column['type']) == 'TIMESTAMP']
+    print(timestamp_columns)
+
+    return timestamp_columns
+
+
+def getObjectColumns(table_name:str) -> list:
+    engine = create_engine(session.get('db_uri', ''))
+    insp = inspect(engine)
+    schema = getTableSchema(table_name) if insp.dialect.name == 'postgresql' else insp.default_schema_name
+    columns = insp.get_columns(table_name, schema)
+    object_columns = [column['name'] for column in columns if str(column['type']) == 'VARCHAR' or str(column['type']) == 'INTEGER' or  str(column['type']) == 'NUMERIC']
+    print(object_columns)
+
+    return object_columns
+
+
+def query_database_for_table_content(engine, table_name, number=100):
     # Initialize content list
     content_list = []
     # Create a connection from the engine
@@ -371,7 +630,7 @@ def getSchema(insp):
 
 def getTableInstance(engine, table_name):
     insp = inspect(engine)
-    table = importMetadata(engine, None, [table_name], False)[table_name]
+    table = importMetadata(engine, None, [table_name], True)[table_name]
     return table
 
 
@@ -392,6 +651,144 @@ def showDistinctValues(engine, table_name, column_name):
     return names
 
 
+def get_min_max_datetime(engine, table_name, time_column, start_time=None, end_time=None):
+    schema = getTableSchema(table_name) if engine.dialect.name == 'postgresql' else engine.dialect.default_schema_name
+    # Formulate the SQL query using the text function
+    query = text(f"SELECT MIN({time_column}) AS start_datetime, MAX({time_column}) AS end_datetime FROM {schema}.{table_name};")
+
+    # Execute the query
+    with engine.connect() as connection:
+        row = connection.execute(query).mappings().fetchone()
+
+
+    # Extract the min and max datetime values
+    if row:
+        min_datetime, max_datetime = row['start_datetime'], row['end_datetime']
+        print("Minimum datetime:", min_datetime)
+        print("Maximum datetime:", max_datetime)
+        return min_datetime, max_datetime
+    else:
+        print("No datetimes found.")
+        return None, None
+
+
+
+def extract_ME_table(engine, table_name: str, type: str, time_column: str, object: list, label: list, features_name: list, start_time: datetime = None, end_time: datetime = None) -> list:
+    conn = engine.connect()
+    table_instance = getTableInstance(engine, table_name)
+    label_column = label[1].strip()
+    label_value = label[2].strip()
+    object_column_value = object[1].strip()
+    join_clause = ''
+
+    full_table_name = f"{table_instance.schema}.{table_instance.name}" if table_instance.schema else table_instance.name
+    sql_columns = [f"{full_table_name}.{time_column}"]
+
+    # Handling object_column logic
+    if object[0].strip()  != 'self' and object[0].strip()  == 'col':
+        print("1")
+        object_column = table_instance.getColumn(object_column_value)
+        object_column_name = object_column.fkof.table.name if object_column.fkof else ''
+        if object_column and object_column.fkof and object_column_name in session.get('object_name', {}):
+            related_table_instance = getTableInstance(engine,  object_column_name)
+            full_related_table_name = f"{related_table_instance.schema}.{related_table_instance.name}" if related_table_instance.schema else related_table_instance.name
+            join_clause = f"LEFT JOIN {full_related_table_name} ON {full_table_name}.{object_column.name} = {full_related_table_name}.{object_column.fkof.name}"
+            sql_columns.append(f"{full_related_table_name}.{session.get('object_name').get(object_column_name)} AS {object_column_value}")
+        else:
+            sql_columns.append(f"{full_table_name}.{object_column.name}")
+    print("12")
+    # If label[0] is not 'self', add it to SQL columns
+    if label[0].strip() != 'self':
+        sql_columns.append(f"{full_table_name}.{label_column}")
+    print("123")
+    # Handling JSON extractions
+    json_extractions = []
+    for feature in features_name:
+        if '(' in feature and ')' in feature:
+            column_name, keys = feature[:-1].split('(')
+            keys = keys.split(', ')
+            for key in keys:
+                json_extraction = f"{full_table_name}.{column_name}->>'{key}' AS {key}"
+                json_extractions.append(json_extraction)
+        else:
+            sql_columns.append(f"{full_table_name}.{feature}")
+    print("1234")
+    # Adding JSON extractions to the select clause
+    sql_select = ', '.join(sql_columns + json_extractions)
+    
+    # Constructing SQL query
+    sql_joins = join_clause
+    if label[0].strip() == 'col':
+        sql_where = f"WHERE {full_table_name}.{label_column} = :label_value"
+        if start_time:
+            sql_where += f" AND {full_table_name}.{time_column} >= :start_time"
+        if end_time:
+            sql_where += f" AND {full_table_name}.{time_column} <= :end_time"
+    else:
+        sql_where = ''
+        if start_time:
+            sql_where += f"WHERE {full_table_name}.{time_column} >= :start_time"
+        if end_time:
+            sql_where += f" AND {full_table_name}.{time_column} <= :end_time"
+
+    sql_query = f"SELECT {sql_select} FROM {full_table_name} {sql_joins} {sql_where} ORDER BY {time_column} ASC LIMIT 500"
+    print("12345")
+    # Executing the query
+    params = {'label_value': label_value}
+    if start_time:
+        params['start_time'] = start_time
+    if end_time:
+        params['end_time'] = end_time
+
+
+    # res = conn.execute(text(sql_query), params).fetchall()
+        
+    # Print the query for debugging
+    print("SQL Query:", sql_query)
+    print("Parameters:", params)
+    
+    # Executing the query
+    try:
+        res = conn.execute(text(sql_query), params).fetchall()
+    except Exception as e:
+        print(f"Error executing query: {e}")
+        return []
+
+    # Append object and label values if necessary
+    final_res = []
+    for row in res:
+        modified_row = list(row)
+        if object[0].strip()  == 'self':
+            modified_row.insert(1, object_column_value)
+        if label[0].strip()  == 'self':
+            label_index = 2 if object[0].strip()  != 'self' else 1
+            modified_row.insert(label_index, label[2])
+        modified_row.insert(2, type)
+        final_res.append(modified_row)
+
+    for row in final_res:
+        print(row)
+
+    return final_res
+
+
+def get_ME_table_HTML(data: list) -> str:
+    # Start the HTML <body> content with an opening <table> tag
+    html_content = ""
+    
+    # Iterate over the data to populate the table rows
+    for row in data:
+        html_content += "<tr><td><input class='uk-checkbox' type='checkbox' aria-label='Checkbox'></td>"
+        for cell in row:
+            if isinstance(cell, datetime):
+                # cell = cell.isoformat()
+                cell = cell.strftime('%Y-%m-%d %H:%M:%S:%f') 
+            html_content += f"<td>{cell}</td>"
+        html_content += "</tr>\n"
+
+    return html_content
+
+
 def importMetadata(engine, schema=None, tables_selected=None, show_all=False):
     tables = {}
     if engine == None:
@@ -643,540 +1040,4 @@ def getThemes():
 
 
 if __name__ == "__main__":
-    app.run(debug=True)
-
-
-
-
-
-
-
-
-# from my_flask_app import app
-# from flask_sqlalchemy import SQLAlchemy
-# from flask import jsonify, render_template, request, session, send_file
-# from sqlalchemy import text
-# import re, pydot, base64
-# import pydot
-
-
-# # Set up database
-# app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
-# app.config['SQLALCHEMY_DATABASE_URI'] = "postgresql://postgres:password@localhost:5432/test"
- 
-# db = SQLAlchemy() 
-# db.init_app(app)
-
-# app.secret_key = 'my_secret_key'  # Needed for session management
-# dropped_items = []
-
-# @app.route('/', methods=['POST', 'GET'])
-# def index():
-#     # Initialize variables
-#     database = db.engine.url.database
-#     tables_selected = []
-#     # tables_selected = ['machine_sensor', 'machine_tool', 'machine_trace']
-#     schemas = getSchema()
-#     themes = getThemes()
-
-#     schema_Selected = request.form.get('schema', None)
-#     show_all = request.form.get('show_all') == 'True'
-
-#     tables1 = importMetadata(database, schema_Selected, tables_selected, show_all)
-#     graph_DOT1 = createGraph(tables1, themes["Blue Navy"], True, True, True)
-#     image1 = generate_erd(graph_DOT1)
-
-#     if dropped_items==[]:
-#         image2 = ""
-#     else:
-#         tables2 = importMetadata(database, None, dropped_items, False)
-#         graph_DOT2 = createGraph(tables2, themes["Blue Navy"], True, True, True)
-#         image2 = generate_erd(graph_DOT2)
-
-#     print(getTableSchema('event_data'))
-     
-#     return render_template('app.html', database=database, schemas=schemas, show_all=show_all, schema_Selected=schema_Selected, tables=tables1, image1=image1, image2=image2, dropped_items=dropped_items)
-
-
-
-# @app.route('/handle-drop', methods=['POST'])
-# def handle_drop():
-#     data = request.json
-#     item_name = data.get('item')
-#     action = data.get('action')
-
-#     if action == 'added':
-#         dropped_items.append(item_name)
-#     elif action == 'removed' and item_name in dropped_items:
-#         dropped_items.remove(item_name)
-
-#     # Regenerate ERD based on the updated dropped_items
-#     database = db.engine.url.database
-#     themes = getThemes()
-#     tables2 = importMetadata(database, None, dropped_items, False)
-#     graph_DOT2 = createGraph(tables2, themes["Blue Navy"], True, True, True)
-#     image2 = generate_erd(graph_DOT2)
-
-#     return jsonify(image2=image2)
-
-
-# @app.route('/get-table-data', methods=['POST'])
-# def get_table_data():
-#     data = request.json
-#     table_name = data.get('table_name')
-#     print(table_name)
-
-#     # Query your database to get the data for the table_name
-#     content = query_database_for_table_content(table_name)
-
-#     # Convert content to HTML table format
-#     html_table = generate_html_table(content)
-
-#     return jsonify({'html_table': html_table})
-
-
-# def generate_html_table(content):
-#     if not content:
-#         return "No data found."
-#     # Generate column headers
-#     columns = content[0]
-#     table_html = "<table class='uk-table uk-table-small uk-table-hover uk-table-divider'><thead><tr>"
-#     for col in columns:
-#         table_html += f"<th>{col}</th>"
-
-#     table_html += "</tr></thead><tbody>"
-
-#     # Generate table rows
-#     for i in range(1, len(content)): 
-#         table_html += "<tr>"
-#         for item in content[i]:
-#             table_html += f"<td>{item}</td>"
-#         table_html += "</tr>"
-#     table_html += "</tbody></table>"
-#     return table_html
-
-
-# def query_database_for_table_content(table_name, number=20):
-#     # Initialize content list
-#     content_list = []
-
-#     # Get the schema of the table
-#     schema = getTableSchema(table_name)
-#     # Query the database to get the content of the table
-#     sql_content = text(f"""SELECT * FROM {schema}.{table_name} LIMIT {number};""")
-#     result = db.session.execute(sql_content, {'table_name': table_name, 'number': number}).fetchall()
-    
-#     if not result:
-#         return []
-    
-#     # Get the column names
-#     sql_columns = text("""
-#             SELECT column_name
-#             FROM information_schema.columns
-#             WHERE table_name = :table_name;
-#         """)
-#     column_names = db.session.execute(sql_columns, {'table_name': table_name}).fetchall()
-
-#     # Prepare column names
-#     columns = [column_name[0] for column_name in column_names]
-#     content_list.append(columns)
-
-#     # Append rows to content list
-#     for row in result:
-#         content_list.append(list(row))
-
-#     return content_list
-
-
-# def getTableSchema(table_name):
-#     sql= text(f"""
-#         SELECT table_schema 
-#         FROM information_schema.tables 
-#         WHERE table_name = :table_name;
-#     """)
-#     schema = db.session.execute(sql, {'table_name': table_name}).fetchone()[0]
-#     return schema
-
-
-# def getSchema():
-#     sql = text("""SELECT schema_name FROM information_schema.schemata;""")
-#     result = db.session.execute(sql)
-#     schemas = [row[0] for row in result]
-#     return schemas
-
-
-# def importMetadata(database, schema=None, tables_selected=None, show_all=False):
-#     tables = {}
-#     if database == '':
-#         return tables
-
-#     # Convert tables_selected to a list to ensure compatibility with SQL IN operation.
-#     tables_selected_list = list(tables_selected) if tables_selected else None
-
-#     # Fetch initial tables based on schema and table_names.
-#     tables = fetch_initial_tables(schema, tables_selected_list)
-
-#     # If show_all is True, expand the list to include related tables.
-#     if show_all:
-#         expand_to_include_related_tables(tables)
-
-#     # Fetch columns for each table.
-#     fetch_columns_for_tables(tables)
-
-#     # Fetch constraints (PK, FK, Unique) for each table.
-#     fetch_constraints_for_tables(tables)
-
-#     return tables
-
-
-# def fetch_initial_tables(schema, tables_selected_list):
-#     tables = {}
-
-#     # Construct WHERE clauses based on input parameters.
-#     schema_condition = "AND table_schema = :schema" if schema else ""
-#     tables_selected_condition = "AND table_name = ANY(:tables_selected)" if tables_selected_list else ""
-
-#     # Fetching tables with dynamic schema and table name filtering.
-#     sql_tables = text(f"""
-#         SELECT table_name, table_schema
-#         FROM information_schema.tables
-#         WHERE table_type = 'BASE TABLE'
-#         {schema_condition} {tables_selected_condition};
-#     """)
-    
-#     # Adjust parameters based on the conditions.
-#     params = {}
-#     if schema:
-#         params['schema'] = schema
-#     if tables_selected_list:
-#         params['tables_selected'] = tables_selected_list
-
-#     result = db.session.execute(sql_tables, params)
-
-#     for row in result:
-#         tableName, tableSchema = row
-#         table = Table(tableName, tableSchema)   # adding schema to the table comment
-#         tables[tableName] = table
-#         table.label = f"n{len(tables)}"
-
-#     return tables
-
-
-# def expand_to_include_related_tables(tables):
-#     # This dictionary will temporarily store related tables to fetch later.
-#     related_tables_to_fetch = {}
-
-#     # Iterate over initially fetched tables to find foreign key relationships.
-#     for tableName, table in tables.items():
-#         # Fetch foreign key relationships for the current table.
-#         sql_fk = text("""
-#             SELECT 
-#                 ccu.table_name AS pk_table_name, 
-#                 ccu.table_schema AS pk_table_schema
-#             FROM 
-#                 information_schema.table_constraints AS tc 
-#                 JOIN information_schema.key_column_usage AS kcu 
-#                 ON tc.constraint_name = kcu.constraint_name AND tc.table_schema = kcu.table_schema AND tc.table_name = kcu.table_name
-#                 JOIN information_schema.constraint_column_usage AS ccu 
-#                 ON ccu.constraint_name = tc.constraint_name
-#             WHERE 
-#                 tc.constraint_type = 'FOREIGN KEY' 
-#                 AND tc.table_name = :table_name
-#         """)
-#         fk_result = db.session.execute(sql_fk, {'table_name': tableName})
-
-        
-#         for referenced_table_name, referenced_schema in fk_result:
-#             if referenced_table_name not in tables and referenced_table_name not in related_tables_to_fetch:
-#                 related_tables_to_fetch[referenced_table_name] = referenced_schema
-
-#     # Fetch and add related tables.
-#     for tableName, tableSchema in related_tables_to_fetch.items():
-#         # Assuming a function fetch_table_details(tableName, tableSchema) that fetches and returns
-#         # a Table object with columns and constraints populated.
-#         table = Table(tableName, tableSchema)
-#         tables[tableName] = table
-
-#     return tables
-
-
-# def fetch_columns_for_tables(tables):
-#     for tableName, table in tables.items():
-#         sql_columns = text("""
-#             SELECT column_name, data_type, is_nullable, column_default
-#             FROM information_schema.columns
-#             WHERE table_name = :table_name;
-#         """)
-#         column_result = db.session.execute(sql_columns, {'table_name': tableName})
-
-#         for col in column_result:
-#             name, datatype, nullable, default = col
-#             column = Column(table, name, '')
-#             column.setDataType({
-#                 "type": datatype,
-#                 "nullable": nullable == 'YES',
-#                 "default": default
-#             })
-#             table.columns.append(column)
-#     return tables  
-
-
-# def fetch_constraints_for_tables(tables):
-#     # Fetching Unique Constraints
-#     for tableName, table in tables.items():
-#         sql_unique = text("""
-#             SELECT kcu.column_name, tc.constraint_name
-#             FROM information_schema.table_constraints AS tc
-#             JOIN information_schema.key_column_usage AS kcu ON tc.constraint_name = kcu.constraint_name
-#             WHERE tc.table_name = :table_name AND tc.constraint_type = 'UNIQUE';
-#         """)
-#         unique_result = db.session.execute(sql_unique, {'table_name': tableName})
-#         for col in unique_result:
-#             name, constraintName = col
-#             column = table.getColumn(name)
-#             if column:
-#                 column.isunique = True
-#                 if constraintName not in table.uniques:
-#                     table.uniques[constraintName] = []
-#                 table.uniques[constraintName].append(column)
-
-
-#     # Primary Keys
-#     for tableName, table in tables.items():
-#         sql_pk = text("""
-#             SELECT kcu.column_name, tc.constraint_name, kcu.ordinal_position
-#             FROM information_schema.table_constraints AS tc
-#             JOIN information_schema.key_column_usage AS kcu ON tc.constraint_name = kcu.constraint_name
-#             WHERE tc.table_name = :table_name AND tc.constraint_type = 'PRIMARY KEY';
-#         """)
-#         pk_result = db.session.execute(sql_pk, {'table_name': tableName})
-#         for col in pk_result:
-#             name, constraintName, ordinal_position = col
-#             column = table.getColumn(name)
-#             if column:
-#                 column.ispk = True
-#                 column.pkconstraint = constraintName
-#                 # Assuming you want to order PKs, though not directly used in provided class
-
-
-#     # Fetching Foreign Keys for each table
-#     for tableName, table in tables.items():
-#         sql_fk = text("""
-#             SELECT 
-#                 tc.constraint_name, 
-#                 tc.table_name AS fk_table_name, 
-#                 kcu.column_name AS fk_column_name, 
-#                 ccu.table_name AS pk_table_name, 
-#                 ccu.column_name AS pk_column_name,
-#                 ccu.table_schema AS pk_table_schema
-#             FROM 
-#                 information_schema.table_constraints AS tc 
-#                 JOIN information_schema.key_column_usage AS kcu 
-#                 ON tc.constraint_name = kcu.constraint_name AND tc.table_schema = kcu.table_schema AND tc.table_name = kcu.table_name
-#                 JOIN information_schema.constraint_column_usage AS ccu 
-#                 ON ccu.constraint_name = tc.constraint_name
-#             WHERE 
-#                 tc.constraint_type = 'FOREIGN KEY' 
-#                 AND tc.table_name = :table_name
-#         """)
-
-#         fk_result = db.session.execute(sql_fk, {'table_name': tableName})
-#         for row in fk_result:
-#             constraintName, fkTableName, fkColumnName, pkTableName, pkColumnName, pkTableSchema = row
-
-#             # Ensure the foreign key table is the current table being processed
-#             if fkTableName != tableName:
-#                 continue
-
-
-#             fkTable = tables.get(fkTableName)
-#             pkTable = tables.get(pkTableName)
-
-#             if fkTable and pkTable:
-#                 fkColumn = fkTable.getColumn(fkColumnName)
-#                 pkColumn = pkTable.getColumn(pkColumnName)
-
-#                 if fkColumn and pkColumn:
-#                     # Here, instead of assigning pkColumn directly, store relevant info
-#                     fkColumn.fkof = pkColumn  # Adjust based on your application's needs
-#                     if constraintName not in fkTable.fks:
-#                         fkTable.fks[constraintName] = []
-#                     fkTable.fks[constraintName].append(fkColumn)
-#     return tables
-
-
-# def createGraph(tables, theme, showColumns, showTypes, useUpperCase):
-#     s = ('digraph {\n'
-#         + '  graph [ rankdir="LR" bgcolor="#ffffff" ]\n'
-#         + f'  node [ style="filled" shape="{theme.shape}" gradientangle="180" ]\n'
-#         + '  edge [ arrowhead="none" arrowtail="none" dir="both" ]\n\n')
-
-#     for name in tables:
-#         s += tables[name].getDotShape(theme, showColumns, showTypes, useUpperCase)
-#     s += "\n"
-#     for name in tables:
-#         s += tables[name].getDotLinks(theme)
-#     s += "}\n"
-#     return s
-
-
-# def generate_erd(graph_DOT):
-#     graph_module = pydot.graph_from_dot_data(graph_DOT)
-#     graph = graph_module[0]
-#     png_image_data = graph.create_png()
-#     encoded_image = base64.b64encode(png_image_data).decode('utf-8')
-#     return encoded_image
-
-
-# def getThemes():
-#     return {
-#         "Common Gray": Theme("#6c6c6c", "#e0e0e0", "#f5f5f5",
-#             "#e0e0e0", "#000000", "#000000", "rounded", "Mrecord", "#696969", "1"),
-#         "Blue Navy": Theme("#1a5282", "#1a5282", "#ffffff",
-#             "#1a5282", "#000000", "#ffffff", "rounded", "Mrecord", "#0078d7", "2"),
-#         #"Gradient Green": Theme("#716f64", "#008080:#ffffff", "#008080:#ffffff",
-#         #    "transparent", "#000000", "#000000", "rounded", "Mrecord", "#696969", "1"),
-#         #"Blue Sky": Theme("#716f64", "#d3dcef:#ffffff", "#d3dcef:#ffffff",
-#         #    "transparent", "#000000", "#000000", "rounded", "Mrecord", "#696969", "1"),
-#         "Common Gray Box": Theme("#6c6c6c", "#e0e0e0", "#f5f5f5",
-#             "#e0e0e0", "#000000", "#000000", "rounded", "record", "#696969", "1")
-#     }
-
-
-# if __name__ == "__main__":
-#     app.run(port=5001)
-
-
-# class Theme:
-#     def __init__(self, color, fillcolor, fillcolorC,
-#             bgcolor, icolor, tcolor, style, shape, pencolor, penwidth):
-#         self.color = color
-#         self.fillcolor = fillcolor
-#         self.fillcolorC = fillcolorC
-#         self.bgcolor = bgcolor
-#         self.icolor = icolor
-#         self.tcolor = tcolor
-#         self.style = style
-#         self.shape = shape
-#         self.pencolor = pencolor
-#         self.penwidth = penwidth
-
-
-# class Table:
-#     def __init__(self, name, comment):
-#         self.name = name
-#         self.comment = comment if comment is not None and comment != 'None' else ''
-#         self.label = None
-
-#         self.columns = []           # list of all columns
-#         self.uniques = {}           # dictionary with UNIQUE constraints, by name + list of columns
-#         self.pks = []               # list of PK columns (if any)
-#         self.fks = {}               # dictionary with FK constraints, by name + list of FK columns
-
-
-#     @classmethod
-#     def getClassName(cls, name, useUpperCase, withQuotes=True):
-#         if re.match("^[A-Z_0-9]*$", name) == None:
-#             return f'"{name}"' if withQuotes else name
-#         return name.upper() if useUpperCase else name.lower()
-
-#     def getName(self, useUpperCase, withQuotes=True):
-#         return Table.getClassName(self.name, useUpperCase, withQuotes)
-
-#     def getColumn(self, name):
-#         for column in self.columns:
-#             if column.name == name:
-#                 return column
-#         return None
-
-#     def getDotShape(self, theme, showColumns, showTypes, useUpperCase):
-#         fillcolor = theme.fillcolorC if showColumns else theme.fillcolor
-#         colspan = "2" if showTypes else "1"
-#         tableName = self.getName(useUpperCase, False)
-
-#         s = (f'  {self.label} [\n'
-#             + f'    fillcolor="{fillcolor}" color="{theme.color}" penwidth="1"\n'
-#             + f'    label=<<table style="{theme.style}" border="0" cellborder="0" cellspacing="0" cellpadding="1">\n'
-#             + f'      <tr><td bgcolor="{theme.bgcolor}" align="center"'
-#             + f' colspan="{colspan}"><font color="{theme.tcolor}"><b>{tableName}</b></font></td></tr>\n')
-
-#         if showColumns:
-#             for column in self.columns:
-#                 name = column.getName(useUpperCase, False)
-#                 if column.ispk: name = f"<u>{name}</u>"
-#                 if column.fkof != None: name = f"<i>{name}</i>"
-#                 if column.nullable: name = f"{name}*"
-#                 if column.identity: name = f"{name} I"
-#                 if column.isunique: name = f"{name} U"
-#                 datatype = column.datatype
-#                 if useUpperCase: datatype = datatype.upper()
-
-#                 if showTypes:
-#                     s += (f'      <tr><td align="left"><font color="{theme.icolor}">{name}&nbsp;</font></td>\n'
-#                         + f'        <td align="left"><font color="{theme.icolor}">{datatype}</font></td></tr>\n')
-#                 else:
-#                     s += f'      <tr><td align="left"><font color="{theme.icolor}">{name}</font></td></tr>\n'
-
-#         return s + '    </table>>\n  ]\n'
-
-
-#     def getDotLinks(self, theme):
-#         s = ""
-#         for constraint in self.fks:
-#             fks = self.fks[constraint]
-#             fk1 = fks[0]
-#             dashed = "" if not fk1.nullable else ' style="dashed"'
-#             arrow = "" if fk1.ispk and len(self.pks) == len(fk1.fkof.table.pks) else ' arrowtail="crow"'
-#             s += (f'  {self.label} -> {fk1.fkof.table.label}'
-#                 + f' [ penwidth="{theme.penwidth}" color="{theme.pencolor}"{dashed}{arrow} ]\n')
-#         return s
-    
-
-# class Column:
-#     def __init__(self, table, name, comment):
-#         self.table = table
-#         self.name = name
-#         self.comment = comment if comment is not None and comment != 'None' else ''
-#         self.nullable = True
-#         self.datatype = None        # with (length, or precision/scale)
-#         self.identity = False
-
-#         self.isunique = False
-#         self.ispk = False
-#         self.pkconstraint = None
-#         self.fkof = None            # points to the PK column on the other side
-
-
-#     def getName(self, useUpperCase, withQuotes=True):
-#         return Table.getClassName(self.name, useUpperCase, withQuotes)
-
-
-#     def setDataType(self, datatype):
-#         self.datatype = datatype["type"]
-#         self.nullable = bool(datatype["nullable"])
-
-#         if self.datatype == "FIXED":
-#             self.datatype = "NUMBER"
-#         elif "fixed" in datatype:
-#             fixed = bool(datatype["fixed"])
-#             if self.datatype == "TEXT":
-#                 self.datatype = "CHAR" if fixed else "VARCHAR"
-
-#         if "length" in datatype:
-#             self.datatype += f"({str(datatype['length'])})"
-#         elif "scale" in datatype:
-#             if int(datatype['precision']) == 0:
-#                 self.datatype += f"({str(datatype['scale'])})"
-#                 if self.datatype == "TIMESTAMP_NTZ(9)":
-#                     self.datatype = "TIMESTAMP"
-#             elif "scale" in datatype and int(datatype['scale']) == 0:
-#                 self.datatype += f"({str(datatype['precision'])})"
-#                 if self.datatype == "NUMBER(38)":
-#                     self.datatype = "INT"
-#                 elif self.datatype.startswith("NUMBER("):
-#                     self.datatype = f"INT({str(datatype['precision'])})"
-#             elif "scale" in datatype:
-#                 self.datatype += f"({str(datatype['precision'])},{str(datatype['scale'])})"
-#                 #if column.datatype.startswith("NUMBER("):
-#                 #    column.datatype = f"FLOAT({str(datatype['precision'])},{str(datatype['scale'])})"
-#         self.datatype = self.datatype.lower()
\ No newline at end of file
+    app.run(debug=True)
\ No newline at end of file
diff --git a/my_flask_app/models/__pycache__/models.cpython-39.pyc b/my_flask_app/models/__pycache__/models.cpython-39.pyc
index c934da4ed83aa67dbcb94493d6d76507c6c13579..85c8c24503febc2cee3793115e586cf4f4bf73ef 100644
Binary files a/my_flask_app/models/__pycache__/models.cpython-39.pyc and b/my_flask_app/models/__pycache__/models.cpython-39.pyc differ
diff --git a/my_flask_app/models/models.py b/my_flask_app/models/models.py
index f19dfeff392718ba0cb3f7fe50e01a2b2f70d669..f01eeb36ba9657d8d40b20a327537ccb37de939e 100644
--- a/my_flask_app/models/models.py
+++ b/my_flask_app/models/models.py
@@ -4,9 +4,10 @@ import re
 
 
 class Observation_Spec:
-    def __init__(self, type:str, label:str, features_name:list = None):
+    def __init__(self, tablename:str, type:str, label:list[str], features_name:list = None):
+        self.tablename = tablename
         self.type = type    # 'event' or 'measurement'
-        self.label = label
+        self.label = label  # (self-define or from column, column name, column value orself-define label)
         self.features_name = features_name if features_name else []
 
     def add_feature(self, name):
@@ -17,6 +18,7 @@ class Observation_Spec:
 
     def to_dict(self):
         return {
+            'tablename': self.tablename,
             'type': self.type,
             'label': self.label,
             'features_name': self.features_name
diff --git a/my_flask_app/templates/app.html b/my_flask_app/templates/app.html
index 0d04707fd7ee6f9c22619b10b03f8d00a8363030..d22226f200239a8c725e41f6fc2aad23afbf4e7b 100644
--- a/my_flask_app/templates/app.html
+++ b/my_flask_app/templates/app.html
@@ -106,6 +106,8 @@
             padding: 0;
             margin-top: 0px;
             border: none;
+            border-top-right-radius: 5px;
+            border-bottom-right-radius: 5px;
         }
         .custom-zoom-button {
             font-size: 14px;
@@ -115,6 +117,7 @@
             background-color: rgba(173, 216, 230, 0.5);
             padding: 0;
             border: none; /* Remove border to make it seamless */
+            border-radius: 5px;
         }
         button { width: 80%; }
         .headerButton {
@@ -279,6 +282,7 @@
             position: sticky;
             top: 0;
         }
+
     </style>
 </head>
 <body>
@@ -487,6 +491,13 @@
                             </div>
                         </div>
 
+
+                        <div class="mb-3" id="self-defined-object-selection" style="display: none; border-bottom: 1px dashed black;">
+                            <label class="form-label">Self-defined Object</label><br>
+                            <input type="text" id="defined-object" class="form-control headerSelect">
+                            <button class="btn btn-primary headerButton" onclick="selfdefinedObject()">add</button>
+                        </div>
+
                         <div class="mb-3" id="object-column-selection" style="display: none;">
                             <label class="form-label">Object name</label><br>
                             <select id="select_column_object" class="form-select headerSelect" name="column" style="margin-right: 5px; display: inline;">
@@ -512,7 +523,7 @@
                             {% endfor %}
                             </select>
 
-                            <select id=label_values class="form-select headerSelect " style="margin-top: 2px; margin-right: 5px; display: inline;">
+                            <select id='label_values' class="form-select headerSelect " style="margin-top: 2px; margin-right: 5px; display: inline;">
                                 <option>Label select...</option>
                                 <optgroup id="defined_label_values" label="self-defined label">
                                 {% for self_label in self_labels %}
@@ -550,87 +561,88 @@
 
             <li>
                 <div style="display: flex; flex-direction: column; height: 87vh;">
-                    <div class="table-container" style="flex: 1; overflow-y: auto;">
-                        <table class="uk-table uk-table-striped" style="overflow-y: scroll;">
+                    <div class="mb-3">
+                        <h4 style="display: inline; margin-left: .2em;">Data Header Table</h4>
+                        <button type="submit" class="btn btn-primary uk-button-small headerButton" style="margin-top: -3px;" onclick="resetDataHeaderTable()">Reset</button>
+                    </div>
+                    <div class="uk-overflow-auto" id="data-header-table" style="flex-grow: 1; overflow-y: auto; max-height: max-content; margin-top: -20px;">
+                        <table class='uk-table uk-table-small uk-table-hover uk-table-divider'>
                             <thead>
                                 <tr>
-                                    <th>Table Heading</th>
-                                    <th>Table Heading</th>
-                                    <th>Table Heading</th>
+                                    <th></th>
+                                    <th>Table name</th>
+                                    <th>Type</th>
+                                    <th>Label</th>
                                 </tr>
                             </thead>
-                            <tbody>
-                                <tr>
-                                    <td>Table Data</td>
-                                    <td>Table Data</td>
-                                    <td>Table Data</td>
-                                </tr>
-                                <tr>
-                                    <td>Table Data</td>
-                                    <td>Table Data</td>
-                                    <td>Table Data</td>
-                                </tr>
-                                <tr>
-                                    <td>Table Data</td>
-                                    <td>Table Data</td>
-                                    <td>Table Data</td>
+                        </table>
+                    </div>
+                    <div class="mb-3">
+                        <h4 style="display: inline; margin-left: .2em;">Machine Data Table (LIMIT 500)</h4>
+                        <button type="submit" class="btn btn-primary uk-button-small headerButton" style="margin-top: -3px;" onclick="resetMachineDataTable()">Reset</button>
+                    </div>
+                    <div class="uk-overflow-auto" id="machine-data-table" style="flex-grow: 1; overflow-y: auto; max-height: max-content; margin-top: -20px;" >
+                        <table  id="MD-table" class="uk-table uk-table-hover uk-table-small uk-table-middle uk-table-divider uk-table-striped" style="cursor: pointer;">
+                            <thead>
+                                <tr class="uk-table-middle">
+                                    <th class="uk-table-shrink">
+                                        <input class="uk-checkbox" onclick="click_all_MD_table(this)" type="checkbox" aria-label="Checkbox" style="margin-top: 7px;">
+                                    </th>
+
+                                    <th data-id="time" class="uk-table-expand">
+                                        <span style="display: flex; flex-direction: row; margin-bottom: -4px;">
+                                            time
+                                            <select id="table_select_time"  class="time-object-select" style="width: 80px; height: 20px; margin-top: -3px; margin-left: 3px;">
+                                                <option>Select a data header first...</option>
+                                            </select>
+                                        </span>
+                                    </th>
+
+                                    <th data-id="object" class="uk-table-expand">
+                                        <span style="display: flex; flex-direction: row; margin-bottom: -4px;">
+                                            object
+                                            <select id="table_object" class="time-object-select" style="width: 80px; height: 20px; margin-top: -3px; margin-left: 3px;">
+                                                <option value="no">Select a data header first...</option>
+                                                
+                                                <optgroup id="defined_object_values" label="self-defined object">
+                                                </optgroup>
+
+                                                <optgroup id="table_select_object" label="object column">             
+                                                </optgroup >
+                                            </select>
+                                            
+                                        </span>
+                                    </th>
+
+                                    <th data-id="type" class="uk-width-small">type</th>
+                                    <th data-id="label" class="uk-table-expand">label</th>
+                                    <th data-id="segment" class="uk-table-expand">segment</th>
+                                    <th data-id="index" class="uk-table-expand">index</th>
+                                    
+                                    <th data-id="starttime" class="uk-table-expand">
+                                        <span style="display: flex; flex-direction: row; margin-bottom: -4px;">
+                                            start time
+                                            <select id="starttime-select" style="width: 80px; height: 20px; margin-top: -3px; margin-left: 3px;">
+                                                <option val="no">Select a column first...</option>
+                                            </select>
+                                        </span>
+                                    </th>
+
+                                    <th data-id="endtime" class="uk-table-expand">
+                                        <span style="display: flex; flex-direction: row; margin-bottom: -4px;">
+                                            end time
+                                            <select id="endtime-select" style="width: 80px; height: 20px; margin-top: -3px; margin-left: 3px;">
+                                                <option val="no">Select a column first...</option>
+                                            </select>
+                                        </span>
+                                    </th>
                                 </tr>
+                            </thead>
+                            <tbody>
+                                
                             </tbody>
                         </table>
                     </div>
-                    <div class="table-container" style="flex: 1; overflow-y: auto;">
-                        <div class="uk-overflow-auto">
-                            <table class="uk-table uk-table-hover uk-table-middle uk-table-divider" style="overflow-y: scroll;">
-                                <thead>
-                                    <tr>
-                                        <th class="uk-table-shrink"></th>
-                                        <th class="uk-table-shrink">Preserve</th>
-                                        <th class="uk-table-expand">Expand + Link</th>
-                                        <th class="uk-width-small">Truncate</th>
-                                        <th class="uk-table-shrink uk-text-nowrap">Shrink + Nowrap</th>
-                                    </tr>
-                                </thead>
-                                <tbody>
-                                    <tr>
-                                        <td><input class="uk-checkbox" type="checkbox" aria-label="Checkbox"></td>
-                                        <td><img class="uk-preserve-width uk-border-circle" src="images/avatar.jpg" width="40" height="40" alt=""></td>
-                                        <td class="uk-table-link">
-                                            <a class="uk-link-reset" href="">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.</a>
-                                        </td>
-                                        <td class="uk-text-truncate">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.</td>
-                                        <td class="uk-text-nowrap">Lorem ipsum dolor</td>
-                                    </tr>
-                                    <tr>
-                                        <td><input class="uk-checkbox" type="checkbox" aria-label="Checkbox"></td>
-                                        <td><img class="uk-preserve-width uk-border-circle" src="images/avatar.jpg" width="40" height="40" alt=""></td>
-                                        <td class="uk-table-link">
-                                            <a class="uk-link-reset" href="">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.</a>
-                                        </td>
-                                        <td class="uk-text-truncate">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.</td>
-                                        <td class="uk-text-nowrap">Lorem ipsum dolor</td>
-                                    </tr>
-                                    <tr>
-                                        <td><input class="uk-checkbox" type="checkbox" aria-label="Checkbox"></td>
-                                        <td><img class="uk-preserve-width uk-border-circle" src="images/avatar.jpg" width="40" height="40" alt=""></td>
-                                        <td class="uk-table-link">
-                                            <a class="uk-link-reset" href="">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.</a>
-                                        </td>
-                                        <td class="uk-text-truncate">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.</td>
-                                        <td class="uk-text-nowrap">Lorem ipsum dolor</td>
-                                    </tr>
-                                    <tr>
-                                        <td><input class="uk-checkbox" type="checkbox" aria-label="Checkbox"></td>
-                                        <td><img class="uk-preserve-width uk-border-circle" src="images/avatar.jpg" width="40" height="40" alt=""></td>
-                                        <td class="uk-table-link">
-                                            <a class="uk-link-reset" href="">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.</a>
-                                        </td>
-                                        <td class="uk-text-truncate">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.</td>
-                                        <td class="uk-text-nowrap">Lorem ipsum dolor</td>
-                                    </tr>
-                                </tbody>
-                            </table>
-                        </div>
-                    </div>
                 </div>
             </li>
         </ul>
@@ -655,32 +667,109 @@
 
     <div id="sidebar2">
         <ul uk-accordion>
-            <li class="uk-open">
-                <a class="uk-accordion-title" href="#">Item 1</a>
-                <div class="uk-accordion-content">
-                    <p>Content for item 1.</p>
-                </div>
-            </li>
             <li>
-                <a class="uk-accordion-title" href="#">Item 2</a>
+                <a class="uk-accordion-title" href="#">Filter</a>
                 <div class="uk-accordion-content">
-                    <p>Content for item 2.</p>
+
+                    <div class="accordion">
+                        <div class="accordion-item">
+                          <h2 class="accordion-header">
+                            <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseTwo" aria-expanded="true" aria-controls="collapseTwo">
+                              Time
+                            </button>
+                          </h2>
+                          <div id="collapseTwo" class="accordion-collapse collapse" data-bs-parent="#accordionExample">
+                            <div class="accordion-body">
+                                <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
+                                <script src="//code.jquery.com/jquery-3.6.0.min.js"></script>
+                                <script src="//code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
+
+                                <p style="margin: -4px -21px 5px -17px; padding: 0px;">
+                                    <label for="amount1">From: </label><br>
+                                    <input type="text" id="amount1" class="form-control" style="display: flex; border: 0; color: #5ea9e2; font-weight:bold;"><br>
+                                    <label for="amount2">Until: </label><br>
+                                    <input type="text" id="amount2" class="form-control" style="border:0; color: #5ea9e2; font-weight:bold;">
+                                </p>
+                                <div id="slider-range"></div>
+                                <button type="submit" class="btn btn-primary headerButton" style="margin: 10px 0px -5px -10px;" onclick="filter_ME_data_table()">Submit</button>
+                            </div>
+                          </div>
+                        </div>
+                    </div>
+        
                 </div>
             </li>
         </ul>
 
-        <!-- set_database.html
-        <form method="post" action="/">
-            <div class="mb-3">
-                <label for="exampleInputPassword1" name="database_uri" class="form-label">Database URI</label>
-                <input type="text" class="form-control" id="exampleInputPassword1" name="database_uri" placeholder="Enter Database URI">
-                <button type="submit" class="btn btn-primary">Submit</button>
-            </div>
-        </form> -->
 
+        
         <div id="resize-handle-left" class="resize-handle-left"></div>
     </div> 
+
     <script>
+        var jq = jQuery.noConflict();
+        function initializeSlider(minDatetime, maxDatetime) {
+            // Default values if min or max datetime is not provided
+            var defaultMinDatetime = '2022-11-01 16:00:00.000000+00:00';
+            var defaultMaxDatetime = '2022-11-02 16:00:00.000000+00:00';
+
+            // Use default values if min or max datetime is empty
+            minDatetime = minDatetime || defaultMinDatetime;
+            maxDatetime = maxDatetime || defaultMaxDatetime;
+            
+            // Function to parse date string with milliseconds
+            function parseDateTime(str) {
+                var date = new Date(str);
+                if (isNaN(date.getTime())) {
+                    console.error('The datetime format is incorrect:', str);
+                    return null;
+                }
+                return date;
+            }
+
+            function toTimestamp(strDate) {
+                var date = parseDateTime(strDate);
+                return date ? date.getTime() : null;
+            }
+
+
+            // Function to format date to string with milliseconds
+            function formatDateTime(date) {
+                var hours = ('0' + date.getHours()).slice(-2);
+                var minutes = ('0' + date.getMinutes()).slice(-2);
+                var seconds = ('0' + date.getSeconds()).slice(-2);
+
+                return jq.datepicker.formatDate('yy-mm-dd', date) +
+                    ' ' + hours + ':' +
+                    minutes + ':' +
+                    seconds;
+            }
+
+            // Initialize the slider with dynamic datetime values
+            console.log("initialize slider with dynamic datetime values");
+            jq("#slider-range").slider({
+                range: true,
+                min: toTimestamp(minDatetime), // Use minDatetime from the server
+                max: toTimestamp(maxDatetime), // Use maxDatetime from the server
+                step: 1, // Step is now 1 millisecond
+                values: [
+                    toTimestamp(minDatetime), // Set the lower handle to minDatetime
+                    toTimestamp(maxDatetime) // Set the upper handle to maxDatetime
+                ],
+                slide: function(event, ui) {
+                    var startDateTime = new Date(ui.values[0]);
+                    var endDateTime = new Date(ui.values[1]);
+                    jq("#amount1").val(formatDateTime(startDateTime));
+                    jq("#amount2").val(formatDateTime(endDateTime));
+                }
+            });
+        }
+
+
+        
+
+
+
         // function select_schema(){
         //     document.getElementById('schemaSelect').addEventListener('changed', function() {
         //         var selectedSchema = this.value;
@@ -747,20 +836,322 @@
         //     });
         // }
 
+        function click_all_MD_table(element) {
+            var checkboxes = document.querySelectorAll('#MD-table tbody input[type="checkbox"]');
+            checkboxes.forEach(function(checkbox) {
+                checkbox.checked = element.checked;
+            });
+        }
+
+        
+        function resetMachineDataTable() {
+            const table = document.getElementById('MD-table');
+            table.querySelector('tbody').innerHTML = ""
+        }
+        
+
+        function getRowData(r) {
+            r.parentNode.querySelectorAll("tr").forEach(function(t) {
+                t.style.backgroundColor = "white";
+            });
+            var value = r.innerHTML;
+            r.style.backgroundColor = "#5ea9e2";
+            const type = r.querySelectorAll("td")[2].innerHTML; // type: M, E, S, SD
+            var numColumns = r.querySelectorAll("td").length;
+
+            const table = document.getElementById('MD-table');
+            table.querySelector('tbody').innerHTML = ""
+
+            var tr = document.getElementById('MD-table').getElementsByTagName('tr')[0];
+            var ths = Array.from(tr.querySelectorAll("th")); 
+            // Start from the end of the NodeList and move backward
+            for (var i = ths.length - 1; i > 0; i--) {
+                if (i > 8) {
+                    ths[i].remove(); // Remove the <th> element
+                } else {
+                    // Safe to apply style because ths[i] exists
+                    ths[i].style.display = "none";
+                }
+            }
+
+            if (type == "M" || type == "E") {
+                [1, 2, 3, 4].forEach(k => {
+                    tr.querySelectorAll("th")[k].style.display = "table-cell";
+                });
+                for (let i = 1; i <= numColumns - 4; i++) {
+                    let th = tr.appendChild(document.createElement('th'));
+                    th.classList.add("uk-table-shrink");
+                    th.innerHTML = "F_" + i;
+                }
+            } else if (type == "S") {
+                [2, 4, 6, 7, 8].forEach(k => {
+                    tr.querySelectorAll("th")[k].style.display = "table-cell";
+                });
+            } else if (type == "SD") {
+                [2, 4, 5, 6].forEach(k => {
+                    tr.querySelectorAll("th")[k].style.display = "table-cell";
+                });
+                for (let i = 1; i <= numColumns - 4; i++) {
+                    let th = tr.appendChild(document.createElement('th'));
+                    th.classList.add("uk-table-shrink");
+                    th.innerHTML = "F_" + i;
+                }
+            }
+
+            fetch('/get-MD-info', {
+                method: 'POST',
+                body: JSON.stringify({ 'value': value }),
+                headers: {
+                    'Content-Type': 'application/json'
+                }
+            })
+            .then(response => response.json())
+            .then(data => {
+                // Set all the select elements to the default value
+                var selectTime = document.getElementById('table_select_time');
+                selectTime.value = "no";
+                var selectObject = document.getElementById('table_object');
+                selectObject.value = "no";
+                
+                //////////////////////////////////////////////////////////////////////////
+                if (type == "M" || type == "E") {
+                    // Update the time select with the new time columns
+                    const selectTime = document.getElementById('table_select_time');
+                    selectTime.innerHTML = '';  // Clear existing options
+                    const init = document.createElement('option');
+                    init.value = "no";
+                    init.textContent = "Select a column...";
+                    selectTime.appendChild(init);
+                    data['time'].forEach(label_value => {
+                        const optionElement = document.createElement('option');
+                        optionElement.value = label_value;
+                        optionElement.textContent = label_value;
+                        selectTime.appendChild(optionElement);  
+                    });
+                    // Update the object select with the new object columns
+                    const selectObject = document.getElementById('table_select_object');
+                    selectObject.innerHTML = '';  // Clear existing options
+                    data['object'].forEach(label_value => {
+                        const optionElement = document.createElement('option');
+                        optionElement.value = label_value;
+                        optionElement.textContent = label_value;
+                        selectObject.appendChild(optionElement);  
+                    });
+                } else if (type == "S") {
+                } else if (type == "SD") {
+                }
+            })
+            .catch(error => {
+                // Handle any error that occurred during the fetch
+                console.error('Error:', error);
+            });
+        }
+
+
+
+        // Select only the specified select elements
+        const time_object_selects = document.querySelectorAll('.time-object-select');
+
+        function checkSelects() {
+        for (let select of time_object_selects) {
+            if (select.value === 'no') {
+            return false; // If any watched select is not chosen, return false
+            }
+        }
+        return true; // If all watched selects have a value, return true
+        }
+
+        time_object_selects.forEach(select => {
+        select.addEventListener('change', () => {
+            if (checkSelects()) {
+                var $ = function(id) { return document.getElementById(id); };
+                // All specified selects have a value, call the fetch function
+                var time_column = document.getElementById('table_select_time').value;
+                var object_column = document.getElementById('table_object').value;
+
+                var selectedOption = $("table_object").options[$("table_object").selectedIndex]; // Get the selected option
+                var optgroupLabel = selectedOption.parentNode.label;   // Get the label of the optgroup
+                if (optgroupLabel == "self-defined object") {
+                    optgroupLabel = "self";
+                } else if (optgroupLabel == "object column") {
+                    optgroupLabel = "col";
+                }
+                console.log(optgroupLabel);
+                console.log(object_column);
+                console.log(time_column);
+
+                fetch('/get-ME-table', {
+                    method: 'POST',
+                    body: JSON.stringify({ 'time_column': time_column, 'object_column': object_column, 'optgroupLabel': optgroupLabel }),
+                    headers: {
+                        'Content-Type': 'application/json'
+                    }
+                })
+                .then(response => response.json())
+                .then(data => {
+                    console.log(data['table_HTML']);
+                    const table = document.getElementById('MD-table');
+                    table.querySelector('tbody').innerHTML = ""
+                    table.querySelector('tbody').innerHTML = data['table_HTML'];
+
+                    if ('min_datetime' in data && 'max_datetime' in data) {
+                        // Initialize the slider with the min and max datetime from the server
+                        console.log("initialize slider with min and max datetime from the server");
+                        initializeSlider(data['min_datetime'], data['max_datetime']);
+                    }
+                })
+                .catch(error => {
+                    // Handle any error that occurred during the fetch
+                    console.error('Error:', error);
+                });
+            }
+        });
+        });
+
+        function filter_ME_data_table() {
+            var $ = function(id) { return document.getElementById(id); };
+            // Get min and max datetime from the slider
+            var minDatetime = $("amount1").value;
+            var maxDatetime = $("amount2").value;
+
+            // All specified selects have a value, call the fetch function
+            var time_column = document.getElementById('table_select_time').value;
+            var object_column = document.getElementById('table_object').value;
+
+            var selectedOption = $("table_object").options[$("table_object").selectedIndex]; // Get the selected option
+            var optgroupLabel = selectedOption.parentNode.label;   // Get the label of the optgroup
+            if (optgroupLabel == "self-defined object") {
+                optgroupLabel = "self";
+            } else if (optgroupLabel == "object column") {
+                optgroupLabel = "col";
+            }
+            console.log(optgroupLabel);
+            console.log(object_column);
+            console.log(time_column);
+
+            fetch('/get-ME-table', {
+                method: 'POST',
+                body: JSON.stringify({ 'time_column': time_column, 'object_column': object_column, 'optgroupLabel': optgroupLabel, 'minDatetime': minDatetime, 'maxDatetime': maxDatetime}),
+                headers: {
+                    'Content-Type': 'application/json'
+                }
+            })
+            .then(response => response.json())
+            .then(data => {
+                console.log(data['table_HTML']);
+                const table = document.getElementById('MD-table');
+                table.querySelector('tbody').innerHTML = ""
+                table.querySelector('tbody').innerHTML = data['table_HTML'];
+            })
+            .catch(error => {
+                // Handle any error that occurred during the fetch
+                console.error('Error:', error);
+            });
+        }
+
+        function selfdefinedObject() {
+            var object = document.getElementById('defined-object').value;
+            var select = document.getElementById('defined_object_values');
+            var opt = document.createElement('option');
+            opt.value = object;
+            opt.innerHTML = object;
+            select.appendChild(opt);
+        }
+
+
+        function deleteRow1(event, r) {
+            event.stopPropagation(); // Stop the event from bubbling up to the <tr>
+            var i = r.parentNode.parentNode.rowIndex;
+            var table = r.closest("table");  // Find the closest table ancestor
+            table.deleteRow(i);
+            // var divv = document.getElementById("data-header-table");
+            // divv.getElementsByTagName("table")[0].deleteRow(i);
+
+            var value = r.parentNode.parentNode.innerHTML
+            
+            console.log(value);
+            console.log("YYYYY");
+            fetch('/delete-data-header', {
+                method: 'POST',
+                body: JSON.stringify({ 'value': value }),
+                headers: {
+                    'Content-Type': 'application/json'
+                }
+            })
+            .then(response => response.json())
+            .then(data => {
+                const table = document.getElementById('data-header-table');
+                table.innerHTML = data['data_header_table'];
+            })
+            .catch(error => {
+                // Handle any error that occurred during the fetch
+                console.error('Error:', error);
+            });
+
+        }
+
+
+        function resetDataHeaderTable() {
+            fetch('/reset-data-header-table', {
+                method: 'POST',
+                headers: {
+                    'Content-Type': 'application/json'
+                }
+            })
+            .then(response => response.json())
+            .then(data => {
+                const table = document.getElementById('data-header-table');
+                table.innerHTML = data['data_header_table'];
+                // "<table class='uk-table uk-table-small uk-table-hover uk-table-divider'><thead><tr><th>Table name</th><th>Type</th><th>Label</th></tr></thead></table>";
+            })
+            .catch(error => {
+                // Handle any error that occurred during the fetch
+                console.error('Error:', error);
+            });
+        }
+
+
+        function initializeDataHeaderTable() {
+            fetch('/init-data-header-table', {
+                method: 'POST',
+                headers: {
+                    'Content-Type': 'application/json'
+                }
+            })
+            .then(response => response.json())
+            .then(data => {
+                const table = document.getElementById('data-header-table');
+                table.innerHTML = data['data_header_table'];
+                // "<table class='uk-table uk-table-small uk-table-hover uk-table-divider'><thead><tr><th>Table name</th><th>Type</th><th>Label</th></tr></thead></table>";
+            })
+            .catch(error => {
+                // Handle any error that occurred during the fetch
+                console.error('Error:', error);
+            });
+        }
+
 
         function submitDataHeader() {
             var $ = function(id) { return document.getElementById(id); };
             var isValid = true;
 
             var radioSelect = document.querySelector('input[name="radio1"]:checked');
-            console.log(radioSelect.value);
-            var label = $("label_values").value;
-            console.log(label);
+
+            var label_column = $("select_column").value;
+            var label = $("label_values").value; 
+            var selectedOption = $("label_values").options[$("label_values").selectedIndex]; // Get the selected option
+            var optgroupLabel = selectedOption.parentNode.label;   // Get the label of the optgroup
+            if (optgroupLabel == "label column data") {
+                optgroupLabel = "col";
+            } else if (optgroupLabel == "self-defined label") {
+                optgroupLabel = "self";
+            }
+            var label_list = ' [" ' + optgroupLabel + ' "," ' + label_column + ' "," ' +  label + ' "] ';
+
             var object_column = $("select_column_object").value;
-            console.log(object_column);
+
             var tmp = $("select_features").selectedOptions;
             var features_list = Array.from(tmp).map(({ value }) => value);
-            console.log(features_list);
 
             if (radioSelect.value == 'measurement') {
                 if (label == 'Label select...' || label == null || label == "") {
@@ -836,20 +1227,22 @@
             $("span").nextElementSibling.textContent = "*";
             $("select_column_object").nextElementSibling.textContent = "*";
 
-            console.log("HERE");
-            console.log(radioSelect, label, object_column, features_list);
+
 
             // Send the value to the server with fetch API
             fetch('/add-data-header', {
                 method: 'POST',
-                body: JSON.stringify({ 'type': radioSelect.value, 'label': label, 'object_column': object_column, 'value_list': features_list}),
+                body: JSON.stringify({ 'type': radioSelect.value, 'label': label_list, 'object_column': object_column, 'value_list': features_list}),
                 headers: {
                     'Content-Type': 'application/json'
                 }
             })
             .then(response => response.json())
             .then(data => {
-                
+                if (radioSelect.value != 'object') {
+                    const table = document.getElementById('data-header-table');
+                    table.innerHTML = data['data_header_table'];
+                }
             })
             .catch(error => {
                 // Handle any error that occurred during the fetch
@@ -1136,6 +1529,7 @@
                 var objectType = document.getElementById('objectType');
 
                 var featuresSelection = document.getElementById('featuresSelection');
+                var selfdefinedObject = document.getElementById('self-defined-object-selection');
                 var objectSelection = document.getElementById('object-column-selection');
                 var selfdefinedlabelSelection = document.getElementById('self-defined-label-selection');
                 var labelSelection = document.getElementById('label-selection');
@@ -1143,22 +1537,26 @@
                 if (segmentType.checked && radio.value === "segment") {
                     featuresSelection.style.display = 'none';
                     objectSelection.style.display = 'none';
+                    selfdefinedObject.style.display = 'none';
                     selfdefinedlabelSelection.style.display = 'block';
                     labelSelection.style.display = 'block';
                 } else if (objectType.checked && objectType.value === "object"){
                     featuresSelection.style.display = 'none';
                     objectSelection.style.display = 'block';
+                    selfdefinedObject.style.display = 'block';
                     selfdefinedlabelSelection.style.display = 'none';
                     labelSelection.style.display = 'none';
                 } else {
                     featuresSelection.style.display = 'block';
                     objectSelection.style.display = 'none';
+                    selfdefinedObject.style.display = 'none';
                     selfdefinedlabelSelection.style.display = 'block';
                     labelSelection.style.display = 'block';
                 }
             });
         });
 
+
         document.addEventListener('DOMContentLoaded', function() {
             // Show the ERD canvas
             showErdCanvas("erdCanvas1", "zoomInBtn1", "zoomOutBtn1", '{{ image1 }}');
@@ -1171,6 +1569,9 @@
             makeTerminalResizable();
             toggleTerminal();
 
+            // Initialize the data header table
+            initializeDataHeaderTable();
+
             // Listen for the 'added' event on the target sortable list
             UIkit.util.on('#dropped_items', 'added removed', function (event) {
                 var item = event.detail[1]; // Adjusted to access the second item