Open Street Map using OSMN: how to get building height? - openstreetmap

I am trying to find a way to extract building heights. Here is what I've tried so far:
place_name = "Uptown, Dallas, Texas"
buildings = ox.geometries_from_place(place_name, tags={'building':True})
print(buildings.columns)
outputs:
Index(['amenity', 'geometry', 'nodes', 'addr:housenumber', 'addr:street',
'building', 'building:levels', 'height', 'name', 'office', 'wikidata',
'wikipedia', 'parking', 'addr:city', 'addr:postcode', 'addr:state',
'layer', 'cuisine', 'access', 'addr:country', 'brand', 'brand:wikidata',
'brand:wikipedia', 'opening_hours', 'operator', 'operator:wikidata',
'operator:wikipedia', 'phone', 'ref:walmart', 'shop', 'website',
'wheelchair', 'beds', 'emergency', 'gnis:feature_id', 'healthcare',
'old_name', 'ele', 'gnis:county_name', 'gnis:import_uuid',
'gnis:reviewed', 'source', 'fee', 'smoking', 'roof:levels',
'roof:shape', 'addr:unit', 'tourism', 'short_name', 'contact:website',
'outdoor_seating', 'ways', 'type'],
dtype='object')
height parameters are NaN for most values. The closet parameter is building:levels but it is just number of stories in buildings.

Related

How to use the #app.callback function with two inputs as dropdowns?

**Hello everyone!
I have been trying to create an interactive dashboard in python using the #app.callback function with two inputs. My dataset layout can be summarized into 4 main columns. [1]: https://i.stack.imgur.com/boMKt.png
I'd like Geography and Time Period to manifest in the form of dropdowns (therefore use the Dcc. dropdown function.
The first dropdown will filter the dataset according to the Geography and the second one will define the "Period time - MAT, L12w or L4w) within the country. Therefore somehow the second dropdown is to be integrated within the first dropdown.
I am familiarized with both the dropdown and #app.callback function. But I can't seem to find a script that fuses both. Important note: the output desired is a pie chart that distinguishes Manufacturers' (Column 2) value share (column 4) according to the selected Geography and time Period. I am guessing the mystery resides in the app.layout structure. However, I tried everything and the code won't work.
Also, you will find the code I have done so far attached. The important bit is from "#DESIGN APP LAYOUT" onwards.
I'd really appreciate a quick response. Thanks in advance for the help!**
from dash import html
from dash import dcc
from dash.dependencies import Input, Output, State
import plotly.express as px
import pandas as pd
import pandas as pd
pd.options.display.max_columns = None
pd.options.display.max_rows = None
pd.options.display.width=None
data = pd.read_csv (r'C:\Users\Sara.Munoz\OneDrive - Unilever\Documents\Sarita.csv',
encoding = "ISO-8859-1",
)
df=data
print(df.head())
cols=df.columns
print(cols)
###RE-ARRANGE DATASET###
df = pd.melt(df, id_vars=['Geography Node Name', 'Geography Id', 'Geography Level',
'Category Node Name', 'Category Id', 'Category Level',
'Global Manufacturer Name', 'Global Manufacturer Id',
'Brand Position Type', 'Brand Position Name', 'Brand Position Id',
'Local Brand Name', 'Local Brand Id', 'Measure',
'Currency or Unit of Measure','Latest Available Date'],value_vars=['MAT','L12W','L4W'], var_name='Period',value_name='Data')
for col in df.columns:
print(col)
###CLEAN DATASET###
df.rename(columns = {'Geography Node Name':'Geography','Category Node Name':'Category',
'Global Manufacturer Name':'Manufacturer','Geography Level':'GLevel'},inplace = True)
df.drop(["Geography Id", "Category Id","Global Manufacturer Id","Brand Position Type",
"Brand Position Name","Brand Position Id","Local Brand Name","Local Brand Id","Latest Available Date",
"Currency or Unit of Measure"], axis = 1, inplace=True)
print("SEE BELOW NEW DATASET")
print(df.head())
#####FOR VALUE SHARE
print("FOR VALUE SHARE")
df2 = df.loc[df['GLevel'] == 5]
df2 = df2.loc[df2['Measure'] == 'Value Share']
df2 = df2.loc[df2['Category'] == 'Toothpaste']
df2 = df2[df2.Manufacturer != 'ALL MANUFACTURERS']
df2 = df2[df2.Category != 'Oral Care']
df2.drop(["GLevel", "Category","Category Level"], axis = 1, inplace=True)
print(df2.head())
#####FOR VOLUME SHARE
print("FOR VOLUME SHARE")
df3 = df.loc[df['GLevel'] == 5]
df3 = df3.loc[df3['Measure'] == 'Volume Share']
df3 = df3.loc[df3['Category'] == 'Toothpaste']
df3 = df3[df3.Manufacturer != 'ALL MANUFACTURERS']
df3 = df3[df3.Category != 'Oral Care']
df3.drop(["GLevel", "Category","Category Level"], axis = 1, inplace=True)
df3=df3.sort_values(['Geography', 'Period'],ascending = [True, True])
df3 = pd.DataFrame(df3)
df3=df3[['Geography','Period','Manufacturer','Measure','Data']]
print(df3)
###############################################################################
app = dash.Dash(__name__)
app.layout = html.Div(
[
dcc.Dropdown(
id="dropdown-1",
options=[
{'label': 'Indonesia', 'value': 'Indonesia'},
{'label': 'France', 'value': 'France'},
{'label': 'Vietnam', 'value': 'Vietnam'},
{'label': 'Chile', 'value': 'Chile'},
{'label': 'United Arab Emirates', 'value': 'United Arab Emirates'},
{'label': 'Morocco', 'value': 'Morocco'},
{'label': 'Russian Federation', 'value': 'Russian Federation'},
{'label': 'China', 'value': 'China'},
{'label': 'Greece', 'value': 'Greece'},
{'label': 'Netherlands', 'value': 'Netherlands'},
{'label': 'Austria', 'value': 'Austria'},
{'label': 'Germany', 'value': 'Germany'},
{'label': 'Switzerland', 'value': 'Switzerland'},
{'label': 'Italy', 'value': 'Italy'},
{'label': 'Denmark', 'value': 'Denmark'},
{'label': 'Norway', 'value': 'Norway'},
{'label': 'Sweden', 'value': 'Sweden'}
],
multi=True,
),
dcc.Dropdown(
id="dropdown-2",
options=[
{'label': 'MAT', 'value': 'MAT'},
{'label': 'L12W', 'value': 'L12W'},
{'label': 'L4W', 'value': 'L4W'}
],
multi=True,
),
html.Div([], id="plot1", children=[])
], style={'display': 'flex'})
#app.callback(
Output("plot1", "children"),
[Input("dropdown-1", "value"), Input("dropdown-2", "value")],
prevent_initial_call=True
)
def get_graph(entered_Geo, entered_Period):
fd = df2[(df3['Geography']==entered_Geo) &
(df3['Period']==entered_Period)]
g1= fd.groupby(['Manufacturer'],as_index=False). \
mean()
g1 = g1
plot1= px.pie(g1, values='Data', names='Manufacturer', title="Value MS")
return[dcc.Graph(figure=plot1)]
if __name__ == '__main__':
app.run_server()
#DESIGN APP LAYOUT##############################################################################
app.layout = html.Div([
html.Label("Geography:",style={'fontSize':30, 'textAlign':'center'}),
dcc.Dropdown(
id='dropdown1',
options=[{'label': s, 'value': s} for s in sorted(df3.Geography.unique())],
value=None,
clearable=False
),
html.Label("Period:", style={'fontSize':30, 'textAlign':'center'}),
dcc.Dropdown(id='dropdown2',
options=[],
value=[],
multi=False),
html.Div([
html.Div([ ], id='plot1'),
html.Div([ ], id='plot2')
], style={'display': 'flex'}),
])
##############
# Populate the Period dropdown with options and values
#app.callback(
Output('dropdown2', 'options'),
Output('dropdown2', 'value'),
Input('dropdown1', 'value'),
)
def set_period_options(chosen_Geo):
dff = df3[df3.Geography==chosen_Geo]
Periods = [{'label': s, 'value': s} for s in df3.Period.unique()]
values_selected = [x['value'] for x in Periods]
return Periods, values_selected
# Create graph component and populate with pie chart
#app.callback([Output(component_id='plot1', component_property='children'),
Output(component_id='plot2', component_property='children')],
Input('dropdown2', 'value'),
Input('dropdown1', 'value'),
prevent_initial_call=True
)
def update_graph(selected_Period, selected_Geo):
if len(selected_Period) == 0:
return no_update
else:
#Volume Share
dff3 = df3[(df3.Geography==selected_Geo) & (df3.Period==selected_Period)]
#Value Share
dff2 = df2[(df2.Geography==selected_Geo) & (df2.Period==selected_Period)]
#####
fig1 = px.pie(dff2, values='Data', names='Manufacturer', title=" Value MS")
fig2 = px.pie(dff3, values='Data', names='Manufacturer', title=" Volume MS")
table =
return [dcc.Graph(figure=fig1),
dcc.Graph(figure=fig2) ]
if __name__ == '__main__':
app.run_server()```

Mapbox - draw lines for each property

I use mapbox-gl to draw a map. In one of the routes (it's a single line) I have 2 attached properties:
{
id: 17,
pcs_mode: 'AtRisk'
},
id: 18,
pcs_mode: 'Excellent'
}
I want to draw 2 lines (each line for a property) and fill using a proper color, depending on pcs_mode.
I've tried to draw these like this:
const layerId = `segment-condition`;
map.current.addLayer({
id: layerId,
type: 'line',
source: SOURCE_NAME,
'source-layer': SOURCE_LAYER_NAME,
layout: {
'line-join': 'round',
'line-cap': 'butt'
},
paint: {
'line-color': [
'case',
['==', ConditionStates.Excellent, ['get', 'pcs_mode']],
CONDITION_COLORS[ConditionStates.Excellent],
['==', ConditionStates.AtRisk, ['get', 'pcs_mode']],
CONDITION_COLORS[ConditionStates.AtRisk],
['==', ConditionStates.Distressed, ['get', 'pcs_mode']],
CONDITION_COLORS[ConditionStates.Distressed],
['==', ConditionStates.NoMsl, ['get', 'pcs_mode']],
CONDITION_COLORS[ConditionStates.NoMsl],
'#000'
],
'line-width': 5,
'line-offset': 5
}
});
But it draws only one line (for the first property I suppose). How to draw lines for each property? Thanks!
In your code you have added only one line layer and the conditions are given for line-color. If you want to visualize two lines , then apply separate line-offset values for each condition state (using expression).

How to set filter only on country boundaries with US worldview?

I'm using Mapbox GL to color dynamically countries. Some of the countries are red, some are green.
For this, I'm using the country-boundaries-v1 source, then I use the iso_3166-1 data from country-boundaries to set a filter on the layers that use the country-boundaries source.
This is the code where I add my layers:
addLayers (map, layers) {
layers.forEach((layer) => {
map.addLayer({
id: layer.id,
source: layer.source,
'source-layer': layer.sourceLayer,
layout: {
visibility: 'none'
},
type: 'fill',
paint: {
'fill-opacity': 0.5
}
}, 'country-label')
})
},
And there is where I make visible my layer, add the color and set my filter on a list of iso_3166-1 codes:
map.setLayoutProperty(state.id, 'visibility', 'visible')
map.setPaintProperty(state.id, 'fill-color', this.layerColor(formattedState))
map.setFilter('positive-countries', ['in', 'iso_3166_1', 'FR', 'BE', 'IN', 'CN', 'JP'])
The problem is that when I add the 'fill-color' property on my layers that have reduced opacity, countries with different worldview (like China, Japan, India) therefore have layers that overlap. The result is that some countries, instead of having a layer with an opacity of 0.6, have 3 with an opacity of 0.6, which makes them opaque.
I tried to add this :
map.setFilter('positive-countries', ['match', ['get', 'worldview'], ['all', 'US'], true, false])
Hope Mapbox only uses the US worldview, but it doesn't work.
Here is a screenshot of my map so you can see the problem:
As you can see, countries like China, India and Japan have multiple layers because there's multiple worldview for these countries, so they look different than others.
Does anyone know if what I want to do is possible?
EDIT:
I tried this:
const filters = [
'any',
['in', 'iso_3166_1', 'MA', 'BR'],
['==', 'all', ['get', 'worldview']],
['in', 'US', ['get', 'worldview']]
]
map.setFilter('positive-countries', filters)
But I got these errors:
mapbox-gl.js:31 Error: layers.positive-countries.filter[2][2]: string, number, or boolean expected, array found
mapbox-gl.js:31 Error: layers.positive-countries.filter[3][2]: string, number, or boolean expected, array found
If I remove ['in', 'iso_3166_1', 'MA', 'BR'], there are no more errors but of course I have no applied filter on my map.
So, I tried this:
const filters = [
'any',
['==', 'all', ['get', 'worldview']],
['in', 'US', ['get', 'worldview']]
]
map.setFilter(params['id'], filters)
map.setFilter(params['id'], ['in', 'iso_3166_1', 'MA', 'BR'])
but the result is the same as without filter on the worldview...
If someone else is facing the same problem, this is the solution:
const filters = [
'all',
['match', ['get', 'worldview'], ['all', 'US'], true, false],
['match', ['get', 'iso_3166_1'], ['MA', 'BR'], true, false]
]
this.map.setFilter(layerId, filters)
Only the countries as seen by the USA are then visible

Google Timeline Chart with more than one column role

I am trying to draw a timeline chart and add two column roles, one for an HTML link (tooltip column role) and another for styling (style).
I can use either one of them successfully but not both at the same time.
For example, here's a sample of my code:
var container = document.getElementById('mychart');
var chart = new google.visualization.Timeline(container);
var dataTable = new google.visualization.DataTable();
dataTable.addColumn({ type: 'string', id: 'Position' });
dataTable.addColumn({ type: 'string', id: 'Name' });
dataTable.addColumn({ type: 'string', role: 'style' });
dataTable.addColumn({ type: 'date', id: 'Start' });
dataTable.addColumn({ type: 'date', id: 'End' });
dataTable.addColumn({ type: 'string', role: 'tooltip', id: 'link', 'p': {'html': true} });
I believe it has to do with the placement of the columns. In the example above, styling is done correctly but the hyperlink is being formed with the tooltip content instead of the actual column role data I'm passing.
If I remove the style column role the hyperlink works fine, even when placed last in the columns. It's leading me to think that I can't have more than one column role but that's not what the documentation says.
Any clues would be appreciated.
In order to have a column have a clickable hyperlink you an extra piece of code:
google.visualization.events.addListener(chart, 'select', function () {
var selection = chart.getSelection();
if (selection.length > 0) {
window.open(dataTable.getValue(selection[0].row, 3), '_blank');
}
});
My single row of data for debugging purposes was:
dataTable.addRows([
['My text here', 'bar label', '#676767', 'https://www.google.com', new Date(2019, 12, 22), new Date(2019, 12, 26)]]);
I had shuffled the columns around and was pointing to the wrong column. Just had to change to the right column above to get it to work (column 3, being zero-based).

Is it possible to add more than 1 card in response?

I am using cards to show output to the user. I can only be able to show maximum of two chat bubbles and one card. But i want to add more than one card to the intent response in the webhook. I am using nodejs webhook using actions-on-google npm module, is there a way i can add more than one card in the response in single turn?
My use case is, i want to show multiple images in the response.
No, it is not. Basic Card can be only rich response element on response. If you want to show more than one element you may consider to use Table Card element.
Here is the all fields you can use with Table Card. You can remove some of fields.
conv.ask(new Table({
title: 'Table Title',
subtitle: 'Table Subtitle',
image: new Image({
url: 'https://developers.google.com/actions/images/badges/XPM_BADGING_GoogleAssistant_VER.png',
alt: 'Alt Text'
}),
columns: [
{
header: 'header 1',
align: 'CENTER',
},
{
header: 'header 2',
align: 'LEADING',
},
{
header: 'header 3',
align: 'TRAILING',
},
],
rows: [
{
cells: ['row 1 item 1', 'row 1 item 2', 'row 1 item 3'],
dividerAfter: false,
},
{
cells: ['row 2 item 1', 'row 2 item 2', 'row 2 item 3'],
dividerAfter: true,
},
{
cells: ['row 2 item 1', 'row 2 item 2', 'row 2 item 3'],
},
],
buttons: new Button({
title: 'Button Text',
url: 'https://assistant.google.com'
}),
}))
Also, you can use Carousel or Browsing Carousel for multiple cards with touch selection option. But, don't forget, you need use these element with option response or web urls.
For more information:
Google Assistant Responses