{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":66052,"databundleVersionId":7284431,"sourceType":"competition"}],"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"#### Manual labeling tool\nIn order to get a first robust understanding of anomalies in the test set, we wrote a quick Python tool to be able to manually label the test data and therefore, get a first impression of the anomalies in the test set. \n##### How the tool works\nThe tool iterates through all test segments and plots selected features in different subplots. For each test segment, one window will be opened sequentially. \nIn each window, there are three subplots in which ranges can be selected. The selected ranges will be interpreted as anomalies. The last chart highlights which segments have been marked as anomalies in the test segment. When a window is closed, the anomalies are saved.\nAfter the last test segment all anomalies are written to a file 'anomalies.csv'. <br>\nHint: To cancel an execution, use STRG+C in the terminal instead of closing all windows one after another.\n##### How to test labeling\nThe output file 'anomalies.csv' can be directly submitted in Kaggle to get feedback on the labeled anomalies.\n##### Caveat\nThe tool relies on a graphical user interface and therefore does not work in Jupyter Notebooks. Please copy the code and run it on a local Python runtime that supports matplotlib backends using interactive frameworks.","metadata":{}},{"cell_type":"code","source":"# CAVEAT\n# The tool relies on a graphical user interfaces and\n# therefore does not work in Jupyter Notebooks\n# Please copy the code and run it on a local python runtime\n\nimport pandas as pd\nimport matplotlib.pyplot as plt\nfrom matplotlib.widgets import SpanSelector\nimport numpy as np\nfrom matplotlib.widgets import Button\n\n# available feature test data\n\"\"\"\n'id', 'Datum_Uhrzeit_CET', \n'Demand', 'correction', 'correctionEcho', 'correctedDemand', 'FRCE', \n'controlBandPos', 'controlBandNeg', \n'LFCInput', 'aFRRactivation', 'aFRRrequest', \n'participationCMO', 'participationIN',\n'BandLimitedCorrectedDemand', \n'controlArea'\n\"\"\"\n# Choose which features to show in graphs:\ncolumns_chart_1=['correction', 'correctionEcho']\ncolumns_chart_2=['aFRRactivation', 'aFRRrequest', 'correctedDemand']\ncolumns_chart_3=[\"FRCE\",'LFCInput', 'Demand']\nall_columns = list(set(columns_chart_1+columns_chart_2+columns_chart_3))\n\n# Control variable if each segment individually should be written to csv\nprint_labels_per_segment=True\n\n# read in test data - the file location and file name might needs to be adjusted\ntest_data_raw = pd.read_csv(\"test.csv\")\ntest_data_raw[\"anomaly\"] = 0\ntest_data_raw['calc_demand'] = test_data_raw['correctedDemand'] - test_data_raw['correction']\nresult = pd.DataFrame(columns=[\"id\",\"anomaly\"])\nsegment_count = 1\nmax_segments = len(test_data_raw[\"test_data_segment_id\"].unique())\n\nfor segment in test_data_raw[\"test_data_segment_id\"].unique():\n\n    test_segment= test_data_raw[test_data_raw[\"test_data_segment_id\"]==segment].copy()\n    test_segment = test_segment.reset_index(drop=True)\n    fig, (ax1, ax2, ax3, ax_label) = plt.subplots(4, figsize=(16, 2))\n    fig.suptitle(f'Segment {segment}: {segment_count}/{max_segments}', fontsize=16)\n    ax1.plot(test_segment['Datum_Uhrzeit_CET'], test_segment[columns_chart_1], label=columns_chart_1)\n    ax2.plot(test_segment['Datum_Uhrzeit_CET'], test_segment[columns_chart_2], label=columns_chart_2)\n    ax3.plot(test_segment['Datum_Uhrzeit_CET'], test_segment[columns_chart_3], label=columns_chart_3)\n    ax1.legend(loc='center left', bbox_to_anchor=(1, 0.5))\n    ax2.legend(loc='center left', bbox_to_anchor=(1, 0.5))\n    ax3.legend(loc='center left', bbox_to_anchor=(1, 0.5))\n    ax1.set_title('Select intervals in the first two graphs. Control in 3')\n    \n    ax_label.plot(\n        test_segment['Datum_Uhrzeit_CET'], \n        test_segment[all_columns], \n        label=all_columns\n    )\n    ax_label.legend(loc='center left', bbox_to_anchor=(1, 0.5))\n\n    aspan_list = []\n    def onselect(xmin, xmax):\n        print(xmin)\n        print(xmax)\n        indmin = max(0,int(xmin))\n        indmax = int(xmax)\n        indmax = min(len(test_segment) - 1, indmax)\n\n        region_x = test_segment[indmin:indmax]\n        test_segment.loc[indmin:indmax,\"anomaly\"] = 1\n        print(test_segment[indmin:indmax][[\"id\",\"anomaly\"]])\n\n        if len(region_x) >= 2:\n            fig.canvas.draw_idle()\n            start = test_segment.iloc[indmin][\"Datum_Uhrzeit_CET\"]\n            end = test_segment.iloc[indmax][\"Datum_Uhrzeit_CET\"]\n            aspan_list.append(ax_label.axvspan(start, end, facecolor='green', alpha=0.3))\n\n    def _delete(event):\n        test_segment[\"anomaly\"] = 0\n        print(aspan_list)\n        for aspan in aspan_list:\n            aspan.remove()\n    \n    span = SpanSelector(\n        ax1,\n        onselect,\n        \"horizontal\",\n        useblit=True,\n        props=dict(alpha=0.5, facecolor=\"tab:blue\"),\n        interactive=True,\n        drag_from_anywhere=False\n    )\n    span2 = SpanSelector(\n        ax2,\n        onselect,\n        \"horizontal\",\n        useblit=True,\n        props=dict(alpha=0.5, facecolor=\"tab:blue\"),\n        interactive=True,\n        drag_from_anywhere=False\n    )\n    span3 = SpanSelector(\n        ax3,\n        onselect,\n        \"horizontal\",\n        useblit=True,\n        props=dict(alpha=0.5, facecolor=\"tab:blue\"),\n        interactive=True,\n        drag_from_anywhere=False\n    )\n\n    axcut = fig.add_axes([0.9, 0.0, 0.1, 0.075])\n    bcut = Button(axcut, 'delete selection', color='red', hovercolor='green')\n    bcut.on_clicked(_delete)\n    plt.subplots_adjust(left=0.05, right=0.85)\n    plt.show()\n    if print_labels_per_segment:\n        test_segment[[\"id\",\"anomaly\"]].to_csv(f\"segment_{segment}_anomaly.csv\", index=False)\n    result = pd.concat([result, test_segment[[\"id\",\"anomaly\"]]], ignore_index=True)\n    segment_count += 1\nresult.to_csv(\"anomaly.csv\", index=False)\n","metadata":{},"execution_count":null,"outputs":[]}]}