Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,14 @@ Or
chart.show()
sys.exit(App.exec())
```

Alternatively a PySide6 based interface is available:

```
from pyside_app.main import main
if __name__ == "__main__":
main()
```
Using the GUI
-------------

Expand Down Expand Up @@ -807,3 +815,8 @@ See LICENSE file.
Contact
-------
https://github.com/naturalstupid/

FastAPI Backend
---------------
A lightweight API implementation using FastAPI is available in `src/astroapi`. Run `uvicorn astroapi.main:app --reload` to start the server.
For a browser-based UI, open `frontend/index.html` with any static file server.
91 changes: 91 additions & 0 deletions frontend/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>AstroCal Chart</title>
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script crossorigin src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<style>
body { font-family: sans-serif; padding: 1rem; }
table { border-collapse: collapse; margin-top: 1rem; }
td, th { border: 1px solid #ccc; padding: 4px 8px; }
</style>
</head>
<body>
<div id="root"></div>

<script type="text/babel">
const API_URL = 'http://localhost:8000/generate_chart';

function App() {
const [form, setForm] = React.useState({
name: '', gender: 'M', birth_date: '', birth_time: '', place: '', latitude: '', longitude: '', timezone: ''
});
const [result, setResult] = React.useState(null);

const handleChange = e => setForm({...form, [e.target.name]: e.target.value});

const submit = async e => {
e.preventDefault();
const res = await fetch(API_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(form)
});
if (res.ok) {
const data = await res.json();
setResult(data);
} else {
alert('API error');
}
};

const copyJson = () => {
if (result) navigator.clipboard.writeText(JSON.stringify(result, null, 2));
};

return (
<div>
<h1>AstroCal Chart Generator</h1>
<form onSubmit={submit}>
<div>Name: <input name="name" value={form.name} onChange={handleChange}/></div>
<div>Gender: <select name="gender" value={form.gender} onChange={handleChange}>
<option value="M">M</option>
<option value="F">F</option>
<option value="Other">Other</option>
</select></div>
<div>Birth Date: <input name="birth_date" type="date" value={form.birth_date} onChange={handleChange}/></div>
<div>Birth Time: <input name="birth_time" type="time" value={form.birth_time} onChange={handleChange}/></div>
<div>Place: <input name="place" value={form.place} onChange={handleChange}/></div>
<div>Latitude: <input name="latitude" type="number" step="0.0001" value={form.latitude} onChange={handleChange}/></div>
<div>Longitude: <input name="longitude" type="number" step="0.0001" value={form.longitude} onChange={handleChange}/></div>
<div>Timezone: <input name="timezone" type="number" step="0.1" value={form.timezone} onChange={handleChange}/></div>
<button type="submit">Generate</button>
</form>

{result && (
<div>
<h2>Result JSON</h2>
<pre>{JSON.stringify(result, null, 2)}</pre>
<button onClick={copyJson}>Copy JSON</button>
{result.info && (
<table>
<tbody>
{Object.entries(result.info).map(([k,v]) => (
<tr key={k}><th>{k}</th><td>{String(v)}</td></tr>
))}
</tbody>
</table>
)}
</div>
)}
</div>
);
}

ReactDOM.createRoot(document.getElementById('root')).render(<App/>);
</script>
</body>
</html>
8 changes: 5 additions & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
attr==0.3.2
conda==4.3.16
geocoder==1.38.1
geopy==2.4.1
img2pdf==0.5.1
Expand All @@ -9,13 +8,16 @@ Pillow==11.1.0
pyephem==9.99
PyQt6==6.8.1
PyQt6_sip==13.8.0
PySide6==6.7.0
pyqtgraph==0.13.7
pyswisseph==2.10.3.2
pytest==7.4.4
pytest.egg==info
python_dateutil==2.9.0.post0
pytz==2024.1
Requests==2.32.3
setuptools==69.5.1
setuptools==75.6.0
timezonefinder==6.5.8

fastapi==0.111.0
uvicorn==0.29.0
pydantic==2.7.1
31 changes: 31 additions & 0 deletions src/astroapi/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# AstroCal FastAPI Backend

This module exposes horoscope computations via a simple REST API.

## Endpoints

- `GET /health` – basic health check
- `POST /chart` or `/generate_chart` – compute a Vedic horoscope

### Example request

```json
{
"name": "John Doe",
"gender": "M",
"birth_date": "2000-01-01",
"birth_time": "12:34:00",
"place": "Chennai, India",
"latitude": 13.0827,
"longitude": 80.2707,
"timezone": 5.5
}
```

Start the API with:

```bash
uvicorn astroapi.main:app --reload
```

The response contains horoscope information ready for client consumption.
Empty file added src/astroapi/__init__.py
Empty file.
5 changes: 5 additions & 0 deletions src/astroapi/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from .main import app

if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
22 changes: 22 additions & 0 deletions src/astroapi/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"""FastAPI application exposing horoscope computation endpoints."""
from fastapi import FastAPI, HTTPException

from .models import ChartRequest
from .services import compute_chart

app = FastAPI(title="AstroCal API")

@app.get("/health")
def health_check():
"""Simple health check endpoint."""
return {"status": "ok"}

@app.post("/chart")
@app.post("/generate_chart")
def generate_chart(request: ChartRequest):
"""Compute a Vedic horoscope and return detailed data."""
try:
return compute_chart(request)
except Exception as exc:
raise HTTPException(status_code=500, detail=str(exc))

14 changes: 14 additions & 0 deletions src/astroapi/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from datetime import date, time
from pydantic import BaseModel

class ChartRequest(BaseModel):
"""Parameters required to compute a horoscope chart."""
name: str
gender: str
birth_date: date
birth_time: time
place: str
latitude: float
longitude: float
timezone: float

37 changes: 37 additions & 0 deletions src/astroapi/services.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"""Utility functions for computing horoscope information."""
from datetime import datetime
from typing import Dict, Any

from jhora.horoscope import main
from jhora.panchanga import drik

from .models import ChartRequest


def compute_chart(request: ChartRequest) -> Dict[str, Any]:
"""Generate horoscope data using existing jhora classes."""
dob = drik.Date(request.birth_date.year, request.birth_date.month, request.birth_date.day)
tob = (request.birth_time.hour, request.birth_time.minute, request.birth_time.second)
place = drik.Place(request.place, request.latitude, request.longitude, request.timezone)

horo = main.Horoscope(
place_with_country_code=request.place,
latitude=request.latitude,
longitude=request.longitude,
timezone_offset=request.timezone,
date_in=dob,
birth_time=request.birth_time.strftime("%H:%M:%S"),
)

info, charts, houses = horo.get_horoscope_information()
vimsottari = horo._get_vimsottari_dhasa_bhukthi(dob, tob, place)

return {
"name": request.name,
"gender": request.gender,
"info": info,
"charts": charts,
"ascendant_houses": houses,
"vimsottari_dhasa": vimsottari,
}

Binary file added src/jhora/__pycache__/__init__.cpython-311.pyc
Binary file not shown.
Binary file added src/jhora/__pycache__/_package_info.cpython-311.pyc
Binary file not shown.
Binary file added src/jhora/__pycache__/const.cpython-311.pyc
Binary file not shown.
Binary file added src/jhora/__pycache__/utils.cpython-311.pyc
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
1 change: 1 addition & 0 deletions src/jhora/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ numpy==2.1.1
pandas==2.2.2
Pillow==10.4.0
PyQt6==6.7.1
PySide6==6.7.0
pyqtgraph==0.13.7
python_dateutil==2.9.0.post0
pytz==2024.1
Expand Down
4 changes: 4 additions & 0 deletions src/jhora/tests/test_ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import pytest

pytest.skip("Manual UI test", allow_module_level=True)

import sys
from PyQt6.QtWidgets import QApplication

Expand Down
Binary file added src/jhora/ui/__pycache__/__init__.cpython-311.pyc
Binary file not shown.
Binary file added src/jhora/ui/__pycache__/chakra.cpython-311.pyc
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading