Parse our .PLT file and return :class:`Plot` object or raise :exc:`ParseException`.

def parse(self):
        """Parse our .PLT file and return :class:`Plot` object or raise :exc:`ParseException`."""
        plt = Plot(name_from_filename(self.pltfilename))

        with open(self.pltfilename, 'rb') as pltfile:
            segment = None

            for line in pltfile:
                if not line:
                    continue

                c, val = line[:1], line[1:]

                if c == 'Z':
                    edist = None
                    try:
                        ymin, ymax, xmin, xmax, zmin, zmax = (float(v) for v in val.split())
                    except ValueError:
                        ymin, ymax, xmin, xmax, zmin, zmax, _, edist = val.split()
                        ymin, ymax, xmin, xmax, zmin, zmax, edist = \
                            (float(v) for v in (ymin, ymax, xmin, xmax, zmin, zmax, edist))
                    plt.set_bounds(ymin, ymax, xmin, xmax, zmin, zmax, edist)

                elif c == 'S':
                    if not plt.name:
                        plt.name = val.strip()

                elif c == 'G':
                    plt.utm_zone = int(val)

                elif c == 'O':
                    plt.datum = val

                elif c == 'N':
                    date, comment = None, ''  # both date and comment are optional
                    try:
                        name, _, m, d, y, comment = val.split(None, 5)
                        date = datetime.date(int(y), int(m), int(d))
                    except ValueError:
                        try:
                            name, _, m, d, y = val.split()
                            date = datetime.date(int(y), int(m), int(d))
                        except ValueError:
                            name = val
                    comment = comment[1:].strip()
                    segment = Segment(name, date, comment)

                elif c == 'M':
                    flags = None  # flags are optional
                    try:
                        y, x, z, name, _, l, u, d, r, _, edist = val.split()
                    except ValueError:
                        y, x, z, name, _, l, u, d, r, _, edist, flags = val.split()
                    cmd = MoveCommand(float(y), float(x), float(z), name[1:],
                                      float(l), float(r), float(u), float(d), float(edist), flags)
                    segment.add_command(cmd)

                elif c in ('D', 'd'):
                    # 'D' for normal stations, 'd' for "hidden" stations with the 'P' flag
                    flags = None
                    try:
                        y, x, z, name, _, l, u, d, r, _, edist = val.split()
                    except ValueError:
                        y, x, z, name, _, l, u, d, r, _, edist, flags = val.split()
                    cmd = DrawCommand(float(y), float(x), float(z), name[1:],
                                      float(l), float(r), float(u), float(d), float(edist), flags)
                    cmd.cmd = c
                    segment.add_command(cmd)

                elif c == 'X':
                    segment.set_bounds(*(float(v) for v in val.split()))

                    # An X-bounds command signifies end of segment
                    plt.add_segment(segment)
                    segment = None

                elif c == 'P':
                    name, y, x, z = val.split()
                    plt.add_fixed_point(name, (float(y), float(x), float(z)))

                elif c == 'C':
                    plt.loop_count = int(val)

                elif c == 'R':
                    count, common, from_sta, to_sta, stations = val.split(None, 4)
                    plt.add_loop(int(count), common, from_sta, to_sta, stations.split())

                elif c == '\x1A':
                    continue  # "soft EOF" ascii SUB ^Z

                else:
                    msg = "Unknown PLT control code '%s': %s" % (c, val)
                    if self.strict_mode:
                        raise ParseException(msg)
                    else:
                        log.warning(msg)

        return plt