Skip to content

Commit

Permalink
Review
Browse files Browse the repository at this point in the history
  • Loading branch information
a-ma72 committed Aug 29, 2021
1 parent ec28f0e commit 9fb1bd9
Show file tree
Hide file tree
Showing 11 changed files with 300 additions and 244 deletions.
2 changes: 1 addition & 1 deletion python/MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
include src/rainflow.c
include src/rainflow.h
include src/rainflow.hpp
LICENSE
include LICENSE
7 changes: 4 additions & 3 deletions python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,17 @@ predefined functions.
pip install {packagename}.tar.gz
where _{packagename}_ is the current package release, for example:

pip install rfcnt-0.1.0.tar.gz
pip install rfcnt-0.1.1.tar.gz

### Test
_rfcnt_ packages include some unit tests, which can be run:

python run_tests.py
python -m rfcnt.run_tests

### Examples
For a quick introduction you can run and inspect a small example:
python run_examples.py

python -m rfcnt.run_examples

![](jupyter_screenshot.png)

Expand Down
2 changes: 2 additions & 0 deletions python/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import tests
from . import utils
18 changes: 11 additions & 7 deletions python/run_examples.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import sys
from rfcnt.tests import examples

print( "Running example 1..." )
examples.example_1()

def main():
print("Running example 1...")
examples.example_1()


if __name__ == '__main__':
main()


"""
Jupyter Notebook:
!pip install ./rfcnt-0.1.0.tar.gz
!pip install ./rfcnt-0.1.1.tar.gz
!pip install --upgrade matplotlib
from rfcnt.tests import examples
examples.example_1()
"""
!python -m rfcnt.run_examples
"""
31 changes: 22 additions & 9 deletions python/run_tests.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,27 @@
from rfcnt.tests import test_rfcnt
from unittest.case import TestCase
import unittest
from io import StringIO
from pprint import pprint

stream = StringIO()
runner = unittest.TextTestRunner(stream=stream)
result = runner.run(unittest.makeSuite(test_rfcnt.TestRainflowCounting))
print( 'Tests run ', result.testsRun )
print( 'Errors ', result.errors )
pprint(result.failures)
stream.seek(0)
print( 'Test output\n', stream.read() )

def run():
stream = StringIO()
runner = unittest.TextTestRunner(stream=stream)
result = runner.run(unittest.makeSuite(test_rfcnt.TestRainflowCounting))
print('Tests run ', result.testsRun)
print('Errors ', result.errors)
pprint(result.failures)
stream.seek(0)
print('Test output\n', stream.read())


if __name__ == '__main__':
run()


"""
Jupyter Notebook:
!pip install ./rfcnt-0.1.1.tar.gz
!pip install --upgrade matplotlib
!python -m rfcnt.run_tests
"""
132 changes: 72 additions & 60 deletions python/setup.py
Original file line number Diff line number Diff line change
@@ -1,74 +1,86 @@
import shutil
from setuptools import setup, Extension
from numpy import get_include as get_numpy_include
from os import path

version = (0,1,0)
version = (0, 1, 1)

try:
from numpy import get_include as get_numpy_include
except ImportError:
def get_numpy_include():
return "NOTFOUND"


def main():
this_directory = path.abspath(path.dirname(__file__))
long_description=""
long_description = ""
with open(path.join(this_directory, 'README.md'), encoding='utf-8') as f:
long_description = f.read()

setup(name="rfcnt",
version="%d.%d.%d" % version,
description="Python interface for rainflow counting",
long_description=long_description,
long_description_content_type='text/markdown',
keywords='rainflow counting',
author="Andreas Martin",
license='BSD-2-Clause License',
url='http://github.com/AndreasMartin72/rainflow',
install_requires=['numpy'],
py_modules=["rfcnt.utils", "rfcnt.examples"],
packages=["rfcnt", "rfcnt.tests"],
package_dir={"rfcnt": "", "rfcnt.tests": "tests"},
package_data={"rfcnt": ["run_examples.py", "run_tests.py", "requirements.txt", "README.md", "LICENSE"],
"rfcnt.tests": ["long_series.csv"]},
ext_modules=[Extension("rfcnt.rfcnt", ["src/rfcnt.cpp", "src/rainflow.c"],
define_macros=[
('NPY_NO_DEPRECATED_API', 'NPY_1_7_API_VERSION'),
('RFC_HAVE_CONFIG_H', '0'),
('RFC_VERSION_MAJOR', str(version[0])),
('RFC_VERSION_MINOR', str(version[1])),
('RFC_USE_INTEGRAL_COUNTS', '0'),
('RFC_USE_HYSTERESIS_FILTER', '1'),
('RFC_MINIMAL', '0'),
('RFC_TP_SUPPORT', '1'),
('RFC_HCM_SUPPORT', '1'),
('RFC_ASTM_SUPPORT', '1'),
('RFC_USE_DELEGATES', '1'),
('RFC_GLOBAL_EXTREMA', '1'),
('RFC_DAMAGE_FAST', '1'),
('RFC_DH_SUPPORT', '1'),
('RFC_AT_SUPPORT', '1'),
('RFC_DEBUG_FLAGS', '0'),
('RFC_EXPORT_MEX', '0')],
include_dirs=['src', get_numpy_include()],
)],
classifiers=[
'Development Status :: 4 - Beta',
'Environment :: Console',
'Framework :: Buildout :: Extension',
'Intended Audience :: Developers',
'Intended Audience :: Education',
'Intended Audience :: Information Technology',
'Intended Audience :: Science/Research',
'License :: OSI Approved :: BSD License',
'Natural Language :: English',
'Operating System :: MacOS :: MacOS X',
'Operating System :: Microsoft :: Windows',
'Operating System :: POSIX',
'Programming Language :: Python :: 3',
'Programming Language :: C++',
'Programming Language :: C',
'Topic :: Scientific/Engineering',
'Topic :: Scientific/Engineering :: Information Analysis',
'Topic :: Scientific/Engineering :: Physics',
])
setup(
name="rfcnt",
version="%d.%d.%d" % version,
description="Python interface for rainflow counting",
long_description=long_description,
long_description_content_type='text/markdown',
keywords='rainflow counting',
author="Andreas Martin",
license='BSD-2-Clause License',
url='http://github.com/AndreasMartin72/rainflow',
setup_requires=['wheel'],
install_requires=['numpy'],
packages=["rfcnt", "rfcnt.tests"],
package_dir={"rfcnt": "", "rfcnt.tests": "tests"},
package_data={
"rfcnt": ["*.py",
"requirements.txt", "README.md", "LICENSE"],
"rfcnt.tests": ["*.py", "long_series.csv"]
},
ext_modules=[
Extension(
"rfcnt.rfcnt", ["src/rfcnt.cpp", "src/rainflow.c"],
define_macros=[
('NPY_NO_DEPRECATED_API', 'NPY_1_7_API_VERSION'),
('RFC_HAVE_CONFIG_H', '0'),
('RFC_VERSION_MAJOR', str(version[0])),
('RFC_VERSION_MINOR', str(version[1])),
('RFC_USE_INTEGRAL_COUNTS', '0'),
('RFC_USE_HYSTERESIS_FILTER', '1'),
('RFC_MINIMAL', '0'),
('RFC_TP_SUPPORT', '1'),
('RFC_HCM_SUPPORT', '1'),
('RFC_ASTM_SUPPORT', '1'),
('RFC_USE_DELEGATES', '1'),
('RFC_GLOBAL_EXTREMA', '1'),
('RFC_DAMAGE_FAST', '1'),
('RFC_DH_SUPPORT', '1'),
('RFC_AT_SUPPORT', '1'),
('RFC_DEBUG_FLAGS', '0'),
('RFC_EXPORT_MEX', '0')],
include_dirs=['src', get_numpy_include()],
)
],
classifiers=[
'Development Status :: 4 - Beta',
'Environment :: Console',
'Framework :: Buildout :: Extension',
'Intended Audience :: Developers',
'Intended Audience :: Education',
'Intended Audience :: Information Technology',
'Intended Audience :: Science/Research',
'License :: OSI Approved :: BSD License',
'Natural Language :: English',
'Operating System :: MacOS :: MacOS X',
'Operating System :: Microsoft :: Windows',
'Operating System :: POSIX',
'Programming Language :: Python :: 3',
'Programming Language :: C++',
'Programming Language :: C',
'Topic :: Scientific/Engineering',
'Topic :: Scientific/Engineering :: Information Analysis',
'Topic :: Scientific/Engineering :: Physics',
]
)


if __name__ == "__main__":
main()
1 change: 1 addition & 0 deletions python/src/rfcnt.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <numpy/arrayobject.h>
#include <vector>
Expand Down
2 changes: 2 additions & 0 deletions python/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import examples
from . import test_rfcnt
96 changes: 52 additions & 44 deletions python/tests/examples.py
Original file line number Diff line number Diff line change
@@ -1,64 +1,72 @@
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from rfcnt import rfcnt, utils # Rainflow module (ftc2)
import os
import sys


def __get_script_path():
return os.path.dirname(os.path.realpath(__file__))
return os.path.dirname(__file__)


def example_1():
data = pd.read_csv(os.path.join(__get_script_path(), "long_series.csv"), header=None)
try:
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
except ImportError as err:
print("This example requires modules 'pandas', 'matplotlib' and 'seaborn!'")
raise err

data = pd.read_csv(
os.path.join(__get_script_path(), "long_series.csv"), header=None)
data = data.to_numpy().squeeze()

class_count = 50
class_range = data.max() - data.min()
class_width = class_range / (class_count - 1)
class_offset = data.min() - class_width / 2

res = rfcnt.rfc(data, class_count=class_count,
class_offset=class_offset,
class_width=class_width,
hysteresis=class_width,
use_HCM=0,
use_ASTM=0,
#spread_damage=0, # RFC_SD_HALF_23
spread_damage=8, # RFC_SD_TRANSIENT_23c
#residual_method=0, # RFC_RES_NONE
residual_method=7, # RFC_RES_REPEATED
wl={"sd": 1e3, "nd": 1e7, "k": 5})
res = rfcnt.rfc(
data, class_count=class_count,
class_offset=class_offset,
class_width=class_width,
hysteresis=class_width,
use_HCM=0,
use_ASTM=0,
#spread_damage=0, # RFC_SD_HALF_23
spread_damage=8, # RFC_SD_TRANSIENT_23c
#residual_method=0, # RFC_RES_NONE
residual_method=7, # RFC_RES_REPEATED
wl={"sd": 1e3, "nd": 1e7, "k": 5})

fig = plt.figure( constrained_layout=True, figsize=(14,10) )
fig = plt.figure(constrained_layout=True, figsize=(14, 10))
fig.tight_layout()
gs = fig.add_gridspec(3, 2)
ax1 = fig.add_subplot( gs[0,0] )
ax1 = fig.add_subplot(gs[0, 0])
sns.heatmap(res["rfm"], cmap="YlOrRd", ax=ax1)
ax1.invert_yaxis()
plt.grid( which="both" )
plt.xlabel( "Class # (to)" )
plt.ylabel( "Class # (from)" )
r = utils.rpplot_prepare( sa=res["rp"][:,0]/2, counts=res["rp"][:,1] )
ax2 = fig.add_subplot( gs[0,1] )
sns.lineplot( x=r["counts"].cumsum(), y=r["sa"], drawstyle='steps-pre', ci=None, ax=ax2 )
plt.xscale( "log" )
plt.ylim( bottom=0, top=1000 )
plt.xlim( left=0.9 )
plt.grid( which="both" )
plt.xlabel( "N (log) [1]" )
plt.ylabel( "$S_a$" )
ax3 = fig.add_subplot( gs[1,:] )
sns.lineplot( x=np.arange(len(res["dh"])), y=res["dh"].cumsum(), ax=ax3 )
plt.grid( which="both" )
plt.xlabel( "Sample #" )
plt.ylabel( "Damage (cumulative)" )
ax4 = fig.add_subplot( gs[2,:] )
sns.lineplot( x=np.arange(len(data)), y=data, ax=ax4 )
plt.grid( which="both" )
plt.xlabel( "Sample #" )
plt.ylabel( "Value" )
plt.grid(which="both")
plt.xlabel("Class # (to)")
plt.ylabel("Class # (from)")
r = utils.rpplot_prepare(sa=res["rp"][:, 0] / 2, counts=res["rp"][:, 1])
ax2 = fig.add_subplot(gs[0, 1])
sns.lineplot(
x=r["counts"].cumsum(),
y=r["sa"],
drawstyle='steps-pre', ci=None, ax=ax2)
plt.xscale("log")
plt.ylim(bottom=0, top=1000)
plt.xlim(left=0.9)
plt.grid(which="both")
plt.xlabel("N (log) [1]")
plt.ylabel("$S_a$")
ax3 = fig.add_subplot(gs[1, :])
sns.lineplot(x=np.arange(len(res["dh"])), y=res["dh"].cumsum(), ax=ax3)
plt.grid(which="both")
plt.xlabel("Sample #")
plt.ylabel("Damage (cumulative)")
ax4 = fig.add_subplot(gs[2, :])
sns.lineplot(x=np.arange(len(data)), y=data, ax=ax4)
plt.grid(which="both")
plt.xlabel("Sample #")
plt.ylabel("Value")
plt.show()

if __name__ == "__main__":
example_1()
Loading

0 comments on commit 9fb1bd9

Please sign in to comment.