Skip to content

Commit

Permalink
Merge pull request #40 from SPF-OST/38-add-improvements-suggested-by-…
Browse files Browse the repository at this point in the history
…alex

addressed most improvements suggested by alex in : #32
  • Loading branch information
sebastian-swob authored Dec 12, 2024
2 parents 3468db9 + f2903e0 commit fc2b2ae
Show file tree
Hide file tree
Showing 18 changed files with 235 additions and 120 deletions.
22 changes: 14 additions & 8 deletions examples/ready-to-run/processing_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,42 +19,48 @@ def processing_of_monthly_data(simulation: api.Simulation):

# modify label for the y axis
ax.set_ylabel("Power [kW]")
# make label fit inside your plot

# This is also done by api.save_plot, but if you want to see your plot before saving it.
# For example with _plt.show(). Calling this function is required, to make the plot look as expected.
_plt.tight_layout()

# create plots folder inside simulation directory and save plot in configured formats
api.save_plot(fig, simulation.path, "monthly-bar-chart")
api.export_plots_in_configured_formats(
fig, simulation.path, "monthly-bar-chart"
)


def processing_of_hourly_data(simulation: api.Simulation):
# create line plot using hourly data
fig, ax = api.line_plot(simulation.hourly, ["QSrc1TIn", "QSrc1TOut"])

# modify label for the y axis
# Here you can modify anything to do with your plot, according to the matplotlib.pyplot standard
ax.set_ylabel("Temperature [°C]")
# make label fit inside your plot
_plt.tight_layout()

# create plots folder inside simulation directory and save plot in configured formats
api.save_plot(fig, simulation.path, "hourly-line-plot")
api.export_plots_in_configured_formats(
fig, simulation.path, "hourly-line-plot"
)


def processing_for_histogram(simulation: api.Simulation):
# create histogram using hourly data
fig, _ = api.histogram(simulation.hourly, ["QSrc1TIn"])

# create plots folder inside simulation directory and save plot in configured formats
api.save_plot(fig, simulation.path, "histogram")
# if you don't want to export your plot, you can also just show it by calling this function
_plt.show()


if __name__ == "__main__":
# This is the entry point to your script.
# In here you can decide how you would like to run your processing steps.
# Here, you can decide how you would like to run your processing steps.
# In the example below we run both processing steps on a whole result set.
# Or a single processing step on a single simulation.
# Make sure to remove the lines you do not want to run.

# bundle the scenarios into a list
# bundle the steps into a list
processing_scenarios = [
processing_of_monthly_data,
processing_of_hourly_data,
Expand Down
8 changes: 6 additions & 2 deletions pytrnsys_process/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,13 @@
)
from pytrnsys_process.process_sim.process_sim import Simulation

# ============================================================
# this lives here, because it needs to be available everywhere
from pytrnsys_process.settings import settings
from pytrnsys_process.utils import save_plot

# ============================================================

from pytrnsys_process.utils import export_plots_in_configured_formats

__all__ = [
"line_plot",
Expand All @@ -35,6 +39,6 @@
"process_single_simulation",
"process_whole_result_set",
"Simulation",
"save_plot",
"export_plots_in_configured_formats",
"settings",
]
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def convert_sim_results_to_csv(
)

for input_file in input_files:
if not input_file.is_file():
if input_file.is_dir():
continue

if ftd.has_pattern(input_file, const.FileType.MONTHLY):
Expand Down Expand Up @@ -130,12 +130,12 @@ def _refactor_filename(
filename: str, patterns: list[str], prefix: str
) -> str:
"""Process filename by removing patterns and adding appropriate prefix.
Args:
filename: The original filename to process
patterns: List of regex patterns to remove from filename
prefix: Prefix to add to the processed filename
Returns:
The processed filename with patterns removed and prefix added
"""
Expand Down
15 changes: 15 additions & 0 deletions pytrnsys_process/logger.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
"""
Configures logging for the pytrnsys_process package with three outputs:
1. Console output (INFO level) - Shows basic messages without stacktrace
2. Regular log file (INFO level) - Logs to pytrnsys_process.log without stacktrace
3. Debug log file (DEBUG level) - Logs to pytrnsys_process_debug.log with full stacktrace
The logging setup includes custom formatting for each handler and uses a TracebackInfoFilter
to control stacktrace visibility in different outputs. The main logger is configured at DEBUG
level to capture all logging events, while individual handlers control what gets displayed
in each output.
All handlers use the same log record.
Once the log record is modified and anything removed from it, will not be available in the other handlers.
"""

import logging
import sys

Expand Down
95 changes: 65 additions & 30 deletions pytrnsys_process/plotting/plot_wrappers.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,19 @@ def line_plot(
>>>
>>> def create_line_plot(simulation: api.Simulation):
>>> fig, ax = api.line_plot(simulation.hourly, columns=['var1', 'var2'])
Customize the plot using the returned axes object:
>>> # Customize the plot using the returned axes object:
>>> ax.set_xlabel('Time')
>>> ax.set_ylabel('Value')
>>> ax.set_title('My Plot')
>>> ax.grid(True)
>>> _plt.show()
>>>
>>> # run the single scenario on a single simulation
>>> api.process_single_simulation(
>>> _pl.Path("data/results/complete-0-SnkScale0.6000-StoreScale8"),
>>> create_line_plot,
>>> )
For additional customization options, refer to:
- Matplotlib documentation: https://matplotlib.org/stable/api/
- Pandas plotting: https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.plot.html
Expand Down Expand Up @@ -70,12 +77,19 @@ def bar_chart(
Example:
>>> from pytrnsys_process import api
>>> fig, ax = api.bar_chart(simulation.monthly, columns=['var1', 'var2'])
Customize the plot using the returned axes object:
>>> ax.set_xlabel('Time')
>>> ax.set_ylabel('Value')
>>> ax.set_title('My Plot')
>>> ax.grid(True)
>>> def create_bar_chart(simulation: api.Simulation):
>>> fig, ax = api.bar_chart(simulation.monthly, columns=['var1', 'var2'])
>>> # Customize the plot using the returned axes object:
>>> ax.set_xlabel('Time')
>>> ax.set_ylabel('Value')
>>> ax.set_title('My Plot')
>>> ax.grid(True)
>>>
>>> # run the single scenario on a single simulation
>>> api.process_single_simulation(
>>> _pl.Path("data/results/complete-0-SnkScale0.6000-StoreScale8"),
>>> create_bar_chart,
>>> )
For additional customization options, refer to:
- Matplotlib documentation: https://matplotlib.org/stable/api/
Expand Down Expand Up @@ -109,12 +123,19 @@ def stacked_bar_chart(
Example:
>>> from pytrnsys_process import api
>>> fig, ax = api.stacked_bar_chart(simulation.monthly, columns=['var1', 'var2', 'var3'])
Customize the plot using the returned axes object:
>>> ax.set_xlabel('Time')
>>> ax.set_ylabel('Value')
>>> ax.set_title('My Plot')
>>> ax.grid(True)
>>> def create_stacked_bar_chart(simulation: api.Simulation):
>>> fig, ax = api.stacked_bar_chart(simulation.monthly, columns=['var1', 'var2', 'var3'])
>>> # Customize the plot using the returned axes object:
>>> ax.set_xlabel('Time')
>>> ax.set_ylabel('Value')
>>> ax.set_title('My Plot')
>>> ax.grid(True)
>>>
>>> # run the single scenario on a single simulation
>>> api.process_single_simulation(
>>> _pl.Path("data/results/complete-0-SnkScale0.6000-StoreScale8"),
>>> create_stacked_bar_chart,
>>> )
For additional customization options, refer to:
- Matplotlib documentation: https://matplotlib.org/stable/api/
Expand Down Expand Up @@ -148,12 +169,19 @@ def histogram(
Example:
>>> from pytrnsys_process import api
>>> fig, ax = api.histogram(simulation.hourly, columns=['var1', 'var2'])
Customize the plot using the returned axes object:
>>> ax.set_xlabel('Value')
>>> ax.set_ylabel('Frequency')
>>> ax.set_title('My Histogram')
>>> ax.grid(True)
>>> def create_histogram(simulation: api.Simulation):
>>> fig, ax = api.histogram(simulation.hourly, columns=['var1', 'var2'])
>>> # Customize the plot using the returned axes object:
>>> ax.set_xlabel('Value')
>>> ax.set_ylabel('Frequency')
>>> ax.set_title('My Histogram')
>>> ax.grid(True)
>>>
>>> # run the single scenario on a single simulation
>>> api.process_single_simulation(
>>> _pl.Path("data/results/complete-0-SnkScale0.6000-StoreScale8"),
>>> create_histogram,
>>> )
For additional customization options, refer to:
- Matplotlib documentation: https://matplotlib.org/stable/api/
Expand Down Expand Up @@ -190,17 +218,24 @@ def scatter_plot(
Example:
>>> from pytrnsys_process import api
>>> fig, ax = api.scatter_plot(
... simulation.hourly,
... columns=["var1", "var2", "var3"],
... x_column="var1",
... y_column="var2",
... )
Customize the plot using the returned axes object:
>>> ax.set_xlabel('Time')
>>> ax.set_ylabel('Value')
>>> ax.set_title('My Scatter Plot')
>>> ax.grid(True)
>>> def create_scatter_plot(simulation: api.Simulation):
>>> fig, ax = api.scatter_plot(
... simulation.hourly,
... columns=["var1", "var2", "var3"],
... x_column="var1",
... y_column="var2",
... )
>>> # Customize the plot using the returned axes object:
>>> ax.set_xlabel('Time')
>>> ax.set_ylabel('Value')
>>> ax.set_title('My Scatter Plot')
>>> ax.grid(True)
>>>
>>> # run the single scenario on a single simulation
>>> api.process_single_simulation(
>>> _pl.Path("data/results/complete-0-SnkScale0.6000-StoreScale8"),
>>> create_scatter_plot,
>>> )
For additional customization options, refer to:
- Matplotlib documentation: https://matplotlib.org/stable/api/
Expand Down
31 changes: 4 additions & 27 deletions pytrnsys_process/plotting/plotters.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
# TODO: deal with legends (curve names, fonts, colors, linestyles) # pylint: disable=fixme
# TODO: clean up old stuff by refactoring # pylint: disable=fixme
# TODO: make issue for docstrings of plotting # pylint: disable=fixme
# TODO: Add colormap support # pylint: disable=fixme


@dataclass
Expand Down Expand Up @@ -113,32 +114,6 @@ def _do_plot(

return fig, ax

# TODO: Add colormap support # pylint: disable=fixme
# def _do_plot(
# self,
# df: _pd.DataFrame,
# columns: list[str],
# use_legend: bool = True,
# size: tuple[float, float] = const.PlotSizes.A4.value,
# **kwargs: _tp.Any,
# ) -> _plt.Figure:
# """The matplot date formatter does not work when using df.plot func.
# This is an example to plot a stacked bar chart without df.plot"""
# fig, ax = _plt.subplots(figsize=size)
# x = _np.arange(len(df.index))
# bottom = _np.zeros(len(df.index))
# for col in columns:
# ax.bar(x, df[col], label=col, bottom=bottom, width=0.35)
# bottom += df[col]
# if use_legend:
# ax.legend()
# ax.set_xticks(x)
# ax.set_xticklabels(
# _pd.to_datetime(df.index).strftime(self.DATE_FORMAT)
# )
# self.configure(ax)
# return fig

# TODO Idea for what an energy balance plot method could look like # pylint: disable=fixme
@staticmethod
def create_energy_balance_monthly(
Expand Down Expand Up @@ -237,6 +212,8 @@ def _do_plot(
) -> tuple[_plt.Figure, _plt.Axes]:
fig, ax = _plt.subplots(figsize=size)
# TODO: cleanup the other Plotters to remove the stringy dictionary.
df[columns].plot.scatter(colormap=self.COLOR_MAP, legend=use_legend, ax=ax, **kwargs)
df[columns].plot.scatter(
colormap=self.COLOR_MAP, legend=use_legend, ax=ax, **kwargs
)
ax = self.configure(ax)
return fig, ax
35 changes: 14 additions & 21 deletions pytrnsys_process/process_sim/process_sim.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ class Simulation:
def process_sim(
sim_files: _abc.Sequence[_pl.Path], sim_folder: _pl.Path
) -> Simulation:
# Used to store the array of dataframes for each file type.
# Later used to concatenate all into one dataframe and saving as Sim object
simulation_data_collector = _SimulationDataCollector()
for sim_file in sim_files:
try:
Expand Down Expand Up @@ -192,25 +194,16 @@ def _process_file(
def _merge_dataframes_into_simulation(
simulation_data_collector: _SimulationDataCollector, sim_folder: _pl.Path
) -> Simulation:
monthly_df = (
handle_duplicate_columns(
_pd.concat(simulation_data_collector.monthly, axis=1)
)
if simulation_data_collector.monthly
else _pd.DataFrame()
)
hourly_df = (
handle_duplicate_columns(
_pd.concat(simulation_data_collector.hourly, axis=1)
)
if simulation_data_collector.hourly
else _pd.DataFrame()
)
timestep_df = (
handle_duplicate_columns(
_pd.concat(simulation_data_collector.step, axis=1)
)
if simulation_data_collector.step
else _pd.DataFrame()
)

monthly_df = get_df_without_duplicates(simulation_data_collector.monthly)
hourly_df = get_df_without_duplicates(simulation_data_collector.hourly)
timestep_df = get_df_without_duplicates(simulation_data_collector.step)

return Simulation(sim_folder, monthly_df, hourly_df, timestep_df)


def get_df_without_duplicates(dfs: _abc.Sequence[_pd.DataFrame]):
if len(dfs) > 0:
return handle_duplicate_columns(_pd.concat(dfs, axis=1))

return _pd.DataFrame()
2 changes: 1 addition & 1 deletion pytrnsys_process/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class Plot:

@dataclass
class Reader:
folder_name_for_printer_files_loc: str = "temp"
folder_name_for_printer_files: str = "temp"
read_step_files: bool = True


Expand Down
Loading

0 comments on commit fc2b2ae

Please sign in to comment.