All Downloads are FREE. Search and download functionalities are using the official Maven repository.

smile.plot.vega.Field Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2010-2021 Haifeng Li. All rights reserved.
 *
 * Smile is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Smile is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Smile.  If not, see .
 */
package smile.plot.vega;

import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

/**
 * Encoding field definition object. An integral part of the data visualization
 * process is encoding data with visual properties of graphical marks.
 * The encoding property of a single view specification represents the
 * mapping between encoding channels (such as x, y, or color) and data
 * fields, constant visual values, or constant data values (datum).
 *
 * @author Haifeng Li
 */
public class Field {
    /** VegaLite's channel field definition object. */
    final ObjectNode spec;

    /**
     * Hides the constructor so that users cannot create the instances directly.
     */
    Field(ObjectNode spec) {
        this.spec = spec;
    }

    @Override
    public String toString() {
        return spec.toString();
    }

    /**
     * Returns the specification in pretty print.
     * @return the specification in pretty print.
     */
    public String toPrettyString() {
        return spec.toPrettyString();
    }

    /**
     * Sets the field's type of measurement.
     * @param type The encoded field's type of measurement ("quantitative",
     *             "temporal", "ordinal", or "nominal"). It can also be a
     *             "geojson" type for encoding ‘geoshape'.
     *
     *             Data type describes the semantics of the data rather than
     *             the primitive data types (number, string, etc.). The same
     *             primitive data type can have different types of
     *             measurement. For example, numeric data can represent
     *             quantitative, ordinal, or nominal data.
     *
     *             Data values for a temporal field can be either a
     *             date-time string (e.g., "2015-03-07 12:32:17",
     *             "17:01", "2015-03-16", "2015") or a timestamp
     *             number (e.g., 1552199579097).
     * @return this object.
     */
    public Field type(String type) {
        spec.put("type", type);
        return this;
    }

    /**
     * Turns on/off binning a quantitative field.
     * @param flag If true, default binning parameters will be applied.
     * @return this object.
     */
    public Field bin(boolean flag) {
        spec.put("bin", flag);
        return this;
    }

    /**
     * Indicates that the data for x or y channel are binned
     * before they are imported into Vega-Lite.
     * @param bin it should be set to "binned".
     * @return this object.
     */
    public Field bin(String bin) {
        assert bin == "binned" : "Invalid bin: " + bin;
        spec.put("bin", bin);
        return this;
    }

    /**
     * Sets custom binning parameters.
     * @param params the binning parameters.
     * @return this object.
     */
    public Field bin(BinParams params) {
        spec.set("bin", params.spec);
        return this;
    }

    /**
     * Sets the time unit for a temporal field. Vega-Lite supports the following time units:
     *
     * "year" - Gregorian calendar years.
     * "quarter" - Three-month intervals, starting in one of January, April, July, and October.
     * "month" - Calendar months (January, February, etc.).
     * "date" - Calendar day of the month (January 1, January 2, etc.).
     * "week" - Sunday-based weeks. Days before the first Sunday of the year are considered to be
     *          in week 0, the first Sunday of the year is the start of week 1, the second Sunday
     *          week 2, etc.
     * "day" - Day of the week (Sunday, Monday, etc.).
     * "dayofyear" - Day of the year (1, 2, …, 365, etc.).
     * "hours" - Hours of the day (12:00am, 1:00am, etc.).
     * "minutes" - Minutes in an hour (12:00, 12:01, etc.).
     * "seconds" - Seconds in a minute (12:00:00, 12:00:01, etc.).
     * "milliseconds" - Milliseconds in a second.
     *
     * @param timeUnit  Time unit.
     * @return this object.
     */
    public Field timeUnit(String timeUnit) {
        spec.put("timeUnit", timeUnit);
        return this;
    }

    /**
     * Sets the aggregation function for the field
     * (e.g., "mean", "sum", "median", "min", "max", "count").
     * @param aggregate Aggregation function for the field.
     * @return this object.
     */
    public Field aggregate(String aggregate) {
        spec.put("aggregate", aggregate);
        return this;
    }

    /**
     * Sets the title for the field. If null, the title will be removed.
     * @param title the title text.
     * @return this object.
     */
    public Field title(String title) {
        spec.put("title", title);
        return this;
    }

    /**
     * Sets the function that transforms values in the data domain (numbers,
     * dates, strings, etc.) to visual values (pixels, colors, sizes) for
     * position and mark property channels.
     *
     * Vega-Lite supports the following categories of scale types:
     *
     * 1) Continuous Scales - mapping continuous domains to continuous output
     * ranges ("linear", "pow", "sqrt", "symlog", "log", "time", "utc".
     *
     * 2) Discrete Scales - mapping discrete domains to discrete ("ordinal")
     * or continuous ("band" and "point") output ranges.
     *
     * 3) Discretizing Scales - mapping continuous domains to discrete output
     * ranges "bin-ordinal", "quantile", "quantize" and "threshold".
     *
     * @param type the function name. If null, the scale will be disabled
     *             and the data value will be directly encoded.
     * @return this object.
     */
    public Field scale(String type) {
        ObjectNode node = spec.has("scale") ? (ObjectNode) spec.get("scale") : spec.putObject("scale");
        node.put("type", type);
        return this;
    }

    /**
     * If true, ensures that a zero baseline value is included in the scale domain.
     * @param flag If true, ensures that a zero baseline value is included in the scale domain.
     * @return this object.
     */
    public Field zero(boolean flag) {
        ObjectNode node = spec.has("scale") ? (ObjectNode) spec.get("scale") : spec.putObject("scale");
        node.put("zero", flag);
        return this;
    }

    /**
     * Sets the customize domain values.
     * @param values the domain values.
     * @return this object.
     */
    public Field domain(double... values) {
        ObjectNode node = spec.has("scale") ? (ObjectNode) spec.get("scale") : spec.putObject("scale");
        ArrayNode domain = node.putArray("domain");
        for (double value : values) {
            domain.add(value);
        }
        return this;
    }

    /**
     * Sets the customize domain values.
     * @param values the domain values.
     * @return this object.
     */
    public Field domain(String... values) {
        ObjectNode node = spec.has("scale") ? (ObjectNode) spec.get("scale") : spec.putObject("scale");
        ArrayNode domain = node.putArray("domain");
        for (String value : values) {
            domain.add(value);
        }
        return this;
    }

    /**
     * Sets the minimum value in the scale domain, overriding the domain property
     * or the default domain. This property is only intended for use with scales
     * having continuous domains.
     * @param min the minimum value in the scale domain.
     * @return this object.
     */
    public Field domainMin(double min) {
        ObjectNode node = spec.has("scale") ? (ObjectNode) spec.get("scale") : spec.putObject("scale");
        node.put("domainMin", min);
        return this;
    }

    /**
     * Sets the minimum value in the scale domain, overriding the domain property
     * or the default domain. This property is only intended for use with scales
     * having continuous domains.
     * @param min the minimum value in the scale domain.
     * @return this object.
     */
    public Field domainMin(String min) {
        ObjectNode node = spec.has("scale") ? (ObjectNode) spec.get("scale") : spec.putObject("scale");
        node.put("domainMin", min);
        return this;
    }

    /**
     * Sets the maximum value in the scale domain, overriding the domain property
     * or the default domain. This property is only intended for use with scales
     * having continuous domains.
     * @param max the maximum value in the scale domain.
     * @return this object.
     */
    public Field domainMax(double max) {
        ObjectNode node = spec.has("scale") ? (ObjectNode) spec.get("scale") : spec.putObject("scale");
        node.put("domainMax", max);
        return this;
    }

    /**
     * Sets the maximum value in the scale domain, overriding the domain property
     * or the default domain. This property is only intended for use with scales
     * having continuous domains.
     * @param max the maximum value in the scale domain.
     * @return this object.
     */
    public Field domainMax(String max) {
        ObjectNode node = spec.has("scale") ? (ObjectNode) spec.get("scale") : spec.putObject("scale");
        node.put("domainMax", max);
        return this;
    }

    /**
     * Sets the customize range values.
     * @param values the range values.
     * @return this object.
     */
    public Field range(double... values) {
        ObjectNode node = spec.has("scale") ? (ObjectNode) spec.get("scale") : spec.putObject("scale");
        ArrayNode range = node.putArray("range");
        for (double value : values) {
            range.add(value);
        }
        return this;
    }

    /**
     * Sets the customize range values.
     * @param values the range values.
     * @return this object.
     */
    public Field range(String... values) {
        ObjectNode node = spec.has("scale") ? (ObjectNode) spec.get("scale") : spec.putObject("scale");
        ArrayNode range = node.putArray("range");
        for (String value : values) {
            range.add(value);
        }
        return this;
    }

    /**
     * Sets the minimum value in the scale range, overriding the range property
     * or the default range. This property is only intended for use with scales
     * having continuous ranges.
     * @param min the minimum value in the scale range.
     * @return this object.
     */
    public Field rangeMin(double min) {
        ObjectNode node = spec.has("scale") ? (ObjectNode) spec.get("scale") : spec.putObject("scale");
        node.put("rangeMin", min);
        return this;
    }

    /**
     * Sets the minimum value in the scale range, overriding the range property
     * or the default range. This property is only intended for use with scales
     * having continuous ranges.
     * @param min the minimum value in the scale range.
     * @return this object.
     */
    public Field rangeMin(String min) {
        ObjectNode node = spec.has("scale") ? (ObjectNode) spec.get("scale") : spec.putObject("scale");
        node.put("rangeMin", min);
        return this;
    }

    /**
     * Sets the maximum value in the scale range, overriding the range property
     * or the default range. This property is only intended for use with scales
     * having continuous ranges.
     * @param max the maximum value in the scale range.
     * @return this object.
     */
    public Field rangeMax(double max) {
        ObjectNode node = spec.has("scale") ? (ObjectNode) spec.get("scale") : spec.putObject("scale");
        node.put("rangeMax", max);
        return this;
    }

    /**
     * Sets the maximum value in the scale range, overriding the range property
     * or the default range. This property is only intended for use with scales
     * having continuous ranges.
     * @param max the maximum value in the scale range.
     * @return this object.
     */
    public Field rangeMax(String max) {
        ObjectNode node = spec.has("scale") ? (ObjectNode) spec.get("scale") : spec.putObject("scale");
        node.put("rangeMax", max);
        return this;
    }

    /**
     * Sets the sorting property.
     *
     * @param value "ascending", "descending", or an encoding channel name to
     *             sort by (e.g., "-x" to sort by x-field, descending).
     * @return this object.
     */
    public Field sort(String value) {
        spec.put("sort", value);
        return this;
    }

    /**
     * Sets the type of stacking offset if the field should be stacked.
     * stack is only applicable for x, y, theta, and radius channels with
     * continuous domains. For example, stack of y can be used to customize
     * stacking for a vertical bar chart.
     *
     * Stack can be one of the following values:
     *
     * "zero" - stacking with baseline offset at zero value of the scale
     * (for creating typical stacked bar and area chart).
     *
     * "normalize" - stacking with normalized domain (for creating normalized
     * stacked bar and area charts and pie charts with percentage tooltip).
     *
     * "center" - stacking with center baseline (for streamgraph).
     *
     * null - No-stacking. This will produce layered bar and area chart.
     *
     * @param type "zero", "normalize", "center", or null.
     */
    public Field stack(String type) {
        spec.put("stack", type);
        return this;
    }

    /**
     * For facet, row and column channels, sets the spacing in pixels between
     * facet's sub-views.
     * @param spacing the spacing in pixels between facet's sub-views.
     * @return this object.
     */
    public Field spacing(double spacing) {
        spec.put("spacing", spacing);
        return this;
    }

    /**
     * Returns the axis definition object.
     * @return the axis definition object.
     */
    public Axis axis() {
        ObjectNode node = spec.has("axis") ? (ObjectNode) spec.get("axis") : spec.putObject("axis");
        return new Axis(node);
    }

    /**
     * Returns the legend definition object.
     * @return the legend definition object.
     */
    public Legend legend() {
        ObjectNode node = spec.has("legend") ? (ObjectNode) spec.get("legend") : spec.putObject("legend");
        return new Legend(node);
    }

    /** Removes the legend for the encoding channel will be removed. */
    public Field removeLegend() {
        spec.putNull("legend");
        return this;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy