-
Notifications
You must be signed in to change notification settings - Fork 63
fix: geometry valid in catchment area, constant as input capacity in 2sfca #3666
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b78bcef
a0b0f9a
3fa4e29
12fbeb3
d8a7b55
882545a
5cbd844
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -426,25 +426,12 @@ class HeatmapConnectivityParams(HeatmapCommon): | |
|
|
||
| class Opportunity2SFCA(OpportunityBase): | ||
| """Opportunity dataset parameters for 2SFCA heatmaps.""" | ||
|
|
||
| capacity_field: str = Field( | ||
| ..., | ||
| description="Field from the opportunity layer that contains the capacity value (e.g., number of beds, seats).", | ||
| json_schema_extra=ui_field( | ||
| section="opportunities", | ||
| field_order=5, | ||
| label_key="capacity_field", | ||
| widget="field-selector", | ||
| widget_options={"source_layer": "input_path", "field_types": ["number"]}, | ||
| visible_when={"input_path": {"$ne": None}}, | ||
| ), | ||
| ) | ||
| sensitivity: SensitivityValue = Field( | ||
| default=300000, | ||
| description="Sensitivity parameter for enhanced 2SFCA methods.", | ||
| json_schema_extra=ui_field( | ||
| section="opportunities", | ||
| field_order=6, | ||
| field_order=3, | ||
| visible_when={ | ||
| "$and": [ | ||
| {"input_path": {"$ne": None}}, | ||
|
|
@@ -454,6 +441,79 @@ class Opportunity2SFCA(OpportunityBase): | |
| ), | ||
| ) | ||
|
|
||
| capacity_type: PotentialType = Field( | ||
| default=PotentialType.constant, | ||
| description="How to determine the capacity value for each opportunity.", | ||
| json_schema_extra=ui_field( | ||
| section="opportunities", | ||
| field_order=4, | ||
| visible_when={"input_path": {"$ne": None}}, | ||
| widget_options={ | ||
| # Only show "expression" option when input_path is a polygon layer | ||
| "enum_geometry_filter": { | ||
| "source_layer": "input_path", | ||
| "expression": ["Polygon", "MultiPolygon"], | ||
| } | ||
| }, | ||
| ), | ||
| ) | ||
|
|
||
| capacity_constant: float | None = Field( | ||
| 1.0, | ||
| gt=0.0, | ||
| description="Constant capacity value applied to all features.", | ||
| json_schema_extra=ui_field( | ||
| section="opportunities", | ||
| field_order=5, | ||
| widget="number", | ||
| visible_when={"input_path": {"$ne": None}, "capacity_type": "constant"}, | ||
| ), | ||
| ) | ||
|
|
||
| capacity_field: str | None = Field( | ||
| None, | ||
| description="Field from the opportunity layer that contains the capacity value (e.g., number of beds, seats).", | ||
| json_schema_extra=ui_field( | ||
| section="opportunities", | ||
| field_order=6, | ||
| label_key="capacity_field", | ||
| widget="field-selector", | ||
| widget_options={"source_layer": "input_path", "field_types": ["number"]}, | ||
| visible_when={"input_path": {"$ne": None}, "capacity_type": "field"}, | ||
| ), | ||
| ) | ||
|
|
||
|
Comment on lines
+444
to
+485
|
||
| capacity_expression: PotentialExpression | None = Field( | ||
| None, | ||
| description="Expression to compute capacity for polygon layers (e.g. area or perimeter).", | ||
| json_schema_extra=ui_field( | ||
| section="opportunities", | ||
| field_order=7, | ||
| visible_when={"input_path": {"$ne": None}, "capacity_type": "expression"}, | ||
| ), | ||
| ) | ||
|
|
||
| @model_validator(mode="after") | ||
| def validate_capacity_fields(self: Self) -> Self: | ||
| """Validate that the correct capacity field is set based on capacity_type.""" | ||
| if self.capacity_type == PotentialType.field: | ||
| if not self.capacity_field: | ||
| raise ValueError( | ||
| "capacity_field must be set when capacity_type is 'field'." | ||
| ) | ||
| elif self.capacity_type == PotentialType.constant: | ||
| if self.capacity_constant is None: | ||
| raise ValueError( | ||
| "capacity_constant must be set when capacity_type is 'constant'." | ||
| ) | ||
| elif self.capacity_type == PotentialType.expression: | ||
| if not self.capacity_expression: | ||
| raise ValueError( | ||
| "capacity_expression must be set when capacity_type is 'expression'." | ||
| ) | ||
| return self | ||
|
|
||
|
|
||
| class TwoSFCAType(StrEnum): | ||
| """Type of 2SFCA method.""" | ||
| twosfca = "twosfca" | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_get_capacity_sqllowercases and returnscapacity_expressionas a raw SQL snippet, butcapacity_expressionis aPotentialExpressionenum (area/perimeter). The “custom user expression” branch is effectively unreachable, and the current precedence also allowscapacity_expressionto overridecapacity_typeif both are set. Consider switching to logic driven strictly bycapacity_typeand mapping enum values directly, which will be clearer and prevent surprising overrides.