# Vega at a Glance

[Source code](#source-code) is located at the end of this topic.

This tutorial provides an overiew of Vega and a simple example to visualize tweets in the EMEA geographic region:

![](/files/wmLK5GoVzpC24LZibA8Y)

## Defining the Source Data

The Vega JSON structure maps data to geometric primitives.

A first task is to specify the data source. You can either define data statically or use a SQL query. This examples uses a SQL query to get tweet geolocation information from a tweets database:

```
SELECT goog_x as x, goog_y as y, tweets_nov_feb.rowid FROM tweets_nov_feb
```

The resulting SQL columns can be referenced in other parts of the specification to drive visualization elements. In this example, the projected columns are `goog_x` and `goog_y`, which are renamed `x` and `y`, and rowid, which is a requirement for [hit-testing](https://en.wikipedia.org/wiki/Hit-testing).

## Creating a Visualization using Vega

The Vega specification for this example includes the following top-level properties:

* `height` and `width`, which define the height and width of the visualization area.
* `data`, which defines the data source. The SQL data described above is defined here with the label `tweets` for later referencing.
* `marks`, which describes the geometric primitives used to render the visualization.
* `scales`, which are referenced by marks to map input domain values to appropriate output range values.

Here is the full Vega specification used in this example:

```
const exampleVega = {
  "width": 384,
  "height": 564,
  "data": [
    {
      "name": "tweets",
      "sql": "SELECT goog_x as x, goog_y as y, tweets_nov_feb.rowid FROM tweets_nov_feb"
    }
  ],
  "scales": [
    {
      "name": "x",
      "type": "linear",
      "domain": [
        -3650484.1235206556,
        7413325.514451755
      ],
      "range": "width"
    },
    {
      "name": "y",
      "type": "linear",
      "domain": [
        -5778161.9183506705,
        10471808.487466192
      ],
      "range": "height"
    }
  ],
  "marks": [
    {
      "type": "points",
      "from": {
        "data": "tweets"
      },
      "properties": {
        "x": {
          "scale": "x",
          "field": "x"
        },
        "y": {
          "scale": "y",
          "field": "y"
        },
        "fillColor": "blue",
        "size": {
          "value": 3
        }
      }
    }
  ]
};
```

The following sections describe the top-level Vega specification properties.

### Define the Visualization Area Dimensions

The `width` and `height` properties define a visualization area `384` pixels wide and `564` pixels high:

```
"width": 384
"height": 564
```

The `scales` position encoding properties map the `marks` into this visualization area.

### Define the Marks

The `marks` property defines visualization geometric primitives. The OmniSci Vega implementation defines the following primitive types:

* `lines` A line
* `points` A point
* `polys` A polygon
* `symbol` A geometric symbol, such as a circle or square

Each primitive type has a set of properties that describe how the primitive is positioned and styled.

This example uses points to represent the `tweets` data:

```
"marks": [
  {
    "type": "points",
    "from": {
      "data": "tweets"
    },
    "properties": {
      "x": {
        "scale": "x",
        "field": "x"
      },
      "y": {
        "scale": "y",
        "field": "y"
      },
      "fillColor": "blue",
      "size": {
        "value": 3
      }
    }
  }
]
```

Points support the following properties; not all are included in the example:

* `x` The x position of the point in pixels.
* `y` The y position of the point in pixels.
* `z` The depth coordinate of the point in pixels.
* `fillColor` The color of the point.
* `fillOpacity` The opacity of the fill, from transparent (`0`) to opaque (`1`).
* `opacity` The opacity of the point as a whole, from transparent (`0`) to opaque (`1`).
* `size` The diameter of the point in pixels.

The points in the example reference the `tweets` SQL data and use the `x` and `y` columns from the SQL to drive the position of the points. The positions are appropriately mapped to the visualization area using scales as described in [Scale Input Domain to Output Range](https://docs.omnisci.com/latest/6_VegaAtaGlance.html#scale-input-domain-to-output-range). The fill color is set to `blue` and point size is set to three pixels.

### Scale Input Domain to Output Range

The `scales` definition maps data domain values to visual range values, where the `domain` property determines the input domain for the scale. See the [d3-scale reference](https://github.com/d3/d3-scale/) for background information about how scaling works.

This example uses linear scales to map mercator-projected coordinates into pixel coordinates for rendering.

```
"scales": [
  {
    "name": "x",
    "type": "linear",
    "domain": [
      -3650484.1235206556,
      7413325.514451755
    ],
    "range": "width"
  },
  {
    "name": "y",
    "type": "linear",
    "domain": [
      -5778161.9183506705,
      10471808.487466192
    ],
    "range": "height"
  },
]
```

The `x` and `y` scales use `linear` interpolation to map point x- and y-coordinates to the `width` and `height` of the viewing area. The `width` and `height` properties are predefined keywords that equate to the range `[0, <current width>]` and `[0, <current height>]`.

After completing the Vega specification, you send the JSON structure to the backend for rendering.

## Connecting to the Server and Rendering the Visualization

The following steps summarize the rendering and visualization sequence:

1. Instantiate the `MapdCon` object for connecting to the backend.
2. Call the connect method with server information, user credentials, and data table name.
3. Provide the `renderVega()` callback function to `connect()` and include the Vega specification as a parameter.
4. Display the returned PNG image in you client browser window.

OmniSci uses [Apache Thrift](https://thrift.apache.org/) for cross-language client communication with the backend. Include the [browser-connector.js](https://github.com/omnisci/mapd-connector/tree/master/dist), connector API, which includes Thrift interface libraries and the `renderVega()` function:

```
<script src="js/browser-connector.js"></script>
```

The following example encapsulates the connect, render request, and response handling sequence:

```
var vegaOptions = {}
var connector = new MapdCon()
  .protocol("http")
  .host("my.host.com")
  .port("6273")
  .dbName("omnisci")
  .user("omnisci")
  .password("changeme")
  .connect(function(error, con) {
    con.renderVega(1, JSON.stringify(exampleVega), vegaOptions, function(error, result) {
      if (error) {
        console.log(error.message);
      }
      else {
        var blobUrl = `data:image/png;base64,${result.image}`
        var body = document.querySelector('body')
        var vegaImg = new Image()
        vegaImg.src = blobUrl
        body.append(vegaImg)
      }
    });
  });
```

## Next Steps

This example demonstrated the basic concepts for understanding and using Vega. To become comfortable with Vega, try this example using your own OmniSci instance, changing the `MapdCon()` parameters according to match your host environment and database.

As you gain experience with Vega and begin writing your own applications, see the [Reference](https://docs.omnisci.com/latest/6_vegaReference.html) for detailed information about Vega code.

## Source Code

### HTML

Vega at a Glance index.html

```
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>OmniSci</title>
    <meta charset="UTF-8">
    <style>
      .title {
        font-weight: bold;
        text-align:center;
      }
      .omnisci {
        position: relative;
        top: 2px;
      }
      .search{
        displa"y": inline-block;
        margin-top: 12px;
        margin-left: 50px;
      }
      .data-count {
        padding-right:20px;
      }
      .filter-count {
        font-weight: bold;
        color:  #45B1E8;
      }
    </style>
  </head>
  <body>

    <script src="js/browser-connector.js"></script>

    <script>

    function init() {
      const exampleVega = {
        "width": 384,
        "height": 564,
        "data": [
          {
            "name": "tweets",
            "sql": "SELECT goog_x as x, goog_y as y, tweets_data_table.rowid FROM tweets_data_table"
          }
        ],
        "scales": [
          {
            "name": "x",
            "type": "linear",
            "domain": [
              -3650484.1235206556,
              7413325.514451755
            ],
            "range": "width"
          },
          {
            "name": "y",
            "type": "linear",
            "domain": [
              -5778161.9183506705,
              10471808.487466192
            ],
            "range": "height"
          }
        ],
        "marks": [
          {
            "type": "points",
            "from": {
              "data": "tweets"
            },
            "properties": {
              "x": {
                "scale": "x",
                "field": "x"
              },
              "y": {
                "scale": "y",
                "field": "y"
              },
              "fillColor": "blue",
              "size": {
                "value": 3
              }
            }
          }
        ]
      };

       var vegaOptions = {}
       var connector = new MapdCon()
         .protocol("http")
         .host("my.host.com")
         .port("6273")
         .dbName("omnisci")
         .user("omnisci")
         .password("changeme")
         .connect(function(error, con) {
           con.renderVega(1, JSON.stringify(exampleVega), vegaOptions, function(error, result) {
             if (error) {
               console.log(error.message);
             }
             else {
               var blobUrl = `data:image/png;base64,${result.image}`
               var body = document.querySelector('body')
               var vegaImg = new Image()
               vegaImg.src = blobUrl
               body.append(vegaImg)
             }
           });
         });
    }

    document.addEventListener('DOMContentLoaded', init, false);
    </script>
  </body>
</html>
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.heavy.ai/apis-and-interfaces/vega/vega-tutorials/tutorial-vega-at-a-glance.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
