Skip to content
Snippets Groups Projects
Select Git revision
  • 27d7aefebaf0d0ff9a45371a226663121a11fe3a
  • master default protected
  • control-single-hba-and-lba
  • stabilise-landing-page
  • all-stations-lofar2
  • L2SS-2357-fix-ruff
  • v0.39.7-backports
  • Move-sdptr-to-v1.5.0
  • fix-build-ubuntu
  • tokens-in-env-files
  • fix-build
  • L2SS-2214-deploy-cdb
  • fix-missing-init
  • add-power-hardware-apply
  • L2SS-2129-Add-Subrack-Routine
  • Also-listen-internal-to-rpc
  • fix-build-dind
  • L2SS-2153--Improve-Error-Handling
  • L2SS-2153-Add-Grpc-Gateway-support
  • L2SS-1970-apsct-lol
  • DNM-pytango10.0.1rc1-test
  • remove-snmp-client
  • v0.52.3 protected
  • v0.52.3dev0 protected
  • 0.53.1dev0
  • v0.52.2-rc3 protected
  • v0.52.2-rc2 protected
  • v0.52.2-rc1 protected
  • v0.52.1.1 protected
  • v0.52.1 protected
  • v0.52.1-rc1 protected
  • v0.51.9-6 protected
  • v0.51.9-5 protected
  • v0.51.9-4 protected
  • v0.51.9-3 protected
  • v0.51.9-2 protected
  • v0.51.9-1 protected
  • v0.51.9 protected
  • v0.51.8 protected
  • v0.39.15-wsrttwo protected
  • v0.39.15-wsrt protected
41 results

lofar_git.py

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    meanshift.cpp 5.09 KiB
    #include <iostream>
    #include <memory>
    #include <vector>
    #include <cmath>
    #include <pybind11/pybind11.h>
    #include <pybind11/numpy.h>
    
    
    namespace py = pybind11;
    typedef double cdt; // coordinate data type, float or double
    typedef std::vector<std::pair<cdt,cdt>> ctype; // type for coordinates
    
    class Grouper{
    
    public:
    Grouper() : _kernelSize(1.0), _numberOfIterations(10), _lookDistance(1.0), _groupingDistance(1.0){
    
    };
    void setKernelSize(double kernelSize){_kernelSize = kernelSize;}
    void setNumberOfIterations (int numberOfIterations){_numberOfIterations = numberOfIterations;}
    void setLookDistance (double lookDistance){_lookDistance = lookDistance;}
    void setGroupingDistance (double groupingDistance){_groupingDistance = groupingDistance;}
    void readCoordinates(py::array_t<cdt> array, py::array_t<cdt> farray); 
    void run();
    void group(py::list l);
    
    private:
    double gaussian_kernel(double distance);
     ctype _coordinates;
     std::vector<cdt> _fluxes;
     double _kernelSize;
     int _numberOfIterations;
     double _lookDistance;
     double _groupingDistance;
    
    };
    
    
    void Grouper::readCoordinates(py::array_t<cdt> array, py::array_t<cdt> farray){  
      auto arraybuf    = array.request();
      auto farraybuf = farray.request();
      cdt* coordinates = (cdt*) arraybuf.ptr;
      cdt* fluxes = (cdt*) farraybuf.ptr;
      if (arraybuf.ndim != 2 || arraybuf.shape[1] != 2){
        py::print("Grouper::readCoordinates: expected 2D array with two columns!");
      }
      if (farraybuf.ndim != 1){
        py::print("Grouper::readCoordinates: expected 1D array!");
      }
      unsigned N = arraybuf.shape[0];
      if (farraybuf.shape[0] != N){
        py::print("Grouper::readCoordinates: array of fluxes does not have the same length as array of coordinates!");
      }
      for (unsigned n=0; n<N; ++n){
        _coordinates.push_back(std::pair<cdt, cdt>(coordinates[2*n],coordinates[2*n+1]));
        _fluxes.push_back(fluxes[n]);  
      }
    
    }
    
    static double euclid_distance(std::pair<cdt, cdt> coordinate1, std::pair<cdt,cdt> coordinate2){
    // Euclidian distance between two points
      double result = 0.0;
      double distx = coordinate1.first - coordinate2.first;
      double disty = coordinate1.second - coordinate2.second;
      return sqrt(distx * distx + disty * disty);
    }
    
    static std::vector<unsigned> neighbourhood_points(std::pair<cdt,cdt> centroid, ctype coordinates, double max_distance){
    std::vector<unsigned> result;
      for (unsigned n=0; n<coordinates.size(); ++n){
        double distance = euclid_distance(centroid, coordinates[n]);
        if (distance < max_distance){
          result.push_back(n);
        }
      }
    return result;
    }
    
    double Grouper::gaussian_kernel(double distance){
    // Gaussian kernel
      double result = 1.0 / (_kernelSize * std::sqrt(2.0*3.14159265359));
      result *= std::exp(-0.5 * distance * distance / (_kernelSize * _kernelSize));
      return result;
    }
    
    void Grouper::run(){
      // run the algorithm
    
      if (_coordinates.size() == 0){
        py::print("Grouper::run: coordinates have not been read!");
      }
    
    
      ctype newcoords = _coordinates;
    
      for (unsigned it = 0; it < _numberOfIterations; ++it){
       py::print("starting iteration ", it); 
    #pragma omp parallel
        for (unsigned n=0; n<_coordinates.size(); ++n){
          std::vector<unsigned> idx_neighbours = neighbourhood_points(_coordinates[n], _coordinates, _lookDistance);
          double denominator = 0.0;
          double numx = 0.0;
          double numy = 0.0;
          for (auto i : idx_neighbours){
             double distance = euclid_distance(_coordinates[i], _coordinates[n]);
             double weight = gaussian_kernel(distance);
             weight *= _fluxes[i];
             numx += weight * _coordinates[i].first;
             numy += weight * _coordinates[i].second;
             denominator +=  weight;
          }
           newcoords[n] = std::pair<cdt,cdt>(numx/denominator, numy/denominator);
        }
        double maxdiff = 0.0;
        unsigned n=0;
        for (auto coordinate : _coordinates){
          double diff = euclid_distance(coordinate, newcoords[n]);
          if (diff > maxdiff){
            maxdiff = diff;
          }
          ++n; 
        }
        _coordinates = newcoords;    
        if ((it > 1) && (maxdiff < _groupingDistance / 2.0)){
          break;
        }
    
      } 
    
    
    }
    
    void Grouper::group(py::list l){
    
      ctype coords_to_check = _coordinates;
    
      while (coords_to_check.size() > 0){
        auto idx_cluster = neighbourhood_points(coords_to_check[0], _coordinates, _groupingDistance);
        auto idx_cluster_to_remove = neighbourhood_points(coords_to_check[0], coords_to_check, _groupingDistance);
        unsigned n = 0;
        for (auto idx : idx_cluster_to_remove){
          coords_to_check.erase(coords_to_check.begin() + idx - n);
          ++n;
        }
    
        py::list newcluster;
        for (auto idx : idx_cluster){
          newcluster.append(py::int_(idx));
        }
        l.append(newcluster);
    
      }
    }
    
    PYBIND11_MODULE(grouper, m)    
    {
      py::class_<Grouper>(m, "Grouper")
        .def(py::init<>())
        .def("run", &Grouper::run)
        .def("setKernelSize", &Grouper::setKernelSize)
        .def("setNumberOfIterations", &Grouper::setNumberOfIterations)
        .def("setLookDistance", &Grouper::setLookDistance)
        .def("setGroupingDistance", &Grouper::setGroupingDistance)
        .def("readCoordinates", &Grouper::readCoordinates)  
        .def("group", &Grouper::group)
    ;
    }
    
    
    int main(){
    
      Py_Initialize();
    
      return 0;
    }