CityScope / CS_Urban_Indicators

Scripts for getting urban data and building urban indicators. A module for computing urban indicators in response to real-time CityScope inputs.
GNU General Public License v3.0
7 stars 4 forks source link

Handle heatmap posting and different viz types #8

Closed crisjf closed 4 years ago

crisjf commented 4 years ago

The Handler class should be able to handle heatmap indicators as well. This will be done by defining a "type" parameter in the indicator class (defaulted to numeric), and the Handler class should know what to do when "type"="access"/"heatmap"

When "type" is numeric, indicators should also specify the type of visualization (e.g. "category"). That will allow the front-end to select indicators to show as radar chars, energy bars, or any other viz type. Handler class should add a default when this is not provided.

crisjf commented 4 years ago

@doorleyr Are there 'layers' in the heatmap data? All I see in: https://cityio.media.mit.edu/api/table/corktown/access is one big geojson. Shouldn't we allow for multiple layers of data geographic data?

crisjf commented 4 years ago

@doorleyr Please have a look at the last two commits and let me know if we can close this issue.

doorleyr commented 4 years ago

Looks great. The different types/layers of accessibility are stored as different properties of each feature. There's one remaining issue about this that's captured elsewhere so I think this one can be closed now.

crisjf commented 4 years ago

Handler class needs to be updated to the new structure as highlighted in #9 { "type": "FeatureCollection", "properties": {"attributes": ["restaurants', "shopping", ...], "features": [ .... ] }

@doorleyr @RELNO:

What if someone tries to post an indicator that uses a different set of points?

Say 'restaurants' and 'shopping' have different 'features', how should we structure this?

doorleyr commented 4 years ago

I think we can assume that the same table shouldn't have multiple heatmaps with different sampling points. This would look weird on the front-end.

Maybe it would make more sense if the sampling grid is not part of the proximity indicator but a separate object which is added to the handler. Then any indicator with the type 'heatmap' would need to ensure that it returns data in the right shape for this grid. i.e. if there are 200 points in the sampling grid and the indicator is calculating 4 different metrics, it should return a 200-length list of 4-length lists as well as a 4-length list of names. What do you think?

crisjf commented 4 years ago

I kinda like the flexibility we currently have.

Maybe filling everything with NULL when the feature belongs to a different set of features, and filtering out the NULLs in the front-end?

We can try to suggest that the model builder uses the same set of points, but then we'd have to provide this set of points somewhere in the API. Are the points currently defined somewhere?

doorleyr commented 4 years ago

Here are the options as I see them. Let me know if this makes sense to you. 1) each heatmap indicator has its own sampling geometry and its own end-point on cityIO. All the proximity layers are contained in a single geojson and posted to ../access. If someone else wants to make a new heatmap layer (eg. elevation), they can use whatever sampling geometry they choose and post to a different location (../elevation).

2) Heatmap indicators can have different sampling geometries but they are all concatenated into one geojson. The issue here is that the same geojson would have different attributes in different features. We could use NULLs as you mention above. Or we could make the properties of each feature an object like {"a": 0.5, "c": 0.2} which only contains the attributes relevant to that feature. Then we would need a mapping in the properties of the overall geojson like {"a": "access to eductation", "b": "elevation", etc.}.

3) Heatmap indicators use the same sampling geometry and are contained in the same geojson (my last suggestion). We could create a new class for the sampling geometry and this would need to be attached to the handler before any heatmap indicators could be attached. The heatmap indicators would get this geometry from the handler on setup. I agree we lose a little flexibility here but I think, in practice, this would suit our use-cases.

One more thing to keep in mind that I previously discussed with @RELNO: I think we should ultimately not be sending the whole geojson with every update of the indicators. Instead we should send the geojson once when the handler is instantiated and after that only update the properties. This is exactly the same as the relationship between the GEOGRID and GEOGRIDDATA fields. This is easy to update on the backend but I think will take a bit more work on the front-end.

crisjf commented 4 years ago

I like 1, but it does add an extra layer of work for the model builder. How are endpoints created in cityIO?

I also like 2, but I get your point about how this can get slow. Maybe we can implement 2 and highly suggest that the model builder uses the same sampling geometries by raising a warning? That way, even if we allow 2, we are effectively implementing 3.

What do you think?

doorleyr commented 4 years ago

A new endpoint can be created simply by posting to that URL so its not much work for the modeller. The handler would just need to enforce that when you create a heatmap-type indicator, you specify the name of the endpoint where the result should be posted. Using the suggestion or warning seems like it would be a bit complicated in practice.

The decision depends a bit on what heatmap indicators we forsee being built. Right now, proximity is the only one. If we don't forsee multiple types of heatmap per project, then (1) makes the most sense. If we think there will be different types of heatmaps which need to cover the same portion of the map, then (3). If we think there will be multiple types of heatmaps covering different portions of the map, then (2).

@RELNO what do you think?

crisjf commented 4 years ago

Awesome! Let's go with 1 then! I'll start working on the Handler.

RELNO commented 4 years ago

@doorleyr maybe we can still do a 10min call to coordinate it, I'm not 100% I'm getting the gist of it

crisjf commented 4 years ago

access properties: ['car','truck','bike','altitude'] features 0: {'geometry':[],'properties':[1,2,1,NULL]} 1: {'geometry':[],'properties':[2,1,1,NULL]} 2: {'geometry':[],'properties':[2,1,1,NULL]} 3: {'geometry':[],'properties':[2,1,1,NULL]} 4: {'geometry':[],'properties':[NULL,NULL,NULL,1]} 5: {'geometry':[],'properties':[NULL,NULL,NULL,2]}

RELNO commented 4 years ago

Just to reiterate: props should be floats, and 0 instead of null is preferred.

crisjf commented 4 years ago

@doorleyr try the Handler class now and let me know if it has the desired behavior.

@RELNO check the README pushed in 62b3c1e5e81709b0cdd9ce22cbed40a93f2d2ce4 . It should have the documentation on the format we will be using for the /access endpoint.

crisjf commented 4 years ago

This seems to be solved after bc8395bc902ac9cfbc5de6801a7ea0d93e83f00c