# Graph

Sqliteviz allows building a graph. To build a graph, run a query to get data. 
Then open the visualisation panel by clicking ![](./img/visualisation.svg)
in any of the two side toolbars and choose a graph mode by clicking ![](./img/graph.svg).

## Requirements for result set

To build a graph, a result set must follow the following requirements:

- the first column must contain JSONs (the rest columns in the result set will be ignored)
- each JSON has a common key indicating if the record represents a node (value 0) or an edge (value 1)
- each JSON representing a node has a common key with a node id
- each JSON representing an edge has a common key with the edge source and a common key with the edge target

Each JSON can have more fields used for graph styling (read more in [Graph styling](#graph-styling)).

### Example
Let's say, you have 2 tables:

house:
| name       | points |
| ---------- | ------ |
| Gryffindor | 100    |
| Hufflepuff | 90     |
| Ravenclaw  | 95     |
| Slytherin  | 80     |

student:
| id | name           | house      |
| -- | -------------- | ---------- |
| 1  | Harry Potter   | Gryffindor |
| 2  | Ron Weasley    | Gryffindor |
| 3  | Draco Malfoy'  | Slytherin  |
| 4  | Luna Lovegood  | Ravenclaw  |
| 5  | Cedric Diggory | Hufflepuff |

Each student belongs to a certain house. 
Let's say you want to build a graph with houses and students as nodes and where each house has a link to its students.

We are going to use [json_object][1] function to form JSONs. The result set should contain both nodes and edges and we have to provide a field indicating that (0 - for nodes and 1 - for edges). Let's provide it as 'object_type':

```sql
SELECT json_object('object_type', 0)
FROM house
UNION ALL
SELECT json_object('object_type', 0)
FROM student
UNION ALL
SELECT json_object('object_type', 1)
FROM student
```
Note that we included `student` table twice. That is because the table contains not only students but also their relationship to houses. 
So the first union will be used as node records and the second one - as edges.

Then we need to provide an ID for each node. For students - `id` and for houses - `name`: 

```sql
SELECT json_object('object_type', 0, 'node_id', name)
FROM house
UNION ALL
SELECT json_object('object_type', 0, 'node_id', id)
FROM student
UNION ALL
SELECT json_object('object_type', 1)
FROM student
```

Each edge record must specify where it starts and where it ends. Let's provide it as `source` and `target`.
Provide values that are used as node IDs. In our case it's house names and student IDs:

```sql
SELECT json_object('object_type', 0, 'node_id', name)
FROM house
UNION ALL
SELECT json_object('object_type', 0, 'node_id', id)
FROM student
UNION ALL
SELECT json_object('object_type', 1, 'source', house, 'target', id)
FROM student
```
Basically, that is enough to build a graph. But it won't be meaningfull without lables.
Also, it would be nice to distinguish house nodes from student nodes e.g. by color.
Let's put additional fields - `label` and `type` that can be used in graph styling.

```sql
SELECT json_object('object_type', 0, 'node_id', name, 'label', name, 'type', 'house')
FROM house
UNION ALL
SELECT json_object('object_type', 0, 'node_id', id, 'label', name, 'type', 'student')
FROM student
UNION ALL
SELECT json_object('object_type', 1, 'source', house, 'target', id)
FROM student
```

Run the query, the result set will look like this:

| json_object('object_type', 0, 'node_id', name, 'label', name, 'type', 'house') |
| ------------------------------------------------------------------------------ |
| {"object_type":0,"node_id":"Gryffindor","label":"Gryffindor","type":"house"}   |
| {"object_type":0,"node_id":"Hufflepuff","label":"Hufflepuff","type":"house"}   |
| {"object_type":0,"node_id":"Ravenclaw","label":"Ravenclaw","type":"house"}     |
| {"object_type":0,"node_id":"Slytherin","label":"Slytherin","type":"house"}     |
| {"object_type":0,"node_id":1,"label":"Harry Potter","type":"student"}          |
| {"object_type":0,"node_id":2,"label":"Ron Weasley","type":"student"}           |
| {"object_type":0,"node_id":3,"label":"Draco Malfoy","type":"student"}          |
| {"object_type":0,"node_id":4,"label":"Luna Lovegood","type":"student"}         |
| {"object_type":0,"node_id":5,"label":"Cedric Diggory","type":"student"}        |
| {"object_type":1,"node_source":"Gryffindor","target":1}                        |
| {"object_type":1,"node_source":"Gryffindor","target":2}                        |
| {"object_type":1,"node_source":"Slytherin","target":3}                         |
| {"object_type":1,"node_source":"Ravenclaw","target":4}                         |
| {"object_type":1,"node_source":"Hufflepuff","target":5}                        |


## Graph structure

Start building a graph by setting a mapping from your records to nodes and edge properties.
Go to `Structure` > `Graph` and set the following fields:

- Object type – a field containing 0 for node records and 1 for edge records.
- Node Id – a field containing the node identifier
- Edge source - a field keeping a node identifier where the edge starts.
- Edge target - a field keeping a node identifier where the edge ends.

This is already enough to build a graph with default styling and circular layout.

![Fig. 1: Graph structure settings](./img/Screenshot_graph_structure.png)

## Graph styling

### General

Set a background color of the graph in `Style` > `General` panel.

### Nodes

There are the following settings in `Style` > `Nodes` panel:

- Label - a field containing a node label. Note that if the graph has too many nodes or the node size
  is too small, some labels can be visible only at a certain zoom level.
- Label Color - a color of node labels
- Size - set a node size. There are 3 modes of node sizing: constant, variable and calculated.

  `Constant` means that all nodes have the same size.
  
  `Variable` allows you to choose a field where the node size will be taken.
  
  `Calculated` allows to choose a method that will be used to calculate the node size.
  Currently, 3 methods are available: total node degree, degree by in-edges and degree by out-edges.

  For variable and calculated sizing it's also possible to set scale, the minimum size and the sizing mode - area or diameter.
  In the diameter mode the difference between node sizes will be more noticeable.
  
- Color - set a node color. There are 3 modes of node color: constant, variable and calculated.

  `Constant` means that all nodes have the same color.
  
  `Variable` allows you to choose a field by which the color will be determined.
  With this option you can also choose if the color value should be taken directly or mapped to a color palette.
  `Direct` mode means that in JSON representing a node, the value available by the selected field will be used as a color.
  The color value in the JSON can be set in different ways:

  **As Hex, 8-digit (RGBA) Hex**
  ```
  "#000"
  "000"
  "#369C"
  "369C"
  "#f0f0f6"
  "f0f0f6"
  "#f0f0f688"
  "f0f0f688"
  ```
  **RGB, RGBA**
  ```
  "rgb (255, 0, 0)"
  "rgb 255 0 0"
  "rgba (255, 0, 0, .5)"
  { "r": 255, "g": 0, "b": 0 }
  ```

  **HSL, HSLA**
  ```
  "hsl(0, 100%, 50%)"
  "hsla(0, 100%, 50%, .5)"
  "hsl(0, 100%, 50%)"
  "hsl 0 1.0 0.5"
  { "h": 0, "s": 1, "l": .5 }
  ```

  **HSV, HSVA**
  ```
  "hsv(0, 100%, 100%)"
  "hsva(0, 100%, 100%, .5)"
  "hsv (0 100% 100%)"
  "hsv 0 1 1"
  { "h": 0, "s": 100, "v": 100 }
  ```

  **Named colors**
  
  Case insenstive names are accepted, using the list of [colors in the CSS spec][3].
  ```
  "RED"
  "blanchedalmond"
  "darkblue"
  ```

  When `Map to` option is selected, the value by the selected field can be anything because it won't be used directly as a color.
  In this case each distinct value will be mapped to a certain color, so nodes with the same value will have the same color.
  Click on a color palette to open a palette selector.
  
  `Calculated` color mode allows to choose a method that will be used to determine a color.
  Currently, 3 methods are available: total node degree, degree by in-edges and degree by out-edges. You can also choose a color palette
  that will be used in a mapping of calculated values into an actual color.

- Color As - defines how color mapping should work - continuously or categorically.
  
    Continuous mode is more suitable when the mapped values have a meaningful order. It looks more informative with sequential palettes.
    In that case the lowest value corresponds to the first color in the palette and the highest value - to the last color.
    The color of each intermediate value reflects the position of that value in the range.

    Categorical mode just uses the next color in the palette for each new distinct value.

- Colorscale Direction - use a selected palette as is or reverse it.  

### Edges

There are the following settings in `Style` > `Edges` panel:

- Direction - show an edges with or without arrows
- Label - a field containing an edge label. Note that if the graph has too many edges,
  some labels can be visible only at a certain zoom level.
- Label Color - a color of edge labels
- Size - set an edge thickness. There are 2 modes of edge sizing: constant and variable.

  `Constant` means that all edges have the same thickness.
  
  `Variable` allows you to choose a field where the edge size will be taken.

  For variable sizing it's also possible to set scale and the minimum size.
  
- Color - set an edge color. There are 2 modes of edge color: constant and variable. They work similar to node color modes.

- Color As - defines how color mapping should work - continuously or categorically, similar to the same node color setting.

- Colorscale Direction - use a selected palette as is or reverse it.  

### Layout

#### Circular
In this layout all nodes are just placed along a circle.

#### Random
This layout places nodes randomly for each seed value. The seed value allows you to restore the random layout you liked
when you open the inquiry and run the query next time.

![Fig. 2: Random layout](./img/Screenshot_graph_random.png)

#### Circle pack
Arranges nodes as a bubble chart according to specified attributes. You can choose multiple hierarchy attributes used to group nodes.

![Fig. 3: Circle pack layout](./img/Screenshot_graph_circle_pack.png)

#### ForceAtlas2
A continuous graph layout algorithm. Read more details about the algorithm and its settings in the [article][4].
The algorithm works in iterations. When you choose ForceAtlas2 layout or run the query, it will automatically run 50 iterations of the algorithm.
You can change the amount of steps run automatically in `Initial Iterations`. 
You can also run and stop the algorithm manually by clicking `Start`/`Stop` button.

![Fig. 3: ForceAtlas2 layout](./img/Screenshot_graph_force_atlas2.png)
[How to build a pivot table in SQL(ite)][1] explores two options with static
(or beforehand-known) and dynamic columns.

[1]: https://sqlite.org/json1.html#jobj
[2]: https://github.com/bgrins/TinyColor?tab=readme-ov-file#accepted-string-input
[3]: https://www.w3.org/TR/css-color-4/#named-colors
[4]: https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0098679

