diff --git a/doc/rtd/content/99_appendices/appendix2/sub/core/mlpro_bf/layer0_elementary/images/.$MLPro-BF-Plot_class_diagram.drawio.bkp b/doc/rtd/content/99_appendices/appendix2/sub/core/mlpro_bf/layer0_elementary/images/.$MLPro-BF-Plot_class_diagram.drawio.bkp new file mode 100644 index 000000000..ae530c13c --- /dev/null +++ b/doc/rtd/content/99_appendices/appendix2/sub/core/mlpro_bf/layer0_elementary/images/.$MLPro-BF-Plot_class_diagram.drawio.bkp @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/doc/rtd/content/99_appendices/appendix2/sub/core/mlpro_bf/layer0_elementary/images/MLPro-BF-Plot_class_diagram.drawio b/doc/rtd/content/99_appendices/appendix2/sub/core/mlpro_bf/layer0_elementary/images/MLPro-BF-Plot_class_diagram.drawio index a0e9cd6df..a4625b332 100644 --- a/doc/rtd/content/99_appendices/appendix2/sub/core/mlpro_bf/layer0_elementary/images/MLPro-BF-Plot_class_diagram.drawio +++ b/doc/rtd/content/99_appendices/appendix2/sub/core/mlpro_bf/layer0_elementary/images/MLPro-BF-Plot_class_diagram.drawio @@ -1 +1 @@ -7V1pc5s6F/41nvbeGWdYvH70kuRN46RunLVfGBmETYMRZYnt/vpXAoHBEg6OwelNSDOpEVjb85yjoyNxVJMHi9W5A+z5FdKgWZMEbVWThzVJkgSxgf8jKeswRZTkVpgycwyNpm0SJsYfSBMFmuobGnRTD3oImZ5hpxNVZFlQ9VJpwHHQMv2Yjsx0qTaYQSZhogKTTX0wNG9OGyZHzSA3/geN2TwqutWkTZ4C9XnmIN+iBVrIguGdBYjyoY1050BDy0SSfFqTBw5CXvhpsRpAk3Rs1GUPF+sHc/TcOv/2w/0N7vqXt9f39TCzs32+ErfOgZb35qxXt6fz+7tL+6nRfrgZPD7Jj+Pnukzzdr111JdQw11LL5HjzdEMWcA83aT2g+6CJFsBX22eGSFk40QRJ/6CnremPAG+h3DS3FuY9K6OLG+ATOTgaw3qwDdxs/rQ0nqECzhxaiL1OUw6M8zoazm7IWoS8h2Vtgmd9QY396fd58upNO/rxqnkP9HuEjzgzKC3o48i/EnHJOhGe/kcogX0nDV+wIEm8IyXNCcBpfYsfm6DEf5AYeJDtqvaL8D0aUljE3kemJqQwdJdGgsTWJD2eQSrjK+Bacws/FnFnQkxEP0X6HgGFqkeveERMPvq3DC1EVgjn3SR62Fxia76c+QYf3C2IAII33Y8irrUSj0xId+kjHGgi58ZRziKcdIIuB59RkWmCWzXmAYVJo8sME6G1cdNRYsooxQRY/kMq+Kg51gZBKTDRIpIV5NkDcCOrsZPJu601A6c6uQO7b2z9DfPgh98f+YAzYAbKifv7cdV0vdwtZNc9G6Dwk81dSO6Xm7UnizQtHlS4wkdIZuQtLgbrJuBNSNEisrDuaUKFDkFii1OgVIrXRwwMc0s4ME+Ac1lxCBuai7J6Dntn1d2e/gw/A0fliNV7T36HMkYKOPR91ulN7i9uD/Ft2pyj+h8PDTVBlKtJzACg1HwEsJhQt3LFA3XBqphzUbBM8PGJuWG9gJJQvi7uhnQcm5oGrQC2noglNeQuDYyLC/opmYf/+JaDYSTZq2JKzTA1+LmGv+Sxx1MOQvzFhgBuSAWmyUkopPSrDXCBEHIoONO3fI6HddplF+jn7yDfHm1IVc5i1IW6JPb3vWwN/p+vQU8ucCPCbeOzyrMCv/98G++O/6dLPzve6OLoXJ/cfowiQlgGriXIgIEvT2sKHAgBTrvToFuFgWGp2e9u9FtQIIK5wNxFsUjAi2c/1HaF7I7VUaz7w8/W41ny4uNpQ3Oyovh+hjBP3BLx39grDcTptKQbhwR6cvVhXCqXfwS7r9PjJv+uP5N4c1xFBtPchTXg7aiYgOSTFkixElvVYAfBHj7iIA3lvLj1fTp4faH5T8Nmp1OUzuvs1ZcCDjOfY7IbIFirRlqBfaBJrvw3gO2nIW2Cz0PQ7GBm3g2JnFiBfshsMtHhH38gHruyn/6vX5u25ryKAzk60yljpaWohsz36kG8UJn5kfE++dMugPw959e/fe3y/l6cSWvp5l4G5bhGYHRplWAFwh494iA38xbYPWtf99D94Pm+vpbv94TeIBvyfUZvayAPgBo+ZhON26V2fGbgdQ0glWHxKIP65F/Be8FRi5Yb6IA3warS3WRIYHMkkDmAG6CKTTHyMXaB5H8nfDZLSK8hnVpqOZ1pXUOB5U7u+ZIb6CqFeUraXDmVJt6086A6ZJb/1TSfRgPWo3jSff50xzqQ3t+Lde7C0d0F2vB4hBhBr20gf4VoyzUa1JrFnZFZagXSIBuTgJsr7AVRgDWz+YyBAhUQp5JW6UQDuRDI9p/cAw+cKssM3wIxgWCfsgDauXJPWrfycPrYBvNgHCCVEsWCQTRmqtwyIecrAsHpaAawdcqFh7Iwrw+4UYBw9LlfUO/q/fc76vx3Wx4edtbjn9mDEuRVQKIUccMS9W08nDg867vFaF+uO7C1o7hiKwHOMCDoR6KLxMLA5XkH7rEH22xeDd/Mbu+GxNAgx4wTMWEL9AMOZBMqWhQIA0aR6TB07DevV1dtOF5Wz/roqb80+/XG+wENbBDQuuD0f2fwNd0lB0+7SPifnUjCCbw2y1JEH+g7g912f/BGfh15KhQ0WdfP5dQM6DlxTsT3JaQE9wiBncuuJw9HRW6RaEb+QrfDV3WUexA3YHuPDl5RME2/V5gq8vDz+lHLAH85hHdSFzwWbeBkkK/QvhAhKMd/e82M+MsGcSeIUXS+M6hUrxC+TxHsdPo8/kpj2EqtnPvLOoeTkjuNjKONbEhpFwR8rMRstHMR8ginJZcQu7UkFZFyM9GyM4RCcmtMutE8W0NeDA2yP/911ael8D5BIiX7zTrSDnxLsJE4+6k5xjhCcBjIy0h92mhH7yHHtrx4RPR8ygvbzXF45lsXIKyLoIUQeWKoJ+boN2ck9wiRkz+2wq7CWpVBP3UBO3KRyQo18/GmnQOXOBeT/hYqd9t42UNX37/4PCX74Lrto/oguOC32S1UwJ9Yt99bIxZES8B5bxvVpSGMrsFJoWyXKF8OMqiIL33Ymh7N8xWBXMRMDeOuCo6MTyt8Xh300T+uWb4wvOztKqzIUsYVElIOptt714xpOJwexS4WjJsHS+2VDuK4xRt/WMHt0aH11FSAaYNt6fYnV/YmDYj2gQtjJjT+u2jcKgPOEQA3SQJbhSyMEoTk7ejPUNh1tMUFNFTpMB6mA1xjYoNe8VmMYIzSCIJ9uK8nO3ccT9MOWlhe7Yqwnw5T8prPaPr6Z55raUtXkN3to/XFqxoLG5ptJ6kJGc2/RrMUwIHeOLTP9kVoK19tRVcuPD/YEEUozV17bA72KSsZqUeuyCNsx00w2a2myvbQpOC4rGUGFqwD/rIFbiBQCNqxEP4j092b8R9FsK+H0HTopuF1J78208qipDDVEqq8sDzHGPqe8GbdFg/SkIY5oKM7sWhdA2XhJP+1DRUops3hZ6FxUWITUk9jIVtwgWJBantrZWKBPSN8PGK2NnNCaUUl1QjXs5UVbYeKAabAJgzw5pDxwi6+zWQ5oC03XC3YcKDsAOzYSlWElJNUJi+LRRNXhWU/WSEsh8brtgACjor6s+zZN3/HgFgu1R4S5PTvEo0/+qd6JTR9qIUa97K8mdNidfTc02glnPcsxM8ZyLZLB1A0tJBaJnpTKslkHQmyiztm62wtVtBavXgJ25Aciqwc2bxuvfy/Wz6KGZ4wqgfQhsGMWEFYrtsQcUJC52ALeul/gi/0db9OKhA3uAD6RDUQRTlcC4hSnvj8moEaYpZXWxGyx50KlaXRM5uvyYHuOYO3GiBYxS+EkNL6550u91W/K+dKliUhBNBkAWx2Wnjvy1hK6x1GGWb5rhhBlNIs3HSaXTE6F9b3quUMEb366V0t4IjIF13YeormEpgnXiCejIyO2c7/DEVi40AhBluxGG/OMZ8CWG3sV2EWp2IiO6gxd8rJMKnFBJZOpE7jZYgi23yt1GKjOwuZF8RWSf6eJfAFEZqdqGfYXEVrj4zXL3eUaHKDVc/7TQbTZIhJxx9bD9khLIvz76I7r7uUeRtNtni9n86VD1fGthdBYw0fKIQSrs1xiHR6Hn0KiCCEr/C7Ep8peL2UHG6LvFVnNaatpqtv1XFVTouQxzYvQmVjstSGf8ZHcduRah0XKGnDv2NOq6y47LEgd2yUem4LJXxF+q4c81UX5B9v+r8elhIFy+iOOdFwhw7yMa1J1VUTeAGbhgsfARmYGnA0WgwY7JNh9zzLZX0LEbVW5+wXupTi2Dhxt83g2hpAv5I/B+LKdS0ODuyi5iTxQQG3zBdRGNx6nXfqLuq4RsMATcKS8zwYSfP5ivCKIuPQUs7txODAYf0aSZLmYMDS7tijlaTpbTekVus3pF4G4W6O7xJeYmoTx4XZ/+7WDxNfjuWd9vT/cc7DhGHWIzHlBX4ztepfvICHAP57skIAW0CXiC7Rawajwsejzf0fuWEwLKo2t3yfOY+BlDuSh9oSP4lDS6fz//Uu8ovaT6uPy276Db7FMDbp/GpMniqRcEhvwzWqmmoXxh5+a9vqWRZt1O7FH7Yn7TD7MurD7nQsusiSWhPxxtoT23DRVoF7h5xvvK+yVAWuOz6QBpc5YqFt0b2NQCrQjl/RITjocytMSvCn3m+VAyo3Zwb2guYL3ErzEpufHKArWi4I2tRkGZivk48bA4S65Uf5aLQv7birW1Sp+1xosCXMm1laVjU5BSEgrN252hJOit6Y6/YyCC2YmMovLCAOGR3yYjoxozuxv/axuW1/ym4y6KdaF/wvPx5iin55RitCjkQ0e2LCxa43ODex3tlpyw9JuaNHyWWZoSwy7LR2RfuB3z3qrSJQt53okvDkV16CjAM5FNR1xWW+bHMHUeyLCzZVfUEltCusMyPZTvvq49lmf+sfk1hqSzwbK4CNP9ZQbnjN5cFKCucC/SCOztE0sbzANv3wigosZVU4Vv4UX9FvKvMrTI7kLqAvo/uYnhtgKtFwdWRsyCvloRXmm0oCz+YwVd45z8EMKc8FxFMhltldnvHOFzTxIhByw1eLqVrn9FK6FQ/IZP8k8Tk/gQnZyxyBswh3wJusMYZZHgFPJJuGtMThivV6mW+bWhSFIsm4hJnLzx3jaZdAJe4kbOi9dQtMmWeE1itUx6yTvnaWuQuopdFypaQ5mTudcpm5yNtHeJKB2d75EC5vzh9UKThtl8rXPWQhh9voSNvPNbdCqbwJczSzrLi7J+kqMsZqMsV6oeinvdo5fJQZ7cJUtSvM1C/rlA/FPW8BxeWdmAZbyfKfW90MQygn0TAVygfgrIovrdwS2yUqhcjCD8RLnriXvpwIJcHZ95zZovwaPHrzIZnAyu4OWh4sZmrkvSTXnCzwjcnvrkjppaGL8cHjVxlFQMcvUFd4ZkHz9yn1ZeGJ2tbETzXFZ5vmiCJR1wiEupLR/qmdsW+pP88t59nxvmAs0OMOFsq+XwjnnmP7S0NT9YKDvCs5PONDowj2kdcPCUWz/jY9QrSt0Ca94iL0iDlr8orGrTJ6l6F6f6YyuIRzSIupuzCvAY9YJiKCV+gWaH6JlTlIxpHL5bU7A1Ua61N5zemdKVPLq85gyl+vMLyLVi2jmgY8Q8WYsGMz+UJAdUMtUI0P6J5Hb7lTUWrt1tKwLUh5rSPCni/hV9lzvEr0QsupMkK6+4t4wRXW0n5IXvRBa6PEL+8UUKpHO8YLVUs4XSzsLz1EcvjuRfKL/CoLeRP0MpFMWMGQQsVSik028QttdhtG6zEjv3gp/eVOIjkNN3F1v5bafGlg0iE883+IAfY8yukQfLE/wE= \ No newline at end of file +7V1bc5s6EP41nvacGWe4+ProS5KT5lI3zv2FkUHY1BhRwHHcX38kEBgs4ZAYSBvT0+mxBUaX79vValdoa/Jg8XLqAHt2iTRo1iRBe6nJw5okSYLYwP8jJeugRJTkVlAydQyNlm0KxsZvSAsFWro0NOgmbvQQMj3DThaqyLKg6iXKgOOgVfI2HZnJWm0whUzBWAUmW3pvaN6MdkwOu0Eu/AeN6SysutWkXZ4AdT510NKiFVrIgsGVBQifQzvpzoCGVrEi+bgmDxyEvODT4mUATTKw4ZDdn63vzYt56/TbD/cXuO2f31zd1YOHnbzlJ1HvHGh57370y83x7O723H5stO+vBw+P8sNoXpfps11vHY4l1PDQ0q/I8WZoiixgHm9K+/5wQfJYAX/b3HOBkI0LRVz4E3remvIELD2Ei2bewqRXdWR5A2QiB3/XoA6WJu5WH1paj3ABF05MpM6DohPDDH+WcRjCLqGlo9I+oZPe4PruuDs/n0izvm4cS8tHOlyCB5wp9HaMUYg/GZgY3egon0K0gJ6zxjc40ASe8ZzkJKDUnkb3bTDCHyhMfMh2NfsZmEta08hEngcmJmSwdFfGwgQWpGMewirj78A0phb+rOLBhBiI/jN0PAOLVI9e8AiYfXVmmNoFWKMlGSLXw+ISfuvPkGP8xo8FIUD4suNR1KVW4o4x+SVljANdfM8oxFGMii6A69F7VGSawHaNid9gcssC42RYfdxVtAgflCBiJJ9BUxw0j5SBTzpMpJB0NUnWAOzoanRn7EpL7cCJTq7Q0TtJ/vLE/4OvTx2gGXBD5fi1t3GVjD182UkuerVB4aeaWu7Q76uN2pMFWjaLazyJFKURklZ3jXUzsKaESGF9+GmJCsUGW6HY4lQotZLVARPTzAIe7BPQXEYMoq5mkoye0366tNvD++EveL+6UNXew5IjGQNldPH9RukNbs7ujvGlmtwjOh9PTbWBVOsJjMBgFLyYcJhQ91JFw7WBaljTC/+eYWNTck1HgRQh/Fvd9Gk5MzQNWj5tPRDIa0BcGxmW5w9Ts4//4lYNhKNmrYkbNMDfxc13/Jfc7mDKWZi3wPDJBbHYrCARnYRmrREmCEIKHXfqltfpuE6i/Br9Qhbtow25ylmU0kAf3/Suhr2L71dbwJMv+DbhxlmyCrPC/234Nz8c/04a/ne9i7Ohcnd2fD+OCGAaeJRCAvijPawosCcFOh9OgW4aBYbHJ73bixufBBXOe+IsiiUCLZz+VtpnsjtRLqbf759ajbnlRcbSBmfl2XCXGMHfcEvHf2KsNwumwpBulIj0+cuZcKyd/RTuvo+N6/6o/k3hrXEUGy9yFNeDtqJiA5IsWULEyWhVgO8FeLtEwBsr+eFy8nh/88NaPg6anU5TO62zVlwAOH76DJHVAsVaM9QK7D1NduGjJ2w5DW0Xeh6GYgM38WyMo8IK9n1gl0uEfXSPeu7L8vHXet62NeVBGMhXqUodrSxFN6ZLp5rEc12Zl4j301S6BfDX717917fz2XpxKa8nqXgbluEZvtGmVYDnCHi3RMCvZy3w8q1/10N3g+b66lu/3hN4gG/J9Qn9WgG9B9BymU63x9v5D/HJahjO+eLUPH+Gk58yx1pT/d6HMNsOsnF31l/x5yn0ArGntwwI9Ftlwj8HQol4ECbN9Z+VMun8KNMpx+UHu1D30dagBwxTMeEzNBmu4I8JuiRvxu3AnZJFglLouhf+3g/AdTGBeR2tRCFXUcjqnGzkIArc9rGqksHXNPwAbSw+zgYvXwF/gWH0Q/MU7Rs/EF8XGUbILCNkDvommEBzhFxsqCHyfCe4d4sVrwFf1ATYyDoBdvYHleuI5Bg6vlWrKESF2aleSRp4OAGmCw9I1Avjgdwob6I7fZxBfWjPruR6d+GI7mItWBwiRPNX6Mv4ilEW6nj6mgZDUfk0ciRAKyMBtjcj5EYA1tJxGQL4KiGLf6tSCPvyoZtxN0wefOA2WWb44M8LBP2AB3RBLPfoUlgeXvk7DsmyKG8bNyPrgknJb4b/s0NhIccCLWCDRNaoaR4W6PldQ7+t99zvL6Pb6fD8prcaPaXMUaGJAoiFx8xRlTtuf+CzrsLz0EXcMEtrx9xE4qgO8GCglKKvsYDqwaiBwgjQkcqzTrluGHYySjrjGLHHo3ZQoOfvcGiJGUHPQ+q5oDfSpT4A3Zf4pL/Wx/3ABL4A7OXOB2O/Yzka9zIycn9oO2gKwL7MlSh3tmc3QaY5mQMNkHA7V9N+btN+K+saNJdpf1jv3rycteFpWz/poqb8tOxzZoDAORksPRnhP4CYbBnbY9tSibhfXguCCZbtliSIP1D3h7rq/+Bofx05KlT06ddKqPcEt1miY4kLLmfvc4VuXuhm3f5aGLpslNCBugPdWdxziPzXWXu+b0YeVkGknF5fEUpcsXHBZ5fpSgL9CuE9EZZKXJdxbXNOvDgKCyiSxo8MFBISyPLB3kQMDi9IVcobc82scevu/oTkvm7BsSY2hJQrQh4aIbtyNkLmEaTiEnKnhrQqQh4YIbtyiYTkNpl1oixtDXgwMsj//ddW5ivgHADiJYfMu+2M4Odhr3FfP+VY5DH0I4stpgSSGuBP2618QFwtRTt1u+XZb1yCsv6CBEHliqAHTVBRyBqKzGP+5L/ju5uhVsXQA2dou0SGct1urIXnwAUe9pjLlbrhNk7X4MyoT45/yeaeKIol+ue4VGiyyirGBWLvfW7Eyzk+qFHiFgkuzOyGyATMcgVzHjC3PzpU2t4Ns1XBnAfMWU8byAPmseFpjYfb6yZanmrGUpjPpZc6e/Afgyo52Nlmh+BNJ7FGh1ZT4Grxw595J7SKQngma/hWCisQjQ5vpKQcTB3uULF7w7B1Hc3wfhdD6rR+LVEQjPNJRBDdFAluePJ3WCbGL4dbioJHTxJYhHeRCuvBY4jnVGzYL+wjLuAUkgO5e9GznO2n43GYcMqC/mw1hPlxlpLXRkbXkyPzWk9bvI7u7B+vL1jTWNzaaDtJTc508tVfuPj+8dinf9IbQHv7ai+4cOH/gwXRjNbEtYPhYIvSupW47Yx0znbQFJvdbqbH5lrkV4+lxND812JKbsA1BBrRIx7C/yzJ5o5ozALY30bQpOimIfVG/r1NKvKQw0RJovHA8xxjsvT8t6yxfpSE4LQ4Mr3nh9IVXBFOLiemoRLdvKn0JKguRGxC2mEsbBMuyJHq2pu1Up6AvhM+XhU7hzmmlKKaasTvmWjK1g35YOMDc2JYM+gY/nC/BtIMkL4b7jZMeBJ2YDos+UpCogsKM7a5oslrgvI2GaHsx5YrtoD8wQrH8yTe9j9HANghFd7T5SSvYt2//CA6pfQ9L8WatbH8ZVPs6JJMK6jVDI/sGC+ayGNWDiBlyVwOzHqm1RJIOZOsgY7NVvaHrVwPuv8n6kB8LbBzafH6cujjbPow9U7MqB9CG/qpFQRiu2xBxcmuEoMt7cCXEL+LrevRgTNZD6ZJZnLxHYvBWkKU3ozLq4lYKGZ1sRm+jEGXYnVJ5CTMaHKAa+7AjVY4QsEbM7S27lG3221F/7UTFYuScCQIsiA2O238b0vYyg4TJKuhT9wwg6mk2TjqNDpi+F8YKc9YS5Dq5vVaulsH5yBdd2HiJ5hKYB27g7oyUgdnO4sIFYuNAAQP3IjD29KB8CWE3eV2Fmh1IiK6gxZ/rpAIBykksnQkdxotQRbb5N9GITKyu5K3isg6Nsa7BCY3UrOhf4bFVdan1KxPekeFKjfr06TTbDTJAzlZnSL7ISUjVHH2ReRTfNWjyNt+ssXtvzrjE18a2G0GjDQc0PF6uzXGPkmdePTK4XQ9foPZyHyl4t6g4nRd4qs4rTVpNVt/qoqrdFyKOLC7Eyodl6Yy/hodx+5FqHRcrsk7/0QdV9lxaeLA7tmodFyayvgDddypZqrPyL576fy8X0hnz6I4452SPNqc9a6awPXdMP4xVFj3WBpwNJoThOzTIdeWlkpGFqPqrY9YL/WxRbBwo9+b/kmaAv5I/B+LCdS06HFkWzHnEWPo/8J0ET2nWa8vjbqrGkuDIeBGYYkpPux4ius8jLIom3DSuZ3YlcmQPslkKXVyYGmXT4ZiWUrqnWhXUIyGEm+nUHeHNykrEfXxw+Lkv7PF4/iXY3k3PX35cMsh4hCL8YiyAl/5OtGPnoFjoKV7dIGANgbPkN0jVs3HOc/HG3q/kmi7KKp2tzyfmbNpy13pE03JP6XB+fz0d72r/JRmo/rjqotu0pNp3zyOjpXBYy08OPjLYK2ahvqFkZe/fU8ly7qd2iX3nNnSDrMvqz7kQsvGReLQHo820B7bhou0Ctw3nPqadfdzUeCy8YEkuMolC2+N7GsAVoVy5hOjsr7KkAPK3BazInzI66V8QO1mfA0ph/USt8Gs5EZZZWxFwwNZC8/rJebr2MPmILFe+Ydg5PqvrXhrm7Rpe57I8S1NW1kZFjU5BSHnR7sztCKDFb7Bl+/BIbZiYyi8oIIonUPBiOjGlO7G/9rG9bX/yXnIwp1oX/C6fD7BlPxSRq8CDoR0++KCBa7Xv/b53tkpSo+JWRM8i4UZIeknz7uf8OWrwhYK4XLxw4xJNvTkY+jLp6KuKyyzY5n1zLfCsGSj6jEsoV1hmR3LrGcXFGb+s/o1gaWywKu5CtDsGZUznwFbFKCscC7QMx7sAEkbrwPspRccixJZSRW+uWfMzuNlZW6T2YnUBfSFdBfDawPcLAqujpwFebUk+KbZhrJY+iv4Cu/MeDczynMeh8twm8xu7xgFMU2MGLRc/+VSGvsMI6ET/Ygs8o9ii/sjXJwS5PSZQ34FXD/G6T/wEnik3DQmRwxXquhltm1oUnh+RaQ7MsZo2jlwiXuUVtiALTKl5pCt4pT7xClfi0XuInpRpGwJW5zMGqds7Yqp/3VxSq50cLZHDpS7s+N7RRpu+7WCqIc0/HyBjqwn6u9WMLmHMPPIdcNHnZ1gKepyCupyhfq+qGfNaFoc6uw2QYr6VQrqVxXq+6LeKRF1bj4z3k6Uu97F2dCHfhwCX6G8D8pi1jzVhQm3xJ5S9Wz4x0/EkpR+MpCLg7NR4iYjfpvZ89nAC9wkoV9s1qqk/KjnX6zwzYhv5lMWC8OX44NGrvISAfwZk8oWh2e3xPAQv82sbUXwXFd4vmuBlPlM4xzwFOorR/qmdsW+pD+d2vOpcTrg7BAjzpZKPt+JZ6PECBEXT9YK9vGs5POdDowS7SMunhKLpwdtxQHByWUVpG+GNGvi7cIgZYO4iSTrFarvQFUWSzSMHm/nP8Qnq2E454tT8/wZTn7KnNBtmHg5QtTPDvE5IeWch50R5XRIsyanyQPSZ0tq9gaqtdYms2tTutTH51ecuRTfXonne8SzVaJdxBVPNhBAvEYKWHoIa1+oepWUvk9Ks/p9C0OWsyAl+RtoePkA5LUAVBtiiUYSF1XWLUh2vVSo7oWq/NHeI5mdUqNsaQGgmqF+VkQLmFcbzRJtJH6bq1cMi8C1k9FeyuElQ36TOUmwwrcMSZcVNuZWRJZtW0kEg3rhF9weIXqDroBaOSEKWqtYQM7JoL51ifXxfLzFV1hqD/lesmJRTLU7abXNnN9YDStON43C/gpF1ZzquaI1F1NtimuF1hm9vJt3tdvL/wLZ9MkTyRY3c2Z174rvOEcKf3UQya2x2ZnqAHt2iTRI7vgf \ No newline at end of file diff --git a/doc/rtd/content/99_appendices/appendix2/sub/core/mlpro_bf/layer0_elementary/images/MLPro-BF-Plot_class_diagram.drawio.png b/doc/rtd/content/99_appendices/appendix2/sub/core/mlpro_bf/layer0_elementary/images/MLPro-BF-Plot_class_diagram.drawio.png index 082030af4..2e9433b72 100644 Binary files a/doc/rtd/content/99_appendices/appendix2/sub/core/mlpro_bf/layer0_elementary/images/MLPro-BF-Plot_class_diagram.drawio.png and b/doc/rtd/content/99_appendices/appendix2/sub/core/mlpro_bf/layer0_elementary/images/MLPro-BF-Plot_class_diagram.drawio.png differ diff --git a/src/mlpro/bf/math/geometry/hypercuboid.py b/src/mlpro/bf/math/geometry/hypercuboid.py index 984d142a9..48e410d0b 100644 --- a/src/mlpro/bf/math/geometry/hypercuboid.py +++ b/src/mlpro/bf/math/geometry/hypercuboid.py @@ -8,10 +8,11 @@ ## -- 2024-05-29 0.0.0 DA Creation ## -- 2024-06-03 1.0.0 DA First implementation ## -- 2024-06-05 1.0.1 DA Stabilization of Hypercuboid.set() +## -- 2024-06-26 1.1.0 DA Refactoring of attribute color ## ------------------------------------------------------------------------------------------------- """ -Ver. 1.0.1 (2024-06-05) +Ver. 1.1.0 (2024-06-26) This module provides a property class for the geometric shape 'hypercuboid'. @@ -79,7 +80,6 @@ def __init__( self, p_properties = p_properties, p_visualize = p_visualize ) - self.color = self.C_PLOT_COLOR self.alpha = self.C_PLOT_ALPHA self.fill = self.C_PLOT_FILL self.linewidth = self.C_PLOT_LINEWIDTH @@ -139,35 +139,40 @@ def _update_plot_2d(self, p_settings: PlotSettings, **p_kwargs): if self.value is None: return boundaries = self.value center_geo = self.center_geo.value + + + # 2 Determine the color of the cuboid + if self.color is None: self.color = self.C_PLOT_COLOR + color = self.color self.center_geo.color = self.color if self._plot_2d_rectangle is None: - # 2 Init all plot objects + # 3 Init all plot objects - # 2.1 Init 2d rectangle + # 3.1 Init 2d rectangle self._plot_2d_rectangle = Rectangle( xy = ( boundaries[0][0], boundaries[1][0] ), width = boundaries[0][1] - boundaries[0][0], height = boundaries[1][1] - boundaries[1][0], fill = self.fill, - edgecolor = self.color, - color = self.color, - facecolor = self.color, + edgecolor = color, + color = color, + facecolor = color, linewidth = self.linewidth, visible = True, alpha = self.alpha ) p_settings.axes.add_patch(self._plot_2d_rectangle) - # 2.2 Init 2d crosshair through the geometric center + # 3.2 Init 2d crosshair through the geometric center self._plot_line1 = p_settings.axes.plot( [ center_geo[0], center_geo[0] ], [ boundaries[1][0], boundaries[1][1] ], - color = self.color, + color = color, linestyle = 'dashed', lw = 0.5 )[0] self._plot_line2 = p_settings.axes.plot( [ boundaries[0][0], boundaries[0][1] ], [ center_geo[1], center_geo[1] ], - color = self.color, + color = color, linestyle = 'dashed', lw = 0.5 )[0] @@ -179,9 +184,9 @@ def _update_plot_2d(self, p_settings: PlotSettings, **p_kwargs): width = boundaries[0][1] - boundaries[0][0], height = boundaries[1][1] - boundaries[1][0] ) - self._plot_2d_rectangle.set( edgecolor = self.color, - facecolor = self.color, - color = self.color ) + self._plot_2d_rectangle.set( edgecolor = color, + facecolor = color, + color = color ) # 3.2 Update crosshair lines self._plot_line1.set_data( [ center_geo[0], center_geo[0] ], @@ -189,8 +194,8 @@ def _update_plot_2d(self, p_settings: PlotSettings, **p_kwargs): self._plot_line2.set_data( [ boundaries[0][0], boundaries[0][1] ], [ center_geo[1], center_geo[1] ] ) - self._plot_line1.set( color = self.color ) - self._plot_line2.set( color = self.color ) + self._plot_line1.set( color = color ) + self._plot_line2.set( color = color ) ## ------------------------------------------------------------------------------------------------- @@ -200,17 +205,22 @@ def _update_plot_3d(self, p_settings: PlotSettings, **p_kwargs): if self.value is None: return b = self.value center_geo = self.center_geo.value - self.center_geo.color = self.color + + # 2 Determine the color of the cuboid + if self.color is None: self.color = self.C_PLOT_COLOR + color = self.color + self.center_geo.color = self.color + if self._plot_3d_polycollection is None: - # 2 Init all plot objects + # 3 Init all plot objects - # 2.1 Init 3d cuboid + # 3.1 Init 3d cuboid self._plot_3d_polycollection = Poly3DCollection( verts= [], linewidths=self.linewidth, - edgecolors=self.color, - facecolors=self.color, + edgecolors=color, + facecolors=color, alpha = self.alpha ) self._plot_settings.axes.add_collection(self._plot_3d_polycollection) @@ -219,19 +229,19 @@ def _update_plot_3d(self, p_settings: PlotSettings, **p_kwargs): self._plot_line1 = p_settings.axes.plot( [ center_geo[0], center_geo[0] ], [ center_geo[1], center_geo[1] ], [ b[2][0], b[2][1] ], - color = self.color, + color = color, linestyle = 'dashed', lw = 0.5 )[0] self._plot_line2 = p_settings.axes.plot( [ center_geo[0], center_geo[0] ], [ b[1][0], b[1][1] ], [ center_geo[2], center_geo[2] ], - color = self.color, + color = color, linestyle = 'dashed', lw = 0.5 )[0] self._plot_line3 = p_settings.axes.plot( [ b[0][0], b[0][1] ], [ center_geo[1], center_geo[1] ], [ center_geo[2], center_geo[2] ], - color = self.color, + color = color, linestyle = 'dashed', lw = 0.5 )[0] @@ -247,9 +257,9 @@ def _update_plot_3d(self, p_settings: PlotSettings, **p_kwargs): [ center_geo[1], center_geo[1] ], [ center_geo[2], center_geo[2] ] ) - self._plot_line1.set( color = self.color ) - self._plot_line2.set( color = self.color ) - self._plot_line3.set( color = self.color ) + self._plot_line1.set( color = color ) + self._plot_line2.set( color = color ) + self._plot_line3.set( color = color ) # 4 Update the 3d cuboid @@ -285,8 +295,8 @@ def _update_plot_3d(self, p_settings: PlotSettings, **p_kwargs): self._plot_3d_polycollection.set_verts(verts) - self._plot_3d_polycollection.set( edgecolor = self.color, - facecolor = self.color ) + self._plot_3d_polycollection.set( edgecolor = color, + facecolor = color ) ## ------------------------------------------------------------------------------------------------- diff --git a/src/mlpro/bf/math/geometry/point.py b/src/mlpro/bf/math/geometry/point.py index d866d4775..7092e8050 100644 --- a/src/mlpro/bf/math/geometry/point.py +++ b/src/mlpro/bf/math/geometry/point.py @@ -19,10 +19,11 @@ ## -- 2024-05-31 1.7.1 DA Improved the stability of the plot methods ## -- 2024-06-03 1.8.0 DA Class Point: new attributes color, marker ## -- 2024-06-05 1.8.1 DA Bugfix in Point._remove_plot_2d() +## -- 2024-06-26 1.9.0 DA Refactoring ## ------------------------------------------------------------------------------------------------- """ -Ver. 1.8.1 (2024-06-05) +Ver. 1.9.0 (2024-06-26) This module provides a property class for the geometric shape 'point'. @@ -65,7 +66,6 @@ class Point (Property): def init_plot(self, p_figure: Figure = None, p_plot_settings: PlotSettings = None, **p_kwargs): self._plot_pos = None self._plot_vel = None - self.color = self.C_PLOT_COLOR self.marker = self.C_PLOT_MARKER super().init_plot(p_figure, p_plot_settings, **p_kwargs) @@ -80,10 +80,15 @@ def _update_plot_2d(self, p_settings: PlotSettings, **p_kwargs): if self._plot_pos is not None: self._plot_pos.remove() + if self.color is not None: + color = self.color + else: + color = self.C_PLOT_COLOR + self._plot_pos, = p_settings.axes.plot( point_pos[0], point_pos[1], marker=self.marker, - color=self.color, + color=color, linestyle='', markersize=3 ) @@ -100,7 +105,7 @@ def _update_plot_2d(self, p_settings: PlotSettings, **p_kwargs): point_pos[1], point_vel[0], point_vel[1], - color=self.color ) + color=color ) ## ------------------------------------------------------------------------------------------------- @@ -113,11 +118,16 @@ def _update_plot_3d(self, p_settings: PlotSettings, **p_kwargs): if self._plot_pos is not None: self._plot_pos.remove() + if self.color is not None: + color = self.color + else: + color = self.C_PLOT_COLOR + self._plot_pos, = p_settings.axes.plot( point_pos[0], point_pos[1], point_pos[2], marker=self.marker, - color=self.color, + color=color, linestyle='', markersize=3 ) @@ -140,7 +150,7 @@ def _update_plot_3d(self, p_settings: PlotSettings, **p_kwargs): np.array([point_vel[2]]), length = len, normalize = True, - color=self.color ) + color=color ) ## ------------------------------------------------------------------------------------------------- diff --git a/src/mlpro/bf/math/properties.py b/src/mlpro/bf/math/properties.py index 6e808737d..a80a0b911 100644 --- a/src/mlpro/bf/math/properties.py +++ b/src/mlpro/bf/math/properties.py @@ -33,10 +33,11 @@ ## -- 2024-06-05 1.1.0 DA New method Properties.replace_property() ## -- 2024-06-06 1.2.0 DA New custom method Properties._update_property_links() ## -- 2024-06-16 1.3.0 DA New method Properties.get_property_definitions() +## -- 2024-06-26 1.4.0 DA New method Properties.set_plot_color() ## ------------------------------------------------------------------------------------------------- """ -Ver. 1.3.0 (2024-06-16) +Ver. 1.4.0 (2024-06-26) This module provides a systematics for enriched managed properties. MLPro's enriched properties store any data like class attributes and they can be used like class attributes. They extend the @@ -428,16 +429,31 @@ def set_plot_settings(self, p_plot_settings : PlotSettings ): if not link: prop.set_plot_settings( p_plot_settings = p_plot_settings ) - + +## ------------------------------------------------------------------------------------------------- + def set_plot_color(self, p_color : str): + + Plottable.set_plot_color( self, p_color = p_color ) + + for (prop, link) in self.get_properties().values(): + if not link: + prop.set_plot_color( p_color = p_color ) + + ## ------------------------------------------------------------------------------------------------- def init_plot(self, p_figure: Figure = None, p_plot_settings: PlotSettings = None): if not self.get_visualization(): return Plottable.init_plot(self, p_figure = p_figure, p_plot_settings = p_plot_settings ) + try: + if not self._plot_initialized: return + except: + return for (prop, link) in self.get_properties().values(): - if not link: prop.init_plot( p_figure = self._figure, p_plot_settings = p_plot_settings) + if not link: + prop.init_plot( p_figure = self._figure, p_plot_settings = p_plot_settings) ## ------------------------------------------------------------------------------------------------- @@ -445,8 +461,11 @@ def update_plot( self, **p_kwargs ): if not self.get_visualization(): return + if ( self._plot_settings.detail_level > 0 ) and ( self._plot_settings.detail_level < self.plot_detail_level ): return + for (prop, link) in self.get_properties().values(): - if not link: prop.update_plot(**p_kwargs) + if not link: + prop.update_plot(**p_kwargs) Plottable.update_plot(self, **p_kwargs ) @@ -468,6 +487,9 @@ def renormalize(self, p_normalizer : Normalizer ): for (prop, link) in self.get_properties().values(): if not link: prop.renormalize( p_normalizer = p_normalizer ) + + color = property( fget = Plottable.get_plot_color, fset = set_plot_color ) + diff --git a/src/mlpro/bf/plot.py b/src/mlpro/bf/plot.py index 1ccb207ad..5a194ff35 100644 --- a/src/mlpro/bf/plot.py +++ b/src/mlpro/bf/plot.py @@ -43,10 +43,18 @@ ## -- 2024-05-22 2.13.0 DA New method PlotSettings.copy() ## -- 2024-06-04 2.13.1 DA/SK Turned on TKAgg for Mac ## -- 2024-06-24 2.14.0 DA New auto-managed attribute Plottable._plot_first_time : bool +## -- 2024-06-25 2.15.0 DA Class Plottable: +## -- - removed method set_plot_detail_level() +## -- - added methods assign_plot_detail_level(), +## -- get_plot_detail_level() and related property plot_detail_level +## -- - added new constant attribute C_PLOT_DETAIL_LEVEL +## -- 2024-06-26 2.16.0 DA - Refactoring, corrections, adjustments +## -- - New property Plottable.color +## -- - Class PlotSettings: removed parameter p_plot_depth ## ------------------------------------------------------------------------------------------------- """ -Ver. 2.14.0 (2024-06-24) +Ver. 2.16.0 (2024-06-26) This module provides various classes related to data plotting. @@ -105,9 +113,6 @@ class PlotSettings: p_plot_horizon : int Optional plot horizon for ND plot. A value > 0 limits the number of data entities shown in the plot. Default = 500. - p_plot_depth : int - Optional plot depth in case of hierarchical plotting. A value of 0 means that the plot - depth is unlimited. Default = 0. p_data_horizon : int Optional data horizon for ND plot. A value > 0 limits the number of data entities buffered internally for plotting. Default = 1000. @@ -139,7 +144,6 @@ def __init__( self, p_size_y : int = 1, p_step_rate : int = 1, p_plot_horizon : int = 500, - p_plot_depth : int = 0, p_data_horizon : int = 1000, p_detail_level : int = 0, p_force_fg : bool = True, @@ -157,7 +161,6 @@ def __init__( self, self.size_x = p_size_x self.size_y = p_size_y self.step_rate = p_step_rate - self.plot_depth = p_plot_depth self.detail_level = p_detail_level self.force_fg = p_force_fg self.id = p_id @@ -182,8 +185,8 @@ def copy(self): p_size_y = self.size_y, p_step_rate = self.step_rate, p_plot_horizon = self.plot_horizon, - p_plot_depth = self.plot_depth, p_data_horizon = self.data_horizon, + p_detail_level = self.detail_level, p_force_fg = self.force_fg, p_id = self.id, p_view_autoselect = self.view_autoselect, @@ -222,18 +225,30 @@ class Plottable: Custom list of views that are supported/implemented (see class PlotSettings) C_PLOT_DEFAULT_VIEW : str = '' Custom attribute for the default view. See class PlotSettings for more details. + C_PLOT_DETAIL_LEVEL : int = 0 + Custom attribute for the assigned detail level. See method assign_plot_detail_level() for + more details. + color : str + Plot color. See also: https://matplotlib.org/stable/gallery/color/named_colors.html + plot_detail_level : int + Own plot detail level. """ C_PLOT_ACTIVE : bool = False C_PLOT_STANDALONE : bool = True C_PLOT_VALID_VIEWS : list = [] C_PLOT_DEFAULT_VIEW : str = PlotSettings.C_VIEW_ND + C_PLOT_DETAIL_LEVEL : int = 0 ## ------------------------------------------------------------------------------------------------- def __init__(self, p_visualize:bool=False): - self._visualize = self.C_PLOT_ACTIVE and p_visualize + self._visualize = self.C_PLOT_ACTIVE and p_visualize self._plot_settings : PlotSettings = None - self._plot_first_time : bool = True + self.plot_detail_level = self.C_PLOT_DETAIL_LEVEL + self._plot_initialized : bool = False + self._plot_first_time : bool = True + self._plot_own_figure : bool = False + self._plot_color = None ## ------------------------------------------------------------------------------------------------- @@ -268,15 +283,12 @@ def set_plot_settings(self, p_plot_settings : PlotSettings ): raise ImplementationError('Please check attribute C_PLOT_DEFAULT_VIEW') self._plot_step_counter = 0 - self.set_plot_step_rate(p_step_rate=self._plot_settings.step_rate) - self.set_plot_detail_level(p_detail_level=self._plot_settings.detail_level) ## ------------------------------------------------------------------------------------------------- def init_plot( self, p_figure:Figure = None, - p_plot_settings : PlotSettings = None, - **p_kwargs): + p_plot_settings : PlotSettings = None ) -> bool: """ Initializes the plot functionalities of the class. @@ -286,6 +298,7 @@ def init_plot( self, Optional MatPlotLib host figure, where the plot shall be embedded. The default is None. p_plot_settings : PlotSettings Optional plot settings. If None, the default view is plotted (see attribute C_PLOT_DEFAULT_VIEW). + """ # 1 Plot functionality turned on? Initialization already called? @@ -294,6 +307,11 @@ def init_plot( self, except: return + try: + if ( p_plot_settings.detail_level > 0 ) and ( p_plot_settings.detail_level < self.plot_detail_level ): return + except: + self.plot_detail_level = self.C_PLOT_DETAIL_LEVEL + try: if self._plot_initialized: return except: @@ -320,7 +338,7 @@ def init_plot( self, else: self._figure : Figure = p_figure - + # 4 Call of all initialization methods of the required views view = self._plot_settings.view try: @@ -352,11 +370,44 @@ def get_visualization(self) -> bool: ## ------------------------------------------------------------------------------------------------- def set_plot_step_rate(self, p_step_rate:int): - if p_step_rate > 0: self._plot_step_rate = p_step_rate + if p_step_rate > 0: self._plot_settings.step_rate = p_step_rate ## ------------------------------------------------------------------------------------------------- - def set_plot_detail_level(self, p_detail_level:int): + def get_plot_color(self): + try: + return self._plot_color + except: + self._plot_color = None + return self._plot_color + + +## ------------------------------------------------------------------------------------------------- + def set_plot_color(self, p_color : str): + self._plot_color = p_color + + +## ------------------------------------------------------------------------------------------------- + def get_plot_detail_level(self) -> int: + try: + return self._plot_detail_level + except: + self.assign_plot_detail_level( p_detail_level = self.C_PLOT_DETAIL_LEVEL ) + return self._plot_detail_level + + +## ------------------------------------------------------------------------------------------------- + def assign_plot_detail_level(self, p_detail_level:int): + """ + Assigns an own plot detail level. Plots are carried out only, if the specified detail level + is less or equal to self._plot_settings.detail_level or self._plot_settings.detail_level = 0. + + Parameters + ---------- + p_detail_level : int + Integer detail level >=0 to be assigned. + """ + self._plot_detail_level = max(0, p_detail_level) @@ -519,17 +570,24 @@ def update_plot(self, **p_kwargs): except: return + # 1 Plot already initialized? try: if not self._plot_initialized: self.init_plot() except: self.init_plot() - # 2 Call of all required plot methods + + # 2 Check the assigned/required detail level + if ( self._plot_settings.detail_level > 0 ) and ( self._plot_settings.detail_level < self.plot_detail_level ): return + + + # 3 Call of all required plot methods view = self._plot_settings.view self._plot_methods[view][1](p_settings=self._plot_settings, **p_kwargs) - # 3 Update content of own(!) figure after self._plot_step_rate calls + + # 4 Update content of own(!) figure after self._plot_step_rate calls self.refresh_plot(p_force=False) @@ -594,7 +652,7 @@ def remove_plot(self, p_refresh:bool = True): # 1 Plot functionality turned on? try: - if ( not self.C_PLOT_ACTIVE ) or ( not self._visualize ): return + if not self._plot_initialized: return except: return @@ -635,6 +693,10 @@ def _remove_plot_nd(self): pass + color = property( fget = get_plot_color, fset = set_plot_color ) + plot_detail_level = property( fget = get_plot_detail_level, fset = assign_plot_detail_level ) + + diff --git a/src/mlpro/oa/streams/tasks/clusteranalyzers/clusters/basics.py b/src/mlpro/oa/streams/tasks/clusteranalyzers/clusters/basics.py index 0fb2a6bcf..4180b0fa4 100644 --- a/src/mlpro/oa/streams/tasks/clusteranalyzers/clusters/basics.py +++ b/src/mlpro/oa/streams/tasks/clusteranalyzers/clusters/basics.py @@ -104,6 +104,11 @@ def __init__( self, KWArgs.__init__( self, **p_kwargs ) Properties.__init__( self, p_properties = p_properties, p_visualize = p_visualize ) Id.__init__( self, p_id = p_id ) + + +## ------------------------------------------------------------------------------------------------- + def set_plot_color(self, p_color): + Properties.set_plot_color( self, p_color = p_color) ## ------------------------------------------------------------------------------------------------- @@ -144,4 +149,7 @@ def get_influence(self, p_inst : Instance ) -> float: A value 0 means that the cluster has no influence on the instance at all. """ - raise NotImplementedError \ No newline at end of file + raise NotImplementedError + + + color = property( fget = Properties.get_plot_color, fset = set_plot_color ) \ No newline at end of file diff --git a/src/mlpro/oa/streams/tasks/clusteranalyzers/clusters/properties/centroid.py b/src/mlpro/oa/streams/tasks/clusteranalyzers/clusters/properties/centroid.py index 7685fcdaa..76aea9e16 100644 --- a/src/mlpro/oa/streams/tasks/clusteranalyzers/clusters/properties/centroid.py +++ b/src/mlpro/oa/streams/tasks/clusteranalyzers/clusters/properties/centroid.py @@ -10,10 +10,11 @@ ## -- 2024-05-30 0.3.0 DA Global aliases: new boolean param ValuePrev ## -- 2024-05-31 0.4.0 DA Improved the stability of the plot methods ## -- 2024-06-13 0.5.0 DA New property definitions cprop_centroid_prev* +## -- 2024-06-26 0.6.0 DA Refactoring ## ------------------------------------------------------------------------------------------------- """ -Ver. 0.5.0 (2024-06-13) +Ver. 0.6.0 (2024-06-26) This module provides ... @@ -110,10 +111,16 @@ def _update_plot_2d(self, p_settings: PlotSettings, **p_kwargs): # 0 Intro if self.value is None: return - super()._update_plot_2d(p_settings, **p_kwargs) - # 1 Get coordinates + # 1 Plot the point + color = self.color + self.color = None + super()._update_plot_2d(p_settings, **p_kwargs) + self.color = color + + + # 2 Get line coordinates centroid = self.value ax_xlim = p_settings.axes.get_xlim() ax_ylim = p_settings.axes.get_ylim() @@ -121,12 +128,18 @@ def _update_plot_2d(self, p_settings: PlotSettings, **p_kwargs): ylim = [ min( ax_ylim[0], centroid[1] ), max(ax_ylim[1], centroid[1] ) ] - # 2 Plot a crosshair - if self._plot_line1 is None: - # 2.1 Add initial crosshair lines - cluster_id = self.id + # 3 Determine the color of the crosshair + cluster_id = self.id + if self.color is None: col_id = cluster_id % len(Cluster.C_CLUSTER_COLORS) color = Cluster.C_CLUSTER_COLORS[col_id] + else: + color = self.color + + + # 4 Plot a crosshair + if self._plot_line1 is None: + # 4.1 Add initial crosshair lines label = ' C' + str(cluster_id) + ' ' self._plot_line1 = p_settings.axes.plot( xlim, [centroid[1],centroid[1]], color=color, linestyle='dashed', lw=1, label=label)[0] self._plot_line2 = p_settings.axes.plot( [centroid[0],centroid[0]], ylim, color=color, linestyle='dashed', lw=1)[0] @@ -137,14 +150,16 @@ def _update_plot_2d(self, p_settings: PlotSettings, **p_kwargs): self._plot_line2_t2 = p_settings.axes.text(centroid[0], ylim[1], label, ha='center', va='bottom',color=color ) p_settings.axes.legend(title='Clusters', alignment='left', loc='upper right', shadow=True, draggable=True) else: - # 2.2 Update data of crosshair lines + # 4.2 Update data of crosshair lines self._plot_line1.set_data( xlim, [centroid[1],centroid[1]] ) + self._plot_line1.set_color( color ) self._plot_line2.set_data( [centroid[0],centroid[0]], ylim ) - self._plot_line1_t1.set(position=(centroid[0], centroid[1]) ) - self._plot_line1_t2.set(position=(xlim[0], centroid[1])) - self._plot_line1_t3.set(position=(xlim[1], centroid[1])) - self._plot_line2_t1.set(position=(centroid[0], ylim[0])) - self._plot_line2_t2.set(position=(centroid[0], ylim[1])) + self._plot_line2.set_color( color ) + self._plot_line1_t1.set(position=(centroid[0], centroid[1]), color=color) + self._plot_line1_t2.set(position=(xlim[0], centroid[1]), color=color) + self._plot_line1_t3.set(position=(xlim[1], centroid[1]), color=color) + self._plot_line2_t1.set(position=(centroid[0], ylim[0]), color=color) + self._plot_line2_t2.set(position=(centroid[0], ylim[1]), color=color) ## ------------------------------------------------------------------------------------------------- @@ -152,7 +167,13 @@ def _update_plot_3d(self, p_settings: PlotSettings, **p_kwargs): # 0 Intro if self.value is None: return - super()._update_plot_3d(p_settings, **p_kwargs) + + + # 1 Plot the point + color = self.color + self.color = None + super()._update_plot_3d(p_settings, **p_kwargs) + self.color = color # 1 Get coordinates @@ -179,14 +200,22 @@ def _update_plot_3d(self, p_settings: PlotSettings, **p_kwargs): l2_t1_ha='left' l3_t1_va='top' + + # 3 Determine the color of the crosshair + cluster_id = self.id + if self.color is None: + col_id = cluster_id % len(Cluster.C_CLUSTER_COLORS) + color = Cluster.C_CLUSTER_COLORS[col_id] + else: + color = self.color - # 3 Plot a crosshair with label texts + + # 4 Plot a crosshair with label texts if self._plot_line1 is None: - # 3.1 Add initial crosshair lines + # 4.1 Add initial crosshair lines cluster_id = self.get_id() - col_id = cluster_id % len(Cluster.C_CLUSTER_COLORS) - color = Cluster.C_CLUSTER_COLORS[col_id] + label = ' C' + str(cluster_id) + ' ' self._plot_line1 = p_settings.axes.plot( xlim, [centroid[1],centroid[1]], [centroid[2],centroid[2]], color=color, linestyle='dashed', lw=1, label=label)[0] self._plot_line2 = p_settings.axes.plot( [centroid[0],centroid[0]], ylim, [centroid[2],centroid[2]], color=color, linestyle='dashed', lw=1)[0] @@ -199,15 +228,18 @@ def _update_plot_3d(self, p_settings: PlotSettings, **p_kwargs): p_settings.axes.legend(title='Clusters', alignment='left', loc='right', shadow=True, draggable=True) else: - # 3.2 Update data of crosshair lines + # 4.2 Update data of crosshair lines self._plot_line1.set_data_3d( xlim, [centroid[1],centroid[1]], [centroid[2],centroid[2]] ) + self._plot_line1.set_color( color ) self._plot_line2.set_data_3d( [centroid[0],centroid[0]], ylim, [centroid[2],centroid[2]] ) + self._plot_line2.set_color( color ) self._plot_line3.set_data_3d( [centroid[0],centroid[0]], [centroid[1],centroid[1]], zlim ) + self._plot_line3.set_color( color ) - self._plot_line1_t1.set(position_3d=(centroid[0], centroid[1], centroid[2])) - self._plot_line1_t2.set(position_3d=(xlim[0], centroid[1], centroid[2]), ha=l1_t2_ha) - self._plot_line2_t1.set(position_3d=(centroid[0], ylim[0], centroid[2]), ha=l2_t1_ha) - self._plot_line3_t1.set(position_3d=(centroid[0], centroid[1], zlim[0]), va=l3_t1_va) + self._plot_line1_t1.set(position_3d=(centroid[0], centroid[1], centroid[2]), color=color) + self._plot_line1_t2.set(position_3d=(xlim[0], centroid[1], centroid[2]), ha=l1_t2_ha, color=color) + self._plot_line2_t1.set(position_3d=(centroid[0], ylim[0], centroid[2]), ha=l2_t1_ha, color=color) + self._plot_line3_t1.set(position_3d=(centroid[0], centroid[1], zlim[0]), va=l3_t1_va, color=color) ## ------------------------------------------------------------------------------------------------- diff --git a/test/howtos/bf/howto_bf_streams_111_stream_task_window_2d.py b/test/howtos/bf/howto_bf_streams_111_stream_task_window_2d.py index 5b3019065..74254a21a 100644 --- a/test/howtos/bf/howto_bf_streams_111_stream_task_window_2d.py +++ b/test/howtos/bf/howto_bf_streams_111_stream_task_window_2d.py @@ -116,7 +116,7 @@ def _setup(self, p_mode, p_visualize:bool, p_logging): if __name__ == '__main__': myscenario.init_plot( p_plot_settings=PlotSettings( p_view=PlotSettings.C_VIEW_ND, p_plot_horizon=100, - p_data_horizon=150) ) + p_data_horizon=150 ) ) input('Press ENTER to start stream processing...') myscenario.run()