          """ Return the path to alignments file """
          logger.debug("Getting location: (folder: '%s', filename: '%s')", folder, filename)
          extension = os.path.splitext(filename)[1]
          if extension in (".json", ".p", ".yaml", ".yml"):
              logger.debug("File extension set from filename: '%s'", extension)
              location = os.path.join(str(folder), filename)
          else:
              location = os.path.join(str(folder),
                                      "{}.{}".format(filename,
                                                     self.serializer.file_extension))
              logger.debug("File extension set from serializer: '%s'",
                           self.serializer.file_extension)
          logger.verbose("Alignments filepath: '%s'", location)
          return location
  
 
</s> remove     @staticmethod
    def get_serializer(filename):
        """ Set the serializer to be used for loading and
            saving alignments

            If a filename with a valid extension is passed in
            this will be used as the serializer, otherwise the
            compressed pickle will be used """
        logger.debug("Getting serializer: (filename: '%s')", filename)
        extension = os.path.splitext(filename)[1]
        if extension in (".json", ".p", ".yaml", ".yml"):
            logger.debug("Serializer set from filename extension: '%s'", extension)
            retval = get_serializer_from_filename(filename)
        else:
            logger.debug("Returning default Pickle serializer")
            retval = get_serializer("compressed")
        logger.verbose("Using '%s' serializer for alignments", retval.file_extension)
        return retval

 </s> add  </s> remove     def set_dfl(self, destination_format):
        """ Set the alignments for dfl alignments """
        logger.debug("Alignments are DFL format")
        self.file = "dfl"
        self.set_destination_format(destination_format)

    def set_destination_format(self, destination_format):
        """ Standardize the destination format to the correct extension """
        extensions = {".json": "json",
                      ".p": "pickle",
                      ".yml": "yaml",
                      ".yaml": "yaml"}
        dst_fmt = None
        file_ext = os.path.splitext(self.file)[1].lower()
        logger.debug("File extension: '%s'", file_ext)

        if destination_format is not None:
            dst_fmt = destination_format
        elif self.file == "dfl":
            dst_fmt = "json"
        elif file_ext in extensions.keys():
            dst_fmt = extensions[file_ext]
        else:
            logger.error("'%s' is not a supported serializer. Exiting", file_ext)
            exit(0)

        logger.verbose("Destination format set to '%s'", dst_fmt)

        self.serializer = self.get_serializer("", dst_fmt)
        filename = os.path.splitext(self.file)[0]
        self.file = "{}.{}".format(filename, self.serializer.file_extension)
        logger.debug("Destination file: '%s'", self.file)

 </s> add  </s> remove         self.serializer = self.get_serializer(filename)
 </s> add         self.serializer = get_serializer("compressed") </s> remove class Legacy():
    """ Update legacy alignments:
        - Rotate landmarks and bounding boxes on legacy alignments
          and remove the 'r' parameter
        - Add face hashes to alignments file
    """

    def __init__(self, alignments, arguments, frames=None, faces=None, child_process=False):
        logger.debug("Initializing %s: (arguments: %s, child_process: %s)",
                     self.__class__.__name__, arguments, child_process)
        self.alignments = alignments
        if child_process:
            self.frames = frames
            self.faces = faces
        else:
            self.frames = Frames(arguments.frames_dir)
            self.faces = Faces(arguments.faces_dir)
        logger.debug("Initialized %s", self.__class__.__name__)

    def process(self):
        """ Run the rotate alignments process """
        rotated = self.alignments.get_legacy_rotation()
        hashes = self.alignments.get_legacy_no_hashes()
        if (not self.frames or not rotated) and (not self.faces or not hashes):
            return
        logger.info("[UPDATE LEGACY LANDMARKS]")  # Tidy up cli output
        if rotated and self.frames:
            logger.info("Legacy rotated frames found. Converting...")
            self.rotate_landmarks(rotated)
            self.alignments.save()
        if hashes and self.faces:
            logger.info("Legacy alignments found. Adding Face Hashes...")
            self.add_hashes(hashes)
            self.alignments.save()

    def rotate_landmarks(self, rotated):
        """ Rotate the landmarks """
        for rotate_item in tqdm(rotated, desc="Rotating Landmarks"):
            frame = self.frames.get(rotate_item, None)
            if frame is None:
                continue
            self.alignments.rotate_existing_landmarks(rotate_item, frame)

    def add_hashes(self, hashes):
        """ Add Face Hashes to the alignments file """
        all_faces = dict()
        logger.info("Getting original filenames, indexes and hashes...")
        for face in self.faces.file_list_sorted:
            filename = face["face_name"]
            extension = face["face_extension"]
            if "_" not in face["face_name"]:
                logger.warning("Unable to determine index of file. Skipping: '%s'", filename)
                continue
            index = filename[filename.rfind("_") + 1:]
            if not index.isdigit():
                logger.warning("Unable to determine index of file. Skipping: '%s'", filename)
                continue
            orig_frame = filename[:filename.rfind("_")] + extension
            all_faces.setdefault(orig_frame, dict())[int(index)] = face["face_hash"]

        logger.info("Updating hashes to alignments...")
        for frame in hashes:
            if frame not in all_faces.keys():
                logger.warning("Skipping missing frame: '%s'", frame)
                continue
            self.alignments.add_face_hashes(frame, all_faces[frame])


 </s> add 
            # Reformat legacy alignments file
            filename = self.update_file_format(folder, filename)
            logger.debug("Updated legacy alignments. New filename: '%s'", filename)
        elif not extension:
            filename = "{}.{}".format(filename, self.serializer.file_extension)
          """ Return the path to alignments file """
          logger.debug("Getting location: (folder: '%s', filename: '%s')", folder, filename)
          extension = os.path.splitext(filename)[1]
          if extension in (".json", ".p", ".yaml", ".yml"):
            # Reformat legacy alignments file
            filename = self.update_file_format(folder, filename)
            logger.debug("Updated legacy alignments. New filename: '%s'", filename)
        elif not extension:
            filename = "{}.{}".format(filename, self.serializer.file_extension)
            # Reformat legacy alignments file
            filename = self.update_file_format(folder, filename)
            logger.debug("Updated legacy alignments. New filename: '%s'", filename)
        elif not extension:
            filename = "{}.{}".format(filename, self.serializer.file_extension)
            # Reformat legacy alignments file
            filename = self.update_file_format(folder, filename)
            logger.debug("Updated legacy alignments. New filename: '%s'", filename)
        elif not extension:
            filename = "{}.{}".format(filename, self.serializer.file_extension)
            # Reformat legacy alignments file
            filename = self.update_file_format(folder, filename)
            logger.debug("Updated legacy alignments. New filename: '%s'", filename)
        elif not extension:
            filename = "{}.{}".format(filename, self.serializer.file_extension)
            # Reformat legacy alignments file
            filename = self.update_file_format(folder, filename)
            logger.debug("Updated legacy alignments. New filename: '%s'", filename)
        elif not extension:
            filename = "{}.{}".format(filename, self.serializer.file_extension)
            # Reformat legacy alignments file
            filename = self.update_file_format(folder, filename)
            logger.debug("Updated legacy alignments. New filename: '%s'", filename)
        elif not extension:
            filename = "{}.{}".format(filename, self.serializer.file_extension)
              logger.debug("File extension set from serializer: '%s'",
                           self.serializer.file_extension)
          logger.verbose("Alignments filepath: '%s'", location)
          return location
  
keep keep keep keep replace replace replace replace replace replace keep keep keep keep keep
 Legacy alignments update

- Remove legacy update hashes
- Remove legacy job from alignment-tools
- Remove legacy landmark rotation
- Add rotate face method to plugins/extract/detect
- Update travis test for new alignments extension
- Alignments format to .fsa
- Remove serializer option from alignments-tool
- Auto update legacy format alignment files to new format 
lib/alignments.py