Skip to content
Merged
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
10 changes: 9 additions & 1 deletion QUICKSTART.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@ This runs:
- Click twice to create a rectangle
- Refresh page - annotation persists!

## Upload Your Own Image

1. Click **"Upload Image"** button on homepage
2. Drag & drop or select an image (JPG, PNG, TIFF)
3. Enter a name and click "Upload & Process"
4. Wait for tile generation (progress shown)
5. View your high-resolution dataset!

## Quick Test

```bash
Expand Down Expand Up @@ -104,9 +112,9 @@ python3 infra/generate_sample_tiles.py

## Next Steps

- Upload your own images (click "Upload Image" on homepage)
- Read [README.md](README.md) for full documentation
- Explore the code in `apps/web/src/components/`
- Add your own datasets (see README)
- Deploy to production

Happy hacking! 🌌
93 changes: 79 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Built for a 36-hour hackathon, Astro-Zoom lets you explore massive astronomical

## ✨ Features

- **📤 Image Upload** — Upload your own images via web UI with automatic tile processing
- **🔍 Deep Zoom Navigation** — Explore gigapixel images with smooth pan/zoom using OpenSeadragon
- **🤖 AI Search** — Find features with natural language queries powered by CLIP embeddings
- **✏️ Annotations** — Create points, rectangles, and polygons with labels
Expand Down Expand Up @@ -110,9 +111,41 @@ Wait ~30s for services to start, then visit http://localhost:3000.

## 📖 Usage

### Using Real NASA Data
### Uploading Your Own Images

The project includes mock sample tiles by default. To use the **real 209MB NASA Andromeda image**:
The easiest way to add your own high-resolution images is through the web interface:

1. **Start the services:** `pnpm dev`
2. **Navigate to** http://localhost:3000
3. **Click "Upload Image"** button
4. **Select or drag-and-drop** your image (JPG, PNG, TIFF up to 500MB)
5. **Enter name and description**
6. **Wait for processing** (10-30 minutes depending on size)
7. **View your dataset!**

The system will automatically generate optimized DZI tiles with progress tracking.

**Supported formats:** JPG, PNG, TIFF • **Max size:** 500MB • **Min dimensions:** 256×256px

### Managing Datasets

Each dataset card on the homepage includes a **delete button** (trash icon):
- Click the delete button on any dataset
- Confirm the deletion
- The system will robustly remove all associated files (tiles, uploads, database entries)
- Deletion works even if the dataset is corrupted or partially missing

**Storage Optimization:** The system automatically cleans up temporary files:
- Original upload files are deleted after successful tile generation
- Temp directories are cleaned automatically
- Only the optimized tiles and database entries are kept
- This saves 40-60% disk space compared to keeping original uploads

See [STORAGE_LOCATIONS.md](STORAGE_LOCATIONS.md) for detailed storage information.

### Using Real NASA Data (Manual Processing)

The project includes mock sample tiles by default. To manually process the **real 209MB NASA Andromeda image**:

```bash
# Install tiling dependencies
Expand Down Expand Up @@ -255,22 +288,48 @@ pnpm test

## 📊 Adding Your Own Datasets

### 1. Create DZI Tiles
### Option 1: Web Upload (Recommended)

The easiest way! Upload through the web interface at http://localhost:3000:

1. Click **"Upload Image"** button
2. Select your image (JPG, PNG, or TIFF up to 500MB)
3. Enter dataset name and description
4. System automatically:
- Validates the image
- Generates multi-resolution DZI tiles
- Creates database entry
- Indexes for search

Use [Vips](https://www.libvips.org/) or [OpenSlide](https://openslide.org/) to generate DZI pyramids:
**API Upload:**

```bash
# With ImageMagick + vips
vips dzsave your_image.tif tiles/my-dataset

# This creates:
# tiles/my-dataset/info.dzi
# tiles/my-dataset/0/0_0.jpg
# tiles/my-dataset/1/*.jpg
# ... etc
curl -X POST http://localhost:8000/uploads/upload \
-F "file=@your-image.jpg" \
-F "name=My Dataset" \
-F "description=Optional description"

# Check processing status
curl http://localhost:8000/uploads/status/{dataset-id}
```

### 2. Register Dataset
### Option 2: Manual Tile Generation

For advanced use cases or external tile generation:

**1. Create DZI Tiles**

Use [Vips](https://www.libvips.org/), [OpenSlide](https://openslide.org/), or Python:

```bash
# With vips
vips dzsave your_image.tif infra/tiles/my-dataset

# Or use the provided script
python infra/process_real_image.py # Edit paths in script
```

**2. Register Dataset**

Add to `apps/api/app/seed.py`:

Expand All @@ -287,7 +346,7 @@ dataset = Dataset(
session.add(dataset)
```

### 3. Build Search Index
**3. Build Search Index** (optional)

```bash
cd apps/ai
Expand Down Expand Up @@ -365,6 +424,12 @@ FastAPI automatically generates OpenAPI docs:
- `GET /tiles/{dataset}/info.dzi` — DZI descriptor
- `GET /tiles/{dataset}/{level}/{col}_{row}.jpg` — Tile image

**Uploads**

- `POST /uploads/upload` — Upload and process image
- `GET /uploads/status/{id}` — Check processing status
- `DELETE /uploads/{id}` — Delete dataset and tiles

## 🤝 Contributing

This is a hackathon project, but contributions are welcome!
Expand Down
3 changes: 2 additions & 1 deletion apps/api/app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

from app.config import CORS_ORIGINS
from app.db import create_db_and_tables
from app.routers import datasets, features, annotations, search, tiles, auth as auth_router
from app.routers import datasets, features, annotations, search, tiles, auth as auth_router, uploads
from app.seed import seed_database

# Rate limiter
Expand Down Expand Up @@ -55,6 +55,7 @@ async def lifespan(app: FastAPI):
app.include_router(annotations.router, prefix="/annotations", tags=["annotations"])
app.include_router(search.router, prefix="/search", tags=["search"])
app.include_router(tiles.router, prefix="/tiles", tags=["tiles"])
app.include_router(uploads.router, prefix="/uploads", tags=["uploads"])


@app.get("/health")
Expand Down
Loading
Loading