Skip to content

Congestion tti#1383

Open
ShahrzadBorjian2 wants to merge 33 commits intomasterfrom
congestion_tti
Open

Congestion tti#1383
ShahrzadBorjian2 wants to merge 33 commits intomasterfrom
congestion_tti

Conversation

@ShahrzadBorjian2
Copy link
Copy Markdown
Contributor

What this pull request accomplishes:

Implementing new segment level and aggregated tti using updated tti methodology

Issue(s) this solves:

What, in particular, needs to reviewed:

  • citywide_daily_segment_tti_dynamic.sql: calculates TTI at the segment level for the entire citywide congestion network
  • segment_here_vkt_2024.sql: generates segment-level VKT proxy using HERE sample size
  • citywide_daily_weighted_sqrt_aadt_length_tti_dynamic.sql: aggregates segment-level TTI to citywide TTI
  • downtown_daily_weighted_sqrt_aadt_length_tti_dynamic.sql: aggregates segment-level TTI to downtown TTI

What needs to be done by a sysadmin after this PR is merged

_create new functions to produce tti values

@ShahrzadBorjian2 ShahrzadBorjian2 self-assigned this Apr 7, 2026
@gabrielwol gabrielwol removed their request for review April 29, 2026 21:06
Copy link
Copy Markdown
Contributor Author

@ShahrzadBorjian2 ShahrzadBorjian2 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @gabrielwol. Looks great. I have added my comments.

@@ -0,0 +1,52 @@
CREATE OR REPLACE FUNCTION here_agg.agg_overnight_tt(
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you add some high level comments?

FROM here_agg.raw_segments
WHERE
dt >= agg_overnight_tt.mnth - interval '6 months'
AND dt < agg_overnight_tt.mnth
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought we decided to use force mnth to month rolling instead of day to day

SELECT
segment_id,
agg_overnight_tt.mnth AS mnth,
AVG(tt) AS overnight_avg_tt,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used weighted average travel time (by obs) not sure if we want to use that approach.

) OR (
dt >= '2024-01-01'::date
AND hr BETWEEN 1 AND 4
)
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to re-run analysis each year to select minim 4 hr time window

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's not an easy thing to operationalize into an automated pipeline, I would suggest omitting it going forward.


INSERT INTO here_agg.segment_overnight_tts (
segment_id, mnth, overnight_avg_tt, rolling_6month_quasi_obs
)
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add minimum observation threshold?

cc.area_name
FROM congestion.congestion_segments AS seg
JOIN gis.community_council_2018 AS cc
ON cc.the_geom && seg.geom --quick bounding box intersection using gist idx
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the function may assign a segment to a community council just because their boxes overlap, even if the real geometries do not?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, I was missing an st_intersects in the where clause. Usually using a && join along with an st_intersects is faster than simply joining on st_intersects.

ON st_intersects(st_transform(dt.geom, 4326), seg.geom)
WHERE seg.ver_id = here_agg.select_map_version(
start_date := segment_areas.mnth,
end_date := segment_areas.mnth + 1,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You meant one day interval not one month, right?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 day is OK, because map version should be the same for entire month.
adding that as a comment.

'Downtown' AS area_name
FROM congestion.congestion_segments AS seg
JOIN gis.to_core_downtown AS dt
ON st_intersects(st_transform(dt.geom, 4326), seg.geom)
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we want any intersect with "downtown" to be considered as "downtown" ?

Copy link
Copy Markdown
Collaborator

@gabrielwol gabrielwol May 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Options:
st_intersects(st_transform(dt.geom, 4326), seg.geom) (950 segments)
Image

Copy link
Copy Markdown
Collaborator

@gabrielwol gabrielwol May 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

st_within(seg.geom, st_transform(dt.geom, 4326)) (861 segments)

Image

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is the winner!

ON st_intersects(st_transform(dt.geom, 4326), seg.geom) AND ST_Length(ST_Intersection(seg.geom, st_transform(dt.geom, 4326))) / ST_Length(seg.geom) > 0.50 (903 segments)

Image

@@ -0,0 +1,22 @@
-- Table: here_agg.monthly_link_vkt
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above, the naming might be confusing as thereis no vkt yet

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renaming to monthly_link_sample_size 👍

Comment thread congestion/readme.md
| hr | smallint | 0 | |
| tti | double precision | 1.0812660631815794 | |
| num_segments | integer | 4777 | |
| road_category | text | Non-Highway | |
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few minor comments:

  • Clarify that the 6-month rolling is based on monthly aggregates, not daily data
  • Note that monthly_link_vkt stores sample_size (not true VKT), VKT is calculated later as sample_size * length
  • Add a simple pipeline/data flow diagram to connect tables
  • Clarify that overnight TT = free-flow baseline (used for TTI denominator)
  • Simplify explanation of num_obs is “approx number of vehicles from probe data”
  • Check segment_id type consistency (integer vs bigint)
  • In area_tti, clarify that TTI is VKT-weighted hourly TTI
  • mention that 6-month rolling aligns with overnight baseline methodology

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants