/* coot-utils/peak-search.hh
 * 
 * Copyright 2004, 2005, 2006 by The University of York
 * Author: Paul Emsley
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or (at
 * your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc.,  51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA
 */

#ifndef HAVE_VECTOR
#include <vector>
#endif

#include <mmdb2/mmdb_manager.h>
#include "clipper/core/coords.h"
#include "clipper/core/xmap.h"
#include "clipper/contrib/skeleton.h"

namespace coot {

   class peak_search {
      float map_rms;
      clipper::Coord_orth move_grid_to_peak(const clipper::Xmap<float> &xmap,
                                            const clipper::Coord_grid &c_g);
      void peak_search_0(const clipper::Xmap<float> &xmap,
                         clipper::Xmap<short int> *marked_map_p,
                         float n_sigma) const;
      void peak_search_0_negative(const clipper::Xmap<float> &xmap,
                                  clipper::Xmap<short int> *marked_map_p,
                                  float n_sigma);
      // like above but more simple - no clustering.
      void peak_search_for_flooding(const clipper::Xmap<float> &xmap,
                                    clipper::Xmap<short int> *marked_map_p,
                                    float n_sigma) const;
      // As above, but give us all the peaks, not just the negative
      // ones.  e.g. if mean is 10 and min is 5, then we want to see
      // such minima.
      void peak_search_0_minima(const clipper::Xmap<float> &xmap,
                                clipper::Xmap<short int> *marked_map_p) const;

      void peak_search_1(const clipper::Xmap<float> &xmap,
                         clipper::Xmap<short int> *marked_map_p);
      void peak_search_2(const clipper::Xmap<float> &xmap,
                         clipper::Xmap<short int> *marked_map_p);

      void peak_search_trace_along(const clipper::Coord_grid &c_g_start,
                                   const clipper::Skeleton_basic::Neighbours &neighb,
                                   const clipper::Xmap<float> &xmap,
                                   clipper::Xmap<short int> *marked_map);
      void mask_around_coord(clipper::Xmap<float> *xmap,
                             const clipper::Coord_orth &co, float atom_radius) const;
      std::vector<clipper::Coord_orth>
      make_sample_protein_coords(mmdb::Manager *mol) const;
      std::vector<clipper::Coord_orth>
      make_sample_protein_coords(mmdb::Manager *mol, int every_n) const;
      clipper::Coord_orth
      move_point_close_to_protein(const clipper::Coord_orth &pt,
                                  const std::vector<clipper::Coord_orth> &protein,
                                  const std::vector<int> &itrans,
                                  const clipper::Xmap<float> &xmap) const;

      const std::vector<int>
      find_protein_to_origin_translations(const std::vector<clipper::Coord_orth> &sampled_protein_coords,
                                          const clipper::Xmap<float> &xmap) const;

      double
      min_dist_to_protein(const clipper::Coord_orth &point,
                          const std::vector<clipper::Coord_orth> &sampled_protein_coords) const;

      static bool compare_ps_peaks(const std::pair<clipper::Coord_orth, float> &a,
                                   const std::pair<clipper::Coord_orth, float> &b);
      static bool compare_ps_peaks_mri(const std::pair<clipper::Xmap<float>::Map_reference_index, float> &a,
                                       const std::pair<clipper::Xmap<float>::Map_reference_index, float> &b);
      static bool compare_ps_peaks_cg(const std::pair<clipper::Coord_grid, float> &a,
                                      const std::pair<clipper::Coord_grid, float> &b);

      std::vector<std::pair<clipper::Coord_orth, float> >
      filter_peaks_by_closeness(const std::vector<std::pair<clipper::Coord_orth, float> > &v) const;

      float max_closeness; // don't allow "smaller" peaks that are
                           // within max_closeness of a larger one.

      // kk elision
      std::pair<bool, clipper::Coord_orth> sym_shift_test(const clipper::Coord_orth &pt,
                                                          clipper::Spacegroup spacegroup,
                                                          clipper::Cell cell,
                                                          const clipper::Coord_orth &center,
                                                          float radius,
                                                          const std::vector<int> &iprotein_trans,
                                                          const clipper::Coord_orth &translated_center,
                                                          const clipper::RTop_orth &orthop_rev) const;

   public:
      peak_search(const clipper::Xmap<float> &xmap);
      std::vector<clipper::Coord_orth>
      get_peaks(const clipper::Xmap<float> &xmap,
                float n_sigma);
      std::vector<clipper::Coord_orth>
      get_peaks_for_flooding(const clipper::Xmap<float> &xmap,
                             float n_sigma);
      std::vector<std::pair<clipper::Xmap<float>::Map_reference_index, float> >
      get_peak_map_indices(const clipper::Xmap<float> &xmap,
                           float n_sigma) const;
      std::vector<std::pair<clipper::Coord_grid, float> >
      get_peak_grid_points(const clipper::Xmap<float> &xmap,
                           float n_sigma) const;
      std::vector<std::pair<clipper::Coord_grid, float> >
      get_minima_grid_points(const clipper::Xmap<float> &xmap,
                             float n_sigma) const;

      // return a list of peaks, together with the density level at
      // that position. but avoiding peaks where the molecule mol is.
      // Peaks list is returned sorted on abolute value of the
      // density.
      //
      std::vector<std::pair<clipper::Coord_orth, float> >
      get_peaks(const clipper::Xmap<float> &xmap,
                          mmdb::Manager *mol,
                          float n_sigma,
                          int do_positive_levels_flag,
                          int also_negative_levels_flag,
                int only_around_protein_flag);

      std::vector<std::pair<clipper::Coord_orth, float> >
      get_peaks(const clipper::Xmap<float> &xmap,
                         float n_sigma,
                         int do_positive_levels_flag,
                         int also_negative_levels_flag);

      std::vector<clipper::Coord_orth>
      get_peaks_from_list(const clipper::Xmap<float> &xmap,
                          const clipper::Coord_orth &center,
                          float radius,
                          const std::vector<clipper::Coord_orth> &peaks);

      void mask_map(clipper::Xmap<float> *xmap,
                    const std::vector<clipper::Coord_orth> &ps_peaks) const;

      void add_peak_vectors(std::vector<clipper::Coord_orth> *in,
                            const std::vector<clipper::Coord_orth> &extras) const;

      void set_max_closeness(float d) { max_closeness = d; }

   };
}

