{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "import numpy as np\n", "import os, sys, json, argparse\n", "import sumolib, traci\n", "from tqdm import tqdm\n", "from datetime import datetime\n", "path_root = os.path.dirname(os.path.dirname(os.path.abspath('.')))" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "class SignalGenerator:\n", " pass\n", "self = SignalGenerator()\n", "self.config_name = 'test_0729'\n", "self.file_net = 'new_sungnam_network_internal_target_0721.net.xml'\n", "self.month = 7\n", "self.day = 29\n", "self.hour = 9\n", "self.minute = 25" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "# 루트폴더 지정\n", "self.path_root = path_root\n", "with open(os.path.join(self.path_root, 'configs', f'config_{self.config_name}.json'), 'r') as config_file:\n", " config = json.load(config_file)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "# 주요 폴더 경로 지정\n", "self.paths = config['paths']\n", "self.path_data = os.path.join(self.path_root, *self.paths['data'])\n", "self.path_intermediates = os.path.join(self.path_root, *self.paths['intermediates'])\n", "self.path_results = os.path.join(self.path_root, *self.paths['results'])\n", "self.path_tables = os.path.join(self.path_root, *self.paths['tables'])\n", "self.path_networks = os.path.join(self.path_root, *self.paths['networks'])\n", "self.path_scripts = os.path.join(self.path_root, *self.paths['scripts'])\n", "\n", "# 이슈사항 목록\n", "self.issues = []" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "c:\\github\\siggen\\test_0729\\data\\tables\n" ] } ], "source": [ "print(self.path_tables)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "self.midnight = int(datetime(2024, self.month, self.day, 0, 0, 0).timestamp())\n", "self.next_day = int(datetime(2024, self.month, self.day+1, 0, 0, 0).timestamp())\n", "self.fsecs = range(self.midnight, self.next_day, 5) # fsecs : unix time by Five SECondS\n", "self.fmins = range(self.midnight, self.next_day, 300) # fmins : unix time by Five MINuteS\n", "\n", "self.present_time = int(datetime(2024, self.month, self.day, self.hour, self.minute).timestamp())\n", "self.present_time = max([fmin for fmin in list(self.fmins) if fmin <= self.present_time])\n", "\n", "self.sim_timespan = 300\n", "self.adder = 600 # 10분 : '현재시점 + 10분'에 가상신호를 생성하기 위함.\n", "self.subtractor = 1800 # 30분 : '현재시점 - 30분'의 신호이력을 가져온다." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "# 1-1. 네트워크 불러오기\n", "self.net = sumolib.net.readNet(os.path.join(self.path_networks, self.file_net))" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "# cnames = []\n", "# cnames.extend(list(self.inter_info))\n", "# cnames.extend(list(self.plan))\n", "# cnames.extend(list(self.history))\n", "# cnames.extend(list(self.inter_node))\n", "# cnames.extend(list(self.matching))\n", "# cnames.extend(list(self.match1))\n", "# cnames.extend(list(self.match6))\n", "# sorted(set(cnames))" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "# 1-2. 테이블 불러오기\n", "# 모든 컬럼에 대하여 데이터타입 지정\n", "loading_dtype_1 = {\n", " 'CRSRD_ID':int, 'FRST_REG_DT':str, 'LAST_MDFCN_DT':str,\n", " 'OCRN_DT':str, 'cycle':int, 'group_no':str,\n", " 'hh':int, 'inc_edge_id':str, 'inter_lat':float,\n", " 'inter_lon':float, 'inter_name':str, 'inter_no':int,\n", " 'inter_type':str, 'main_phase_no':str,'mm':int,\n", " 'move_A':int, 'move_B':int, 'move_no':int,\n", " 'node_id':str, 'offset':int, 'out_edge_id':str,\n", " 'phas_A':int, 'phas_B':int, 'phase_no':int,\n", " 'plan_no':int, 'ring_type':str, 'state':str,\n", " 'turn_type':str\n", " }\n", "loading_dtype_2 = dict()\n", "for alph in ['A', 'B']:\n", " for j in range(1,9):\n", " loading_dtype_2[f'RING{alph}_PHASE{j}'] = int\n", " loading_dtype_2[f'dura_{alph}{j}'] = int\n", " loading_dtype_2[f'red_{alph}{j}'] = int\n", " loading_dtype_2[f'yellow_{alph}{j}'] = int\n", "loading_dtype = {**loading_dtype_1, **loading_dtype_2}\n", "\n", "# 테이블 불러오기\n", "self.inter_info = pd.read_csv(os.path.join(self.path_tables, 'inter_info.csv'), dtype=loading_dtype)\n", "self.plan = pd.read_csv(os.path.join(self.path_tables, 'plan.csv'), dtype=loading_dtype)\n", "self.history = pd.read_csv(os.path.join(self.path_tables, 'TL_IF_SIGL_CYCL.csv'), dtype=loading_dtype)\n", "self.inter_node = pd.read_csv(os.path.join(self.path_tables, 'inter_node.csv'), dtype=loading_dtype)\n", "self.matching = pd.read_csv(os.path.join(self.path_intermediates, 'matching.csv'), dtype=loading_dtype)\n", "self.match1 = pd.read_csv(os.path.join(self.path_intermediates, 'match1.csv'), dtype=loading_dtype)\n", "self.match6 = pd.read_csv(os.path.join(self.path_intermediates, 'match6.csv'), dtype=loading_dtype)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "# 컬럼명 변경 적용\n", "self.history = self.history.rename(columns={'OCRN_DT':'end_unix', 'CRSRD_ID':'inter_no'})\n", "self.history = self.history.rename(columns={f'RING{alph}_PHASE{i}':f'dura_{alph}{i}' for alph in ['A', 'B'] for i in range(1,9)})\n", "self.history = self.history.drop(columns='FRST_REG_DT')\n", "self.history['end_unix'] = pd.to_datetime(self.history['end_unix'])\n", "self.history['end_unix'] = self.history['end_unix'].astype(int) // 10**9\n", "self.plan = self.plan.rename(columns={'hh':'start_hour', 'mm':'start_minute'})" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "# 1-5. 보조 딕셔너리, 데이터프레임, 리스트 등 만들기\n", "\n", "# inter2node : a dictionary that maps inter_no to the node_id\n", "inter_node_p = self.inter_node[self.inter_node.inter_type=='parent']\n", "self.inter2node = dict(zip(inter_node_p['inter_no'], inter_node_p['node_id']))\n", "self.node2inter = dict(zip(self.inter_node['node_id'], self.inter_node['inter_no']))\n", "\n", "# split, isplit : A,B 분리 혹은 통합시 사용될 수 있는 딕셔너리 \n", "self.splits = {} # splits maps (inter_no, start_hour, start_minute) to split \n", "for i, row in self.plan.iterrows():\n", " inter_no = row.inter_no\n", " start_hour = row.start_hour\n", " start_minute = row.start_minute\n", " cycle = row.cycle\n", "\n", " dura_A = np.array(row[[f'dura_A{j}' for j in range(1, 9)]])\n", " dura_B = np.array(row[[f'dura_B{j}' for j in range(1, 9)]])\n", "\n", " cums_A = dura_A.cumsum()\n", " cums_B = dura_B.cumsum()\n", " combined_row = np.unique(np.concatenate((cums_A,cums_B)))\n", " detailed_durations = np.concatenate(([combined_row[0]], np.diff(combined_row)))\n", "\n", " self.splits[(inter_no, start_hour, start_minute)] = {} # split maps (phas_A, phas_B) to k\n", " ja = 0\n", " jb = 0\n", " for k in range(len(detailed_durations)):\n", " dura_A[ja] -= detailed_durations[k]\n", " dura_B[jb] -= detailed_durations[k]\n", " self.splits[(inter_no, start_hour, start_minute)][(ja+1, jb+1)] = k+1\n", " if dura_A[ja] == 0:\n", " ja += 1\n", " if dura_B[jb] == 0:\n", " jb += 1\n", "\n", "self.isplits = {} # the inverse of splits\n", "for i in self.splits:\n", " self.isplits[i] = {self.splits[i][k]:k for k in self.splits[i]} # isplit maps k to (phas_A, phas_B)\n", "\n", "# timetable : 교차로별 프로그램 시작시각\n", "self.timetable = self.plan[['start_hour', 'start_minute']].drop_duplicates()\n", "self.timetable['start_seconds'] = self.midnight + self.timetable['start_hour'] * 3600 + self.timetable['start_minute'] * 60\n", "\n", "with open(os.path.join(self.path_intermediates, 'ids.json'), 'r') as file:\n", " ids = json.load(file)\n", "self.inter_nos = ids['inter_nos']\n", "self.node_ids = ids['node_ids']\n", "self.parent_ids = ids['parent_ids']\n", "self.child_ids = ids['child_ids']\n", "self.uturn_ids = ids['uturn_ids']\n", "self.coord_ids = ids['coord_ids']\n", "\n", "# A dictionary that maps parent_id to a list of child_ids\n", "self.pa2ch = {}\n", "for parent_id in self.parent_ids:\n", " inter_no = self.node2inter[parent_id]\n", " self.pa2ch[parent_id] = list(self.inter_node[(self.inter_node.inter_no==inter_no) & (self.inter_node.inter_type=='child')].node_id)\n", "\n", "# node2num_cycles : A dictionary that maps a node_id to the number of cycles\n", "with open(os.path.join(self.path_intermediates, 'node2num_cycles.json'), 'r') as file:\n", " # json.load() 함수를 사용해 파일 내용을 Python 딕셔너리로 불러옵니다.\n", " self.node2num_cycles = json.load(file)\n", "\n", "# 초기화신호 불러오기\n", "with open(os.path.join(self.path_intermediates, 'node2init.json'), 'r') as file:\n", " self.node2init = json.load(file) \n", "\n", "self.plan_set = self.plan.set_index(['inter_no','start_hour','start_minute'])" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "def load_prow(inter_no, time):\n", " '''\n", " load the planned row\n", " '''\n", " # 프로그램 시작시각\n", " program_starts = np.array(self.timetable.start_seconds)\n", " idx = (program_starts <= time).sum() - 1\n", " program_start = program_starts[idx]\n", "\n", " # 최근 프로그램 시작시각에 대한 신호계획\n", " start_hour = self.timetable.iloc[idx].start_hour\n", " start_minute = self.timetable.iloc[idx].start_minute\n", " # prow = self.plan[(self.plan.inter_no==inter_no) & (self.plan.start_hour==start_hour) & (self.plan.start_minute==start_minute)] # planned row\n", " prow = self.plan_set.loc[(inter_no, start_hour, start_minute)]\n", " prow = pd.DataFrame([prow],index=[0])\n", " prow['inter_no'] = inter_no\n", "\n", " return program_start, prow\n" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "ename": "KeyError", "evalue": "(np.int64(456), np.int64(6), np.int64(0))", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mKeyError\u001b[0m Traceback (most recent call last)", "File \u001b[1;32mc:\\github\\siggen\\siggen_env\\Lib\\site-packages\\pandas\\core\\indexes\\multi.py:3220\u001b[0m, in \u001b[0;36mMultiIndex._get_loc_level\u001b[1;34m(self, key, level)\u001b[0m\n\u001b[0;32m 3219\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m-> 3220\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m (\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_engine\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_loc\u001b[49m\u001b[43m(\u001b[49m\u001b[43mkey\u001b[49m\u001b[43m)\u001b[49m, \u001b[38;5;28;01mNone\u001b[39;00m)\n\u001b[0;32m 3221\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mKeyError\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m err:\n", "File \u001b[1;32mindex.pyx:776\u001b[0m, in \u001b[0;36mpandas._libs.index.BaseMultiIndexCodesEngine.get_loc\u001b[1;34m()\u001b[0m\n", "File \u001b[1;32mindex.pyx:167\u001b[0m, in \u001b[0;36mpandas._libs.index.IndexEngine.get_loc\u001b[1;34m()\u001b[0m\n", "File \u001b[1;32mindex.pyx:196\u001b[0m, in \u001b[0;36mpandas._libs.index.IndexEngine.get_loc\u001b[1;34m()\u001b[0m\n", "File \u001b[1;32mpandas\\\\_libs\\\\hashtable_class_helper.pxi:2152\u001b[0m, in \u001b[0;36mpandas._libs.hashtable.UInt64HashTable.get_item\u001b[1;34m()\u001b[0m\n", "File \u001b[1;32mpandas\\\\_libs\\\\hashtable_class_helper.pxi:2176\u001b[0m, in \u001b[0;36mpandas._libs.hashtable.UInt64HashTable.get_item\u001b[1;34m()\u001b[0m\n", "\u001b[1;31mKeyError\u001b[0m: 594", "\nThe above exception was the direct cause of the following exception:\n", "\u001b[1;31mKeyError\u001b[0m Traceback (most recent call last)", "Cell \u001b[1;32mIn[16], line 24\u001b[0m\n\u001b[0;32m 22\u001b[0m \u001b[38;5;66;03m# present_time + adder 의 시각에 한 주기의 신호 추가\u001b[39;00m\n\u001b[0;32m 23\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m inter_no \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mset\u001b[39m(whole_inter_nos):\n\u001b[1;32m---> 24\u001b[0m program_start, prow \u001b[38;5;241m=\u001b[39m \u001b[43mload_prow\u001b[49m\u001b[43m(\u001b[49m\u001b[43minter_no\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mpresent_time\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 25\u001b[0m cycle \u001b[38;5;241m=\u001b[39m prow\u001b[38;5;241m.\u001b[39mcycle\u001b[38;5;241m.\u001b[39miloc[\u001b[38;5;241m0\u001b[39m]\n\u001b[0;32m 26\u001b[0m row3 \u001b[38;5;241m=\u001b[39m prow\u001b[38;5;241m.\u001b[39mcopy()\n", "Cell \u001b[1;32mIn[15], line 14\u001b[0m, in \u001b[0;36mload_prow\u001b[1;34m(inter_no, time)\u001b[0m\n\u001b[0;32m 12\u001b[0m start_minute \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtimetable\u001b[38;5;241m.\u001b[39miloc[idx]\u001b[38;5;241m.\u001b[39mstart_minute\n\u001b[0;32m 13\u001b[0m \u001b[38;5;66;03m# prow = self.plan[(self.plan.inter_no==inter_no) & (self.plan.start_hour==start_hour) & (self.plan.start_minute==start_minute)] # planned row\u001b[39;00m\n\u001b[1;32m---> 14\u001b[0m prow \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mplan_set\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mloc\u001b[49m\u001b[43m[\u001b[49m\u001b[43m(\u001b[49m\u001b[43minter_no\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mstart_hour\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mstart_minute\u001b[49m\u001b[43m)\u001b[49m\u001b[43m]\u001b[49m\n\u001b[0;32m 15\u001b[0m prow \u001b[38;5;241m=\u001b[39m pd\u001b[38;5;241m.\u001b[39mDataFrame([prow],index\u001b[38;5;241m=\u001b[39m[\u001b[38;5;241m0\u001b[39m])\n\u001b[0;32m 16\u001b[0m prow[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124minter_no\u001b[39m\u001b[38;5;124m'\u001b[39m] \u001b[38;5;241m=\u001b[39m inter_no\n", "File \u001b[1;32mc:\\github\\siggen\\siggen_env\\Lib\\site-packages\\pandas\\core\\indexing.py:1184\u001b[0m, in \u001b[0;36m_LocationIndexer.__getitem__\u001b[1;34m(self, key)\u001b[0m\n\u001b[0;32m 1182\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_is_scalar_access(key):\n\u001b[0;32m 1183\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mobj\u001b[38;5;241m.\u001b[39m_get_value(\u001b[38;5;241m*\u001b[39mkey, takeable\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_takeable)\n\u001b[1;32m-> 1184\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_getitem_tuple\u001b[49m\u001b[43m(\u001b[49m\u001b[43mkey\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 1185\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m 1186\u001b[0m \u001b[38;5;66;03m# we by definition only have the 0th axis\u001b[39;00m\n\u001b[0;32m 1187\u001b[0m axis \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39maxis \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;241m0\u001b[39m\n", "File \u001b[1;32mc:\\github\\siggen\\siggen_env\\Lib\\site-packages\\pandas\\core\\indexing.py:1368\u001b[0m, in \u001b[0;36m_LocIndexer._getitem_tuple\u001b[1;34m(self, tup)\u001b[0m\n\u001b[0;32m 1366\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m suppress(IndexingError):\n\u001b[0;32m 1367\u001b[0m tup \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_expand_ellipsis(tup)\n\u001b[1;32m-> 1368\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_getitem_lowerdim\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtup\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 1370\u001b[0m \u001b[38;5;66;03m# no multi-index, so validate all of the indexers\u001b[39;00m\n\u001b[0;32m 1371\u001b[0m tup \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_validate_tuple_indexer(tup)\n", "File \u001b[1;32mc:\\github\\siggen\\siggen_env\\Lib\\site-packages\\pandas\\core\\indexing.py:1057\u001b[0m, in \u001b[0;36m_LocationIndexer._getitem_lowerdim\u001b[1;34m(self, tup)\u001b[0m\n\u001b[0;32m 1047\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m (\n\u001b[0;32m 1048\u001b[0m \u001b[38;5;28misinstance\u001b[39m(ax0, MultiIndex)\n\u001b[0;32m 1049\u001b[0m \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mname \u001b[38;5;241m!=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124miloc\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m (...)\u001b[0m\n\u001b[0;32m 1054\u001b[0m \u001b[38;5;66;03m# is equivalent.\u001b[39;00m\n\u001b[0;32m 1055\u001b[0m \u001b[38;5;66;03m# (see the other place where we call _handle_lowerdim_multi_index_axis0)\u001b[39;00m\n\u001b[0;32m 1056\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m suppress(IndexingError):\n\u001b[1;32m-> 1057\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mcast\u001b[49m\u001b[43m(\u001b[49m\u001b[43m_LocIndexer\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m)\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_handle_lowerdim_multi_index_axis0\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtup\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 1059\u001b[0m tup \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_validate_key_length(tup)\n\u001b[0;32m 1061\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m i, key \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28menumerate\u001b[39m(tup):\n", "File \u001b[1;32mc:\\github\\siggen\\siggen_env\\Lib\\site-packages\\pandas\\core\\indexing.py:1394\u001b[0m, in \u001b[0;36m_LocIndexer._handle_lowerdim_multi_index_axis0\u001b[1;34m(self, tup)\u001b[0m\n\u001b[0;32m 1390\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mKeyError\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m ek:\n\u001b[0;32m 1391\u001b[0m \u001b[38;5;66;03m# raise KeyError if number of indexers match\u001b[39;00m\n\u001b[0;32m 1392\u001b[0m \u001b[38;5;66;03m# else IndexingError will be raised\u001b[39;00m\n\u001b[0;32m 1393\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mndim \u001b[38;5;241m<\u001b[39m \u001b[38;5;28mlen\u001b[39m(tup) \u001b[38;5;241m<\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mobj\u001b[38;5;241m.\u001b[39mindex\u001b[38;5;241m.\u001b[39mnlevels:\n\u001b[1;32m-> 1394\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m ek\n\u001b[0;32m 1395\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m IndexingError(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mNo label returned\u001b[39m\u001b[38;5;124m\"\u001b[39m) \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mek\u001b[39;00m\n", "File \u001b[1;32mc:\\github\\siggen\\siggen_env\\Lib\\site-packages\\pandas\\core\\indexing.py:1388\u001b[0m, in \u001b[0;36m_LocIndexer._handle_lowerdim_multi_index_axis0\u001b[1;34m(self, tup)\u001b[0m\n\u001b[0;32m 1385\u001b[0m axis \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39maxis \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;241m0\u001b[39m\n\u001b[0;32m 1386\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m 1387\u001b[0m \u001b[38;5;66;03m# fast path for series or for tup devoid of slices\u001b[39;00m\n\u001b[1;32m-> 1388\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_get_label\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtup\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43maxis\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43maxis\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 1390\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mKeyError\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m ek:\n\u001b[0;32m 1391\u001b[0m \u001b[38;5;66;03m# raise KeyError if number of indexers match\u001b[39;00m\n\u001b[0;32m 1392\u001b[0m \u001b[38;5;66;03m# else IndexingError will be raised\u001b[39;00m\n\u001b[0;32m 1393\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mndim \u001b[38;5;241m<\u001b[39m \u001b[38;5;28mlen\u001b[39m(tup) \u001b[38;5;241m<\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mobj\u001b[38;5;241m.\u001b[39mindex\u001b[38;5;241m.\u001b[39mnlevels:\n", "File \u001b[1;32mc:\\github\\siggen\\siggen_env\\Lib\\site-packages\\pandas\\core\\indexing.py:1381\u001b[0m, in \u001b[0;36m_LocIndexer._get_label\u001b[1;34m(self, label, axis)\u001b[0m\n\u001b[0;32m 1379\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_get_label\u001b[39m(\u001b[38;5;28mself\u001b[39m, label, axis: AxisInt):\n\u001b[0;32m 1380\u001b[0m \u001b[38;5;66;03m# GH#5567 this will fail if the label is not present in the axis.\u001b[39;00m\n\u001b[1;32m-> 1381\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mobj\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mxs\u001b[49m\u001b[43m(\u001b[49m\u001b[43mlabel\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43maxis\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43maxis\u001b[49m\u001b[43m)\u001b[49m\n", "File \u001b[1;32mc:\\github\\siggen\\siggen_env\\Lib\\site-packages\\pandas\\core\\generic.py:4293\u001b[0m, in \u001b[0;36mNDFrame.xs\u001b[1;34m(self, key, axis, level, drop_level)\u001b[0m\n\u001b[0;32m 4290\u001b[0m index \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mindex\n\u001b[0;32m 4292\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(index, MultiIndex):\n\u001b[1;32m-> 4293\u001b[0m loc, new_index \u001b[38;5;241m=\u001b[39m \u001b[43mindex\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_get_loc_level\u001b[49m\u001b[43m(\u001b[49m\u001b[43mkey\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mlevel\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[0;32m 4294\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m drop_level:\n\u001b[0;32m 4295\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m lib\u001b[38;5;241m.\u001b[39mis_integer(loc):\n\u001b[0;32m 4296\u001b[0m \u001b[38;5;66;03m# Slice index must be an integer or None\u001b[39;00m\n", "File \u001b[1;32mc:\\github\\siggen\\siggen_env\\Lib\\site-packages\\pandas\\core\\indexes\\multi.py:3222\u001b[0m, in \u001b[0;36mMultiIndex._get_loc_level\u001b[1;34m(self, key, level)\u001b[0m\n\u001b[0;32m 3220\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m (\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_engine\u001b[38;5;241m.\u001b[39mget_loc(key), \u001b[38;5;28;01mNone\u001b[39;00m)\n\u001b[0;32m 3221\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mKeyError\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m err:\n\u001b[1;32m-> 3222\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mKeyError\u001b[39;00m(key) \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01merr\u001b[39;00m\n\u001b[0;32m 3223\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mTypeError\u001b[39;00m:\n\u001b[0;32m 3224\u001b[0m \u001b[38;5;66;03m# e.g. partial string indexing\u001b[39;00m\n\u001b[0;32m 3225\u001b[0m \u001b[38;5;66;03m# test_partial_string_timestamp_multiindex\u001b[39;00m\n\u001b[0;32m 3226\u001b[0m \u001b[38;5;28;01mpass\u001b[39;00m\n", "\u001b[1;31mKeyError\u001b[0m: (np.int64(456), np.int64(6), np.int64(0))" ] } ], "source": [ "# 2. 신호이력 전처리\n", "# 2-1. rhistory\n", "\n", "# 1. 조회시점의 유닉스 타임 이전의 신호이력 수집\n", "self.rhistory = self.history.copy() # recent history\n", "self.rhistory = self.rhistory[(self.rhistory.end_unix <= self.present_time) & (self.rhistory.end_unix > self.present_time - self.subtractor)]\n", "\n", "# rhistory에 모든 교차로번호가 존재하지 않으면 해당 교차로번호에 대한 신호이력을 추가함 (at 최근 프로그램 시작시각)\n", "whole_inter_nos = set(self.history.inter_no.unique())\n", "recent_inter_nos = set(self.rhistory.inter_no.unique())\n", "if not whole_inter_nos==recent_inter_nos:\n", " for inter_no in whole_inter_nos - recent_inter_nos:\n", " program_start, prow = load_prow(inter_no, self.present_time - self.subtractor)\n", " cycle = prow.cycle.iloc[0]\n", " row1 = prow.copy()\n", " row2 = prow.copy()\n", " # prow에서 필요한 부분을 rhistory에 추가\n", " row1['end_unix'] = program_start\n", " row2['end_unix'] = program_start + cycle\n", " self.rhistory = pd.concat([self.rhistory, row1, row2])#.reset_index(drop=True)\n", "\n", "# present_time + adder 의 시각에 한 주기의 신호 추가\n", "for inter_no in set(whole_inter_nos):\n", " program_start, prow = load_prow(inter_no, self.present_time)\n", " cycle = prow.cycle.iloc[0]\n", " row3 = prow.copy()\n", " # prow에서 필요한 부분을 rhistory에 추가\n", " row3['end_unix'] = self.present_time + self.adder\n", " self.rhistory = pd.concat([self.rhistory, row3])#.reset_index(drop=True)\n", "\n", "# 2. 시작 유닉스 타임컬럼 생성 후 종류 유닉스 타임에서 현시별 현시기간 컬럼의 합을 뺀 값으로 입력\n", "# - 현시시간의 합을 뺀 시간의 +- 10초 이내에 이전 주기정보가 존재하면 그 유닉스 시간을 시작 유닉스시간 값으로 하고, 존재하지 않으면 현시시간의 합을 뺀 유닉스 시간을 시작 유닉스 시간으로 지정\n", "for i, row in self.rhistory.iterrows():\n", " inter_no = row.inter_no\n", " end_unix = row.end_unix\n", " elapsed_time = row[[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]].sum() // 2 # 현시시간 합\n", " # 이전 유닉스 존재하지 않음 : 현시시간 합의 차\n", " start_unix = end_unix - elapsed_time\n", " pre_rows = self.history[:i] # previous rows\n", " if inter_no in pre_rows.inter_no.unique(): # 이전 유닉스 존재\n", " pre_unix = pre_rows[pre_rows.inter_no == inter_no]['end_unix'].iloc[-1] # previous unix time\n", " # 이전 유닉스 존재, abs < 10 : 이전 유닉스\n", " if abs(pre_unix - start_unix) < 10:\n", " start_unix = pre_unix\n", " # 이전 유닉스 존재, abs >=10 : 현시시간 합의 차\n", " else:\n", " pass\n", " self.rhistory.loc[i, 'start_unix'] = start_unix\n", "self.rhistory[self.rhistory.isna()] = 0\n", "self.rhistory['start_unix'] = self.rhistory['start_unix'].astype(int)\n", "self.rhistory = self.rhistory[['inter_no', 'start_unix'] + [f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)] + ['cycle']]" ] } ], "metadata": { "kernelspec": { "display_name": "siggen_env", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.4" } }, "nbformat": 4, "nbformat_minor": 2 }