Metadata-Version: 2.4
Name: geodatasim
Version: 0.6.5
Summary: Production-Grade City Intelligence: Offline-first data platform with auto-retry, graceful degradation & configurable logging
Author-email: Teyfik OZ <teyfikoz@yahoo.com>
License: MIT
Project-URL: Homepage, https://github.com/teyfikoz/GeoDataSim
Project-URL: Repository, https://github.com/teyfikoz/GeoDataSim
Project-URL: Documentation, https://github.com/teyfikoz/GeoDataSim#readme
Project-URL: Issues, https://github.com/teyfikoz/GeoDataSim/issues
Keywords: geography,geospatial,city-data,socioeconomic,climate,world-bank,urban-planning,data-science,gis,location-intelligence,machine-learning,clustering,visualization,plotly,sklearn,auto-update,city-analytics
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: GIS
Classifier: Topic :: Scientific/Engineering :: Information Analysis
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.31.0
Requires-Dist: pandas>=2.0.0
Requires-Dist: numpy>=1.24.0
Requires-Dist: python-dateutil>=2.8.0
Requires-Dist: scikit-learn>=1.3.0
Requires-Dist: numba>=0.58.0
Requires-Dist: pydantic>=2.5.0
Requires-Dist: plotly>=5.17.0
Requires-Dist: kaleido>=0.2.1
Requires-Dist: geopy>=2.4.0
Requires-Dist: tqdm>=4.66.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0; extra == "dev"
Requires-Dist: pytest-timeout>=2.0; extra == "dev"
Requires-Dist: black>=23.0; extra == "dev"
Requires-Dist: ruff>=0.1.0; extra == "dev"
Requires-Dist: mypy>=1.0; extra == "dev"
Provides-Extra: export
Requires-Dist: openpyxl>=3.1.0; extra == "export"
Requires-Dist: tabulate>=0.9.0; extra == "export"
Provides-Extra: weather
Requires-Dist: pyowm>=3.3.0; extra == "weather"
Provides-Extra: full
Requires-Dist: openpyxl>=3.1.0; extra == "full"
Requires-Dist: tabulate>=0.9.0; extra == "full"
Requires-Dist: pyowm>=3.3.0; extra == "full"
Requires-Dist: geopy>=2.4.0; extra == "full"
Requires-Dist: pycountry>=23.0; extra == "full"
Dynamic: license-file

# GeoDataSim

**World's most comprehensive city intelligence platform** — geographic, socioeconomic, climate, and ML-powered analytics for 46+ world cities. World Bank integration, city similarity, ML clustering, interactive visualization, and automatic data updates. Zero API key required.

[![PyPI version](https://badge.fury.io/py/geodatasim.svg)](https://pypi.org/project/geodatasim/)
[![CI](https://github.com/teyfikoz/geodatasim/actions/workflows/ci.yml/badge.svg)](https://github.com/teyfikoz/geodatasim/actions/workflows/ci.yml)
[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

## Installation

```bash
pip install geodatasim
```

Full extras (ML clustering, visualization, World Bank updates):

```bash
pip install "geodatasim[full]"
```

## Quick Start

```python
from geodatasim import City

istanbul = City("Istanbul")
print(istanbul.population)       # ~15,800,000
print(istanbul.gdp_per_capita)   # ~28,000 (USD)
print(istanbul.climate_zone)     # Mediterranean
print(istanbul.country)          # Turkey

# Find the 5 most similar cities worldwide
similar = istanbul.find_similar(n=5)
for city in similar:
    print(city.name, city.country)
# Athens, Greece
# Madrid, Spain
# ...
```

---

## Features at a Glance

| Feature | Description |
|---------|-------------|
| **City Data** | 46+ cities — population, GDP, climate, coordinates, timezone |
| **Similarity Engine** | Multi-indicator cosine similarity across economic + geographic metrics |
| **ML Clustering** | K-means + agglomerative clustering with cluster labels |
| **World Bank API** | Live GDP, population, HDI data refresh |
| **Batch Analysis** | Compare multiple cities side-by-side in a DataFrame |
| **Rankings** | Rank cities by any indicator (GDP, population, HDI, ...) |
| **Export** | CSV, Excel, JSON, Markdown output |
| **Visualization** | Scatter, heatmap, radar charts (requires plotly) |
| **Data Validation** | Pydantic models for type-safe city data |
| **Auto-Update** | Monthly data refresh from public APIs |

---

## City Object

```python
from geodatasim import City

city = City("Tokyo")

# Geographic
print(city.latitude, city.longitude)
print(city.country, city.continent)
print(city.timezone)               # Asia/Tokyo
print(city.elevation_m)            # 40

# Socioeconomic
print(city.population)             # ~13,960,000
print(city.gdp_per_capita)         # ~48,000
print(city.unemployment_rate)      # 2.4
print(city.hdi)                    # 0.919

# Climate
print(city.climate_zone)           # Humid subtropical
print(city.avg_temp_celsius)       # 15.4
print(city.annual_rainfall_mm)     # 1,528

# Infrastructure
print(city.internet_penetration)   # 0.94
print(city.airport_iata)           # HND / NRT

# City classification
print(city.city_type)              # Megacity
```

---

## City Similarity

```python
from geodatasim import City, CitySimilarity

city = City("Istanbul")

# 5 most similar cities (multi-indicator weighted cosine)
similar = city.find_similar(n=5)
for c in similar:
    print(f"{c.name:20s} {c.country:15s}")
# Athens               Greece
# Madrid               Spain
# Milan                Italy
# Barcelona            Spain
# Lisbon               Portugal

# Custom similarity with CitySimilarity directly
cs = CitySimilarity()
score = cs.compute("Istanbul", "Athens")
print(f"Similarity score: {score:.3f}")  # 0.921

# Compare a city to all others and rank
ranking = cs.rank_similar("Tokyo", top_n=10)
```

---

## Batch Analysis

```python
from geodatasim import BatchAnalyzer

# Compare multiple cities at once
analyzer = BatchAnalyzer(["Istanbul", "Paris", "Tokyo", "New York", "Singapore"])

# Get full DataFrame
df = analyzer.to_dataframe()
print(df[["city", "country", "population", "gdp_per_capita", "hdi"]].to_string(index=False))

# Export
analyzer.to_csv("city_comparison.csv")
analyzer.to_excel("city_comparison.xlsx")
analyzer.to_json("city_comparison.json")
analyzer.to_markdown("city_comparison.md")
```

---

## City Rankings

```python
from geodatasim import CityRankings, rank_cities

rankings = CityRankings()

# Rank by indicator
top_gdp = rankings.by_gdp_per_capita(n=10)
top_pop = rankings.by_population(n=5)
top_hdi = rankings.by_hdi(n=10)

print("Top 5 by GDP per capita:")
for i, city in enumerate(top_gdp[:5], 1):
    print(f"  {i}. {city.name:20s} ${city.gdp_per_capita:,.0f}")

# Quick function
top5 = rank_cities(indicator="internet_penetration", n=5)
```

---

## ML Clustering

```python
from geodatasim import CityClustering, cluster_cities, BatchAnalyzer

# Build DataFrame of all cities
df = BatchAnalyzer.all_cities().to_dataframe()

# Cluster into 5 groups
clustering = CityClustering(n_clusters=5)
clustering.fit(df)

print(clustering.cluster_labels_)
# {'Istanbul': 2, 'Paris': 3, 'Tokyo': 4, 'Lagos': 0, ...}

# Get cities in same cluster as Istanbul
cluster_id = clustering.cluster_labels_["Istanbul"]
peers = clustering.get_cluster(cluster_id)
print(f"Istanbul's cluster: {peers}")

# Quick shortcut
groups = cluster_cities(n_clusters=4)
```

---

## Fast Similarity (ML-Powered)

```python
from geodatasim import FastSimilarityEngine, find_similar_fast

engine = FastSimilarityEngine()
engine.build_index()   # builds ANN index once

# Lightning-fast nearest neighbors
similar = engine.find_similar("London", n=5)

# Or use the shortcut
results = find_similar_fast("Berlin", n=8)
for city_name, score in results:
    print(f"  {city_name:20s}  score={score:.3f}")
```

---

## Visualization

```python
from geodatasim import CityVisualizer, BatchAnalyzer

df = BatchAnalyzer.all_cities().to_dataframe()
viz = CityVisualizer()

# Scatter plot: GDP vs Population
fig = viz.scatter(df, x="gdp_per_capita", y="population", color="continent", size="hdi")
fig.show()

# Heatmap of all numeric indicators
heatmap = viz.heatmap(df)
heatmap.show()

# Radar chart comparing 3 cities
radar = viz.radar(
    ["Istanbul", "Singapore", "Amsterdam"],
    indicators=["gdp_per_capita", "hdi", "internet_penetration"]
)
radar.show()

# Quick functions
from geodatasim import quick_scatter, quick_heatmap, quick_radar
quick_scatter(df, "population", "gdp_per_capita").show()
```

---

## World Bank Auto-Update

```python
from geodatasim.core.updater import UpdateEngine, update_city_data

# Update a single city from World Bank API
istanbul_data = {"name": "Istanbul", "country_code": "TUR"}
updated = update_city_data(istanbul_data)
print(f"Updated GDP: ${updated['gdp_per_capita']:,.0f}")

# Batch update all cities
engine = UpdateEngine()
engine.update_all()   # fetches World Bank data for all cities
engine.save()         # writes updated dataset to cache
```

---

## Data Validation

```python
from geodatasim.core.validator import CityModel, validate_city_data

# Validate raw data against the City schema (Pydantic)
raw = {
    "name": "Testville",
    "country": "Testland",
    "population": 1_000_000,
    "gdp_per_capita": 25000,
    "latitude": 40.0,
    "longitude": 29.0,
}
city = validate_city_data(raw)
print(city)  # CityModel instance with type-safe fields
```

---

## Economic & Climate Profiles

```python
from geodatasim import City, EconomicIndicators, ClimateProfile

city = City("Singapore")

econ: EconomicIndicators = city.economic_indicators
print(econ.gdp_per_capita)
print(econ.unemployment_rate)
print(econ.hdi)
print(econ.gini_coefficient)

climate: ClimateProfile = city.climate_profile
print(climate.zone)              # Tropical rainforest
print(climate.avg_temp_celsius)
print(climate.annual_rainfall_mm)
print(climate.humidity_pct)
```

---

## Full Pipeline Example

```python
from geodatasim import City, BatchAnalyzer, CityRankings, CityClustering

# 1. Load all cities into DataFrame
df = BatchAnalyzer.all_cities().to_dataframe()

# 2. Cluster into 4 economic groups
clustering = CityClustering(n_clusters=4)
clustering.fit(df)

# 3. Rank within Istanbul's cluster
istanbul_cluster = clustering.get_cluster(clustering.cluster_labels_["Istanbul"])
ranked = CityRankings().by_gdp_per_capita(cities=istanbul_cluster)
print("Istanbul's economic peer group (ranked by GDP):")
for i, c in enumerate(ranked, 1):
    print(f"  {i}. {c.name:20s} ${c.gdp_per_capita:>8,.0f}")

# 4. Find Istanbul's top 3 similar cities
istanbul = City("Istanbul")
print("\nMost similar cities:")
for c in istanbul.find_similar(3):
    print(f"  {c.name} ({c.country})")
```

---

## Data Sources

All data from public domain sources:
- **World Bank Open Data** — GDP, population, HDI
- **REST Countries** — country metadata
- **Open-Meteo** — climate data

---

## License

MIT — [Teyfik Öz](https://github.com/teyfikoz)
