Пример #1
0
        d3.json("/api/photos/tree/map", function(data){

            var treemap = d3.layout.treemap()
                .size([500, 500])
                .nodes(data);

            var cells = canvas.selectAll(".cell")
                .data(treemap)
                .enter()
                .append("g")
                .attr('class', 'cell');

                cells.append('rect')
                    .attr('x', d => d.x )
                    .attr('y', d => d.y )
                    .attr('width', d => d.dx )
                    .attr('height', d => d.dy )
                    .attr('fill', d => d.children ? null : color(d.parent.name) )
                    .attr('stroke', '#ffffff' );

                cell.append('text')
                    .attr('x', d => d.x + d.dx/2 )
                    .attr('y', d => d.y + d.dy/2 )
                    .attr('text-anchor', 'midlde')
                    .text(d => d.children ? null : d.name);

        })
Пример #2
0
  render() {
    var el = RFD.createElement('g');
    var sel = d3.select(el);

    sel.attr('transform', generateTranslateString(this.margins.left, this.margins.top));

    var treemap = d3.layout.treemap()
      .value(this.props.valueFn)
      .size([this.widthSpan, this.heightSpan])
      .sort(this.props.dataSort);

    // extend copies the array first
    var data = this.props.dataProcessor(this.props.data);

    var nodes = sel.datum(data).selectAll('.node')
      .data(treemap.nodes);
    var nodeEnter = nodes.enter().append('g')
      .classed('node', true)
      .on('mouseenter', this.props.enterFn)
      .on('mouseleave', this.props.leaveFn)
      .on('touchstart', this.props.enterFn)
      .attr({
        transform : d => generateTranslateString(d.x, d.y)
      });

    var self = this;
    nodeEnter.each(function(d) {
      var sel = d3.select(this);
      sel.append('rect')
        .attr({
          fill : self.props.colourScale,
          width : d => Math.max(0, d.dx - self.props.spacing),
          height : d => Math.max(0, d.dy - self.props.spacing)
        });
      if(d.applicants && d.hideText !== true && d.dx > 50 && d.dy > 30) {
        var txt = sel.append('text')
          .classed('node-label', true)
          .attr({
            'font-size' : 14,
            x : d.dx / 2,
            y : d.dy / 2 - 3,
            'text-anchor' : 'middle'
          });
        txt.append('tspan')
          .classed('node-country-name', true)
          .text(d.countryName);
        txt.append('tspan')
          .classed('node-country-value', true)
          .text(self.props.valueFormat(d.applicants))
          .attr({
            x : d.dx / 2, dy: 16
          });
        }
    });

    return el.toReact();
  }
Пример #3
0
  constructor(props) {
    super(props);

    this.treemap = d3.layout.treemap()
      .children(d => d.children)
      .value(d => d.size)
      .size([WIDTH, HEIGHT]);

    this.state = { prev: {} };
  }
Пример #4
0
    render: function() {
        this.width = this.model.get("width");
        this.height = this.model.get("height");
        this.margin = this.model.get('margin');

        this.el.style["width"] = this.width + this.margin.left + this.margin.right;
        this.el.style["height"] = this.height + this.margin.top + this.margin.bottom;

        var sector_data = this.model.get('data');
        this.colors = this.model.get('colors');
        this.mode = this.model.get('mode');

        var color= d3.scale.category10();
        var that = this;
        this.d3el.append("div")
            .style("position", "relative")
            .style("width", (this.width + this.margin.left + this.margin.right) + "px")
            .style("height", (this.height + this.margin.top + this.margin.bottom) + "px")
            .style("left", this.margin.left + "px")
            .style("top", this.margin.top + "px");

        this.margin = this.model.get("margin");

        this.tree_map = d3.layout.treemap()
            .size([this.width, this.height])
            .sticky(true)
            .padding(null)
            .mode(this.mode)
            .value(function(d) {return d.size;});

        var element = this.d3el.datum(sector_data).selectAll(".node")
            .data(this.tree_map.nodes)
            .enter().append("div")
            .attr("class", "node")
            .call(this.position)
            .style({
                "background": function(d, i) {
                    return d.children ? color(d.name): null;
                },
                "border": "solid white"
            })
            .text(function(d) { return d.children ? null : d.name; })
            .style({
                'font': '11px sans-serif',
                'position': 'absolute',
                'text-align': 'center',
                'overflow': 'hidden',
                'color': 'white',
            });
    },
Пример #5
0
  /**
   * Create the list of nodes to render.
   * @returns {Array} Array of nodes.
   * @private
   */
  _getNodesToRender() {
    const data = this.props.data;
    const height = this.props.height;
    const width = this.props.width;
    const mode = this.props.mode;
    const padding = this.props.padding;
    let nodes = [];
    let layout;
    if (data) {
      layout = d3.layout.treemap()
        .padding(padding)
        .mode(mode)
        .sort((a, b) => a.size - b.size);
      nodes = layout
        .size([width, height])
        .value(d => d.size)
        .sticky(true)
        .nodes(data);
    }

    return nodes;
  }
Пример #6
0
  render:function() {

    var props = this.props;
    
    var data = props.data;
    var value = props.value;
    var label = props.label;

    var colors = d3.scale.category20c();

    var treemap = d3.layout.treemap()
                    // make sure calculation loop through all objects inside array 
                    .children(function(d) {return d;})
                    .size([props.width, props.height])
                    .sticky(true)
                    .value(function(d) { return d[value]; });
    
    var cells = treemap(data).map(function(node, i)  {
      return (
        React.createElement(Cell, {
          x: node.x, 
          y: node.y, 
          width: node.dx, 
          height: node.dy, 
          fill: colors(i), 
          label: node[label], 
          fontSize: props.fontSize, 
          textColor: props.textColor, 
          key: i}
        ) 
      ); 
    }, this);

    return (
      React.createElement("g", {transform: props.transform, className: "treemap"}, 
        cells
      )
    );
  }
Пример #7
0
  render:function() {
    console.log('props in data series: ', this.props );
    var props = this.props;

    var treemap = d3.layout.treemap()
                    // make sure calculation loop through all objects inside array
                    .children( function(d)  {return d;})
                    .size([props.width, props.height])
                    .sticky(true)
                    .value( function(d)  { console.log('this is d.value: ', d.value); return d.value; });

    var tree = treemap(props.data);

    var cells = tree.map( function(node, idx)  {
      console.log('this is node.label: ', node.label)
      return (
        React.createElement(CellContainer, {
          key: idx,
          x: node.x,
          y: node.y,
          width: node.dx,
          height: node.dy,
          fill: props.colors(props.colorAccessor(node, idx)),
          label: node.label,
          fontSize: props.fontSize,
          textColor: props.textColor,
          hoverAnimation: props.hoverAnimation,
          value: node.value}
        )
      );
    }, this);

    return (
      React.createElement("g", {transform: props.transform, className: "treemap"},
        cells
      )
    );
  }
Пример #8
0
var React = require('react')

var TreeMap = React.createClass({
  sel() { return d3.select(this.getDOMNode()) },
  getDefaultProps() {
    return {
      valueAccessor: d => d.value,
      colorAccessor: d => d.color,
      width: 400,
      height: 400,
      maxArea: 1000,
    }
  },
  getInitialState() {
    return {
      treemapLayout: d3.layout.treemap().sort(null)
    }
  },
  render() {
    var {props, state} = this
    var {data, width, height, style} = props
    var backgroundColor = 'rgba(0, 0, 0, 0.1)'
    
    style = Object.assign({backgroundColor}, style || {})
    props = Object.assign({}, props, {style: undefined, data: undefined})

    var wrappedData = data.map(d => {value: props.valueAccessor(d), d})
    
    var nodes = state.treemapLayout
      .size([height, width])
      .nodes({children: wrappedData})
Пример #9
0
  build(endpoint, cube, params, wrapper, colorScale) {
    params = _.cloneDeep(params);
    var that = this;

    if (colorScale === undefined) {
      colorScale = Utils.defaultColorScale();
    }

    this.wrapper = wrapper;
    var size = {
      width: this.wrapper.clientWidth,
      height: this.wrapper.clientWidth * 0.6
    };

    that.emit('loading', that);

    that.treemap = d3.layout.treemap()
      .size([size.width, size.height])
      .sticky(true)
      .sort(function(a, b) {
        return a.value - b.value;
      })
      .value(function(d) {
        return d.value;
      });

    d3.select(wrapper).select('div').remove();
    var div = d3.select(wrapper).append('div')
      .style('position', 'relative')
      .style('width', size.width + 'px')
      .style('height', size.height + 'px');


    var api = this.getApiInstance();
    api.aggregate(endpoint, cube, params)
      .then((data) => {
        var valueFormat = that.getValueFormatter();
        const ratioFormat = d3.format('.1%');

        var root = {};
        root.children = [];
        root.summary = data.summary[params.aggregates];
        root.currency = data.currency[params.aggregates];
        root.summaryFmt = valueFormat(data.summary[params.aggregates]);
        root.summaryFmtCurrency = Utils.moneyFormat(root.summaryFmt,
          root.currency);

        _.each(data.cells, (item, index) => {
          var dimension = _.first(item.dimensions);
          var measure = _.find(item.measures, {key: params.aggregates});
          var cell = {};
          cell.areaFmt = valueFormat(measure.value);
          cell.areaFmtCurrency = Utils.moneyFormat(cell.areaFmt, root.currency);
          cell.value = measure.value;
          cell.key = dimension.keyValue;
          cell.name = dimension.nameValue;
          cell.color = colorScale(index);

          cell.percentage = (measure.value && data.summary && params.aggregates)
            ? (measure.value / Math.max(data.summary[params.aggregates], 1))
            : 0;
          root.children.push(cell);
        });

        var node = div.datum(root).selectAll('.node')
          .data(that.treemap.nodes)
          .enter().append('a')
          .attr('href', function(d) {
            return d.href;
          })
          .attr('class', 'node')
          .attr('title', (d) => `${d.name}\n${d.areaFmtCurrency} (${ratioFormat(d.percentage)})`)
          .call(positionNode)
          .style('background', '#fff')
          .html(function(d) {
            if (d.percentage < 0.02) {
              return '';
            }
            return d.children ? null : `<span class=\'amount\'>${d.areaFmtCurrency}</span>${d.name}`;
          })
          .on('click', (d) => {
            that.emit('click', that, d);
          })
          .on('mouseover', function(d) {
            d3.select(this).transition().duration(200)
              .style({'background': d3.rgb(d.color).darker() });
          })
          .on('mouseout', function(d) {
            d3.select(this).transition().duration(500)
              .style({'background': d.color});
          })
          .transition()
          .duration(500)
          .delay(function(d, i) { return Math.min(i * 30, 1500); })
          .style('background', function(d) { return d.color; });

        // Check & Remove all rectangles with text overflow:
        var boxContentRemover = (item => $(item).empty());
        var hasTextOverflow = TreemapUtils.checkForTextOverflow('a.node', boxContentRemover);
        if (hasTextOverflow) {
          that.emit('textOverflow', that);
        }

        that.emit('loaded', that, data, root);
        that.emit('ready', that, data, null);
      })
      .catch((error) => {
        that.emit('error', that, error);
        that.emit('ready', that, null, error);
      });
  }
Пример #10
0
    function makeTreeMap() {
        var width = $('#taxon-treemap').width();
        var height = $('#taxon-treemap').height();

        var color = d3.scale.category20c();

        var treemap = d3.layout.treemap()
                .size([width, height])
                .sort(function(a, b) { return b.id - a.id; })
                .value(function(d) { return d.count; });

        var div = d3.select("#taxon-treemap").append("div")
                .attr("class", "treemap")
                .style("position", "relative")
                .style("width", width + "px")
                .style("height", height + "px");

        var genusTreeDefItem = new schema.models.TaxonTreeDefItem.LazyCollection({
            filters: {name: "Genus"} });

        var getGenusRankID = genusTreeDefItem.fetch({limit: 1}).pipe(function() {
            return genusTreeDefItem.length > 0 ? genusTreeDefItem.at(0).get('rankid') : null;
        });

        var getTreeData = $.getJSON('/barvis/taxon_bar/');

        $.when(getTreeData, getGenusRankID).done(function buildFromData(data, genusRankID) {
            var tree = buildTree(data[0]);
            var root = tree[0];
            var thres = tree[1];
            var makeName;

            if (_.isNull(genusRankID)) {
                makeName = function(d) {
                    return (function recur(d) {
                        return d.parent ? recur(d.parent) + ' ' + d.name : "";
                    })(d.parent) + " " + d.count;
                };
            } else {
                makeName = function(d) {
                    var name = (d.rankId <= genusRankID) ? d.name :
                            (function recur(d) {
                                return (d.parent && d.rankId >= genusRankID) ? recur(d.parent) + ' ' + d.name : "";
                            })(d.parent);

                    name === "" && console.error("empty name for", d, "with rankId", d.rankId);
                    return name + " " + d.count;
                };
            }

            var node = div.selectAll(".node")
                    .data(treemap.nodes(root).filter(function(d) { return !d.children; }))
                    .enter()
                    .append("div")
                    .attr("class", "node")
                    .call(position)
                    .attr("title", makeName)
                    .style("background", function(d) { return d.children ? null : color(d.name); });

            _.defer(function addToolTips() {
                $('.treemap .node').tooltip({track: true, show: false, hide: false});
            });

            $('<p>', { title: "Showing Taxa with " + thres + " or more Collection Objects" })
                .text("Taxon Tiles")
                .appendTo(div[0])
                .tooltip({track: true, show: false, hide: false});
        });
    }
Пример #11
0
        selection.each(function(data) {
            /*
               var chart = d3.select(element)
               .attr('left', 0 + 'px')
               .attr('top', 0 + 'px')
               .attr('width', width + 'px')
               .attr('height', height + 'px')
               .style('position', 'absolute')
               .append('svg:svg')
               .style('width', width + margin.right + margin.left)
               .style('height', height + margin.top + margin.bottom)
               .attr('class', 'chartx')
               .attr('pointer-events', 'none')
               .style('position', 'absolute');
               */

            var zoomG = selection.append('g')
            .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
            .attr('class', 'main')

            zoomG.append('svg:rect')
            .attr('width', width*2)
            .attr('height', height)
            .classed('zoom-rect', true)

            var rootG = zoomG.append('g').attr('id', 'root-g');

            function zoom() {
                var t = d3.event.translate,
                s = d3.event.scale;

                rootG.attr("transform", "translate(" + t + ")scale(" + s + ")");
            }

            var zoomer = d3.behavior.zoom()
            .scaleExtent([0.3,2])
            .on("zoom", zoom);

            zoomG.call(zoomer)

            d3.select('body')
            .on('keydown', function() {
                if (d3.event.keyCode === 67) { //c key
                    zoomer.translate([0,0]);
                    zoomer.scale(1);

                    rootG.attr('transform', 'translate(0,0)scale(1)');
                }
            });

            var gUnder = rootG.append('g');
            var gMiddle = rootG.append('g').attr('pointer-events', 'all').attr('transform', 'translate(' + width + ',0)').attr('id', 'middle-layer');
            var gMain = rootG.append('g').attr('pointer-events', 'all');

            function highlightNucleotide(num1, prefix) {
                gMiddle.selectAll('[nuc_num="' + num1 + '"]')
                .classed('selected', true);

                gMain.selectAll('[' + prefix + 'text-nuc-num="' + num1 + '"]')
                .classed('visible', true)

                gUnder.selectAll('[' + prefix + 'guide-num="' + num1 + '"]')
                .classed('guide-selected', true)
            }

            function unHighlight() {
                gMiddle.selectAll('.rna-base')
                .classed('selected', false);

                var gAll = gMain.selectAll();

                gMain.selectAll('.text-highlight-rect')
                .classed('visible', false);

                gUnder.selectAll('.guide-line')
                .classed('guide-selected', false);
            }


            function ensembleRectangleMouseOver(d) {
                var xx = d3.select(this);
                xx.style('stroke', '#444')
                .style('stroke-width', 4);

                var selectText = '#text-' + d.i + '-' + d.j;
                gMain.selectAll(selectText).classed('visible', true)

                //highlightPair(d.i, d.j);
                highlightNucleotide(d.i, 'right-');
                highlightNucleotide(d.j, 'top-');

            }

            function mfeRectangleMouseOver(d) {
                var xx = d3.select(this);
                xx.style('stroke', '#444')
                .style('stroke-width', 4);

                //highlightPair(d.i, d.j);
                highlightNucleotide(d.j, 'left-');
                highlightNucleotide(d.i, 'bottom-');

            }

            function rectangleMouseOut(d) {
                var xx = d3.select(this);
                xx.style('stroke', '#444')
                .style('stroke-width', 0);

                var selectText = '#text-' + d.i + '-' + d.j;
                gMain.selectAll(selectText).classed('visible', false)

                //unHighlightPair(d.i, d.j);
                unHighlight();

            }

            data.bps.forEach(function(d) {
                d.i = +d.i;
                d.j = +d.j;
                d.p = +d.p;
            });

            self.data = data;

            var iSet = d3.set(data.bps.map(function(d) { return +d.i; })).values();
            var jSet = d3.set(data.bps.map(function(d) { return +d.j; })).values();

            var structIxs = data.structs.map(function(d) { return d.ix; });

            var color = d3.scale.category10().domain(structIxs);

            var structLength = data.structs[0].struct.length;
            var sequenceNumbers = Array.apply(0, Array(structLength)).map(function(x,y) { return y+1; });

            var xScale = d3.scale.ordinal()
            .domain([' '].concat(sequenceNumbers).concat([' ']) )
            .rangeRoundBands([ 0, innerWidth ]);

            var yScale = d3.scale.ordinal()
            .domain([' '].concat(sequenceNumbers).concat([' ']))
            .rangeRoundBands([ 0, innerHeight ]);

            var r = d3.scale.linear()
            //.domain([1, d3.max(data.bps.map(function(d) { return d.p; }))])
            //.domain(d3.extent(data.bps.map(function(d) { return d.p; })))
            .domain([0, 1])
            .range([0, xScale.rangeBand()]);

            gMain.selectAll(".topXLabel")
            .data(jSet)
            .enter()
            .append("text")
            .classed('sequence-text', true)
            .attr('transform', function(d) { return 'translate(' + (xScale(d) + xScale.rangeBand() - 2) + ',0)rotate(-90)';})
            .text(function(d) { return d; });

            gMain.selectAll(".rightYLabel")
            .data(iSet)
            .enter()
            .append("text")
            .classed('sequence-text', true)
            .attr('transform', function(d) { return 'translate(' + innerWidth + "," + (yScale(d) + yScale.rangeBand() - 2) + ')';})
            .text(function(d) { return d; });


            gUnder.selectAll(".x-guide-line")
            .data(data.bps)
            .enter().append("svg:line")
            .attr("x1", function(d) { return xScale(d.j) + xScale.rangeBand() / 2; })
            .attr("y1", 0)
            .attr("x2", function(d) { return xScale(d.j) + xScale.rangeBand() / 2; })
            .attr("y2", function(d) { return yScale(d.i) + yScale.rangeBand() / 2; })
            .attr('nucPair', function(d) { return d.i + '-' + d.j; })
            .attr('top-guide-num', function(d) { return d.j; })
            .classed('x-guide-line', true)
            .classed('guide-line', true);

            gUnder.selectAll(".y-guide-line")
            .data(data.bps)
            .enter().append("svg:line")
            .attr("x1", innerWidth)
            .attr("y1", function(d) { return yScale(d.i) + yScale.rangeBand() / 2; })
            .attr("x2", function(d) { return xScale(d.j) + xScale.rangeBand() / 2; })
            .attr("y2", function(d) { return yScale(d.i) + yScale.rangeBand() / 2; })
            .attr('nucPair', function(d) { return d.i + "-" + d.j; })
            .attr('right-guide-num', function(d) { return d.i; })
            .classed('y-guide-line', true)
            .classed('guide-line', true);

            gMain.selectAll("scatter-dots")
            .data(data.bps)
            .enter().append("svg:rect")
            .attr("x", function (d,i) { return xScale(d.j) + (xScale.rangeBand() - r(d.p)) / 2; } )
            .attr("y", function (d) { return yScale(d.i) + (yScale.rangeBand() - r(d.p)) / 2; } )
            .attr("width", function(d) { return r(d.p); } )
            .attr("height", function(d) { return r(d.p); } )
            .attr('fill', function(d) { return color(d.ix); })
            .attr('pointer-events', 'all')
            .on('mouseover', ensembleRectangleMouseOver)
            .on('mouseout', rectangleMouseOut);

            gMain.selectAll(".scatter-dots-text")
            .data(data.bps)
            .enter().append('text')
            .attr('x', function(d,i) { return xScale(d.j) + (xScale.rangeBand() - r(d.p)) / 2 - 5; } )
            .attr("y", function (d) { return yScale(d.i) + (yScale.rangeBand() + r(d.p)) / 2; } )
            .text(function(d) { return "(" + d.i + "," + d.j + "): " + d.p; })
            .attr('id', function(d) { return 'text-' + d.i + "-" + d.j; })
            .classed('scatter-dots-text', true);

            var mfeBps = data.bps.filter(function(d) { return d.ix === 0; });


            gMain.selectAll(".bottomXLabelMfe")
            .data(mfeBps)
            .enter()
            .append("text")
            .classed('sequence-text', true)
            .attr('transform', function(d) { return 'translate(' + (xScale(d.i) + xScale.rangeBand() - 2) + ',' + innerHeight + ')rotate(-90)';})
            .attr('text-anchor', 'end')
            .text(function(d) { return d.i; });

            gMain.selectAll(".leftYLabelMfe")
            .data(mfeBps)
            .enter()
            .append("text")
            .classed('sequence-text', true)
            .attr('transform', function(d) { return 'translate(0, ' + (yScale(d.j) + yScale.rangeBand() - 2) + ')';})
            .attr('text-anchor', 'end')
            .text(function(d) { return d.j; });

            gUnder.selectAll(".x-guide-lineMfe")
            .data(mfeBps)
            .enter().append("svg:line")
            .attr("x1", function(d) { return xScale(d.i) + xScale.rangeBand() / 2; })
            .attr("y1", innerHeight)
            .attr("x2", function(d) { return xScale(d.i) + xScale.rangeBand() / 2; })
            .attr("y2", function(d) { return yScale(d.j) + yScale.rangeBand() / 2; })
            .attr('left-guide-num', function(d) { return d.j; })
            .classed('x-guide-lineMfe', true)
            .classed('guide-line', true);

            gUnder.selectAll(".y-guide-lineMfe")
            .data(mfeBps)
            .enter().append("svg:line")
            .attr("x1", 0)
            .attr("y1", function(d) { return yScale(d.j) + yScale.rangeBand() / 2; })
            .attr("x2", function(d) { return xScale(d.i) + xScale.rangeBand() / 2; })
            .attr("y2", function(d) { return yScale(d.j) + yScale.rangeBand() / 2; })
            .attr('bottom-guide-num', function(d) { return d.i; })
            .classed('y-guide-lineMfe', true)
            .classed('guide-line', true);

            gMain.selectAll("scatter-dots-mfe")
            .data(mfeBps)
            .enter().append("svg:rect")
            .attr("x", function (d,i) { return xScale(d.i) + (xScale.rangeBand() - r(d.p)) / 2; } )
            .attr("y", function (d) { return yScale(d.j) + (yScale.rangeBand() - r(d.p)) / 2; } )
            .attr("width", function(d) { return r(d.p); } )
            .attr("height", function(d) { return r(d.p); } )
            .attr('fill', function(d) { return color(d.ix); })
            .attr('pointer-events', 'all')
            .on('mouseover', mfeRectangleMouseOver)
            .on('mouseout', rectangleMouseOut);

            var seq = data.seq.split('').map(function(d, i) { return {"s": d, "i": i+1}; });

            /////////////////////////////////////////////////////////////

            var bpColors = d3.scale.linear().domain([0,1]).range(['white', '#888']);

            gMain.selectAll('.topProbs')
            .data(data.baseProbs)
            .enter()
            .append('svg:rect')
            .classed('topProbs', true)
            .attr('x', function(d) { return xScale(d[0]); })
            .attr('y', function(d) { return 0; })
            .attr('width', xScale.rangeBand())
            .attr('height', yScale.rangeBand())
            .attr('fill', function(d) { return bpColors(d[1]); });

            gMain.selectAll('.leftProbs')
            .data(data.baseProbs)
            .enter()
            .append('svg:rect')
            .classed('topProbs', true)
            .attr('x', function(d) { return 0; })
            .attr('y', function(d) { return yScale(d[0]); })
            .attr('width', xScale.rangeBand())
            .attr('height', yScale.rangeBand())
            .attr('fill', function(d) { return bpColors(d[1]); });

            var highlightSeq = function(d, node, prefix ) {
                var svgRect = node.getBBox();
                var parentNode = d3.select(node.parentNode);

                parentNode.append('rect')
                .attr('x', svgRect.x-2)
                .attr('y', svgRect.y)
                .attr('height', svgRect.height)
                .attr('width', svgRect.width + 2)
                .attr(prefix + 'text-nuc-num', d.i) // enable highlighting of nucleotide numbers
                .classed('text-highlight-rect', true);

            }

            gMain.selectAll('.topSeq')
            .data(seq)
            .enter()
            .append('text')
            .attr('x', function(d) {
                return xScale(d.i);
            })
            .attr('y', -20)
            .classed('sequence-text', true)
            .text(function(d) { return d.s; })
            .each(function(d) { highlightSeq(d, this, 'top-'); });

            gMain.selectAll('.bottomSeq')
            .data(seq)
            .enter()
            .append('text')
            .classed('sequence-text', true)
            .attr('x', function(d) {
                return xScale(d.i);
            })
            .attr('y', innerHeight + 25)
            .text(function(d) { return d.s; })
            .each(function(d) { highlightSeq(d, this, 'bottom-'); });

            gMain.selectAll('.leftSeq')
            .data(seq)
            .enter()
            .append('text')
            .classed('sequence-text', true)
            .attr('x', -25)
            .attr('y', function(d) { return yScale(d.i) + 8; })
            .text(function(d) { return d.s; })
            .each(function(d) { highlightSeq(d, this, 'left-'); });

            gMain.selectAll('.rightSeq')
            .data(seq)
            .enter()
            .append('text')
            .classed('sequence-text', true)
            .attr('x', innerWidth + 18)
            .attr('y', function(d) { return yScale(d.i) + 8; })
            .text(function(d) { return d.s; })
            .each(function(d) { highlightSeq(d, this, 'right-'); });

            ////////////////////////////////////////////////////////////
            var root = {"name": "graph",
                "children": data.structs.map(function(d) {
                    return {"name": d.ix,
                        "structure": d.struct,
                        "sequence": self.data.seq,
                        "size": +d.sprob * 100 };
                })
            };

            gUnder.append('svg:line')
            .attr('x1', 0)
            .attr('y1', 0)
            .attr('x2', innerWidth)
            .attr('y2', innerHeight)
            .classed('diagonal-line', true);


            function divName(d) {
                return "subopt" + d.name;
            }


            var highlightCircle = gMain.append('circle');
            var highlightCircleMfe = gMain.append('circle');

            highlightCircle.attr('r', xScale.rangeBand())
            .classed('highlight-circle', true)

            highlightCircleMfe.attr('r', xScale.rangeBand())
            .classed('highlight-circle', true)

            function nucleotideMouseOver(d) {
                var pairingPartner = d.rna.pairtable[d.num];
                highlightNucleotide(d.num);

                if (pairingPartner === 0)
                    return;

                var points  = [d.num, pairingPartner];
                points.sort(function(a,b) { return +a - +b;} );

                var selectText = '#text-' + points[0] + '-' + points[1];
                gMain.selectAll(selectText).classed('visible', true)

                highlightCircle
                .attr('cx', xScale(points[1]) + xScale.rangeBand() / 2)
                .attr('cy', yScale(points[0]) + yScale.rangeBand() / 2)
                .style('opacity', 0.3);

                //highlightPair(points[0], points[1]);
                highlightNucleotide(points[0], 'right-');
                highlightNucleotide(points[1], 'top-');

                if (d.structName == '0') {
                    // base pair is in the MFE structure
                    highlightNucleotide(points[1], 'left-');
                    highlightNucleotide(points[0], 'bottom-');

                    highlightCircleMfe
                    .attr('cx', xScale(points[0]) + xScale.rangeBand() / 2)
                    .attr('cy', yScale(points[1]) + yScale.rangeBand() / 2)
                    .style('opacity', 0.3);

                }

            }

            function nucleotideMouseOut(d) {
                highlightCircle.style('opacity', 0);
                highlightCircleMfe.style('opacity', 0);

                unHighlight();

                var selectText = '.scatter-dots-text';
                gMain.selectAll(selectText).classed('visible', false)
            }

            console.log('root:', root);

                var treemap = d3.layout.treemap()
                .size([innerWidth, innerHeight])
                .sticky(false)
                .value(function(d) { return d.size; });

                function positionTreemapRect() {
                    this.attr("width", function(d) { return Math.max(0, d.dx); })
                    .attr("height", function(d) { return Math.max(0, d.dy); });
                }

                console.log('root', root);

                var treemapGnodes = gMiddle.datum(root).selectAll(".treemapNode")
                .data(treemap.nodes)
                .enter()
                .append('g')
                .attr('class', 'treemapNode')
                .attr('id', divName)
                .each(function(d) {
                    // create a background rectangle for each RNA structure
                    d3.select(this).attr('transform', function(d) { return 'translate(' + d.x + "," + d.y + ')' })
                    .append('rect')
                    //.attr('fill', function(d) { return color(d.name); })
                    .classed('structure-background-rect', true)
                    .call(positionTreemapRect)

                    var chart = rnaPlot();
                    chart.width( Math.max(0, d.dx))
                    .height( Math.max(0, d.dy))
                    .labelInterval(0)
                    .rnaEdgePadding(10)
                    .showNucleotideLabels(false);

                    if ('structure' in d) {
                        //let's draw an RNA!

                        d3.select(this)
                        .call(chart)
                        .classed('rnaStruct', true)
                        .attr('struct_id', function(n) { return "struct"+n.name; })
                        .selectAll('.rna-base')
                        .attr('nuc_num', function(n) { return n.num; })
                        .on('mouseover', nucleotideMouseOver)
                        .on('mouseout', nucleotideMouseOut);

                    }
                });

                data.bps.forEach(function(d) {
                    var rnaStruct = gMiddle.selectAll('[struct_id=struct' + d.ix + ']')

                    rnaStruct.selectAll('[nuc_num="' + d.i + '"],[nuc_num="' + d.j + '"]')
                    .classed('from-this-structure', true)
                    .style('fill', color(d.ix))

                    var containers = gMiddle.selectAll(".rnaStruct")
                    .each(function(c) {
                        if (c.rnaGraph.pairtable[d.i] === d.j) {
                            //this base is paired in this structure
                            d3.select(this).selectAll('[nuc_num="' + d.i + '"],[nuc_num="' + d.j + '"]')
                            .style('fill', color(d.ix))

                        }
                    });

                });
        });
Пример #12
0
    buildTree() {
        var margin = {top: 20, right: 0, bottom: 0, left: 0},
            width = 960,
            height = 500 - margin.top - margin.bottom,
            formatNumber = d3.format(",d"),
            transitioning;

        var x = d3.scale.linear()
            .domain([0, width])
            .range([0, width]);

        var y = d3.scale.linear()
            .domain([0, height])
            .range([0, height]);

        var treemap = d3.layout.treemap()
            .children(function (d, depth) {
                return depth ? null : d._children;
            })
            .sort(function (a, b) {
                return a.value - b.value;
            })
            .ratio(height / width * 0.5 * (1 + Math.sqrt(5)))
            .round(false);

        var svg = d3.select(".d3-container").append("svg")
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.bottom + margin.top)
            .style("margin-left", -margin.left + "px")
            .style("margin.right", -margin.right + "px")
            .append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
            .style("shape-rendering", "crispEdges");

        var grandparent = svg.append("g")
            .attr("class", "grandparent");

        grandparent.append("rect")
            .attr("y", -margin.top)
            .attr("width", width)
            .attr("height", margin.top);

        grandparent.append("text")
            .attr("x", 6)
            .attr("y", 6 - margin.top)
            .attr("dy", ".75em");

        d3.json("/api/photos/tree/map", function (root) {
            initialize(root);
            accumulate(root);
            layout(root);
            display(root);

            function initialize(root) {
                root.x = root.y = 0;
                root.dx = width;
                root.dy = height;
                root.depth = 0;
            }

            // Aggregate the values for internal nodes. This is normally done by the
            // treemap layout, but not here because of our custom implementation.
            // We also take a snapshot of the original children (_children) to avoid
            // the children being overwritten when when layout is computed.
            function accumulate(d) {
                return (d._children = d.children)
                    ? d.value = d.children.reduce(function (p, v) {
                    return p + accumulate(v);
                }, 0)
                    : d.value;
            }

            // Compute the treemap layout recursively such that each group of siblings
            // uses the same size (1×1) rather than the dimensions of the parent cell.
            // This optimizes the layout for the current zoom state. Note that a wrapper
            // object is created for the parent node for each group of siblings so that
            // the parent’s dimensions are not discarded as we recurse. Since each group
            // of sibling was laid out in 1×1, we must rescale to fit using absolute
            // coordinates. This lets us use a viewport to zoom.
            function layout(d) {
                if (d._children) {
                    treemap.nodes({_children: d._children});
                    d._children.forEach(function (c) {
                        c.x = d.x + c.x * d.dx;
                        c.y = d.y + c.y * d.dy;
                        c.dx *= d.dx;
                        c.dy *= d.dy;
                        c.parent = d;
                        layout(c);
                    });
                }
            }

            function display(d) {
                grandparent
                    .datum(d.parent)
                    .on("click", transition)
                    .select("text")
                    .text(name(d));

                var g1 = svg.insert("g", ".grandparent")
                    .datum(d)
                    .attr("class", "depth");

                var g = g1.selectAll("g")
                    .data(d._children)
                    .enter().append("g");

                g.filter(function (d) {
                        return d._children;
                    })
                    .classed("children", true)
                    .on("click", transition);

                var children = g.selectAll(".child")
                    .data(function (d) {
                        return d._children || [d];
                    })
                    .enter();

                children.append("rect")
                    .attr("class", "child")
                    .call(rect);

                children.append("svg:image")
                    .attr("xlink:href", d => d.image )
                    .attr("class", "child-image")
                    .call(rect);

                g.append("rect")
                    .attr("class", "parent")
                    .call(rect)
                    .append("title")
                    .text(function (d) {
                        return formatNumber(d.value);
                    });

                g.append("svg:image")
                    .attr("xlink:href", d => d.image )
                    .attr("class", "parent-image")
                    .call(rect);

                g.append("text")
                    .attr("dy", ".75em")
                    .text(function (d) {
                        return d.name;
                    })
                    .call(text);

                function transition(d) {
                    if (transitioning || !d) return;
                    transitioning = true;

                    var g2 = display(d),
                        t1 = g1.transition().duration(750),
                        t2 = g2.transition().duration(750);

                    // Update the domain only after entering new elements.
                    x.domain([d.x, d.x + d.dx]);
                    y.domain([d.y, d.y + d.dy]);

                    // Enable anti-aliasing during the transition.
                    svg.style("shape-rendering", null);

                    // Draw child nodes on top of parent nodes.
                    svg.selectAll(".depth").sort(function (a, b) {
                        return a.depth - b.depth;
                    });

                    // Fade-in entering text.
                    g2.selectAll("text").style("fill-opacity", 0);

                    // Transition to the new view.
                    t1.selectAll("text").call(text).style("fill-opacity", 0);
                    t1.selectAll("rect").call(rect).style("stroke-opacity", 0);
                    t1.selectAll(".parent-image").call(rect).style("opacity", 0);
                    t1.selectAll(".child-image").call(rect).style("opacity", 0);

                    t2.selectAll("text").call(text).style("fill-opacity", 1);
                    t2.selectAll("rect").call(rect).style("stroke-opacity", 0.5);
                    t2.selectAll(".parent-image").call(rect).style("opacity", 1);
                    t2.selectAll(".child-image").call(rect).style("opacity", 1);

                    // Remove the old node when the transition is finished.
                    t1.remove().each("end", function () {
                        svg.style("shape-rendering", "crispEdges");
                        transitioning = false;
                    });
                }

                return g;
            }

            function text(text) {
                text.attr("x", function (d) {
                        return x(d.x) + 6;
                    })
                    .attr("y", function (d) {
                        return y(d.y) + 6;
                    });
            }

            function rect(rect) {
                rect.attr("x", function (d) {
                        return x(d.x);
                    })
                    .attr("y", function (d) {
                        return y(d.y);
                    })
                    .attr("width", function (d) {
                        return x(d.x + d.dx) - x(d.x);
                    })
                    .attr("height", function (d) {
                        return y(d.y + d.dy) - y(d.y);
                    });
            }

            function name(d) {
                return d.parent
                    ? name(d.parent) + "." + d.name
                    : d.name;
            }
        });
    }
Пример #13
0
    initialize: function(options) {

      var self = this;

      self.width = options.width;
      self.height = options.height;
      self.cols = options.cols || 3;
      self.rows = options.rows || 2;

      self.base.classed('treemap', true);

      // starting treemap breakdown, by version.
      self._breakdown = null;

      self.treemapLayout = d3.layout.treemap()
        .padding(3)
        .size([self.width, self.height])
        .mode('slice')
        .value(function(d) { return d.value; })
        .sort(function(d, d2) {
          return d2.idx - d.idx;
        });

      self.bases = {
        legend: self.base.append('g')
          .classed('legend', true)
          .attr('transform', 'translate(3,15)'), // because text.
        rects : self.base.append('g')
          .classed('rects', true)
          .attr('transform', 'translate(0,'+self.height / 2+')')
      };

      self.layer('legend', self.bases.legend, {
        dataBind: function(data) {
          var chart = this.chart();
          return this.selectAll('g.item')
            .data(chart.data.children, function(d) {
              return d.id;
            });
        },

        insert : function() {
          return this.append('g')
            .classed('item', true);
        },

        events: {
          enter: function() {
            var chart = this.chart();
            this.attr('transform', function(d, i) {
              var col = i % chart.cols; // cols
              var row = Math.floor(i / chart.cols); //rows

              return 'translate('+ (col * chart.width/chart.cols) +
                ','+ (row * chart.height / (chart.cols * chart.rows)) +')';
            });

            this.append('rect')
              .attr({
                x: 0,
                y: 0,
                width: 15,
                height: 15,
                fill: function(d) { return d.color; }
              });

            this.append('text')
              .attr({
                x: 20,
                y: 10
              }).text(function(d) {
                return d.name + ' ('+ d.percent +')';
              });
          },

          exit: function() {
            this.remove();
          }
        }
      });

      self.layer('rect', self.bases.rects, {
        dataBind: function(data) {
          var chart = this.chart();
          return this.datum(data).selectAll('g.node')
            .data(chart.treemapLayout.nodes, function(d) {
              return d.id;
            });
        },

        insert: function() {
          return this.append('g')
            .classed('node', true);
        },
        events: {
          enter: function() {

            // move group to correct location
            this.attr('transform', function(d) {
              return 'translate('+d.x+','+d.y+')';
            });

            // append a rect at 0,0 with 0 width and height
            this.append('rect')
              .attr({
                x: 0,
                y: 0,
                width: 0,
                height: 0,
                fill: function(d, i) { return d.color; }
              });
          },

          "merge": function() {
            this.select('rect').transition().attr({
              width: function(d) { return d.dx; },
              height: function(d) { return d.dy; }
            });
          },
          "exit": function() {
            var self = this;
            this.select('rect').transition().attr({
              width: 0,
              height: 0
            }).each("end", function() {
              this.remove();
              self.remove();
            });
          }
        }
      });
    },
Пример #14
0
        return "#ffffff" ;
      }
    };

    const dimensions = this.get('dimensions');
    const treeMapData = this.get('treeMapData');

    if (!dimensions) { return; }

    for (var i = 0; i < dimensions.length; i++) {
      var data = treeMapData[i];
      var dimension = dimensions[i];
      var dimensionPlaceHolderId = '#' + dimension + '-heatmap-placeholder';
      var height = $(dimensionPlaceHolderId).height();
      var width = $(dimensionPlaceHolderId).width();
      var treeMap = d3.layout.treemap().size([ width, height ]).sort(function(a, b) {
        return a.value - b.value;
      });

      var div = d3.select(dimensionPlaceHolderId).attr("class", "heatmap")
        .append("svg:svg").attr("width", width).attr("height", height).append("svg:g").attr("transform", "translate(.5,.5)");

      var nodes = treeMap.nodes(data).filter(function(d) {
        return !d.children;
      });
      var cell = div.selectAll("g").data(nodes).enter().append("svg:g").attr("class", "cell").attr("transform", function(d) {
        return "translate(" + d.x + "," + d.y + ")";
      // }).on("click", function(d) {
        // return zoom(node == d.parent ? root : d.parent);
      }).on("mousemove", function(d) {
Пример #15
0
  const _draw = function (data, eltWidth, eltHeight, formData) {
    const margin = { top: 0, right: 0, bottom: 0, left: 0 };
    const navBarHeight = 36;
    const navBarTitleSize = navBarHeight / 3;
    const navBarBuffer = 10;
    const width = eltWidth - margin.left - margin.right;
    const height = (eltHeight - navBarHeight - navBarBuffer -
                 margin.top - margin.bottom);
    const formatNumber = d3.format(formData.number_format);
    let transitioning;

    const x = d3.scale.linear()
        .domain([0, width])
        .range([0, width]);

    const y = d3.scale.linear()
        .domain([0, height])
        .range([0, height]);

    const treemap = d3.layout.treemap()
        .children(function (d, depth) { return depth ? null : d._children; })
        .sort(function (a, b) { return a.value - b.value; })
        .ratio(formData.treemap_ratio)
        .mode('squarify')
        .round(false);

    const svg = div.append('svg')
        .attr('class', 'treemap')
        .attr('width', eltWidth)
        .attr('height', eltHeight);

    const chartContainer = svg.append('g')
        .attr('transform', 'translate(' + margin.left + ',' +
                           (margin.top + navBarHeight + navBarBuffer) + ')')
        .style('shape-rendering', 'crispEdges');

    const grandparent = svg.append('g')
        .attr('class', 'grandparent')
        .attr('transform', 'translate(0,' + (margin.top + (navBarBuffer / 2)) + ')');

    grandparent.append('rect')
        .attr('width', width)
        .attr('height', navBarHeight);

    grandparent.append('text')
        .attr('x', width / 2)
        .attr('y', (navBarHeight / 2) + (navBarTitleSize / 2))
        .style('font-size', navBarTitleSize + 'px')
        .style('text-anchor', 'middle');

    const initialize = function (root) {
      root.x = 0;
      root.y = 0;
      root.dx = width;
      root.dy = height;
      root.depth = 0;
    };

    // Aggregate the values for internal nodes. This is normally done by the
    // treemap layout, but not here because of our custom implementation.
    // We also take a snapshot of the original children (_children) to avoid
    // the children being overwritten when when layout is computed.
    const accumulate = function (d) {
      d._children = d.children;
      if (d._children) {
        d.value = d.children.reduce(function (p, v) { return p + accumulate(v); }, 0);
      }
      return d.value;
    };

    // Compute the treemap layout recursively such that each group of siblings
    // uses the same size (1x1) rather than the dimensions of the parent cell.
    // This optimizes the layout for the current zoom state. Note that a wrapper
    // object is created for the parent node for each group of siblings so that
    // the parents dimensions are not discarded as we recurse. Since each group
    // of sibling was laid out in 1x1, we must rescale to fit using absolute
    // coordinates. This lets us use a viewport to zoom.
    const layout = function (d) {
      if (d._children) {
        treemap.nodes({ _children: d._children });
        d._children.forEach(function (c) {
          c.x = d.x + (c.x * d.dx);
          c.y = d.y + (c.y * d.dy);
          c.dx *= d.dx;
          c.dy *= d.dy;
          c.parent = d;
          layout(c);
        });
      }
    };

    const display = function (d) {
      const transition = function (d) {
        if (transitioning || !d) { return; }
        transitioning = true;

        const g2 = display(d);
        const t1 = g1.transition().duration(750);
        const t2 = g2.transition().duration(750);

        // Update the domain only after entering new elements.
        x.domain([d.x, d.x + d.dx]);
        y.domain([d.y, d.y + d.dy]);

        // Enable anti-aliasing during the transition.
        chartContainer.style('shape-rendering', null);

        // Draw child nodes on top of parent nodes.
        chartContainer.selectAll('.depth').sort(function (a, b) { return a.depth - b.depth; });

        // Fade-in entering text.
        g2.selectAll('text').style('fill-opacity', 0);

        // Transition to the new view.
        t1.selectAll('.ptext').call(text).style('fill-opacity', 0);
        t1.selectAll('.ctext').call(text2).style('fill-opacity', 0);
        t2.selectAll('.ptext').call(text).style('fill-opacity', 1);
        t2.selectAll('.ctext').call(text2).style('fill-opacity', 1);
        t1.selectAll('rect').call(rect);
        t2.selectAll('rect').call(rect);

        // Remove the old node when the transition is finished.
        t1.remove().each('end', function () {
          chartContainer.style('shape-rendering', 'crispEdges');
          transitioning = false;
        });
      };

      grandparent
          .datum(d.parent)
          .on('click', transition)
        .select('text')
          .text(name(d));

      const g1 = chartContainer.append('g')
          .datum(d)
          .attr('class', 'depth');

      const g = g1.selectAll('g')
          .data(d._children)
        .enter()
        .append('g');

      g.filter(function (d) { return d._children; })
          .classed('children', true)
          .on('click', transition);

      const children = g.selectAll('.child')
          .data(function (d) { return d._children || [d]; })
        .enter()
        .append('g');

      children.append('rect')
          .attr('class', 'child')
          .call(rect)
        .append('title')
          .text(function (d) { return d.name + ' (' + formatNumber(d.value) + ')'; });

      children.append('text')
          .attr('class', 'ctext')
          .text(function (d) { return d.name; })
          .call(text2);

      g.append('rect')
          .attr('class', 'parent')
          .call(rect);

      const t = g.append('text')
          .attr('class', 'ptext')
          .attr('dy', '.75em');

      t.append('tspan')
          .text(function (d) { return d.name; });
      t.append('tspan')
          .attr('dy', '1.0em')
          .text(function (d) { return formatNumber(d.value); });
      t.call(text);
      g.selectAll('rect')
          .style('fill', function (d) { return getColorFromScheme(d.name, formData.color_scheme); });

      return g;
    };

    const text = function (selection) {
      selection.selectAll('tspan')
          .attr('x', function (d) { return x(d.x) + 6; });
      selection.attr('x', function (d) { return x(d.x) + 6; })
          .attr('y', function (d) { return y(d.y) + 6; })
          .style('opacity', function (d) {
            return this.getComputedTextLength() < x(d.x + d.dx) - x(d.x) ? 1 : 0;
          });
    };

    const text2 = function (selection) {
      selection.attr('x', function (d) { return x(d.x + d.dx) - this.getComputedTextLength() - 6; })
          .attr('y', function (d) { return y(d.y + d.dy) - 6; })
          .style('opacity', function (d) {
            return this.getComputedTextLength() < x(d.x + d.dx) - x(d.x) ? 1 : 0;
          });
    };

    const rect = function (selection) {
      selection.attr('x', function (d) { return x(d.x); })
               .attr('y', function (d) { return y(d.y); })
               .attr('width', function (d) { return x(d.x + d.dx) - x(d.x); })
               .attr('height', function (d) { return y(d.y + d.dy) - y(d.y); });
    };

    const name = function (d) {
      return d.parent
          ? name(d.parent) + ' / ' + d.name + ' (' + formatNumber(d.value) + ')'
          : (slice.datasource.verbose_map[d.name] || d.name) + ' (' + formatNumber(d.value) + ')';
    };

    initialize(data);
    accumulate(data);
    layout(data);
    display(data);
  };
Пример #16
0
        {translate('no_data')}
      </div>
      <TreemapBreadcrumbs {...this.props}/>
    </div>;
  },

  render () {
    if (!this.state.width || !this.state.height) {
      return <div>&nbsp;</div>;
    }

    if (!this.props.items.length) {
      return this.renderWhenNoData();
    }

    let treemap = d3.layout.treemap()
        .round(true)
        .value(d => d.size)
        .sort((a, b) => a.value - b.value)
        .size([this.state.width, this.state.height]);
    let nodes = treemap
        .nodes({ children: this.props.items })
        .filter(d => !d.children)
        .filter(d => !!d.dx && !!d.dy);

    let prefix = mostCommitPrefix(this.props.items.map(item => item.label));
    let prefixLength = prefix.length;

    let rectangles = nodes.map(node => {
      const key = node.label;
      let label = prefixLength ? `${prefix}<br>${node.label.substr(prefixLength)}` : node.label;