batoolset 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. batoolset/GUI/__init__.py +0 -0
  2. batoolset/GUI/list_gui.py +513 -0
  3. batoolset/GUI/multi_image_display.py +989 -0
  4. batoolset/GUI/open.py +325 -0
  5. batoolset/GUI/overlay_hints.py +45 -0
  6. batoolset/GUI/paint2.py +1345 -0
  7. batoolset/GUI/scrollablepaint.py +1152 -0
  8. batoolset/IJ_ROIs/__init__.py +0 -0
  9. batoolset/IJ_ROIs/tools.py +40 -0
  10. batoolset/PATH/__init__.py +0 -0
  11. batoolset/PATH/tools.py +79 -0
  12. batoolset/SQLite_tools/__init__.py +0 -0
  13. batoolset/SQLite_tools/tools.py +840 -0
  14. batoolset/__init__.py +0 -0
  15. batoolset/binary/__init__.py +0 -0
  16. batoolset/binary/tools.py +123 -0
  17. batoolset/binarytools/__init__.py +0 -0
  18. batoolset/binarytools/cell_center_detector.py +290 -0
  19. batoolset/clipboard_tools/__init__.py +0 -0
  20. batoolset/clipboard_tools/tools.py +7 -0
  21. batoolset/colors/__init__.py +0 -0
  22. batoolset/colors/colorgen.py +193 -0
  23. batoolset/colors/tools.py +22 -0
  24. batoolset/command_line/__init__.py +0 -0
  25. batoolset/command_line/tools.py +18 -0
  26. batoolset/dialogs/__init__.py +0 -0
  27. batoolset/dialogs/opensave.py +228 -0
  28. batoolset/dicts/__init__.py +0 -0
  29. batoolset/dicts/tools.py +299 -0
  30. batoolset/dims/__init__.py +0 -0
  31. batoolset/dims/tools.py +83 -0
  32. batoolset/draw/__init__.py +0 -0
  33. batoolset/draw/shapes/Position.py +183 -0
  34. batoolset/draw/shapes/__init__.py +0 -0
  35. batoolset/draw/shapes/automated_alignment_drawing_refactored.py +346 -0
  36. batoolset/draw/shapes/circle2d.py +99 -0
  37. batoolset/draw/shapes/compute_optimal_size_all_merged.py +317 -0
  38. batoolset/draw/shapes/ellipse2d.py +336 -0
  39. batoolset/draw/shapes/freehand2d.py +235 -0
  40. batoolset/draw/shapes/group.py +1830 -0
  41. batoolset/draw/shapes/image2d.py +2469 -0
  42. batoolset/draw/shapes/line2d.py +575 -0
  43. batoolset/draw/shapes/point2d.py +257 -0
  44. batoolset/draw/shapes/polygon2d.py +357 -0
  45. batoolset/draw/shapes/polyline2d.py +235 -0
  46. batoolset/draw/shapes/rect2d.py +388 -0
  47. batoolset/draw/shapes/rectangle2d.py +601 -0
  48. batoolset/draw/shapes/scalebar.py +304 -0
  49. batoolset/draw/shapes/serializablefont.py +126 -0
  50. batoolset/draw/shapes/serializableguiparams.py +10 -0
  51. batoolset/draw/shapes/square2d.py +103 -0
  52. batoolset/draw/shapes/textorientation.py +45 -0
  53. batoolset/draw/shapes/tools.py +467 -0
  54. batoolset/draw/shapes/transform2D.py +350 -0
  55. batoolset/draw/shapes/txt2d.py +550 -0
  56. batoolset/draw/widgets/__init__.py +0 -0
  57. batoolset/draw/widgets/col.py +343 -0
  58. batoolset/draw/widgets/image_group.py +248 -0
  59. batoolset/draw/widgets/image_organizer.py +96 -0
  60. batoolset/draw/widgets/paint.py +184 -0
  61. batoolset/draw/widgets/vectorial.py +257 -0
  62. batoolset/figure/__init__.py +0 -0
  63. batoolset/figure/alignment.py +814 -0
  64. batoolset/figure/column.py +1117 -0
  65. batoolset/figure/fig_tools.py +285 -0
  66. batoolset/figure/minimal_debugger_scale_etc.py +139 -0
  67. batoolset/figure/panel.py +697 -0
  68. batoolset/figure/row.py +852 -0
  69. batoolset/figure/user_selection.py +287 -0
  70. batoolset/files/__init__.py +0 -0
  71. batoolset/files/tools.py +1321 -0
  72. batoolset/images/__init__.py +0 -0
  73. batoolset/images/tools.py +81 -0
  74. batoolset/img.py +5216 -0
  75. batoolset/linux/__init__.py +0 -0
  76. batoolset/linux/tools.py +72 -0
  77. batoolset/lists/__init__.py +0 -0
  78. batoolset/lists/tools.py +436 -0
  79. batoolset/luts/__init__.py +0 -0
  80. batoolset/luts/lut_minimal_test.py +1207 -0
  81. batoolset/matplolib/__init__.py +0 -0
  82. batoolset/matplolib/tools.py +44 -0
  83. batoolset/np_tools/__init__.py +0 -0
  84. batoolset/np_tools/tools.py +252 -0
  85. batoolset/np_tools/trash.py +15 -0
  86. batoolset/pandas_tools/__init__.py +0 -0
  87. batoolset/pandas_tools/tools.py +880 -0
  88. batoolset/partials/__init__.py +0 -0
  89. batoolset/partials/tools.py +83 -0
  90. batoolset/plot_tools/__init__.py +0 -0
  91. batoolset/plot_tools/tools.py +70 -0
  92. batoolset/pyqt/__init__.py +0 -0
  93. batoolset/pyqt/tools.py +691 -0
  94. batoolset/re_tools/__init__.py +0 -0
  95. batoolset/re_tools/tools.py +35 -0
  96. batoolset/serialization/__init__.py +0 -0
  97. batoolset/serialization/tools.py +1192 -0
  98. batoolset/sets/__init__.py +0 -0
  99. batoolset/sets/tools.py +109 -0
  100. batoolset/settings/__init__.py +0 -0
  101. batoolset/settings/global_settings.py +134 -0
  102. batoolset/strings/__init__.py +0 -0
  103. batoolset/strings/tools.py +225 -0
  104. batoolset/ta/__init__.py +0 -0
  105. batoolset/ta/database/__init__.py +0 -0
  106. batoolset/ta/database/advanced_sql_plotter.py +1170 -0
  107. batoolset/ta/database/my_qt_table.py +79 -0
  108. batoolset/ta/database/preview_and_edit_sqlite_db.py +405 -0
  109. batoolset/ta/database/sql.py +2141 -0
  110. batoolset/ta/database/sql_column_name_dialog.py +122 -0
  111. batoolset/ta/measurements/TAmeasures.py +2226 -0
  112. batoolset/ta/measurements/__init__.py +0 -0
  113. batoolset/ta/measurements/measurements3D/__init__.py +0 -0
  114. batoolset/ta/measurements/measurements3D/get_point_on_surface_if_centroid_is_bad.py +175 -0
  115. batoolset/ta/measurements/measurements3D/height_map_to_projection.py +82 -0
  116. batoolset/ta/measurements/measurements3D/measures3D.py +208 -0
  117. batoolset/ta/measurements/measurements3D/triangulate.py +331 -0
  118. batoolset/ta/measurements/nematic.py +562 -0
  119. batoolset/ta/measurements/nematic_measurements.py +107 -0
  120. batoolset/ta/segmentation/__init__.py +0 -0
  121. batoolset/ta/segmentation/neo_wshed.py +314 -0
  122. batoolset/ta/selections/__init__.py +0 -0
  123. batoolset/ta/selections/selection.py +329 -0
  124. batoolset/ta/tracking/__init__.py +0 -0
  125. batoolset/ta/tracking/last_tracking_based_on_matching_or_on_translation_from_mermaid_warp.py +653 -0
  126. batoolset/ta/tracking/local_to_track_correspondance.py +138 -0
  127. batoolset/ta/tracking/rapid_detection_of_vertices.py +517 -0
  128. batoolset/ta/tracking/registration.py +108 -0
  129. batoolset/ta/tracking/swap_detector_and_fixer.py +296 -0
  130. batoolset/ta/tracking/track_correction.py +238 -0
  131. batoolset/ta/tracking/tracking_error_detector_and_fixer.py +3099 -0
  132. batoolset/ta/tracking/tracking_yet_another_approach_pyramidal_registration_n_neo_swapping_correction.py +725 -0
  133. batoolset/ta/utils/TA_tools.py +43 -0
  134. batoolset/ta/utils/__init__.py +0 -0
  135. batoolset/ta/utils/rps_tools.py +1783 -0
  136. batoolset/tests/__init__.py +0 -0
  137. batoolset/tests/rps_tools.py +51 -0
  138. batoolset/tests/tools.py +10 -0
  139. batoolset/tools/__init__.py +0 -0
  140. batoolset/tools/early_stopper_class.py +9 -0
  141. batoolset/tools/guided_data_recoverer.py +110 -0
  142. batoolset/tools/logger.py +100 -0
  143. batoolset/tools/mytimer.py +31 -0
  144. batoolset/tools/prompt_color.py +160 -0
  145. batoolset/tools/qthandler.py +118 -0
  146. batoolset/uitools/__init__.py +0 -0
  147. batoolset/uitools/blinker.py +56 -0
  148. batoolset/unsafe/__init__.py +0 -0
  149. batoolset/unsafe/tools.py +115 -0
  150. batoolset/utils/__init__.py +0 -0
  151. batoolset/utils/commontools.py +158 -0
  152. batoolset/utils/loadlist.py +728 -0
  153. batoolset/version.py +10 -0
  154. batoolset/xml/__init__.py +0 -0
  155. batoolset/xml/tools.py +65 -0
  156. batoolset/zip_tools/__init__.py +0 -0
  157. batoolset/zip_tools/tools.py +76 -0
  158. batoolset-0.1.0.dist-info/LICENSE +24 -0
  159. batoolset-0.1.0.dist-info/METADATA +45 -0
  160. batoolset-0.1.0.dist-info/RECORD +162 -0
  161. batoolset-0.1.0.dist-info/WHEEL +5 -0
  162. batoolset-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,880 @@
1
+ # Pandas related tools/methods
2
+
3
+ # in vs code only ctrl + F5 works for running and having the path
4
+ # DEV NOTE TWO LINES BELOW KEEP FIX FOR RUNNING IN VS CODE §!!!!!!!!! --> very dirty though
5
+ #import sys
6
+ #sys.path.append('/home/aigouy/mon_prog/Python/epyseg_pkg/')
7
+
8
+ import matplotlib.pyplot as plt
9
+ import sqlite3
10
+ import pandas as pd
11
+ import numpy as np
12
+ from sklearn.decomposition import PCA
13
+ from sklearn.cluster import KMeans
14
+
15
+ from batoolset.files.tools import open_file_with_default_handler
16
+
17
+
18
+ def add_cumulative_sum(df):
19
+ """
20
+ Modify a DataFrame so that each row contains the cumulative sum of all rows above it.
21
+
22
+ Args:
23
+ df (pd.DataFrame): The input DataFrame.
24
+
25
+ Returns:
26
+ pd.DataFrame: The modified DataFrame with cumulative sums.
27
+
28
+ Examples:
29
+ >>> data = {'A': [1, 2, 3, 4]}
30
+ >>> df = pd.DataFrame(data)
31
+ >>> df_cumulative = add_cumulative_sum(df)
32
+ >>> print(df_cumulative)
33
+ A
34
+ 0 1
35
+ 1 3
36
+ 2 6
37
+ 3 10
38
+ """
39
+ # Use the cumsum() function along the rows (axis=0) to calculate cumulative sums
40
+ df_cumulative = df.cumsum(axis=0)
41
+
42
+ return df_cumulative
43
+
44
+
45
+ def remove_columns_with_string(df, substring):
46
+ """
47
+ Remove all columns from a DataFrame that contain a specified substring in their name.
48
+
49
+ Args:
50
+ df (pd.DataFrame): The input DataFrame.
51
+ substring (str): The substring to search for in column names.
52
+
53
+ Returns:
54
+ pd.DataFrame: The DataFrame with columns containing the substring removed.
55
+
56
+ Examples:
57
+ >>> data = {'fruit_flies_count': [10, 20, 30], 'apple_count': [5, 15, 25]}
58
+ >>> df = pd.DataFrame(data)
59
+ >>> df_filtered = remove_columns_with_string(df, 'flies')
60
+ >>> print(df_filtered)
61
+ apple_count
62
+ 0 5
63
+ 1 15
64
+ 2 25
65
+ """
66
+ # Get a list of column names to keep (those that do not contain the specified substring)
67
+ columns_to_keep = [col for col in df.columns if substring not in col]
68
+
69
+ # Create a new DataFrame with the selected columns
70
+ df_filtered = df[columns_to_keep]
71
+
72
+ return df_filtered
73
+
74
+ def append_row_to_df(df, row_content):
75
+ df.loc[len(df)] = row_content
76
+ return df # do I even need to return the df
77
+
78
+
79
+
80
+ def numpy_array_to_pandas_df(my_array, header=None):
81
+ """
82
+ loads a numpy array to a pandas df.
83
+
84
+ Args:
85
+ my_array (numpy.ndarray): The numpy array to save.
86
+ header_names (list, optional): A list of header names for the pandas df. If not provided, no header will be added.
87
+ """
88
+ # Convert the numpy array to a pandas DataFrame
89
+ df = pd.DataFrame(my_array,columns=header)
90
+
91
+ # Add headers if provided
92
+ # if header is not None:
93
+ # if not isinstance(header, np.ndarray):
94
+ # header = np.asarray(header)
95
+ # df.columns = header
96
+
97
+ # Save the DataFrame to a CSV file
98
+ # df.to_csv(file_path, index=False)
99
+
100
+ return df
101
+
102
+ def create_empty_table_like(df):
103
+ # Create an empty DataFrame with the same column names
104
+ empty_df = pd.DataFrame(columns=df.columns)
105
+ return empty_df
106
+
107
+
108
+ def add_column(df, new_column_name):
109
+ # Add a new empty column named 'NewEmptyColumn'
110
+ df[new_column_name] = pd.Series()
111
+ return df
112
+
113
+ def create_empty_df(header):
114
+ return numpy_array_to_pandas_df(None,header=header)
115
+
116
+ def insert_column_at_position(df, index_position, new_column_name ):
117
+ # Insert the new column at the specified index position
118
+ df.insert(index_position, new_column_name, value=None)
119
+ return df
120
+
121
+ def prepend_column(df, col_name, col_values):
122
+ """
123
+ Prepends a new column to a pandas DataFrame.
124
+
125
+ Args:
126
+ df (pandas.DataFrame): The DataFrame to prepend the column to.
127
+ col_name (str): The name of the new column to prepend.
128
+ col_values (list): A list of values to populate the new column.
129
+ """
130
+ # Use the insert() method to prepend the new column to the DataFrame
131
+ df.insert(loc=0, column=col_name, value=col_values)
132
+ return df
133
+
134
+ def get_column_factors(df, column):
135
+ """
136
+ Returns a list of all the unique values in the specified column of the DataFrame,
137
+ using either the column name or the value as an index if it is an integer.
138
+
139
+ Parameters:
140
+ - df: The DataFrame containing the data.
141
+ - column: The name or index of the column.
142
+
143
+ Returns:
144
+ A list of unique values in the specified column.
145
+
146
+ Examples:
147
+ >>> df = pd.DataFrame({'A': [1, 2, 3, 4], 'B': [1, 2, 2, 3]})
148
+ >>> get_column_factors(df, 'B')
149
+ array([1, 2, 3])
150
+ """
151
+ # If the column is specified as an index (integer), get the corresponding column name
152
+ if isinstance(column, int):
153
+ column = df.columns[column]
154
+
155
+ # Retrieve the unique values from the specified column
156
+ factors = df[column].unique()
157
+
158
+ # Return the list of unique values
159
+ return factors
160
+
161
+
162
+ def get_combined_factors(df, columns):
163
+ """
164
+ Returns a list of all the unique values in the specified columns of the DataFrame,
165
+ using either the column names or the values as indices if they are integers.
166
+
167
+ Parameters:
168
+ - df: The DataFrame containing the data.
169
+ - columns: A list of column names or indices.
170
+
171
+ Returns:
172
+ A list of unique values from the specified columns.
173
+
174
+ Examples:
175
+ >>> df = pd.DataFrame({'A': [1, 2, 3, 4], 'B': [1, 2, 2, 3], 'C': ['X', 'Y', 'Z', 'Z']})
176
+ >>> get_combined_factors(df, ['A', 1, 'C'])
177
+ array([1, 2, 3, 4, 'X', 'Y', 'Z'], dtype=object)
178
+ """
179
+ # Convert column indices to column names if they are integers
180
+ column_names = [df.columns[col] if isinstance(col, int) else col for col in columns]
181
+
182
+ # Concatenate the specified columns into a single series
183
+ combined_series = pd.concat([df[name] for name in column_names])
184
+
185
+ # Retrieve the unique values from the combined series
186
+ factors = combined_series.unique()
187
+
188
+ # Return the list of unique values
189
+ return factors
190
+
191
+ def strip_column(df, col_name_or_idx):
192
+ if isinstance(col_name_or_idx, str):
193
+ df[col_name_or_idx] = df[col_name_or_idx].str.strip()
194
+ else:
195
+ # Strip leading and trailing whitespace from the specified column
196
+ df.iloc[:, col_name_or_idx] = df.iloc[:, col_name_or_idx].str.strip()
197
+ return df
198
+
199
+
200
+ def diff_dataframes(df1, df2):
201
+ """
202
+ Returns a DataFrame with only the rows that differ between the two input DataFrames.
203
+
204
+ Parameters:
205
+ - df1: The first DataFrame.
206
+ - df2: The second DataFrame.
207
+
208
+ Returns:
209
+ A DataFrame containing the differing rows between df1 and df2.
210
+
211
+ Examples:
212
+ >>> df1 = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})
213
+ >>> df2 = pd.DataFrame({'A': [1, 2, 4], 'B': [4, 5, 7]})
214
+ >>> diff_dataframes(df1, df2)
215
+ A B _merge
216
+ 2 3 6 left_only
217
+ 3 4 7 right_only
218
+ """
219
+
220
+ # Merge the two DataFrames based on all columns, with an indicator column added
221
+ merged = pd.merge(df1, df2, how='outer', indicator=True)
222
+
223
+ # Filter the merged DataFrame to only include rows that are not present in both DataFrames
224
+ diff = merged[merged['_merge'] != 'both']
225
+
226
+ # Return the resulting DataFrame with differing rows
227
+ return diff
228
+
229
+ def open_as_df(file_path, sep='\t', header=None):
230
+ # Read the file into a DataFrame with a header
231
+ df = pd.read_csv(file_path, delimiter=sep, header=header)
232
+ return df
233
+
234
+
235
+ def filter_out_rows(df1, other_dfs):
236
+ """
237
+ Filter out rows from a DataFrame that are contained in one or more other DataFrames.
238
+
239
+ Parameters:
240
+ - df1 (pandas.DataFrame): The main DataFrame from which rows will be filtered.
241
+ - other_dfs (list of pandas.DataFrame): A list of other DataFrames to check for containment.
242
+
243
+ Returns:
244
+ - pandas.DataFrame: A DataFrame containing only the rows from df1 that are not contained in any of the other DataFrames.
245
+
246
+ Example:
247
+ >>> import pandas as pd
248
+ >>> data1 = {'ID': [1, 2, 3, 4, 5, 6], 'Value': ['A', 'B', 'C', 'D', 'E', 'G']}
249
+ >>> df1 = pd.DataFrame(data1)
250
+ >>> data2 = {'ID': [2, 4], 'Value': ['B', 'D']}
251
+ >>> df2 = pd.DataFrame(data2)
252
+ >>> data3 = {'ID': [1, 3, 5], 'Value': ['A', 'C', 'E']}
253
+ >>> df3 = pd.DataFrame(data3)
254
+ >>> other_dfs = [df2, df3]
255
+ >>> filtered_df = filter_out_rows(df1, other_dfs)
256
+ >>> print(filtered_df)
257
+ ID Value
258
+ 0 6 G
259
+ """
260
+ # Initialize the filtered DataFrame with df1
261
+ filtered_df = df1
262
+
263
+ if not isinstance(other_dfs, list):
264
+ other_dfs = [other_dfs]
265
+
266
+ # Loop through each DataFrame in other_dfs
267
+ for other_df in other_dfs:
268
+ # Use the isin() method to check if rows in df1 are contained in the current other DataFrame
269
+ mask = df1.isin(other_df.to_dict(orient='list')).all(axis=1)
270
+
271
+ # Filter out the rows based on the mask
272
+ filtered_df = filtered_df[~mask]
273
+
274
+ # Reset the index of the filtered DataFrame
275
+ filtered_df.reset_index(drop=True, inplace=True)
276
+
277
+ return filtered_df
278
+
279
+
280
+ def rename_column(df, index, new_name):
281
+ return df.rename(columns={df.columns[index]: new_name})
282
+
283
+ def combine_dataframes(dataframes):
284
+ """
285
+ Combines a list of dataframes into a single master dataframe.
286
+
287
+ Parameters:
288
+ - dataframes: A list of pandas.DataFrame objects to combine.
289
+
290
+ Returns:
291
+ A master dataframe that combines all the input dataframes.
292
+
293
+ Examples:
294
+ >>> df1 = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})
295
+ >>> df2 = pd.DataFrame({'A': [4, 5, 6], 'B': [7, 8, 9]})
296
+ >>> combine_dataframes([df1, df2])
297
+ A B
298
+ 0 1 4
299
+ 1 2 5
300
+ 2 3 6
301
+ 3 4 7
302
+ 4 5 8
303
+ 5 6 9
304
+ """
305
+
306
+ # Combine the dataframes into a single master dataframe
307
+ master_df = pd.concat(dataframes, ignore_index=True)
308
+
309
+ return master_df
310
+
311
+
312
+ def load_table_to_pandas_df(path_to_db, table_name):
313
+ """
314
+ Loads a SQL table into a pandas DataFrame from the specified SQLite database file.
315
+
316
+ Parameters:
317
+ - path_to_db: The path to the SQLite database file.
318
+ - table_name: The name of the table to load.
319
+
320
+ Returns:
321
+ A pandas DataFrame containing the data from the specified table.
322
+
323
+ # Examples:
324
+ # >>> df = load_table_to_pandas_df('mydatabase.db', 'mytable')
325
+ """
326
+
327
+ # Create a connection to the SQLite database
328
+ conn = sqlite3.connect(path_to_db)
329
+
330
+ # Load the SQL table into a pandas DataFrame
331
+ df = pd.read_sql('SELECT * FROM ' + table_name, conn)
332
+
333
+ # Close the connection to the database
334
+ conn.close()
335
+
336
+ return df
337
+
338
+
339
+ def get_blob_columns(df):
340
+ """
341
+ Returns a list of column names from the DataFrame that have object (string) data type.
342
+
343
+ Parameters:
344
+ - df: The DataFrame from which to extract the blob columns.
345
+
346
+ Returns:
347
+ A list of column names that have object data type.
348
+
349
+ Examples:
350
+ >>> df = pd.DataFrame({'A': [1, 2, 3], 'B': ['abc', 'def', 'ghi'], 'C': [True, False, True]})
351
+ >>> get_blob_columns(df)
352
+ ['B']
353
+ """
354
+ blob_columns = df.select_dtypes(include=['object']).columns.tolist()
355
+ return blob_columns
356
+
357
+
358
+ def dict_of_tables_to_SQL(tables_dict, output_sql_file):
359
+ """
360
+ Saves a dictionary of DataFrames as separate tables in an SQLite database file.
361
+
362
+ Parameters:
363
+ - tables_dict: A dictionary containing table names as keys and DataFrames as values.
364
+ - output_sql_file: The path to the output SQLite database file.
365
+
366
+ Returns:
367
+ None
368
+
369
+ # Examples:
370
+ # >>> df1 = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})
371
+ # >>> df2 = pd.DataFrame({'A': [4, 5, 6], 'B': [7, 8, 9]})
372
+ # >>> tables_dict = {'table1': df1, 'table2': df2}
373
+ # >>> dict_of_tables_to_SQL(tables_dict, 'output.db')
374
+ """
375
+
376
+ # Create a connection to the SQLite database
377
+ conn = sqlite3.connect(output_sql_file)
378
+
379
+ # Loop through the dictionary and save each DataFrame as a table in the SQL file
380
+ for table_name, df in tables_dict.items():
381
+ df.to_sql(table_name, conn, if_exists='replace')
382
+
383
+ # Close the connection to the database
384
+ conn.close()
385
+
386
+
387
+ def add_dataframe_to_sql(df, db_file, table_name):
388
+ """
389
+ Adds a Pandas DataFrame to an SQL database as a new table.
390
+
391
+ Parameters:
392
+ - df: The DataFrame to be added to the database.
393
+ - db_file: The name and path of the SQL database file.
394
+ - table_name: The name to be given to the new table in the database.
395
+
396
+ Returns:
397
+ None
398
+
399
+ # Examples:
400
+ # >>> df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})
401
+ # >>> add_dataframe_to_sql(df, 'mydatabase.db', 'mytable')
402
+ """
403
+ # Connect to the SQL database
404
+ conn = sqlite3.connect(db_file)
405
+
406
+ # Use the to_sql() method to add the DataFrame to the database
407
+ df.to_sql(table_name, conn, if_exists='replace')
408
+
409
+ # Close the database connection
410
+ conn.close()
411
+
412
+
413
+ def name_index_column(df, name_to_use='index_label'):
414
+ """
415
+ Sets the name of the index column in the DataFrame.
416
+
417
+ Parameters:
418
+ - df: The DataFrame in which the index column name will be set.
419
+ - name_to_use: The name to assign to the index column (default is 'index_label').
420
+
421
+ Returns:
422
+ The DataFrame with the updated index column name.
423
+
424
+ Examples:
425
+ >>> import re
426
+ >>> df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})
427
+ >>> re.sub(r'\s+', '', str(name_index_column(df, 'new_index')))
428
+ 'ABnew_index014125236'
429
+ """
430
+
431
+ # Set the name of the index column in the DataFrame
432
+ df.index.name = name_to_use
433
+
434
+ # Return the updated DataFrame
435
+ return df
436
+
437
+
438
+ def kmeans_clustering(df, n_clusters, exclude_non_numeric_columns=True, verbose=False):
439
+ """
440
+ Perform K-means clustering on a Pandas DataFrame.
441
+
442
+ Parameters:
443
+ - df: The DataFrame to cluster.
444
+ - n_clusters: The number of clusters to create.
445
+ - exclude_non_numeric_columns: Boolean value indicating whether non-numeric columns should be excluded from clustering (default is True).
446
+
447
+ Returns:
448
+ The input DataFrame with an additional column 'cluster', containing the cluster labels for each row.
449
+
450
+ Examples:
451
+ >>> df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})
452
+ >>> kmeans_clustering(df, 2)
453
+ A B cluster
454
+ 0 1 4 1
455
+ 1 2 5 0
456
+ 2 3 6 0
457
+ """
458
+ if exclude_non_numeric_columns:
459
+ # create a numpy array with only the numeric columns
460
+ X = df.select_dtypes(include=[np.number]).values
461
+ else:
462
+ X = df.values # convert DataFrame to a numpy array
463
+
464
+ # create a KMeans object and fit it to the data
465
+ kmeans = KMeans(n_clusters=n_clusters, random_state=42,n_init='auto')
466
+ df['cluster'] = kmeans.fit_predict(X)
467
+
468
+ if True:
469
+ # perform KMeans clustering and obtain the transformed distances
470
+ distances = kmeans.fit_transform(X)
471
+ # compute the correlation between each column and the transformed distances
472
+ correlations = df.corrwith(pd.DataFrame(distances))
473
+
474
+ # sort the correlations in descending order of absolute value
475
+ sorted_correlations = correlations.abs().sort_values(ascending=False)
476
+
477
+ # print the sorted correlations
478
+ if verbose:
479
+ print("Feature correlations with KMeans distances in descending order:")
480
+ print(sorted_correlations)
481
+
482
+ if False:
483
+ # get the distances of each sample to each cluster center
484
+ distances = kmeans.transform(X)
485
+ # convert the distances array to a DataFrame with column names
486
+ X = pd.DataFrame(distances, columns=[f"distance_{i}" for i in range(distances.shape[1])])
487
+
488
+ # compute the mean distance for each column
489
+ mean_distances = X.mean(axis=0)
490
+
491
+ # create a dictionary of column names and their corresponding mean distances
492
+ distance_dict = dict(zip(X.columns, mean_distances))
493
+
494
+ # sort the dictionary by mean distance in ascending order
495
+ sorted_distances = sorted(distance_dict.items(), key=lambda x: x[1])
496
+
497
+ # print the sorted dictionary
498
+ print("Feature distances in ascending order:")
499
+ for feature, distance in sorted_distances:
500
+ print(f"{feature}: {distance:.3f}")
501
+
502
+ return df
503
+
504
+
505
+ def pca_analysis(df, exclude_non_numeric_columns=True):
506
+ """
507
+ Perform PCA clustering on a DataFrame and determine the most important feature.
508
+
509
+ Parameters:
510
+ - df: a pandas DataFrame containing the data to be analyzed.
511
+ - exclude_non_numeric_columns: Boolean value indicating whether non-numeric columns should be excluded from PCA analysis (default is True).
512
+
513
+ Returns:
514
+ - A tuple containing the explained variance ratio for each component,
515
+ the component matrix showing the contribution of each original feature to each principal component,
516
+ and the name of the most important feature.
517
+
518
+ Examples:
519
+ >>> df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})
520
+ >>> pca_analysis(df)
521
+ (array([1.00000000e+00, 2.81351049e-34]), A B
522
+ 0 0.707107 0.707107
523
+ 1 0.707107 -0.707107, 'A')
524
+ """
525
+ if exclude_non_numeric_columns:
526
+ # select only the numeric columns
527
+ numeric_df = df.select_dtypes(include=[np.number])
528
+ else:
529
+ numeric_df = df
530
+
531
+ # perform PCA on the numeric DataFrame
532
+ pca = PCA()
533
+ components = pca.fit_transform(numeric_df.values)
534
+
535
+ # get the explained variance ratio for each component
536
+ explained_variance_ratio = pca.explained_variance_ratio_
537
+
538
+ # create a component matrix DataFrame
539
+ component_matrix = pd.DataFrame(pca.components_, columns=numeric_df.columns)
540
+
541
+ # determine the most important feature based on the first principal component
542
+ most_important_feature = component_matrix.iloc[0].idxmax()
543
+
544
+ return explained_variance_ratio, component_matrix, most_important_feature
545
+
546
+ def pca_analysis2(df, n_clusters=2):
547
+ """
548
+ Perform PCA clustering on a DataFrame and determine the most important feature.
549
+
550
+ Parameters:
551
+ - df: a pandas DataFrame containing the data to be analyzed.
552
+ - n_clusters: the number of clusters to use in KMeans clustering.
553
+
554
+ Returns:
555
+ - A tuple containing the explained variance ratio for each component,
556
+ the component matrix showing the contribution of each original feature to each principal component,
557
+ the name of the most important feature,
558
+ and a pandas Series containing the cluster labels for each sample in the input DataFrame.
559
+ """
560
+ # select only the numeric columns
561
+ numeric_df = df.select_dtypes(include=[np.number])
562
+
563
+ # drop any rows that contain missing values or non-numeric values
564
+ clean_df = numeric_df.dropna().apply(pd.to_numeric, errors='coerce')
565
+
566
+ # instantiate the PCA model with n_components=2
567
+ pca = PCA(n_components=2)
568
+
569
+ # fit the model to the data and transform the data
570
+ pca.fit(clean_df)
571
+ transformed = pca.transform(clean_df)
572
+
573
+ # get the explained variance ratio for each component
574
+ explained_variance_ratio = pca.explained_variance_ratio_
575
+
576
+ # compute the contribution of each original feature to each principal component
577
+ component_matrix = pd.DataFrame(pca.components_, columns=clean_df.columns, index=['PC1', 'PC2'])
578
+
579
+ # instantiate the KMeans model with the specified number of clusters
580
+ kmeans = KMeans(n_clusters=n_clusters,n_init='auto')
581
+
582
+ # fit the model to the transformed data and predict the cluster labels
583
+ kmeans.fit(transformed)
584
+ labels = kmeans.predict(transformed)
585
+
586
+ # add the cluster labels as a new column in the input DataFrame
587
+ df['Cluster'] = labels
588
+
589
+ # determine the most important feature
590
+ most_important_feature = component_matrix.abs().idxmax(axis=1)
591
+
592
+ if True:
593
+ # create a scatter plot of the PCA components colored by cluster label
594
+ plt.scatter(transformed[:, 0], transformed[:, 1], c=labels)
595
+ plt.xlabel('PC1')
596
+ plt.ylabel('PC2')
597
+ plt.title('PCA Plot')
598
+ plt.show()
599
+
600
+ # return the results as a tuple
601
+ results = (explained_variance_ratio, component_matrix, most_important_feature, labels)
602
+
603
+ return results
604
+
605
+
606
+ def split_column(df, col_name, new_col_names, strip='()'):
607
+ """
608
+ Split a column in a pandas DataFrame into two new columns and drop the original column.
609
+
610
+ Parameters:
611
+ - df: a pandas DataFrame containing the column to split.
612
+ - col_name: a string specifying the name of the column to split.
613
+ - new_col_names: a tuple of two strings specifying the names of the new columns to create.
614
+
615
+ Returns:
616
+ - A pandas DataFrame containing the input DataFrame with the original column dropped and
617
+ two new columns added containing the split values of the original column.
618
+ """
619
+ # split the column into two new columns
620
+ df[new_col_names] = df[col_name].str.strip(strip).str.split(',', expand=True).astype(float)
621
+
622
+ # drop the original column
623
+ df = df.drop(col_name, axis=1)
624
+
625
+ return df
626
+
627
+
628
+ def to_clipboard(df, index=False, header=True):
629
+ """
630
+ Copy the contents of a Pandas DataFrame to the system clipboard.
631
+
632
+ Parameters:
633
+ df : pandas.DataFrame
634
+ The DataFrame to be copied to the clipboard.
635
+ index : bool, optional
636
+ Whether to include the index column in the copied data. Default is False.
637
+ header : bool, optional
638
+ Whether to include the column headers in the copied data. Default is True.
639
+
640
+ Returns:
641
+ None
642
+
643
+ Examples:
644
+ >>> import pandas as pd
645
+ >>> df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6], 'C': [7, 8, 9]})
646
+ >>> to_clipboard(df)
647
+ """
648
+ return df.to_clipboard(index=index, header=header)
649
+
650
+ def set_df_starting_index(df, start_index):
651
+ df.index = range(start_index, start_index + len(df))
652
+ return df
653
+
654
+ def nullify_df_indices(df):
655
+ df.index = None
656
+ return df
657
+
658
+ def copy_df_and_fill_withvalue(df, value):
659
+ # Create a copy of the DataFrame
660
+ df_copy = df.copy()
661
+ df_copy = df_copy.replace(df_copy.values, value)
662
+ return df_copy
663
+
664
+ def check_and_remove_duplicate_indices(df):
665
+ # Check if indices are unique
666
+ if df.index.duplicated().any():
667
+ # Remove duplicates and keep the first instance
668
+ df = df[~df.index.duplicated(keep='first')]
669
+
670
+ return df
671
+
672
+ def merge_df_and_keep_indices(*dfs, remove_na=True):
673
+ # result_df = pd.merge(df1, df2, left_index=True, right_index=True, how='outer')
674
+ # Merge the single-column DataFrames into a single DataFrame with n columns
675
+ result_df = pd.concat(dfs, axis=1, join='outer')
676
+ if remove_na:
677
+ result_df.fillna('', inplace=True)
678
+ return result_df
679
+
680
+ if __name__ == '__main__':
681
+
682
+ if False:
683
+ import pandas as pd
684
+
685
+ # Example DataFrames with different indices
686
+ # Your n single-column DataFrames with different indices
687
+ df1 = pd.DataFrame({'Column1': ['A', 'T', 'G']}, index=[1, 2, 3])
688
+ df2 = pd.DataFrame({'Column2': ['C', 50, 60]}, index=[4, 5, 6])
689
+ df3 = pd.DataFrame({'Column3': [70, 80, 90]}, index=[12, 8, 8])
690
+
691
+ # Merge the single-column DataFrames into a single DataFrame with n columns
692
+ # result_df = pd.concat([df1, df2, df3], axis=1, join='outer')
693
+
694
+ # print(result_df)
695
+ # Merge DataFrames on indices
696
+ # merged_df = pd.merge(df1, df2, left_index=True, right_index=True, how='outer')
697
+ merged_df = merge_df_and_keep_indices(df1, df2, df3)
698
+
699
+
700
+
701
+ # Display the merged DataFrame
702
+ print(merged_df)
703
+
704
+ import sys
705
+ sys.exit(0)
706
+
707
+ if True:
708
+ print(create_empty_df(['test1','test2', 'tutu']))
709
+
710
+ import sys
711
+ sys.exit(0)
712
+
713
+
714
+ from batoolset.img import Img
715
+ if True:
716
+ files = ['/media/teamPrudhomme/EqpPrudhomme2/Benoit_pr_Benjamin/coccinelles/latest images_20230614/raw images/effet_sexe_29.db', '/media/teamPrudhomme/EqpPrudhomme2/Benoit_pr_Benjamin/coccinelles/latest images_20230614/raw images/effet_sexe_18.db', '/media/teamPrudhomme/EqpPrudhomme2/Benoit_pr_Benjamin/coccinelles/ANALYZE_LATER/25°N4N45F_25°N4N42M_25°R16F_25°R17M_29°R26inds-26-05-2023_014/ladybug_seg.db']
717
+ corresponding_image = [None, None, '/media/teamPrudhomme/EqpPrudhomme2/Benoit_pr_Benjamin/coccinelles/ANALYZE_LATER/25°N4N45F_25°N4N42M_25°R16F_25°R17M_29°R26inds-26-05-2023_014.tif']
718
+ idx = 0
719
+
720
+ conn = sqlite3.connect(files[idx])
721
+
722
+ img = None
723
+ if corresponding_image[idx] is not None:
724
+ img = Img(corresponding_image[idx])
725
+
726
+
727
+ df = pd.read_sql_query('SELECT * FROM elytras_shape', conn)
728
+ # df = pd.read_sql_query('SELECT * FROM ' + table_name, conn)
729
+ if idx == 2: # TODO --> remove this line
730
+ df = df.loc[df['cluster'].isin([1, 2])]
731
+
732
+ old = df.copy()
733
+ # use the drop() method to remove the column
734
+ forbidden_columns = ['index', 'cluster','local_ID']
735
+ for col in forbidden_columns:
736
+ try:
737
+ df = df.drop(col, axis=1)
738
+ except:
739
+ print('no ' + col+' column --> ignoring')
740
+
741
+ print(df.columns)
742
+ print(df.head())
743
+
744
+ # print(pca_analysis(df))
745
+ print(pca_analysis2(df))
746
+
747
+ # df = kmeans_clustering(df, 2)
748
+
749
+ print(df)
750
+ old['new_cluster']=df['Cluster']
751
+
752
+ print(old)
753
+ # group the DataFrame by the pairs of values in columns A and B and count the number of occurrences of each pair
754
+ counts = old.groupby(['cluster', 'new_cluster']).size().reset_index(name='Count')
755
+
756
+ # print the counts for each pair
757
+ print(counts)
758
+
759
+ # group the DataFrame by the 'cluster' column and compute the max value of 'Count' for each group
760
+ max_counts = counts.groupby('cluster')['Count'].max()
761
+
762
+ # group the DataFrame by the 'cluster' column and compute the sum of 'Count' for each group
763
+ sum_counts = counts.groupby('cluster')['Count'].sum()
764
+
765
+ # compute the ratio of max counts to sum counts
766
+ ratios = max_counts / sum_counts
767
+
768
+ # print the resulting ratios
769
+ print(ratios)
770
+
771
+ old = split_column(old, 'centroids', ['centroid_y','centroid_x'], strip='()')
772
+
773
+ print(old['centroid_y'])
774
+
775
+ # define a dictionary that maps cluster values to colors
776
+ color_map = {0: 'purple', 1: 'blue', 2: 'red', 3: 'green', 4: 'yellow', 5: 'cyan'}
777
+
778
+ # print(df.head())
779
+ conn.close()
780
+
781
+ if img is not None:
782
+ img = img/img.max()
783
+ # plot the image
784
+ fig, ax = plt.subplots()
785
+ ax.imshow(img)
786
+ # define a colormap
787
+ cmap = 'viridis'
788
+
789
+ # plot the points over the image
790
+ for i, row in old.iterrows():
791
+ cluster = row['new_cluster']
792
+ y = row['centroid_y']
793
+ x = row['centroid_x']
794
+ ax.scatter(x, y, c=color_map[cluster])
795
+
796
+ # add a colorbar
797
+ fig.colorbar(ax.collections[0], ax=ax)
798
+ # add a legend
799
+ # ax.legend()
800
+
801
+ # show the plot
802
+ plt.show()
803
+
804
+ import sys
805
+ sys.exit(0)
806
+
807
+
808
+ if True:
809
+ # Create a sample DataFrame
810
+ data = {'A': [1, 2, 3], 'B': [4, 5, 6]}
811
+ df = pd.DataFrame(data)
812
+ print("Before naming the index column:")
813
+ print(df)
814
+
815
+ # Name the index column as 'ID'
816
+ df_named = name_index_column(df, 'ID')
817
+
818
+ print("After naming the index column:")
819
+ print(df_named)
820
+
821
+
822
+ if True:
823
+ # Create a list of dataframes
824
+ df1 = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})
825
+ df2 = pd.DataFrame({'A': [4, 5, 6], 'B': [7, 8, 9]})
826
+ df3 = pd.DataFrame({'A': [7, 8, 9], 'B': [10, 11, 12]})
827
+ df_list = [df1, df2, df3]
828
+
829
+ # Call the combine_dataframes() method to create a master dataframe
830
+ master_df = combine_dataframes(df_list)
831
+
832
+ # Print the master dataframe
833
+ print(master_df)
834
+
835
+ import sys
836
+ sys.exit(0)
837
+
838
+
839
+ if True:
840
+ # Create two sample DataFrames
841
+ df1 = pd.DataFrame({'A': [1, 2, 3], 'B': ['foo', 'bar', 'baz']})
842
+ df2 = pd.DataFrame({'A': [1, 3, 4], 'B': ['foo', 'baz', 'qux']})
843
+
844
+ # Call the diff_dataframes() method to get the rows that differ between the two DataFrames
845
+ diff = diff_dataframes(df1, df2)
846
+
847
+ print(diff)
848
+
849
+ import sys
850
+ sys.exit(0)
851
+
852
+ # Create a sample DataFrame
853
+ df = pd.DataFrame({'col1': ['foo', 'bar', 'baz', 'foo', 'qux', 'bar'], 'col2': [1, 2, 3, 4, 5, 6]})
854
+
855
+ # Call the get_column_factors() method with a column name
856
+ factors1 = get_column_factors(df, 'col1')
857
+ print(factors1)
858
+
859
+ # Call the get_column_factors() method with an integer index
860
+ factors2 = get_column_factors(df, 1)
861
+ print(factors2)
862
+
863
+ # Create a sample DataFrame
864
+ df = pd.DataFrame({'col1': ['foo', 'bar', 'baz', 'foo', 'qux', 'bar'],
865
+ 'col2': [1, 2, 3, 4, 5, 6],
866
+ 'col3': ['baz', 'qux', 'foo', 'baz', 'bar', 'qux']})
867
+
868
+ # Call the get_combined_factors() method with column names
869
+ factors1 = get_combined_factors(df, ['col1', 'col3'])
870
+ print(factors1)
871
+
872
+ # Call the get_combined_factors() method with integer indices
873
+ factors2 = get_combined_factors(df, [0, 2])
874
+ print(factors2)
875
+
876
+
877
+ # Call the get_combined_factors() method with mixed columns
878
+ factors2 = get_combined_factors(df, ['col1', 2])
879
+ print(factors2)
880
+