Category: Tools

Why Jefferson Park residents should allow more housing

Short answer: To provide more shoppers for the local businesses. Read on for the longer answer. 

Over on Chicago Cityscape I added a new feature called “market analysis” which measures the number of people who live within specific walking areas (measured by time) and driving areas (measured by distance). 

I am in favor of removing apartment & condo bans in Chicago, especially in areas where they were previously allowed and near train stations.

Jefferson Park is centered around two co-located train stations, serviced by CTA and Metra respectively. There have been multiple proposals for multi-family housing near the stations (collectively called the Jefferson Park Transit Center) and some have been approved. 

Always, however, there are residents who resist these proposals and the number of originally proposed apartments or condos gets reduced in the final version (classic NIMBYism). 

There’re four reasons – at least – why more housing should be allowed near the Jefferson Park Transit Center:

  • Locally owned businesses require a significant amount of shoppers who live nearby and walk up traffic
  • More people should have the opportunity to live near low-cost transportation
  • It will include more affordable housing, through Chicago’s inclusionary zoning rules (the Affordable Requirements Ordinance, ARO)
  • There will be less driving, and therefore lower household transportation costs and less neighborhood pollution

To support the first reason, I used the “market analysis” tool to see just how many people live in a walkable area centered around Veterans Square, a mixed-use office and retail development adjacent to the train stations. 

Only 9,368 people live within a 10 minute walk to Veterans Square (get the Address Snapshot). 

Comparatively, 19,707 people live within a 10 minute walk to The Crotch, or the center of Wicker Park, at the intersection of Milwaukee/North/Damen (get the Address Snapshot). The Blue Line station is about 75 feet south of the center point.

I would grant the low Veterans Square number a small discount based on the proximity to the Kennedy Expressway, which severely truncates walking areas up and down the northwest side. Still, even with that discount, ending up with less than half the amount as the one in Wicker Park, is disturbing. Wicker Park is hardly characterized by high-density housing. In fact, all of the new high-rises are just outside the 10 minute walk shed!

The genius of using ST_Subdivide to speed up PostGIS intersection comparisons

You should use ST_Subdivide to break up large shapes into smaller ones

This infographic visually compares the difference between running a PostGIS comparison query like ST_Intersects on a large shape versus a subdivided version of that large shape. Click to embiggen.

Hundreds of GIS intersection comparisons are completed every hour on Chicago Cityscape.*

People are looking at, say, a map of the South Shore community area. That “Place” page then grabs all of the building permits, building violations, business licenses, and other “feature layers” that are stored as points.

A classic “point in polygon” comparison is made using the ST_Intersects(place_geometry, permits_geometry) function.

This has worked very well for several years.

The problem

But as Chicago Cityscape handles larger shapes – they come from users drawing their own, large shapes, and from large shapes like the downtown Chicago area – this query doesn’t cut it.

Setting indexes on the geometry is imperative, but it’s not the end of the to optimize performance. That’s because the index of the geometry is a rectangular bounding box (which is also called an “envelope” in GIS) that contains the entire shape of the South Shore community area.

The downtown Chicago area, however, is not even the largest shape I have. That belongs to the new Place, “Neighborhood Opportunity Fund investment zones” (NOF). Combined, they cover 75 square miles of Chicago. Downtown is only 7.7 square miles.

After I added the NOF map and tested its Place page, it “crashed” my server, metaphorically speaking. The query to just count the number of building permits in the area would take about five minutes.

There had to be a better way; in the meantime, however, I divided the NOF map into the West and South sections. This hardly improved the counting time.

The solution

Thankfully, today, I saw a tweet from Paul Ramsey linking to his blog that linked to his slides from a recent presentation about the use of PostgreSQL to store and manipulate GIS data.

In it he explained how the ST_Subdividefunction worked. I’m going to demonstrate it using graphics from my own maps.

A normal intersection comparison, using ST_Intersects(place_geometry, permits_geometry) in a query creates a bounding box (envelope) around each geometry and quickly determines whether the two envelopes overlap. If they do, then it checks again to see if the actual geometries overlap. If they do, that data is returned as a response to your query.

When your two datasets are massive, like the NOF zones, which collectively cover 1/3rd of Chicago, and the building permits, which are found across the entire city…well, that led to the five minutes counting time.

Enter ST_Subdivide. To use it properly you would run it against your existing geometry and store the much smaller shapes, derived from the big shape, in a new table. I applied the function to all the 22,203 maps that Chicago Cityscape has and stored their unique IDs and subdivided geometries in a new “lookup” table.

Now, any time I want to compare the building permits against the NOF, the building permits are instead compared to the small shapes that were subdivided.

The query

Chicago Cityscape uses a single table (created as a materialized view) to combine all 22,203 maps. Each map is stored in a source table (for example, there’s a table to hold the 77 community areas) and the materialized view runs once a day to combine all of the maps in the source tables. This ensures our data is managed well: different source tables can hold different information, and the single table holds only the name, type, and geometry of the source tables, for faster comparison. Each entry in the single table also has a “slug”, its unique identifier.

Thus, the materialized view of the subdivided maps is created from the aforementioned single table, using this query:

create materialized view view_places_subdivided as
select gid || '_' || random() as gid, slug, st_subdivide(geom) as geom
from view_places;

The “gid” is designed to create a new unique ID field, as the slug field will be repeated for every subdivided of each map. A unique ID field is necessary if you want to refresh the materialized view concurrently (to allow for other queries to access the materialized view while it’s being refreshed).

* The results are cached for a few hours, because the feature layers change 1-2 times per day and at different times each day, so the limited duration cache accommodates that. Ideally I would code a way to invalidate the cache when the feature layer data is updated.

Update 12/31/19: ST_Subdivide will fail if your geometries have any or certain geometry errors (I don’t know if it’s any kind of error, or certain kinds of errors that make the function fail). Chicago Cityscape has over 37,000 features that ST_Subdivide is attempting to process, and there is a lot of room for error in managing that many features from dozens of sources.

Inclusionary zoning calculator will tell you how many units a developer can afford to make “affordable”

An “inclusionary zoning” calculator can help you determine how much affordable housing your town should require that developers build in their new construction residential buildings.

I learned about Grounded Solutions Network’s Inclusionary Housing Calculator at the second-ever YIMBYtown conference in Oakland, California, two weeks ago.

YIMBY (yes in my back yard) is a movement to reduce barriers to building more housing in order to be able to house everyone at a level they can afford. It’s a movement for other things, and it means a lot of different things to a lot of different people but the end result is that more housing needs to be built.

An interested person inputs a lot of values relevant to their local housing market into the IHC and it will calculate the cost of construction per unit and the rental income from those units, and then will figure the profit margin for the developer. What makes this “inclusionary” is that one also needs to enter the desired portion of units that are set aside as “affordable” (to people making a certain income) and subsidized by the developer’s rental income.

I put the IHC through a real world exercise by inputting as much data as I knew about a rejected proposal in Pilsen.

The first proposal from Property Markets Group had 500 units, and 16 percent of them were set aside (news on this and their subsequent proposals) [I cannot find the source of the “16 percent on-site” factor]. Chicago’s Affordable Requirements Ordinance, or ARO, requires that 10 percent of the units are affordable, and that 25 percent of those 10 percent must be built on site. The other 75 percent can be built on site, or the developer can pay an in-lieu fee per unit.

Needless to say, 16 percent on-site is much, much higher than 25 percent of 10 percent. A neighborhood organization, the Pilsen Land Use Committee, however, requires 21 percent in the area, and the city council member, Danny Solis, 25th Ward, adheres to.

PMG said they couldn’t go that high, and that’s what I wanted to test.

According to this Inclusionary Housing Calculator, could the developer make enough profit (considered as 10 percent) if the building had 21 percent of units as affordable?

In this exercise, the answer was “no, PMG could not make a profit if they had to set aside 21 percent of the units as affordable.”

But the calculator showed that they could earn a 12 percent profit if 16 percent of the units were affordable. 

Some of the inputs are actual, like the sale price of the land (found in the Illinois Department of Revenue’s transactions database), but I had to make up some inputs, including the apartments’ bedroom mix, and the future rental prices of those apartments.

Further reading

  • It’s tough for people to move into one of these set-aside apartments in Chicago (DNAinfo Chicago, July 28, 2017)
  • Inclusionary zoning cannot create enough affordable units (City Observatory, February 11, 2016)
  • Other housing cost calculators like this one (City Observatory, July 26, 2016)

At least 2.5 percent of the land area in Chicago is covered in parking lots and garages

Here’s how I know that at least 2.5 percent of the land area in Chicago is covered in parking lots and garages, as of February 5, 2017.

That’s a lot of polluted water runoff.

I grabbed the land area of 227.3 from the Wikipedia page.

I grabbed all the parking lots from OpenStreetMap via Metro Extracts, which is going to be the most complete map of parking lots and garages.

Volunteer mappers, including me, drew these by tracing satellite imagery.

With the parking lots data in GIS, I can count their area in square feet, which comes out to 160,075,942.42. Convert that to square miles and you get 5.74.

5.74/227.3*100 = 2.5 percent

The last snapshot of parking lot data I have is from February 2016, when only 3.39 square miles of parking lots have been drawn.

There are still many more parking lots to be drawn!

Essential apps for traveling in parts of Europe

Train Radar

The Train Radar in Reisplanner Xtra (from NS, the Dutch intercity train operator) is a fun feature to show you trains nearby. The rest of the app is essential for efficient use of NS trains.

I’ve used a bunch of apps that are necessary when you’re traveling within and between countries in the parts of Europe I’m staying in an visiting this year.

The first app you should install is maps.me (iOS, Android, Amazon). It stores maps offline by downloading them from OpenStreetMap. Before leaving for the next city, download it on wifi! Each city takes up 25-60 MB on your phone, and it’s easy to delete a city’s map after you depart. This app is super fast, looks nice, has offline route planning, and can show any area in the world.

Travel apps for the Netherlands

  • Reisplanner Xtra, is essential because it has a journey planner for traveling within the country. It also shows real-time information, and even has a map of all the trains running in the country at that moment. It lists real-time OV-fiets bike availability.
  • NS International, for looking up timetables for trains between the Netherlands and France, Germany, and Belgium. You can’t buy tickets in the app, but it will link you to a shopping cart on the NS International website.
  • 9292.nl, journey planner app for all public transport in the Netherlands. It doesn’t have network maps, though, if you’re only interested in where the Rotterdam Metro goes.

maps.me gets data from OpenStreetMap, the wiki-style map that regular people around the world edit (including myself). The map improves as more people add more information!

maps.me gets data from OpenStreetMap, the wiki-style map that regular people around the world edit (including myself). The map improves as more people add more information!

Travel apps for Germany

  • DB Navigator, this has all public transport in Germany, including intercity trains. It even has intercity trains for so many other countries, regardless if that train has service in Germany. When you look up timetables for trains outside Germany, it will rarely be able to show you the price, but just seeing the schedule, and what trains are available, is important. You can buy tickets within the app, and use the app as a mobile ticket.

Other travel apps

  • Rome2rio, is remarkable because it will show you all ways to get between two cities, and it works worldwide. It incorporates timetables and maps from local transit systems, intercity coach buses, intercity trains, flights, and driving. It’s multimodal, too. It won’t book tickets, but it’s the only service I know of that focuses on showing the multitude of options – simultaneously, with prices! – for future travel planning. And it’s super fast – I think it’s getting results before you even push the “search” button.

Rome2rio showing directions between Stockholm and Malmo

Rome2rio shows results for all modes (and combined modes) between two cities, here listing 11 options on trains, buses, cars, and plans between Stockholm and Mälmo, Sweden.

  • Skyscanner, this flight-finding service has more intra-Europe airlines than services popular in the United States (like Hipmunk, Orbitz, and KAYAK).
  • Captain Train is a continental train ticketing company with a nice app that will sell you tickets for service within and between many countries.
  • Voyages-sncf, is useful if you’ll be taking fast or regular intercity trains in France, but I don’t believe it has mobile ticketing. However, you can buy tickets in the app or on the website and pick up the tickets at a vending machine at many train stations in France. This is where I bought a Thalys (high-speed train) ticket; it’s better than NS International and the Belgian equivalent from SNCB.
  • United, this airline has implemented a superior entertainment system. I call it “Netflix in the sky”. To be clear, Netflix isn’t involved. It works like this: Install the United app on your device, and then connect to the airplane’s wifi network. There’s a server in the plane that has a lot of movies and TV shows, and these stream directly to your device. This is especially useful in United’s older 767 planes that don’t have seatback screens (IFE).

What apps do you recommend and why?