|
1 | 1 | # Python imports |
2 | 2 | from datetime import date |
3 | | -import json |
4 | 3 | import math |
5 | 4 |
|
6 | 5 | # third party libraries |
|
18 | 17 |
|
19 | 18 | # E12 imports |
20 | 19 | from ..decorator import user_may_view_this_organisation, login_and_otp_required |
21 | | -from epilepsy12.constants import INDIVIDUAL_KPI_MEASURES, EnumAbstractionLevel |
| 20 | +from epilepsy12.constants import INDIVIDUAL_KPI_MEASURES |
22 | 21 | from epilepsy12.models import ( |
23 | 22 | Organisation, |
24 | 23 | KPI, |
|
54 | 53 | from epilepsy12.common_view_functions.aggregate_by import ( |
55 | 54 | update_all_kpi_agg_models, |
56 | 55 | ) |
57 | | -from epilepsy12.common_view_functions.tiles_for_region import return_tile_for_region |
58 | | -from epilepsy12.common_view_functions.map_from_shape_file import ( |
59 | | - generate_case_counts_for_each_region_in_each_abstraction_level, |
60 | | -) |
61 | 56 |
|
62 | 57 |
|
63 | 58 | def selected_organisation_summary_select(request): |
@@ -190,139 +185,72 @@ def selected_organisation_summary(request, organisation_id): |
190 | 185 | # - Other nations: default to 2011 boundaries |
191 | 186 | is_england = selected_organisation.country.boundary_identifier == "E92000001" |
192 | 187 | imd_tile_era = "2021" if (is_england and cohort_number >= 8) else "2011" |
| 188 | + nation_by_boundary_identifier = { |
| 189 | + "E92000001": "england", |
| 190 | + "W92000004": "wales", |
| 191 | + "S92000003": "scotland", |
| 192 | + "N92000002": "northern_ireland", |
| 193 | + } |
| 194 | + imd_initial_nation = nation_by_boundary_identifier.get( |
| 195 | + selected_organisation.country.boundary_identifier, "all" |
| 196 | + ) |
193 | 197 |
|
194 | | - # Serialise case locations as GeoJSON for the MapLibre deprivation map |
195 | | - _case_features = [] |
| 198 | + # Build patient list for the IMD map |
| 199 | + imd_map_patients = [] |
196 | 200 | if not case_distances_dataframe.empty: |
197 | 201 | _required = {"latitude", "longitude"} |
198 | 202 | if _required.issubset(case_distances_dataframe.columns): |
199 | 203 | for _, _row in case_distances_dataframe.dropna( |
200 | 204 | subset=["latitude", "longitude"] |
201 | 205 | ).iterrows(): |
202 | | - _props = {} |
203 | | - for _col in ( |
204 | | - "pk", |
205 | | - "distance_mi", |
206 | | - "distance_km", |
207 | | - "epilepsy12_sites__organisation__name", |
208 | | - ): |
209 | | - if _col in case_distances_dataframe.columns: |
210 | | - _val = _row[_col] |
211 | | - _props[_col] = ( |
212 | | - None |
213 | | - if (isinstance(_val, float) and math.isnan(_val)) |
214 | | - else _val |
215 | | - ) |
216 | | - _case_features.append( |
217 | | - { |
218 | | - "type": "Feature", |
219 | | - "geometry": { |
220 | | - "type": "Point", |
221 | | - "coordinates": [ |
222 | | - float(_row["longitude"]), |
223 | | - float(_row["latitude"]), |
224 | | - ], |
225 | | - }, |
226 | | - "properties": _props, |
227 | | - } |
| 206 | + patient_lat = float(_row["latitude"]) |
| 207 | + patient_lon = float(_row["longitude"]) |
| 208 | + patient_id = ( |
| 209 | + _row["pk"] if "pk" in case_distances_dataframe.columns else None |
228 | 210 | ) |
229 | | - cases_geojson = json.dumps( |
230 | | - {"type": "FeatureCollection", "features": _case_features} |
231 | | - ) |
232 | | - |
233 | | - def _build_boundary_overlay( |
234 | | - *, |
235 | | - overlay_id, |
236 | | - boundary_type, |
237 | | - region_key, |
238 | | - abstraction_enum, |
239 | | - identifier_property, |
240 | | - line_color, |
| 211 | + if patient_id is None or ( |
| 212 | + isinstance(patient_id, float) and math.isnan(patient_id) |
| 213 | + ): |
| 214 | + patient_id = f"case-{len(imd_map_patients) + 1}" |
| 215 | + |
| 216 | + imd_map_patient = { |
| 217 | + "id": str(patient_id), |
| 218 | + "lat": patient_lat, |
| 219 | + "lon": patient_lon, |
| 220 | + } |
| 221 | + if "distance_mi" in case_distances_dataframe.columns: |
| 222 | + distance_mi = _row["distance_mi"] |
| 223 | + if not (isinstance(distance_mi, float) and math.isnan(distance_mi)): |
| 224 | + imd_map_patient["distance_mi"] = float(distance_mi) |
| 225 | + if "distance_km" in case_distances_dataframe.columns: |
| 226 | + distance_km = _row["distance_km"] |
| 227 | + if not (isinstance(distance_km, float) and math.isnan(distance_km)): |
| 228 | + imd_map_patient["distance_km"] = float(distance_km) |
| 229 | + imd_map_patients.append(imd_map_patient) |
| 230 | + imd_map_lead_centre = None |
| 231 | + if ( |
| 232 | + selected_organisation.latitude is not None |
| 233 | + and selected_organisation.longitude is not None |
241 | 234 | ): |
242 | | - """Create a boundary overlay payload for the frontend map.""" |
243 | | - region_geojson = json.loads(return_tile_for_region(region_key)) |
244 | | - case_counts_df = generate_case_counts_for_each_region_in_each_abstraction_level( |
245 | | - abstraction_level=abstraction_enum, |
246 | | - cohort=cohort_number, |
247 | | - organisation=selected_organisation, |
248 | | - ) |
249 | | - |
250 | | - case_count_by_identifier = {} |
251 | | - if not case_counts_df.empty: |
252 | | - for _, count_row in case_counts_df.iterrows(): |
253 | | - identifier = count_row.get("identifier") |
254 | | - if identifier is None: |
255 | | - continue |
256 | | - raw_cases = count_row.get("cases", 0) |
257 | | - case_count_by_identifier[str(identifier)] = int(raw_cases or 0) |
258 | | - |
259 | | - for feature in region_geojson.get("features", []): |
260 | | - props = feature.setdefault("properties", {}) |
261 | | - identifier = props.get(identifier_property) |
262 | | - props["boundary_type"] = boundary_type |
263 | | - props["boundary_name"] = props.get("name", "Unknown boundary") |
264 | | - props["boundary_code"] = identifier if identifier is not None else "N/A" |
265 | | - props["case_count"] = case_count_by_identifier.get(str(identifier), 0) |
266 | | - |
267 | | - return { |
268 | | - "id": overlay_id, |
269 | | - "sourceType": "geojson", |
270 | | - "data": region_geojson, |
271 | | - "beforeLayerId": "cases-layer", |
272 | | - "linePaint": { |
273 | | - "line-color": line_color, |
274 | | - "line-width": 2, |
275 | | - "line-opacity": 0.85, |
276 | | - }, |
277 | | - "fillPaint": { |
278 | | - "fill-color": "#000000", |
279 | | - "fill-opacity": 0.0, |
280 | | - }, |
| 235 | + imd_map_lead_centre = { |
| 236 | + "lat": float(selected_organisation.latitude), |
| 237 | + "lon": float(selected_organisation.longitude), |
| 238 | + "label": selected_organisation.name, |
281 | 239 | } |
282 | 240 |
|
283 | | - boundary_overlays = [] |
284 | | - |
285 | | - # Always provide Welsh LHB boundaries so they are visible when zooming out from any centre. |
286 | | - boundary_overlays.append( |
287 | | - _build_boundary_overlay( |
288 | | - overlay_id="lhb-boundaries", |
289 | | - boundary_type="Local Health Board", |
290 | | - region_key="lhb", |
291 | | - abstraction_enum=EnumAbstractionLevel.LOCAL_HEALTH_BOARD, |
292 | | - identifier_property="ods_code", |
293 | | - line_color="#2e7d32", |
294 | | - ) |
295 | | - ) |
| 241 | + organisation_cases_imd_payload = { |
| 242 | + "initialNation": imd_initial_nation, |
| 243 | + "initialEra": imd_tile_era, |
| 244 | + "patients": imd_map_patients, |
| 245 | + "leadCentre": imd_map_lead_centre, |
| 246 | + } |
296 | 247 |
|
297 | 248 | # Use centre geography to choose trust/LHB denominator for completion summary cards. |
298 | 249 | if selected_organisation.country.boundary_identifier == "W92000004": # Wales |
299 | 250 | abstraction_level = "local_health_board" |
300 | 251 | else: |
301 | 252 | abstraction_level = "trust" |
302 | 253 |
|
303 | | - # Add English hierarchy overlays for contextual tooltips (not applicable to Jersey). |
304 | | - if selected_organisation.ods_code != "RGT1W": |
305 | | - boundary_overlays.append( |
306 | | - _build_boundary_overlay( |
307 | | - overlay_id="icb-boundaries", |
308 | | - boundary_type="Integrated Care Board", |
309 | | - region_key="icb", |
310 | | - abstraction_enum=EnumAbstractionLevel.ICB, |
311 | | - identifier_property="ods_code", |
312 | | - line_color="#7a1f2b", |
313 | | - ) |
314 | | - ) |
315 | | - boundary_overlays.append( |
316 | | - _build_boundary_overlay( |
317 | | - overlay_id="nhs-region-boundaries", |
318 | | - boundary_type="NHS England Region", |
319 | | - region_key="nhs_england_region", |
320 | | - abstraction_enum=EnumAbstractionLevel.NHS_ENGLAND_REGION, |
321 | | - identifier_property="region_code", |
322 | | - line_color="#6b7280", |
323 | | - ) |
324 | | - ) |
325 | | - |
326 | 254 | # query to return all completed E12 cases in the current cohort in this organisation |
327 | 255 | count_of_current_cohort_registered_completed_cases_in_this_organisation = ( |
328 | 256 | all_registered_cases_for_cohort_and_abstraction_level( |
@@ -460,13 +388,8 @@ def _build_boundary_overlay( |
460 | 388 | "count_of_all_current_cohort_registered_cases_in_this_trust": count_of_all_current_cohort_registered_cases_in_this_trust, |
461 | 389 | "count_of_current_cohort_registered_completed_cases_in_this_trust": count_of_current_cohort_registered_completed_cases_in_this_trust, |
462 | 390 | "individual_kpi_choices": INDIVIDUAL_KPI_MEASURES, |
463 | | - "cases_geojson": cases_geojson, |
464 | | - "boundary_overlays_geojson": json.dumps(boundary_overlays), |
465 | | - "imd_tile_era": imd_tile_era, |
466 | 391 | "deprivation_tiles_url": settings.RCPCH_DEPRIVATION_TILES_URL, |
467 | | - "org_lat": selected_organisation.latitude, |
468 | | - "org_lng": selected_organisation.longitude, |
469 | | - "org_name": selected_organisation.name, |
| 392 | + "organisation_cases_imd_payload": organisation_cases_imd_payload, |
470 | 393 | "aggregated_distances": aggregated_distances, |
471 | 394 | "organisational_audit_submission_period": organisational_audit_submission_period, |
472 | 395 | } |
|
0 commit comments