<jupyter_start><jupyter_text>Introdução<jupyter_code>import os
import re
import time
import json
import folium
import random
import requests
import numpy as np
import pandas as pd
import seaborn as sns
import geopandas as gpd
from folium import plugins
from osgeo import gdal, osr
from bs4 import BeautifulSoup
from tqdm.notebook import trange, tqdm<jupyter_output><empty_output><jupyter_text>Merge Dados Tabulares e Espaciais<jupyter_code># Lê o arquivo csv com o nome dos municípios
df = pd.read_csv(
    'https://raw.githubusercontent.com/michelmetran/sp_bombeiro/main/data/tabs/tab_municipios_bombeiros.csv',
)

# Lê o arquivo csv com o nome dos municípios
gdf = gpd.read_file(
    'https://raw.githubusercontent.com/michelmetran/sp/main/data/shps/sp_250k_wgs84.geojson',
)
gdf.drop(['municipio_nome'], axis=1, inplace=True)
gdf['id_municipio'] = gdf['id_municipio'].astype(int)
gdf['geometry'] = gdf.simplify(0.0015)

# Merge
gdf = gdf.merge(
    df,
    on='id_municipio',
    how='left'
)

# Results
gdf.head()<jupyter_output><empty_output><jupyter_text>Create Popups<jupyter_code># Add Field
def popup_html(row):
    tel_1 = str(row['telefone_1']).replace('-', '').replace(')', '').replace('(', '+55').replace(' ', '')
    tel_2 = str(row['telefone_2']).replace('-', '').replace(')', '').replace('(', '+55').replace(' ', '')
    
    html = """
    <div>
    <p><b>{}</b> pertence ao:
    <h4><b>{}</b></h4></p>
    <p><b>Sede:</b><br>
    {}{}{}<br>
    {}<br>
    {}<br>
    {}</p>
    <p><b>Contatos:</b><br>
    {}<br>
    {}{}</p>
    </div>
    """.format(
        '' if row['municipio_nome'] is np.NaN else '{}'.format(row['municipio_nome']),
        '' if row['gb_nome'] is np.NaN else '{}'.format(row['gb_nome']),        
        '' if row['endereco'] is np.NaN else '{}'.format(row['endereco']),
        '' if row['numero'] is np.NaN else ', {}'.format(row['numero']),
        '' if row['complemento'] is np.NaN or np.isnan(row['complemento']) else ' - {}'.format(row['complemento']),
        '' if row['bairro'] is np.NaN else 'Bairro: {}'.format(row['bairro']),
        '' if row['municipio'] is np.NaN else 'Município: {}'.format(row['municipio']),
        '' if row['cep'] is np.NaN else 'CEP: {}'.format(row['cep']),
        '' if row['email'] is np.NaN else 'E-mail: <a href="mailto:{}">{}</a>'.format(row['email'], row['email']),
        '' if row['telefone_1'] is np.NaN else 'Telefone: <a href="tel:{}">{}</a>'.format(tel_1, row['telefone_1']),
        '' if row['telefone_2'] is np.NaN else ' / <a href="tel:{}">{}</a>'.format(tel_2, row['telefone_2']),        
    )
    
    html = html.replace('\n','')    
    html = re.sub('\s\s+' , ' ', html) # Remove Espaços no meio
    html = html.strip()
    return html
# Ajusta Tabela
gdf['popup'] = gdf.apply(popup_html, axis=1)
gdf.drop([
    'id_municipio', 'endereco', 'numero',
    'complemento', 'bairro', 'municipio', 
    'cep', 'email', 'telefone_1', 'telefone_2',
    'id_gbmar', 'id_gb', 'zona',
    'comando_sigla', 'comando_nome', 
], axis=1, inplace=True)
print(gdf.columns)

# Save geojson
gdf.to_file(
    os.path.join('data', 'shps', 'sp_bombeiro.geojson'),
    driver='GeoJSON',
    encoding='utf-8'
)

# Results
gdf.head()
def get_centroid(gdf):
    gdf['apenasparacentroid'] = 35
    gdf_dissolve = gdf.dissolve(by='apenasparacentroid')
    gdf_centroid = gdf_dissolve.representative_point()
    gdf = gdf.drop('apenasparacentroid', axis=1)
    return [float(gdf_centroid.y), float(gdf_centroid.x)]
list_centroid = get_centroid(gdf)
list_centroid<jupyter_output><empty_output><jupyter_text>Folium<jupyter_code>bbox = {
    'max_lat': 0,
    'max_lon': 0,
    'min_lat': 0,
    'min_lon': 0,
}
def map_bomb(input_geojson, bbox):
    gdf = gpd.read_file(input_geojson)
    
    # Column with category
    col_categories = 'gb_nome'
    
    # Set palette
    palette_polygon = 'Paired'

    # Get list of unique values
    categories = set(gdf[col_categories])
    categories = list(categories)
    categories.sort()

    # See the palette chosed
    pal = sns.color_palette(palette_polygon, n_colors=len(categories))

    # Set dictionary
    color_polygon = dict(zip(categories, pal.as_hex()))

    # Create Map
    m = folium.Map(
        [-22.545968889465207, -49.56185387118866],
        zoom_start=6,
        min_zoom=6,
        max_zoom=11,
        max_bounds=True,
        min_lon = bbox['min_lon']*(101/100),
        max_lon = bbox['max_lon']*(99/100),        
        min_lat = bbox['min_lat']*(101/100),
        max_lat = bbox['max_lat']*(99/100),
        #zoom_delta=0.1,
    )
    folium.GeoJson(
        gdf,
        name='Bombeiros',
        smooth_factor=1.0,
        zoom_on_click=False,
        embed=False,
        style_function=lambda x: {
            'fillColor': color_polygon[x['properties'][col_categories]],
            'color': color_polygon[x['properties'][col_categories]],
            'weight': 1,
            'fillOpacity': 0.3,
        },
        highlight_function=lambda x: {
            'weight': 3,
            'fillOpacity': 0.6,
        },
        tooltip=folium.features.GeoJsonTooltip(
            fields=['municipio_nome', 'gb_sigla'],
            aliases=['Munícipio', 'Grupamento'],
            sticky=True,
            opacity=0.9,
            direction='right',
        ),
        popup=folium.GeoJsonPopup(
            ['popup'],
            parse_html=False,
            max_width='300',
            show=False,
            labels=False,
            sticky=True,            
        )        
    ).add_to(m)

    # Plugins
    m.fit_bounds(m.get_bounds())
    plugins.Fullscreen(
        position='topleft',
        title='Clique para Maximizar',
        title_cancel='Mininizar',
    ).add_to(m)
    return m
m = map_bomb(os.path.join('data', 'shps', 'sp_bombeiro.geojson'), bbox)
bounds = {
    'max_lat': m.get_bounds()[1][0],
    'min_lat': m.get_bounds()[0][0],
    'max_lon': m.get_bounds()[1][1],
    'min_lon': m.get_bounds()[0][1],
}
print(bounds)
m = map_bomb(os.path.join('data', 'shps', 'sp_bombeiro.geojson'), bounds)
m
os.makedirs('maps', exist_ok=True)
m.save(os.path.join('maps', 'bombeiro_map.html'))
m.save(os.path.join('..', '..', '..', 'case_django', 'divadmin', 'templates', 'bombeiro_map.html'))<jupyter_output><empty_output><jupyter_text>Outras Tentativas TopoJson<jupyter_code># I/O Files
input_geojson=os.path.join('..', 'sp', 'data', 'shps', 'sp_250k_wgs84.geojson')
input_dataframe=os.path.join('data', 'tabs', 'tab_municipios_bombeiros.csv')
def convert_geojson2topojson(input_geojson, output_topojson, precision):
    import fiona
    import topojson as tp
    
    # Open and Convert
    with fiona.open(input_geojson) as fio_col:
        topo = tp.Topology(fio_col)

    # Simplify
    topo = topo.toposimplify(precision)

    # Output file
    topo.to_json(output_topojson)
# Convert to TopoJson
convert_geojson2topojson(
    os.path.join('data', 'shps', 'sp_bombeiros.geojson'),
    os.path.join('data', 'shps', 'sp_bombeiros.json'),
    0.001
)
# Column with category
col_categories = 'gb_nome'

# Set palette
palette_polygon = 'Paired'

# Get list of unique values
categories = set(gdf[col_categories])
categories = list(categories)
categories.sort()

# See the palette chosed
pal = sns.color_palette(palette_polygon, n_colors=len(categories))

# Set dictionary
color_polygon = dict(zip(categories, pal.as_hex()))
# Cria o mapa
m = folium.Map(
    location=[-23.9619271,-46.3427499],
    zoom_start=12,
)

# Adiciona as diferentes empresas com gráficos no popup
lyr = folium.TopoJson(
    open(os.path.join('data', 'shps', 'sp_bombeiros.json')),
    object_path='objects.data',
    name='São Paulo',
    style_function=lambda x: {
        'fillColor': color_polygon[x['properties'][col_categories]],
        'color': color_polygon[x['properties'][col_categories]],
        'weight': 1,
        'fillOpacity': 0.3,
    },
    tooltip=folium.features.GeoJsonTooltip(
        fields=['municipio_nome', 'gb_sigla'],
        aliases=['Munícipio', 'Grupamento'],
        sticky=True,
        opacity=0.9,
        direction='right',
    ),
    #popup='test', # Doesnt Work
)

lyr.add_child(
    folium.Popup(
        #'test',
        gdf['popup'][0],
        #lambda x: x['properties']['popup'],
        #sticky=False,
        #localize=True,
        #parse_html=False,
        max_width=400
    )
)    

# Add Layer to Map
lyr.add_to(m)

# Apresenta o mapa
m.fit_bounds(m.get_bounds())
plugins.Fullscreen(
    position='topleft',
    title='Clique para Maximizar',
    title_cancel='Mininizar',
).add_to(m)
m<jupyter_output><empty_output><jupyter_text>Issue<jupyter_code>import folium
import geopandas as gpd
from folium import plugins

# Read
gdf = gpd.read_file('https://raw.githubusercontent.com/michelmetran/sp_bombeiro/main/data/shps/sp_bombeiros.geojson')

# Dict
color_polygon = {
    '1º Grupamento de Bombeiros': '#ffff99',
    '5º Grupamento de Bombeiros': '#a6cee3',
    '6º Grupamento de Bombeiros': '#1f78b4',
    '7º Grupamento de Bombeiros': '#b2df8a',
    '8º Grupamento de Bombeiros': '#33a02c',
    '9º Grupamento de Bombeiros': '#fb9a99',
    '10º Grupamento de Bombeiros': '#a6cee3',
    '11º Grupamento de Bombeiros': '#1f78b4',
    '12º Grupamento de Bombeiros': '#b2df8a',
    '13º Grupamento de Bombeiros': '#33a02c',
    '14º Grupamento de Bombeiros': '#fb9a99',
    '15º Grupamento de Bombeiros': '#e31a1c',
    '16º Grupamento de Bombeiros': '#fdbf6f',
    '17º Grupamento de Bombeiros': '#ff7f00',
    '18º Grupamento de Bombeiros': '#cab2d6',
    '19º Grupamento de Bombeiros': '#6a3d9a',
    '20º Grupamento de Bombeiros': '#b15928'
}

# Map
m = folium.Map([-23, -47], zoom_start=6)

# Layer
folium.GeoJson(
    gdf,
    name='Bombeiros',
    smooth_factor=1.0,
    #zoom_on_click=True,
    embed=False,
    style_function=lambda x: {
        'fillColor': color_polygon[x['properties']['gb_nome']],
        'color': color_polygon[x['properties']['gb_nome']],
        'weight': 1,
        'fillOpacity': 0.3,
    },
    highlight_function=lambda x: {'weight': 3},
    tooltip=folium.features.GeoJsonTooltip(
        fields=['municipio_nome', 'gb_sigla'],
        aliases=['Munícipio', 'Grupamento'],
        sticky=True,
        opacity=0.9,
        direction='right',
    ),
    popup=folium.GeoJsonPopup(
        ['popup'],
        parse_html=False,
        max_width='300',
        show=False,
        labels=False,
        sticky=True,
    )
).add_to(m)

# Plugins
m.fit_bounds(m.get_bounds())
plugins.Fullscreen(
    position='topleft',
    title='Clique para Maximizar',
    title_cancel='Mininizar',    
).add_to(m)
m
import folium
import requests

# Url Data
url = 'https://raw.githubusercontent.com/michelmetran/sp_bombeiro/main/data/shps/sp_bombeiros.json'

# Map
m = folium.Map(
    location=[-23.9619271,-46.3427499],
    zoom_start=12,
)

# Dict
color_polygon = {
    '1º Grupamento de Bombeiros': '#ffff99',
    '5º Grupamento de Bombeiros': '#a6cee3',
    '6º Grupamento de Bombeiros': '#1f78b4',
    '7º Grupamento de Bombeiros': '#b2df8a',
    '8º Grupamento de Bombeiros': '#33a02c',
    '9º Grupamento de Bombeiros': '#fb9a99',
    '10º Grupamento de Bombeiros': '#a6cee3',
    '11º Grupamento de Bombeiros': '#1f78b4',
    '12º Grupamento de Bombeiros': '#b2df8a',
    '13º Grupamento de Bombeiros': '#33a02c',
    '14º Grupamento de Bombeiros': '#fb9a99',
    '15º Grupamento de Bombeiros': '#e31a1c',
    '16º Grupamento de Bombeiros': '#fdbf6f',
    '17º Grupamento de Bombeiros': '#ff7f00',
    '18º Grupamento de Bombeiros': '#cab2d6',
    '19º Grupamento de Bombeiros': '#6a3d9a',
    '20º Grupamento de Bombeiros': '#b15928'
}

# Layer
lyr = folium.TopoJson(
    #open(os.path.join('data', 'shps', 'sp_bombeiros.json')),  # Local File
    requests.get(url).json(),
    object_path='objects.data',
    name='São Paulo',
    style_function=lambda x: {
        'fillColor': color_polygon[x['properties']['gb_nome']],
        'color': color_polygon[x['properties']['gb_nome']],
        'weight': 1,
        'fillOpacity': 0.3,
    },
    tooltip=folium.features.GeoJsonTooltip(
        fields=['municipio_nome', 'gb_sigla'],
        aliases=['Munícipio', 'Grupamento'],
        sticky=True,
        opacity=0.9,
        direction='right',
    ),
    #popup='test', # Doesnt Work! ERROR!
)

lyr.add_child(
    folium.Popup(
        #'test',   # Doesnt Work, static text...
        #['popup'],   # Doesnt Work, blank
        gdf['popup'][0],   # Doesnt Work STATIC INFOS, NOT DYNAMIC!
        #lambda x: x['properties']['popup'],   # Doesnt Work
        #sticky=False,
        #localize=True,
        #parse_html=False,
        max_width=400
    )
)

# Add Layer to Map
lyr.add_to(m)

# Apresenta o mapa
m.fit_bounds(m.get_bounds())
plugins.Fullscreen(
    position='topleft',
    title='Clique para Maximizar',
    title_cancel='Mininizar',
).add_to(m)
m<jupyter_output><empty_output><jupyter_text>Iterar o Json<jupyter_code># Cria o mapa
m = folium.Map(
    location=[-23.9619271,-46.3427499],
    zoom_start=12,
)
group = folium.FeatureGroup(name='ssss')
j = json.load(open(os.path.join('data', 'shps', 'sp_bombeiros.json')))
for row in j['objects']['data']['geometries']:
    #print(json.dumps({'type': 'Topology', 'objects': {'data': {'geometries': [row]}}}))
    #print(json.dumps(row, indent=4, sort_keys=True))
    #print('---')
    #print(row['properties']['gb_nome'])    
    data = {
        'type': 'Topology',
        'objects': {'data': {'geometries': [row]}},
        'bbox': j['bbox'],
        'transform': j['transform'],
        'arcs': j['arcs'],
    }
    folium.TopoJson(
        data,
        object_path='objects.data'
    ).add_to(group)

group.add_to(m)
LayerControl().add_to(m)
#m.fit_bounds(m.get_bounds())
m
m = folium.Map([0, 0], zoom_start=7)
folium.TopoJson(
    data,
    object_path='objects.two_squares'
).add_to(m)
m<jupyter_output><empty_output><jupyter_text>Estudos de Json<jupyter_code>j = json.load(open(os.path.join('data', 'shps', 'sp_bombeiros.json')))
print(j.keys())
#print(data.keys())
j = j['objects']['data']['geometries'][0]
data = data['objects']['data']['geometries'][0]
print(j.keys())
print(data.keys())
j = j['properties']
data = data['properties']
print(j.keys())
print(data.keys())<jupyter_output><empty_output><jupyter_text>Topo as<jupyter_code>m = folium.Map([0, 0], zoom_start=7)
folium.TopoJson(
    {
      "type":"Topology",
      "transform":{
        "scale": [1,1],
        "translate": [0,0]
      },
      "objects":{ 
        "two_squares":{
          "type": "GeometryCollection",
          "geometries":[
            {"type": "Polygon", "arcs":[[0,1]],"properties": {"name": "Left_Polygon" }},
            {"type": "Polygon", "arcs":[[2,-1]],"properties": {"name": "Right_Polygon" }}
          ]
        }
      },
      "arcs": [
        [[1,2],[0,-2]],
        [[1,0],[-1,0],[0,2],[1,0]],
        [[1,2],[1,0],[0,-2],[-1,0]]
      ]
    },
    object_path='objects.two_squares'
).add_to(m)
m<jupyter_output><empty_output><jupyter_text>Colores<jupyter_code>color_polygon = {
    '1º Grupamento de Bombeiros': '#ffff99',
    '5º Grupamento de Bombeiros': '#a6cee3',
    '6º Grupamento de Bombeiros': '#1f78b4',
    '7º Grupamento de Bombeiros': '#b2df8a',
    '8º Grupamento de Bombeiros': '#33a02c',
    '9º Grupamento de Bombeiros': '#fb9a99',
    '10º Grupamento de Bombeiros': '#a6cee3',
    '11º Grupamento de Bombeiros': '#1f78b4',
    '12º Grupamento de Bombeiros': '#b2df8a',
    '13º Grupamento de Bombeiros': '#33a02c',
    '14º Grupamento de Bombeiros': '#fb9a99',
    '15º Grupamento de Bombeiros': '#e31a1c',
    '16º Grupamento de Bombeiros': '#fdbf6f',
    '17º Grupamento de Bombeiros': '#ff7f00',
    '18º Grupamento de Bombeiros': '#cab2d6',
    '19º Grupamento de Bombeiros': '#6a3d9a',
    '20º Grupamento de Bombeiros': '#b15928'
}

color_polygon['20º Grupamento de Bombeiros'] = 22
color_polygon<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.17509727626459143, 'fraction_numerical': 0.03131668131040542, 'mean_word_length': 3.4424310008363537, 'pattern_counts': {'":': 17, '<': 71, '<?xml version=': 0, '>': 71, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '10', 'dir': 'jupyter-structured-clean-dedup', 'id': '23185', 'license': 'MIT', 'n_tokens_mistral': 6467, 'n_tokens_neox': 6251, 'n_words': 1090, 'path': 'bombeiro_create_map_tests.ipynb', 'repo_name': 'michelmetran/sp_bombeiro', 'size': '15934'}