Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Preprosessering

Authors
Affiliations
SINTEF Energi
SINTEF Energi
SINTEF Energi

Fra TK-data til intervallsensurert data

For å kunne bruke tidsserier av TK-data til å estimere oppholdstider i de ulike TKene, må dataene tilpasses modellen som benyttes. Siden TKer kun registreres ved inspeksjoner, er overgangstidspunktet mellom to TKer ikke kjent eksakt. Man vet bare at overgangen har skjedd mellom to inspeksjoner, noe som gir intervalsensurerte data. Kode for å gjøre om tidsserier av TK-data til intervallsensurert data er demonstrert under.

MERK: Denne metoden krever at data stiger monotont, det vil si, TK-serien kan ikke innneholde overganger fra høyere TK til lavere TK. I virkeligheten vil slike overganger kunne finnes i TK-data på grunn av støy og/eller måleusikkerhet. Vi ser på måter å behandle dette lengre ned.

Source
# importer nødvendige python-moduler
import numpy as np
import matplotlib.pyplot as plt
%config InlineBackend.figure_format = 'retina'
import matplotlib as mpl
mpl.rcParams.update({
    "figure.facecolor": "none",
    "axes.facecolor": "none",
    "savefig.facecolor": "none",})
Fontconfig error: No writable cache directories

Anta at du har en serie av TKer og tilsvarende serie tt som angir tidspunkt for inspeksjon. Vi skriver om serien på formatet (TKforrige_{\rm{forrige}}, TKna˚_{\rm{nå}}, dt)

TK_raw = [1,1,1,2,2,2,3,4]
t = [0,8,10,12,19,25,28,29] # 0:1990

fig = plt.figure(figsize=(4,3))
plt.plot([i+1990 for i in t],TK_raw,'-o');
plt.xlabel('Tid (år)');plt.ylabel('TK');plt.grid();plt.title('Kaplan turbin')
plt.show()

trans = [
    (TK_raw[i-1],
     TK_raw[i],
     t[i] - t[i-1])
    for i in range(1, len(TK_raw))
]
print(f'TK transisjoner og tidsdifferanse: {trans}')
<Figure size 400x300 with 1 Axes>
TK transisjoner og tidsdifferanse: [(1, 1, 8), (1, 1, 2), (1, 2, 2), (2, 2, 7), (2, 2, 6), (2, 3, 3), (3, 4, 1)]

Deretter definerer vi en funksjon som regner ut minimum og maksimum oppholdstid i hver karakter.

def state_intervals(trans, absorbing_state=5):
    """
    trans: list of (state_prev, state_now, dt)

    returns:
        list of (state, tmin, tmax)

    Håndterer:
    - intervallsensurering
    - hopp over tilstander (f.eks. TK1 -> TK3)
    - høyresensurering av siste tilstand
    - absorberende sluttilstand (f.eks. TK5)
    """

    result = []
    time_in_state = 0

    for prev_state, curr_state, dt in trans:

        if prev_state == curr_state:

            time_in_state += dt

        else:

            # Tilstanden som forlates
            result.append(
                (
                    prev_state,
                    time_in_state,
                    time_in_state + dt
                )
            )

            # Eventuelle tilstander som hoppes over
            for state in range(prev_state + 1, curr_state):

                result.append(
                    (
                        state,
                        0,
                        dt
                    )
                )

            time_in_state = 0

    # Siste observerte tilstand
    last_state = trans[-1][1]

    # Ikke modeller oppholdstid i absorberende tilstand
    if last_state != absorbing_state:

        result.append(
            (
                last_state,
                0,
                np.inf
            )
        )

    return result
interval = state_intervals(trans)
print(f'min og max oppholdstid per TK: {interval}')
min og max oppholdstid per TK: [(1, 10, 12), (2, 13, 16), (3, 0, 1), (4, 0, inf)]

Dersom man har flere serier av TK-data kan man repetere prosessen og få ut en liste av minimum og maksimum oppholdstid per TK.

Source
TK_raw1 = [1,1,1,2,2,2,3,4]
TK_raw2 = [1,1,1,1,1,1,1,3]
TK_raw3 = [1,1,2,2,3,3,4,5]
t = [0,8,10,12,19,25,28,29]

TK_raw_all = [TK_raw1, TK_raw2, TK_raw3]

fig = plt.figure(figsize=(4,3))
for k in range(3):
    plt.plot([i+1990 for i in t],TK_raw_all[k],'-o',label=f'Kaplan {k+1}');
plt.xlabel('Tid (år)');plt.ylabel('TK');plt.grid();plt.legend();
plt.show()

all_intervals = []
for k, TK_raw in enumerate(TK_raw_all):
    trans = [
        (
            TK_raw[i-1],
            TK_raw[i],
            t[i] - t[i-1]
        )
        for i in range(1, len(TK_raw))
    ]

    intervals = state_intervals(trans)
    print(f"Intervaller for serie {k+1}: {intervals}")
    all_intervals.extend(intervals)

# Finn hvilke TK-er som finnes
states = sorted(set(state for state, _, _ in all_intervals))

# Opprett min/max-arrays per TK
minT = {state: [] for state in states}
maxT = {state: [] for state in states}

for state, tmin, tmax in all_intervals:
    minT[state].append(tmin)
    maxT[state].append(tmax)

print("\nIntervallsensurerte data per TK:")

for state in states:
    print(f"\nTK {state}")
    print("minT =", minT[state])
    print("maxT =", maxT[state])
<Figure size 400x300 with 1 Axes>
Intervaller for serie 1: [(1, 10, 12), (2, 13, 16), (3, 0, 1), (4, 0, inf)]
Intervaller for serie 2: [(1, 28, 29), (2, 0, 1), (3, 0, inf)]
Intervaller for serie 3: [(1, 8, 10), (2, 2, 9), (3, 6, 9), (4, 0, 1)]

Intervallsensurerte data per TK:

TK 1
minT = [10, 28, 8]
maxT = [12, 29, 10]

TK 2
minT = [13, 0, 2]
maxT = [16, 1, 9]

TK 3
minT = [0, 0, 6]
maxT = [1, inf, 9]

TK 4
minT = [0, 0]
maxT = [inf, 1]

Filtrering av støy fra TK-data

Dersom støy og/eller måleusikkerhet fører til en ikke-monotont stigende TK-trend, må vi behandle dataen før vi bruker koden beskrevet over. Dette kan gjøres ved å bruke filtre som jevner ut trenden. Her bruker vi isoton regresjon, en metode som finner kurven som ligger nærmest de observerte TKene i minste kvadraters forstand. Metoden endrer data så lite som mulig, men fjerner alle brudd på monotoni.

MERK: Registrerte overganger fra høyere til lavere TK kan være et resultat av “normalt vedlikehold”. Vi anser dette som vedlikeholdoppgaver som må gjøres for å holde komponenten i drift (utbedring av oljelekkasje, smøring av lager osv), men som ikke direkte påvirker komponentens levetid. Ved å filtrere bort denne type data antar vi dermed at vi ikke mister informasjon om levetid. Eksempler som demonstrerer effekten av isoton regresjon er vist under:

Source
from sklearn.isotonic import IsotonicRegression
TK_non_monotone = [1,1,1,2,1,1,2,2]

iso = IsotonicRegression(y_min=1, y_max=5,increasing=True)
TK_monotone = iso.fit_transform(t, TK_non_monotone)
TK_int = np.round(TK_monotone).astype(int) # make integer
TK_int = np.maximum.accumulate(TK_int)

fig = plt.figure(figsize=(4,3))
plt.plot([2002],[2],'r^',markersize=12,label='oljelekkasje oppdaget')
plt.plot([i+1990 for i in t],TK_non_monotone,'--ko',label='TK ved inspeksjon');
plt.plot([i+1990 for i in t],TK_int,'-m',label='Filtrert');
plt.ylim([0,4]);plt.yticks(range(5));
plt.xlabel('Tid (år)');plt.ylabel('TK');plt.grid();plt.legend();
plt.show()
<Figure size 400x300 with 1 Axes>
Source
TK_non_monotone = [1,1,1,3,3,1,1,3]

iso = IsotonicRegression(y_min=1, y_max=5,increasing=True)
TK_monotone = iso.fit_transform(t, TK_non_monotone)
TK_int = np.round(TK_monotone).astype(int) # make integer
TK_int = np.maximum.accumulate(TK_int)

fig = plt.figure(figsize=(4,3))
#plt.plot([2002],[2],'r^',markersize=12,label='oljelekkasje 2002')
plt.plot([i+1990 for i in t],TK_non_monotone,'--ko',label='TK ved inspeksjon');
plt.plot([i+1990 for i in t],TK_int,'-m',label='Filtrert');
plt.ylim([0,4]);plt.yticks(range(5));
plt.xlabel('Tid (år)');plt.ylabel('TK');plt.grid();plt.legend();
plt.show()
<Figure size 400x300 with 1 Axes>
Source
TK_non_monotone = [1,1,2,1,1,2,3,2]

iso = IsotonicRegression(y_min=1, y_max=5,increasing=True)
TK_monotone = iso.fit_transform(t, TK_non_monotone)
TK_int = np.round(TK_monotone).astype(int) # make integer
TK_int = np.maximum.accumulate(TK_int)

fig = plt.figure(figsize=(4,3))
#plt.plot([2002],[2],'r^',markersize=12,label='oljelekkasje 2002')
plt.plot([i+1990 for i in t],TK_non_monotone,'--ko',label='TK ved inspeksjon');
plt.plot([i+1990 for i in t],TK_int,'-m',label='Filtrert');
plt.ylim([0,4]);plt.yticks(range(5));
plt.xlabel('Tid (år)');plt.ylabel('TK');plt.grid();plt.legend();
plt.show()
<Figure size 400x300 with 1 Axes>