class CloneProject(Worker): ''' worker for cloning a project ''' def __init__(self, project_name, project, parent=None): super().__init__(parent=parent) self.project_name = project_name self.origin_project = project self.project_manager = ProjectManager() def work(self): cloned_project = self.project_manager.create_project( self.project_name, create_folder=False) self.log('Kopiere Projektordner...') # copy template folder try: shutil.copytree(self.origin_project.path, cloned_project.path) except Exception as e: self.error.emit(str(e)) self.project_manager.remove_project(self.project_name) return self.log('Neues Projekt erfolgreich angelegt ' f'unter {cloned_project.path}') return cloned_project
def create(self, **kwargs): area = kwargs['area'] features = Gewerbeanteile.features().filter(id_teilflaeche=area.id) df = features.to_pandas() basedata = ProjectManager().basedata df_branchen = basedata.get_table('Gewerbe_Branchen', 'Definition_Projekt').to_pandas() colors = plt.cm.Accent(np.linspace(0, 1, len(df))) idx = df['anteil_branche'] > 0 df = df[idx] colors = colors[idx] df_branchen.rename(columns={'ID_Branche_ProjektCheck': 'id_branche'}, inplace=True) joined = df.merge(df_branchen, on='id_branche') figure = plt.figure() subplot = figure.add_subplot(111) ax = joined['anteil_branche'].plot( kind='pie', labels=[''] * len(df), autopct='%.0f%%', figsize=(8, 8), title=' ', #shadow=True, #explode=[0.1] * len(table_df), colors=colors, ax=subplot) #title = ax.set_title(self.title) #title.set_position((.5, 1.0)) plt.figtext(.5, .92, self.title, horizontalalignment='center', fontsize=12) #, fontweight='bold') ax.set_ylabel('') ax.set_xlabel('') ax.legend(joined['Name_Branche_ProjektCheck'], loc='upper center', bbox_to_anchor=(0.5, 0.05)) # didn't find a way to pass custom colors directly for color, handle in zip(colors, ax.get_legend().legendHandles): handle.set_linewidth(2.0) handle.set_color(color) box = ax.get_position() ax.set_position([box.x0, box.y0 + box.y0 * 0.5, box.width, box.height]) figure.tight_layout() figure.subplots_adjust(bottom=0.2) return figure
def setUpClass(cls): cls.project_manager = ProjectManager() cls.project_manager.basedata = Geopackage(base_path='.', read_only=True) if cls.projectname in [p.name for p in cls.project_manager.projects]: cls.project_manager.remove_project(cls.projectname) cls.workspace = None
def setUpClass(cls): cls.project_manager = ProjectManager() if cls.projectname in [p.name for p in cls.project_manager.projects]: cls.project_manager.remove_project(cls.projectname) cls.project = cls.project_manager.create_project(cls.projectname) cls.project_manager.active_project = cls.project cls.workspace = None
def create(self, **kwargs): project = kwargs.get('project', ProjectManager().active_project) self.title = (f'{project.name}: Kosten der punktuellen Maßnahmen ' '(nur erstmalige Herstellung)') x_label = ('Kosten der punktuellen Maßnahmen ' '(nur erstmalige Herstellung)') point_df = ErschliessungsnetzPunkte.features(create=True).to_pandas() base_df = project.basedata.get_table('Netze_und_Netzelemente', 'Kosten', fields=['IDNetz', 'Netz']).to_pandas() # duplicate entries for 'IDNetz'/'Netz' combinations del base_df['fid'] base_df.drop_duplicates(inplace=True) joined = point_df.merge(base_df, on='IDNetz', how='right') joined.fillna(0, inplace=True) grouped = joined.groupby(by='IDNetz') categories = [] costs = [] for id_netz, grouped_df in grouped: categories.append(grouped_df['Netz'].values[0]) costs.append(grouped_df['Euro_EH'].sum()) figure, ax = plt.subplots(figsize=(10, 5)) y_pos = np.arange(len(categories)) bar_width = 0.5 patches = ax.barh(y_pos, costs, height=bar_width, align='center') text_offset = max([ patch.get_x() + patch.get_width() for patch in patches.get_children() ]) * 0.02 for i, patch in enumerate(patches.get_children()): width = patch.get_x() + patch.get_width() y = patch.get_y() + bar_width / 2 ax.text(width + text_offset, y, locale.format_string("%d", width, grouping=True) + ' €', color='black', ha='left', va='center') x_min, x_max = ax.get_xlim() ax.set_xlim(x_min, x_max * 1.2) ax.set_yticks(y_pos) ax.set_yticklabels(categories) ax.set_title(self.title) ax.set_xlabel(x_label) ax.get_xaxis().set_major_formatter( mticker.FuncFormatter(lambda x, p: locale.format_string( "%d", x, grouping=True) + ' €')) ax.xaxis.grid(True, which='major') box = ax.get_position() ax.set_position( [box.x0 + box.width * 0.12, box.y0, box.width * 0.88, box.height]) return figure
def next_working_day(min_days_infront=2): ''' get the next working day in germany (no holidays, no saturdays, no sundays in all federal states) requires the basetable "Feriendichte" to hold days infront of today Parameters ---------- min_days_infront : int (default: 2) returned day will be at least n days infront Returns ------- datetime.date the next day without holidays, if day is out of range of basetable: today + min_days_infront ''' today = np.datetime64(date.today()) basedata = ProjectManager().basedata day = today + np.timedelta64(min_days_infront,'D') # get working days (excl. holidays) where = ("Wochentag <> 'Samstag' and " "Wochentag <> 'Sonntag' and " "Anteil_Ferien_Bevoelkerung = 0") table = basedata.get_table('Feriendichte', 'Basisdaten_deutschland') table.where = where df_density = table.to_pandas() # can't compare directly because datetime64 has no length dates = pd.to_datetime(df_density['Datum'], format='%Y/%m/%d %H:%M:%S.%f') df_density['Datum'] = dates.dt.tz_convert(None) df_density.sort_values('Datum', inplace=True) infront = np.where(df_density['Datum'] >= day)[0] if len(infront) > 0: # get the first day matching all conditions day = df_density.iloc[infront[0]]['Datum'] return pd.Timestamp(day).date()
def create(self, **kwargs): project = kwargs.get('project', ProjectManager().active_project) self.title = (f'{project.name}: Länge der zusätzlichen ' 'Infrastrukturnetze (ohne punktuelle Maßnahmen)') x_label = u"Meter zusätzliche Netzlänge (ohne punktuelle Maßnahmen)" linien_df = ErschliessungsnetzLinien.features(create=True).to_pandas() base_df = project.basedata.get_table('Netze_und_Netzelemente', 'Kosten', fields=['IDNetz', 'Netz']).to_pandas() # duplicate entries for 'IDNetz'/'Netz' combinations del base_df['fid'] base_df.drop_duplicates(inplace=True) joined = linien_df.merge(base_df, on='IDNetz', how='right') joined.fillna(0, inplace=True) grouped = joined.groupby(by='IDNetz') categories = [] lengths = [] for id_netz, grouped_df in grouped: categories.append(grouped_df['Netz'].values[0]) lengths.append(grouped_df['length'].sum()) figure, ax = plt.subplots(figsize=(10, 5)) ax.tick_params(axis='both', which='major', labelsize=9) y_pos = np.arange(len(categories)) bar_width = 0.5 patches = ax.barh(y_pos, lengths, height=bar_width, align='center') # Anfang Barlabels text_offset = max([ patch.get_x() + patch.get_width() for patch in patches.get_children() ]) * 0.02 for i, patch in enumerate(patches.get_children()): width = patch.get_x() + patch.get_width() y = patch.get_y() ax.text(width + text_offset, y + bar_width / 2, locale.format_string("%d", width, grouping=True) + ' m', color='black', ha='left', va='center') x_min, x_max = ax.get_xlim() ax.set_xlim(x_min, x_max * 1.2) # Ende Barlabels ax.set_yticks(y_pos) ax.set_yticklabels(categories) ax.set_title(self.title) ax.set_xlabel(x_label) ax.xaxis.grid(True, which='major') ax.get_xaxis().set_major_formatter( mticker.FuncFormatter(lambda x, p: locale.format_string( "%d", x, grouping=True) + ' m')) box = ax.get_position() ax.set_position( [box.x0 + box.width * 0.12, box.y0, box.width * 0.88, box.height]) return figure
def create(self, **kwargs): project = kwargs.get('project', ProjectManager().active_project) self.title = (f'Vergleich: Erschließungskosten pro {self._unit} ' '(in den ersten 25 Jahren)') x_label = (f'Gesamtkosten der Erschließung pro {self._unit} ' '(in den ersten 25 Jahren)') tou = self._type_of_use.value df_areas = Teilflaechen.features(project=project).filter( nutzungsart=tou).to_pandas() df_reference = project.basedata.get_table('Vergleichswerte', 'Kosten').to_pandas() df_costs = Gesamtkosten.features(project=project).to_pandas() # there is only one row for each type of use df_reference = df_reference[df_reference['IDNutzungsart'] == tou].iloc[0] x = df_areas[self._column].sum() total_costs = df_costs['Euro'].sum() costs_per_x = int((total_costs / x) / 1000) * 1000 if x > 0 else 0 reference = df_reference['Wert'] categories = [ u'Vergleichswert (Schätzung):\n{}'.format( df_reference['Beschreibung']), f'Projekt "{project.name}" (alle Netze, ' '\nKostenphasen und Kostenträger)' ] categories = ['\n'.join(wrap(c, 40)) for c in categories] figure, ax = plt.subplots(figsize=(9, 4)) y_pos = np.arange(len(categories)) bar_width = 0.5 patches = ax.barh(y_pos, [reference, costs_per_x], height=bar_width, align='center') #, color=[ '#99aaff', '#2c64ff']) # Anfang Barlabels text_offset = max([ patch.get_x() + patch.get_width() for patch in patches.get_children() ]) * 0.02 for i, patch in enumerate(patches.get_children()): width = patch.get_x() + patch.get_width() y = patch.get_y() ax.text(width + text_offset, y + bar_width / 2, locale.format_string("%d", width, grouping=True) + ' €', color='black', ha='left', va='center') x_min, x_max = ax.get_xlim() ax.set_xlim(x_min, x_max * 1.2) # Ende Barlabels ax.tick_params(axis='both', which='major', labelsize=9) ax.set_yticks(y_pos) ax.set_yticklabels(categories) ax.set_title(self.title) ax.set_xlabel(x_label) ax.get_xaxis().set_major_formatter( mticker.FuncFormatter(lambda x, p: locale.format_string( "%d", x, grouping=True) + ' €')) ax.xaxis.grid(True, which='major') box = ax.get_position() ax.set_position( [box.x0 + box.width * 0.2, box.y0, box.width * 0.8, box.height]) return figure
def create(self, **kwargs): project = kwargs.get('project', ProjectManager().active_project) years = kwargs.get('years', 20) self.title = (f'{project.name}: Aufteilung der Gesamtkosten ' 'auf die Kostenträger') y_label = ('Kosten der erstmaligen Herstellung, \n' 'Betriebs- und Unterhaltungskosten in den \n' f'ersten {years} Jahren sowie Erneuerungskosten \n' f'(anteilig für die ersten {years} Jahre)') df_shares = GesamtkostenTraeger.get_table(project=project).to_pandas() df_shareholders = project.basedata.get_table('Kostentraeger', 'Kosten').to_pandas() categories = df_shareholders['Kostentraeger'] cols = df_shareholders['spalte'] pos_idx = np.arange(len(categories)) figure, ax = plt.subplots(figsize=(12, 5)) colors = self.colors summed = np.zeros(len(cols)) for j, (index, net_share) in enumerate(df_shares.iterrows()): data = [] for i, col in enumerate(cols): data.append(net_share[col]) patches = ax.bar(pos_idx, data, bottom=summed, color=colors[j]) for i, rect in enumerate(patches.get_children()): value = data[i] bottom = summed[i] if value != 0: color = 'black' if j in [1, 2]: color = 'white' ax.text(i, bottom + value / 2., locale.format_string("%d", value, grouping=True) + ' €', ha='center', va='center', color=color) summed += data ax.set_xticks(pos_idx) ax.set_xticklabels(categories) ax.set_title(self.title) ax.set_ylabel(y_label, rotation=90, labelpad=15) ax.get_yaxis().set_major_formatter( mticker.FuncFormatter(lambda y, p: locale.format_string( "%d", y, grouping=True) + ' €')) ax.yaxis.grid(True, which='major') box = ax.get_position() ax.set_position([ box.x0 + box.width * 0.2, box.y0 + box.height * 0.25, box.width * 0.8, box.height * 0.75 ]) # Put the legend to the right of the current axis ax.legend(df_shares['Netz'], loc='center left', bbox_to_anchor=(0, -0.35)) # didn't find a way to pass custom colors directly for color, handle in zip(colors, ax.get_legend().legendHandles): handle.set_color(color) return figure
def create(self, **kwargs): years = kwargs.get('years', 20) project = kwargs.get('project', ProjectManager().active_project) legend = [ '1 - Kosten der erstmaligen Herstellung', '2 - Kosten für Betrieb und Unterhaltung in den ' f'ersten {years} Jahren', '3 - Anteilige Kosten der Erneuerung (bezogen auf ' f'einen Zeitraum von {years} Jahren)' ] self.title = (f"{project.name}: Gesamtkosten der infrastrukturellen " f"Maßnahmen in den ersten {years} Jahren") x_label = u"Kosten für Netzerweiterungen und punktuelle Maßnahmen" df_costs = Gesamtkosten.get_table(project=project).to_pandas() u, u_idx = np.unique(df_costs['Netz'], return_index=True) categories = df_costs['Netz'][np.sort(u_idx)] pos_idx = np.arange(len(categories)) bar_width = 0.2 spacing = 1.15 figure, ax = plt.subplots(figsize=(10, 6)) plt.gca().invert_yaxis() grouped = df_costs.groupby(by='IDKostenphase') phase_names = [] text_offset = max(df_costs['Euro']) * 0.07 if len(df_costs) > 0 else 0 for i, (phase_id, group) in enumerate(grouped): costs = group['Euro'].values patches = ax.barh(pos_idx + i * bar_width * spacing, costs, height=bar_width, align='center') phase_names.append(legend[group['IDKostenphase'].values[0] - 1]) for index, patch in enumerate(patches): width = patch.get_width() ax.text(width + text_offset, pos_idx[index] + i * bar_width * spacing, locale.format_string("%d", width, grouping=True) + ' €', ha='center', va='center') ax.tick_params(axis='both', which='major', labelsize=9) ax.set_yticks(pos_idx + bar_width * spacing) ax.set_yticklabels(categories) ax.set_title(self.title) ax.set_xlabel(x_label) ax.get_xaxis().set_major_formatter( mticker.FuncFormatter(lambda x, p: locale.format_string( "%d", x, grouping=True) + ' €')) ax.xaxis.grid(True, which='major') xmin, xmax = ax.get_xlim() ax.set_xlim(left=None, right=xmax * 1.1, emit=True, auto=False) box = ax.get_position() ax.set_position([ box.x0 + box.width * 0.12, box.y0 + box.height * 0.2, box.width * 0.88, box.height * 0.8 ]) # Put a legend to the right of the current axis ax.legend(phase_names, loc='center left', bbox_to_anchor=(0, -0.3)) return figure
def __init__(self, project_name, area_layer, epsg, parent=None): super().__init__(parent=parent) self.project_name = project_name self.project_manager = ProjectManager() self.area_layer = area_layer self.epsg = epsg
class ProjectInitialization(Worker): ''' worker for creating a new project with some basic setup depending on location and size of the included areas ''' def __init__(self, project_name, area_layer, epsg, parent=None): super().__init__(parent=parent) self.project_name = project_name self.project_manager = ProjectManager() self.area_layer = area_layer self.epsg = epsg def work(self): try: return self.create_project() except Exception as e: if self.project_areas is not None: self.project_areas.workspace.close() self.project_manager.remove_project(self.project) self.log('Projekt nach Fehler wieder entfernt.') raise e def create_project(self): self.project = self.project_manager.create_project(self.project_name) self.project_areas = None source_crs = self.area_layer.crs() target_crs = QgsCoordinateReferenceSystem(f'epsg:{self.epsg}') self.project_areas = Teilflaechen.features(project=self.project, create=True) # remove z-values from imported areas (they might mess up the geometries # later) try: parameters = { 'INPUT': self.area_layer, 'DROP_Z_VALUES': True, 'OUTPUT': 'memory:' } area_layer = processing.run('native:dropmzvalues', parameters)['OUTPUT'] # native:dropmzvalues is not always available (e.g. in tests) except QgsProcessingException: area_layer = self.area_layer layer_features = list(area_layer.getFeatures()) self.log(f'Neues Projekt angelegt im Ordner {self.project.path}') self.set_progress(10) trans_geoms = [] self.log(f'Füge {len(layer_features)} Fläche(n) hinzu...') tr = QgsCoordinateTransform(source_crs, target_crs, QgsProject.instance()) if not layer_features: raise Exception( 'Es wurden keine Flächen im Eingangslayer gefunden') for area in layer_features: geom = area.geometry() geom.transform(tr) trans_geoms.append(geom) # gather additional information about areas basedata = self.project_manager.basedata ags_feats = get_ags(layer_features, basedata, source_crs=source_crs, use_centroid=True) ags = [f.AGS for f in ags_feats] gem_names = [f.GEN for f in ags_feats] gem_types = [f.Gemeindetyp for f in ags_feats] if len(np.unique(ags)) > 1: raise Exception("Die Teilflächen liegen nicht in " "der selben Gemeinde") project_ags = ags[0] centroids = [geom.centroid().asPoint() for geom in trans_geoms] xs = [centroid.x() for centroid in centroids] ys = [centroid.y() for centroid in centroids] project_centroid = QgsPointXY(np.mean(xs), np.mean(ys)) max_dist = getattr(settings, 'MAX_AREA_DISTANCE', None) self.set_progress(33) self.log(f'Überprüfe die Flächenlage...') if max_dist is not None and len(layer_features) > 1: distances = [] for i in range(len(layer_features)): for j in range(i): dist = np.linalg.norm( np.subtract((xs[i], ys[i]), (xs[j], ys[j]))) distances.append(dist) if distances and max(distances) > max_dist: raise Exception("Der Abstand zwischen den Schwerpunkten der " "Teilflächen darf nicht größer " "als {} m sein!".format(max_dist)) self.set_progress(50) traffic_connectors = Connectors.features(project=self.project, create=True) self.log(f'Berechne Projektrahmendaten...') # create areas and connections to roads now = datetime.now() for i, feature in enumerate(layer_features): area = self.project_areas.add( nutzungsart=Nutzungsart.UNDEFINIERT.value, name=f'Flaeche_{i+1}', validiert=0, aufsiedlungsdauer=1, beginn_nutzung=now.year, ags_bkg=ags[i], gemeinde_name=gem_names[i], gemeinde_typ=gem_types[i], geom=trans_geoms[i]) traffic_connectors.add(id_teilflaeche=area.id, name_teilflaeche=area.name, geom=centroids[i]) self.set_progress(50) # general project data project_frame = Projektrahmendaten.features(project=self.project, create=True) local_versions = self.project_manager.local_versions( settings.basedata_path) # newest local version basedata_version = local_versions[0] project_frame.add(ags=ags[0], gemeinde_name=gem_names[0], gemeinde_typ=gem_types[0], projekt_name=self.project.name, geom=project_centroid, datum=now.strftime("%d.%m.%Y"), basisdaten_version=basedata_version['version'], basisdaten_datum=basedata_version['date']) self.set_progress(60) # create selectable centers around the areas for the market competition # domain sk_radius = getattr(settings, 'PROJECT_RADIUS', 20000) self.log( f'Ermittle Gemeinden im Umkreis von {int(sk_radius/1000)} km...') workspace = basedata.get_workspace('Basisdaten_deutschland') vg_table = workspace.get_table('Verwaltungsgemeinschaften') buffer = QgsGeometry.fromPointXY(QgsPointXY(*project_centroid)).buffer( sk_radius, 20) vg_table.spatial_filter(buffer.asWkt()) centers = Centers.features(project=self.project, create=True) rs_list = [] for row in vg_table: centers.add( name=row['GEN'], rs=row['RS'], geom=row['geom'], # -1 indicates that it is a vg for selection and output only nutzerdefiniert=-1) rs_list.append(row['RS']) project_rs = None gem_table = workspace.get_table('bkg_gemeinden') for row in gem_table: cut_rs = row['RS'][:9] ags = row['AGS'] if cut_rs in rs_list: if ags == project_ags: project_rs = cut_rs centers.add( name=row['GEN'], rs=cut_rs, ags=ags, geom=row['geom'], # 0 indicates gemeinden, for calculations only nutzerdefiniert=0) # preselect the VG the project is in if project_rs: project_vg = centers.get(rs=project_rs, nutzerdefiniert=-1) project_vg.auswahl = -1 project_vg.save() self.set_progress(100) return self.project
def __init__(self, project_name, project, parent=None): super().__init__(parent=parent) self.project_name = project_name self.origin_project = project self.project_manager = ProjectManager()