$.fn.enrichedChart = function(data, inSettings) {
    var plot = {};
    var extraDefaults = {
        yLabels: '',
        yTickFormat: '',
        minY: 0,
        dimension: {w: 850, h: 300},
        padding: {t: 20, r: 20, b: 85, l: 50},
        bgColor: '',
        barWidth: 11,
        xLabelsHide: false,
        extendedTooltip: false
    };
    var settings = addDefaultPlotSettings(inSettings, extraDefaults);
    plot.settings = settings;

    // Inner dimension
    var width = plot.width = settings.dimension.w - settings.padding.l - settings.padding.r; // inner width
    var height = plot.height = settings.dimension.h - settings.padding.t - settings.padding.b; // inner height

    var xScale = plot.x = d3.scaleBand()
        .range([0, width])
        .domain(data.map(function(d) { return d.label; }));
    var xAxis = d3.axisBottom(xScale)
        .tickSizeOuter(0);

    if (settings.xLabelsHide) {
        xAxis
            .tickFormat('')
            .tickSize(0);
    }

    var yScale;
    var yMin, yMax, yAxis;
    if (settings.yLabels) {
        yMin = plot.yMin = 0;
        yMax = plot.yMax = d3.max(d3.keys(settings.yLabels));
        yScale = plot.y = d3.scaleLinear()
            .range([height, 0])
            .domain([yMin, yMax]);
        yAxis = d3.axisLeft(yScale)
            .tickFormat(function(d) { return settings.yLabels[d]; })
            .tickValues(d3.keys(settings.yLabels));
    }
    else {
        yMin = plot.yMin = 0.3;
        yMax = plot.yMax = Math.max(d3.max(data, function(d) { return parseFloat(d.value); }), settings.minY);
        yScale = plot.y = d3.scaleLinear()
            .range([height, 0])
            .domain([yMin, yMax])
            .nice(5);
        yAxis = d3.axisLeft(yScale)
            .ticks(5);
        if (settings.yTickSize != undefined) {
            yAxis.tickSize(settings.yTickSize);
        }
        if (settings.yTickFormat) {
            yAxis.tickFormat(d3.format(settings.yTickFormat));
        }
    }
    var vis = plot.vis = d3.select($(this).get(0))
        .append("svg")
        .attr("class", "barchart")
        .attr("width", width + settings.padding.l + settings.padding.r)
        .attr("height", height + settings.padding.t + settings.padding.b)
        .append("g")
        .attr("transform", "translate(" + settings.padding.l + "," + settings.padding.t + ")")
        .attr("width", width)
        .attr("height", height);

    $(this).on('click', '[url]', function() {
        document.location.href = $(this).attr('url');
    });

    if (settings.bgColor) {
        vis.append("rect")
            .attr("class", "chart_field")
            .attr("width", width)
            .attr("height", height+4)
            .attr("transform", "translate(0,-4)")
            .style("fill", settings.bgColor);
    }

    var bar_g = vis.selectAll(".bar_g")
        .data(data)
        .enter()
        .append("g")
        .attr("class", function(d) { return d.class? "bar_g "+d.class : "bar_g"; })
        .attr("transform", function(d) { return 'translate('+xScale(d.label)+', 0)'; })
        .attr("title", function(d) { return d.tooltip; });

    var link = bar_g.append("a")
        .each(function(d) { if (d.url) d3.select(this).attr("xlink:href", d.url); });

    if (settings.extendedTooltip) {
        var bar_transp = link.append("rect")
            .attr("class","bartrans")
            .attr("y", 0)
            .attr("x", function(d) { return xScale.bandwidth()/2 - settings.barWidth/2 ; })
            .attr("width", settings.barWidth)
            .attr("height", height)
            .style("fill", "transparent");
    }
    var bar_line = link.append("line")
        .attr("class","bar")
        .style("stroke", "grey")
        .style("stroke-width", 0.5)
        .attr("y1", function(d) { return (d.na == 1 || d.value<0.3)?0:yScale(d.value); })
        .attr("x1", function(d) { return xScale.bandwidth()/2 ; })
        .attr("y2", function(d) { return (d.na == 1 || d.value<0.3)?0:yScale(0.3); })
        .attr("x2", function(d) { return xScale.bandwidth()/2 ; })

    var bar_circle = link.append("circle")
        .attr("class", "bar")
        //.attr("transform", "translate(0,0)")
        .attr("cy", function(d) { return (d.na == 1)?0:yScale(d.value); })
        .attr("cx", function(d) { return xScale.bandwidth()/2 ; })
        .attr("r", function(d) { return (d.na == 1 || d.value<0.3)?0:d.radius})
        //.style("stoke","1px solid black")
        .style("stroke", d => d.radius>4 ? "black" : "transparent")
        //.attr("width", settings.barWidth)
        //.attr("height", function(d) { return (d.na == 1)?height:(height-yScale(d.value));})
        .style("fill", function(d){
            if (d.na==1) {
                return "#FAFAFA";
            } else if (typeof d.color_group!='undefined') {
                return colorbrewer[d.color_group[0]][d.color_group[1]][d.color_group[2]];
            } else {
                return d.color;
            }
        });

    var bar_text = bar_g.filter(function(d){ return d.na == 1; })
        .append("text")
        .attr("class", "na_text")
        .style("text-anchor", "middle")
        .attr("transform", "rotate(-90)")
        .attr("y", settings.barWidth/2+6)
        .attr("x", -height/2)
        .text("N/A");

    if (settings.valueLabels) {
        link.append("text")
            .attr("class", "valueLabel")
            .style("text-anchor", "middle")
            .attr("x", function(d, i) { return xScale.bandwidth()/2; })
            .attr("y", function(d) { return (d.na == 1)?0:yScale(d.value)-2; })
            .text(function(d) { return (d.na == 1)?'':d.value; });
    }

    vis.append("g")
        .attr("class", "x axis")
        .attr("transform", "translate(0," + height + ")")
        .call(xAxis)
        .selectAll(".tick text")
        .attr("class", "barchartlabel")
        .attr("y", 0)
        .attr("x", -9)
        .attr("transform", "rotate(-55)")
        .style("text-anchor", "end")
        .each(function(d, i) {
            if (data[i].tooltip) {
                d3.select(this).attr('title', data[i].tooltip);
            }
            if (data[i].url) {
                d3.select(this).attr('url', data[i].url).style('cursor', 'pointer');
            }
        });
		
			$(this).on('click', '[url]', function() {
				document.location.href = $(this).attr('url');
			});
		
    // x axis label
    vis.selectAll(".x.axis")
        .append("text")
        .attr("y", 20)
        .attr("x", width/2)
        .text(settings.xAxisLabel);
    // y axis label
    vis.append("g")
        .attr("class", "y axis")
        .call(yAxis)
        .append("text")
        .attr("y", -8)
        .style("text-anchor", "middle")
        .text(settings.yAxisLabel);

    vis.selectAll(".y .tick text")
        .call(wrap, settings.padding.l);

    // Legend
    if (settings.legend !== '') {
        var legend = vis.selectAll(".legend")
            .data(d3.map(data, function(d){return d.legend;}).values())
            .enter().append("g")
            .attr("class", "legend")
            .attr("transform", function(d, i) { return "translate(0," + i * (settings.barWidth+2) + ")"; });

        legend.append("rect")
            .attr("x", settings.legend.x)
            .attr("y", settings.legend.y)
            .attr("width", settings.barWidth)
            .attr("height", settings.barWidth)
            .style("fill", function(d, i) {return d.color; });

        legend.append("text")
            .attr("x", settings.legend.x+settings.barWidth+2)
            .attr("y", settings.legend.y+settings.barWidth/2)
            .attr("dy", ".35em")
            .style("text-anchor", settings.legend.txtAnchor)
            .text(function(d) { return d.legend; });

    }

    $(this).on('sort', function(e, order) {
        var x0 = xScale.domain(
            data.sort(
                order==='pos'? function(a, b) { return a.pos - b.pos; }
                    :order==='value'? function(a, b) { return a.na? 1000 : b.na? -1000 : b.value - a.value; }
                    :order==='real_value'? function(a, b) { return a.na? 1000 : b.na? -1000 : b.real_value - a.real_value; }
                        :order==='label'? function(a, b) { return a.label.localeCompare(b.label); }
                            :order==='origin'? function(a, b) { return a.origin.localeCompare(b.origin); }
                                :order==='category'? function(a, b) { return a.category.localeCompare(b.category); }
                                    : function(a,b) { return 0; }
            )
                .map(function(d) { return d.label; })
        )
            .copy();
        vis.selectAll(".bar_g").sort(function(a, b) { return x0(a.value) - x0(b.value); });
        vis.selectAll(".x.axis.tick").sort(function(a, b) { return x0(a.value) - x0(b.value); });

        var transition = vis.transition().duration(100);
        transition.selectAll(".bar_g")
            .attr("transform", function(d) { return 'translate('+x0(d.label)+', 0)'; });
        transition.select(".x.axis")
            .call(xAxis)
            .selectAll(".tick text")
            .style("text-anchor", "end")
            .attr("y", 0)
            .attr("x", -9);
    });

    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"),
                x = text.attr("x"),
                dy = parseFloat(text.attr("dy")),
                tspan = text.text(null).append("tspan").attr("x", x).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", x).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word);
                }
            }
        });
    }
    return plot;
};
$.fn.core_panel = function(data) {
    var margin = {top: 0, right: 80, bottom: 95, left: 135},
        width = 465 - margin.left - margin.right,
        height = 235 - margin.top - margin.bottom;

    // append the svg object to the body of the page
    var svg = d3.select($(this).get(0))
        .append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
        .append("g")
        .attr("transform",
            "translate(" + margin.left + "," + margin.top + ")");
    // Build X scales and axis:
    var x = d3.scaleBand()
        .range([ 0, width ])
        .domain(data.map(function(d) { return d.tissue; }))
        .padding(0.01);
    var xAxis = d3.axisBottom(x);
    svg.append("g")
        .attr("class", "x axis")
        .attr("transform", "translate(0," + height + ")")
        .call(xAxis)
        .selectAll(".tick text")
        .attr("class", "barchartlabel")
        .attr("y", 0)
        .attr("x", -9)
        .attr("transform", "rotate(-55)")
        .style("text-anchor", "end")
        .each(function(d, i) {
            if (data[i].tooltip) {
                d3.select(this).attr('title', data[i].tooltip);
            }
            if (data[i].url) {
                d3.select(this).attr('url', data[i].url).style('cursor', 'pointer');
            }
        });
    var y = d3.scaleBand()
        .range([ height, 0 ])
        .domain(data.map(function(d) { return d.cell_type; }))
        .padding(0.01);
    svg.append("g")
        .call(d3.axisLeft(y));

    // Build color scale
    var myColor = d3.scaleLinear()
        .range(["white", "#69b3a2"])
        .domain([1,100])
    svg.selectAll()
        .data(data, function(d) {return d.tissue+':'+d.cell_type;})
        .enter()
        .append("rect")
        .attr("x", function(d) { return x(d.tissue) })
        .attr("y", function(d) { return y(d.cell_type) })
        .attr("width", x.bandwidth())
        .attr("height", y.bandwidth())
        //.attr("width", x.bandwidth() )
        //.attr("height", y.bandwidth() )
        .style("fill", function(d) { return (d.value == -1)?'white':'white'} )
    svg.selectAll()
        .data(data)
        .enter()
        .append("line")
        .style("stroke", "lightgrey")
        .style("stroke-width", 1)
        .attr("x1", function(d) { return x(d.tissue) + x.bandwidth() })
        .attr("y1", function(d) { return height})
        .attr("x2", function(d) { return x(d.tissue) + x.bandwidth() })
        .attr("y2", function(d) { return 0 })
    svg.selectAll()
        .data(data)
        .enter()
        .append("line")
        .style("stroke", "grey")
        .style("stroke-width", 1)
        .attr("x1",0)
        .attr("y1", function(d) { return y(d.cell_type)})
        .attr("x2", width)
        .attr("y2", function(d) { return y(d.cell_type) })
    //.attr("width", x.bandwidth() )
    //.attr("height", y.bandwidth() )
    svg.selectAll()
    .data(data, function(d) {return d.tissue+':'+d.cell_type;})
    .enter()
    .append("circle")
    .attr("cx", function(d) { return x.bandwidth()/2 + x(d.tissue) })
    .attr("cy", function(d) { return y.bandwidth()/2 +y(d.cell_type) })
    .attr("r", function(d) { if(d.value >= 0) {return x.bandwidth()/2-3} else {return 0}})
    //.attr("width", x.bandwidth() )
    //.attr("height", y.bandwidth() )
    .style("fill", function(d) { return ((d.value==0)?'lightgrey':d.color)} )
    .each(function(d, i) {
        if (data[i].tooltip) {
            d3.select(this).attr('title', data[i].tooltip);
        }
        if (data[i].url) {
            d3.select(this).attr('url', data[i].url).style('cursor', 'pointer');
        }
    });
		$(this).on('click', '[url]', function() {
			document.location.href = $(this).attr('url');
		});
}