|
39 | 39 | import math |
40 | 40 | import re |
41 | 41 | import six |
| 42 | +import warnings |
42 | 43 |
|
43 | 44 | from .qt import * |
44 | 45 | from . import qt4_circular_render as crender |
45 | 46 | from . import qt4_rect_render as rrender |
46 | 47 | from .main import _leaf, NodeStyle, _FaceAreas, tracktime, TreeStyle |
| 48 | +from ..treeview.faces import CircleFace |
47 | 49 | from .node_gui_actions import _NodeActions as _ActionDelegator |
48 | 50 | from .qt4_face_render import update_node_faces, _FaceGroupItem, _TextFaceItem |
49 | 51 | from .templates import _DEFAULT_STYLE, apply_template |
@@ -362,9 +364,12 @@ def render(root_node, img, hide_root=False): |
362 | 364 | mainRect.adjust(_x, _y, _x, _y) |
363 | 365 |
|
364 | 366 | # Add extra components and adjust mainRect to them |
365 | | - add_legend(img, mainRect, frame) |
366 | 367 | add_title(img, mainRect, frame) |
| 368 | + add_legend(img, mainRect, frame) |
367 | 369 | add_scale(img, mainRect, frame) |
| 370 | + add_y_scale(img, mainRect, frame, root_node) |
| 371 | + |
| 372 | + |
368 | 373 | frame.setRect(mainRect) |
369 | 374 |
|
370 | 375 | # Draws a border around the tree |
@@ -468,6 +473,142 @@ def add_scale(img, mainRect, parent): |
468 | 473 | scaleItem.moveBy(img.margin_left, 0) |
469 | 474 | mainRect.adjust(0, 0, 0, length) |
470 | 475 |
|
| 476 | + |
| 477 | +def add_y_scale(img, mainRect, parent, root): |
| 478 | + |
| 479 | + if img.y_axis['show']: |
| 480 | + |
| 481 | + if img.scale is None: |
| 482 | + scale_length = root.get_farthest_leaf()[1] * img._scale + \ |
| 483 | + int((root.get_farthest_leaf(topology_only=True)[1]+1)/img._scale) |
| 484 | + # scale_length = img.y_axis['scale_length'] * img._scale + \ |
| 485 | + # int((root.get_farthest_leaf(topology_only=True)[1] + 1) / img._scale) |
| 486 | + else: |
| 487 | + scale_length = root.get_farthest_leaf()[1] * img.scale + \ |
| 488 | + int((root.get_farthest_leaf(topology_only=True)[1]+1)/img.scale) |
| 489 | + # scale_length = img.y_axis['scale_length'] * img.scale + \ |
| 490 | + # int((root.get_farthest_leaf(topology_only=True)[1] + 1) / img.scale) |
| 491 | + |
| 492 | + scale_item = _EmptyItem() |
| 493 | + custom_pen = QtGui.QPen(QtGui.QColor("black"), 1) |
| 494 | + |
| 495 | + line = QtGui.QGraphicsLineItem(scale_item) |
| 496 | + line.setPen(custom_pen) |
| 497 | + |
| 498 | + mark = {} |
| 499 | + if img.y_axis['scale_type'] == 'log': |
| 500 | + calculate_marks = int(math.ceil(math.log(root.get_farthest_leaf()[1], 10))) |
| 501 | + |
| 502 | + for x in range(10*calculate_marks+1): |
| 503 | + mark[x] = QtGui.QGraphicsLineItem(scale_item) |
| 504 | + mark[x].setPen(custom_pen) |
| 505 | + |
| 506 | + elif img.y_axis['scale_type'] == 'linear': |
| 507 | + calculate_marks = int(root.get_farthest_leaf(topology_only=True)[1]+1) |
| 508 | + |
| 509 | + for x in range(calculate_marks + 1): |
| 510 | + mark[x] = QtGui.QGraphicsLineItem(scale_item) |
| 511 | + mark[x].setPen(custom_pen) |
| 512 | + else: |
| 513 | + raise ValueError('The scale {} does not exist'.format(img.y_axis['scale_type'])) |
| 514 | + |
| 515 | + # scale line |
| 516 | + if img.rotation == 0 or img.rotation == 180: |
| 517 | + line.setLine(0, -10, scale_length, -10) |
| 518 | + elif img.rotation == 90 or img.rotation == 270: |
| 519 | + line.setLine(-10, 0, -10, scale_length) |
| 520 | + else: |
| 521 | + warnings.warn('The scale can\'t be rotated with the angle of the tree.' |
| 522 | + 'Setting the scale in upright position') |
| 523 | + line.setLine(0, -10, scale_length, -10) |
| 524 | + |
| 525 | + # Adding markers |
| 526 | + if img.y_axis['scale_type'] == 'log': |
| 527 | + marker = scale_length/(math.log(root.get_farthest_leaf()[1], 10)) |
| 528 | + |
| 529 | + for x in range(10*calculate_marks): |
| 530 | + if x % 10: |
| 531 | + log_step = math.log(math.pow(10, int(x / 10)) * (x % 10), 10) |
| 532 | + else: |
| 533 | + log_step = math.log(math.pow(10, int(x / 10)), 10) |
| 534 | + |
| 535 | + if (marker*log_step) > scale_length: |
| 536 | + continue |
| 537 | + if img.rotation == 0 or img.rotation == 180: |
| 538 | + mark[x].setLine(marker*log_step, -15, marker*log_step, -10) |
| 539 | + elif img.rotation == 90 or img.rotation == 270: |
| 540 | + mark[x].setLine(-15, marker*log_step, -10, marker*log_step) |
| 541 | + else: |
| 542 | + mark[x].setLine(marker*log_step, -15, marker*log_step, -10) |
| 543 | + |
| 544 | + elif img.y_axis['scale_type'] == 'linear': |
| 545 | + marker = int(scale_length / (root.get_farthest_leaf(topology_only=True)[1]+1)) |
| 546 | + for x in range(calculate_marks): |
| 547 | + if img.rotation == 0 or img.rotation == 180: |
| 548 | + mark[x].setLine(x*marker, -15, x*marker, -10) |
| 549 | + elif img.rotation == 90 or img.rotation == 270: |
| 550 | + mark[x].setLine(-15, x*marker, -10, x*marker) |
| 551 | + else: |
| 552 | + mark[x].setLine(x * marker, -15, x * marker, -10) |
| 553 | + |
| 554 | + if img.rotation == 0 or img.rotation == 180: |
| 555 | + mark[calculate_marks].setLine(scale_length, -15, scale_length, -10) |
| 556 | + elif img.rotation == 90 or img.rotation == 270: |
| 557 | + mark[calculate_marks].setLine(-15, scale_length, -10, scale_length) |
| 558 | + else: |
| 559 | + mark[calculate_marks].setLine(scale_length, -15, scale_length, -10) |
| 560 | + |
| 561 | + # adding text to scale |
| 562 | + if img.y_axis['scale_type'] == 'linear': |
| 563 | + if img.y_axis['scale_length'] != 1: |
| 564 | + scale_mesure = img.y_axis['scale_length'] / calculate_marks |
| 565 | + else: |
| 566 | + scale_mesure = (root.get_farthest_leaf()[1] - root.dist)/calculate_marks |
| 567 | + |
| 568 | + for x in range(calculate_marks+1): |
| 569 | + if (x*marker) > scale_length: |
| 570 | + break |
| 571 | + |
| 572 | + if img.y_axis['scale_type'] == 'log': |
| 573 | + scale_text = '10<sup>'+str(x)+'</sup>' |
| 574 | + |
| 575 | + elif img.y_axis['scale_type'] == 'linear': |
| 576 | + length_text = scale_mesure * x |
| 577 | + if length_text < 1 and length_text != 0: |
| 578 | + scale_text = "%0.4f" % length_text |
| 579 | + else: |
| 580 | + scale_text = "%0.1f" % length_text |
| 581 | + |
| 582 | + font = QtGui.QFont('White Rabbit') |
| 583 | + font.setPointSize(8) |
| 584 | + scale = QtGui.QGraphicsTextItem() |
| 585 | + scale.setHtml(scale_text) |
| 586 | + scale.setFont(font) |
| 587 | + # scale.setFlag(scale.ItemIgnoresTransformations, True) |
| 588 | + scale.setParentItem(scale_item) |
| 589 | + |
| 590 | + if img.rotation == 0 or img.rotation == 180: |
| 591 | + scale.setPos(x*marker-5, -13) |
| 592 | + elif img.rotation == 90 or img.rotation == 270: |
| 593 | + scale.setPos(-13, x*marker-5) |
| 594 | + else: |
| 595 | + scale.setPos(x*marker-5, -13) |
| 596 | + |
| 597 | + scale_item.setParentItem(parent) |
| 598 | + |
| 599 | + x_pos = mainRect.topLeft().x() |
| 600 | + y_pos = mainRect.topLeft().y() |
| 601 | + if img.title: |
| 602 | + title = _FaceGroupItem(img.title, None) |
| 603 | + lg_w, lg_h = title.get_size() |
| 604 | + root_pos = img.margin_top + lg_h + 15 |
| 605 | + else: |
| 606 | + root_pos = img.margin_top |
| 607 | + mainRect.adjust(0, -20, 0, 0) |
| 608 | + scale_item.setPos(x_pos-10, y_pos+root_pos) |
| 609 | + alter_internal_nodes(root) |
| 610 | + |
| 611 | + |
471 | 612 | def rotate_inverted_faces(n2i, n2f, img): |
472 | 613 | for node, faceblock in six.iteritems(n2f): |
473 | 614 | item = n2i[node] |
|
0 commit comments