Spaces:
Sleeping
A newer version of the Gradio SDK is available: 6.15.2
title: Farm Drip Irrigation Designer
emoji: π§
colorFrom: green
colorTo: blue
sdk: gradio
sdk_version: 6.14.0
app_file: app.py
pinned: false
short_description: Design drip irrigation layouts with deterministic geometry
Farm Drip Irrigation Designer
Overview
A conversational tool for designing drip irrigation systems for farms. Phase 1 focuses on the geometry engine: deterministic pipe layout generation using shapely and pyproj.
Key features:
- Parse farm boundaries (geofences) from text input
- Generate drip irrigation layouts (main lines + parallel laterals)
- Calculate material requirements and cost estimates
- Support for multiple crop types with optimized spacing parameters
Architecture
Phase 1: Geometry Engine (Current)
Core modules:
drip_engine.pyβ Pure geometry functions (no ML)- Geofence parsing and validation
- UTM coordinate conversion (via pyproj)
- Drip layout generation (main + laterals with clipping)
- Bill of materials (BOM) estimation
- Human-readable design summaries
app.pyβ Gradio UI for testing- Input: farm boundary (geofence), crop type, design parameters
- Output: visualized layout, BOM (JSON), design summary
- Example geofences for quick testing
test_drip_engine.pyβ Comprehensive test suite- 26 unit tests covering parsing, geometry, BOM, edge cases
- All tests passing β
Phase 2: LLM Integration (Planned)
llm_handler.pyβ Conversational interface- LLM as drip irrigation specialist
- Guides users through design decisions
- Calls geometry engine to update designs
- Answers domain-specific questions
Phase 3: Deployment & Polish
- Error handling and input validation
- HF Spaces deployment with live inference
- Documentation and user workflows
Getting Started
Install Dependencies
pip install -r requirements.txt
Run Tests
python3 -m pytest test_drip_engine.py -v
Expected: 26/26 tests passing
Run the UI
python3 app.py
Then open http://localhost:7860 in your browser.
Example: 1-hectare tomato field
- Default geofence:
0,0;100,0;100,100;0,100(100m Γ 100m = 1 ha) - Select crop: "tomato" (0.5m lateral spacing)
- Headland: 1.0 m
- Click "Generate Design"
Output:
- Visual layout (green boundary, red main line, blue laterals)
- BOM with pipe lengths and costs
- Design summary with emitter count and flow rate
Design Decisions
Why Geometry, Not ML?
Drip design is deterministic. Given a field shape, crop type, and spacing preferences, the layout is fully determined. ML would be:
- Slower
- Harder to debug
- Less accurate
- Overkill for a well-defined problem
The geometry engine is the source of truth. Future ML (e.g., SAM for boundary extraction) would feed into this engine, not replace it.
Why LLM in Phase 2?
Users think in intent ("I want to grow tomatoes on 3 hectares, budget $500"), not parameters ("0.5m lateral spacing, 100m mains"). The LLM:
- Translates intent β geometry parameters
- Explains design tradeoffs
- Answers agronomic questions
- Iteratively refines based on feedback
Coordinate Systems
- Input: Pixel coords (from map screenshots) or lat/lon (GPS)
- Internal: UTM (meters) β accurate area/length calculations
- Output: Geometry objects (shapely) + JSON specs
Extensibility
Add a New Crop
Edit drip_engine.py's CROP_DEFAULTS:
CROP_DEFAULTS = {
"my_crop": {
"lateral_spacing_m": 0.75,
"emitter_spacing_m": 0.35,
"emitter_discharge_lph": 5
},
# ...
}
Adjust Cost Estimates
Edit PIPE_COSTS in drip_engine.py:
PIPE_COSTS = {
"main_line_16mm": 0.60, # Update $/meter
# ...
}
Support Lat/Lon Input
Use latlon_to_utm() instead of treating pixel coords as UTM:
polygon_latlon = parse_geofence_to_polygon(user_input)
polygon_utm = latlon_to_utm(polygon_latlon) # Auto-selects UTM zone
design = generate_drip_layout(polygon_utm, ...)
Testing
Test coverage includes:
- β Geofence parsing (valid, invalid, edge cases)
- β Polygon validation (self-intersecting, too small, etc.)
- β Area calculation (hectares from UTM)
- β Layout generation (rectangular, irregular, triangular fields)
- β Headland buffering
- β Crop-specific spacing
- β BOM cost breakdown
- β Edge cases (tiny fields, long strips, etc.)
REST API
In addition to the Gradio UI, the Space exposes a one-shot REST endpoint that accepts a flat farm / plots / water_sources payload β no Gradio /call/ two-step required.
Endpoints
GET /api/v1/healthβ{ "status": "ok", "schema_version": "v1" }POST /api/v1/designβ returns{ farm_name, design_summary, bom, zone_details, warnings, geojson }
Request schema
{
"farm": {
"name": "DakshFarm",
"location": { "address": "...", "latitude": 20.5937, "longitude": 78.9629 },
"size": { "value": 2.5, "unit": "acres" },
"crop_name": "Wheat"
},
"plots": [
{
"plot_id": "plot_1",
"name": "Plot 1",
"area_sq_m": 12450.0,
"centroid": { "latitude": 20.5938, "longitude": 78.9627 },
"boundaries": [
{ "latitude": 20.5937, "longitude": 78.9626 },
{ "latitude": 20.5939, "longitude": 78.9626 },
{ "latitude": 20.5939, "longitude": 78.9628 },
{ "latitude": 20.5937, "longitude": 78.9628 }
]
}
],
"water_sources": [
{
"water_source_id": "ws_1",
"type": "Motor",
"name": "Motor-1",
"location": { "latitude": 20.5938, "longitude": 78.9627 },
"plot_id": "plot_1"
}
],
"pump_hp": 5.0,
"headland_buffer_m": 1.0
}
curl example
curl -X POST 'https://uniphy-farm-layout-model.hf.space/api/v1/design' \
-H 'Content-Type: application/json' \
-d @samples/rest_input_example.json
Notes / current limits
- Multiple
water_sourcesare accepted, but only the first is used as the pump (returned inwarnings). - All plots inherit
farm.crop_nameas their crop. Per-plot crop overrides aren't wired up yet. - If plot polygons don't overlap, the engine sees the convex hull of their union as the farm boundary.
API Reference
parse_geofence_to_polygon(geofence_input: str) β Polygon
Parse text like "0,0;100,0;100,100;0,100" into a Shapely Polygon.
generate_drip_layout(polygon_utm, crop, headland_buffer_m, ...) β Dict
Generate layout. Returns dict with:
farm_area_ha: Area in hectaresmain_line: LineStringlaterals: List of LineStringstotal_drip_tape_m: Total lateral lengthemitter_count: Estimated emittersdesign_params: Spacing, discharge, etc.
estimate_bom(design, unit="usd") β Dict
Bill of materials with quantities and costs.
design_summary(design, bom) β str
Human-readable summary for the user.
Next Steps
- Deploy Phase 1 to HF Spaces β test with real users
- Build Phase 2 β add LLM conversational layer
- Integrate boundary extraction β use SAM or segmentation model for auto-boundary from aerial imagery (optional)
- Real-world validation β test designs with actual irrigation installers
References
- Shapely geometry library
- Pyproj coordinate transformations
- Web Mercator projection
- Drip irrigation design standards
License
MIT (for now β update as needed)