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"]
class VlJson:
 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.

kind
num
b
arr
keys
members
isInt
@staticmethod
def nullValue() -> VlJson:
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.

@staticmethod
def boolValue(value: bool) -> VlJson:
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.

@staticmethod
def numberValue(value: float) -> VlJson:
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

@staticmethod
def intValue(value: int) -> VlJson:
 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

@staticmethod
def stringValue(value: str) -> VlJson:
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.

@staticmethod
def arrayValue() -> VlJson:
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.

@staticmethod
def objectValue() -> VlJson:
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.

@staticmethod
def numberToText(value: float, wasInt: bool) -> str:
141  @staticmethod
142  def numberToText(value: float, wasInt: bool) -> str:
143    return VlJson.formatNumber(value, 6);
@staticmethod
def formatSignificant(value: float, digits: int) -> str:
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);
@staticmethod
def withMinusSign(text: str) -> str:
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;
@staticmethod
def domainKey(cell: VlJson) -> str:
164  @staticmethod
165  def domainKey(cell: VlJson) -> str:
166    if cell.isNull():
167      return "null";
168    return cell.asString();
@staticmethod
def formatNumber(value: float, maxDecimals: int) -> str:
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;
@staticmethod
def digitAt(rest: float, place: float) -> int:
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;
@staticmethod
def fractionDigits(frac: float, maxDecimals: int) -> str:
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];
@staticmethod
def intToText(value: int) -> str:
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;
@staticmethod
def digitChar(d: int) -> str:
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";
def isNull(self) -> bool:
299  def isNull(self) -> bool:
300    return self.kind == 0;
def isBool(self) -> bool:
301  def isBool(self) -> bool:
302    return self.kind == 1;
def isNumber(self) -> bool:
303  def isNumber(self) -> bool:
304    return self.kind == 2;
def isString(self) -> bool:
305  def isString(self) -> bool:
306    return self.kind == 3;
def isArray(self) -> bool:
307  def isArray(self) -> bool:
308    return self.kind == 4;
def isObject(self) -> bool:
309  def isObject(self) -> bool:
310    return self.kind == 5;
def isDefined(self) -> bool:
311  def isDefined(self) -> bool:
312    return self.kind != 0;
def looksNumeric(self) -> bool:
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;
def asInt(self) -> int:
324  def asInt(self) -> int:
325    return math.floor(self.num);
def asDouble(self) -> float:
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;
def asString(self) -> str:
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 "";
def asBool(self) -> bool:
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;
def count(self) -> int:
365  def count(self) -> int:
366    return len(self.arr);
def at(self, index: int) -> VlJson:
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];
def has(self, key: str) -> bool:
373  def has(self, key: str) -> bool:
374    return key in self.members;
def get(self, key: str) -> VlJson:
375  def get(self, key: str) -> VlJson:
376    if key in self.members:
377      return self.members.get(key);
378    return VlJson.nullValue();
def intOr(self, key: str, dflt: int) -> int:
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;
def doubleOr(self, key: str, dflt: float) -> float:
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;
def stringOr(self, key: str, dflt: str) -> str:
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;
def boolOr(self, key: str, dflt: bool) -> bool:
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;
def setMember(self, key: str, value: VlJson) -> None:
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;
def removeMember(self, key: str) -> None:
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;
class VlDataRow:
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)

obj
owner
def num(self, field: str, value: float) -> VlDataRow:
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.

def whole(self, field: str, value: int) -> VlDataRow:
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

def flag(self, field: str, value: bool) -> VlDataRow:
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.

def json(self, field: str, value: VlJson) -> VlDataRow:
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.

def back(self) -> VlDataset:
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.

class VlDataset:
 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)

rows
name
@staticmethod
def create() -> VlDataset:
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.

@staticmethod
def looksLikeDate(text: str) -> bool:
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;
def row(self) -> VlDataRow:
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

def addRow(self, row: VlJson) -> VlDataset:
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.

def fromValues(self, values: VlJson) -> VlDataset:
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.

def numbers(self, field: str, values: list[float]) -> VlDataset:
 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

def strings(self, field: str, values: list[str]) -> VlDataset:
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

def rowAt(self, index: int) -> VlJson:
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.

def count(self) -> int:
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.

def hasField(self, field: str) -> bool:
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.

def fieldType(self, field: str) -> str:
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.

def toValues(self) -> VlJson:
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.

class VlChartMark:
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")

markType
props
enc
cursor
owner
def note(self, message: str) -> None:
1136  def note(self, message: str) -> None:
1137    if (self.owner is not None):
1138      o = self.owner
1139      o.error(message)
def channel(self, name: str, field: str) -> VlChartMark:
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;

Sets any channel to a column by name.

The named channel becomes the cursor, so the next aggregate, title or type applies to it.

Arguments:
  • name (str): The channel name, as Vega-Lite spells it.
  • field (str): The column name.
Returns:

VlChartMark: This mark, so calls chain.

def x(self, field: str) -> VlChartMark:
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.

def y(self, field: str) -> VlChartMark:
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.

def x2(self, field: str) -> VlChartMark:
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

def y2(self, field: str) -> VlChartMark:
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

def color(self, field: str) -> VlChartMark:
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.

def fill(self, field: str) -> VlChartMark:
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

def stroke(self, field: str) -> VlChartMark:
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

def size(self, field: str) -> VlChartMark:
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

def shape(self, field: str) -> VlChartMark:
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.

def opacity(self, field: str) -> VlChartMark:
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

def theta(self, field: str) -> VlChartMark:
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

def radius(self, field: str) -> VlChartMark:
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

def detail(self, field: str) -> VlChartMark:
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.

def text(self, field: str) -> VlChartMark:
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.

def order(self, field: str) -> VlChartMark:
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.

def column(self, field: str) -> VlChartMark:
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

def row(self, field: str) -> VlChartMark:
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

def xOffset(self, field: str) -> VlChartMark:
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

def yOffset(self, field: str) -> VlChartMark:
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

def count(self, channel: str) -> VlChartMark:
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.

def valueNumber(self, channel: str, value: float) -> VlChartMark:
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

def valueString(self, channel: str, value: str) -> VlChartMark:
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

def encodeJson( self, channel: str, definition: VlJson) -> VlChartMark:
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.

def on(self, channel: str) -> VlChartMark:
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.

def cursorChannel(self) -> VlJson:
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);
def setOnCursor(self, key: str, value: VlJson) -> VlChartMark:
1536  def setOnCursor(self, key: str, value: VlJson) -> VlChartMark:
1537    ch = self.cursorChannel()
1538    ch.setMember(key, value)
1539    return self;
def aggregate(self, op: str) -> VlChartMark:
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, count and the rest of Vega-Lite's operations.
Returns:

VlChartMark: This mark, so calls chain.

def maxBins(self, count: int) -> VlChartMark:
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

def timeUnit(self, unit: str) -> VlChartMark:
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.

def title(self, label: str) -> VlChartMark:
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.

def stack(self, how: str) -> VlChartMark:
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, normalize or center.
Returns:

VlChartMark: This mark, so calls chain.

See Also:

noStack

def noStack(self) -> VlChartMark:
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

def sortBy(self, field: str) -> VlChartMark:
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

def keepOrder(self) -> VlChartMark:
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

def scaleJson(self, scale: VlJson) -> VlChartMark:
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.

def scaleType(self, kind: str) -> VlChartMark:
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, point and the rest.
Returns:

VlChartMark: This mark, so calls chain.

def scheme(self, name: str) -> VlChartMark:
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 category10 or viridis.
Returns:

VlChartMark: This mark, so calls chain.

def noLegend(self) -> VlChartMark:
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.

def noAxis(self) -> VlChartMark:
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.

def axisOrient(self, side: str) -> VlChartMark:
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, top or bottom.
Returns:

VlChartMark: This mark, so calls chain.

def axisJson(self, axis: VlJson) -> VlChartMark:
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.

def propNumber(self, key: str, value: float) -> VlChartMark:
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.

def propString(self, key: str, value: str) -> VlChartMark:
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.

def propFlag(self, key: str, value: bool) -> VlChartMark:
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.

def filled(self, value: bool) -> VlChartMark:
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.

def markSize(self, value: float) -> VlChartMark:
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

def markColor(self, value: str) -> VlChartMark:
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

def markOpacity(self, value: float) -> VlChartMark:
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

def interpolate(self, kind: str) -> VlChartMark:
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, basis and the rest.
Returns:

VlChartMark: This mark, so calls chain.

def withPoints(self, value: bool) -> VlChartMark:
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.

def innerRadius(self, value: float) -> VlChartMark:
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.

def cornerRadius(self, value: float) -> VlChartMark:
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.

def tooltip(self, value: bool) -> VlChartMark:
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

def tooltipField(self, field: str) -> VlChartMark:
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

def tooltipFields(self, fields: list[str]) -> VlChartMark:
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

def thickness(self, value: float) -> VlChartMark:
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.

def strokeWidth(self, value: float) -> VlChartMark:
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.

def orient(self, value: str) -> VlChartMark:
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): horizontal or vertical.
Returns:

VlChartMark: This mark, so calls chain.

def extent(self, value: str) -> VlChartMark:
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, ci or iqr.
Returns:

VlChartMark: This mark, so calls chain.

def chart(self) -> VlChart:
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.

class VlChart:
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()

data
marks
enc
cursor
props
transforms
cfg
resolve
errors
@staticmethod
def create(data: VlDataset) -> VlChart:
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

@staticmethod
def copyOf(v: VlJson) -> VlJson:
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;
@staticmethod
def markValue(m: VlChartMark) -> VlJson:
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;
def mark(self, markType: str) -> VlChartMark:
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.

def bar(self) -> VlChartMark:
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.

def line(self) -> VlChartMark:
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.

def area(self) -> VlChartMark:
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.

def point(self) -> VlChartMark:
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.

def circle(self) -> VlChartMark:
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.

def square(self) -> VlChartMark:
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.

def tick(self) -> VlChartMark:
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.

def rule(self) -> VlChartMark:
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.

def rect(self) -> VlChartMark:
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.

def arc(self) -> VlChartMark:
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.

def label(self) -> VlChartMark:
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.

def boxplot(self) -> VlChartMark:
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.

def errorbar(self) -> VlChartMark:
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

def errorband(self) -> VlChartMark:
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

def trail(self) -> VlChartMark:
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.

def image(self) -> VlChartMark:
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.

def geoshape(self) -> VlChartMark:
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.

def latest(self) -> VlChartMark:
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;

The mark added last, for a caller that built one and let go of it.

A chart with no marks answers a mark belonging to nothing and reports it in errors, rather than quietly adding a point nobody asked for.

Returns:

VlChartMark: The last mark added.

def channel(self, name: str, field: str) -> VlChart:
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.

def x(self, field: str) -> VlChart:
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.

def y(self, field: str) -> VlChart:
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.

def color(self, field: str) -> VlChart:
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.

def detail(self, field: str) -> VlChart:
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.

def encodeJson(self, channel: str, definition: VlJson) -> VlChart:
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.

def on(self, channel: str) -> VlChart:
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.

def setOnCursor(self, key: str, value: VlJson) -> VlChart:
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;
def title(self, label: str) -> VlChart:
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

def timeUnit(self, unit: str) -> VlChart:
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.

def keepOrder(self) -> VlChart:
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.

def size(self, width: int, height: int) -> VlChart:
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.

def width(self, value: int) -> VlChart:
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.

def height(self, value: int) -> VlChart:
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.

def heading(self, text: str) -> VlChart:
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

def background(self, colour: str) -> VlChart:
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.

def propJson(self, key: str, value: VlJson) -> VlChart:
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.

def configJson(self, config: VlJson) -> VlChart:
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.

def calculate(self, expression: str, _as: str) -> VlChart:
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.

def transformJson(self, transform: VlJson) -> VlChart:
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.

def independent(self, channel: str) -> VlChart:
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.

def error(self, message: str) -> None:
2531  def error(self, message: str) -> None:
2532    for said in self.errors:
2533      if said == message:
2534        return;
2535    self.errors.append(message)
def mergedEncoding(self, m: VlChartMark) -> VlJson:
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;
def resolveTypes(self, encoding: VlJson) -> None:
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))
def inferType(self, ch: VlJson) -> str:
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;
def toSpec(self) -> VlJson:
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()

def toText(self) -> str:
2635  def toText(self) -> str:
2636    spec = self.toSpec()
2637    w = VlJsonWriter()
2638    return w.write(spec);