00001
00012 #ifdef _MSC_VER
00013 #include "msdevstudio/MSconfig.h"
00014 #endif
00015
00016 #include "binners/BinnerAxisLog.h"
00017
00018 #include <algorithm>
00019 #include <stdexcept>
00020
00021 #include <cmath>
00022 #include <cassert>
00023
00024
00025 #ifdef ITERATOR_MEMBER_DEFECT
00026 using namespace std;
00027 #else
00028 using std::max;
00029 using std::pow;
00030 using std::upper_bound;
00031 using std::vector;
00032 #endif
00033
00034 using namespace hippodraw;
00035
00036 BinnerAxisLog::
00037 BinnerAxisLog ()
00038 : BinnerAxis ( "BinnerLog" )
00039 {
00040 }
00041
00042 BinnerAxisLog::BinnerAxisLog ( const BinnerAxisLog & binner )
00043 : BinnerAxis ( binner ),
00044 bins ( binner.bins )
00045 {
00046 }
00047
00048 BinnerAxisLog::~BinnerAxisLog ()
00049 {
00050 }
00051
00052 BinnerAxis *
00053 BinnerAxisLog::clone ()
00054 {
00055 return new BinnerAxisLog ( *this );
00056 }
00057
00058 void
00059 BinnerAxisLog::axisSetNumberOfBins( int nb )
00060 {
00061 m_num_bins = nb;
00062 }
00063
00064 int
00065 BinnerAxisLog::axisBinNumber ( double x ) const
00066 {
00067 vector<double>::const_iterator it
00068 = upper_bound ( bins.begin(), bins.end(), x );
00069 int i = it - bins.begin();
00070 if( i < 1 ) i = 0;
00071 if ( i > m_num_bins ) i = m_num_bins + 1;
00072
00073 return i;
00074 }
00075
00076 double
00077 BinnerAxisLog::
00078 getCoordinate ( int i ) const
00079 {
00080 assert ( i < m_num_bins && !( i < 0 ) );
00081
00082 double low = bins[i];
00083 double high = bins[i+1];
00084
00085 return sqrt(low*high);
00086 }
00087
00088 double
00089 BinnerAxisLog::axisBinWidth ( int bins_number) const
00090 {
00091 bins_number = std::min ( bins_number, m_num_bins -1 );
00092 bins_number = std::max ( bins_number, 0 );
00093
00094 double width = bins[bins_number+1] - bins[bins_number];
00095 assert ( width >= 0.0 );
00096
00097 return width;
00098 }
00099
00100
00101 double
00102 BinnerAxisLog::getConstWid ( ) const
00103 {
00104 return m_width;
00105 }
00106
00107 double
00108 BinnerAxisLog::
00109 getBinWidth ( ) const
00110 {
00111 return m_width;
00112 }
00113
00114 void
00115 BinnerAxisLog::setConstWid ( )
00116 {
00117 m_width = calcWidthParm ( m_num_bins );
00118 }
00119
00120 double
00121 BinnerAxisLog::calcWidthParm ( int num_bins ) const
00122 {
00123 double width_parm = 0;
00124 double low = m_range.low();
00125 double high = m_range.high();
00126 width_parm = log10 ( high / low ) / num_bins;
00127
00128 return width_parm;
00129 }
00130
00131 void
00132 BinnerAxisLog::setBins ()
00133 {
00134 double low = m_range.low ();
00135 assert ( low > 0.0 );
00136
00137 vector<double>::iterator it = bins.begin();
00138 *it++ = low;
00139
00140 for ( int i = 1; it != bins.end(); ++it, i++ ) {
00141 *it = low * pow ( 10.0, i * m_width );
00142 }
00143 }
00144
00145 const Range &
00146 BinnerAxisLog::
00147 setRange ( const Range & range, bool hold_width )
00148 {
00149 m_range = range;
00150
00151 if ( hold_width ) {
00152 m_num_bins = getNob ( range );
00153 }
00154 else {
00155 m_width = calcWidthParm ( m_num_bins );
00156 }
00157
00158 double low = m_range.low ();
00159 double high = 1.0;
00160 if (low <= 0) {
00161 low = m_range.high()/pow(10., m_num_bins*m_width);
00162 m_range.setLow(low);
00163 } else {
00164 high = low * pow ( 10.0, m_num_bins * m_width );
00165 m_range.setHigh(high);
00166 }
00167
00168 if (high <= 0) {
00169 throw std::runtime_error("BinnerAxisLog::Range: attempt to set range "
00170 "to negative values.");
00171 }
00172
00173 bins.resize( m_num_bins + 1, 0.0 );
00174 setBins();
00175
00176 return m_range;
00177 }
00178
00179 const Range &
00180 BinnerAxisLog::setBinWidth ( double wid )
00181 {
00182 assert ( wid > 0.0 );
00183
00184 m_width = wid;
00185 m_num_bins = getNob ( m_width );
00186
00187 double low = m_range.low ();
00188 double high = low * pow ( 10.0, m_num_bins * wid );
00189 m_range.setHigh ( high );
00190 bins.resize( m_num_bins + 1, 0.0 );
00191 setBins();
00192
00193 return m_range;
00194 }
00195
00196 double
00197 BinnerAxisLog::calcOffset ( int parm, bool dragging ) const
00198 {
00199 setStartRange ( dragging );
00200
00201 return ( parm - 50 ) / 50.0;
00202 }
00203
00206 double
00207 BinnerAxisLog::getOffset () const
00208 {
00209 return m_offset;
00210 }
00211
00212 const void
00213 BinnerAxisLog::setOffset ( double offset )
00214 {
00215 double oldoff = m_offset;
00216 m_offset = offset;
00217 double change = m_offset - oldoff;
00218
00219 if( offset == 0.0 ) return;
00220 double low = m_range_start.low ();
00221 double width = low * pow ( 10.0, m_width );
00222 double woffset = width * change;
00223 double new_low = low * pow ( 10.0, woffset * m_width );
00224 double new_high = new_low * pow ( 10.0, ( bins.size() -1 ) * m_width );
00225
00226 Range r( new_low, new_high );
00227 setRange( r );
00228 }
00229
00230 double
00231 BinnerAxisLog::scaleFactorWid ( )
00232 {
00233 return 1.0;
00234 }
00235
00236 int BinnerAxisLog::getNob ( const Range & range ) const
00237 {
00238 double low = range.low ();
00239 double high = range.high ();
00240 int tmp = static_cast< int > ( ceil ( log10 ( high/low ) /
00241 m_width ) );
00242
00243 return tmp ? tmp : 1;
00244 }
00245
00246 int BinnerAxisLog::getNob ( double wid ) const
00247 {
00248 double low = m_range.low ();
00249 double high = m_range.high ();
00250 int tmp = static_cast < int > ( ceil ( log10 ( high/low ) /
00251 wid ) );
00252 return tmp ? tmp : 1;
00253 }