diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 000000000..e0a93b982 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python Debugger: Current File with Arguments", + "type": "debugpy", + "request": "launch", + "program": "${file}", + "console": "integratedTerminal", + "args": "${command:pickArgs}" + } + ] +} \ No newline at end of file diff --git a/Data/tables/nema.csv b/Data/tables/nema.csv index 8d6d27e02..6ef7b6036 100644 --- a/Data/tables/nema.csv +++ b/Data/tables/nema.csv @@ -1,4 +1,4 @@ -move_no,inc_dir,out_dir +move_no,inc_dire,out_dire 1,, 2,, 3,, diff --git a/Results/sn_1704418800.add.xml b/Results/sn_1704418800.add.xml index 4d9d3a95d..4843391a1 100644 --- a/Results/sn_1704418800.add.xml +++ b/Results/sn_1704418800.add.xml @@ -1,447 +1,414 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - + @@ -481,271 +448,187 @@ - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + diff --git a/Scripts/preprocess_daily.py b/Scripts/preprocess_daily.py index c46300577..d29bb7880 100644 --- a/Scripts/preprocess_daily.py +++ b/Scripts/preprocess_daily.py @@ -254,7 +254,7 @@ class DailyPreprocessor(): ''' match2의 각 이동류번호에 진입방향, 진출방향을 매칭시킨 테이블 - 컬럼명 : inter_no, phase_no, ring_type, move_no, inc_dir, out_dir + 컬럼명 : inter_no, phase_no, ring_type, move_no, inc_dire, out_dire ''' # nema 정보 불러오기 및 병합 self.match3 = pd.merge(self.match2, self.nema, how='left', on='move_no').drop_duplicates() @@ -264,7 +264,7 @@ class DailyPreprocessor(): ''' match3의 각 이동류번호에 진입, 진출 방위각을 매칭시킨 테이블 - 컬럼명 : inter_no, phase_no, ring_type, move_no, inc_dir, out_dir, inc_angle, out_angle + 컬럼명 : inter_no, phase_no, ring_type, move_no, inc_dire, out_dire, inc_angle, out_angle ''' # # 계층화 @@ -312,29 +312,10 @@ class DailyPreprocessor(): # 2-1-5 def make_match5(self): ''' - 진입엣지id, 진출엣지id, 노드id를 추가함 (주교차로). - - match4의 컬럼 : inter_no, phase_no, ring_type, move_no, inc_dir, out_dir, inc_angle, out_angle - - match5의 컬럼 : inter_no, phase_no, ring_type, move_no, inc_dir, out_dir, inc_angle, out_angle, inc_edge, out_edge, node_id - - 사용된 데이터 : - (1) net - - 성남시 정자동 부근의 샘플 네트워크 - (2) inter_node - - 교차로번호와 노드id를 매칭시키는 테이블. - - parent/child 정보도 포함되어 있음 - - 컬럼 : inter_no, node_id, inter_type - (3) inter_info - - 교차로 정보. 여기에서는 위도와 경도가 쓰임. - - 컬럼 : inter_no, inter_name, inter_lat, inter_lon, group_no, main_phase_no - - 진입엣지id, 진출엣지id를 얻는 과정 : - - match5 = match4.copy()의 각 열을 순회하면서 아래 과정을 반복함. - * 진입에 대해서만 서술하겠지만 진출도 마찬가지로 설명될 수 있음 - - 해당 행의 교차로정보로부터 노드ID를 얻어내고, 해당 노드에 대한 모든 진출엣지id를 inc_edges에 저장. - * inc_edge(진입엣지) : incoming edge, out_edge(진출엣지) : outgoing_edge - - inc_edges의 모든 진입엣지에 대하여 진입방향(inc_dires, 2차원 단위벡터)을 얻어냄. - - 해당 행의 진입각으로부터 그에 대응되는 진입각방향(단위벡터)를 얻어냄. - - 주어진 진입각방향에 대하여 내적이 가장 작은 진입방향에 대한 진입엣지를 inc_edge_id로 지정함. + match4의 각 행에 진입엣지id, 진출엣지id 노드id 추가한 테이블 + * 진입, 진출엣지id를 얻은 방법 : cosine similarity + + 컬럼명 : inter_no, phase_no, ring_type, move_no, inc_dire, out_dire, inc_angle, out_angle, inc_edge, out_edge, node_id ''' # parent node만 가져옴. @@ -392,53 +373,9 @@ class DailyPreprocessor(): # 2-1-6 def make_match6(self): ''' - 진입엣지id, 진출엣지id, 노드id를 추가함 (부교차로). - - match6의 컬럼 : inter_no, phase_no, ring_type, move_no, inc_dir, out_dir, inc_angle, out_angle, inc_edge, out_edge, node_id - - 사용된 데이터 : - (1) inter_node - - 교차로번호와 노드id를 매칭시키는 테이블. - - parent/child 정보도 포함되어 있음 - - 컬럼 : inter_no, node_id, inter_type - (2) uturn (유턴정보) - - 컬럼 : parent_id, child_id, direction, condition, inc_edge, out_edge - - parent_id, child_id : 주교차로id, 유턴교차로id - - direction : 주교차로에 대한 유턴노드의 상대적인 위치(방향) - - condition : 좌회전시, 직진시, 직좌시, 보행신호시 중 하나 - - inc_edge, out_edge : 유턴에 대한 진입진출엣지 - (3) coord (연동교차로정보) - - 컬럼 : parent_id, child_id, phase_no, ring_type, inc_edge, out_edge - - parent_id, child_id : 주교차로id, 연동교차로id - - 나머지 컬럼 : 각 (현시, 링)별 진입진출엣지 - - 설명 : - - match5는 주교차로에 대해서만 진입엣지id, 진출엣지id, 노드id를 추가했었음. - 여기에서 uturn, coord를 사용해서 부교차로들(유턴교차로, 연동교차로)에 대해서도 해당 값들을 부여함. - 유턴교차로 : - - directions를 정북기준 시계방향의 8방위로 정함. - - 이를 통해 진입방향이 주어진 경우에 좌회전, 직진, 보행 등에 대한 (진입방향, 진출방향)을 얻어낼 수 있음. - - 예) 진입방향(direction)이 '북'일 때, - - 직진 : (북, 남) - * 남 : directions[(ind + 4) % len(directions)] - - 좌회전 : (북, 동) - * 동 : directions[(ind + 2) % len(directions)] - - 보행 : (서, 동) - * 서 : directions[(ind - 2) % len(directions)] - - uturn의 각 행을 순회하면서 아래 과정을 반복함 - - match5에서 parent_id에 해당하는 행들을 가져옴(cmatch). - - condition 별로 진입방향, 진출방향을 정함. - - 상술한 directions를 활용하여 정함. - - (진입방향, 진출방향)을 고려하여 (현시, 링) 별로 진입엣지id, 진출엣지id를 정함. - - ex) cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id] - - 순회하면서 만든 cmatch를 cmatchs라는 리스트에 저장함. - - 연동교차로 : - - 연동교차로의 경우 coord에 (현시, 링)별 진입엣지ID, 진출엣지ID가 명시되어 있음. - - 'inc_dir', 'out_dir', 'inc_angle','out_angle'와 같은 열들은 np.nan을 지정해놓음. - - 이 열들은, 사실상 다음 스텝부터는 사용되지 않는 열들이기 때문에 np.nan으로 지정해놓아도 문제없음. - - match6 : - - 이렇게 얻은 match5, cmatchs, coord를 모두 pd.concat하여 match6을 얻어냄. + match5에서 부교차로(유턴교차로, 연동교차로)에 대한 행들을 추가함 + + 컬럼명 : inter_no, phase_no, ring_type, move_no, inc_dire, out_dire, inc_angle, out_angle, inc_edge, out_edge, node_id ''' self.node2inter = dict(zip(self.inter_node['node_id'], self.inter_node['inter_no'])) @@ -489,8 +426,8 @@ class DailyPreprocessor(): out_dire_right = self.directions[(ind + 2) % len(self.directions)] # 보행신호시/좌회전시 조건 - pedes_exists = (cmatch.inc_dir==inc_dire_pedes) & (cmatch.out_dir==out_dire_pedes) - right_exists = (cmatch.inc_dir==inc_dire_right) & (cmatch.out_dir==out_dire_right) + pedes_exists = (cmatch.inc_dire==inc_dire_pedes) & (cmatch.out_dire==out_dire_pedes) + right_exists = (cmatch.inc_dire==inc_dire_right) & (cmatch.out_dire==out_dire_right) # 보행신호시/좌회전시 진입/진출 엣지id 배정 ind = self.directions.index(direction) @@ -515,18 +452,18 @@ class DailyPreprocessor(): cmatch.loc[pedes_exists, ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id] # 보행신호이동류(17) 발생시 elif crosswalk_on.any(): - cmatch.loc[crosswalk_on & (cmatch.out_dir!=direction), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id] + cmatch.loc[crosswalk_on & (cmatch.out_dire!=direction), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id] # 신호없음이동류(18) 발생시 elif all_redsigns.any(): - cmatch.loc[all_redsigns & (cmatch.out_dir!=direction), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id] + cmatch.loc[all_redsigns & (cmatch.out_dire!=direction), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id] cmatches.append(cmatch) # 각 연등교차로(coordination node)에 대하여 (inc_edge_id, out_edge_id) 부여 self.coord['inter_no'] = self.coord['parent_id'].map(self.node2inter) self.coord = self.coord.rename(columns={'child_id':'node_id'}) - self.coord[['inc_dir', 'out_dir', 'inc_angle','out_angle']] = np.nan + self.coord[['inc_dire', 'out_dire', 'inc_angle','out_angle']] = np.nan self.coord['move_no'] = 20 - self.coord = self.coord[['inter_no', 'phase_no', 'ring_type', 'move_no', 'inc_dir', 'out_dir', 'inc_angle','out_angle', 'inc_edge_id', 'out_edge_id', 'node_id']] + self.coord = self.coord[['inter_no', 'phase_no', 'ring_type', 'move_no', 'inc_dire', 'out_dire', 'inc_angle','out_angle', 'inc_edge_id', 'out_edge_id', 'node_id']] # display(coord) cmatches = pd.concat(cmatches) @@ -537,50 +474,38 @@ class DailyPreprocessor(): # 2-1-7 def make_matching(self): ''' - 이동류 매칭 : 각 교차로에 대하여, 가능한 모든 이동류 (1~18, 21)에 대한 진입·진출엣지ID를 지정한다. - 모든 이동류에 대해 지정하므로, 시차제시 이전과 다른 이동류가 등장하더라도 항상 진입·진출 엣지 ID를 지정할 수 있다. - - matching의 컬럼 : inter_no, move_no, inc_dir, out_dir, inc_edge, out_edge, node_id - - 설명 : - - 필요한 리스트, 딕셔너리 등을 정의 - (1) 가능한 (진입방향, 진출방향) 목록 [리스트] - (2) 각 교차로별 방향 목록 : pdires (possible directions) [딕셔너리] - (3) 각 (교차로, 진입방향) 별 진입id 목록 : inc2id (incoming direction to incoming edge_id) [딕셔너리] - (4) 각 (교차로, 진출방향) 별 진출id 목록 : out2id (outgoing direction to outgoing edge_id) [딕셔너리] - (5) 각 교차로별 가능한 (진입방향, 진출방향) 목록 : pflow (possible flows) [딕셔너리] - - matching은 빈 리스트로 지정. - - 모든 노드id에 대하여 다음 과정을 반복 - - 해당 노드id에 대한 모든 가능한 (진입방향, 진출방향)에 대하여 다음 과정을 반복 - - (노드id, 진입방향)으로부터 진입엣지id를 얻어냄. 마찬가지로 진출엣지id도 얻어냄 - - 얻어낸 정보를 바탕으로 한 행(new_row)을 만들고 이것을 matching에 append + 각 교차로에 대하여, 가능한 모든 이동류 (1~18, 21)에 대한 진입·진출엣지ID를 지정한 테이블 + * 시차제 + + 컬럼명 : inter_no, move_no, inc_dire, out_dire, inc_edge, out_edge, node_id ''' self.match7 = self.match6.copy() - self.match7 = self.match7[['inter_no', 'move_no', 'inc_dir', 'out_dir', 'inc_edge', 'out_edge', 'node_id']] + self.match7 = self.match7[['inter_no', 'move_no', 'inc_dire', 'out_dire', 'inc_edge', 'out_edge', 'node_id']] # parent_ids = sorted(self.inter_node[self.inter_node.inter_type=='parent'].node_id.unique()) # child_ids = sorted(self.inter_node[self.inter_node.inter_type=='child'].node_id.unique()) # (1) 가능한 (진입방향, 진출방향) 목록 - flows = self.nema.dropna().apply(lambda row: (row['inc_dir'], row['out_dir']), axis=1).tolist() + flows = self.nema.dropna().apply(lambda row: (row['inc_dire'], row['out_dire']), axis=1).tolist() # (2) 각 교차로별 방향 목록 : pdires (possible directions) pdires = {} for node_id in self.parent_ids: - dires = self.match7[self.match7.node_id == node_id][['inc_dir','out_dir']].values.flatten() + dires = self.match7[self.match7.node_id == node_id][['inc_dire','out_dire']].values.flatten() dires = {dire for dire in dires if type(dire)==str} pdires[node_id] = dires # (3) 각 (교차로, 진입방향) 별 진입id 목록 : inc2id (incoming direction to incoming edge_id) inc2id = {} for node_id in self.parent_ids: - for inc_dir in pdires[node_id]: - df = self.match7[(self.match7.node_id==node_id) & (self.match7.inc_dir==inc_dir)] - inc2id[(node_id, inc_dir)] = df.inc_edge.iloc[0] + for inc_dire in pdires[node_id]: + df = self.match7[(self.match7.node_id==node_id) & (self.match7.inc_dire==inc_dire)] + inc2id[(node_id, inc_dire)] = df.inc_edge.iloc[0] # (4) 각 (교차로, 진출방향) 별 진출id 목록 : out2id (outgoing direction to outgoing edge_id) out2id = {} for node_id in self.parent_ids: - for out_dir in pdires[node_id]: - df = self.match7[(self.match7.node_id==node_id) & (self.match7.out_dir==out_dir)] - out2id[(node_id, out_dir)] = df.out_edge.iloc[0] + for out_dire in pdires[node_id]: + df = self.match7[(self.match7.node_id==node_id) & (self.match7.out_dire==out_dire)] + out2id[(node_id, out_dire)] = df.out_edge.iloc[0] # (5) 각 교차로별 가능한 (진입방향, 진출방향) 목록 : pflow (possible flows) pflow = {} for node_id in self.parent_ids: @@ -592,28 +517,28 @@ class DailyPreprocessor(): for node_id in self.parent_ids: inter_no = self.node2inter[node_id] # 좌회전과 직진(1 ~ 16) - for (inc_dir, out_dir) in pflow[node_id]: - move_no = self.nema[(self.nema.inc_dir==inc_dir) & (self.nema.out_dir==out_dir)].move_no.iloc[0] - inc_edge = inc2id[(node_id, inc_dir)] - out_edge = out2id[(node_id, out_dir)] + for (inc_dire, out_dire) in pflow[node_id]: + move_no = self.nema[(self.nema.inc_dire==inc_dire) & (self.nema.out_dire==out_dire)].move_no.iloc[0] + inc_edge = inc2id[(node_id, inc_dire)] + out_edge = out2id[(node_id, out_dire)] new_row = pd.DataFrame({'inter_no':[inter_no], 'move_no':[move_no], - 'inc_dir':[inc_dir], 'out_dir':[out_dir], + 'inc_dire':[inc_dire], 'out_dire':[out_dire], 'inc_edge':[inc_edge], 'out_edge':[out_edge], 'node_id':[node_id]}) self.matching.append(new_row) # 보행신호(17), 전적색(18) new_row = pd.DataFrame({'inter_no':[inter_no] * 2, 'move_no':[17, 18], - 'inc_dir':[None]*2, 'out_dir':[None]*2, + 'inc_dire':[None]*2, 'out_dire':[None]*2, 'inc_edge':[None]*2, 'out_edge':[None]*2, 'node_id':[node_id]*2}) self.matching.append(new_row) # 신호우회전(21) for d in range(len(dires_right)-1): - inc_dir = dires_right[d] - out_dir = dires_right[d+1] - if {inc_dir, out_dir}.issubset(pdires[node_id]): - inc_edge = inc2id[(node_id, inc_dir)] - out_edge = out2id[(node_id, out_dir)] + inc_dire = dires_right[d] + out_dire = dires_right[d+1] + if {inc_dire, out_dire}.issubset(pdires[node_id]): + inc_edge = inc2id[(node_id, inc_dire)] + out_edge = out2id[(node_id, out_dire)] new_row = pd.DataFrame({'inter_no':[inter_no], 'move_no':[21], - 'inc_dir':[inc_dir], 'out_dir':[out_dir], + 'inc_dire':[inc_dire], 'out_dire':[out_dire], 'inc_edge':[inc_edge], 'out_edge':[out_edge], 'node_id':[node_id]}) self.matching.append(new_row) self.matching.append(self.match7[self.match7.node_id.isin(self.child_ids)])