Creates a CTRL file object from a string. This will mostly be
        used to read an LMTOCtrl object from a CTRL file. Empty spheres
        are ignored.

        Args:
            data: String representation of the CTRL file.

        Returns:
            An LMTOCtrl object.

def from_string(cls, data, sigfigs=8):
        """
        Creates a CTRL file object from a string. This will mostly be
        used to read an LMTOCtrl object from a CTRL file. Empty spheres
        are ignored.

        Args:
            data: String representation of the CTRL file.

        Returns:
            An LMTOCtrl object.
        """
        lines = data.split("\n")[:-1]
        struc_lines = {"HEADER": [], "VERS": [], "SYMGRP": [],
                       "STRUC": [], "CLASS": [], "SITE": []}
        for line in lines:
            if line != "" and not line.isspace():
                if not line[0].isspace():
                    cat = line.split()[0]
                if cat in struc_lines:
                    struc_lines[cat].append(line)
                else:
                    pass
        for cat in struc_lines:
            struc_lines[cat] = " ".join(struc_lines[cat]).replace("= ", "=")

        structure_tokens = {"ALAT": None,
                            "PLAT": [],
                            "CLASS": [],
                            "SITE": []}

        for cat in ["STRUC", "CLASS", "SITE"]:
            fields = struc_lines[cat].split("=")
            for f, field in enumerate(fields):
                token = field.split()[-1]
                if token == "ALAT":
                    alat = round(float(fields[f+1].split()[0]), sigfigs)
                    structure_tokens["ALAT"] = alat
                elif token == "ATOM":
                    atom = fields[f+1].split()[0]
                    if not bool(re.match("E[0-9]*$", atom)):
                        if cat == "CLASS":
                            structure_tokens["CLASS"].append(atom)
                        else:
                            structure_tokens["SITE"].append({"ATOM": atom})
                    else:
                        pass
                elif token in ["PLAT", "POS"]:
                    try:
                        arr = np.array([round(float(i), sigfigs)
                                       for i in fields[f+1].split()])
                    except ValueError:
                        arr = np.array([round(float(i), sigfigs)
                                       for i in fields[f+1].split()[:-1]])
                    if token == "PLAT":
                        structure_tokens["PLAT"] = arr.reshape([3, 3])
                    elif not bool(re.match("E[0-9]*$", atom)):
                        structure_tokens["SITE"][-1]["POS"] = arr
                    else:
                        pass
                else:
                    pass
        try:
            spcgrp_index = struc_lines["SYMGRP"].index("SPCGRP")
            spcgrp = struc_lines["SYMGRP"][spcgrp_index:spcgrp_index+12]
            structure_tokens["SPCGRP"] = spcgrp.split("=")[1].split()[0]
        except ValueError:
            pass

        for token in ["HEADER", "VERS"]:
                try:
                    value = re.split(token + r"\s*", struc_lines[token])[1]
                    structure_tokens[token] = value.strip()
                except IndexError:
                    pass
        return LMTOCtrl.from_dict(structure_tokens)