Related
I'm looking for a way to output custom legends for multi-field data. Ideally, I'd like to statically color-code all the fields I may have (in total there might be about 20), and output legends per color and arbitrary text, or at least a field name.
In the example below, I'd like a legend to show "blue stroke Series 1 red stroke Series 2".
I'd be happy to show what I have at the moment, but I have tried placing "legend" seemingly everywhere it may fit, and it doesn't do anything.
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {
"values": [
{"x": 1, "y": 10},
{"x": 2, "y": 7},
{"x2": 1, "y2": 11},
{"x2": 2, "y2": 12}
]
},
"encoding": {"x": {"type": "quantitative"},
"y": {"type": "quantitative"}},
"layer": [
{
"layer": [
{
"mark": "line",
"encoding": {
"x": {"field": "x"},
"y": {"field": "y"},
"color": {"value": "blue"}
}
},
{
"mark": "line",
"encoding": {
"x": {"field": "x2"},
"y": {"field": "y2"},
"color": {"value": "red"}
}
}
]
}
]
}
Legends in Vega-Lite are created from encodings, so if you want a legend to be shown you need to construct an appropriate encoding. For layered charts, one way to do this is using a datum encoding for each layer, and then you can construct a custom color scale mapping these encodings to the desired color. For example (open in editor):
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {
"values": [
{"x": 1, "y": 10},
{"x": 2, "y": 7},
{"x2": 1, "y2": 11},
{"x2": 2, "y2": 12}
]
},
"encoding": {
"x": {"type": "quantitative"},
"y": {"type": "quantitative"},
"color": {
"type": "nominal",
"scale": {"domain": ["Series1", "Series2"], "range": ["blue", "red"]}
}
},
"layer": [
{
"mark": "line",
"encoding": {
"x": {"field": "x"},
"y": {"field": "y"},
"color": {"datum": "Series1"}
}
},
{
"mark": "line",
"encoding": {
"x": {"field": "x2"},
"y": {"field": "y2"},
"color": {"datum": "Series2"}
}
}
]
}
Given a stacked bar plot, how can I add labels with the values of each of the bar?
Below is an example of what I'm trying to do:
You can do this by layering a bar mark and a text mark. For example (open in editor):
{
"data": {"url": "data/barley.json"},
"width": 400,
"encoding": {
"x": {
"type": "quantitative",
"aggregate": "sum",
"field": "yield",
"stack": "zero"
},
"y": {"type": "nominal", "field": "variety"}
},
"layer": [
{
"mark": "bar",
"encoding": {"color": {"type": "nominal", "field": "site"}}
},
{
"mark": {"type": "text", "color": "white", "dx": -15, "dy": 3},
"encoding": {
"detail": {"type": "nominal", "field": "site"},
"text": {
"type": "quantitative",
"aggregate": "sum",
"field": "yield",
"format": ".1f"
}
}
}
]
}
I've created a plot using Vega-Lite that allows me to use a binder to alter the parameters of a functions that I'm visualizing. It's similar to this sample code:
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"description": "Plots two functions using a generated sequence.",
"width": 300,
"height": 150,
"data": {"sequence": {"start": 0, "stop": 12.7, "step": 0.1, "as": "x"}},
"transform": [
{"calculate": "amp.sin * sin(datum.x)", "as": "sin(x)"},
{"calculate": "amp.cos * cos(datum.x)", "as": "cos(x)"},
{"fold": ["sin(x)", "cos(x)"]}
],
"mark": "line",
"encoding": {
"x": {"type": "quantitative", "field": "x"},
"y": {"field": "value", "type": "quantitative"},
"color": {"field": "key", "type": "nominal", "title": null}
},
"selection": {
"amp": {
"type": "single",
"fields": ["sin", "cos"],
"init": {"sin": 1, "cos": 1},
"bind": {
"sin": {"input": "range", "min": 0, "max": 10, "step": 0.1},
"cos": {"input": "range", "min": 0, "max": 10, "step": 0.1}
}
}
}
}
Here is the code above in the Vega editor.
Now, what I'd like to do is to create another visualization parallel to this one, but with another function, but that would also vary with the same binder.
Is this possible? Note that in my code, each plot uses a different dataset, but share the variable of the binder in common.
Yes, for example you can do this using a "concat". Here is an example based on your chart (open in editor):
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"description": "Plots two functions using a generated sequence.",
"data": {"sequence": {"start": 0, "stop": 12.7, "step": 0.1, "as": "x"}},
"concat": [
{
"width": 300,
"height": 150,
"transform": [
{"calculate": "amp.sin * sin(datum.x)", "as": "sin(x)"},
{"calculate": "amp.cos * cos(datum.x)", "as": "cos(x)"},
{"fold": ["sin(x)", "cos(x)"]}
],
"mark": "line",
"encoding": {
"x": {"type": "quantitative", "field": "x"},
"y": {"field": "value", "type": "quantitative"},
"color": {"field": "key", "type": "nominal", "title": null}
},
"selection": {
"amp": {
"type": "single",
"fields": ["sin", "cos"],
"init": {"sin": 1, "cos": 1},
"bind": {
"sin": {"input": "range", "min": 0, "max": 10, "step": 0.1},
"cos": {"input": "range", "min": 0, "max": 10, "step": 0.1}
}
}
}
},
{
"width": 300,
"height": 150,
"transform": [
{
"calculate": "amp.cos * cos(datum.x) - amp.sin * sin(datum.x)",
"as": "cos(x) - sin(x)"
}
],
"mark": "line",
"encoding": {
"x": {"type": "quantitative", "field": "x"},
"y": {"field": "cos(x) - sin(x)", "type": "quantitative"}
}
}
],
"resolve": {"scale": {"y": "shared", "color": "independent"}}
}
Vega is available as CDN script that can be included in HTML & used directly in js code.
But, how to proceed if we wish to use the same with generic web components built with polymer or StencilJS. including CDN js is not a good idea there.
Is there any way to include vega as npm module in such projects ?
have a look at this fiddle it is a native webComponent using vega:
<script src="https://cdn.jsdelivr.net/npm/vega#5"></script>
<script src="https://cdn.jsdelivr.net/npm/vega-lite#3"></script>
<script src="https://cdn.jsdelivr.net/npm/vega-embed#4"></script>
<script type="module">
const barChart = {
"$schema": "https://vega.github.io/schema/vega/v5.json",
"width": 400,
"height": 200,
"padding": 5,
"data": [
{
"name": "table",
"values": [
{"category": "A", "amount": 28},
{"category": "B", "amount": 55},
{"category": "C", "amount": 43},
{"category": "D", "amount": 91},
{"category": "E", "amount": 81},
{"category": "F", "amount": 53},
{"category": "G", "amount": 19},
{"category": "H", "amount": 87}
]
}
],
"signals": [
{
"name": "tooltip",
"value": {},
"on": [
{"events": "rect:mouseover", "update": "datum"},
{"events": "rect:mouseout", "update": "{}"}
]
}
],
"scales": [
{
"name": "xscale",
"type": "band",
"domain": {"data": "table", "field": "category"},
"range": "width",
"padding": 0.05,
"round": true
},
{
"name": "yscale",
"domain": {"data": "table", "field": "amount"},
"nice": true,
"range": "height"
}
],
"axes": [
{ "orient": "bottom", "scale": "xscale" },
{ "orient": "left", "scale": "yscale" }
],
"marks": [
{
"type": "rect",
"from": {"data":"table"},
"encode": {
"enter": {
"x": {"scale": "xscale", "field": "category"},
"width": {"scale": "xscale", "band": 1},
"y": {"scale": "yscale", "field": "amount"},
"y2": {"scale": "yscale", "value": 0}
},
"update": {
"fill": {"value": "steelblue"}
},
"hover": {
"fill": {"value": "red"}
}
}
},
{
"type": "text",
"encode": {
"enter": {
"align": {"value": "center"},
"baseline": {"value": "bottom"},
"fill": {"value": "#333"}
},
"update": {
"x": {"scale": "xscale", "signal": "tooltip.category", "band": 0.5},
"y": {"scale": "yscale", "signal": "tooltip.amount", "offset": -2},
"text": {"signal": "tooltip.amount"},
"fillOpacity": [
{"test": "datum === tooltip", "value": 0},
{"value": 1}
]
}
}
}
]
}
class VegaElement extends HTMLElement {
constructor() {
super()
this.innerHTML = "<div id='view'></div>"
}
connectedCallback() {
vegaEmbed( '#view', barChart ); }
}
customElements.define('vega-element', VegaElement);
</script>
<vega-element></vega-element>
Trying to transcript audio from Telegram voice message but I got "unable to transcode data stream audio/opus -> audio/x-float-array" error from watson's speech to text node.
I'm using Node-Red on Raspberry to simply transcript audio from Telegram voice message with node-red-contrib-telegrambot and node-red-node-watson.
With text messages, my code works as a charm.
With Voice Messages, I got "unable to transcode data stream audio/opus -> audio/x-float-array" error from watson's speech to text node.
node-red flow images I don't have enough reputation point to post images :(
JSON flow export
[
{
"id": "b4106ec1.63dd58",
"type": "tab",
"label": "Telegram",
"disabled": false,
"info": ""
},
{
"id": "d1198164.e38f68",
"type": "telegram receiver",
"z": "b4106ec1.63dd58",
"name": "FMWatsonBot",
"bot": "5f347711.7876d8",
"saveDataDir": "",
"x": 110,
"y": 100,
"wires": [
[
"f4b4ab25.5dde18",
"f5d126df.5b6928"
],
[]
]
},
{
"id": "c6ec445d.0840d8",
"type": "telegram sender",
"z": "b4106ec1.63dd58",
"name": "Send2Telegram",
"bot": "5f347711.7876d8",
"x": 780,
"y": 80,
"wires": [
[]
]
},
{
"id": "f4b4ab25.5dde18",
"type": "debug",
"z": "b4106ec1.63dd58",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"x": 290,
"y": 60,
"wires": []
},
{
"id": "f5d126df.5b6928",
"type": "function",
"z": "b4106ec1.63dd58",
"name": "Save chat context",
"func": "msg.chatId = msg.payload.chatId;\nmsg.type = msg.payload.type;\nmsg.content = msg.payload.content;\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 230,
"y": 160,
"wires": [
[
"c3d1a92d.227568"
]
]
},
{
"id": "276cfad7.cef62e",
"type": "function",
"z": "b4106ec1.63dd58",
"name": "Set Chat Context",
"func": "msg.payload = {\n chatId : msg.chatId,\n topic : msg.type,\n type : \"message\",\n content : msg.payload};\nreturn msg;\n",
"outputs": 1,
"noerr": 0,
"x": 730,
"y": 220,
"wires": [
[
"c6ec445d.0840d8"
]
]
},
{
"id": "c3d1a92d.227568",
"type": "switch",
"z": "b4106ec1.63dd58",
"name": "Check msg type",
"property": "type",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "message",
"vt": "str"
},
{
"t": "eq",
"v": "voice",
"vt": "str"
},
{
"t": "else"
}
],
"checkall": "true",
"repair": false,
"outputs": 3,
"x": 300,
"y": 240,
"wires": [
[
"e8452a44.f967c8"
],
[
"6aea6224.578d8c"
],
[]
]
},
{
"id": "e8452a44.f967c8",
"type": "function",
"z": "b4106ec1.63dd58",
"name": "Echo message",
"func": "msg.payload = {\n chatId : msg.chatId,\n topic : \"Text Echo\",\n type : msg.type,\n content : msg.content};\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 540,
"y": 80,
"wires": [
[
"c6ec445d.0840d8"
]
]
},
{
"id": "6aea6224.578d8c",
"type": "change",
"z": "b4106ec1.63dd58",
"name": "Set voice URL",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "payload.weblink",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 440,
"y": 300,
"wires": [
[
"fc7b1590.557c"
]
]
},
{
"id": "493d1bac.216d3c",
"type": "change",
"z": "b4106ec1.63dd58",
"name": "Set transcription",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "transcription",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 680,
"y": 300,
"wires": [
[
"276cfad7.cef62e"
]
]
},
{
"id": "fc7b1590.557c",
"type": "watson-speech-to-text",
"z": "b4106ec1.63dd58",
"name": "S2T",
"alternatives": 1,
"speakerlabels": false,
"smartformatting": false,
"lang": "en-GB",
"langhidden": "en-GB",
"langcustom": "NoCustomisationSetting",
"langcustomhidden": "",
"custom-weight": "0.5",
"band": "BroadbandModel",
"bandhidden": "BroadbandModel",
"keywords": "",
"keywords-threshold": "0.5",
"word-confidence": false,
"password": "",
"apikey": "#########CHANGED VALUE TO POST###########",
"payload-response": false,
"streaming-mode": false,
"streaming-mute": true,
"auto-connect": false,
"discard-listening": false,
"disable-precheck": false,
"default-endpoint": true,
"service-endpoint": "https://stream.watsonplatform.net/speech-to-text/api",
"x": 530,
"y": 360,
"wires": [
[
"493d1bac.216d3c"
]
]
},
{
"id": "5f347711.7876d8",
"type": "telegram bot",
"z": "",
"botname": "FMWatsonBot",
"usernames": "",
"chatids": "",
"baseapiurl": "",
"updatemode": "polling",
"pollinterval": "300",
"bothost": "",
"localbotport": "8443",
"publicbotport": "8443",
"privatekey": "",
"certificate": "",
"verboselogging": false
}
]
Any hint?
Thanks in advance
Ferruccio
It boils down to how you are fetching the audio from Telegram. Check the answer to this related question - https://developer.ibm.com/answers/questions/424777/help-how-do-i-use-speech-to-text-with-my-telegram/
which shows how to build the url to send through to the Speech to text node.
Update: Flow perfectly works with telegram node v4.4.0, but fails with new version 5.1.5
So, it's not a problem regarding Speech to Text node.