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