easysurfvis 0.0.1.dev4__tar.gz → 0.0.1.dev6__tar.gz

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 (55) hide show
  1. easysurfvis-0.0.1.dev6/MANIFEST.in +1 -0
  2. {easysurfvis-0.0.1.dev4 → easysurfvis-0.0.1.dev6}/PKG-INFO +1 -1
  3. {easysurfvis-0.0.1.dev4 → easysurfvis-0.0.1.dev6}/setup.py +5 -1
  4. easysurfvis-0.0.1.dev6/src/easysurfvis/cores/__init__.py +0 -0
  5. easysurfvis-0.0.1.dev6/src/easysurfvis/cores/afni_extension.py +202 -0
  6. easysurfvis-0.0.1.dev6/src/easysurfvis/cores/custom_matplotlib.py +214 -0
  7. easysurfvis-0.0.1.dev6/src/easysurfvis/cores/general_util.py +150 -0
  8. easysurfvis-0.0.1.dev6/src/easysurfvis/cores/surface_data.py +243 -0
  9. easysurfvis-0.0.1.dev6/src/easysurfvis/cores/surface_roi.py +182 -0
  10. easysurfvis-0.0.1.dev6/src/easysurfvis/cores/surface_util.py +109 -0
  11. easysurfvis-0.0.1.dev6/src/easysurfvis/data/ROI/Brodmann/L_roi_values.npy +0 -0
  12. easysurfvis-0.0.1.dev6/src/easysurfvis/data/ROI/Brodmann/L_roi_vertex_info.json +1 -0
  13. easysurfvis-0.0.1.dev6/src/easysurfvis/data/ROI/Brodmann/L_rois.npy +0 -0
  14. easysurfvis-0.0.1.dev6/src/easysurfvis/data/ROI/Brodmann/R_roi_values.npy +0 -0
  15. easysurfvis-0.0.1.dev6/src/easysurfvis/data/ROI/Brodmann/R_roi_vertex_info.json +1 -0
  16. easysurfvis-0.0.1.dev6/src/easysurfvis/data/ROI/Brodmann/R_rois.npy +0 -0
  17. easysurfvis-0.0.1.dev6/src/easysurfvis/data/ROI/FAN/L_roi_values.npy +0 -0
  18. easysurfvis-0.0.1.dev6/src/easysurfvis/data/ROI/FAN/L_roi_vertex_info.json +1 -0
  19. easysurfvis-0.0.1.dev6/src/easysurfvis/data/ROI/FAN/L_rois.npy +0 -0
  20. easysurfvis-0.0.1.dev6/src/easysurfvis/data/ROI/FAN/R_roi_values.npy +0 -0
  21. easysurfvis-0.0.1.dev6/src/easysurfvis/data/ROI/FAN/R_roi_vertex_info.json +1 -0
  22. easysurfvis-0.0.1.dev6/src/easysurfvis/data/ROI/FAN/R_rois.npy +0 -0
  23. easysurfvis-0.0.1.dev6/src/easysurfvis/data/Sample/l_sampling_datas1.npy +0 -0
  24. easysurfvis-0.0.1.dev6/src/easysurfvis/data/Sample/l_sampling_datas2.npy +0 -0
  25. easysurfvis-0.0.1.dev6/src/easysurfvis/data/Sample/l_virtual_strip_mask.npy +0 -0
  26. easysurfvis-0.0.1.dev6/src/easysurfvis/data/Sample/r_sampling_datas1.npy +0 -0
  27. easysurfvis-0.0.1.dev6/src/easysurfvis/data/Sample/r_sampling_datas2.npy +0 -0
  28. easysurfvis-0.0.1.dev6/src/easysurfvis/data/Sample/r_virtual_strip_mask.npy +0 -0
  29. easysurfvis-0.0.1.dev6/src/easysurfvis/data/Sample/sample_3d_data.nii.gz +0 -0
  30. easysurfvis-0.0.1.dev6/src/easysurfvis/data/Sulcus/L_sulcus.json +1 -0
  31. easysurfvis-0.0.1.dev6/src/easysurfvis/data/Sulcus/L_sulcus_sensorimotor.json +230 -0
  32. easysurfvis-0.0.1.dev6/src/easysurfvis/data/Sulcus/R_sulcus.json +1 -0
  33. easysurfvis-0.0.1.dev6/src/easysurfvis/data/Sulcus/R_sulcus_sensorimotor.json +250 -0
  34. easysurfvis-0.0.1.dev6/src/easysurfvis/data/Template/fs_LR.32k.L.flat.surf.gii +81 -0
  35. easysurfvis-0.0.1.dev6/src/easysurfvis/data/Template/fs_LR.32k.L.inflated.surf.gii +136 -0
  36. easysurfvis-0.0.1.dev6/src/easysurfvis/data/Template/fs_LR.32k.L.pial.surf.gii +1453 -0
  37. easysurfvis-0.0.1.dev6/src/easysurfvis/data/Template/fs_LR.32k.L.shape.gii +6 -0
  38. easysurfvis-0.0.1.dev6/src/easysurfvis/data/Template/fs_LR.32k.L.white.surf.gii +1453 -0
  39. easysurfvis-0.0.1.dev6/src/easysurfvis/data/Template/fs_LR.32k.R.flat.surf.gii +89 -0
  40. easysurfvis-0.0.1.dev6/src/easysurfvis/data/Template/fs_LR.32k.R.inflated.surf.gii +136 -0
  41. easysurfvis-0.0.1.dev6/src/easysurfvis/data/Template/fs_LR.32k.R.pial.surf.gii +1453 -0
  42. easysurfvis-0.0.1.dev6/src/easysurfvis/data/Template/fs_LR.32k.R.shape.gii +6 -0
  43. easysurfvis-0.0.1.dev6/src/easysurfvis/data/Template/fs_LR.32k.R.white.surf.gii +1453 -0
  44. {easysurfvis-0.0.1.dev4 → easysurfvis-0.0.1.dev6}/src/easysurfvis/profile_analysis.py +3 -3
  45. {easysurfvis-0.0.1.dev4 → easysurfvis-0.0.1.dev6}/src/easysurfvis/query_server.py +1 -2
  46. {easysurfvis-0.0.1.dev4 → easysurfvis-0.0.1.dev6}/src/easysurfvis.egg-info/PKG-INFO +1 -1
  47. easysurfvis-0.0.1.dev6/src/easysurfvis.egg-info/SOURCES.txt +52 -0
  48. easysurfvis-0.0.1.dev4/src/easysurfvis.egg-info/SOURCES.txt +0 -11
  49. {easysurfvis-0.0.1.dev4 → easysurfvis-0.0.1.dev6}/README.md +0 -0
  50. {easysurfvis-0.0.1.dev4 → easysurfvis-0.0.1.dev6}/setup.cfg +0 -0
  51. {easysurfvis-0.0.1.dev4 → easysurfvis-0.0.1.dev6}/src/easysurfvis/__init__.py +0 -0
  52. {easysurfvis-0.0.1.dev4 → easysurfvis-0.0.1.dev6}/src/easysurfvis/surface_visualization.py +0 -0
  53. {easysurfvis-0.0.1.dev4 → easysurfvis-0.0.1.dev6}/src/easysurfvis.egg-info/dependency_links.txt +0 -0
  54. {easysurfvis-0.0.1.dev4 → easysurfvis-0.0.1.dev6}/src/easysurfvis.egg-info/requires.txt +0 -0
  55. {easysurfvis-0.0.1.dev4 → easysurfvis-0.0.1.dev6}/src/easysurfvis.egg-info/top_level.txt +0 -0
@@ -0,0 +1 @@
1
+ recursive-include src/easysurfvis/data *
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: easysurfvis
3
- Version: 0.0.1.dev4
3
+ Version: 0.0.1.dev6
4
4
  Summary: visualize surface map easily
5
5
  Home-page: https://github.com/SeojinYoon/easy_surf_vis
6
6
  Author: seojin
@@ -5,15 +5,19 @@ with open("README.md", "r") as fh:
5
5
 
6
6
  setup(
7
7
  name = "easysurfvis",
8
- version = "0.0.1dev4",
8
+ version = "0.0.1dev6",
9
9
  author = "seojin",
10
10
  author_email = "pures1@hanyang.ac.kr",
11
11
  description = "visualize surface map easily",
12
12
  long_description = long_description,
13
13
  long_description_content_type="text/markdown",
14
14
  url = "https://github.com/SeojinYoon/easy_surf_vis",
15
+
15
16
  packages = find_packages(where = "src"),
16
17
  package_dir = {"": "src"},
18
+
19
+ include_package_data=True,
20
+
17
21
  classifiers = [
18
22
  "Programming Language :: Python :: 3",
19
23
  "License :: OSI Approved :: MIT License",
@@ -0,0 +1,202 @@
1
+
2
+ # Common Libraries
3
+ import os
4
+ import subprocess
5
+ import numpy as np
6
+ import pandas as pd
7
+
8
+ # Custom Libraries
9
+ from general_util import get_multiple_elements_in_list
10
+
11
+ # Functions
12
+ def set_afni_abin(abin_path):
13
+ """
14
+ set abin path
15
+
16
+ :param abin_path: path of afni binnary ex) "/Users/clmn/abin/afni"
17
+ """
18
+ os.environ['PATH'] = os.environ['PATH'] + ":" + abin_path
19
+
20
+ def whereami(x,
21
+ y,
22
+ z,
23
+ coord = "spm",
24
+ atlas = None,
25
+ is_show_command = False,
26
+ is_parsing = True):
27
+ """
28
+ Where is the location?
29
+
30
+ https://afni.nimh.nih.gov/pub/dist/doc/program_help/whereami.html
31
+
32
+ :param x: (int)
33
+ :param y: (int)
34
+ :param z: (int)
35
+ :param coord: (string) spm, dicom
36
+ -meaning spm: is equal to RAS+, lpi coords
37
+ -meaning dicom: is equal to LPS+ rai coords
38
+
39
+ :param atlas: (string)
40
+ -Haskins_Pediatric_Nonlinear_1.0
41
+ -CA_ML_18_MNI
42
+ -and so on...
43
+
44
+ return (pd.DataFrame)
45
+ -row: atlas info
46
+ """
47
+
48
+ if atlas != None:
49
+ command = f"whereami {x} {y} {z} -{coord} -atlas {atlas}"
50
+ else:
51
+ command = f"whereami {x} {y} {z} -{coord}"
52
+
53
+ if is_show_command:
54
+ print(command)
55
+
56
+ # command
57
+ output = subprocess.check_output(command, shell=True)
58
+ output = output.decode('utf-8').split("\n")
59
+
60
+ if is_parsing == False:
61
+ return output
62
+ else:
63
+ atlas_lines = search_stringAcrossTarget(output,
64
+ search_keys = ["Atlas"],
65
+ exclude_keys=["nearby"],
66
+ return_type = "index")
67
+
68
+ search_atlas = []
69
+ search_infos = []
70
+ search_names = []
71
+ for i in range(len(atlas_lines)):
72
+ if len(atlas_lines) == 1:
73
+ start_line_i = atlas_lines[0]
74
+ end_line_i = search_stringAcrossTarget(output,
75
+ search_keys = ["Please", "caution"],
76
+ return_type = "index")[0]
77
+ else:
78
+ if i + 1 < len(atlas_lines):
79
+ # Search region name based on each atlas
80
+ start_line_i = atlas_lines[i]
81
+ end_line_i = atlas_lines[i+1] - 1
82
+ else:
83
+ continue
84
+
85
+ atlas_name = output[start_line_i].split(": ")[0].replace("Atlas ", "")
86
+ selected_output = output[start_line_i:end_line_i]
87
+
88
+ # search result
89
+ search_results = search_stringAcrossTarget(selected_output,
90
+ search_keys = ["Focus", "Within"],
91
+ search_type = "any")
92
+
93
+ for result in search_results:
94
+ sp_result = result.split(":")
95
+
96
+ info = sp_result[0].strip()
97
+ name = sp_result[1].strip()
98
+
99
+ search_atlas.append(atlas_name)
100
+ search_infos.append(info)
101
+ search_names.append(name)
102
+
103
+
104
+ result_df = pd.DataFrame({
105
+ "atlas" : search_atlas,
106
+ "info" : search_infos,
107
+ "name" : search_names,
108
+ })
109
+
110
+ return result_df
111
+
112
+ def search_string(target, search_keys, search_type = "any", exclude_keys = []):
113
+ """
114
+ Search string with keys in target
115
+
116
+ :param target(str): target string
117
+ :param keys(list - str): search key
118
+ :param search_type(str): search type - 'any', 'all', any is 'or' condition, all is 'and' condition
119
+ :param exclude_keys(list - str): exclude key
120
+
121
+ return boolean
122
+ """
123
+ if search_type == "any":
124
+ search_result = any([key in target for key in search_keys])
125
+ elif search_type == "all":
126
+ search_result = all([key in target for key in search_keys])
127
+ elif search_type == "correct":
128
+ assert(len(search_keys) == 1), "please input only one search key"
129
+ search_result = search_keys[0] == target
130
+
131
+ if exclude_keys != None and exclude_keys != []:
132
+ exclude_result = not any([key in target for key in exclude_keys])
133
+
134
+ return search_result and exclude_result
135
+ else:
136
+ return search_result
137
+
138
+ def search_stringAcrossTarget(targets,
139
+ search_keys,
140
+ search_type = "any",
141
+ exclude_keys = [],
142
+ validation_type = None,
143
+ return_type = "string"):
144
+ """
145
+ Search string across target strings
146
+
147
+ :param target(list): target string
148
+ :param keys(str): search key
149
+ :param search_type(str): search type - 'any', 'all', any is or condition, all is and condition
150
+ :param exclude_keys(list - str): exclude key
151
+ :param validation_type(File_validation): kinds of validation checking from search result
152
+ :param return_type(string): 'string' or 'index'
153
+
154
+ return list of searched string
155
+ """
156
+ search_results = [search_string(target = target,
157
+ search_keys = search_keys,
158
+ search_type = search_type,
159
+ exclude_keys = exclude_keys) for target in targets]
160
+ search_flags = np.array(search_results)
161
+ indexes = np.where(search_flags == True)[0]
162
+ result = get_multiple_elements_in_list(targets, indexes)
163
+
164
+ # search validation
165
+ if validation_type == None:
166
+ pass
167
+ else:
168
+ if validation_type.value & File_validation.exist.value != 0:
169
+ # Check the search result existed
170
+ assert len(result) != 0, "Please check to exist file"
171
+ if validation_type.value & File_validation.only.value != 0:
172
+ if len(result) > 1:
173
+ print(result)
174
+ raise Exception("Multiple similar files")
175
+
176
+ # return
177
+ def return_func():
178
+ if return_type == "index":
179
+ return indexes
180
+ elif return_type == "flag":
181
+ return search_flags
182
+ else:
183
+ return result
184
+
185
+ if validation_type == None:
186
+ return return_func()
187
+ else:
188
+ if validation_type.value & File_validation.only.value != 0:
189
+ if return_type == "index":
190
+ return indexes[0]
191
+ elif return_type == "flag":
192
+ return search_flags
193
+ else:
194
+ return result[0]
195
+ else:
196
+ return return_func()
197
+
198
+
199
+
200
+ if __name__ == "__main__":
201
+ set_afni_abin("/Users/clmn/abin/afni")
202
+ whereami(x = 10, y = 10, z = 10)
@@ -0,0 +1,214 @@
1
+
2
+ """
3
+ This file contains the basic source code to visualize graph using matplotlib
4
+ """
5
+ # Common Libraries
6
+ import numpy as np
7
+ import matplotlib.pylab as plt
8
+ from scipy.stats import cumfreq
9
+ from matplotlib.lines import Line2D
10
+ from matplotlib.ticker import FuncFormatter
11
+
12
+ # Custom Libraries
13
+ from general_util import search_stringAcrossTarget, find_consecutive_ranges
14
+
15
+ # Functions
16
+ def draw_title(axis, title_info = {}):
17
+ """
18
+ Draw title in the axis
19
+
20
+ :param title_info(dictionary):
21
+ -k, title(string): title
22
+ -k, title_weight(string): weight of font
23
+ -k, title_size(string): size of title
24
+ -k, title_y_pos(string): y pos of title
25
+ """
26
+ title = title_info.get("title", "")
27
+ title_weight = title_info.get("title_weight", "bold")
28
+ title_size = title_info.get("title_size", 20)
29
+ title_y_pos = title_info.get("title_y_pos", 1.0)
30
+
31
+ axis.set_title(title,
32
+ fontweight = title_weight,
33
+ size = title_size,
34
+ y = title_y_pos)
35
+
36
+ def draw_label(axis, label_info = {}):
37
+ """
38
+ Draw label in the axis
39
+
40
+ :param label_info(dictionary):
41
+ -k, color(string): label color
42
+ -k, x_label(string): x label text
43
+ -k, y_label(string): y label text
44
+ -k, x_weight(string): x label weight
45
+ -k, y_weight(string): y label weight
46
+ -k, x_size(float): x label size
47
+ -k, y_size(float): y label size
48
+ """
49
+ color = label_info.get("color", "black")
50
+
51
+ x_label = label_info.get("x_label", "")
52
+ y_label = label_info.get("y_label", "")
53
+
54
+ x_weight = label_info.get("x_weight", "normal")
55
+ y_weight = label_info.get("y_weight", "normal")
56
+
57
+ x_label_size = label_info.get("x_size", 16)
58
+ y_label_size = label_info.get("y_size", 16)
59
+
60
+ x_label_pad = label_info.get("x_label_pad", 10)
61
+ y_label_pad = label_info.get("y_label_pad", 10)
62
+
63
+ axis.set_xlabel(x_label,
64
+ color = color,
65
+ weight = x_weight,
66
+ size = x_label_size,
67
+ labelpad = x_label_pad)
68
+
69
+ axis.set_ylabel(y_label,
70
+ color = color,
71
+ weight = y_weight,
72
+ size = y_label_size,
73
+ labelpad = y_label_pad)
74
+
75
+ def draw_ticks(axis, tick_info = {}):
76
+ """
77
+ Draw ticks in the axis
78
+
79
+ :param tick_info(dictionary): tick style configuration
80
+ -k, x_data(list): x tick positions ex) [1,2,3]
81
+ -k, x_names(list): x tick text ex) ["a", "b", "c"]
82
+ -k, x_tick_weight(string): x tick weight
83
+ -k, x_tick_size(float): x tick size
84
+ -k, x_tick_rotation(int): x tick rotation
85
+
86
+ -k, y_data(list): y tick positions ex) [1,2,3]
87
+ -k, y_names(list): y tick text ex) ["a", "b", "c"]
88
+ -k, y_tick_precision(float): Number of decimal places to display on y-axis ticks
89
+ -k, y_tick_weight(string): y tick weight
90
+ -k, y_tick_size(float): y tick size
91
+ -k, y_tick_rotation(int): y tick rotation
92
+ -k, y_divided(int): the number of division for showing y-tick
93
+ -k, y_need_tick(list): the y-tick which must to show
94
+ """
95
+ x_data = tick_info.get("x_data", [])
96
+ x_names = tick_info.get("x_names", [])
97
+
98
+ x_tick_weight = tick_info.get("x_tick_weight", "normal")
99
+ x_tick_size = tick_info.get("x_tick_size", 14)
100
+ x_tick_rotation = tick_info.get("x_tick_rotation", 90)
101
+ x_tick_viewType = tick_info.get("x_tick_viewType", "remove_duplication")
102
+
103
+ y_data = tick_info.get("y_data", [])
104
+ y_names = tick_info.get("y_names", [])
105
+
106
+ y_tick_weight = tick_info.get("y_tick_weight", "normal")
107
+ y_tick_size = tick_info.get("y_tick_size", 14)
108
+ y_tick_rotation = tick_info.get("y_tick_rotation", 0)
109
+ y_tick_precision = tick_info.get("y_tick_precision", None)
110
+
111
+ # X
112
+ x_data = np.array(x_data)
113
+ x_names = np.array(x_names)
114
+
115
+ if x_tick_viewType == "remove_duplication":
116
+ x_tick_duplication = np.array([int((start + end) / 2) for start, end in find_consecutive_ranges(x_names)], dtype = int)
117
+ x_tick_data = np.array([(x_data[start] + x_data[end]) / 2 for start, end in find_consecutive_ranges(x_names)])
118
+
119
+ if len(x_tick_duplication) > 0:
120
+ x_names = x_names[x_tick_duplication]
121
+ x_data = x_tick_data
122
+
123
+ axis.set_xticks(x_data,
124
+ x_names,
125
+ rotation = x_tick_rotation,
126
+ weight = x_tick_weight,
127
+ size = x_tick_size)
128
+
129
+ # Y
130
+ axis.set_yticks(y_data,
131
+ y_names,
132
+ rotation = y_tick_rotation,
133
+ weight = y_tick_weight,
134
+ size = y_tick_size)
135
+ if y_tick_precision is not None:
136
+ axis.yaxis.set_major_formatter(FuncFormatter(lambda y, _: f"{y:.{y_tick_precision}f}"))
137
+
138
+ def draw_spine(axis, spine_info = {}):
139
+ """
140
+ Draw spine in the axis
141
+
142
+ :param spine_info(dictionary):
143
+ -k, spine_linewidth(float): spine line width ex) 2
144
+ -k, spine_color(string): spine line color ex) "black"
145
+ -k, invisibles(list): invisible informations ex) ["right", "top"]
146
+ """
147
+ spine_line_width = spine_info.get("spine_linewidth", 1)
148
+ spine_color = spine_info.get("spine_color", "black")
149
+ invisibles = spine_info.get("invisibles", ["right", "top"])
150
+
151
+ all_spines = ["bottom", "top", "left", "right"]
152
+ for invisible in invisibles:
153
+ axis.spines[invisible].set_visible(False)
154
+ all_spines.remove(invisible)
155
+
156
+ for ax_name in all_spines:
157
+ axis.spines[ax_name].set_linewidth(spine_line_width)
158
+ axis.spines[ax_name].set_linewidth(spine_line_width)
159
+ axis.spines[ax_name].set_color(spine_color)
160
+
161
+ def make_colorbar(vmin,
162
+ vmax,
163
+ figsize = (2, 6),
164
+ n_inner_ticks = 3,
165
+ cmap = "jet",
166
+ tick_precision = 4,
167
+ orientation = "horizontal",
168
+ fontsize = 12):
169
+ """
170
+ Creates a customizable colorbar using matplotlib.
171
+
172
+
173
+ :param vmin (float): The minimum value for the colorbar.
174
+ :param vmax (float): The maximum value for the colorbar.
175
+ :param figsize (tuple): The size of the figure (width, height). Defaults to (2, 6).
176
+ :param n_div (int): Number of divisions (ticks) on the colorbar. Defaults to 4.
177
+ :param cmap (str): Colormap to use for the colorbar. Defaults to "jet".
178
+ :param tick_precision (int): Number of decimal places to display on the tick labels. Defaults to 4.
179
+ :param orientation (str): Orientation of the colorbar, either "horizontal" or "vertical". Defaults to "horizontal".
180
+
181
+ return (tuple): A tuple containing the matplotlib figure and axis objects.
182
+ """
183
+ n_div = n_inner_ticks + 1
184
+
185
+ interval = (vmax - vmin) / n_div
186
+ ticks = np.linspace(vmin, vmax, n_div + 1)
187
+
188
+ # Create the figure and axis for the colorbar
189
+ fig = plt.figure(figsize = figsize)
190
+
191
+ if orientation == "vertical":
192
+ axis = fig.add_axes([0.05, 0.05, 0.15, 0.9]) # [left, bottom, width, height]
193
+ else:
194
+ axis = fig.add_axes([0.1, 0.5, 0.8, 0.3]) # [left, bottom, width, height]
195
+
196
+ # Create the colorbar
197
+ cmap = plt.get_cmap(cmap)
198
+ norm = plt.Normalize(vmin = vmin, vmax = vmax)
199
+ cbar = fig.colorbar(plt.cm.ScalarMappable(norm=norm, cmap=cmap), cax=axis, orientation=orientation)
200
+
201
+ # Set the ticks and labels
202
+ if orientation == "vertical":
203
+ axis.set_yticks(ticks)
204
+ axis.set_yticklabels([f"{tick:.{tick_precision}f}" for tick in ticks], fontsize = fontsize)
205
+ axis.get_xaxis().set_visible(False)
206
+ else:
207
+ axis.set_xticks(ticks)
208
+ axis.set_xticklabels([f"{tick:.{tick_precision}f}" for tick in ticks], fontsize = fontsize)
209
+ axis.get_yaxis().set_visible(False)
210
+
211
+ return fig, axis, ticks
212
+
213
+ if __name__=="__main__":
214
+ pass
@@ -0,0 +1,150 @@
1
+
2
+ # Common Libraries
3
+ import re
4
+ import numpy as np
5
+ from enum import Enum
6
+
7
+ # Classes
8
+ class File_validation(Enum):
9
+ exist = 1 << 0
10
+ only = 1 << 1
11
+
12
+ exist_only = exist | only
13
+
14
+ # Functions
15
+ def search_string(target, search_keys, search_type = "any", exclude_keys = []):
16
+ """
17
+ Search string with keys in target
18
+
19
+ :param target(str): target string
20
+ :param keys(list - str): search key
21
+ :param search_type(str): search type - 'any', 'all', any is 'or' condition, all is 'and' condition
22
+ :param exclude_keys(list - str): exclude key
23
+
24
+ return boolean
25
+ """
26
+ if search_type == "any":
27
+ search_result = any([key in target for key in search_keys])
28
+ elif search_type == "all":
29
+ search_result = all([key in target for key in search_keys])
30
+ elif search_type == "correct":
31
+ assert(len(search_keys) == 1), "please input only one search key"
32
+ search_result = search_keys[0] == target
33
+
34
+ if exclude_keys != None and exclude_keys != []:
35
+ exclude_result = not any([key in target for key in exclude_keys])
36
+
37
+ return search_result and exclude_result
38
+ else:
39
+ return search_result
40
+
41
+ def search_stringAcrossTarget(targets,
42
+ search_keys,
43
+ search_type = "any",
44
+ exclude_keys = [],
45
+ validation_type = None,
46
+ return_type = "string"):
47
+ """
48
+ Search string across target strings
49
+
50
+ :param target(list): target string
51
+ :param keys(str): search key
52
+ :param search_type(str): search type - 'any', 'all', any is or condition, all is and condition
53
+ :param exclude_keys(list - str): exclude key
54
+ :param validation_type(File_validation): kinds of validation checking from search result
55
+ :param return_type(string): 'string' or 'index'
56
+
57
+ return list of searched string
58
+ """
59
+ search_results = [search_string(target = target,
60
+ search_keys = search_keys,
61
+ search_type = search_type,
62
+ exclude_keys = exclude_keys) for target in targets]
63
+ search_flags = np.array(search_results)
64
+ indexes = np.where(search_flags == True)[0]
65
+ result = list(np.array(targets)[indexes])
66
+
67
+ # search validation
68
+ if validation_type is not None:
69
+ if validation_type.value & File_validation.exist.value != 0: # check existence
70
+ assert len(result) != 0, "Please check to exist file"
71
+ if validation_type.value & File_validation.only.value != 0: # check the number of files
72
+ if len(result) > 1:
73
+ raise Exception("Multiple similar files")
74
+
75
+ # return
76
+ if return_type == "index":
77
+ out = indexes
78
+ elif return_type == "flag":
79
+ out = search_flags
80
+ else:
81
+ out = results
82
+
83
+ # only 옵션이면 scalar로 축약
84
+ if (validation_type is not None
85
+ and (validation_type.value & File_validation.only.value)
86
+ and return_type != "flag"
87
+ ):
88
+ return out[0]
89
+
90
+ return out
91
+
92
+ def find_consecutive_ranges(data):
93
+ """
94
+ Find index ranges of consecutive identical values
95
+
96
+ :param data: (list)
97
+
98
+ return [(start index, stop index)]
99
+ """
100
+ if not isinstance(data, list):
101
+ data = list(data)
102
+
103
+ if not data:
104
+ return []
105
+
106
+ result = []
107
+ start = 0
108
+
109
+ for i in range(1, len(data)):
110
+ if data[i] != data[i - 1]:
111
+ result.append((start, i - 1))
112
+ start = i
113
+
114
+ result.append((start, len(data) - 1))
115
+ return result
116
+
117
+ def get_multiple_elements_in_list(in_list, in_indices):
118
+ """
119
+ Get multiple element using indexes
120
+
121
+ :param in_list: data(list)
122
+ :param in_indices: indexes to be extracted from in_list
123
+ """
124
+ return [in_list[i] for i in in_indices]
125
+
126
+ def get_unique_values(data):
127
+ """
128
+ Get unique values from data
129
+
130
+ :param data: (list)
131
+
132
+ return (list)
133
+ """
134
+
135
+ unique_values = []
136
+ for e in data:
137
+ if e in unique_values:
138
+ pass
139
+ else:
140
+ unique_values.append(e)
141
+ return unique_values
142
+
143
+ # Examples
144
+ if __name__ == "__main__":
145
+ a_string = "A string is more than its parts!"
146
+ matches = ["more", "d"]
147
+ search_string(a_string, matches, search_type = "all")
148
+
149
+ search_stringAcrossTarget(targets = ["1","2","3"], search_keys=["1"], return_type = "flag")
150
+ find_consecutive_ranges([1,1,2,3])