iamlikeme / rainflow

Implementation of the rainflow-counting algorythm in Python
MIT License
105 stars 34 forks source link

Runtime error: Stop Iteration #27

Closed capnjess closed 4 years ago

capnjess commented 4 years ago

Hi Piotr,

Thanks for your work with this excellent package. I ran into this error while using this package on a time series of about 3 million entries. I changed the 'yield' parts of the code to have

except StopIteration: return However this did not seem to work. I know this might b more of a stackoverflow question but I was wondering if you knew any quickfix.

Many thanks

iamlikeme commented 4 years ago

Hi, can you provide a code snipped that caused the error and the traceback (i.e. the full error message printed by python)?

capnjess commented 4 years ago

This is the code :

from collections import defaultdict counts = defaultdict(float) for low, high, mult in rf.extract_cycles(Hookload_p1, left = 'TRUE', right ='TRUE'): mean = 0.5 * (high + low)
rng = high - low
counts[(mean, rng)] += mult

Y_rfc = pd.DataFrame([(k[0], k[1], v) for k, v in counts.items()], columns = ['Mean', 'Range', 'Cycle'])

This is the error:

from collections import defaultdict counts = defaultdict(float) for low, high, mult in rf.extract_cycles(Hookload_p1, left = 'TRUE', right ='TRUE'): mean = 0.5 * (high + low)
rng = high - low
counts[(mean, rng)] += mult

Y_rfc = pd.DataFrame([(k[0], k[1], v) for k, v in counts.items()], columns = ['Mean', 'Range', 'Cycle']) Traceback (most recent call last):

File "", line 3, in for low, high, mult in rf.extract_cycles(Hookload_p1, left = 'TRUE', right ='TRUE'):

File "C:\Users\Public\Anaconda3\lib\site-packages\rainflow.py", line 69, in wrapper for low, high, mult in func(*args, **kwargs):

File "C:\Users\Public\Anaconda3\lib\site-packages\rainflow.py", line 98, in extract_cycles for x in reversals(series, left=left, right=right):

RuntimeError: generator raised StopIteration

iamlikeme commented 4 years ago

What is the type of Hookload_p1?

capnjess commented 4 years ago

Hookload_p1 is a float64

iamlikeme commented 4 years ago

I meant to ask what is the type of Hookload_p1 itself, not the types of its values. It must be some sort of iterable. I suspect Hookload_p1 is a generator and it has an implementation error. The RuntimeError you mention happens in cases like this:

def gen(n):
    for i in range(n):
        yield 10 * i
    raise StopIteration  # This line will cause an error

list(gen(5))
# RuntimeError: generator raised StopIteration
capnjess commented 4 years ago

I meant to ask what is the type of Hookload_p1 itself, not the types of its values. It must be some sort of iterable. I suspect Hookload_p1 is a generator and it has an implementation error. The RuntimeError you mention happens in cases like this:

def gen(n):
    for i in range(n):
        yield 10 * i
    raise StopIteration  # This line will cause an error

list(gen(5))
# RuntimeError: generator raised StopIteration

Hookload_p1 is a time series of load values from a structural crane member. The values vary from 50t to 300/400 t and this occurs randomly.

iamlikeme commented 4 years ago

What do you see when you type type(Hookload_p1) in a Python console?

capnjess commented 4 years ago

Hi,

It shows "pandas.core.frame.DataFrame"

iamlikeme commented 4 years ago

I see what causes the problem now. Function rainflow.extract_cycles expects its first argument to be a sequence of numbers, but a pandas DataFrame is not a sequence of numbers. If you iterate over a DataFrame you get the list of column names, e.g.:

# Create a dataframe with one column called "load"
df = pd.DataFrame.from_dict({"load": [0, -2, 1, -3, 5, -1, 3, -4, 4, -2, 0]})                                                                 

type(df)                                                               
# pandas.core.frame.DataFrame

for item in df: 
    print(item) 
# load

list(rainflow.extract_cycles(df))
# RuntimeError: generator raised StopIteration

The correct usage is to pass a specific column from the DataFrame to extract_cycles:

list(rainflow.extract_cycles(df.load))
# [(-2, 1, 0.5),
#  (-3, 1, 0.5),
#  (-1, 3, 1.0),
#  (-3, 5, 0.5),
#  (-4, 5, 0.5),
#  (-4, 4, 0.5),
#  (-2, 4, 0.5)]