def round_N ( value , n ) : """Round value to to N-digits >>> new_value = round_N ( value , 3 ) """ assert isinstance ( n , integer_types ) and 0 <= n,\ "round_N: invalid ``n'' %s (must be non-negative integer)" % n ## return cpp_round_N ( value , n ) v = float ( value ) if 0 == v : return 0 a , b = frexp10 ( v ) e = b - 1 m = a * 10 ni = n - 1 f1 = 10 ** ni f2 = 1 if ni < e : f2 = ( 10 ** ( e - ni ) ) elif ni > e : f2 = 1.0/( 10 ** ( ni - e ) ) return round ( m * f1 ) * float ( f2 )
def _frexp10_ ( value ) : """Get ``mantissa'' (1<=m<10) and exponent for radix10 similar for frexp, but use radix=10 >>> m , e = _frexp10_ ( value ) """ m , e = frexp10 ( value ) return m * 10 , e-1
def pretty_2ve(value, eh, el, width=8, precision=6): assert isinstance ( value , num_types ),\ 'Invalid value parameter %s/%s' % ( value , type ( value ) ) assert isinstance ( eh , num_types ),\ 'Invalid eh parameter %s/%s' % ( eh , type ( eh ) ) assert isinstance ( el , num_types ),\ 'Invalid el parameter %s/%s' % ( el , type ( el ) ) v = value e = max(abs(eh), abs(el)) assert isinstance ( width , integer_types ) and \ isinstance ( precision , integer_types ) and 2 <= precision < width, \ "Invalid width/precision parameters %s/%s" % ( width , precision ) assert 0 <= eh or 0 <= el, 'Both errors cannot be negative!' if eh < 0 and el < 0: eh, el = el, eh elif eh >= 0 and el < 0: eh, el = eh, abs(el) av = max(abs(v), e) if 100 <= av < 1000: fmt2 = '( %%+%d.%df +/%%-%d.%df -/%%-%d.%df )' % ( width, precision - 2, width, precision - 2, width, precision - 2) return fmt2 % (v, eh, el), None elif 10 <= av < 100: fmt1 = '( %%+%d.%df +/%%-%d.%df -/%%-%d.%df )' % ( width, precision - 1, width, precision - 1, width, precision - 1) return fmt1 % (v, eh, el), None elif 1 <= av < 10: fmt0 = '( %%+%d.%df +/%%-%d.%df -/%%-%d.%df )' % ( width, precision, width, precision, width, precision) return fmt0 % (v, eh, el), None from ostap.math.base import frexp10 v_a, v_e = frexp10(av) v /= 10**(v_e - 1) eh /= 10**(v_e - 1) el /= 10**(v_e - 1) v_e -= 1 n, r = divmod(v_e, 3) if 0 != r: r -= 3 n += 1 v *= 10**r eh *= 10**r el *= 10**r fmt0 = '( %%+%d.%df +/%%-%d.%df -/%%-%d.%df )' % ( width, precision, width, precision, width, precision) return fmt0 % (v, eh, el), 3 * n
def three_digits ( value ) : """Get three first significant digits >>> nums = three_digits ( value ) """ # if not 0.1<= abs ( value ) < 1 : value = frexp10 ( float ( value ) ) [0] # return int ( round ( float ( value ) * 1000 , 0 ) )
def fmt_pretty_float(value, width=8, precision=6): """Format for nice printout of the floating number - return format for nice string and the separate exponent >>> fmt , n = fmt_pretty_float ( number ) """ from ostap.core.ostap_types import integer_types, num_types assert isinstance ( value , num_types ),\ 'Invalid value parameter %s/%s' % ( value , type ( value ) ) ## not finite? from ostap.math.base import isfinite if not isfinite(value): return "%s", 0 assert isinstance ( width , integer_types ) and \ isinstance ( precision , integer_types ) and 2 <= precision < width, \ "Invalid width/precision parameters %s/%s" % ( width , precision ) v = value av = abs(v) if 100 <= av < 1000: fmt2 = '%%+%d.%df' % (width, precision - 2) return fmt2, 0 elif 10 <= av < 100: fmt1 = '%%+%d.%df' % (width, precision - 1) return fmt1, 0 elif 1 <= av < 10: fmt0 = '%%+%d.%df' % (width, precision) return fmt0, 0 elif 0.1 <= av < 1: fmt0 = '%%+%d.%df' % (width, precision) return fmt0, 0 from ostap.math.base import frexp10, iszero if iszero(av): fmt0 = '%%+%d.%df' % (width, precision) return fmt0, 0 v_a, v_e = frexp10(v) if 0 == v_e and iszero(v_a): fmt0 = '%%+0%d.%df' % (width, precision) return fmt0, 0 v_a *= 10 v_e -= 1 n, r = divmod(v_e, 3) ra = v_a * (10**r) fmt, p = fmt_pretty_float(ra, width, precision) return fmt, p + 3 * n
def pretty_ve(value, width=8, precision=6): """Nice printout of the ValueWithError obejct ( string + exponent) - return nice stirng and the separate exponent >>> s , n = pretty_ve ( number ) """ from ostap.math.ve import VE v = value.value() e = max(0, value.error()) assert isinstance(value, VE), 'Invalid type for value %s' % value assert isinstance ( width , integer_types ) and \ isinstance ( precision , integer_types ) and 2 <= precision < width, \ "Invalid width/precision parameters %s/%s" % ( width , precision ) av = max(abs(v), e) if 100 <= av < 1000: fmt2 = '( %%+%d.%df +/- %%-%d.%df )' % (width, precision - 2, width, precision - 2) return fmt2 % (v, e), None elif 10 <= av < 100: fmt1 = '( %%+%d.%df +/- %%-%d.%df )' % (width, precision - 1, width, precision - 1) return fmt1 % (v, e), None elif 1 <= av < 10: fmt0 = '( %%+%d.%df +/- %%-%d.%df )' % (width, precision, width, precision) return fmt0 % (v, e), None from ostap.math.base import frexp10 v_a, v_e = frexp10(av) v /= 10**(v_e - 1) e /= 10**(v_e - 1) v_e -= 1 n, r = divmod(v_e, 3) if 0 != r: r -= 3 n += 1 v *= 10**r e *= 10**r fmt0 = '( %%+%d.%df +/- %%-%d.%df )' % (width, precision, width, precision) return fmt0 % (v, e), 3 * n
def pretty_float(value, width=8, precision=6): """N Nice printout of the floating number - return nice string and the separate exponent >>> s , n = pretty_float ( number ) """ assert isinstance ( value , num_types ),\ 'Invalid value parameter %s/%s' % ( value , type ( value ) ) assert isinstance ( width , integer_types ) and \ isinstance ( precision , integer_types ) and 2 <= precision < width, \ "Invalid width/precision parameters %s/%s" % ( width , precision ) v = value av = abs(v) if 100 <= av < 1000: fmt2 = '%%+%d.%df' % (width, precision - 2) return fmt2 % v, None elif 10 <= av < 100: fmt1 = '%%+%d.%df' % (width, precision - 1) return fmt1 % v, None elif 1 <= av < 10: fmt0 = '%%+%d.%df' % (width, precision) return fmt0 % v, None from ostap.math.base import frexp10 v_a, v_e = frexp10(av) v_a *= 10 v_e -= 1 n, r = divmod(v_e, 3) if 0 != r: r -= 3 n += 1 ra = v_a * (10**r) fmt0 = '%%+%d.%df' % (width, precision) return fmt0 % (ra), 3 * n
def pdg_format3( value , error1 , error2 , error3 , latex = False , mode = 'total' ) : """Round value/error accoridng to PDG prescription and format it for print @see http://pdg.lbl.gov/2010/reviews/rpp2010-rev-rpp-intro.pdf @see section 5.3 of doi:10.1088/0954-3899/33/1/001 Quote: The basic rule states that if the three highest order digits of the error lie between 100 and 354, we round to two significant digits. If they lie between 355 and 949, we round to one significant digit. Finally, if they lie between 950 and 999, we round up to 1000 and keep two significant digits. In all cases, the central value is given with a precision that matches that of the error. >>> value, error1, error2 = ... >>> print ' Rounded value/error is %s ' % pdg_format2 ( value , error1 , error2 , True ) """ if isinstance ( mode , str ) : mode = mode.lower() ## if mode in ( 'min' , 'mn' ) : error = min ( abs ( error1 ) , abs ( error2 ) , abs ( error3 ) ) elif mode in ( 'max' , 'mx' ) : error = max ( abs ( error1 ) , abs ( error2 ) , abs ( error3 ) ) elif mode in ( 'total' , 'tot' ) : error = math.sqrt ( 1.0 * error1 * error1 + error2 * error2 + error3 * error3 ) else : ## use the default policy error = math.sqrt ( 1.0 * error1 * error1 + error2 * error2 + error3 * error3 ) ## round value, error and get the scaling factor v , e , q , c = pdg_round__ ( value , error ) v_ , e1 , q_ , _ = pdg_round__ ( value , error1 ) v_ , e2 , q_ , _ = pdg_round__ ( value , error2 ) v_ , e3 , q_ , _ = pdg_round__ ( value , error3 ) ## get scaling factors for printout qv , bv = frexp10 ( value ) n = int ( math.floor ( bv / 3. ) ) short = ( 0 == n ) or ( 1 == n and abs(v) < 10000 ) or ( -1 == n and abs(v) > 0.1 ) if not short : q = 3 - ( q % 3 ) if c == 3 and q == 3 : q = 1 elif c == 2 and q == 3 : q = 0 if latex : fmt = "$(%%.%df \pm %%.%df \pm %%.%df \pm %%.%df)\cdot10^{%%d}$" % ( q , q , q , q ) else : fmt = "(%%.%df +/- %%.%df +/- %%.%df +/- %%.%df)*10^{%%d}" % ( q , q , q , q ) v /= 10**(3*n) e1 /= 10**(3*n) e2 /= 10**(3*n) e3 /= 10**(3*n) ## return fmt % ( v , e1 , e2 , e3 , n*3 ) else : q = abs ( q ) if latex : fmt = "$%%.%df \pm %%.%df \pm %%.%df \pm %%.%df$" % ( q , q , q , q ) else : fmt = "%%.%df +/- %%.%df +/- %%.%df +/- %%.%df" % ( q , q , q , q ) ## return fmt % ( v , e1 , e2 , e3 )
def fmt_pretty_2ve ( value , eh , el , width = 8 , precision = 6 , parentheses = True ) : from ostap.math.ve import VE from ostap.core.ostap_types import integer_types, num_types assert isinstance ( value , num_types ),\ 'Invalid value parameter %s/%s' % ( value , type ( value ) ) assert isinstance ( eh , num_types ),\ 'Invalid eh parameter %s/%s' % ( eh , type ( eh ) ) assert isinstance ( el , num_types ),\ 'Invalid el parameter %s/%s' % ( el , type ( el ) ) v = value e = max ( abs ( eh ), abs ( el ) ) assert isinstance ( width , integer_types ) and \ isinstance ( precision , integer_types ) and 2 <= precision < width, \ "Invalid width/precision parameters %s/%s" % ( width , precision ) assert 0 <= eh or 0 <= el, 'Both errors cannot be negative!' if eh < 0 and el < 0 : eh , el = el , eh elif eh >= 0 and el < 0 : eh , el = eh , abs ( el ) av = max ( abs ( v ) , e ) if 100 <= av < 1000 : fmtv = '%%+%d.%df' % ( width , precision - 2 ) fmte = '%%-%d.%df' % ( width , precision - 2 ) fmt = '%%+%d.%df +/%%-%d.%df -/%%-%d.%df' % ( width , precision - 2 , width , precision - 2 , width , precision - 2 ) if parentheses : fmt = '( ' + fmt + ' )' return fmt , fmtv , fmte , 0 elif 10 <= av < 100 : fmtv = '%%+%d.%df' % ( width , precision - 1 ) fmte = '%%-%d.%df' % ( width , precision - 1 ) fmt = '%%+%d.%df +/%%-%d.%df -/%%-%d.%df' % ( width , precision - 1 , width , precision - 1 , width , precision - 1 ) if parentheses : fmt = '( ' + fmt + ' )' return fmt , fmtv , fmte , 0 elif 1 <= av < 10 : fmtv = '%%+%d.%df' % ( width , precision ) fmte = '%%-%d.%df' % ( width , precision ) fmt = '%%+%d.%df +/%%-0%d.%df -/%%-%d.%df' % ( width , precision , width , precision , width , precision ) if parentheses : fmt = '( ' + fmt + ' )' return fmt , fmtv , fmte , 0 elif 0.1 <= av < 1 : fmtv = '%%+%d.%df' % ( width , precision ) fmte = '%%-%d.%df' % ( width , precision ) fmt = '%%+%d.%df +/%%-0%d.%df -/%%-%d.%df' % ( width , precision , width , precision , width , precision ) if parentheses : fmt = '( ' + fmt + ' )' return fmt , fmtv , fmte , 0 from ostap.math.base import frexp10, iszero if iszero ( av ) : fmtv = '%%+%d.%df' % ( width , precision ) fmte = '%%-%d.%df' % ( width , precision ) fmt = '%%+%d.%df +/%%-%d.%df -/%%-%d.%df' % ( width , precision , width , precision , width , precision ) if parentheses : fmt = '( ' + fmt + ' )' return fmt , fmtv , fmte , 0 v_a , v_e = frexp10 ( av ) v /= 10**(v_e-1) eh /= 10**(v_e-1) el /= 10**(v_e-1) v_e -= 1 n , r = divmod ( v_e , 3 ) v *= 10**r eh *= 10**r el *= 10**r fmt , fmtv , fmte , p = fmt_pretty_2ve ( v , eh , el , width , precision , parentheses ) return fmt , fmtv , fmte , p + 3 * n
def fmt_pretty_ve ( value , width = 8 , precision = 6 , parentheses = True ) : """Formats for nice printout of the ValueWithError object ( string + exponent) - return formats for nice stirng and the separate exponent >>> fmt , fmt_v , fmt_e , n = pretty_ve ( number ) """ from ostap.math.ve import VE from ostap.core.ostap_types import integer_types v = value.value () e = max ( 0 , value.error () ) assert isinstance ( value , VE ), 'Invalid type for value %s' % value assert isinstance ( width , integer_types ) and \ isinstance ( precision , integer_types ) and 2 <= precision < width, \ "Invalid width/precision parameters %s/%s" % ( width , precision ) av = max ( abs ( v ) , e ) if 100 <= av < 1000 : fmtv = '%%+%d.%df' % ( width , precision - 2 ) fmte = '%%-%d.%df' % ( width , precision - 2 ) fmt = '%%+%d.%df +/- %%-%d.%df' % ( width , precision - 2 , width , precision - 2 ) if parentheses : fmt = '( ' + fmt + ' )' return fmt , fmtv , fmte , 0 elif 10 <= av < 100 : fmtv = '%%+%d.%df' % ( width , precision - 1 ) fmte = '%%-%d.%df' % ( width , precision - 1 ) fmt = '%%+%d.%df +/- %%-%d.%df' % ( width , precision - 1 , width , precision - 1 ) if parentheses : fmt = '( ' + fmt + ' )' return fmt , fmtv , fmte , 0 elif 1 <= av < 10 : fmtv = '%%+%d.%df' % ( width , precision ) fmte = '%%-%d.%df' % ( width , precision ) fmt = '%%+%d.%df +/- %%-%d.%df' % ( width , precision , width , precision ) if parentheses : fmt = '( ' + fmt + ' )' return fmt , fmtv , fmte , 0 elif 0.1 <= av < 1 : fmtv = '%%+%d.%df' % ( width , precision ) fmte = '%%-%d.%df' % ( width , precision ) fmt = '%%+%d.%df +/- %%-%d.%df' % ( width , precision , width , precision ) if parentheses : fmt = '( ' + fmt + ' )' return fmt , fmtv , fmte , 0 from ostap.math.base import frexp10, iszero if iszero ( av ) : fmtv = '%%+%d.%df' % ( width , precision ) fmte = '%%-%d.%df' % ( width , precision ) fmt = '%%+%d.%df +/- %%-%d.%df' % ( width , precision , width , precision ) if parentheses : fmt = '( ' + fmt + ' )' return fmt , fmtv , fmte , 0 v_a , v_e = frexp10 ( av ) v /= 10**(v_e-1) e /= 10**(v_e-1) v_e -= 1 n , r = divmod ( v_e , 3 ) v *= 10**r e *= 10**r fmt , fmtv , fmte , p = fmt_pretty_ve ( VE ( v , e * e ) , width, precision , parentheses ) return fmt , fmtv , fmte , p + 3 * n