Dieses Dokument beschreibt den Prozess der Datenaufbereitung vom Laden aus der MongoDB bis zum exportieren der Trainingsdatensätze als csv.
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from datetime import datetime, timedelta
import copy
import importbib
Als erstes werden die Daten für einen bestimmten Zeitabschnitt über die Funktion loadTimeframeFromMongoDB heruntergeladen. Start- und Endzeitpunkt des Reibvorgans müssen in etwa bekannt sein. Der angegebene Zeitrahmen muss größer gewählt werden, sodass auf jeden Fall alle Reibdaten enthalten sind. Achtung: Während dem Download muss der entsprechende Rechner im VPN der Hochschule sein.
dtStart = datetime(2019,11,26,12,0)
dtEnd = datetime(2019,11,26,23,59)
dfTimeFrame = importbib.loadTimeframeFromMongoDB(dtStart,dtEnd)
dfTimeFrame.to_csv("csv_Files/2019-11-26_VALUES_EXPORT.csv", index=False, sep=",", encoding="utf-8")
Bereits heruntergeladene Daten können über die normale Pandasfunktion read_csv gelesen werden. Timestampfelder müssen dann aber noch umgewandelt werden:
dfTimeFrame = pd.read_csv("csv_Files/2019-11-26_VALUES_EXPORT.csv", encoding="utf-8")
dfTimeFrame.timeStamp = pd.to_datetime(dfTimeFrame.timeStamp)
dfTimeFrame.dtypes
Zur visuellen Kontrolle können die Daten der Z-Achse, und die Logdaten weiterer Komponenten geplottet werden. Dazu steht die Hilfsfunktion plotSpecificIDs bereit:
importbib.plotActualZ1(dfTimeFrame, saveFile=False)
In diesem Zeitabschnitt sind neben dem Reiben auch bohren und entgraten zu sehen. Um diesen Vorgang eindeutig von den Anderen unterscheiden zu können, benötigen wir die Daten aus MongoDB-Collection values_ncprogram. Mithilfe der importbib können diese einfach von der MongoDB geladen werden. Achtung: Während dem Download muss der entsprechende Rechner im VPN der Hochschule sein.
dtStart = datetime(2019,11,26,12,0)
dtEnd = datetime(2019,11,26,23,59)
dfReibdaten = importbib.loadReibdatenFromMongoDB(dtStart,dtEnd)
dfReibdaten.to_csv("csv_Files/2019-11-26_NCPROGRAM_EXPORT.csv", index=False, sep=",", encoding="utf-8")
dfReibdaten.head()
Plottet man nun Z-Achsendaten und Reibdaten in den gleichen Plot, so sieht man, wann die Reibe aktiv war:
fig = plt.figure(figsize=(15, 5), dpi=80)
zAxisData = dfTimeFrame.loc[lambda l: l['ValueID'] == "12430012063.Z1_Axis.Actual_Position_MCS",:]
plt.plot(zAxisData.timeStamp,zAxisData.value)
plt.scatter(dfReibdaten.timeStamp,[-100]*len(dfReibdaten), s=1.0,c='r')
Wir speichern diesen Bereich des Datensatzes nun in einem einem eigenen DataFrame ab. Dafür existiert die Funktion approxRangeInSteps, die einen kleinen Zeitraum innerhalb des Vorgangs entgegennimmt (hier z.b. 12:55 Uhr - 13 Uhr, der Samplezeitraum), minimum und maximum des Z-Achsenwertes misst, und dann versucht, den größten Bereich zu finden, in dem der Z-Achsenwert diese Werte nicht unter- bzw. überschreitet.
dtSampleStart = datetime(2019,11,26,12,55)
dtSampleEnd = datetime(2019,11,26,13,0)
dtNewStart,dtNewEnd = importbib.approxRangeInSteps(dfTimeFrame,dtSampleStart,dtSampleEnd)
print(str(dtNewStart))
print(str(dtNewEnd))
dfEineEbene = dfTimeFrame.loc[lambda l: ((dtNewStart <= l.timeStamp) & (l.timeStamp <= dtNewEnd)),:]
importbib.plotActualZ1(dfEineEbene, saveFile=False)
Nun müssen die Daten nach den einzelnen Löcher getrennt werden. Hierfür werden die höchsten Z-Achsenwerte hergenommen:
top = dfEineEbene.loc[lambda l: l.ValueID == "12430012063.Z1_Axis.Actual_Position_MCS","value"].max()
tolerance = 5.0
topMostPoints = dfEineEbene.loc[lambda l: ((l.ValueID == "12430012063.Z1_Axis.Actual_Position_MCS") & (top-tolerance < l.value) & (l.value < top+tolerance)),:]
fig = plt.figure(figsize=(15, 5), dpi=80)
zAxisEineEbene = dfEineEbene.loc[lambda l: l.ValueID == "12430012063.Z1_Axis.Actual_Position_MCS",:]
plt.plot(zAxisEineEbene.timeStamp,zAxisEineEbene.value, c='b')
plt.scatter(zAxisEineEbene.timeStamp,zAxisEineEbene.value,c='r',s=1)
plt.scatter(topMostPoints["timeStamp"], topMostPoints["value"], c='r',s=30)
plt.legend(["12430012063.Z1_Axis.Actual_Position_MCS","12430012063.Z1_Axis.Actual_Position_MCS", "max"])
plt.show()
print("Anzahl der gefundenen Spitzen: "+str(len(topMostPoints)))
Aus dem Diagramm folgt: Wir möchten am Ende 81 Spitzen gefunden haben (9x9 Löcher). Zusammen mit dem Start können wir so 81 Datensätze aggregieren. Genau eine Spitze pro Loch zu finden erfordert nun verschiedene Versuche, die auch variieren können:
# Versuch über die Steigung: ist die Steigung links des Punktes positiv, und rechts davon negativ, so handelt es sich um eine Spitze
dfTops = pd.DataFrame()
for i in range(1,zAxisEineEbene.shape[0]-1):
diff1 = zAxisEineEbene.iloc[i].value - zAxisEineEbene.iloc[i-1].value # muss positiv sein
diff2 = zAxisEineEbene.iloc[i].value - zAxisEineEbene.iloc[i+1].value # muss auch positiv sein
if diff1 > 0 and diff2 > 0:
dfTops = dfTops.append(zAxisEineEbene.iloc[i])
print(len(dfTops))
fig = plt.figure(figsize=(15, 5), dpi=80)
zAxisEineEbene = dfEineEbene.loc[lambda l: l.ValueID == "12430012063.Z1_Axis.Actual_Position_MCS",:]
plt.plot(zAxisEineEbene.timeStamp,zAxisEineEbene.value, c='b')
plt.scatter(zAxisEineEbene.timeStamp,zAxisEineEbene.value,c='r',s=1)
plt.scatter(dfTops.timeStamp, dfTops.value, c='r',s=30)
plt.legend(["12430012063.Z1_Axis.Actual_Position_MCS","12430012063.Z1_Axis.Actual_Position_MCS", "max"])
plt.show()
Der letzte und der erste Punkt müssen manuell hinzugefügt werden
dfTops = dfTops.append(zAxisEineEbene.iloc[0])
dfTops = dfTops.append(zAxisEineEbene.iloc[-1])
dfTops = dfTops.sort_values(by="timeStamp")
plt.plot(dfTops.timeStamp)
plt.show()
print(len(dfTops))
Nachdem nun die Korrekte Anzahl an Löchern gefunden wurde, und die Timestamps entsprechend sortiert sind, kann eine Schleife die Daten Pro Loch generieren. Dieser Algorithmus kann noch erweitert werden, je nach dem, welche Daten erfasst werden sollen. Anschließend wird eine Label-Spalte hinzugefügt, die im nächsten Schritt befüllt wird.
ls = []
for start,end in zip(dfTops.iloc[:-1,:].timeStamp,dfTops.iloc[1:,:].timeStamp):
curData = dfTimeFrame.loc[lambda l: ((start <= l.timeStamp) & (l.timeStamp <= end)),["ValueID","value","timeStamp"]]
curData = curData.groupby(by="ValueID", as_index=False).mean().T
curData.columns = curData.iloc[0]
curData.drop(curData.index[0], inplace=True)
curData["timeStamp"] = start
ls.append(curData)
dfData = pd.concat(ls, ignore_index=True, sort=False)
dfData.sort_values(by=["timeStamp"], inplace=True)
dfData["Label"] = "-"
dfData.head()
Nun muss das entsprechende Messprotokoll geladen und die eingereichtete Spalte damit befüllt werden.
Das zugehörige Messprotokoll wird mittels "importbib.importMeasurementData('csv_Files/MEAS_PROTOCOL_CSV_E1.CSV')" eingelesen und in ein Pandas-Dataframe geschrieben. Hierbei muss beachtet werden, dass das Messprotokoll zur richtigen Ebene geladen wird, da die Timestamps nicht übereinstimmen, weil die Messung zeitlich versetzt stattfindet.
# Einlesen der Daten des Messprotokolls
dfMeas = importbib.importMeasurementData('csv_Files/MEAS_PROTOCOL_CSV_E1.CSV')
dfMeas.head(-1)
In der Spalte "Difference" ist das Messergebnis des Lochs. Die dazugehörigen Daten liegen in sehr ungeordneter Weise vor. Wir haben Spalten, die mehrere Leerzeichen und ungünstig formatierte Strings beinhalten. Diese Spalten müssen wir für die Auswertung erst aufbereiten.
Achtung: Die nachfolgenden Zellen immer nur einmal ausführen. Sonst stimmt das Ausgangs-DataFrame nicht mehr. Bei mehrmaliger Ausführung neues Dataframe laden.
# Transformation des Pandas-Dataframe zur List und Umwandlung der Strings in Floats
dfMeas = importbib.transformStringListToFloatList(dfMeas, 'Setpoint')
dfMeas = importbib.transformStringListToFloatList(dfMeas, 'Measured')
dfMeas = importbib.transformStringListToFloatList(dfMeas, 'Difference')
# Serialisierung der Daten in eine CSV-Datei
dfMeas.to_csv("csv_Files/MEAS_PROTOCOL_CSV_E1_TRAININGDATA.csv",index=False,encoding="utf-8")
listMeas_setPoint = dfMeas['Setpoint']
# Separierung der Setpoint-Werte
listMeas_setPointX = listMeas_setPoint[0::3]
listMeas_setPointY = listMeas_setPoint[1::3]
listMeas_setPointDia = listMeas_setPoint[2::3]
# Plotten der Messpunkte
plt.scatter(listMeas_setPointX, listMeas_setPointY)
plt.show()
Wie gut zu sehen ist, entsteht ein klares Raster der Messpunkte. Mit den Maschinendaten zusammen bildet sich ein umfassendes Gesamtbild der gewonnenen Daten.
Im letzten Schritt werden noch die Achsleistungdaten aufbereitet und versucht in Verbindung mit dem restlichen Daten zu bringen.
# Einlesen der Daten der Achsleistung
dfAchs = importbib.importAchsleistungsData('csv_Files/Achsleistung-2019-11-20T10-27-03_E1.csv')
dfAchs.head(10)
dfData.to_csv("csv_Files/data_2019-26-11_TRAININGDATA.csv",index=False,encoding="utf-8")