COBie_Flat / app.py
IanYeo's picture
cobie flat with system
c42041f
raw
history blame
No virus
7.83 kB
#!/usr/bin/env python
# coding: utf-8
# In[1]:
import numpy as np
import pandas as pd
import regex as re
import streamlit as st
import pickle
import io
import simplejson as json
import base64
import uuid
# In[2]:
def decodeIfc(txt):
# In regex "\" is hard to manage in Python... I use this workaround
txt = txt.replace('\\', 'µµµ')
txt = re.sub('µµµX2µµµ([0-9A-F]{4,})+µµµX0µµµ', decodeIfcX2, txt)
txt = re.sub('µµµSµµµ(.)', decodeIfcS, txt)
txt = re.sub('µµµXµµµ([0-9A-F]{2})', decodeIfcX, txt)
txt = txt.replace('µµµ','\\')
return txt
def decodeIfcX2(match):
# X2 encodes characters with multiple of 4 hexadecimal numbers.
return ''.join(list(map(lambda x : chr(int(x,16)), re.findall('([0-9A-F]{4})',match.group(1)))))
def decodeIfcS(match):
return chr(ord(match.group(1))+128)
def decodeIfcX(match):
# Sometimes, IFC files were made with old Mac... wich use MacRoman encoding.
num = int(match.group(1), 16)
if (num <= 127) | (num >= 160):
return chr(num)
else:
return bytes.fromhex(match.group(1)).decode("macroman")
def convert_unicode_string(row, column_name):
return decodeIfc(row[column_name])
def decode_cobie(cobie_df):
columns_to_decode = ['Name', 'TypeName', 'Description']
for column_to_decode in columns_to_decode:
cobie_df[column_to_decode] = cobie_df.apply(
convert_unicode_string,
column_name=column_to_decode,
axis=1
)
return cobie_df
# In[3]:
def combine_type_component(cobie_type_df, cobie_component_df):
cobie_type_df.rename(columns={
'Name':'TypeName',
'ExtObject':'TypeExtObject',
'ExtIdentifier':'TypeExtIdentifier',
}, inplace=True)
cobie_type_component = pd.merge(
cobie_component_df[[
'Name','TypeName', 'Space',
'ExtObject', 'ExtIdentifier', 'SerialNumber',
]],
cobie_type_df[[
'TypeName', 'Category', 'Description',
'Manufacturer', 'ModelNumber',
'TypeExtObject', 'TypeExtIdentifier',
]],
on='TypeName',
how='left',
)
return cobie_type_component
# In[4]:
def combine_full_component_system(cobie_flat, cobie_system_df):
cobie_system_df.rename(columns={
'Name':'SystemName',
'Description':'SystemDescription',
'Category':'SystemCategory',
'ComponentNames':'Name',
}, inplace=True)
system_all = cobie_system_df.explode(column='Name')
cobie_flat = pd.merge(
cobie_flat,
system_all[[
'SystemName', 'SystemDescription', 'SystemCategory',
'Name',
]],
on='Name',
how='left',
)
cobie_flat = cobie_flat[[
'Name',
'TypeName',
'Description',
'Category',
'SystemName',
'SystemDescription',
'SystemCategory',
'Space',
'ExtObject',
'ExtIdentifier',
'SerialNumber',
'Manufacturer',
'ModelNumber',
'TypeExtObject',
'TypeExtIdentifier',
]]
cobie_flat = cobie_flat.drop_duplicates(
subset=['ExtIdentifier'],
)
return cobie_flat
# In[5]:
def download_button(object_to_download, download_filename, button_text, pickle_it=False):
"""
Generates a link to download the given object_to_download.
Params:
------
object_to_download: The object to be downloaded.
download_filename (str): filename and extension of file. e.g. mydata.csv,
some_txt_output.txt download_link_text (str): Text to display for download
link.
button_text (str): Text to display on download button (e.g. 'click here to download file')
pickle_it (bool): If True, pickle file.
Returns:
-------
(str): the anchor tag to download object_to_download
Examples:
--------
download_link(your_df, 'YOUR_DF.csv', 'Click to download data!')
download_link(your_str, 'YOUR_STRING.txt', 'Click to download text!')
"""
if pickle_it:
try:
object_to_download = pickle.dumps(object_to_download)
except pickle.PicklingError as e:
st.write(e)
return None
else:
if isinstance(object_to_download, bytes):
pass
elif isinstance(object_to_download, pd.DataFrame):
#object_to_download = object_to_download.to_csv(index=False)
towrite = io.BytesIO()
object_to_download = object_to_download.to_excel(
towrite,
encoding='utf-8',
index=False,
header=True,
na_rep=''
)
towrite.seek(0)
# Try JSON encode for everything else
else:
object_to_download = json.dumps(object_to_download)
try:
# some strings <-> bytes conversions necessary here
b64 = base64.b64encode(object_to_download.encode()).decode()
except AttributeError as e:
b64 = base64.b64encode(towrite.read()).decode()
button_uuid = str(uuid.uuid4()).replace('-', '')
button_id = re.sub('\d+', '', button_uuid)
custom_css = f"""
<style>
#{button_id} {{
display: inline-flex;
align-items: center;
justify-content: center;
background-color: rgb(255, 255, 255);
color: rgb(38, 39, 48);
padding: .25rem .75rem;
position: relative;
text-decoration: none;
border-radius: 4px;
border-width: 1px;
border-style: solid;
border-color: rgb(230, 234, 241);
border-image: initial;
}}
#{button_id}:hover {{
border-color: rgb(246, 51, 102);
color: rgb(246, 51, 102);
}}
#{button_id}:active {{
box-shadow: none;
background-color: rgb(246, 51, 102);
color: white;
}}
</style> """
dl_link = custom_css + f'<a download="{download_filename}" id="{button_id}" href="data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,{b64}">{button_text}</a><br></br>'
return dl_link
# In[7]:
# In[8]:
# In[9]:
# In[10]:
# In[11]:
# In[12]:
# In[13]:
# In[ ]:
cobie_file_button = st.text_input("Dropbox link to COBie file", key="cobie_file_button")
# In[ ]:
if cobie_file_button:
cobie_file_path = st.session_state.cobie_file_button
if '=0' in cobie_file_path:
cobie_file_path = cobie_file_path.replace('=0', '=1')
cobie_file = pd.ExcelFile(cobie_file_path)
cobie_floor_df = cobie_file.parse(sheet_name = 'Floor', dtype={'ExtIdentifier':str, 'Name':str})
cobie_space_df = cobie_file.parse(sheet_name = 'Space', dtype={'ExtIdentifier':str, 'Name':str})
cobie_type_df = cobie_file.parse(sheet_name = 'Type', dtype={'ExtIdentifier':str, 'Description':str, 'Name':str})
cobie_system_df = cobie_file.parse(sheet_name = 'System', dtype={'ExtIdentifier':str, 'Description':str, 'Name':str})
cobie_component_df = cobie_file.parse(sheet_name = 'Component', dtype={'ExtIdentifier':str, 'Space':str, 'Description':str, 'Name':str})
cobie_type_component = combine_type_component(cobie_type_df, cobie_component_df)
cobie_flat = combine_full_component_system(cobie_type_component, cobie_system_df)
cobie_flat = decode_cobie(cobie_flat)
file_name = 'cobie_flat.xlsx'
download_button_str = download_button(cobie_flat, file_name, f'Click here to download {file_name}', pickle_it=False)
st.markdown(download_button_str, unsafe_allow_html=True)