def polygon_event(self): filename, _ = QFileDialog.getOpenFileName( self, 'Open a .shp file', '', 'Polygon file (*.shp)', options=QFileDialog.Options() | QFileDialog.DontUseNativeDialog) if not filename: return if not test_open(filename): return polygons = [] try: for polygon in Shapefile.get_polygons(filename): polygons.append(polygon) except struct.error: QMessageBox.critical(self, 'Error', 'Inconsistent bytes.', QMessageBox.Ok) return if not polygons: QMessageBox.critical(self, 'Error', 'The file does not contain any polygon.', QMessageBox.Ok) return items = [ '%d - %s' % (index, name) for (index, name) in Shapefile.get_numeric_attribute_names(filename) ] if not items: QMessageBox.critical( self, 'Error', 'The polygons do not have numeric attributes.', QMessageBox.Ok) return dlg = AttributeDialog(items) if dlg.exec_() != QDialog.Accepted: return attribute_index, attribute_name = dlg.attribute_box.currentText( ).split(' - ') attribute_index = int(attribute_index) short_name = os.path.join(os.path.basename(filename), os.path.split(filename)[1]) row = self.polygon_table.rowCount() self.polygon_table.insertRow(row) self.polygon_table.setItem(row, 0, QTableWidgetItem('POLY%d' % (row + 1))) self.polygon_table.setItem(row, 1, QTableWidgetItem(attribute_name)) self.polygon_table.setItem(row, 2, QTableWidgetItem(short_name)) self.parent.editor_tab.pool.add_polygonal_mask(polygons, attribute_index)
def get_zones_from_i3s_file(shp_name, threshold, operator_str): polylines = [] attributes = shp.get_numeric_attribute_names(shp_name) if args.attr_to_shift_z is not None: try: index_attr = [attr for _, attr in attributes].index(args.attr_to_shift_z) except ValueError: logger.critical('Attribute "%s" is not found.' % args.attr_to_shift_z) sys.exit(1) for polyline in shp.get_open_polylines(shp_name): if not polyline.polyline().is_valid: sys.exit("ERROR: polyline is not valid (probably because it intersects itself)!") # Shift z (if requested) if args.attr_to_shift_z is not None: dz = polyline.attributes()[index_attr] print(dz) polyline = polyline.apply_transformations([Transformation(0.0, 1.0, 1.0, 0.0, 0.0, dz)]) # Linear interpolation along the line for values below the threshold if threshold is not None: np_coord = np.array(polyline.coords()) Xt = np.sqrt(np.power(np.ediff1d(np_coord[:, 0], to_begin=0.), 2) + np.power(np.ediff1d(np_coord[:, 1], to_begin=0.), 2)) Xt = Xt.cumsum() ref_rows = np_coord[:, 2] > args.threshold np_coord[:, 2] = np.interp(Xt, Xt[ref_rows], np_coord[ref_rows, 2]) polyline = geo.LineString(np_coord) polylines.append(polyline) zones = [] for prev_line, next_line in zip(polylines[:-1], polylines[1:]): zones.append(Zone(prev_line, next_line, operator_str)) return zones
def from_file(filename, label, field_id=None, project_straight_line=False): section_seq = CrossSectionSequence() if filename.endswith('.i3s'): with bk.Read(filename) as in_i3s: in_i3s.read_header() for i, line in enumerate(in_i3s.get_open_polylines()): line_id = i if field_id is None else line.attributes()[ 0] # Use `Value` if field is not None z_array = np.array([(coord[2], ) for coord in line.polyline().coords], dtype=float_vars('Z')) line = line.to_2d() section = CrossSection(line_id, list(line.polyline().coords), label) section.coord.values = z_array section_seq.add_section(section) elif filename.endswith('.shp'): shp_type = shp.get_shape_type(filename) if shp_type in (shapefile.POLYLINEZ, shapefile.POLYLINEM): field_id_index = get_field_index(filename, field_id) for i, line in enumerate(shp.get_open_polylines(filename)): line_id = i if field_id is None else line.attributes( )[field_id_index] z_array = np.array([(coord[2], ) for coord in line.polyline().coords], dtype=float_vars(['Z'])) line = line.to_2d() section = CrossSection(line_id, list(line.polyline().coords), label) section.coord.values = z_array section_seq.add_section(section) elif shp_type in (shapefile.POINT, shapefile.POINTZ): field_id_index = get_field_index(filename, field_id) field_indexes, field_names = [], [] if shp_type == shapefile.POINTZ: field_names.append('Z') for index, name in shp.get_numeric_attribute_names(filename): if name.startswith('Z'): field_indexes.append(index) field_names.append(name) coords, z_layers = [], [] last_point_id = None for i, (point, attributes) in enumerate( shp.get_points(filename, with_z=shp_type == shapefile.POINTZ)): point_id = attributes[ field_id_index] # FIXME: should raise exception if field_id_index is None! if i > 0 and point_id != last_point_id: z_array = np.array(z_layers, dtype=float_vars(field_names)) section = CrossSection(last_point_id, coords, label) section.coord.values = z_array section_seq.add_section(section) coords, z_layers = [], [] coords.append(point[:2]) if shp_type == shapefile.POINTZ: z_layers.append((point[2], ) + tuple(attributes[index] for index in field_indexes)) else: z_layers.append( tuple(attributes[index] for index in field_indexes)) last_point_id = point_id z_array = np.array(z_layers, dtype=float_vars(field_names)) section = CrossSection(last_point_id, coords, label) section.coord.values = z_array section_seq.add_section(section) else: raise TatooineException( "The type of file %s is not POINT[Z] or POLYLINEZ[M]" % filename) else: raise NotImplementedError( "Only shp and i3s formats are supported for cross-sections") if project_straight_line: for section in section_seq: section.project_straight_line() return section_seq
def slf_bottom_friction(args): # Check argument consistency if args.in_strickler_zones is not None or args.in_strickler_attr is not None: if args.in_strickler_zones is None or args.in_strickler_attr is None: logger.critical( 'Both arguments `--in_strickler_zones` and `--in_strickler_attr` have to be defined.' ) sys.exit(2) # Read polygons to compute volume if not args.in_polygons.endswith('.shp'): logger.critical('File "%s" is not a shp file.' % args.in_polygons) sys.exit(3) polygons = [] try: for polygon in Shapefile.get_polygons(args.in_polygons): polygons.append(polygon) except ShapefileException as e: logger.error(e) sys.exit(3) if not polygons: logger.error('The file does not contain any polygon.') sys.exit(1) logger.debug('The file contains {} polygon{}.'.format( len(polygons), 's' if len(polygons) > 1 else '')) names = ['Polygon %d' % (i + 1) for i in range(len(polygons))] varIDs = ['US', 'TAU'] out_varIDs = ['W'] + varIDs pos_TAU = out_varIDs.index('TAU') with Serafin.Read(args.in_slf, args.lang) as resin: resin.read_header() if not resin.header.is_2d: logger.critical('The file has to be a 2D Serafin!') sys.exit(3) in_varIDs = resin.header.var_IDs # Compute Strickler values if necessary ori_values = {} if args.in_strickler_zones is not None: if not args.in_strickler_zones.endswith('.shp'): logger.critical('File "%s" is not a shp file.' % args.in_strickler_zones) sys.exit(3) attributes = Shapefile.get_numeric_attribute_names( args.in_strickler_zones) try: index_attr = [attr for _, attr in attributes ].index(args.in_strickler_attr) except ValueError: logger.critical('Attribute "%s" is not found.' % args.in_strickler_attr) sys.exit(1) strickler_zones = [] try: for zone in Shapefile.get_polygons(args.in_strickler_zones): strickler_zones.append(zone) except ShapefileException as e: logger.error(e) sys.exit(3) if not strickler_zones: logger.error('The file does not contain any friction zone.') sys.exit(1) logger.debug('Recomputing friction coefficient values from zones') friction_coeff = np.full( resin.header.nb_nodes_2d, 0.0) # default value for nodes not included in any zone for i, (x, y) in enumerate( zip(tqdm(resin.header.x), tqdm(resin.header.y))): point = Point(x, y) for zone in strickler_zones: if zone.contains(point): friction_coeff[i] = zone.attributes()[index_attr] exit in_varIDs.append('W') ori_values['W'] = friction_coeff else: if 'W' not in resin.header.varIDs: logger.critical('The variable W is missing.') sys.exit(1) us_equation = None if args.friction_law: us_equation = get_US_equation(args.friction_law) resin.get_time() necessary_equations = get_necessary_equations(in_varIDs, out_varIDs, is_2d=True, us_equation=us_equation) calculator = VolumeCalculator(VolumeCalculator.NET, 'TAU', None, resin, names, polygons, 1) calculator.construct_triangles(tqdm) calculator.construct_weights(tqdm) output_header = resin.header.copy() output_header.empty_variables() for var_ID in out_varIDs: output_header.add_variable_from_ID(var_ID) with Serafin.Write(args.out_slf, args.lang, args.force) as resout: resout.write_header(output_header) mode = 'w' if args.force else 'x' with open(args.out_csv, mode, newline='') as csvfile: csvwriter = csv.writer(csvfile, delimiter=args.sep) csvwriter.writerow(['time'] + names) for time_index, time in enumerate(tqdm(resin.time)): values = do_calculations_in_frame( necessary_equations, resin, time_index, out_varIDs, resin.header.np_float_type, is_2d=True, us_equation=STRICKLER_EQUATION, ori_values=ori_values) resout.write_entire_frame(output_header, time, values) row = [time] for j in range(len(calculator.polygons)): weight = calculator.weights[j] volume = calculator.volume_in_frame_in_polygon( weight, values[pos_TAU], calculator.polygons[j]) row.append(volume) csvwriter.writerow(row)