          var_t = ((flm[6][1] - flm[8][1]) + (flm[10][1] - flm[8][1])) / 2.0
          var_b = flm[8][1]
          return var_b - var_t
  
      @staticmethod
      def calc_landmarks_face_yaw(flm):
          """ Calculate the amount of yaw in a face """
          var_l = ((flm[27][0] - flm[0][0])
                   + (flm[28][0] - flm[1][0])
                   + (flm[29][0] - flm[2][0])) / 3.0
          var_r = ((flm[16][0] - flm[27][0])
                   + (flm[15][0] - flm[28][0])
                   + (flm[14][0] - flm[29][0])) / 3.0
          return var_r - var_l
  
      @staticmethod
      def set_process_file_method(log_changes, keep_original):
          """
          Assigns the final file processing method based on whether changes are
 
</s> remove     @staticmethod
    def set_process_file_method(log_changes, keep_original):
        """
        Assigns the final file processing method based on whether changes are
        being logged and whether the original files are being kept in the
        input directory.
        Relevant cli arguments: -k, -l
        :return: function reference
 </s> add         These are files which are sorted but not binned, so just the filename gets updated </s> remove         if metadata is not None:
            alignments = metadata["alignments"]
            det_face = DetectedFace()
            det_face.from_png_meta(alignments)
            aln_face = AlignedFace(np.array(alignments["landmarks_xy"], dtype="float32"),
                                   image=image,
                                   centering="legacy",
                                   size=256,
                                   is_aligned=True)
            mask = det_face.mask["components"]
            mask.set_sub_crop(aln_face.pose.offset[mask.stored_centering],
                              aln_face.pose.offset["legacy"],
                              centering="legacy")
            mask = cv2.resize(mask.mask, (256, 256), interpolation=cv2.INTER_CUBIC)[..., None]
            image = np.minimum(aln_face.face, mask)
        if image.ndim == 3:
            image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        height, width = image.shape
        c_height, c_width = (int(height / 2.0), int(width / 2.0))
        fft = np.fft.fft2(image)
        fft_shift = np.fft.fftshift(fft)
        fft_shift[c_height - 75:c_height + 75, c_width - 75:c_width + 75] = 0
        ifft_shift = np.fft.ifftshift(fft_shift)
        shift_back = np.fft.ifft2(ifft_shift)
        magnitude = np.log(np.abs(shift_back))
        score = np.mean(magnitude)
        return score

    @staticmethod
    def calc_landmarks_face_pitch(flm):
        """ UNUSED - Calculate the amount of pitch in a face """
        var_t = ((flm[6][1] - flm[8][1]) + (flm[10][1] - flm[8][1])) / 2.0
        var_b = flm[8][1]
        return var_b - var_t
 </s> add         is_rename = self._args.sort_method != "none"

        logger.info("Creating %s group folders in '%s'.",
                    len(self._sorter.binned), self._args.output_dir)
        bin_names = [f"_{b}" for b in self._sorter.bin_names]
        if is_rename:
            bin_names = [f"{name}_by_{self._args.sort_method}" for name in bin_names]
        for name in bin_names:
            folder = os.path.join(self._args.output_dir, name)
            if os.path.exists(folder):
                rmtree(folder)
            os.makedirs(folder)

        description = f"{'Copying' if self._args.keep_original else 'Moving'} into groups"
        description += " and renaming" if is_rename else ""

        pbar = tqdm(range(len(self._sorter.sorted_filelist)),
                    desc=description,
                    file=sys.stdout,
                    leave=False)
        idx = 0
        for bin_id, bin_ in enumerate(self._sorter.binned):
            pbar.set_description(f"{description}: Bin {bin_id + 1} of {len(self._sorter.binned)}")
            output_path = os.path.join(self._args.output_dir, bin_names[bin_id])
            if not bin_:
                logger.debug("Removing empty bin: %s", output_path)
                os.rmdir(output_path)
            for source in bin_:
                basename = os.path.basename(source)
                dst_name = f"{idx:06d}_{basename}" if is_rename else basename
                dest = os.path.join(output_path, dst_name)
                self._sort_file(source, dest)
                idx += 1
                pbar.update(1) </s> remove     @staticmethod
    def get_avg_score_faces_cnn(fl1, references):
        """ Return the average CNN similarity score
            between a face and reference image """
        scores = []
        for fl2 in references:
            score = np.sum(np.absolute((fl2 - fl1).flatten()))
            scores.append(score)
        return sum(scores) / len(scores)
 </s> add             self._sort_file(source, dest) </s> remove     def sorted_similarity(self, predictions, method="ward"):
        """ Sort a matrix of predictions by similarity.
 </s> add  </s> remove         result_linkage = func(predictions, **kwargs)
        result_order = self._seriation(result_linkage,
                                       num_predictions,
                                       num_predictions + num_predictions - 2)
        return result_order
 </s> add     @classmethod
    def _integer_iterator(cls) -> Generator[int, None, None]:
        """ Iterator that just yields consecutive integers """
        i = -1
        while True:
            i += 1
            yield i
    # Output methods
    def _output_non_grouped(self) -> None:
        """ Output non-grouped files.
          var_t = ((flm[6][1] - flm[8][1]) + (flm[10][1] - flm[8][1])) / 2.0
          var_b = flm[8][1]
          return var_b - var_t
  
    # Output methods
    def _output_non_grouped(self) -> None:
        """ Output non-grouped files.
    # Output methods
    def _output_non_grouped(self) -> None:
        """ Output non-grouped files.
    # Output methods
    def _output_non_grouped(self) -> None:
        """ Output non-grouped files.
    # Output methods
    def _output_non_grouped(self) -> None:
        """ Output non-grouped files.
    # Output methods
    def _output_non_grouped(self) -> None:
        """ Output non-grouped files.
    # Output methods
    def _output_non_grouped(self) -> None:
        """ Output non-grouped files.
    # Output methods
    def _output_non_grouped(self) -> None:
        """ Output non-grouped files.
    # Output methods
    def _output_non_grouped(self) -> None:
        """ Output non-grouped files.
    # Output methods
    def _output_non_grouped(self) -> None:
        """ Output non-grouped files.
    # Output methods
    def _output_non_grouped(self) -> None:
        """ Output non-grouped files.
  
      @staticmethod
      def set_process_file_method(log_changes, keep_original):
          """
          Assigns the final file processing method based on whether changes are
keep keep keep keep replace replace replace replace replace replace replace replace replace replace keep keep keep keep keep
 Overhaul sort:
  - Standardize image data reading and writing
  - Optimize loading (just one pass required)
  - Make all sort groups binnable (to greater or lesser results)
  - Add sort by pitch
  - Deprecate multiple options
  - linting, docs + locales 
tools/sort/sort.py