1
0
mirror of https://github.com/kmein/niveum synced 2026-03-16 18:21:07 +01:00
Files
niveum/packages/scripts/horoscope/transits.py

182 lines
5.6 KiB
Python

from flatlib import aspects, const
from flatlib.chart import Chart
from flatlib.datetime import Datetime
import pytz
from flatlib.geopos import GeoPos
import timezonefinder
import operator
import click
import itertools
from datetime import datetime, timedelta
tf = timezonefinder.TimezoneFinder()
planets = [
const.SUN,
const.MOON,
const.MERCURY,
const.VENUS,
const.MARS,
const.JUPITER,
const.SATURN,
const.URANUS,
const.NEPTUNE,
const.PLUTO,
]
planet_symbols = {
const.SUN: "",
const.MOON: "",
const.MERCURY: "",
const.VENUS: "",
const.MARS: "",
const.JUPITER: "",
const.SATURN: "",
const.URANUS: "",
const.NEPTUNE: "",
const.PLUTO: "",
}
aspect_symbols = {
const.NO_ASPECT: " ",
const.CONJUNCTION: "",
const.SEXTILE: "",
const.SQUARE: "",
const.TRINE: "",
const.OPPOSITION: "",
}
def convert_into_stupid_flatlib_format(dt):
return Datetime(
dt.strftime("%Y/%m/%d"),
dt.strftime("%H:%M"),
dt.utcoffset().total_seconds() / 3600,
)
here_latitude = 52.52
here_longitude = 13.4
def get_aspects(chart1, chart2, *, threshold):
for planet1 in chart1.objects:
for planet2 in chart2.objects:
aspect = aspects.getAspect(planet1, planet2, const.MAJOR_ASPECTS)
if aspect.exists() and aspect.orb <= threshold:
yield aspect
def get_chart(position, dt_naive):
timezone = pytz.timezone(tf.timezone_at(lat=position.lat, lng=position.lon))
dt_aware = timezone.localize(dt_naive)
return Chart(convert_into_stupid_flatlib_format(dt_aware), position, IDs=planets)
def show_aspect(aspect):
return " ".join(
[
planet_symbols[aspect.active.id],
aspect_symbols[aspect.type],
planet_symbols[aspect.passive.id],
]
)
@click.command()
@click.option("--natal-latitude", type=click.FLOAT, default=here_latitude)
@click.option("--natal-longitude", type=click.FLOAT, default=here_longitude)
@click.option("--natal-date", type=click.DateTime(), default=datetime.now())
@click.option("--transit-latitude", type=click.FLOAT, default=here_latitude)
@click.option("--transit-longitude", type=click.FLOAT, default=here_longitude)
@click.option("--transit-date", type=click.DateTime(), default=datetime.now())
@click.option("--threshold", type=click.FLOAT, default=5)
def forecast(
natal_latitude: float,
natal_longitude: float,
natal_date: datetime,
transit_latitude: float,
transit_longitude: float,
transit_date: datetime,
threshold: float,
):
transit_position = GeoPos(transit_latitude, transit_longitude)
natal_position = GeoPos(natal_latitude, natal_longitude)
natal_chart = get_chart(natal_position, natal_date)
transit_chart = get_chart(transit_position, transit_date)
offset = 0
previous_aspects = set(
show_aspect(a)
for a in get_aspects(natal_chart, transit_chart, threshold=threshold)
)
while True:
then = transit_date + timedelta(minutes=offset)
current_chart = get_chart(transit_position, then)
current_aspects = set(
show_aspect(a)
for a in get_aspects(natal_chart, current_chart, threshold=threshold)
)
entered = current_aspects - previous_aspects
exited = previous_aspects - current_aspects
if entered or exited:
print(
then.strftime("%Y-%m-%d %H:%M"),
"".join([" | +" + a for a in entered] + [" | -" + a for a in exited]),
sep="",
)
previous_aspects = current_aspects
offset += 1
@click.command()
@click.option("--natal-latitude", type=click.FLOAT, default=here_latitude)
@click.option("--natal-longitude", type=click.FLOAT, default=here_longitude)
@click.option("--natal-date", "-D", type=click.DateTime(), default=datetime.now())
@click.option("--transit-latitude", type=click.FLOAT, default=here_latitude)
@click.option("--transit-longitude", type=click.FLOAT, default=here_longitude)
@click.option("--transit-date", "-d", type=click.DateTime(), default=datetime.now())
@click.option("--threshold", "-t", type=click.FLOAT, default=5)
def current(
natal_latitude: float,
natal_longitude: float,
natal_date: datetime,
transit_latitude: float,
transit_longitude: float,
transit_date: datetime,
threshold: float,
):
transit_position = GeoPos(transit_latitude, transit_longitude)
natal_position = GeoPos(natal_latitude, natal_longitude)
natal_chart = get_chart(natal_position, natal_date)
transit_chart = get_chart(transit_position, transit_date)
relevant_aspects = list(
get_aspects(natal_chart, transit_chart, threshold=threshold)
)
def aspect_switch_date(aspect, *, direction=1, threshold):
offset = 0
while True:
then = transit_date + direction * timedelta(days=offset)
current_chart = get_chart(transit_position, then)
aspects = [
show_aspect(a)
for a in get_aspects(natal_chart, current_chart, threshold=threshold)
]
if aspect not in aspects:
return then.date()
offset += 1
for aspect in sorted(relevant_aspects, key=operator.attrgetter("orb")):
aspect_string = show_aspect(aspect)
print(
aspect_switch_date(
aspect_string, direction=-1, threshold=threshold
).isoformat(),
aspect_switch_date(
aspect_string, direction=1, threshold=threshold
).isoformat(),
aspect_string,
)