contrib/brl/bbas/bsta/bsta_spherical_histogram.h
Go to the documentation of this file.
00001 // This is brl/bbas/bsta/bsta_spherical_histogram.h
00002 #ifndef bsta_spherical_histogram_h_
00003 #define bsta_spherical_histogram_h_
00004 //:
00005 // \file
00006 // \brief A 2-d histogram with bins defined on a unit sphere
00007 // \author Joseph L. Mundy
00008 // \date May 3, 2011
00009 //
00010 // A histogram on the sphere. There are a number of popular choices for
00011 // spherical coordinates and units that are handled. The units for angle
00012 // can be either degrees or radians. Also there are many choices for
00013 // coordinate systems on the sphere. For example in geographic coordinates
00014 // the North and South poles are at +-90 degrees. Also the azimuthal angle
00015 // can exhibit the range 0 -> 360 or -180 -> 180, with discontinuities in
00016 // the angle coordinate (a branch cut). The latter choice of branch cut is used
00017 // for geographic coordinates where positive azimuths are East of Greenwich,
00018 // England. More typically for physics applications the elevation is 0 at the
00019 // North pole of the sphere and increases to 180 degrees at the South pole, with// the azimuthal range 0 -> 360. Note that azimuth is undefined at the
00020 // North and South poles and a special elevation bin centered at the poles
00021 // is needed. The current implementation does not include such a pole bin.
00022 //
00023 // The histogram is implemented as a map on the linear coordinate derived
00024 // from azimuth and elevation indices. Bins with zero count are not
00025 // present in the map.
00026 //
00027 // Methods are provided for the mean and covariance matrix of the histogram
00028 // distribution. The mean is derived from the mean Cartesian vector
00029 // of points on the unit sphere corresponding to the populated bin centers.
00030 // Covariance is computed on angle differences and so is valid only in the
00031 // tangent plane to the unit sphere at the mean.
00032 //
00033 // \verbatim
00034 //  Modifications
00035 //   (none yet)
00036 // \endverbatim
00037 //
00038 //
00039 
00040 #include <vcl_map.h>
00041 #include <vcl_vector.h>
00042 #include <vcl_iostream.h>
00043 #include <vnl/vnl_math.h>
00044 #include <vnl/vnl_matrix_fixed.h>
00045 //: A histogram on the unit sphere
00046 template <class T>
00047 class bsta_spherical_histogram
00048 {
00049  public:
00050   enum ang_units {RADIANS, DEG};
00051   enum angle_bounds {B_0_360, B_180_180, B_0_180, B_90_90};
00052   bsta_spherical_histogram();
00053   bsta_spherical_histogram(unsigned n_azimuth, unsigned n_elevation,
00054                            T azimuth_start, T azimuth_range,
00055                            T elevation_start, T elevation_range,
00056                            ang_units units = DEG,
00057                            angle_bounds az_branch_cut = B_180_180,
00058                            angle_bounds el_poles = B_90_90);
00059 
00060   ~bsta_spherical_histogram() {}
00061 
00062   //: angle units e.g. RADIANS, DEG
00063   ang_units units() const {return units_;}
00064   //: discontinuity azimuthal angle coordinates
00065   angle_bounds azimuth_branch_cut() const {return az_branch_cut_;}
00066   //: location of north and south poles on the sphere
00067   angle_bounds elevation_poles() const {return el_poles_;}
00068 
00069   //: number of bins allowed
00070   unsigned n_azimuth() const {return n_azimuth_;}
00071   unsigned n_elevation() const {return n_elevation_;}
00072 
00073   //: indices for individual spherical coordinates
00074   int azimuth_index(T azimuth) const;
00075   int elevation_index(T elevation) const;
00076   //: 1-d linear indices
00077   int linear_index(int azimuth_index, int elevation_index) const
00078     {return elevation_index*n_azimuth_ + azimuth_index;}
00079   //: function name different since T could be int
00080   int lin_index(T azimuth, T elevation)
00081     {return linear_index(azimuth_index(azimuth), elevation_index(elevation));}
00082 
00083   //: azimuth bounds
00084   T azimuth_start() const;
00085   T azimuth_range() const;
00086 
00087   //: elevation bounds
00088   T elevation_start() const;
00089   T elevation_range() const;
00090 
00091   void azimuth_interval(int azimuth_index, T& azimuth_start, T& azimuth_range) const;
00092   void azimuth_interval(T azimuth, T& azimuth_start, T& azimuth_range) const {
00093     int az_ind = azimuth_index(azimuth);
00094     azimuth_interval(az_ind, azimuth_start, azimuth_range);}
00095 
00096   void elevation_interval(int  elevation_index,
00097                           T& elevation_start, T& elevation_range) const;
00098 
00099   void elevation_interval(T elevation, T& elevation_start, T& elevation_range) const{
00100   int el_ind = elevation_index(elevation);
00101   elevation_interval(el_ind, elevation_start, elevation_range);}
00102 
00103   T azimuth_center(int azimuth_index) const;
00104   T elevation_center(int elevation_index) const;
00105   void center(int linear_index, T& az_center, T& el_center);
00106 
00107   //: increment the count in a given bin by mag
00108   void upcount(T azimuth, T elevation, T mag = T(1.0));
00109 
00110   //: weight the increment by spherical area of the bin, i.e. mag/sin(el)
00111   void upcount_weighted_by_area(T azimuth, T elevation, T mag = T(1.0));
00112 
00113   //: counts in a specified bin
00114   T counts (int azimuth_index, int elevation_index) {
00115     if (azimuth_index>=0&&azimuth_index<=static_cast<int>(n_azimuth())&&
00116        elevation_index>=0&&elevation_index<=static_cast<int>(n_elevation())) {
00117       int lidx = linear_index(azimuth_index,elevation_index);
00118       if (counts_[lidx])
00119         return counts_[lidx];
00120     }
00121  return T(0);
00122   }
00123   T counts(T azimuth, T elevation)  {
00124     int az_ind = azimuth_index(azimuth);
00125     int el_ind = elevation_index(elevation);
00126     return counts(az_ind, el_ind);
00127   }
00128 
00129   T counts(int linear_index) {return counts_[linear_index];}
00130 
00131   //:total number of counts, cached so non-const
00132   T total_counts();
00133 
00134   //: probability of a bin
00135   T p(int azimuth_index, int elevation_index) ;
00136   T p(T azimuth, T elevation)
00137   {
00138     int az_ind = azimuth_index(azimuth),el_ind = elevation_index(elevation);
00139     return p(az_ind, el_ind);
00140   }
00141 
00142   //: mean of histogram distribution
00143   void mean(T& mean_az, T& mean_el);
00144 
00145   //: covariance matrix of histogram cvar = [(az-mu_az)][(az-mu_az) (el-mu_el)]
00146   //                                        [(el-mu_el)]
00147   vnl_matrix_fixed<T, 2, 2> covariance_matrix();
00148 
00149   //: marginal standard deviations
00150   void std_dev(T& std_dev_az, T& std_dev_el);
00151 
00152   //: linear index of bins which have centers lying inside the cone
00153   vcl_vector<int> bins_intersecting_cone(T center_az, T center_el,
00154                                          T cone_half_angle);
00155 
00156 
00157   //:unit conversions
00158   static T deg_to_rad(T ang) {return static_cast<T>(vnl_math::pi_over_180*ang);}
00159   static T rad_to_deg(T ang) {return static_cast<T>(vnl_math::deg_per_rad*ang);}
00160 
00161   //:output of bin ranges and counts (zero counts not output)
00162   void write_counts_with_interval(vcl_ostream& os, int azimuth_index,
00163                                   int elevation_index);
00164   //:output of bin center and counts (zero counts not output)
00165   void write_counts_with_center(vcl_ostream& os, int azimuth_index,
00166                                 int elevation_index);
00167   //: write bin centers (azimuth elevation) and non_zero counts to stream
00168   void print_to_text(vcl_ostream& os);
00169 
00170   //: display counts in vrml with reference sphere
00171   void print_to_vrml(vcl_ostream& os, T transparency = T(0));
00172 
00173   //: convenient utilities
00174   void convert_to_cartesian(T azimuth, T elevation, T& x, T& y, T& z) const;
00175   void convert_to_spherical(T x, T y, T z, T& azimuth, T& elevation) const;
00176  private:
00177   //: members
00178   unsigned n_azimuth_;
00179   unsigned n_elevation_;
00180   T azimuth_start_;
00181   T azimuth_range_;
00182   T elevation_start_;
00183   T elevation_range_;
00184   T delta_az_;
00185   T delta_el_;
00186   angle_bounds az_branch_cut_;
00187   angle_bounds el_poles_;
00188   ang_units units_;
00189   bool total_counts_valid_;
00190   T total_counts_;
00191   vcl_map<int, T> counts_;
00192 };
00193 
00194 //: Write histogram to stream
00195 // \relatesalso bsta_spherical_histogram
00196 template <class T>
00197 vcl_ostream&  operator<<(vcl_ostream& s, bsta_spherical_histogram<T> const& h);
00198 
00199 //: Read histogram from stream
00200 // \relatesalso bsta_spherical_histogram
00201 template <class T>
00202 vcl_istream&  operator>>(vcl_istream& is,  bsta_spherical_histogram<T>& h);
00203 
00204 
00205 #endif // bsta_spherical_histogram_h_