From ee04517e297060d4c16c50889de4ee950c7ea9ce Mon Sep 17 00:00:00 2001
From: dm1sh <me@dmitriy.icu>
Date: Mon, 30 Oct 2023 16:46:25 +0300
Subject: [PATCH] Moved PyQt-Plotter-Dialog to separate repository:
 https://git.dm1sh.ru/ADV/PyQt-Plotter-Dialog

---
 PyQt-Plotter-Dialog/README.md                 |  71 -----
 PyQt-Plotter-Dialog/graph_widget/__init__.py  |   3 -
 PyQt-Plotter-Dialog/graph_widget/graph.py     |  67 -----
 .../graph_widget/graph_widget.py              |  24 --
 PyQt-Plotter-Dialog/parser/README.md          |  81 ------
 PyQt-Plotter-Dialog/parser/__init__.py        |  21 --
 PyQt-Plotter-Dialog/parser/__main__.py        |  16 --
 PyQt-Plotter-Dialog/parser/constants.py       |   6 -
 PyQt-Plotter-Dialog/parser/expression.py      |  81 ------
 PyQt-Plotter-Dialog/parser/operation.py       | 113 --------
 PyQt-Plotter-Dialog/parser/parser.py          | 104 --------
 PyQt-Plotter-Dialog/parser/tokenizer.py       | 114 --------
 PyQt-Plotter-Dialog/parser/types.py           |  23 --
 .../plotter_dialog/__init__.py                |   3 -
 .../plotter_dialog/__main__.py                |  23 --
 .../plotter_dialog/button_group.py            |  44 ----
 .../plotter_dialog/constants.py               |  27 --
 PyQt-Plotter-Dialog/plotter_dialog/dialog.py  | 247 ------------------
 .../plotter_dialog/flow_layout.py             | 147 -----------
 .../plotter_dialog/graph_requester.py         |  56 ----
 PyQt-Plotter-Dialog/plotter_dialog/utils.py   |  10 -
 PyQt-Plotter-Dialog/requirements.dev.txt      |   6 -
 PyQt-Plotter-Dialog/requirements.txt          |   4 -
 PyQt-Plotter-Dialog/tests/__init__.py         |   0
 PyQt-Plotter-Dialog/tests/test_parser.py      |  14 -
 25 files changed, 1305 deletions(-)
 delete mode 100644 PyQt-Plotter-Dialog/README.md
 delete mode 100644 PyQt-Plotter-Dialog/graph_widget/__init__.py
 delete mode 100644 PyQt-Plotter-Dialog/graph_widget/graph.py
 delete mode 100644 PyQt-Plotter-Dialog/graph_widget/graph_widget.py
 delete mode 100644 PyQt-Plotter-Dialog/parser/README.md
 delete mode 100644 PyQt-Plotter-Dialog/parser/__init__.py
 delete mode 100644 PyQt-Plotter-Dialog/parser/__main__.py
 delete mode 100644 PyQt-Plotter-Dialog/parser/constants.py
 delete mode 100644 PyQt-Plotter-Dialog/parser/expression.py
 delete mode 100644 PyQt-Plotter-Dialog/parser/operation.py
 delete mode 100644 PyQt-Plotter-Dialog/parser/parser.py
 delete mode 100644 PyQt-Plotter-Dialog/parser/tokenizer.py
 delete mode 100644 PyQt-Plotter-Dialog/parser/types.py
 delete mode 100644 PyQt-Plotter-Dialog/plotter_dialog/__init__.py
 delete mode 100644 PyQt-Plotter-Dialog/plotter_dialog/__main__.py
 delete mode 100644 PyQt-Plotter-Dialog/plotter_dialog/button_group.py
 delete mode 100644 PyQt-Plotter-Dialog/plotter_dialog/constants.py
 delete mode 100644 PyQt-Plotter-Dialog/plotter_dialog/dialog.py
 delete mode 100644 PyQt-Plotter-Dialog/plotter_dialog/flow_layout.py
 delete mode 100644 PyQt-Plotter-Dialog/plotter_dialog/graph_requester.py
 delete mode 100644 PyQt-Plotter-Dialog/plotter_dialog/utils.py
 delete mode 100644 PyQt-Plotter-Dialog/requirements.dev.txt
 delete mode 100644 PyQt-Plotter-Dialog/requirements.txt
 delete mode 100644 PyQt-Plotter-Dialog/tests/__init__.py
 delete mode 100644 PyQt-Plotter-Dialog/tests/test_parser.py

diff --git a/PyQt-Plotter-Dialog/README.md b/PyQt-Plotter-Dialog/README.md
deleted file mode 100644
index fbc025b..0000000
--- a/PyQt-Plotter-Dialog/README.md
+++ /dev/null
@@ -1,71 +0,0 @@
-# PyQT graph plotter
-
-## Интерфейс пакетов
-
-- `graph_widget`
-
-```python
-   graph = Graph(x, y, labels, mult_subplots=mult_plots)
-   #x,y-данные для графиков. x-вводится пользователем или подтягивается из бд
-   #y-формируется из введенного математического выражения
-   #labels- список наименований графиков
-   #mult_subplots=True/False отрисовка графиков в виде subplots или на одном plot
-   
-```
-- `parser`
-
-    [parser/README.md](./parser/README.md)
-
-- `plotter_dialog`
-
-```python
-from plotter_dialog import PlotterDialog, FUNCTION_NAMES
-
-PlotterDialog(
-    variable_values: dict[str, np.ndarray] = {} # Значения для подстановки в переменные
-    variable_full_names: dict[str, str] = {} # Надписи для кнопок переменных и подсказок для них
-    function_full_names: dict[str, str] = FUNCTION_NAMES # То же самое для функций
-)
-
-FUNCTION_NAMES = {
-    "abs": "Модуль",
-    "acos": "Арккосинус",
-    "acosh": "Гиперболический арккосинус",
-    "acot": "Арккотангенс",
-    "asin": "Арксинус",
-    "asinh": "Гиперболический арксинус",
-    "atan": "Арктангенс",
-    "avg": "Среднее",
-    "cos": "Косинус",
-    "cosh": "Гиперболический косинус",
-    "cot": "Котангенс",
-    "exp": "Экспонента (e^x)",
-    "lg": "Десятичный логарифм",
-    "ln": "Натуральный логарифм",
-    "log2": "Двоичный логарифм",
-    "max": "Максимум",
-    "min": "Минимум",
-    "prod": "Произведение",
-    "sgn": "Знак",
-    "sin": "Синус",
-    "sinh": "Гиперболический синус",
-    "sqrt": "Квадратный корень",
-    "sum": "Сумма",
-    "tanh": "Гиперболический тангенс",
-    "tan": "Тангенс",
-}
-```
-
-`variable_full_names` и `variable_values` должны иметь одни и те же ключи.
-
-## Инструкции по запуску демо-версии
-
-Выполнить в корневой папке:
-
-```bash
-python -m venv .venv
-source .venv/bin/activate
-pip install -r requirements.txt
-
-python -m plotter_dialog
-```
diff --git a/PyQt-Plotter-Dialog/graph_widget/__init__.py b/PyQt-Plotter-Dialog/graph_widget/__init__.py
deleted file mode 100644
index 299cfd8..0000000
--- a/PyQt-Plotter-Dialog/graph_widget/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from .graph_widget import GraphWidget
-
-__all__ = ("GraphWidget",)
diff --git a/PyQt-Plotter-Dialog/graph_widget/graph.py b/PyQt-Plotter-Dialog/graph_widget/graph.py
deleted file mode 100644
index f527ebf..0000000
--- a/PyQt-Plotter-Dialog/graph_widget/graph.py
+++ /dev/null
@@ -1,67 +0,0 @@
-from matplotlib.figure import Figure
-
-
-class Graph:
-    def __init__(
-        self, x, y, labels, mult_subplots=0, xl="x", yl="y", linetype="k", lims=False
-    ):
-        # словарь из настроек?
-        self.labels = labels
-        self.__x = x
-        self.__y = y
-        self.__fig = Figure(figsize=(5, 4), dpi=100)
-        self.__chb = mult_subplots
-        self.__ax = self.__fig.add_subplot()
-
-        self.draw_n_func_plot()
-        
-        self.draw_subplots()
-
-        self.__ax.set_xlabel(xl)
-        self.__ax.set_ylabel(yl)
-        self.__ax.legend()
-        self.figure.tight_layout()
-
-    def add_vline(ax, x=0, ymin=0, ymax=1):
-        ax.axvline(x, ymin, ymax)
-        # принимаем плот и на нем же рисуем
-
-    def add_hline(
-        ax,
-        y=0,
-        xmin=0,
-        xmax=1,
-    ):
-        ax.axhline(y, xmin, xmax)
-
-    def draw_n_func_plot(
-        self,
-    ):  # много графиков на одном холсте
-        if self.__chb == 0 and len(self.__x) > 1:
-            for i in range(len(self.__x)):
-                self.__ax.plot(self.__x[i], self.__y[i], label=self.labels[i])
-                #новое(старое) условие против проскока
-        if self.__chb == 0 and len(self.__x) == 1:
-            self.__ax.plot(self.__x[0], self.__y[0], label=self.labels[0]) 
-
-    
-
-    def draw_subplots(
-        self,
-    ):
-        if self.__chb == 1 and len(self.__x) > 1:
-            for i in range(len(self.__x)):
-                n = int(f"{len(self.__x)}1{i+1}")
-
-                axes = self.__fig.add_subplot(n)
-                axes.set_title(f"График №{i+1}")
-                axes.plot(self.__x[i], self.__y[i], label=self.labels[i])
-                        #новое(старое) условие против проскока
-        if self.__chb ==1  and len(self.__x) == 1:
-            self.__ax.plot(self.__x[0], self.__y[0], label=self.labels[0])
-
-    @property
-    def figure(
-        self,
-    ):
-        return self.__fig
diff --git a/PyQt-Plotter-Dialog/graph_widget/graph_widget.py b/PyQt-Plotter-Dialog/graph_widget/graph_widget.py
deleted file mode 100644
index b6352cf..0000000
--- a/PyQt-Plotter-Dialog/graph_widget/graph_widget.py
+++ /dev/null
@@ -1,24 +0,0 @@
-from .graph import Graph
-import matplotlib
-from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
-from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
-from PyQt5 import QtWidgets
-
-matplotlib.use("Qt5Agg")
-
-
-class GraphWidget(QtWidgets.QWidget):
-    def __init__(self, x, y, labels, mult_plots=False):
-        super().__init__()
-        graph = Graph(x, y, labels, mult_subplots=mult_plots)
-
-        sc = FigureCanvasQTAgg(graph.figure)
-
-        # Create toolbar, passing canvas as first parament, parent (self, the MainWindow) as second.
-        toolbar = NavigationToolbar(sc, self)
-
-        layout = QtWidgets.QVBoxLayout()
-        layout.addWidget(toolbar)
-        layout.addWidget(sc)
-
-        self.setLayout(layout)
diff --git a/PyQt-Plotter-Dialog/parser/README.md b/PyQt-Plotter-Dialog/parser/README.md
deleted file mode 100644
index b548112..0000000
--- a/PyQt-Plotter-Dialog/parser/README.md
+++ /dev/null
@@ -1,81 +0,0 @@
-# Math expression parser
-
-Math expression evaluation library. It supports most of useful math operations and functions. Expressions can contain variables which can be substituted with `int`s, `float`s or `numpy.ndarray`s.
-
-## Example usage
-
-```python
-from parser import Parser
-
-parser = Parser("(-b + sqrt(b^2-4a c))/(2a)")
-
-parser.variables_names # {'c', 'a', 'b'}
-
-parser.evaluate({"a": 1, "b": -3, "c": 2}) # 1.0
-
-parser.evaluate({"a": [1, 1, 1], "b": [-5, -6, -9], "c": [6, 9, 20]}) # [2. 3. 4.]
-```
-## Expression syntax
-
-Expression can contain numbers or variable names with functions applied to them, separated with operators or united with braces. Numbers do not support `*`-less multiplication with spaces. Variables must be separated by space.
-
-Here are examples with `_` as space
-
-| Wrong | Right |
-|--|--|
-| `2_a` | `2a` or `2*a` |
-| `a_2` | `a*2` |
-| `a_2_a` | `a*2*a` |
-| `2_cos(a)` | `2cos(a)` or `2*cos(a)` |
-| `cos(a)_2` | `cos(a)*2` |
-| `aa` | `a*a` or `a_a` |
-| - | `cos(a)cos(a)` or `cos(a)_cos(a)` or `cos(a)*cos(a)` |
-
-
-Theese are supported:
-
-Functions: 
-
-| name | math |
-|--|--|
-| `abs` | $\|x\|$ |
-| `acos` | $\cos^{-1}(x)$ |
-| `acosh` | $\cosh^{-1}(x)$ |
-| `acot` | $\cot^{-1}(x)$ |
-| `asin` | $\sin^{-1}(x)$ |
-| `asinh` | $\sinh^{-1}(x)$ |
-| `atan` | $\tan^{-1}(x)$ |
-| `avg` | $\overline X$ |
-| `cos` | $\cos(x)$ |
-| `cosh` | $\cosh(x)$ |
-| `cot` | $\cot(x)$ |
-| `exp` | $\exp(x)$ |
-| `inf` | $\inf(X)$ |
-| `lg` | $\lg(x)$ |
-| `ln` | $\ln(x)$ |
-| `log10` | $\log_{10}(x)$ |
-| `log2` | $\log_2(x)$ |
-| `max` | $\sup(X)$ |
-| `min` | $\inf(X)$ |
-| `prod` | $\displaystyle \prod_{i=0}^n x_i$ |
-| `sgn` | $sgn(x)$ |
-| `sign` | $sgn(x)$ |
-| `sin` | $\sin(x)$ |
-| `sinh` | $\sinh(x)$ |
-| `sqrt` | $\sqrt{x}$ |
-| `sum` | $\displaystyle\sum_{i=0}^n x_i$ |
-| `sup` | $\sup(X)$ |
-| `tan` | $\tan(x)$ |
-| `tanh` | $\tanh(x)$ |
-
-Operators: `+`, `-`, `*`, `/`, `^`, `%`
-
-Braces: `()`, `[]`, `{}`
-
-Floating points: `.`, `,`
-
-Functions have only one argument, provided in braces. Operators must have two operands except minus (if it is the first character of equation or braced expression).
-
-`avg`, `sum`, `max`, `sup`, `min`, `inf` and `prod` applied on `numpy.ndarray` produce `float`.
-
-**! There is no error handling yet !**
diff --git a/PyQt-Plotter-Dialog/parser/__init__.py b/PyQt-Plotter-Dialog/parser/__init__.py
deleted file mode 100644
index 3385e94..0000000
--- a/PyQt-Plotter-Dialog/parser/__init__.py
+++ /dev/null
@@ -1,21 +0,0 @@
-from .parser import (
-    BinaryExpression,
-    Expression,
-    Operation,
-    Parser,
-    Token,
-    Tokenizer,
-    UnaryExpression,
-    ValueExpression,
-)
-
-__all__ = (
-    "BinaryExpression",
-    "Expression",
-    "Operation",
-    "Parser",
-    "Token",
-    "Tokenizer",
-    "UnaryExpression",
-    "ValueExpression",
-)
diff --git a/PyQt-Plotter-Dialog/parser/__main__.py b/PyQt-Plotter-Dialog/parser/__main__.py
deleted file mode 100644
index 7ef68bf..0000000
--- a/PyQt-Plotter-Dialog/parser/__main__.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from . import Parser
-
-expression = input("Input math expression: ")
-
-parser = Parser(expression)
-
-print("Variables in your expression: " + ", ".join(parser.variables_names))
-
-variables = {}
-
-for key in parser.variables_names:
-    variables[key] = float(input(f"Input '{key}' variable value: "))
-
-res = parser.evaluate(variables)
-
-print(f"Evaluation result is: {res}")
diff --git a/PyQt-Plotter-Dialog/parser/constants.py b/PyQt-Plotter-Dialog/parser/constants.py
deleted file mode 100644
index 6b7b711..0000000
--- a/PyQt-Plotter-Dialog/parser/constants.py
+++ /dev/null
@@ -1,6 +0,0 @@
-import numpy as np
-
-CONSTANTS = {
-    "e": np.e,
-    "pi": np.pi,
-}
diff --git a/PyQt-Plotter-Dialog/parser/expression.py b/PyQt-Plotter-Dialog/parser/expression.py
deleted file mode 100644
index 50c579d..0000000
--- a/PyQt-Plotter-Dialog/parser/expression.py
+++ /dev/null
@@ -1,81 +0,0 @@
-"""
-Contains classes for expression tree representation and evaluation
-"""
-
-import abc
-from collections.abc import Callable, Mapping
-
-from .types import FunctionType, OperatorType, ValueType
-
-
-class Expression(abc.ABC):
-    """
-    Abstract base class for a single parsed expression as a tree data
-    structure. It also defines its public function for triggering
-    evaluation. Each child class sets `_evaluator` property to a
-    function that accepts variables values and produces numpy array.
-    """
-
-    _evaluator: Callable[[Mapping[str, ValueType]], ValueType]
-
-    def evaluate(self, variables: Mapping[str, ValueType]):
-        return self._evaluator(variables)
-
-
-class ValueExpression(Expression):
-    """
-    This expression accepts variable name, numpy array or scalar number
-    and evaluates to either constant or variable value, corresponding
-    to its name.
-    """
-
-    def __init__(self, a: str | ValueType):
-        self.__debug_a = a
-
-        if isinstance(a, str):
-            self._evaluator = lambda vars: vars[a]
-        else:
-            self._evaluator = lambda _: a
-
-    def __repr__(self):
-        return f"<{self.__debug_a}>"
-
-
-class UnaryExpression(Expression):
-    """
-    This expression accepts function with one argument and `Expression`
-    (value, unary or binary) and that function on expression, passed into it.
-    It is applied for named functions like `exp(a)`
-    """
-
-    def __init__(self, function: FunctionType, a: Expression):
-        self.__debug_f = function.__name__
-        self.__debug_a = repr(a)
-
-        self._evaluator = lambda vars: function(a.evaluate(vars))
-
-    def __repr__(self):
-        return f"<{self.__debug_f}({self.__debug_a})>"
-
-
-class BinaryExpression(Expression):
-    """
-    This expression is similar to `UnaryExpression`, but accepts function
-    with two arguments and two expressions.
-    It is applied for math operators like `a - b`
-    """
-
-    def __init__(
-        self,
-        function: OperatorType,
-        a: Expression,
-        b: Expression,
-    ):
-        self.__debug_f = function.__name__
-        self.__debug_a = repr(a)
-        self.__debug_b = repr(b)
-
-        self._evaluator = lambda vars: function(a.evaluate(vars), b.evaluate(vars))
-
-    def __repr__(self):
-        return f"<{self.__debug_a} {self.__debug_f} {self.__debug_b}>"
diff --git a/PyQt-Plotter-Dialog/parser/operation.py b/PyQt-Plotter-Dialog/parser/operation.py
deleted file mode 100644
index ecdeb01..0000000
--- a/PyQt-Plotter-Dialog/parser/operation.py
+++ /dev/null
@@ -1,113 +0,0 @@
-from dataclasses import dataclass
-
-import numpy as np
-
-from .types import FunctionType, OperatorType, ValueType
-
-
-# Additional functions that are not defined in numpy
-
-
-def acot(x: ValueType):
-    return np.arctan(1 / x)
-
-
-def cot(x: ValueType):
-    return 1 / np.tan(x)
-
-
-# Function and operation names to evaluators mapping
-
-
-functions: dict[str, FunctionType] = {
-    "abs": np.abs,
-    "acos": np.arccos,
-    "acosh": np.arccosh,
-    "acot": acot,
-    "asin": np.arcsin,
-    "asinh": np.arcsinh,
-    "atan": np.arctan,
-    "avg": np.average,
-    "cos": np.cos,
-    "cosh": np.cosh,
-    "cot": cot,
-    "exp": np.exp,
-    "inf": np.inf,
-    "lg": np.log10,
-    "ln": np.log,
-    "log10": np.log10,
-    "log2": np.log2,
-    "max": np.max,
-    "min": np.min,
-    "prod": np.prod,
-    "sgn": np.sign,
-    "sign": np.sign,
-    "sin": np.sin,
-    "sinh": np.sinh,
-    "sqrt": np.sqrt,
-    "sum": np.sum,
-    "sup": np.max,
-    "tanh": np.tanh,
-    "tan": np.tan,
-}
-
-operators: dict[str, OperatorType] = {
-    "+": np.add,
-    "-": np.subtract,
-    "*": np.multiply,
-    "/": np.divide,
-    "%": np.mod,
-    "^": np.float_power,
-}
-
-priorities: dict[str, int] = {
-    "(": 0,
-    "+": 1,
-    "-": 1,
-    "*": 2,
-    "/": 2,
-    "%": 2,
-    "^": 3,
-    "f": 4,  # function
-    ")": 5,
-}
-
-
-@dataclass
-class Operation:
-    """
-    Base class for math operation token (function, brace, operator).
-    It stores the way it is evaluated, evaluation priority and number
-    of arguments it supports.
-    """
-
-    evaluator: (FunctionType | OperatorType | str)
-    priority: int
-    size: int
-
-
-class FunctionOperation(Operation):
-    """
-    `Operator` class factory that represents function
-    """
-
-    def __init__(self, name: str):
-        super().__init__(functions[name], priorities["f"], 1)
-
-
-class BraceOperation(Operation):
-    """
-    `Operator` class factory that represents brace
-    """
-
-    def __init__(self, name: str):
-        super().__init__(name, priorities[name], 0)
-
-
-class OperatorOperation(Operation):
-    """
-    `Operator` class factory that represents binary operator
-    """
-
-    def __init__(self, name: str):
-        super().__init__(operators[name], priorities[name], 2)
diff --git a/PyQt-Plotter-Dialog/parser/parser.py b/PyQt-Plotter-Dialog/parser/parser.py
deleted file mode 100644
index c0be8d0..0000000
--- a/PyQt-Plotter-Dialog/parser/parser.py
+++ /dev/null
@@ -1,104 +0,0 @@
-from .expression import BinaryExpression, Expression, UnaryExpression, ValueExpression
-from .operation import (
-    BraceOperation,
-    FunctionOperation,
-    Operation,
-    OperatorOperation,
-    priorities,
-)
-from .tokenizer import Token, Tokenizer
-from .types import ValueType
-from .constants import CONSTANTS
-
-
-class Parser:
-    """
-    Class that accepts math expression in its constructor,
-    parses it and provides `evaluate` method to substitue
-    variables values to it
-    """
-
-    def __init__(self, input_expr: str):
-        self.input_expr = input_expr
-        self.variables_names: set[str] = set()
-
-        self._tokenize()
-        self._parse()
-
-    def _tokenize(self):
-        """
-        Uses `Tokenizer` class for math expression splitting
-        """
-        self.tokens = Tokenizer(self.input_expr)
-
-    def _parse(self):
-        """
-        Generates an evaluation tree from tokens by utilizing two
-        stacks - one for values and one for operations. Values and
-        operations are placed into corresponding stacks, and when
-        possible, assempled into tree node.
-        """
-        self.val_stack: list[Expression] = []
-        self.op_stack: list[Operation] = []
-
-        for t_val, t_type in self.tokens:
-            if t_type in (Token.Number, Token.Variable):
-                self.val_stack.append(ValueExpression(t_val))
-
-                if t_type == Token.Variable:
-                    self.variables_names.add(t_val)
-
-            elif t_type == Token.Function:
-                self.op_stack.append(FunctionOperation(t_val))
-
-            elif t_type == Token.LBrace:
-                self.op_stack.append(BraceOperation("("))
-
-            elif t_type == Token.RBrace:
-                while len(self.op_stack) > 0 and not (
-                    self.op_stack[-1].size == 0 and self.op_stack[-1].priority == 0
-                ):  # until next in stack is lbrace
-                    self._do_one()
-                self.op_stack.pop()  # pop lbrace
-
-            elif t_type == Token.Operator:
-                t_priority = priorities[t_val]
-
-                while (
-                    len(self.op_stack) > 0 and self.op_stack[-1].priority > t_priority
-                ):
-                    self._do_one()
-
-                self.op_stack.append(OperatorOperation(t_val))
-
-        while len(self.op_stack) > 0:
-            self._do_one()
-
-        self._evaluator = self.val_stack[0].evaluate
-
-        self.__debug_expr = repr(self.val_stack)
-
-    def _do_one(self):
-        """
-        Assembles one operation into `Expression` tree node that is stored
-        on value stack.
-        """
-        op = self.op_stack.pop()
-
-        if op.size == 1:
-            a = self.val_stack.pop()
-            self.val_stack.append(UnaryExpression(op.evaluator, a))
-        elif op.size == 2:
-            b, a = self.val_stack.pop(), self.val_stack.pop()  # inversed pop order
-            self.val_stack.append(BinaryExpression(op.evaluator, a, b))
-
-    def evaluate(self, variables: dict[str, ValueType]):
-        """
-        Evaluates supplied to constructor expression with provided 
-        variables values
-        """
-        variables |= CONSTANTS
-        return self._evaluator(variables)
-
-    def __repr__(self):
-        return self.__debug_expr
diff --git a/PyQt-Plotter-Dialog/parser/tokenizer.py b/PyQt-Plotter-Dialog/parser/tokenizer.py
deleted file mode 100644
index 4395e3b..0000000
--- a/PyQt-Plotter-Dialog/parser/tokenizer.py
+++ /dev/null
@@ -1,114 +0,0 @@
-from collections.abc import Generator
-from dataclasses import dataclass
-from typing import Optional
-
-from .operation import functions, operators
-from .types import Token, TokenType
-
-
-@dataclass
-class Tokenizer:
-    """
-    Implements an iterator that yields `Token`s one by one.
-    It's grammatics is context-sensitive, but respects only a
-    single previous token.
-    """
-
-    expression: str
-
-    def __iter__(self) -> Generator[TokenType, None, None]:
-        accumulator = ""
-        prev = None
-
-        for ch in self.expression:
-            if (breaker_type := Tokenizer.is_breaker(ch)) is not None:
-                if len(accumulator) > 0:
-                    # ch is `(` after function name
-                    if breaker_type == Token.LBrace and Tokenizer.is_function(
-                        accumulator
-                    ):
-                        yield accumulator, Token.Function
-                        prev = Token.Function
-                        accumulator = ""
-                    else:
-                        value, token_type = Tokenizer.detect_number(accumulator)
-                        yield value, token_type
-                        prev = token_type
-                        accumulator = ""
-
-                        # `(` after variable or number
-                        if breaker_type == Token.LBrace:
-                            yield "*", Token.Operator
-                            prev = Token.Operator
-
-                # Unary minus case
-                if ch == "-" and (prev == Token.LBrace or prev is None):
-                    yield 0, Token.Number
-                    prev = Token.Number
-
-                # `(expr)(expr)` case
-                if breaker_type == Token.LBrace and prev == Token.RBrace:
-                    yield "*", Token.Operator
-                    prev = Token.Operator
-
-                if breaker_type != Token.Space:
-                    yield ch, breaker_type
-                    prev = breaker_type
-            else:
-                # Variable or function name after braced expr or variable and space
-                if prev == Token.RBrace or prev == Token.Variable:
-                    yield "*", Token.Operator
-                    prev = Token.Operator
-
-                # Floating point number
-                if ch in ",.":
-                    accumulator += "."
-                    continue
-
-                # Variable or function name after number
-                if (
-                    not ch.isdecimal()
-                    and (num := Tokenizer.is_number(accumulator)) is not None
-                ):
-                    yield num, Token.Number
-                    yield "*", Token.Operator
-                    prev = Token.Operator
-                    accumulator = ""
-
-                accumulator += ch
-        if len(accumulator) > 0:
-            yield self.detect_number(accumulator)
-
-    @staticmethod
-    def is_breaker(character) -> Optional[Token]:
-        if character in operators:
-            return Token.Operator
-        if character in "([{":
-            return Token.LBrace
-        if character in ")]}":
-            return Token.RBrace
-        if character == " ":
-            return Token.Space
-
-        return None
-
-    @staticmethod
-    def is_number(string) -> Optional[float]:
-        try:
-            return float(string)
-        except ValueError:
-            return None
-
-    @staticmethod
-    def detect_number(string) -> TokenType:
-        if (num := Tokenizer.is_number(string)) is not None:
-            return num, Token.Number
-        else:
-            return string, Token.Variable
-
-    @staticmethod
-    def is_function(lexeme: str) -> bool:
-        if lexeme in functions:
-            return True
-
-        return False
diff --git a/PyQt-Plotter-Dialog/parser/types.py b/PyQt-Plotter-Dialog/parser/types.py
deleted file mode 100644
index f451f39..0000000
--- a/PyQt-Plotter-Dialog/parser/types.py
+++ /dev/null
@@ -1,23 +0,0 @@
-from collections.abc import Callable
-from enum import Enum, auto
-
-import numpy as np
-
-ValueType = int | float | np.ndarray
-
-FunctionType = Callable[[ValueType], ValueType]
-
-OperatorType = Callable[[ValueType, ValueType], ValueType]
-
-
-class Token(Enum):
-    Variable = auto()
-    Number = auto()
-    Function = auto()
-    Operator = auto()
-    LBrace = auto()
-    RBrace = auto()
-    Space = auto()
-
-
-TokenType = tuple[str | float, Token]
diff --git a/PyQt-Plotter-Dialog/plotter_dialog/__init__.py b/PyQt-Plotter-Dialog/plotter_dialog/__init__.py
deleted file mode 100644
index 3ea9aa5..0000000
--- a/PyQt-Plotter-Dialog/plotter_dialog/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from .dialog import PlotterDialog
-
-__all__ = ("PlotterDialog",)
diff --git a/PyQt-Plotter-Dialog/plotter_dialog/__main__.py b/PyQt-Plotter-Dialog/plotter_dialog/__main__.py
deleted file mode 100644
index f88bdb6..0000000
--- a/PyQt-Plotter-Dialog/plotter_dialog/__main__.py
+++ /dev/null
@@ -1,23 +0,0 @@
-import sys
-
-from PyQt5.QtWidgets import QApplication
-
-import numpy as np
-
-from . import PlotterDialog
-
-
-def main():
-    app = QApplication(sys.argv)
-
-    variables = [chr(ord("a") + i) for i in range(10)]
-
-    dlg = PlotterDialog(
-        variable_values={key: np.sort(np.random.random(10)) * 10 for key in variables},
-        variable_full_names={key: key.upper() for key in variables},
-    )
-    dlg.show()
-
-    sys.exit(app.exec())
-
-main()
diff --git a/PyQt-Plotter-Dialog/plotter_dialog/button_group.py b/PyQt-Plotter-Dialog/plotter_dialog/button_group.py
deleted file mode 100644
index 0145d2c..0000000
--- a/PyQt-Plotter-Dialog/plotter_dialog/button_group.py
+++ /dev/null
@@ -1,44 +0,0 @@
-from collections.abc import Callable
-
-from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QPushButton
-
-from .flow_layout import FlowLayout
-
-
-class ButtonGroup(QWidget):
-    def __init__(
-        self,
-        category: str,
-        full_names: dict[str, str],
-        buttons_action: Callable[[str], None],
-        parent=None,
-    ):
-        super().__init__()
-        self.layout = QVBoxLayout()  # Создание основного лаяутв
-        Doplayout = FlowLayout()
-        label = QLabel(category)
-
-        self.layout.addWidget(label)
-        for button_name in full_names:
-            button = QPushButton(button_name, self)
-
-            button.setFixedWidth(80)
-            button.setToolTip(
-                full_names[button_name]
-            )  # Создание подскачоки при наведении
-
-            button.clicked.connect(
-                lambda _, name=button_name: buttons_action(  # ignore checked state with _
-                    name
-                )
-            )  # Назначение кнопочке действия
-
-            Doplayout.addWidget(button)  # отрисовывание кнопок
-
-        Doplayout.setContentsMargins(0, 0, 0, 0)
-
-        self.layout.addLayout(Doplayout)
-
-        self.layout.setContentsMargins(0, 0, 0, 0)
-
-        self.setLayout(self.layout)
diff --git a/PyQt-Plotter-Dialog/plotter_dialog/constants.py b/PyQt-Plotter-Dialog/plotter_dialog/constants.py
deleted file mode 100644
index 60d356c..0000000
--- a/PyQt-Plotter-Dialog/plotter_dialog/constants.py
+++ /dev/null
@@ -1,27 +0,0 @@
-FUNCTION_NAMES = {
-    "sin": "Синус",
-    "cos": "Косинус",
-    "tan": "Тангенс",
-    "cot": "Котангенс",
-    "abs": "Модуль",
-    "exp": "Экспонента (e^x)",
-    "sqrt": "Квадратный корень",
-    "ln": "Натуральный логарифм",
-    "lg": "Десятичный логарифм",
-    "log2": "Двоичный логарифм",
-    "sgn": "Знак",
-    "asin": "Арксинус",
-    "acos": "Арккосинус",
-    "atan": "Арктангенс",
-    "acot": "Арккотангенс",
-    "sinh": "Гиперболический синус",
-    "cosh": "Гиперболический косинус",
-    "tanh": "Гиперболический тангенс",
-    "acosh": "Гиперболический арккосинус",
-    "asinh": "Гиперболический арксинус",
-    "sum": "Сумма",
-    "prod": "Произведение",
-    "min": "Минимум",
-    "avg": "Среднее",
-    "max": "Максимум",
-}
diff --git a/PyQt-Plotter-Dialog/plotter_dialog/dialog.py b/PyQt-Plotter-Dialog/plotter_dialog/dialog.py
deleted file mode 100644
index ac18323..0000000
--- a/PyQt-Plotter-Dialog/plotter_dialog/dialog.py
+++ /dev/null
@@ -1,247 +0,0 @@
-from PyQt5.QtCore import Qt, QTimer
-from PyQt5.QtWidgets import (
-    QDialog,
-    QVBoxLayout,
-    QScrollArea,
-    QWidget,
-    QPushButton,
-    QLineEdit,
-    QMessageBox,
-    QHBoxLayout,
-    QCheckBox,
-)
-
-import numpy as np
-
-from .button_group import ButtonGroup
-from .constants import FUNCTION_NAMES
-from .graph_requester import GraphRequester
-from .utils import size
-
-from parser import Parser
-
-from graph_widget import GraphWidget
-
-
-class PlotterDialog(QDialog):
-    focused_line_edit = None
-
-    def __init__(
-        self,
-        variable_values: dict[str, np.ndarray] = {},
-        variable_full_names: dict[str, str] = {},
-        function_full_names: dict[str, str] = FUNCTION_NAMES,
-    ):
-        super().__init__()
-
-        self.variable_values = variable_values
-
-        self.setWindowTitle("Графопостроитель")
-
-        layout_boss = QVBoxLayout()  # главный лояут
-
-        self.scroll = QScrollArea()
-
-        self.scroll.verticalScrollBar().rangeChanged.connect(self.scroll_bottom)
-
-        scrollWidget = QWidget()
-
-        self.scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
-
-        self.inputs_layout = QVBoxLayout()  # лаяут первой трети
-        self.inputs_layout.addStretch(1)
-
-        self.num_of_input = 0  # инициализация первого графика
-        self.add_input()
-
-        QTimer.singleShot(0, self.focus_first_input)
-
-        scrollWidget.setLayout(self.inputs_layout)
-
-        self.scroll.setWidgetResizable(True)
-        self.scroll.setWidget(scrollWidget)
-
-        layout_boss.addWidget(self.scroll)
-
-        Button_make_fun_button = QPushButton("+")
-        Button_make_fun_button.clicked.connect(self.add_input)
-        Button_make_fun_button.setFixedWidth(80)
-        layout_boss.addWidget(Button_make_fun_button, alignment=Qt.AlignRight)
-
-        layout_boss.addWidget(
-            ButtonGroup(
-                "Переменные",
-                full_names=variable_full_names,
-                buttons_action=self.insert_variable,
-            )
-        )
-        layout_boss.addWidget(
-            ButtonGroup(
-                "Функции",
-                full_names=function_full_names,
-                buttons_action=self.insert_function,
-            )
-        )
-
-        layout_boss.addSpacing(10)
-
-        buttons_layout = QHBoxLayout()
-
-        buttons_layout.setDirection(QHBoxLayout.RightToLeft)
-
-        submit_button = QPushButton("Построить")
-        reset_button = QPushButton("Сброс")
-
-        submit_button.clicked.connect(self.plot)
-        reset_button.clicked.connect(self.reset)
-
-        submit_button.setDefault(True)
-
-        buttons_layout.addWidget(submit_button)
-        buttons_layout.addWidget(reset_button)
-
-        self.subplots_checkbox = QCheckBox("Рисовать графики на отдельных осях")
-        buttons_layout.addWidget(self.subplots_checkbox)
-
-        buttons_layout.addStretch(1)
-
-        layout_boss.addLayout(buttons_layout)
-
-        self.setLayout(layout_boss)
-
-    def add_input(self):
-        self.num_of_input += 1
-
-        graph_requester = GraphRequester(self.num_of_input)
-
-        for line_edit in (graph_requester.LineEditX, graph_requester.LineEditY):
-            line_edit.focused_in.connect(
-                lambda line_edit=line_edit: self.set_focused_line_edit(line_edit)
-            )
-
-        graph_requester.LineEditGraf.focused_in.connect(
-            lambda: self.set_focused_line_edit(None)
-        )
-
-        self.inputs_layout.insertWidget(self.inputs_layout.count() - 1, graph_requester)
-
-        graph_requester.LineEditGraf.setFocus()
-
-    def set_focused_line_edit(self, line_edit: QLineEdit | None):
-        self.focused_line_edit = line_edit
-
-    def scroll_bottom(self):
-        self.scroll.verticalScrollBar().setValue(
-            self.scroll.verticalScrollBar().maximum()
-        )
-
-    def insert_string(self, string: str, string_cursor_padding=-1):
-        line_edit = self.focused_line_edit
-
-        if line_edit is None:
-            dlg = QMessageBox(
-                QMessageBox.Warning,
-                "Ошибка",
-                "Выберите поле ввода выражения",
-            )
-            dlg.exec()
-
-            return
-
-        cusor_pos = line_edit.cursorPosition()
-        text = line_edit.text()
-
-        if string_cursor_padding < 1:
-            string_cursor_padding = len(string)
-
-        line_edit.setText(text[:cusor_pos] + string + text[cusor_pos:])
-        line_edit.setCursorPosition(cusor_pos + string_cursor_padding)
-
-        self.scroll.ensureWidgetVisible(line_edit)
-        line_edit.setFocus()
-
-    def insert_variable(self, name: str):
-        self.insert_string(f" {name} ")
-
-    def insert_function(self, name: str):
-        string = f" {name}()"
-        self.insert_string(string, len(string) - 1)  # len - 1 for cursor between braces
-
-    def plot(self):
-        xs, ys, labels = [], [], []
-
-        for i in range(self.inputs_layout.count()):
-            graph_requester = self.inputs_layout.itemAt(i).widget()
-
-            if graph_requester is not None:
-                x_expr = graph_requester.LineEditX.text()
-                y_expr = graph_requester.LineEditY.text()
-                label = graph_requester.LineEditGraf.text()
-
-                if len(x_expr) * len(y_expr) == 0:
-                    dlg = QMessageBox(
-                        QMessageBox.Warning,
-                        "Ошибка",
-                        f'График "{label}" не задан',
-                    )
-                    dlg.exec()
-                    return
-
-                x = Parser(x_expr).evaluate(self.variable_values)
-                y = Parser(y_expr).evaluate(self.variable_values)
-
-                if size(x) != size(y):
-                    dlg = QMessageBox(
-                        QMessageBox.Critical,
-                        "Ошибка",
-                        "\n\n".join(
-                            (
-                                "Выражения имеют разную размерность",
-                                f'y: "{y}" -> {size(y)}',
-                                f'x: "{x}" -> {size(x)}',
-                            )
-                        ),
-                    )
-                    dlg.exec()
-
-                    graph_requester.LineEditY.setFocus()
-                    return
-
-                xs.append(x)
-                ys.append(y)
-                labels.append(label)
-
-        mult_subplots = self.subplots_checkbox.isChecked()
-
-        self.graph = GraphWidget(xs, ys, labels, mult_plots=mult_subplots)
-
-        self.graph.show()
-
-    def reset(self):
-        dlg = QMessageBox(
-            QMessageBox.Question,
-            "Очистка",
-            "Вы уверены, что хотите очистить все введённые выражения?",
-            buttons=QMessageBox.Yes | QMessageBox.No,
-        )
-
-        res = dlg.exec()
-
-        if res != QMessageBox.Yes:
-            return
-
-        while self.inputs_layout.count() > 0:
-            widget = self.inputs_layout.takeAt(0).widget()
-            if widget is not None:
-                widget.setParent(None)
-
-        self.focused_line_edit = None
-
-        self.num_of_input = 0
-
-        self.add_input()
-
-    def focus_first_input(self):
-        first_graph_request = self.inputs_layout.itemAt(0).widget()
-        if first_graph_request is not None:
-            first_graph_request.LineEditGraf.setFocus()
diff --git a/PyQt-Plotter-Dialog/plotter_dialog/flow_layout.py b/PyQt-Plotter-Dialog/plotter_dialog/flow_layout.py
deleted file mode 100644
index e756d9d..0000000
--- a/PyQt-Plotter-Dialog/plotter_dialog/flow_layout.py
+++ /dev/null
@@ -1,147 +0,0 @@
-#############################################################################
-##
-## Copyright (C) 2013 Riverbank Computing Limited.
-## Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-## All rights reserved.
-##
-## This file is part of the examples of PyQt.
-##
-## $QT_BEGIN_LICENSE:BSD$
-## You may use this file under the terms of the BSD license as follows:
-##
-## "Redistribution and use in source and binary forms, with or without
-## modification, are permitted provided that the following conditions are
-## met:
-##   * Redistributions of source code must retain the above copyright
-##     notice, this list of conditions and the following disclaimer.
-##   * Redistributions in binary form must reproduce the above copyright
-##     notice, this list of conditions and the following disclaimer in
-##     the documentation and/or other materials provided with the
-##     distribution.
-##   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
-##     the names of its contributors may be used to endorse or promote
-##     products derived from this software without specific prior written
-##     permission.
-##
-## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-## $QT_END_LICENSE$
-##
-#############################################################################
-
-
-from PyQt5 import QtCore, QtWidgets
-
-
-class FlowLayout(QtWidgets.QLayout):
-    def __init__(self, parent=None, margin=-1, hspacing=-1, vspacing=-1):
-        super(FlowLayout, self).__init__(parent)
-        self._hspacing = hspacing
-        self._vspacing = vspacing
-        self._items = []
-        self.setContentsMargins(margin, margin, margin, margin)
-
-    def __del__(self):
-        del self._items[:]
-
-    def addItem(self, item):
-        self._items.append(item)
-
-    def horizontalSpacing(self):
-        if self._hspacing >= 0:
-            return self._hspacing
-        else:
-            return self.smartSpacing(QtWidgets.QStyle.PM_LayoutHorizontalSpacing)
-
-    def verticalSpacing(self):
-        if self._vspacing >= 0:
-            return self._vspacing
-        else:
-            return self.smartSpacing(QtWidgets.QStyle.PM_LayoutVerticalSpacing)
-
-    def count(self):
-        return len(self._items)
-
-    def itemAt(self, index):
-        if 0 <= index < len(self._items):
-            return self._items[index]
-
-    def takeAt(self, index):
-        if 0 <= index < len(self._items):
-            return self._items.pop(index)
-
-    def expandingDirections(self):
-        return QtCore.Qt.Orientations(0)
-
-    def hasHeightForWidth(self):
-        return True
-
-    def heightForWidth(self, width):
-        return self.doLayout(QtCore.QRect(0, 0, width, 0), True)
-
-    def setGeometry(self, rect):
-        super(FlowLayout, self).setGeometry(rect)
-        self.doLayout(rect, False)
-
-    def sizeHint(self):
-        return self.minimumSize()
-
-    def minimumSize(self):
-        size = QtCore.QSize()
-        for item in self._items:
-            size = size.expandedTo(item.minimumSize())
-        left, top, right, bottom = self.getContentsMargins()
-        size += QtCore.QSize(left + right, top + bottom)
-        return size
-
-    def doLayout(self, rect, testonly):
-        left, top, right, bottom = self.getContentsMargins()
-        effective = rect.adjusted(+left, +top, -right, -bottom)
-        x = effective.x()
-        y = effective.y()
-        lineheight = 0
-        for item in self._items:
-            widget = item.widget()
-            hspace = self.horizontalSpacing()
-            if hspace == -1:
-                hspace = widget.style().layoutSpacing(
-                    QtWidgets.QSizePolicy.PushButton,
-                    QtWidgets.QSizePolicy.PushButton,
-                    QtCore.Qt.Horizontal,
-                )
-            vspace = self.verticalSpacing()
-            if vspace == -1:
-                vspace = widget.style().layoutSpacing(
-                    QtWidgets.QSizePolicy.PushButton,
-                    QtWidgets.QSizePolicy.PushButton,
-                    QtCore.Qt.Vertical,
-                )
-            nextX = x + item.sizeHint().width() + hspace
-            if nextX - hspace > effective.right() and lineheight > 0:
-                x = effective.x()
-                y = y + lineheight + vspace
-                nextX = x + item.sizeHint().width() + hspace
-                lineheight = 0
-            if not testonly:
-                item.setGeometry(QtCore.QRect(QtCore.QPoint(x, y), item.sizeHint()))
-            x = nextX
-            lineheight = max(lineheight, item.sizeHint().height())
-        return y + lineheight - rect.y() + bottom
-
-    def smartSpacing(self, pm):
-        parent = self.parent()
-        if parent is None:
-            return -1
-        elif parent.isWidgetType():
-            return parent.style().pixelMetric(pm, None, parent)
-        else:
-            return parent.spacing()
diff --git a/PyQt-Plotter-Dialog/plotter_dialog/graph_requester.py b/PyQt-Plotter-Dialog/plotter_dialog/graph_requester.py
deleted file mode 100644
index fb3f0fa..0000000
--- a/PyQt-Plotter-Dialog/plotter_dialog/graph_requester.py
+++ /dev/null
@@ -1,56 +0,0 @@
-from PyQt5.QtWidgets import (
-    QVBoxLayout,
-    QHBoxLayout,
-    QLabel,
-    QPushButton,
-    QLineEdit,
-    QWidget,
-)
-
-from PyQt5.QtCore import pyqtSignal
-
-
-class FocusNotifyingLineEdit(QLineEdit):
-    focused_in = pyqtSignal()
-
-    def focusInEvent(self, event):
-        self.focused_in.emit()
-        super(FocusNotifyingLineEdit, self).focusInEvent(event)
-
-
-class GraphRequester(QWidget):
-    LineEditGraf: FocusNotifyingLineEdit
-    LineEditX: FocusNotifyingLineEdit
-    LineEditY: FocusNotifyingLineEdit
-
-    def __init__(self, nomer_grafika=1):
-        super().__init__()
-        layout = QVBoxLayout(self)
-        layout_x = QHBoxLayout()
-        layout_y = QHBoxLayout()
-        layout_close_and_name = QHBoxLayout()
-        self.LineEditGraf = FocusNotifyingLineEdit(f"график {nomer_grafika}")
-        NameX = QLabel("X")
-        NameY = QLabel("Y")
-        Name_Close = QPushButton("x")
-
-        self.LineEditX = FocusNotifyingLineEdit()
-        self.LineEditY = FocusNotifyingLineEdit()
-
-        layout_x.addWidget(NameX)
-        layout_x.addWidget(self.LineEditX)
-
-        layout_y.addWidget(NameY)
-        layout_y.addWidget(self.LineEditY)
-
-        Name_Close.clicked.connect(lambda: self.setParent(None))
-
-        layout_close_and_name.addWidget(self.LineEditGraf)
-        layout_close_and_name.addWidget(Name_Close)
-
-        layout.addLayout(layout_close_and_name)  # Вложения названия и закрыть
-        layout.addLayout(layout_y)  # Вложение
-        layout.addLayout(layout_x)  # Вложение
-
-        layout.setContentsMargins(0, 0, 0, 0)
-        layout.addStretch(1)
diff --git a/PyQt-Plotter-Dialog/plotter_dialog/utils.py b/PyQt-Plotter-Dialog/plotter_dialog/utils.py
deleted file mode 100644
index 07e64bc..0000000
--- a/PyQt-Plotter-Dialog/plotter_dialog/utils.py
+++ /dev/null
@@ -1,10 +0,0 @@
-import numpy as np
-
-from parser.types import ValueType
-
-
-def size(x: ValueType) -> int:
-    if isinstance(x, np.ndarray):
-        return x.size
-    else:
-        return 1
diff --git a/PyQt-Plotter-Dialog/requirements.dev.txt b/PyQt-Plotter-Dialog/requirements.dev.txt
deleted file mode 100644
index 677613b..0000000
--- a/PyQt-Plotter-Dialog/requirements.dev.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-black==23.9.1
-mypy==1.5.1
-ruff==0.0.292
-jedi-language-server==0.41.1
-isort==5.12.0
-pytest==7.4.2
\ No newline at end of file
diff --git a/PyQt-Plotter-Dialog/requirements.txt b/PyQt-Plotter-Dialog/requirements.txt
deleted file mode 100644
index bb11c95..0000000
--- a/PyQt-Plotter-Dialog/requirements.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-numpy==1.26.0
-pyqt5==5.15.2
-pyqt5-qt5==5.15.2
-matplotlib==3.8.0
diff --git a/PyQt-Plotter-Dialog/tests/__init__.py b/PyQt-Plotter-Dialog/tests/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/PyQt-Plotter-Dialog/tests/test_parser.py b/PyQt-Plotter-Dialog/tests/test_parser.py
deleted file mode 100644
index 2bca931..0000000
--- a/PyQt-Plotter-Dialog/tests/test_parser.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from parser import Parser
-
-
-def test_Parser():
-    parser = Parser("(-b + sqrt(b^2-4a c))/(2a)")
-
-    assert parser.variables_names == {"c", "a", "b"}
-
-    assert parser.evaluate({"a": 1, "b": -3, "c": 2}) == 1.0
-
-    assert all(
-        parser.evaluate({"a": [1, 1, 1], "b": [-5, -6, -9], "c": [6, 9, 20]})
-        == [2.0, 3.0, 4.0]
-    )