55
66
77class SQLDb :
8+ """
9+ SQLite database handler for managing TSNE data visualization points.
10+ Provides methods for creating, storing, and retrieving 3D visualization data
11+ with associated metadata like original labels and classified labels.
12+ """
13+
814 def __init__ (self , table_name = "" , db_path = "manifolk.db" , create_table = True ):
15+ # The commented code below was likely a path validation check
916 # if not Path(db_path).is_file():
1017 # raise Exception(f"The Database path should be a full path of a file even if it doesnt exist. "
1118 # f"A new databse will be created at that path. Please pass full file path name")
19+
20+ # Store the database file path
1221 self .db_path = db_path
22+
23+ # Create a unique table name by appending current timestamp to avoid collisions
1324 datetime_now = datetime .now ().strftime ("%Y-%m-%d-%H:%M:%S" )
1425 self .table_name = f"[{ table_name } _{ datetime_now } ]"
26+
27+ # Initialize connection objects to None
1528 self .conn = None
1629 self .table_cursor = None
30+
31+ # Optionally create the table immediately (default behavior)
1732 if create_table :
1833 self .create_table ()
1934
2035 def create_table (self ):
36+ """
37+ Create a new SQLite table with the schema needed for storing TSNE visualization data.
38+ Schema includes:
39+ - epoch: training epoch/iteration number
40+ - X, Y, Z: 3D coordinates for visualization
41+ - DATAPOINT_NAME: unique identifier for each data point
42+ - ORIGINAL_LABEL: ground truth label
43+ - CLASSIFIED_AS_LABEL: model's predicted label
44+ """
45+ # Establish connection to the SQLite database
2146 self .conn = sqlite3 .connect (self .db_path )
2247 self .table_cursor = self .conn .cursor ()
48+
49+ # Execute SQL to create the table with required columns
2350 self .table_cursor .execute (
2451 f"CREATE TABLE "
2552 f"{ self .table_name } "
@@ -31,40 +58,79 @@ def create_table(self):
3158 f"ORIGINAL_LABEL text, "
3259 f"CLASSIFIED_AS_LABEL text)"
3360 )
61+ # Commit the changes to the database
3462 self .conn .commit ()
3563
3664 def sanitize_input (self , * args ):
65+ """
66+ Validate input types before inserting into the database.
67+ Ensures data integrity by checking that each value has the expected type.
68+
69+ Args:
70+ *args: A sequence of values to validate in the following order:
71+ epoch (int), x (float), y (float), z (float),
72+ datapoint_name (str), original_label (str), classified_label (str)
73+
74+ Raises:
75+ Exception: If any input value doesn't match its expected type
76+ """
77+ # Validate epoch is an integer
3778 epoch = args [0 ]
3879 if not isinstance (epoch , int ):
39- raise Exception (f"The input x is not a int value: { epoch } " )
80+ raise Exception (f"The input epoch is not an int value: { epoch } " )
81+
82+ # Validate X coordinate is a float
4083 x = args [1 ]
4184 if not (isinstance (x , float ) or isinstance (x , np .float32 )):
4285 raise Exception (f"The input x is not a float value: { x } " )
86+
87+ # Validate Y coordinate is a float
4388 y = args [2 ]
4489 if not (isinstance (y , float ) or isinstance (y , np .float32 )):
45- raise Exception (f"The input x is not a float value: { y } " )
90+ raise Exception (f"The input y is not a float value: { y } " )
91+
92+ # Validate Z coordinate is a float
4693 z = args [3 ]
4794 if not (isinstance (z , float ) or isinstance (z , np .float32 )):
48- raise Exception (f"The input x is not a float value: { z } " )
95+ raise Exception (f"The input z is not a float value: { z } " )
96+
97+ # Validate datapoint_name is a string
4998 datapoint_name = args [4 ]
5099 if not isinstance (datapoint_name , str ):
51- raise Exception (f"The input x is not a string value: { datapoint_name } " )
100+ raise Exception (f"The input datapoint_name is not a string value: { datapoint_name } " )
101+
102+ # Validate original_label is a string
52103 original_label = args [5 ]
53104 if not isinstance (original_label , str ):
54- raise Exception (f"The input x is not a string value: { original_label } " )
105+ raise Exception (f"The input original_label is not a string value: { original_label } " )
106+
107+ # Validate classified_label is a string
55108 classified_label = args [6 ]
56109 if not isinstance (classified_label , str ):
57- raise Exception (f"The input x is not a string value: { classified_label } " )
110+ raise Exception (f"The input classified_label is not a string value: { classified_label } " )
58111
59112 def insert_entry (self , * args ):
113+ """
114+ Insert a single data point entry into the database.
115+
116+ Args:
117+ *args: A sequence of values in the following order:
118+ epoch (int), x (float), y (float), z (float),
119+ datapoint_name (str), original_label (str), classified_label (str)
120+ """
121+ # Validate input types
60122 self .sanitize_input (* args )
123+
124+ # Extract values from args
61125 epoch = args [0 ]
62126 x = args [1 ]
63127 y = args [2 ]
64128 z = args [3 ]
65129 datapoint_name = args [4 ]
66130 original_label = args [5 ]
67131 classified_label = args [6 ]
132+
133+ # Execute SQL INSERT statement
68134 self .table_cursor .execute (
69135 f"""INSERT INTO { self .table_name } VALUES
70136 ("{ epoch } ",
@@ -75,31 +141,72 @@ def insert_entry(self, *args):
75141 "{ original_label } ",
76142 "{ classified_label } ")"""
77143 )
144+ # Commit the transaction
78145 self .conn .commit ()
79146
80147 def insert (
81148 self , epoch : int , tsne_array : np .array , original_labels : list , predicted_labels : list , datapoint_ids : list
82149 ):
150+ """
151+ Insert multiple data points for a given epoch into the database.
152+
153+ Args:
154+ epoch (int): The training epoch/iteration number
155+ tsne_array (np.array): Array of 3D points from TSNE dimensionality reduction
156+ original_labels (list): List of ground truth labels for each point
157+ predicted_labels (list): List of model-predicted labels for each point
158+ datapoint_ids (list): List of unique identifiers for each data point
159+ """
160+ # Iterate through all data points and their associated metadata
83161 for each_point , original_label , predicted_label , datapoint_id in zip (
84162 tsne_array , original_labels , predicted_labels , datapoint_ids
85163 ):
164+ # Unpack X, Y, Z coordinates from the point
86165 x , y , z = each_point
166+ # Insert each point as an individual entry
87167 self .insert_entry (epoch , x , y , z , datapoint_id , original_label , predicted_label )
88168
89169 def get_all_table_names (self ):
170+ """
171+ Retrieve all table names from the SQLite database.
172+
173+ Returns:
174+ list: List of all table names in the database with square brackets
175+ to handle special characters in table names
176+ """
177+ # Create a new connection to the database
90178 conn = sqlite3 .connect (self .db_path )
179+ # Query the sqlite_master table to get all table names
91180 res = conn .execute ("SELECT name FROM sqlite_master WHERE type='table';" )
92181 all_table_names = []
182+ # Process results and format table names with square brackets
93183 for name in res :
94184 all_table_names .append (f"[{ name [0 ]} ]" )
185+ # Close the connection
95186 conn .close ()
96187 return all_table_names
97188
98189 def get_pandas_frame (self , table_name ):
190+ """
191+ Load a table from the database into a pandas DataFrame.
192+
193+ Args:
194+ table_name (str): Name of the table to load
195+
196+ Returns:
197+ pandas.DataFrame: DataFrame containing all data from the specified table
198+ """
199+ # Create a new connection to the database
99200 conn = sqlite3 .connect (self .db_path )
201+ # Use pandas to read the SQL query result directly into a DataFrame
100202 df = pd .read_sql_query (f"SELECT * from { table_name } " , conn )
203+ # Close the connection
101204 conn .close ()
102205 return df
103206
104207 def close_connection (self ):
208+ """
209+ Close the database connection.
210+ Should be called when the database operations are complete.
211+ """
105212 self .conn .close ()
0 commit comments