Exemple #1
0
def calculateNthWeekdayOfYearOperator( year, nth, weekday ):
    ''' Monday = 1, etc., as per arrow, nth == -1 for last, etc.'''
    if isinstance( year, RPNDateTime ):
        year = year.year

    if nth > 0:
        firstDay = RPNDateTime( year, 1, 1 )

        firstWeekDay = weekday - firstDay.isoweekday( ) + 1

        if firstWeekDay < 1:
            firstWeekDay += 7

        result = RPNDateTime( year, 1, firstWeekDay ).add( RPNMeasurement( nth - 1, 'week' ) )
        result.setDateOnly( )

        return result

    if nth < 0:
        lastDay = RPNDateTime( year, 12, 31 )

        lastWeekDay = weekday - lastDay.isoweekday( )

        if lastWeekDay > 0:
            lastWeekDay -= 7

        lastWeekDay += 31

        result = RPNDateTime( year, 12, lastWeekDay, dateOnly = True ).add( RPNMeasurement( ( nth + 1 ), 'week' ) )
        result.setDateOnly( )

        return result

    raise ValueError( '0th weekday makes no sense in this context' )
Exemple #2
0
def getKSphereRadius(n, k):
    if k < 3:
        raise ValueError('the number of dimensions must be at least 3')

    if not isinstance(n, RPNMeasurement):
        return RPNMeasurement(n, 'meter')

    dimensions = n.getDimensions()

    if dimensions == {'length': 1}:
        return n

    if dimensions == {'length': int(k - 1)}:
        area = n.convertValue(RPNMeasurement(1, [{'meter': int(k - 1)}]))

        result = root(
            fdiv(fmul(area, gamma(fdiv(k, 2))), fmul(2, power(pi, fdiv(k,
                                                                       2)))),
            fsub(k, 1))

        return RPNMeasurement(result, [{'meter': 1}])

    if dimensions == {'length': int(k)}:
        volume = n.convertValue(RPNMeasurement(1, [{'meter': int(k)}]))

        result = root(
            fmul(fdiv(gamma(fadd(fdiv(k, 2), 1)), power(pi, fdiv(k, 2))),
                 volume), k)

        return RPNMeasurement(result, [{'meter': 1}])

    raise ValueError(
        'incompatible measurement type for computing the radius: ' +
        str(dimensions))
Exemple #3
0
    def getAzimuthAndAltitude( self, location=None, date=None ):
        if location and date:
            if isinstance( location, str ):
                location = getLocation( location )

            location.observer.date = date.to( 'utc' ).format( )
            self.object.compute( location.observer )

        return RPNMeasurement( mpmathify( self.object.az ), 'radians' ), \
               RPNMeasurement( mpmathify( self.object.alt ), 'radians' )
Exemple #4
0
    def validateLength(self, argument):
        if isinstance(argument, (complex, mpc, mpf, int, float)):
            self.validateReal(argument)
            argument = RPNMeasurement(argument, 'meter')
        elif isinstance(argument, RPNMeasurement):
            if argument.getDimensions() != {'length': 1}:
                raise ValueError('measurement argument must be a length')
        else:
            raise ValueError(
                f'\'type\' { type( argument ) } found, measurement (length) expected'
            )

        return argument
Exemple #5
0
def calculateWindChillOperator( measurement1, measurement2 ):
    '''
    https://www.ibiblio.org/units/dictW.html
    '''

    validUnitTypes = [
        [ 'velocity', 'temperature' ],
    ]

    arguments = matchUnitTypes( [ measurement1, measurement2 ], validUnitTypes )

    if not arguments:
        raise ValueError( '\'wind_chill\' requires velocity and temperature measurements' )

    windSpeed = arguments[ 'velocity' ].convert( 'miles/hour' ).value
    temperature = arguments[ 'temperature' ].convert( 'degrees_F' ).value

    if windSpeed < 3:
        raise ValueError( '\'wind_chill\' is not defined for wind speeds less than 3 mph' )

    if temperature > 50:
        raise ValueError( '\'wind_chill\' is not defined for temperatures over 50 degrees fahrenheit' )

    result = fsum( [ 35.74, fmul( temperature, 0.6215 ), fneg( fmul( 35.75, power( windSpeed, 0.16 ) ) ),
                     fprod( [ 0.4275, temperature, power( windSpeed, 0.16 ) ] ) ] )

    # in case someone puts in a silly velocity
    if result < -459.67:
        result = -459.67

    return RPNMeasurement( result, 'degrees_F' ).convert( arguments[ 'temperature' ].units )
Exemple #6
0
def calculateMolarMass(n):
    result = 0

    for atom in n:
        result = fadd(result, fmul(getAtomicWeight(atom), n[atom]))

    return RPNMeasurement(result, 'gram')
Exemple #7
0
def performTrigOperation(i, operation):
    if isinstance(i, RPNMeasurement):
        value = mpf(i.convertValue(RPNMeasurement(1, {'radian': 1})))
    else:
        value = i

    return operation(value)
Exemple #8
0
def multiply(n, k):
    if isinstance(n, RPNMeasurement):
        return n.multiply(k)

    if isinstance(k, RPNMeasurement):
        return RPNMeasurement(n).multiply(k)

    return fmul(n, k)
Exemple #9
0
def getDistanceFromSunOperator( arg1, arg2 ):
    validUnitTypes = [ [ 'body', 'datetime' ] ]
    arguments = matchUnitTypes( [ arg1, arg2 ], validUnitTypes )

    if not arguments:
        raise ValueError( 'unexpected arguments' )

    return RPNMeasurement( arguments[ 'body' ].getDistanceFromSun( arguments[ 'datetime' ] ), 'meters' )
Exemple #10
0
def divide(n, k):
    if isinstance(n, RPNMeasurement):
        return n.divide(k)

    if isinstance(k, RPNMeasurement):
        return RPNMeasurement(n).divide(k)

    return fdiv(n, k)
Exemple #11
0
def getTimeZoneOffset(value):
    if isinstance(value, str):
        try:
            tz = pytz.timezone(value)
        except:
            tz = pytz.timezone(getTimeZoneName(value))
    else:
        tz = pytz.timezone(getTimeZoneName(value))

    # compute the timezone's offset
    now = datetime.datetime.now()

    if tz:
        now1 = tz.localize(now)
        now2 = pytz.utc.localize(now)
        return RPNMeasurement((now2 - now1).total_seconds(), 'seconds')

    return RPNMeasurement(0, 'seconds')
Exemple #12
0
def convertUnits(unit1, unit2):
    if isinstance(unit1, RPNGenerator):
        unit1 = list(unit1)

        if len(unit1) == 1:
            unit1 = unit1[0]

    if isinstance(unit2, RPNGenerator):
        unit2 = list(unit2)

        if len(unit2) == 1:
            unit2 = unit2[0]

    if isinstance(unit1, list):
        result = []

        for unit in unit1:
            result.append(convertUnits(unit, unit2))

        return result

    if not isinstance(unit1, RPNMeasurement):
        raise ValueError('cannot convert non-measurements')

    if isinstance(unit2, list):
        return unit1.convertValue(unit2)

    if isinstance(unit2, (str, RPNUnits)):
        measurement = RPNMeasurement(1, unit2)
        return RPNMeasurement(unit1.convertValue(measurement), unit2)

    if not isinstance(unit2, (list, str, RPNUnits, RPNMeasurement)):
        raise ValueError('cannot convert non-measurements')

    debugPrint('convertUnits')
    debugPrint('unit1:', unit1.getUnitTypes())
    debugPrint('unit2:', unit2.getUnitTypes())

    newValue = unit1.convertValue(unit2)

    debugPrint('*** value:', newValue)

    return RPNMeasurement(newValue, unit2.units)
Exemple #13
0
def calculateAscensionThursdayOperator( year ):
    '''
I don't know why Ascension is 39 days after Easter instead of 40, but that's
how the math works out.  It's the 40th day of the Easter season.

Or as John Wright says, "Catholics can't count."  I think it stems from the
Church being created before the number 0.
    '''
    return RPNDateTime( *calculateEaster( year ).add( RPNMeasurement( 39, 'days' ) ).getYMD( ),
                        dateOnly = True )
Exemple #14
0
    def getAngularSeparation( self, other, location, date ):
        if isinstance( location, str ):
            location = getLocation( location )

        location.observer.date = date.to( 'utc' ).format( )

        self.object.compute( location.observer )
        other.object.compute( location.observer )

        return RPNMeasurement( mpmathify( ephem.separation( ( self.object.az, self.object.alt ),
                                                            ( other.object.az, other.object.alt ) ) ), 'radian' )
Exemple #15
0
def getConstant( name ):
    if name not in g.constantOperators:
        raise ValueError( 'Invalid constant: ', name )

    unit = g.constantOperators[ name ].unit
    value = g.constantOperators[ name ].value

    if unit == '':
        return mpmathify( value )

    return RPNMeasurement( value, unit )
Exemple #16
0
    def getAngularSize( self, location=None, date=None ):
        if location and date:
            if isinstance( location, str ):
                location = getLocation( location )

            location.observer.date = date.to( 'utc' ).format( )
            self.object.compute( location.observer )

        # I have no idea why size seems to return the value in arcseconds... that
        # goes against the pyephem documentation that it always uses radians for angles.
        return RPNMeasurement( mpmathify( fdiv( fmul( fdiv( self.object.size, 3600 ), pi ), 180 ) ), 'radian' )
Exemple #17
0
def estimateOperator(measurement):
    if not isinstance(measurement, RPNMeasurement):
        raise TypeError('incompatible type for estimating')

    unitType = None

    dimensions = measurement.getDimensions()

    for key, basicUnitType in g.basicUnitTypes.items():
        if dimensions == basicUnitType.dimensions:
            unitType = key
            break

    if unitType is None:
        return 'No estimates are available for this unit type'

    unitTypeInfo = g.basicUnitTypes[unitType]

    unit = RPNMeasurement(1, unitTypeInfo.baseUnit)
    value = RPNMeasurement(measurement.convertValue(unit), unit.units).value

    if not unitTypeInfo.estimateTable:
        return 'No estimates are available for this unit type (' + unitType + ').'

    matchingKeys = [key for key in unitTypeInfo.estimateTable if key <= value]

    if matchingKeys:
        estimateKey = max(matchingKeys)

        multiple = fdiv(value, estimateKey)

        return 'approximately ' + nstr( multiple, 3 ) + ' times ' + \
               unitTypeInfo.estimateTable[ estimateKey ]
    else:
        estimateKey = min(key for key in unitTypeInfo.estimateTable)

        multiple = fdiv(estimateKey, value)

        return 'approximately ' + nstr( multiple, 3 ) + ' times smaller than ' + \
               unitTypeInfo.estimateTable[ estimateKey ]
Exemple #18
0
def applyNumberValueToUnit(number, term, constant):
    if isinstance(term, RPNUnits):
        value = RPNMeasurement(number, term)
        value = value.normalizeUnits()

        if value.units == RPNUnits('_null_unit'):
            value = mpmathify(1)
    elif constant:
        if g.constantOperators[term].unit:
            value = RPNMeasurement(
                fmul(number, mpmathify(g.constantOperators[term].value)),
                g.constantOperators[term].unit)
        else:
            value = fmul(number, g.constantOperators[term].value)
    else:
        if g.unitOperators[term].unitType == 'constant':
            value = RPNMeasurement(number, term).convertValue(
                RPNMeasurement(1, {'unity': 1}))
        else:
            value = RPNMeasurement(number, term)

    return value
Exemple #19
0
def add(n, k):
    if isinstance(n, RPNDateTime) and isinstance(k, RPNMeasurement):
        return n.add(k)

    if isinstance(n, RPNMeasurement) and isinstance(k, RPNDateTime):
        return k.add(n)

    if isinstance(n, RPNMeasurement):
        return n.add(k)

    if isinstance(k, RPNMeasurement):
        return RPNMeasurement(n).add(k)

    return fadd(n, k)
Exemple #20
0
def getKSphereVolume(n, k):
    if not isinstance(n, RPNMeasurement):
        return getKSphereVolume(RPNMeasurement(n, 'meter'), k)

    dimensions = n.getDimensions()
    m = n.value

    if dimensions == {'length': 1}:
        m = n.convertValue(RPNMeasurement(1, [{'meter': 1}]))

        result = fmul(fdiv(power(pi, fdiv(k, 2)), gamma(fadd(fdiv(k, 2), 1))),
                      power(m, k))

        return RPNMeasurement(result, [{'meter': k}])

    if dimensions == {'length': int(k - 1)}:
        radius = getKSphereRadius(n, k)
        return getKSphereVolume(radius, k)

    if dimensions == {'length': int(k)}:
        return n

    raise ValueError('incompatible measurement type for computing the volume')
Exemple #21
0
def getKSphereSurfaceArea(n, k):
    if not isinstance(n, RPNMeasurement):
        return getKSphereSurfaceArea(n, RPNMeasurement(n, 'meter'))

    dimensions = n.getDimensions()

    if dimensions == {'length': 1}:
        m = n.convertValue(RPNMeasurement(1, [{'meter': 1}]))

        result = fmul(fdiv(fmul(power(pi, fdiv(k, 2)), 2), gamma(fdiv(k, 2))),
                      power(m, fsub(k, 1)))

        return RPNMeasurement(result, [{'meter': int(k - 1)}])

    if dimensions == {'length': int(k - 1)}:
        return n

    if dimensions == {'length': int(k)}:
        radius = getKSphereRadius(n, k)
        return getKSphereSurfaceArea(radius, k)

    raise ValueError(
        'incompatible measurement type for computing the surface area')
Exemple #22
0
def subtract(n, k):
    if isinstance(n, RPNDateTime):
        return n.subtract(k)

    if isinstance(n, RPNMeasurement):
        if isinstance(k, RPNDateTime):
            return k.subtract(n)

        return n.subtract(k)

    if isinstance(k, RPNMeasurement):
        return RPNMeasurement(n).subtract(k)

    return fsub(n, k)
Exemple #23
0
def getGeographicDistanceOperator(location1, location2):
    if isinstance(location1, str):
        location1 = getLocation(location1)

    if isinstance(location2, str):
        location2 = getLocation(location2)

    if not isinstance(location1, RPNLocation) or not isinstance(
            location2, RPNLocation):
        raise ValueError('two location arguments expected')

    distance = geodesic((location1.getLat(), location1.getLong()),
                        (location2.getLat(), location2.getLong())).miles

    return RPNMeasurement(distance, [{'miles': 1}])
Exemple #24
0
def calculateHeatIndexOperator( measurement1, measurement2 ):
    '''
    https://en.wikipedia.org/wiki/Heat_index#Formula
    '''
    # pylint: disable=invalid-name
    validUnitTypes = [
        [ 'temperature', 'constant' ],
    ]

    arguments = matchUnitTypes( [ measurement1, measurement2 ], validUnitTypes )

    if not arguments:
        raise ValueError( '\'heat_index\' requires a temperature measurement and the relative humidity in percent' )

    T = arguments[ 'temperature' ].convert( 'degrees_F' ).value
    R = arguments[ 'constant' ]

    if T < 80:
        raise ValueError( '\'heat_index\' is not defined for temperatures less than 80 degrees fahrenheit' )

    if R < 0.4 or R > 1.0:
        raise ValueError( '\'heat_index\' requires a relative humidity value ranging from 40% to 100%' )

    R = fmul( R, 100 )

    c1 = -42.379
    c2 = 2.04901523
    c3 = 10.14333127
    c4 = -0.22475541
    c5 = -6.83783e-3
    c6 = -5.481717e-2
    c7 = 1.22874e-3
    c8 = 8.5282e-4
    c9 = -1.99e-6

    heatIndex = fsum( [ c1, fmul( c2, T ), fmul( c3, R ), fprod( [ c4, T, R ] ), fprod( [ c5, T, T ] ),
                        fprod( [ c6, R, R ] ), fprod( [ c7, T, T, R ] ), fprod( [ c8, T, R, R ] ),
                        fprod( [ c9, T, T, R, R ] ) ] )

    return RPNMeasurement( heatIndex, 'fahrenheit' ).convert( arguments[ 'temperature' ].units )
Exemple #25
0
def makeJulianTime( n ):
    if isinstance( n, RPNGenerator ):
        return makeJulianTime( list( n ) )

    if len( n ) == 1:
        return RPNDateTime( n[ 0 ], 1, 1 )

    result = RPNDateTime( n[ 0 ], 1, 1 ).add( RPNMeasurement( n[ 1 ] - 1, 'day' ) )

    if len( n ) >= 3:
        result = result.replace( hour = n[ 2 ] )

    if len( n ) >= 4:
        result = result.replace( minute = n[ 3 ] )

    if len( n ) >= 5:
        result = result.replace( second = n[ 4 ] )

    if len( n ) >= 6:
        result = result.replace( microsecond = n[ 5 ] )

    return result
Exemple #26
0
def getProduct( n ):
    if isinstance( n, RPNGenerator ):
        return getProduct( list( n ) )

    if isinstance( n[ 0 ], ( list, RPNGenerator ) ):
        return [ getProduct( arg ) for arg in n ]

    if not n:
        return 0

    if len( n ) == 1:
        return n[ 0 ]

    hasUnits = False

    for item in n:
        if isinstance( item, RPNMeasurement ):
            hasUnits = True
            break

    if hasUnits:
        result = RPNMeasurement( 1 )

        for item in n:
            if isinstance( item, list ):
                return [ getProduct( arg ) for arg in item ]

            result = multiply( result, item )

        return result

    if not n:
        return 0

    if isinstance( n[ 0 ], list ):
        return [ getProduct( item ) for item in n ]

    return fprod( n )
Exemple #27
0
def calculatePentecostSundayOperator( year ):
    return RPNDateTime( *( calculateEaster( year ).add( RPNMeasurement( 7, 'weeks' ) ).getYMD( ) ),
                        dateOnly = True )
Exemple #28
0
def calculateAdventOperator( year ):
    firstAdvent = getChristmasDay( year ).add( RPNMeasurement( -3, 'week' ) )
    firstAdvent = firstAdvent.subtract( RPNMeasurement( getWeekday( firstAdvent ), 'day'  ) )

    return RPNDateTime( *firstAdvent.getYMD( ), dateOnly = True )
Exemple #29
0
def calculateGoodFridayOperator( year ):
    '''2 days before Easter'''
    goodFriday = calculateEaster( year ).add( RPNMeasurement( -2, 'day' ) )
    return RPNDateTime( *goodFriday.getYMD( ), dateOnly = True )
Exemple #30
0
def calculateAshWednesdayOperator( year ):
    '''46 days before Easter (40 days, not counting Sundays)'''
    ashWednesday = calculateEaster( year ).add( RPNMeasurement( -46, 'day' ) )
    return RPNDateTime( *ashWednesday.getYMD( ), dateOnly = True )