vela_chart
1# -*- coding: utf-8 -*- 2from __future__ import annotations 3from typing import Optional 4 5import math 6 7def r_str_to_double(s): 8 try: 9 return float(s) 10 except (TypeError, ValueError): 11 return None 12 13 14 15def r_div_f64(a, b): 16 if b == 0.0: 17 if a == 0.0 or a != a: 18 return float('nan') 19 return math.copysign(float('inf'), a) * math.copysign(1.0, b) 20 return a / b 21 22 23class VlJson: 24 """A JSON value: null, a boolean, a number, text, an array or an object. 25 26 This is the value model the whole of Vela exchanges — a specification arrives 27 as one, the chart API emits one, and the runtime reads one. It is pure Ranger 28 with no host JSON, so the same tree is built on every target, which is what 29 makes a scene comparison against the reference implementation mean anything. 30 31 Two things it carries that a plain JSON model does not: object keys keep the 32 order they were written in, so a re-serialised specification is stable; and a 33 number remembers whether it was written as an integer, so `5` does not come 34 back as `5.0`. 35 """ 36 def __init__(self) -> None: 37 self.kind = 0 38 self.num = 0 39 self.b = False 40 self._str = "" 41 self.arr = [] 42 self.keys = [] 43 self.members = {} 44 self.isInt = False 45 @staticmethod 46 def nullValue() -> VlJson: 47 """Builds the JSON null value. 48 49 Returns: 50 VlJson: A null value. 51 """ 52 v = VlJson() 53 return v; 54 @staticmethod 55 def boolValue(value: bool) -> VlJson: 56 """Builds a JSON boolean. 57 58 Args: 59 value (bool): The boolean. 60 61 Returns: 62 VlJson: A boolean value. 63 """ 64 v = VlJson() 65 v.kind = 1; 66 v.b = value; 67 return v; 68 @staticmethod 69 def numberValue(value: float) -> VlJson: 70 """Builds a JSON number that prints with a fraction, so 5 comes back as `5.0`. 71 72 Args: 73 value (float): The number. 74 75 Returns: 76 VlJson: A number value. 77 78 See Also: 79 intValue 80 """ 81 v = VlJson() 82 v.kind = 2; 83 v.num = value; 84 return v; 85 @staticmethod 86 def intValue(value: int) -> VlJson: 87 """Builds a JSON number that prints without a fraction, so 5 stays `5`. 88 89 JSON has one number type; the text does not. A count written with this prints 90 as a count. 91 92 Args: 93 value (int): The whole number. 94 95 Returns: 96 VlJson: A number value that remembers it was written as an integer. 97 98 See Also: 99 numberValue 100 """ 101 v = VlJson() 102 v.kind = 2; 103 v.num = float(value); 104 v.isInt = True; 105 return v; 106 @staticmethod 107 def stringValue(value: str) -> VlJson: 108 """Builds a JSON string. 109 110 Args: 111 value (str): The text. 112 113 Returns: 114 VlJson: A string value. 115 """ 116 v = VlJson() 117 v.kind = 3; 118 v._str = value; 119 return v; 120 @staticmethod 121 def arrayValue() -> VlJson: 122 """Builds an empty JSON array. 123 124 Returns: 125 VlJson: An array value with no elements. 126 """ 127 v = VlJson() 128 v.kind = 4; 129 return v; 130 @staticmethod 131 def objectValue() -> VlJson: 132 """Builds an empty JSON object. 133 134 Returns: 135 VlJson: An object value with no members. 136 """ 137 v = VlJson() 138 v.kind = 5; 139 return v; 140 @staticmethod 141 def numberToText(value: float, wasInt: bool) -> str: 142 return VlJson.formatNumber(value, 6); 143 @staticmethod 144 def formatSignificant(value: float, digits: int) -> str: 145 m = value 146 if m < 0: 147 m = 0 - m; 148 whole = 1 149 while m >= 10: 150 m = r_div_f64(m, 10); 151 whole = whole + 1; 152 decimals = digits - whole 153 if decimals < 0: 154 decimals = 0; 155 return VlJson.formatNumber(value, decimals); 156 @staticmethod 157 def withMinusSign(text: str) -> str: 158 if len(text) == 0: 159 return text; 160 if text[0:1] == "-": 161 return chr(8722) + text[1:len(text)]; 162 return text; 163 @staticmethod 164 def domainKey(cell: VlJson) -> str: 165 if cell.isNull(): 166 return "null"; 167 return cell.asString(); 168 @staticmethod 169 def formatNumber(value: float, maxDecimals: int) -> str: 170 v = value 171 if False == (value == value): 172 return "NaN"; 173 if v == 0: 174 return "0"; 175 if value * 0.5 == value: 176 if value > 0: 177 return "Infinity"; 178 return "-Infinity"; 179 neg = False 180 if v < 0: 181 neg = True; 182 v = 0 - v; 183 if v >= 1000000000: 184 place = 1 185 while r_div_f64(v, place) >= 10: 186 place = place * 10; 187 big = "" 188 rest = v 189 while place >= 1: 190 big = big + VlJson.digitChar(VlJson.digitAt(rest, place)); 191 rest = rest - float(VlJson.digitAt(rest, place)) * place; 192 place = r_div_f64(place, 10); 193 tail = VlJson.fractionDigits(rest, maxDecimals) 194 if len(tail) > 0: 195 big = (big + ".") + tail; 196 if neg: 197 return "-" + big; 198 return big; 199 scale = 1 200 k = 0 201 while k < maxDecimals: 202 scale = scale * 10; 203 k = k + 1; 204 whole = math.floor(v) 205 frac = v - float(whole) 206 if frac == 0: 207 if neg: 208 return "-" + VlJson.intToText(whole); 209 return VlJson.intToText(whole); 210 units = frac * scale + 0.5 211 if False == (units < scale): 212 whole = whole + 1; 213 units = 0; 214 out = VlJson.intToText(whole) 215 fracText = "" 216 place_1 = scale 217 rest_1 = units 218 i = 0 219 while i < maxDecimals: 220 place_1 = r_div_f64(place_1, 10); 221 digit = math.floor(r_div_f64(rest_1, place_1)) 222 rest_1 = rest_1 - float(digit) * place_1; 223 fracText = fracText + VlJson.digitChar(digit); 224 i = i + 1; 225 end = len(fracText) 226 stop = False 227 while end > 0 and False == stop: 228 if ord(fracText[(end - 1)]) == 48: 229 end = end - 1; 230 else: 231 stop = True; 232 if end > 0: 233 out = (out + ".") + fracText[0:end]; 234 if neg: 235 return "-" + out; 236 return out; 237 @staticmethod 238 def digitAt(rest: float, place: float) -> int: 239 digit = math.floor(r_div_f64(rest, place)) 240 if digit > 9: 241 return 9; 242 if digit < 0: 243 return 0; 244 return digit; 245 @staticmethod 246 def fractionDigits(frac: float, maxDecimals: int) -> str: 247 out = "" 248 rest = frac 249 place = 0.1 250 i = 0 251 while i < maxDecimals: 252 digit = VlJson.digitAt(rest, place) 253 out = out + VlJson.digitChar(digit); 254 rest = rest - float(digit) * place; 255 place = r_div_f64(place, 10); 256 i = i + 1; 257 end = len(out) 258 stop = False 259 while end > 0 and False == stop: 260 if out[(end - 1):end] == "0": 261 end = end - 1; 262 else: 263 stop = True; 264 return out[0:end]; 265 @staticmethod 266 def intToText(value: int) -> str: 267 if value <= 0: 268 return "0"; 269 v = value 270 digits = "" 271 while v > 0: 272 _next = ((v) // (10)) 273 digit = v - _next * 10 274 digits = VlJson.digitChar(digit) + digits; 275 v = _next; 276 return digits; 277 @staticmethod 278 def digitChar(d: int) -> str: 279 if d <= 0: 280 return "0"; 281 if d == 1: 282 return "1"; 283 if d == 2: 284 return "2"; 285 if d == 3: 286 return "3"; 287 if d == 4: 288 return "4"; 289 if d == 5: 290 return "5"; 291 if d == 6: 292 return "6"; 293 if d == 7: 294 return "7"; 295 if d == 8: 296 return "8"; 297 return "9"; 298 def isNull(self) -> bool: 299 return self.kind == 0; 300 def isBool(self) -> bool: 301 return self.kind == 1; 302 def isNumber(self) -> bool: 303 return self.kind == 2; 304 def isString(self) -> bool: 305 return self.kind == 3; 306 def isArray(self) -> bool: 307 return self.kind == 4; 308 def isObject(self) -> bool: 309 return self.kind == 5; 310 def isDefined(self) -> bool: 311 return self.kind != 0; 312 def looksNumeric(self) -> bool: 313 if self.kind == 2: 314 return True; 315 if self.kind != 3: 316 return False; 317 if len(self._str) == 0: 318 return False; 319 d = r_str_to_double(self._str) 320 if d is not None: 321 return True; 322 return False; 323 def asInt(self) -> int: 324 return math.floor(self.num); 325 def asDouble(self) -> float: 326 if self.kind == 2: 327 return self.num; 328 if self.kind == 1: 329 if self.b: 330 return 1; 331 return 0; 332 if self.kind == 3: 333 d = r_str_to_double(self._str) 334 if d is not None: 335 return d; 336 return 0; 337 def asString(self) -> str: 338 if self.kind == 3: 339 return self._str; 340 if self.kind == 4: 341 joined = "" 342 k = 0 343 while k < len(self.arr): 344 if k > 0: 345 joined = joined + "\n"; 346 joined = joined + self.arr[k].asString(); 347 k = k + 1; 348 return joined; 349 if self.kind == 2: 350 return VlJson.numberToText(self.num, self.isInt); 351 if self.kind == 1: 352 if self.b: 353 return "true"; 354 return "false"; 355 return ""; 356 def asBool(self) -> bool: 357 if self.kind == 1: 358 return self.b; 359 if self.kind == 2: 360 return self.num != 0; 361 if self.kind == 3: 362 return len(self._str) > 0; 363 return False; 364 def count(self) -> int: 365 return len(self.arr); 366 def at(self, index: int) -> VlJson: 367 if index < 0: 368 return VlJson.nullValue(); 369 if index >= len(self.arr): 370 return VlJson.nullValue(); 371 return self.arr[index]; 372 def has(self, key: str) -> bool: 373 return key in self.members; 374 def get(self, key: str) -> VlJson: 375 if key in self.members: 376 return self.members.get(key); 377 return VlJson.nullValue(); 378 def intOr(self, key: str, dflt: int) -> int: 379 if key in self.members: 380 v = self.members.get(key) 381 if v.kind == 2: 382 return math.floor(v.num); 383 return dflt; 384 def doubleOr(self, key: str, dflt: float) -> float: 385 if key in self.members: 386 v = self.members.get(key) 387 if v.kind == 2: 388 return v.num; 389 return dflt; 390 def stringOr(self, key: str, dflt: str) -> str: 391 if key in self.members: 392 v = self.members.get(key) 393 if v.kind == 3: 394 return v._str; 395 return dflt; 396 def boolOr(self, key: str, dflt: bool) -> bool: 397 if key in self.members: 398 v = self.members.get(key) 399 if v.kind == 1: 400 return v.b; 401 return dflt; 402 def setMember(self, key: str, value: VlJson) -> None: 403 if False == (key in self.members): 404 self.keys.append(key) 405 self.members[key] = value; 406 def removeMember(self, key: str) -> None: 407 if False == (key in self.members): 408 return; 409 kept = [] 410 fresh = {} 411 for k in self.keys: 412 if k != key: 413 kept.append(k) 414 fresh[k] = self.members.get(k); 415 self.keys = kept; 416 self.members = fresh; 417class VlJsonParser: 418 def __init__(self) -> None: 419 self.s = "" 420 self.i = 0 421 self.n = 0 422 self.ok = True 423 self.err = "" 424 def parse(self, text: str) -> VlJson: 425 self.s = text; 426 self.i = 0; 427 self.n = len(text); 428 self.ok = True; 429 self.err = ""; 430 v = self.parseValue() 431 return v; 432 def isWs(self, c: int) -> bool: 433 if c == 32: 434 return True; 435 if c == 9: 436 return True; 437 if c == 10: 438 return True; 439 if c == 13: 440 return True; 441 return False; 442 def skipWs(self) -> None: 443 go = True 444 while go: 445 if self.i >= self.n: 446 go = False; 447 else: 448 c = ord(self.s[self.i]) 449 if self.isWs(c): 450 self.i = self.i + 1; 451 else: 452 go = False; 453 def isNumChar(self, c: int) -> bool: 454 if c == 45: 455 return True; 456 if c == 43: 457 return True; 458 if c == 46: 459 return True; 460 if c == 101: 461 return True; 462 if c == 69: 463 return True; 464 if c >= 48: 465 if c <= 57: 466 return True; 467 return False; 468 def fail(self, msg: str) -> None: 469 if self.ok: 470 self.ok = False; 471 self.err = msg; 472 def parseValue(self) -> VlJson: 473 self.skipWs() 474 if self.i >= self.n: 475 self.fail("unexpected end of input") 476 return VlJson.nullValue(); 477 c = ord(self.s[self.i]) 478 if c == 123: 479 return self.parseObject(); 480 if c == 91: 481 return self.parseArray(); 482 if c == 34: 483 return self.parseString(); 484 if c == 116: 485 return self.parseKeyword("true", 1, True); 486 if c == 102: 487 return self.parseKeyword("false", 1, False); 488 if c == 110: 489 return self.parseKeyword("null", 0, False); 490 return self.parseNumber(); 491 def parseKeyword(self, word: str, kind: int, bval: bool) -> VlJson: 492 wl = len(word) 493 matched = True 494 k = 0 495 while k < wl: 496 if self.i + k >= self.n: 497 matched = False; 498 k = wl; 499 else: 500 if ord(self.s[(self.i + k)]) != ord(word[k]): 501 matched = False; 502 k = wl; 503 else: 504 k = k + 1; 505 v = VlJson() 506 if matched: 507 self.i = self.i + wl; 508 v.kind = kind; 509 v.b = bval; 510 else: 511 self.fail("invalid literal, expected " + word) 512 return v; 513 def parseNumber(self) -> VlJson: 514 start = self.i 515 sawFraction = False 516 go = True 517 while go: 518 if self.i >= self.n: 519 go = False; 520 else: 521 c = ord(self.s[self.i]) 522 if self.isNumChar(c): 523 if c == 46: 524 sawFraction = True; 525 if c == 101: 526 sawFraction = True; 527 if c == 69: 528 sawFraction = True; 529 self.i = self.i + 1; 530 else: 531 go = False; 532 v = VlJson() 533 if self.i > start: 534 sub = self.s[start:self.i] 535 d = r_str_to_double(sub) 536 v.kind = 2; 537 v.isInt = False == sawFraction; 538 if d is not None: 539 v.num = d; 540 else: 541 self.fail("invalid number: " + sub) 542 else: 543 self.fail("expected value") 544 return v; 545 def hexDigit(self, c: int) -> int: 546 if c >= 48: 547 if c <= 57: 548 return c - 48; 549 if c >= 97: 550 if c <= 102: 551 return (c - 97) + 10; 552 if c >= 65: 553 if c <= 70: 554 return (c - 65) + 10; 555 return 0; 556 def readRawString(self) -> str: 557 self.i = self.i + 1; 558 out = "" 559 go = True 560 while go: 561 if self.i >= self.n: 562 self.fail("unterminated string") 563 go = False; 564 else: 565 c = ord(self.s[self.i]) 566 if c == 34: 567 self.i = self.i + 1; 568 go = False; 569 else: 570 if c == 92: 571 self.i = self.i + 1; 572 if self.i >= self.n: 573 self.fail("unterminated escape") 574 go = False; 575 else: 576 e = ord(self.s[self.i]) 577 out = out + self.decodeEscape(e); 578 self.i = self.i + 1; 579 else: 580 out = out + self.s[self.i:(self.i + 1)]; 581 self.i = self.i + 1; 582 return out; 583 def decodeEscape(self, e: int) -> str: 584 if e == 34: 585 return chr(34); 586 if e == 92: 587 return chr(92); 588 if e == 47: 589 return chr(47); 590 if e == 98: 591 return chr(8); 592 if e == 102: 593 return chr(12); 594 if e == 110: 595 return chr(10); 596 if e == 114: 597 return chr(13); 598 if e == 116: 599 return chr(9); 600 if e == 117: 601 cp = 0 602 k = 0 603 while k < 4: 604 hc = ord(self.s[((self.i + 1) + k)]) 605 cp = cp * 16 + self.hexDigit(hc); 606 k = k + 1; 607 self.i = self.i + 4; 608 return chr(cp); 609 return chr(e); 610 def parseString(self) -> VlJson: 611 v = VlJson() 612 v.kind = 3; 613 v._str = self.readRawString(); 614 return v; 615 def parseArray(self) -> VlJson: 616 v = VlJson() 617 v.kind = 4; 618 self.i = self.i + 1; 619 self.skipWs() 620 if self.i < self.n: 621 if ord(self.s[self.i]) == 93: 622 self.i = self.i + 1; 623 return v; 624 go = True 625 while go: 626 item = self.parseValue() 627 v.arr.append(item) 628 self.skipWs() 629 if self.i >= self.n: 630 self.fail("unterminated array") 631 go = False; 632 else: 633 c = ord(self.s[self.i]) 634 if c == 44: 635 self.i = self.i + 1; 636 self.skipWs() 637 else: 638 if c == 93: 639 self.i = self.i + 1; 640 go = False; 641 else: 642 self.fail("expected ',' or ']' in array") 643 go = False; 644 if self.ok == False: 645 go = False; 646 return v; 647 def parseObject(self) -> VlJson: 648 v = VlJson() 649 v.kind = 5; 650 self.i = self.i + 1; 651 self.skipWs() 652 if self.i < self.n: 653 if ord(self.s[self.i]) == 125: 654 self.i = self.i + 1; 655 return v; 656 go = True 657 while go: 658 self.skipWs() 659 if self.i >= self.n: 660 self.fail("unterminated object") 661 go = False; 662 else: 663 if ord(self.s[self.i]) != 34: 664 self.fail("expected string key in object") 665 go = False; 666 else: 667 key = self.readRawString() 668 self.skipWs() 669 if self.i >= self.n: 670 self.fail("expected ':' in object") 671 go = False; 672 else: 673 if ord(self.s[self.i]) != 58: 674 self.fail("expected ':' in object") 675 go = False; 676 else: 677 self.i = self.i + 1; 678 val = self.parseValue() 679 v.setMember(key, val) 680 self.skipWs() 681 if self.i >= self.n: 682 self.fail("unterminated object") 683 go = False; 684 else: 685 c = ord(self.s[self.i]) 686 if c == 44: 687 self.i = self.i + 1; 688 else: 689 if c == 125: 690 self.i = self.i + 1; 691 go = False; 692 else: 693 self.fail("expected ',' or '}' in object") 694 go = False; 695 if self.ok == False: 696 go = False; 697 return v; 698class VlJsonWriter: 699 def __init__(self) -> None: 700 self.decimals = 6 701 def write(self, v: VlJson) -> str: 702 return self.writeValue(v, 0, False); 703 def writePretty(self, v: VlJson) -> str: 704 return self.writeValue(v, 0, True); 705 def indent(self, depth: int) -> str: 706 out = "" 707 k = 0 708 while k < depth: 709 out = out + " "; 710 k = k + 1; 711 return out; 712 def writeValue(self, v: VlJson, depth: int, pretty: bool) -> str: 713 if v.kind == 0: 714 return "null"; 715 if v.kind == 1: 716 if v.b: 717 return "true"; 718 return "false"; 719 if v.kind == 2: 720 return VlJson.formatNumber(v.num, self.decimals); 721 if v.kind == 3: 722 return self.quote(v._str); 723 if v.kind == 4: 724 return self.writeArray(v, depth, pretty); 725 return self.writeObject(v, depth, pretty); 726 def writeArray(self, v: VlJson, depth: int, pretty: bool) -> str: 727 total = len(v.arr) 728 if total == 0: 729 return "[]"; 730 out = "[" 731 k = 0 732 while k < total: 733 if k > 0: 734 out = out + ","; 735 if pretty: 736 out = (out + chr(10)) + self.indent((depth + 1)); 737 item = v.arr[k] 738 out = out + self.writeValue(item, (depth + 1), pretty); 739 k = k + 1; 740 if pretty: 741 out = ((out + chr(10)) + self.indent(depth)) + "]"; 742 else: 743 out = out + "]"; 744 return out; 745 def writeObject(self, v: VlJson, depth: int, pretty: bool) -> str: 746 total = len(v.keys) 747 if total == 0: 748 return "{}"; 749 out = "{" 750 k = 0 751 while k < total: 752 key = v.keys[k] 753 if k > 0: 754 out = out + ","; 755 if pretty: 756 out = (out + chr(10)) + self.indent((depth + 1)); 757 out = (out + self.quote(key)) + ":"; 758 if pretty: 759 out = out + " "; 760 item = v.get(key) 761 out = out + self.writeValue(item, (depth + 1), pretty); 762 k = k + 1; 763 if pretty: 764 out = ((out + chr(10)) + self.indent(depth)) + "}"; 765 else: 766 out = out + "}"; 767 return out; 768 def quote(self, s: str) -> str: 769 q = chr(34) 770 bs = chr(92) 771 total = len(s) 772 out = q 773 start = 0 774 k = 0 775 while k < total: 776 c = ord(s[k]) 777 if (c == 34 or c == 92) or ((c == 10 or c == 13) or c == 9): 778 if k > start: 779 out = out + s[start:k]; 780 if c == 34: 781 out = (out + bs) + q; 782 if c == 92: 783 out = (out + bs) + bs; 784 if c == 10: 785 out = (out + bs) + "n"; 786 if c == 13: 787 out = (out + bs) + "r"; 788 if c == 9: 789 out = (out + bs) + "t"; 790 start = k + 1; 791 k = k + 1; 792 if total > start: 793 out = out + s[start:total]; 794 return out + q; 795class VlDataRow: 796 """One row of a dataset, filled column by column. 797 798 A row is handed back already attached to its dataset, so nothing has to be 799 pushed anywhere by the caller. 800 801 See Also: 802 VlDataset 803 804 Example: 805 data = VlDataset.create() 806 data.row()._str("region", "North").num("sales", 120) 807 data.row()._str("region", "South").num("sales", 93) 808 """ 809 def __init__(self) -> None: 810 self.obj = VlJson.objectValue() 811 self.owner = None 812 def num(self, field: str, value: float) -> VlDataRow: 813 """Puts a number in one column of this row. 814 815 Args: 816 field (str): The column name. 817 value (float): The value. 818 819 Returns: 820 VlDataRow: This row, so columns chain. 821 """ 822 self.obj.setMember(field, VlJson.numberValue(value)) 823 return self; 824 def whole(self, field: str, value: int) -> VlDataRow: 825 """Puts a whole number in one column of this row. 826 827 A count is an integer and prints as one: 12, not 12.0. Use this rather than 828 `num` wherever the value counts things, or the axis labels will say so. 829 830 Args: 831 field (str): The column name. 832 value (int): The value. 833 834 Returns: 835 VlDataRow: This row, so columns chain. 836 837 See Also: 838 num 839 """ 840 self.obj.setMember(field, VlJson.intValue(value)) 841 return self; 842 def _str(self, field: str, value: str) -> VlDataRow: 843 """Puts text in one column of this row. 844 845 A column of text is read as a category unless every value in it parses as an 846 ISO date, in which case it is an instant. 847 848 Args: 849 field (str): The column name. 850 value (str): The value. 851 852 Returns: 853 VlDataRow: This row, so columns chain. 854 """ 855 self.obj.setMember(field, VlJson.stringValue(value)) 856 return self; 857 def flag(self, field: str, value: bool) -> VlDataRow: 858 """Puts true or false in one column of this row. 859 860 Args: 861 field (str): The column name. 862 value (bool): The value. 863 864 Returns: 865 VlDataRow: This row, so columns chain. 866 """ 867 self.obj.setMember(field, VlJson.boolValue(value)) 868 return self; 869 def json(self, field: str, value: VlJson) -> VlDataRow: 870 """Puts an already-built value in one column of this row. 871 872 The escape hatch for a column this API has no typed setter for — a nested 873 object a geoshape reads, or a value that came out of the parser. 874 875 Args: 876 field (str): The column name. 877 value (VlJson): The value, as the JSON model holds it. 878 879 Returns: 880 VlDataRow: This row, so columns chain. 881 """ 882 self.obj.setMember(field, value) 883 return self; 884 def back(self) -> VlDataset: 885 """Returns to the dataset this row belongs to, so rows chain one after another. 886 887 Returns: 888 VlDataset: The owning dataset, or a fresh empty one if this row was built without a dataset. 889 """ 890 if (self.owner is not None): 891 return self.owner; 892 return VlDataset.create(); 893class VlDataset: 894 """A table of rows, built once and given to as many charts as want it. 895 896 Rows are JSON objects — the same values the parser produces for 897 `"data": {"values": […]}` — so a dataset built here and one read off disk are 898 the same thing to everything downstream. 899 900 The dataset is a value **beside** the chart rather than a thing inside it: a 901 spreadsheet's selection becomes one dataset and a dashboard's six panels read 902 it. 903 904 See Also: 905 VlChart 906 907 Example: 908 data = VlDataset.create() 909 data.row()._str("region", "North").num("sales", 120) 910 data.row()._str("region", "South").num("sales", 93) 911 """ 912 def __init__(self) -> None: 913 self.rows = [] 914 self.name = "" 915 @staticmethod 916 def create() -> VlDataset: 917 """Builds an empty dataset. 918 919 Returns: 920 VlDataset: A dataset with no rows. 921 """ 922 d = VlDataset() 923 return d; 924 @staticmethod 925 def looksLikeDate(text: str) -> bool: 926 n = len(text) 927 if n < 6 or n > 40: 928 return False; 929 i = 0 930 while i < 4: 931 c = ord(text[i]) 932 if c < 48 or c > 57: 933 return False; 934 i = i + 1; 935 sep = ord(text[4]) 936 if sep != 45: 937 return False; 938 d = ord(text[5]) 939 if d < 48 or d > 57: 940 return False; 941 return True; 942 def row(self) -> VlDataRow: 943 """Adds a row and hands it back, ready to be filled. 944 945 Returns: 946 VlDataRow: The new row, already attached to this dataset. 947 948 See Also: 949 VlDataRow 950 """ 951 r = VlDataRow() 952 r.owner = self; 953 self.rows.append(r.obj) 954 return r; 955 def addRow(self, row: VlJson) -> VlDataset: 956 """Adds a row that was built elsewhere. 957 958 Args: 959 row (VlJson): A JSON object whose members are the columns. 960 961 Returns: 962 VlDataset: This dataset, so calls chain. 963 """ 964 self.rows.append(row) 965 return self; 966 def fromValues(self, values: VlJson) -> VlDataset: 967 """Takes the rows of a JSON array as they came out of the parser. 968 969 A dataset built here and one read off disk are the same thing to everything 970 downstream, so a selection from a grid, a file somebody read and a literal all 971 arrive the same way. 972 973 Args: 974 values (VlJson): A JSON array of row objects. 975 976 Returns: 977 VlDataset: This dataset, so calls chain. 978 """ 979 i = 0 980 n = values.count() 981 while i < n: 982 self.rows.append(values.at(i)) 983 i = i + 1; 984 return self; 985 def numbers(self, field: str, values: list[float]) -> VlDataset: 986 """Fills one numeric column from an array, one value per row. 987 988 Column-wise filling, for a caller that holds arrays rather than records — a 989 spreadsheet column, a series of measurements. Row `i` of every column is the 990 same row, so two calls with arrays of the same length make a table. 991 992 Args: 993 field (str): The column name. 994 values (None): One value per row, in row order. 995 996 Returns: 997 VlDataset: This dataset, so calls chain. 998 999 See Also: 1000 strings 1001 """ 1002 for i, v in enumerate(values): 1003 r = self.rowAt(i) 1004 r.setMember(field, VlJson.numberValue(v)) 1005 return self; 1006 def strings(self, field: str, values: list[str]) -> VlDataset: 1007 """Fills one text column from an array, one value per row. 1008 1009 Args: 1010 field (str): The column name. 1011 values (None): One value per row, in row order. 1012 1013 Returns: 1014 VlDataset: This dataset, so calls chain. 1015 1016 See Also: 1017 numbers 1018 """ 1019 for i, v in enumerate(values): 1020 r = self.rowAt(i) 1021 r.setMember(field, VlJson.stringValue(v)) 1022 return self; 1023 def rowAt(self, index: int) -> VlJson: 1024 """The row at an index, growing the dataset with empty rows if it is not there yet. 1025 1026 Args: 1027 index (int): A zero-based row number. 1028 1029 Returns: 1030 VlJson: The row object, which can be written into directly. 1031 """ 1032 while len(self.rows) <= index: 1033 self.rows.append(VlJson.objectValue()) 1034 return self.rows[index]; 1035 def count(self) -> int: 1036 """How many rows the dataset holds. 1037 1038 Returns: 1039 int: The row count. 1040 """ 1041 return len(self.rows); 1042 def hasField(self, field: str) -> bool: 1043 """Whether any row has this column. 1044 1045 Args: 1046 field (str): The column name. 1047 1048 Returns: 1049 bool: True when at least one row carries the column. 1050 """ 1051 for r in self.rows: 1052 if r.has(field): 1053 return True; 1054 return False; 1055 def fieldType(self, field: str) -> str: 1056 """What kind of thing a column holds, in Vega-Lite's vocabulary. 1057 1058 Read off the rows rather than declared: numbers are a quantity, ISO dates are 1059 an instant, anything else is a name. A column the data does not have answers 1060 the empty string, so a caller can tell "no such column" from "a column of 1061 names" — which is the difference between a mistake and a chart. 1062 1063 Args: 1064 field (str): The column name. 1065 1066 Returns: 1067 str: `quantitative`, `temporal`, `nominal`, or the empty string when no row has the column. 1068 """ 1069 sawNumber = False 1070 sawText = False 1071 sawDate = False 1072 sawAny = False 1073 for r in self.rows: 1074 if r.has(field): 1075 v = r.get(field) 1076 if False == v.isNull(): 1077 sawAny = True; 1078 if v.isNumber(): 1079 sawNumber = True; 1080 if v.isString(): 1081 sawText = True; 1082 if VlDataset.looksLikeDate(v._str): 1083 sawDate = True; 1084 if False == sawAny: 1085 return ""; 1086 if sawText: 1087 if sawDate: 1088 return "temporal"; 1089 return "nominal"; 1090 if sawNumber: 1091 return "quantitative"; 1092 return "nominal"; 1093 def toValues(self) -> VlJson: 1094 """The dataset as the `data` block of a specification: `{"values": […]}`. 1095 1096 Returns: 1097 VlJson: A JSON object holding every row. 1098 """ 1099 _list = VlJson.arrayValue() 1100 for r in self.rows: 1101 _list.arr.append(r) 1102 obj = VlJson.objectValue() 1103 obj.setMember("values", _list) 1104 return obj; 1105class VlChartMark: 1106 """One mark and the channels it reads. 1107 1108 Every setter answers the mark, so a mark is written as one sentence. 1109 1110 `aggregate`, `bin`, `title` and the rest apply to the channel most recently 1111 named — the cursor — which is what makes that sentence read in the order it is 1112 thought. `on` moves the cursor back to a channel already set. 1113 1114 A channel names a **column**. A constant goes through `valueNumber` or 1115 `valueString`, and the two are kept apart on purpose: `.color("red")` meaning a 1116 column called red and `.color("#c00")` meaning paint it red cannot both be 1117 true, and the version that guesses is the one that draws a chart nobody asked 1118 for. 1119 1120 See Also: 1121 VlChart 1122 1123 Example: 1124 data = VlDataset.create() 1125 data.row()._str("region", "North").num("sales", 120) 1126 chart = VlChart.create(data) 1127 chart.bar().x("region").y("sales").aggregate("sum").title("Total sales") 1128 """ 1129 def __init__(self) -> None: 1130 self.markType = "point" 1131 self.props = VlJson.objectValue() 1132 self.enc = VlJson.objectValue() 1133 self.cursor = "" 1134 self.owner = None 1135 def note(self, message: str) -> None: 1136 if (self.owner is not None): 1137 o = self.owner 1138 o.error(message) 1139 def channel(self, name: str, field: str) -> VlChartMark: 1140 """Sets any channel to a column by name. 1141 1142 The named channel becomes the cursor, so the next `aggregate`, `title` or 1143 `type` applies to it. 1144 1145 Args: 1146 name (str): The channel name, as Vega-Lite spells it. 1147 field (str): The column name. 1148 1149 Returns: 1150 VlChartMark: This mark, so calls chain. 1151 """ 1152 ch = VlJson.objectValue() 1153 ch.setMember("field", VlJson.stringValue(field)) 1154 self.enc.setMember(name, ch) 1155 self.cursor = name; 1156 return self; 1157 def x(self, field: str) -> VlChartMark: 1158 """Position along the horizontal axis. 1159 1160 Names a COLUMN, never a constant. `.color("red")` means a column 1161 called red; painting a mark red is `markColor`. 1162 1163 Args: 1164 field (str): The column name. 1165 1166 Returns: 1167 VlChartMark: This mark, so channels chain. 1168 """ 1169 return self.channel("x", field); 1170 def y(self, field: str) -> VlChartMark: 1171 """Position along the vertical axis. 1172 1173 Names a COLUMN, never a constant. `.color("red")` means a column 1174 called red; painting a mark red is `markColor`. 1175 1176 Args: 1177 field (str): The column name. 1178 1179 Returns: 1180 VlChartMark: This mark, so channels chain. 1181 """ 1182 return self.channel("y", field); 1183 def x2(self, field: str) -> VlChartMark: 1184 """The far end of a horizontal interval, for a bar, an area or a rule that spans two values. 1185 1186 Names a COLUMN, never a constant. `.color("red")` means a column 1187 called red; painting a mark red is `markColor`. 1188 1189 Args: 1190 field (str): The column name. 1191 1192 Returns: 1193 VlChartMark: This mark, so channels chain. 1194 1195 See Also: 1196 x 1197 """ 1198 return self.channel("x2", field); 1199 def y2(self, field: str) -> VlChartMark: 1200 """The far end of a vertical interval, for a bar, an area or a rule that spans two values. 1201 1202 Names a COLUMN, never a constant. `.color("red")` means a column 1203 called red; painting a mark red is `markColor`. 1204 1205 Args: 1206 field (str): The column name. 1207 1208 Returns: 1209 VlChartMark: This mark, so channels chain. 1210 1211 See Also: 1212 y 1213 """ 1214 return self.channel("y2", field); 1215 def color(self, field: str) -> VlChartMark: 1216 """Colour, and the legend that explains it. 1217 1218 Names a COLUMN, never a constant. `.color("red")` means a column 1219 called red; painting a mark red is `markColor`. 1220 1221 Args: 1222 field (str): The column name. 1223 1224 Returns: 1225 VlChartMark: This mark, so channels chain. 1226 """ 1227 return self.channel("color", field); 1228 def fill(self, field: str) -> VlChartMark: 1229 """Fill colour, set apart from the outline. 1230 1231 Names a COLUMN, never a constant. `.color("red")` means a column 1232 called red; painting a mark red is `markColor`. 1233 1234 Args: 1235 field (str): The column name. 1236 1237 Returns: 1238 VlChartMark: This mark, so channels chain. 1239 1240 See Also: 1241 stroke 1242 """ 1243 return self.channel("fill", field); 1244 def stroke(self, field: str) -> VlChartMark: 1245 """Outline colour, set apart from the fill. 1246 1247 Names a COLUMN, never a constant. `.color("red")` means a column 1248 called red; painting a mark red is `markColor`. 1249 1250 Args: 1251 field (str): The column name. 1252 1253 Returns: 1254 VlChartMark: This mark, so channels chain. 1255 1256 See Also: 1257 fill 1258 """ 1259 return self.channel("stroke", field); 1260 def size(self, field: str) -> VlChartMark: 1261 """Mark size: the area of a point, the width of a trail. 1262 1263 Names a COLUMN, never a constant. `.color("red")` means a column 1264 called red; painting a mark red is `markColor`. 1265 1266 Args: 1267 field (str): The column name. 1268 1269 Returns: 1270 VlChartMark: This mark, so channels chain. 1271 1272 See Also: 1273 markSize 1274 """ 1275 return self.channel("size", field); 1276 def shape(self, field: str) -> VlChartMark: 1277 """The symbol a point is drawn as. 1278 1279 Names a COLUMN, never a constant. `.color("red")` means a column 1280 called red; painting a mark red is `markColor`. 1281 1282 Args: 1283 field (str): The column name. 1284 1285 Returns: 1286 VlChartMark: This mark, so channels chain. 1287 """ 1288 return self.channel("shape", field); 1289 def opacity(self, field: str) -> VlChartMark: 1290 """How opaque the mark is. 1291 1292 Names a COLUMN, never a constant. `.color("red")` means a column 1293 called red; painting a mark red is `markColor`. 1294 1295 Args: 1296 field (str): The column name. 1297 1298 Returns: 1299 VlChartMark: This mark, so channels chain. 1300 1301 See Also: 1302 markOpacity 1303 """ 1304 return self.channel("opacity", field); 1305 def theta(self, field: str) -> VlChartMark: 1306 """The angle an arc covers, which is what makes a pie or a donut. 1307 1308 Names a COLUMN, never a constant. `.color("red")` means a column 1309 called red; painting a mark red is `markColor`. 1310 1311 Args: 1312 field (str): The column name. 1313 1314 Returns: 1315 VlChartMark: This mark, so channels chain. 1316 1317 See Also: 1318 radius 1319 """ 1320 return self.channel("theta", field); 1321 def radius(self, field: str) -> VlChartMark: 1322 """How far from the centre an arc reaches. 1323 1324 Names a COLUMN, never a constant. `.color("red")` means a column 1325 called red; painting a mark red is `markColor`. 1326 1327 Args: 1328 field (str): The column name. 1329 1330 Returns: 1331 VlChartMark: This mark, so channels chain. 1332 1333 See Also: 1334 theta 1335 """ 1336 return self.channel("radius", field); 1337 def detail(self, field: str) -> VlChartMark: 1338 """Groups the rows without drawing anything of its own: one line per group, no legend. 1339 1340 Names a COLUMN, never a constant. `.color("red")` means a column 1341 called red; painting a mark red is `markColor`. 1342 1343 Args: 1344 field (str): The column name. 1345 1346 Returns: 1347 VlChartMark: This mark, so channels chain. 1348 """ 1349 return self.channel("detail", field); 1350 def text(self, field: str) -> VlChartMark: 1351 """The text a label mark shows. 1352 1353 Names a COLUMN, never a constant. `.color("red")` means a column 1354 called red; painting a mark red is `markColor`. 1355 1356 Args: 1357 field (str): The column name. 1358 1359 Returns: 1360 VlChartMark: This mark, so channels chain. 1361 """ 1362 return self.channel("text", field); 1363 def order(self, field: str) -> VlChartMark: 1364 """The order the rows are drawn in, and the order a line joins its points. 1365 1366 Names a COLUMN, never a constant. `.color("red")` means a column 1367 called red; painting a mark red is `markColor`. 1368 1369 Args: 1370 field (str): The column name. 1371 1372 Returns: 1373 VlChartMark: This mark, so channels chain. 1374 """ 1375 return self.channel("order", field); 1376 def column(self, field: str) -> VlChartMark: 1377 """Splits the chart into side-by-side panels, one per value. 1378 1379 Names a COLUMN, never a constant. `.color("red")` means a column 1380 called red; painting a mark red is `markColor`. 1381 1382 Args: 1383 field (str): The column name. 1384 1385 Returns: 1386 VlChartMark: This mark, so channels chain. 1387 1388 See Also: 1389 row 1390 """ 1391 return self.channel("column", field); 1392 def row(self, field: str) -> VlChartMark: 1393 """Splits the chart into stacked panels, one per value. 1394 1395 Names a COLUMN, never a constant. `.color("red")` means a column 1396 called red; painting a mark red is `markColor`. 1397 1398 Args: 1399 field (str): The column name. 1400 1401 Returns: 1402 VlChartMark: This mark, so channels chain. 1403 1404 See Also: 1405 column 1406 """ 1407 return self.channel("row", field); 1408 def xOffset(self, field: str) -> VlChartMark: 1409 """What separates the bars of a grouped bar chart, across the horizontal axis. 1410 1411 Names a COLUMN, never a constant. `.color("red")` means a column 1412 called red; painting a mark red is `markColor`. 1413 1414 Args: 1415 field (str): The column name. 1416 1417 Returns: 1418 VlChartMark: This mark, so channels chain. 1419 1420 See Also: 1421 yOffset 1422 """ 1423 return self.channel("xOffset", field); 1424 def yOffset(self, field: str) -> VlChartMark: 1425 """What separates the bars of a grouped bar chart, across the vertical axis. 1426 1427 Names a COLUMN, never a constant. `.color("red")` means a column 1428 called red; painting a mark red is `markColor`. 1429 1430 Args: 1431 field (str): The column name. 1432 1433 Returns: 1434 VlChartMark: This mark, so channels chain. 1435 1436 See Also: 1437 xOffset 1438 """ 1439 return self.channel("yOffset", field); 1440 def count(self, channel: str) -> VlChartMark: 1441 """Sets a channel to a count of rows: one number per group, with no column to read. 1442 1443 Args: 1444 channel (str): The channel to put the count on, usually "y" or "x". 1445 1446 Returns: 1447 VlChartMark: This mark, so calls chain. 1448 """ 1449 ch = VlJson.objectValue() 1450 ch.setMember("aggregate", VlJson.stringValue("count")) 1451 ch.setMember("type", VlJson.stringValue("quantitative")) 1452 self.enc.setMember(channel, ch) 1453 self.cursor = channel; 1454 return self; 1455 def valueNumber(self, channel: str, value: float) -> VlChartMark: 1456 """Sets a channel to a constant number rather than to a column. 1457 1458 Args: 1459 channel (str): The channel name. 1460 value (float): The constant. 1461 1462 Returns: 1463 VlChartMark: This mark, so calls chain. 1464 1465 See Also: 1466 valueString 1467 """ 1468 ch = VlJson.objectValue() 1469 ch.setMember("value", VlJson.numberValue(value)) 1470 self.enc.setMember(channel, ch) 1471 self.cursor = channel; 1472 return self; 1473 def valueString(self, channel: str, value: str) -> VlChartMark: 1474 """Sets a channel to a constant string rather than to a column. 1475 1476 This is how a mark is painted a fixed colour: `.valueString("color" "#c00")`. 1477 The channel setters name columns and never constants, because a `.color(…)` 1478 that guessed between the two would draw a chart nobody asked for. 1479 1480 Args: 1481 channel (str): The channel name. 1482 value (str): The constant. 1483 1484 Returns: 1485 VlChartMark: This mark, so calls chain. 1486 1487 See Also: 1488 valueNumber 1489 """ 1490 ch = VlJson.objectValue() 1491 ch.setMember("value", VlJson.stringValue(value)) 1492 self.enc.setMember(channel, ch) 1493 self.cursor = channel; 1494 return self; 1495 def encodeJson(self, channel: str, definition: VlJson) -> VlChartMark: 1496 """Sets a whole channel from an already-built definition. 1497 1498 The escape hatch. Vega-Lite is larger than any fluent surface over it, and a 1499 definition that lands in the same specification is better than waiting for this 1500 API to grow a method. 1501 1502 Args: 1503 channel (str): The channel name. 1504 definition (VlJson): The channel definition. 1505 1506 Returns: 1507 VlChartMark: This mark, so calls chain. 1508 """ 1509 self.enc.setMember(channel, definition) 1510 self.cursor = channel; 1511 return self; 1512 def on(self, channel: str) -> VlChartMark: 1513 """Moves the cursor back to a channel that is already set. 1514 1515 Everything that follows — `aggregate`, `title`, `scaleType` — applies to it. 1516 A channel that was never set is reported in the chart's `errors` rather than 1517 silently created. 1518 1519 Args: 1520 channel (str): The channel name. 1521 1522 Returns: 1523 VlChartMark: This mark, so calls chain. 1524 """ 1525 if self.enc.has(channel): 1526 self.cursor = channel; 1527 else: 1528 self.note(("no channel called '" + channel) + "' has been set on this mark") 1529 return self; 1530 def cursorChannel(self) -> VlJson: 1531 if len(self.cursor) == 0: 1532 self.note("a channel property was set before any channel was named") 1533 return VlJson.objectValue(); 1534 return self.enc.get(self.cursor); 1535 def setOnCursor(self, key: str, value: VlJson) -> VlChartMark: 1536 ch = self.cursorChannel() 1537 ch.setMember(key, value) 1538 return self; 1539 def aggregate(self, op: str) -> VlChartMark: 1540 """How the rows in each group are reduced to one value. 1541 1542 Args: 1543 op (str): `sum`, `mean`, `median`, `min`, `max`, `count` and the rest of Vega-Lite's operations. 1544 1545 Returns: 1546 VlChartMark: This mark, so calls chain. 1547 """ 1548 return self.setOnCursor("aggregate", VlJson.stringValue(op)); 1549 def _bin(self) -> VlChartMark: 1550 """Bins the cursor channel's column into buckets. 1551 1552 Returns: 1553 VlChartMark: This mark, so calls chain. 1554 1555 See Also: 1556 maxBins 1557 """ 1558 return self.setOnCursor("bin", VlJson.boolValue(True)); 1559 def maxBins(self, count: int) -> VlChartMark: 1560 """Bins the cursor channel's column into at most this many buckets. 1561 1562 Args: 1563 count (int): The upper bound on the number of bins. 1564 1565 Returns: 1566 VlChartMark: This mark, so calls chain. 1567 1568 See Also: 1569 bin 1570 """ 1571 b = VlJson.objectValue() 1572 b.setMember("maxbins", VlJson.intValue(count)) 1573 return self.setOnCursor("bin", b); 1574 def timeUnit(self, unit: str) -> VlChartMark: 1575 """Which part of an instant to read: `year`, `month`, `yearmonth`, `hours` and the rest. 1576 1577 Args: 1578 unit (str): The time unit. 1579 1580 Returns: 1581 VlChartMark: This mark, so calls chain. 1582 """ 1583 return self.setOnCursor("timeUnit", VlJson.stringValue(unit)); 1584 def _type(self, kind: str) -> VlChartMark: 1585 """States what the column holds, when the data cannot say. 1586 1587 A column of years is numbers and is usually a category, which is the case this 1588 exists for. 1589 1590 Args: 1591 kind (str): `quantitative`, `nominal`, `ordinal` or `temporal`. 1592 1593 Returns: 1594 VlChartMark: This mark, so calls chain. 1595 """ 1596 return self.setOnCursor("type", VlJson.stringValue(kind)); 1597 def title(self, label: str) -> VlChartMark: 1598 """The axis or legend label for the cursor channel. 1599 1600 Args: 1601 label (str): The label. 1602 1603 Returns: 1604 VlChartMark: This mark, so calls chain. 1605 """ 1606 return self.setOnCursor("title", VlJson.stringValue(label)); 1607 def _format(self, pattern: str) -> VlChartMark: 1608 """The number or date format its axis labels are drawn in. 1609 1610 Args: 1611 pattern (str): A d3-format or d3-time-format pattern. 1612 1613 Returns: 1614 VlChartMark: This mark, so calls chain. 1615 """ 1616 axis = VlJson.objectValue() 1617 axis.setMember("format", VlJson.stringValue(pattern)) 1618 return self.setOnCursor("axis", axis); 1619 def stack(self, how: str) -> VlChartMark: 1620 """How marks sharing a position are stacked. 1621 1622 Args: 1623 how (str): `zero`, `normalize` or `center`. 1624 1625 Returns: 1626 VlChartMark: This mark, so calls chain. 1627 1628 See Also: 1629 noStack 1630 """ 1631 return self.setOnCursor("stack", VlJson.stringValue(how)); 1632 def noStack(self) -> VlChartMark: 1633 """Draws the marks overlapping rather than stacked. 1634 1635 Returns: 1636 VlChartMark: This mark, so calls chain. 1637 1638 See Also: 1639 stack 1640 """ 1641 return self.setOnCursor("stack", VlJson.nullValue()); 1642 def sortBy(self, field: str) -> VlChartMark: 1643 """The order a discrete scale runs in, taken from another column. 1644 1645 Args: 1646 field (str): The column to sort by. 1647 1648 Returns: 1649 VlChartMark: This mark, so calls chain. 1650 1651 See Also: 1652 keepOrder 1653 """ 1654 return self.setOnCursor("sort", VlJson.stringValue(field)); 1655 def keepOrder(self) -> VlChartMark: 1656 """Keeps the order the rows arrived in, rather than sorting alphabetically. 1657 1658 The one every spreadsheet wants. 1659 1660 Returns: 1661 VlChartMark: This mark, so calls chain. 1662 1663 See Also: 1664 sortBy 1665 """ 1666 return self.setOnCursor("sort", VlJson.nullValue()); 1667 def scaleJson(self, scale: VlJson) -> VlChartMark: 1668 """Sets the cursor channel's whole scale definition. 1669 1670 Args: 1671 scale (VlJson): The scale definition. 1672 1673 Returns: 1674 VlChartMark: This mark, so calls chain. 1675 """ 1676 return self.setOnCursor("scale", scale); 1677 def scaleType(self, kind: str) -> VlChartMark: 1678 """The kind of scale the cursor channel uses. 1679 1680 Args: 1681 kind (str): `linear`, `log`, `sqrt`, `time`, `band`, `point` and the rest. 1682 1683 Returns: 1684 VlChartMark: This mark, so calls chain. 1685 """ 1686 s = VlJson.objectValue() 1687 s.setMember("type", VlJson.stringValue(kind)) 1688 return self.setOnCursor("scale", s); 1689 def scheme(self, name: str) -> VlChartMark: 1690 """The colour scheme a colour channel draws from. 1691 1692 Args: 1693 name (str): A Vega scheme name, such as `category10` or `viridis`. 1694 1695 Returns: 1696 VlChartMark: This mark, so calls chain. 1697 """ 1698 s = VlJson.objectValue() 1699 s.setMember("scheme", VlJson.stringValue(name)) 1700 return self.setOnCursor("scale", s); 1701 def noLegend(self) -> VlChartMark: 1702 """Draws the cursor channel without a legend. 1703 1704 Returns: 1705 VlChartMark: This mark, so calls chain. 1706 """ 1707 return self.setOnCursor("legend", VlJson.nullValue()); 1708 def noAxis(self) -> VlChartMark: 1709 """Draws the cursor channel without an axis. 1710 1711 Returns: 1712 VlChartMark: This mark, so calls chain. 1713 """ 1714 return self.setOnCursor("axis", VlJson.nullValue()); 1715 def axisOrient(self, side: str) -> VlChartMark: 1716 """Which side of the plot the cursor channel's axis stands on. 1717 1718 A Pareto chart's cumulative line is measured up the right-hand side, which is 1719 the whole point of drawing it there. 1720 1721 Args: 1722 side (str): `left`, `right`, `top` or `bottom`. 1723 1724 Returns: 1725 VlChartMark: This mark, so calls chain. 1726 """ 1727 axis = VlJson.objectValue() 1728 axis.setMember("orient", VlJson.stringValue(side)) 1729 return self.setOnCursor("axis", axis); 1730 def axisJson(self, axis: VlJson) -> VlChartMark: 1731 """Sets the cursor channel's whole axis definition. 1732 1733 Args: 1734 axis (VlJson): The axis definition. 1735 1736 Returns: 1737 VlChartMark: This mark, so calls chain. 1738 """ 1739 return self.setOnCursor("axis", axis); 1740 def propNumber(self, key: str, value: float) -> VlChartMark: 1741 """Sets any numeric property of the mark itself. 1742 1743 Args: 1744 key (str): The property name. 1745 value (float): The value. 1746 1747 Returns: 1748 VlChartMark: This mark, so calls chain. 1749 """ 1750 self.props.setMember(key, VlJson.numberValue(value)) 1751 return self; 1752 def propString(self, key: str, value: str) -> VlChartMark: 1753 """Sets any string property of the mark itself. 1754 1755 Args: 1756 key (str): The property name. 1757 value (str): The value. 1758 1759 Returns: 1760 VlChartMark: This mark, so calls chain. 1761 """ 1762 self.props.setMember(key, VlJson.stringValue(value)) 1763 return self; 1764 def propFlag(self, key: str, value: bool) -> VlChartMark: 1765 """Sets any boolean property of the mark itself. 1766 1767 Args: 1768 key (str): The property name. 1769 value (bool): The value. 1770 1771 Returns: 1772 VlChartMark: This mark, so calls chain. 1773 """ 1774 self.props.setMember(key, VlJson.boolValue(value)) 1775 return self; 1776 def filled(self, value: bool) -> VlChartMark: 1777 """Whether the mark is filled or drawn as an outline. 1778 1779 Args: 1780 value (bool): True to fill. 1781 1782 Returns: 1783 VlChartMark: This mark, so calls chain. 1784 """ 1785 return self.propFlag("filled", value); 1786 def markSize(self, value: float) -> VlChartMark: 1787 """How big every mark is drawn, as one number rather than from a column. 1788 1789 Args: 1790 value (float): The size. 1791 1792 Returns: 1793 VlChartMark: This mark, so calls chain. 1794 1795 See Also: 1796 size 1797 """ 1798 return self.propNumber("size", value); 1799 def markColor(self, value: str) -> VlChartMark: 1800 """Paints every mark one colour, rather than reading a column. 1801 1802 Args: 1803 value (str): A CSS colour. 1804 1805 Returns: 1806 VlChartMark: This mark, so calls chain. 1807 1808 See Also: 1809 color 1810 """ 1811 return self.propString("color", value); 1812 def markOpacity(self, value: float) -> VlChartMark: 1813 """How opaque every mark is drawn, as one number rather than from a column. 1814 1815 Args: 1816 value (float): 0 to 1. 1817 1818 Returns: 1819 VlChartMark: This mark, so calls chain. 1820 1821 See Also: 1822 opacity 1823 """ 1824 return self.propNumber("opacity", value); 1825 def interpolate(self, kind: str) -> VlChartMark: 1826 """How a line joins its points. 1827 1828 Args: 1829 kind (str): `linear`, `monotone`, `step-after`, `basis` and the rest. 1830 1831 Returns: 1832 VlChartMark: This mark, so calls chain. 1833 """ 1834 return self.propString("interpolate", kind); 1835 def withPoints(self, value: bool) -> VlChartMark: 1836 """Draws a line showing the points it was drawn through. 1837 1838 Args: 1839 value (bool): True to show them. 1840 1841 Returns: 1842 VlChartMark: This mark, so calls chain. 1843 """ 1844 return self.propFlag("point", value); 1845 def innerRadius(self, value: float) -> VlChartMark: 1846 """The hole in the middle of an arc, which is what turns a pie into a donut. 1847 1848 Args: 1849 value (float): The inner radius in pixels. 1850 1851 Returns: 1852 VlChartMark: This mark, so calls chain. 1853 """ 1854 return self.propNumber("innerRadius", value); 1855 def cornerRadius(self, value: float) -> VlChartMark: 1856 """How rounded the corners of a bar or a rectangle are. 1857 1858 Args: 1859 value (float): The radius in pixels. 1860 1861 Returns: 1862 VlChartMark: This mark, so calls chain. 1863 """ 1864 return self.propNumber("cornerRadius", value); 1865 def tooltip(self, value: bool) -> VlChartMark: 1866 """Shows every column the mark encodes when the reader points at it. 1867 1868 Args: 1869 value (bool): True to show a tooltip. 1870 1871 Returns: 1872 VlChartMark: This mark, so calls chain. 1873 1874 See Also: 1875 tooltipFields 1876 """ 1877 return self.propFlag("tooltip", value); 1878 def tooltipField(self, field: str) -> VlChartMark: 1879 """Shows one named column as the tooltip. 1880 1881 Args: 1882 field (str): The column name. 1883 1884 Returns: 1885 VlChartMark: This mark, so calls chain. 1886 1887 See Also: 1888 tooltipFields 1889 """ 1890 return self.channel("tooltip", field); 1891 def tooltipFields(self, fields: list[str]) -> VlChartMark: 1892 """Shows several named columns as the tooltip, in the order they should be read. 1893 1894 A list is not a channel, so the cursor does not move onto it: the next `title` 1895 belongs to whatever was named before. 1896 1897 Args: 1898 fields (None): The column names, in reading order. 1899 1900 Returns: 1901 VlChartMark: This mark, so calls chain. 1902 1903 See Also: 1904 tooltip 1905 """ 1906 _list = VlJson.arrayValue() 1907 for field in fields: 1908 one = VlJson.objectValue() 1909 one.setMember("field", VlJson.stringValue(field)) 1910 _list.arr.append(one) 1911 self.enc.setMember("tooltip", _list) 1912 return self; 1913 def thickness(self, value: float) -> VlChartMark: 1914 """How thick a tick is drawn across its band. 1915 1916 A hi-lo-open-close chart's open and close are ticks, and a two-pixel one is 1917 what makes them read as marks rather than as hairlines. 1918 1919 Args: 1920 value (float): The thickness in pixels. 1921 1922 Returns: 1923 VlChartMark: This mark, so calls chain. 1924 """ 1925 return self.propNumber("thickness", value); 1926 def strokeWidth(self, value: float) -> VlChartMark: 1927 """How thick the mark's outline is drawn. 1928 1929 Args: 1930 value (float): The width in pixels. 1931 1932 Returns: 1933 VlChartMark: This mark, so calls chain. 1934 """ 1935 return self.propNumber("strokeWidth", value); 1936 def orient(self, value: str) -> VlChartMark: 1937 """Which way a tick lies, or which way a bar with only one position channel runs. 1938 1939 Args: 1940 value (str): `horizontal` or `vertical`. 1941 1942 Returns: 1943 VlChartMark: This mark, so calls chain. 1944 """ 1945 return self.propString("orient", value); 1946 def extent(self, value: str) -> VlChartMark: 1947 """What an interval mark is computed from. 1948 1949 Args: 1950 value (str): `stderr`, `stdev`, `ci` or `iqr`. 1951 1952 Returns: 1953 VlChartMark: This mark, so calls chain. 1954 """ 1955 return self.propString("extent", value); 1956 def chart(self) -> VlChart: 1957 """Returns to the chart, when the next thing to say is about the view. 1958 1959 Returns: 1960 VlChart: The owning chart, or a fresh empty one if this mark was built without a chart. 1961 """ 1962 if (self.owner is not None): 1963 return self.owner; 1964 empty = VlDataset.create() 1965 return VlChart.create(empty); 1966class VlChart: 1967 """A chart: a dataset, the channels every mark shares, how big it is, and the marks. 1968 1969 The fluent surface is a **writer of specifications**, not the engine. Every 1970 call writes into a specification and `toSpec` hands that specification over; 1971 nothing here computes a scale, a layout or a pixel. There is no path where the 1972 API computes something the engine would have computed differently, because the 1973 API computes nothing at all. 1974 1975 A channel said on the chart is inherited by every mark on it, so a line and the 1976 points on top of it are two marks and one set of axes rather than two charts. 1977 1978 A channel need not state its type — the data says. A column of numbers is a 1979 quantity, a column of ISO dates an instant, anything else a name. A field the 1980 data does not have is an **error** rather than a guess: `errors` is non-empty 1981 and the caller can say so instead of drawing an empty axis. 1982 1983 .. versionadded:: 1.0 1984 1985 See Also: 1986 VlDataset 1987 1988 Example: 1989 data = VlDataset.create() 1990 data.row()._str("region", "North").num("sales", 120) 1991 data.row()._str("region", "South").num("sales", 93) 1992 chart = VlChart.create(data) 1993 chart.size(300, 200) 1994 chart.bar().x("region").y("sales").aggregate("sum") 1995 _spec = chart.toSpec() 1996 1997 Example: 1998 data = VlDataset.create() 1999 data.row()._str("region", "North").num("sales", 120) 2000 chart = VlChart.create(data) 2001 chart.x("region").y("sales").color("region") 2002 chart.area().markOpacity(0.35) 2003 chart.line() 2004 """ 2005 def __init__(self) -> None: 2006 self.data = None 2007 self.marks = [] 2008 self.enc = VlJson.objectValue() 2009 self.cursor = "" 2010 self.props = VlJson.objectValue() 2011 self.transforms = VlJson.arrayValue() 2012 self.cfg = VlJson.objectValue() 2013 self.resolve = VlJson.objectValue() 2014 self.errors = [] 2015 @staticmethod 2016 def create(data: VlDataset) -> VlChart: 2017 """Builds a chart over a dataset. 2018 2019 Args: 2020 data (VlDataset): The rows the chart draws. 2021 2022 Returns: 2023 VlChart: A chart with no marks yet. 2024 2025 See Also: 2026 VlDataset 2027 """ 2028 c = VlChart() 2029 c.data = data; 2030 return c; 2031 @staticmethod 2032 def copyOf(v: VlJson) -> VlJson: 2033 if v.isArray(): 2034 _list = VlJson.arrayValue() 2035 i = 0 2036 n = v.count() 2037 while i < n: 2038 child = v.at(i) 2039 _list.arr.append(VlChart.copyOf(child)) 2040 i = i + 1; 2041 return _list; 2042 if v.isObject(): 2043 obj = VlJson.objectValue() 2044 for ki, k in enumerate(v.keys): 2045 member = v.get(k) 2046 obj.setMember(k, VlChart.copyOf(member)) 2047 return obj; 2048 return v; 2049 @staticmethod 2050 def markValue(m: VlChartMark) -> VlJson: 2051 n = len(m.props.keys) 2052 if n == 0: 2053 return VlJson.stringValue(m.markType); 2054 obj = VlJson.objectValue() 2055 obj.setMember("type", VlJson.stringValue(m.markType)) 2056 for ki, k in enumerate(m.props.keys): 2057 obj.setMember(k, m.props.get(k)) 2058 return obj; 2059 def mark(self, markType: str) -> VlChartMark: 2060 """Adds a mark of any type the compiler knows. 2061 2062 Args: 2063 markType (str): The Vega-Lite mark name. 2064 2065 Returns: 2066 VlChartMark: The new mark, so its channels and properties chain. 2067 """ 2068 m = VlChartMark() 2069 m.markType = markType; 2070 m.owner = self; 2071 self.marks.append(m) 2072 return m; 2073 def bar(self) -> VlChartMark: 2074 """Adds a bar mark to the chart. 2075 2076 A rectangle per row: the bar chart, and with `x2`/`y2` a range. 2077 2078 Returns: 2079 VlChartMark: The new mark, so its channels and properties chain. 2080 """ 2081 return self.mark("bar"); 2082 def line(self) -> VlChartMark: 2083 """Adds a line mark to the chart. 2084 2085 A line joining the rows in order. 2086 2087 Returns: 2088 VlChartMark: The new mark, so its channels and properties chain. 2089 """ 2090 return self.mark("line"); 2091 def area(self) -> VlChartMark: 2092 """Adds an area mark to the chart. 2093 2094 A filled band between a line and a baseline. 2095 2096 Returns: 2097 VlChartMark: The new mark, so its channels and properties chain. 2098 """ 2099 return self.mark("area"); 2100 def point(self) -> VlChartMark: 2101 """Adds a point mark to the chart. 2102 2103 One symbol per row: the scatter plot. 2104 2105 Returns: 2106 VlChartMark: The new mark, so its channels and properties chain. 2107 """ 2108 return self.mark("point"); 2109 def circle(self) -> VlChartMark: 2110 """Adds a circle mark to the chart. 2111 2112 A filled circle per row — `point` with the shape settled. 2113 2114 Returns: 2115 VlChartMark: The new mark, so its channels and properties chain. 2116 """ 2117 return self.mark("circle"); 2118 def square(self) -> VlChartMark: 2119 """Adds a square mark to the chart. 2120 2121 A filled square per row — `point` with the shape settled. 2122 2123 Returns: 2124 VlChartMark: The new mark, so its channels and properties chain. 2125 """ 2126 return self.mark("square"); 2127 def tick(self) -> VlChartMark: 2128 """Adds a tick mark to the chart. 2129 2130 A short stroke per row, across the band it sits in. 2131 2132 Returns: 2133 VlChartMark: The new mark, so its channels and properties chain. 2134 """ 2135 return self.mark("tick"); 2136 def rule(self) -> VlChartMark: 2137 """Adds a rule mark to the chart. 2138 2139 A line at one value, spanning the plot or between `x2`/`y2`. 2140 2141 Returns: 2142 VlChartMark: The new mark, so its channels and properties chain. 2143 """ 2144 return self.mark("rule"); 2145 def rect(self) -> VlChartMark: 2146 """Adds a rect mark to the chart. 2147 2148 A rectangle over two ranges: the heatmap. 2149 2150 Returns: 2151 VlChartMark: The new mark, so its channels and properties chain. 2152 """ 2153 return self.mark("rect"); 2154 def arc(self) -> VlChartMark: 2155 """Adds an arc mark to the chart. 2156 2157 A wedge, which with `theta` is a pie and with `innerRadius` a donut. 2158 2159 Returns: 2160 VlChartMark: The new mark, so its channels and properties chain. 2161 """ 2162 return self.mark("arc"); 2163 def label(self) -> VlChartMark: 2164 """Adds a text mark, which draws the value of its `text` channel. 2165 2166 Returns: 2167 VlChartMark: The new mark, so its channels and properties chain. 2168 """ 2169 return self.mark("text"); 2170 def boxplot(self) -> VlChartMark: 2171 """Adds a boxplot mark to the chart. 2172 2173 A box and whiskers, computed from the rows rather than read off them. 2174 2175 Returns: 2176 VlChartMark: The new mark, so its channels and properties chain. 2177 """ 2178 return self.mark("boxplot"); 2179 def errorbar(self) -> VlChartMark: 2180 """Adds an error bar: an interval computed from the rows rather than read off them. 2181 2182 `extent` decides what the interval is — `stderr` by default, or `stdev`, `ci` 2183 or `iqr`. 2184 2185 Returns: 2186 VlChartMark: The new mark, so its channels and properties chain. 2187 2188 See Also: 2189 errorband 2190 """ 2191 return self.mark("errorbar"); 2192 def errorband(self) -> VlChartMark: 2193 """Adds an error band: the same interval as an error bar, drawn as a filled region. 2194 2195 Returns: 2196 VlChartMark: The new mark, so its channels and properties chain. 2197 2198 See Also: 2199 errorbar 2200 """ 2201 return self.mark("errorband"); 2202 def trail(self) -> VlChartMark: 2203 """Adds a trail mark to the chart. 2204 2205 A line whose width says something: a trail thickens with its `size`. 2206 2207 Returns: 2208 VlChartMark: The new mark, so its channels and properties chain. 2209 """ 2210 return self.mark("trail"); 2211 def image(self) -> VlChartMark: 2212 """Adds an image mark to the chart. 2213 2214 A picture per row, placed by its position channels. 2215 2216 Returns: 2217 VlChartMark: The new mark, so its channels and properties chain. 2218 """ 2219 return self.mark("image"); 2220 def geoshape(self) -> VlChartMark: 2221 """Adds a geoshape mark to the chart. 2222 2223 A map: the shapes come from the data and the projection places them. 2224 2225 Returns: 2226 VlChartMark: The new mark, so its channels and properties chain. 2227 """ 2228 return self.mark("geoshape"); 2229 def latest(self) -> VlChartMark: 2230 """The mark added last, for a caller that built one and let go of it. 2231 2232 A chart with no marks answers a mark belonging to nothing and reports it in 2233 `errors`, rather than quietly adding a `point` nobody asked for. 2234 2235 Returns: 2236 VlChartMark: The last mark added. 2237 """ 2238 n = len(self.marks) 2239 if n > 0: 2240 return self.marks[(n - 1)]; 2241 self.error("the chart has no marks, so there is no last one") 2242 loose = VlChartMark() 2243 loose.owner = self; 2244 return loose; 2245 def channel(self, name: str, field: str) -> VlChart: 2246 """Sets a channel that every mark on this view inherits. 2247 2248 Args: 2249 name (str): The channel name. 2250 field (str): The column name. 2251 2252 Returns: 2253 VlChart: This chart, so calls chain. 2254 """ 2255 ch = VlJson.objectValue() 2256 ch.setMember("field", VlJson.stringValue(field)) 2257 self.enc.setMember(name, ch) 2258 self.cursor = name; 2259 return self; 2260 def x(self, field: str) -> VlChart: 2261 """Position along the horizontal axis. 2262 2263 Names a COLUMN, never a constant. `.color("red")` means a column 2264 called red; painting a mark red is `markColor`. 2265 2266 Args: 2267 field (str): The column name. 2268 2269 Returns: 2270 VlChart: This view, so channels chain. 2271 """ 2272 return self.channel("x", field); 2273 def y(self, field: str) -> VlChart: 2274 """Position along the vertical axis. 2275 2276 Names a COLUMN, never a constant. `.color("red")` means a column 2277 called red; painting a mark red is `markColor`. 2278 2279 Args: 2280 field (str): The column name. 2281 2282 Returns: 2283 VlChart: This view, so channels chain. 2284 """ 2285 return self.channel("y", field); 2286 def color(self, field: str) -> VlChart: 2287 """Colour, and the legend that explains it. 2288 2289 Names a COLUMN, never a constant. `.color("red")` means a column 2290 called red; painting a mark red is `markColor`. 2291 2292 Args: 2293 field (str): The column name. 2294 2295 Returns: 2296 VlChart: This view, so channels chain. 2297 """ 2298 return self.channel("color", field); 2299 def detail(self, field: str) -> VlChart: 2300 """Groups the rows without drawing anything of its own: one line per group, no legend. 2301 2302 Names a COLUMN, never a constant. `.color("red")` means a column 2303 called red; painting a mark red is `markColor`. 2304 2305 Args: 2306 field (str): The column name. 2307 2308 Returns: 2309 VlChart: This view, so channels chain. 2310 """ 2311 return self.channel("detail", field); 2312 def encodeJson(self, channel: str, definition: VlJson) -> VlChart: 2313 """Sets a whole shared channel from an already-built definition. 2314 2315 Args: 2316 channel (str): The channel name. 2317 definition (VlJson): The channel definition. 2318 2319 Returns: 2320 VlChart: This chart, so calls chain. 2321 """ 2322 self.enc.setMember(channel, definition) 2323 self.cursor = channel; 2324 return self; 2325 def on(self, channel: str) -> VlChart: 2326 """Moves the cursor back to a shared channel that is already set. 2327 2328 Args: 2329 channel (str): The channel name. 2330 2331 Returns: 2332 VlChart: This chart, so calls chain. 2333 """ 2334 if self.enc.has(channel): 2335 self.cursor = channel; 2336 else: 2337 self.error(("no channel called '" + channel) + "' has been set on this view") 2338 return self; 2339 def setOnCursor(self, key: str, value: VlJson) -> VlChart: 2340 if len(self.cursor) == 0: 2341 self.error("a channel property was set before any channel was named") 2342 return self; 2343 ch = self.enc.get(self.cursor) 2344 ch.setMember(key, value) 2345 return self; 2346 def _type(self, kind: str) -> VlChart: 2347 """States what a shared channel's column holds, when the data cannot say. 2348 2349 Args: 2350 kind (str): `quantitative`, `nominal`, `ordinal` or `temporal`. 2351 2352 Returns: 2353 VlChart: This chart, so calls chain. 2354 """ 2355 return self.setOnCursor("type", VlJson.stringValue(kind)); 2356 def title(self, label: str) -> VlChart: 2357 """The axis or legend label for the shared cursor channel. 2358 2359 Args: 2360 label (str): The label. 2361 2362 Returns: 2363 VlChart: This chart, so calls chain. 2364 2365 See Also: 2366 heading 2367 """ 2368 return self.setOnCursor("title", VlJson.stringValue(label)); 2369 def timeUnit(self, unit: str) -> VlChart: 2370 """Which part of an instant a shared channel reads. 2371 2372 Args: 2373 unit (str): The time unit. 2374 2375 Returns: 2376 VlChart: This chart, so calls chain. 2377 """ 2378 return self.setOnCursor("timeUnit", VlJson.stringValue(unit)); 2379 def keepOrder(self) -> VlChart: 2380 """Keeps the order the rows arrived in for the shared cursor channel. 2381 2382 Returns: 2383 VlChart: This chart, so calls chain. 2384 """ 2385 return self.setOnCursor("sort", VlJson.nullValue()); 2386 def size(self, width: int, height: int) -> VlChart: 2387 """How big the plotting area is, in pixels. 2388 2389 Args: 2390 width (int): The width. 2391 height (int): The height. 2392 2393 Returns: 2394 VlChart: This chart, so calls chain. 2395 """ 2396 self.props.setMember("width", VlJson.intValue(width)) 2397 self.props.setMember("height", VlJson.intValue(height)) 2398 return self; 2399 def width(self, value: int) -> VlChart: 2400 """How wide the plotting area is, in pixels. 2401 2402 Args: 2403 value (int): The width. 2404 2405 Returns: 2406 VlChart: This chart, so calls chain. 2407 """ 2408 self.props.setMember("width", VlJson.intValue(value)) 2409 return self; 2410 def height(self, value: int) -> VlChart: 2411 """How tall the plotting area is, in pixels. 2412 2413 Args: 2414 value (int): The height. 2415 2416 Returns: 2417 VlChart: This chart, so calls chain. 2418 """ 2419 self.props.setMember("height", VlJson.intValue(value)) 2420 return self; 2421 def heading(self, text: str) -> VlChart: 2422 """The chart's title, drawn above the plot. 2423 2424 Args: 2425 text (str): The title. 2426 2427 Returns: 2428 VlChart: This chart, so calls chain. 2429 2430 See Also: 2431 title 2432 """ 2433 self.props.setMember("title", VlJson.stringValue(text)) 2434 return self; 2435 def background(self, colour: str) -> VlChart: 2436 """The colour behind the plot. 2437 2438 Args: 2439 colour (str): A CSS colour. 2440 2441 Returns: 2442 VlChart: This chart, so calls chain. 2443 """ 2444 self.props.setMember("background", VlJson.stringValue(colour)) 2445 return self; 2446 def propJson(self, key: str, value: VlJson) -> VlChart: 2447 """Sets any top-level property of the specification. 2448 2449 Args: 2450 key (str): The property name. 2451 value (VlJson): The value. 2452 2453 Returns: 2454 VlChart: This chart, so calls chain. 2455 """ 2456 self.props.setMember(key, value) 2457 return self; 2458 def configJson(self, config: VlJson) -> VlChart: 2459 """Merges a configuration block into the specification. 2460 2461 Args: 2462 config (VlJson): The configuration object. 2463 2464 Returns: 2465 VlChart: This chart, so calls chain. 2466 """ 2467 for ki, k in enumerate(config.keys): 2468 self.cfg.setMember(k, config.get(k)) 2469 return self; 2470 def _filter(self, expression: str) -> VlChart: 2471 """Keeps only the rows an expression accepts. 2472 2473 Args: 2474 expression (str): A Vega expression over the row's columns. 2475 2476 Returns: 2477 VlChart: This chart, so calls chain. 2478 """ 2479 t = VlJson.objectValue() 2480 t.setMember("filter", VlJson.stringValue(expression)) 2481 self.transforms.arr.append(t) 2482 return self; 2483 def calculate(self, expression: str, _as: str) -> VlChart: 2484 """Adds a column computed from the others. 2485 2486 Args: 2487 expression (str): A Vega expression over the row's columns. 2488 _as (str): The name of the new column. 2489 2490 Returns: 2491 VlChart: This chart, so calls chain. 2492 """ 2493 t = VlJson.objectValue() 2494 t.setMember("calculate", VlJson.stringValue(expression)) 2495 t.setMember("as", VlJson.stringValue(_as)) 2496 self.transforms.arr.append(t) 2497 return self; 2498 def transformJson(self, transform: VlJson) -> VlChart: 2499 """Appends an already-built transform. 2500 2501 Args: 2502 transform (VlJson): The transform definition. 2503 2504 Returns: 2505 VlChart: This chart, so calls chain. 2506 """ 2507 self.transforms.arr.append(transform) 2508 return self; 2509 def independent(self, channel: str) -> VlChart: 2510 """Stops the layers sharing one scale on a channel. 2511 2512 Two marks measuring different things up the same side of the plot must not 2513 share a scale. This is what makes a Pareto chart — bars against a count, a 2514 line against a running percentage — rather than two series averaged into one 2515 axis neither of them asked for. 2516 2517 Args: 2518 channel (str): The channel to split, usually "y". 2519 2520 Returns: 2521 VlChart: This chart, so calls chain. 2522 """ 2523 scales = self.resolve.get("scale") 2524 if False == scales.isObject(): 2525 fresh = VlJson.objectValue() 2526 self.resolve.setMember("scale", fresh) 2527 scales = fresh; 2528 scales.setMember(channel, VlJson.stringValue("independent")) 2529 return self; 2530 def error(self, message: str) -> None: 2531 for said in self.errors: 2532 if said == message: 2533 return; 2534 self.errors.append(message) 2535 def mergedEncoding(self, m: VlChartMark) -> VlJson: 2536 out = VlJson.objectValue() 2537 for ki, k in enumerate(self.enc.keys): 2538 shared = self.enc.get(k) 2539 out.setMember(k, VlChart.copyOf(shared)) 2540 for mi, mk in enumerate(m.enc.keys): 2541 own = m.enc.get(mk) 2542 out.setMember(mk, VlChart.copyOf(own)) 2543 self.resolveTypes(out) 2544 return out; 2545 def resolveTypes(self, encoding: VlJson) -> None: 2546 for ki, k in enumerate(encoding.keys): 2547 ch = encoding.get(k) 2548 if ch.isArray(): 2549 i = 0 2550 n = ch.count() 2551 while i < n: 2552 one = ch.at(i) 2553 if one.isObject(): 2554 if False == one.has("type"): 2555 listKind = self.inferType(one) 2556 if len(listKind) > 0: 2557 one.setMember("type", VlJson.stringValue(listKind)) 2558 i = i + 1; 2559 if ch.isObject(): 2560 if False == ch.has("type"): 2561 if False == ch.has("value"): 2562 kind = self.inferType(ch) 2563 if len(kind) > 0: 2564 ch.setMember("type", VlJson.stringValue(kind)) 2565 def inferType(self, ch: VlJson) -> str: 2566 if ch.has("bin"): 2567 return "quantitative"; 2568 if ch.has("timeUnit"): 2569 return "temporal"; 2570 if ch.has("aggregate"): 2571 return "quantitative"; 2572 if False == ch.has("field"): 2573 return ""; 2574 field = ch.stringOr("field", "") 2575 if self.data.count() == 0: 2576 return "nominal"; 2577 kind = self.data.fieldType(field) 2578 if len(kind) == 0: 2579 self.error(("the data has no column called '" + field) + "'") 2580 return "nominal"; 2581 return kind; 2582 def toSpec(self) -> VlJson: 2583 """The chart as a Vega-Lite specification. 2584 2585 One mark comes out as a plain specification; several come out as layers, each 2586 carrying the shared channels in full — a specification that states everything 2587 is one the compiler already handles and one a person can read in a diff. 2588 2589 May be called more than once. Check `errors` afterwards: a chart that names a 2590 column its data does not have is reported here, where Vega-Lite would have 2591 drawn an empty axis and said nothing. 2592 2593 Returns: 2594 VlJson: A Vega-Lite specification, ready for `VlCompile`. 2595 2596 Example: 2597 data = VlDataset.create() 2598 data.row()._str("region", "North").num("sales", 120) 2599 data.row()._str("region", "South").num("sales", 93) 2600 chart = VlChart.create(data) 2601 chart.size(300, 200) 2602 chart.bar().x("region").y("sales").aggregate("sum") 2603 _spec = chart.toSpec() 2604 """ 2605 out = VlJson.objectValue() 2606 for ki, k in enumerate(self.props.keys): 2607 out.setMember(k, self.props.get(k)) 2608 out.setMember("data", self.data.toValues()) 2609 if self.transforms.count() > 0: 2610 out.setMember("transform", self.transforms) 2611 markCount = len(self.marks) 2612 if markCount == 0: 2613 self.error("the chart has no marks") 2614 return out; 2615 if markCount == 1: 2616 only = self.marks[0] 2617 out.setMember("mark", VlChart.markValue(only)) 2618 out.setMember("encoding", self.mergedEncoding(only)) 2619 else: 2620 layers = VlJson.arrayValue() 2621 for m in self.marks: 2622 layer = VlJson.objectValue() 2623 layer.setMember("mark", VlChart.markValue(m)) 2624 layer.setMember("encoding", self.mergedEncoding(m)) 2625 layers.arr.append(layer) 2626 out.setMember("layer", layers) 2627 resolveCount = len(self.resolve.keys) 2628 if resolveCount > 0: 2629 out.setMember("resolve", self.resolve) 2630 cfgCount = len(self.cfg.keys) 2631 if cfgCount > 0: 2632 out.setMember("config", self.cfg) 2633 return out; 2634 def toText(self) -> str: 2635 spec = self.toSpec() 2636 w = VlJsonWriter() 2637 return w.write(spec); 2638 2639__docformat__ = "google" 2640 2641 2642# The public API surface, from the `doc { public }` declarations. 2643__all__ = ["VlJson", "VlDataRow", "VlDataset", "VlChartMark", "VlChart"]
24class VlJson: 25 """A JSON value: null, a boolean, a number, text, an array or an object. 26 27 This is the value model the whole of Vela exchanges — a specification arrives 28 as one, the chart API emits one, and the runtime reads one. It is pure Ranger 29 with no host JSON, so the same tree is built on every target, which is what 30 makes a scene comparison against the reference implementation mean anything. 31 32 Two things it carries that a plain JSON model does not: object keys keep the 33 order they were written in, so a re-serialised specification is stable; and a 34 number remembers whether it was written as an integer, so `5` does not come 35 back as `5.0`. 36 """ 37 def __init__(self) -> None: 38 self.kind = 0 39 self.num = 0 40 self.b = False 41 self._str = "" 42 self.arr = [] 43 self.keys = [] 44 self.members = {} 45 self.isInt = False 46 @staticmethod 47 def nullValue() -> VlJson: 48 """Builds the JSON null value. 49 50 Returns: 51 VlJson: A null value. 52 """ 53 v = VlJson() 54 return v; 55 @staticmethod 56 def boolValue(value: bool) -> VlJson: 57 """Builds a JSON boolean. 58 59 Args: 60 value (bool): The boolean. 61 62 Returns: 63 VlJson: A boolean value. 64 """ 65 v = VlJson() 66 v.kind = 1; 67 v.b = value; 68 return v; 69 @staticmethod 70 def numberValue(value: float) -> VlJson: 71 """Builds a JSON number that prints with a fraction, so 5 comes back as `5.0`. 72 73 Args: 74 value (float): The number. 75 76 Returns: 77 VlJson: A number value. 78 79 See Also: 80 intValue 81 """ 82 v = VlJson() 83 v.kind = 2; 84 v.num = value; 85 return v; 86 @staticmethod 87 def intValue(value: int) -> VlJson: 88 """Builds a JSON number that prints without a fraction, so 5 stays `5`. 89 90 JSON has one number type; the text does not. A count written with this prints 91 as a count. 92 93 Args: 94 value (int): The whole number. 95 96 Returns: 97 VlJson: A number value that remembers it was written as an integer. 98 99 See Also: 100 numberValue 101 """ 102 v = VlJson() 103 v.kind = 2; 104 v.num = float(value); 105 v.isInt = True; 106 return v; 107 @staticmethod 108 def stringValue(value: str) -> VlJson: 109 """Builds a JSON string. 110 111 Args: 112 value (str): The text. 113 114 Returns: 115 VlJson: A string value. 116 """ 117 v = VlJson() 118 v.kind = 3; 119 v._str = value; 120 return v; 121 @staticmethod 122 def arrayValue() -> VlJson: 123 """Builds an empty JSON array. 124 125 Returns: 126 VlJson: An array value with no elements. 127 """ 128 v = VlJson() 129 v.kind = 4; 130 return v; 131 @staticmethod 132 def objectValue() -> VlJson: 133 """Builds an empty JSON object. 134 135 Returns: 136 VlJson: An object value with no members. 137 """ 138 v = VlJson() 139 v.kind = 5; 140 return v; 141 @staticmethod 142 def numberToText(value: float, wasInt: bool) -> str: 143 return VlJson.formatNumber(value, 6); 144 @staticmethod 145 def formatSignificant(value: float, digits: int) -> str: 146 m = value 147 if m < 0: 148 m = 0 - m; 149 whole = 1 150 while m >= 10: 151 m = r_div_f64(m, 10); 152 whole = whole + 1; 153 decimals = digits - whole 154 if decimals < 0: 155 decimals = 0; 156 return VlJson.formatNumber(value, decimals); 157 @staticmethod 158 def withMinusSign(text: str) -> str: 159 if len(text) == 0: 160 return text; 161 if text[0:1] == "-": 162 return chr(8722) + text[1:len(text)]; 163 return text; 164 @staticmethod 165 def domainKey(cell: VlJson) -> str: 166 if cell.isNull(): 167 return "null"; 168 return cell.asString(); 169 @staticmethod 170 def formatNumber(value: float, maxDecimals: int) -> str: 171 v = value 172 if False == (value == value): 173 return "NaN"; 174 if v == 0: 175 return "0"; 176 if value * 0.5 == value: 177 if value > 0: 178 return "Infinity"; 179 return "-Infinity"; 180 neg = False 181 if v < 0: 182 neg = True; 183 v = 0 - v; 184 if v >= 1000000000: 185 place = 1 186 while r_div_f64(v, place) >= 10: 187 place = place * 10; 188 big = "" 189 rest = v 190 while place >= 1: 191 big = big + VlJson.digitChar(VlJson.digitAt(rest, place)); 192 rest = rest - float(VlJson.digitAt(rest, place)) * place; 193 place = r_div_f64(place, 10); 194 tail = VlJson.fractionDigits(rest, maxDecimals) 195 if len(tail) > 0: 196 big = (big + ".") + tail; 197 if neg: 198 return "-" + big; 199 return big; 200 scale = 1 201 k = 0 202 while k < maxDecimals: 203 scale = scale * 10; 204 k = k + 1; 205 whole = math.floor(v) 206 frac = v - float(whole) 207 if frac == 0: 208 if neg: 209 return "-" + VlJson.intToText(whole); 210 return VlJson.intToText(whole); 211 units = frac * scale + 0.5 212 if False == (units < scale): 213 whole = whole + 1; 214 units = 0; 215 out = VlJson.intToText(whole) 216 fracText = "" 217 place_1 = scale 218 rest_1 = units 219 i = 0 220 while i < maxDecimals: 221 place_1 = r_div_f64(place_1, 10); 222 digit = math.floor(r_div_f64(rest_1, place_1)) 223 rest_1 = rest_1 - float(digit) * place_1; 224 fracText = fracText + VlJson.digitChar(digit); 225 i = i + 1; 226 end = len(fracText) 227 stop = False 228 while end > 0 and False == stop: 229 if ord(fracText[(end - 1)]) == 48: 230 end = end - 1; 231 else: 232 stop = True; 233 if end > 0: 234 out = (out + ".") + fracText[0:end]; 235 if neg: 236 return "-" + out; 237 return out; 238 @staticmethod 239 def digitAt(rest: float, place: float) -> int: 240 digit = math.floor(r_div_f64(rest, place)) 241 if digit > 9: 242 return 9; 243 if digit < 0: 244 return 0; 245 return digit; 246 @staticmethod 247 def fractionDigits(frac: float, maxDecimals: int) -> str: 248 out = "" 249 rest = frac 250 place = 0.1 251 i = 0 252 while i < maxDecimals: 253 digit = VlJson.digitAt(rest, place) 254 out = out + VlJson.digitChar(digit); 255 rest = rest - float(digit) * place; 256 place = r_div_f64(place, 10); 257 i = i + 1; 258 end = len(out) 259 stop = False 260 while end > 0 and False == stop: 261 if out[(end - 1):end] == "0": 262 end = end - 1; 263 else: 264 stop = True; 265 return out[0:end]; 266 @staticmethod 267 def intToText(value: int) -> str: 268 if value <= 0: 269 return "0"; 270 v = value 271 digits = "" 272 while v > 0: 273 _next = ((v) // (10)) 274 digit = v - _next * 10 275 digits = VlJson.digitChar(digit) + digits; 276 v = _next; 277 return digits; 278 @staticmethod 279 def digitChar(d: int) -> str: 280 if d <= 0: 281 return "0"; 282 if d == 1: 283 return "1"; 284 if d == 2: 285 return "2"; 286 if d == 3: 287 return "3"; 288 if d == 4: 289 return "4"; 290 if d == 5: 291 return "5"; 292 if d == 6: 293 return "6"; 294 if d == 7: 295 return "7"; 296 if d == 8: 297 return "8"; 298 return "9"; 299 def isNull(self) -> bool: 300 return self.kind == 0; 301 def isBool(self) -> bool: 302 return self.kind == 1; 303 def isNumber(self) -> bool: 304 return self.kind == 2; 305 def isString(self) -> bool: 306 return self.kind == 3; 307 def isArray(self) -> bool: 308 return self.kind == 4; 309 def isObject(self) -> bool: 310 return self.kind == 5; 311 def isDefined(self) -> bool: 312 return self.kind != 0; 313 def looksNumeric(self) -> bool: 314 if self.kind == 2: 315 return True; 316 if self.kind != 3: 317 return False; 318 if len(self._str) == 0: 319 return False; 320 d = r_str_to_double(self._str) 321 if d is not None: 322 return True; 323 return False; 324 def asInt(self) -> int: 325 return math.floor(self.num); 326 def asDouble(self) -> float: 327 if self.kind == 2: 328 return self.num; 329 if self.kind == 1: 330 if self.b: 331 return 1; 332 return 0; 333 if self.kind == 3: 334 d = r_str_to_double(self._str) 335 if d is not None: 336 return d; 337 return 0; 338 def asString(self) -> str: 339 if self.kind == 3: 340 return self._str; 341 if self.kind == 4: 342 joined = "" 343 k = 0 344 while k < len(self.arr): 345 if k > 0: 346 joined = joined + "\n"; 347 joined = joined + self.arr[k].asString(); 348 k = k + 1; 349 return joined; 350 if self.kind == 2: 351 return VlJson.numberToText(self.num, self.isInt); 352 if self.kind == 1: 353 if self.b: 354 return "true"; 355 return "false"; 356 return ""; 357 def asBool(self) -> bool: 358 if self.kind == 1: 359 return self.b; 360 if self.kind == 2: 361 return self.num != 0; 362 if self.kind == 3: 363 return len(self._str) > 0; 364 return False; 365 def count(self) -> int: 366 return len(self.arr); 367 def at(self, index: int) -> VlJson: 368 if index < 0: 369 return VlJson.nullValue(); 370 if index >= len(self.arr): 371 return VlJson.nullValue(); 372 return self.arr[index]; 373 def has(self, key: str) -> bool: 374 return key in self.members; 375 def get(self, key: str) -> VlJson: 376 if key in self.members: 377 return self.members.get(key); 378 return VlJson.nullValue(); 379 def intOr(self, key: str, dflt: int) -> int: 380 if key in self.members: 381 v = self.members.get(key) 382 if v.kind == 2: 383 return math.floor(v.num); 384 return dflt; 385 def doubleOr(self, key: str, dflt: float) -> float: 386 if key in self.members: 387 v = self.members.get(key) 388 if v.kind == 2: 389 return v.num; 390 return dflt; 391 def stringOr(self, key: str, dflt: str) -> str: 392 if key in self.members: 393 v = self.members.get(key) 394 if v.kind == 3: 395 return v._str; 396 return dflt; 397 def boolOr(self, key: str, dflt: bool) -> bool: 398 if key in self.members: 399 v = self.members.get(key) 400 if v.kind == 1: 401 return v.b; 402 return dflt; 403 def setMember(self, key: str, value: VlJson) -> None: 404 if False == (key in self.members): 405 self.keys.append(key) 406 self.members[key] = value; 407 def removeMember(self, key: str) -> None: 408 if False == (key in self.members): 409 return; 410 kept = [] 411 fresh = {} 412 for k in self.keys: 413 if k != key: 414 kept.append(k) 415 fresh[k] = self.members.get(k); 416 self.keys = kept; 417 self.members = fresh;
A JSON value: null, a boolean, a number, text, an array or an object.
This is the value model the whole of Vela exchanges — a specification arrives as one, the chart API emits one, and the runtime reads one. It is pure Ranger with no host JSON, so the same tree is built on every target, which is what makes a scene comparison against the reference implementation mean anything.
Two things it carries that a plain JSON model does not: object keys keep the
order they were written in, so a re-serialised specification is stable; and a
number remembers whether it was written as an integer, so 5 does not come
back as 5.0.
46 @staticmethod 47 def nullValue() -> VlJson: 48 """Builds the JSON null value. 49 50 Returns: 51 VlJson: A null value. 52 """ 53 v = VlJson() 54 return v;
Builds the JSON null value.
Returns:
VlJson: A null value.
55 @staticmethod 56 def boolValue(value: bool) -> VlJson: 57 """Builds a JSON boolean. 58 59 Args: 60 value (bool): The boolean. 61 62 Returns: 63 VlJson: A boolean value. 64 """ 65 v = VlJson() 66 v.kind = 1; 67 v.b = value; 68 return v;
Builds a JSON boolean.
Arguments:
- value (bool): The boolean.
Returns:
VlJson: A boolean value.
69 @staticmethod 70 def numberValue(value: float) -> VlJson: 71 """Builds a JSON number that prints with a fraction, so 5 comes back as `5.0`. 72 73 Args: 74 value (float): The number. 75 76 Returns: 77 VlJson: A number value. 78 79 See Also: 80 intValue 81 """ 82 v = VlJson() 83 v.kind = 2; 84 v.num = value; 85 return v;
Builds a JSON number that prints with a fraction, so 5 comes back as 5.0.
Arguments:
- value (float): The number.
Returns:
VlJson: A number value.
See Also:
intValue
86 @staticmethod 87 def intValue(value: int) -> VlJson: 88 """Builds a JSON number that prints without a fraction, so 5 stays `5`. 89 90 JSON has one number type; the text does not. A count written with this prints 91 as a count. 92 93 Args: 94 value (int): The whole number. 95 96 Returns: 97 VlJson: A number value that remembers it was written as an integer. 98 99 See Also: 100 numberValue 101 """ 102 v = VlJson() 103 v.kind = 2; 104 v.num = float(value); 105 v.isInt = True; 106 return v;
Builds a JSON number that prints without a fraction, so 5 stays 5.
JSON has one number type; the text does not. A count written with this prints as a count.
Arguments:
- value (int): The whole number.
Returns:
VlJson: A number value that remembers it was written as an integer.
See Also:
numberValue
107 @staticmethod 108 def stringValue(value: str) -> VlJson: 109 """Builds a JSON string. 110 111 Args: 112 value (str): The text. 113 114 Returns: 115 VlJson: A string value. 116 """ 117 v = VlJson() 118 v.kind = 3; 119 v._str = value; 120 return v;
Builds a JSON string.
Arguments:
- value (str): The text.
Returns:
VlJson: A string value.
121 @staticmethod 122 def arrayValue() -> VlJson: 123 """Builds an empty JSON array. 124 125 Returns: 126 VlJson: An array value with no elements. 127 """ 128 v = VlJson() 129 v.kind = 4; 130 return v;
Builds an empty JSON array.
Returns:
VlJson: An array value with no elements.
131 @staticmethod 132 def objectValue() -> VlJson: 133 """Builds an empty JSON object. 134 135 Returns: 136 VlJson: An object value with no members. 137 """ 138 v = VlJson() 139 v.kind = 5; 140 return v;
Builds an empty JSON object.
Returns:
VlJson: An object value with no members.
144 @staticmethod 145 def formatSignificant(value: float, digits: int) -> str: 146 m = value 147 if m < 0: 148 m = 0 - m; 149 whole = 1 150 while m >= 10: 151 m = r_div_f64(m, 10); 152 whole = whole + 1; 153 decimals = digits - whole 154 if decimals < 0: 155 decimals = 0; 156 return VlJson.formatNumber(value, decimals);
169 @staticmethod 170 def formatNumber(value: float, maxDecimals: int) -> str: 171 v = value 172 if False == (value == value): 173 return "NaN"; 174 if v == 0: 175 return "0"; 176 if value * 0.5 == value: 177 if value > 0: 178 return "Infinity"; 179 return "-Infinity"; 180 neg = False 181 if v < 0: 182 neg = True; 183 v = 0 - v; 184 if v >= 1000000000: 185 place = 1 186 while r_div_f64(v, place) >= 10: 187 place = place * 10; 188 big = "" 189 rest = v 190 while place >= 1: 191 big = big + VlJson.digitChar(VlJson.digitAt(rest, place)); 192 rest = rest - float(VlJson.digitAt(rest, place)) * place; 193 place = r_div_f64(place, 10); 194 tail = VlJson.fractionDigits(rest, maxDecimals) 195 if len(tail) > 0: 196 big = (big + ".") + tail; 197 if neg: 198 return "-" + big; 199 return big; 200 scale = 1 201 k = 0 202 while k < maxDecimals: 203 scale = scale * 10; 204 k = k + 1; 205 whole = math.floor(v) 206 frac = v - float(whole) 207 if frac == 0: 208 if neg: 209 return "-" + VlJson.intToText(whole); 210 return VlJson.intToText(whole); 211 units = frac * scale + 0.5 212 if False == (units < scale): 213 whole = whole + 1; 214 units = 0; 215 out = VlJson.intToText(whole) 216 fracText = "" 217 place_1 = scale 218 rest_1 = units 219 i = 0 220 while i < maxDecimals: 221 place_1 = r_div_f64(place_1, 10); 222 digit = math.floor(r_div_f64(rest_1, place_1)) 223 rest_1 = rest_1 - float(digit) * place_1; 224 fracText = fracText + VlJson.digitChar(digit); 225 i = i + 1; 226 end = len(fracText) 227 stop = False 228 while end > 0 and False == stop: 229 if ord(fracText[(end - 1)]) == 48: 230 end = end - 1; 231 else: 232 stop = True; 233 if end > 0: 234 out = (out + ".") + fracText[0:end]; 235 if neg: 236 return "-" + out; 237 return out;
246 @staticmethod 247 def fractionDigits(frac: float, maxDecimals: int) -> str: 248 out = "" 249 rest = frac 250 place = 0.1 251 i = 0 252 while i < maxDecimals: 253 digit = VlJson.digitAt(rest, place) 254 out = out + VlJson.digitChar(digit); 255 rest = rest - float(digit) * place; 256 place = r_div_f64(place, 10); 257 i = i + 1; 258 end = len(out) 259 stop = False 260 while end > 0 and False == stop: 261 if out[(end - 1):end] == "0": 262 end = end - 1; 263 else: 264 stop = True; 265 return out[0:end];
278 @staticmethod 279 def digitChar(d: int) -> str: 280 if d <= 0: 281 return "0"; 282 if d == 1: 283 return "1"; 284 if d == 2: 285 return "2"; 286 if d == 3: 287 return "3"; 288 if d == 4: 289 return "4"; 290 if d == 5: 291 return "5"; 292 if d == 6: 293 return "6"; 294 if d == 7: 295 return "7"; 296 if d == 8: 297 return "8"; 298 return "9";
338 def asString(self) -> str: 339 if self.kind == 3: 340 return self._str; 341 if self.kind == 4: 342 joined = "" 343 k = 0 344 while k < len(self.arr): 345 if k > 0: 346 joined = joined + "\n"; 347 joined = joined + self.arr[k].asString(); 348 k = k + 1; 349 return joined; 350 if self.kind == 2: 351 return VlJson.numberToText(self.num, self.isInt); 352 if self.kind == 1: 353 if self.b: 354 return "true"; 355 return "false"; 356 return "";
796class VlDataRow: 797 """One row of a dataset, filled column by column. 798 799 A row is handed back already attached to its dataset, so nothing has to be 800 pushed anywhere by the caller. 801 802 See Also: 803 VlDataset 804 805 Example: 806 data = VlDataset.create() 807 data.row()._str("region", "North").num("sales", 120) 808 data.row()._str("region", "South").num("sales", 93) 809 """ 810 def __init__(self) -> None: 811 self.obj = VlJson.objectValue() 812 self.owner = None 813 def num(self, field: str, value: float) -> VlDataRow: 814 """Puts a number in one column of this row. 815 816 Args: 817 field (str): The column name. 818 value (float): The value. 819 820 Returns: 821 VlDataRow: This row, so columns chain. 822 """ 823 self.obj.setMember(field, VlJson.numberValue(value)) 824 return self; 825 def whole(self, field: str, value: int) -> VlDataRow: 826 """Puts a whole number in one column of this row. 827 828 A count is an integer and prints as one: 12, not 12.0. Use this rather than 829 `num` wherever the value counts things, or the axis labels will say so. 830 831 Args: 832 field (str): The column name. 833 value (int): The value. 834 835 Returns: 836 VlDataRow: This row, so columns chain. 837 838 See Also: 839 num 840 """ 841 self.obj.setMember(field, VlJson.intValue(value)) 842 return self; 843 def _str(self, field: str, value: str) -> VlDataRow: 844 """Puts text in one column of this row. 845 846 A column of text is read as a category unless every value in it parses as an 847 ISO date, in which case it is an instant. 848 849 Args: 850 field (str): The column name. 851 value (str): The value. 852 853 Returns: 854 VlDataRow: This row, so columns chain. 855 """ 856 self.obj.setMember(field, VlJson.stringValue(value)) 857 return self; 858 def flag(self, field: str, value: bool) -> VlDataRow: 859 """Puts true or false in one column of this row. 860 861 Args: 862 field (str): The column name. 863 value (bool): The value. 864 865 Returns: 866 VlDataRow: This row, so columns chain. 867 """ 868 self.obj.setMember(field, VlJson.boolValue(value)) 869 return self; 870 def json(self, field: str, value: VlJson) -> VlDataRow: 871 """Puts an already-built value in one column of this row. 872 873 The escape hatch for a column this API has no typed setter for — a nested 874 object a geoshape reads, or a value that came out of the parser. 875 876 Args: 877 field (str): The column name. 878 value (VlJson): The value, as the JSON model holds it. 879 880 Returns: 881 VlDataRow: This row, so columns chain. 882 """ 883 self.obj.setMember(field, value) 884 return self; 885 def back(self) -> VlDataset: 886 """Returns to the dataset this row belongs to, so rows chain one after another. 887 888 Returns: 889 VlDataset: The owning dataset, or a fresh empty one if this row was built without a dataset. 890 """ 891 if (self.owner is not None): 892 return self.owner; 893 return VlDataset.create();
One row of a dataset, filled column by column.
A row is handed back already attached to its dataset, so nothing has to be pushed anywhere by the caller.
See Also:
VlDataset
Example:
data = VlDataset.create() data.row()._str("region", "North").num("sales", 120) data.row()._str("region", "South").num("sales", 93)
813 def num(self, field: str, value: float) -> VlDataRow: 814 """Puts a number in one column of this row. 815 816 Args: 817 field (str): The column name. 818 value (float): The value. 819 820 Returns: 821 VlDataRow: This row, so columns chain. 822 """ 823 self.obj.setMember(field, VlJson.numberValue(value)) 824 return self;
Puts a number in one column of this row.
Arguments:
- field (str): The column name.
- value (float): The value.
Returns:
VlDataRow: This row, so columns chain.
825 def whole(self, field: str, value: int) -> VlDataRow: 826 """Puts a whole number in one column of this row. 827 828 A count is an integer and prints as one: 12, not 12.0. Use this rather than 829 `num` wherever the value counts things, or the axis labels will say so. 830 831 Args: 832 field (str): The column name. 833 value (int): The value. 834 835 Returns: 836 VlDataRow: This row, so columns chain. 837 838 See Also: 839 num 840 """ 841 self.obj.setMember(field, VlJson.intValue(value)) 842 return self;
Puts a whole number in one column of this row.
A count is an integer and prints as one: 12, not 12.0. Use this rather than
num wherever the value counts things, or the axis labels will say so.
Arguments:
- field (str): The column name.
- value (int): The value.
Returns:
VlDataRow: This row, so columns chain.
See Also:
num
858 def flag(self, field: str, value: bool) -> VlDataRow: 859 """Puts true or false in one column of this row. 860 861 Args: 862 field (str): The column name. 863 value (bool): The value. 864 865 Returns: 866 VlDataRow: This row, so columns chain. 867 """ 868 self.obj.setMember(field, VlJson.boolValue(value)) 869 return self;
Puts true or false in one column of this row.
Arguments:
- field (str): The column name.
- value (bool): The value.
Returns:
VlDataRow: This row, so columns chain.
870 def json(self, field: str, value: VlJson) -> VlDataRow: 871 """Puts an already-built value in one column of this row. 872 873 The escape hatch for a column this API has no typed setter for — a nested 874 object a geoshape reads, or a value that came out of the parser. 875 876 Args: 877 field (str): The column name. 878 value (VlJson): The value, as the JSON model holds it. 879 880 Returns: 881 VlDataRow: This row, so columns chain. 882 """ 883 self.obj.setMember(field, value) 884 return self;
Puts an already-built value in one column of this row.
The escape hatch for a column this API has no typed setter for — a nested object a geoshape reads, or a value that came out of the parser.
Arguments:
- field (str): The column name.
- value (VlJson): The value, as the JSON model holds it.
Returns:
VlDataRow: This row, so columns chain.
885 def back(self) -> VlDataset: 886 """Returns to the dataset this row belongs to, so rows chain one after another. 887 888 Returns: 889 VlDataset: The owning dataset, or a fresh empty one if this row was built without a dataset. 890 """ 891 if (self.owner is not None): 892 return self.owner; 893 return VlDataset.create();
Returns to the dataset this row belongs to, so rows chain one after another.
Returns:
VlDataset: The owning dataset, or a fresh empty one if this row was built without a dataset.
894class VlDataset: 895 """A table of rows, built once and given to as many charts as want it. 896 897 Rows are JSON objects — the same values the parser produces for 898 `"data": {"values": […]}` — so a dataset built here and one read off disk are 899 the same thing to everything downstream. 900 901 The dataset is a value **beside** the chart rather than a thing inside it: a 902 spreadsheet's selection becomes one dataset and a dashboard's six panels read 903 it. 904 905 See Also: 906 VlChart 907 908 Example: 909 data = VlDataset.create() 910 data.row()._str("region", "North").num("sales", 120) 911 data.row()._str("region", "South").num("sales", 93) 912 """ 913 def __init__(self) -> None: 914 self.rows = [] 915 self.name = "" 916 @staticmethod 917 def create() -> VlDataset: 918 """Builds an empty dataset. 919 920 Returns: 921 VlDataset: A dataset with no rows. 922 """ 923 d = VlDataset() 924 return d; 925 @staticmethod 926 def looksLikeDate(text: str) -> bool: 927 n = len(text) 928 if n < 6 or n > 40: 929 return False; 930 i = 0 931 while i < 4: 932 c = ord(text[i]) 933 if c < 48 or c > 57: 934 return False; 935 i = i + 1; 936 sep = ord(text[4]) 937 if sep != 45: 938 return False; 939 d = ord(text[5]) 940 if d < 48 or d > 57: 941 return False; 942 return True; 943 def row(self) -> VlDataRow: 944 """Adds a row and hands it back, ready to be filled. 945 946 Returns: 947 VlDataRow: The new row, already attached to this dataset. 948 949 See Also: 950 VlDataRow 951 """ 952 r = VlDataRow() 953 r.owner = self; 954 self.rows.append(r.obj) 955 return r; 956 def addRow(self, row: VlJson) -> VlDataset: 957 """Adds a row that was built elsewhere. 958 959 Args: 960 row (VlJson): A JSON object whose members are the columns. 961 962 Returns: 963 VlDataset: This dataset, so calls chain. 964 """ 965 self.rows.append(row) 966 return self; 967 def fromValues(self, values: VlJson) -> VlDataset: 968 """Takes the rows of a JSON array as they came out of the parser. 969 970 A dataset built here and one read off disk are the same thing to everything 971 downstream, so a selection from a grid, a file somebody read and a literal all 972 arrive the same way. 973 974 Args: 975 values (VlJson): A JSON array of row objects. 976 977 Returns: 978 VlDataset: This dataset, so calls chain. 979 """ 980 i = 0 981 n = values.count() 982 while i < n: 983 self.rows.append(values.at(i)) 984 i = i + 1; 985 return self; 986 def numbers(self, field: str, values: list[float]) -> VlDataset: 987 """Fills one numeric column from an array, one value per row. 988 989 Column-wise filling, for a caller that holds arrays rather than records — a 990 spreadsheet column, a series of measurements. Row `i` of every column is the 991 same row, so two calls with arrays of the same length make a table. 992 993 Args: 994 field (str): The column name. 995 values (None): One value per row, in row order. 996 997 Returns: 998 VlDataset: This dataset, so calls chain. 999 1000 See Also: 1001 strings 1002 """ 1003 for i, v in enumerate(values): 1004 r = self.rowAt(i) 1005 r.setMember(field, VlJson.numberValue(v)) 1006 return self; 1007 def strings(self, field: str, values: list[str]) -> VlDataset: 1008 """Fills one text column from an array, one value per row. 1009 1010 Args: 1011 field (str): The column name. 1012 values (None): One value per row, in row order. 1013 1014 Returns: 1015 VlDataset: This dataset, so calls chain. 1016 1017 See Also: 1018 numbers 1019 """ 1020 for i, v in enumerate(values): 1021 r = self.rowAt(i) 1022 r.setMember(field, VlJson.stringValue(v)) 1023 return self; 1024 def rowAt(self, index: int) -> VlJson: 1025 """The row at an index, growing the dataset with empty rows if it is not there yet. 1026 1027 Args: 1028 index (int): A zero-based row number. 1029 1030 Returns: 1031 VlJson: The row object, which can be written into directly. 1032 """ 1033 while len(self.rows) <= index: 1034 self.rows.append(VlJson.objectValue()) 1035 return self.rows[index]; 1036 def count(self) -> int: 1037 """How many rows the dataset holds. 1038 1039 Returns: 1040 int: The row count. 1041 """ 1042 return len(self.rows); 1043 def hasField(self, field: str) -> bool: 1044 """Whether any row has this column. 1045 1046 Args: 1047 field (str): The column name. 1048 1049 Returns: 1050 bool: True when at least one row carries the column. 1051 """ 1052 for r in self.rows: 1053 if r.has(field): 1054 return True; 1055 return False; 1056 def fieldType(self, field: str) -> str: 1057 """What kind of thing a column holds, in Vega-Lite's vocabulary. 1058 1059 Read off the rows rather than declared: numbers are a quantity, ISO dates are 1060 an instant, anything else is a name. A column the data does not have answers 1061 the empty string, so a caller can tell "no such column" from "a column of 1062 names" — which is the difference between a mistake and a chart. 1063 1064 Args: 1065 field (str): The column name. 1066 1067 Returns: 1068 str: `quantitative`, `temporal`, `nominal`, or the empty string when no row has the column. 1069 """ 1070 sawNumber = False 1071 sawText = False 1072 sawDate = False 1073 sawAny = False 1074 for r in self.rows: 1075 if r.has(field): 1076 v = r.get(field) 1077 if False == v.isNull(): 1078 sawAny = True; 1079 if v.isNumber(): 1080 sawNumber = True; 1081 if v.isString(): 1082 sawText = True; 1083 if VlDataset.looksLikeDate(v._str): 1084 sawDate = True; 1085 if False == sawAny: 1086 return ""; 1087 if sawText: 1088 if sawDate: 1089 return "temporal"; 1090 return "nominal"; 1091 if sawNumber: 1092 return "quantitative"; 1093 return "nominal"; 1094 def toValues(self) -> VlJson: 1095 """The dataset as the `data` block of a specification: `{"values": […]}`. 1096 1097 Returns: 1098 VlJson: A JSON object holding every row. 1099 """ 1100 _list = VlJson.arrayValue() 1101 for r in self.rows: 1102 _list.arr.append(r) 1103 obj = VlJson.objectValue() 1104 obj.setMember("values", _list) 1105 return obj;
A table of rows, built once and given to as many charts as want it.
Rows are JSON objects — the same values the parser produces for
"data": {"values": […]} — so a dataset built here and one read off disk are
the same thing to everything downstream.
The dataset is a value beside the chart rather than a thing inside it: a spreadsheet's selection becomes one dataset and a dashboard's six panels read it.
See Also:
VlChart
Example:
data = VlDataset.create() data.row()._str("region", "North").num("sales", 120) data.row()._str("region", "South").num("sales", 93)
916 @staticmethod 917 def create() -> VlDataset: 918 """Builds an empty dataset. 919 920 Returns: 921 VlDataset: A dataset with no rows. 922 """ 923 d = VlDataset() 924 return d;
Builds an empty dataset.
Returns:
VlDataset: A dataset with no rows.
925 @staticmethod 926 def looksLikeDate(text: str) -> bool: 927 n = len(text) 928 if n < 6 or n > 40: 929 return False; 930 i = 0 931 while i < 4: 932 c = ord(text[i]) 933 if c < 48 or c > 57: 934 return False; 935 i = i + 1; 936 sep = ord(text[4]) 937 if sep != 45: 938 return False; 939 d = ord(text[5]) 940 if d < 48 or d > 57: 941 return False; 942 return True;
943 def row(self) -> VlDataRow: 944 """Adds a row and hands it back, ready to be filled. 945 946 Returns: 947 VlDataRow: The new row, already attached to this dataset. 948 949 See Also: 950 VlDataRow 951 """ 952 r = VlDataRow() 953 r.owner = self; 954 self.rows.append(r.obj) 955 return r;
Adds a row and hands it back, ready to be filled.
Returns:
VlDataRow: The new row, already attached to this dataset.
See Also:
VlDataRow
956 def addRow(self, row: VlJson) -> VlDataset: 957 """Adds a row that was built elsewhere. 958 959 Args: 960 row (VlJson): A JSON object whose members are the columns. 961 962 Returns: 963 VlDataset: This dataset, so calls chain. 964 """ 965 self.rows.append(row) 966 return self;
Adds a row that was built elsewhere.
Arguments:
- row (VlJson): A JSON object whose members are the columns.
Returns:
VlDataset: This dataset, so calls chain.
967 def fromValues(self, values: VlJson) -> VlDataset: 968 """Takes the rows of a JSON array as they came out of the parser. 969 970 A dataset built here and one read off disk are the same thing to everything 971 downstream, so a selection from a grid, a file somebody read and a literal all 972 arrive the same way. 973 974 Args: 975 values (VlJson): A JSON array of row objects. 976 977 Returns: 978 VlDataset: This dataset, so calls chain. 979 """ 980 i = 0 981 n = values.count() 982 while i < n: 983 self.rows.append(values.at(i)) 984 i = i + 1; 985 return self;
Takes the rows of a JSON array as they came out of the parser.
A dataset built here and one read off disk are the same thing to everything downstream, so a selection from a grid, a file somebody read and a literal all arrive the same way.
Arguments:
- values (VlJson): A JSON array of row objects.
Returns:
VlDataset: This dataset, so calls chain.
986 def numbers(self, field: str, values: list[float]) -> VlDataset: 987 """Fills one numeric column from an array, one value per row. 988 989 Column-wise filling, for a caller that holds arrays rather than records — a 990 spreadsheet column, a series of measurements. Row `i` of every column is the 991 same row, so two calls with arrays of the same length make a table. 992 993 Args: 994 field (str): The column name. 995 values (None): One value per row, in row order. 996 997 Returns: 998 VlDataset: This dataset, so calls chain. 999 1000 See Also: 1001 strings 1002 """ 1003 for i, v in enumerate(values): 1004 r = self.rowAt(i) 1005 r.setMember(field, VlJson.numberValue(v)) 1006 return self;
Fills one numeric column from an array, one value per row.
Column-wise filling, for a caller that holds arrays rather than records — a
spreadsheet column, a series of measurements. Row i of every column is the
same row, so two calls with arrays of the same length make a table.
Arguments:
- field (str): The column name.
- values (None): One value per row, in row order.
Returns:
VlDataset: This dataset, so calls chain.
See Also:
strings
1007 def strings(self, field: str, values: list[str]) -> VlDataset: 1008 """Fills one text column from an array, one value per row. 1009 1010 Args: 1011 field (str): The column name. 1012 values (None): One value per row, in row order. 1013 1014 Returns: 1015 VlDataset: This dataset, so calls chain. 1016 1017 See Also: 1018 numbers 1019 """ 1020 for i, v in enumerate(values): 1021 r = self.rowAt(i) 1022 r.setMember(field, VlJson.stringValue(v)) 1023 return self;
Fills one text column from an array, one value per row.
Arguments:
- field (str): The column name.
- values (None): One value per row, in row order.
Returns:
VlDataset: This dataset, so calls chain.
See Also:
numbers
1024 def rowAt(self, index: int) -> VlJson: 1025 """The row at an index, growing the dataset with empty rows if it is not there yet. 1026 1027 Args: 1028 index (int): A zero-based row number. 1029 1030 Returns: 1031 VlJson: The row object, which can be written into directly. 1032 """ 1033 while len(self.rows) <= index: 1034 self.rows.append(VlJson.objectValue()) 1035 return self.rows[index];
The row at an index, growing the dataset with empty rows if it is not there yet.
Arguments:
- index (int): A zero-based row number.
Returns:
VlJson: The row object, which can be written into directly.
1036 def count(self) -> int: 1037 """How many rows the dataset holds. 1038 1039 Returns: 1040 int: The row count. 1041 """ 1042 return len(self.rows);
How many rows the dataset holds.
Returns:
int: The row count.
1043 def hasField(self, field: str) -> bool: 1044 """Whether any row has this column. 1045 1046 Args: 1047 field (str): The column name. 1048 1049 Returns: 1050 bool: True when at least one row carries the column. 1051 """ 1052 for r in self.rows: 1053 if r.has(field): 1054 return True; 1055 return False;
Whether any row has this column.
Arguments:
- field (str): The column name.
Returns:
bool: True when at least one row carries the column.
1056 def fieldType(self, field: str) -> str: 1057 """What kind of thing a column holds, in Vega-Lite's vocabulary. 1058 1059 Read off the rows rather than declared: numbers are a quantity, ISO dates are 1060 an instant, anything else is a name. A column the data does not have answers 1061 the empty string, so a caller can tell "no such column" from "a column of 1062 names" — which is the difference between a mistake and a chart. 1063 1064 Args: 1065 field (str): The column name. 1066 1067 Returns: 1068 str: `quantitative`, `temporal`, `nominal`, or the empty string when no row has the column. 1069 """ 1070 sawNumber = False 1071 sawText = False 1072 sawDate = False 1073 sawAny = False 1074 for r in self.rows: 1075 if r.has(field): 1076 v = r.get(field) 1077 if False == v.isNull(): 1078 sawAny = True; 1079 if v.isNumber(): 1080 sawNumber = True; 1081 if v.isString(): 1082 sawText = True; 1083 if VlDataset.looksLikeDate(v._str): 1084 sawDate = True; 1085 if False == sawAny: 1086 return ""; 1087 if sawText: 1088 if sawDate: 1089 return "temporal"; 1090 return "nominal"; 1091 if sawNumber: 1092 return "quantitative"; 1093 return "nominal";
What kind of thing a column holds, in Vega-Lite's vocabulary.
Read off the rows rather than declared: numbers are a quantity, ISO dates are an instant, anything else is a name. A column the data does not have answers the empty string, so a caller can tell "no such column" from "a column of names" — which is the difference between a mistake and a chart.
Arguments:
- field (str): The column name.
Returns:
str:
quantitative,temporal,nominal, or the empty string when no row has the column.
1094 def toValues(self) -> VlJson: 1095 """The dataset as the `data` block of a specification: `{"values": […]}`. 1096 1097 Returns: 1098 VlJson: A JSON object holding every row. 1099 """ 1100 _list = VlJson.arrayValue() 1101 for r in self.rows: 1102 _list.arr.append(r) 1103 obj = VlJson.objectValue() 1104 obj.setMember("values", _list) 1105 return obj;
The dataset as the data block of a specification: {"values": […]}.
Returns:
VlJson: A JSON object holding every row.
1106class VlChartMark: 1107 """One mark and the channels it reads. 1108 1109 Every setter answers the mark, so a mark is written as one sentence. 1110 1111 `aggregate`, `bin`, `title` and the rest apply to the channel most recently 1112 named — the cursor — which is what makes that sentence read in the order it is 1113 thought. `on` moves the cursor back to a channel already set. 1114 1115 A channel names a **column**. A constant goes through `valueNumber` or 1116 `valueString`, and the two are kept apart on purpose: `.color("red")` meaning a 1117 column called red and `.color("#c00")` meaning paint it red cannot both be 1118 true, and the version that guesses is the one that draws a chart nobody asked 1119 for. 1120 1121 See Also: 1122 VlChart 1123 1124 Example: 1125 data = VlDataset.create() 1126 data.row()._str("region", "North").num("sales", 120) 1127 chart = VlChart.create(data) 1128 chart.bar().x("region").y("sales").aggregate("sum").title("Total sales") 1129 """ 1130 def __init__(self) -> None: 1131 self.markType = "point" 1132 self.props = VlJson.objectValue() 1133 self.enc = VlJson.objectValue() 1134 self.cursor = "" 1135 self.owner = None 1136 def note(self, message: str) -> None: 1137 if (self.owner is not None): 1138 o = self.owner 1139 o.error(message) 1140 def channel(self, name: str, field: str) -> VlChartMark: 1141 """Sets any channel to a column by name. 1142 1143 The named channel becomes the cursor, so the next `aggregate`, `title` or 1144 `type` applies to it. 1145 1146 Args: 1147 name (str): The channel name, as Vega-Lite spells it. 1148 field (str): The column name. 1149 1150 Returns: 1151 VlChartMark: This mark, so calls chain. 1152 """ 1153 ch = VlJson.objectValue() 1154 ch.setMember("field", VlJson.stringValue(field)) 1155 self.enc.setMember(name, ch) 1156 self.cursor = name; 1157 return self; 1158 def x(self, field: str) -> VlChartMark: 1159 """Position along the horizontal axis. 1160 1161 Names a COLUMN, never a constant. `.color("red")` means a column 1162 called red; painting a mark red is `markColor`. 1163 1164 Args: 1165 field (str): The column name. 1166 1167 Returns: 1168 VlChartMark: This mark, so channels chain. 1169 """ 1170 return self.channel("x", field); 1171 def y(self, field: str) -> VlChartMark: 1172 """Position along the vertical axis. 1173 1174 Names a COLUMN, never a constant. `.color("red")` means a column 1175 called red; painting a mark red is `markColor`. 1176 1177 Args: 1178 field (str): The column name. 1179 1180 Returns: 1181 VlChartMark: This mark, so channels chain. 1182 """ 1183 return self.channel("y", field); 1184 def x2(self, field: str) -> VlChartMark: 1185 """The far end of a horizontal interval, for a bar, an area or a rule that spans two values. 1186 1187 Names a COLUMN, never a constant. `.color("red")` means a column 1188 called red; painting a mark red is `markColor`. 1189 1190 Args: 1191 field (str): The column name. 1192 1193 Returns: 1194 VlChartMark: This mark, so channels chain. 1195 1196 See Also: 1197 x 1198 """ 1199 return self.channel("x2", field); 1200 def y2(self, field: str) -> VlChartMark: 1201 """The far end of a vertical interval, for a bar, an area or a rule that spans two values. 1202 1203 Names a COLUMN, never a constant. `.color("red")` means a column 1204 called red; painting a mark red is `markColor`. 1205 1206 Args: 1207 field (str): The column name. 1208 1209 Returns: 1210 VlChartMark: This mark, so channels chain. 1211 1212 See Also: 1213 y 1214 """ 1215 return self.channel("y2", field); 1216 def color(self, field: str) -> VlChartMark: 1217 """Colour, and the legend that explains it. 1218 1219 Names a COLUMN, never a constant. `.color("red")` means a column 1220 called red; painting a mark red is `markColor`. 1221 1222 Args: 1223 field (str): The column name. 1224 1225 Returns: 1226 VlChartMark: This mark, so channels chain. 1227 """ 1228 return self.channel("color", field); 1229 def fill(self, field: str) -> VlChartMark: 1230 """Fill colour, set apart from the outline. 1231 1232 Names a COLUMN, never a constant. `.color("red")` means a column 1233 called red; painting a mark red is `markColor`. 1234 1235 Args: 1236 field (str): The column name. 1237 1238 Returns: 1239 VlChartMark: This mark, so channels chain. 1240 1241 See Also: 1242 stroke 1243 """ 1244 return self.channel("fill", field); 1245 def stroke(self, field: str) -> VlChartMark: 1246 """Outline colour, set apart from the fill. 1247 1248 Names a COLUMN, never a constant. `.color("red")` means a column 1249 called red; painting a mark red is `markColor`. 1250 1251 Args: 1252 field (str): The column name. 1253 1254 Returns: 1255 VlChartMark: This mark, so channels chain. 1256 1257 See Also: 1258 fill 1259 """ 1260 return self.channel("stroke", field); 1261 def size(self, field: str) -> VlChartMark: 1262 """Mark size: the area of a point, the width of a trail. 1263 1264 Names a COLUMN, never a constant. `.color("red")` means a column 1265 called red; painting a mark red is `markColor`. 1266 1267 Args: 1268 field (str): The column name. 1269 1270 Returns: 1271 VlChartMark: This mark, so channels chain. 1272 1273 See Also: 1274 markSize 1275 """ 1276 return self.channel("size", field); 1277 def shape(self, field: str) -> VlChartMark: 1278 """The symbol a point is drawn as. 1279 1280 Names a COLUMN, never a constant. `.color("red")` means a column 1281 called red; painting a mark red is `markColor`. 1282 1283 Args: 1284 field (str): The column name. 1285 1286 Returns: 1287 VlChartMark: This mark, so channels chain. 1288 """ 1289 return self.channel("shape", field); 1290 def opacity(self, field: str) -> VlChartMark: 1291 """How opaque the mark is. 1292 1293 Names a COLUMN, never a constant. `.color("red")` means a column 1294 called red; painting a mark red is `markColor`. 1295 1296 Args: 1297 field (str): The column name. 1298 1299 Returns: 1300 VlChartMark: This mark, so channels chain. 1301 1302 See Also: 1303 markOpacity 1304 """ 1305 return self.channel("opacity", field); 1306 def theta(self, field: str) -> VlChartMark: 1307 """The angle an arc covers, which is what makes a pie or a donut. 1308 1309 Names a COLUMN, never a constant. `.color("red")` means a column 1310 called red; painting a mark red is `markColor`. 1311 1312 Args: 1313 field (str): The column name. 1314 1315 Returns: 1316 VlChartMark: This mark, so channels chain. 1317 1318 See Also: 1319 radius 1320 """ 1321 return self.channel("theta", field); 1322 def radius(self, field: str) -> VlChartMark: 1323 """How far from the centre an arc reaches. 1324 1325 Names a COLUMN, never a constant. `.color("red")` means a column 1326 called red; painting a mark red is `markColor`. 1327 1328 Args: 1329 field (str): The column name. 1330 1331 Returns: 1332 VlChartMark: This mark, so channels chain. 1333 1334 See Also: 1335 theta 1336 """ 1337 return self.channel("radius", field); 1338 def detail(self, field: str) -> VlChartMark: 1339 """Groups the rows without drawing anything of its own: one line per group, no legend. 1340 1341 Names a COLUMN, never a constant. `.color("red")` means a column 1342 called red; painting a mark red is `markColor`. 1343 1344 Args: 1345 field (str): The column name. 1346 1347 Returns: 1348 VlChartMark: This mark, so channels chain. 1349 """ 1350 return self.channel("detail", field); 1351 def text(self, field: str) -> VlChartMark: 1352 """The text a label mark shows. 1353 1354 Names a COLUMN, never a constant. `.color("red")` means a column 1355 called red; painting a mark red is `markColor`. 1356 1357 Args: 1358 field (str): The column name. 1359 1360 Returns: 1361 VlChartMark: This mark, so channels chain. 1362 """ 1363 return self.channel("text", field); 1364 def order(self, field: str) -> VlChartMark: 1365 """The order the rows are drawn in, and the order a line joins its points. 1366 1367 Names a COLUMN, never a constant. `.color("red")` means a column 1368 called red; painting a mark red is `markColor`. 1369 1370 Args: 1371 field (str): The column name. 1372 1373 Returns: 1374 VlChartMark: This mark, so channels chain. 1375 """ 1376 return self.channel("order", field); 1377 def column(self, field: str) -> VlChartMark: 1378 """Splits the chart into side-by-side panels, one per value. 1379 1380 Names a COLUMN, never a constant. `.color("red")` means a column 1381 called red; painting a mark red is `markColor`. 1382 1383 Args: 1384 field (str): The column name. 1385 1386 Returns: 1387 VlChartMark: This mark, so channels chain. 1388 1389 See Also: 1390 row 1391 """ 1392 return self.channel("column", field); 1393 def row(self, field: str) -> VlChartMark: 1394 """Splits the chart into stacked panels, one per value. 1395 1396 Names a COLUMN, never a constant. `.color("red")` means a column 1397 called red; painting a mark red is `markColor`. 1398 1399 Args: 1400 field (str): The column name. 1401 1402 Returns: 1403 VlChartMark: This mark, so channels chain. 1404 1405 See Also: 1406 column 1407 """ 1408 return self.channel("row", field); 1409 def xOffset(self, field: str) -> VlChartMark: 1410 """What separates the bars of a grouped bar chart, across the horizontal axis. 1411 1412 Names a COLUMN, never a constant. `.color("red")` means a column 1413 called red; painting a mark red is `markColor`. 1414 1415 Args: 1416 field (str): The column name. 1417 1418 Returns: 1419 VlChartMark: This mark, so channels chain. 1420 1421 See Also: 1422 yOffset 1423 """ 1424 return self.channel("xOffset", field); 1425 def yOffset(self, field: str) -> VlChartMark: 1426 """What separates the bars of a grouped bar chart, across the vertical axis. 1427 1428 Names a COLUMN, never a constant. `.color("red")` means a column 1429 called red; painting a mark red is `markColor`. 1430 1431 Args: 1432 field (str): The column name. 1433 1434 Returns: 1435 VlChartMark: This mark, so channels chain. 1436 1437 See Also: 1438 xOffset 1439 """ 1440 return self.channel("yOffset", field); 1441 def count(self, channel: str) -> VlChartMark: 1442 """Sets a channel to a count of rows: one number per group, with no column to read. 1443 1444 Args: 1445 channel (str): The channel to put the count on, usually "y" or "x". 1446 1447 Returns: 1448 VlChartMark: This mark, so calls chain. 1449 """ 1450 ch = VlJson.objectValue() 1451 ch.setMember("aggregate", VlJson.stringValue("count")) 1452 ch.setMember("type", VlJson.stringValue("quantitative")) 1453 self.enc.setMember(channel, ch) 1454 self.cursor = channel; 1455 return self; 1456 def valueNumber(self, channel: str, value: float) -> VlChartMark: 1457 """Sets a channel to a constant number rather than to a column. 1458 1459 Args: 1460 channel (str): The channel name. 1461 value (float): The constant. 1462 1463 Returns: 1464 VlChartMark: This mark, so calls chain. 1465 1466 See Also: 1467 valueString 1468 """ 1469 ch = VlJson.objectValue() 1470 ch.setMember("value", VlJson.numberValue(value)) 1471 self.enc.setMember(channel, ch) 1472 self.cursor = channel; 1473 return self; 1474 def valueString(self, channel: str, value: str) -> VlChartMark: 1475 """Sets a channel to a constant string rather than to a column. 1476 1477 This is how a mark is painted a fixed colour: `.valueString("color" "#c00")`. 1478 The channel setters name columns and never constants, because a `.color(…)` 1479 that guessed between the two would draw a chart nobody asked for. 1480 1481 Args: 1482 channel (str): The channel name. 1483 value (str): The constant. 1484 1485 Returns: 1486 VlChartMark: This mark, so calls chain. 1487 1488 See Also: 1489 valueNumber 1490 """ 1491 ch = VlJson.objectValue() 1492 ch.setMember("value", VlJson.stringValue(value)) 1493 self.enc.setMember(channel, ch) 1494 self.cursor = channel; 1495 return self; 1496 def encodeJson(self, channel: str, definition: VlJson) -> VlChartMark: 1497 """Sets a whole channel from an already-built definition. 1498 1499 The escape hatch. Vega-Lite is larger than any fluent surface over it, and a 1500 definition that lands in the same specification is better than waiting for this 1501 API to grow a method. 1502 1503 Args: 1504 channel (str): The channel name. 1505 definition (VlJson): The channel definition. 1506 1507 Returns: 1508 VlChartMark: This mark, so calls chain. 1509 """ 1510 self.enc.setMember(channel, definition) 1511 self.cursor = channel; 1512 return self; 1513 def on(self, channel: str) -> VlChartMark: 1514 """Moves the cursor back to a channel that is already set. 1515 1516 Everything that follows — `aggregate`, `title`, `scaleType` — applies to it. 1517 A channel that was never set is reported in the chart's `errors` rather than 1518 silently created. 1519 1520 Args: 1521 channel (str): The channel name. 1522 1523 Returns: 1524 VlChartMark: This mark, so calls chain. 1525 """ 1526 if self.enc.has(channel): 1527 self.cursor = channel; 1528 else: 1529 self.note(("no channel called '" + channel) + "' has been set on this mark") 1530 return self; 1531 def cursorChannel(self) -> VlJson: 1532 if len(self.cursor) == 0: 1533 self.note("a channel property was set before any channel was named") 1534 return VlJson.objectValue(); 1535 return self.enc.get(self.cursor); 1536 def setOnCursor(self, key: str, value: VlJson) -> VlChartMark: 1537 ch = self.cursorChannel() 1538 ch.setMember(key, value) 1539 return self; 1540 def aggregate(self, op: str) -> VlChartMark: 1541 """How the rows in each group are reduced to one value. 1542 1543 Args: 1544 op (str): `sum`, `mean`, `median`, `min`, `max`, `count` and the rest of Vega-Lite's operations. 1545 1546 Returns: 1547 VlChartMark: This mark, so calls chain. 1548 """ 1549 return self.setOnCursor("aggregate", VlJson.stringValue(op)); 1550 def _bin(self) -> VlChartMark: 1551 """Bins the cursor channel's column into buckets. 1552 1553 Returns: 1554 VlChartMark: This mark, so calls chain. 1555 1556 See Also: 1557 maxBins 1558 """ 1559 return self.setOnCursor("bin", VlJson.boolValue(True)); 1560 def maxBins(self, count: int) -> VlChartMark: 1561 """Bins the cursor channel's column into at most this many buckets. 1562 1563 Args: 1564 count (int): The upper bound on the number of bins. 1565 1566 Returns: 1567 VlChartMark: This mark, so calls chain. 1568 1569 See Also: 1570 bin 1571 """ 1572 b = VlJson.objectValue() 1573 b.setMember("maxbins", VlJson.intValue(count)) 1574 return self.setOnCursor("bin", b); 1575 def timeUnit(self, unit: str) -> VlChartMark: 1576 """Which part of an instant to read: `year`, `month`, `yearmonth`, `hours` and the rest. 1577 1578 Args: 1579 unit (str): The time unit. 1580 1581 Returns: 1582 VlChartMark: This mark, so calls chain. 1583 """ 1584 return self.setOnCursor("timeUnit", VlJson.stringValue(unit)); 1585 def _type(self, kind: str) -> VlChartMark: 1586 """States what the column holds, when the data cannot say. 1587 1588 A column of years is numbers and is usually a category, which is the case this 1589 exists for. 1590 1591 Args: 1592 kind (str): `quantitative`, `nominal`, `ordinal` or `temporal`. 1593 1594 Returns: 1595 VlChartMark: This mark, so calls chain. 1596 """ 1597 return self.setOnCursor("type", VlJson.stringValue(kind)); 1598 def title(self, label: str) -> VlChartMark: 1599 """The axis or legend label for the cursor channel. 1600 1601 Args: 1602 label (str): The label. 1603 1604 Returns: 1605 VlChartMark: This mark, so calls chain. 1606 """ 1607 return self.setOnCursor("title", VlJson.stringValue(label)); 1608 def _format(self, pattern: str) -> VlChartMark: 1609 """The number or date format its axis labels are drawn in. 1610 1611 Args: 1612 pattern (str): A d3-format or d3-time-format pattern. 1613 1614 Returns: 1615 VlChartMark: This mark, so calls chain. 1616 """ 1617 axis = VlJson.objectValue() 1618 axis.setMember("format", VlJson.stringValue(pattern)) 1619 return self.setOnCursor("axis", axis); 1620 def stack(self, how: str) -> VlChartMark: 1621 """How marks sharing a position are stacked. 1622 1623 Args: 1624 how (str): `zero`, `normalize` or `center`. 1625 1626 Returns: 1627 VlChartMark: This mark, so calls chain. 1628 1629 See Also: 1630 noStack 1631 """ 1632 return self.setOnCursor("stack", VlJson.stringValue(how)); 1633 def noStack(self) -> VlChartMark: 1634 """Draws the marks overlapping rather than stacked. 1635 1636 Returns: 1637 VlChartMark: This mark, so calls chain. 1638 1639 See Also: 1640 stack 1641 """ 1642 return self.setOnCursor("stack", VlJson.nullValue()); 1643 def sortBy(self, field: str) -> VlChartMark: 1644 """The order a discrete scale runs in, taken from another column. 1645 1646 Args: 1647 field (str): The column to sort by. 1648 1649 Returns: 1650 VlChartMark: This mark, so calls chain. 1651 1652 See Also: 1653 keepOrder 1654 """ 1655 return self.setOnCursor("sort", VlJson.stringValue(field)); 1656 def keepOrder(self) -> VlChartMark: 1657 """Keeps the order the rows arrived in, rather than sorting alphabetically. 1658 1659 The one every spreadsheet wants. 1660 1661 Returns: 1662 VlChartMark: This mark, so calls chain. 1663 1664 See Also: 1665 sortBy 1666 """ 1667 return self.setOnCursor("sort", VlJson.nullValue()); 1668 def scaleJson(self, scale: VlJson) -> VlChartMark: 1669 """Sets the cursor channel's whole scale definition. 1670 1671 Args: 1672 scale (VlJson): The scale definition. 1673 1674 Returns: 1675 VlChartMark: This mark, so calls chain. 1676 """ 1677 return self.setOnCursor("scale", scale); 1678 def scaleType(self, kind: str) -> VlChartMark: 1679 """The kind of scale the cursor channel uses. 1680 1681 Args: 1682 kind (str): `linear`, `log`, `sqrt`, `time`, `band`, `point` and the rest. 1683 1684 Returns: 1685 VlChartMark: This mark, so calls chain. 1686 """ 1687 s = VlJson.objectValue() 1688 s.setMember("type", VlJson.stringValue(kind)) 1689 return self.setOnCursor("scale", s); 1690 def scheme(self, name: str) -> VlChartMark: 1691 """The colour scheme a colour channel draws from. 1692 1693 Args: 1694 name (str): A Vega scheme name, such as `category10` or `viridis`. 1695 1696 Returns: 1697 VlChartMark: This mark, so calls chain. 1698 """ 1699 s = VlJson.objectValue() 1700 s.setMember("scheme", VlJson.stringValue(name)) 1701 return self.setOnCursor("scale", s); 1702 def noLegend(self) -> VlChartMark: 1703 """Draws the cursor channel without a legend. 1704 1705 Returns: 1706 VlChartMark: This mark, so calls chain. 1707 """ 1708 return self.setOnCursor("legend", VlJson.nullValue()); 1709 def noAxis(self) -> VlChartMark: 1710 """Draws the cursor channel without an axis. 1711 1712 Returns: 1713 VlChartMark: This mark, so calls chain. 1714 """ 1715 return self.setOnCursor("axis", VlJson.nullValue()); 1716 def axisOrient(self, side: str) -> VlChartMark: 1717 """Which side of the plot the cursor channel's axis stands on. 1718 1719 A Pareto chart's cumulative line is measured up the right-hand side, which is 1720 the whole point of drawing it there. 1721 1722 Args: 1723 side (str): `left`, `right`, `top` or `bottom`. 1724 1725 Returns: 1726 VlChartMark: This mark, so calls chain. 1727 """ 1728 axis = VlJson.objectValue() 1729 axis.setMember("orient", VlJson.stringValue(side)) 1730 return self.setOnCursor("axis", axis); 1731 def axisJson(self, axis: VlJson) -> VlChartMark: 1732 """Sets the cursor channel's whole axis definition. 1733 1734 Args: 1735 axis (VlJson): The axis definition. 1736 1737 Returns: 1738 VlChartMark: This mark, so calls chain. 1739 """ 1740 return self.setOnCursor("axis", axis); 1741 def propNumber(self, key: str, value: float) -> VlChartMark: 1742 """Sets any numeric property of the mark itself. 1743 1744 Args: 1745 key (str): The property name. 1746 value (float): The value. 1747 1748 Returns: 1749 VlChartMark: This mark, so calls chain. 1750 """ 1751 self.props.setMember(key, VlJson.numberValue(value)) 1752 return self; 1753 def propString(self, key: str, value: str) -> VlChartMark: 1754 """Sets any string property of the mark itself. 1755 1756 Args: 1757 key (str): The property name. 1758 value (str): The value. 1759 1760 Returns: 1761 VlChartMark: This mark, so calls chain. 1762 """ 1763 self.props.setMember(key, VlJson.stringValue(value)) 1764 return self; 1765 def propFlag(self, key: str, value: bool) -> VlChartMark: 1766 """Sets any boolean property of the mark itself. 1767 1768 Args: 1769 key (str): The property name. 1770 value (bool): The value. 1771 1772 Returns: 1773 VlChartMark: This mark, so calls chain. 1774 """ 1775 self.props.setMember(key, VlJson.boolValue(value)) 1776 return self; 1777 def filled(self, value: bool) -> VlChartMark: 1778 """Whether the mark is filled or drawn as an outline. 1779 1780 Args: 1781 value (bool): True to fill. 1782 1783 Returns: 1784 VlChartMark: This mark, so calls chain. 1785 """ 1786 return self.propFlag("filled", value); 1787 def markSize(self, value: float) -> VlChartMark: 1788 """How big every mark is drawn, as one number rather than from a column. 1789 1790 Args: 1791 value (float): The size. 1792 1793 Returns: 1794 VlChartMark: This mark, so calls chain. 1795 1796 See Also: 1797 size 1798 """ 1799 return self.propNumber("size", value); 1800 def markColor(self, value: str) -> VlChartMark: 1801 """Paints every mark one colour, rather than reading a column. 1802 1803 Args: 1804 value (str): A CSS colour. 1805 1806 Returns: 1807 VlChartMark: This mark, so calls chain. 1808 1809 See Also: 1810 color 1811 """ 1812 return self.propString("color", value); 1813 def markOpacity(self, value: float) -> VlChartMark: 1814 """How opaque every mark is drawn, as one number rather than from a column. 1815 1816 Args: 1817 value (float): 0 to 1. 1818 1819 Returns: 1820 VlChartMark: This mark, so calls chain. 1821 1822 See Also: 1823 opacity 1824 """ 1825 return self.propNumber("opacity", value); 1826 def interpolate(self, kind: str) -> VlChartMark: 1827 """How a line joins its points. 1828 1829 Args: 1830 kind (str): `linear`, `monotone`, `step-after`, `basis` and the rest. 1831 1832 Returns: 1833 VlChartMark: This mark, so calls chain. 1834 """ 1835 return self.propString("interpolate", kind); 1836 def withPoints(self, value: bool) -> VlChartMark: 1837 """Draws a line showing the points it was drawn through. 1838 1839 Args: 1840 value (bool): True to show them. 1841 1842 Returns: 1843 VlChartMark: This mark, so calls chain. 1844 """ 1845 return self.propFlag("point", value); 1846 def innerRadius(self, value: float) -> VlChartMark: 1847 """The hole in the middle of an arc, which is what turns a pie into a donut. 1848 1849 Args: 1850 value (float): The inner radius in pixels. 1851 1852 Returns: 1853 VlChartMark: This mark, so calls chain. 1854 """ 1855 return self.propNumber("innerRadius", value); 1856 def cornerRadius(self, value: float) -> VlChartMark: 1857 """How rounded the corners of a bar or a rectangle are. 1858 1859 Args: 1860 value (float): The radius in pixels. 1861 1862 Returns: 1863 VlChartMark: This mark, so calls chain. 1864 """ 1865 return self.propNumber("cornerRadius", value); 1866 def tooltip(self, value: bool) -> VlChartMark: 1867 """Shows every column the mark encodes when the reader points at it. 1868 1869 Args: 1870 value (bool): True to show a tooltip. 1871 1872 Returns: 1873 VlChartMark: This mark, so calls chain. 1874 1875 See Also: 1876 tooltipFields 1877 """ 1878 return self.propFlag("tooltip", value); 1879 def tooltipField(self, field: str) -> VlChartMark: 1880 """Shows one named column as the tooltip. 1881 1882 Args: 1883 field (str): The column name. 1884 1885 Returns: 1886 VlChartMark: This mark, so calls chain. 1887 1888 See Also: 1889 tooltipFields 1890 """ 1891 return self.channel("tooltip", field); 1892 def tooltipFields(self, fields: list[str]) -> VlChartMark: 1893 """Shows several named columns as the tooltip, in the order they should be read. 1894 1895 A list is not a channel, so the cursor does not move onto it: the next `title` 1896 belongs to whatever was named before. 1897 1898 Args: 1899 fields (None): The column names, in reading order. 1900 1901 Returns: 1902 VlChartMark: This mark, so calls chain. 1903 1904 See Also: 1905 tooltip 1906 """ 1907 _list = VlJson.arrayValue() 1908 for field in fields: 1909 one = VlJson.objectValue() 1910 one.setMember("field", VlJson.stringValue(field)) 1911 _list.arr.append(one) 1912 self.enc.setMember("tooltip", _list) 1913 return self; 1914 def thickness(self, value: float) -> VlChartMark: 1915 """How thick a tick is drawn across its band. 1916 1917 A hi-lo-open-close chart's open and close are ticks, and a two-pixel one is 1918 what makes them read as marks rather than as hairlines. 1919 1920 Args: 1921 value (float): The thickness in pixels. 1922 1923 Returns: 1924 VlChartMark: This mark, so calls chain. 1925 """ 1926 return self.propNumber("thickness", value); 1927 def strokeWidth(self, value: float) -> VlChartMark: 1928 """How thick the mark's outline is drawn. 1929 1930 Args: 1931 value (float): The width in pixels. 1932 1933 Returns: 1934 VlChartMark: This mark, so calls chain. 1935 """ 1936 return self.propNumber("strokeWidth", value); 1937 def orient(self, value: str) -> VlChartMark: 1938 """Which way a tick lies, or which way a bar with only one position channel runs. 1939 1940 Args: 1941 value (str): `horizontal` or `vertical`. 1942 1943 Returns: 1944 VlChartMark: This mark, so calls chain. 1945 """ 1946 return self.propString("orient", value); 1947 def extent(self, value: str) -> VlChartMark: 1948 """What an interval mark is computed from. 1949 1950 Args: 1951 value (str): `stderr`, `stdev`, `ci` or `iqr`. 1952 1953 Returns: 1954 VlChartMark: This mark, so calls chain. 1955 """ 1956 return self.propString("extent", value); 1957 def chart(self) -> VlChart: 1958 """Returns to the chart, when the next thing to say is about the view. 1959 1960 Returns: 1961 VlChart: The owning chart, or a fresh empty one if this mark was built without a chart. 1962 """ 1963 if (self.owner is not None): 1964 return self.owner; 1965 empty = VlDataset.create() 1966 return VlChart.create(empty);
One mark and the channels it reads.
Every setter answers the mark, so a mark is written as one sentence.
aggregate, bin, title and the rest apply to the channel most recently
named — the cursor — which is what makes that sentence read in the order it is
thought. on moves the cursor back to a channel already set.
A channel names a column. A constant goes through valueNumber or
valueString, and the two are kept apart on purpose: .color("red") meaning a
column called red and .color("#c00") meaning paint it red cannot both be
true, and the version that guesses is the one that draws a chart nobody asked
for.
See Also:
VlChart
Example:
data = VlDataset.create() data.row()._str("region", "North").num("sales", 120) chart = VlChart.create(data) chart.bar().x("region").y("sales").aggregate("sum").title("Total sales")
1140 def channel(self, name: str, field: str) -> VlChartMark: 1141 """Sets any channel to a column by name. 1142 1143 The named channel becomes the cursor, so the next `aggregate`, `title` or 1144 `type` applies to it. 1145 1146 Args: 1147 name (str): The channel name, as Vega-Lite spells it. 1148 field (str): The column name. 1149 1150 Returns: 1151 VlChartMark: This mark, so calls chain. 1152 """ 1153 ch = VlJson.objectValue() 1154 ch.setMember("field", VlJson.stringValue(field)) 1155 self.enc.setMember(name, ch) 1156 self.cursor = name; 1157 return self;
1158 def x(self, field: str) -> VlChartMark: 1159 """Position along the horizontal axis. 1160 1161 Names a COLUMN, never a constant. `.color("red")` means a column 1162 called red; painting a mark red is `markColor`. 1163 1164 Args: 1165 field (str): The column name. 1166 1167 Returns: 1168 VlChartMark: This mark, so channels chain. 1169 """ 1170 return self.channel("x", field);
Position along the horizontal axis.
Names a COLUMN, never a constant. .color("red") means a column
called red; painting a mark red is markColor.
Arguments:
- field (str): The column name.
Returns:
VlChartMark: This mark, so channels chain.
1171 def y(self, field: str) -> VlChartMark: 1172 """Position along the vertical axis. 1173 1174 Names a COLUMN, never a constant. `.color("red")` means a column 1175 called red; painting a mark red is `markColor`. 1176 1177 Args: 1178 field (str): The column name. 1179 1180 Returns: 1181 VlChartMark: This mark, so channels chain. 1182 """ 1183 return self.channel("y", field);
Position along the vertical axis.
Names a COLUMN, never a constant. .color("red") means a column
called red; painting a mark red is markColor.
Arguments:
- field (str): The column name.
Returns:
VlChartMark: This mark, so channels chain.
1184 def x2(self, field: str) -> VlChartMark: 1185 """The far end of a horizontal interval, for a bar, an area or a rule that spans two values. 1186 1187 Names a COLUMN, never a constant. `.color("red")` means a column 1188 called red; painting a mark red is `markColor`. 1189 1190 Args: 1191 field (str): The column name. 1192 1193 Returns: 1194 VlChartMark: This mark, so channels chain. 1195 1196 See Also: 1197 x 1198 """ 1199 return self.channel("x2", field);
The far end of a horizontal interval, for a bar, an area or a rule that spans two values.
Names a COLUMN, never a constant. .color("red") means a column
called red; painting a mark red is markColor.
Arguments:
- field (str): The column name.
Returns:
VlChartMark: This mark, so channels chain.
See Also:
x
1200 def y2(self, field: str) -> VlChartMark: 1201 """The far end of a vertical interval, for a bar, an area or a rule that spans two values. 1202 1203 Names a COLUMN, never a constant. `.color("red")` means a column 1204 called red; painting a mark red is `markColor`. 1205 1206 Args: 1207 field (str): The column name. 1208 1209 Returns: 1210 VlChartMark: This mark, so channels chain. 1211 1212 See Also: 1213 y 1214 """ 1215 return self.channel("y2", field);
The far end of a vertical interval, for a bar, an area or a rule that spans two values.
Names a COLUMN, never a constant. .color("red") means a column
called red; painting a mark red is markColor.
Arguments:
- field (str): The column name.
Returns:
VlChartMark: This mark, so channels chain.
See Also:
y
1216 def color(self, field: str) -> VlChartMark: 1217 """Colour, and the legend that explains it. 1218 1219 Names a COLUMN, never a constant. `.color("red")` means a column 1220 called red; painting a mark red is `markColor`. 1221 1222 Args: 1223 field (str): The column name. 1224 1225 Returns: 1226 VlChartMark: This mark, so channels chain. 1227 """ 1228 return self.channel("color", field);
Colour, and the legend that explains it.
Names a COLUMN, never a constant. .color("red") means a column
called red; painting a mark red is markColor.
Arguments:
- field (str): The column name.
Returns:
VlChartMark: This mark, so channels chain.
1229 def fill(self, field: str) -> VlChartMark: 1230 """Fill colour, set apart from the outline. 1231 1232 Names a COLUMN, never a constant. `.color("red")` means a column 1233 called red; painting a mark red is `markColor`. 1234 1235 Args: 1236 field (str): The column name. 1237 1238 Returns: 1239 VlChartMark: This mark, so channels chain. 1240 1241 See Also: 1242 stroke 1243 """ 1244 return self.channel("fill", field);
Fill colour, set apart from the outline.
Names a COLUMN, never a constant. .color("red") means a column
called red; painting a mark red is markColor.
Arguments:
- field (str): The column name.
Returns:
VlChartMark: This mark, so channels chain.
See Also:
stroke
1245 def stroke(self, field: str) -> VlChartMark: 1246 """Outline colour, set apart from the fill. 1247 1248 Names a COLUMN, never a constant. `.color("red")` means a column 1249 called red; painting a mark red is `markColor`. 1250 1251 Args: 1252 field (str): The column name. 1253 1254 Returns: 1255 VlChartMark: This mark, so channels chain. 1256 1257 See Also: 1258 fill 1259 """ 1260 return self.channel("stroke", field);
Outline colour, set apart from the fill.
Names a COLUMN, never a constant. .color("red") means a column
called red; painting a mark red is markColor.
Arguments:
- field (str): The column name.
Returns:
VlChartMark: This mark, so channels chain.
See Also:
fill
1261 def size(self, field: str) -> VlChartMark: 1262 """Mark size: the area of a point, the width of a trail. 1263 1264 Names a COLUMN, never a constant. `.color("red")` means a column 1265 called red; painting a mark red is `markColor`. 1266 1267 Args: 1268 field (str): The column name. 1269 1270 Returns: 1271 VlChartMark: This mark, so channels chain. 1272 1273 See Also: 1274 markSize 1275 """ 1276 return self.channel("size", field);
Mark size: the area of a point, the width of a trail.
Names a COLUMN, never a constant. .color("red") means a column
called red; painting a mark red is markColor.
Arguments:
- field (str): The column name.
Returns:
VlChartMark: This mark, so channels chain.
See Also:
markSize
1277 def shape(self, field: str) -> VlChartMark: 1278 """The symbol a point is drawn as. 1279 1280 Names a COLUMN, never a constant. `.color("red")` means a column 1281 called red; painting a mark red is `markColor`. 1282 1283 Args: 1284 field (str): The column name. 1285 1286 Returns: 1287 VlChartMark: This mark, so channels chain. 1288 """ 1289 return self.channel("shape", field);
The symbol a point is drawn as.
Names a COLUMN, never a constant. .color("red") means a column
called red; painting a mark red is markColor.
Arguments:
- field (str): The column name.
Returns:
VlChartMark: This mark, so channels chain.
1290 def opacity(self, field: str) -> VlChartMark: 1291 """How opaque the mark is. 1292 1293 Names a COLUMN, never a constant. `.color("red")` means a column 1294 called red; painting a mark red is `markColor`. 1295 1296 Args: 1297 field (str): The column name. 1298 1299 Returns: 1300 VlChartMark: This mark, so channels chain. 1301 1302 See Also: 1303 markOpacity 1304 """ 1305 return self.channel("opacity", field);
How opaque the mark is.
Names a COLUMN, never a constant. .color("red") means a column
called red; painting a mark red is markColor.
Arguments:
- field (str): The column name.
Returns:
VlChartMark: This mark, so channels chain.
See Also:
markOpacity
1306 def theta(self, field: str) -> VlChartMark: 1307 """The angle an arc covers, which is what makes a pie or a donut. 1308 1309 Names a COLUMN, never a constant. `.color("red")` means a column 1310 called red; painting a mark red is `markColor`. 1311 1312 Args: 1313 field (str): The column name. 1314 1315 Returns: 1316 VlChartMark: This mark, so channels chain. 1317 1318 See Also: 1319 radius 1320 """ 1321 return self.channel("theta", field);
The angle an arc covers, which is what makes a pie or a donut.
Names a COLUMN, never a constant. .color("red") means a column
called red; painting a mark red is markColor.
Arguments:
- field (str): The column name.
Returns:
VlChartMark: This mark, so channels chain.
See Also:
radius
1322 def radius(self, field: str) -> VlChartMark: 1323 """How far from the centre an arc reaches. 1324 1325 Names a COLUMN, never a constant. `.color("red")` means a column 1326 called red; painting a mark red is `markColor`. 1327 1328 Args: 1329 field (str): The column name. 1330 1331 Returns: 1332 VlChartMark: This mark, so channels chain. 1333 1334 See Also: 1335 theta 1336 """ 1337 return self.channel("radius", field);
How far from the centre an arc reaches.
Names a COLUMN, never a constant. .color("red") means a column
called red; painting a mark red is markColor.
Arguments:
- field (str): The column name.
Returns:
VlChartMark: This mark, so channels chain.
See Also:
theta
1338 def detail(self, field: str) -> VlChartMark: 1339 """Groups the rows without drawing anything of its own: one line per group, no legend. 1340 1341 Names a COLUMN, never a constant. `.color("red")` means a column 1342 called red; painting a mark red is `markColor`. 1343 1344 Args: 1345 field (str): The column name. 1346 1347 Returns: 1348 VlChartMark: This mark, so channels chain. 1349 """ 1350 return self.channel("detail", field);
Groups the rows without drawing anything of its own: one line per group, no legend.
Names a COLUMN, never a constant. .color("red") means a column
called red; painting a mark red is markColor.
Arguments:
- field (str): The column name.
Returns:
VlChartMark: This mark, so channels chain.
1351 def text(self, field: str) -> VlChartMark: 1352 """The text a label mark shows. 1353 1354 Names a COLUMN, never a constant. `.color("red")` means a column 1355 called red; painting a mark red is `markColor`. 1356 1357 Args: 1358 field (str): The column name. 1359 1360 Returns: 1361 VlChartMark: This mark, so channels chain. 1362 """ 1363 return self.channel("text", field);
The text a label mark shows.
Names a COLUMN, never a constant. .color("red") means a column
called red; painting a mark red is markColor.
Arguments:
- field (str): The column name.
Returns:
VlChartMark: This mark, so channels chain.
1364 def order(self, field: str) -> VlChartMark: 1365 """The order the rows are drawn in, and the order a line joins its points. 1366 1367 Names a COLUMN, never a constant. `.color("red")` means a column 1368 called red; painting a mark red is `markColor`. 1369 1370 Args: 1371 field (str): The column name. 1372 1373 Returns: 1374 VlChartMark: This mark, so channels chain. 1375 """ 1376 return self.channel("order", field);
The order the rows are drawn in, and the order a line joins its points.
Names a COLUMN, never a constant. .color("red") means a column
called red; painting a mark red is markColor.
Arguments:
- field (str): The column name.
Returns:
VlChartMark: This mark, so channels chain.
1377 def column(self, field: str) -> VlChartMark: 1378 """Splits the chart into side-by-side panels, one per value. 1379 1380 Names a COLUMN, never a constant. `.color("red")` means a column 1381 called red; painting a mark red is `markColor`. 1382 1383 Args: 1384 field (str): The column name. 1385 1386 Returns: 1387 VlChartMark: This mark, so channels chain. 1388 1389 See Also: 1390 row 1391 """ 1392 return self.channel("column", field);
Splits the chart into side-by-side panels, one per value.
Names a COLUMN, never a constant. .color("red") means a column
called red; painting a mark red is markColor.
Arguments:
- field (str): The column name.
Returns:
VlChartMark: This mark, so channels chain.
See Also:
row
1393 def row(self, field: str) -> VlChartMark: 1394 """Splits the chart into stacked panels, one per value. 1395 1396 Names a COLUMN, never a constant. `.color("red")` means a column 1397 called red; painting a mark red is `markColor`. 1398 1399 Args: 1400 field (str): The column name. 1401 1402 Returns: 1403 VlChartMark: This mark, so channels chain. 1404 1405 See Also: 1406 column 1407 """ 1408 return self.channel("row", field);
Splits the chart into stacked panels, one per value.
Names a COLUMN, never a constant. .color("red") means a column
called red; painting a mark red is markColor.
Arguments:
- field (str): The column name.
Returns:
VlChartMark: This mark, so channels chain.
See Also:
column
1409 def xOffset(self, field: str) -> VlChartMark: 1410 """What separates the bars of a grouped bar chart, across the horizontal axis. 1411 1412 Names a COLUMN, never a constant. `.color("red")` means a column 1413 called red; painting a mark red is `markColor`. 1414 1415 Args: 1416 field (str): The column name. 1417 1418 Returns: 1419 VlChartMark: This mark, so channels chain. 1420 1421 See Also: 1422 yOffset 1423 """ 1424 return self.channel("xOffset", field);
What separates the bars of a grouped bar chart, across the horizontal axis.
Names a COLUMN, never a constant. .color("red") means a column
called red; painting a mark red is markColor.
Arguments:
- field (str): The column name.
Returns:
VlChartMark: This mark, so channels chain.
See Also:
yOffset
1425 def yOffset(self, field: str) -> VlChartMark: 1426 """What separates the bars of a grouped bar chart, across the vertical axis. 1427 1428 Names a COLUMN, never a constant. `.color("red")` means a column 1429 called red; painting a mark red is `markColor`. 1430 1431 Args: 1432 field (str): The column name. 1433 1434 Returns: 1435 VlChartMark: This mark, so channels chain. 1436 1437 See Also: 1438 xOffset 1439 """ 1440 return self.channel("yOffset", field);
What separates the bars of a grouped bar chart, across the vertical axis.
Names a COLUMN, never a constant. .color("red") means a column
called red; painting a mark red is markColor.
Arguments:
- field (str): The column name.
Returns:
VlChartMark: This mark, so channels chain.
See Also:
xOffset
1441 def count(self, channel: str) -> VlChartMark: 1442 """Sets a channel to a count of rows: one number per group, with no column to read. 1443 1444 Args: 1445 channel (str): The channel to put the count on, usually "y" or "x". 1446 1447 Returns: 1448 VlChartMark: This mark, so calls chain. 1449 """ 1450 ch = VlJson.objectValue() 1451 ch.setMember("aggregate", VlJson.stringValue("count")) 1452 ch.setMember("type", VlJson.stringValue("quantitative")) 1453 self.enc.setMember(channel, ch) 1454 self.cursor = channel; 1455 return self;
Sets a channel to a count of rows: one number per group, with no column to read.
Arguments:
- channel (str): The channel to put the count on, usually "y" or "x".
Returns:
VlChartMark: This mark, so calls chain.
1456 def valueNumber(self, channel: str, value: float) -> VlChartMark: 1457 """Sets a channel to a constant number rather than to a column. 1458 1459 Args: 1460 channel (str): The channel name. 1461 value (float): The constant. 1462 1463 Returns: 1464 VlChartMark: This mark, so calls chain. 1465 1466 See Also: 1467 valueString 1468 """ 1469 ch = VlJson.objectValue() 1470 ch.setMember("value", VlJson.numberValue(value)) 1471 self.enc.setMember(channel, ch) 1472 self.cursor = channel; 1473 return self;
Sets a channel to a constant number rather than to a column.
Arguments:
- channel (str): The channel name.
- value (float): The constant.
Returns:
VlChartMark: This mark, so calls chain.
See Also:
valueString
1474 def valueString(self, channel: str, value: str) -> VlChartMark: 1475 """Sets a channel to a constant string rather than to a column. 1476 1477 This is how a mark is painted a fixed colour: `.valueString("color" "#c00")`. 1478 The channel setters name columns and never constants, because a `.color(…)` 1479 that guessed between the two would draw a chart nobody asked for. 1480 1481 Args: 1482 channel (str): The channel name. 1483 value (str): The constant. 1484 1485 Returns: 1486 VlChartMark: This mark, so calls chain. 1487 1488 See Also: 1489 valueNumber 1490 """ 1491 ch = VlJson.objectValue() 1492 ch.setMember("value", VlJson.stringValue(value)) 1493 self.enc.setMember(channel, ch) 1494 self.cursor = channel; 1495 return self;
Sets a channel to a constant string rather than to a column.
This is how a mark is painted a fixed colour: .valueString("color" "#c00").
The channel setters name columns and never constants, because a .color(…)
that guessed between the two would draw a chart nobody asked for.
Arguments:
- channel (str): The channel name.
- value (str): The constant.
Returns:
VlChartMark: This mark, so calls chain.
See Also:
valueNumber
1496 def encodeJson(self, channel: str, definition: VlJson) -> VlChartMark: 1497 """Sets a whole channel from an already-built definition. 1498 1499 The escape hatch. Vega-Lite is larger than any fluent surface over it, and a 1500 definition that lands in the same specification is better than waiting for this 1501 API to grow a method. 1502 1503 Args: 1504 channel (str): The channel name. 1505 definition (VlJson): The channel definition. 1506 1507 Returns: 1508 VlChartMark: This mark, so calls chain. 1509 """ 1510 self.enc.setMember(channel, definition) 1511 self.cursor = channel; 1512 return self;
Sets a whole channel from an already-built definition.
The escape hatch. Vega-Lite is larger than any fluent surface over it, and a definition that lands in the same specification is better than waiting for this API to grow a method.
Arguments:
- channel (str): The channel name.
- definition (VlJson): The channel definition.
Returns:
VlChartMark: This mark, so calls chain.
1513 def on(self, channel: str) -> VlChartMark: 1514 """Moves the cursor back to a channel that is already set. 1515 1516 Everything that follows — `aggregate`, `title`, `scaleType` — applies to it. 1517 A channel that was never set is reported in the chart's `errors` rather than 1518 silently created. 1519 1520 Args: 1521 channel (str): The channel name. 1522 1523 Returns: 1524 VlChartMark: This mark, so calls chain. 1525 """ 1526 if self.enc.has(channel): 1527 self.cursor = channel; 1528 else: 1529 self.note(("no channel called '" + channel) + "' has been set on this mark") 1530 return self;
Moves the cursor back to a channel that is already set.
Everything that follows — aggregate, title, scaleType — applies to it.
A channel that was never set is reported in the chart's errors rather than
silently created.
Arguments:
- channel (str): The channel name.
Returns:
VlChartMark: This mark, so calls chain.
1540 def aggregate(self, op: str) -> VlChartMark: 1541 """How the rows in each group are reduced to one value. 1542 1543 Args: 1544 op (str): `sum`, `mean`, `median`, `min`, `max`, `count` and the rest of Vega-Lite's operations. 1545 1546 Returns: 1547 VlChartMark: This mark, so calls chain. 1548 """ 1549 return self.setOnCursor("aggregate", VlJson.stringValue(op));
How the rows in each group are reduced to one value.
Arguments:
- op (str):
sum,mean,median,min,max,countand the rest of Vega-Lite's operations.
Returns:
VlChartMark: This mark, so calls chain.
1560 def maxBins(self, count: int) -> VlChartMark: 1561 """Bins the cursor channel's column into at most this many buckets. 1562 1563 Args: 1564 count (int): The upper bound on the number of bins. 1565 1566 Returns: 1567 VlChartMark: This mark, so calls chain. 1568 1569 See Also: 1570 bin 1571 """ 1572 b = VlJson.objectValue() 1573 b.setMember("maxbins", VlJson.intValue(count)) 1574 return self.setOnCursor("bin", b);
Bins the cursor channel's column into at most this many buckets.
Arguments:
- count (int): The upper bound on the number of bins.
Returns:
VlChartMark: This mark, so calls chain.
See Also:
bin
1575 def timeUnit(self, unit: str) -> VlChartMark: 1576 """Which part of an instant to read: `year`, `month`, `yearmonth`, `hours` and the rest. 1577 1578 Args: 1579 unit (str): The time unit. 1580 1581 Returns: 1582 VlChartMark: This mark, so calls chain. 1583 """ 1584 return self.setOnCursor("timeUnit", VlJson.stringValue(unit));
Which part of an instant to read: year, month, yearmonth, hours and the rest.
Arguments:
- unit (str): The time unit.
Returns:
VlChartMark: This mark, so calls chain.
1598 def title(self, label: str) -> VlChartMark: 1599 """The axis or legend label for the cursor channel. 1600 1601 Args: 1602 label (str): The label. 1603 1604 Returns: 1605 VlChartMark: This mark, so calls chain. 1606 """ 1607 return self.setOnCursor("title", VlJson.stringValue(label));
The axis or legend label for the cursor channel.
Arguments:
- label (str): The label.
Returns:
VlChartMark: This mark, so calls chain.
1620 def stack(self, how: str) -> VlChartMark: 1621 """How marks sharing a position are stacked. 1622 1623 Args: 1624 how (str): `zero`, `normalize` or `center`. 1625 1626 Returns: 1627 VlChartMark: This mark, so calls chain. 1628 1629 See Also: 1630 noStack 1631 """ 1632 return self.setOnCursor("stack", VlJson.stringValue(how));
How marks sharing a position are stacked.
Arguments:
- how (str):
zero,normalizeorcenter.
Returns:
VlChartMark: This mark, so calls chain.
See Also:
noStack
1633 def noStack(self) -> VlChartMark: 1634 """Draws the marks overlapping rather than stacked. 1635 1636 Returns: 1637 VlChartMark: This mark, so calls chain. 1638 1639 See Also: 1640 stack 1641 """ 1642 return self.setOnCursor("stack", VlJson.nullValue());
Draws the marks overlapping rather than stacked.
Returns:
VlChartMark: This mark, so calls chain.
See Also:
stack
1643 def sortBy(self, field: str) -> VlChartMark: 1644 """The order a discrete scale runs in, taken from another column. 1645 1646 Args: 1647 field (str): The column to sort by. 1648 1649 Returns: 1650 VlChartMark: This mark, so calls chain. 1651 1652 See Also: 1653 keepOrder 1654 """ 1655 return self.setOnCursor("sort", VlJson.stringValue(field));
The order a discrete scale runs in, taken from another column.
Arguments:
- field (str): The column to sort by.
Returns:
VlChartMark: This mark, so calls chain.
See Also:
keepOrder
1656 def keepOrder(self) -> VlChartMark: 1657 """Keeps the order the rows arrived in, rather than sorting alphabetically. 1658 1659 The one every spreadsheet wants. 1660 1661 Returns: 1662 VlChartMark: This mark, so calls chain. 1663 1664 See Also: 1665 sortBy 1666 """ 1667 return self.setOnCursor("sort", VlJson.nullValue());
Keeps the order the rows arrived in, rather than sorting alphabetically.
The one every spreadsheet wants.
Returns:
VlChartMark: This mark, so calls chain.
See Also:
sortBy
1668 def scaleJson(self, scale: VlJson) -> VlChartMark: 1669 """Sets the cursor channel's whole scale definition. 1670 1671 Args: 1672 scale (VlJson): The scale definition. 1673 1674 Returns: 1675 VlChartMark: This mark, so calls chain. 1676 """ 1677 return self.setOnCursor("scale", scale);
Sets the cursor channel's whole scale definition.
Arguments:
- scale (VlJson): The scale definition.
Returns:
VlChartMark: This mark, so calls chain.
1678 def scaleType(self, kind: str) -> VlChartMark: 1679 """The kind of scale the cursor channel uses. 1680 1681 Args: 1682 kind (str): `linear`, `log`, `sqrt`, `time`, `band`, `point` and the rest. 1683 1684 Returns: 1685 VlChartMark: This mark, so calls chain. 1686 """ 1687 s = VlJson.objectValue() 1688 s.setMember("type", VlJson.stringValue(kind)) 1689 return self.setOnCursor("scale", s);
The kind of scale the cursor channel uses.
Arguments:
- kind (str):
linear,log,sqrt,time,band,pointand the rest.
Returns:
VlChartMark: This mark, so calls chain.
1690 def scheme(self, name: str) -> VlChartMark: 1691 """The colour scheme a colour channel draws from. 1692 1693 Args: 1694 name (str): A Vega scheme name, such as `category10` or `viridis`. 1695 1696 Returns: 1697 VlChartMark: This mark, so calls chain. 1698 """ 1699 s = VlJson.objectValue() 1700 s.setMember("scheme", VlJson.stringValue(name)) 1701 return self.setOnCursor("scale", s);
The colour scheme a colour channel draws from.
Arguments:
- name (str): A Vega scheme name, such as
category10orviridis.
Returns:
VlChartMark: This mark, so calls chain.
1702 def noLegend(self) -> VlChartMark: 1703 """Draws the cursor channel without a legend. 1704 1705 Returns: 1706 VlChartMark: This mark, so calls chain. 1707 """ 1708 return self.setOnCursor("legend", VlJson.nullValue());
Draws the cursor channel without a legend.
Returns:
VlChartMark: This mark, so calls chain.
1709 def noAxis(self) -> VlChartMark: 1710 """Draws the cursor channel without an axis. 1711 1712 Returns: 1713 VlChartMark: This mark, so calls chain. 1714 """ 1715 return self.setOnCursor("axis", VlJson.nullValue());
Draws the cursor channel without an axis.
Returns:
VlChartMark: This mark, so calls chain.
1716 def axisOrient(self, side: str) -> VlChartMark: 1717 """Which side of the plot the cursor channel's axis stands on. 1718 1719 A Pareto chart's cumulative line is measured up the right-hand side, which is 1720 the whole point of drawing it there. 1721 1722 Args: 1723 side (str): `left`, `right`, `top` or `bottom`. 1724 1725 Returns: 1726 VlChartMark: This mark, so calls chain. 1727 """ 1728 axis = VlJson.objectValue() 1729 axis.setMember("orient", VlJson.stringValue(side)) 1730 return self.setOnCursor("axis", axis);
Which side of the plot the cursor channel's axis stands on.
A Pareto chart's cumulative line is measured up the right-hand side, which is the whole point of drawing it there.
Arguments:
- side (str):
left,right,toporbottom.
Returns:
VlChartMark: This mark, so calls chain.
1731 def axisJson(self, axis: VlJson) -> VlChartMark: 1732 """Sets the cursor channel's whole axis definition. 1733 1734 Args: 1735 axis (VlJson): The axis definition. 1736 1737 Returns: 1738 VlChartMark: This mark, so calls chain. 1739 """ 1740 return self.setOnCursor("axis", axis);
Sets the cursor channel's whole axis definition.
Arguments:
- axis (VlJson): The axis definition.
Returns:
VlChartMark: This mark, so calls chain.
1741 def propNumber(self, key: str, value: float) -> VlChartMark: 1742 """Sets any numeric property of the mark itself. 1743 1744 Args: 1745 key (str): The property name. 1746 value (float): The value. 1747 1748 Returns: 1749 VlChartMark: This mark, so calls chain. 1750 """ 1751 self.props.setMember(key, VlJson.numberValue(value)) 1752 return self;
Sets any numeric property of the mark itself.
Arguments:
- key (str): The property name.
- value (float): The value.
Returns:
VlChartMark: This mark, so calls chain.
1753 def propString(self, key: str, value: str) -> VlChartMark: 1754 """Sets any string property of the mark itself. 1755 1756 Args: 1757 key (str): The property name. 1758 value (str): The value. 1759 1760 Returns: 1761 VlChartMark: This mark, so calls chain. 1762 """ 1763 self.props.setMember(key, VlJson.stringValue(value)) 1764 return self;
Sets any string property of the mark itself.
Arguments:
- key (str): The property name.
- value (str): The value.
Returns:
VlChartMark: This mark, so calls chain.
1765 def propFlag(self, key: str, value: bool) -> VlChartMark: 1766 """Sets any boolean property of the mark itself. 1767 1768 Args: 1769 key (str): The property name. 1770 value (bool): The value. 1771 1772 Returns: 1773 VlChartMark: This mark, so calls chain. 1774 """ 1775 self.props.setMember(key, VlJson.boolValue(value)) 1776 return self;
Sets any boolean property of the mark itself.
Arguments:
- key (str): The property name.
- value (bool): The value.
Returns:
VlChartMark: This mark, so calls chain.
1777 def filled(self, value: bool) -> VlChartMark: 1778 """Whether the mark is filled or drawn as an outline. 1779 1780 Args: 1781 value (bool): True to fill. 1782 1783 Returns: 1784 VlChartMark: This mark, so calls chain. 1785 """ 1786 return self.propFlag("filled", value);
Whether the mark is filled or drawn as an outline.
Arguments:
- value (bool): True to fill.
Returns:
VlChartMark: This mark, so calls chain.
1787 def markSize(self, value: float) -> VlChartMark: 1788 """How big every mark is drawn, as one number rather than from a column. 1789 1790 Args: 1791 value (float): The size. 1792 1793 Returns: 1794 VlChartMark: This mark, so calls chain. 1795 1796 See Also: 1797 size 1798 """ 1799 return self.propNumber("size", value);
How big every mark is drawn, as one number rather than from a column.
Arguments:
- value (float): The size.
Returns:
VlChartMark: This mark, so calls chain.
See Also:
size
1800 def markColor(self, value: str) -> VlChartMark: 1801 """Paints every mark one colour, rather than reading a column. 1802 1803 Args: 1804 value (str): A CSS colour. 1805 1806 Returns: 1807 VlChartMark: This mark, so calls chain. 1808 1809 See Also: 1810 color 1811 """ 1812 return self.propString("color", value);
Paints every mark one colour, rather than reading a column.
Arguments:
- value (str): A CSS colour.
Returns:
VlChartMark: This mark, so calls chain.
See Also:
color
1813 def markOpacity(self, value: float) -> VlChartMark: 1814 """How opaque every mark is drawn, as one number rather than from a column. 1815 1816 Args: 1817 value (float): 0 to 1. 1818 1819 Returns: 1820 VlChartMark: This mark, so calls chain. 1821 1822 See Also: 1823 opacity 1824 """ 1825 return self.propNumber("opacity", value);
How opaque every mark is drawn, as one number rather than from a column.
Arguments:
- value (float): 0 to 1.
Returns:
VlChartMark: This mark, so calls chain.
See Also:
opacity
1826 def interpolate(self, kind: str) -> VlChartMark: 1827 """How a line joins its points. 1828 1829 Args: 1830 kind (str): `linear`, `monotone`, `step-after`, `basis` and the rest. 1831 1832 Returns: 1833 VlChartMark: This mark, so calls chain. 1834 """ 1835 return self.propString("interpolate", kind);
How a line joins its points.
Arguments:
- kind (str):
linear,monotone,step-after,basisand the rest.
Returns:
VlChartMark: This mark, so calls chain.
1836 def withPoints(self, value: bool) -> VlChartMark: 1837 """Draws a line showing the points it was drawn through. 1838 1839 Args: 1840 value (bool): True to show them. 1841 1842 Returns: 1843 VlChartMark: This mark, so calls chain. 1844 """ 1845 return self.propFlag("point", value);
Draws a line showing the points it was drawn through.
Arguments:
- value (bool): True to show them.
Returns:
VlChartMark: This mark, so calls chain.
1846 def innerRadius(self, value: float) -> VlChartMark: 1847 """The hole in the middle of an arc, which is what turns a pie into a donut. 1848 1849 Args: 1850 value (float): The inner radius in pixels. 1851 1852 Returns: 1853 VlChartMark: This mark, so calls chain. 1854 """ 1855 return self.propNumber("innerRadius", value);
The hole in the middle of an arc, which is what turns a pie into a donut.
Arguments:
- value (float): The inner radius in pixels.
Returns:
VlChartMark: This mark, so calls chain.
1856 def cornerRadius(self, value: float) -> VlChartMark: 1857 """How rounded the corners of a bar or a rectangle are. 1858 1859 Args: 1860 value (float): The radius in pixels. 1861 1862 Returns: 1863 VlChartMark: This mark, so calls chain. 1864 """ 1865 return self.propNumber("cornerRadius", value);
How rounded the corners of a bar or a rectangle are.
Arguments:
- value (float): The radius in pixels.
Returns:
VlChartMark: This mark, so calls chain.
1866 def tooltip(self, value: bool) -> VlChartMark: 1867 """Shows every column the mark encodes when the reader points at it. 1868 1869 Args: 1870 value (bool): True to show a tooltip. 1871 1872 Returns: 1873 VlChartMark: This mark, so calls chain. 1874 1875 See Also: 1876 tooltipFields 1877 """ 1878 return self.propFlag("tooltip", value);
Shows every column the mark encodes when the reader points at it.
Arguments:
- value (bool): True to show a tooltip.
Returns:
VlChartMark: This mark, so calls chain.
See Also:
tooltipFields
1879 def tooltipField(self, field: str) -> VlChartMark: 1880 """Shows one named column as the tooltip. 1881 1882 Args: 1883 field (str): The column name. 1884 1885 Returns: 1886 VlChartMark: This mark, so calls chain. 1887 1888 See Also: 1889 tooltipFields 1890 """ 1891 return self.channel("tooltip", field);
Shows one named column as the tooltip.
Arguments:
- field (str): The column name.
Returns:
VlChartMark: This mark, so calls chain.
See Also:
tooltipFields
1892 def tooltipFields(self, fields: list[str]) -> VlChartMark: 1893 """Shows several named columns as the tooltip, in the order they should be read. 1894 1895 A list is not a channel, so the cursor does not move onto it: the next `title` 1896 belongs to whatever was named before. 1897 1898 Args: 1899 fields (None): The column names, in reading order. 1900 1901 Returns: 1902 VlChartMark: This mark, so calls chain. 1903 1904 See Also: 1905 tooltip 1906 """ 1907 _list = VlJson.arrayValue() 1908 for field in fields: 1909 one = VlJson.objectValue() 1910 one.setMember("field", VlJson.stringValue(field)) 1911 _list.arr.append(one) 1912 self.enc.setMember("tooltip", _list) 1913 return self;
Shows several named columns as the tooltip, in the order they should be read.
A list is not a channel, so the cursor does not move onto it: the next title
belongs to whatever was named before.
Arguments:
- fields (None): The column names, in reading order.
Returns:
VlChartMark: This mark, so calls chain.
See Also:
tooltip
1914 def thickness(self, value: float) -> VlChartMark: 1915 """How thick a tick is drawn across its band. 1916 1917 A hi-lo-open-close chart's open and close are ticks, and a two-pixel one is 1918 what makes them read as marks rather than as hairlines. 1919 1920 Args: 1921 value (float): The thickness in pixels. 1922 1923 Returns: 1924 VlChartMark: This mark, so calls chain. 1925 """ 1926 return self.propNumber("thickness", value);
How thick a tick is drawn across its band.
A hi-lo-open-close chart's open and close are ticks, and a two-pixel one is what makes them read as marks rather than as hairlines.
Arguments:
- value (float): The thickness in pixels.
Returns:
VlChartMark: This mark, so calls chain.
1927 def strokeWidth(self, value: float) -> VlChartMark: 1928 """How thick the mark's outline is drawn. 1929 1930 Args: 1931 value (float): The width in pixels. 1932 1933 Returns: 1934 VlChartMark: This mark, so calls chain. 1935 """ 1936 return self.propNumber("strokeWidth", value);
How thick the mark's outline is drawn.
Arguments:
- value (float): The width in pixels.
Returns:
VlChartMark: This mark, so calls chain.
1937 def orient(self, value: str) -> VlChartMark: 1938 """Which way a tick lies, or which way a bar with only one position channel runs. 1939 1940 Args: 1941 value (str): `horizontal` or `vertical`. 1942 1943 Returns: 1944 VlChartMark: This mark, so calls chain. 1945 """ 1946 return self.propString("orient", value);
Which way a tick lies, or which way a bar with only one position channel runs.
Arguments:
- value (str):
horizontalorvertical.
Returns:
VlChartMark: This mark, so calls chain.
1947 def extent(self, value: str) -> VlChartMark: 1948 """What an interval mark is computed from. 1949 1950 Args: 1951 value (str): `stderr`, `stdev`, `ci` or `iqr`. 1952 1953 Returns: 1954 VlChartMark: This mark, so calls chain. 1955 """ 1956 return self.propString("extent", value);
What an interval mark is computed from.
Arguments:
- value (str):
stderr,stdev,cioriqr.
Returns:
VlChartMark: This mark, so calls chain.
1957 def chart(self) -> VlChart: 1958 """Returns to the chart, when the next thing to say is about the view. 1959 1960 Returns: 1961 VlChart: The owning chart, or a fresh empty one if this mark was built without a chart. 1962 """ 1963 if (self.owner is not None): 1964 return self.owner; 1965 empty = VlDataset.create() 1966 return VlChart.create(empty);
Returns to the chart, when the next thing to say is about the view.
Returns:
VlChart: The owning chart, or a fresh empty one if this mark was built without a chart.
1967class VlChart: 1968 """A chart: a dataset, the channels every mark shares, how big it is, and the marks. 1969 1970 The fluent surface is a **writer of specifications**, not the engine. Every 1971 call writes into a specification and `toSpec` hands that specification over; 1972 nothing here computes a scale, a layout or a pixel. There is no path where the 1973 API computes something the engine would have computed differently, because the 1974 API computes nothing at all. 1975 1976 A channel said on the chart is inherited by every mark on it, so a line and the 1977 points on top of it are two marks and one set of axes rather than two charts. 1978 1979 A channel need not state its type — the data says. A column of numbers is a 1980 quantity, a column of ISO dates an instant, anything else a name. A field the 1981 data does not have is an **error** rather than a guess: `errors` is non-empty 1982 and the caller can say so instead of drawing an empty axis. 1983 1984 .. versionadded:: 1.0 1985 1986 See Also: 1987 VlDataset 1988 1989 Example: 1990 data = VlDataset.create() 1991 data.row()._str("region", "North").num("sales", 120) 1992 data.row()._str("region", "South").num("sales", 93) 1993 chart = VlChart.create(data) 1994 chart.size(300, 200) 1995 chart.bar().x("region").y("sales").aggregate("sum") 1996 _spec = chart.toSpec() 1997 1998 Example: 1999 data = VlDataset.create() 2000 data.row()._str("region", "North").num("sales", 120) 2001 chart = VlChart.create(data) 2002 chart.x("region").y("sales").color("region") 2003 chart.area().markOpacity(0.35) 2004 chart.line() 2005 """ 2006 def __init__(self) -> None: 2007 self.data = None 2008 self.marks = [] 2009 self.enc = VlJson.objectValue() 2010 self.cursor = "" 2011 self.props = VlJson.objectValue() 2012 self.transforms = VlJson.arrayValue() 2013 self.cfg = VlJson.objectValue() 2014 self.resolve = VlJson.objectValue() 2015 self.errors = [] 2016 @staticmethod 2017 def create(data: VlDataset) -> VlChart: 2018 """Builds a chart over a dataset. 2019 2020 Args: 2021 data (VlDataset): The rows the chart draws. 2022 2023 Returns: 2024 VlChart: A chart with no marks yet. 2025 2026 See Also: 2027 VlDataset 2028 """ 2029 c = VlChart() 2030 c.data = data; 2031 return c; 2032 @staticmethod 2033 def copyOf(v: VlJson) -> VlJson: 2034 if v.isArray(): 2035 _list = VlJson.arrayValue() 2036 i = 0 2037 n = v.count() 2038 while i < n: 2039 child = v.at(i) 2040 _list.arr.append(VlChart.copyOf(child)) 2041 i = i + 1; 2042 return _list; 2043 if v.isObject(): 2044 obj = VlJson.objectValue() 2045 for ki, k in enumerate(v.keys): 2046 member = v.get(k) 2047 obj.setMember(k, VlChart.copyOf(member)) 2048 return obj; 2049 return v; 2050 @staticmethod 2051 def markValue(m: VlChartMark) -> VlJson: 2052 n = len(m.props.keys) 2053 if n == 0: 2054 return VlJson.stringValue(m.markType); 2055 obj = VlJson.objectValue() 2056 obj.setMember("type", VlJson.stringValue(m.markType)) 2057 for ki, k in enumerate(m.props.keys): 2058 obj.setMember(k, m.props.get(k)) 2059 return obj; 2060 def mark(self, markType: str) -> VlChartMark: 2061 """Adds a mark of any type the compiler knows. 2062 2063 Args: 2064 markType (str): The Vega-Lite mark name. 2065 2066 Returns: 2067 VlChartMark: The new mark, so its channels and properties chain. 2068 """ 2069 m = VlChartMark() 2070 m.markType = markType; 2071 m.owner = self; 2072 self.marks.append(m) 2073 return m; 2074 def bar(self) -> VlChartMark: 2075 """Adds a bar mark to the chart. 2076 2077 A rectangle per row: the bar chart, and with `x2`/`y2` a range. 2078 2079 Returns: 2080 VlChartMark: The new mark, so its channels and properties chain. 2081 """ 2082 return self.mark("bar"); 2083 def line(self) -> VlChartMark: 2084 """Adds a line mark to the chart. 2085 2086 A line joining the rows in order. 2087 2088 Returns: 2089 VlChartMark: The new mark, so its channels and properties chain. 2090 """ 2091 return self.mark("line"); 2092 def area(self) -> VlChartMark: 2093 """Adds an area mark to the chart. 2094 2095 A filled band between a line and a baseline. 2096 2097 Returns: 2098 VlChartMark: The new mark, so its channels and properties chain. 2099 """ 2100 return self.mark("area"); 2101 def point(self) -> VlChartMark: 2102 """Adds a point mark to the chart. 2103 2104 One symbol per row: the scatter plot. 2105 2106 Returns: 2107 VlChartMark: The new mark, so its channels and properties chain. 2108 """ 2109 return self.mark("point"); 2110 def circle(self) -> VlChartMark: 2111 """Adds a circle mark to the chart. 2112 2113 A filled circle per row — `point` with the shape settled. 2114 2115 Returns: 2116 VlChartMark: The new mark, so its channels and properties chain. 2117 """ 2118 return self.mark("circle"); 2119 def square(self) -> VlChartMark: 2120 """Adds a square mark to the chart. 2121 2122 A filled square per row — `point` with the shape settled. 2123 2124 Returns: 2125 VlChartMark: The new mark, so its channels and properties chain. 2126 """ 2127 return self.mark("square"); 2128 def tick(self) -> VlChartMark: 2129 """Adds a tick mark to the chart. 2130 2131 A short stroke per row, across the band it sits in. 2132 2133 Returns: 2134 VlChartMark: The new mark, so its channels and properties chain. 2135 """ 2136 return self.mark("tick"); 2137 def rule(self) -> VlChartMark: 2138 """Adds a rule mark to the chart. 2139 2140 A line at one value, spanning the plot or between `x2`/`y2`. 2141 2142 Returns: 2143 VlChartMark: The new mark, so its channels and properties chain. 2144 """ 2145 return self.mark("rule"); 2146 def rect(self) -> VlChartMark: 2147 """Adds a rect mark to the chart. 2148 2149 A rectangle over two ranges: the heatmap. 2150 2151 Returns: 2152 VlChartMark: The new mark, so its channels and properties chain. 2153 """ 2154 return self.mark("rect"); 2155 def arc(self) -> VlChartMark: 2156 """Adds an arc mark to the chart. 2157 2158 A wedge, which with `theta` is a pie and with `innerRadius` a donut. 2159 2160 Returns: 2161 VlChartMark: The new mark, so its channels and properties chain. 2162 """ 2163 return self.mark("arc"); 2164 def label(self) -> VlChartMark: 2165 """Adds a text mark, which draws the value of its `text` channel. 2166 2167 Returns: 2168 VlChartMark: The new mark, so its channels and properties chain. 2169 """ 2170 return self.mark("text"); 2171 def boxplot(self) -> VlChartMark: 2172 """Adds a boxplot mark to the chart. 2173 2174 A box and whiskers, computed from the rows rather than read off them. 2175 2176 Returns: 2177 VlChartMark: The new mark, so its channels and properties chain. 2178 """ 2179 return self.mark("boxplot"); 2180 def errorbar(self) -> VlChartMark: 2181 """Adds an error bar: an interval computed from the rows rather than read off them. 2182 2183 `extent` decides what the interval is — `stderr` by default, or `stdev`, `ci` 2184 or `iqr`. 2185 2186 Returns: 2187 VlChartMark: The new mark, so its channels and properties chain. 2188 2189 See Also: 2190 errorband 2191 """ 2192 return self.mark("errorbar"); 2193 def errorband(self) -> VlChartMark: 2194 """Adds an error band: the same interval as an error bar, drawn as a filled region. 2195 2196 Returns: 2197 VlChartMark: The new mark, so its channels and properties chain. 2198 2199 See Also: 2200 errorbar 2201 """ 2202 return self.mark("errorband"); 2203 def trail(self) -> VlChartMark: 2204 """Adds a trail mark to the chart. 2205 2206 A line whose width says something: a trail thickens with its `size`. 2207 2208 Returns: 2209 VlChartMark: The new mark, so its channels and properties chain. 2210 """ 2211 return self.mark("trail"); 2212 def image(self) -> VlChartMark: 2213 """Adds an image mark to the chart. 2214 2215 A picture per row, placed by its position channels. 2216 2217 Returns: 2218 VlChartMark: The new mark, so its channels and properties chain. 2219 """ 2220 return self.mark("image"); 2221 def geoshape(self) -> VlChartMark: 2222 """Adds a geoshape mark to the chart. 2223 2224 A map: the shapes come from the data and the projection places them. 2225 2226 Returns: 2227 VlChartMark: The new mark, so its channels and properties chain. 2228 """ 2229 return self.mark("geoshape"); 2230 def latest(self) -> VlChartMark: 2231 """The mark added last, for a caller that built one and let go of it. 2232 2233 A chart with no marks answers a mark belonging to nothing and reports it in 2234 `errors`, rather than quietly adding a `point` nobody asked for. 2235 2236 Returns: 2237 VlChartMark: The last mark added. 2238 """ 2239 n = len(self.marks) 2240 if n > 0: 2241 return self.marks[(n - 1)]; 2242 self.error("the chart has no marks, so there is no last one") 2243 loose = VlChartMark() 2244 loose.owner = self; 2245 return loose; 2246 def channel(self, name: str, field: str) -> VlChart: 2247 """Sets a channel that every mark on this view inherits. 2248 2249 Args: 2250 name (str): The channel name. 2251 field (str): The column name. 2252 2253 Returns: 2254 VlChart: This chart, so calls chain. 2255 """ 2256 ch = VlJson.objectValue() 2257 ch.setMember("field", VlJson.stringValue(field)) 2258 self.enc.setMember(name, ch) 2259 self.cursor = name; 2260 return self; 2261 def x(self, field: str) -> VlChart: 2262 """Position along the horizontal axis. 2263 2264 Names a COLUMN, never a constant. `.color("red")` means a column 2265 called red; painting a mark red is `markColor`. 2266 2267 Args: 2268 field (str): The column name. 2269 2270 Returns: 2271 VlChart: This view, so channels chain. 2272 """ 2273 return self.channel("x", field); 2274 def y(self, field: str) -> VlChart: 2275 """Position along the vertical axis. 2276 2277 Names a COLUMN, never a constant. `.color("red")` means a column 2278 called red; painting a mark red is `markColor`. 2279 2280 Args: 2281 field (str): The column name. 2282 2283 Returns: 2284 VlChart: This view, so channels chain. 2285 """ 2286 return self.channel("y", field); 2287 def color(self, field: str) -> VlChart: 2288 """Colour, and the legend that explains it. 2289 2290 Names a COLUMN, never a constant. `.color("red")` means a column 2291 called red; painting a mark red is `markColor`. 2292 2293 Args: 2294 field (str): The column name. 2295 2296 Returns: 2297 VlChart: This view, so channels chain. 2298 """ 2299 return self.channel("color", field); 2300 def detail(self, field: str) -> VlChart: 2301 """Groups the rows without drawing anything of its own: one line per group, no legend. 2302 2303 Names a COLUMN, never a constant. `.color("red")` means a column 2304 called red; painting a mark red is `markColor`. 2305 2306 Args: 2307 field (str): The column name. 2308 2309 Returns: 2310 VlChart: This view, so channels chain. 2311 """ 2312 return self.channel("detail", field); 2313 def encodeJson(self, channel: str, definition: VlJson) -> VlChart: 2314 """Sets a whole shared channel from an already-built definition. 2315 2316 Args: 2317 channel (str): The channel name. 2318 definition (VlJson): The channel definition. 2319 2320 Returns: 2321 VlChart: This chart, so calls chain. 2322 """ 2323 self.enc.setMember(channel, definition) 2324 self.cursor = channel; 2325 return self; 2326 def on(self, channel: str) -> VlChart: 2327 """Moves the cursor back to a shared channel that is already set. 2328 2329 Args: 2330 channel (str): The channel name. 2331 2332 Returns: 2333 VlChart: This chart, so calls chain. 2334 """ 2335 if self.enc.has(channel): 2336 self.cursor = channel; 2337 else: 2338 self.error(("no channel called '" + channel) + "' has been set on this view") 2339 return self; 2340 def setOnCursor(self, key: str, value: VlJson) -> VlChart: 2341 if len(self.cursor) == 0: 2342 self.error("a channel property was set before any channel was named") 2343 return self; 2344 ch = self.enc.get(self.cursor) 2345 ch.setMember(key, value) 2346 return self; 2347 def _type(self, kind: str) -> VlChart: 2348 """States what a shared channel's column holds, when the data cannot say. 2349 2350 Args: 2351 kind (str): `quantitative`, `nominal`, `ordinal` or `temporal`. 2352 2353 Returns: 2354 VlChart: This chart, so calls chain. 2355 """ 2356 return self.setOnCursor("type", VlJson.stringValue(kind)); 2357 def title(self, label: str) -> VlChart: 2358 """The axis or legend label for the shared cursor channel. 2359 2360 Args: 2361 label (str): The label. 2362 2363 Returns: 2364 VlChart: This chart, so calls chain. 2365 2366 See Also: 2367 heading 2368 """ 2369 return self.setOnCursor("title", VlJson.stringValue(label)); 2370 def timeUnit(self, unit: str) -> VlChart: 2371 """Which part of an instant a shared channel reads. 2372 2373 Args: 2374 unit (str): The time unit. 2375 2376 Returns: 2377 VlChart: This chart, so calls chain. 2378 """ 2379 return self.setOnCursor("timeUnit", VlJson.stringValue(unit)); 2380 def keepOrder(self) -> VlChart: 2381 """Keeps the order the rows arrived in for the shared cursor channel. 2382 2383 Returns: 2384 VlChart: This chart, so calls chain. 2385 """ 2386 return self.setOnCursor("sort", VlJson.nullValue()); 2387 def size(self, width: int, height: int) -> VlChart: 2388 """How big the plotting area is, in pixels. 2389 2390 Args: 2391 width (int): The width. 2392 height (int): The height. 2393 2394 Returns: 2395 VlChart: This chart, so calls chain. 2396 """ 2397 self.props.setMember("width", VlJson.intValue(width)) 2398 self.props.setMember("height", VlJson.intValue(height)) 2399 return self; 2400 def width(self, value: int) -> VlChart: 2401 """How wide the plotting area is, in pixels. 2402 2403 Args: 2404 value (int): The width. 2405 2406 Returns: 2407 VlChart: This chart, so calls chain. 2408 """ 2409 self.props.setMember("width", VlJson.intValue(value)) 2410 return self; 2411 def height(self, value: int) -> VlChart: 2412 """How tall the plotting area is, in pixels. 2413 2414 Args: 2415 value (int): The height. 2416 2417 Returns: 2418 VlChart: This chart, so calls chain. 2419 """ 2420 self.props.setMember("height", VlJson.intValue(value)) 2421 return self; 2422 def heading(self, text: str) -> VlChart: 2423 """The chart's title, drawn above the plot. 2424 2425 Args: 2426 text (str): The title. 2427 2428 Returns: 2429 VlChart: This chart, so calls chain. 2430 2431 See Also: 2432 title 2433 """ 2434 self.props.setMember("title", VlJson.stringValue(text)) 2435 return self; 2436 def background(self, colour: str) -> VlChart: 2437 """The colour behind the plot. 2438 2439 Args: 2440 colour (str): A CSS colour. 2441 2442 Returns: 2443 VlChart: This chart, so calls chain. 2444 """ 2445 self.props.setMember("background", VlJson.stringValue(colour)) 2446 return self; 2447 def propJson(self, key: str, value: VlJson) -> VlChart: 2448 """Sets any top-level property of the specification. 2449 2450 Args: 2451 key (str): The property name. 2452 value (VlJson): The value. 2453 2454 Returns: 2455 VlChart: This chart, so calls chain. 2456 """ 2457 self.props.setMember(key, value) 2458 return self; 2459 def configJson(self, config: VlJson) -> VlChart: 2460 """Merges a configuration block into the specification. 2461 2462 Args: 2463 config (VlJson): The configuration object. 2464 2465 Returns: 2466 VlChart: This chart, so calls chain. 2467 """ 2468 for ki, k in enumerate(config.keys): 2469 self.cfg.setMember(k, config.get(k)) 2470 return self; 2471 def _filter(self, expression: str) -> VlChart: 2472 """Keeps only the rows an expression accepts. 2473 2474 Args: 2475 expression (str): A Vega expression over the row's columns. 2476 2477 Returns: 2478 VlChart: This chart, so calls chain. 2479 """ 2480 t = VlJson.objectValue() 2481 t.setMember("filter", VlJson.stringValue(expression)) 2482 self.transforms.arr.append(t) 2483 return self; 2484 def calculate(self, expression: str, _as: str) -> VlChart: 2485 """Adds a column computed from the others. 2486 2487 Args: 2488 expression (str): A Vega expression over the row's columns. 2489 _as (str): The name of the new column. 2490 2491 Returns: 2492 VlChart: This chart, so calls chain. 2493 """ 2494 t = VlJson.objectValue() 2495 t.setMember("calculate", VlJson.stringValue(expression)) 2496 t.setMember("as", VlJson.stringValue(_as)) 2497 self.transforms.arr.append(t) 2498 return self; 2499 def transformJson(self, transform: VlJson) -> VlChart: 2500 """Appends an already-built transform. 2501 2502 Args: 2503 transform (VlJson): The transform definition. 2504 2505 Returns: 2506 VlChart: This chart, so calls chain. 2507 """ 2508 self.transforms.arr.append(transform) 2509 return self; 2510 def independent(self, channel: str) -> VlChart: 2511 """Stops the layers sharing one scale on a channel. 2512 2513 Two marks measuring different things up the same side of the plot must not 2514 share a scale. This is what makes a Pareto chart — bars against a count, a 2515 line against a running percentage — rather than two series averaged into one 2516 axis neither of them asked for. 2517 2518 Args: 2519 channel (str): The channel to split, usually "y". 2520 2521 Returns: 2522 VlChart: This chart, so calls chain. 2523 """ 2524 scales = self.resolve.get("scale") 2525 if False == scales.isObject(): 2526 fresh = VlJson.objectValue() 2527 self.resolve.setMember("scale", fresh) 2528 scales = fresh; 2529 scales.setMember(channel, VlJson.stringValue("independent")) 2530 return self; 2531 def error(self, message: str) -> None: 2532 for said in self.errors: 2533 if said == message: 2534 return; 2535 self.errors.append(message) 2536 def mergedEncoding(self, m: VlChartMark) -> VlJson: 2537 out = VlJson.objectValue() 2538 for ki, k in enumerate(self.enc.keys): 2539 shared = self.enc.get(k) 2540 out.setMember(k, VlChart.copyOf(shared)) 2541 for mi, mk in enumerate(m.enc.keys): 2542 own = m.enc.get(mk) 2543 out.setMember(mk, VlChart.copyOf(own)) 2544 self.resolveTypes(out) 2545 return out; 2546 def resolveTypes(self, encoding: VlJson) -> None: 2547 for ki, k in enumerate(encoding.keys): 2548 ch = encoding.get(k) 2549 if ch.isArray(): 2550 i = 0 2551 n = ch.count() 2552 while i < n: 2553 one = ch.at(i) 2554 if one.isObject(): 2555 if False == one.has("type"): 2556 listKind = self.inferType(one) 2557 if len(listKind) > 0: 2558 one.setMember("type", VlJson.stringValue(listKind)) 2559 i = i + 1; 2560 if ch.isObject(): 2561 if False == ch.has("type"): 2562 if False == ch.has("value"): 2563 kind = self.inferType(ch) 2564 if len(kind) > 0: 2565 ch.setMember("type", VlJson.stringValue(kind)) 2566 def inferType(self, ch: VlJson) -> str: 2567 if ch.has("bin"): 2568 return "quantitative"; 2569 if ch.has("timeUnit"): 2570 return "temporal"; 2571 if ch.has("aggregate"): 2572 return "quantitative"; 2573 if False == ch.has("field"): 2574 return ""; 2575 field = ch.stringOr("field", "") 2576 if self.data.count() == 0: 2577 return "nominal"; 2578 kind = self.data.fieldType(field) 2579 if len(kind) == 0: 2580 self.error(("the data has no column called '" + field) + "'") 2581 return "nominal"; 2582 return kind; 2583 def toSpec(self) -> VlJson: 2584 """The chart as a Vega-Lite specification. 2585 2586 One mark comes out as a plain specification; several come out as layers, each 2587 carrying the shared channels in full — a specification that states everything 2588 is one the compiler already handles and one a person can read in a diff. 2589 2590 May be called more than once. Check `errors` afterwards: a chart that names a 2591 column its data does not have is reported here, where Vega-Lite would have 2592 drawn an empty axis and said nothing. 2593 2594 Returns: 2595 VlJson: A Vega-Lite specification, ready for `VlCompile`. 2596 2597 Example: 2598 data = VlDataset.create() 2599 data.row()._str("region", "North").num("sales", 120) 2600 data.row()._str("region", "South").num("sales", 93) 2601 chart = VlChart.create(data) 2602 chart.size(300, 200) 2603 chart.bar().x("region").y("sales").aggregate("sum") 2604 _spec = chart.toSpec() 2605 """ 2606 out = VlJson.objectValue() 2607 for ki, k in enumerate(self.props.keys): 2608 out.setMember(k, self.props.get(k)) 2609 out.setMember("data", self.data.toValues()) 2610 if self.transforms.count() > 0: 2611 out.setMember("transform", self.transforms) 2612 markCount = len(self.marks) 2613 if markCount == 0: 2614 self.error("the chart has no marks") 2615 return out; 2616 if markCount == 1: 2617 only = self.marks[0] 2618 out.setMember("mark", VlChart.markValue(only)) 2619 out.setMember("encoding", self.mergedEncoding(only)) 2620 else: 2621 layers = VlJson.arrayValue() 2622 for m in self.marks: 2623 layer = VlJson.objectValue() 2624 layer.setMember("mark", VlChart.markValue(m)) 2625 layer.setMember("encoding", self.mergedEncoding(m)) 2626 layers.arr.append(layer) 2627 out.setMember("layer", layers) 2628 resolveCount = len(self.resolve.keys) 2629 if resolveCount > 0: 2630 out.setMember("resolve", self.resolve) 2631 cfgCount = len(self.cfg.keys) 2632 if cfgCount > 0: 2633 out.setMember("config", self.cfg) 2634 return out; 2635 def toText(self) -> str: 2636 spec = self.toSpec() 2637 w = VlJsonWriter() 2638 return w.write(spec);
A chart: a dataset, the channels every mark shares, how big it is, and the marks.
The fluent surface is a writer of specifications, not the engine. Every
call writes into a specification and toSpec hands that specification over;
nothing here computes a scale, a layout or a pixel. There is no path where the
API computes something the engine would have computed differently, because the
API computes nothing at all.
A channel said on the chart is inherited by every mark on it, so a line and the points on top of it are two marks and one set of axes rather than two charts.
A channel need not state its type — the data says. A column of numbers is a
quantity, a column of ISO dates an instant, anything else a name. A field the
data does not have is an error rather than a guess: errors is non-empty
and the caller can say so instead of drawing an empty axis.
New in version 1.0.
See Also:
VlDataset
Example:
data = VlDataset.create() data.row()._str("region", "North").num("sales", 120) data.row()._str("region", "South").num("sales", 93) chart = VlChart.create(data) chart.size(300, 200) chart.bar().x("region").y("sales").aggregate("sum") _spec = chart.toSpec()
Example:
data = VlDataset.create() data.row()._str("region", "North").num("sales", 120) chart = VlChart.create(data) chart.x("region").y("sales").color("region") chart.area().markOpacity(0.35) chart.line()
2016 @staticmethod 2017 def create(data: VlDataset) -> VlChart: 2018 """Builds a chart over a dataset. 2019 2020 Args: 2021 data (VlDataset): The rows the chart draws. 2022 2023 Returns: 2024 VlChart: A chart with no marks yet. 2025 2026 See Also: 2027 VlDataset 2028 """ 2029 c = VlChart() 2030 c.data = data; 2031 return c;
Builds a chart over a dataset.
Arguments:
- data (VlDataset): The rows the chart draws.
Returns:
VlChart: A chart with no marks yet.
See Also:
VlDataset
2032 @staticmethod 2033 def copyOf(v: VlJson) -> VlJson: 2034 if v.isArray(): 2035 _list = VlJson.arrayValue() 2036 i = 0 2037 n = v.count() 2038 while i < n: 2039 child = v.at(i) 2040 _list.arr.append(VlChart.copyOf(child)) 2041 i = i + 1; 2042 return _list; 2043 if v.isObject(): 2044 obj = VlJson.objectValue() 2045 for ki, k in enumerate(v.keys): 2046 member = v.get(k) 2047 obj.setMember(k, VlChart.copyOf(member)) 2048 return obj; 2049 return v;
2050 @staticmethod 2051 def markValue(m: VlChartMark) -> VlJson: 2052 n = len(m.props.keys) 2053 if n == 0: 2054 return VlJson.stringValue(m.markType); 2055 obj = VlJson.objectValue() 2056 obj.setMember("type", VlJson.stringValue(m.markType)) 2057 for ki, k in enumerate(m.props.keys): 2058 obj.setMember(k, m.props.get(k)) 2059 return obj;
2060 def mark(self, markType: str) -> VlChartMark: 2061 """Adds a mark of any type the compiler knows. 2062 2063 Args: 2064 markType (str): The Vega-Lite mark name. 2065 2066 Returns: 2067 VlChartMark: The new mark, so its channels and properties chain. 2068 """ 2069 m = VlChartMark() 2070 m.markType = markType; 2071 m.owner = self; 2072 self.marks.append(m) 2073 return m;
Adds a mark of any type the compiler knows.
Arguments:
- markType (str): The Vega-Lite mark name.
Returns:
VlChartMark: The new mark, so its channels and properties chain.
2074 def bar(self) -> VlChartMark: 2075 """Adds a bar mark to the chart. 2076 2077 A rectangle per row: the bar chart, and with `x2`/`y2` a range. 2078 2079 Returns: 2080 VlChartMark: The new mark, so its channels and properties chain. 2081 """ 2082 return self.mark("bar");
Adds a bar mark to the chart.
A rectangle per row: the bar chart, and with x2/y2 a range.
Returns:
VlChartMark: The new mark, so its channels and properties chain.
2083 def line(self) -> VlChartMark: 2084 """Adds a line mark to the chart. 2085 2086 A line joining the rows in order. 2087 2088 Returns: 2089 VlChartMark: The new mark, so its channels and properties chain. 2090 """ 2091 return self.mark("line");
Adds a line mark to the chart.
A line joining the rows in order.
Returns:
VlChartMark: The new mark, so its channels and properties chain.
2092 def area(self) -> VlChartMark: 2093 """Adds an area mark to the chart. 2094 2095 A filled band between a line and a baseline. 2096 2097 Returns: 2098 VlChartMark: The new mark, so its channels and properties chain. 2099 """ 2100 return self.mark("area");
Adds an area mark to the chart.
A filled band between a line and a baseline.
Returns:
VlChartMark: The new mark, so its channels and properties chain.
2101 def point(self) -> VlChartMark: 2102 """Adds a point mark to the chart. 2103 2104 One symbol per row: the scatter plot. 2105 2106 Returns: 2107 VlChartMark: The new mark, so its channels and properties chain. 2108 """ 2109 return self.mark("point");
Adds a point mark to the chart.
One symbol per row: the scatter plot.
Returns:
VlChartMark: The new mark, so its channels and properties chain.
2110 def circle(self) -> VlChartMark: 2111 """Adds a circle mark to the chart. 2112 2113 A filled circle per row — `point` with the shape settled. 2114 2115 Returns: 2116 VlChartMark: The new mark, so its channels and properties chain. 2117 """ 2118 return self.mark("circle");
Adds a circle mark to the chart.
A filled circle per row — point with the shape settled.
Returns:
VlChartMark: The new mark, so its channels and properties chain.
2119 def square(self) -> VlChartMark: 2120 """Adds a square mark to the chart. 2121 2122 A filled square per row — `point` with the shape settled. 2123 2124 Returns: 2125 VlChartMark: The new mark, so its channels and properties chain. 2126 """ 2127 return self.mark("square");
Adds a square mark to the chart.
A filled square per row — point with the shape settled.
Returns:
VlChartMark: The new mark, so its channels and properties chain.
2128 def tick(self) -> VlChartMark: 2129 """Adds a tick mark to the chart. 2130 2131 A short stroke per row, across the band it sits in. 2132 2133 Returns: 2134 VlChartMark: The new mark, so its channels and properties chain. 2135 """ 2136 return self.mark("tick");
Adds a tick mark to the chart.
A short stroke per row, across the band it sits in.
Returns:
VlChartMark: The new mark, so its channels and properties chain.
2137 def rule(self) -> VlChartMark: 2138 """Adds a rule mark to the chart. 2139 2140 A line at one value, spanning the plot or between `x2`/`y2`. 2141 2142 Returns: 2143 VlChartMark: The new mark, so its channels and properties chain. 2144 """ 2145 return self.mark("rule");
Adds a rule mark to the chart.
A line at one value, spanning the plot or between x2/y2.
Returns:
VlChartMark: The new mark, so its channels and properties chain.
2146 def rect(self) -> VlChartMark: 2147 """Adds a rect mark to the chart. 2148 2149 A rectangle over two ranges: the heatmap. 2150 2151 Returns: 2152 VlChartMark: The new mark, so its channels and properties chain. 2153 """ 2154 return self.mark("rect");
Adds a rect mark to the chart.
A rectangle over two ranges: the heatmap.
Returns:
VlChartMark: The new mark, so its channels and properties chain.
2155 def arc(self) -> VlChartMark: 2156 """Adds an arc mark to the chart. 2157 2158 A wedge, which with `theta` is a pie and with `innerRadius` a donut. 2159 2160 Returns: 2161 VlChartMark: The new mark, so its channels and properties chain. 2162 """ 2163 return self.mark("arc");
Adds an arc mark to the chart.
A wedge, which with theta is a pie and with innerRadius a donut.
Returns:
VlChartMark: The new mark, so its channels and properties chain.
2164 def label(self) -> VlChartMark: 2165 """Adds a text mark, which draws the value of its `text` channel. 2166 2167 Returns: 2168 VlChartMark: The new mark, so its channels and properties chain. 2169 """ 2170 return self.mark("text");
Adds a text mark, which draws the value of its text channel.
Returns:
VlChartMark: The new mark, so its channels and properties chain.
2171 def boxplot(self) -> VlChartMark: 2172 """Adds a boxplot mark to the chart. 2173 2174 A box and whiskers, computed from the rows rather than read off them. 2175 2176 Returns: 2177 VlChartMark: The new mark, so its channels and properties chain. 2178 """ 2179 return self.mark("boxplot");
Adds a boxplot mark to the chart.
A box and whiskers, computed from the rows rather than read off them.
Returns:
VlChartMark: The new mark, so its channels and properties chain.
2180 def errorbar(self) -> VlChartMark: 2181 """Adds an error bar: an interval computed from the rows rather than read off them. 2182 2183 `extent` decides what the interval is — `stderr` by default, or `stdev`, `ci` 2184 or `iqr`. 2185 2186 Returns: 2187 VlChartMark: The new mark, so its channels and properties chain. 2188 2189 See Also: 2190 errorband 2191 """ 2192 return self.mark("errorbar");
Adds an error bar: an interval computed from the rows rather than read off them.
extent decides what the interval is — stderr by default, or stdev, ci
or iqr.
Returns:
VlChartMark: The new mark, so its channels and properties chain.
See Also:
errorband
2193 def errorband(self) -> VlChartMark: 2194 """Adds an error band: the same interval as an error bar, drawn as a filled region. 2195 2196 Returns: 2197 VlChartMark: The new mark, so its channels and properties chain. 2198 2199 See Also: 2200 errorbar 2201 """ 2202 return self.mark("errorband");
Adds an error band: the same interval as an error bar, drawn as a filled region.
Returns:
VlChartMark: The new mark, so its channels and properties chain.
See Also:
errorbar
2203 def trail(self) -> VlChartMark: 2204 """Adds a trail mark to the chart. 2205 2206 A line whose width says something: a trail thickens with its `size`. 2207 2208 Returns: 2209 VlChartMark: The new mark, so its channels and properties chain. 2210 """ 2211 return self.mark("trail");
Adds a trail mark to the chart.
A line whose width says something: a trail thickens with its size.
Returns:
VlChartMark: The new mark, so its channels and properties chain.
2212 def image(self) -> VlChartMark: 2213 """Adds an image mark to the chart. 2214 2215 A picture per row, placed by its position channels. 2216 2217 Returns: 2218 VlChartMark: The new mark, so its channels and properties chain. 2219 """ 2220 return self.mark("image");
Adds an image mark to the chart.
A picture per row, placed by its position channels.
Returns:
VlChartMark: The new mark, so its channels and properties chain.
2221 def geoshape(self) -> VlChartMark: 2222 """Adds a geoshape mark to the chart. 2223 2224 A map: the shapes come from the data and the projection places them. 2225 2226 Returns: 2227 VlChartMark: The new mark, so its channels and properties chain. 2228 """ 2229 return self.mark("geoshape");
Adds a geoshape mark to the chart.
A map: the shapes come from the data and the projection places them.
Returns:
VlChartMark: The new mark, so its channels and properties chain.
2230 def latest(self) -> VlChartMark: 2231 """The mark added last, for a caller that built one and let go of it. 2232 2233 A chart with no marks answers a mark belonging to nothing and reports it in 2234 `errors`, rather than quietly adding a `point` nobody asked for. 2235 2236 Returns: 2237 VlChartMark: The last mark added. 2238 """ 2239 n = len(self.marks) 2240 if n > 0: 2241 return self.marks[(n - 1)]; 2242 self.error("the chart has no marks, so there is no last one") 2243 loose = VlChartMark() 2244 loose.owner = self; 2245 return loose;
2246 def channel(self, name: str, field: str) -> VlChart: 2247 """Sets a channel that every mark on this view inherits. 2248 2249 Args: 2250 name (str): The channel name. 2251 field (str): The column name. 2252 2253 Returns: 2254 VlChart: This chart, so calls chain. 2255 """ 2256 ch = VlJson.objectValue() 2257 ch.setMember("field", VlJson.stringValue(field)) 2258 self.enc.setMember(name, ch) 2259 self.cursor = name; 2260 return self;
Sets a channel that every mark on this view inherits.
Arguments:
- name (str): The channel name.
- field (str): The column name.
Returns:
VlChart: This chart, so calls chain.
2261 def x(self, field: str) -> VlChart: 2262 """Position along the horizontal axis. 2263 2264 Names a COLUMN, never a constant. `.color("red")` means a column 2265 called red; painting a mark red is `markColor`. 2266 2267 Args: 2268 field (str): The column name. 2269 2270 Returns: 2271 VlChart: This view, so channels chain. 2272 """ 2273 return self.channel("x", field);
Position along the horizontal axis.
Names a COLUMN, never a constant. .color("red") means a column
called red; painting a mark red is markColor.
Arguments:
- field (str): The column name.
Returns:
VlChart: This view, so channels chain.
2274 def y(self, field: str) -> VlChart: 2275 """Position along the vertical axis. 2276 2277 Names a COLUMN, never a constant. `.color("red")` means a column 2278 called red; painting a mark red is `markColor`. 2279 2280 Args: 2281 field (str): The column name. 2282 2283 Returns: 2284 VlChart: This view, so channels chain. 2285 """ 2286 return self.channel("y", field);
Position along the vertical axis.
Names a COLUMN, never a constant. .color("red") means a column
called red; painting a mark red is markColor.
Arguments:
- field (str): The column name.
Returns:
VlChart: This view, so channels chain.
2287 def color(self, field: str) -> VlChart: 2288 """Colour, and the legend that explains it. 2289 2290 Names a COLUMN, never a constant. `.color("red")` means a column 2291 called red; painting a mark red is `markColor`. 2292 2293 Args: 2294 field (str): The column name. 2295 2296 Returns: 2297 VlChart: This view, so channels chain. 2298 """ 2299 return self.channel("color", field);
Colour, and the legend that explains it.
Names a COLUMN, never a constant. .color("red") means a column
called red; painting a mark red is markColor.
Arguments:
- field (str): The column name.
Returns:
VlChart: This view, so channels chain.
2300 def detail(self, field: str) -> VlChart: 2301 """Groups the rows without drawing anything of its own: one line per group, no legend. 2302 2303 Names a COLUMN, never a constant. `.color("red")` means a column 2304 called red; painting a mark red is `markColor`. 2305 2306 Args: 2307 field (str): The column name. 2308 2309 Returns: 2310 VlChart: This view, so channels chain. 2311 """ 2312 return self.channel("detail", field);
Groups the rows without drawing anything of its own: one line per group, no legend.
Names a COLUMN, never a constant. .color("red") means a column
called red; painting a mark red is markColor.
Arguments:
- field (str): The column name.
Returns:
VlChart: This view, so channels chain.
2313 def encodeJson(self, channel: str, definition: VlJson) -> VlChart: 2314 """Sets a whole shared channel from an already-built definition. 2315 2316 Args: 2317 channel (str): The channel name. 2318 definition (VlJson): The channel definition. 2319 2320 Returns: 2321 VlChart: This chart, so calls chain. 2322 """ 2323 self.enc.setMember(channel, definition) 2324 self.cursor = channel; 2325 return self;
Sets a whole shared channel from an already-built definition.
Arguments:
- channel (str): The channel name.
- definition (VlJson): The channel definition.
Returns:
VlChart: This chart, so calls chain.
2326 def on(self, channel: str) -> VlChart: 2327 """Moves the cursor back to a shared channel that is already set. 2328 2329 Args: 2330 channel (str): The channel name. 2331 2332 Returns: 2333 VlChart: This chart, so calls chain. 2334 """ 2335 if self.enc.has(channel): 2336 self.cursor = channel; 2337 else: 2338 self.error(("no channel called '" + channel) + "' has been set on this view") 2339 return self;
Moves the cursor back to a shared channel that is already set.
Arguments:
- channel (str): The channel name.
Returns:
VlChart: This chart, so calls chain.
2357 def title(self, label: str) -> VlChart: 2358 """The axis or legend label for the shared cursor channel. 2359 2360 Args: 2361 label (str): The label. 2362 2363 Returns: 2364 VlChart: This chart, so calls chain. 2365 2366 See Also: 2367 heading 2368 """ 2369 return self.setOnCursor("title", VlJson.stringValue(label));
The axis or legend label for the shared cursor channel.
Arguments:
- label (str): The label.
Returns:
VlChart: This chart, so calls chain.
See Also:
heading
2370 def timeUnit(self, unit: str) -> VlChart: 2371 """Which part of an instant a shared channel reads. 2372 2373 Args: 2374 unit (str): The time unit. 2375 2376 Returns: 2377 VlChart: This chart, so calls chain. 2378 """ 2379 return self.setOnCursor("timeUnit", VlJson.stringValue(unit));
Which part of an instant a shared channel reads.
Arguments:
- unit (str): The time unit.
Returns:
VlChart: This chart, so calls chain.
2380 def keepOrder(self) -> VlChart: 2381 """Keeps the order the rows arrived in for the shared cursor channel. 2382 2383 Returns: 2384 VlChart: This chart, so calls chain. 2385 """ 2386 return self.setOnCursor("sort", VlJson.nullValue());
Keeps the order the rows arrived in for the shared cursor channel.
Returns:
VlChart: This chart, so calls chain.
2387 def size(self, width: int, height: int) -> VlChart: 2388 """How big the plotting area is, in pixels. 2389 2390 Args: 2391 width (int): The width. 2392 height (int): The height. 2393 2394 Returns: 2395 VlChart: This chart, so calls chain. 2396 """ 2397 self.props.setMember("width", VlJson.intValue(width)) 2398 self.props.setMember("height", VlJson.intValue(height)) 2399 return self;
How big the plotting area is, in pixels.
Arguments:
- width (int): The width.
- height (int): The height.
Returns:
VlChart: This chart, so calls chain.
2400 def width(self, value: int) -> VlChart: 2401 """How wide the plotting area is, in pixels. 2402 2403 Args: 2404 value (int): The width. 2405 2406 Returns: 2407 VlChart: This chart, so calls chain. 2408 """ 2409 self.props.setMember("width", VlJson.intValue(value)) 2410 return self;
How wide the plotting area is, in pixels.
Arguments:
- value (int): The width.
Returns:
VlChart: This chart, so calls chain.
2411 def height(self, value: int) -> VlChart: 2412 """How tall the plotting area is, in pixels. 2413 2414 Args: 2415 value (int): The height. 2416 2417 Returns: 2418 VlChart: This chart, so calls chain. 2419 """ 2420 self.props.setMember("height", VlJson.intValue(value)) 2421 return self;
How tall the plotting area is, in pixels.
Arguments:
- value (int): The height.
Returns:
VlChart: This chart, so calls chain.
2422 def heading(self, text: str) -> VlChart: 2423 """The chart's title, drawn above the plot. 2424 2425 Args: 2426 text (str): The title. 2427 2428 Returns: 2429 VlChart: This chart, so calls chain. 2430 2431 See Also: 2432 title 2433 """ 2434 self.props.setMember("title", VlJson.stringValue(text)) 2435 return self;
The chart's title, drawn above the plot.
Arguments:
- text (str): The title.
Returns:
VlChart: This chart, so calls chain.
See Also:
title
2436 def background(self, colour: str) -> VlChart: 2437 """The colour behind the plot. 2438 2439 Args: 2440 colour (str): A CSS colour. 2441 2442 Returns: 2443 VlChart: This chart, so calls chain. 2444 """ 2445 self.props.setMember("background", VlJson.stringValue(colour)) 2446 return self;
The colour behind the plot.
Arguments:
- colour (str): A CSS colour.
Returns:
VlChart: This chart, so calls chain.
2447 def propJson(self, key: str, value: VlJson) -> VlChart: 2448 """Sets any top-level property of the specification. 2449 2450 Args: 2451 key (str): The property name. 2452 value (VlJson): The value. 2453 2454 Returns: 2455 VlChart: This chart, so calls chain. 2456 """ 2457 self.props.setMember(key, value) 2458 return self;
Sets any top-level property of the specification.
Arguments:
- key (str): The property name.
- value (VlJson): The value.
Returns:
VlChart: This chart, so calls chain.
2459 def configJson(self, config: VlJson) -> VlChart: 2460 """Merges a configuration block into the specification. 2461 2462 Args: 2463 config (VlJson): The configuration object. 2464 2465 Returns: 2466 VlChart: This chart, so calls chain. 2467 """ 2468 for ki, k in enumerate(config.keys): 2469 self.cfg.setMember(k, config.get(k)) 2470 return self;
Merges a configuration block into the specification.
Arguments:
- config (VlJson): The configuration object.
Returns:
VlChart: This chart, so calls chain.
2484 def calculate(self, expression: str, _as: str) -> VlChart: 2485 """Adds a column computed from the others. 2486 2487 Args: 2488 expression (str): A Vega expression over the row's columns. 2489 _as (str): The name of the new column. 2490 2491 Returns: 2492 VlChart: This chart, so calls chain. 2493 """ 2494 t = VlJson.objectValue() 2495 t.setMember("calculate", VlJson.stringValue(expression)) 2496 t.setMember("as", VlJson.stringValue(_as)) 2497 self.transforms.arr.append(t) 2498 return self;
Adds a column computed from the others.
Arguments:
- expression (str): A Vega expression over the row's columns.
- _as (str): The name of the new column.
Returns:
VlChart: This chart, so calls chain.
2499 def transformJson(self, transform: VlJson) -> VlChart: 2500 """Appends an already-built transform. 2501 2502 Args: 2503 transform (VlJson): The transform definition. 2504 2505 Returns: 2506 VlChart: This chart, so calls chain. 2507 """ 2508 self.transforms.arr.append(transform) 2509 return self;
Appends an already-built transform.
Arguments:
- transform (VlJson): The transform definition.
Returns:
VlChart: This chart, so calls chain.
2510 def independent(self, channel: str) -> VlChart: 2511 """Stops the layers sharing one scale on a channel. 2512 2513 Two marks measuring different things up the same side of the plot must not 2514 share a scale. This is what makes a Pareto chart — bars against a count, a 2515 line against a running percentage — rather than two series averaged into one 2516 axis neither of them asked for. 2517 2518 Args: 2519 channel (str): The channel to split, usually "y". 2520 2521 Returns: 2522 VlChart: This chart, so calls chain. 2523 """ 2524 scales = self.resolve.get("scale") 2525 if False == scales.isObject(): 2526 fresh = VlJson.objectValue() 2527 self.resolve.setMember("scale", fresh) 2528 scales = fresh; 2529 scales.setMember(channel, VlJson.stringValue("independent")) 2530 return self;
Stops the layers sharing one scale on a channel.
Two marks measuring different things up the same side of the plot must not share a scale. This is what makes a Pareto chart — bars against a count, a line against a running percentage — rather than two series averaged into one axis neither of them asked for.
Arguments:
- channel (str): The channel to split, usually "y".
Returns:
VlChart: This chart, so calls chain.
2536 def mergedEncoding(self, m: VlChartMark) -> VlJson: 2537 out = VlJson.objectValue() 2538 for ki, k in enumerate(self.enc.keys): 2539 shared = self.enc.get(k) 2540 out.setMember(k, VlChart.copyOf(shared)) 2541 for mi, mk in enumerate(m.enc.keys): 2542 own = m.enc.get(mk) 2543 out.setMember(mk, VlChart.copyOf(own)) 2544 self.resolveTypes(out) 2545 return out;
2546 def resolveTypes(self, encoding: VlJson) -> None: 2547 for ki, k in enumerate(encoding.keys): 2548 ch = encoding.get(k) 2549 if ch.isArray(): 2550 i = 0 2551 n = ch.count() 2552 while i < n: 2553 one = ch.at(i) 2554 if one.isObject(): 2555 if False == one.has("type"): 2556 listKind = self.inferType(one) 2557 if len(listKind) > 0: 2558 one.setMember("type", VlJson.stringValue(listKind)) 2559 i = i + 1; 2560 if ch.isObject(): 2561 if False == ch.has("type"): 2562 if False == ch.has("value"): 2563 kind = self.inferType(ch) 2564 if len(kind) > 0: 2565 ch.setMember("type", VlJson.stringValue(kind))
2566 def inferType(self, ch: VlJson) -> str: 2567 if ch.has("bin"): 2568 return "quantitative"; 2569 if ch.has("timeUnit"): 2570 return "temporal"; 2571 if ch.has("aggregate"): 2572 return "quantitative"; 2573 if False == ch.has("field"): 2574 return ""; 2575 field = ch.stringOr("field", "") 2576 if self.data.count() == 0: 2577 return "nominal"; 2578 kind = self.data.fieldType(field) 2579 if len(kind) == 0: 2580 self.error(("the data has no column called '" + field) + "'") 2581 return "nominal"; 2582 return kind;
2583 def toSpec(self) -> VlJson: 2584 """The chart as a Vega-Lite specification. 2585 2586 One mark comes out as a plain specification; several come out as layers, each 2587 carrying the shared channels in full — a specification that states everything 2588 is one the compiler already handles and one a person can read in a diff. 2589 2590 May be called more than once. Check `errors` afterwards: a chart that names a 2591 column its data does not have is reported here, where Vega-Lite would have 2592 drawn an empty axis and said nothing. 2593 2594 Returns: 2595 VlJson: A Vega-Lite specification, ready for `VlCompile`. 2596 2597 Example: 2598 data = VlDataset.create() 2599 data.row()._str("region", "North").num("sales", 120) 2600 data.row()._str("region", "South").num("sales", 93) 2601 chart = VlChart.create(data) 2602 chart.size(300, 200) 2603 chart.bar().x("region").y("sales").aggregate("sum") 2604 _spec = chart.toSpec() 2605 """ 2606 out = VlJson.objectValue() 2607 for ki, k in enumerate(self.props.keys): 2608 out.setMember(k, self.props.get(k)) 2609 out.setMember("data", self.data.toValues()) 2610 if self.transforms.count() > 0: 2611 out.setMember("transform", self.transforms) 2612 markCount = len(self.marks) 2613 if markCount == 0: 2614 self.error("the chart has no marks") 2615 return out; 2616 if markCount == 1: 2617 only = self.marks[0] 2618 out.setMember("mark", VlChart.markValue(only)) 2619 out.setMember("encoding", self.mergedEncoding(only)) 2620 else: 2621 layers = VlJson.arrayValue() 2622 for m in self.marks: 2623 layer = VlJson.objectValue() 2624 layer.setMember("mark", VlChart.markValue(m)) 2625 layer.setMember("encoding", self.mergedEncoding(m)) 2626 layers.arr.append(layer) 2627 out.setMember("layer", layers) 2628 resolveCount = len(self.resolve.keys) 2629 if resolveCount > 0: 2630 out.setMember("resolve", self.resolve) 2631 cfgCount = len(self.cfg.keys) 2632 if cfgCount > 0: 2633 out.setMember("config", self.cfg) 2634 return out;
The chart as a Vega-Lite specification.
One mark comes out as a plain specification; several come out as layers, each carrying the shared channels in full — a specification that states everything is one the compiler already handles and one a person can read in a diff.
May be called more than once. Check errors afterwards: a chart that names a
column its data does not have is reported here, where Vega-Lite would have
drawn an empty axis and said nothing.
Returns:
VlJson: A Vega-Lite specification, ready for
VlCompile.
Example:
data = VlDataset.create() data.row()._str("region", "North").num("sales", 120) data.row()._str("region", "South").num("sales", 93) chart = VlChart.create(data) chart.size(300, 200) chart.bar().x("region").y("sales").aggregate("sum") _spec = chart.toSpec()