🐥

plt3d

2023/09/10に公開
import pandas as pd
import matplotlib.pyplot as plt
from pathlib import Path
from mpl_toolkits.mplot3d import Axes3D


class SingleLotDataModel:
    def __init__(self, csvPath):
        self.timeFromStart = "TimeFromStart"
        self.timeFromPlane = "TimeFromPlane"
        self.timeFromLayer = "TimeFromLayer"
        self.intervalName = "INTERVAL"
        self.planeName = "SET CNT"
        self.layerName = "積層数(現)"
        self.__loadData(csvPath=csvPath)
        # print(self.dataFrame.head())
        self.__addTimeFromStart()
        self.__addTimeFromPlane()
        self.__addTimeFromLayer()

    def __loadData(self, csvPath):
        try:
            self.dataFrame = pd.read_csv(
                filepath_or_buffer=csvPath, header=0, encoding="shift-jis"
            )
            # print(self.dataFrame.head())
        except UnicodeDecodeError:
            print("encodingが正しくありません")
            raise
        except FileNotFoundError:
            print("Fileが見つかりません")
            raise
        except ValueError:
            print("Headerの指定が正しくありません")
            raise

    def __addTimeFromStart(self):
        self.dataFrame[self.timeFromStart] = self.dataFrame[
            self.intervalName
        ].cumsum()

    def __addTimeFromPlane(self):
        # planeNumber = self.dataFrame[self.planeName].max()
        # timeList = []
        # self.dataFrame["tempInterval"] = self.dataFrame[self.intervalName]
        # for i in range(1, planeNumber + 1):
        #     time = self.dataFrame.loc[
        #         self.dataFrame[self.planeName] == i, ["tempInterval"]
        #     ]
        #     time.iat[0, 0] = 0
        #     time = time.cumsum()
        #     timeList.append(time)
        # self.dataFrame[self.timeFromPlane] = pd.concat(timeList)
        # self.dataFrame.drop(columns="tempInterval")

        # pandasでgroupby計算
        self.dataFrame[self.timeFromPlane] = self.dataFrame.groupby(
            self.planeName
        )[self.timeFromStart].transform(lambda x: x - x.iloc[0])

        # print(self.dataFrame.head(30))

    def __addTimeFromLayer(self):
        self.dataFrame[self.timeFromLayer] = self.dataFrame.groupby(
            [self.planeName, self.layerName]
        )[self.timeFromStart].transform(lambda x: x - x.iloc[0])
        # print(self.dataFrame.head(30))

        # planeNumber = self.dataFrame[self.planeName].max()
        # timeList = []
        # self.dataFrame["tempInterval"] = self.dataFrame[self.intervalName]
        # for i in range(1, planeNumber + 1):
        #     layerNumber = self.dataFrame[self.layerName].max()
        #     for j in range(1, layerNumber + 1):
        #         time = self.dataFrame.loc[
        #             (self.dataFrame[self.planeName] == i)
        #             & (self.dataFrame[self.layerName] == j),
        #             ["tempInterval"],
        #         ]
        #         time.iat[0, 0] = 0
        #         time = time.cumsum()
        #         timeList.append(time)
        # self.dataFrame[self.timeFromLayer] = pd.concat(timeList)
        # self.dataFrame.drop(columns="tempInterval")

    def medianOfEveryLayer(self, sensorNameList):
        colmuns = [self.planeName, self.layerName] + sensorNameList
        data = self.dataFrame[colmuns]
        groupData = data.groupby([self.planeName, self.layerName]).median()
        return groupData


class DataModel:
    def __init__(self, folderPath, fileType):
        self.loadFolder(folderPath=folderPath, fileType=fileType)

    def loadFolder(self, folderPath, fileType):
        filesPath = folderPath.glob(fileType)
        # print(list(filesName))
        self.lotDataList: SingleLotDataModel = []
        if fileType == "*.csv":
            for filePath in filesPath:
                self.lotDataList.append(SingleLotDataModel(csvPath=filePath))

    def showMedianOfEveryLayerBySensor(self, lot, sensorNameList):
        figure = plt.figure()
        # graph = Axes3D(figure)
        figure.add_subplot(1, 1, 1)
        groupDataFrame = lot.medianOfEveryLayer(sensorNameList=sensorNameList)
        # print(groupDataFrame.reset_index(inplace=True))
        # print(dataFrame)
        graphList = []
        for i, sensor in enumerate(sensorNameList, start=1):
            graphList.append(
                figure.add_subplot(len(sensorNameList), 1, i, projection="3d")
            )
            for index, row in groupDataFrame.groupby(level=lot.planeName):
                row.reset_index(inplace=True)
                x = row[lot.planeName]
                y = row[lot.layerName]
                z = row[sensor]
                graphList[-1].plot(x, y, z)
        figure.subplots_adjust(right=0.8)
        plt.show()
        plt.close()

    def showPlotSelectedLayerByLot(
        self, sensorNameList, planeNumber=1, layerNumber=1
    ):
        figure = plt.figure()
        graphList = []
        minValue = float("inf")
        maxValue = -float("inf")

        for i, lotData in enumerate(self.lotDataList, start=1):
            selectedLayer = lotData.dataFrame.loc[
                (lotData.dataFrame[lotData.planeName] == planeNumber)
                & (lotData.dataFrame[lotData.layerName] == layerNumber)
            ]
            time = selectedLayer[lotData.timeFromLayer]
            selectedSensor = selectedLayer[sensorNameList]
            graphList.append(figure.add_subplot(len(self.lotDataList), 1, i))
            maxValue = (
                selectedSensor.max().max()
                if maxValue < selectedSensor.max().max()
                else maxValue
            )
            minValue = (
                selectedSensor.min().min()
                if minValue > selectedSensor.min().min()
                else minValue
            )
            for colmun in selectedSensor.columns:
                graphList[-1].plot(time, selectedSensor[colmun], label=colmun)
            graphList[-1].legend(
                title="Sensors", loc="upper left", bbox_to_anchor=(1, 1)
            )
            for graph in graphList:
                graph.set_ylim(
                    minValue * 1.1 if minValue < 0 else minValue * 0.9,
                    maxValue * 1.1 if maxValue > 0 else maxValue * 0.9,
                )
                # graph.set_yticks(
                # )
        figure.subplots_adjust(right=0.8)
        plt.show()
        plt.close()


if __name__ == "__main__":
    homePath = Path.home()
    folderPath = homePath / Path(r"Downloads/sampleCSV2")
    fileType = "*.csv"
    sensorNameList = ["Sensor1", "Sensor2", "Sensor3", "Sensor4"]
    dataModel = DataModel(folderPath=folderPath, fileType=fileType)
    # print(dataModel.lotDataList[0].dataFrame["TimeFromLayer"].head(30))
    # dataModel.showPlotSelectedLayerByLot(
    #     sensorNameList=sensorNameList, planeNumber=1, layerNumber=2
    # )

    dataModel.showMedianOfEveryLayerBySensor(
        lot=dataModel.lotDataList[0], sensorNameList=sensorNameList
    )

    # dataModel.lotDataList[0].showMedianOfEveryLayer(
    #     sensorNameList=sensorNameList
    # )

Discussion