Skip to content

Commit

Permalink
Merge pull request #18 from NRCan/dev
Browse files Browse the repository at this point in the history
bugs and small fixes
  • Loading branch information
cefect authored Sep 4, 2024
2 parents 7860f93 + 5a0e2ce commit 87857cb
Show file tree
Hide file tree
Showing 385 changed files with 1,414 additions and 187 deletions.
2 changes: 1 addition & 1 deletion cancurve/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#===============================================================================
# plugin metadata
#===============================================================================
__version__='0.1.0'
__version__='0.1.3'

#===============================================================================
# plugin entry point
Expand Down
2 changes: 1 addition & 1 deletion cancurve/bldgs/assertions.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def assert_proj_db_fp(fp, **kwargs):
assert_proj_db(conn, **kwargs)

except Exception as e:
raise AssertionError(f'project DB connection failed w/\n {e}')
raise ValueError(f'project DB connection failed w/\n {e}')



Expand Down
3 changes: 0 additions & 3 deletions cancurve/bldgs/bldg_meta_rqmts.csv
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
varName_core,varName_ui,varName_canflood,type,required_core,required_canflood,default_canflood,widgetName,case1,case2,case3,case4_R2,case5_crawl
,,tag,str,FALSE,TRUE,?,,test_case1,test_case2,heather_0509,R_2-L-BD-CU_ABCA,R_1-L-C-ST_ABCA
,,location,str,FALSE,FALSE,?,,,,,,
,,date,str,FALSE,FALSE,?,,,,,,
,,source,str,FALSE,FALSE,?,,,,,,
,currency,impact_units,str,FALSE,TRUE,$CAD,currency_ComboBox,,,,,
,costBasis,impact_var,str,FALSE,FALSE,damage,costBasis_ComboBox,,,Depreciated Costs,,
,,exposure_units,str,FALSE,FALSE,m,comboBox_tab3dataInput_expoUnits,,,,,
Expand Down
121 changes: 93 additions & 28 deletions cancurve/bldgs/cc_bldgs_dialog.ui
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ QTabBar::tab:selected { /* Style for selected tabs */
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
p, li { white-space: pre-wrap; }
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:14px; font-weight:400; font-style:normal;">
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Welcome to the CanCurve </span><span style=" font-size:12pt; font-weight:600;">Buildings Tool.</span><span style=" font-size:12pt;"> This tool is designed to create </span><span style=" font-size:12pt; font-style:italic;">Depth Damage Functions</span><span style=" font-size:12pt;"> (DDF) for Canadian buildings.</span></p>
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Welcome to the CanCurve </span><span style=" font-size:12pt; font-weight:600;">Buildings Tool.</span><span style=" font-size:12pt;"> This tool is designed to create </span><span style=" font-size:12pt; font-style:italic;">Depth Damage Functions</span><span style=" font-size:12pt;"> (DDF) for Canadian buildings. To get started or to learn more, see the </span><a href="https://github.com/NRCan/CanCurve"><span style=" font-size:12pt; text-decoration: underline; color:#0000ff;">Documentation</span></a><span style=" font-size:12pt;">.</span></p>
<p align="center" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/plugins/cancurve/img/icon.png" /></p>
<p align="center" style="-qt-paragraph-type:empty; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The following inputs are required:</span></p>
Expand All @@ -149,7 +149,7 @@ p, li { white-space: pre-wrap; }
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">The following inputs are optional:</span></p>
<p style=" margin-top:12px; margin-bottom:12px; margin-left:16px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Depth Replacement-Factor (DRF) dataset</span><span style=" font-size:12pt;">: This dataset relates flood depth to the percentage loss or damage of a restoration item and is specified on the </span><span style=" font-size:12pt; font-style:italic;">Data Input</span><span style=" font-size:12pt;"> tab. By default, the DRF dataset shipped with CanCurve will be used.</span></p>
<p style="-qt-paragraph-type:empty; margin-top:12px; margin-bottom:12px; margin-left:16px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"><br /></p>
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;Navigate through the tabs at the top of the window from left-to-right to create your own DDF.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;Navigate through the tabs at the top of the window from left-to-right to create your own DDF. For help and support, see the &lt;/span&gt;&lt;a href=&quot;https://github.com/NRCan/CanCurve/issues&quot;&gt;&lt;span style=&quot; font-size:12pt; text-decoration: underline; color:#0000ff;&quot;&gt;CanCurve Project GitHub Issues Page&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>
Expand All @@ -160,39 +160,98 @@ p, li { white-space: pre-wrap; }
</widget>
</item>
<item alignment="Qt::AlignHCenter">
<widget class="QGroupBox" name="groupBox_dev">
<property name="styleSheet">
<string notr="true">QPushButton {
background-color: red;
color: black;
}</string>
<widget class="QgsCollapsibleGroupBox" name="mGroupBox">
<property name="minimumSize">
<size>
<width>750</width>
<height>0</height>
</size>
</property>
<property name="title">
<string>!DEVELOPMENT ONLY! EASY PARAMETER LOADING OF TEST CASES</string>
<string>Tutorials</string>
</property>
<property name="collapsed">
<bool>true</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_12">
<layout class="QVBoxLayout" name="verticalLayout_22">
<item>
<widget class="QComboBox" name="comboBox_dev">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<widget class="QLabel" name="label_10">
<property name="text">
<string>Use this box to load tutorial data into the Buildings Tool. Note this will overwrite all fields.</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_dev">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Load Testing Values</string>
</property>
</widget>
<layout class="QHBoxLayout" name="horizontalLayout_12">
<item>
<spacer name="horizontalSpacer_7">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_9">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Name:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBox_dev">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_dev">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Load</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
Expand Down Expand Up @@ -908,6 +967,9 @@ QGroupBox {
<layout class="QHBoxLayout" name="horizontalLayout_10">
<item>
<widget class="QRadioButton" name="radioButton_6">
<property name="toolTip">
<string>The resulting DDF will reflect the total restoration costs for the archetype as a function of depth</string>
</property>
<property name="text">
<string>Total ($/structure)</string>
</property>
Expand All @@ -918,6 +980,9 @@ QGroupBox {
</item>
<item>
<widget class="QRadioButton" name="radioButton_tab3dataInput_rcvm2">
<property name="toolTip">
<string>The resulting DDF will reflect the restoration costs per area of the structure as a function of depth</string>
</property>
<property name="text">
<string>Area-based ($/area)</string>
</property>
Expand Down Expand Up @@ -1957,7 +2022,7 @@ QLabel {
</resources>
<connections/>
<buttongroups>
<buttongroup name="buttonGroup_costbasis"/>
<buttongroup name="buttonGroup_runControl"/>
<buttongroup name="buttonGroup_costbasis"/>
</buttongroups>
</ui>
19 changes: 13 additions & 6 deletions cancurve/bldgs/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -806,14 +806,17 @@ def c00_setup_project(
bx = np.invert(ci_df.index.isin(drf_df2.index))
if bx.any():
"""TODO: add some support for populating missing entries into the DRF"""
msg = f'DRF ({os.path.basename(drf_db_fp)}) is missing {bx.sum()}/{len(bx)} entries from the cost-items'
msg = f'The specified DRF ({os.path.basename(drf_db_fp)}) is missing {bx.sum()}/{len(bx)} entries found in the Cost-Item Table. '

ofp1 = os.path.join(out_dir, f'missing_DRF.csv')
ci_df[bx].to_csv(ofp1)

msg+=f'\noutput missing entries {ci_df[bx].shape} to:\n {ofp1}'

msg+=f'\nupdate the DRF and re-run this step before proceeding'
msg+=f'For reference, the missing entries have been written to file:\n\n{ofp1}'
msg+=f'\n\nTo proceed, update the DRF to provide factors for the missing cost items' + \
' (or remove the entries from the Cost Items table). '+\
'Typically, this is done by editing the Project Database with a third-party SQLite3 editor. '+\
'Once the tables are corrected, proceed with \'Step 2\'.'


log.warning(msg)

Expand Down Expand Up @@ -954,9 +957,13 @@ def c01_join_drf(proj_db_fp,
drf_df = pd.read_sql('SELECT * FROM c00_drf', conn, index_col=['cat', 'sel'])

#check
bx = ~ci_df['drf_intersect'].astype(bool)
bx = np.invert(ci_df.index.isin(drf_df.index))

#no... this flag is just for helping the user to fix the intersect
#need to re-calc the intersect to allow the user to update the database
#bx = ~ci_df['drf_intersect'].astype(bool)
if bx.any():
msg = f'missing {bx.sum()}/{len(bx)} cost-item keys in DRF... update your DRF and re-run step 1'
msg = f'missing {bx.sum()}/{len(bx)} cost-item keys in DRF\n add keys to DRF or remove from cost-items'
log.error(msg)
raise KeyError(msg)

Expand Down
23 changes: 18 additions & 5 deletions cancurve/bldgs/plots.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def plot_c00_costitems(df_raw,
#sum and pivot
ser1 = ser.groupby(['group_code', 'story', 'drf_intersect']).sum() #.unstack('group_code')


log.debug(f'groupby.sum to {len(ser1)}')

#===========================================================================
# plot
Expand All @@ -108,10 +108,23 @@ def plot_c00_costitems(df_raw,


#create two axijs side by side
stories_l = ser1.index.unique('story').to_list()
ax_d = dict(zip(stories_l, figure.subplots(nrows=1, ncols=len(stories_l), sharey=True)))
story_l = ser1.index.unique('story').to_list()
log.debug(f'on storys: {story_l}')

# Create subplots based on the number of stories
if len(story_l) == 1:
# When there's only one story, subplots returns a single Axes object
ax_d = {story_l[0]: figure.subplots(nrows=1, ncols=1, sharey=True)}
else:
# When there are multiple stories, subplots returns a list of Axes
ax_list = figure.subplots(nrows=1, ncols=len(story_l), sharey=True)
# Ensure ax_list is iterable, even if it contains just one element
ax_d = dict(zip(story_l, ax_list))


ymax = max(ser1.groupby('story').sum())

log.debug(f'plotting on {len(ax_d)}')
for k0, ax in ax_d.items():
gser = ser1.xs(k0, level='story')

Expand Down Expand Up @@ -165,7 +178,7 @@ def plot_c00_costitems(df_raw,
ha=next(ha_l), va='bottom',
arrowprops=dict(arrowstyle="->", connectionstyle="arc3"))
else:
ax.bar_label(container, labels = [f'{group_name} {100*(val/gser.sum()):.0f}% ({val:,.0f})'], label_type='center')
ax.bar_label(container, labels = [f'{group_name}: {100*(val/gser.sum()):.0f}% ({val:,.0f})'], label_type='center')



Expand Down Expand Up @@ -197,7 +210,7 @@ def plot_c00_costitems(df_raw,
#ax.set_xlabel(f'story \'{k0}\'')

#left-most
if k0==stories_l[0]:
if k0==story_l[0]:
ax.yaxis.set_major_formatter(plt.matplotlib.ticker.StrMethodFormatter('{x:,.0f}'))
ax.set_ylabel('Replacement Cost (Sum)')

Expand Down
2 changes: 1 addition & 1 deletion docs/source/03_tutorials.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ This tutorial will demonstrate how to create a :ref:`CanFlood format DDF <sec02-
Step 1: Download the example Cost-Item Table
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

From the project repository, download the `example Cost-Item Table <https://github.com/NRCan/CanCurve/blob/main/tutorial/case1/R_1-L-BD-CU_ABCA.csv>`_ somewhere easy to find.
From the project repository, download the `example Cost-Item Table <https://github.com/NRCan/CanCurve/blob/main/tutorial/01/R_1-L-BD-CU_ABCA.csv>`_ somewhere easy to find.

Step 2: Enter Metadata
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down
50 changes: 23 additions & 27 deletions tests/bldgs/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@
from tests.data.bldgs_data_scripts import fixed_costs_master_d, test_data_dir_master#, bldg_meta_rqmt_df_test


#these cases are setup for unit tests
#end-to-end test cases are in bldgs_data_scripts.test_cases_l
cases_l = [
'case1',
'case2',
'case3',
'AB-Calgary_R_1-L-C-ST_ABCA'
]


#===============================================================================
# fixtrues--------
#===============================================================================
Expand All @@ -33,7 +43,8 @@ def proj_db_fp(testCase, testPhase, tmp_path):

#get the target directory
tdata_dir = os.path.join(test_data_dir_master, testCase, testPhase)
assert os.path.exists(tdata_dir), tdata_dir
if not os.path.exists(tdata_dir):
raise FileNotFoundError(tdata_dir)

#get the project db file
fp = find_single_file_by_extension(tdata_dir, '.cancurve')
Expand All @@ -51,6 +62,15 @@ def ci_fp(testCase):

@pytest.fixture(scope='function')
def fixed_costs_d(testCase):
"""retrieve fixed_costs_d from master
normally, fixed_costs_master_d is hard-coded and kept in
bldgs.dialog_test_scripts.fixed_costs_master_d
However, this can also be updated using pickels by calling
tests.data.bldgs_data_scripts.load_tests_cases_from_file()
"""

if not testCase in fixed_costs_master_d:
raise AssertionError(f'test case \'{testCase}\' missing from fixed_costs_master_d')
return fixed_costs_master_d[testCase]
Expand All @@ -66,29 +86,5 @@ def bldg_meta_d(testCase):
d = _get_bldg_meta_d(testCase, df=bldg_meta_rqmt_df_test)
return d

#===============================================================================
# @pytest.fixture(scope='function')
# def bldg_meta_d_ui(testCase):
# """full set of parameters for the UI"""
#
# if testCase=='case1':
# #just take first from parameters
# d = {k:v[0] for k,v in building_details_options_d.items()}
#
# elif testCase=='case2':
#
# #random choice
# d = {k: random.choice(v) for k, v in building_details_options_d.items()}
#
# """
# for k,v in d.items():
# print(f'{k}\n {v} ({type(v)})')
# """
# return d
#
#
# @pytest.fixture(scope='function')
# def bldg_meta_d_strict(testCase):
# """strict building meta parameters needed by core"""
# return {'basement_height_m':1.8, 'scale_value_m2':232.0, 'bldg_layout':'default'}
#===============================================================================


Loading

0 comments on commit 87857cb

Please sign in to comment.