8000 Add scale_voltage_current_power to ModelChain.pvwatts_dc by cwhanse · Pull Request #1138 · pvlib/pvlib-python · GitHub
[go: up one dir, main page]

Skip to content

Add scale_voltage_current_power to ModelChain.pvwatts_dc #1138

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jan 21, 2021
Prev Previous commit
Next Next commit
handle tuples, use temporary DataFrame
  • Loading branch information
cwhanse committed Jan 21, 2021
commit 917737a9dab8fabc32db04e721fc169cc19f3568
13 changes: 11 additions & 2 deletions pvlib/modelchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -747,10 +747,19 @@ def pvwatts_dc(self):
"""
self.results.dc = self.system.pvwatts_dc(
self.results.effective_irradiance, self.results.cell_temperature)
self.results.dc = self.system.scale_voltage_current_power(
self.results.dc,
if isinstance(self.results.dc, tuple):
temp = tuple(
pd.DataFrame(s, columns=['p_mp']) for s in self.results.dc)
else:
temp = pd.DataFrame(self.results.dc, columns=['p_mp'])
scaled = self.system.scale_voltage_current_power(
temp,
unwrap=False
)
if isinstance(scaled, tuple):
self.results.dc = tuple(pd.Series(s) for s in scaled)
else:
self.results.dc = pd.Series(scaled)
return self

@property
Expand Down
29 changes: 10 additions & 19 deletions pvlib/pvsystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -891,7 +891,7 @@ def scale_voltage_current_power(self, data):
Parameters
----------
data: DataFrame or tuple of DataFrame
Must contain columns `'v_mp', 'v_oc', 'i_mp' ,'i_x', 'i_xx',
May contain columns `'v_mp', 'v_oc', 'i_mp' ,'i_x', 'i_xx',
'i_sc', 'p_mp'`.

Returns
Expand Down Expand Up @@ -2631,18 +2631,17 @@ def scale_voltage_current_power(data, voltage=1, current=1):

Parameters
----------
data: DataFrame or Series
data: DataFrame
May contain columns `'v_mp', 'v_oc', 'i_mp' ,'i_x', 'i_xx',
'i_sc', 'p_mp'`. If Series, the content must be indicated using
one of these keys as the Series name.
'i_sc', 'p_mp'`.
voltage: numeric, default 1
The amount by which to multiply the voltages.
current: numeric, default 1
The amount by which to multiply the currents.

Returns
-------
scaled_data: DataFrame or Series
scaled_data: DataFrame
A scaled copy of the input data.
`'p_mp'` is scaled by `voltage * current`.
"""
Expand All @@ -2653,20 +2652,12 @@ def scale_voltage_current_power(data, voltage=1, current=1):
current_keys = ['i_mp', 'i_x', 'i_xx', 'i_sc']
power_keys = ['p_mp']
data = data.copy()
if isinstance(data, pd.DataFrame):
voltages = voltage_keys and data.columns
currents = current_keys and data.columns
powers = power_keys and data.columns
data[voltages] *= voltage
data[currents] *= current
data[powers] *= voltage * current
else:
if data.name in voltage_keys:
data *= voltage
elif data.name in current_keys:
data *= current
elif data.name in power_keys:
data *= voltage * current
voltages = voltage_keys and data.columns
currents = current_keys and data.columns
powers = power_keys and data.columns
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking of something like this:

In [28]: voltage = 5

In [29]: current = 10

In [30]: df = pd.DataFrame([[1, 1, 1]], columns=['p_mp', 'v_mp', 'i_mp'])

In [31]: df
Out[31]:
   p_mp  v_mp  i_mp
0     1     1     1

In [32]:     voltage_keys = ['v_mp', 'v_oc']
    ...:     current_keys = ['i_mp', 'i_x', 'i_xx', 'i_sc']
    ...:     power_keys = ['p_mp']

In [33]: df.filter(voltage_keys, axis=1) * voltage
Out[33]:
   v_mp
0     5

In [34]: df.filter(current_keys, axis=1) * current
Out[34]:
   i_mp
0    10

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In [35]: voltage_df = df.filter(voltage_keys, axis=1) * voltage

In [36]: current_df = df.filter(current_keys, axis=1) * current

In [37]: df = pd.concat([voltage_df, current_df], axis=1)

In [38]: df['p_mp'] = df['v_mp'] * df['i_mp']

In [39]: df
Out[39]:
   v_mp  i_mp  p_mp
0     5    10    50

Copy link
Member
@wholmgren wholmgren Jan 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know how to scale a power other than p_mp without hugely complicating the code. I also don't know that there's a need for it at this time.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pvwatts methods don't produce voltage or current.

Copy link
Member
@wholmgren wholmgren Jan 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was still in the mindset that we could provide a DataFrame with p_mp=pdc, v_mp=pdc, and i_mp=1 as I suggested above. But yes it is better to just multiply the power keys by the voltage and current scale factors.

In [42]: df = pd.DataFrame([[1, 1, 1]], columns=['p_mp', 'v_mp', 'i_mp'])

In [43]: voltage_df = df.filter(voltage_keys, axis=1) * voltage

In [44]: current_df = df.filter(current_keys, axis=1) * current

In [45]: power_df = df.filter(power_keys, axis=1) * voltage * current

In [49]: concat_df = pd.concat([voltage_df, current_df, power_df], axis=1)

In [50]: concat_df = concat_df[df.columns]

In [51]: concat_df
Out[51]:
   p_mp  v_mp  i_mp
0    50     5    10

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One issue with the temporary DataFrame: when converting back to Series, the column label 'p_mp' is assigned to the Series name, which affect 8FB7 s testing but likely no user code. Any concern here?

Copy link
Member
@wholmgren wholmgren Jan 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no concern. pandas assert_series_equal only recently started checking that attribute and it was a fair bit of work to fix all of the newly broken tests in the Arbiter.

data[voltages] *= voltage
data[currents] *= current
data[powers] *= voltage * current
return data


Expand Down
0