|
15 | 15 | ScatterSize, |
16 | 16 | ) |
17 | 17 | from .models import AnnotationsMixin |
18 | | -from .serializers import PlotHeight |
| 18 | +from .serializers import ColorCategory, PlotHeight |
19 | 19 |
|
20 | 20 |
|
21 | 21 | class ScatterPlot(AnnotationsMixin, BaseChart): |
@@ -198,6 +198,41 @@ class ScatterPlot(AnnotationsMixin, BaseChart): |
198 | 198 | description="Whether to show the color key", |
199 | 199 | ) |
200 | 200 |
|
| 201 | + #: The column with the color for the points |
| 202 | + color_column: str = Field( |
| 203 | + default="", |
| 204 | + alias="color-column", |
| 205 | + description="The column with the color for the points", |
| 206 | + ) |
| 207 | + |
| 208 | + #: A mapping of layer names to colors |
| 209 | + color_category: dict[str, str] = Field( |
| 210 | + default_factory=dict, |
| 211 | + alias="color-category", |
| 212 | + description="A mapping of layer names to colors", |
| 213 | + ) |
| 214 | + |
| 215 | + #: Dictionary mapping category names to their display labels in the color legend |
| 216 | + category_labels: dict[str, str] = Field( |
| 217 | + default_factory=dict, |
| 218 | + alias="category-labels", |
| 219 | + description="Dictionary mapping category names to their display labels in the color legend", |
| 220 | + ) |
| 221 | + |
| 222 | + #: List defining the order in which categories appear in the chart and legend |
| 223 | + category_order: list[str] = Field( |
| 224 | + default_factory=list, |
| 225 | + alias="category-order", |
| 226 | + description="List defining the order in which categories appear in the chart and legend", |
| 227 | + ) |
| 228 | + |
| 229 | + #: A list of columns to exclude from the color key |
| 230 | + exclude_from_color_key: list[str] = Field( |
| 231 | + default_factory=list, |
| 232 | + alias="exclude-from-color-key", |
| 233 | + description="A list of columns to exclude from the color key", |
| 234 | + ) |
| 235 | + |
201 | 236 | # |
202 | 237 | # Size |
203 | 238 | # |
@@ -498,6 +533,8 @@ def serialize_model(self) -> dict: |
498 | 533 | axes["shape"] = self.shape_column |
499 | 534 | if self.label_column: |
500 | 535 | axes["labels"] = self.label_column |
| 536 | + if self.color_column: |
| 537 | + axes["color"] = self.color_column |
501 | 538 |
|
502 | 539 | # Add axes to metadata |
503 | 540 | model["metadata"]["axes"] = axes |
@@ -529,6 +566,13 @@ def serialize_model(self) -> dict: |
529 | 566 | "outlines": self.outlines, |
530 | 567 | "color-outline": self.color_outline, |
531 | 568 | "show-color-key": self.show_color_key, |
| 569 | + "color-category": ColorCategory.serialize( |
| 570 | + self.color_category, |
| 571 | + self.category_labels, |
| 572 | + self.category_order, |
| 573 | + self.exclude_from_color_key, |
| 574 | + ), |
| 575 | + "color-by-column": bool(self.color_category), |
532 | 576 | # Size |
533 | 577 | "size": self.size, |
534 | 578 | "fixed-size": self.fixed_size, |
@@ -604,6 +648,8 @@ def deserialize_model(cls, api_response: dict[str, Any]) -> dict[str, Any]: |
604 | 648 | init_data["size_column"] = axes.get("size") |
605 | 649 | init_data["shape_column"] = axes.get("shape") |
606 | 650 | init_data["label_column"] = axes.get("labels") |
| 651 | + if "color" in axes: |
| 652 | + init_data["color_column"] = axes["color"] |
607 | 653 |
|
608 | 654 | # Parse x-axis |
609 | 655 | x_axis = visualize.get("x-axis", {}) |
@@ -653,6 +699,9 @@ def deserialize_model(cls, api_response: dict[str, Any]) -> dict[str, Any]: |
653 | 699 | if "show-color-key" in visualize: |
654 | 700 | init_data["show_color_key"] = visualize["show-color-key"] |
655 | 701 |
|
| 702 | + # Parse color-category using utility |
| 703 | + init_data.update(ColorCategory.deserialize(visualize.get("color-category"))) |
| 704 | + |
656 | 705 | # Size |
657 | 706 | if "size" in visualize: |
658 | 707 | init_data["size"] = visualize["size"] |
|
0 commit comments