function dashvacancies(data, base = "dashvacancies") {
    var graphic = d3.select('#' + base);
    var keypoints = d3.select('#keypoints');
    var thismeasure = "vacancies";
    var dvc, textdata, graphic_data, keys, annotations, lineNo, var_group, changeonQuarter, changeonPandemic;

    function beforedrawgraphic(width) {
        textdata = data.text.filter(function (d) { return d.measure == thismeasure });
        drawGraphic(width, textdata);
        d3.select("#" + base + "-wrapper .measureheading").text(textdata[0].heading)
        d3.select("#" + base + "-wrapper .measuredefinition").text(textdata[0].definition)
        d3.select("#" + base + "-wrapper .measurecommentary").html(textdata[0].commentary)
        d3.select("#" + base + "-wrapper .measuresource").text(textdata[0].source)
    }
    function drawGraphic(width, textdata) {

        //write the atomated up/down arrows
        changeonQuarter = textdata[0]["quarterly change"];
        // console.log(changeonQuarter)
        d3.select("#" + base + "-wrapper .measureMonth")
            .text(function (d) {
                if (parseInt(changeonQuarter) == 0) { return "Quarterly change: ◀▶ 0" }
                else if (parseInt(changeonQuarter) > 0) { return "Quarterly change: ▲" + changeonQuarter + "" }
                else if (parseInt(changeonQuarter) < 0) { return "Quarterly change: ▼" + changeonQuarter + "" }
            })

        changeonPandemic = textdata[0]["change since JM20"];
        d3.select("#" + base + "-wrapper .measurePandemic")
            .text(function (d) {
                if (parseInt(changeonPandemic) == 0) { return "Since Jan-Mar 2020: ◀▶" + changeonPandemic + "" }
                else if (parseInt(changeonPandemic) > 0) { return "Since Jan-Mar 2020: ▲" + changeonPandemic + "" }
                else if (parseInt(changeonPandemic) < 0) { return "Since Jan-Mar 2020: ▼" + changeonPandemic + "" }
            })


        var threshold_md = 400;
        var threshold_sm = dvc.optional.mobileBreakpoint;

        //set variables for chart dimensions dependent on width of #graphic
        var size, margin, chart_width, height;

        if (parseInt(graphic.style("width")) < threshold_sm) {
            margin = {
                top: dvc.optional.margin_sm[0],
                right: dvc.optional.margin_sm[1],
                bottom: dvc.optional.margin_sm[2],
                left: dvc.optional.margin_sm[3]
            };
            size = 0;	// used for margin_centre and x_ticks
            chart_width = parseInt(graphic.style("width")) - margin.left - margin.right;
            height = Math.ceil((chart_width * dvc.optional.aspectRatio_sm[1]) / dvc.optional.aspectRatio_sm[0]) - margin.top - margin.bottom;
        }

        else if (parseInt(graphic.style("width")) < threshold_md) {
            margin = {
                top: dvc.optional.margin_md[0],
                right: dvc.optional.margin_md[1],
                bottom: dvc.optional.margin_md[2],
                left: dvc.optional.margin_md[3]
            };
            size = 1;
            chart_width = parseInt(graphic.style("width")) - margin.left - margin.right;
            height = Math.ceil((chart_width * dvc.optional.aspectRatio_md[1]) / dvc.optional.aspectRatio_md[0]) - margin.top - margin.bottom;
        }

        else {
            margin = {
                top: dvc.optional.margin_lg[0],
                right: dvc.optional.margin_lg[1],
                bottom: dvc.optional.margin_lg[2],
                left: dvc.optional.margin_lg[3]
            };
            size = 2;
            chart_width = parseInt(graphic.style("width")) - margin.left - margin.right;
            height = Math.ceil((chart_width * dvc.optional.aspectRatio_lg[1]) / dvc.optional.aspectRatio_lg[0]) - margin.top - margin.bottom;
        }

        height = 150;
        // clear out existing graphics
        graphic.selectAll("*").remove();
        keypoints.selectAll("*").remove();

        var x = d3.scaleTime()
            .range([10, chart_width]);

        var y = d3.scaleLinear()
            .range([height, 0]);

        x.domain(d3.extent(graphic_data, function (d) { return d.date; }));

        var xAxis = d3.axisBottom(x)
            .tickFormat(function (d, i) {
                //specify date format for x axis depending on #graphic width
                if (parseInt(graphic.style("width")) <= threshold_sm) {
                    var fmt = d3.timeFormat(dvc.optional.xAxisTextFormat_sm_md_lg[0]);
                    //console.log("S "+fmt(d));
                    return fmt(d);
                } else if (parseInt(graphic.style("width")) <= threshold_md) {
                    var fmt = d3.timeFormat(dvc.optional.xAxisTextFormat_sm_md_lg[1]);
                    //console.log("M "+fmt(d));
                    return fmt(d);
                } else {
                    //console.log(dvc.optional.xAxisTextFormat_sm_md_lg[2] + ",  " + d);
                    var fmt = d3.timeFormat(dvc.optional.xAxisTextFormat_sm_md_lg[2]);
                    //console.log("L "+fmt(d));
                    return fmt(d);
                }
            })
            .tickPadding(5)


        //specify number of ticks on x axis and whether 1st and last data point labels are included
        if (parseInt(graphic.style("width")) < 1) {
            xAxis.tickValues(x.ticks(graphic_data.length));
        } else if (parseInt(graphic.style("width")) <= threshold_md) {
            xAxis.tickValues(x.ticks(graphic_data.length))//.concat( x.domain());
        } else {
            xAxis.tickValues(x.ticks(graphic_data.length))//.concat( x.domain() );
        }

        var yAxis = d3.axisLeft(y);


        //specify number or ticks on y axis
        if (parseInt(graphic.style("width")) <= threshold_sm) {
            yAxis.ticks(dvc.optional.y_num_ticks_sm_md_lg[0])
        } else if (parseInt(graphic.style("width")) <= threshold_md) {
            yAxis.ticks(dvc.optional.y_num_ticks_sm_md_lg[1])
        } else {
            yAxis.ticks(dvc.optional.y_num_ticks_sm_md_lg[2])
        }

        //gridlines
        var y_axis_grid = function () { return yAxis; }

        var counter;


        var line = d3.line()
            .defined(function (d) { return d.amt !== ''; }) // nobody can tell me what this line actually does
            .curve(d3.curveLinear)
            .x(function (d) { return x(d.date); })
            .y(function (d) { return y(d.amt); });

        // parse data into columns
        var lines = {};
        for (var column in graphic_data[0]) {
            if (column == 'date') continue;
            lines[column] = graphic_data.map(function (d) {
                return {
                    'date': d.date,
                    'amt': d[column]
                };
            });
        }


        // do some code to overwrite blanks with the last known point
        keys = d3.keys(lines)
        for (i = 0; i < keys.length; i++) {
            // console.log(lines[keys[i]])
            lines[keys[i]].forEach(function (d, j) {
                if (d.amt != "null") {
                    counter = j;
                } else {
                    d.date = lines[keys[i]][counter].date
                    d.amt = lines[keys[i]][counter].amt
                }

            })

        }


        //y domain calculations	: zero to intelligent max choice, or intelligent min and max choice,  or interval chosen manually
        var yDomain = [textdata[0].yaxisstart, textdata[0].yaxisend];
        //   if (dvc.essential.yAxisScale == "auto_zero_max"){
        //    var yDomain = [
        // 					0,
        // 					d3.max(d3.entries(lines), function(c) {
        // 						return d3.max(c.value, function(v) {
        // 							var n = v.amt;
        // 							return Math.ceil(n);
        // 						});
        // 					})
        // 				 ];
        // } else if (dvc.essential.yAxisScale == "auto_min_max"){
        // 	var yDomain = [
        // 					d3.min(d3.entries(lines), function(c) {
        // 						return d3.min(c.value, function(v) {
        // 							var n = v.amt;
        // 							return Math.floor(n);
        // 						});
        // 					}),
        //
        // 					d3.max(d3.entries(lines), function(c) {
        // 						return d3.max(c.value, function(v) {
        // 							var n = v.amt;
        // 							return Math.ceil(n);
        // 						});
        // 					})
        // 		 		];
        // } else {
        //    var yDomain = dvc.essential.yAxisScale;
        //   }

        y.domain(yDomain);

        //console.log(chart_width +" , "+ height);
        //console.log(chart_width + margin.left + margin.right +" , "+ (height + margin.top + margin.bottom));


        //var svg = d3.select('#graphic').append('svg')
        var svg = graphic.append('svg')
            .attr("id", "chart")
            .style("background-color", "#fff")
            .attr("width", chart_width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom)  //+30)
            .append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");


        svg.append("rect")
            .style("fill", "#fff")
            .attr("width", chart_width)
            .attr("height", height);

        svg.append('g')
            .attr('class', 'y axis')
            .call(yAxis);

        svg.append('g')
            .attr('class', 'y grid')
            .call(y_axis_grid()
                .tickSize(-chart_width, 0, 0)
                .tickFormat('')
            );

        //y axis label
        svg.append("text")
            //.attr('class', 'unit')
            .attr('transform', 'translate(' + -margin.left + ',-10)') // " + eval(-margin.top + (lineNo+1)*20) + "
            .attr("font-size", "14px")
            .attr("fill", "#666")
            .text(function (d, i) { return dvc.essential.yAxisLabel });

        svg.append("text")
            .attr("x", x(graphic_data[graphic_data.length - 1].date) + 7)
            .attr("y", y(graphic_data[graphic_data.length - 1][thismeasure]) + 8)
            .attr("font-size", "14px")
            .attr("font-weight", "bold")
            .attr("text-anchor", "start")
            .attr("fill", "#206095")
            .text(d3.format(",")(graphic_data[graphic_data.length - 1][thismeasure]));

        svg.append('circle')
            .attr('cx', x(graphic_data[graphic_data.length - 1].date))
            .attr("cy", y(graphic_data[graphic_data.length - 1][thismeasure]))
            .attr('r', 4)
            .attr("fill", "#206095");

        //create x axis, if y axis doesn't start at 0 drop x axis accordingly
        svg.append('g')
            .attr('class', 'x axis')
            .attr('transform', function (d) {
                if (yDomain[0] != 0) {
                    return 'translate(0,' + (height + 20) + ')'
                } else {
                    return 'translate(0,' + height + ')'
                }
            })
            .call(xAxis);

        graphic.select(".x").select("path").style("stroke", "#666")

        //create icon to symbolise break in y axis if required
        if (yDomain[0] > 0 && dvc.essential.yAxisBreak == true) {
            var paths = svg.append("defs")
                .append("g")
                .attr("id", "icon")
                .append("g");

            paths.append("polyline")
                .attr("points", "2.881,9.54 7.94,5.061 12.341,9.54 17.77,5.061")
                .attr("stroke", "#666")
                .attr("fill", "none")
            paths.append("polyline")
                .attr("points", "2.881,14.54 7.94,10.061 12.341,14.54 17.77,10.061")
                .attr("stroke", "#666")
                .attr("fill", "none");

            //specify position of icon
            svg.append("g").attr("id", "iconpath")
                .attr("transform", "translate(-10,3)")
                .append("use")
                .attr("xlink:href", "#icon")
                .attr("x", x(x.domain()[0]))
                .attr("y", function () {
                    if (parseInt(graphic.style("width")) < threshold_sm) {
                        return y(dvc.essential.yAxisBreak_sm_md_lg[0])
                    } else if (parseInt(graphic.style("width")) < threshold_md) {
                        return y(dvc.essential.yAxisBreak_sm_md_lg[1])
                    } else {
                        return y(dvc.essential.yAxisBreak_sm_md_lg[2])
                    }
                });
        }


        //just first and last points
        graphic.select("g.x.axis").selectAll(".tick").attr("class", function (d, i) {
            return "ticky ticky" + i;
        })
        graphic.selectAll(".ticky").style("display", "none");
        graphic.select(".ticky0").style("display", "block").selectAll("text").text(textdata[0].startdate).attr("text-anchor", "start").call(wrap, 70)
        graphic.select(".ticky" + (graphic_data.length - 1)).style("display", "block").selectAll("text").text(textdata[0].enddate).attr("text-anchor", "end").call(wrap, 70)

        graphic.select("g.y.grid").style("display", "none");



        //create centre line if required
        if (dvc.optional.centre_line == true) {
            svg.append("line")
                //.attr("id","centreline")
                .attr("stroke", "#CCC")
                .attr("stroke-width", 3)
                .attr('y1', y(dvc.optional.centre_line_value))
                .attr('y2', y(dvc.optional.centre_line_value))
                .attr('x1', 0)
                .attr('x2', chart_width);
        } else if (yDomain[0] < 0) {
            svg.append("line")
                //.attr("id","centreline")
                .attr("stroke", "#CCC")
                .attr("stroke-width", 3)
                .attr('y1', y(0))
                .attr('y2', y(0))
                .attr('x1', 0)
                .attr('x2', chart_width);
        }


        //create vertical line if required
        if (dvc.optional.vertical_line == true) {

            dvc.optional.annotateLineX1_Y1_X2_Y2.forEach(function (d, i) {

                svg.append("line")
                    .attr('x1', x(d3.timeParse(dvc.essential.dateFormat)(dvc.optional.annotateLineX1_Y1_X2_Y2[i][0][0])))
                    .attr('x2', x(d3.timeParse(dvc.essential.dateFormat)(dvc.optional.annotateLineX1_Y1_X2_Y2[i][1][0])))
                    .attr('y1', y(dvc.optional.annotateLineX1_Y1_X2_Y2[i][0][1]))
                    .attr('y2', y(dvc.optional.annotateLineX1_Y1_X2_Y2[i][1][1]))
                    .style('stroke', '#888')
                    .style('stroke-width', 2);
                //.style('stroke-dasharray', '5 5');   ,dash px,space px




            })
        }

        //create rectangle
        if (dvc.optional.annotateRect == true) {

            dvc.optional.annotateRectX_Y.forEach(function (d, i) {

                svg.append("rect")
                    .attr('x', x(d3.timeParse(dvc.essential.dateFormat)(dvc.optional.annotateRectX_Y[i][0][0])))
                    .attr('y', y(dvc.optional.annotateRectX_Y[i][0][1]))
                    .attr('height', y(dvc.optional.annotateRectX_Y[i][1][1]) - y(dvc.optional.annotateRectX_Y[i][0][1]))
                    .attr('width', x(d3.timeParse(dvc.essential.dateFormat)(dvc.optional.annotateRectX_Y[i][1][0])) - x(d3.timeParse(dvc.essential.dateFormat)(dvc.optional.annotateRectX_Y[i][0][0])))
                    .style('fill', dvc.optional.lineColor_opcty[i][0])
                    .style('stroke-width', 2)
                    .style('opacity', dvc.optional.lineColor_opcty[i][1]);

            })
        }


        //create lines
        svg.append('g').selectAll('path')
            .data(d3.entries(lines).filter(line.defined()))
            .enter()
            .append('path')
            //.attr('class', 'line')
            .style("stroke", "#206095")
            .style("fill", 'none')
            .style("stroke-width", 3)
            .style("stroke-linecap", 'round')
            .attr("class", function (d) { return "alllines line" + d.key })
            .style("stroke-linejoin", 'round')
            .attr('d', function (d) {
                return line(d.value);
            });

        graphic.selectAll(".alllines").style("display", "none");
        graphic.selectAll(".line" + thismeasure).style("display", "block");

        // graphic_data.forEach(function(d,i){
        //   svg.append('circle')
        //   .attr('cx',x(graphic_data[i].date))
        //   .attr('cy',y(graphic_data[i].payrolledemployees))
        //   .attr('r', 4)
        //   .attr("fill",function(){
        //     if(graphic_data[i].payrolledemployees == 0) {return "none"}
        //     else{return '#003C57'}
        //   });
        // })

        // add markers
        if (parseInt(graphic.style("width")) > threshold_sm && dvc.optional.lineMarkers == true) {
            for (var column in graphic_data[0]) {
                if (column == 'date') continue;
                svg.append("g")
                    .selectAll("circles")
                    .data(lines[column]) // raw data
                    .enter()
                    .append('circle')
                    .style('fill', '#fff')
                    .style('stroke', function (d) { return dvc.essential.colour_palette[column]; })
                    .style('stroke-width', 2)
                    .attr("cx", function (d) {
                        return x(d.date);
                    })
                    .attr("cy", function (d) {
                        return y(d.amt);
                    })
                    .attr("r", function (d) { if (d[column] != 0) { return 3 } else { return 0 } });
            }
        } // ends if

        // circle annotations
        if (dvc.essential.circles == true) {
            dvc.essential.annotationCXCY.forEach(function (d, i) {
                svg.append("circle")
                    .attr("cx", x(d3.timeParse(dvc.essential.dateFormat)(dvc.essential.annotationCXCY[i][0])))
                    .attr("cy", y(dvc.essential.annotationCXCY[i][1]))
                    .attr("r", 6)
                    .attr("fill", dvc.essential.annotationColour)

                svg.append("text")
                    .attr("x", x(d3.timeParse(dvc.essential.dateFormat)(dvc.essential.annotationCXCY[i][0])) - 20)
                    .attr("y", y(dvc.essential.annotationCXCY[i][1]) - 15)
                    .text(dvc.essential.annotationCXCY[i][0])
            })
        } // ends if

        writeAnnotation();

        //d3.select("g.y.grid").style("display","none")



        function writeAnnotation() {

            if (parseInt(graphic.style("width")) < 100) {

                dvc.essential.annotationBullet.forEach(function (d, i) {

                    graphic.select("#keypoints").append("svg")
                        .attr("width", "15px")
                        .attr("height", "15px")
                        .attr("class", "circles")
                        .append("circle")
                        .attr("class", "annocirc" + (i))
                        .attr("r", "2")
                        .attr('cy', "9px")
                        .attr("cx", "10px");

                    graphic.select("#keypoints")
                        .append("p")
                        .style("font-size", "14px")
                        .style("font-weight", 400)
                        .text(dvc.essential.annotationBullet[i]);

                })// end foreach

            }
            else {

                annotations = dvc.essential.annotationsChart;

                // For elements with time series
                for (i = 0; i < annotations.length; i++) {
                    annotations[i].xVal = new Date(annotations[i].xVal);

                }

                var swoopy = d3.swoopyDrag()
                    .x(function (d) { return x(d.xVal) })
                    .y(function (d) { return y(d.yVal) })
                    .draggable(dvc.essential.draggable)
                    .annotations(annotations);


                var swoopySel = svg.append('g').attr("class", "annotations").call(swoopy); // Expected number, "translate()". error for each annotation

                svg.append('marker')
                    .attr('id', 'arrow')
                    .attr('viewBox', '-10 -10 20 20')
                    .attr('markerWidth', 20)
                    .attr('markerHeight', 20)
                    .attr('orient', 'auto')
                    .append('path')
                    .attr('d', 'M-6.75,-6.75 L 0,0 L -6.75,6.75')
                    .attr('fill', '#808080');

                swoopySel.selectAll('path').attr('marker-end', 'url(#arrow)');


                graphic.selectAll(".annotations path")
                    .style("stroke", "#808080")
                    .attr("fill", "none");

                swoopySel.selectAll('text')
                    .attr("font-size", "13px")
                    .attr("font-weight", "bold")
                    .attr("fill", "#27A0CC")
                    .attr("class", function (d, i) { return "annotexty" + i })
                    .each(function (d, i) {
                        d3.select(this)
                            .text('')                        //clear existing text
                            .tspans(d3.wordwrap(d.text, dvc.essential.wordwrap[i])) //wrap after xx char
                    });


                swoopySel.selectAll('text')
                    .each(function (d, i) {
                        d3.select(this).selectAll('tspan')
                            .attr("text-anchor", dvc.essential.annoAlign[i]);
                    });
            } // end else ...

            return;

        }// end function writeAnnotation()

        // always create a legend on mobile. when not on mobile, only create a legend if not using direct line labeling.
        var onMobile = parseInt(graphic.style("width")) < dvc.optional.mobileBreakpoint;
        if (!dvc.essential.directLabeling || onMobile) {
            //createLegend();
        }
        else {
            //createLineLabels();
        }

        function createLegend() {

            var prevX = 0;
            var prevY = 0;
            lineNo = 0;
            var lineNoOld = 0;

            dvc.essential.legendLabels.forEach(function (d, i) {

                // draw legend text based on content of var legendLabels ...
                var_group = graphic.select("#legend").append("g")

                var_group.append("rect")
                    .attr("class", "rect" + i)
                    .attr("fill", dvc.essential.colour_palette[d])
                    .attr("x", 0)
                    .attr("y", 0)
                    .attr("width", function (d) {
                        if (dvc.essential.legendStyle == "rect") {
                            return 15;
                        } else {
                            return 20;
                        }
                    })
                    .attr("height", function (d) {
                        if (dvc.essential.legendStyle == "rect") {
                            return 15;
                        } else {
                            return 3;
                        }
                    })

                var_group.append("text")
                    .text(dvc.essential.legendLabels[i])
                    .attr("class", "legend" + i)
                    .attr("text-anchor", "start")
                    .style("font-size", "14px")
                    .style("fill", "#666")
                    .attr('y', 15)
                    .attr('x', 0);


                graphic.selectAll(".legend" + (i))
                    .each(calcPosition);

                function calcPosition() {


                    var BBox = this.getBBox()


                    //prevY =BBox.width
                    graphic.select(".legend" + (i))
                        .attr("y", function (d) {
                            if ((prevX + BBox.width + 50) > parseInt(graphic.style("width"))) {
                                lineNoOld = lineNo;
                                lineNo = lineNo + 1;
                                prevX = 0;
                            }
                            return eval((lineNo * 20) + 20);
                        })
                        .attr("x", function (d) { return prevX + 25; })


                    graphic.select(".rect" + (i))
                        .attr("y", function (d) {

                            if ((prevX + BBox.width + 50) > parseInt(graphic.style("width"))) {
                                lineNoOld = lineNo;
                                lineNo = lineNo + 1;
                                prevX = 0;
                            }

                            if (dvc.essential.legendStyle == "rect") {
                                return eval((lineNo * 20) + 5);
                            } else {
                                return eval((lineNo * 20) + 12);

                            }
                        })
                        .attr("x", function (d) { return prevX; })

                    prevX = prevX + BBox.width + 50



                }; // end function calcPosition()
            });	// end foreach
        }// end function createLegend()


        function createLineLabels() {

            for (var column in graphic_data[0]) {
                if (column == 'date') continue;

                svg.append("text")
                    // place the line labels to the right of the lines and add label adjustment from config
                    .attr("transform", function (d) {
                        var xcoord = x(graphic_data[graphic_data.length - 1]["date"]) + dvc.essential.directLabelingAdjust[column]['x']
                        var ycoord = y(graphic_data[graphic_data.length - 1][column]) + dvc.essential.directLabelingAdjust[column]['y'];
                        return "translate(" + xcoord + "," + ycoord + ")";
                    })
                    .attr("x", 10)
                    .attr("dy", ".35em")
                    .attr("class", "label")
                    .style("fill", dvc.essential.colour_palette[column])
                    .text(column)
                    .call(wrap, margin.right)
            } // end for loop running through data columns
        } // end function createLineLabels()

        function wrap(text, width) {
            text.each(function () {
                var text = d3.select(this),
                    words = text.text().split(/\s+/).reverse(),
                    word,
                    line = [],
                    lineNumber = 0,
                    lineHeight = 1.1, // ems
                    y = text.attr("y"),
                    dy = 0.71,
                    tspan = text.text(null).append("tspan").attr("x", 0).attr("y", y).attr("dy", dy + "em");
                while (word = words.pop()) {
                    line.push(word);
                    tspan.text(line.join(" "));
                    if (tspan.node().getComputedTextLength() > width) {
                        line.pop();
                        tspan.text(line.join(" "));
                        line = [word];
                        tspan = text.append("tspan").attr("x", 0).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word);
                    }
                }
            });
        }

        // css fix
        graphic.selectAll("path").attr("fill", "none");

        graphic.selectAll("text").attr("font-family", "'Open Sans', sans-serif");

        graphic.selectAll(".x text").attr("font-size", "14px").attr("fill", "#666");
        graphic.selectAll(".y text").attr("font-size", "14px").attr("fill", "#666");

        graphic.selectAll(".y line")
            .attr("stroke", "#CCC")
            .attr("stroke-width", "1px")
            .style("shape-rendering", "crispEdges");

        graphic.selectAll(".x line")
            .attr("stroke", "#CCC")
            .attr("stroke-width", "1px")
            .style("shape-rendering", "crispEdges");


        // save SVG
        graphic.select("#buttonid").on("click", function () { saveSvgAsPng(document.getElementById("chart"), "diagram.png") });

    }  // ends draw graphic

    d3.json("../" + base + "/config.json", function (error, config) {
        dvc = config

        //load chart data
        graphic_data = data.charts.filter(function (d) { return d[thismeasure] !== "" });

        graphic_data.forEach(function (d) {
            if (typeof d.date === "string") d.date = d3.timeParse(dvc.essential.dateFormat)(d.date);
        });
        beforedrawgraphic();
    });
}