cosmopharm 0.0.26__py3-none-any.whl → 0.0.27__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.
- cosmopharm/__init__.py +2 -2
- cosmopharm/actmodels/actmodel.py +118 -118
- cosmopharm/actmodels/cosmo.py +152 -152
- cosmopharm/components.py +31 -31
- cosmopharm/equilibrium/__init__.py +2 -2
- cosmopharm/equilibrium/lle.py +178 -178
- cosmopharm/equilibrium/sle.py +244 -244
- cosmopharm/utils/__init__.py +3 -3
- cosmopharm/utils/convert.py +58 -58
- cosmopharm/utils/helpers.py +36 -36
- cosmopharm/utils/lle_scanner.py +188 -188
- cosmopharm/utils/spacing.py +246 -246
- {cosmopharm-0.0.26.dist-info → cosmopharm-0.0.27.dist-info}/LICENSE +20 -20
- {cosmopharm-0.0.26.dist-info → cosmopharm-0.0.27.dist-info}/METADATA +150 -150
- cosmopharm-0.0.27.dist-info/RECORD +18 -0
- {cosmopharm-0.0.26.dist-info → cosmopharm-0.0.27.dist-info}/WHEEL +1 -1
- cosmopharm-0.0.26.dist-info/RECORD +0 -18
- {cosmopharm-0.0.26.dist-info → cosmopharm-0.0.27.dist-info}/top_level.txt +0 -0
cosmopharm/utils/spacing.py
CHANGED
@@ -1,246 +1,246 @@
|
|
1
|
-
'''
|
2
|
-
A selection of rate functions, i.e., speed curves for animations.
|
3
|
-
(1) https://docs.manim.community/en/stable/reference/manim.utils.rate_functions.html
|
4
|
-
(2) https://easings.net/
|
5
|
-
'''
|
6
|
-
# Indicate which objects should be imported with "from spacing import *"
|
7
|
-
__all__ = ["spacing"]
|
8
|
-
|
9
|
-
import numpy as np
|
10
|
-
|
11
|
-
# =============================================================================
|
12
|
-
# Define Spacing Functions
|
13
|
-
# =============================================================================
|
14
|
-
def easeOutExpo(x, base=2, power=-10):
|
15
|
-
return 1 - base**(power * x)
|
16
|
-
|
17
|
-
def easeOutPoly(x, n=1.5):
|
18
|
-
return 1 - (1 - x)**n
|
19
|
-
|
20
|
-
def sigmoid(x: float) -> float:
|
21
|
-
r"""Returns the output of the logistic function.
|
22
|
-
|
23
|
-
The logistic function, a common example of a sigmoid function, is defined
|
24
|
-
as :math:`\frac{1}{1 + e^{-x}}`.
|
25
|
-
|
26
|
-
References
|
27
|
-
----------
|
28
|
-
- https://en.wikipedia.org/wiki/Sigmoid_function
|
29
|
-
- https://en.wikipedia.org/wiki/Logistic_function
|
30
|
-
"""
|
31
|
-
return 1.0 / (1 + np.exp(-x))
|
32
|
-
|
33
|
-
def smooth(t: float, inflection: float = 10.0) -> float:
|
34
|
-
error = sigmoid(-inflection / 2)
|
35
|
-
err = (sigmoid(inflection * (t - 0.5)) - error) / (1 - 2 * error)
|
36
|
-
return np.minimum(np.maximum(err, 0), 1)
|
37
|
-
|
38
|
-
funcs = {
|
39
|
-
'circle' : lambda x, n=2: (1 - (x - 1)**n)**(1/n),
|
40
|
-
'easeOutExpo' : easeOutExpo,
|
41
|
-
'poly' : easeOutPoly,
|
42
|
-
'root' : lambda x, n=2: x**(1/n),
|
43
|
-
'linear' : lambda x: easeOutPoly(x, n=1),
|
44
|
-
'quadratic' : lambda x: easeOutPoly(x, n=2),
|
45
|
-
'cubic' : lambda x: easeOutPoly(x, n=3),
|
46
|
-
# 'sigmoid' : smooth,
|
47
|
-
}
|
48
|
-
|
49
|
-
|
50
|
-
def spacing(mi, ma, num, func_name='linear', reverse=False, log_scale=False, **kwargs):
|
51
|
-
if log_scale:
|
52
|
-
# mi, ma = np.log10(mi), np.log10(ma)
|
53
|
-
mi, ma = 10**mi, 10**ma
|
54
|
-
x = np.linspace(0, 1, num)
|
55
|
-
y = evaluate_function(x, func_name, **kwargs)
|
56
|
-
y = (1 - y)[::-1] if reverse else y
|
57
|
-
# result = mi + (ma - mi) * y
|
58
|
-
# return 10**result if log_scale else result
|
59
|
-
return mi + (ma - mi) * y
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
# =============================================================================
|
64
|
-
# MAIN
|
65
|
-
# =============================================================================
|
66
|
-
def main():
|
67
|
-
trim = False
|
68
|
-
|
69
|
-
# Choose what to plot
|
70
|
-
plot_bar_chart(trim=trim)
|
71
|
-
# plot_specific_function('all', trim=trim)
|
72
|
-
pass
|
73
|
-
|
74
|
-
|
75
|
-
# =============================================================================
|
76
|
-
# OPTIONS
|
77
|
-
# =============================================================================
|
78
|
-
def plot_bar_chart(trim=True):
|
79
|
-
x, values, diffs, colors = prepare_data(trim=trim)
|
80
|
-
fig, ax = plt.subplots()
|
81
|
-
ax.set_ylim(0, 1)
|
82
|
-
for idx, (name, dy) in enumerate(diffs.items()):
|
83
|
-
bottom = 0
|
84
|
-
for i, segment in enumerate(dy):
|
85
|
-
bar = ax.bar(name, segment, bottom=bottom, color=colors[i])
|
86
|
-
bar_width = bar[0].get_width()
|
87
|
-
# if i > 0:
|
88
|
-
# # Plot a dotted line connecting the corresponding segments
|
89
|
-
# ax.plot([idx - 1, idx], [bottom, bottom], linestyle=':', color='black')
|
90
|
-
if idx > 0:
|
91
|
-
# Get previous bar's corresponding segment
|
92
|
-
prev_bottom = sum(list(diffs.values())[idx - 1][:i])
|
93
|
-
# Plot a dotted line connecting the corresponding segments
|
94
|
-
w = bar_width / 2
|
95
|
-
x, y = [(idx-1)+w, idx-w], [prev_bottom, bottom]
|
96
|
-
ax.plot(x,y, ls=':', c='black', lw=.8)
|
97
|
-
bottom += segment
|
98
|
-
# Set the tick positions and labels for the x-axis
|
99
|
-
ax.set_xticks(range(len(diffs.keys())))
|
100
|
-
# Set the rotation angle for the x-axis tick labels
|
101
|
-
ax.set_xticklabels(ax.get_xticklabels(), rotation=60)
|
102
|
-
|
103
|
-
|
104
|
-
def plot_specific_function(name, trim=True):
|
105
|
-
x, values, diffs, colors = prepare_data(name, trim)
|
106
|
-
for name, y in values.items():
|
107
|
-
plot(x, y, name)
|
108
|
-
|
109
|
-
|
110
|
-
# =============================================================================
|
111
|
-
# Auxilliary functions
|
112
|
-
# =============================================================================
|
113
|
-
def evaluate_function(x, func_name, trim=True, **kwargs):
|
114
|
-
func = funcs.get(func_name)
|
115
|
-
if func is None:
|
116
|
-
raise ValueError(f"Function with name '{func_name}' not found")
|
117
|
-
# Call the selected function
|
118
|
-
trim_funcs = ('root', 'circle')
|
119
|
-
if (func_name in trim_funcs) and trim:
|
120
|
-
x = np.linspace(0, 1, len(x) + 1)
|
121
|
-
y = func(x, **kwargs)[1:]
|
122
|
-
y = (y-min(y))/(max(y)-min(y))
|
123
|
-
else:
|
124
|
-
y = func(x, **kwargs)
|
125
|
-
return y
|
126
|
-
|
127
|
-
|
128
|
-
def prepare_data(specific_func=None, trim=True):
|
129
|
-
# # Generate an array of equally spaced points between 0 and 1
|
130
|
-
x = np.linspace(0, 1, 11)
|
131
|
-
|
132
|
-
# Calculate function values for each function in the funcs dictionary
|
133
|
-
if specific_func is None or specific_func == 'all':
|
134
|
-
values = {name: evaluate_function(x, name, trim) for name in funcs.keys()}
|
135
|
-
else:
|
136
|
-
values = {specific_func: evaluate_function(x, specific_func, trim)}
|
137
|
-
|
138
|
-
# Compute the differences between consecutive values for each function
|
139
|
-
diffs = {k: np.diff(y) for k, y in values.items()}
|
140
|
-
|
141
|
-
# # Get the first segment for each function
|
142
|
-
# first_segments = {k: y[1] for k, y in values.items()}
|
143
|
-
# # Sort the functions based on the first segment
|
144
|
-
# sorted_list = sorted(diffs.items(), key=lambda item: first_segments[item[0]])
|
145
|
-
# diffs = dict(sorted_list)
|
146
|
-
# sorted_list = ['linear','poly','quadratic','cubic','easeOutExpo', 'circle','root']
|
147
|
-
# diffs = {name: diffs[name] for name in sorted_list}
|
148
|
-
|
149
|
-
# # First sort by y[1]
|
150
|
-
# # sort1 = {k: y[1] for k, y in values.items()}
|
151
|
-
# sort1 = {k: (y[1],y[2]) for k, y in values.items()}
|
152
|
-
# sort1 = sorted(sort1.items(), key=lambda item: item[1])
|
153
|
-
# # sort1 = sorted(values.items(), key=lambda item: sort1[item[0]])
|
154
|
-
|
155
|
-
# for i,(k,v) in enumerate(sort1):
|
156
|
-
# v_next = sort1[i+1][1][1]
|
157
|
-
# v_curr = v[1]
|
158
|
-
# if v_curr > v_next:
|
159
|
-
# change_index = i+1
|
160
|
-
# break
|
161
|
-
|
162
|
-
# sort2 = sort1[change_index:]
|
163
|
-
# sort2 = {k: y[2] for k, y in sort2}
|
164
|
-
# sort2 = sorted(sort2.items(), key=lambda item: item[0])
|
165
|
-
# sorted_list = sort1[:change_index]
|
166
|
-
# # sort2 = sorted(values.items(), key=lambda item: sort2[item[0]])
|
167
|
-
|
168
|
-
# Create sort1 dictionary
|
169
|
-
sort1 = {k: (y[1], y[2]) for k, y in values.items()}
|
170
|
-
|
171
|
-
# Sort sort1 by y[1] in ascending order
|
172
|
-
sort1_keys_sorted = sorted(sort1, key=lambda k: sort1[k][0])
|
173
|
-
|
174
|
-
# Find the change_index
|
175
|
-
for i, k in enumerate(sort1_keys_sorted[:-1]):
|
176
|
-
curr_y2 = sort1[k][1]
|
177
|
-
next_y2 = sort1[sort1_keys_sorted[i + 1]][1]
|
178
|
-
if curr_y2 > next_y2:
|
179
|
-
change_index = i + 1
|
180
|
-
break
|
181
|
-
|
182
|
-
# Divide the list into two parts
|
183
|
-
first_part = sort1_keys_sorted[:change_index]
|
184
|
-
second_part = sort1_keys_sorted[change_index:]
|
185
|
-
|
186
|
-
# Sort the second part by y[2] in descending order
|
187
|
-
second_part_sorted = sorted(second_part, key=lambda k: sort1[k][1], reverse=True)
|
188
|
-
|
189
|
-
# Combine the two parts to get the final order
|
190
|
-
final_order = first_part + second_part_sorted
|
191
|
-
|
192
|
-
# Create a new dictionary sorted according to the final order of keys
|
193
|
-
sorted_values = {k: values[k] for k in final_order}
|
194
|
-
diffs = {k: diffs[k] for k in sorted_values.keys()}
|
195
|
-
|
196
|
-
|
197
|
-
# # Find the index where the order changes from ascending to descending
|
198
|
-
# change_index = None
|
199
|
-
# for i in range(1, len(sorted_list)):
|
200
|
-
# if sort1[sorted_list[i][0]] < sort1[sorted_list[i - 1][0]]:
|
201
|
-
# change_index = i
|
202
|
-
# break
|
203
|
-
|
204
|
-
# # Sort the remaining elements in descending order based on y[2]
|
205
|
-
# if change_index is not None:
|
206
|
-
# sort2 = {k: y[2] for k, y in values.items()}
|
207
|
-
# sorted_list = (
|
208
|
-
# sorted_list[:change_index]
|
209
|
-
# + sorted(
|
210
|
-
# sorted_list[change_index:],
|
211
|
-
# key=lambda item: sort2[item[0]],
|
212
|
-
# reverse=True
|
213
|
-
# )
|
214
|
-
# )
|
215
|
-
# diffs = dict(sorted_list)
|
216
|
-
|
217
|
-
# Get the default color cycle
|
218
|
-
default_colors = plt.rcParams['axes.prop_cycle'].by_key()['color']
|
219
|
-
# Generate additional colors using the viridis colormap
|
220
|
-
additional_colors = plt.cm.viridis(np.linspace(0, 1, len(x)))
|
221
|
-
additional_colors = [matplotlib.colors.to_hex(color) for color in additional_colors]
|
222
|
-
# Combine default and additional colors
|
223
|
-
colors = default_colors + additional_colors
|
224
|
-
|
225
|
-
# Return the prepared data
|
226
|
-
return x, values, diffs, colors
|
227
|
-
|
228
|
-
|
229
|
-
def plot(x,y,name):
|
230
|
-
fig,ax = plt.subplots()
|
231
|
-
ax.plot(x,y,'.-',label=name)
|
232
|
-
for xx,yy in zip(x,y):
|
233
|
-
ax.axhline(yy, xmin=0, xmax=xx, ls=':')
|
234
|
-
ax.set_ylim(0,1)
|
235
|
-
ax.set_xlim(0,1)
|
236
|
-
ax.legend(loc='lower right')
|
237
|
-
ax.set_aspect('equal', 'box')
|
238
|
-
|
239
|
-
|
240
|
-
# =============================================================================
|
241
|
-
# Call MAIN
|
242
|
-
# =============================================================================
|
243
|
-
if __name__=='__main__':
|
244
|
-
import matplotlib.pyplot as plt
|
245
|
-
import matplotlib.colors
|
246
|
-
main()
|
1
|
+
'''
|
2
|
+
A selection of rate functions, i.e., speed curves for animations.
|
3
|
+
(1) https://docs.manim.community/en/stable/reference/manim.utils.rate_functions.html
|
4
|
+
(2) https://easings.net/
|
5
|
+
'''
|
6
|
+
# Indicate which objects should be imported with "from spacing import *"
|
7
|
+
__all__ = ["spacing"]
|
8
|
+
|
9
|
+
import numpy as np
|
10
|
+
|
11
|
+
# =============================================================================
|
12
|
+
# Define Spacing Functions
|
13
|
+
# =============================================================================
|
14
|
+
def easeOutExpo(x, base=2, power=-10):
|
15
|
+
return 1 - base**(power * x)
|
16
|
+
|
17
|
+
def easeOutPoly(x, n=1.5):
|
18
|
+
return 1 - (1 - x)**n
|
19
|
+
|
20
|
+
def sigmoid(x: float) -> float:
|
21
|
+
r"""Returns the output of the logistic function.
|
22
|
+
|
23
|
+
The logistic function, a common example of a sigmoid function, is defined
|
24
|
+
as :math:`\frac{1}{1 + e^{-x}}`.
|
25
|
+
|
26
|
+
References
|
27
|
+
----------
|
28
|
+
- https://en.wikipedia.org/wiki/Sigmoid_function
|
29
|
+
- https://en.wikipedia.org/wiki/Logistic_function
|
30
|
+
"""
|
31
|
+
return 1.0 / (1 + np.exp(-x))
|
32
|
+
|
33
|
+
def smooth(t: float, inflection: float = 10.0) -> float:
|
34
|
+
error = sigmoid(-inflection / 2)
|
35
|
+
err = (sigmoid(inflection * (t - 0.5)) - error) / (1 - 2 * error)
|
36
|
+
return np.minimum(np.maximum(err, 0), 1)
|
37
|
+
|
38
|
+
funcs = {
|
39
|
+
'circle' : lambda x, n=2: (1 - (x - 1)**n)**(1/n),
|
40
|
+
'easeOutExpo' : easeOutExpo,
|
41
|
+
'poly' : easeOutPoly,
|
42
|
+
'root' : lambda x, n=2: x**(1/n),
|
43
|
+
'linear' : lambda x: easeOutPoly(x, n=1),
|
44
|
+
'quadratic' : lambda x: easeOutPoly(x, n=2),
|
45
|
+
'cubic' : lambda x: easeOutPoly(x, n=3),
|
46
|
+
# 'sigmoid' : smooth,
|
47
|
+
}
|
48
|
+
|
49
|
+
|
50
|
+
def spacing(mi, ma, num, func_name='linear', reverse=False, log_scale=False, **kwargs):
|
51
|
+
if log_scale:
|
52
|
+
# mi, ma = np.log10(mi), np.log10(ma)
|
53
|
+
mi, ma = 10**mi, 10**ma
|
54
|
+
x = np.linspace(0, 1, num)
|
55
|
+
y = evaluate_function(x, func_name, **kwargs)
|
56
|
+
y = (1 - y)[::-1] if reverse else y
|
57
|
+
# result = mi + (ma - mi) * y
|
58
|
+
# return 10**result if log_scale else result
|
59
|
+
return mi + (ma - mi) * y
|
60
|
+
|
61
|
+
|
62
|
+
|
63
|
+
# =============================================================================
|
64
|
+
# MAIN
|
65
|
+
# =============================================================================
|
66
|
+
def main():
|
67
|
+
trim = False
|
68
|
+
|
69
|
+
# Choose what to plot
|
70
|
+
plot_bar_chart(trim=trim)
|
71
|
+
# plot_specific_function('all', trim=trim)
|
72
|
+
pass
|
73
|
+
|
74
|
+
|
75
|
+
# =============================================================================
|
76
|
+
# OPTIONS
|
77
|
+
# =============================================================================
|
78
|
+
def plot_bar_chart(trim=True):
|
79
|
+
x, values, diffs, colors = prepare_data(trim=trim)
|
80
|
+
fig, ax = plt.subplots()
|
81
|
+
ax.set_ylim(0, 1)
|
82
|
+
for idx, (name, dy) in enumerate(diffs.items()):
|
83
|
+
bottom = 0
|
84
|
+
for i, segment in enumerate(dy):
|
85
|
+
bar = ax.bar(name, segment, bottom=bottom, color=colors[i])
|
86
|
+
bar_width = bar[0].get_width()
|
87
|
+
# if i > 0:
|
88
|
+
# # Plot a dotted line connecting the corresponding segments
|
89
|
+
# ax.plot([idx - 1, idx], [bottom, bottom], linestyle=':', color='black')
|
90
|
+
if idx > 0:
|
91
|
+
# Get previous bar's corresponding segment
|
92
|
+
prev_bottom = sum(list(diffs.values())[idx - 1][:i])
|
93
|
+
# Plot a dotted line connecting the corresponding segments
|
94
|
+
w = bar_width / 2
|
95
|
+
x, y = [(idx-1)+w, idx-w], [prev_bottom, bottom]
|
96
|
+
ax.plot(x,y, ls=':', c='black', lw=.8)
|
97
|
+
bottom += segment
|
98
|
+
# Set the tick positions and labels for the x-axis
|
99
|
+
ax.set_xticks(range(len(diffs.keys())))
|
100
|
+
# Set the rotation angle for the x-axis tick labels
|
101
|
+
ax.set_xticklabels(ax.get_xticklabels(), rotation=60)
|
102
|
+
|
103
|
+
|
104
|
+
def plot_specific_function(name, trim=True):
|
105
|
+
x, values, diffs, colors = prepare_data(name, trim)
|
106
|
+
for name, y in values.items():
|
107
|
+
plot(x, y, name)
|
108
|
+
|
109
|
+
|
110
|
+
# =============================================================================
|
111
|
+
# Auxilliary functions
|
112
|
+
# =============================================================================
|
113
|
+
def evaluate_function(x, func_name, trim=True, **kwargs):
|
114
|
+
func = funcs.get(func_name)
|
115
|
+
if func is None:
|
116
|
+
raise ValueError(f"Function with name '{func_name}' not found")
|
117
|
+
# Call the selected function
|
118
|
+
trim_funcs = ('root', 'circle')
|
119
|
+
if (func_name in trim_funcs) and trim:
|
120
|
+
x = np.linspace(0, 1, len(x) + 1)
|
121
|
+
y = func(x, **kwargs)[1:]
|
122
|
+
y = (y-min(y))/(max(y)-min(y))
|
123
|
+
else:
|
124
|
+
y = func(x, **kwargs)
|
125
|
+
return y
|
126
|
+
|
127
|
+
|
128
|
+
def prepare_data(specific_func=None, trim=True):
|
129
|
+
# # Generate an array of equally spaced points between 0 and 1
|
130
|
+
x = np.linspace(0, 1, 11)
|
131
|
+
|
132
|
+
# Calculate function values for each function in the funcs dictionary
|
133
|
+
if specific_func is None or specific_func == 'all':
|
134
|
+
values = {name: evaluate_function(x, name, trim) for name in funcs.keys()}
|
135
|
+
else:
|
136
|
+
values = {specific_func: evaluate_function(x, specific_func, trim)}
|
137
|
+
|
138
|
+
# Compute the differences between consecutive values for each function
|
139
|
+
diffs = {k: np.diff(y) for k, y in values.items()}
|
140
|
+
|
141
|
+
# # Get the first segment for each function
|
142
|
+
# first_segments = {k: y[1] for k, y in values.items()}
|
143
|
+
# # Sort the functions based on the first segment
|
144
|
+
# sorted_list = sorted(diffs.items(), key=lambda item: first_segments[item[0]])
|
145
|
+
# diffs = dict(sorted_list)
|
146
|
+
# sorted_list = ['linear','poly','quadratic','cubic','easeOutExpo', 'circle','root']
|
147
|
+
# diffs = {name: diffs[name] for name in sorted_list}
|
148
|
+
|
149
|
+
# # First sort by y[1]
|
150
|
+
# # sort1 = {k: y[1] for k, y in values.items()}
|
151
|
+
# sort1 = {k: (y[1],y[2]) for k, y in values.items()}
|
152
|
+
# sort1 = sorted(sort1.items(), key=lambda item: item[1])
|
153
|
+
# # sort1 = sorted(values.items(), key=lambda item: sort1[item[0]])
|
154
|
+
|
155
|
+
# for i,(k,v) in enumerate(sort1):
|
156
|
+
# v_next = sort1[i+1][1][1]
|
157
|
+
# v_curr = v[1]
|
158
|
+
# if v_curr > v_next:
|
159
|
+
# change_index = i+1
|
160
|
+
# break
|
161
|
+
|
162
|
+
# sort2 = sort1[change_index:]
|
163
|
+
# sort2 = {k: y[2] for k, y in sort2}
|
164
|
+
# sort2 = sorted(sort2.items(), key=lambda item: item[0])
|
165
|
+
# sorted_list = sort1[:change_index]
|
166
|
+
# # sort2 = sorted(values.items(), key=lambda item: sort2[item[0]])
|
167
|
+
|
168
|
+
# Create sort1 dictionary
|
169
|
+
sort1 = {k: (y[1], y[2]) for k, y in values.items()}
|
170
|
+
|
171
|
+
# Sort sort1 by y[1] in ascending order
|
172
|
+
sort1_keys_sorted = sorted(sort1, key=lambda k: sort1[k][0])
|
173
|
+
|
174
|
+
# Find the change_index
|
175
|
+
for i, k in enumerate(sort1_keys_sorted[:-1]):
|
176
|
+
curr_y2 = sort1[k][1]
|
177
|
+
next_y2 = sort1[sort1_keys_sorted[i + 1]][1]
|
178
|
+
if curr_y2 > next_y2:
|
179
|
+
change_index = i + 1
|
180
|
+
break
|
181
|
+
|
182
|
+
# Divide the list into two parts
|
183
|
+
first_part = sort1_keys_sorted[:change_index]
|
184
|
+
second_part = sort1_keys_sorted[change_index:]
|
185
|
+
|
186
|
+
# Sort the second part by y[2] in descending order
|
187
|
+
second_part_sorted = sorted(second_part, key=lambda k: sort1[k][1], reverse=True)
|
188
|
+
|
189
|
+
# Combine the two parts to get the final order
|
190
|
+
final_order = first_part + second_part_sorted
|
191
|
+
|
192
|
+
# Create a new dictionary sorted according to the final order of keys
|
193
|
+
sorted_values = {k: values[k] for k in final_order}
|
194
|
+
diffs = {k: diffs[k] for k in sorted_values.keys()}
|
195
|
+
|
196
|
+
|
197
|
+
# # Find the index where the order changes from ascending to descending
|
198
|
+
# change_index = None
|
199
|
+
# for i in range(1, len(sorted_list)):
|
200
|
+
# if sort1[sorted_list[i][0]] < sort1[sorted_list[i - 1][0]]:
|
201
|
+
# change_index = i
|
202
|
+
# break
|
203
|
+
|
204
|
+
# # Sort the remaining elements in descending order based on y[2]
|
205
|
+
# if change_index is not None:
|
206
|
+
# sort2 = {k: y[2] for k, y in values.items()}
|
207
|
+
# sorted_list = (
|
208
|
+
# sorted_list[:change_index]
|
209
|
+
# + sorted(
|
210
|
+
# sorted_list[change_index:],
|
211
|
+
# key=lambda item: sort2[item[0]],
|
212
|
+
# reverse=True
|
213
|
+
# )
|
214
|
+
# )
|
215
|
+
# diffs = dict(sorted_list)
|
216
|
+
|
217
|
+
# Get the default color cycle
|
218
|
+
default_colors = plt.rcParams['axes.prop_cycle'].by_key()['color']
|
219
|
+
# Generate additional colors using the viridis colormap
|
220
|
+
additional_colors = plt.cm.viridis(np.linspace(0, 1, len(x)))
|
221
|
+
additional_colors = [matplotlib.colors.to_hex(color) for color in additional_colors]
|
222
|
+
# Combine default and additional colors
|
223
|
+
colors = default_colors + additional_colors
|
224
|
+
|
225
|
+
# Return the prepared data
|
226
|
+
return x, values, diffs, colors
|
227
|
+
|
228
|
+
|
229
|
+
def plot(x,y,name):
|
230
|
+
fig,ax = plt.subplots()
|
231
|
+
ax.plot(x,y,'.-',label=name)
|
232
|
+
for xx,yy in zip(x,y):
|
233
|
+
ax.axhline(yy, xmin=0, xmax=xx, ls=':')
|
234
|
+
ax.set_ylim(0,1)
|
235
|
+
ax.set_xlim(0,1)
|
236
|
+
ax.legend(loc='lower right')
|
237
|
+
ax.set_aspect('equal', 'box')
|
238
|
+
|
239
|
+
|
240
|
+
# =============================================================================
|
241
|
+
# Call MAIN
|
242
|
+
# =============================================================================
|
243
|
+
if __name__=='__main__':
|
244
|
+
import matplotlib.pyplot as plt
|
245
|
+
import matplotlib.colors
|
246
|
+
main()
|
@@ -1,21 +1,21 @@
|
|
1
|
-
MIT License
|
2
|
-
|
3
|
-
Copyright (c) 2024 Ivan Antolovic <Ivan.Antolovic@tu-berlin.de>, Martin Klajmon <Martin.Klajmon@vscht.cz>
|
4
|
-
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
7
|
-
in the Software without restriction, including without limitation the rights
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
10
|
-
furnished to do so, subject to the following conditions:
|
11
|
-
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
13
|
-
copies or substantial portions of the Software.
|
14
|
-
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2024 Ivan Antolovic <Ivan.Antolovic@tu-berlin.de>, Martin Klajmon <Martin.Klajmon@vscht.cz>
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
21
|
SOFTWARE.
|