cropforge 0.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
cropforge/__init__.py ADDED
@@ -0,0 +1,31 @@
1
+ """
2
+ CropForge — Virtual Farm Runtime for Agricultural Researchers.
3
+
4
+ Open-source, code-first simulation engine. Researchers write the model;
5
+ CropForge faithfully executes it and visualises the result.
6
+
7
+ Public API (PRD Section 6.1):
8
+ from cropforge import Farm, Field, Crop
9
+
10
+ Maintainer : Saswat Sundar Rath, ICAR-IARI Jharkhand
11
+ Licence : MIT
12
+ """
13
+
14
+ __version__ = "0.2.0"
15
+
16
+ # Core public API — matches `from cropforge import Farm, Field, Crop, Weather, Soil, ...`
17
+ from cropforge.crop import Crop
18
+ from cropforge.farm import Farm, Field
19
+ from cropforge.loaders import Soil, Weather
20
+ from cropforge.runtime import CropForgeStepError, CropForgeVisualizeError
21
+
22
+ __all__ = [
23
+ "Farm",
24
+ "Field",
25
+ "Crop",
26
+ "Weather",
27
+ "Soil",
28
+ "CropForgeStepError",
29
+ "CropForgeVisualizeError",
30
+ "__version__",
31
+ ]
cropforge/crop.py ADDED
@@ -0,0 +1,77 @@
1
+ """
2
+ cropforge/crop.py
3
+ =================
4
+ Crop metadata class.
5
+
6
+ The ``Crop`` object carries species identity, variety, and sowing calendar.
7
+ It is **not** a model — it holds no physiological equations. The researcher's
8
+ ``@farm.step`` functions are the model. ``Crop`` is attached to a ``Field``
9
+ via ``Field.set_crop()`` and made available to step functions through the
10
+ field's state so they can make phenology decisions (e.g. days since sowing).
11
+
12
+ PRD Reference: Section 6.1 — Basic Usage Example.
13
+
14
+ Author : Saswat Sundar Rath, ICAR-IARI Jharkhand
15
+ Licence: MIT
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ from dataclasses import dataclass, field
21
+ from typing import Any, Dict
22
+
23
+
24
+ @dataclass
25
+ class Crop:
26
+ """Metadata describing a crop planted in a field.
27
+
28
+ Parameters
29
+ ----------
30
+ species:
31
+ Common species name, e.g. ``"wheat"``, ``"maize"``, ``"chickpea"``.
32
+ CropForge imposes no controlled vocabulary — the string is passed
33
+ through to the state log and is entirely researcher-defined.
34
+ variety:
35
+ Cultivar or variety identifier, e.g. ``"HD-2967"``, ``"custom"``.
36
+ Defaults to ``"generic"`` when the researcher does not distinguish
37
+ varieties.
38
+ sowing_doy:
39
+ Calendar day-of-year (1–366) on which sowing occurs. The runtime
40
+ engine uses this to determine when to set ``PlantState.age_days = 0``
41
+ for each plant in the field. Plants are placed in the field on the
42
+ first simulation day whose ``EnvironmentState.doy`` matches or
43
+ exceeds ``sowing_doy``.
44
+ custom:
45
+ Arbitrary researcher-defined crop metadata (e.g. base temperature,
46
+ photoperiod sensitivity). Not used by the engine directly; accessible
47
+ inside step functions via ``field.crop.custom``.
48
+
49
+ Examples
50
+ --------
51
+ >>> crop = Crop(species="wheat", variety="HD-2967", sowing_doy=290)
52
+ >>> crop.species
53
+ 'wheat'
54
+ >>> crop.sowing_doy
55
+ 290
56
+ """
57
+
58
+ species: str
59
+ variety: str = "generic"
60
+ sowing_doy: int = 1
61
+
62
+ # Extensibility hook — keeps the same pattern as SimulationState objects
63
+ custom: Dict[str, Any] = field(default_factory=dict)
64
+
65
+ def __post_init__(self) -> None:
66
+ if not isinstance(self.species, str) or not self.species.strip():
67
+ raise ValueError("Crop.species must be a non-empty string.")
68
+ if not (1 <= self.sowing_doy <= 366):
69
+ raise ValueError(
70
+ f"Crop.sowing_doy must be between 1 and 366, got {self.sowing_doy}."
71
+ )
72
+
73
+ def __repr__(self) -> str:
74
+ return (
75
+ f"Crop(species={self.species!r}, variety={self.variety!r}, "
76
+ f"sowing_doy={self.sowing_doy})"
77
+ )
@@ -0,0 +1,3 @@
1
+ # cropforge/environment.py
2
+ # Environment resolver — Phase 1 implementation target.
3
+ # Stub created in Phase 0 to satisfy package import structure.