iam-git / WellMet (public) (License: MIT) (since 2021-08-31) (hash sha1)
WellMet is pure Python framework for spatial structural reliability analysis. Or, more specifically, for "failure probability estimation and detection of failure surfaces by adaptive sequential decomposition of the design domain".
List of commits:
Subject Hash Author Date (UTC)
mplot: include Axes3d patch 8f5dc7f04b6c804b5ec169ec7b744a8618b3bb69 I am 2021-09-10 11:05:20
rework mplot module considerably 5343602c63032f6f7fd06701b0883eaabb4fc6c1 I am 2021-09-09 13:24:45
convex_hull: reduce max R to that not overflows everything everytime 2108df698e4d45bfae9d9882d4b4cc62340b03cc Aleksei Gerasimov 2021-07-21 13:56:41
sball: make Sball a little bit more scipy.stats-compatible 9414aceedf826e7fc6e35c722b2eecee81dead1e Aleksei Gerasimov 2021-07-21 13:40:28
convex_hull: fire() function has been reworked. shot() function is introduced 4e6b7546f163a9a32fdb4bf5790f416300b2c1ec Aleksei Gerasimov 2021-07-21 13:11:52
ghull: 1DS integration scheme has been implemented. convex_hull has been divided into convex_hull itself and separated ghull module. 29b21b4fc1396384bf8c9bb21b91f82005850574 Aleksei Gerasimov 2021-07-20 13:26:47
IS_stat: add 1D IS-like helpful sampling function 58416707171522e8129333e8bd93f512c7578879 Aleksei Gerasimov 2021-07-20 11:06:27
convex_hull: orth estimation is ready. Uses QR decomposition. 75f20d8771021b037c360df9c7207b8f46f65d91 Aleksei Gerasimov 2021-07-20 08:25:20
convex_hull: 2FORM za mně je Ready. Orth potřebuje Gram-Schmidtovou ortogonalizaci. Oboje jsou otestovany ve 2D. There is some weirdness with candidates inherited from WIP recent commit. It need to be fixed. ffae78d5a15884476760b8ab759963d7ef8ff5fc Aleksei Gerasimov 2021-07-19 14:48:34
convex_hull: 2FORM estimation WIP a0f04ef282d6dacbda52c9734f36f9e7ec9b46da I am 2021-07-19 06:14:54
convex_hull.fire: use sf instead of cdf function to fix precision issue in distant areas. e3b9f036f9d50994357e32827586fb98d85d43a7 I am 2021-07-15 09:13:58
qt_plot: add matplotlib menu 73835a59908b82f08d618a06c4c05a96703715b1 I am 2021-07-14 17:01:54
mart: add candidates plot functions 56b3f5320e83071886c0d8f65a3d9df7c5a231a8 I am 2021-07-13 10:55:13
dicebox.Goal.assess_candidates: put back dd attribute 5da7c67800b8cd6eb3f221273a8270393a571e2b I am 2021-07-12 08:47:00
sball: fix Radial pdf 830fbf3119e2e54e42ea48640dfe553ffa2b3c1f I am 2021-07-08 19:50:42
spring: try to fix infinite loop 0e9a6161996c1b078698b1631d10f1a171332818 I am 2021-07-08 17:54:04
dicebox.Goal: add q_psee potential 4c151252460f6e96f7c1ac5662f81474eae305a0 I am 2021-07-08 00:34:27
dicebox.Goal: Goal is back after the breakage! 19c3c63001ebc19ed5e17892e4b11edb4dbfe828 I am 2021-07-06 16:14:14
IS_stat.PushAndPull: small variance fix, spíše formální 7b5b87655b6978828ed06ba3743ada46a2bfde6b I am 2021-07-06 04:31:43
qt_plot.Ghull: update Ghull related code. A lot of fixes. Вроде фурычит. 29cd8fce14cecc872e1be856d73d9669a6395b08 I am 2021-07-05 18:47:53
Commit 8f5dc7f04b6c804b5ec169ec7b744a8618b3bb69 - mplot: include Axes3d patch
Author: I am
Author date (UTC): 2021-09-10 11:05
Committer name: I am
Committer date (UTC): 2021-09-10 11:05
Parent(s): 5343602c63032f6f7fd06701b0883eaabb4fc6c1
Signer:
Signing key:
Signing status: N
Tree: e202aaa8b6ac445118fec1523f34aada909d573c
File Lines added Lines deleted
mplot/_axes3d.py 274 0
mplot/_axis3d_margins_patch.py 21 0
mplot/misc.py 3 94
File mplot/_axes3d.py added (mode: 100644) (index 0000000..1d61f6f)
1 #!/usr/bin/env python
2 # coding: utf-8
3
4
5 # Monkey patch module
6 # Removes side panes on Axes3D plot
7 # Just import it to make MPL unpredictable
8
9 import numpy as np
10 from matplotlib import artist
11 from mpl_toolkits.mplot3d.axis3d import Axis
12 from mpl_toolkits.mplot3d.axis3d import art3d, proj3d, move_from_center, tick_update_position
13
14 from mpl_toolkits.mplot3d.axes3d import Axes3D
15 from matplotlib.axes import Axes
16
17
18 @artist.allow_rasterization
19 def draw(self, renderer):
20 self.label._transform = self.axes.transData
21 renderer.open_group('axis3d', gid=self.get_gid())
22
23 ticks = self._update_ticks()
24
25 info = self._axinfo
26 index = info['i']
27
28 mins, maxs, centers, deltas, tc, highs = self._get_coord_info(renderer)
29
30 # Determine grid lines
31 minmax = np.where(highs, maxs, mins)
32 maxmin = np.where(highs, mins, maxs)
33
34 # Draw main axis line
35 juggled = info['juggled']
36 edgep1 = minmax.copy()
37 edgep1[juggled[0]] = maxmin[juggled[0]]
38
39 edgep2 = edgep1.copy()
40 edgep2[juggled[1]] = maxmin[juggled[1]]
41 pep = np.asarray(
42 proj3d.proj_trans_points([edgep1, edgep2], renderer.M))
43 centpt = proj3d.proj_transform(*centers, renderer.M)
44 self.line.set_data(pep[0], pep[1])
45 self.line.draw(renderer)
46
47 # Grid points where the planes meet
48 xyz0 = np.tile(minmax, (len(ticks), 1))
49 xyz0[:, index] = [tick.get_loc() for tick in ticks]
50
51 # Draw labels
52 # The transAxes transform is used because the Text object
53 # rotates the text relative to the display coordinate system.
54 # Therefore, if we want the labels to remain parallel to the
55 # axis regardless of the aspect ratio, we need to convert the
56 # edge points of the plane to display coordinates and calculate
57 # an angle from that.
58 # TODO: Maybe Text objects should handle this themselves?
59 dx, dy = (self.axes.transAxes.transform([pep[0:2, 1]]) -
60 self.axes.transAxes.transform([pep[0:2, 0]]))[0]
61
62 lxyz = 0.5 * (edgep1 + edgep2)
63
64 # A rough estimate; points are ambiguous since 3D plots rotate
65 ax_scale = self.axes.bbox.size / self.figure.bbox.size
66 ax_inches = np.multiply(ax_scale, self.figure.get_size_inches())
67 ax_points_estimate = sum(72. * ax_inches)
68 deltas_per_point = 48 / ax_points_estimate
69 default_offset = 21.
70 labeldeltas = (
71 (self.labelpad + default_offset) * deltas_per_point * deltas)
72 axmask = [True, True, True]
73 axmask[index] = False
74 lxyz = move_from_center(lxyz, centers, labeldeltas, axmask)
75 tlx, tly, tlz = proj3d.proj_transform(*lxyz, renderer.M)
76 self.label.set_position((tlx, tly))
77 if self.get_rotate_label(self.label.get_text()):
78 angle = art3d._norm_text_angle(np.rad2deg(np.arctan2(dy, dx)))
79 self.label.set_rotation(angle)
80 self.label.set_va(info['label']['va'])
81 self.label.set_ha(info['label']['ha'])
82 self.label.draw(renderer)
83
84 # Draw Offset text
85
86 # Which of the two edge points do we want to
87 # use for locating the offset text?
88 if juggled[2] == 2:
89 outeredgep = edgep1
90 outerindex = 0
91 else:
92 outeredgep = edgep2
93 outerindex = 1
94
95 pos = move_from_center(outeredgep, centers, labeldeltas, axmask)
96 olx, oly, olz = proj3d.proj_transform(*pos, renderer.M)
97 self.offsetText.set_text(self.major.formatter.get_offset())
98 self.offsetText.set_position((olx, oly))
99 angle = art3d._norm_text_angle(np.rad2deg(np.arctan2(dy, dx)))
100 self.offsetText.set_rotation(angle)
101 # Must set rotation mode to "anchor" so that
102 # the alignment point is used as the "fulcrum" for rotation.
103 self.offsetText.set_rotation_mode('anchor')
104
105 #----------------------------------------------------------------------
106 # Note: the following statement for determining the proper alignment of
107 # the offset text. This was determined entirely by trial-and-error
108 # and should not be in any way considered as "the way". There are
109 # still some edge cases where alignment is not quite right, but this
110 # seems to be more of a geometry issue (in other words, I might be
111 # using the wrong reference points).
112 #
113 # (TT, FF, TF, FT) are the shorthand for the tuple of
114 # (centpt[info['tickdir']] <= pep[info['tickdir'], outerindex],
115 # centpt[index] <= pep[index, outerindex])
116 #
117 # Three-letters (e.g., TFT, FTT) are short-hand for the array of bools
118 # from the variable 'highs'.
119 # ---------------------------------------------------------------------
120 if centpt[info['tickdir']] > pep[info['tickdir'], outerindex]:
121 # if FT and if highs has an even number of Trues
122 if (centpt[index] <= pep[index, outerindex]
123 and np.count_nonzero(highs) % 2 == 0):
124 # Usually, this means align right, except for the FTT case,
125 # in which offset for axis 1 and 2 are aligned left.
126 if highs.tolist() == [False, True, True] and index in (1, 2):
127 align = 'left'
128 else:
129 align = 'right'
130 else:
131 # The FF case
132 align = 'left'
133 else:
134 # if TF and if highs has an even number of Trues
135 if (centpt[index] > pep[index, outerindex]
136 and np.count_nonzero(highs) % 2 == 0):
137 # Usually mean align left, except if it is axis 2
138 if index == 2:
139 align = 'right'
140 else:
141 align = 'left'
142 else:
143 # The TT case
144 align = 'right'
145
146 self.offsetText.set_va('center')
147 self.offsetText.set_ha(align)
148 self.offsetText.draw(renderer)
149
150 if self.axes._draw_grid and len(ticks):
151 # Grid lines go from the end of one plane through the plane
152 # intersection (at xyz0) to the end of the other plane. The first
153 # point (0) differs along dimension index-2 and the last (2) along
154 # dimension index-1.
155 lines = np.stack([xyz0, xyz0, xyz0], axis=1)
156
157 lines[:, 0, index - 2] = maxmin[index - 2]
158 lines[:, 2, index - 1] = maxmin[index - 1]
159
160 lines[:, :, 2] = np.min(lines[:, :, 2])
161 #print("lajny:", lines[:, :, 2])
162 self.gridlines.set_segments(lines)
163 self.gridlines.set_color(info['grid']['color'])
164 self.gridlines.set_linewidth(info['grid']['linewidth'])
165 self.gridlines.set_linestyle(info['grid']['linestyle'])
166 self.gridlines.draw(renderer, project=True)
167
168 # Draw ticks
169 tickdir = info['tickdir']
170 tickdelta = deltas[tickdir]
171 if highs[tickdir]:
172 ticksign = 1
173 else:
174 ticksign = -1
175
176 for tick in ticks:
177 # Get tick line positions
178 pos = edgep1.copy()
179 pos[index] = tick.get_loc()
180 pos[tickdir] = (
181 edgep1[tickdir]
182 + info['tick']['outward_factor'] * ticksign * tickdelta)
183 x1, y1, z1 = proj3d.proj_transform(*pos, renderer.M)
184 pos[tickdir] = (
185 edgep1[tickdir]
186 - info['tick']['inward_factor'] * ticksign * tickdelta)
187 x2, y2, z2 = proj3d.proj_transform(*pos, renderer.M)
188
189 # Get position of label
190 default_offset = 8. # A rough estimate
191 labeldeltas = (
192 (tick.get_pad() + default_offset) * deltas_per_point * deltas)
193
194 axmask = [True, True, True]
195 axmask[index] = False
196 pos[tickdir] = edgep1[tickdir]
197 pos = move_from_center(pos, centers, labeldeltas, axmask)
198 lx, ly, lz = proj3d.proj_transform(*pos, renderer.M)
199
200 tick_update_position(tick, (x1, x2), (y1, y2), (lx, ly))
201 tick.tick1line.set_linewidth(
202 info['tick']['linewidth'][tick._major])
203 tick.draw(renderer)
204
205 renderer.close_group('axis3d')
206 self.stale = False
207
208 Axis.draw = draw
209
210
211
212 @artist.allow_rasterization
213 def draw(self, renderer):
214 # draw the background patch
215 self.patch.draw(renderer)
216 self._frameon = False
217
218 # first, set the aspect
219 # this is duplicated from `axes._base._AxesBase.draw`
220 # but must be called before any of the artist are drawn as
221 # it adjusts the view limits and the size of the bounding box
222 # of the axes
223 locator = self.get_axes_locator()
224 if locator:
225 pos = locator(self, renderer)
226 self.apply_aspect(pos)
227 else:
228 self.apply_aspect()
229
230 # add the projection matrix to the renderer
231 self.M = self.get_proj()
232 renderer.M = self.M
233 renderer.vvec = self.vvec
234 renderer.eye = self.eye
235 renderer.get_axis_position = self.get_axis_position
236
237 # Calculate projection of collections and patches and zorder them.
238 # Make sure they are drawn above the grids.
239 zorder_offset = max(axis.get_zorder()
240 for axis in self._get_axis_list()) + 1
241 for i, col in enumerate(
242 sorted(self.collections,
243 key=lambda col: col.do_3d_projection(renderer),
244 reverse=True)):
245 col.zorder = zorder_offset + i
246 for i, patch in enumerate(
247 sorted(self.patches,
248 key=lambda patch: patch.do_3d_projection(renderer),
249 reverse=True)):
250 patch.zorder = zorder_offset + i
251
252 if self._axis3don:
253 # Draw panes first
254 #print(self._get_axis_list())
255 axis_list = self._get_axis_list()
256 #axis_list[0].draw_pane(renderer)
257 #axis_list[1].draw_pane(renderer)
258 #for axis in self._get_axis_list():
259 # axis.draw_pane(renderer)
260
261 # Then axes
262 #print(self._get_axis_list())
263 #for axis in self._get_axis_list():
264 # axis.draw(renderer)
265 axis_list[0].draw(renderer)
266 axis_list[1].draw(renderer)
267
268
269 # Then rest
270 Axes.draw(self, renderer)
271
272 Axes3D.draw = draw
273
274
File mplot/_axis3d_margins_patch.py added (mode: 100644) (index 0000000..2931745)
1 #!/usr/bin/env python
2 # coding: utf-8
3
4 # Monkey patch module
5 # Just import it to make MPL unpredictable
6
7 # taken from StackOverflow
8 # https://stackoverflow.com/questions/16488182/removing-axes-margins-in-3d-plot
9 # © HYRY, 2013
10 # license: CC BY-SA 3.0
11 ###patch start###
12 from mpl_toolkits.mplot3d.axis3d import Axis
13 if not hasattr(Axis, "_get_coord_info_old"):
14 def _get_coord_info_new(self, renderer):
15 mins, maxs, centers, deltas, tc, highs = self._get_coord_info_old(renderer)
16 mins += deltas / 4
17 maxs -= deltas / 4
18 return mins, maxs, centers, deltas, tc, highs
19 Axis._get_coord_info_old = Axis._get_coord_info
20 Axis._get_coord_info = _get_coord_info_new
21 ###patch end###
File mplot/misc.py changed (mode: 100644) (index fcf7b7e..647e2cb)
5 5 # nazvy proměnných jsou v angličtině # nazvy proměnných jsou v angličtině
6 6 # Ale komenty teda ne) # Ale komenty teda ne)
7 7
8 __all__ = ['grid3d_patch']
8 9
9 import matplotlib as mpl
10 def grid3d_patch(*args, **kwargs):
11 from . import _axis3d_margins_patch, _axes3d
10 12
11
12
13 __all__ = ['font']
14
15 def font(*args, **kwargs):
16 mpl.rcParams['font.size'] = 22
17
18
19 def show2D(sample_box, space='R', drawing=None):
20 fig = plt.figure()
21 ax = fig.add_subplot(111)
22 ax.space = space
23 ax.sample_box = sample_box
24
25 if drawing is None:
26 maxes.base_drawing(ax)
27 else:
28 getattr(maxes, drawing)(ax)
29 # specially for qt_plot. It already runs event loop
30 return fig.show()
31
32
33
34 def subplot3D(sample_box, ax3d, space='R'):
35 Fails = getattr(sample_box.failure_samples, space)
36 Succeses = getattr(sample_box.success_samples, space)
37 xyz = [0,1,2]
38 ax3d.scatter(Fails[:,xyz[0]], Fails[:,xyz[1]], Fails[:,xyz[2]], c='r', marker='.')
39 ax3d.scatter(Succeses[:,xyz[0]], Succeses[:,xyz[1]], Succeses[:,xyz[2]], c='g', marker='.')
40
41 ax3d.set_xlabel('X')
42 ax3d.set_ylabel('Y')
43 ax3d.set_zlabel('Z')
44
45
46
47 def plot3D(sample_box, space='R', filename='', format='pdf'):
48 if not filename:
49 filename = 'store/%s_%s_%s_plot3D'%(sample_box.gm_signature, space, sample_box.nsim)
50 fig = plt.figure()
51 ax3d = fig.add_subplot(111, projection='3d')
52 subplot3D(sample_box, ax3d, space)
53
54 try: # jen pro formu zkusíme, vždyť musí funkce formálně něco dělat, žejo?
55 fig.savefig(filename + "." + format)#, dpi=300)
56 except:
57 pass # nic se neděje
58
59 # vracím plt místo figury, protože nechcem sa trapiť ivent lupem
60 # return plt insted of just fig to bypass event loop issues
61 return plt.show()
62
63
64
65 # nikdo mi neuvěří, že by tohle postačílo a nebylo by nutné tohlensto furt úpravovat
66 def plot2D(sample_box, space='R', candidates=False, filename=None, format='pdf'):
67 if filename is None:
68 try:
69 filename = sample_box.filename
70 except:
71 filename = 'store/%s_%s_%s_plot2D'%(sample_box.gm_signature, space, sample_box.nsim)
72
73 fig = plt.figure()
74 ax = fig.add_subplot(111)
75 ax.space = space
76 ax.sample_box = sample_box
77
78 mart.setup(ax)
79 mart.curly(ax)
80 mart.plot_boundaries(ax, linewidth=0.7)
81 mart.scatter_points(ax)
82 try:
83 mart.triplot(ax, color="grey", linewidth=0.4)
84 except:
85 pass
86
87 if candidates:
88 #č ax.scatter posílá parameter cmap Collections třídě.
89 #č Třída mimo jiného dědí cm.ScalarMappable,
90 #č která inicializaci deleguje funkci cm.get_cmap() ve (svém) modulu cm.
91 # cmap='viridis_r' #cmap='plasma',
92 mart.scatter_candidates(ax, s=5, marker='.', cmap='plasma_r',\
93 alpha=None, linewidths=None, edgecolors=None, plotnonfinite=False)
94 mart.plot_the_best_candidate(ax, "^", color='#3D0D5B')
95
96 try: # jen pro formu zkusíme, vždyť musí funkce formálně něco dělat, žejo?
97 fig.savefig(filename + "." + format, dpi=300)
98 except:
99 pass # nic se neděje
100
101 # vracím plt místo figury, protože nechcem sa trapiť ivent lupem
102 # return plt insted of just fig to bypass event loop issues
103 return plt.show()
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/iam-git/WellMet

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/iam-git/WellMet

Clone this repository using git:
git clone git://git.rocketgit.com/user/iam-git/WellMet

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main