Skip to content

Commit

Permalink
0.8.1 (#17)
Browse files Browse the repository at this point in the history
This release removed quite a few modules and migrated them to another open source project `fsetools`. The purpose of `sfeprapy` is to aid the sophisticated performance based approach of probability reliability assessment (PRA) in fire safety & structural engineering. However, many helper tools which are not so relevant to PRA had been built as parts of `sfeprapy` during research and development. These helper tools lost their purpose as part of `sfeprapy` when features are improved or new technics are discovered and implemented. Thus, to provide accommodation to these helper tools as they may still be useful other than PRA, `fsetools` has been created to serve the purpose of collecting all fire safety engineering related open source codes.


* New:
  - New `sfeprapy.func.mcs` module, a base class for all Monte Carlo Simulation classes.
  - New `sfeprapy.mcs2` module behaves like `sfeprapy.mcs0` but takes different input parameters.


* Improved:

  * Removed `probability_weight`. Only `p1`, `p2`, `p3`, `p4` and `general_room_floor_area` are required.
  * Multiprocessing instances in `sfeprapy.func.mcs` are being reused to improve efficiency.
  * One way data to hard drive jobs in `sfeprapy.func.mcs` are carried out in non-blocking threads to improve its performance.

* Depreciated:
  - Removed all GUI components.
  - Removed unnecessary output from `sfeprapy.mcs0`, e.g. `fire_time`, `fire_temperature` etc. 
  - Removed figure plotting features, i.e. `all` features relevant to `plotly` and `matplotlib`.
  • Loading branch information
fuyans authored Oct 23, 2020
1 parent 5083e5b commit cf1804c
Show file tree
Hide file tree
Showing 44 changed files with 1,198 additions and 3,662 deletions.
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ language: python
python:
- "3.7"
install:
- pip install -r requirements-dev.txt
- pip install --upgrade "git+https://github.com/fsepy/fsetools.git@dev"
- pip install .
- pip install codecov
- pip install pytest-cov
Expand Down
9 changes: 1 addition & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
# SfePrapy
[![GitHub version](https://badge.fury.io/gh/fsepy%2Fsfeprapy.svg)](https://github.com/fsepy/SfePrapy)
[![Updates](https://pyup.io/repos/github/fsepy/SfePrapy/shield.svg)](https://pyup.io/repos/github/fsepy/SfePrapy/)
[![Build Status](https://img.shields.io/travis/fsepy/SfePrapy.svg?branch=master&label=build%20(master)&style=flat)](https://travis-ci.org/fsepy/SfePrapy)
[![Build Status](https://img.shields.io/travis/fsepy/SfePrapy.svg?branch=dev&label=build%20(dev)&style=flat)](https://travis-ci.org/fsepy/SfePrapy)
[![codecov](https://codecov.io/gh/fsepy/SfePrapy/branch/dev/graph/badge.svg)](https://codecov.io/gh/fsepy/SfePrapy)

Structural fire engineering (Sfe) probabilistic reliability assessment (Pra) Python (py) is a probabilistic analysis tool. It calculates equivalent of time exposure to ISO 834 standard fire and this can be used to assess the appropriate fire resistance rating for structural elements using reliability based methods.

`sfeprapy` is evolving and actively used in research and real engineering design problems.
`sfeprapy` is under continuous development and actively used in research and real engineering design problems.

A publication summarising the capabilities can be found [here](https://www.researchgate.net/publication/333202825_APPLICATION_OF_PYTHON_PROGRAMMING_LANGUAGE_IN_STRUCTURAL_FIRE_ENGINEERING_-_MONTE_CARLO_SIMULATION).

Expand Down Expand Up @@ -64,12 +63,6 @@ sfeprapy mcs0 -p 4 example_input.csv

`sfeprapy.mcs0` uses the [multiprocessing](https://docs.python.org/3.4/library/multiprocessing.html#module-multiprocessing) library to utilise full potential performance of multi-core CPUs. The `-p 4` defines 4 threads will be used in running the simulation, 1 is the default value.

#### To produce a figure (once a `sfeprapy.mcs0` simulation is complete)

```sh
sfeprapy mcs0 figure mcs.out.csv
```

## Authors

**Ian Fu** - *ian.fu@ofrconsultants.com*
Expand Down
19 changes: 6 additions & 13 deletions profiler/mcs0.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@

def profile_standard_case():
import copy
from sfeprapy.func.mcs_obj import MCS
from sfeprapy.mcs0 import EXAMPLE_INPUT_DICT, EXAMPLE_CONFIG_DICT
from sfeprapy.mcs0.mcs0_calc import teq_main, teq_main_wrapper, mcs_out_post
from sfeprapy.func.mcs_gen import main as gen
from sfeprapy.mcs0.mcs0_calc import MCS0

# increase the number of simulations so it gives sensible results
mcs_input = copy.deepcopy(EXAMPLE_INPUT_DICT)
Expand All @@ -18,19 +16,14 @@ def profile_standard_case():
mcs_input[k]["timber_exposed_area"] = 0
mcs_input[k].pop("beam_position_horizontal")
mcs_input[k]["beam_position_horizontal:dist"] = "uniform_"
mcs_input[k]["beam_position_horizontal:ubound"] = (
mcs_input[k]["room_depth"] * 0.9
)
mcs_input[k]["beam_position_horizontal:lbound"] = (
mcs_input[k]["room_depth"] * 0.6
)
mcs_input[k]["beam_position_horizontal:ubound"] = mcs_input[k]["room_depth"] * 0.9
mcs_input[k]["beam_position_horizontal:lbound"] = mcs_input[k]["room_depth"] * 0.6

# increase the number of threads so it runs faster
mcs_config["n_threads"] = 3
mcs = MCS()
mcs.define_problem(data=mcs_input, config=mcs_config)
mcs.define_stochastic_parameter_generator(gen)
mcs.define_calculation_routine(teq_main, teq_main_wrapper, mcs_out_post)
mcs = MCS0()
mcs.mcs_inputs = mcs_input
mcs.mcs_config = mcs_config
mcs.run_mcs()


Expand Down
1 change: 1 addition & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
cython>=0.29.21
10 changes: 4 additions & 6 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
numpy>=1.17.1
pandas>=0.25.1
scipy>=1.3.1
matplotlib>=3.1.1
tqdm>=4.36
pandas>=1.1.1
scipy>=1.5.2
matplotlib>=3.2.2
tqdm>=4.50.2
xlrd>=1.2.0
plotly>=4.2.1
docopt>=0.6
pyside2>=5.12
openpyxl>=3.0.3
13 changes: 7 additions & 6 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,12 @@
with open(os.path.join(os.path.dirname(os.path.realpath(__file__)), "README.md")) as f:
long_description = f.read()

with open("requirements.txt") as f:
requirements = f.read().splitlines()
try:
with open("requirements.txt") as f:
requirements = f.read().splitlines()
except FileNotFoundError:
with open(os.path.join(os.path.dirname(os.path.realpath(__file__)), "requirements.txt")) as f:
requirements = f.read().splitlines()

setuptools.setup(
name="sfeprapy",
Expand All @@ -38,12 +42,9 @@
"sfeprapy.dat",
"sfeprapy.mcs0",
"sfeprapy.mcs1",
"sfeprapy.mcs2",
"sfeprapy.func",
"sfeprapy.dist_fit",
"sfeprapy.cli",
"sfeprapy.gui",
"sfeprapy.gui.layout",
"sfeprapy.gui.logic",
],
install_requires=requirements,
include_package_data=True,
Expand Down
59 changes: 52 additions & 7 deletions sfeprapy/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,47 @@
import logging
import os


# setup logger
def get_logger(f_handler_fp: str = None, f_handler_level=logging.WARNING, c_handler_level=logging.INFO):
logger_ = logging.getLogger('sfeprapy')

if f_handler_fp:
f_handler = logging.FileHandler(os.path.realpath(f_handler_fp))
else:
f_handler = logging.FileHandler(os.path.join(os.path.expanduser('~'), 'fsetoolsgui.log'))
f_handler.setLevel(f_handler_level)
f_handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)-8s [%(filename)s:%(lineno)d] %(message)s'))
logger_.addHandler(f_handler)

c_handler = logging.StreamHandler()
c_handler.setLevel(c_handler_level)
c_handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)-8s [%(filename)s:%(lineno)d] %(message)s'))
logger_.addHandler(c_handler)

logger_.setLevel(logging.DEBUG)

return logger_


logger = get_logger()

# make root directory of this app which will be used 1. when running the app; 2. pyinstaller at compiling the app.
if os.path.exists(os.path.dirname(__file__)):
# this path should be used when running the app as a Python package (non compiled) and/or pyinstaller at compiling
# stage.
__root_dir__ = os.path.realpath(os.path.dirname(__file__))
elif os.path.exists(os.path.dirname(os.path.dirname(__file__))):
# the path will become invalid when the app run after compiled as the dirname `fsetoolsGUI` will disappear.
# instead, the parent folder of the project dir will be used.
__root_dir__ = os.path.realpath(os.path.dirname(os.path.dirname(__file__)))
else:
raise IsADirectoryError(
f'Project root directory undefined: '
f'{os.path.dirname(__file__)} nor '
f'{os.path.dirname(os.path.dirname(__file__))}'
)

"""
VERSION IDENTIFICATION RULES DOCUMENTED IN PEP 440 ARE FOLLOWED.
Expand Down Expand Up @@ -34,11 +78,10 @@
"""

__version__ = "0.7.1.post6"
__version__ = "0.8.1"


def check_pip_upgrade():

# Parse the latest version string
import subprocess
from subprocess import STDOUT, check_output
Expand Down Expand Up @@ -70,13 +113,15 @@ def check_pip_upgrade():
if __name__ == "__main__":
import re


def is_canonical(version):
return (
re.match(
r"^([1-9][0-9]*!)?(0|[1-9][0-9]*)(\.(0|[1-9][0-9]*))*((a|b|rc)(0|[1-9][0-9]*))?(\.post(0|[1-9][0-9]*))?(\.dev(0|[1-9][0-9]*))?$",
version,
)
is not None
re.match(
r"^([1-9][0-9]*!)?(0|[1-9][0-9]*)(\.(0|[1-9][0-9]*))*((a|b|rc)(0|[1-9][0-9]*))?(\.post(0|[1-9][0-9]*))?(\.dev(0|[1-9][0-9]*))?$",
version,
)
is not None
)


assert is_canonical(__version__)
58 changes: 29 additions & 29 deletions sfeprapy/cli/__main__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
"""SfePrapy CLI Help.
Usage:
sfeprapy
sfeprapy mcs0 gui
sfeprapy mcs0 run [-p=<int>] <file_name>
sfeprapy mcs0 figure <file_name>
sfeprapy mcs0 template <file_name>
sfeprapy distfit [--data_t=<int>] [--dist_g=<int>] <file_name>
sfeprapy mcs2 run [-p=<int>] <file_name>
sfeprapy mcs2 template <file_name>
Examples:
sfeprapy mcs0 template inputs.csv
sfeprapy mcs0 template inputs.xlsx
sfeprapy mcs0 run -p 2 inputs.csv
sfeprapy mcs0 figure mcs.out.csv
Options:
--data_t=<int> an integer indicating data type:
Expand All @@ -15,12 +20,10 @@
--dist_g=<int> an integer indicating what distribution group to be used for fitting the data:
0 fit to all available distributions.
1 (default) fit to common distribution types.
-p=<int> to define number of processes for MCS, positive integer only.
-p=<int> to define number of processes for MCS, positive integer only. 2 by default.
-h --help to show this message.
Commands:
Will run `mcs0 gui` if no command is supplied.
mcs0 gui Experimental GUI version of sfeprapy.
mcs0 run Monte Carlo Simulation to solve equivalent time exposure in ISO 834 fire, method 0.
mcs0 figure produce figure from the output file <file_name>.
mcs0 template save example input file to <file_name>.
Expand All @@ -29,10 +32,12 @@
from docopt import docopt

from sfeprapy.func.stats_dist_fit import auto_fit_2
from sfeprapy.gui.__main__ import main as main_gui
from sfeprapy.mcs0 import EXAMPLE_INPUT_CSV
from sfeprapy.mcs0 import EXAMPLE_INPUT_CSV as EXAMPLE_INPUT_CSV_MCS0
from sfeprapy.mcs0 import EXAMPLE_INPUT_DF as EXAMPLE_INPUT_DF_MCS0
from sfeprapy.mcs0.__main__ import main as mcs0
from sfeprapy.mcs0.__main__ import save_figure as mcs0_figure
from sfeprapy.mcs2 import EXAMPLE_INPUT_CSV as EXAMPLE_INPUT_CSV_MCS2
from sfeprapy.mcs2 import EXAMPLE_INPUT_DF as EXAMPLE_INPUT_DF_MCS2
from sfeprapy.mcs2.__main__ import main as mcs2


def main():
Expand All @@ -44,42 +49,37 @@ def main():
arguments["<file_name>"] = os.path.realpath(arguments["<file_name>"])

if arguments["mcs0"]:

if arguments["gui"]:
main_gui()
return 0

elif arguments["figure"]:

mcs0_figure(fp_mcs0_out=arguments["<file_name>"])

elif arguments["template"]:
from sfeprapy.mcs0 import EXAMPLE_INPUT_CSV, EXAMPLE_INPUT_DF

if arguments["template"]:
if arguments["<file_name>"].endswith('.xlsx'):
EXAMPLE_INPUT_DF.to_excel(arguments["<file_name>"])
EXAMPLE_INPUT_DF_MCS0.to_excel(arguments["<file_name>"])
else:
with open(arguments["<file_name>"], "w+", encoding='utf-8') as f:
f.write(EXAMPLE_INPUT_CSV)
f.write(EXAMPLE_INPUT_CSV_MCS0)

else:

fp_mcs_in = arguments["<file_name>"]
n_threads = arguments["-p"] or 2
mcs0(fp_mcs_in=fp_mcs_in, n_threads=int(n_threads))

elif arguments["distfit"]:
elif arguments['mcs2']:
if arguments['template']:
if arguments["<file_name>"].endswith('.xlsx'):
EXAMPLE_INPUT_DF_MCS2.to_excel(arguments["<file_name>"])
else:
with open(arguments["<file_name>"], "w+", encoding='utf-8') as f:
f.write(EXAMPLE_INPUT_CSV_MCS2)
else:
fp_mcs_in = arguments["<file_name>"]
n_threads = arguments["-p"] or 2
mcs2(fp_mcs_in=fp_mcs_in, n_threads=int(n_threads))

elif arguments["distfit"]:
# Default values
data_type = arguments["--data_t"] or 2
distribution_list = arguments["--dist_g"] or 1

# Main
auto_fit_2(
data_type=int(data_type),
distribution_list=int(distribution_list),
data=arguments["<file_name>"],
)

else:
main_gui()
Loading

0 comments on commit cf1804c

Please sign in to comment.