pyroll-core 3.0.0.post3__tar.gz → 3.0.1__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 (80) hide show
  1. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/PKG-INFO +7 -7
  2. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/hatch.toml +3 -3
  3. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyproject.toml +6 -4
  4. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/__init__.py +5 -3
  5. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/config.py +20 -17
  6. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/grooves/spline.py +33 -43
  7. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/repr.py +14 -7
  8. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/roll/hookimpls.py +15 -6
  9. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/roll_pass/__init__.py +0 -5
  10. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/roll_pass/hookimpls/profile.py +6 -1
  11. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/rotator/hookimpls.py +7 -0
  12. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/sequence/sequence.py +5 -5
  13. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/shapes.py +55 -12
  14. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/transport/hookimpls/transport.py +1 -1
  15. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/.gitignore +0 -0
  16. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/LICENSE +0 -0
  17. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/README.md +0 -0
  18. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/disk_elements/__init__.py +0 -0
  19. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/disk_elements/disk_element_unit.py +0 -0
  20. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/disk_elements/hookimpls.py +0 -0
  21. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/grooves/__init__.py +0 -0
  22. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/grooves/base.py +0 -0
  23. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/grooves/boxes/__init__.py +0 -0
  24. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/grooves/boxes/box.py +0 -0
  25. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/grooves/boxes/constricted_box.py +0 -0
  26. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/grooves/boxes/upset_box.py +0 -0
  27. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/grooves/diamonds/__init__.py +0 -0
  28. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/grooves/diamonds/diamond.py +0 -0
  29. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/grooves/diamonds/gothic.py +0 -0
  30. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/grooves/diamonds/square.py +0 -0
  31. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/grooves/equivalent_ripped_groove.py +0 -0
  32. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/grooves/flat.py +0 -0
  33. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/grooves/generic_elongation.py +0 -0
  34. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/grooves/generic_elongation_solvers.py +0 -0
  35. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/grooves/hexagonal.py +0 -0
  36. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/grooves/ovals/__init__.py +0 -0
  37. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/grooves/ovals/circular_oval.py +0 -0
  38. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/grooves/ovals/constricted_circular_oval.py +0 -0
  39. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/grooves/ovals/constricted_swedish_oval.py +0 -0
  40. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/grooves/ovals/flat_oval.py +0 -0
  41. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/grooves/ovals/oval_3radii.py +0 -0
  42. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/grooves/ovals/oval_3radii_flanked.py +0 -0
  43. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/grooves/ovals/swedish_oval.py +0 -0
  44. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/grooves/ovals/upset_oval.py +0 -0
  45. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/grooves/rounds/__init__.py +0 -0
  46. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/grooves/rounds/false_round.py +0 -0
  47. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/grooves/rounds/round.py +0 -0
  48. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/hooks.py +0 -0
  49. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/log.py +0 -0
  50. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/profile/__init__.py +0 -0
  51. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/profile/hookimpls.py +0 -0
  52. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/profile/profile.py +0 -0
  53. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/roll/__init__.py +0 -0
  54. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/roll/roll.py +0 -0
  55. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/roll_pass/base.py +0 -0
  56. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/roll_pass/deformation_unit.py +0 -0
  57. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/roll_pass/hookimpls/__init__.py +0 -0
  58. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/roll_pass/hookimpls/base_roll_pass.py +0 -0
  59. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/roll_pass/hookimpls/deformation_unit.py +0 -0
  60. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/roll_pass/hookimpls/disk_element.py +0 -0
  61. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/roll_pass/hookimpls/helpers.py +0 -0
  62. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/roll_pass/hookimpls/roll.py +0 -0
  63. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/roll_pass/hookimpls/symmetric_roll_pass.py +0 -0
  64. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/roll_pass/hookimpls/three_roll_pass.py +0 -0
  65. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/roll_pass/hookimpls/two_roll_pass.py +0 -0
  66. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/roll_pass/symmetric_roll_pass.py +0 -0
  67. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/roll_pass/three_roll_pass.py +0 -0
  68. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/roll_pass/two_roll_pass.py +0 -0
  69. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/rotator/__init__.py +0 -0
  70. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/rotator/rotator.py +0 -0
  71. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/sequence/__init__.py +0 -0
  72. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/sequence/hookimpls.py +0 -0
  73. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/transport/__init__.py +0 -0
  74. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/transport/cooling_pipe.py +0 -0
  75. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/transport/hookimpls/__init__.py +0 -0
  76. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/transport/hookimpls/cooling_pipe.py +0 -0
  77. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/transport/transport.py +0 -0
  78. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/unit/__init__.py +0 -0
  79. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/unit/hookimpls.py +0 -0
  80. {pyroll_core-3.0.0.post3 → pyroll_core-3.0.1}/pyroll/core/unit/unit.py +0 -0
@@ -1,13 +1,12 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pyroll-core
3
- Version: 3.0.0.post3
3
+ Version: 3.0.1
4
4
  Summary: PyRoll rolling simulation framework - core library.
5
5
  Project-URL: Homepage, https://pyroll-project.github.io
6
6
  Project-URL: Repository, https://github.com/pyroll-project/pyroll-core
7
7
  Project-URL: Documentation, https://pyroll.readthedocs.io/en/latest
8
8
  Author-email: Max Weiner <max.weiner@imf.tu-freiberg.de>, Christoph Renzing <christoph.renzing@imf.tu-freiberg.de>, Matthias Schmidtchen <matthias.schmidtchen@imf.tu-freiberg.de>, Max Stirl <max.stirl@imf.tu-freiberg.de>
9
- License-Expression: BSD-3-Clause
10
- License-File: LICENSE
9
+ License: BSD-3-Clause
11
10
  Classifier: Development Status :: 5 - Production/Stable
12
11
  Classifier: Framework :: Hatch
13
12
  Classifier: Framework :: IPython
@@ -25,10 +24,11 @@ Classifier: Programming Language :: Python :: 3.10
25
24
  Classifier: Programming Language :: Python :: 3.11
26
25
  Classifier: Topic :: Scientific/Engineering
27
26
  Requires-Python: >=3.9
28
- Requires-Dist: ezdxf
29
- Requires-Dist: numpy~=1.19
30
- Requires-Dist: scipy~=1.9
31
- Requires-Dist: shapely~=2.0
27
+ Requires-Dist: numpy~=2.0
28
+ Requires-Dist: scipy~=1.13
29
+ Requires-Dist: shapely<3.0,>=2.0.6
30
+ Provides-Extra: dxf
31
+ Requires-Dist: ezdxf-shapely~=1.0; extra == 'dxf'
32
32
  Provides-Extra: matplotlib
33
33
  Requires-Dist: matplotlib~=3.7; extra == 'matplotlib'
34
34
  Provides-Extra: plot
@@ -11,16 +11,16 @@ path = ".venv"
11
11
  dependencies = [
12
12
  "ipython ~= 8.0",
13
13
  "pytest ~= 7.0",
14
- "pyroll-report ~= 2.0",
14
+ "pyroll-report ~= 3.0",
15
15
  "jupyter",
16
16
  ]
17
- features = ["plotly", "matplotlib"]
17
+ features = ["plotly", "matplotlib", "dxf"]
18
18
 
19
19
  [envs.test]
20
20
  path = ""
21
21
  dependencies = [
22
22
  "pytest ~= 7.0",
23
- "pyroll-report ~= 2.0",
23
+ "pyroll-report ~= 3.0",
24
24
  ]
25
25
 
26
26
  [[envs.test.matrix]]
@@ -34,10 +34,9 @@ classifiers = [
34
34
  requires-python = ">=3.9"
35
35
 
36
36
  dependencies = [
37
- "numpy ~= 1.19",
38
- "scipy ~= 1.9",
39
- "shapely ~= 2.0",
40
- "ezdxf"
37
+ "numpy ~= 2.0",
38
+ "scipy ~= 1.13",
39
+ "shapely >= 2.0.6, <3.0",
41
40
  ]
42
41
 
43
42
  dynamic = ["version"]
@@ -53,6 +52,9 @@ plotly = [
53
52
  "plotly ~= 5.18",
54
53
  "pandas ~= 2.0",
55
54
  ]
55
+ dxf = [
56
+ "ezdxf-shapely ~= 1.0",
57
+ ]
56
58
 
57
59
  [project.urls]
58
60
  Homepage = "https://pyroll-project.github.io"
@@ -2,7 +2,8 @@ from . import shapes as _
2
2
 
3
3
  from .grooves import *
4
4
  from .transport import Transport, CoolingPipe
5
- from .roll_pass import BaseRollPass, RollPass, DeformationUnit, ThreeRollPass, SymmetricRollPass
5
+ from .roll_pass import BaseRollPass, DeformationUnit, ThreeRollPass, SymmetricRollPass, TwoRollPass
6
+ from .roll_pass import TwoRollPass as RollPass
6
7
  from .unit import Unit
7
8
  from .roll import Roll
8
9
  from .profile import *
@@ -10,9 +11,9 @@ from .rotator import Rotator
10
11
  from .sequence import PassSequence
11
12
  from .hooks import Hook, HookHost, HookFunction, root_hooks
12
13
  from .disk_elements import DiskElementUnit
13
- from .config import Config, config
14
+ from .config import Config, config, PlottingBackend
14
15
 
15
- VERSION = "3.0.0post3"
16
+ VERSION = "3.0.1"
16
17
 
17
18
  root_hooks.extend(
18
19
  [
@@ -31,6 +32,7 @@ root_hooks.extend(
31
32
  BaseRollPass.OutProfile.filling_error,
32
33
  BaseRollPass.OutProfile.cross_section_error,
33
34
  BaseRollPass.OutProfile.velocity,
35
+ BaseRollPass.InProfile.velocity,
34
36
  PassSequence.log_elongation,
35
37
  BaseRollPass.OutProfile.technologically_orientated_cross_section,
36
38
  BaseRollPass.technologically_orientated_contour_lines,
@@ -1,19 +1,20 @@
1
1
  import os
2
+ from enum import Enum
2
3
  from pathlib import Path
3
4
  from typing import Optional, Iterable, Mapping, Any, Callable
4
5
 
5
6
 
6
7
  class ConfigValue:
7
8
  """Helper descriptor for storing configuration values, able to determine the value from explictly set values,
8
- environment variables and default values."""
9
+ environment variables and default values."""
9
10
 
10
11
  def __init__(
11
- self,
12
- default,
13
- *,
14
- env_var: Optional[str] = None,
15
- env_var_prefix: Optional[str] = None,
16
- parser: Optional[Callable[[str], Any]] = None
12
+ self,
13
+ default,
14
+ *,
15
+ env_var: Optional[str] = None,
16
+ env_var_prefix: Optional[str] = None,
17
+ parser: Optional[Callable[[str], Any]] = None,
17
18
  ):
18
19
  self.default = default
19
20
  self.type = type(default)
@@ -26,7 +27,7 @@ class ConfigValue:
26
27
  self.owner = owner
27
28
  self.name = name
28
29
  if not self._env_var_prefix:
29
- self._env_var_prefix = self.owner.__module__.upper().replace('.', '_')
30
+ self._env_var_prefix = self.owner.__module__.upper().replace(".", "_")
30
31
 
31
32
  @property
32
33
  def env_var(self):
@@ -83,11 +84,7 @@ class ConfigValue:
83
84
  class ConfigMeta(type):
84
85
  def to_dict(cls):
85
86
  """Return the config values of this class as dict."""
86
- return {
87
- n: v
88
- for n, v in type(cls).__dict__.items()
89
- if isinstance(v, ConfigValue)
90
- }
87
+ return {n: v for n, v in type(cls).__dict__.items() if isinstance(v, ConfigValue)}
91
88
 
92
89
  def update(cls, d: dict[str, Any]):
93
90
  """
@@ -138,10 +135,7 @@ def config(env_var_prefix):
138
135
  else:
139
136
  # noinspection PyProtectedMember
140
137
  meta_dict[n] = ConfigValue(
141
- default=v.default,
142
- env_var_prefix=env_var_prefix,
143
- env_var=v._env_var,
144
- parser=v.parser
138
+ default=v.default, env_var_prefix=env_var_prefix, env_var=v._env_var, parser=v.parser
145
139
  )
146
140
 
147
141
  meta = type(cls.__name__ + "Meta", (ConfigMeta,), meta_dict)
@@ -151,9 +145,15 @@ def config(env_var_prefix):
151
145
  return dec
152
146
 
153
147
 
148
+ class PlottingBackend(Enum):
149
+ PLOTLY = 1
150
+ MATPLOTLIB = 2
151
+
152
+
154
153
  @config("PYROLL_CORE")
155
154
  class Config:
156
155
  """Configuration class for ``pyroll.core``."""
156
+
157
157
  ROLL_PASS_AUTO_ROTATION = True
158
158
  """Whether to enable automatic rotation of incoming profiles in roll passes by default."""
159
159
 
@@ -199,3 +199,6 @@ class Config:
199
199
 
200
200
  PLOT_RESOLUTION = 100
201
201
  """Resolution of plots in dots per inches (dpi)."""
202
+
203
+ PREFERRED_PLOTTING_BACKEND = PlottingBackend.PLOTLY
204
+ """Sets the preferred plotting backend to use when both matplotlib and plotly are installed."""
@@ -1,7 +1,6 @@
1
1
  import numpy as np
2
2
  import scipy.interpolate
3
3
  from pathlib import Path
4
- from ezdxf import readfile
5
4
  from shapely.geometry import Polygon, LineString
6
5
  from typing import Union, Tuple, Iterable, Optional
7
6
 
@@ -12,10 +11,10 @@ class SplineGroove(GrooveBase):
12
11
  """Represents a groove defined by a linear spline contour."""
13
12
 
14
13
  def __init__(
15
- self,
16
- contour_points: Union[Iterable[Tuple[float, float]], np.ndarray],
17
- classifiers: Iterable[str],
18
- usable_width: Optional[float] = None,
14
+ self,
15
+ contour_points: Union[Iterable[Tuple[float, float]], np.ndarray],
16
+ classifiers: Iterable[str],
17
+ usable_width: Optional[float] = None,
19
18
  ):
20
19
  """
21
20
  :param contour_points: an iterable of contour points to be used for the spline
@@ -34,9 +33,11 @@ class SplineGroove(GrooveBase):
34
33
  raise ValueError("first and last element of contour_points should have y coordinate equal to 0")
35
34
 
36
35
  # strip boundary
37
- contour_points = contour_points[np.logical_not(
38
- (np.isclose(np.roll(contour_points[:, 1], 1), 0)) & (np.isclose(np.roll(contour_points[:, 1], -1), 0))
39
- )]
36
+ contour_points = contour_points[
37
+ np.logical_not(
38
+ (np.isclose(np.roll(contour_points[:, 1], 1), 0)) & (np.isclose(np.roll(contour_points[:, 1], -1), 0))
39
+ )
40
+ ]
40
41
 
41
42
  # shift center to 0,0
42
43
  contour_points[:, 0] -= np.mean(contour_points[:, 0])
@@ -56,8 +57,7 @@ class SplineGroove(GrooveBase):
56
57
  self._depth = np.max(contour_points[:, 1])
57
58
 
58
59
  self._local_depth = scipy.interpolate.interp1d(
59
- contour_points[:, 0], contour_points[:, 1],
60
- fill_value="extrapolate"
60
+ contour_points[:, 0], contour_points[:, 1], fill_value="extrapolate"
61
61
  )
62
62
  self._classifiers = tuple(classifiers)
63
63
 
@@ -93,46 +93,36 @@ class SplineGroove(GrooveBase):
93
93
  return self._local_depth(z)
94
94
 
95
95
  @classmethod
96
- def from_dxf_drawing(cls, filepath: Path, classifiers: Iterable[str], usable_width: Optional[float] = None,
97
- arc_discretization: int = 1000) -> 'SplineGroove':
96
+ def from_dxf_drawing(
97
+ cls,
98
+ filepath: Path,
99
+ classifiers: Iterable[str],
100
+ usable_width: Optional[float] = None,
101
+ arc_degrees_per_segment: float = 0.5,
102
+ spline_delta: float = 0.1,
103
+ dxf_query: str = '* [layer=="0"]',
104
+ ) -> "SplineGroove":
98
105
  """
99
106
  Creates a spline groove with a given contour line as defined inside the .dxf drawing.
100
107
 
101
108
  :param filepath: the filepath to the drawing
102
109
  :param classifiers: an iterable of string keys used as type classifiers
103
110
  :param usable_width: the usable width to assume for this instance, if None, the maximum width will be used
104
- :param arc_discretization: discretization of arcs of the dxf drawing, default is 1000.
111
+ :param arc_degrees_per_segment: discretization width in degrees for arcs and circles
112
+ :param dxf_query: query to filter the wanted geometries out of the dxf, see the ezdxf docs for details
105
113
  """
106
114
 
107
- doc = readfile(filepath)
108
- msp = doc.modelspace()
115
+ try:
116
+ from ezdxf import readfile
117
+ from ezdxf_shapely import convert_all, line_merge
118
+ except ImportError as e:
119
+ raise RuntimeError("ezdxf-shapely is required for DXF import, you may install it with the dxf extra") from e
120
+ from shapely.affinity import translate
109
121
 
110
- points = []
111
- for entity in msp:
112
- if entity.dxftype() == 'LINE':
113
- points.append((entity.dxf.start[0], entity.dxf.start[1]))
114
- points.append((entity.dxf.end[0], entity.dxf.end[1]))
122
+ dxf_doc = readfile(filepath)
123
+ msp = dxf_doc.modelspace().query(dxf_query)
124
+ geoms = convert_all(msp, spline_delta=spline_delta, degrees_per_segment=arc_degrees_per_segment)
125
+ geom = line_merge(geoms)
126
+ geom = translate(geom, -geom.centroid.x, -geom.bounds[1])
115
127
 
116
- elif entity.dxftype() == 'ARC':
117
- center = (entity.dxf.center[0], entity.dxf.center[1])
118
- radius = entity.dxf.radius
119
- start_angle = np.radians(entity.dxf.start_angle)
120
- end_angle = np.radians(entity.dxf.end_angle)
121
-
122
- arc_points = [
123
- (
124
- center[0] + radius * np.cos(start_angle + (end_angle - start_angle) * i / arc_discretization),
125
- center[1] + radius * np.sin(start_angle + (end_angle - start_angle) * i / arc_discretization),
126
- )
127
- for i in range(arc_discretization + 1)
128
- ]
129
- points.extend(arc_points)
130
-
131
- points.sort(key=lambda p: p[0])
132
-
133
- distance_to_y_0 = -points[0][1]
134
-
135
- shifted_points = [(x, y + distance_to_y_0) for x, y in points]
136
- shifted_points.sort(key=lambda p: p[0])
137
-
138
- return SplineGroove(contour_points=shifted_points, classifiers=classifiers, usable_width=usable_width)
128
+ return SplineGroove(contour_points=geom.coords, classifiers=classifiers, usable_width=usable_width)
@@ -1,8 +1,8 @@
1
1
  import html
2
2
  from abc import ABC, abstractmethod
3
3
  from io import StringIO
4
- from .config import Config
5
- from .log import global_logger
4
+
5
+ from .config import Config, PlottingBackend
6
6
 
7
7
 
8
8
  class ReprMixin(ABC):
@@ -49,11 +49,18 @@ class ReprMixin(ABC):
49
49
 
50
50
  :returns: either a plotly or matplotlib figure object
51
51
  """
52
-
53
- try:
54
- return self.plot_plotly()
55
- except (NotImplementedError, ImportError):
56
- return self.plot_matplotlib()
52
+ if Config.PREFERRED_PLOTTING_BACKEND == PlottingBackend.PLOTLY:
53
+ try:
54
+ return self.plot_plotly()
55
+ except (NotImplementedError, ImportError):
56
+ return self.plot_matplotlib()
57
+ elif Config.PREFERRED_PLOTTING_BACKEND == PlottingBackend.MATPLOTLIB:
58
+ try:
59
+ return self.plot_matplotlib()
60
+ except (NotImplementedError, ImportError):
61
+ return self.plot_plotly()
62
+
63
+ raise ValueError("Invalid value given for 'Config.PREFERRED_PLOTTING_BACKEND'. Value must be a member of the pyroll.core.PlottingBackend enumeration.")
57
64
 
58
65
  def __str__(self):
59
66
  return type(self).__qualname__
@@ -25,18 +25,27 @@ def roll_power(self: Roll):
25
25
 
26
26
 
27
27
  @Roll.working_velocity
28
- def working_velocity(self: Roll):
29
- return self.rotational_frequency * self.working_radius * 2 * np.pi
28
+ def working_velocity(self: Roll, cycle):
29
+ if not cycle:
30
+ return self.rotational_frequency * self.working_radius * 2 * np.pi
30
31
 
31
32
 
32
33
  @Roll.surface_velocity
33
- def surface_velocity(self: Roll):
34
- return self.rotational_frequency * self.nominal_radius * 2 * np.pi
34
+ def surface_velocity(self: Roll, cycle):
35
+ if not cycle:
36
+ return self.rotational_frequency * self.nominal_radius * 2 * np.pi
35
37
 
36
38
 
37
39
  @Roll.rotational_frequency
38
- def rotational_frequency(self: Roll):
39
- return self.surface_velocity / (2 * np.pi * self.nominal_radius)
40
+ def rotational_frequency(self: Roll, cycle):
41
+ if not cycle:
42
+ return self.surface_velocity / (2 * np.pi * self.nominal_radius)
43
+
44
+
45
+ @Roll.rotational_frequency
46
+ def rotational_frequency(self: Roll, cycle):
47
+ if not cycle:
48
+ return self.working_velocity / (2 * np.pi * self.working_radius)
40
49
 
41
50
 
42
51
  @Roll.width
@@ -5,8 +5,3 @@ from .deformation_unit import DeformationUnit
5
5
  from .symmetric_roll_pass import SymmetricRollPass
6
6
 
7
7
  from . import hookimpls
8
-
9
- RollPass = TwoRollPass
10
-
11
-
12
-
@@ -88,6 +88,11 @@ def classifiers(self: BaseRollPass.OutProfile):
88
88
  return set(self.roll_pass.classifiers)
89
89
 
90
90
 
91
+ @BaseRollPass.InProfile.velocity
92
+ def in_velocity(self: BaseRollPass.InProfile):
93
+ return self.roll_pass.out_profile.velocity * self.unit.out_profile.cross_section.area / self.cross_section.area
94
+
95
+
91
96
  @BaseRollPass.OutProfile.velocity
92
- def velocity(self: BaseRollPass.OutProfile):
97
+ def out_velocity(self: BaseRollPass.OutProfile):
93
98
  return self.roll_pass.velocity
@@ -52,6 +52,13 @@ def box_diamond_45(self: Rotator):
52
52
  return 45
53
53
 
54
54
 
55
+ @Rotator.rotation
56
+ def flat_flat_0(self: Rotator):
57
+ if "3fold" not in self.next_roll_pass.classifiers:
58
+ if "flat" in self.in_profile.classifiers and "flat" in self.next_roll_pass.classifiers:
59
+ return 0
60
+
61
+
55
62
  @Rotator.rotation
56
63
  def box_flat_0(self: Rotator):
57
64
  if "box" in self.in_profile.classifiers and "flat" in self.next_roll_pass.classifiers:
@@ -4,7 +4,7 @@ from collections.abc import Sequence
4
4
  from typing import overload, List, cast
5
5
 
6
6
  from ..unit import Unit
7
- from ..roll_pass import RollPass
7
+ from ..roll_pass import BaseRollPass
8
8
  from ..transport import Transport
9
9
  from ..hooks import Hook
10
10
 
@@ -104,9 +104,9 @@ class PassSequence(Unit, Sequence[Unit]):
104
104
  return list(self._subunits)
105
105
 
106
106
  @property
107
- def roll_passes(self) -> List[RollPass]:
107
+ def roll_passes(self) -> List[BaseRollPass]:
108
108
  """Returns a list of all roll passes in this sequence."""
109
- return list(u for u in self._subunits if isinstance(u, RollPass))
109
+ return list(u for u in self._subunits if isinstance(u, BaseRollPass))
110
110
 
111
111
  @property
112
112
  def transports(self) -> List[Transport]:
@@ -135,7 +135,7 @@ class PassSequence(Unit, Sequence[Unit]):
135
135
  for i in range(len(cross_sections_areas) - 2, -1, -1):
136
136
  velocities[i] = velocities[i + 1] * cross_sections_areas[i + 1] / cross_sections_areas[i]
137
137
 
138
- def set_velocities_to_roll_passes(roll_passes: List[RollPass], velocities: np.ndarray[float]):
138
+ def set_velocities_to_roll_passes(roll_passes: List[BaseRollPass], velocities: np.ndarray[float]):
139
139
  for roll_pass, velocity in zip(roll_passes, velocities):
140
140
  roll_pass.velocity = velocity
141
141
 
@@ -179,7 +179,7 @@ class PassSequence(Unit, Sequence[Unit]):
179
179
  for i in range(1, len(usable_cross_section_areas)):
180
180
  velocities[i] = velocities[i - 1] * cross_sections_areas[i - 1] / cross_sections_areas[i]
181
181
 
182
- def set_velocities_to_roll_passes(roll_passes: List[RollPass], velocities: np.ndarray[float]):
182
+ def set_velocities_to_roll_passes(roll_passes: List[BaseRollPass], velocities: np.ndarray[float]):
183
183
  for roll_pass, velocity in zip(roll_passes, velocities):
184
184
  roll_pass.velocity = velocity
185
185
 
@@ -91,23 +91,21 @@ def multi_polygon_plot_matplotlib(self: MultiPolygon):
91
91
  ax.set_aspect("equal", "datalim")
92
92
  ax.grid(lw=0.5)
93
93
 
94
- for g, c in zip(self.geoms, plt.color_sequences["default"]):
95
- ax.plot(*g.boundary.xy, color=c)
96
- ax.fill(*g.boundary.xy, alpha=0.5, color=c)
94
+ for g in self.geoms:
95
+ l = ax.plot(*g.boundary.xy)
96
+ ax.fill(*g.boundary.xy, alpha=0.5, color=l[0].get_color())
97
97
  return fig
98
98
 
99
99
 
100
100
  def multi_polygon_plot_plotly(self: MultiPolygon):
101
101
  import plotly.graph_objects as pgo
102
- from pandas import DataFrame
103
102
 
104
103
  fig = pgo.Figure()
105
104
 
106
105
  for g in self.geoms:
107
- fig.add_trace(pgo.line(
108
- x=[g.boundary.xy[0] for g in self.geoms],
109
- y=[g.boundary.xy[1] for g in self.geoms],
110
- labels={"y": "y", "x": "z"},
106
+ fig.add_trace(pgo.Line(
107
+ x=np.array(g.boundary.xy[0]),
108
+ y=np.array(g.boundary.xy[1]),
111
109
  ))
112
110
 
113
111
  fig.update_traces(
@@ -116,9 +114,12 @@ def multi_polygon_plot_plotly(self: MultiPolygon):
116
114
 
117
115
  fig.update_yaxes(
118
116
  scaleanchor="x",
119
- scaleratio=1
117
+ scaleratio=1,
118
+ title="y"
120
119
  )
121
120
 
121
+ fig.update_xaxes(title="z")
122
+
122
123
  return fig
123
124
 
124
125
 
@@ -134,7 +135,7 @@ def line_string_plot_matplotlib(self: LineString):
134
135
  ax.set_aspect("equal", "datalim")
135
136
  ax.grid(lw=0.5)
136
137
 
137
- ax.plot(*self.xy, color="k")
138
+ ax.plot(*self.xy)
138
139
  return fig
139
140
 
140
141
 
@@ -147,8 +148,6 @@ def line_string_plot_plotly(self: LineString):
147
148
  labels={"y": "y", "x": "z"},
148
149
  )
149
150
 
150
- fig.update_traces(line_color="black")
151
-
152
151
  fig.update_yaxes(
153
152
  scaleanchor="x",
154
153
  scaleratio=1
@@ -157,6 +156,45 @@ def line_string_plot_plotly(self: LineString):
157
156
  return fig
158
157
 
159
158
 
159
+ def multi_line_string_plot_matplotlib(self: MultiLineString):
160
+ import matplotlib.pyplot as plt
161
+
162
+ fig: plt.Figure = plt.figure()
163
+ ax: plt.Axes = fig.subplots()
164
+
165
+ ax.set_ylabel("y")
166
+ ax.set_xlabel("z")
167
+
168
+ ax.set_aspect("equal", "datalim")
169
+ ax.grid(lw=0.5)
170
+
171
+ for g in self.geoms:
172
+ ax.plot(*g.xy)
173
+ return fig
174
+
175
+
176
+ def multi_line_string_plot_plotly(self: MultiLineString):
177
+ import plotly.graph_objects as pgo
178
+
179
+ fig = pgo.Figure()
180
+
181
+ for g in self.geoms:
182
+ fig.add_trace(pgo.Line(
183
+ x=np.array(g.xy[0]),
184
+ y=np.array(g.xy[1]),
185
+ ))
186
+
187
+ fig.update_yaxes(
188
+ scaleanchor="x",
189
+ scaleratio=1,
190
+ title="y"
191
+ )
192
+
193
+ fig.update_xaxes(title="z")
194
+
195
+ return fig
196
+
197
+
160
198
  for cls in [
161
199
  LineString,
162
200
  MultiLineString,
@@ -203,6 +241,11 @@ LineString._plot_matplotlib_ = line_string_plot_matplotlib
203
241
  # noinspection PyProtectedMember
204
242
  LineString._plot_plotly_ = line_string_plot_plotly
205
243
 
244
+ # noinspection PyProtectedMember
245
+ MultiLineString._plot_matplotlib_ = multi_line_string_plot_matplotlib
246
+ # noinspection PyProtectedMember
247
+ MultiLineString._plot_plotly_ = multi_line_string_plot_plotly
248
+
206
249
  _RECTANGLE_CORNERS = np.asarray(
207
250
  [
208
251
  (-0.5, -0.5),
@@ -31,7 +31,7 @@ def length_from_roll_pass_positions(self: Transport, cycle):
31
31
  if cycle:
32
32
  return None
33
33
 
34
- from ...roll_pass import RollPass
34
+ from pyroll.core import RollPass
35
35
  next_pass = self.next_of(RollPass)
36
36
  prev_pass = self.prev_of(RollPass)
37
37
 
File without changes
File without changes