cryogenic22 commited on
Commit
d083c8f
·
verified ·
1 Parent(s): 4477cc3

Update astro_core.py

Browse files
Files changed (1) hide show
  1. astro_core.py +56 -86
astro_core.py CHANGED
@@ -1,54 +1,38 @@
1
  from datetime import datetime, timedelta
2
- import zoneinfo # Use zoneinfo instead of pytz
3
  from typing import Dict, Any
4
  from flatlib.datetime import Datetime
5
  from flatlib.geopos import GeoPos
6
  from flatlib.chart import Chart
 
 
7
 
8
- # Define our own constants
9
  ZODIAC_SIGNS = [
10
- 'Aries', 'Taurus', 'Gemini', 'Cancer',
11
  'Leo', 'Virgo', 'Libra', 'Scorpio',
12
  'Sagittarius', 'Capricorn', 'Aquarius', 'Pisces'
13
  ]
14
 
15
  class ChartCalculator:
16
  """Handles astrological calculations"""
17
-
18
  def __init__(self):
19
  self.planets = [
20
- 'Sun', 'Moon', 'Mercury', 'Venus', 'Mars',
21
  'Jupiter', 'Saturn', 'Uranus', 'Neptune', 'Pluto'
22
  ]
23
-
24
- def _get_house_number(self, lon: float, chart: Chart) -> int:
25
- """Determine house number for a given longitude"""
26
- house_lons = []
27
- for i in range(1, 13):
28
- try:
29
- house = chart.houses.get(i)
30
- house_lons.append(house.lon if house else 0)
31
- except (KeyError, AttributeError):
32
- house_lons.append(0)
33
-
34
- # Simplified zodiac wrap-around handling
35
- lon = self._normalize_longitude(lon)
36
- house_lons = [self._normalize_longitude(lon) for lon in house_lons]
37
- for i in range(12):
38
- if house_lons[i] <= lon < house_lons[(i + 1) % 12]:
39
- return i + 1
40
- return 1 # Default to first house if no match
41
 
42
  def _normalize_longitude(self, lon: float) -> float:
43
  """Normalize longitude to 0-360 range"""
44
  return lon % 360
45
-
46
  def _get_zodiac_sign(self, longitude: float) -> str:
47
  """Get zodiac sign from longitude"""
48
  sign_num = int(self._normalize_longitude(longitude) / 30)
49
  return ZODIAC_SIGNS[sign_num]
50
-
51
- def calculate_birth_chart(self,
52
  birth_datetime: datetime,
53
  latitude: float,
54
  longitude: float,
@@ -58,69 +42,43 @@ class ChartCalculator:
58
  Returns a dictionary of planetary positions and house cusps
59
  """
60
  try:
61
- # Timezone handling with zoneinfo
62
- tz = zoneinfo.ZoneInfo(timezone)
63
  birth_datetime = birth_datetime.replace(tzinfo=tz)
64
-
65
- # Get UTC offset in hours
66
  utc_offset = int(birth_datetime.utcoffset().total_seconds() / 3600)
67
 
68
- # Extract date and time components (adjust time for UTC)
69
  adjusted_datetime = birth_datetime - timedelta(hours=utc_offset)
70
  date_str = adjusted_datetime.strftime('%Y/%m/%d')
71
  time_str = adjusted_datetime.strftime('%H:%M')
72
 
73
- # Convert to flatlib datetime (using UTC offset)
74
- date = Datetime(date_str, time_str, utc_offset) # Pass numeric UTC offset here
75
  pos = GeoPos(latitude, longitude)
76
 
77
- # Calculate chart
78
  chart = Chart(date, pos)
79
 
80
  # Extract planetary positions
81
  positions = {}
82
  for planet in self.planets:
83
- try:
84
- obj = chart.get(planet)
85
- if obj:
86
- # Normalize longitude
87
- lon = self._normalize_longitude(obj.lon)
88
-
89
- # Get sign
90
- sign = self._get_zodiac_sign(lon)
91
-
92
- # Get house
93
- house = self._get_house_number(lon, chart)
94
-
95
- positions[planet] = {
96
- 'sign': sign,
97
- 'degrees': lon,
98
- 'house': house
99
- }
100
- except Exception as e:
101
  positions[planet] = {
102
- 'sign': 'Unknown',
103
- 'degrees': 0,
104
- 'house': 1,
105
- 'error': str(e)
106
  }
107
 
108
  # Extract house cusps
109
  houses = {}
110
  for i in range(1, 13):
111
- try:
112
- house = chart.houses.get(i)
113
- if house:
114
- lon = self._normalize_longitude(house.lon)
115
- houses[f'House_{i}'] = {
116
- 'sign': self._get_zodiac_sign(lon),
117
- 'degrees': lon
118
- }
119
- except Exception as e:
120
  houses[f'House_{i}'] = {
121
- 'sign': 'Unknown',
122
- 'degrees': 0,
123
- 'error': str(e)
124
  }
125
 
126
  return {
@@ -128,26 +86,38 @@ class ChartCalculator:
128
  'houses': houses
129
  }
130
 
131
- except zoneinfo.ZoneInfoNotFoundError:
132
- return {
133
- 'error': f"Invalid timezone: {timezone}",
134
- 'planets': {},
135
- 'houses': {}
136
- }
137
- except KeyError as e:
138
- return {
139
- 'error': f"KeyError during chart calculation: {str(e)}",
140
- 'planets': {},
141
- 'houses': {}
142
- }
143
- except Exception as e:
144
  return {
145
- 'error': f"Failed to calculate birth chart: {str(e)}",
146
  'planets': {},
147
  'houses': {}
148
  }
149
 
150
- def get_planet_aspects(self, chart_data: Dict[str, Any]) -> Dict[str, list]:
151
- """Calculate major aspects between planets"""
152
- # TODO: Implement aspect calculation using flatlib
153
- return {}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  from datetime import datetime, timedelta
2
+ import zoneinfo
3
  from typing import Dict, Any
4
  from flatlib.datetime import Datetime
5
  from flatlib.geopos import GeoPos
6
  from flatlib.chart import Chart
7
+ import matplotlib.pyplot as plt
8
+ import numpy as np
9
 
10
+ # Define constants
11
  ZODIAC_SIGNS = [
12
+ 'Aries', 'Taurus', 'Gemini', 'Cancer',
13
  'Leo', 'Virgo', 'Libra', 'Scorpio',
14
  'Sagittarius', 'Capricorn', 'Aquarius', 'Pisces'
15
  ]
16
 
17
  class ChartCalculator:
18
  """Handles astrological calculations"""
19
+
20
  def __init__(self):
21
  self.planets = [
22
+ 'Sun', 'Moon', 'Mercury', 'Venus', 'Mars',
23
  'Jupiter', 'Saturn', 'Uranus', 'Neptune', 'Pluto'
24
  ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
 
26
  def _normalize_longitude(self, lon: float) -> float:
27
  """Normalize longitude to 0-360 range"""
28
  return lon % 360
29
+
30
  def _get_zodiac_sign(self, longitude: float) -> str:
31
  """Get zodiac sign from longitude"""
32
  sign_num = int(self._normalize_longitude(longitude) / 30)
33
  return ZODIAC_SIGNS[sign_num]
34
+
35
+ def calculate_birth_chart(self,
36
  birth_datetime: datetime,
37
  latitude: float,
38
  longitude: float,
 
42
  Returns a dictionary of planetary positions and house cusps
43
  """
44
  try:
45
+ # Handle timezone
46
+ tz = zoneinfo.ZoneInfo(timezone)
47
  birth_datetime = birth_datetime.replace(tzinfo=tz)
 
 
48
  utc_offset = int(birth_datetime.utcoffset().total_seconds() / 3600)
49
 
50
+ # Adjust to UTC
51
  adjusted_datetime = birth_datetime - timedelta(hours=utc_offset)
52
  date_str = adjusted_datetime.strftime('%Y/%m/%d')
53
  time_str = adjusted_datetime.strftime('%H:%M')
54
 
55
+ # Create flatlib datetime and position
56
+ date = Datetime(date_str, time_str, utc_offset)
57
  pos = GeoPos(latitude, longitude)
58
 
59
+ # Generate the chart
60
  chart = Chart(date, pos)
61
 
62
  # Extract planetary positions
63
  positions = {}
64
  for planet in self.planets:
65
+ obj = chart.get(planet)
66
+ if obj:
67
+ lon = self._normalize_longitude(obj.lon)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
  positions[planet] = {
69
+ 'sign': self._get_zodiac_sign(lon),
70
+ 'degrees': lon
 
 
71
  }
72
 
73
  # Extract house cusps
74
  houses = {}
75
  for i in range(1, 13):
76
+ house = chart.houses.get(i)
77
+ if house:
78
+ lon = self._normalize_longitude(house.lon)
 
 
 
 
 
 
79
  houses[f'House_{i}'] = {
80
+ 'sign': self._get_zodiac_sign(lon),
81
+ 'degrees': lon
 
82
  }
83
 
84
  return {
 
86
  'houses': houses
87
  }
88
 
89
+ except Exception as e:
 
 
 
 
 
 
 
 
 
 
 
 
90
  return {
91
+ 'error': str(e),
92
  'planets': {},
93
  'houses': {}
94
  }
95
 
96
+ def draw_chart(self, chart_data: Dict[str, Any]):
97
+ """Generate a graphical view of the astrology chart"""
98
+ fig, ax = plt.subplots(figsize=(8, 8), subplot_kw={'projection': 'polar'})
99
+ ax.set_theta_zero_location("S")
100
+ ax.set_theta_direction(-1)
101
+
102
+ # Draw zodiac signs
103
+ zodiac_angles = np.linspace(0, 2 * np.pi, 13) # 12 zodiac signs
104
+ for i, sign in enumerate(ZODIAC_SIGNS):
105
+ angle = zodiac_angles[i]
106
+ ax.text(angle, 1.05, sign, ha='center', va='center', fontsize=10)
107
+
108
+ # Draw houses
109
+ house_angles = np.linspace(0, 2 * np.pi, 13) # 12 houses
110
+ for i in range(1, 13):
111
+ angle = house_angles[i - 1]
112
+ ax.text(angle, 0.8, f"H{i}", ha='center', va='center', fontsize=10)
113
+
114
+ # Plot planets
115
+ for planet, data in chart_data['planets'].items():
116
+ degrees = data['degrees']
117
+ angle = np.deg2rad(degrees)
118
+ ax.plot([angle], [0.5], marker='o', label=planet, markersize=10)
119
+
120
+ # Draw the chart
121
+ ax.legend(loc='upper right', bbox_to_anchor=(1.3, 1))
122
+ plt.title("Astrology Chart", va='bottom', fontsize=15)
123
+ plt.show()