# 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:

![](https://875484548-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgWRc88gdQeZ7mRBB46Rx%2Fuploads%2Fgit-blob-fe31462ec9fbb03a993114ba4e288a4968b791b6%2F6_demoScreenshot.png?alt=media)

## 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>
```
