def slf_max_over_files(args): if args.vars is None: with Serafin.Read(args.in_slfs[0], args.lang) as resin: resin.read_header() var_IDs = resin.header.var_IDs if args.vars is None else args.vars else: var_IDs = args.vars if args.operation == 'max': fun = np.maximum elif args.operation == 'min': fun = np.minimum else: raise NotImplementedError # Read polygons if args.in_polygons is not None: 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.info('The file contains {} polygon{}.'.format(len(polygons), 's' if len(polygons) > 1 else '')) else: polygons = None output_header = None out_values = None # min or max values mask_nodes = None for i, in_slf in enumerate(args.in_slfs): with Serafin.Read(in_slf, args.lang) as resin: resin.read_header() logger.info(resin.header.summary()) if not resin.header.is_2d: logger.critical('The file has to be a 2D Serafin!') sys.exit(3) resin.get_time() for var_ID in var_IDs: if var_ID not in resin.header.var_IDs: logger.critical('The variable %s is missing in %s' % (var_ID, in_slf)) sys.exit(3) if i == 0: output_header = resin.header.copy() output_header.empty_variables() for var_ID in var_IDs: output_header.add_variable_from_ID(var_ID) out_values = np.empty((output_header.nb_var, output_header.nb_nodes), dtype=output_header.np_float_type) if polygons is not None: mask_nodes = np.zeros(output_header.nb_nodes, dtype=bool) for idx_node, (x, y) in enumerate(zip(output_header.x, output_header.y)): point = Point(x, y) for polygon in polygons: if polygon.contains(point): mask_nodes[idx_node] = True break logger.info('Number of nodes inside polygon(s): %i (over %i)' % (mask_nodes.sum(), output_header.nb_nodes)) else: mask_nodes = np.ones(output_header.nb_nodes, dtype=bool) else: if not resin.header.same_2d_mesh(output_header): logger.critical('The mesh of %s is different from the first one' % in_slf) sys.exit(1) for time_index, time in enumerate(resin.time): for j, var_ID in enumerate(var_IDs): values = resin.read_var_in_frame(time_index, var_ID) if time_index == 0 and i == 0: out_values[j, :] = values else: out_values[j, mask_nodes] = fun(out_values[j, mask_nodes], values[mask_nodes]) with Serafin.Write(args.out_slf, args.lang, overwrite=args.force) as resout: resout.write_header(output_header) resout.write_entire_frame(output_header, 0.0, out_values)
help='upper variable', metavar='VA', required=True) parser.add_argument('--lower_var', help='lower variable', metavar='VB', default=None) parser.add_argument('--detailed', help='add positive and negative volumes', action='store_true') parser.add_known_argument('out_csv') parser.add_group_general(['force', 'verbose']) if __name__ == '__main__': args = parser.parse_args() try: slf_volume(args) except (Serafin.SerafinRequestError, Serafin.SerafinValidationError): # Message is already reported by slf logger sys.exit(1) except FileNotFoundError as e: logger.error('Input file %s not found.' % e.filename) sys.exit(3) except FileExistsError as e: logger.error( 'Output file %s already exists. Remove it or add `--force` argument' % e.filename) sys.exit(3)
def slf_volume(args): # Read set of lines from input file polygons = [] if args.in_polygons.endswith('.i2s'): with BlueKenue.Read(args.in_polygons) as f: f.read_header() for poly in f.get_polygons(): polygons.append(poly) elif args.in_polygons.endswith('.shp'): try: for polygon in Shapefile.get_polygons(args.in_polygons): polygons.append(polygon) except ShapefileException as e: logger.error(e) sys.exit(3) else: logger.error('File "%s" is not a i2s or shp file.' % args.in_polygons) sys.exit(2) 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))] # Read Serafin file with Serafin.Read(args.in_slf, args.lang) as resin: resin.read_header() logger.info(resin.header.summary()) resin.get_time() if not resin.header.is_2d: logger.error('The file has to be a 2D Serafin!') sys.exit(3) # Check variables consistency if args.upper_var not in resin.header.var_IDs: logger.error('Upper variable "%s" is not in Serafin file' % args.upper_var) sys.exit(1) upper_var = args.upper_var lower_var = args.lower_var if args.lower_var is not None: if args.lower_var == 'init': lower_var = VolumeCalculator.INIT_VALUE else: if lower_var not in resin.header.var_IDs: logger.error('Lower variable "%s" is not in Serafin file' % lower_var) sys.exit(1) if args.detailed: volume_type = VolumeCalculator.POSITIVE else: volume_type = VolumeCalculator.NET calculator = VolumeCalculator(volume_type, upper_var, lower_var, resin, names, polygons, args.ech) calculator.construct_triangles(tqdm) calculator.construct_weights(tqdm) result = [] for time_index in tqdm(calculator.time_indices, unit='frame'): i_result = [str(resin.time[time_index])] values = calculator.read_values_in_frame(time_index) for j in range(len(calculator.polygons)): weight = calculator.weights[j] volume = calculator.volume_in_frame_in_polygon( weight, values, calculator.polygons[j]) if calculator.volume_type == VolumeCalculator.POSITIVE: for v in volume: i_result.append(settings.FMT_FLOAT.format(v)) else: i_result.append(settings.FMT_FLOAT.format(volume)) result.append(i_result) # Write CSV mode = 'w' if args.force else 'x' with open(args.out_csv, mode) as out_csv: calculator.write_csv(result, out_csv, args.sep)
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)