Python code

profilegen_1
work.zip

work/Error.bmp

work/Output.bmp

Codes.txt

#!/usr/bin/python import math as _math import traceback as _traceback import os import inro.modeller as _m import inro.emme.core.exception as _except class AdjacentNodes(_m.Tool()): node_selection = _m.Attribute(unicode) north_angle = _m.Attribute(float) export_file = _m.Attribute(unicode) export_file_5 = _m.Attribute(unicode) export_file_6 = _m.Attribute(unicode) scenario = _m.Attribute(_m.InstanceType) tool_run_msg = "" def __init__(self): self.north_angle = 90 self.node_selection = "all" def page(self): pb = _m.ToolPageBuilder(self, title="List Adjacent Nodes", description="Exports the nodes specified by a selection expression to " "a text file, with a list of the adjacent nodes " "sorted North, Northwest, West, Southwest, South, Southeast, " "East, and Northeast.<br>", branding_text="INRO - Emme") if self.tool_run_msg != "": pb.tool_run_status(self.tool_run_msg_status) pb.add_text_box("node_selection", size=20, title="Node selection expression:", multi_line=True) pb.add_text_box("north_angle", size=10, title="North Angle:", note="Angle which is North, counterclockwise relative to the horizontal axis.") pb.add_select_file("export_file", window_type="save_file", file_filter="Text Documents (*.txt)", start_path=os.path.dirname(_m.Modeller().desktop.project_file_name()), title="Export file (4 or less nodes) :") pb.add_select_file("export_file_5", window_type="save_file", file_filter="Text Documents (*.txt)", start_path=os.path.dirname(_m.Modeller().desktop.project_file_name()), title="Export file (5 nodes):") pb.add_select_file("export_file_6", window_type="save_file", file_filter="Text Documents (*.txt)", start_path=os.path.dirname(_m.Modeller().desktop.project_file_name()), title="Export file (6+ nodes):") if not self.scenario: self.scenario = _m.Modeller().desktop.data_explorer().\ primary_scenario.core_scenario pb.add_select_scenario("scenario", title="Scenario:") return pb.render() def run(self): self.tool_run_msg = "" try: self(self.node_selection, self.north_angle, self.export_file, self.export_file_5, self.export_file_6, self.scenario) self.tool_run_msg = _m.PageBuilder.format_info("Tool completed.") except Exception, e: self.tool_run_msg += _m.PageBuilder.format_exception( e, _traceback.format_exc(e)) raise @_m.logbook_trace(name="List nodes and directionally sorted adjacent nodes", save_arguments=True) def __call__(self, node_selection, north_angle, export_file, export_file_5, export_file_6, scenario): UTILITIES_NAME = "inro.emme.utility.export_utilities" export_utils = _m.Modeller().module(UTILITIES_NAME) network = scenario.get_network() node_ids = export_utils.apply_node_selection(scenario, {"node": node_selection}) classify = ClassifyAdjacentNodes(north_angle) f = None f5 = None f6 = None file_hdr = "Node N NW W SW S SE E NE\n" if export_file: f = open(export_file, 'w') f.write(file_hdr) if export_file_5 and export_file_5 != export_file: f5 = open(export_file_5, 'w') f5.write(file_hdr) if export_file_6 and export_file_6 != export_file and export_file_6 != export_file_5: f6 = open(export_file_6, 'w') f6.write(file_hdr) if not (f or f5 or f6): raise _except.Error("Missing output file name") for node_id in node_ids: node = network.node(node_id) adj, node_count = classify(node) line_buf = str(node_id) l = 0 while True: for i in range(8): d = ["N", "NW", "W", "SW", "S", "SE", "E", "NE"][i] if d in adj and l < len(adj[d]): line_buf = "%-*s %s" % (i * 8 + 7, line_buf, adj[d][l]) if not line_buf: break line_buf += "\n" if node_count < 5: if f: f.write(line_buf) elif node_count < 6: if f5: f5.write(line_buf) elif f6: f6.write(line_buf) line_buf = "" l += 1 return @_m.method(return_type=_m.UnicodeType) def tool_run_msg_status(self): return self.tool_run_msg class ClassifyAdjacentNodes(object): def __init__(self, north_angle=90): self.directions = ["N", "NW", "W", "SW", "S", "SE", "E", "NE"] # counter clockwise order, starting with North self.expected_angles = [(x + north_angle) % 360 for x in range(0, 360, 45)] def __call__(self, at_node): out_link_nodes = set([l.j_node for l in at_node.outgoing_links()]) in_link_nodes = set([l.i_node for l in at_node.incoming_links()]) adjacent_nodes = out_link_nodes.union(in_link_nodes) directional_nodes = {} for node in adjacent_nodes: closest = self._closest_direction(at_node, node) if not closest in directional_nodes: directional_nodes[closest] = [node] else: directional_nodes[closest] += [node] return directional_nodes, len(adjacent_nodes) def _closest_direction(self, at_node, dir_node): angle = _math.degrees(_math.atan2(dir_node.y - at_node.y, dir_node.x - at_node.x)) angle_names = zip(self.expected_angles, self.directions) angle_diffs = [(self._normalize(a - angle), n) for a, n in angle_names] angle_diffs.sort() return angle_diffs[0][1] def _normalize(self, ang_diff): v = abs(ang_diff) % 360 if v > 180: return 360 - v return v