SherlockRamos commited on
Commit
cdcd73e
·
verified ·
1 Parent(s): 562cef5

Upload 14 files

Browse files
.gitattributes CHANGED
@@ -33,3 +33,7 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ generated-icon.png filter=lfs diff=lfs merge=lfs -text
37
+ seas_18.se1 filter=lfs diff=lfs merge=lfs -text
38
+ semo_18.se1 filter=lfs diff=lfs merge=lfs -text
39
+ sepl_18.se1 filter=lfs diff=lfs merge=lfs -text
Pasted-C-Configurar-o-caminho-para-os-arquivos-de-efem-rides-ajuste-conforme-necess-rio-swe-set-ephe-pa-1740106355605.txt ADDED
@@ -0,0 +1,185 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ C
2
+ # Configurar o caminho para os arquivos de efemérides (ajuste conforme necessário)
3
+ swe.set_ephe_path('/path/to/ephe') # Substitua pelo caminho correto no seu sistema
4
+
5
+ def download_ephe_files():
6
+ """Baixa e configura os arquivos de efemérides necessários."""
7
+ # Criar diretório para as efemérides se não existir
8
+ ephe_dir = Path("ephe")
9
+ ephe_dir.mkdir(exist_ok=True)
10
+
11
+ # URL base do repositório
12
+ base_url = "https://raw.githubusercontent.com/aloistr/swisseph/master/ephe/"
13
+
14
+ # Lista de arquivos essenciais
15
+ essential_files = [
16
+ "seas_18.se1", # Arquivo principal do Sol
17
+ "semo_18.se1", # Arquivo principal da Lua
18
+ "sepl_18.se1" # Arquivo principal dos planetas
19
+ ]
20
+
21
+ # Baixar arquivos
22
+ for filename in essential_files:
23
+ file_path = ephe_dir / filename
24
+ if not file_path.exists():
25
+ print(f"Baixando {filename}...")
26
+ try:
27
+ response = requests.get(f"{base_url}{filename}")
28
+ response.raise_for_status()
29
+ with open(file_path, "wb") as f:
30
+ f.write(response.content)
31
+ except Exception as e:
32
+ print(f"Erro ao baixar {filename}: {e}")
33
+ return False
34
+
35
+ # Configurar o caminho das efemérides
36
+ swe.set_ephe_path(str(ephe_dir))
37
+ return True
38
+
39
+ # Funções auxiliares
40
+ def get_timezone(cidade):
41
+ """Obtém latitude, longitude e fuso horário a partir do nome da cidade."""
42
+ geolocator = Nominatim(user_agent="astro_calculator")
43
+ location = geolocator.geocode(cidade)
44
+ if not location:
45
+ raise ValueError("Cidade não encontrada.")
46
+ lat, lon = location.latitude, location.longitude
47
+ tf = TimezoneFinder()
48
+ timezone_str = tf.timezone_at(lat=lat, lng=lon)
49
+ if not timezone_str:
50
+ raise ValueError("Fuso horário não encontrado para esta localização.")
51
+ return timezone_str, lat, lon
52
+
53
+ def get_julian_day(data_str, hora_str, timezone_str):
54
+ """Converte data e hora local para Julian Day (UTC)."""
55
+ try:
56
+ # Parsear data e hora
57
+ dia, mes, ano = map(int, data_str.split('/'))
58
+ hora, minuto = map(int, hora_str.split(':'))
59
+ # Criar objeto datetime com fuso horário local
60
+ tz = pytz.timezone(timezone_str)
61
+ dt_local = tz.localize(datetime(ano, mes, dia, hora, minuto))
62
+ # Converter para UTC
63
+ dt_utc = dt_local.astimezone(pytz.UTC)
64
+ # Calcular Julian Day
65
+ return swe.utc_to_jd(dt_utc.year, dt_utc.month, dt_utc.day,
66
+ dt_utc.hour, dt_utc.minute, dt_utc.second,
67
+ swe.GREG_CAL)[1]
68
+ except Exception as e:
69
+ print(f"Erro ao converter data/hora: {e}")
70
+ return None
71
+
72
+ def calcular_signo(graus):
73
+ """Converte uma posição em graus para o signo correspondente."""
74
+ signos = ["Áries", "Touro", "Gêmeos", "Câncer", "Leão", "Virgem",
75
+ "Libra", "Escorpião", "Sagitário", "Capricórnio", "Aquário", "Peixes"]
76
+ grau_normalizado = graus % 360
77
+ indice = int(grau_normalizado // 30)
78
+ return signos[indice]
79
+
80
+ def calcular_aspectos(posicoes):
81
+ """Calcula aspectos principais entre os planetas."""
82
+ aspectos = []
83
+ orbes = {"Conjunção": 8, "Oposição": 8, "Trígono": 6, "Quadrratura": 6, "Sextil": 4}
84
+ tipos_aspectos = {
85
+ 0: "Conjunção", 60: "Sextil", 90: "Quadrratura", 120: "Trígono", 180: "Oposição"
86
+ }
87
+
88
+ planetas_lista = list(posicoes.keys())
89
+ for i in range(len(planetas_lista)):
90
+ for j in range(i + 1, len(planetas_lista)):
91
+ p1, p2 = planetas_lista[i], planetas_lista[j]
92
+ grau1, grau2 = posicoes[p1]["graus"], posicoes[p2]["graus"]
93
+ diff = min((grau1 - grau2) % 360, (grau2 - grau1) % 360)
94
+
95
+ for angulo, tipo in tipos_aspectos.items():
96
+ if abs(diff - angulo) <= orbes[tipo]:
97
+ aspectos.append(f"{p1} em {tipo} com {p2} ({diff:.2f}°)")
98
+
99
+ return aspectos
100
+
101
+ # Programa principal
102
+ def main():
103
+ print("Bem-vindo ao cálculo do Mapa Astral!")
104
+
105
+ # Adicionar verificação e download dos arquivos de efemérides
106
+ print("Verificando arquivos de efemérides...")
107
+ if not download_ephe_files():
108
+ print("Erro ao configurar os arquivos de efemérides. O programa não pode continuar.")
109
+ return
110
+
111
+ data_nascimento = input("Digite sua data de nascimento (dd/mm/aaaa): ")
112
+ hora_nascimento = input("Digite sua hora de nascimento (hh:mm): ")
113
+ cidade_nascimento = input("Digite a cidade e país de nascimento (ex.: São Paulo, Brasil): ")
114
+
115
+ try:
116
+ # Obter fuso horário e coordenadas
117
+ timezone, latitude, longitude = get_timezone(cidade_nascimento)
118
+ print(f"\nLocal: {cidade_nascimento} (Lat: {latitude:.4f}, Lon: {longitude:.4f})")
119
+ print(f"Fuso horário: {timezone}")
120
+
121
+ # Converter para Julian Day
122
+ julian_day = get_julian_day(data_nascimento, hora_nascimento, timezone)
123
+ if julian_day is None:
124
+ raise ValueError("Erro ao calcular o Julian Day.")
125
+
126
+ # Calcular posições planetárias e nodos
127
+ planetas = {
128
+ "Sol": swe.SUN, "Lua": swe.MOON, "Mercúrio": swe.MERCURY,
129
+ "Vênus": swe.VENUS, "Marte": swe.MARS, "Júpiter": swe.JUPITER,
130
+ "Saturno": swe.SATURN, "Urano": swe.URANUS, "Netuno": swe.NEPTUNE,
131
+ "Plutão": swe.PLUTO, "Nodo Norte": swe.MEAN_NODE
132
+ }
133
+ posicoes = {}
134
+ for nome, planeta in planetas.items():
135
+ resultado = swe.calc_ut(julian_day, planeta)
136
+ pos = resultado[0][0] # Pegando apenas a longitude eclíptica
137
+ posicoes[nome] = {"graus": pos, "signo": calcular_signo(pos)}
138
+
139
+ # Nodo Sul é oposto ao Nodo Norte
140
+ nodo_sul_graus = (posicoes["Nodo Norte"]["graus"] + 180) % 360
141
+ posicoes["Nodo Sul"] = {"graus": nodo_sul_graus, "signo": calcular_signo(nodo_sul_graus)}
142
+
143
+ # Calcular Ascendente e casas
144
+ casas, aspectos_casas = swe.houses(julian_day, latitude, longitude, b'P') # Placidus
145
+ ascendente = casas[0]
146
+ signo_ascendente = calcular_signo(ascendente)
147
+ meio_do_ceu = casas[9]
148
+ signo_mc = calcular_signo(meio_do_ceu)
149
+
150
+ # Calcular aspectos
151
+ aspectos = calcular_aspectos(posicoes)
152
+
153
+ # Exibir resultados
154
+ print("\n=== Mapa Astral ===")
155
+ print(f"Signo Solar: {posicoes['Sol']['signo']} ({posicoes['Sol']['graus']:.2f}°)")
156
+ print(f"Signo Lunar: {posicoes['Lua']['signo']} ({posicoes['Lua']['graus']:.2f}°)")
157
+ print(f"Ascendente: {signo_ascendente} ({ascendente:.2f}°)")
158
+ print(f"Meio do Céu: {signo_mc} ({meio_do_ceu:.2f}°)")
159
+
160
+ print("\n=== Outros Planetas ===")
161
+ for planeta, info in posicoes.items():
162
+ if planeta not in ["Sol", "Lua", "Nodo Norte", "Nodo Sul"]:
163
+ print(f"{planeta}: {info['signo']} ({info['graus']:.2f}°)")
164
+
165
+ print("\n=== Nodos Lunares ===")
166
+ print(f"Nodo Norte: {posicoes['Nodo Norte']['signo']} ({posicoes['Nodo Norte']['graus']:.2f}°)")
167
+ print(f"Nodo Sul: {posicoes['Nodo Sul']['signo']} ({posicoes['Nodo Sul']['graus']:.2f}°)")
168
+
169
+ print("\n=== Casas Astrológicas ===")
170
+ for i, casa in enumerate(casas[:12], 1):
171
+ signo_casa = calcular_signo(casa)
172
+ print(f"Casa {i}: {signo_casa} ({casa:.2f}°)")
173
+
174
+ print("\n=== Aspectos Principais ===")
175
+ if aspectos:
176
+ for aspecto in aspectos:
177
+ print(aspecto)
178
+ else:
179
+ print("Nenhum aspecto significativo encontrado.")
180
+
181
+ except Exception as e:
182
+ print(f"Erro: {e}")
183
+
184
+ if __name__ == "__main__":
185
+ main()
Pasted-import-swisseph-as-swe-from-datetime-import-datetime-import-pytz-from-geopy-geocoders-import-Nominat-1740106507168.txt ADDED
@@ -0,0 +1,194 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import swisseph as swe
2
+ from datetime import datetime
3
+ import pytz
4
+ from geopy.geocoders import Nominatim
5
+ from timezonefinder import TimezoneFinder
6
+ import os
7
+ import requests
8
+ import zipfile
9
+ from pathlib import Path
10
+
11
+ # Configurar o caminho para os arquivos de efemérides (ajuste conforme necessário)
12
+ swe.set_ephe_path('/path/to/ephe') # Substitua pelo caminho correto no seu sistema
13
+
14
+ def download_ephe_files():
15
+ """Baixa e configura os arquivos de efemérides necessários."""
16
+ # Criar diretório para as efemérides se não existir
17
+ ephe_dir = Path("ephe")
18
+ ephe_dir.mkdir(exist_ok=True)
19
+
20
+ # URL base do repositório
21
+ base_url = "https://raw.githubusercontent.com/aloistr/swisseph/master/ephe/"
22
+
23
+ # Lista de arquivos essenciais
24
+ essential_files = [
25
+ "seas_18.se1", # Arquivo principal do Sol
26
+ "semo_18.se1", # Arquivo principal da Lua
27
+ "sepl_18.se1" # Arquivo principal dos planetas
28
+ ]
29
+
30
+ # Baixar arquivos
31
+ for filename in essential_files:
32
+ file_path = ephe_dir / filename
33
+ if not file_path.exists():
34
+ print(f"Baixando {filename}...")
35
+ try:
36
+ response = requests.get(f"{base_url}{filename}")
37
+ response.raise_for_status()
38
+ with open(file_path, "wb") as f:
39
+ f.write(response.content)
40
+ except Exception as e:
41
+ print(f"Erro ao baixar {filename}: {e}")
42
+ return False
43
+
44
+ # Configurar o caminho das efemérides
45
+ swe.set_ephe_path(str(ephe_dir))
46
+ return True
47
+
48
+ # Funções auxiliares
49
+ def get_timezone(cidade):
50
+ """Obtém latitude, longitude e fuso horário a partir do nome da cidade."""
51
+ geolocator = Nominatim(user_agent="astro_calculator")
52
+ location = geolocator.geocode(cidade)
53
+ if not location:
54
+ raise ValueError("Cidade não encontrada.")
55
+ lat, lon = location.latitude, location.longitude
56
+ tf = TimezoneFinder()
57
+ timezone_str = tf.timezone_at(lat=lat, lng=lon)
58
+ if not timezone_str:
59
+ raise ValueError("Fuso horário não encontrado para esta localização.")
60
+ return timezone_str, lat, lon
61
+
62
+ def get_julian_day(data_str, hora_str, timezone_str):
63
+ """Converte data e hora local para Julian Day (UTC)."""
64
+ try:
65
+ # Parsear data e hora
66
+ dia, mes, ano = map(int, data_str.split('/'))
67
+ hora, minuto = map(int, hora_str.split(':'))
68
+ # Criar objeto datetime com fuso horário local
69
+ tz = pytz.timezone(timezone_str)
70
+ dt_local = tz.localize(datetime(ano, mes, dia, hora, minuto))
71
+ # Converter para UTC
72
+ dt_utc = dt_local.astimezone(pytz.UTC)
73
+ # Calcular Julian Day
74
+ return swe.utc_to_jd(dt_utc.year, dt_utc.month, dt_utc.day,
75
+ dt_utc.hour, dt_utc.minute, dt_utc.second,
76
+ swe.GREG_CAL)[1]
77
+ except Exception as e:
78
+ print(f"Erro ao converter data/hora: {e}")
79
+ return None
80
+
81
+ def calcular_signo(graus):
82
+ """Converte uma posição em graus para o signo correspondente."""
83
+ signos = ["Áries", "Touro", "Gêmeos", "Câncer", "Leão", "Virgem",
84
+ "Libra", "Escorpião", "Sagitário", "Capricórnio", "Aquário", "Peixes"]
85
+ grau_normalizado = graus % 360
86
+ indice = int(grau_normalizado // 30)
87
+ return signos[indice]
88
+
89
+ def calcular_aspectos(posicoes):
90
+ """Calcula aspectos principais entre os planetas."""
91
+ aspectos = []
92
+ orbes = {"Conjunção": 8, "Oposição": 8, "Trígono": 6, "Quadrratura": 6, "Sextil": 4}
93
+ tipos_aspectos = {
94
+ 0: "Conjunção", 60: "Sextil", 90: "Quadrratura", 120: "Trígono", 180: "Oposição"
95
+ }
96
+
97
+ planetas_lista = list(posicoes.keys())
98
+ for i in range(len(planetas_lista)):
99
+ for j in range(i + 1, len(planetas_lista)):
100
+ p1, p2 = planetas_lista[i], planetas_lista[j]
101
+ grau1, grau2 = posicoes[p1]["graus"], posicoes[p2]["graus"]
102
+ diff = min((grau1 - grau2) % 360, (grau2 - grau1) % 360)
103
+
104
+ for angulo, tipo in tipos_aspectos.items():
105
+ if abs(diff - angulo) <= orbes[tipo]:
106
+ aspectos.append(f"{p1} em {tipo} com {p2} ({diff:.2f}°)")
107
+
108
+ return aspectos
109
+
110
+ # Programa principal
111
+ def main():
112
+ print("Bem-vindo ao cálculo do Mapa Astral!")
113
+
114
+ # Adicionar verificação e download dos arquivos de efemérides
115
+ print("Verificando arquivos de efemérides...")
116
+ if not download_ephe_files():
117
+ print("Erro ao configurar os arquivos de efemérides. O programa não pode continuar.")
118
+ return
119
+
120
+ data_nascimento = input("Digite sua data de nascimento (dd/mm/aaaa): ")
121
+ hora_nascimento = input("Digite sua hora de nascimento (hh:mm): ")
122
+ cidade_nascimento = input("Digite a cidade e país de nascimento (ex.: São Paulo, Brasil): ")
123
+
124
+ try:
125
+ # Obter fuso horário e coordenadas
126
+ timezone, latitude, longitude = get_timezone(cidade_nascimento)
127
+ print(f"\nLocal: {cidade_nascimento} (Lat: {latitude:.4f}, Lon: {longitude:.4f})")
128
+ print(f"Fuso horário: {timezone}")
129
+
130
+ # Converter para Julian Day
131
+ julian_day = get_julian_day(data_nascimento, hora_nascimento, timezone)
132
+ if julian_day is None:
133
+ raise ValueError("Erro ao calcular o Julian Day.")
134
+
135
+ # Calcular posições planetárias e nodos
136
+ planetas = {
137
+ "Sol": swe.SUN, "Lua": swe.MOON, "Mercúrio": swe.MERCURY,
138
+ "Vênus": swe.VENUS, "Marte": swe.MARS, "Júpiter": swe.JUPITER,
139
+ "Saturno": swe.SATURN, "Urano": swe.URANUS, "Netuno": swe.NEPTUNE,
140
+ "Plutão": swe.PLUTO, "Nodo Norte": swe.MEAN_NODE
141
+ }
142
+ posicoes = {}
143
+ for nome, planeta in planetas.items():
144
+ resultado = swe.calc_ut(julian_day, planeta)
145
+ pos = resultado[0][0] # Pegando apenas a longitude eclíptica
146
+ posicoes[nome] = {"graus": pos, "signo": calcular_signo(pos)}
147
+
148
+ # Nodo Sul é oposto ao Nodo Norte
149
+ nodo_sul_graus = (posicoes["Nodo Norte"]["graus"] + 180) % 360
150
+ posicoes["Nodo Sul"] = {"graus": nodo_sul_graus, "signo": calcular_signo(nodo_sul_graus)}
151
+
152
+ # Calcular Ascendente e casas
153
+ casas, aspectos_casas = swe.houses(julian_day, latitude, longitude, b'P') # Placidus
154
+ ascendente = casas[0]
155
+ signo_ascendente = calcular_signo(ascendente)
156
+ meio_do_ceu = casas[9]
157
+ signo_mc = calcular_signo(meio_do_ceu)
158
+
159
+ # Calcular aspectos
160
+ aspectos = calcular_aspectos(posicoes)
161
+
162
+ # Exibir resultados
163
+ print("\n=== Mapa Astral ===")
164
+ print(f"Signo Solar: {posicoes['Sol']['signo']} ({posicoes['Sol']['graus']:.2f}°)")
165
+ print(f"Signo Lunar: {posicoes['Lua']['signo']} ({posicoes['Lua']['graus']:.2f}°)")
166
+ print(f"Ascendente: {signo_ascendente} ({ascendente:.2f}°)")
167
+ print(f"Meio do Céu: {signo_mc} ({meio_do_ceu:.2f}°)")
168
+
169
+ print("\n=== Outros Planetas ===")
170
+ for planeta, info in posicoes.items():
171
+ if planeta not in ["Sol", "Lua", "Nodo Norte", "Nodo Sul"]:
172
+ print(f"{planeta}: {info['signo']} ({info['graus']:.2f}°)")
173
+
174
+ print("\n=== Nodos Lunares ===")
175
+ print(f"Nodo Norte: {posicoes['Nodo Norte']['signo']} ({posicoes['Nodo Norte']['graus']:.2f}°)")
176
+ print(f"Nodo Sul: {posicoes['Nodo Sul']['signo']} ({posicoes['Nodo Sul']['graus']:.2f}°)")
177
+
178
+ print("\n=== Casas Astrológicas ===")
179
+ for i, casa in enumerate(casas[:12], 1):
180
+ signo_casa = calcular_signo(casa)
181
+ print(f"Casa {i}: {signo_casa} ({casa:.2f}°)")
182
+
183
+ print("\n=== Aspectos Principais ===")
184
+ if aspectos:
185
+ for aspecto in aspectos:
186
+ print(aspecto)
187
+ else:
188
+ print("Nenhum aspecto significativo encontrado.")
189
+
190
+ except Exception as e:
191
+ print(f"Erro: {e}")
192
+
193
+ if __name__ == "__main__":
194
+ main()
app.py ADDED
@@ -0,0 +1,216 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import datetime
3
+ from utils import (
4
+ download_ephe_files, get_location_data, calculate_julian_day,
5
+ get_planet_positions, calculate_houses
6
+ )
7
+ from chart_generator import create_wheel_chart, PLANET_NAMES
8
+
9
+ # Zodiac sign symbols and names
10
+ ZODIAC_SYMBOLS = {
11
+ "Aries": "♈",
12
+ "Taurus": "♉",
13
+ "Gemini": "♊",
14
+ "Cancer": "♋",
15
+ "Leo": "♌",
16
+ "Virgo": "♍",
17
+ "Libra": "♎",
18
+ "Scorpio": "♏",
19
+ "Sagittarius": "♐",
20
+ "Capricorn": "♑",
21
+ "Aquarius": "♒",
22
+ "Pisces": "♓"
23
+ }
24
+
25
+ def calcular_signo(longitude):
26
+ signo = ""
27
+ if 0 <= longitude < 30:
28
+ signo = "Aries"
29
+ elif 30 <= longitude < 60:
30
+ signo = "Taurus"
31
+ elif 60 <= longitude < 90:
32
+ signo = "Gemini"
33
+ elif 90 <= longitude < 120:
34
+ signo = "Cancer"
35
+ elif 120 <= longitude < 150:
36
+ signo = "Leo"
37
+ elif 150 <= longitude < 180:
38
+ signo = "Virgo"
39
+ elif 180 <= longitude < 210:
40
+ signo = "Libra"
41
+ elif 210 <= longitude < 240:
42
+ signo = "Scorpio"
43
+ elif 240 <= longitude < 270:
44
+ signo = "Sagittarius"
45
+ elif 270 <= longitude < 300:
46
+ signo = "Capricorn"
47
+ elif 300 <= longitude < 330:
48
+ signo = "Aquarius"
49
+ elif 330 <= longitude < 360:
50
+ signo = "Pisces"
51
+ return signo
52
+
53
+ # Configuração da página
54
+ st.set_page_config(
55
+ page_title="Visualizador de Mapa Astral",
56
+ page_icon="🌟",
57
+ layout="centered"
58
+ )
59
+
60
+ # Carregar CSS personalizado
61
+ with open("styles/custom.css") as f:
62
+ st.markdown(f"<style>{f.read()}</style>", unsafe_allow_html=True)
63
+
64
+ # Inicializar arquivos de efemérides
65
+ if not download_ephe_files():
66
+ st.error("Falha ao inicializar dados astronômicos. Por favor, tente novamente.")
67
+ st.stop()
68
+
69
+ # Título e descrição
70
+ st.markdown("""
71
+ <div style='text-align: center; padding: 2rem 0;'>
72
+ <h1 class='glow-text'>✨ Visualizador de Mapa Astral ✨</h1>
73
+ </div>
74
+ """, unsafe_allow_html=True)
75
+
76
+ st.markdown("""
77
+ <div class='cosmic-card'>
78
+ <p style='text-align: center; font-size: 1.2rem;'>
79
+ Descubra seu mapa astral através deste visualizador interativo.<br>
80
+ Insira seus dados de nascimento abaixo para revelar as posições celestiais no momento do seu nascimento.
81
+ </p>
82
+ </div>
83
+ """, unsafe_allow_html=True)
84
+
85
+ # Formulário de entrada
86
+ st.markdown("<div class='cosmic-card'>", unsafe_allow_html=True)
87
+ if st.viewport_width < 768:
88
+ # Layout em uma coluna para dispositivos móveis
89
+ birth_date = st.date_input(
90
+ "Data de Nascimento",
91
+ min_value=datetime.date(1900, 1, 1),
92
+ max_value=datetime.date.today(),
93
+ help="Selecione sua data de nascimento"
94
+ )
95
+
96
+ birth_time = st.time_input(
97
+ "Hora de Nascimento",
98
+ help="Insira o horário mais preciso possível"
99
+ )
100
+
101
+ birth_place = st.text_input(
102
+ "Local de Nascimento",
103
+ placeholder="Ex: São Paulo, Brasil",
104
+ help="Digite a cidade e país de nascimento"
105
+ )
106
+ else:
107
+ # Layout em três colunas para desktop
108
+ col1, col2, col3 = st.columns(3)
109
+ with col1:
110
+ birth_date = st.date_input(
111
+ "Data de Nascimento",
112
+ min_value=datetime.date(1900, 1, 1),
113
+ max_value=datetime.date.today(),
114
+ help="Selecione sua data de nascimento"
115
+ )
116
+
117
+ with col2:
118
+ birth_time = st.time_input(
119
+ "Hora de Nascimento",
120
+ help="Insira o horário mais preciso possível"
121
+ )
122
+
123
+ with col3:
124
+ birth_place = st.text_input(
125
+ "Local de Nascimento",
126
+ placeholder="Ex: São Paulo, Brasil",
127
+ help="Digite a cidade e país de nascimento"
128
+ )
129
+
130
+ if st.button("✨ Gerar Mapa Astral ✨", key="generate"):
131
+ try:
132
+ with st.spinner("🌟 Calculando posições celestiais..."):
133
+ location_data = get_location_data(birth_place)
134
+ jd = calculate_julian_day(birth_date, birth_time, location_data['timezone'])
135
+ planet_positions = get_planet_positions(jd)
136
+ houses = calculate_houses(
137
+ jd,
138
+ location_data['latitude'],
139
+ location_data['longitude']
140
+ )
141
+
142
+ # Calcular signo solar
143
+ signo_solar = calcular_signo(planet_positions['Sun']['longitude'])
144
+ simbolo_solar = ZODIAC_SYMBOLS[signo_solar]
145
+
146
+ st.markdown("<div style='text-align: center;'><h2 class='glow-text'>Seu Mapa Astral</h2></div>", unsafe_allow_html=True)
147
+
148
+ # Ajuste do layout responsivo para o resultado
149
+ if st.viewport_width < 768:
150
+ # Layout em uma coluna para mobile
151
+ st.markdown(f"""
152
+ <div class='cosmic-card signo-solar-card'>
153
+ <div class='signo-symbol'>{simbolo_solar}</div>
154
+ <h2 class='signo-nome'>{signo_solar}</h2>
155
+ <p class='signo-grau'>{planet_positions['Sun']['longitude']:.2f}°</p>
156
+ </div>
157
+ """, unsafe_allow_html=True)
158
+
159
+ st.markdown("<div class='chart-container'>", unsafe_allow_html=True)
160
+ fig = create_wheel_chart(planet_positions, houses)
161
+ st.plotly_chart(fig, use_container_width=True)
162
+ st.markdown("</div>", unsafe_allow_html=True)
163
+
164
+ st.markdown("<div class='cosmic-card'>", unsafe_allow_html=True)
165
+ st.markdown("<h3>🌍 Posições Planetárias</h3>", unsafe_allow_html=True)
166
+ for planet, data in planet_positions.items():
167
+ planet_name = PLANET_NAMES.get(planet, planet) # Usar nome traduzido
168
+ st.write(f"✨ {planet_name}: {data['longitude']:.2f}°")
169
+
170
+ st.markdown("<h3>🏠 Cúspides das Casas</h3>", unsafe_allow_html=True)
171
+ for i, cusp in enumerate(houses['cusps'], 1):
172
+ st.write(f"Casa {i}: {cusp:.2f}°")
173
+ st.markdown("</div>", unsafe_allow_html=True)
174
+
175
+ st.markdown("<div class='cosmic-card'>", unsafe_allow_html=True)
176
+ st.markdown("<h3>🌟 Pontos Importantes</h3>", unsafe_allow_html=True)
177
+ st.write(f"⭐ Ascendente: {houses['ascendant']:.2f}°")
178
+ st.write(f"🌠 Meio do Céu: {houses['mc']:.2f}°")
179
+ st.markdown("</div>", unsafe_allow_html=True)
180
+ else:
181
+ # Layout em duas colunas para desktop
182
+ chart_col, info_col = st.columns([2, 1])
183
+
184
+ with chart_col:
185
+ st.markdown("<div class='chart-container'>", unsafe_allow_html=True)
186
+ fig = create_wheel_chart(planet_positions, houses)
187
+ st.plotly_chart(fig, use_container_width=True)
188
+ st.markdown("</div>", unsafe_allow_html=True)
189
+
190
+ with info_col:
191
+ st.markdown("<div class='cosmic-card'>", unsafe_allow_html=True)
192
+ st.markdown("<h3>🌍 Posições Planetárias</h3>", unsafe_allow_html=True)
193
+ for planet, data in planet_positions.items():
194
+ planet_name = PLANET_NAMES.get(planet, planet) # Usar nome traduzido
195
+ st.write(f"✨ {planet_name}: {data['longitude']:.2f}°")
196
+
197
+ st.markdown("<h3>🏠 Cúspides das Casas</h3>", unsafe_allow_html=True)
198
+ for i, cusp in enumerate(houses['cusps'], 1):
199
+ st.write(f"Casa {i}: {cusp:.2f}°")
200
+ st.markdown("</div>", unsafe_allow_html=True)
201
+
202
+ st.markdown("<div class='cosmic-card'>", unsafe_allow_html=True)
203
+ st.markdown("<h3>🌟 Pontos Importantes</h3>", unsafe_allow_html=True)
204
+ st.write(f"⭐ Ascendente: {houses['ascendant']:.2f}°")
205
+ st.write(f"🌠 Meio do Céu: {houses['mc']:.2f}°")
206
+ st.markdown("</div>", unsafe_allow_html=True)
207
+
208
+ except Exception as e:
209
+ st.error(f"Ocorreu um erro: {str(e)}")
210
+
211
+ # Rodapé
212
+ st.markdown("""
213
+ <div class='cosmic-card' style='text-align: center; margin-top: 2rem;'>
214
+ <p>Feito com ✨ e energia cósmica</p>
215
+ </div>
216
+ """, unsafe_allow_html=True)
chart_generator.py ADDED
@@ -0,0 +1,193 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import plotly.graph_objects as go
2
+ import numpy as np
3
+
4
+ THEME_COLORS = {
5
+ 'dark': {
6
+ 'background': 'rgba(28, 28, 28, 0.95)',
7
+ 'primary': '#9C27B0',
8
+ 'accent': '#FF4081',
9
+ 'text': '#FFFFFF',
10
+ 'grid': 'rgba(156, 39, 176, 0.2)',
11
+ 'line': 'rgba(156, 39, 176, 0.5)'
12
+ },
13
+ 'light': {
14
+ 'background': 'rgba(255, 255, 255, 0.95)',
15
+ 'primary': '#7B1FA2',
16
+ 'accent': '#E91E63',
17
+ 'text': '#333333',
18
+ 'grid': 'rgba(123, 31, 162, 0.2)',
19
+ 'line': 'rgba(123, 31, 162, 0.5)'
20
+ }
21
+ }
22
+
23
+ # Dicionário de tradução para os nomes dos planetas
24
+ PLANET_NAMES = {
25
+ 'Sun': 'Sol',
26
+ 'Moon': 'Lua',
27
+ 'Mercury': 'Mercúrio',
28
+ 'Venus': 'Vênus',
29
+ 'Mars': 'Marte',
30
+ 'Jupiter': 'Júpiter',
31
+ 'Saturn': 'Saturno',
32
+ 'Uranus': 'Urano',
33
+ 'Neptune': 'Netuno',
34
+ 'Pluto': 'Plutão'
35
+ }
36
+
37
+ # Dicionário de símbolos dos signos
38
+ ZODIAC_SYMBOLS = {
39
+ "Áries": "♈",
40
+ "Touro": "♉",
41
+ "Gêmeos": "♊",
42
+ "Câncer": "♋",
43
+ "Leão": "♌",
44
+ "Virgem": "♍",
45
+ "Libra": "♎",
46
+ "Escorpião": "♏",
47
+ "Sagitário": "♐",
48
+ "Capricórnio": "♑",
49
+ "Aquário": "♒",
50
+ "Peixes": "♓"
51
+ }
52
+
53
+ def calcular_signo(graus):
54
+ """Converte uma posição em graus para o signo correspondente."""
55
+ signos = ["Áries", "Touro", "Gêmeos", "Câncer", "Leão", "Virgem",
56
+ "Libra", "Escorpião", "Sagitário", "Capricórnio", "Aquário", "Peixes"]
57
+ grau_normalizado = graus % 360
58
+ indice = int(grau_normalizado // 30)
59
+ return signos[indice]
60
+
61
+ def create_wheel_chart(planet_positions, houses, theme='dark'):
62
+ """Gera um gráfico interativo do mapa astral usando Plotly."""
63
+ colors = THEME_COLORS[theme]
64
+
65
+ # Criar o círculo base
66
+ theta = np.linspace(0, 2*np.pi, 360)
67
+ r = np.ones_like(theta)
68
+
69
+ # Criar a figura
70
+ fig = go.Figure()
71
+
72
+ # Adicionar o círculo principal
73
+ fig.add_trace(go.Scatterpolar(
74
+ r=r,
75
+ theta=np.degrees(theta),
76
+ mode='lines',
77
+ line=dict(color=colors['primary'], width=2),
78
+ showlegend=False,
79
+ fill='toself',
80
+ fillcolor=colors['background']
81
+ ))
82
+
83
+ # Adicionar linhas das casas
84
+ for house in houses['cusps']:
85
+ angle = house
86
+ fig.add_trace(go.Scatterpolar(
87
+ r=[0, 1],
88
+ theta=[angle, angle],
89
+ mode='lines',
90
+ line=dict(color=colors['line'], width=1),
91
+ showlegend=False
92
+ ))
93
+
94
+ # Adicionar o signo solar com destaque
95
+ sun_longitude = planet_positions['Sun']['longitude']
96
+ sun_sign = calcular_signo(sun_longitude)
97
+ fig.add_trace(go.Scatterpolar(
98
+ r=[0.9],
99
+ theta=[sun_longitude],
100
+ mode='text',
101
+ text=[f"{sun_sign} {ZODIAC_SYMBOLS[sun_sign]}"],
102
+ textposition="middle center",
103
+ textfont=dict(
104
+ color=colors['text'],
105
+ size=24,
106
+ family="Arial"
107
+ ),
108
+ showlegend=False
109
+ ))
110
+
111
+
112
+ # Adicionar planetas
113
+ for planet, data in planet_positions.items():
114
+ if planet != 'Sun': #Avoid duplicating Sun
115
+ planet_name = PLANET_NAMES.get(planet, planet) # Usar nome traduzido
116
+ fig.add_trace(go.Scatterpolar(
117
+ r=[0.8],
118
+ theta=[data['longitude']],
119
+ mode='markers+text',
120
+ name=planet_name,
121
+ text=[planet_name],
122
+ textposition="top center",
123
+ textfont=dict(
124
+ color=colors['text'],
125
+ size=16, # Aumentado o tamanho da fonte
126
+ family="Arial" # Fonte mais legível
127
+ ),
128
+ marker=dict(
129
+ size=18, # Aumentado o tamanho do marcador
130
+ color=colors['accent'],
131
+ symbol='star',
132
+ line=dict(
133
+ color=colors['text'],
134
+ width=1
135
+ )
136
+ ),
137
+ showlegend=True
138
+ ))
139
+
140
+ # Atualizar layout
141
+ fig.update_layout(
142
+ polar=dict(
143
+ radialaxis=dict(
144
+ visible=False,
145
+ range=[0, 1]
146
+ ),
147
+ angularaxis=dict(
148
+ direction="clockwise",
149
+ period=360,
150
+ rotation=90,
151
+ tickmode='array',
152
+ ticktext=['♈', '♉', '♊', '♋', '♌', '♍', '♎', '♏', '♐', '♑', '♒', '♓'],
153
+ tickvals=np.arange(0, 360, 30),
154
+ tickfont=dict(
155
+ size=24, # Aumentado o tamanho dos símbolos zodiacais
156
+ color=colors['text']
157
+ ),
158
+ gridcolor=colors['grid'],
159
+ linecolor=colors['line']
160
+ ),
161
+ bgcolor=colors['background']
162
+ ),
163
+ paper_bgcolor='rgba(0,0,0,0)',
164
+ plot_bgcolor='rgba(0,0,0,0)',
165
+ showlegend=True,
166
+ legend=dict(
167
+ bgcolor=colors['background'],
168
+ bordercolor=colors['primary'],
169
+ borderwidth=1,
170
+ font=dict(
171
+ color=colors['text'],
172
+ size=14,
173
+ family="Arial"
174
+ ),
175
+ itemsizing='constant',
176
+ yanchor="top",
177
+ y=0.99,
178
+ xanchor="left",
179
+ x=1.1,
180
+ title=dict(
181
+ text="Planetas",
182
+ font=dict(
183
+ size=16,
184
+ family="Arial",
185
+ color=colors['text']
186
+ )
187
+ )
188
+ ),
189
+ margin=dict(l=20, r=120, t=20, b=20), # Ajustado para acomodar a legenda
190
+ height=800
191
+ )
192
+
193
+ return fig
custom.css ADDED
@@ -0,0 +1,237 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Custom styling for the mystical theme */
2
+ .stApp {
3
+ background: linear-gradient(135deg, #1a1a1a 0%, #2d1a2f 100%);
4
+ font-family: 'Poppins', sans-serif;
5
+ letter-spacing: 0.02em;
6
+ line-height: 1.6;
7
+ }
8
+
9
+ /* Card styling */
10
+ .cosmic-card {
11
+ background: rgba(28, 28, 28, 0.95);
12
+ border: 1px solid rgba(156, 39, 176, 0.3);
13
+ border-radius: 15px;
14
+ padding: 25px;
15
+ box-shadow: 0 0 20px rgba(156, 39, 176, 0.2);
16
+ transition: all 0.3s ease;
17
+ margin-bottom: 20px;
18
+ }
19
+
20
+ .cosmic-card:hover {
21
+ box-shadow: 0 0 30px rgba(156, 39, 176, 0.4);
22
+ transform: translateY(-2px);
23
+ }
24
+
25
+ /* Text styling */
26
+ .glow-text {
27
+ color: #FF4081;
28
+ text-shadow: 0 0 10px rgba(255, 64, 129, 0.5);
29
+ font-size: 2.5rem;
30
+ font-weight: 600;
31
+ text-align: center;
32
+ margin-bottom: 30px;
33
+ }
34
+
35
+ h1, h2, h3 {
36
+ color: #FFFFFF;
37
+ margin-bottom: 20px;
38
+ font-weight: 600;
39
+ }
40
+
41
+ p, li {
42
+ color: #E0E0E0;
43
+ font-size: 1.1rem;
44
+ line-height: 1.8;
45
+ }
46
+
47
+ /* Chart container styling */
48
+ .chart-container {
49
+ border-radius: 50%;
50
+ box-shadow: 0 0 30px rgba(156, 39, 176, 0.3);
51
+ padding: 20px;
52
+ background: rgba(28, 28, 28, 0.8);
53
+ transition: all 0.3s ease;
54
+ }
55
+
56
+ .chart-container:hover {
57
+ box-shadow: 0 0 40px rgba(156, 39, 176, 0.5);
58
+ }
59
+
60
+ /* Form inputs styling */
61
+ .stTextInput > div > div, .stDateInput > div > div, .stTimeInput > div > div {
62
+ background: rgba(40, 40, 40, 0.9) !important;
63
+ border: 1px solid rgba(156, 39, 176, 0.5) !important;
64
+ border-radius: 8px !important;
65
+ color: #FFFFFF !important;
66
+ font-size: 1.1rem !important;
67
+ transition: all 0.3s ease;
68
+ }
69
+
70
+ .stTextInput > div > div:focus-within,
71
+ .stDateInput > div > div:focus-within,
72
+ .stTimeInput > div > div:focus-within {
73
+ border-color: #FF4081 !important;
74
+ box-shadow: 0 0 10px rgba(255, 64, 129, 0.3) !important;
75
+ }
76
+
77
+ /* Button styling */
78
+ .stButton > button {
79
+ background: linear-gradient(135deg, #9C27B0 0%, #FF4081 100%) !important;
80
+ color: white !important;
81
+ border: none !important;
82
+ padding: 12px 30px !important;
83
+ border-radius: 8px !important;
84
+ font-size: 1.1rem !important;
85
+ font-weight: 600 !important;
86
+ letter-spacing: 0.05em !important;
87
+ transition: all 0.3s ease !important;
88
+ text-transform: uppercase;
89
+ }
90
+
91
+ .stButton > button:hover {
92
+ transform: translateY(-2px) !important;
93
+ box-shadow: 0 5px 15px rgba(156, 39, 176, 0.4) !important;
94
+ }
95
+
96
+ .stButton > button:active {
97
+ transform: translateY(1px) !important;
98
+ }
99
+
100
+ /* Labels and text inputs */
101
+ .stTextInput label, .stDateInput label, .stTimeInput label {
102
+ color: #FFFFFF !important;
103
+ font-size: 1.1rem !important;
104
+ font-weight: 500 !important;
105
+ margin-bottom: 8px !important;
106
+ }
107
+
108
+ /* Loading spinner */
109
+ .stSpinner > div {
110
+ border-color: #FF4081 !important;
111
+ }
112
+
113
+ /* Error messages */
114
+ .stAlert {
115
+ background: rgba(244, 67, 54, 0.1) !important;
116
+ border-color: rgba(244, 67, 54, 0.5) !important;
117
+ color: #FFFFFF !important;
118
+ }
119
+
120
+ /* Success messages */
121
+ .stSuccess {
122
+ background: rgba(76, 175, 80, 0.1) !important;
123
+ border-color: rgba(76, 175, 80, 0.5) !important;
124
+ color: #FFFFFF !important;
125
+ }
126
+
127
+ /* Estilo especial para o card do signo solar */
128
+ .signo-solar-card {
129
+ background: linear-gradient(135deg, rgba(156, 39, 176, 0.2) 0%, rgba(255, 64, 129, 0.2) 100%);
130
+ text-align: center;
131
+ padding: 2rem;
132
+ margin-bottom: 2rem;
133
+ border: 2px solid rgba(156, 39, 176, 0.5);
134
+ transform: translateY(0);
135
+ transition: all 0.3s ease;
136
+ }
137
+
138
+ .signo-solar-card:hover {
139
+ transform: translateY(-5px);
140
+ box-shadow: 0 10px 30px rgba(156, 39, 176, 0.3);
141
+ }
142
+
143
+ .signo-symbol {
144
+ font-size: 4rem;
145
+ color: #FF4081;
146
+ text-shadow: 0 0 20px rgba(255, 64, 129, 0.5);
147
+ margin-bottom: 1rem;
148
+ animation: float 3s ease-in-out infinite;
149
+ }
150
+
151
+ .signo-nome {
152
+ font-size: 2.5rem;
153
+ color: #FFFFFF;
154
+ margin: 1rem 0;
155
+ font-weight: 600;
156
+ letter-spacing: 0.1em;
157
+ }
158
+
159
+ .signo-grau {
160
+ font-size: 1.2rem;
161
+ color: #E0E0E0;
162
+ font-family: 'Courier New', monospace;
163
+ }
164
+
165
+ @keyframes float {
166
+ 0% {
167
+ transform: translateY(0px);
168
+ }
169
+ 50% {
170
+ transform: translateY(-10px);
171
+ }
172
+ 100% {
173
+ transform: translateY(0px);
174
+ }
175
+ }
176
+
177
+ /* Media Queries para Responsividade */
178
+ @media screen and (max-width: 768px) {
179
+ .glow-text {
180
+ font-size: 1.8rem;
181
+ }
182
+
183
+ .cosmic-card {
184
+ padding: 15px;
185
+ margin-bottom: 15px;
186
+ }
187
+
188
+ .signo-symbol {
189
+ font-size: 3rem;
190
+ }
191
+
192
+ .signo-nome {
193
+ font-size: 2rem;
194
+ }
195
+
196
+ .chart-container {
197
+ padding: 10px;
198
+ }
199
+
200
+ .stButton > button {
201
+ padding: 10px 20px !important;
202
+ font-size: 1rem !important;
203
+ }
204
+ }
205
+
206
+ @media screen and (max-width: 480px) {
207
+ .glow-text {
208
+ font-size: 1.5rem;
209
+ }
210
+
211
+ .cosmic-card {
212
+ padding: 10px;
213
+ margin-bottom: 10px;
214
+ }
215
+
216
+ p, li {
217
+ font-size: 1rem;
218
+ }
219
+
220
+ .signo-symbol {
221
+ font-size: 2.5rem;
222
+ }
223
+
224
+ .signo-nome {
225
+ font-size: 1.8rem;
226
+ }
227
+
228
+ .signo-grau {
229
+ font-size: 1rem;
230
+ }
231
+
232
+ .stTextInput > div > div,
233
+ .stDateInput > div > div,
234
+ .stTimeInput > div > div {
235
+ font-size: 1rem !important;
236
+ }
237
+ }
generated-icon.png ADDED

Git LFS Details

  • SHA256: d87ca5b1e83e98b830a6d51a3715f82acbc1f340efe8e142fc0392aa2fff085f
  • Pointer size: 131 Bytes
  • Size of remote file: 361 kB
pyproject.toml ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [project]
2
+ name = "repl-nix-workspace"
3
+ version = "0.1.0"
4
+ description = "Add your description here"
5
+ requires-python = ">=3.11"
6
+ dependencies = [
7
+ "geopy>=2.4.1",
8
+ "numpy>=2.2.3",
9
+ "plotly>=6.0.0",
10
+ "pyswisseph>=2.10.3.2",
11
+ "pytz>=2025.1",
12
+ "requests>=2.32.3",
13
+ "streamlit>=1.42.2",
14
+ "swisseph>=0.0.0.dev1",
15
+ "timezonefinder>=6.5.8",
16
+ "trafilatura>=2.0.0",
17
+ ]
requirements.txt ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ streamlit==1.42.2
2
+ geopy
3
+ numpy
4
+ plotly
5
+ pyswisseph
6
+ pytz
7
+ requests
8
+ swisseph
9
+ timezonefinder
seas_18.se1 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:5fd9c2aa1654e37c09a6aeb558076e795409b7dc4bd948ebc0faa7d4a7686b5b
3
+ size 223002
semo_18.se1 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ecfa54dbf5bc0b5a9bc3e04ed28629a821e98625eacae38f4070593bba0e2980
3
+ size 1304771
sepl_18.se1 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:0b7e416e3c1be9e6a0dd1d711dae7f7685793a0e7df13f76363a493dc27b6ea1
3
+ size 484055
streamlit.service ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [Unit]
2
+ Description=Streamlit Mapa Astral
3
+ After=network.target
4
+
5
+ [Service]
6
+ User=root
7
+ WorkingDirectory=/var/www/mapa-astral
8
+ Environment="PATH=/var/www/mapa-astral/venv/bin"
9
+ ExecStart=/var/www/mapa-astral/venv/bin/streamlit run app.py --server.port=8501 --server.address=0.0.0.0
10
+
11
+ [Install]
12
+ WantedBy=multi-user.target
utils.py ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import swisseph as swe
2
+ from datetime import datetime
3
+ import pytz
4
+ from geopy.geocoders import Nominatim
5
+ from timezonefinder import TimezoneFinder
6
+ import requests
7
+ from pathlib import Path
8
+
9
+ def download_ephe_files():
10
+ """Download and configure ephemeris files."""
11
+ ephe_dir = Path("ephe")
12
+ ephe_dir.mkdir(exist_ok=True)
13
+
14
+ base_url = "https://raw.githubusercontent.com/aloistr/swisseph/master/ephe/"
15
+ essential_files = ["seas_18.se1", "semo_18.se1", "sepl_18.se1"]
16
+
17
+ for filename in essential_files:
18
+ file_path = ephe_dir / filename
19
+ if not file_path.exists():
20
+ try:
21
+ response = requests.get(f"{base_url}{filename}")
22
+ response.raise_for_status()
23
+ with open(file_path, "wb") as f:
24
+ f.write(response.content)
25
+ except Exception:
26
+ return False
27
+
28
+ swe.set_ephe_path(str(ephe_dir))
29
+ return True
30
+
31
+ def get_location_data(location_string):
32
+ """Get coordinates and timezone for a location."""
33
+ geolocator = Nominatim(user_agent="mystical_chart")
34
+ location = geolocator.geocode(location_string)
35
+ if not location:
36
+ raise ValueError("Location not found")
37
+
38
+ tf = TimezoneFinder()
39
+ timezone_str = tf.timezone_at(lat=location.latitude, lng=location.longitude)
40
+
41
+ return {
42
+ 'latitude': location.latitude,
43
+ 'longitude': location.longitude,
44
+ 'timezone': timezone_str
45
+ }
46
+
47
+ def calculate_julian_day(date, time, timezone_str):
48
+ """Calculate Julian Day from date and time."""
49
+ tz = pytz.timezone(timezone_str)
50
+ datetime_obj = datetime.combine(date, time)
51
+ local_dt = tz.localize(datetime_obj)
52
+ utc_dt = local_dt.astimezone(pytz.UTC)
53
+
54
+ jd = swe.utc_to_jd(
55
+ utc_dt.year, utc_dt.month, utc_dt.day,
56
+ utc_dt.hour, utc_dt.minute, utc_dt.second,
57
+ swe.GREG_CAL
58
+ )[1]
59
+
60
+ return jd
61
+
62
+ def get_planet_positions(jd):
63
+ """Calculate positions for all planets."""
64
+ planets = {
65
+ "Sun": swe.SUN,
66
+ "Moon": swe.MOON,
67
+ "Mercury": swe.MERCURY,
68
+ "Venus": swe.VENUS,
69
+ "Mars": swe.MARS,
70
+ "Jupiter": swe.JUPITER,
71
+ "Saturn": swe.SATURN,
72
+ "Uranus": swe.URANUS,
73
+ "Neptune": swe.NEPTUNE,
74
+ "Pluto": swe.PLUTO
75
+ }
76
+
77
+ positions = {}
78
+ for name, planet_id in planets.items():
79
+ result = swe.calc_ut(jd, planet_id)
80
+ positions[name] = {
81
+ 'longitude': result[0][0],
82
+ 'latitude': result[0][1],
83
+ 'distance': result[0][2]
84
+ }
85
+
86
+ return positions
87
+
88
+ def calculate_houses(jd, lat, lon):
89
+ """Calculate house cusps using Placidus system."""
90
+ houses, angles = swe.houses(jd, lat, lon, b'P')
91
+ return {
92
+ 'cusps': houses,
93
+ 'ascendant': angles[0],
94
+ 'mc': angles[1],
95
+ 'armc': angles[2],
96
+ 'vertex': angles[3]
97
+ }
uv.lock ADDED
The diff for this file is too large to render. See raw diff