示例#1
0
export function indataVisitor(name, args, scope, params) {
  if (args[0].type !== Literal) error('First argument to indata must be a string literal.');
  if (args[1].type !== Literal) error('Second argument to indata must be a string literal.');

  var data = args[0].value,
      field = args[1].value,
      indexName = indexPrefix + field;

  if (!params.hasOwnProperty(indexName)) {
    params[indexName] = scope.getData(data).indataRef(scope, field);
  }
}
示例#2
0
export default function(data, format) {
  var method, object, property;
  data = json(data, format);

  method = (format && (property = format.feature)) ? feature
    : (format && (property = format.mesh)) ? mesh
    : error('Missing TopoJSON feature or mesh parameter.');

  object = (object = data.objects[property])
    ? method(data, object)
    : error('Invalid TopoJSON object: ' + property);

  return object && object.features || [object];
}
示例#3
0
function parseSort(sort, multidomain) {
  if (sort) {
    if (!sort.field && !sort.op) {
      if (isObject(sort)) sort.field = 'key';
      else sort = {field: 'key'};
    } else if (!sort.field && sort.op !== 'count') {
      error('No field provided for sort aggregate op: ' + sort.op);
    } else if (multidomain && sort.field) {
      error('Multiple domain scales can not sort by field.');
    } else if (multidomain && sort.op && sort.op !== 'count') {
      error('Multiple domain scales support op count only.');
    }
  }
  return sort;
}
示例#4
0
function dataref(view, name) {
  var data = view._runtime.data;
  if (!data.hasOwnProperty(name)) {
    error('Unrecognized data set: ' + name);
  }
  return data[name];
}
示例#5
0
prototype.transform = function(_, pulse) {
  var sx = _.sourceX || sourceX,
      sy = _.sourceY || sourceY,
      tx = _.targetX || targetX,
      ty = _.targetY || targetY,
      orient = _.orient || 'vertical',
      shape = _.shape || 'line',
      path = PATHS.get(shape + '-' + orient) || PATHS.get(shape);

  if (!path) {
    error('LinkPath unsupported type: ' + _.shape + '-' + _.orient);
  }

  function set(t) {
    t.path = path(sx(t), sy(t), tx(t), ty(t));
  }

  if (_.modified()) {
    pulse.visit(pulse.SOURCE, set).reflow();
  } else {
    pulse.visit(pulse.ALL, set);
  }

  return pulse.modifies('path');
};
示例#6
0
/**
 * Parse a parameter object for a probability distribution.
 * @param {object} def - The distribution parameter object.
 * @param {function():Array<object>} - A method for requesting
 *   source data. Used for distributions (such as KDE) that
 *   require sample data points. This method will only be
 *   invoked if the 'from' parameter for a target data source
 *   is not provided. Typically this method returns backing
 *   source data for a Pulse object.
 * @return {object} - The output distribution object.
 */
export default function parse(def, data) {
  var func = def[FUNCTION];
  if (!Distributions.hasOwnProperty(func)) {
    error('Unknown distribution function: ' + func);
  }

  var d = Distributions[func]();

  for (var name in def) {
    // if data field, extract values
    if (name === FIELD) {
      d.data((def.from || data()).map(def[name]));
    }

    // if distribution mixture, recurse to parse each definition
    else if (name === DISTRIBUTIONS) {
      d[name](def[name].map(function(_) { return parse(_, data); }));
    }

    // otherwise, simply set the parameter
    else if (typeof d[name] === FUNCTION) {
      d[name](def[name]);
    }
  }

  return d;
}
示例#7
0
function getForce(_) {
  var f, p;
  if (!FORCE_MAP.has(_.force)) error('Unrecognized force: ' + _.force);
  f = FORCE_MAP.get(_.force)();
  for (p in _) if (isFunction(f[p])) f[p](_[p]);
  return f;
}
示例#8
0
prototype.transform = function(_, pulse) {
  if (!pulse.source) {
    error('Stratify transform requires an upstream data source.');
  }

  var tree = this.value,
      mod = _.modified(),
      out = pulse.fork(pulse.ALL).materialize(pulse.SOURCE),
      run = !this.value
         || mod
         || pulse.changed(pulse.ADD_REM)
         || pulse.modified(_.key.fields)
         || pulse.modified(_.parentKey.fields);

  // prevent upstream source pollution
  out.source = out.source.slice();

  if (run) {
    if (out.source.length) {
      tree = lookup(
        stratify().id(_.key).parentId(_.parentKey)(out.source)
        , _.key, truthy);
    } else {
      tree = lookup(stratify()([{}]), _.key, _.key);
    }
  }

  out.source.root = this.value = tree;
  return out;
};
示例#9
0
prototype.transform = function(_, pulse) {
  if (!pulse.source) {
    error('Rank transform requires an upstream data source.');
  }

  var norm  = _.normalize,
      field = _.field,
      ranks = {},
      n = -1, rank;

  if (field) {
    // If we have a field accessor, first compile distinct keys.
    pulse.visit(pulse.SOURCE, function(t) {
      var v = field(t);
      if (ranks[v] == null) ranks[v] = ++n;
    });
    pulse.visit(pulse.SOURCE, norm && --n
      ? function(t) { t.rank = ranks[field(t)] / n; }
      : function(t) { t.rank = ranks[field(t)]; }
    );
  } else {
    n += pulse.source.length;
    rank = -1;
    // Otherwise rank all the tuples together.
    pulse.visit(pulse.SOURCE, norm && n
      ? function(t) { t.rank = ++rank / n; }
      : function(t) { t.rank = ++rank; }
    );
  }

  return pulse.reflow().modifies('rank');
};
示例#10
0
 array(value).forEach(function(op) {
   if (!(op instanceof Operator)) {
     error('Pulse parameters must be operator instances.');
   } else if (op !== self) {
     op.targets().add(self);
     deps.push(op);
   }
 });
示例#11
0
export default function parseStream(stream, scope) {
  var method = stream.merge ? mergeStream
    : stream.stream ? nestedStream
    : stream.type ? eventStream
    : error('Invalid stream specification: ' + stringValue(stream));

  return method(stream, scope);
}
示例#12
0
export function change(name, changes) {
  if (!isChangeSet(changes)) {
    error('Second argument to changes must be a changeset.');
  }
  var dataset = dataref(this, name);
  dataset.modified = true;
  return this.pulse(dataset.input, changes);
}
示例#13
0
export function intersect(scene, bounds, filter) {
  const hits = [], // intersection results
        box = new Bounds().union(bounds), // defensive copy
        type = scene.marktype;

  return type ? intersectMark(scene, box, filter, hits)
    : type === 'group' ? intersectGroup(scene, box, filter, hits)
    : error('Intersect scene must be mark node or group item.');
}
示例#14
0
文件: View.js 项目: glimpseio/vega
prototype.renderer = function(type) {
  if (!arguments.length) return this._renderType;
  if (!renderModule(type)) error('Unrecognized renderer type: ' + type);
  if (type !== this._renderType) {
    this._renderType = type;
    this._resetRenderer();
  }
  return this;
};
示例#15
0
/**
 * Render the current scene in a headless fashion.
 * This method is asynchronous, returning a Promise instance.
 * @return {Promise} - A Promise that resolves to a renderer.
 */
export default async function(view, type, scaleFactor, opt) {
  const module = renderModule(type),
        ctr = module && module.headless;

  if (!ctr) error('Unrecognized renderer type: ' + type);

  await view.runAsync();
  return initializeRenderer(view, null, null, ctr, scaleFactor, opt)
    .renderAsync(view._scenegraph.root);
}
示例#16
0
文件: mark.js 项目: vega/vega
 spec.transform.forEach(function(_) {
   const tx = parseTransform(_, scope),
         md = tx.metadata;
   if (md.generates || md.changes) {
     error('Mark transforms should not generate new data.');
   }
   if (!md.nomod) enc.params.mod = true; // update encode mod handling
   tx.params.pulse = ref(op);
   scope.add(op = tx);
 });
示例#17
0
prototype.transform = function(_, pulse) {
  if (!pulse.source || !pulse.source.root) {
    error('TreeLinks transform requires a backing tree data source.');
  }

  var root = pulse.source.root,
      nodes = root.lookup,
      links = this.value,
      key = _.key || tupleid,
      mods = {},
      out = pulse.fork();

  function modify(id) {
    var link = links[id];
    if (link) {
      mods[id] = 1;
      out.mod.push(link);
    }
  }

  // process removed tuples
  // assumes that if a parent node is removed the child will be, too.
  pulse.visit(pulse.REM, function(t) {
    var id = key(t),
        link = links[id];
    if (link) {
      delete links[id];
      out.rem.push(link);
    }
  });

  // create new link instances for added nodes with valid parents
  pulse.visit(pulse.ADD, function(t) {
    var id = key(t), p;
    if (p = parentTuple(nodes[id])) {
      out.add.push(links[id] = ingest({source: p, target: t}));
      mods[id] = 1;
    }
  });

  // process modified nodes and their children
  pulse.visit(pulse.MOD, function(t) {
    var id = key(t),
        node = nodes[id],
        kids = node.children;

    modify(id);
    if (kids) for (var i=0, n=kids.length; i<n; ++i) {
      if (!mods[(id=key(kids[i].data))]) modify(id);
    }
  });

  return out;
};
示例#18
0
function configureRangeStep(type, _, count) {
  if (type !== Band && type !== Point) {
    error('Only band and point scales support rangeStep.');
  }

  // calculate full range based on requested step size and padding
  var outer = (_.paddingOuter != null ? _.paddingOuter : _.padding) || 0,
      inner = type === Point ? 1
            : ((_.paddingInner != null ? _.paddingInner : _.padding) || 0);
  return [0, _.rangeStep * bandSpace(count, inner, outer)];
}
示例#19
0
export function dataVisitor(name, args, scope, params) {
  if (args[0].type !== Literal) {
    error('First argument to data functions must be a string literal.');
  }

  var data = args[0].value,
      dataName = dataPrefix + data;

  if (!params.hasOwnProperty(dataName)) {
    params[dataName] = scope.getData(data).tuplesRef();
  }
}
示例#20
0
文件: topojson.js 项目: vega/vega
export default function topojson(data, format) {
  let method, object, property, filter;
  data = json(data, format);

  if (format && format.feature) {
    method = feature;
    property = format.feature;
  } else if (format && format.mesh) {
    method = mesh;
    property = format.mesh;
    filter = filters[format.filter];
  } else {
    error('Missing TopoJSON feature or mesh parameter.');
  }

  object = (object = data.objects[property])
    ? method(data, object, filter)
    : error('Invalid TopoJSON object: ' + property);

  return object && object.features || [object];
}
示例#21
0
export function initScale(spec, scope) {
  var type = spec.type || 'linear';

  if (!allTypes.hasOwnProperty(type)) {
    error('Unrecognized scale type: ' + stringValue(type));
  }

  scope.addScale(spec.name, {
    type:   type,
    domain: undefined
  });
}
示例#22
0
prototype.transform = function(_, pulse) {
  if (!pulse.source || !pulse.source.root) {
    error(this.constructor.name
      + ' transform requires a backing tree data source.');
  }
  var layout = this.layout(_.method),
      root = pulse.source.root;

  if (_.field) root.sum(_.field);
  if (_.sort) root.sort(_.sort);

  this.setParams(layout, _);
  try {
    this.value = layout(root);
  } catch (err) {
    error(err);
  }
  root.each(this.setFields);

  return pulse.reflow().modifies(this.setParams.fields); // fork?
};
示例#23
0
export default function(data, schema, dateParse) {
  schema = schema || {};

  var reader = formats(schema.type || 'json');
  if (!reader) error('Unknown data format type: ' + schema.type);

  data = reader(data, schema);
  if (schema.parse) parse(data, schema.parse, dateParse);

  if (data.hasOwnProperty('columns')) delete data.columns;
  return data;
}
示例#24
0
function parseScaleDomain(domain, spec, scope) {
  if (!domain) {
    if (spec.domainMin != null || spec.domainMax != null) {
      error('No scale domain defined for domainMin/domainMax to override.');
    }
    return; // default domain
  }

  return domain.signal ? scope.signalRef(domain.signal)
    : (isArray(domain) ? explicitDomain
    : domain.fields ? multipleDomain
    : singularDomain)(domain, spec, scope);
}
示例#25
0
export function vlSelectionVisitor(name, args, scope, params) {
  if (args[0].type !== Literal) error('First argument to indata must be a string literal.');

  var data = args[0].value,
      op = args.length >= 2 && args[args.length-1].value,
      field = 'unit',
      indexName = indexPrefix + field;

  if (op === INTERSECT && !params.hasOwnProperty(indexName)) {
    params[indexName] = scope.getData(data).indataRef(scope, field);
  }

  dataVisitor(name, args, scope, params);
}
示例#26
0
文件: rank.js 项目: glimpseio/vega
export function rerank(op) {
  var queue = [op],
      cur, list, i;

  while (queue.length) {
    this.rank(cur = queue.pop());
    if (list = cur._targets) {
      for (i=list.length; --i >= 0;) {
        queue.push(cur = list[i]);
        if (cur === op) error('Cycle detected in dataflow graph.');
      }
    }
  }
}
示例#27
0
function parseScaleRange(spec, scope, params) {
  var range = spec.range,
      config = scope.config.range;

  if (range.signal) {
    return scope.signalRef(range.signal);
  } else if (isString(range)) {
    if (config && config.hasOwnProperty(range)) {
      spec = extend({}, spec, {range: config[range]});
      return parseScaleRange(spec, scope, params);
    } else if (range === 'width') {
      range = [0, {signal: 'width'}]
    } else if (range === 'height') {
      range = isOrdinal(spec.type)
        ? [0, {signal: 'height'}]
        : [{signal: 'height'}, 0]
    } else {
      error('Unrecognized scale range value: ' + stringValue(range));
    }
  } else if (range.scheme) {
    params.scheme = parseLiteral(range.scheme, scope);
    if (range.extent) params.schemeExtent = parseArray(range.extent, scope);
    if (range.count) params.schemeCount = parseLiteral(range.count, scope);
    return;
  } else if (range.step) {
    params.rangeStep = parseLiteral(range.step, scope);
    return;
  } else if (isOrdinal(spec.type) && !isArray(range)) {
    return parseScaleDomain(range, spec, scope);
  } else if (!isArray(range)) {
    error('Unsupported range type: ' + stringValue(range));
  }

  return range.map(function(v) {
    return parseLiteral(v, scope);
  });
}
示例#28
0
prototype.transform = function(_, pulse) {
  if (!pulse.source || !pulse.source.root) {
    error(this.constructor.name
      + ' transform requires a backing tree data source.');
  }

  var layout = this.layout(_.method),
      fields = this.fields,
      root = pulse.source.root,
      as = _.as || fields;

  if (_.field) root.sum(_.field);
  if (_.sort) root.sort(_.sort);

  setParams(layout, this.params, _);
  try {
    this.value = layout(root);
  } catch (err) {
    error(err);
  }
  root.each(function(node) { setFields(node, fields, as); });

  return pulse.reflow(_.modified()).modifies(as).modifies('leaf');
};
示例#29
0
prototype.transform = function(_, pulse) {
  if (!pulse.source) {
    error('Nest transform requires an upstream data source.');
  }

  var key = _.key || tupleid,
      gen = _.generate,
      mod = _.modified(),
      out = pulse.clone(),
      root, tree, map;

  if (!this.value || mod || pulse.changed()) {
    // collect nodes to remove
    if (gen && this.value) {
      this.value.each(function(node) {
        if (node.children) out.rem.push(node);
      });
    }

    // generate new tree structure
    root = array(_.keys)
      .reduce(function(n, k) { n.key(k); return n; }, nest())
      .entries(out.source);
    this.value = tree = hierarchy({values: root}, children);

    // collect nodes to add
    if (gen) {
      tree.each(function(node) {
        if (node.children) {
          node = ingest(node.data);
          out.add.push(node);
          out.source.push(node);
        }
      });
    }

    // build lookup table
    map = tree.lookup = {};
    tree.each(function(node) {
      if (tupleid(node.data) != null) {
        map[key(node.data)] = node;
      }
    });
  }

  out.source.root = this.value;
  return out;
};
示例#30
0
export function tickCount(scale, count) {
  var step;

  if (isObject(count)) {
    step = count.step;
    count = count.interval;
  }

  if (isString(count)) {
    count = scale.type === 'time' ? timeInterval(count)
      : scale.type === 'utc' ? utcInterval(count)
      : error('Only time and utc scales accept interval strings.');
    if (step) count = count.every(step);
  }

  return count;
}