forked from ChelseaKR/nearmiss
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
214 lines (202 loc) · 10.8 KB
/
Copy pathindex.html
File metadata and controls
214 lines (202 loc) · 10.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>nearmiss — where the danger actually is (Davis)</title>
<meta
name="description"
content="The same near-miss reports mapped two ways: raw counts (what most maps show) versus exposure-normalized rates with confidence intervals and Getis-Ord hotspots (where the danger actually is). The data table is the authoritative, non-visual equivalent of the maps."
/>
<link rel="stylesheet" href="vendor/leaflet/leaflet.css" />
<link rel="stylesheet" href="style.css" />
</head>
<body>
<a class="skip-link" href="#main" data-i18n="skip">Skip to the data</a>
<header>
<div class="lang-switch" role="group" aria-label="Language / Idioma">
<button type="button" data-lang="en" aria-pressed="true">English</button>
<button type="button" data-lang="es" aria-pressed="false">Español</button>
</div>
<h1 data-i18n="h1">nearmiss — where the danger actually is</h1>
<p class="lede" data-i18n="lede">
Road-hazard and near-miss <strong>rates, normalized by exposure</strong>, each with a
95% confidence interval and an <em>n</em>. Raw counts are report volume, not danger.
The two maps below show the difference; the <a href="#data-table">data table</a>
carries every finding and is the authoritative, non-visual equivalent of the maps.
</p>
<p class="demo-note" data-i18n="demo">
⚠️ Showing the <strong>Davis synthetic demo</strong> dataset — generated test data, not
real reports. The method is the point: swap in real reports with no code change.
</p>
<p class="report-cta">
<a href="submit.html" data-i18n="report_cta">Report a near-miss →</a>
</p>
</header>
<main id="main">
<p id="bottom-line" class="bottom-line" data-i18n="blLoading">Summarizing…</p>
<section aria-labelledby="map-heading">
<h2 id="map-heading" data-i18n="map_h">Two maps, the same reports</h2>
<p id="map-desc" data-i18n="map_desc">
The same near-miss reports, mapped two ways on a real street map. On the left, the
<strong>raw report count</strong> — what most safety maps show: the busiest street looks
the most dangerous. On the right, the <strong>rate per 1000 units of exposure</strong> —
which is what actually reflects danger. Watch the busiest street recede and the real
hotspot emerge. Nothing is conveyed by color alone: line thickness scales with the value,
and significant hotspots are dashed and labeled. Everything here is in the
<a href="#data-table">data table</a>, which the maps supplement.
</p>
<p id="hotspot-summary" class="hotspot-summary" aria-live="polite" data-i18n="hsLoading">
Summarizing hotspots…
</p>
<div class="map-toggle" role="group" aria-labelledby="map-toggle-label">
<span id="map-toggle-label" data-i18n="mv_label">Show:</span>
<button type="button" data-mapview="both" aria-pressed="true" data-i18n="mv_both">Both maps</button>
<button type="button" data-mapview="reports" aria-pressed="false" data-i18n="mv_reports">Reports only</button>
<button type="button" data-mapview="rate" aria-pressed="false" data-i18n="mv_rate">Rate only</button>
</div>
<div class="map-split" data-view="both">
<figure class="map-fig">
<figcaption class="map-title" data-i18n="map_reports_t">
① Raw report count — what most maps show
</figcaption>
<div
id="map-reports"
class="leaflet-map"
role="group"
aria-label="Map of reported near-miss counts by street segment. The equivalent data is in the table below."
aria-describedby="cap-reports"
></div>
<figcaption id="cap-reports" class="map-cap" data-i18n="loading_map">Loading map…</figcaption>
</figure>
<figure class="map-fig">
<figcaption class="map-title" data-i18n="map_rate_t">
② Exposure-normalized rate — where the danger actually is
</figcaption>
<div
id="map-rate"
class="leaflet-map"
role="group"
aria-label="Map of exposure-normalized hazard rates with significant hotspots by street segment. The equivalent data is in the table below."
aria-describedby="cap-rate"
></div>
<figcaption id="cap-rate" class="map-cap" data-i18n="loading_map">Loading map…</figcaption>
</figure>
</div>
</section>
<section aria-labelledby="data-heading">
<h2 id="data-heading" data-i18n="data_h">Ranked segments</h2>
<p data-i18n="sort_help">
Sort the table with the column buttons. <strong>Significance</strong> and
<strong>confidence</strong> are stated in words, not by color.
</p>
<p id="sort-status" class="visually-hidden" aria-live="polite"></p>
<div class="table-controls">
<label for="table-filter" data-i18n="filter_label">Filter segments by name</label>
<input type="search" id="table-filter" autocomplete="off" />
<span id="filter-status" class="filter-status" aria-live="polite"></span>
</div>
<div class="table-wrap" tabindex="0" role="region" aria-label="Ranked segments table (scrollable)">
<table id="data-table">
<caption id="data-caption">Loading…</caption>
<thead>
<tr>
<th scope="col">
<button type="button" data-sort="name" data-i18n="th_segment">Segment</button>
</th>
<th scope="col" data-i18n-title="tt_rate">
<button type="button" data-sort="rate" data-i18n="th_rate">Rate /1000</button>
</th>
<th scope="col" data-i18n="th_ci" data-i18n-title="tt_ci">95% CI</th>
<th scope="col" data-i18n-title="tt_n">
<button type="button" data-sort="n" data-i18n="th_n">Reports (n)</button>
</th>
<th scope="col" data-i18n="th_hazards" data-i18n-title="tt_hazards">Hazards</th>
<th scope="col" data-i18n="th_conf" data-i18n-title="tt_conf">Confidence</th>
<th scope="col" data-i18n-title="tt_hot">
<button type="button" data-sort="getis_ord_z" data-i18n="th_hot">Hotspot (Gi*)</button>
</th>
<th scope="col" data-i18n="th_flags" data-i18n-title="tt_flags">Quality flags</th>
</tr>
</thead>
<tbody id="data-body">
<tr>
<td colspan="8" data-i18n="loading">Loading published data…</td>
</tr>
</tbody>
</table>
</div>
<p class="downloads">
<a id="download-data" href="../data/published/davis.geojson" download data-i18n="download"
>Download this dataset (GeoJSON)</a
><span id="download-meta"></span>
</p>
</section>
<section aria-labelledby="legend-heading">
<h2 id="legend-heading" data-i18n="legend_h">How to read this</h2>
<ul data-i18n="legend">
<li><strong>Rate /1000</strong> — reports per 1000 units of exposure, not a raw count.</li>
<li><strong>95% CI</strong> — the plausible range. A wide range means uncertainty.</li>
<li>
<strong>Confidence</strong> — “uncertain” marks small samples; “exposure unknown”
marks segments with no denominator (never ranked as if certain).
</li>
<li>
<strong>Hotspot (Gi*)</strong> — “★ Significant” marks a statistically significant
cluster (Getis-Ord Gi*, z > 1.96): hot beyond what exposure and chance explain.
</li>
</ul>
</section>
<section aria-labelledby="faq-heading">
<h2 id="faq-heading" data-i18n="faq_h">Questions people ask</h2>
<details class="faq">
<summary data-i18n="faq_q1">Why isn’t my busy street the most dangerous one?</summary>
<p data-i18n="faq_a1">
Because volume is not danger. A busy street collects the most reports simply because the
most people use it. We divide reports by exposure (how much cycling each street carries),
so the map shows the rate per rider, not the raw count. A high-traffic street can have
many reports and still be safer per trip than a quiet one with a few.
</p>
</details>
<details class="faq">
<summary data-i18n="faq_q2">Is a near-miss the same as a crash?</summary>
<p data-i18n="faq_a2">
No. These are self-reported near-misses and hazards, which by definition usually leave no
police report. They are an early-warning signal, not verified injuries or collision
statistics, and we never present them as such.
</p>
</details>
<details class="faq">
<summary data-i18n="faq_q3">What does “exposure unknown” mean?</summary>
<p data-i18n="faq_a3">
It means we have no trustworthy count of how many people cycle that street, so we will not
invent a denominator. Those segments are shown as uncertain and are never ranked as if we
were sure. A rate without a denominator is not published.
</p>
</details>
<details class="faq">
<summary data-i18n="faq_q4">How do I know which streets are really hotspots?</summary>
<p data-i18n="faq_a4">
A street is marked “★ Significant” only when a statistical test (Getis-Ord Gi*, with a
false-discovery-rate correction) says it is hotter than exposure and chance alone would
explain. Everything else carries a confidence interval so you can see how sure — or
unsure — the number is.
</p>
</details>
</section>
</main>
<footer>
<p data-i18n="footer">
Open data, Apache-2.0.
<a href="https://github.com/ChelseaKR/nearmiss">Source on GitHub</a> ·
<a href="https://chelseakr.com">chelseakr.com</a>. Maps ©
<a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors. Methods:
<code>docs/METHODOLOGY.md</code>; what it can't tell you: <code>docs/LIMITATIONS.md</code>;
limits and biases: <code>docs/DATA-CARD.md</code>.
Every figure regenerates with <code>make reproduce</code>.
</p>
</footer>
<script src="vendor/leaflet/leaflet.js"></script>
<script src="app.js"></script>
</body>
</html>