Spaces:
Sleeping
Sleeping
#!/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) | |