flowchart TB
C[/"City counts<br/>15-minute slices, 2024 to 2026"/]:::data
J[/"S1 junctions"/]:::data
P[/"S4 places<br/>with their hours text"/]:::data
R[/"Rules: within 15 m,<br/>open at half past"/]:::rule
subgraph MEASURED["MEASURED"]
Q["QUARTERS<br/>every counted slice, zeros kept"]:::step --> H["HOURS<br/>four quarters, or no value"]:::step
H --> S["SHAPE<br/>each day over its reference hours"]:::step
S --> W["A WEEKDAY<br/>mean, lowest, highest"]:::step
end
subgraph PROMISED["PROMISED"]
O["READ THE HOURS<br/>minute by minute"]:::step --> K["EACH HOUR<br/>open, closed or unknown"]:::step
end
C --> Q
J --> Q
R -.-> Q
P --> O
R -.-> K
W --> OUT1[/"weekday shape,<br/>counts by junction"/]:::out
K --> OUT2[/"each place's week,<br/>places open per hour"/]:::out
OUT1 --> T["TESTS"]:::test
OUT2 --> T
classDef data fill:none,stroke:#8a8a8a,color:#e6e6e6
classDef rule fill:none,stroke:#8a8a8a,stroke-dasharray:4 3,color:#a6a6a6
classDef step fill:none,stroke:#e6e6e6,color:#e6e6e6
classDef out fill:none,stroke:#e6e6e6,stroke-width:2px,color:#ffffff
classDef test fill:none,stroke:#fe83cc,color:#fe83cc
style MEASURED fill:none,stroke:#3a3a3a
style PROMISED fill:none,stroke:#3a3a3a
How S5 is built and tested
Blueprint
From quarter-hours to hours
The city counts in 15-minute slices, by kind of road user. S5 keeps every slice counted within 15 m of an S1 junction, the same rule as the counts page, and sums it by mode, keeping people on foot and bicycles apart from motor vehicles of every kind. A slice with nobody in it stays a counted zero, which differs from a slice nobody counted.
An hour gets a value only when all four of its quarters were counted. Several of the one-day windows open or close on the half hour, so their edge hours are partial: 16 hours at the junctions, 48 rows across the modes, stay empty, each with the number of quarters it had. S5 never stretches a part of an hour into a whole one.
The day’s shape
A busy junction and a quiet one can share a rhythm, so S5 compares each day with itself. The reference hours are the hours counted in full on every day: 7h, 8h, 11h, 12h, 16h and 17h. Each day, for each mode, is divided by its own mean over those six hours, so 1.0 is an ordinary daytime hour of that day. Two of the six fall in each of the city’s windows, so no window outweighs another.
A weekday hour takes the mean of every day that counted it, and keeps their lowest and highest values. Each value names the days behind it, so it can be rebuilt by hand. Outside the reference hours, most hours rest on J040 alone, and S5 marks them.
Only Tuesdays, Wednesdays and Thursdays were counted. S5 lets their shape stand in for Monday and Friday, and says so on every such row. Saturday and Sunday stay empty, with the reason.
Bicycle detectors
The city’s permanent bicycle detectors report every hour, by site, direction and lane. S5 keeps the detectors whose point lies inside the study area, by the same test S4 uses for buildings: Peel at Ottawa, northbound and southbound, and William at Nazareth, westbound. Two detectors on Peel at Notre-Dame stand 35 and 49 m from junction J187, outside the area, and S5 lists them without using them.
A recorded hour of 0 stays 0, and a missing hour is a gap. A detector’s day counts only when all 24 hours were recorded, and the Griffintown day sums the three detectors on days when every one is complete: 376 days. Each such day is divided by its own mean over the same reference hours as the counts, then grouped by kind of day (weekday, Saturday, Sunday) and season. A group keeps its mean and its middle half, the range of the central half of its days.
The seasons are the meteorological ones: winter from December to February, spring from March to May, and so on. Holidays are not set apart, so a public holiday on a Monday counts as a weekday.
Reading opening hours
OpenStreetMap writes hours in a small grammar, like Mo-Fr 07:00-22:00; Sa 08:00-20:00; Su off. S5 reads the part of it Griffintown’s places use. Rules separated by a semicolon replace what earlier rules said about the same days; a rule after a comma adds to them. A day the text never names is closed, which is the tag’s own convention. Hours that run past midnight carry into the next morning, so a bar open 17:00-03:00 on Saturday is open early on Sunday. An opening with no closing time, a note such as “sur rdv” (by appointment), or a text S5 cannot parse leaves those hours unknown. Public holidays are set aside, since S5 has no calendar yet.
The city’s list of public places writes its hours in French, day by day, and sometimes for a season only: the play fountains at Place des Aiguilleurs open from 21 May and close from 22 September. S5 keeps the season with the place.
A place counts as open in an hour when it is open at half past. A place with no hours is unknown at every hour, never closed.
Assumptions
| Assumption | Why I accept it for now | What would replace it |
|---|---|---|
| a weekday has one shape, Monday to Friday | only Tuesday to Thursday were counted | counts on Mondays and Fridays |
| seven junctions stand for Griffintown’s streets | they are the only counts at S1 junctions | the bicycle counters, field observation |
| winter, spring and autumn days stand for any season | no summer day was counted | the bicycle counters, which run all year |
| a day the hours never name is closed | the opening_hours convention | a look at the door, or the place’s own website |
| open in an hour means open at half past | simple to explain, and the stress test shows it matters little | finer steps once S9 runs by the minute |
| three detectors on Peel and William stand for Griffintown’s cycling | the only detectors inside the area | a counter on the canal path, field observation |
| a holiday behaves like the kind of day it falls on | the counts carry no calendar | a list of Québec holidays, to set them apart |
Tests
Twelve checks
Each check asks one plain question of what S5 wrote. Ten must pass, and all ten do; the last two only report. The Lab shows the latest results.
| Question | Answer | |
|---|---|---|
| T1 | Does the evidence hold every counted quarter-hour, with the same totals as the city’s file? | yes, 1,440 quarters |
| T2 | Does an hour get a value only when all four quarters were counted? | yes; 48 partial hours stay empty |
| T3 | Were the reference hours counted every day, and does each day average 1 over them? | yes |
| T4 | Can every hour of the weekday shape be rebuilt from the days it names? | yes |
| T5 | Do Saturday and Sunday stay empty, with the reason? | yes |
| T6 | Is every S4 place here once, and is a place without readable hours unknown at every hour? | yes, 610 rows: 558 places and 52 repeats, each pointing to its twin |
| T7 | Does the hours reader give the expected week on fixed examples? | yes, 16 examples |
| T8 | Does every place’s week come from its own hours text, and do the counts per hour add up? | yes |
| T9 | Do the detector days hold every recorded hour, with a total only when all 24 were recorded? | yes; 309 incomplete detector-days left without a total |
| T10 | Can every bicycle shape and monthly level be rebuilt from the detector hours? | yes, 376 days |
| T11 | How much do the sources cover? | report: 17 of 24 weekday hours rest on J040 alone; 83 of 558 places give hours |
| T12 | Do the counts and the detectors agree on a weekday’s bicycles? | report: correlation 0.87 in winter, 0.89 over all seasons |
A test that always passes proves nothing. So I broke the finished files five ways: I gave Saturday at 8h a value, turned one unknown hour of a place without hours into closed, added one person to one counted hour, filled a partial hour, and changed one letter of a place’s week in the Lab’s copy. Each was caught: the first by T4 and T5, the second by T6 and T8, the third by T1 and T4, the fourth by T1 and T2, and the last by the Lab’s check L7. Then I put the files back.
Stress tests
Run twice on the same input, S5 gives the same output (X1). The other stress tests ask how much the shape depends on so few days.
X2 leaves out one counted day at a time. In the reference hours, which nine days share, no value moves by more than 0.12, and for people on foot and cars by no more than 0.06. In the hours J040 holds alone, the three December days disagree more: leaving out one of them moves people on foot by up to 0.12 and bicycles by up to 0.44, since a few cyclists in an hour make a large share. The bicycle values at night and in mid-afternoon are the weakest numbers in S5.
X3 leaves out one junction at a time. The busiest hour stays 17h for every mode, with one exception: without J040, the bicycles’ busiest hour moves to 8h. So the evening cycling peak leans on J040.
X5 leaves out one month of detector days at a time. Weekday shapes hold well, moving by at most 0.05 in summer and 0.04 in autumn. Weekend shapes rest on fewer days and move more, up to 0.46 for a winter Sunday, and spring is the thinnest season, with 22 weekdays, 8 Saturdays and 9 Sundays.
X4 changes what “open in this hour” means. Of the other readings I tried, the strictest, open for the whole hour, removes 75 of the week’s 5,626 open place-hours, and the others move fewer. The choice of half past hardly matters.