コード例 #1
0
ファイル: rpnDateTime.py プロジェクト: GaelicGrime/rpn
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' )
コード例 #2
0
ファイル: rpnGeometry.py プロジェクト: GaelicGrime/rpn
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))
コード例 #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' )
コード例 #4
0
ファイル: rpnValidator.py プロジェクト: GaelicGrime/rpn
    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
コード例 #5
0
ファイル: rpnPhysics.py プロジェクト: GaelicGrime/rpn
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 )
コード例 #6
0
ファイル: rpnChemistry.py プロジェクト: GaelicGrime/rpn
def calculateMolarMass(n):
    result = 0

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

    return RPNMeasurement(result, 'gram')
コード例 #7
0
ファイル: rpnMath.py プロジェクト: GaelicGrime/rpn
def performTrigOperation(i, operation):
    if isinstance(i, RPNMeasurement):
        value = mpf(i.convertValue(RPNMeasurement(1, {'radian': 1})))
    else:
        value = i

    return operation(value)
コード例 #8
0
ファイル: rpnMath.py プロジェクト: GaelicGrime/rpn
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)
コード例 #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' )
コード例 #10
0
ファイル: rpnMath.py プロジェクト: GaelicGrime/rpn
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)
コード例 #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')
コード例 #12
0
ファイル: rpnMeasurement.py プロジェクト: GaelicGrime/rpn
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)
コード例 #13
0
ファイル: rpnDateTime.py プロジェクト: GaelicGrime/rpn
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 )
コード例 #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' )
コード例 #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 )
コード例 #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' )
コード例 #17
0
ファイル: rpnMeasurement.py プロジェクト: GaelicGrime/rpn
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 ]
コード例 #18
0
ファイル: rpnMeasurement.py プロジェクト: GaelicGrime/rpn
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
コード例 #19
0
ファイル: rpnMath.py プロジェクト: GaelicGrime/rpn
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)
コード例 #20
0
ファイル: rpnGeometry.py プロジェクト: GaelicGrime/rpn
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')
コード例 #21
0
ファイル: rpnGeometry.py プロジェクト: GaelicGrime/rpn
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')
コード例 #22
0
ファイル: rpnMath.py プロジェクト: GaelicGrime/rpn
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)
コード例 #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}])
コード例 #24
0
ファイル: rpnPhysics.py プロジェクト: GaelicGrime/rpn
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 )
コード例 #25
0
ファイル: rpnDateTime.py プロジェクト: GaelicGrime/rpn
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
コード例 #26
0
ファイル: rpnList.py プロジェクト: GaelicGrime/rpn
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 )
コード例 #27
0
ファイル: rpnDateTime.py プロジェクト: GaelicGrime/rpn
def calculatePentecostSundayOperator( year ):
    return RPNDateTime( *( calculateEaster( year ).add( RPNMeasurement( 7, 'weeks' ) ).getYMD( ) ),
                        dateOnly = True )
コード例 #28
0
ファイル: rpnDateTime.py プロジェクト: GaelicGrime/rpn
def calculateAdventOperator( year ):
    firstAdvent = getChristmasDay( year ).add( RPNMeasurement( -3, 'week' ) )
    firstAdvent = firstAdvent.subtract( RPNMeasurement( getWeekday( firstAdvent ), 'day'  ) )

    return RPNDateTime( *firstAdvent.getYMD( ), dateOnly = True )
コード例 #29
0
ファイル: rpnDateTime.py プロジェクト: GaelicGrime/rpn
def calculateGoodFridayOperator( year ):
    '''2 days before Easter'''
    goodFriday = calculateEaster( year ).add( RPNMeasurement( -2, 'day' ) )
    return RPNDateTime( *goodFriday.getYMD( ), dateOnly = True )
コード例 #30
0
ファイル: rpnDateTime.py プロジェクト: GaelicGrime/rpn
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 )