def getPlanetsForDatetimeAndTimezone(dt, locTuple): """Returns a string with the planet longitude position for the given datetime and timezone. """ locName = locTuple[0] locLongitude = locTuple[1] locLatitude = locTuple[2] locElevation = locTuple[3] # Set the Location (required). Ephemeris.setGeographicPosition(locLongitude, locLatitude, locElevation) longitudeType = "tropical" fieldName = "longitude" rv = "For datetime: " + Ephemeris.datetimeToDayStr(dt) + \ ", location: " + locName + endl for planetName in geocentricPlanetNames: pi = Ephemeris.getPlanetaryInfo(planetName, dt) longitude = pi.geocentric[longitudeType][fieldName] # Format differently for lunation phase of G.MoSu. if planetName == "MoSu": rv += " {: <14}".format("G." + planetName + ": ") + \ "{:>.3f}".format(longitude) + \ " Phase (of max 30): {:.2f}".format(longitude / 12.0) + \ endl else: rv += " {: <14}".format("G." + planetName + ": ") + \ "{:>.3f}".format(longitude) + \ endl rv += endl for planetName in heliocentricPlanetNames: pi = Ephemeris.getPlanetaryInfo(planetName, dt) rv += " {: <14}".format("H." + planetName + ": ") + \ "{:>.3f}".format(pi.heliocentric[longitudeType][fieldName]) + \ endl return rv
def getFieldValue(dt, planetParams, fieldName): """Creates the PlanetaryInfo object for the given planetParamsList and returns the value of the field desired. """ log.debug("planetParams passed in is: {}".\ format(planetParams)) t = planetParams planetName = t[0] centricityType = t[1] longitudeType = t[2] pi = Ephemeris.getPlanetaryInfo(planetName, dt) log.debug("Planet {} has geo sid longitude: {}".\ format(planetName, pi.geocentric["sidereal"]["longitude"])) fieldValue = None if centricityType.lower() == "geocentric": fieldValue = pi.geocentric[longitudeType][fieldName] elif centricityType.lower() == "topocentric": fieldValue = pi.topocentric[longitudeType][fieldName] elif centricityType.lower() == "heliocentric": fieldValue = pi.heliocentric[longitudeType][fieldName] else: log.error("Unknown centricity type: {}".\ format(centricityType)) fieldValue = None return fieldValue
def getFieldValue(dt, planetParamsList, fieldName): """Creates the PlanetaryInfo object for the given planetParamsList and returns the value of the field desired. """ log.debug("planetParamsList passed in is: {}".\ format(planetParamsList)) unAveragedFieldValues = [] for t in planetParamsList: planetName = t[0] centricityType = t[1] longitudeType = t[2] pi = Ephemeris.getPlanetaryInfo(planetName, dt) log.debug("Planet {} has geo sid longitude: {}".\ format(planetName, pi.geocentric["sidereal"]["longitude"])) fieldValue = None if centricityType.lower() == "geocentric": fieldValue = pi.geocentric[longitudeType][fieldName] elif centricityType.lower() == "topocentric": fieldValue = pi.topocentric[longitudeType][fieldName] elif centricityType.lower() == "heliocentric": fieldValue = pi.heliocentric[longitudeType][fieldName] else: log.error("Unknown centricity type: {}".\ format(centricityType)) fieldValue = None unAveragedFieldValues.append(fieldValue) log.debug("unAveragedFieldValues is: {}".\ format(unAveragedFieldValues)) # Average the field values. total = 0.0 for v in unAveragedFieldValues: total += v averagedFieldValue = total / len(unAveragedFieldValues) log.debug("averagedFieldValue is: {}".\ format(averagedFieldValue)) return averagedFieldValue
def getGeocentricPlanetDirectRetrogradeInfo(planetName): """ Returns a list of tuples, each tuple containing: (planetName, julianDay, datetime, "R" or "D", geoTropLongitudeOfPlanet, geoSidLongitudeOfPlanet) """ # Return value. rv = [] prevDt = None currDt = copy.deepcopy(startDt) prevTropLongitudeSpeed = None currTropLongitudeSpeed = None currTropLongitude = None currSidLongitude = None while currDt <= endDt: dt = currDt pi = Ephemeris.getPlanetaryInfo(planetName, dt) log.debug("Just obtained planetaryInfo for planet '{}', timestamp: {}".\ format(planetName, Ephemeris.datetimeToStr(dt))) # Get the geocentric longitude and geocentric longitude speed. tropLongitudeSpeed = pi.geocentric['tropical']['longitude_speed'] tropLongitude = pi.geocentric['tropical']['longitude'] sidLongitude = pi.geocentric['sidereal']['longitude'] # Store new current planet values. currTropLongitudeSpeed = tropLongitudeSpeed currTropLongitude = tropLongitude currSidLongitude = sidLongitude log.debug("prevTropLongitudeSpeed={}, currTropLongitudeSpeed={}".\ format(prevTropLongitudeSpeed, currTropLongitudeSpeed)) # We need two data points to proceed. if prevTropLongitudeSpeed != None and \ currTropLongitudeSpeed != None and \ prevDt != None: # Check to see if we passed over 0 degrees. if prevTropLongitudeSpeed < 0.0 and currTropLongitudeSpeed >= 0.0: # Crossed over from negative to positive! log.debug("Crossed over from negative to positive!") # This is the upper-bound of the error timedelta. t1 = prevDt t2 = currDt currErrorTd = t2 - t1 # Refine the timestamp until it is less than the # desired threshold. while currErrorTd > maxErrorTd: log.debug("Refining between {} and {}".\ format(Ephemeris.datetimeToStr(t1), Ephemeris.datetimeToStr(t2))) # Check the timestamp between. diffTd = t2 - t1 halfDiffTd = \ datetime.\ timedelta(days=(diffTd.days / 2.0), seconds=(diffTd.seconds / 2.0), microseconds=(diffTd.microseconds / 2.0)) testDt = t1 + halfDiffTd pi = Ephemeris.getPlanetaryInfo(planetName, testDt) testTropLongitudeSpeed = \ pi.geocentric['tropical']['longitude_speed'] testTropLongitude = pi.geocentric['tropical']['longitude'] testSidLongitude = pi.geocentric['sidereal']['longitude'] if testTropLongitudeSpeed >= 0.0: t2 = testDt # Update the curr values as the later boundary. currDt = t2 currTropLongitudeSpeed = testTropLongitudeSpeed currTropLongitude = testTropLongitude currSidLongitude = testSidLongitude else: t1 = testDt currErrorTd = t2 - t1 # Broke out of while loop, meaning we have a timestamp # within our threshold. # Create a tuple to add to our list. tup = (planetName, Ephemeris.datetimeToJulianDay(currDt), currDt, directStr, currTropLongitude, currSidLongitude) # Append to the list. rv.append(tup) elif prevTropLongitudeSpeed > 0.0 and currTropLongitudeSpeed <= 0.0: # Crossed over from positive to negative! log.debug("Crossed over from positive to negative!") # This is the upper-bound of the error timedelta. t1 = prevDt t2 = currDt currErrorTd = t2 - t1 # Refine the timestamp until it is less than the # desired threshold. while currErrorTd > maxErrorTd: log.debug("Refining between {} and {}".\ format(Ephemeris.datetimeToStr(t1), Ephemeris.datetimeToStr(t2))) # Check the timestamp between. diffTd = t2 - t1 halfDiffTd = \ datetime.\ timedelta(days=(diffTd.days / 2.0), seconds=(diffTd.seconds / 2.0), microseconds=(diffTd.microseconds / 2.0)) testDt = t1 + halfDiffTd pi = Ephemeris.getPlanetaryInfo(planetName, testDt) testTropLongitudeSpeed = \ pi.geocentric['tropical']['longitude_speed'] testTropLongitude = pi.geocentric['tropical']['longitude'] testSidLongitude = pi.geocentric['sidereal']['longitude'] if testTropLongitudeSpeed <= 0.0: t2 = testDt # Update the curr values as the later boundary. currDt = t2 currTropLongitudeSpeed = testTropLongitudeSpeed currTropLongitude = testTropLongitude currSidLongitude = testSidLongitude else: t1 = testDt currErrorTd = t2 - t1 # Broke out of while loop, meaning we have a timestamp # within our threshold. # Create a tuple to add to our list. tup = (planetName, Ephemeris.datetimeToJulianDay(currDt), currDt, retrogradeStr, currTropLongitude, currSidLongitude) # Append to the list. rv.append(tup) # Increment currDt timestamp. prevDt = currDt currDt = currDt + stepSizeTd # Move the previous currTropLongitudeSpeed to prevTropLongitudeSpeed. prevTropLongitudeSpeed = currTropLongitudeSpeed currTropLongitudeSpeed = None currTropLongitude = None currSidLongitude = None log.debug("prevTropLongitudeSpeed={}, currTropLongitudeSpeed={}".\ format(prevTropLongitudeSpeed, currTropLongitudeSpeed)) return rv
currDt = startDt prevDt = None while currDt < endDt: # See if this is a new month. if prevDt == None or prevDt.month != currDt.month: log.info("Processing: {} {}".\ format(Util.monthNumberToAbbrev(currDt.month), currDt.year)) # Add the text for a new table. text += getTableHeaderText(currDt) planetaryInfosDict = {} for planetName in planetNames: pi = Ephemeris.getPlanetaryInfo(planetName, currDt) planetaryInfosDict[planetName] = pi dateStr = formatToDateStr(currDt) # Add text for a row in the table. text += convertPlanetaryInfosToLine(dateStr, planetaryInfosDict) # Prepare currDt for the next iteration. prevDt = currDt currDt = copy.deepcopy(currDt) + datetime.timedelta(days=1) currDt = currDt.replace(hour=hourOfDay, minute=minuteOfHour) if prevDt.month != currDt.month: # Month passed. Close the table. text += getTableFooterText()
# - planetName1TropicalLongitude_ZodiacSignFormat # - planetName2TropicalLongitude_ZodiacSignFormat # - planetName1TropicalLongitudeLongitudeSpeed # - planetName2TropicalLongitudeLongitudeSpeed # - planetName1SiderealLongitude_Degrees # - planetName2SiderealLongitude_Degrees # - planetName1SiderealLongitude_ZodiacSignFormat # - planetName2SiderealLongitude_ZodiacSignFormat # - planetName1SiderealLongitudeLongitudeSpeed # - planetName2SiderealLongitudeLongitudeSpeed resultList = [] # Create a tuple for each timestamp that was found # that was a conjunction. for dt in conjunctionTimestamps: pi1 = Ephemeris.getPlanetaryInfo(planetName1, dt) pi2 = Ephemeris.getPlanetaryInfo(planetName2, dt) tup = (comboPlanetName, Ephemeris.datetimeToJulianDay(dt), dt, desiredAspectDegree, pi1.heliocentric["tropical"]["longitude"], pi2.heliocentric["tropical"]["longitude"], pi1.heliocentric["tropical"]["longitude_speed"], pi2.heliocentric["tropical"]["longitude_speed"], pi1.heliocentric["sidereal"]["longitude"], pi2.heliocentric["sidereal"]["longitude"], pi1.heliocentric["sidereal"]["longitude_speed"], pi2.heliocentric["sidereal"]["longitude_speed"])
def getLongitudeDiffBetweenDatetimes(planetName, centricityType, dt1, loc1Tuple, dt2, loc2Tuple): startTimestamp = dt1 endTimestamp = dt2 loc1Name = loc1Tuple[0] loc1Longitude = loc1Tuple[1] loc1Latitude = loc1Tuple[2] loc1Elevation = loc1Tuple[3] loc2Name = loc2Tuple[0] loc2Longitude = loc2Tuple[1] loc2Latitude = loc2Tuple[2] loc2Elevation = loc2Tuple[3] # maxErrorTd - datetime.timedelta object holding the maximum # time difference between the exact planetary # timestamp for the phenomena, and the one # calculated. This would define the accuracy of # the calculations. # maxErrorTd = datetime.timedelta(seconds=4) # Size of a circle, in degrees. # # Here we define our own value instead of using the value in # AstrologyUtils.degreesInCircle because it is possible we may # want to test different sizes of a 'circle'. circleSizeInDegrees = 360.0 # All references to longitude_speed need to # be from tropical zodiac measurements! If I use # sidereal zodiac measurements for getting the # longitude_speed, then the measurements from the # Swiss Ephemeris do not yield the correct values. # I use the following variable in these locations. zodiacTypeForLongitudeSpeed = "tropical" tropicalZodiacFlag = True # Text to set in the text item. text = "" # Total number of degrees elapsed. totalDegrees = 0 Ephemeris.setGeographicPosition(loc1Longitude, loc1Latitude, loc1Elevation) # List of PlanetaryInfo objects for this particular # planet, sorted by timestamp. planetData = [] # Step size to use in populating the data list with # PlanetaryInfos. # # The step size should cause the planet to move less # than 120 degrees in all cases, and idealy much less # than this, that way we can easily narrow down when # the planet passes the 0 degree or 360 degree # threshold, and also so it is easier to narrow down # when retrograde periods happen. If the step size is # too large, it is possible that we would miss a whole # time window of retrograde movement, so discretion # has to be used in determining what to use for this value. # # Here we will set it to 1 day for the default case, # but if the planet name is a house cusp then shrink # the step size so we will get the correct resolution. # Also, if the planet name is an outer planet with a # large period, we can increase the step size slightly # to improve performance. stepSizeTd = datetime.timedelta(days=1) if Ephemeris.isHouseCuspPlanetName(planetName) or \ Ephemeris.isAscmcPlanetName(planetName): stepSizeTd = datetime.timedelta(hours=1) elif planetName == "Jupiter" or \ planetName == "Saturn" or \ planetName == "Neptune" or \ planetName == "Uranus" or \ planetName == "Pluto": stepSizeTd = datetime.timedelta(days=5) log.debug("Stepping through from {} to {} ...".\ format(Ephemeris.datetimeToStr(startTimestamp), Ephemeris.datetimeToStr(endTimestamp))) # Current datetime as we step through all the # timestamps between the start and end timestamp. currDt = copy.deepcopy(startTimestamp) # Step through the timestamps, calculating the planet positions. while currDt < endTimestamp: p = Ephemeris.getPlanetaryInfo(planetName, currDt) planetData.append(p) # Increment step size. currDt += stepSizeTd # We must also append the planet calculation for the end timestamp. Ephemeris.setGeographicPosition(loc2Longitude, loc2Latitude, loc2Elevation) p = Ephemeris.getPlanetaryInfo(planetName, endTimestamp) planetData.append(p) # Geocentric measurement. if centricityType == "geocentric": # Get the PlanetaryInfos for the timestamps of the # planet at the moment right after the # longitude_speed polarity changes. additionalPlanetaryInfos = [] prevLongitudeSpeed = None for i in range(len(planetData)): currLongitudeSpeed = \ planetData[i].geocentric[zodiacTypeForLongitudeSpeed]['longitude_speed'] if prevLongitudeSpeed != None and \ ((prevLongitudeSpeed < 0 and currLongitudeSpeed >= 0) or \ (prevLongitudeSpeed >= 0 and currLongitudeSpeed < 0)): # Polarity changed. # Try to narrow down the exact moment in # time when this occured. t1 = planetData[i-1].dt t2 = planetData[i].dt currErrorTd = t2 - t1 while currErrorTd > maxErrorTd: if log.isEnabledFor(logging.DEBUG) == True: log.debug("Refining between {} and {}".\ format(Ephemeris.datetimeToStr(t1), Ephemeris.datetimeToStr(t2))) # Check the timestamp between. diffTd = t2 - t1 halfDiffTd = \ datetime.\ timedelta(days=(diffTd.days / 2.0), seconds=(diffTd.seconds / 2.0), microseconds=(diffTd.\ microseconds / 2.0)) testDt = t1 + halfDiffTd p = Ephemeris.getPlanetaryInfo(planetName, testDt) testLongitudeSpeed = \ p.geocentric[zodiacTypeForLongitudeSpeed]['longitude_speed'] if ((prevLongitudeSpeed < 0 and \ testLongitudeSpeed >= 0) or \ (prevLongitudeSpeed >= 0 and \ testLongitudeSpeed < 0)): # Polarity change at the test timestamp. t2 = testDt else: # No polarity change yet. t1 = testDt # Update the currErrorTd. currErrorTd = t2 - t1 log.debug("Broke out of loop to find " + \ "velocity polarity change. " + \ "currErrorTd is: {}, ".\ format(currErrorTd)) # Timestamp at t2 is now within the amount # of the time error threshold ('maxErrorTd') # following the polarity change. # Append this value to the list. p = Ephemeris.getPlanetaryInfo(planetName, t2) additionalPlanetaryInfos.append(p) t1pi = planetData[i-1] t2pi = Ephemeris.getPlanetaryInfo(planetName, t2) if log.isEnabledFor(logging.DEBUG) == True: log.debug("t1 == {}, ".\ format(Ephemeris.datetimeToStr(t1pi.dt)) + \ "longitude(tropical) == {}, ".\ format(t1pi.geocentric['tropical']['longitude']) + \ "longitude(sidereal) == {}, ".\ format(t1pi.geocentric['sidereal']['longitude']) + \ "longitude_speed == {}, ".\ format(t1pi.geocentric[zodiacTypeForLongitudeSpeed]['longitude_speed'])) log.debug("t2 == {}, ".\ format(Ephemeris.datetimeToStr(t2pi.dt)) + \ "longitude(tropical) == {}, ".\ format(t2pi.geocentric['tropical']['longitude']) + \ "longitude(sidereal) == {}, ".\ format(t2pi.geocentric['sidereal']['longitude']) + \ "longitude_speed == {}, ".\ format(t2pi.geocentric[zodiacTypeForLongitudeSpeed]['longitude_speed'])) # There is no need to update # currLongitudeSpeed here, because the # longitude_speed for 'p' should be the # same polarity. # Update prevLongitudeSpeed. prevLongitudeSpeed = currLongitudeSpeed # Sort all the extra PlanetaryInfo objects by timestamp. additionalPlanetaryInfos = \ sorted(additionalPlanetaryInfos, key=lambda c: c.dt) # Insert PlanetaryInfos from # 'additionalPlanetaryInfos' into 'planetData' at # the timestamp-ordered location. currLoc = 0 for i in range(len(additionalPlanetaryInfos)): pi = additionalPlanetaryInfos[i] insertedFlag = False while currLoc < len(planetData): if pi.dt < planetData[currLoc].dt: planetData.insert(currLoc, pi) insertedFlag = True currLoc += 1 break else: currLoc += 1 if insertedFlag == False: # PlanetaryInfo 'pi' has a timestamp that # is later than the last PlanetaryInfo in # 'planetData', so just append it. planetData.append(pi) # Increment currLoc so that the rest of # the PlanetaryInfos in # 'additionalPlanetaryInfos' can be # appended without doing anymore timestamp tests. currLoc += 1 # Do summations to determine the measurements. showGeocentricRetroAsNegativeTextFlag = True if showGeocentricRetroAsNegativeTextFlag == True: if tropicalZodiacFlag == True: totalDegrees = 0 zodiacType = "tropical" for i in range(len(planetData)): if i != 0: prevPi = planetData[i-1] currPi = planetData[i] if prevPi.geocentric[zodiacTypeForLongitudeSpeed]['longitude_speed'] >= 0: # Direct motion. # Elapsed amount for this segment should be positive. # Find the amount of longitude elasped. longitudeElapsed = \ currPi.geocentric[zodiacType]['longitude'] - \ prevPi.geocentric[zodiacType]['longitude'] # See if there was a crossing of the # 0 degree point or the 360 degree point. # If so, make the necessary adjustments # so that the longitude elapsed is # correct. longitudeElapsed = \ Util.toNormalizedAngle(longitudeElapsed) totalDegrees += longitudeElapsed else: # Retrograde motion. # Elapsed amount for this segment should be negative. # Find the amount of longitude elasped. longitudeElapsed = \ currPi.geocentric[zodiacType]['longitude'] - \ prevPi.geocentric[zodiacType]['longitude'] # See if there was a crossing of the # 0 degree point or the 360 degree point. # If so, make the necessary adjustments # so that the longitude elapsed is # correct. if longitudeElapsed > 0: longitudeElapsed -= 360 totalDegrees += longitudeElapsed # Line of text. We append measurements to # this line of text depending on what # measurements are enabled. line = "G T {} moves ".format(planetName) numCircles = totalDegrees / circleSizeInDegrees numBiblicalCircles = \ totalDegrees / AstrologyUtils.degreesInBiblicalCircle line += "{:.2f} deg ".format(totalDegrees) # Append last part of the line. line += "(r as -)" text += line + os.linesep if centricityType == "heliocentric": if tropicalZodiacFlag == True: totalDegrees = 0 zodiacType = "tropical" for i in range(len(planetData)): if i != 0: prevPi = planetData[i-1] currPi = planetData[i] if prevPi.heliocentric[zodiacTypeForLongitudeSpeed]['longitude_speed'] >= 0: # Direct motion. # Elapsed amount for this segment should be positive. # Find the amount of longitude elasped. longitudeElapsed = \ currPi.heliocentric[zodiacType]['longitude'] - \ prevPi.heliocentric[zodiacType]['longitude'] # See if there was a crossing of the # 0 degree point or the 360 degree point. # If so, make the necessary adjustments # so that the longitude elapsed is # correct. longitudeElapsed = \ Util.toNormalizedAngle(longitudeElapsed) totalDegrees += longitudeElapsed else: # Retrograde motion. # Elapsed amount for this segment should be negative. # Find the amount of longitude elasped. longitudeElapsed = \ currPi.heliocentric[zodiacType]['longitude'] - \ prevPi.heliocentric[zodiacType]['longitude'] # See if there was a crossing of the # 0 degree point or the 360 degree point. # If so, make the necessary adjustments # so that the longitude elapsed is # correct. if longitudeElapsed > 0: longitudeElapsed -= 360 totalDegrees += longitudeElapsed # Line of text. We append measurements to # this line of text depending on what # measurements are enabled. line = "H T {} moves ".format(planetName) numCircles = totalDegrees / circleSizeInDegrees numBiblicalCircles = \ totalDegrees / AstrologyUtils.degreesInBiblicalCircle line += "{:.2f} deg ".format(totalDegrees) text += line + os.linesep text = text.rstrip() return totalDegrees