gsplot 0.0.1__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.
gsplot/path/path.py ADDED
@@ -0,0 +1,227 @@
1
+ import os
2
+ import sys
3
+
4
+ __all__: list[str] = ["home", "pwd", "pwd_move", "pwd_main"]
5
+
6
+
7
+ class Path:
8
+ """
9
+ A utility class for handling common file system operations.
10
+
11
+ This class provides methods for retrieving the home directory, current working
12
+ directory, and moving to the current working directory.
13
+
14
+ Methods
15
+ --------------------
16
+ get_home()
17
+ Returns the path to the user's home directory.
18
+ get_pwd()
19
+ Returns the current working directory.
20
+ move_to_pwd()
21
+ Changes the current working directory to the current value of `get_pwd()`.
22
+
23
+ Examples
24
+ --------------------
25
+ >>> path_util = Path()
26
+ >>> home_dir = path_util.get_home()
27
+ >>> print(home_dir)
28
+ "/home/user" # Example output
29
+
30
+ >>> pwd = path_util.get_pwd()
31
+ >>> print(pwd)
32
+ "/home/user/project" # Example output
33
+
34
+ >>> path_util.move_to_pwd() # Moves to the current working directory
35
+ """
36
+
37
+ def get_home(self) -> str:
38
+ """
39
+ Returns the path to the user's home directory.
40
+
41
+ Returns
42
+ --------------------
43
+ str
44
+ The absolute path to the home directory.
45
+
46
+ Examples
47
+ --------------------
48
+ >>> path_util = Path()
49
+ >>> home_dir = path_util.get_home()
50
+ >>> print(home_dir)
51
+ "/home/user" # Example output
52
+ """
53
+ return os.path.expanduser("~")
54
+
55
+ def get_pwd(self) -> str:
56
+ """
57
+ Returns the current working directory.
58
+
59
+ Returns
60
+ --------------------
61
+ str
62
+ The absolute path of the current working directory.
63
+
64
+ Examples
65
+ --------------------
66
+ >>> path_util = Path()
67
+ >>> pwd = path_util.get_pwd()
68
+ >>> print(pwd)
69
+ "/home/user/project" # Example output
70
+ """
71
+ return os.getcwd()
72
+
73
+ def move_to_pwd(self) -> None:
74
+ """
75
+ Changes the current working directory to the current value of `get_pwd()`.
76
+
77
+ This is typically redundant, as the current working directory is already the result of `get_pwd()`.
78
+
79
+ Examples
80
+ --------------------
81
+ >>> path_util = Path()
82
+ >>> path_util.move_to_pwd() # Changes directory to the current working directory
83
+ """
84
+ os.chdir(self.get_pwd())
85
+
86
+
87
+ def home() -> str:
88
+ """
89
+ Returns the path to the user's home directory.
90
+
91
+ This is a convenience function wrapping `Path.get_home`.
92
+
93
+ Returns
94
+ --------------------
95
+ str
96
+ The absolute path to the home directory.
97
+
98
+ Examples
99
+ --------------------
100
+ >>> import gsplot as gs
101
+ >>> home_dir = gs.home()
102
+ >>> print(home_dir)
103
+ "/home/user" # Example output
104
+ """
105
+ return Path().get_home()
106
+
107
+
108
+ def pwd() -> str:
109
+ """
110
+ Returns the current working directory.
111
+
112
+ This is a convenience function wrapping `Path.get_pwd`.
113
+
114
+ Returns
115
+ --------------------
116
+ str
117
+ The absolute path of the current working directory.
118
+
119
+ Examples
120
+ --------------------
121
+ >>> import gsplot as gs
122
+ >>> current_dir = gs.pwd()
123
+ >>> print(current_dir)
124
+ "/home/user/project" # Example output
125
+ """
126
+ return Path().get_pwd()
127
+
128
+
129
+ def pwd_move() -> None:
130
+ """
131
+ Changes the current working directory to the value of `pwd()`.
132
+
133
+ This is a convenience function wrapping `Path.move_to_pwd`.
134
+
135
+ Examples
136
+ --------------------
137
+ >>> import gsplot as gs
138
+ >>> gs.pwd_move() # Changes directory to the current working directory
139
+ """
140
+ Path().move_to_pwd()
141
+
142
+
143
+ class PathToMain:
144
+ """
145
+ A utility class to retrieve the directory of the executed main file.
146
+
147
+ This class determines the directory of the script or module being executed as the main
148
+ program. If executed in an environment where `__file__` is not available (e.g., REPL or
149
+ interactive environments), it falls back to the current working directory.
150
+
151
+ Attributes
152
+ --------------------
153
+ EXECUTED_FILE_DIR : str or None
154
+ The directory of the executed main file. Initialized as `None`.
155
+
156
+ Methods
157
+ --------------------
158
+ get_executed_file_dir()
159
+ Retrieves the directory of the executed main file or the current working directory.
160
+
161
+ Examples
162
+ --------------------
163
+ >>> path_util = PathToMain()
164
+ >>> executed_dir = path_util.get_executed_file_dir()
165
+ >>> print(executed_dir)
166
+ "/home/user/project" # Example output for an executed script
167
+ """
168
+
169
+ EXECUTED_FILE_DIR: str | None = None
170
+
171
+ def get_executed_file_dir(self) -> str:
172
+ """
173
+ Retrieves the directory of the executed main file or the current working directory.
174
+
175
+ This method checks the `__file__` attribute of the `__main__` module to determine
176
+ the directory of the executed script. If unavailable (e.g., in REPL), it defaults to
177
+ the current working directory.
178
+
179
+ Returns
180
+ --------------------
181
+ str
182
+ The directory of the executed main file or the current working directory.
183
+
184
+ Raises
185
+ --------------------
186
+ ValueError
187
+ If the executed file directory cannot be determined.
188
+
189
+ Examples
190
+ --------------------
191
+ >>> path_util = PathToMain()
192
+ >>> executed_dir = path_util.get_executed_file_dir()
193
+ >>> print(executed_dir)
194
+ "/home/user/project" # Example output for an executed script
195
+ """
196
+ if hasattr(sys.modules["__main__"], "__file__"):
197
+ file_path = sys.modules["__main__"].__file__
198
+ if file_path:
199
+ self.EXECUTED_FILE_DIR = os.path.dirname(os.path.abspath(file_path))
200
+ else:
201
+ # case when __file__ does not exist in REPL or environment
202
+ self.EXECUTED_FILE_DIR = os.getcwd() # current working directory
203
+
204
+ if self.EXECUTED_FILE_DIR is None:
205
+ raise ValueError("Cannot find the executed file directory.")
206
+ return self.EXECUTED_FILE_DIR
207
+
208
+
209
+ def pwd_main() -> str:
210
+ """
211
+ Retrieves the directory of the executed main file or the current working directory.
212
+
213
+ This function is a convenience wrapper around `PathToMain.get_executed_file_dir`.
214
+
215
+ Returns
216
+ --------------------
217
+ str
218
+ The directory of the executed main file or the current working directory.
219
+
220
+ Examples
221
+ --------------------
222
+ >>> import gsplot as gs
223
+ >>> executed_dir = gs.pwd_main()
224
+ >>> print(executed_dir)
225
+ "/home/user/project" # Example output for an executed script
226
+ """
227
+ return PathToMain().get_executed_file_dir()
gsplot/plot/line.py ADDED
@@ -0,0 +1,328 @@
1
+ import numbers
2
+ from typing import Any
3
+
4
+ import matplotlib.pyplot as plt
5
+ import numpy as np
6
+ from matplotlib import colors
7
+ from matplotlib.axes import Axes
8
+ from matplotlib.lines import Line2D
9
+ from matplotlib.typing import ColorType, LineStyleType, MarkerType
10
+ from numpy.typing import ArrayLike, NDArray
11
+
12
+ from ..base.base import CreateClassParams, ParamsGetter, bind_passed_params
13
+ from ..base.base_alias_validator import AliasValidator
14
+ from ..figure.axes_base import AxesRangeSingleton, AxesResolver
15
+ from .line_base import AutoColor, NumLines
16
+
17
+ __all__: list[str] = ["line"]
18
+
19
+
20
+ class Line:
21
+ """
22
+ A utility class for creating and plotting a line on a specified axis.
23
+
24
+ This class manages line properties such as color, markers, and styles, and provides a method to plot the line on a specified Matplotlib axis.
25
+
26
+ Parameters
27
+ --------------------
28
+ axis_target : int or matplotlib.axes.Axes
29
+ The target axis, specified either as an index or an `Axes` object.
30
+ x : ArrayLike
31
+ The x-coordinates of the data points.
32
+ y : ArrayLike
33
+ The y-coordinates of the data points.
34
+ color : ColorType, optional
35
+ The color of the line (default is None, which uses the auto color).
36
+ marker : MarkerType, optional
37
+ The marker style (default is "o").
38
+ markersize : int or float, optional
39
+ The size of the marker (default is 7.0).
40
+ markeredgewidth : int or float, optional
41
+ The width of the marker edge (default is 1.5).
42
+ markeredgecolor : ColorType, optional
43
+ The color of the marker edge (default is None, which uses the line color).
44
+ markerfacecolor : ColorType, optional
45
+ The color of the marker face (default is None, which uses the line color with modified alpha).
46
+ linestyle : LineStyleType, optional
47
+ The line style (default is "--").
48
+ linewidth : int or float, optional
49
+ The width of the line (default is 1.0).
50
+ alpha : int or float, optional
51
+ The opacity of the line (default is 1.0).
52
+ alpha_mfc : int or float, optional
53
+ The opacity of the marker face color (default is 0.2).
54
+ label : str, optional
55
+ The label for the line (default is None).
56
+ *args : Any
57
+ Additional positional arguments passed to `Axes.plot`.
58
+ **kwargs : Any
59
+ Additional keyword arguments passed to `Axes.plot`.
60
+
61
+ Methods
62
+ --------------------
63
+ plot()
64
+ Plots the line on the specified axis.
65
+
66
+ Examples
67
+ --------------------
68
+ >>> line = Line(axis_target=0, x=[0, 1, 2], y=[2, 4, 6], color="red", linestyle="-")
69
+ >>> line.plot()
70
+ """
71
+
72
+ def __init__(
73
+ self,
74
+ axis_target: int | Axes,
75
+ x: ArrayLike,
76
+ y: ArrayLike,
77
+ color: ColorType | None = None,
78
+ marker: MarkerType = "o",
79
+ markersize: int | float = 7.0,
80
+ markeredgewidth: int | float = 1.5,
81
+ markeredgecolor: ColorType | None = None,
82
+ markerfacecolor: ColorType | None = None,
83
+ linestyle: LineStyleType = "--",
84
+ linewidth: int | float = 1.0,
85
+ alpha: int | float = 1.0,
86
+ alpha_mfc: int | float = 0.2,
87
+ label: str | None = None,
88
+ *args: Any,
89
+ **kwargs: Any,
90
+ ) -> None:
91
+
92
+ self.axis_target: int | Axes = axis_target
93
+
94
+ self._x: ArrayLike = x
95
+ self._y: ArrayLike = y
96
+
97
+ self.color: ColorType | None = color
98
+ self.marker: MarkerType = marker
99
+ self.markersize: int | float = markersize
100
+ self.markeredgewidth: int | float = markeredgewidth
101
+ self.markeredgecolor: ColorType | None = markeredgecolor
102
+ self.markerfacecolor: ColorType | None = markerfacecolor
103
+ self.linestyle: LineStyleType = linestyle
104
+ self.linewidth: int | float = linewidth
105
+ self.alpha: int | float = alpha
106
+ self.alpha_mfc: int | float = alpha_mfc
107
+ self.label: str | None = label
108
+ self.args: Any = args
109
+ self.kwargs: Any = kwargs
110
+
111
+ # Ensure x and y data are NumPy arrays
112
+ self.x: NDArray[Any] = np.array(self._x)
113
+ self.y: NDArray[Any] = np.array(self._y)
114
+
115
+ self.axis_index: int = AxesResolver(axis_target).axis_index
116
+ self.axis: Axes = AxesResolver(axis_target).axis
117
+
118
+ self._set_colors()
119
+
120
+ def _set_colors(self) -> None:
121
+ """
122
+ Sets the colors for the line, marker edge, and marker face.
123
+ """
124
+ cycle_color: NDArray[Any] | str = AutoColor(self.axis_index).get_color()
125
+ if isinstance(cycle_color, np.ndarray):
126
+ cycle_color = colors.to_hex(
127
+ tuple(cycle_color)
128
+ ) # convert numpy array to tuple
129
+
130
+ default_color: ColorType = cycle_color if self.color is None else self.color
131
+
132
+ self._color = self._modify_color_alpha(default_color, self.alpha)
133
+ self._color_mec = self._modify_color_alpha(
134
+ self.markeredgecolor if self.markeredgecolor is not None else default_color,
135
+ self.alpha,
136
+ )
137
+ self._color_mfc = self._modify_color_alpha(
138
+ self.markerfacecolor if self.markerfacecolor is not None else default_color,
139
+ self.alpha_mfc * self.alpha,
140
+ )
141
+
142
+ def _modify_color_alpha(self, color: ColorType, alpha: float | int | None) -> tuple:
143
+ """
144
+ Modifies the alpha value of the given color.
145
+
146
+ Parameters
147
+ --------------------
148
+ color : ColorType
149
+ The base color.
150
+ alpha : float or int or None
151
+ The alpha value to apply.
152
+
153
+ Returns
154
+ --------------------
155
+ tuple
156
+ The RGBA color with the modified alpha value.
157
+
158
+ Raises
159
+ --------------------
160
+ ValueError
161
+ If `color` or `alpha` is None, or if `alpha` is not a float.
162
+ """
163
+ if color is None or alpha is None:
164
+ raise ValueError("Both color and alpha must be provided")
165
+
166
+ if not isinstance(alpha, numbers.Real):
167
+ raise ValueError("Alpha must be a float")
168
+
169
+ rgb = list(colors.to_rgba(color))
170
+ rgb[3] = float(alpha)
171
+ return tuple(rgb)
172
+
173
+ @NumLines.count
174
+ @AxesRangeSingleton.update
175
+ def plot(self) -> list[Line2D]:
176
+ """
177
+ Plots the line on the specified axis.
178
+
179
+ Returns
180
+ --------------------
181
+ list of matplotlib.lines.Line2D
182
+ The list of Line2D objects representing the plotted line.
183
+
184
+ Examples
185
+ --------------------
186
+ >>> line = Line(axis_target=0, x=[0, 1, 2], y=[2, 4, 6], color="blue")
187
+ >>> line.plot()
188
+ """
189
+ _plot = self.axis.plot(
190
+ self.x,
191
+ self.y,
192
+ color=self._color,
193
+ marker=self.marker,
194
+ markersize=self.markersize,
195
+ markeredgewidth=self.markeredgewidth,
196
+ linestyle=self.linestyle,
197
+ linewidth=self.linewidth,
198
+ markeredgecolor=self._color_mec,
199
+ markerfacecolor=self._color_mfc,
200
+ label=self.label,
201
+ *self.args,
202
+ **self.kwargs,
203
+ )
204
+ return _plot
205
+
206
+
207
+ @bind_passed_params()
208
+ def line(
209
+ axis_target: int | Axes,
210
+ x: ArrayLike,
211
+ y: ArrayLike,
212
+ color: ColorType | None = None,
213
+ marker: MarkerType = "o",
214
+ markersize: int | float = 7.0,
215
+ markeredgewidth: int | float = 1.5,
216
+ markeredgecolor: ColorType | None = None,
217
+ markerfacecolor: ColorType | None = None,
218
+ linestyle: LineStyleType = "--",
219
+ linewidth: int | float = 1.0,
220
+ alpha: int | float = 1,
221
+ alpha_mfc: int | float = 0.2,
222
+ label: str | None = None,
223
+ *args: Any,
224
+ **kwargs: Any,
225
+ ) -> list[Line2D]:
226
+ """
227
+ A convenience function to plot a line with extensive customization on a Matplotlib axis.
228
+
229
+ This function wraps the `Line` class for easier usage and provides support for aliasing
230
+ common parameters. It handles axis resolution, automatic color cycling, and parameter validation.
231
+
232
+ Parameters
233
+ --------------------
234
+ axis_target : int or matplotlib.axes.Axes
235
+ The target axis where the line should be plotted. Can be an axis index or an `Axes` object.
236
+ x : ArrayLike
237
+ The x-coordinates of the line data.
238
+ y : ArrayLike
239
+ The y-coordinates of the line data.
240
+ color : ColorType or None, optional
241
+ The color of the line (default is `None`, using auto color cycling).
242
+ marker : MarkerType, optional
243
+ The marker style for the data points (default is "o").
244
+ markersize : int or float, optional
245
+ The size of the markers (default is 7.0).
246
+ markeredgewidth : int or float, optional
247
+ The width of the marker edges (default is 1.5).
248
+ markeredgecolor : ColorType or None, optional
249
+ The edge color of the markers (default is `None`).
250
+ markerfacecolor : ColorType or None, optional
251
+ The face color of the markers (default is `None`).
252
+ linestyle : LineStyleType, optional
253
+ The style of the line (default is "--").
254
+ linewidth : int or float, optional
255
+ The width of the line (default is 1.0).
256
+ alpha : int or float, optional
257
+ The transparency level of the line (default is 1).
258
+ alpha_mfc : int or float, optional
259
+ The transparency level of the marker face color (default is 0.2).
260
+ label : str or None, optional
261
+ The label for the line, used in legends (default is `None`).
262
+ *args : Any
263
+ Additional positional arguments passed to `matplotlib.axes.Axes.plot`.
264
+ **kwargs : Any
265
+ Additional keyword arguments passed to `matplotlib.axes.Axes.plot`.
266
+
267
+ Notes
268
+ --------------------
269
+ - This function utilizes the `ParamsGetter` to retrieve bound parameters and the `CreateClassParams` class to handle the merging of default, configuration, and passed parameters.
270
+ - Alias validation is performed using the `AliasValidator` class.
271
+
272
+ - 'ms' (markersize)
273
+ - 'mew' (markeredgewidth)
274
+ - 'ls' (linestyle)
275
+ - 'lw' (linewidth)
276
+ - 'c' (color)
277
+ - 'mec' (markeredgecolor)
278
+ - 'mfc' (markerfacecolor).
279
+
280
+ Returns
281
+ --------------------
282
+ list of matplotlib.lines.Line2D
283
+ The list of Line2D objects representing the plotted line.
284
+
285
+ Examples
286
+ --------------------
287
+ >>> import gsplot as gs
288
+ >>> x = [0, 1, 2, 3]
289
+ >>> y = [1, 2, 3, 4]
290
+ >>> line_plot = gs.line(0, x, y, color="blue", linestyle="-")
291
+ >>> print(line_plot)
292
+ [<matplotlib.lines.Line2D object at 0x...>]
293
+ """
294
+
295
+ alias_map = {
296
+ "ms": "markersize",
297
+ "mew": "markeredgewidth",
298
+ "ls": "linestyle",
299
+ "lw": "linewidth",
300
+ "c": "color",
301
+ "mec": "markeredgecolor",
302
+ "mfc": "markerfacecolor",
303
+ }
304
+
305
+ passed_params: dict[str, Any] = ParamsGetter("passed_params").get_bound_params()
306
+ AliasValidator(alias_map, passed_params).validate()
307
+ class_params: dict[str, Any] = CreateClassParams(passed_params).get_class_params()
308
+
309
+ _line = Line(
310
+ class_params["axis_target"],
311
+ class_params["x"],
312
+ class_params["y"],
313
+ class_params["color"],
314
+ class_params["marker"],
315
+ class_params["markersize"],
316
+ class_params["markeredgewidth"],
317
+ class_params["markeredgecolor"],
318
+ class_params["markerfacecolor"],
319
+ class_params["linestyle"],
320
+ class_params["linewidth"],
321
+ class_params["alpha"],
322
+ class_params["alpha_mfc"],
323
+ class_params["label"],
324
+ *class_params["args"],
325
+ **class_params["kwargs"],
326
+ )
327
+
328
+ return _line.plot()