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) | |