          if folder:
              logger.verbose("Alignments file exists at '%s'", alignments_file)
          return folder, filename
  
      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)
  
      def save(self):
          """ Backup copy of old alignments and save new alignments """
          self.backup()
          super().save()
  
 
</s> remove             logger.info("Using extracted pngs for alignments")
 </s> add             logger.info("Using extracted DFL faces for alignments") </s> remove             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))
 </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) </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 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  </s> remove     def get_dest_format(self):
        """ Set the destination format for Alignments """
        dest_format = None
        if hasattr(self.args, 'alignment_format') and self.args.alignment_format:
            dest_format = self.args.alignment_format
        logger.debug(dest_format)
        return dest_format

 </s> add 
          if folder:
              logger.verbose("Alignments file exists at '%s'", alignments_file)
          return folder, filename
  

































      def save(self):
          """ Backup copy of old alignments and save new alignments """
          self.backup()
          super().save()
  
keep keep keep keep replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace 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 
tools/lib_alignments/media.py