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.
- easysurfvis-0.0.1.dev6/MANIFEST.in +1 -0
- {easysurfvis-0.0.1.dev4 → easysurfvis-0.0.1.dev6}/PKG-INFO +1 -1
- {easysurfvis-0.0.1.dev4 → easysurfvis-0.0.1.dev6}/setup.py +5 -1
- easysurfvis-0.0.1.dev6/src/easysurfvis/cores/__init__.py +0 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/cores/afni_extension.py +202 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/cores/custom_matplotlib.py +214 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/cores/general_util.py +150 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/cores/surface_data.py +243 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/cores/surface_roi.py +182 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/cores/surface_util.py +109 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/data/ROI/Brodmann/L_roi_values.npy +0 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/data/ROI/Brodmann/L_roi_vertex_info.json +1 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/data/ROI/Brodmann/L_rois.npy +0 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/data/ROI/Brodmann/R_roi_values.npy +0 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/data/ROI/Brodmann/R_roi_vertex_info.json +1 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/data/ROI/Brodmann/R_rois.npy +0 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/data/ROI/FAN/L_roi_values.npy +0 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/data/ROI/FAN/L_roi_vertex_info.json +1 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/data/ROI/FAN/L_rois.npy +0 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/data/ROI/FAN/R_roi_values.npy +0 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/data/ROI/FAN/R_roi_vertex_info.json +1 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/data/ROI/FAN/R_rois.npy +0 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/data/Sample/l_sampling_datas1.npy +0 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/data/Sample/l_sampling_datas2.npy +0 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/data/Sample/l_virtual_strip_mask.npy +0 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/data/Sample/r_sampling_datas1.npy +0 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/data/Sample/r_sampling_datas2.npy +0 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/data/Sample/r_virtual_strip_mask.npy +0 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/data/Sample/sample_3d_data.nii.gz +0 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/data/Sulcus/L_sulcus.json +1 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/data/Sulcus/L_sulcus_sensorimotor.json +230 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/data/Sulcus/R_sulcus.json +1 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/data/Sulcus/R_sulcus_sensorimotor.json +250 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/data/Template/fs_LR.32k.L.flat.surf.gii +81 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/data/Template/fs_LR.32k.L.inflated.surf.gii +136 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/data/Template/fs_LR.32k.L.pial.surf.gii +1453 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/data/Template/fs_LR.32k.L.shape.gii +6 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/data/Template/fs_LR.32k.L.white.surf.gii +1453 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/data/Template/fs_LR.32k.R.flat.surf.gii +89 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/data/Template/fs_LR.32k.R.inflated.surf.gii +136 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/data/Template/fs_LR.32k.R.pial.surf.gii +1453 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/data/Template/fs_LR.32k.R.shape.gii +6 -0
- easysurfvis-0.0.1.dev6/src/easysurfvis/data/Template/fs_LR.32k.R.white.surf.gii +1453 -0
- {easysurfvis-0.0.1.dev4 → easysurfvis-0.0.1.dev6}/src/easysurfvis/profile_analysis.py +3 -3
- {easysurfvis-0.0.1.dev4 → easysurfvis-0.0.1.dev6}/src/easysurfvis/query_server.py +1 -2
- {easysurfvis-0.0.1.dev4 → easysurfvis-0.0.1.dev6}/src/easysurfvis.egg-info/PKG-INFO +1 -1
- easysurfvis-0.0.1.dev6/src/easysurfvis.egg-info/SOURCES.txt +52 -0
- easysurfvis-0.0.1.dev4/src/easysurfvis.egg-info/SOURCES.txt +0 -11
- {easysurfvis-0.0.1.dev4 → easysurfvis-0.0.1.dev6}/README.md +0 -0
- {easysurfvis-0.0.1.dev4 → easysurfvis-0.0.1.dev6}/setup.cfg +0 -0
- {easysurfvis-0.0.1.dev4 → easysurfvis-0.0.1.dev6}/src/easysurfvis/__init__.py +0 -0
- {easysurfvis-0.0.1.dev4 → easysurfvis-0.0.1.dev6}/src/easysurfvis/surface_visualization.py +0 -0
- {easysurfvis-0.0.1.dev4 → easysurfvis-0.0.1.dev6}/src/easysurfvis.egg-info/dependency_links.txt +0 -0
- {easysurfvis-0.0.1.dev4 → easysurfvis-0.0.1.dev6}/src/easysurfvis.egg-info/requires.txt +0 -0
- {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 *
|
|
@@ -5,15 +5,19 @@ with open("README.md", "r") as fh:
|
|
|
5
5
|
|
|
6
6
|
setup(
|
|
7
7
|
name = "easysurfvis",
|
|
8
|
-
version = "0.0.
|
|
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",
|
|
File without changes
|
|
@@ -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])
|