pyrbd 0.3.0__py3-none-any.whl → 0.3.2__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.
- pyrbd/block.py +98 -30
- pyrbd/diagram.py +3 -1
- pyrbd/py.typed +0 -0
- {pyrbd-0.3.0.dist-info → pyrbd-0.3.2.dist-info}/METADATA +3 -2
- pyrbd-0.3.2.dist-info/RECORD +8 -0
- pyrbd-0.3.0.dist-info/RECORD +0 -7
- {pyrbd-0.3.0.dist-info → pyrbd-0.3.2.dist-info}/WHEEL +0 -0
- {pyrbd-0.3.0.dist-info → pyrbd-0.3.2.dist-info}/licenses/LICENSE +0 -0
pyrbd/block.py
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
"""Module containing Block, Series and Group class definitions."""
|
2
2
|
|
3
|
-
from typing import Optional
|
4
|
-
from itertools import combinations
|
3
|
+
from typing import Optional, Generator
|
5
4
|
from copy import deepcopy
|
5
|
+
from collections import namedtuple
|
6
|
+
|
7
|
+
|
8
|
+
Padding = namedtuple("Padding", ["n", "e", "s", "w"])
|
6
9
|
|
7
10
|
|
8
11
|
class Block:
|
@@ -49,6 +52,7 @@ class Block:
|
|
49
52
|
)
|
50
53
|
|
51
54
|
arrow_options: str = "arrowcolor, thick"
|
55
|
+
arrow_length: float = 0.5
|
52
56
|
|
53
57
|
def __init__(
|
54
58
|
self,
|
@@ -70,7 +74,13 @@ class Block:
|
|
70
74
|
if self.parent is None:
|
71
75
|
return ""
|
72
76
|
|
73
|
-
return
|
77
|
+
return " ".join(
|
78
|
+
[
|
79
|
+
f"[right={self.arrow_length + self.shift[0]}cm",
|
80
|
+
f"of {self.parent.id},",
|
81
|
+
f"yshift={self.shift[1]}cm]",
|
82
|
+
]
|
83
|
+
)
|
74
84
|
|
75
85
|
def arrow(self, connector_position: float) -> str:
|
76
86
|
"""Get TikZ arrow string.
|
@@ -97,13 +107,13 @@ class Block:
|
|
97
107
|
]
|
98
108
|
)
|
99
109
|
|
100
|
-
def get_node(self, connector_position: float =
|
110
|
+
def get_node(self, connector_position: Optional[float] = None) -> str:
|
101
111
|
"""Get TikZ node string.
|
102
112
|
|
103
113
|
Parameters
|
104
114
|
----------
|
105
|
-
connector_position : float
|
106
|
-
distance in cm to right angle bend in connector
|
115
|
+
connector_position : Optional[float]
|
116
|
+
distance in cm to right angle bend in connector. Defaults to `0.5*arrow_length`.
|
107
117
|
|
108
118
|
Returns
|
109
119
|
-------
|
@@ -111,6 +121,9 @@ class Block:
|
|
111
121
|
TikZ string for rendering block
|
112
122
|
"""
|
113
123
|
|
124
|
+
if connector_position is None:
|
125
|
+
connector_position = self.arrow_length / 2
|
126
|
+
|
114
127
|
node = "".join(
|
115
128
|
[
|
116
129
|
"% Block\n",
|
@@ -123,6 +136,11 @@ class Block:
|
|
123
136
|
)
|
124
137
|
return node
|
125
138
|
|
139
|
+
def get_blocks(self) -> Generator["Block", None, None]:
|
140
|
+
"""Yield child `Block` istances."""
|
141
|
+
|
142
|
+
yield self
|
143
|
+
|
126
144
|
def __add__(self, block: "Block") -> "Series":
|
127
145
|
"""Add two `Block` instances to make a `Series` instance.
|
128
146
|
|
@@ -208,6 +226,10 @@ class Series(Block):
|
|
208
226
|
]
|
209
227
|
)
|
210
228
|
|
229
|
+
internal_arrow_length = 0.3
|
230
|
+
pad = Padding(1, 1, 1, 2.5)
|
231
|
+
label_height = 5
|
232
|
+
|
211
233
|
def __init__(
|
212
234
|
self,
|
213
235
|
blocks: list[Block],
|
@@ -219,11 +241,13 @@ class Series(Block):
|
|
219
241
|
|
220
242
|
self.blocks = blocks
|
221
243
|
self.blocks[0].id = f"{self.id}+0"
|
244
|
+
self.blocks[0].shift = (self.internal_arrow_length, 0)
|
222
245
|
for i, (block, new_parent) in enumerate(
|
223
246
|
zip(self.blocks[1::], self.blocks[0:-1]), start=1
|
224
247
|
):
|
225
248
|
block.parent = new_parent
|
226
249
|
block.id = f"{self.id}+{i}"
|
250
|
+
block.arrow_length = self.internal_arrow_length
|
227
251
|
|
228
252
|
@property
|
229
253
|
def background(self) -> str:
|
@@ -232,11 +256,13 @@ class Series(Block):
|
|
232
256
|
if self.color in ("white", ""):
|
233
257
|
return ""
|
234
258
|
|
259
|
+
pad = self.pad
|
260
|
+
|
235
261
|
return "".join(
|
236
262
|
[
|
237
263
|
"\\begin{pgfonlayer}{background}\n",
|
238
|
-
f"\\coordinate (sw) at ($({self.id}.south west)+(-
|
239
|
-
f"\\coordinate (ne) at ($({self.id}.north east)+(
|
264
|
+
f"\\coordinate (sw) at ($({self.id}.south west)+(-{pad.w}mm, -{pad.s}mm)$);\n",
|
265
|
+
f"\\coordinate (ne) at ($({self.id}.north east)+({pad.e}mm, {pad.n}mm)$);\n",
|
240
266
|
f"\\draw[{self.color}, thick] (sw) rectangle (ne);\n",
|
241
267
|
"\\end{pgfonlayer}\n",
|
242
268
|
]
|
@@ -249,24 +275,27 @@ class Series(Block):
|
|
249
275
|
if len(self.text) == 0:
|
250
276
|
return ""
|
251
277
|
|
278
|
+
pad = self.pad
|
279
|
+
|
252
280
|
return "".join(
|
253
281
|
[
|
254
|
-
f"\\coordinate (nw) at ($({self.id}.north west)+(-
|
255
|
-
f"\\coordinate (ne) at ($({self.id}.north east)+(
|
256
|
-
|
282
|
+
f"\\coordinate (nw) at ($({self.id}.north west)+(-{pad.w}mm, {pad.n}mm)$);\n",
|
283
|
+
f"\\coordinate (ne) at ($({self.id}.north east)+({pad.e}mm, {pad.n}mm)$);\n",
|
284
|
+
"\\coordinate (n) at "
|
285
|
+
f"($({self.id}.north)+(0mm, {self.label_height / 2 + pad.n}mm)$);\n",
|
257
286
|
f"\\draw[{self.color}, fill={self.color}!50, thick] (nw) ",
|
258
|
-
"rectangle ($(ne)+(0,
|
259
|
-
f"\\node[anchor=
|
287
|
+
f"rectangle ($(ne)+(0, {self.label_height}mm)$);\n",
|
288
|
+
f"\\node[anchor=center, inner sep=0pt, outer sep=0pt] at (n) {{{self.text}}};\n",
|
260
289
|
]
|
261
290
|
)
|
262
291
|
|
263
|
-
def get_node(self, connector_position: float =
|
292
|
+
def get_node(self, connector_position: Optional[float] = None) -> str:
|
264
293
|
"""Get TikZ node string.
|
265
294
|
|
266
295
|
Parameters
|
267
296
|
----------
|
268
|
-
connector_position : float
|
269
|
-
distance in cm to right angle bend in connector
|
297
|
+
connector_position : Optional[float]
|
298
|
+
distance in cm to right angle bend in connector. Defaults to `0.5 * arrow_length`
|
270
299
|
|
271
300
|
Returns
|
272
301
|
-------
|
@@ -275,12 +304,15 @@ class Series(Block):
|
|
275
304
|
|
276
305
|
"""
|
277
306
|
|
307
|
+
if connector_position is None:
|
308
|
+
connector_position = self.arrow_length / 2
|
309
|
+
|
278
310
|
block_nodes = "\n".join(
|
279
311
|
block.get_node(connector_position) for block in self.blocks
|
280
312
|
)
|
281
313
|
series_node = "".join(
|
282
314
|
[
|
283
|
-
f"\\node[{self.tikz_options}]",
|
315
|
+
f"%%% Series\n\\node[{self.tikz_options}]",
|
284
316
|
f"({self.id})",
|
285
317
|
self.position,
|
286
318
|
"{\\begin{tikzpicture}\n",
|
@@ -293,6 +325,11 @@ class Series(Block):
|
|
293
325
|
)
|
294
326
|
return series_node
|
295
327
|
|
328
|
+
def get_blocks(self) -> Generator[Block, None, None]:
|
329
|
+
yield from [
|
330
|
+
children for block in self.blocks for children in block.get_blocks()
|
331
|
+
]
|
332
|
+
|
296
333
|
|
297
334
|
class Group(Block):
|
298
335
|
"""Group of `Block` instances for vertical stacking.
|
@@ -322,6 +359,9 @@ class Group(Block):
|
|
322
359
|
"anchor=west",
|
323
360
|
]
|
324
361
|
)
|
362
|
+
internal_arrow_length = 0.3
|
363
|
+
pad = Padding(1, 1, 1, 1)
|
364
|
+
label_height = 5
|
325
365
|
|
326
366
|
def __init__(
|
327
367
|
self,
|
@@ -337,6 +377,7 @@ class Group(Block):
|
|
337
377
|
block.shift = (0, shift)
|
338
378
|
block.parent = self
|
339
379
|
block.id = f"{self.id}-{i}"
|
380
|
+
block.arrow_length = self.internal_arrow_length
|
340
381
|
|
341
382
|
@property
|
342
383
|
def shifts(self) -> list[float]:
|
@@ -359,11 +400,13 @@ class Group(Block):
|
|
359
400
|
if self.color in ("white", ""):
|
360
401
|
return ""
|
361
402
|
|
403
|
+
pad = self.pad
|
404
|
+
|
362
405
|
return "".join(
|
363
406
|
[
|
364
407
|
"\\begin{pgfonlayer}{background}\n",
|
365
|
-
f"\\coordinate (sw) at ($({self.id}.south west)+(-
|
366
|
-
f"\\coordinate (ne) at ($({self.id}.north east)+(
|
408
|
+
f"\\coordinate (sw) at ($({self.id}.south west)+(-{pad.w}mm, -{pad.s}mm)$);\n",
|
409
|
+
f"\\coordinate (ne) at ($({self.id}.north east)+({pad.e}mm, {pad.n}mm)$);\n",
|
367
410
|
f"\\draw[{self.color}, thick] (sw) rectangle (ne);\n",
|
368
411
|
"\\end{pgfonlayer}\n",
|
369
412
|
]
|
@@ -376,14 +419,17 @@ class Group(Block):
|
|
376
419
|
if len(self.text) == 0:
|
377
420
|
return ""
|
378
421
|
|
422
|
+
pad = self.pad
|
423
|
+
|
379
424
|
return "".join(
|
380
425
|
[
|
381
|
-
f"\\coordinate (nw) at ($({self.id}.north west)+(-
|
382
|
-
f"\\coordinate (ne) at ($({self.id}.north east)+(
|
383
|
-
|
426
|
+
f"\\coordinate (nw) at ($({self.id}.north west)+(-{pad.w}mm, {pad.n}mm)$);\n",
|
427
|
+
f"\\coordinate (ne) at ($({self.id}.north east)+({pad.e}mm, {pad.n}mm)$);\n",
|
428
|
+
"\\coordinate (n) at ",
|
429
|
+
f"($({self.id}.north)+(0mm, {self.label_height / 2 + pad.n}mm)$);\n",
|
384
430
|
f"\\draw[{self.color}, fill={self.color}!50, thick] (nw) ",
|
385
|
-
"rectangle ($(ne)+(0,
|
386
|
-
f"\\node[anchor=
|
431
|
+
f"rectangle ($(ne)+(0, {self.label_height}mm)$);\n",
|
432
|
+
f"\\node[anchor=center, inner sep=0pt, outer sep=0pt] at (n) {{{self.text}}};\n",
|
387
433
|
]
|
388
434
|
)
|
389
435
|
|
@@ -410,25 +456,41 @@ class Group(Block):
|
|
410
456
|
def arrows(self) -> str:
|
411
457
|
"""Get TikZ string for arrow connecting stacked blocks."""
|
412
458
|
|
459
|
+
scaling = 0.75
|
460
|
+
|
461
|
+
series_blocks = [block for block in self.blocks if isinstance(block, Series)]
|
462
|
+
series_blocks.sort(
|
463
|
+
key=lambda block: len(list(block.get_blocks())), reverse=True
|
464
|
+
)
|
465
|
+
|
466
|
+
if len(series_blocks) > 0:
|
467
|
+
longest_series_index = self.blocks.index(series_blocks[0])
|
468
|
+
else:
|
469
|
+
longest_series_index = 0
|
470
|
+
blocks = deepcopy(self.blocks)
|
471
|
+
longest_series = blocks.pop(longest_series_index)
|
472
|
+
|
413
473
|
return "\n".join(
|
414
474
|
[
|
415
475
|
" ".join(
|
416
476
|
[
|
417
|
-
f"\\draw[{self.arrow_options},
|
418
|
-
f"
|
477
|
+
f"\\draw[{self.arrow_options},",
|
478
|
+
f"rectangle line={scaling * self.internal_arrow_length}cm]",
|
479
|
+
f"({longest_series.id}.east) to ({block.id}.east);\n",
|
419
480
|
]
|
420
481
|
)
|
421
|
-
for
|
482
|
+
for block in blocks
|
422
483
|
]
|
423
484
|
)
|
424
485
|
|
425
|
-
def get_node(self, connector_position: float =
|
486
|
+
def get_node(self, connector_position: Optional[float] = None) -> str:
|
426
487
|
"""Get TikZ node string.
|
427
488
|
|
428
489
|
Parameters
|
429
490
|
----------
|
430
|
-
connector_position : float
|
431
|
-
distance in cm to right angle bend in connector
|
491
|
+
connector_position : Optional[float]
|
492
|
+
distance in cm to right angle bend in connector.
|
493
|
+
Locked to 0.0 for `Group` class
|
432
494
|
|
433
495
|
Returns
|
434
496
|
-------
|
@@ -436,12 +498,15 @@ class Group(Block):
|
|
436
498
|
TikZ string for rendering group
|
437
499
|
"""
|
438
500
|
|
501
|
+
connector_position = 0.0
|
502
|
+
|
439
503
|
block_nodes = "\n".join(
|
440
504
|
block.get_node(connector_position) for block in self.blocks
|
441
505
|
)
|
442
506
|
|
443
507
|
group_node = "".join(
|
444
508
|
[
|
509
|
+
"%%% Group\n"
|
445
510
|
f"\\node[anchor=west, outer sep=0pt, inner sep=0pt, align=center] ({self.id}) ",
|
446
511
|
self.position,
|
447
512
|
"{\\begin{tikzpicture}\n",
|
@@ -456,3 +521,6 @@ class Group(Block):
|
|
456
521
|
)
|
457
522
|
|
458
523
|
return group_node
|
524
|
+
|
525
|
+
def get_blocks(self) -> Generator[Block, None, None]:
|
526
|
+
yield from self.blocks
|
pyrbd/diagram.py
CHANGED
@@ -143,7 +143,9 @@ class Diagram:
|
|
143
143
|
"""
|
144
144
|
|
145
145
|
try:
|
146
|
-
subprocess.check_call(
|
146
|
+
subprocess.check_call(
|
147
|
+
["latexmk", "--lualatex", f"{self.filename}.tex", "--silent"]
|
148
|
+
)
|
147
149
|
subprocess.check_call(["latexmk", "-c", f"{self.filename}.tex"])
|
148
150
|
if clear_source:
|
149
151
|
subprocess.check_call(["rm", f"{self.filename}.tex"])
|
pyrbd/py.typed
ADDED
File without changes
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: pyrbd
|
3
|
-
Version: 0.3.
|
3
|
+
Version: 0.3.2
|
4
4
|
Summary: Package for creating simple reliability block diagrams (RBDs) using LaTeX and TikZ.
|
5
5
|
Project-URL: Repository, https://github.com/hghugdal/pyrbd
|
6
6
|
Project-URL: Issues, https://github.com/hghugdal/pyrbd/issues
|
@@ -11,6 +11,7 @@ License-File: LICENSE
|
|
11
11
|
Classifier: Development Status :: 4 - Beta
|
12
12
|
Classifier: Programming Language :: Python :: 3
|
13
13
|
Requires-Python: >=3.10
|
14
|
+
Requires-Dist: pre-commit>=4.3.0
|
14
15
|
Requires-Dist: pymupdf>=1.26.3
|
15
16
|
Description-Content-Type: text/markdown
|
16
17
|
|
@@ -46,6 +47,6 @@ diagram.compile()
|
|
46
47
|
```
|
47
48
|
|
48
49
|
producing the following diagram
|
49
|
-
<div><img src="https://raw.githubusercontent.com/hghugdal/pyrbd/
|
50
|
+
<div><img src="https://raw.githubusercontent.com/hghugdal/pyrbd/e11808e9a40c902f0e1c2c2b0b42ca0d90170cd1/docs/examples/simple_RBD.svg" width=500/></div>
|
50
51
|
|
51
52
|
For more examples, visit the [documentation](https://hghugdal.github.io/pyrbd/).
|
@@ -0,0 +1,8 @@
|
|
1
|
+
pyrbd/__init__.py,sha256=mpsb022BX9eDGSBhuYIr2gOr4sg_M9sYbPGHLPIdvl0,219
|
2
|
+
pyrbd/block.py,sha256=xRb4FnPTCA6CEAax2q3GRsngtzJvXlg9wCqr5q3nkEQ,14576
|
3
|
+
pyrbd/diagram.py,sha256=YiU2tslUh4HbtuVP2dXSsVQFKpOjLl_ArSYjCSiQoks,6806
|
4
|
+
pyrbd/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
|
+
pyrbd-0.3.2.dist-info/METADATA,sha256=3JIMvqVdxlQq-30y4omd_yipT8YfgxZOmZxq5SopBBU,2402
|
6
|
+
pyrbd-0.3.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
7
|
+
pyrbd-0.3.2.dist-info/licenses/LICENSE,sha256=mxXMgWpFgk71JpEEElFrb9FJxeoaDgvrU8gjUUU9LzA,1069
|
8
|
+
pyrbd-0.3.2.dist-info/RECORD,,
|
pyrbd-0.3.0.dist-info/RECORD
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
pyrbd/__init__.py,sha256=mpsb022BX9eDGSBhuYIr2gOr4sg_M9sYbPGHLPIdvl0,219
|
2
|
-
pyrbd/block.py,sha256=qQJx2Sn_SvAnm3Chz1f078nTzbS61LSFdxaEveu2RcY,12319
|
3
|
-
pyrbd/diagram.py,sha256=llZ0ncDmyJRg7zyQfTXAzbEM1W66wyHs9gfiovy-ujI,6762
|
4
|
-
pyrbd-0.3.0.dist-info/METADATA,sha256=KEMFXHPv7ykDCYbh2fOOjcKPyqhOchXl0Ck2pc3ODwQ,2369
|
5
|
-
pyrbd-0.3.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
6
|
-
pyrbd-0.3.0.dist-info/licenses/LICENSE,sha256=mxXMgWpFgk71JpEEElFrb9FJxeoaDgvrU8gjUUU9LzA,1069
|
7
|
-
pyrbd-0.3.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|