Skip to content

Commit

Permalink
Merge branch 'develop' of https://github.com/e2nIEE/pandapower into d…
Browse files Browse the repository at this point in the history
…evelop
  • Loading branch information
jwiemer112 committed Feb 12, 2021
2 parents 8612995 + 765b89e commit 13a69d6
Show file tree
Hide file tree
Showing 16 changed files with 63 additions and 60 deletions.
2 changes: 1 addition & 1 deletion pandapower/converter/pypower/to_ppc.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def to_ppc(net, calculate_voltage_angles=False, trafo_model="t", switch_rx_ratio
**switch_rx_ratio** (float, 2) - rx_ratio of bus-bus-switches. If impedance is zero, \
buses connected by a closed bus-bus switch are fused to model an ideal bus. \
Otherwise, they are modelled as branches with resistance defined as z_ohm column in \
switch table and this parameter
switch table and this parameter
**check_connectivity** (bool, True) - Perform an extra connectivity test after the
conversion from pandapower to PYPOWER
Expand Down
6 changes: 1 addition & 5 deletions pandapower/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ def create_empty_network(name="", f_hz=50., sn_mva=1, add_stdtypes=True):
('order', "float64"),
('level', dtype(object)),
('initial_run', "bool"),
("recycle", "bool"),
("recycle", dtype(object)),
],
# geodata
"line_geodata": [("coords", dtype(object))],
Expand Down Expand Up @@ -3345,10 +3345,6 @@ def create_measurement(net, meas_type, element_type, value, std_dev, element, si
4.5 MVar line measurement with 0.1 MVar standard deviation on the "to_bus" side of line 2
create_measurement(net, "q", "line", 2, 4.5, 0.1, "to")
"""
if meas_type in ("p", "q") and element_type == "bus":
logger.warning("Attention! Signing system of P,Q measurement of buses now changed to load "
"reference (match pandapower res_bus pq)!")

if meas_type not in ("v", "p", "q", "i", "va", "ia"):
raise UserWarning("Invalid measurement type ({})".format(meas_type))

Expand Down
8 changes: 4 additions & 4 deletions pandapower/estimation/algorithm/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def initialize(self, eppci: ExtendedPPCI):
self.pp_meas_indices = eppci.pp_meas_indices
self.check_observability(eppci, eppci.z)

def estimate(self, ppci: ExtendedPPCI, **kwargs):
def estimate(self, eppci: ExtendedPPCI, **kwargs):
# Must be implemented individually!!
pass

Expand All @@ -76,7 +76,7 @@ def __init__(self, tolerance, maximum_iterations, logger=std_logger):
self.H = None
self.hx = None

def estimate(self, eppci, **kwargs):
def estimate(self, eppci: ExtendedPPCI, **kwargs):
self.initialize(eppci)
# matrix calculation object
sem = BaseAlgebra(eppci)
Expand Down Expand Up @@ -129,7 +129,7 @@ def estimate(self, eppci, **kwargs):


class WLSZeroInjectionConstraintsAlgorithm(BaseAlgorithm):
def estimate(self, eppci, **kwargs):
def estimate(self, eppci: ExtendedPPCI, **kwargs):
# state vector built from delta, |V| and zero injections
# Find pq bus with zero p,q and shunt admittance
if not np.any(eppci["bus"][:, bus_cols + ZERO_INJ_FLAG]):
Expand Down Expand Up @@ -199,7 +199,7 @@ def estimate(self, eppci, **kwargs):


class IRWLSAlgorithm(BaseAlgorithm):
def estimate(self, eppci, estimator="wls", **kwargs):
def estimate(self, eppci: ExtendedPPCI, estimator="wls", **kwargs):
self.initialize(eppci)

# matrix calculation object
Expand Down
15 changes: 8 additions & 7 deletions pandapower/estimation/algorithm/estimator.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def create_cost_jacobian(self, E):
# dr/dE = drho / dr * d(z-hx) / dE
# dr/dE = (drho/dr) * - (d(hx)/dE)
# 2 * rx * (1/sigma**2)* -(dhx/dE)
rx = self.create_rx(E)
rx = self.create_rx(E)
hx_jac = self.create_hx_jacobian(E)
drho_dr = 2 * (rx * (1/self.sigma**2))
jac = - np.sum(drho_dr.reshape((-1, 1)) * hx_jac, axis=0)
Expand All @@ -83,11 +83,11 @@ def __init__(self, eppci: ExtendedPPCI, **hyperparameters):

def create_phi(self, E):
r = self.create_rx(E)
chi2_res, w = self.weight(E)
_, w = self.weight(E)
rsi = r / (w * self.sigma)
phi = 1/(self.sigma**2)
condition_mask = np.abs(rsi)>self.a
phi[condition_mask] = (1/(self.sigma**2) * np.abs(self.a / rsi))[condition_mask]
phi[condition_mask] = (1/(self.sigma**2) * np.abs(self.a / rsi))[condition_mask]
return np.diagflat(phi)

def weight(self, E):
Expand All @@ -97,7 +97,8 @@ def weight(self, E):
ps = self._ps(H)
return chi2_res, np.min(np.c_[(chi2_res/ps)**2, np.ones(ps.shape)], axis=1)

def _ps(self, H):
@staticmethod
def _ps(H):
omega = np.dot(H, H.T)

x = np.zeros(omega.shape[0]-1)
Expand Down Expand Up @@ -180,7 +181,7 @@ def create_cost_jacobian(self, E):

class QLEstimatorOpt(BaseEstimatorOpt):
def __init__(self, eppci, **hyperparameters):
super(QLEstimatorOpt, self).__init__(eppci, **hyperparameters)
super(QLEstimatorOpt, self).__init__(eppci, **hyperparameters)
assert 'a' in hyperparameters
self.a = hyperparameters['a']

Expand All @@ -203,6 +204,6 @@ def create_cost_jacobian(self, E):
drho_dr = 2 * (rx * (1/self.sigma)**2)
large_dev_mask = np.abs(rx/self.sigma) > self.a
if np.any(large_dev_mask):
drho_dr[large_dev_mask] = (np.sign(rx)* (1/self.sigma))[large_dev_mask]
jac = - np.sum(drho_dr.reshape((-1, 1)) * hx_jac, axis=0)
drho_dr[large_dev_mask] = (np.sign(rx)* (1/self.sigma))[large_dev_mask]
jac = - np.sum(drho_dr.reshape((-1, 1)) * hx_jac, axis=0)
return jac
6 changes: 4 additions & 2 deletions pandapower/estimation/algorithm/lp.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@
from scipy.optimize import linprog
import warnings

from pandapower.estimation.ppc_conversion import ExtendedPPCI
from pandapower.estimation.algorithm.base import BaseAlgorithm
from pandapower.estimation.algorithm.matrix_base import BaseAlgebra


class LPAlgorithm(BaseAlgorithm):
def estimate(self, eppci, **kwargs):
def estimate(self, eppci: ExtendedPPCI, **kwargs):
if "estimator" in kwargs and kwargs["estimator"].lower() != "lav": # pragma: no cover
self.logger.warning("LP Algorithm supports only LAV Estimator!! Set to LAV!!")

Expand Down Expand Up @@ -49,7 +50,8 @@ def estimate(self, eppci, **kwargs):
self.check_result(current_error, cur_it)
return eppci

def solve_lp(self, H, x, r):
@staticmethod
def solve_lp(H, x, r):
n, m = H.shape[1], H.shape[0]
zero_n = np.zeros((n, 1))
one_m = np.ones((m, 1))
Expand Down
14 changes: 7 additions & 7 deletions pandapower/estimation/algorithm/matrix_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,10 @@
# Copyright (c) 2016-2021 by University of Kassel and Fraunhofer Institute for Energy Economics
# and Energy System Technology (IEE), Kassel. All rights reserved.

import warnings
import numpy as np
from scipy.sparse import vstack, hstack, diags
from scipy.sparse import csr_matrix as sparse
from scipy.sparse import vstack, hstack

from pandapower.pypower.idx_brch import F_BUS, T_BUS
from pandapower.pypower.makeYbus import makeYbus
from pandapower.pypower.dSbus_dV import dSbus_dV
from pandapower.pypower.dSbr_dV import dSbr_dV
from pandapower.pypower.dIbr_dV import dIbr_dV
Expand All @@ -21,6 +18,7 @@

class BaseAlgebra:
def __init__(self, eppci: ExtendedPPCI):
"""Object to calculate matrices required in state-estimation iterations."""
self.eppci = eppci

self.fb = eppci['branch'][:, F_BUS].real.astype(int)
Expand Down Expand Up @@ -140,11 +138,13 @@ def _dSbr_dv(self, V):
dSf_dth, dSf_dv, dSt_dth, dSt_dv, _, _ = dSbr_dV(self.eppci['branch'], self.Yf, self.Yt, V)
return dSf_dth, dSf_dv, dSt_dth, dSt_dv

def _dvmbus_dV(self, V):
@staticmethod
def _dvmbus_dV(V):
dvm_dth, dvm_dv = np.zeros((V.shape[0], V.shape[0])), np.eye(V.shape[0], V.shape[0])
return dvm_dth, dvm_dv

def _dvabus_dV(self, V):
@staticmethod
def _dvabus_dV(V):
dva_dth, dva_dv = np.eye(V.shape[0], V.shape[0]), np.zeros((V.shape[0], V.shape[0]))
return dva_dth, dva_dv

Expand All @@ -160,7 +160,7 @@ def _dimiabr_dV(self, V):
difa_dv = (np.angle(1e-5 * dif_dv + If.reshape((-1, 1))) - np.angle(If.reshape((-1, 1))))/1e-5
dita_dth = (np.angle(1e-5 * dit_dth + It.reshape((-1, 1))) - np.angle(It.reshape((-1, 1))))/1e-5
dita_dv = (np.angle(1e-5 * dit_dv + It.reshape((-1, 1))) - np.angle(It.reshape((-1, 1))))/1e-5
return difm_dth, difm_dv, ditm_dth, ditm_dv, difa_dth, difa_dv, dita_dth, dita_dv
return difm_dth, difm_dv, ditm_dth, ditm_dv, difa_dth, difa_dv, dita_dth, dita_dv


class BaseAlgebraZeroInjConstraints(BaseAlgebra):
Expand Down
9 changes: 4 additions & 5 deletions pandapower/estimation/algorithm/optimization.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,22 @@

from scipy.optimize import minimize

from pandapower.estimation.ppc_conversion import ExtendedPPCI
from pandapower.estimation.algorithm.base import BaseAlgorithm
from pandapower.estimation.algorithm.estimator import BaseEstimatorOpt, get_estimator

# DEFAULT_OPT_METHOD = "Newton-CG"
DEFAULT_OPT_METHOD = "TNC"


# DEFAULT_OPT_METHOD = "SLSQP"
# DEFAULT_OPT_METHOD = 'L-BFGS-B'


class OptAlgorithm(BaseAlgorithm):
def estimate(self, eppci, estimator="wls", **opt_vars):
opt_method = DEFAULT_OPT_METHOD if 'opt_method' not in opt_vars else opt_vars['opt_method']
def estimate(self, eppci: ExtendedPPCI, estimator="wls", **kwargs):
opt_method = DEFAULT_OPT_METHOD if 'opt_method' not in kwargs else kwargs['opt_method']

# matrix calculation object
estm = get_estimator(BaseEstimatorOpt, estimator)(eppci, **opt_vars)
estm = get_estimator(BaseEstimatorOpt, estimator)(eppci, **kwargs)

jac = estm.create_cost_jacobian
res = minimize(estm.cost_function, x0=eppci.E,
Expand Down
2 changes: 1 addition & 1 deletion pandapower/estimation/ppc_conversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ def pp2eppci(net, v_start=None, delta_start=None,

class ExtendedPPCI(UserDict):
def __init__(self, ppci):
# Initialize ppci with measurements
"""Initialize ppci object with measurements."""
self.data = ppci

# Measurement relevant parameters
Expand Down
10 changes: 5 additions & 5 deletions pandapower/estimation/state_estimation.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,19 +50,19 @@ def estimate(net, algorithm='wls',
**calculate_voltage_angles** - (boolean) - Take into account absolute voltage angles and phase
shifts in transformers, if init is 'slack'. Default is True
**zero_injection** - (str, iterable, None) - Defines which buses are zero injection bus or the method
to identify zero injection bus, with 'wls_estimator' virtual measurements will be added, with
to identify zero injection bus, with 'wls_estimator' virtual measurements will be added, with
'wls_estimator with zero constraints' the buses will be handled as constraints
"auto": all bus without p,q measurement, without p, q value (load, sgen...) and aux buses will be
identified as zero injection bus
identified as zero injection bus
"aux_bus": only aux bus will be identified as zero injection bus
None: no bus will be identified as zero injection bus
iterable: the iterable should contain index of the zero injection bus and also aux bus will be identified
as zero-injection bus
**fuse_buses_with_bb_switch** - (str, iterable, None) - Defines how buses with closed bb switches should
be handled, if fuse buses will only fused to one for calculation, if not fuse, an auxiliary bus and
**fuse_buses_with_bb_switch** - (str, iterable, None) - Defines how buses with closed bb switches should
be handled, if fuse buses will only fused to one for calculation, if not fuse, an auxiliary bus and
auxiliary line will be automatically added to the network to make the buses with different p,q injection
measurements identifieble
"all": all buses with bb-switches will be fused, the same as the default behaviour in load flow
Expand Down
2 changes: 1 addition & 1 deletion pandapower/estimation/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ def add_virtual_pmu_meas_from_loadflow(net, v_std_dev=0.001, i_std_dev=0.1,
'trafo3w': {'side': ('hv', 'mv', 'lv'),
'meas_type': ('i_ka', 'ia_degree', 'p_mw', 'q_mvar')}}

# Added degree result for branches
# Added degree result for branches
for br_type in branch_meas_type.keys():
for side in branch_meas_type[br_type]['side']:
p, q, vm, va = net["res_" + br_type]["p_%s_mw" % side].values, \
Expand Down
16 changes: 10 additions & 6 deletions pandapower/plotting/collections.py
Original file line number Diff line number Diff line change
Expand Up @@ -314,8 +314,9 @@ def _create_complex_branch_collection(coords, patch_maker, size=1, infos=None, r
infos_pc = list(np.repeat(infos, repeat_infos[0]))
infos_lc = list(np.repeat(infos, repeat_infos[1]))

lines, patches, popped_keywords = patch_maker(coords, size, patch_facecolor=patch_facecolor,
patch_edgecolor=patch_edgecolor, linewidths=linewidths, **kwargs)
lines, patches, popped_keywords = patch_maker(
coords, size, patch_facecolor=patch_facecolor, patch_edgecolor=patch_edgecolor,
linewidths=linewidths, **kwargs)
for kw in set(popped_keywords) & set(kwargs.keys()):
kwargs.pop(kw)
patch_coll = PatchCollection(patches, match_original=True, picker=picker, **kwargs)
Expand Down Expand Up @@ -908,7 +909,7 @@ def create_gen_collection(net, gens=None, size=1., infofunc=None, orientation=np
"""
gens = get_index_array(gens, net.gen.index)
infos = [infofunc(i) for i in range(len(gens))] if infofunc is not None else []
node_coords = net.bus_geodata.loc[:, ["x", "y"]].values[net.gen.loc[gens, "bus"].values]
node_coords = net.bus_geodata.loc[net.gen.loc[gens, "bus"].values, ["x", "y"]].values
gen_pc, gen_lc = _create_node_element_collection(
node_coords, gen_patches, size=size, infos=infos, orientation=orientation,
picker=picker, **kwargs)
Expand Down Expand Up @@ -950,16 +951,18 @@ def create_sgen_collection(net, sgens=None, size=1., infofunc=None, orientation=
picker=picker, **kwargs)
return sgen_pc, sgen_lc

def create_storage_collection(net, storages=None, size=1., infofunc=None, orientation=np.pi, picker=False,
**kwargs):

def create_storage_collection(net, storages=None, size=1., infofunc=None, orientation=np.pi,
picker=False, **kwargs):
"""
Creates a matplotlib patch collection of pandapower storage element.
Input:
**net** (pandapowerNet) - The pandapower network
OPTIONAL:
**storages** (list of ints, None) - the net.storage.index values to include in the collection
**storages** (list of ints, None) - the net.storage.index values to include in the
collection
**size** (float, 1) - patch size
Expand All @@ -984,6 +987,7 @@ def create_storage_collection(net, storages=None, size=1., infofunc=None, orient
picker=picker, **kwargs)
return storage_pc, storage_lc


def create_ext_grid_collection(net, size=1., infofunc=None, orientation=0, picker=False,
ext_grids=None, ext_grid_buses=None, **kwargs):
"""
Expand Down
3 changes: 1 addition & 2 deletions pandapower/plotting/patch_makers.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,8 +210,7 @@ def gen_patches(node_coords, size, angles, **kwargs):
polys.append(
Arc(p2 + np.array([size / 6.2, size / 2.6]), size / 2, size, theta1=245, theta2=300,
ec=edgecolors[i]))
print("Arc:", polys[-1])
lines.append((node_geo, p2 + np.array([0, size])))
lines.append((node_geo, p2 + _rotate_dim2(np.array([0, size]), -all_angles[i])))
return lines, polys, {"offset", "patch_edgecolor", "patch_facecolor"}


Expand Down
2 changes: 2 additions & 0 deletions pandapower/plotting/plotly/mapbox_plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,10 @@ def geo_data_to_latlong(net, projection):
logger.warning('Geo-coordinates check cannot be peformed because pyproj package not available \n\t--> '
'if geo-coordinates are not in lat/lon format an empty plot may appear...')
return

if projection == 'epsg:4326':
return

wgs84 = Proj(init='epsg:4326') # lat/long

try:
Expand Down
4 changes: 2 additions & 2 deletions pandapower/pypower/makeLODF.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
# Copyright (c) 2016-2021 by University of Kassel and Fraunhofer Institute for Energy Economics
# and Energy System Technology (IEE), Kassel. All rights reserved.

"""Builds the line outage distribution factor matrix.
"""
# Builds the line outage distribution factor matrix.


from numpy import ones, diag, r_, arange
import numpy as np
Expand Down
4 changes: 2 additions & 2 deletions pandapower/pypower/makePTDF.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
# Copyright (c) 2016-2021 by University of Kassel and Fraunhofer Institute for Energy Economics
# and Energy System Technology (IEE), Kassel. All rights reserved.

"""Builds the DC PTDF matrix for a given choice of slack.
"""
# Builds the DC PTDF matrix for a given choice of slack.


from sys import stderr

Expand Down
Loading

0 comments on commit 13a69d6

Please sign in to comment.