def validate_and_transform_options(series: MultiSeries, kwargs: Dict = {}) -> Options: """ This will check the keyword arguments passed to the `uniplot.plot` function, will transform them and will return them in form of an `Options` object. """ # Set bounds to show all points by default kwargs["x_min"] = kwargs.get("x_min") or series.x_min() kwargs["x_max"] = kwargs.get("x_max") or ( series.x_max() + 1e-4 * (series.x_max() - series.x_min())) if float(kwargs["x_min"]) == float(kwargs["x_max"]): kwargs["x_min"] = kwargs["x_min"] - 1 kwargs["x_max"] = kwargs["x_max"] + 1 kwargs["y_min"] = kwargs.get("y_min") or series.y_min() kwargs["y_max"] = kwargs.get("y_max") or ( series.y_max() + 1e-4 * (series.y_max() - series.y_min())) if float(kwargs["y_min"]) == float(kwargs["y_max"]): kwargs["y_min"] = kwargs["y_min"] - 1 kwargs["y_max"] = kwargs["y_max"] + 1 # Make sure the length of the labels is not exceeding the number of series if kwargs.get("legend_labels") is not None: kwargs["legend_labels"] = list(kwargs["legend_labels"])[0:len(series)] if "color" not in kwargs: kwargs["color"] = len(series) > 1 return Options(**kwargs)
def validate_and_transform_options(series: MultiSeries, kwargs: Dict = {}) -> Options: """ This will check the keyword arguments passed to the `uniplot.plot` function, will transform them and will return them in form of an `Options` object. The idea is to cast arguments into the right format to be used by the rest of the library, and to be as tolerant as possible for ease of use of the library. As a result the somewhat hacky code below should at least be confined to this function, and not spread throughout uniplot. """ # Set x bounds to show all points by default x_enlarge_delta = AUTO_WINDOW_ENLARGE_FACTOR * (series.x_max() - series.x_min()) kwargs["x_min"] = kwargs.get("x_min", series.x_min() - x_enlarge_delta) kwargs["x_max"] = kwargs.get("x_max", series.x_max() + x_enlarge_delta) # Fallback for only a single data point, or multiple with single x coordinate if float(kwargs["x_min"]) == float(kwargs["x_max"]): kwargs["x_min"] = kwargs["x_min"] - 1 kwargs["x_max"] = kwargs["x_max"] + 1 # Set y bounds to show all points by default y_enlarge_delta = AUTO_WINDOW_ENLARGE_FACTOR * (series.y_max() - series.y_min()) kwargs["y_min"] = kwargs.get("y_min", series.y_min() - y_enlarge_delta) kwargs["y_max"] = kwargs.get("y_max", series.y_max() + y_enlarge_delta) # Fallback for only a single data point, or multiple with single y coordinate if float(kwargs["y_min"]) == float(kwargs["y_max"]): kwargs["y_min"] = kwargs["y_min"] - 1 kwargs["y_max"] = kwargs["y_max"] + 1 # Make sure the length of the labels is not exceeding the number of series if kwargs.get("legend_labels") is not None: kwargs["legend_labels"] = list(kwargs["legend_labels"])[0:len(series)] # By default, enable color for multiple series, disable color for a single one kwargs["color"] = kwargs.get("color", len(series) > 1) # Set lines option for all series if not kwargs.get("lines"): # This will work for both unset lines option and `False` kwargs["lines"] = [False] * len(series) elif kwargs.get("lines") is True: # This is used to expand a single `True` kwargs["lines"] = [True] * len(series) elif len(kwargs.get("lines")) != len(series): # type: ignore raise ValueError("Invalid 'lines' option.") return Options(**kwargs)
def test_min_and_max(): ys = [[1, 222, 3, -3.14, 0], [1, 222, 3, -3.14, 0]] xs = [[1000, 222, 3, -314, 0], [0, 2222, 3, -3.14, 0]] series = MultiSeries(xs=xs, ys=ys) assert series.x_min() == -314 assert series.x_max() == 2222 assert series.y_min() == -3.14 assert series.y_max() == 222
def histogram( xs: Any, bins: int = 20, bins_min: Optional[float] = None, bins_max: Optional[float] = None, **kwargs, ) -> None: """ Plot a histogram to the terminal. Parameters: - `xs` are the values of the points to plot. This parameter is mandatory and can either be a list or a list of lists, or the equivalent NumPy array. - Any additional keyword arguments are passed to the `uniplot.options.Options` class. """ # HACK Use the `MultiSeries` constructor to cast values to uniform format multi_series = MultiSeries(ys=xs) # Histograms usually make sense only with lines kwargs["lines"] = kwargs.get("lines", True) bins_min = bins_min or multi_series.y_min() bins_max = bins_max or multi_series.y_max() range = bins_max - bins_min if range > 0: bins_min = bins_min - 0.1 * range bins_max = bins_max + 0.1 * range xs_histo_series = [] ys_histo_series = [] for s in multi_series.ys: hist, bin_edges = np.histogram(s, bins=bins, range=(bins_min, bins_max)) # Draw vertical and horizontal lines to connect points xs_here = np.zeros(1 + 2 * bins + 1) ys_here = np.zeros(1 + 2 * bins + 1) xs_here[0] = bin_edges[0] xs_here[1::2] = bin_edges xs_here[2::2] = bin_edges[1:] ys_here[1:-1:2] = hist ys_here[2:-1:2] = hist xs_histo_series.append(xs_here) ys_histo_series.append(ys_here) plot(xs=xs_histo_series, ys=ys_histo_series, **kwargs)