kaxe 1.6.2.dev0__tar.gz → 1.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {kaxe-1.6.2.dev0/src/kaxe.egg-info → kaxe-1.7.0}/PKG-INFO +1 -1
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/pyproject.toml +1 -1
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/chart/bar.py +2 -2
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/chart/box.py +2 -2
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/chart/pie.py +2 -2
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/chart/qqplot.py +8 -7
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/core/__init__.py +1 -1
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/core/color.py +5 -9
- kaxe-1.7.0/src/kaxe/core/palette.py +42 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/core/styles.py +75 -40
- kaxe-1.7.0/src/kaxe/core/symbol.py +140 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/core/window.py +14 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/objects/d2/__init__.py +1 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/objects/d2/arrow.py +3 -1
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/objects/d2/equation.py +4 -3
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/objects/d2/fill.py +5 -8
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/objects/d2/function.py +5 -8
- kaxe-1.7.0/src/kaxe/objects/d2/guide_grid.py +266 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/objects/d2/parameter.py +7 -6
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/objects/d2/pillar.py +3 -3
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/objects/d2/point.py +3 -1
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/objects/text.py +3 -1
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/plot/zoom.py +1 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/project/__init__.py +0 -2
- {kaxe-1.6.2.dev0 → kaxe-1.7.0/src/kaxe.egg-info}/PKG-INFO +1 -1
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe.egg-info/SOURCES.txt +2 -4
- kaxe-1.6.2.dev0/src/kaxe/core/symbol.py +0 -60
- kaxe-1.6.2.dev0/src/kaxe/resources/symbolcross.png +0 -0
- kaxe-1.6.2.dev0/src/kaxe/resources/symboldonut.png +0 -0
- kaxe-1.6.2.dev0/src/kaxe/resources/symbollollipop.png +0 -0
- kaxe-1.6.2.dev0/src/kaxe/resources/symboltriangle.png +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/LICENSE +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/MANIFEST.in +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/README.md +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/setup.cfg +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/__init__.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/_require_3d.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/chart/__init__.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/core/axis.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/core/bounds.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/core/d3/backend.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/core/d3/camera.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/core/d3/helper.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/core/d3/hud.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/core/d3/objects/__init__.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/core/d3/objects/color.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/core/d3/objects/line.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/core/d3/objects/point.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/core/d3/objects/pointer.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/core/d3/objects/triangle.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/core/d3/openglrender.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/core/d3/translator.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/core/draw.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/core/fileloader.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/core/helper.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/core/ipython_display.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/core/legend.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/core/line.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/core/marker.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/core/profiler.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/core/progress.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/core/round.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/core/shapes.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/core/svg.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/core/svg_pdf.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/core/text.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/data/__init__.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/data/excel.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/objects/__init__.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/objects/_lazy.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/objects/d2/bubble.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/objects/d2/contour.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/objects/d2/inequality.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/objects/d2/map.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/objects/d3/__init__.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/objects/d3/base.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/objects/d3/function.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/objects/d3/mesh.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/objects/d3/point.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/objects/d3/potato.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/objects/function.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/objects/legend.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/objects/mapdata.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/objects/point.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/plot/__init__.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/plot/_lazy.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/plot/box.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/plot/constants.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/plot/d3/__init__.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/plot/d3/axes.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/plot/d3/geometry.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/plot/d3/plot3d.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/plot/d3/variants.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/plot/double.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/plot/empty.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/plot/grid.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/plot/log.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/plot/polar.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/plot/standard.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/plot/themes.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/plot/zoom_connector.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/project/codec.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/project/context.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/project/document.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/project/registry.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/project/sample.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/project/sampled_curve.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/project/serializers.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/project/window.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/resources/__init__.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/resources/computer-modern-family/__init__.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/resources/computer-modern-family/cmu.bright-oblique.ttf +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/resources/computer-modern-family/cmu.bright-roman.ttf +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/resources/computer-modern-family/cmu.bright-semibold.ttf +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/resources/computer-modern-family/cmu.bright-semiboldoblique.ttf +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/resources/computer-modern-family/cmu.classical-serif-italic.ttf +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/resources/computer-modern-family/cmu.concrete-bold.ttf +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/resources/computer-modern-family/cmu.concrete-bolditalic.ttf +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/resources/computer-modern-family/cmu.concrete-italic.ttf +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/resources/computer-modern-family/cmu.concrete-roman.ttf +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/resources/computer-modern-family/cmu.sans-serif-bold.ttf +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/resources/computer-modern-family/cmu.sans-serif-boldoblique.ttf +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/resources/computer-modern-family/cmu.sans-serif-demi-condensed-demicondensed.ttf +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/resources/computer-modern-family/cmu.sans-serif-medium.ttf +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/resources/computer-modern-family/cmu.sans-serif-oblique.ttf +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/resources/computer-modern-family/cmu.serif-bold.ttf +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/resources/computer-modern-family/cmu.serif-bolditalic.ttf +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/resources/computer-modern-family/cmu.serif-extra-boldslanted.ttf +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/resources/computer-modern-family/cmu.serif-extra-romanslanted.ttf +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/resources/computer-modern-family/cmu.serif-italic.ttf +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/resources/computer-modern-family/cmu.serif-roman.ttf +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/resources/computer-modern-family/cmu.serif-upright-italic-uprightitalic.ttf +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/resources/computer-modern-family/cmu.typewriter-text-bold.ttf +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/resources/computer-modern-family/cmu.typewriter-text-bolditalic.ttf +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/resources/computer-modern-family/cmu.typewriter-text-italic.ttf +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/resources/computer-modern-family/cmu.typewriter-text-light.ttf +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/resources/computer-modern-family/cmu.typewriter-text-lightoblique.ttf +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/resources/computer-modern-family/cmu.typewriter-text-regular.ttf +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/resources/computer-modern-family/cmu.typewriter-text-variable-width-italic.ttf +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/resources/computer-modern-family/cmu.typewriter-text-variable-width-medium.ttf +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/resources/computer-modern-family/readme.txt +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe/resources/logo-small.png +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe.egg-info/dependency_links.txt +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe.egg-info/requires.txt +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/src/kaxe.egg-info/top_level.txt +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/tests/test.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/tests/test2.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/tests/test3.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/tests/test_4.py +0 -0
- {kaxe-1.6.2.dev0 → kaxe-1.7.0}/tests/test_5.py +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
from ..core.helper import *
|
|
3
3
|
from ..core.axis import *
|
|
4
|
-
from ..core.styles import
|
|
4
|
+
from ..core.styles import isLightOrDark
|
|
5
5
|
from ..core.symbol import symbol
|
|
6
6
|
from ..core.window import Window
|
|
7
7
|
from ..objects.d2.pillar import Pillars
|
|
@@ -90,7 +90,7 @@ class Bar(Window):
|
|
|
90
90
|
def __getColors__(self):
|
|
91
91
|
self.colors = self.getAttr('barColor')
|
|
92
92
|
if self.colors == None:
|
|
93
|
-
self.colors = [
|
|
93
|
+
self.colors = [self.nextSeriesColor() for _ in range(self.maxNumberAmount)]
|
|
94
94
|
elif type(self.colors[0]) is int:
|
|
95
95
|
self.colors = [self.colors]
|
|
96
96
|
|
|
@@ -4,7 +4,7 @@ from ..core.helper import *
|
|
|
4
4
|
import logging
|
|
5
5
|
from ..core.axis import *
|
|
6
6
|
from ..plot.zoom_connector import compute_boxplot_whiskers
|
|
7
|
-
from ..core.styles import
|
|
7
|
+
from ..core.styles import isLightOrDark
|
|
8
8
|
from ..core.symbol import symbol as symbols
|
|
9
9
|
from ..core.symbol import makeSymbolShapes
|
|
10
10
|
from ..core.window import Window
|
|
@@ -195,7 +195,7 @@ class BoxPlot(Window):
|
|
|
195
195
|
"""
|
|
196
196
|
|
|
197
197
|
if color is None:
|
|
198
|
-
color =
|
|
198
|
+
color = self.nextSeriesColor()
|
|
199
199
|
|
|
200
200
|
self.boxplots.append({"data": data, "color": color, "symbol": symbol})
|
|
201
201
|
|
|
@@ -7,7 +7,7 @@ from ..core.helper import *
|
|
|
7
7
|
import logging
|
|
8
8
|
from ..core.axis import *
|
|
9
9
|
from ..core.window import Window
|
|
10
|
-
from ..core.styles import
|
|
10
|
+
from ..core.styles import isLightOrDark
|
|
11
11
|
from ..core.symbol import symbol
|
|
12
12
|
|
|
13
13
|
XYPLOT = 'xy'
|
|
@@ -135,7 +135,7 @@ class Pie(Window):
|
|
|
135
135
|
|
|
136
136
|
colors = self.getAttr('pieColor')
|
|
137
137
|
if colors == None:
|
|
138
|
-
colors = [
|
|
138
|
+
colors = [self.nextSeriesColor() for _ in range(self.pieslices)]
|
|
139
139
|
elif type(colors[0]) is int:
|
|
140
140
|
colors = [colors]
|
|
141
141
|
|
|
@@ -4,7 +4,6 @@ import numpy as np
|
|
|
4
4
|
import statistics
|
|
5
5
|
from ..objects.point import Points2D
|
|
6
6
|
from ..objects.function import Function2D
|
|
7
|
-
from ..core.styles import getRandomColor
|
|
8
7
|
from ..core.symbol import symbol
|
|
9
8
|
|
|
10
9
|
|
|
@@ -40,12 +39,7 @@ class QQPlot(BoxedPlot):
|
|
|
40
39
|
def __init__(self, data, quantiles:list=None, color:list=[None, None], size=50):
|
|
41
40
|
|
|
42
41
|
self.size = size
|
|
43
|
-
|
|
44
|
-
self.color = color
|
|
45
|
-
if color[0] is None:
|
|
46
|
-
self.color[0] = getRandomColor()
|
|
47
|
-
if color[1] is None:
|
|
48
|
-
self.color[1] = getRandomColor()
|
|
42
|
+
self._pending_colors = list(color)
|
|
49
43
|
|
|
50
44
|
data = sorted(data)
|
|
51
45
|
|
|
@@ -57,6 +51,13 @@ class QQPlot(BoxedPlot):
|
|
|
57
51
|
|
|
58
52
|
super().__init__()
|
|
59
53
|
|
|
54
|
+
self.color = self._pending_colors
|
|
55
|
+
if self.color[0] is None:
|
|
56
|
+
self.color[0] = self.nextSeriesColor()
|
|
57
|
+
if self.color[1] is None:
|
|
58
|
+
self.color[1] = self.nextSeriesColor()
|
|
59
|
+
del self._pending_colors
|
|
60
|
+
|
|
60
61
|
points = self.points = self.add(Points2D(
|
|
61
62
|
self.quantiles,
|
|
62
63
|
self.data,
|
|
@@ -231,6 +231,9 @@ class SingleColormap(Colormap):
|
|
|
231
231
|
super().__init__(arr)
|
|
232
232
|
|
|
233
233
|
|
|
234
|
+
from .palette import DEFAULT_SEQUENTIAL_STEPS
|
|
235
|
+
|
|
236
|
+
|
|
234
237
|
class Colormaps:
|
|
235
238
|
"""
|
|
236
239
|
A collection of predefined colormaps for various color schemes.
|
|
@@ -238,7 +241,7 @@ class Colormaps:
|
|
|
238
241
|
Attributes
|
|
239
242
|
----------
|
|
240
243
|
standard : Colormap
|
|
241
|
-
|
|
244
|
+
Default sequential colormap (blue to green, colorblind-safe).
|
|
242
245
|
green : Colormap
|
|
243
246
|
A colormap with various shades of green.
|
|
244
247
|
brown : Colormap
|
|
@@ -254,14 +257,7 @@ class Colormaps:
|
|
|
254
257
|
"""
|
|
255
258
|
|
|
256
259
|
|
|
257
|
-
standard = Colormap(
|
|
258
|
-
"#AFE3C0",
|
|
259
|
-
"#90C290",
|
|
260
|
-
"#FF5154",
|
|
261
|
-
"#91A6FF",
|
|
262
|
-
"#FAFF7F",
|
|
263
|
-
"#ED7D3A",
|
|
264
|
-
])
|
|
260
|
+
standard = Colormap(DEFAULT_SEQUENTIAL_STEPS)
|
|
265
261
|
green = Colormap([
|
|
266
262
|
"#004b23",
|
|
267
263
|
"#006400",
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""Default color palettes for Kaxe figures.
|
|
2
|
+
|
|
3
|
+
Series colors follow the Okabe–Ito palette (colorblind-safe, common in
|
|
4
|
+
publication figures). See: https://jfly.uni-koeln.de/color/
|
|
5
|
+
|
|
6
|
+
Pure black is omitted from the series cycle; it remains reserved for axes,
|
|
7
|
+
ticks, and text ink.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from .color import to_rgba
|
|
13
|
+
|
|
14
|
+
# Okabe–Ito categorical series (7 colors; black excluded from data series).
|
|
15
|
+
OKABE_ITO_SERIES = [
|
|
16
|
+
"#E69F00", # orange
|
|
17
|
+
"#56B4E9", # sky blue
|
|
18
|
+
"#009E73", # bluish green
|
|
19
|
+
"#F0E442", # yellow
|
|
20
|
+
"#0072B2", # blue
|
|
21
|
+
"#D55E00", # vermillion
|
|
22
|
+
"#CC79A7", # reddish purple
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
# Sequential ramp for heatmaps, contours, and color scales (blue → green).
|
|
26
|
+
DEFAULT_SEQUENTIAL_STEPS = [
|
|
27
|
+
"#0072B2",
|
|
28
|
+
"#2088A8",
|
|
29
|
+
"#329E96",
|
|
30
|
+
"#009E73",
|
|
31
|
+
"#3CB371",
|
|
32
|
+
"#56B4E9",
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
DEFAULT_SERIES_COLORS = [to_rgba(c) for c in OKABE_ITO_SERIES]
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def apply_series_palette(color_list: list | None = None) -> list[tuple[int, int, int, int]]:
|
|
39
|
+
"""Normalize a color list to RGBA tuples, or return the default series palette."""
|
|
40
|
+
if color_list is None:
|
|
41
|
+
return list(DEFAULT_SERIES_COLORS)
|
|
42
|
+
return [to_rgba(c) for c in color_list]
|
|
@@ -4,41 +4,95 @@ from types import MappingProxyType, FunctionType
|
|
|
4
4
|
import math
|
|
5
5
|
|
|
6
6
|
from .color import is_color_attr
|
|
7
|
+
from .palette import DEFAULT_SERIES_COLORS, apply_series_palette
|
|
7
8
|
|
|
8
9
|
# COLORS
|
|
9
10
|
WHITE = (255,255,255,255)
|
|
10
11
|
BLACK = (0,0,0,255)
|
|
11
12
|
|
|
12
13
|
colorNum = -1
|
|
14
|
+
colors = list(DEFAULT_SERIES_COLORS)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _series_palette() -> list:
|
|
18
|
+
return colors
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _palette_color_at(index: int) -> tuple:
|
|
22
|
+
palette = _series_palette()
|
|
23
|
+
return palette[index % len(palette)]
|
|
24
|
+
|
|
25
|
+
|
|
13
26
|
def getRandomColor() -> tuple:
|
|
14
|
-
"""Return the next color from Kaxe's default
|
|
27
|
+
"""Return the next color from Kaxe's default series palette.
|
|
15
28
|
|
|
16
|
-
Colors rotate through the built-in palette.
|
|
17
|
-
|
|
29
|
+
Colors rotate through the built-in Okabe–Ito palette. Each plot window
|
|
30
|
+
maintains its own cycle for objects added without an explicit color; this
|
|
31
|
+
global function is for manual use (e.g. ``color=kaxe.getRandomColor()``).
|
|
32
|
+
Call :func:`resetColor` to restart the global cycle manually.
|
|
18
33
|
|
|
19
34
|
Returns
|
|
20
35
|
-------
|
|
21
36
|
tuple
|
|
22
|
-
RGBA color tuple, e.g. ``(
|
|
37
|
+
RGBA color tuple, e.g. ``(230, 159, 0, 255)``.
|
|
23
38
|
"""
|
|
24
39
|
global colorNum
|
|
25
|
-
colorNum+=1
|
|
26
|
-
return
|
|
40
|
+
colorNum += 1
|
|
41
|
+
return _palette_color_at(colorNum)
|
|
42
|
+
|
|
27
43
|
|
|
28
44
|
def resetColor() -> None:
|
|
29
|
-
"""
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
resetting any color-related state that depends on this variable.
|
|
45
|
+
"""Reset the global series color cycle to before the first palette color."""
|
|
46
|
+
global colorNum
|
|
47
|
+
colorNum = -1
|
|
33
48
|
|
|
34
|
-
Note
|
|
35
|
-
----
|
|
36
|
-
This resets all plot color progress
|
|
37
49
|
|
|
38
|
-
|
|
50
|
+
def _apply_function2d_color(obj, color: tuple) -> None:
|
|
51
|
+
from .color import to_rgba
|
|
52
|
+
obj.color = to_rgba(color)
|
|
53
|
+
obj.legendColor = obj.color
|
|
54
|
+
if len(obj.color) > 3:
|
|
55
|
+
obj.fillcolor = (*obj.color[:3], int(obj.color[3] * 0.5))
|
|
56
|
+
else:
|
|
57
|
+
obj.fillcolor = (*obj.color, 175)
|
|
39
58
|
|
|
40
|
-
|
|
41
|
-
|
|
59
|
+
|
|
60
|
+
def _apply_fill_color(obj, color: tuple) -> None:
|
|
61
|
+
from .color import to_rgba
|
|
62
|
+
rgba = list(to_rgba(color))
|
|
63
|
+
if len(rgba) > 3:
|
|
64
|
+
rgba[3] = 100
|
|
65
|
+
else:
|
|
66
|
+
rgba.append(100)
|
|
67
|
+
obj.color = tuple(rgba)
|
|
68
|
+
obj.legendColor = obj.color
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def assign_series_color(plot, obj) -> None:
|
|
72
|
+
"""Assign the next series palette color from *plot* when the object defers color."""
|
|
73
|
+
if getattr(obj, 'randomColor', False):
|
|
74
|
+
count = getattr(obj, '_autoColorCount', 1)
|
|
75
|
+
obj.color = [plot.nextSeriesColor() for _ in range(count)]
|
|
76
|
+
obj.legendColor = obj.color[0]
|
|
77
|
+
obj.randomColor = False
|
|
78
|
+
return
|
|
79
|
+
|
|
80
|
+
if not getattr(obj, '_autoSeriesColor', False):
|
|
81
|
+
return
|
|
82
|
+
|
|
83
|
+
color = plot.nextSeriesColor()
|
|
84
|
+
obj._autoSeriesColor = False
|
|
85
|
+
|
|
86
|
+
if type(obj).__name__ == 'Function2D':
|
|
87
|
+
_apply_function2d_color(obj, color)
|
|
88
|
+
elif type(obj).__name__ == 'Fill':
|
|
89
|
+
_apply_fill_color(obj, color)
|
|
90
|
+
else:
|
|
91
|
+
from .color import Colormap, to_rgba
|
|
92
|
+
obj.color = to_rgba(color)
|
|
93
|
+
obj.legendColor = obj.color
|
|
94
|
+
if type(obj.color) is Colormap:
|
|
95
|
+
obj.legendColor = obj.color.getColor(0, 1, 2)
|
|
42
96
|
|
|
43
97
|
|
|
44
98
|
def isLightOrDark(rgbColor=[0,128,255,255]):
|
|
@@ -49,36 +103,17 @@ def isLightOrDark(rgbColor=[0,128,255,255]):
|
|
|
49
103
|
return False
|
|
50
104
|
|
|
51
105
|
|
|
52
|
-
colors = [
|
|
53
|
-
(222,107,72, 255),
|
|
54
|
-
(91,200,175, 255),
|
|
55
|
-
(6,71,137, 255),
|
|
56
|
-
(8,45,15, 255),
|
|
57
|
-
# (247,197,72, 255),
|
|
58
|
-
(251, 111, 146),
|
|
59
|
-
(0, 53,102),
|
|
60
|
-
(188, 108,37),
|
|
61
|
-
(33, 104, 105),
|
|
62
|
-
]
|
|
63
|
-
|
|
64
106
|
def setDefaultColors(colorList:list):
|
|
65
|
-
"""
|
|
66
|
-
|
|
67
|
-
|
|
107
|
+
"""Replace the global default series palette.
|
|
108
|
+
|
|
68
109
|
Parameters
|
|
69
110
|
----------
|
|
70
111
|
colorList : list
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
Notes
|
|
75
|
-
-----
|
|
76
|
-
This function sets the global variable `colors` to the provided list of colors.
|
|
112
|
+
Colors for the series cycle. Entries may be RGBA tuples or hex/named
|
|
113
|
+
color strings (see :func:`kaxe.to_rgba`).
|
|
77
114
|
"""
|
|
78
|
-
from .color import to_rgba
|
|
79
|
-
|
|
80
115
|
global colors
|
|
81
|
-
colors =
|
|
116
|
+
colors = apply_series_palette(colorList)
|
|
82
117
|
|
|
83
118
|
|
|
84
119
|
class bcolors:
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
|
|
2
|
+
import math
|
|
3
|
+
|
|
4
|
+
from .shapes import Batch, Line, Shape, shapes
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class SymbolGroup(Shape):
|
|
8
|
+
"""Composite symbol built from shapes in a size×size local box."""
|
|
9
|
+
|
|
10
|
+
def __init__(self, size: int, parts: list, batch: Batch = None):
|
|
11
|
+
self.size = int(size)
|
|
12
|
+
self.parts = parts
|
|
13
|
+
self.x = 0
|
|
14
|
+
self.y = 0
|
|
15
|
+
self.batch = batch
|
|
16
|
+
super().__init__()
|
|
17
|
+
if batch:
|
|
18
|
+
batch.add(self)
|
|
19
|
+
|
|
20
|
+
def getBoundingBox(self):
|
|
21
|
+
return [self.size, self.size]
|
|
22
|
+
|
|
23
|
+
def centerAlign(self):
|
|
24
|
+
self.x -= self.size / 2
|
|
25
|
+
self.y -= self.size / 2
|
|
26
|
+
|
|
27
|
+
def push(self, x, y):
|
|
28
|
+
self.x += x
|
|
29
|
+
self.y += y
|
|
30
|
+
|
|
31
|
+
def _offset_part(self, part, dx, dy):
|
|
32
|
+
if isinstance(part, Line):
|
|
33
|
+
part.push(dx, dy)
|
|
34
|
+
else:
|
|
35
|
+
part.x += dx
|
|
36
|
+
part.y += dy
|
|
37
|
+
|
|
38
|
+
def _restore_part(self, part, dx, dy):
|
|
39
|
+
if isinstance(part, Line):
|
|
40
|
+
part.push(-dx, -dy)
|
|
41
|
+
else:
|
|
42
|
+
part.x -= dx
|
|
43
|
+
part.y -= dy
|
|
44
|
+
|
|
45
|
+
def _draw_parts(self, draw_fn):
|
|
46
|
+
for part in self.parts:
|
|
47
|
+
self._offset_part(part, self.x, self.y)
|
|
48
|
+
draw_fn(part)
|
|
49
|
+
self._restore_part(part, self.x, self.y)
|
|
50
|
+
|
|
51
|
+
def drawPillow(self, surface):
|
|
52
|
+
self._draw_parts(lambda part: part.drawPillow(surface))
|
|
53
|
+
|
|
54
|
+
def drawSvg(self, doc):
|
|
55
|
+
self._draw_parts(lambda part: part.drawSvg(doc))
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
# SYMBOLS
|
|
59
|
+
class symbol:
|
|
60
|
+
CIRCLE = 'o'
|
|
61
|
+
LINE = 'LINE'
|
|
62
|
+
TRIANGLE = 'TRI'
|
|
63
|
+
STAR = 'STAR'
|
|
64
|
+
RECTANGLE = "RECT"
|
|
65
|
+
LOLLIPOP = 'LOLLIPOP'
|
|
66
|
+
THICKLINE = 'THICKLINE'
|
|
67
|
+
CROSS = "CROSS"
|
|
68
|
+
DONUT = "DONUT"
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _triangle_symbol(size: int, color: tuple, batch: Batch):
|
|
72
|
+
return SymbolGroup(
|
|
73
|
+
size,
|
|
74
|
+
[shapes.Polygon((size / 2, 0), (0, size), (size, size), color=color, batch=None)],
|
|
75
|
+
batch=batch,
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _star_symbol(size: int, color: tuple, batch: Batch):
|
|
80
|
+
cx = cy = size / 2
|
|
81
|
+
outer_r = size / 2
|
|
82
|
+
inner_r = outer_r * 0.4
|
|
83
|
+
points = []
|
|
84
|
+
for i in range(10):
|
|
85
|
+
angle = math.pi / 2 + i * math.pi / 5
|
|
86
|
+
radius = outer_r if i % 2 == 0 else inner_r
|
|
87
|
+
points.append((cx + radius * math.cos(angle), cy - radius * math.sin(angle)))
|
|
88
|
+
return SymbolGroup(size, [shapes.Polygon(*points, color=color, batch=None)], batch=batch)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def _cross_symbol(size: int, color: tuple, batch: Batch):
|
|
92
|
+
thickness = max(1, int(size / 6))
|
|
93
|
+
parts = [
|
|
94
|
+
Line(0, 0, size, size, color=color, width=thickness, batch=None),
|
|
95
|
+
Line(size, 0, 0, size, color=color, width=thickness, batch=None),
|
|
96
|
+
]
|
|
97
|
+
return SymbolGroup(size, parts, batch=batch)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _lollipop_symbol(size: int, color: tuple, batch: Batch):
|
|
101
|
+
stem_h = max(1, size // 4)
|
|
102
|
+
stem_y = (size - stem_h) // 2
|
|
103
|
+
head_r = max(1, size // 3)
|
|
104
|
+
stem_w = max(1, size - head_r)
|
|
105
|
+
parts = [
|
|
106
|
+
shapes.Rectangle(0, stem_y, stem_w, stem_h, color=color, batch=None),
|
|
107
|
+
shapes.Circle(size - head_r, size // 2, head_r, color=color, batch=None, cornerAlign=False),
|
|
108
|
+
]
|
|
109
|
+
return SymbolGroup(size, parts, batch=batch)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def makeSymbolShapes(symb: str, height: int, color: tuple, batch):
|
|
113
|
+
size = int(height)
|
|
114
|
+
if symb == symbol.LINE:
|
|
115
|
+
return shapes.Rectangle(0, 0, size, size / 6, color=color, batch=batch)
|
|
116
|
+
if symb == symbol.THICKLINE:
|
|
117
|
+
return shapes.Rectangle(0, 0, size, size / 2, color=color, batch=batch)
|
|
118
|
+
if symb == symbol.RECTANGLE:
|
|
119
|
+
return shapes.Rectangle(0, 0, size, size, color=color, batch=batch)
|
|
120
|
+
if symb == symbol.CIRCLE:
|
|
121
|
+
return shapes.Circle(0, 0, int(size / 2), cornerAlign=True, color=color, batch=batch)
|
|
122
|
+
if symb == symbol.TRIANGLE:
|
|
123
|
+
return _triangle_symbol(size, color, batch)
|
|
124
|
+
if symb == symbol.STAR:
|
|
125
|
+
return _star_symbol(size, color, batch)
|
|
126
|
+
if symb == symbol.LOLLIPOP:
|
|
127
|
+
return _lollipop_symbol(size, color, batch)
|
|
128
|
+
if symb == symbol.CROSS:
|
|
129
|
+
return _cross_symbol(size, color, batch)
|
|
130
|
+
if symb == symbol.DONUT:
|
|
131
|
+
return shapes.Circle(
|
|
132
|
+
0,
|
|
133
|
+
0,
|
|
134
|
+
int(size / 2),
|
|
135
|
+
cornerAlign=True,
|
|
136
|
+
fill=False,
|
|
137
|
+
width=max(1, size // 8),
|
|
138
|
+
color=color,
|
|
139
|
+
batch=batch,
|
|
140
|
+
)
|
|
@@ -10,6 +10,7 @@ from .shapes import shapes
|
|
|
10
10
|
from .svg import SvgDocument, infer_format, is_file_path
|
|
11
11
|
from .progress import make_progress_bar
|
|
12
12
|
from .ipython_display import display_png_bytes, is_notebook, to_png_bytes
|
|
13
|
+
from .styles import assign_series_color, _palette_color_at
|
|
13
14
|
from PIL import Image
|
|
14
15
|
|
|
15
16
|
|
|
@@ -112,6 +113,7 @@ class Window(AttrObject):
|
|
|
112
113
|
bottom to top is always positive
|
|
113
114
|
"""
|
|
114
115
|
super().__init__()
|
|
116
|
+
self._seriesColorNum = -1
|
|
115
117
|
self.identity = None
|
|
116
118
|
|
|
117
119
|
self.attrmap = AttrMap()
|
|
@@ -486,6 +488,7 @@ class Window(AttrObject):
|
|
|
486
488
|
|
|
487
489
|
# enables this code to be manipulated with in other subclasses
|
|
488
490
|
def __callFinalizeObject__(self, obj):
|
|
491
|
+
self._assignSeriesColor(obj)
|
|
489
492
|
obj.finalize(self)
|
|
490
493
|
|
|
491
494
|
def __addInnerContent__(self):
|
|
@@ -674,6 +677,16 @@ class Window(AttrObject):
|
|
|
674
677
|
def addDrawingFunction(self, shape, z=0):
|
|
675
678
|
self.shapes.append((shape, z))
|
|
676
679
|
|
|
680
|
+
def nextSeriesColor(self) -> tuple:
|
|
681
|
+
self._seriesColorNum += 1
|
|
682
|
+
return _palette_color_at(self._seriesColorNum)
|
|
683
|
+
|
|
684
|
+
def resetSeriesColors(self) -> None:
|
|
685
|
+
self._seriesColorNum = -1
|
|
686
|
+
|
|
687
|
+
def _assignSeriesColor(self, obj) -> None:
|
|
688
|
+
assign_series_color(self, obj)
|
|
689
|
+
|
|
677
690
|
# api
|
|
678
691
|
def add(self, obj):
|
|
679
692
|
"""
|
|
@@ -691,6 +704,7 @@ class Window(AttrObject):
|
|
|
691
704
|
"""
|
|
692
705
|
|
|
693
706
|
if self.identity in obj.supports:
|
|
707
|
+
self._assignSeriesColor(obj)
|
|
694
708
|
self.objects.append(obj)
|
|
695
709
|
else:
|
|
696
710
|
logging.error(f'{obj}, is not supported in {self}')
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
|
|
2
2
|
from ...core.shapes import shapes
|
|
3
|
-
from ...core.styles import getRandomColor
|
|
4
3
|
from ...core.color import to_rgba
|
|
5
4
|
from ...core.symbol import symbol
|
|
6
5
|
from ...plot import identities
|
|
@@ -141,10 +140,12 @@ class Equation:
|
|
|
141
140
|
|
|
142
141
|
self.width = width
|
|
143
142
|
if color is None:
|
|
144
|
-
self.color =
|
|
143
|
+
self.color = None
|
|
144
|
+
self._autoSeriesColor = True
|
|
145
145
|
else:
|
|
146
|
+
self._autoSeriesColor = False
|
|
146
147
|
self.color = to_rgba(color)
|
|
147
|
-
self.legendColor = self.color
|
|
148
|
+
self.legendColor = self.color
|
|
148
149
|
|
|
149
150
|
self.dots = []
|
|
150
151
|
self.dotsPosAbstract = set()
|
|
@@ -51,16 +51,13 @@ class Fill:
|
|
|
51
51
|
|
|
52
52
|
# color
|
|
53
53
|
if color is None:
|
|
54
|
-
self.color =
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
else:
|
|
58
|
-
self.color.append(100)
|
|
59
|
-
self.color = tuple(self.color)
|
|
54
|
+
self.color = None
|
|
55
|
+
self._autoSeriesColor = True
|
|
56
|
+
self.legendColor = None
|
|
60
57
|
else:
|
|
58
|
+
self._autoSeriesColor = False
|
|
61
59
|
self.color = to_rgba(color)
|
|
62
|
-
|
|
63
|
-
self.legendColor = self.color
|
|
60
|
+
self.legendColor = self.color
|
|
64
61
|
|
|
65
62
|
self.supports = [identities.XYPLOT]
|
|
66
63
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
from typing import Callable, Optional, Sequence, Tuple, Union
|
|
3
3
|
from .point import Points2D
|
|
4
|
-
from ...core.styles import
|
|
4
|
+
from ...core.styles import _apply_function2d_color
|
|
5
5
|
from ...core.color import to_rgba
|
|
6
6
|
from ...core.helper import *
|
|
7
7
|
from ...core.shapes import shapes
|
|
@@ -86,20 +86,17 @@ class Function2D:
|
|
|
86
86
|
self.dashed = dashed
|
|
87
87
|
|
|
88
88
|
if color is None:
|
|
89
|
-
self.color =
|
|
89
|
+
self.color = None
|
|
90
|
+
self._autoSeriesColor = True
|
|
90
91
|
else:
|
|
91
|
-
self.
|
|
92
|
-
|
|
92
|
+
self._autoSeriesColor = False
|
|
93
|
+
_apply_function2d_color(self, to_rgba(color))
|
|
93
94
|
|
|
94
95
|
self.legendSymbol = symbol.LINE
|
|
95
96
|
if self.dotted:
|
|
96
97
|
self.legendSymbol = symbol.CIRCLE
|
|
97
98
|
|
|
98
99
|
self.thickness = width
|
|
99
|
-
if len(self.color) > 3:
|
|
100
|
-
self.fillcolor = (*self.color[:3], int(self.color[3]*0.5))
|
|
101
|
-
else:
|
|
102
|
-
self.fillcolor = (*self.color, 175)
|
|
103
100
|
|
|
104
101
|
self.otherArgs = args
|
|
105
102
|
self.otherKwargs = kwargs
|