Rendering mpld3 JSON chart in React - matplotlib

Good day.
I just recently came across mpld3 and I am trying to see if it will be the solution to my issue.
I want to create Matplotlib charts in Python, save them as JSON objects to a database, and then render them in my React webpage.
So far I have created a plot in Python, using Matplotlib and converted it to a JSON object in a dictionary:
fig = plt.gcf()
mpld3.display(fig)
fig_to_dict = mpld3.fig_to_dict(fig)
Now I can save the dictionary to a file.
My question is: Can I then render this JSON chart in my React project? And if so, how do I do that?
Another thing is - I cannot use D3 in the front-end, I need to do all my "chart making" in the back-end.
Thank you for any and all assistance!

This is not a perfect answer, but I seemed to be solving a similar problem and I appear to have got it working so am sharing my code as is. Hopefully it will prove useful to someone.
This is my react component ('matPlotLibFig.js') that renders a simple figure
import React from 'react'
import mpld3_load_lib from "./mpld3_load_lib";
import mpld3 from 'mpld3'
import _json from "./plot_b.json"
const MatPlotLibFig = () => {
const fig_name = "fig_el427345810798888193429725"
return <div>
<script>
mpld3_load_lib("https://d3js.org/d3.v5.js", function () {
mpld3_load_lib("https://mpld3.github.io/js/mpld3.v0.5.8.js", function () {
mpld3.remove_figure(fig_name)
mpld3.draw_figure(fig_name, _json);
})
});
</script>
<div id={fig_name}></div>
</div>
}
export default MatPlotLibFig
plot_b.json:
{
"width": 640.0,
"height": 480.0,
"axes": [
{
"bbox": [0.125, 0.11, 0.775, 0.77],
"xlim": [-0.5, 10],
"ylim": [0, 10],
"xdomain": [-0.2, 10],
"ydomain": [0.0, 10],
"xscale": "linear",
"yscale": "linear",
"axes": [
{
"position": "bottom",
"nticks": 11,
"tickvalues": null,
"tickformat_formatter": "",
"tickformat": null,
"scale": "linear",
"fontsize": 10.0,
"grid": {
"gridOn": false
},
"visible": true
},
{
"position": "left",
"nticks": 11,
"tickvalues": null,
"tickformat_formatter": "",
"tickformat": null,
"scale": "linear",
"fontsize": 10.0,
"grid": {
"gridOn": false
},
"visible": true
}
],
"axesbg": "#FFFFFF",
"axesbgalpha": null,
"zoomable": true,
"id": "el91906139874005984112",
"lines": [
{
"data": "data01",
"xindex": 0,
"yindex": 1,
"coordinates": "data",
"id": "el91906139873968544448",
"color": "#000000",
"linewidth": 1.5,
"dasharray": "none",
"alpha": 1,
"zorder": 2,
"drawstyle": "default"
}
],
"paths": [],
"markers": [
{
"data": "data01",
"xindex": 0,
"yindex": 1,
"coordinates": "data",
"id": "el91906139873968544448pts",
"facecolor": "#000000",
"edgecolor": "#FFFFFF",
"edgewidth": 5,
"alpha": 1,
"zorder": 2,
"markerpath": [
[
[
-10.0,
10.0
],
[
10.0,
10.0
],
[
10.0,
-10.0
],
[
-10.0,
-10.0
]
],
[
"M",
"L",
"L",
"L",
"Z"
]
]
}
],
"texts": [],
"collections": [],
"images": [],
"sharex": [],
"sharey": []
}
],
"data": {
"data01": [
[
0.0,
6.0
],
[
1.0,
2.0
],
[
2.0,
8.0
],
[
3.0,
3.0
],
[
4.0,
0.0
],
[
5.0,
7.0
]
]
},
"id": "el91906139874196422128",
"plugins": [
{
"type": "reset"
},
{
"type": "zoom",
"button": true,
"enabled": false
},
{
"type": "boxzoom",
"button": true,
"enabled": false
}
]
}
mpld3_load_lib.js:
const mpld3_load_lib = (url, callback) => {
var s = document.createElement('script');
s.src = url;
s.async = true;
s.onreadystatechange = s.onload = callback;
s.onerror = function () { console.warn("failed to load library " + url); };
document.getElementsByTagName("head")[0].appendChild(s);
}
export default mpld3_load_lib
Which renders a dynamic plot that looks like

Related

Azure DevOps API release definition error

I am creating azure-devops release pipeline with API, but getting error. I have validated the json as well and is correct from https://jsonlint.com/ Any help would be really appreciated
I have followed this issue as well and retention policy is correctly passed
Azure DevOps API release definition
error: "message": "VS402982: A retention policy is not set for the stage ‘Test-New-2’. Retention policies at the release pipeline level are deprecated. Use a retention policy at the stage level
POST https://vsrm.dev.azure.com/{{organization}}/{{project}}/_apis/release/definitions?api-version=6.0
json body:
"retentionPolicy": {
"daysToKeep": 30,
"releasesToKeep": 3,
"retainBuild": true
},
Yes, it should be the syntax issue, to create a release definition, you could refer to this sample.
Reruest URL:
POST https://vsrm.dev.azure.com/{organization}/{project}/_apis/release/definitions?api-version=6.0
Request Body:
{
"source": "undefined",
"revision": 1,
"description": null,
"createdBy": null,
"createdOn": "0001-01-01T00:00:00",
"modifiedBy": null,
"modifiedOn": "0001-01-01T00:00:00",
"isDeleted": false,
"variables": {},
"variableGroups": [],
"environments": [
{
"id": 0,
"name": "PROD",
"variables": {},
"variableGroups": [],
"preDeployApprovals": {
"approvals": [
{
"rank": 1,
"isAutomated": false,
"isNotificationOn": false,
"approver": {
"displayName": null,
"id": "aeb95c63-4fac-4948-84ce-711b0a9dda97"
},
"id": 0
}
]
},
"postDeployApprovals": {
"approvals": [
{
"rank": 1,
"isAutomated": true,
"isNotificationOn": false,
"id": 0
}
]
},
"deployPhases": [
{
"deploymentInput": {
"parallelExecution": {
"parallelExecutionType": "none"
},
"skipArtifactsDownload": false,
"artifactsDownloadInput": {},
"queueId": 15,
"demands": [],
"enableAccessToken": false,
"timeoutInMinutes": 0,
"jobCancelTimeoutInMinutes": 1,
"condition": "succeeded()",
"overrideInputs": {}
},
"rank": 1,
"phaseType": "agentBasedDeployment",
"name": "Run on agent",
"workflowTasks": []
}
],
"environmentOptions": {
"emailNotificationType": "OnlyOnFailure",
"emailRecipients": "release.environment.owner;release.creator",
"skipArtifactsDownload": false,
"timeoutInMinutes": 0,
"enableAccessToken": false,
"publishDeploymentStatus": false,
"badgeEnabled": false,
"autoLinkWorkItems": false,
"pullRequestDeploymentEnabled": false
},
"demands": [],
"conditions": [],
"executionPolicy": {
"concurrencyCount": 0,
"queueDepthCount": 0
},
"schedules": [],
"retentionPolicy": {
"daysToKeep": 30,
"releasesToKeep": 3,
"retainBuild": true
},
"properties": {},
"preDeploymentGates": {
"id": 0,
"gatesOptions": null,
"gates": []
},
"postDeploymentGates": {
"id": 0,
"gatesOptions": null,
"gates": []
},
"environmentTriggers": []
}
],
"artifacts": [],
"triggers": [],
"releaseNameFormat": null,
"tags": [],
"properties": {},
"id": 0,
"name": "Fabrikam-web",
"projectReference": null,
"_links": {}
}
I test it on my side, it works for me.

How to add a tooltip to a d3.js path?

I am building a floormap from geojson data using d3.js topo and d3.js path. For clarification, I am also using vue.js. I want to add a tooltip when the user hovers over a room (aka the d3.js path). First I added just a console log to when the user hovers over a path but that did not work. I noticed that every time I load the app it does a console log but not when a user clicks / hovers over the d3.js path. I heard someone say that I would have to create an invisible circle or rectangle which would have the tooltip property bind to it but I don't think that route would work once the floor maps get complex. I dont care about adding any actual data to the tooltip right now but later I would want to. Can someone point me in the right direction, please? Thank you.
const data = {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
0, 0
],
[
0, 11.4
],
[
7, 11.4
],
[
7, 0
],
[
0, 0
]
]
]
}
},
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
7, 0
],
[
7, 11.4
],
[
12, 11.4
],
[
12, 0
],
[
7, 0
]
]
]
}
},
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
12, 0
],
[
12, 11.4
],
[
19, 11.4
],
[
19, 0
],
[
12, 0
]
]
]
}
}
]
};
var svg = d3.select("svg")
var width = +svg.attr("width")
var height = +svg.attr("height")
svg.attr("transform", "translate(" + width / 2 + ",0)")
var projection = d3.geoIdentity().fitSize([width, height], data)
var path = d3.geoPath(projection)
svg.selectAll("path")
.data(data.features)
.enter()
.append("path")
.attr("d", path)
.attr("fill", "grey")
.attr("fill-opacity", .2)
.attr("stroke", "black")
.attr("stroke-width", 1.5)
.on("mouseover", console.log("hello"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="400" height="200"></svg>
There are several ways to do this. The simplest - but most limited - one is to create a <title> element in each path. It will show on hover, as it's browser native.
const data = {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": { "name": "Kitchen" },
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
0, 0
],
[
0, 11.4
],
[
7, 11.4
],
[
7, 0
],
[
0, 0
]
]
]
}
},
{
"type": "Feature",
"properties": { "name": "Living room" },
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
7, 0
],
[
7, 11.4
],
[
12, 11.4
],
[
12, 0
],
[
7, 0
]
]
]
}
},
{
"type": "Feature",
"properties": { "name": "Toilet" },
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
12, 0
],
[
12, 11.4
],
[
19, 11.4
],
[
19, 0
],
[
12, 0
]
]
]
}
}
]
};
var svg = d3.select("svg")
var width = +svg.attr("width")
var height = +svg.attr("height")
svg.attr("transform", "translate(" + width / 2 + ",0)")
var projection = d3.geoIdentity().fitSize([width, height], data)
var path = d3.geoPath(projection)
svg.selectAll("path")
.data(data.features)
.enter()
.append("path")
.attr("d", path)
.attr("fill", "grey")
.attr("fill-opacity", .2)
.attr("stroke", "black")
.attr("stroke-width", 1.5)
.append("title")
// Do this to maintain access to the features you drew
.datum(function(d) { return d; })
.text(function(d) {
return d.properties.name;
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="400" height="200"></svg>
More complicated ones can use an absolutely positioned div, for example:
const data = {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {
"name": "Kitchen"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
0, 0
],
[
0, 11.4
],
[
7, 11.4
],
[
7, 0
],
[
0, 0
]
]
]
}
},
{
"type": "Feature",
"properties": {
"name": "Living room"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
7, 0
],
[
7, 11.4
],
[
12, 11.4
],
[
12, 0
],
[
7, 0
]
]
]
}
},
{
"type": "Feature",
"properties": {
"name": "Toilet"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
12, 0
],
[
12, 11.4
],
[
19, 11.4
],
[
19, 0
],
[
12, 0
]
]
]
}
}
]
};
var svg = d3.select("svg")
var width = +svg.attr("width")
var height = +svg.attr("height")
var tooltip = d3.select("#tooltip")
svg.attr("transform", "translate(" + width / 2 + ",0)")
var projection = d3.geoIdentity().fitSize([width, height], data)
var path = d3.geoPath(projection)
svg.selectAll("path")
.data(data.features)
.enter()
.append("path")
.attr("d", path)
.attr("fill", "grey")
.attr("fill-opacity", .2)
.attr("stroke", "black")
.attr("stroke-width", 1.5)
.on("mousemove", function(d) {
// +3 as some offset to make sure spawning the tooltip doesn't
// accidentally also cause unhover and thus removing itself
tooltip
.html(d.properties.name)
.style("display", "block")
.style("left", d3.event.x + 3 + 'px')
.style("top", d3.event.y + 3 + 'px');
})
.on("mouseleave", function() {
tooltip
.style("display", null)
.style("left", null)
.style("top", null);
});
#tooltip {
position: absolute;
top: 0;
left: 0;
display: none;
border: solid 1px red;
padding: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="400" height="200"></svg>
<div id="tooltip"></div>

How can I extend the x-axis on a Highcharts graph?

I have a Highcharts bar graph. Each point has a group of results, however the first and last element are being cropped. How can I extend the x-axis so every bar is shown?
In the image below each group has the same results so you can see the N and P are dropped from the first group and S and Mg from the last grouping.
The data is coming from a database, so i don't know how many groups there will be, or what range (so simply adding a day to each end is not sufficient, the overlap could be larger or smaller)
const conf = {
chart: {
type: "column",
animation: false,
marginRight: 10,
dateFormat: "dd/mm/YYYY"
},
title: {
text: "Spread Events"
},
xAxis: {
type: "datetime",
tickPixelInterval: 50
},
yAxis: {
title: {
text: "Spread"
},
plotLines: [
{
value: 0,
width: 1,
color: "#808080"
}
]
},
legend: {
enabled: true
},
exporting: {
enabled: false
},
plotOptions: {
column: {
pointPadding: 0.2,
borderWidth: 0
}
},
series: this.state.graphData
};
and this is the graphData from the example
[
{
"name": "N",
"data": [[1559669642443, 300], [1559343600000, 300], [1559257200000, 300]]
},
{
"name": "P",
"data": [[1559669642443, 160], [1559343600000, 160], [1559257200000, 160]]
},
{
"name": "K",
"data": [[1559669642443, 470], [1559343600000, 470], [1559257200000, 470]]
},
{
"name": "S",
"data": [[1559669642443, 120], [1559343600000, 120], [1559257200000, 120]]
},
{
"name": "Mg",
"data": [[1559669642443, 90], [1559343600000, 90], [1559257200000, 90]]
}
]
You have Highcharts error #15 in a console, which means that your data is not sorted. Highcharts requires sorted data in ascending X order:
series: [{
...,
data: [
[1559257200000, 300],
[1559343600000, 300],
[1559669642443, 300]
]
}, ...
]
Live demo: http://jsfiddle.net/BlackLabel/y2rzd65m/

Highcharts-vue: Stacked Columns with Drilldown

I'm trying to replicate this chart http://jsfiddle.net/edzk8Loe/ using vue js.
To be honest, I'm learning vuejs and so I'm trying to replicate already ready projects to get confident quickly.
The issue I'm facing at the moment I guess is a logic one. The functions have to create new series as drilldown when click on a column, seams not triggered at all. I'm not getting any error in the console and I'm
Not having yet a totally clear idea about the structure, I think I'm messing up the code. Hereunder you'll find the code I'm using in VUE.
<template>
<div class="chartElem">
<div class="row">
<highcharts class="chart" :constructor-type="'chart'" :options="chartOptions"></highcharts>
</div>
</div>
</template>
<script>
import HighchartsVue from "highcharts-vue";
import Highcharts from "highcharts";
import dataModule from "highcharts/modules/data";
import drilldown from "highcharts/modules/drilldown";
drilldown( Highcharts );
dataModule( Highcharts );
let drilldownChart, drilldownEvent, drilldownLevel = 0;
const chartOptions = {
chart: {
"type": "column",
},
credits: {
"enabled": false
},
plotOptions: {
column: {
stacking: "normal",
events: {
click: function ( event ) {
return false;
}
}
},
"series": {
"borderWidth": 0,
"dataLabels": {
"enabled": true,
"style": {
"textShadow": false,
"fontSize": "10px"
}
}
}
},
"legend": {
"enabled": false,
},
"yAxis": {
"stackLabels": {
"enabled": false,
"style": {
"fontWeight": "bold",
"color": "gray"
}
}
},
"title": {
"text": "Stacked Column Drilldown Chart",
"fontWeight": "bold"
},
"xAxis": {
"title": {},
"type": "category"
},
"yAxis": [ {
"title": {
"text": "Number of Students"
},
"min": 0,
"allowDecimals": false
} ],
"series": [ {
"name": "Outstanding",
"color": "rgb(102, 168, 255)",
"data": [ {
"name": "English",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "105"
}, {
"name": "Social Science",
"y": 1,
"parentCategoryHierarchyId": "0",
"graphParentId": "119",
"drilldown": true
}, {
"name": "Science",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "126"
}, {
"name": "Maths",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "139"
}, {
"name": "Hindi",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "146"
} ]
}, {
type: 'column',
"name": "Very Good",
"color": "rgb(128, 183, 255)",
"data": [ {
"name": "English",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "105"
}, {
"name": "Social Science",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "119",
"drilldown": true
}, {
"name": "Science",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "126"
}, {
"name": "Maths",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "139"
}, {
"name": "Hindi",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "146"
} ]
}, {
type: 'column',
"name": "Satisfactory",
"color": "rgb(179, 212, 255)",
"data": [ {
"name": "English",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "105"
}, {
"name": "Social Science",
"y": 1,
"parentCategoryHierarchyId": "0",
"graphParentId": "119",
"drilldown": true
}, {
"name": "Science",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "126"
}, {
"name": "Maths",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "139"
}, {
"name": "Hindi",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "146"
} ]
}, {
type: 'column',
"name": "Needs Improvement",
"color": "rgb(204, 226, 255)",
"data": [ {
"name": "English",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "105"
}, {
"name": "Social Science",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "119",
"drilldown": true
}, {
"name": "Science",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "126"
}, {
"name": "Maths",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "139"
}, {
"name": "Hindi",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "146"
} ]
}, {
type: 'column',
"name": "Not Performing",
"color": "rgb(230, 242, 255)",
"data": [ {
"name": "English",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "105"
}, {
"name": "Social Science",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "119",
"drilldown": true
}, {
"name": "Science",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "126"
}, {
"name": "Maths",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "139"
}, {
"name": "Hindi",
"y": 0,
"parentCategoryHierarchyId": "0",
"graphParentId": "146"
} ]
} ]
};
export default {
data: () => ( {
chartOptions,
drilldownChart,
drilldownEvent,
drilldownLevel
} ),
methods: {},
computed:{
drilldown: function ( e ) {
if ( !e.seriesOptions ) {
updateGraph( true, this, e );
}
},
drillup: function ( e ) {
if ( !e.seriesOptions.flag ) {
drilldownLevel = e.seriesOptions._levelNumber;
updateGraph( false );
}
}
},
mounted() {
function updateGraph( isDrilldown, chart, e ) {
if ( isDrilldown ) {
drilldownLevel++;
drilldownChart = chart;
drilldownEvent = e;
if ( drilldownLevel === 1 ) {
var drilldowns = {
'Social Science': {
name: 'Outstanding',
color: 'rgb(102, 168, 255)',
data: [ {
name: 'Geography',
y: 7,
drilldown: true
}, {
name: 'History',
y: 4
}, {
name: 'Civics',
y: 9
} ]
}
},
drilldowns2 = {
'Social Science': {
name: 'Very Good',
color: 'rgb(128, 183, 255)',
data: [ {
name: 'Geography',
y: 4,
drilldown: true
}, {
name: 'History',
y: 8
}, {
name: 'Civics',
y: 2
} ],
},
},
drilldowns3 = {
'Social Science': {
name: 'Satisfactory',
color: 'rgb(179, 212, 255)',
data: [ {
name: 'Geography',
y: 4,
drilldown: true
}, {
name: 'History',
y: 7
}, {
name: 'Civics',
y: 1
} ],
}
},
drilldowns4 = {
'Social Science': {
name: 'Needs Improvement',
color: 'rgb(204, 226, 255)',
data: [ {
name: 'Geography',
y: 2,
drilldown: true
}, {
name: 'History',
y: 7
}, {
name: 'Civics',
y: 2
} ]
}
},
drilldowns5 = {
'Social Science': {
name: 'Not Performing',
color: 'rgb(230, 242, 255)',
data: [ {
name: 'Geography',
y: 6,
drilldown: true
}, {
name: 'History',
y: 3
}, {
name: 'Civics',
y: 0
} ],
}
},
series = drilldowns[ e.point.name ],
series2 = drilldowns2[ e.point.name ],
series3 = drilldowns3[ e.point.name ],
series4 = drilldowns4[ e.point.name ],
series5 = drilldowns5[ e.point.name ];
chart.addSingleSeriesAsDrilldown( e.point, series );
chart.addSingleSeriesAsDrilldown( e.point, series2 );
chart.addSingleSeriesAsDrilldown( e.point, series3 );
chart.addSingleSeriesAsDrilldown( e.point, series4 );
chart.addSingleSeriesAsDrilldown( e.point, series5 );
chart.applyDrilldown();
} else if ( drilldownLevel === 2 ) {
var drilldown1 = {
"Geography": {
"name": "Yes",
stacking: 'percent',
color: 'red',
"data": [ {
"name": "Q1",
"y": 1
}, {
"name": "Q2",
"y": 2
}, {
"name": "Q3",
"y": 3
}, {
"name": "Q4",
"y": 4
} ]
}
};
var drilldown2 = {
"Geography": {
"name": "No",
stacking: 'percent',
color: 'green',
"data": [ {
"name": "Q1",
"y": 1
}, {
"name": "Q2",
"y": 2
}, {
"name": "Q3",
"y": 3
}, {
"name": "Q4",
"y": 4
} ]
}
};
var drilldown3 = {
"exampleDrilldown": {
type: 'line',
"name": "Example",
color: 'black',
"data": [ {
"name": "Q1",
"y": 10
}, {
"name": "Q2",
"y": 20
}, {
"name": "Q3",
"y": 30
}, {
"name": "Q4",
"y": 40
} ]
}
}
chart.addSingleSeriesAsDrilldown( e.point, drilldown1[ e.point.name ] );
chart.addSingleSeriesAsDrilldown( e.point, drilldown2[ e.point.name ] );
chart.addSingleSeriesAsDrilldown( e.point, drilldown3[ 'exampleDrilldown' ] );
console.log( e );
chart.applyDrilldown();
}
}
}
}
}
</script>
I'm not looking for someone is doing the task instead of me, I won't learn anything. Ideas and tips are super welcomed.
Cheers
You've made several simple mistakes in your code.
1) Add updateGraph function to chart methods - that way you can invoke this method in drilldown callback
2) Save chart component reference in the chart object to be able to use updateGraph method from drilldown callback function. You can make it using mounted() hook:
mounted() {
this.$children[0].chart.vueRef = this;
}
3) Data should be a function that returns an object with properties:
data() {
return {
chartOptions,
drilldownChart,
drilldownEvent,
drilldownLevel
}
}
4) Add drilldown and drillup callbacks to chart.events object. There you can invoke updateGraph method from the chart component reference saved in mounted hook:
chart: {
"type": "column",
events: {
drilldown: function(e) {
if (!e.seriesOptions) {
this.vueRef.updateGraph(true, this, e);
}
},
drillup: function(e) {
if (!e.seriesOptions.flag) {
this.vueRef.drilldownLevel = e.seriesOptions._levelNumber;
this.vueRef.updateGraph(false);
}
}
}
}
Demo:
https://codesandbox.io/s/2w513lwpw0

Yosys interpret and and not gate as nand for visualization

I was trying to use yosys purely for visualization in combination with https://github.com/nturley/netlistsvg. A tool which takes a yosys generated json file and creates an SVG out of it. If I have the verilog code:
module test(a,b,c);
input wire a,b;
output wire c;
assign c = ~(a & b);
endmodule
I want to generate an SVG file that has a NAND gate. I use the following Yosys commands:
read_verilog test.v
write_json output.json
Yosys interprests the assign statement as an AND gate and a NOT gate and outputs the following json:
{
"creator": "Yosys 0.7 (git sha1 61f6811, gcc 6.2.0-11ubuntu1 -O2 -fdebug-prefix-map=/build/yosys-OIL3SR/yosys-0.7=. -fstack-protector-strong -fPIC -Os)",
"modules": {
"test": {
"attributes": {
"src": "test.v:1"
},
"ports": {
"a": {
"direction": "input",
"bits": [ 2 ]
},
"b": {
"direction": "input",
"bits": [ 3 ]
},
"c": {
"direction": "output",
"bits": [ 4 ]
}
},
"cells": {
"$not$test.v:4$2": {
"hide_name": 1,
"type": "$not",
"parameters": {
"Y_WIDTH": 1,
"A_WIDTH": 1,
"A_SIGNED": 0
},
"attributes": {
"src": "test.v:4"
},
"port_directions": {
"Y": "output",
"A": "input"
},
"connections": {
"Y": [ 4 ],
"A": [ 5 ]
}
},
"$and$test.v:4$1": {
"hide_name": 1,
"type": "$and",
"parameters": {
"Y_WIDTH": 1,
"B_WIDTH": 1,
"A_WIDTH": 1,
"B_SIGNED": 0,
"A_SIGNED": 0
},
"attributes": {
"src": "test.v:4"
},
"port_directions": {
"Y": "output",
"B": "input",
"A": "input"
},
"connections": {
"Y": [ 5 ],
"B": [ 3 ],
"A": [ 2 ]
}
}
},
"netnames": {
"$not$test.v:4$2_Y": {
"hide_name": 1,
"bits": [ 4 ],
"attributes": {
"src": "test.v:4"
}
},
"$and$test.v:4$1_Y": {
"hide_name": 1,
"bits": [ 5 ],
"attributes": {
"src": "test.v:4"
}
},
"c": {
"hide_name": 0,
"bits": [ 4 ],
"attributes": {
"src": "test.v:3"
}
},
"b": {
"hide_name": 0,
"bits": [ 3 ],
"attributes": {
"src": "test.v:2"
}
},
"a": {
"hide_name": 0,
"bits": [ 2 ],
"attributes": {
"src": "test.v:2"
}
}
}
}
}
}
Is there anyway to force yosys to interpret the line as a nand gate and output json more like this:
{
"creator": "Yosys 0.7 (git sha1 61f6811, gcc 6.2.0-11ubuntu1 -O2 -fdebug-prefix-map=/build/yosys-OIL3SR/yosys-0.7=. -fstack-protector-strong -fPIC -Os)",
"modules": {
"test": {
"attributes": {
"src": "test.v:1"
},
"ports": {
"a": {
"direction": "input",
"bits": [ 2 ]
},
"b": {
"direction": "input",
"bits": [ 3 ]
},
"c": {
"direction": "output",
"bits": [ 4 ]
}
},
"cells": {
"$nand$test.v:4$1": {
"hide_name": 1,
"type": "$nand",
"parameters": {
"Y_WIDTH": 1,
"B_WIDTH": 1,
"A_WIDTH": 1,
"B_SIGNED": 0,
"A_SIGNED": 0
},
"attributes": {
"src": "test.v:4"
},
"port_directions": {
"Y": "output",
"B": "input",
"A": "input"
},
"connections": {
"Y": [ 4 ],
"B": [ 3 ],
"A": [ 2 ]
}
}
},
"netnames": {
"$nand$test.v:4$1_Y": {
"hide_name": 1,
"bits": [ 5 ],
"attributes": {
"src": "test.v:4"
}
},
"c": {
"hide_name": 0,
"bits": [ 4 ],
"attributes": {
"src": "test.v:3"
}
},
"b": {
"hide_name": 0,
"bits": [ 3 ],
"attributes": {
"src": "test.v:2"
}
},
"a": {
"hide_name": 0,
"bits": [ 2 ],
"attributes": {
"src": "test.v:2"
}
}
}
}
}
}
Or is this not something that can be done.
As you have not run any kind of synthesis, the design is still in the form of a word-wide RTL netlist. In this context "$and", "$not" and similar lowercase cells are multibit cells designed to match the Verilog operators.
Running the "synth" command will synthesise your design to a standard set of single-bit gate level cells. This includes a NAND cell. Note that these cells will have uppercase names such as "$_NAND_" and are equivalent to basic logic gates.