mirror of
				https://github.com/Telecominfraproject/oopt-gnpy.git
				synced 2025-10-31 01:57:54 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			104 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			104 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| #!/usr/bin/env python3
 | |
| 
 | |
| from sys import exit
 | |
| try:
 | |
|     from xlrd import open_workbook
 | |
| except ModuleNotFoundError:
 | |
|     exit('Required: `pip install xlrd`')
 | |
| from argparse import ArgumentParser
 | |
| from collections import namedtuple, Counter
 | |
| from json import dumps
 | |
| 
 | |
| Node = namedtuple('Node', 'city state country region latitude longitude')
 | |
| class Link(namedtuple('Link', 'from_city to_city distance distance_units')):
 | |
|     def __new__(cls, from_city, to_city, distance, distance_units='km'):
 | |
|         return super().__new__(cls, from_city, to_city, distance, distance_units)
 | |
| 
 | |
| def parse_excel(args):
 | |
|     with open_workbook(args.workbook) as wb:
 | |
|         nodes_sheet = wb.sheet_by_name('Nodes')
 | |
|         links_sheet = wb.sheet_by_name('Links')
 | |
| 
 | |
|         # sanity check
 | |
|         header = [x.value.strip() for x in nodes_sheet.row(4)]
 | |
|         expected = ['City', 'State', 'Country', 'Region', 'Latitude', 'Longitude']
 | |
|         if header != expected:
 | |
|             raise ValueError(f'Malformed header on Nodes sheet: {header} != {expected}')
 | |
| 
 | |
|         nodes = []
 | |
|         for row in all_rows(nodes_sheet, start=5):
 | |
|             nodes.append(Node(*(x.value for x in row)))
 | |
| 
 | |
|         # sanity check
 | |
|         header = [x.value.strip() for x in links_sheet.row(4)]
 | |
|         expected = ['Node A', 'Node Z', 'Distance (km)']
 | |
|         if header != expected:
 | |
|             raise ValueError(f'Malformed header on Nodes sheet: {header} != {expected}')
 | |
| 
 | |
|         links = []
 | |
|         for row in all_rows(links_sheet, start=5):
 | |
|             links.append(Link(*(x.value for x in row)))
 | |
| 
 | |
|     # sanity check
 | |
|     all_cities = Counter(n.city for n in nodes)
 | |
|     if len(all_cities) != len(nodes):
 | |
|         ValueError(f'Duplicate city: {all_cities}')
 | |
|     if any(ln.from_city not in all_cities or
 | |
|            ln.to_city   not in all_cities for ln in links):
 | |
|         ValueError(f'Bad link.')
 | |
| 
 | |
|     return nodes, links
 | |
| 
 | |
| parser = ArgumentParser()
 | |
| parser.add_argument('workbook', nargs='?', default='CORONET_Global_Topology.xls')
 | |
| parser.add_argument('-f', '--filter-region', action='append', default=[])
 | |
| 
 | |
| all_rows = lambda sh, start=0: (sh.row(x) for x in range(start, sh.nrows))
 | |
| 
 | |
| def midpoint(city_a, city_b):
 | |
|     lats  = city_a.latitude, city_b.latitude
 | |
|     longs = city_a.longitude, city_b.longitude
 | |
|     return {
 | |
|         'latitude':  sum(lats)  / 2,
 | |
|         'longitude': sum(longs) / 2,
 | |
|     }
 | |
| 
 | |
| if __name__ == '__main__':
 | |
|     args = parser.parse_args()
 | |
|     nodes, links = parse_excel(args)
 | |
| 
 | |
|     if args.filter_region:
 | |
|         nodes = [n for n in nodes if n.region in args.filter_region]
 | |
|         cities = {n.city for n in nodes}
 | |
|         links = [lnk for lnk in links if lnk.from_city in cities and
 | |
|                                          lnk.to_city in cities]
 | |
|         cities = {lnk.from_city for lnk in links} | {lnk.to_city for lnk in links}
 | |
|         nodes = [n for n in nodes if n.city in cities]
 | |
| 
 | |
|     nodes_by_city = {n.city: n for n in nodes}
 | |
| 
 | |
|     data = {
 | |
|         'elements':
 | |
|             [{'id': x.city,
 | |
|               'metadata': {'city': x.city, 'region': x.region,
 | |
|                            'latitude': x.latitude,
 | |
|                            'longitude': x.longitude},
 | |
|               'type': 'City'}
 | |
|              for x in nodes] +
 | |
|             [{'id': f'fiber ({x.from_city} → {x.to_city})',
 | |
|               'metadata': {'length': x.distance, 'units': x.distance_units,
 | |
|                             **midpoint(nodes_by_city[x.from_city],
 | |
|                                        nodes_by_city[x.to_city])},
 | |
|               'type': 'Fiber'}
 | |
|              for x in links],
 | |
|         'connections':
 | |
|             [{'from_node': x.from_city,
 | |
|               'to_node':   f'fiber ({x.from_city} → {x.to_city})'}
 | |
|              for x in links] +
 | |
|             [{'from_node': f'fiber ({x.from_city} → {x.to_city})',
 | |
|               'to_node':   x.to_city}
 | |
|              for x in links]
 | |
|     }
 | |
| 
 | |
|     print(dumps(data, indent=2))
 | 
