def readFromFile(self, infile, format="fasta"):
        """read multiple alignment from file in various format."""

        self.mMali = {}
        self.mIdentifiers = []

        pattern_parse_ranges = re.compile("(\S+)/(\d+)-(\d+)")

        # read profiles - a profile possibly consists of several
        # entries per file so treat it differently
        if format.lower() == "profile":

            while 1:
                line = infile.readline()
                if not line:
                    return False
                if line[0] != "#":
                    break

            if line[0] != ">":
                raise "expected '>' at as first character in line %s" % line

            try:
                self.mName, length, width = re.match(
                    ">profile=(\S+) length=(\d+) width=(\d+)", line).groups()
            except __HOLE__:
                raise "could not parse header line %s" % line
            width = int(width)
            for x in range(0, width):
                id = "seq%i" % x
                self.mIdentifiers.append(id)
                line = infile.readline()
                if not line:
                    raise "expected %i sequences, only got %i" % (width, x)
                self.mMali[id] = AlignedString(
                    id, 0, self.countCharacters(line[:-1]), line[:-1])
            return True

        if isinstance(infile, list) or \
           isinstance(infile, tuple):
            lines = infile
        else:
            lines = infile.readlines()

        if format not in ("stockholm"):
            # save comments
            self.mComments = filter(lambda x: x[0] == "#", lines)
            lines = filter(lambda x: x[0] != "#", lines)
        else:
            self.mComments = []

        # remove empty lines
        lines = filter(lambda x: x.strip(), lines)
        if not lines:
            raise AttributeError("empty alignment")

        def getId(id, s):
            x = pattern_parse_ranges.match(id)
            if x:
                id, fr, to = x.groups()
                fr, to = int(fr) - 1, int(to)
            else:
                fr, to = 0, self.countCharacters(s)
                self.mWriteRanges = False

            return id, fr, to

        #######################################################################
        if format.lower() == "plain":

            for line in lines:
                if not line.strip():
                    continue
                data = line[:-1].split("\t")
                id = data[3]
                xid = id
                x = 0
                while xid in self.mMali:
                    xid = id + "-" + str(x)
                    x += 1

                self.addEntry(
                    AlignedString(xid, 
                                  int(data[0]) - 1,
                                  int(data[2]),
                                  data[1]))

        #######################################################################
        elif format.lower() == "fasta":
            pattern_identifier = "\S+"
            id = None
            fragments = []
            for line in lines:
                if line[0] == ">":
                    if id:
                        s = re.sub("\s", "", string.join(fragments, ""))
                        id, fr, to = getId(id, s)
                        self.addEntry(AlignedString(id, fr, to, s))

                    id = re.search(
                        "^(%s)" % pattern_identifier, line[1:-1]).group(0)
                    fragments = []
                    continue
                fragments.append(line[:-1])

            s = re.sub("\s", "", string.join(fragments, ""))
            id, fr, to = getId(id, s)
            self.addEntry(AlignedString(id, fr, to, s))

        #######################################################################
        elif format.lower() == "phylip":
            nsequences, nchars = re.split("\s+", lines[0][:-1].strip())
            nsequences = int(nsequences)
            for line in lines[1:]:
                l = line[:-1].strip()
                if not l:
                    continue
                id, sequence = re.match("(\S+)\s+(.*)", l).groups()
                sequence = re.sub("\s", "", sequence)
                if id not in self.mMali:
                    self.mIdentifiers.append(id)
                    self.mMali[id] = []

                self.mMali[id].append(sequence)

            for id, frags in self.mMali.items():
                s = "".join(frags)
                fr, to = 0, self.countCharacters(s)
                self.mMali[id] = AlignedString(id, fr, to, s)

        #######################################################################
        elif format.lower() == "clustal":
            # skip header line
            del lines[0]
            fragments = {}

            # prune lines
            lines = map(lambda x: x.strip(), lines)
            # remove empty lines
            lines = filter(lambda x: len(x[:-1]) > 0, lines)

            for line in lines:
                # remove consensus lines
                if line[0] in ("*", ":"):
                    continue

                data = re.split("\s+", line)
                if len(data) != 2:
                    raise ValueError("parsing error in line %s" % line)

                id, fragment = data
                if id not in fragments:
                    fragments[id] = []
                    self.mIdentifiers.append(id)

                fragments[id].append(fragment)

            for id, f in fragments.items():
                s = re.sub("\s", "", string.join(f, ""))
                self.mMali[id] = AlignedString(
                    id, 0, self.countCharacters(s), s)

        elif format.lower() == "stockholm":
            # skip header line
            assert lines[0].startswith(
                "# STOCKHOLM"), "file is not in stockholm format"
            del lines[0]
            fragments = {}
            annotations = {}
            # prune lines
            lines = map(lambda x: x.strip(), lines)
            # remove empty lines
            lines = filter(lambda x: len(x[:-1]) > 0, lines)

            for line in lines:
                data = re.split("\s+", line)

                if data[0] == "//":
                    break

                if line[0] == '#':
                    if data[0] == "#=GC":
                        id, fragment = data[1:3]
                    else:
                        self.mComments.append(line)
                        continue
                    if id not in annotations:
                        annotations[id] = []
                    annotations[id].append(fragment)
                else:

                    if len(data) > 2:
                        raise ValueError("parsing error in line %s" % line)
                    elif len(data) == 1:
                        # treat empty alignments/lines
                        id = data[0]
                        fragment = ""
                    else:
                        id, fragment = data

                    if id not in fragments:
                        fragments[id] = []
                        self.mIdentifiers.append(id)

                    fragments[id].append(fragment)

            n = []
            for id in self.mIdentifiers:
                f = fragments[id]

                s = re.sub("\s", "", string.join(f, ""))
                x = pattern_parse_ranges.match(id)
                if x:
                    id, fr, to = x.groups()
                    fr, to = int(fr) - 1, int(to)
                else:
                    fr, to = 0, self.countCharacters(s)

                n.append(id)
                self.mMali[id] = AlignedString(id, fr, to, s)
            self.mIdentifiers = n

            for id, f in annotations.items():
                s = re.sub("\s", "", string.join(f, ""))
                annotations[id] = s
            self.mAnnotations = annotations
        else:
            raise "unknown alignment format %s" % format

        if len(self.mMali) == 0:
            self.mLength = 0
        else:
            self.mLength = min(
                map(lambda x: len(x.mString), self.mMali.values()))
dataset/ETHPy150Open CGATOxford/cgat/CGAT/Mali.py/Mali.readFromFile