diff --git a/bpeng/dimensions/__init__.py b/bpeng/dimensions/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..398d05e1ea050896a5b466b8c4f98e2a52ef6028 --- /dev/null +++ b/bpeng/dimensions/__init__.py @@ -0,0 +1 @@ +from .parse_dimensions import ParseDimensions diff --git a/bpeng/dimensions/parse_dimensions.py b/bpeng/dimensions/parse_dimensions.py new file mode 100644 index 0000000000000000000000000000000000000000..12b28fff6493790e0b113f45ea373048077b28cf --- /dev/null +++ b/bpeng/dimensions/parse_dimensions.py @@ -0,0 +1,196 @@ +""" +Parse a dimensions file +""" + +import xlrd + + +# pylint: disable=too-many-locals,too-few-public-methods +class ParseDimensions: + """ + Class to parse a dimensions file + """ + + DIRECTION_DICT = { + 'South': 1, 'south': 1, 'S': 1, + 'East': 2, 'east': 2, 'E': 2, + 'West': 3, 'west': 3, 'W': 3, + 'North': 4, 'north': 4, 'N': 4, + } + + FEATURE_DICT = { + 'Door': 1, + 'Window': 2, + 'Building Point': 3, + 'Roof Point': 4, + 'Adjacent Building 1 Point': 5, + 'Adjacent Building 2 Point': 6, + 'Adjacent Building 3 Point': 7, + } + + @staticmethod + def parse(dimensions_file): + """ + Parse a dimensions file + Relies on specific formatting + + Args: + + dimensions_file (bytes): The file to parse + + Returns: + + list: An array of dicts representing + windows doors + list: An array of dicts representing + points + dict: A dict repesenting + the data that is building specific + + """ + workbook = xlrd.open_workbook(file_contents=dimensions_file) + worksheet = workbook.sheet_by_index(0) + + num_floors = worksheet.cell(1, 1).value + perimeter = worksheet.cell(1, 3).value + area = worksheet.cell(1, 5).value + + building_dimensions = { + 'perimeter': float(perimeter), + 'area': float(area), + 'num_floors': int(num_floors), + } + + point_list = [] + # Building, roof and adjacent building points have seperate starting places on the excel spreadsheet, + start_points = [ + { + 'row_start': 5, + 'column_start': 1, + 'feature': ParseDimensions.FEATURE_DICT['Building Point'], + }, + { + 'row_start': 3, + 'column_start': 23, + 'feature': ParseDimensions.FEATURE_DICT['Roof Point'], + }, + { + 'row_start': 3, + 'column_start': 28, + 'feature': ParseDimensions.FEATURE_DICT['Adjacent Building 1 Point'], + }, + { + 'row_start': 3, + 'column_start': 33, + 'feature': ParseDimensions.FEATURE_DICT['Adjacent Building 2 Point'], + }, + { + 'row_start': 3, + 'column_start': 38, + 'feature': ParseDimensions.FEATURE_DICT['Adjacent Building 3 Point'], + }, + ] + # Get the building, roof and adjacent building points + for start_point in start_points: + row_start = start_point['row_start'] + column_start = start_point['column_start'] + row_counter = 0 + lat = worksheet.cell(row_start, column_start).value + while lat: + column_counter = 1 + longt = worksheet.cell( + row_start + row_counter, + column_start + column_counter + ).value + column_counter += 1 + elevation = worksheet.cell( + row_start + row_counter, + column_start + column_counter + ).value + point_data = { + 'latitude': float(lat), + 'longitude': float(longt), + 'elevation': float(elevation), + 'feature': start_point['feature'], + } + # The row counter also serves to count the wall we are on, + # but this is only relevant for building points + if start_point['feature'] == ParseDimensions.FEATURE_DICT['Building Point']: + point_data['wall_num_first'] = row_counter + point_data['wall_num_second'] = row_counter + 1 + point_list.append(point_data) + row_counter += 1 + lat = worksheet.cell(row_start + row_counter, column_start).value + # Once we've finished parsing we should update the first point to reflect + # the actual corresponding wall + if start_point['feature'] == ParseDimensions.FEATURE_DICT['Building Point']: + point_list[0]['wall_num_first'] = row_counter + + windows_and_doors = [] + # Places where windows and doors height and width data rae stored + feature_start_points = [ + { + 'column_start': 9, + 'row_start': 4, + 'feature': ParseDimensions.FEATURE_DICT['Window'], + }, + { + 'column_start': 11, + 'row_start': 4, + 'feature': ParseDimensions.FEATURE_DICT['Window'], + }, + { + 'column_start': 13, + 'row_start': 4, + 'feature': ParseDimensions.FEATURE_DICT['Window'], + }, + { + 'column_start': 15, + 'row_start': 4, + 'feature': ParseDimensions.FEATURE_DICT['Window'], + }, + { + 'column_start': 17, + 'row_start': 4, + 'feature': ParseDimensions.FEATURE_DICT['Window'], + }, + { + 'column_start': 19, + 'row_start': 4, + 'feature': ParseDimensions.FEATURE_DICT['Door'], + }, + ] + # The start points for window and doors data + row_start = 6 + column_start = 8 + orientation = worksheet.cell(row_start, column_start).value + row_counter = 0 + while orientation: + for start_point in feature_start_points: + # Get the quantity for this window/door type + quantity = worksheet.cell( + row_start + row_counter, + start_point['column_start'], + ).value + if quantity and int(quantity) > 0: + # Get the height and width for this window/door type + height = worksheet.cell( + start_point['row_start'], + start_point['column_start'], + ).value + width = worksheet.cell( + start_point['row_start'], + start_point['column_start'] + 1, + ).value + windows_and_doors.append({ + 'height': float(height), + 'width': float(width), + 'quantity': int(quantity), + 'orientation': ParseDimensions.DIRECTION_DICT[orientation], + 'wall_num': row_counter + 1, + 'feature': start_point['feature'], + }) + row_counter += 1 + orientation = worksheet.cell(row_start + row_counter, column_start).value + + return windows_and_doors, point_list, building_dimensions