Revit Project Dashboard with pyRevit and Streamlit
1. pyRevitとは
pyRevitは、Autodesk Revit®のラピッド・アプリケーション・デベロップメント (RAD) 環境です。Revit 環境とその API を使用して、使い慣れた言語で、自動化やアドオンのアイデアを素早くスケッチすることができます。また、開発環境としての使用例を示す豊富で強力なツールのセットが付属しています。pyRevitをダウンロードしてインストールすることで、Revitを起動し、新しく表示されるpyRevitタブおよび含まれるツールも参考にしてください!!
インストール方法はこちら
2. Streamlitとは
StreamlitはPythonを使って数分でデータ表示をすることができる共有可能なWebアプリケーションを作ることができます。
以下のコマンドを実行することでインストールすることができます。
使用可能なPythonのバージョンは3.6-3.8となります。
pip install streamlit
streamlit hello
3. pyRevit Routeとは
ウェブアプリケーションは2つの部分に分割されます。
- フロントエンド: ブラウザで動作し、ユーザーインターフェースとして動作する部分
- バックエンド:フロントエンドがデータを送受信するために接触する部分
フロントエンドを今回はStreamlitで担います。しかし、Revitデータにアクセスして Revit ドキュメントを操作、修正したりできるバックエンドをどのように作成するかという課題が常にありました。pyRevit Routeを用いることでバックエンドの問題を解決することができます。
4. pyRevit Route Extensionの使い方
pyRevit側のフォルダ構成
まずはpyRevitのExtensionと指定しているディレクトリ(フォルダ)の直下にRoute用のフォルダを作成します。作成後作製したディレクトリの直下にstartup.py
というファイルを作成すると完了です。
pyRevit-Sample-Extensions/
|----pyRevitRoute.Extension/
|----startup.py
5. Streamlitでプロジェクトタイトルを表示する
5.1 pyRevit側
まずは、Startupファイルでプロジェクトタイトルを取得します。
doc = __revit__.ActiveUIDocument.Document
title = doc.Title
このデータを送る場所を決めます。今回はroute-sample
の中に/title
を作ってデータを送ってみましょう!!
from pyrevit import routes
api = routes.API('route-sample')
@api.route('/title')
def get_title(doc):
return routes.make_response(data=doc.Title)
ここまでコードしたらpyRevitをリロードしてみましょう。
自身のブラウザで http://localhost:48884/route-sample/title に飛んでみてください。
以下の画像のように表示されていたらpyRevit側は成功です。
5.2 Streamlit側のコード
streamlit側ではpyRevit Routeで送られたJson形式のデータを読み込みにいきます。ここではrequests
を使って読み込んでみましょう。
動かす前に以下のコードを実行しておいてください。
pip requests
空のディレクトリを用意して、その中にapp.py
を用意します。
コードは以下のようにします。
import streamlit as st
import requests
BASE_URL = 'http://localhost:48884/route-sample/'
def get_title():
url = BASE_URL + 'title'
res= requests.get(url)
if res.status_code == 200:
return res.json()
st.title(get_title())
app.py
のディレクトリ上で以下のコマンドを実行します。
streamlit run app.py
以下のように表示されたら成功です。
6. プロジェクトに含まれるレベルを表形式で表示する
pandasのDataFrameを用いて表を作成します。
6.1 pyRevit側
まずはpyRevit側でレベルの名前とエレベーションを取得します。
この段階で、リストをエレベーションでソートしておきます。
@api.route('/levels')
def get_levels(doc):
level_list = []
levels = db.Collector(
of_category='Levels',
is_not_type=True).get_elements()
for level in levels:
level_dict = {}
level_dict['name'] = level.name
level_dict['Elevation']= level.Elevation * 304.8
level_list.append(level_dict)
sorted_level_list = sorted(level_list, key=lambda x:x['Elevation'])
return routes.make_response(data=sorted_level_list)
##6.2 Streamlit側
Streamlit側では表を表示する形式を以下のようにします。
def get_levels():
name_list = []
elevation_list = []
url = BASE_URL + 'levels'
res= requests.get(url)
if res.status_code == 200:
for l in res.json():
name_list.append(l['name'])
elevation_list.append(l['Elevation'])
level_tuple = list(zip(name_list, elevation_list))
chart_data = pd.DataFrame(
level_tuple,
columns = ['Level Name','Elevation'])
return chart_data
st.subheader(" レベル表 ")
st.dataframe(get_levels())
成功すると以下のように表示されます。
7. プロジェクトに含まれる窓のタイプ別個数をグラフで表示
pyRevit側
今回はファミリ名でバーチャートを分けてみます。
ファミリ名と個数をそれぞれ取得してデータを送ります。
@api.route('/furniture')
def get_furnitures(doc):
furnitures = db.Collector(
of_category='Furniture',
is_not_type=True).get_elements()
furniture_dict = {}
for w in furnitures:
if w.Symbol.FamilyName in furniture_dict.keys():
furniture_dict[w.Symbol.FamilyName] += 1
else:
furniture_dict[w.Symbol.FamilyName] = 1
return routes.make_response(data=furniture_dict)
Streamlit側
def get_furnitures():
url = BASE_URL + 'furniture'
res= requests.get(url)
if res.status_code == 200:
furniture_dict = res.json()
chart_data = pd.DataFrame(
furniture_dict.values(),
index=furniture_dict.keys())
return chart_data
st.subheader(" 家具ファミリ別 ")
st.bar_chart(get_furnitures())
成功すると以下のように表示されます。
Discussion