コード例 #1
0
    def __init__(self, total_size, duration, args):
        self._total_size = total_size
        self._duration = duration
        self._args = args
        self._tracker = AncestryTracker()
        self._num_pieces = 0
        self._unit = args.unit

        if args.growth_time_limit:
            self._tracker.growth_time_limit = args.growth_time_limit

        if args.output_type != "dot":
            if args.edge_style == LINE:
                if args.stroke_style == SHRINKING:
                    self._edge_plot_method = self.draw_shrinking_line
                else:
                    self._edge_plot_method = self.draw_line
            elif args.edge_style in [CURVE, SPLINE]:
                if args.stroke_style == SHRINKING:
                    self._edge_plot_method = self.draw_shrinking_curve
                else:
                    self._edge_plot_method = self.draw_curve

            if args.stroke_style == SHRINKING:
                self._path_plot_method = self._draw_shrinking_path
            else:
                self._path_plot_method = self.draw_path

            if args.geometry == RECT:
                self._position = self._rect_position
            elif args.geometry == CIRCLE:
                self._position = self._circle_position
コード例 #2
0
 def __init__(self, pieces, args):
     visualizer.Visualizer.__init__(self, args)
     self._tracker = AncestryTracker()
     for chunk in pieces:
         self._tracker.add(Piece(chunk["id"], chunk["t"], chunk["begin"], chunk["end"]))
     self._nodes = {}
     self._override_recursion_limit()
     for piece in self._tracker.last_pieces():
         self._follow_piece(piece)
コード例 #3
0
class AncestryPlotter:
    def __init__(self, total_size, duration, args):
        self._total_size = total_size
        self._duration = duration
        self._args = args
        self._tracker = AncestryTracker()
        self._num_pieces = 0
        self._unit = args.unit

        if args.growth_time_limit:
            self._tracker.growth_time_limit = args.growth_time_limit

        if args.output_type != "dot":
            if args.edge_style == LINE:
                if args.stroke_style == SHRINKING:
                    self._edge_plot_method = self.draw_shrinking_line
                else:
                    self._edge_plot_method = self.draw_line
            elif args.edge_style in [CURVE, SPLINE]:
                if args.stroke_style == SHRINKING:
                    self._edge_plot_method = self.draw_shrinking_curve
                else:
                    self._edge_plot_method = self.draw_curve

            if args.stroke_style == SHRINKING:
                self._path_plot_method = self._draw_shrinking_path
            else:
                self._path_plot_method = self.draw_path

            if args.geometry == RECT:
                self._position = self._rect_position
            elif args.geometry == CIRCLE:
                self._position = self._circle_position

    def set_size(self, width, height):
        self._width = width
        self._height = height

        if self._args.canvas_width:
            self._canvas_width = self._args.canvas_width
        else:
            self._canvas_width = width

        if self._args.canvas_height:
            self._canvas_height = self._args.canvas_height
        else:
            self._canvas_height = height

    @staticmethod
    def add_parser_arguments(parser):
        try:
            parser.add_argument("-width", type=int, default=2000)
            parser.add_argument("-height", type=int, default=2000)
        except argparse.ArgumentError:
            pass
        parser.add_argument("--canvas-width", type=float)
        parser.add_argument("--canvas-height", type=float)
        parser.add_argument("--edge-style",
                            choices=[LINE, CURVE, SPLINE],
                            default=LINE)
        parser.add_argument("--node-size", type=float, default=3)
        parser.add_argument("--root-node-size", type=float, default=9)
        parser.add_argument("--geometry",
                            choices=GEOMETRIES,
                            default=GEOMETRIES[0])
        parser.add_argument("--stroke-style",
                            choices=[PLAIN, SHRINKING])
        parser.add_argument("-stroke-width", type=float, default=2)
        parser.add_argument("-stroke-color", type=str, default="black")
        parser.add_argument("--output-type", choices=OUTPUT_TYPES.keys(),
                            default="svg")
        parser.add_argument("--unit", type=str, default="")
        parser.add_argument("--growth-time-limit", type=float)

    def add_piece(self, piece_id, t, begin, end):
        self._tracker.add(Piece(piece_id, t, begin, end))
        self._num_pieces += 1

    def _rect_position(self, t, byte_pos):
        y = (1 - t / self._duration) * self._width
        x = float(byte_pos) / self._total_size * self._height
        return Vector2d(x, y)

    def _circle_position(self, t, byte_pos):
        angle = float(byte_pos) / self._total_size * 2*math.pi
        x = self._width / 2 + (1 - t / self._duration) * self._width / 2 * math.cos(angle)
        y = self._height / 2 + (1 - t / self._duration) * self._height / 2 * math.sin(angle)
        return Vector2d(x, y)

    def plot(self):
        self._override_recursion_limit()
        for piece in self._tracker.last_pieces():
            self._follow_piece(piece)

    def _override_recursion_limit(self):
        sys.setrecursionlimit(max(self._num_pieces, sys.getrecursionlimit()))

    def _follow_piece(self, piece, child=None):
        self.plot_piece(piece, child)
        if len(piece.growth) > 0:
            path = [(piece.t,
                    (piece.begin + piece.end) / 2)]
            for older_version in reversed(piece.growth):
                path.append((older_version.t,
                             (older_version.begin + older_version.end) / 2))
            self._path_plot_method(path)

        for parent in piece.parents.values():
            self._connect_generations(parent, piece, child)
            self._follow_piece(parent, piece)

    def plot_piece(self, piece, child):
        pass

    def _connect_generations(self, parent, child, grandchild, parent_t=None):
        if parent_t is None:
            parent_t = parent.t
        parent_pos = self._position(parent_t, (parent.begin + parent.end) / 2)
        child_pos = self._position(child.t, (child.begin + child.end) / 2)
        self._stroke_width1 = self._stroke_width_at_time(child.t)
        self._stroke_width2 = self._stroke_width_at_time(parent_t)

        if self._args.edge_style == SPLINE and grandchild is not None:
            grandchild_pos = self._position(grandchild.t, (grandchild.begin + grandchild.end) / 2)
            control_point = self._spline_control_point(parent_pos, child_pos, grandchild_pos)
            self._draw_spline(parent_pos, child_pos, control_point)
        else:
            self._edge_plot_method(child_pos.x, child_pos.y, parent_pos.x, parent_pos.y)

    def _spline_control_point(self, parent, child, grandchild):
        return grandchild + (child - grandchild)*1.3

    def _draw_spline(self, p1, p2, p_control):
        self._write_svg('<path style="stroke:%s;stroke-opacity=0.5;fill:none;stroke-width:%f" d="M%f,%f Q%f,%f %f,%f" />' % (
                self._args.stroke_color,
                self._args.stroke_width,
                p1.x, p1.y,
                p_control.x, p_control.y,
                p2.x, p2.y))

    def _stroke_width_at_time(self, t):
        return self._args.stroke_width * (1 - pow(t/self._duration, 0.6))

    def is_root_piece(self, piece):
        return (piece.end - piece.begin) == self._total_size
コード例 #4
0
class Ancestry(visualizer.Visualizer):
    def __init__(self, pieces, args):
        visualizer.Visualizer.__init__(self, args)
        self._tracker = AncestryTracker()
        for chunk in pieces:
            self._tracker.add(Piece(chunk["id"], chunk["t"], chunk["begin"], chunk["end"]))
        self._nodes = {}
        self._override_recursion_limit()
        for piece in self._tracker.last_pieces():
            self._follow_piece(piece)

    def _follow_piece(self, piece):
        node = Node(piece.id)
        for parent in piece.parents.values():
            node.add_edge(parent.id)
            self._follow_piece(parent)
        self._nodes[piece.id] = node
        
    def _override_recursion_limit(self):
        sys.setrecursionlimit(max(len(self._tracker.pieces()), sys.getrecursionlimit()))

    def render(self):
        self._update()

        glColor3f(0,0,0)
        self._min_x = min([node.position.x for node in self._nodes.values()])
        self._max_x = max([node.position.x for node in self._nodes.values()])
        self._min_y = min([node.position.y for node in self._nodes.values()])
        self._max_y = max([node.position.y for node in self._nodes.values()])

        for node in self._nodes.values():
            self._render_node(node)

    def _render_node(self, node):
        glPointSize(3.0)
        glBegin(GL_POINTS)
        px = self._px(node.position.x)
        py = self._py(node.position.y)
        glVertex2f(px, py)
        glEnd()

        glBegin(GL_LINES)
        for other_node_id in node.edges:
            other_node = self._nodes[other_node_id]
            glVertex2f(px, py)
            glVertex2f(self._px(other_node.position.x),
                       self._py(other_node.position.y))
        glEnd()

    def _px(self, x):
        return (x - self._min_x) / (self._max_x - self._min_x) * self.width

    def _py(self, y):
        return (y - self._min_y) / (self._max_y - self._min_y) * self.height

    def _update(self):
        for node in self._nodes.values():
            node.force = Vector2d(0,0)
        for node in self._nodes.values():
            self._get_node_force(node)
        for node in self._nodes.values():
            self._apply_node_force(node)

    def _get_node_force(self, node):
        for other_node_id in node.edges:
            other_node = self._nodes[other_node_id]
            self.apply_hooke_attraction(node, other_node)
            self.apply_hooke_attraction(other_node, node)

        for other_node in self._nodes.values():
            if other_node != node:
                self.apply_coulomb_repulsion(node, other_node)

    def _apply_node_force(self, node):
        node.velocity += node.force * 0.01
        node.position += node.velocity

    def apply_coulomb_repulsion(self, f, other):
        d = f.position - other.position
        distance = d.mag()
        if distance == 0:
            f.force += Vector2d(random.uniform(0.0, 0.0001),
                                random.uniform(0.0, 0.0001))
        else:
            d.normalize()
            f.force += d / pow(distance, 2)

    def apply_hooke_attraction(self, f, other):
        d = other.position - f.position
        f.force += d