Example #1
0
class Segment(waves.Segment, heat_map.Segment):
    def __init__(self, *args):
        waves.Segment.__init__(self, *args)
        heat_map.Segment.__init__(self, *args)
        self._amp_smoother = Smoother(response_factor=2.5)

    def relative_size(self):
        age = self.age()
        if age > (self.duration - self._fade_time):
            return 1 - sigmoid(1 - (self.duration - age) / self._fade_time)
        else:
            self._amp_smoother.smooth(
                max([abs(value) for value in self.waveform]),
                self.visualizer.time_increment)
            return sigmoid(pow(max(self._amp_smoother.value(), 0), 0.25))
class Ancestry(visualizer.Visualizer, AncestryPlotter):
    def __init__(self, tr_log, pieces, args):
        visualizer.Visualizer.__init__(self, args)
        AncestryPlotter.__init__(self, tr_log.total_file_size(), tr_log.lastchunktime(), args)
        self._unfold_function = getattr(self, "_unfold_%s" % args.unfold)

        self._pre_render()

        self._autozoom = (args.geometry == CIRCLE and self.args.autozoom)
        if self._autozoom:
            self._max_pxy = 0
            self._zoom_smoother = Smoother()

    @staticmethod
    def add_parser_arguments(parser):
        AncestryPlotter.add_parser_arguments(parser)
        visualizer.Visualizer.add_parser_arguments(parser)
        parser.add_argument("-z", dest="timefactor", type=float, default=1.0)

    def _pre_render(self):
        print "pre-rendering..."
        self._timeline = []
        for piece in pieces:
            self.add_piece(piece["id"], piece["t"], piece["begin"], piece["end"])
            frame = {"t": piece["t"],
                     "tracker": copy.deepcopy(self._tracker),
                     "num_pieces": self._num_pieces}
            self._timeline.append(frame)
        print "ok"

    def InitGL(self):
        visualizer.Visualizer.InitGL(self)
        glClearColor(0.0, 0.0, 0.0, 0.0)

    def ReSizeGLScene(self, width, height):
        visualizer.Visualizer.ReSizeGLScene(self, width, height)
        self._size = min(width, height) - 2*MARGIN
        AncestryPlotter.set_size(self, self._size, self._size)

    def render(self):
        glTranslatef(MARGIN + (self.width - self._size)/2, MARGIN, 0)
        glLineWidth(LINE_WIDTH * self.width)
        glEnable(GL_LINE_SMOOTH)
        glHint(GL_LINE_SMOOTH_HINT, GL_NICEST)
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        glColor3f(1,1,1)

        self._unfold_function(self.current_time() * self.args.timefactor)
        frame = self._frame_at_cursor()
        self._activate_frame(frame)

        if self._autozoom:
            self._zoom = self._zoom_smoother.value()
            if self._zoom is None:
                self._zoom = 0.0
        else:
            self._zoom = 1.0

        self.plot()

        if self._autozoom:
            if self._max_pxy == 0:
                zoom = 0.5
            else:
                zoom = 0.5 + self.cursor_t/self._duration * 0.5 / self._max_pxy
            self._zoom_smoother.smooth(zoom, self.time_increment)
        
    def _unfold_backward(self, t):
        self._cursor_t = self._duration - t % self._duration

    def _unfold_forward(self, t):
        self._cursor_t = t % self._duration

    def _frame_at_cursor(self):
        for frame in self._timeline:
            if frame["t"] >= self._cursor_t:
                return frame
        return self._timeline[-1]

    def _activate_frame(self, frame):
        self._num_pieces = frame["num_pieces"]
        self._tracker = frame["tracker"]

    # def _follow_piece(self, piece):
    #     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.draw_path(path)

    #     for parent in piece.parents.values():
    #         if self.min_t < parent.t < self.max_t:
    #             self._connect_child_and_parent(
    #                 piece.t, (piece.begin + piece.end) / 2,
    #                 parent.t, (parent.begin + parent.end) / 2)
    #             self._follow_piece(parent)
    #         else:
    #             if self.args.unfold == BACKWARD:
    #                 t = self.cursor_t - pow(self.cursor_t - parent.t, 0.7)
    #             else:
    #                 t = self.cursor_t
    #             self._connect_child_and_parent(
    #                 piece.t, (piece.begin + piece.end) / 2,
    #                 t, (parent.begin + parent.end) / 2)

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

    def _circle_position(self, t, byte_pos):
        angle = float(byte_pos) / self._total_size * 2*math.pi
        rel_t = 1 - t / self._duration
        px = rel_t * math.cos(angle)
        py = rel_t * math.sin(angle)
        x = self._width / 2 + (px * self._zoom) * self._width / 2
        y = self._height / 2 + (py * self._zoom) * self._height / 2
        if self._autozoom:
            self._max_pxy = max([self._max_pxy, abs(px), abs(py)])
        return x, y

    def draw_path(self, points):
        glBegin(GL_LINE_STRIP)
        for (t, b) in points:
            x, y = self._position(t, b)
            glVertex2f(x, y)
        glEnd()

    def draw_curve(self, x1, y1, x2, y2):
        control_points = [
            Vector2d(x1, y1),
            Vector2d(x1 + (x2 - x1) * 0.3, y1),
            Vector2d(x1 + (x2 - x1) * 0.7, y2),
            Vector2d(x2, y2)
            ]
        bezier = make_bezier([(p.x, p.y) for p in control_points])
        points = bezier(CURVE_PRECISION)
        glBegin(GL_LINE_STRIP)
        for x, y in points:
            glVertex2f(x, y)
        glEnd()
class Ancestry(visualizer.Visualizer, AncestryPlotter):
    def __init__(self, tr_log, pieces, args):
        visualizer.Visualizer.__init__(self, args)
        AncestryPlotter.__init__(self, tr_log.total_file_size(), tr_log.lastchunktime(), args)

        if args.unfold == BACKWARD:
            for piece in pieces:
                self.add_piece(piece["id"], piece["t"], piece["begin"], piece["end"])
        elif args.unfold == FORWARD:
            self._remaining_pieces = copy.copy(pieces)

        self._autozoom = (args.geometry == CIRCLE and self.args.autozoom)
        if self._autozoom:
            self._max_pxy = 0
            self._zoom_smoother = Smoother()

        if args.node_style == CIRCLE:
            self._node_plot_method = self._draw_node_circle
            self._nodes = {}
        else:
            self._node_plot_method = None

        if args.node_size_envelope:
            attack, decay, sustain = args.node_size_envelope.split(",")
            self._node_size_envelope = AdsrEnvelope(
                attack, decay, sustain, args.node_size_envelope_slope)
        else:
            self._node_size_envelope = None

        if args.sway_envelope:
            attack, decay, sustain = args.sway_envelope.split(",")
            self._sway_envelope = AdsrEnvelope(attack, decay, sustain)
        else:
            self._sway_envelope = None


    @staticmethod
    def add_parser_arguments(parser):
        AncestryPlotter.add_parser_arguments(parser)
        visualizer.Visualizer.add_parser_arguments(parser)
        parser.add_argument("-z", dest="timefactor", type=float, default=1.0)

    def InitGL(self):
        visualizer.Visualizer.InitGL(self)
        glClearColor(0.0, 0.0, 0.0, 0.0)

        if self.args.node_style == CIRCLE:
            self._node_circle_lists = []
            for n in range(0, NODE_SIZE_PRECISION):
                display_list = self.new_display_list_id()
                self._node_circle_lists.append(display_list)
                glNewList(display_list, GL_COMPILE)
                self._render_node_circle(0, 0, n)
                glEndList()

    def ReSizeGLScene(self, width, height):
        visualizer.Visualizer.ReSizeGLScene(self, width, height)
        self._size = min(width, height) - 2*MARGIN
        AncestryPlotter.set_size(self, self._size, self._size)

    def render(self):
        glTranslatef(MARGIN + (self.width - self._size)/2, MARGIN, 0)
        glLineWidth(self.args.line_width)
        glEnable(GL_LINE_SMOOTH)
        glHint(GL_LINE_SMOOTH_HINT, GL_NICEST)
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        glColor3f(1,1,1)

        if self.args.unfold == BACKWARD:
            self._cursor_t = self._duration - self._adjusted_current_time() % self._duration
        elif self.args.unfold == FORWARD:
            if self.args.ff:
                self._add_oldest_remaining_piece()
            else:
                while (len(self._remaining_pieces) > 0 and
                       self._remaining_pieces[0]["t"] <= self._adjusted_current_time()):
                    self._add_oldest_remaining_piece()

        if self._autozoom:
            self._zoom = self._zoom_smoother.value()
            if self._zoom is None:
                self._zoom = 0.0
        else:
            self._zoom = 1.0

        self.plot()

        if self._autozoom:
            if self._max_pxy == 0:
                zoom = 0.5
            else:
                zoom = 0.5 + self._cursor_t/self._duration * 0.5 / self._max_pxy
            self._zoom_smoother.smooth(zoom, self.time_increment)

    def _add_oldest_remaining_piece(self):
        piece = self._remaining_pieces.pop(0)
        self.add_piece(piece["id"], piece["t"], piece["begin"], piece["end"])

    def finished(self):
        return self.current_time() > (self._duration / self.args.timefactor + SUSTAIN_TIME)

    def _adjusted_current_time(self):
        return self.current_time() * self.args.timefactor

    def _follow_piece(self, piece, child=None):
        self._update_and_draw_node(piece, piece.t, (piece.begin + piece.end) / 2)

        if len(piece.growth) > 0:
            path = [(piece.t,
                    (piece.begin + piece.end) / 2)]
            for older_version in reversed(piece.growth):
                if self.args.unfold == FORWARD or self._cursor_t < older_version.t:
                    path.append((older_version.t,
                                 (older_version.begin + older_version.end) / 2))
            self.draw_path(piece, path)
            self._update_and_draw_node(piece, path[-1][0], path[-1][1])

        for parent in piece.parents.values():
            if self.args.unfold == FORWARD or self._cursor_t < parent.t:
                self._connect_generations(parent, piece, child)
                self._follow_piece(parent, piece)
            else:
                if self.args.unfold == BACKWARD:
                    t = self._cursor_t - pow(self._cursor_t - parent.t, 0.7)
                else:
                    t = self._cursor_t
                self._connect_generations(parent, piece, child, t)
                self._update_and_draw_node(parent, t, (parent.begin + parent.end) / 2)

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

    def _circle_position(self, t, byte_pos):
        angle = float(byte_pos) / self._total_size * 2*math.pi
        rel_t = 1 - t / self._duration
        px = rel_t * math.cos(angle)
        py = rel_t * math.sin(angle)
        x = self._width / 2 + (px * self._zoom) * self._width / 2
        y = self._height / 2 + (py * self._zoom) * self._height / 2
        if self._autozoom:
            self._max_pxy = max([self._max_pxy, abs(px), abs(py)])
        return Vector2d(x, y)

    def draw_path(self, piece, points):
        if self.args.sway:
            piece_sway_magnitude = self._sway_magnitude(piece)
        glBegin(GL_LINE_STRIP)
        n = 0
        for (t, b) in points:
            x, y = self._position(t, b)
            if self.args.sway:
                magnitude = (1 - float(n) / len(points)) * piece_sway_magnitude
                x += piece.sway.sway.x * magnitude * self._size
                y += piece.sway.sway.y * magnitude * self._size
                n += 1
            glVertex2f(x, y)
        glEnd()

    def draw_curve(self, x1, y1, x2, y2):
        control_points = [
            Vector2d(x1, y1),
            Vector2d(x1 + (x2 - x1) * 0.3, y1),
            Vector2d(x1 + (x2 - x1) * 0.7, y2),
            Vector2d(x2, y2)
            ]
        bezier = make_bezier([(p.x, p.y) for p in control_points])
        points = bezier(CURVE_PRECISION)
        glBegin(GL_LINE_STRIP)
        for x, y in points:
            glVertex2f(x, y)
        glEnd()

    def draw_line(self, x1, y1, x2, y2):
        glBegin(GL_LINES)
        glVertex2f(x1, y1)
        glVertex2f(x2, y2)
        glEnd()

    def _update_and_draw_node(self, piece, t, b):
        if self.args.sway:
            self._update_sway(piece)
        if self._node_plot_method:
            self._node_plot_method(piece, t, b)

    def _update_sway(self, piece):
        if not hasattr(piece, "sway"):
            piece.sway = Sway(self.args.sway_magnitude)
        piece.sway.update(self.time_increment)

    def _draw_node_circle(self, piece, t, b):
        age = self._age(piece)
        size = self._node_size(age)
        cx, cy = self._position(t, b)
        if self.args.sway:
            piece_sway_magnitude = self._sway_magnitude(piece)
            cx += piece.sway.sway.x * piece_sway_magnitude * self._size
            cy += piece.sway.sway.y * piece_sway_magnitude * self._size
        glPushMatrix()
        glTranslatef(cx, cy, 0)
        glCallList(self._node_circle_lists[size])
        glPopMatrix()

    def _age(self, piece):
        try:
            appearance_time = piece.appearance_time
        except AttributeError:
            appearance_time = piece.appearance_time = self._adjusted_current_time()
        return self._adjusted_current_time() - appearance_time

    def _node_size(self, age):
        if self._node_size_envelope:
            return int(self._node_size_envelope.value(age) * (NODE_SIZE_PRECISION-1))
        else:
            return NODE_SIZE_PRECISION-1

    def _sway_magnitude(self, piece):
        age = self._age(piece)
        if self._sway_envelope:
            return self._sway_envelope.value(age)
        else:
            return 1

    def _render_node_circle(self, cx, cy, size):
        # glColor3f(0,0,0)
        # self._render_filled_circle(cx, cy, size)
        # glColor3f(1,1,1)
        # self._render_circle_outline(cx, cy, size)

        # glColor3f(1,1,1)
        # self._render_filled_circle(cx, cy, size)

        glColor3f(1,1,1)
        glEnable(GL_POINT_SMOOTH)
        radius = max(self.args.node_size * self.width * size / (NODE_SIZE_PRECISION-1), 0.1)
        glPointSize(radius * 2)
        glBegin(GL_POINTS)
        glVertex2f(cx, cy)
        glEnd()

    def _render_filled_circle(self, cx, cy, size):
        glBegin(GL_TRIANGLE_FAN)
        glVertex2f(cx, cy)
        angle = 0
        radius = self.args.node_size * self.width * size / (NODE_SIZE_PRECISION-1)
        while angle < 2*math.pi:
            x = cx + math.cos(angle) * radius
            y = cy + math.sin(angle) * radius
            glVertex2f(x, y)
            angle += 0.1
        x = cx + math.cos(0) * radius
        y = cy + math.sin(0) * radius
        glVertex2f(x, y)
        glEnd()

    def _render_circle_outline(self, cx, cy, size):
        glBegin(GL_LINE_STRIP)
        angle = 0
        radius = self.args.node_size * self.width * size / (NODE_SIZE_PRECISION-1)
        while angle < 2*math.pi:
            x = cx + math.cos(angle) * radius
            y = cy + math.sin(angle) * radius
            glVertex2f(x, y)
            angle += 0.1
        glEnd()