3

I have the following code:

var indata = [{
  'sample': "Foo",
  "pies_pct": [{
    "score": 6.7530200000000002,
    "celltype": "Bcells"
  }, {
    "score": 11.432763461538459,
    "celltype": "DendriticCells"
  }]

}, {
  'sample': "Bar",
  "pies_pct": [{
    "score": 26.8530200000000002,
    "celltype": "Bcells"
  }, {
    "score": 31.432763461538459,
    "celltype": "DendriticCells"
  }]

}, ];



processData(indata);

function processData(data) {

  pies = data.map(function(data) {
    return {
      title: data.sample,
      dataset: data.pies_pct
    };


  });

  buildPlots();
}

function buildPlots() {
  var $pieContainer = $('#sample-pies');

  pies.forEach(function(pie, index) {
    var elementId = "sample-pie-" + index;

    $(document.createElementNS('http://www.w3.org/2000/svg', 'svg'))
      .css({
        width: '200px',
        height: '200px',
        display: 'inline-block'
      })
      .attr('id', elementId)
      .appendTo($pieContainer);


    plotSamplePie(pie.title, pie.dataset, '#' + elementId);
  });


}




function plotSamplePie(title, purity_data, targetElement) {
  var scale = new Plottable.Scales.Linear();
  var tableau20 = ['#1F77B4', '#FF7F0E', '#2CA02C', '#D62728',
    '#9467BD', '#8C564B', '#CFECF9', '#7F7F7F', '#BCBD22', '#17BECF'
  ];
  var colorScale = new Plottable.Scales.Color();
  var legend = new Plottable.Components.Legend(colorScale);
  colorScale.range(tableau20);




  var titleLabel = new Plottable.Components.TitleLabel(title);
  var plot = new Plottable.Plots.Pie()
    .addDataset(new Plottable.Dataset(purity_data))
    .attr("fill", function(d) {
      return d.score;
    }, colorScale)
    .sectorValue(function(d) {
      return d.score;
    }, scale)
    .labelsEnabled(true);


  new Plottable.Components.Table([
    [titleLabel],
    [plot]
  ]).renderTo(targetElement);

}


function drawPieLegend(targetElement) {
  new Plottable.Components.Legend(colorScale)
    .renderTo(targetElement);
}


drawPieLegend('#pies-legend')
<html>

<head>
  <link href="https://cdnjs.cloudflare.com/ajax/libs/plottable.js/1.15.0/plottable.css" rel="stylesheet" />
  <link href="https://cdnjs.cloudflare.com/ajax/libs/qtip2/2.2.1/basic/jquery.qtip.css" rel="stylesheet" />


</head>

<body>


  My Plot

  <!-- Show histograms -->
  <div id="sample-pies"></div>
  
  Legend here:
  <div id="pies-legend"></div>

  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/plottable.js/1.15.0/plottable.js"></script>





</body>

</html>

What I want do do is to display one legend for both pie charts under '#pies-legend' as the target element called by the function drawPieLegend(). But why it does not show up?

pdubois
  • 7,640
  • 21
  • 70
  • 99

2 Answers2

3

colorScale is defined inside plotSamplePie(), so it doesn't appear in the scope of drawPieLegend(). Declaring colorScale outside both functions will make it possible for both functions to access it (although this is a bit messy since it is now a global variable). It'd probably be cleaner to create colorScale inside the processing function, then pass it to the functions that make the pies and the legend separately. Here's a quick attempt at fixing it:

var indata = [{
  'sample': "Foo",
  "pies_pct": [{
    "score": 6.7530200000000002,
    "celltype": "Bcells"
  }, {
    "score": 11.432763461538459,
    "celltype": "DendriticCells"
  }]

}, {
  'sample': "Bar",
  "pies_pct": [{
    "score": 26.8530200000000002,
    "celltype": "Bcells"
  }, {
    "score": 31.432763461538459,
    "celltype": "DendriticCells"
  }]

}, ];

              
var colorScale = new Plottable.Scales.Color();
var tableau20 = ['#1F77B4', '#FF7F0E', '#2CA02C', '#D62728',
    '#9467BD', '#8C564B', '#CFECF9', '#7F7F7F', '#BCBD22', '#17BECF'
];
colorScale.range(tableau20);

processData(indata);

function processData(data) {

  pies = data.map(function(data) {
    return {
      title: data.sample,
      dataset: data.pies_pct
    };


  });

  buildPlots();
}

function buildPlots() {
  var $pieContainer = $('#sample-pies');

  pies.forEach(function(pie, index) {
    var elementId = "sample-pie-" + index;

    $(document.createElementNS('http://www.w3.org/2000/svg', 'svg'))
      .css({
        width: '200px',
        height: '200px',
        display: 'inline-block'
      })
      .attr('id', elementId)
      .appendTo($pieContainer);


    plotSamplePie(pie.title, pie.dataset, '#' + elementId);
  });


}




function plotSamplePie(title, purity_data, targetElement) {
  var scale = new Plottable.Scales.Linear();
  var titleLabel = new Plottable.Components.TitleLabel(title);
  var plot = new Plottable.Plots.Pie()
    .addDataset(new Plottable.Dataset(purity_data))
    .attr("fill", function(d) {
      return d.celltype;
    }, colorScale)
    .sectorValue(function(d) {
      return d.score;
    }, scale)
    .labelsEnabled(true);


  new Plottable.Components.Table([
    [titleLabel],
    [plot]
  ]).renderTo(targetElement);

}


function drawPieLegend(targetElement) {
  new Plottable.Components.Legend(colorScale)
    .maxEntriesPerRow(Infinity)
    .renderTo(targetElement);
}


drawPieLegend('#pies-legend');
<html>

<head>
  <link href="https://cdnjs.cloudflare.com/ajax/libs/plottable.js/1.15.0/plottable.css" rel="stylesheet" />
  <link href="https://cdnjs.cloudflare.com/ajax/libs/qtip2/2.2.1/basic/jquery.qtip.css" rel="stylesheet" />


</head>

<body>


  My Plot

  <!-- Show histograms -->
  <div id="sample-pies"></div>
  
  Legend here:
  <svg id="pies-legend" height="50" width="400"></svg>

  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/plottable.js/1.15.0/plottable.js"></script>





</body>

</html>

Note also the change from

.attr("fill", function(d) {
  return d.score;
}, colorScale)

to

.attr("fill", function(d) {
  return d.celltype;
}, colorScale)

which causes the colors to be driven by celltype rather than score.

Community
  • 1
  • 1
jtlan
  • 341
  • 1
  • 4
  • Thanks. But we'd like the legend to have just **two** colours: for `Bcells` and `DendriticCells`. Moreover the value of the legend should be `Bcells` and `DendriticCells`, not 6.75 etc2. How can we modify your code? – neversaint Dec 05 '15 at 02:38
  • 2
    I amended the above comment to drive the fill color based on celltype. – jtlan Dec 07 '15 at 18:21
2

You need to add legend to new Plottable.Components.Table().

new Plottable.Components.Table([
    [titleLabel],
    [plot],
    [legend]
  ]).renderTo(targetElement);

Go through below snippet.

var indata = [{
  'sample': "Foo",
  "pies_pct": [{
    "score": 6.7530200000000002,
    "celltype": "Bcells"
  }, {
    "score": 11.432763461538459,
    "celltype": "DendriticCells"
  }]

}, {
  'sample': "Bar",
  "pies_pct": [{
    "score": 26.8530200000000002,
    "celltype": "Bcells"
  }, {
    "score": 31.432763461538459,
    "celltype": "BCells"
  }]

}, ];



processData(indata);

function processData(data) {

  pies = data.map(function(data) {
    return {
      title: data.sample,
      dataset: data.pies_pct
    };


  });

  buildPlots();
}

function buildPlots() {
  var $pieContainer = $('#sample-pies');

  pies.forEach(function(pie, index) {
    var elementId = "sample-pie-" + index;

    $(document.createElementNS('http://www.w3.org/2000/svg', 'svg'))
      .css({
        width: '200px',
        height: '200px',
        display: 'inline-block'
      })
      .attr('id', elementId)
      .appendTo($pieContainer);


    plotSamplePie(pie.title, pie.dataset, '#' + elementId);
  });


}




function plotSamplePie(title, purity_data, targetElement) {
  var scale = new Plottable.Scales.Linear();
  var tableau20 = ['#1F77B4', '#FF7F0E', '#2CA02C', '#D62728',
    '#9467BD', '#8C564B', '#CFECF9', '#7F7F7F', '#BCBD22', '#17BECF'
  ];
  var colorScale = new Plottable.Scales.Color();
  var legend = new Plottable.Components.Legend(colorScale);
  colorScale.range(tableau20);




  var titleLabel = new Plottable.Components.TitleLabel(title);
  var plot = new Plottable.Plots.Pie()
    .addDataset(new Plottable.Dataset(purity_data))
    .attr("fill", function(d) {
      return d.score;
    }, colorScale)
    .sectorValue(function(d) {
      return d.score;
    }, scale)
    .labelsEnabled(true);


  new Plottable.Components.Table([
    [titleLabel],
    [plot],
    [legend]
  ]).renderTo(targetElement);

}


function drawPieLegend(targetElement) {
  new Plottable.Components.Legend(colorScale)
    .renderTo(targetElement);
}


drawPieLegend('#pies-legend')
<html>

<head>
  <link href="https://cdnjs.cloudflare.com/ajax/libs/plottable.js/1.15.0/plottable.css" rel="stylesheet" />
  <link href="https://cdnjs.cloudflare.com/ajax/libs/qtip2/2.2.1/basic/jquery.qtip.css" rel="stylesheet" />


</head>

<body>


  My Plot

  <!-- Show histograms -->
  <div id="sample-pies"></div>
  
  Legend here:
  <div id="pies-legend"></div>

  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/plottable.js/1.15.0/plottable.js"></script>





</body>

</html>
J-D
  • 1,575
  • 1
  • 11
  • 22
  • Thanks. But that's not what I want. We want to display **one** legend for both pie chart. And the legend content should be for *Dendritic cell* and *B Cell* not its value. – pdubois Dec 03 '15 at 06:17
  • Try using legend.renderTo("svg#legend_example"); But this need to be work on as shown in jsfiddle http://jsfiddle.net/3fpw33oL/ – J-D Dec 03 '15 at 06:31
  • Thanks. Not quite there. By doing that you are appending multiple chart legend to one plot. – pdubois Dec 03 '15 at 06:37