After Width: | Height: | Size: 52 KiB |
After Width: | Height: | Size: 37 KiB |
After Width: | Height: | Size: 31 KiB |
After Width: | Height: | Size: 91 KiB |
After Width: | Height: | Size: 586 KiB |
After Width: | Height: | Size: 31 KiB |
After Width: | Height: | Size: 32 KiB |
@ -0,0 +1,269 @@
|
|||||||
|
# Simplified Solution Reports
|
||||||
|
|
||||||
|
In addition to the full output format described in [data formats](format.md), RELOG can also generate a number of simplified reports in tabular data format (CSV), which can be more easily processed by spreadsheet software (such as Microsoft Excel), by data analysis libraries (such as Pandas) or by relational databases (such as SQLite).
|
||||||
|
|
||||||
|
In this page, we also illustrate what types of charts and visualizations can be produced from these tabular data files. The sample charts have been produced using Python, matplotlib, seaborn and geopandas.
|
||||||
|
|
||||||
|
## Plants report
|
||||||
|
|
||||||
|
Report showing plant costs, capacities, energy expenditure and utilization factors.
|
||||||
|
|
||||||
|
Generated by `RELOG.write_plants_report(solution, filename)`. For a concrete example, see [nimh_plants.csv](https://github.com/ANL-CEEESA/RELOG/blob/master/test/fixtures/nimh_plants.csv).
|
||||||
|
|
||||||
|
| Column | Description
|
||||||
|
|:--------------------------------------|---------------|
|
||||||
|
| `plant type` | Plant type.
|
||||||
|
| `location name` | Location name.
|
||||||
|
| `year` | What year this row corresponds to. This reports includes one row for each year in the simulation.
|
||||||
|
| `latitude (deg)` | Latitude of the plant.
|
||||||
|
| `longitude (deg)` | Longitude of the plant.
|
||||||
|
| `capacity (tonne)` | Capacity of the plant at this point in time.
|
||||||
|
| `amount processed (tonne)` | Amount of input material received by the plant this year.
|
||||||
|
| `utilization factor (%)` | Amount processed by the plant this year divided by current plant capacity.
|
||||||
|
| `energy (GJ)` | Amount of energy expended by the plant this year.
|
||||||
|
| `opening cost ($)` | Amount spent opening the plant. This value is only positive if the plant became operational this year.
|
||||||
|
| `expansion cost ($)` | Amount spent this year expanding the plant capacity.
|
||||||
|
| `fixed operating cost ($)` | Amount spent for keeping the plant operational this year.
|
||||||
|
| `variable operating cost ($)` | Amount spent for processing the input material this year.
|
||||||
|
| `total cost ($)` | Sum of all previous plant costs.
|
||||||
|
|
||||||
|
|
||||||
|
### Sample charts
|
||||||
|
|
||||||
|
* Bar plot with total plant costs per year, grouped by plant type (in Python):
|
||||||
|
```python
|
||||||
|
import pandas as pd
|
||||||
|
import seaborn as sns; sns.set()
|
||||||
|
|
||||||
|
data = pd.read_csv("plants_report.csv")
|
||||||
|
sns.barplot(x="year",
|
||||||
|
y="total cost ($)",
|
||||||
|
hue="plant type",
|
||||||
|
data=data.groupby(["plant type", "year"])
|
||||||
|
.sum()
|
||||||
|
.reset_index());
|
||||||
|
```
|
||||||
|
|
||||||
|
<img src="../images/ex_plant_cost_per_year.png" width="500px"/>
|
||||||
|
|
||||||
|
* Map showing plant locations (in Python):
|
||||||
|
```python
|
||||||
|
import pandas as pd
|
||||||
|
import geopandas as gp
|
||||||
|
|
||||||
|
# Plot base map
|
||||||
|
world = gp.read_file(gp.datasets.get_path('naturalearth_lowres'))
|
||||||
|
world = world[world.continent == 'North America']
|
||||||
|
ax = world.plot(color='white', edgecolor='50', figsize=(15,15))
|
||||||
|
|
||||||
|
# Plot plant locations
|
||||||
|
data = pd.read_csv("plants_report.csv")
|
||||||
|
points = gp.points_from_xy(data["longitude (deg)"],
|
||||||
|
data["latitude (deg)"])
|
||||||
|
gp.GeoDataFrame(data, geometry=points).plot(ax=ax);
|
||||||
|
```
|
||||||
|
|
||||||
|
<img src="../images/ex_plant_locations.png" width="1000px"/>
|
||||||
|
|
||||||
|
|
||||||
|
## Plant outputs report
|
||||||
|
|
||||||
|
Report showing amount of products produced, sent and disposed of by each plant, as well as disposal costs.
|
||||||
|
|
||||||
|
Generated by `RELOG.write_plant_outputs_report(solution, filename)`. For a concrete example, see [nimh_plant_outputs.csv](https://github.com/ANL-CEEESA/RELOG/blob/master/test/fixtures/nimh_plant_outputs.csv).
|
||||||
|
|
||||||
|
|
||||||
|
| Column | Description
|
||||||
|
|:--------------------------------------|---------------|
|
||||||
|
| `plant type` | Plant type.
|
||||||
|
| `location name` | Location name.
|
||||||
|
| `year` | What year this row corresponds to. This reports includes one row for each year in the simulation.
|
||||||
|
| `product` | Product being produced.
|
||||||
|
| `amount produced (tonne)` | Amount of product produced this year.
|
||||||
|
| `amount sent (tonne)` | Amount of product produced by this plant and sent to another plant for further processing this year.
|
||||||
|
| `amount disposed (tonne)` | Amount produced produced by this plant and immediately disposed of locally this year.
|
||||||
|
| `disposal cost ($)` | Disposal cost for this year.
|
||||||
|
|
||||||
|
### Sample charts
|
||||||
|
|
||||||
|
* Bar plot showing total amount produced for each product, grouped by year (in Python):
|
||||||
|
|
||||||
|
```python
|
||||||
|
import pandas as pd
|
||||||
|
import seaborn as sns; sns.set()
|
||||||
|
|
||||||
|
data = pd.read_csv("plant_outputs_report.csv")
|
||||||
|
sns.barplot(x="amount produced (tonne)",
|
||||||
|
y="product name",
|
||||||
|
hue="year",
|
||||||
|
data=data.groupby(["product name", "year"])
|
||||||
|
.sum()
|
||||||
|
.reset_index());
|
||||||
|
```
|
||||||
|
|
||||||
|
<img src="../images/ex_amount_produced.png" width="500px"/>
|
||||||
|
|
||||||
|
|
||||||
|
## Plant emissions report
|
||||||
|
|
||||||
|
Report showing amount of emissions produced by each plant.
|
||||||
|
|
||||||
|
Generated by `RELOG.write_plant_emissions_report(solution, filename)`. For a concrete example, see [nimh_plant_emissions.csv](https://github.com/ANL-CEEESA/RELOG/blob/master/test/fixtures/nimh_plant_emissions.csv).
|
||||||
|
|
||||||
|
| Column | Description
|
||||||
|
|:--------------------------------------|---------------|
|
||||||
|
| `plant type` | Plant type.
|
||||||
|
| `location name` | Location name.
|
||||||
|
| `year` | Year.
|
||||||
|
| `emission type` | Type of emission.
|
||||||
|
| `amount (tonne)` | Amount of emission produced by the plant this year.
|
||||||
|
|
||||||
|
### Sample charts
|
||||||
|
|
||||||
|
* Bar plot showing total emission by plant type, grouped type of emissions (in Python):
|
||||||
|
|
||||||
|
```python
|
||||||
|
import pandas as pd
|
||||||
|
import seaborn as sns; sns.set()
|
||||||
|
|
||||||
|
data = pd.read_csv("plant_emissions_report.csv")
|
||||||
|
sns.barplot(x="plant type",
|
||||||
|
y="emission amount (tonne)",
|
||||||
|
hue="emission type",
|
||||||
|
data=data.groupby(["plant type", "emission type"])
|
||||||
|
.sum()
|
||||||
|
.reset_index());
|
||||||
|
```
|
||||||
|
|
||||||
|
<img src="../images/ex_emissions.png" width="500px"/>
|
||||||
|
|
||||||
|
## Transportation report
|
||||||
|
|
||||||
|
Report showing amount of product sent from initial locations to plants, and from one plant to another. Includes the distance between each pair of locations, amount-distance shipped, transportation costs and energy expenditure.
|
||||||
|
|
||||||
|
Generated by `RELOG.write_transportation_report(solution, filename)`. For a concrete example, see [nimh_transportation.csv](https://github.com/ANL-CEEESA/RELOG/blob/master/test/fixtures/nimh_transportation.csv).
|
||||||
|
|
||||||
|
|
||||||
|
| Column | Description
|
||||||
|
|:--------------------------------------|---------------|
|
||||||
|
| `source type` | If product is being shipped from an initial location, equals `Origin`. If product is being shipped from a plant, equals plant type.
|
||||||
|
| `source location name` | Name of the location where the product is being shipped from.
|
||||||
|
| `source latitude (deg)` | Latitude of the source location.
|
||||||
|
| `source longitude (deg)` | Longitude of the source location.
|
||||||
|
| `destination type`| Type of plant the product is being shipped to.
|
||||||
|
| `destination location name`| Name of the location where the product is being shipped to.
|
||||||
|
| `destination latitude (deg)` | Latitude of the destination location.
|
||||||
|
| `destination longitude (deg)` | Longitude of the destination location.
|
||||||
|
| `product`| Product being shipped.
|
||||||
|
| `year`| Year.
|
||||||
|
| `distance (km)`| Distance between source and destination.
|
||||||
|
| `amount (tonne)`| Total amount of product being shipped between the two locations this year.
|
||||||
|
| `amount-distance (tonne-km)`| Total amount being shipped this year times distance.
|
||||||
|
| `transportation cost ($)`| Cost to transport this amount of product between the two locations for this year.
|
||||||
|
| `transportation energy (GJ)`| Energy expended transporting this amount of product between the two locations.
|
||||||
|
|
||||||
|
### Sample charts
|
||||||
|
|
||||||
|
* Bar plot showing total amount-distance for each product type, grouped by year (in Python):
|
||||||
|
|
||||||
|
```python
|
||||||
|
import pandas as pd
|
||||||
|
import seaborn as sns; sns.set()
|
||||||
|
|
||||||
|
data = pd.read_csv("transportation_report.csv")
|
||||||
|
sns.barplot(x="product",
|
||||||
|
y="amount-distance (tonne-km)",
|
||||||
|
hue="year",
|
||||||
|
data=data.groupby(["product", "year"])
|
||||||
|
.sum()
|
||||||
|
.reset_index());
|
||||||
|
```
|
||||||
|
|
||||||
|
<img src="../images/ex_transportation_amount_distance.png" width="500px"/>
|
||||||
|
|
||||||
|
* Map of transportation lines (in Python):
|
||||||
|
|
||||||
|
```python
|
||||||
|
import pandas as pd
|
||||||
|
import geopandas as gp
|
||||||
|
from shapely.geometry import Point, LineString
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
from matplotlib import collections
|
||||||
|
|
||||||
|
# Plot base map
|
||||||
|
world = gp.read_file(gp.datasets.get_path('naturalearth_lowres'))
|
||||||
|
ax = world.plot(color='white', edgecolor='50', figsize=(14,7))
|
||||||
|
ax.set_ylim([23, 50])
|
||||||
|
ax.set_xlim([-128, -65])
|
||||||
|
|
||||||
|
# Draw transportation lines
|
||||||
|
data = pd.read_csv("transportation_report.csv")
|
||||||
|
lines = [[(row["source longitude (deg)"], row["source latitude (deg)"]),
|
||||||
|
(row["destination longitude (deg)"], row["destination latitude (deg)"])
|
||||||
|
] for (index, row) in data.iterrows()]
|
||||||
|
ax.add_collection(collections.LineCollection(lines,
|
||||||
|
linewidths=0.25,
|
||||||
|
zorder=1,
|
||||||
|
alpha=0.5,
|
||||||
|
color="50"))
|
||||||
|
|
||||||
|
# Draw source points
|
||||||
|
points = gp.points_from_xy(data["source longitude (deg)"],
|
||||||
|
data["source latitude (deg)"])
|
||||||
|
gp.GeoDataFrame(data, geometry=points).plot(ax=ax,
|
||||||
|
color="0.5",
|
||||||
|
markersize=1);
|
||||||
|
|
||||||
|
# Draw destination points
|
||||||
|
points = gp.points_from_xy(data["destination longitude (deg)"],
|
||||||
|
data["destination latitude (deg)"])
|
||||||
|
gp.GeoDataFrame(data, geometry=points).plot(ax=ax,
|
||||||
|
color="red",
|
||||||
|
markersize=50);
|
||||||
|
```
|
||||||
|
|
||||||
|
<img src="../images/ex_transportation.png" width="1000px"/>
|
||||||
|
|
||||||
|
|
||||||
|
## Transportation emissions report
|
||||||
|
|
||||||
|
Report showing emissions for each trip between initial locations and plants, and between pairs of plants.
|
||||||
|
|
||||||
|
Generated by `RELOG.write_transportation_emissions_report(solution, filename)`. For a concrete example, see [nimh_transportation_emissions.csv](https://github.com/ANL-CEEESA/RELOG/blob/master/test/fixtures/nimh_transportation_emissions.csv).
|
||||||
|
|
||||||
|
| Column | Description
|
||||||
|
|:--------------------------------------|---------------|
|
||||||
|
| `source type` | If product is being shipped from an initial location, equals `Origin`. If product is being shipped from a plant, equals plant type.
|
||||||
|
| `source location name` | Name of the location where the product is being shipped from.
|
||||||
|
| `source latitude (deg)` | Latitude of the source location.
|
||||||
|
| `source longitude (deg)` | Longitude of the source location.
|
||||||
|
| `destination type`| Type of plant the product is being shipped to.
|
||||||
|
| `destination location name`| Name of the location where the product is being shipped to.
|
||||||
|
| `destination latitude (deg)` | Latitude of the destination location.
|
||||||
|
| `destination longitude (deg)` | Longitude of the destination location.
|
||||||
|
| `product`| Product being shipped.
|
||||||
|
| `year`| Year.
|
||||||
|
| `distance (km)`| Distance between source and destination.
|
||||||
|
| `shipped amount (tonne)`| Total amount of product being shipped between the two locations this year.
|
||||||
|
| `shipped amount-distance (tonne-km)`| Total amount being shipped this year times distance.
|
||||||
|
| `emission type` | Type of emission.
|
||||||
|
| `emission amount (tonne)` | Amount of emission produced by transportation segment this year.
|
||||||
|
|
||||||
|
### Sample charts
|
||||||
|
|
||||||
|
* Bar plot showing total emission amount by emission type, grouped by type of product being transported (in Python):
|
||||||
|
|
||||||
|
```python
|
||||||
|
import pandas as pd
|
||||||
|
import seaborn as sns; sns.set()
|
||||||
|
|
||||||
|
data = pd.read_csv("transportation_emissions_report.csv")
|
||||||
|
sns.barplot(x="emission type",
|
||||||
|
y="emission amount (tonne)",
|
||||||
|
hue="product",
|
||||||
|
data=data.groupby(["product", "emission type"])
|
||||||
|
.sum()
|
||||||
|
.reset_index());
|
||||||
|
```
|
||||||
|
|
||||||
|
<img src="../images/ex_transportation_emissions.png" width="500px"/>
|
@ -0,0 +1,268 @@
|
|||||||
|
# RELOG: Reverse Logistics Optimization
|
||||||
|
# Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved.
|
||||||
|
# Released under the modified BSD license. See COPYING.md for more details.
|
||||||
|
|
||||||
|
using DataFrames
|
||||||
|
using CSV
|
||||||
|
|
||||||
|
function plants_report(solution::Dict)::DataFrame
|
||||||
|
df = DataFrame()
|
||||||
|
df."plant type" = String[]
|
||||||
|
df."location name" = String[]
|
||||||
|
df."year" = Int[]
|
||||||
|
df."latitude (deg)" = Float64[]
|
||||||
|
df."longitude (deg)" = Float64[]
|
||||||
|
df."capacity (tonne)" = Float64[]
|
||||||
|
df."amount processed (tonne)" = Float64[]
|
||||||
|
df."utilization factor (%)" = Float64[]
|
||||||
|
df."energy (GJ)" = Float64[]
|
||||||
|
df."opening cost (\$)" = Float64[]
|
||||||
|
df."expansion cost (\$)" = Float64[]
|
||||||
|
df."fixed operating cost (\$)" = Float64[]
|
||||||
|
df."variable operating cost (\$)" = Float64[]
|
||||||
|
df."total cost (\$)" = Float64[]
|
||||||
|
T = length(solution["Energy"]["Plants (GJ)"])
|
||||||
|
for (plant_name, plant_dict) in solution["Plants"]
|
||||||
|
for (location_name, location_dict) in plant_dict
|
||||||
|
var_cost = zeros(T)
|
||||||
|
for (src_plant_name, src_plant_dict) in location_dict["Input"]
|
||||||
|
for (src_location_name, src_location_dict) in src_plant_dict
|
||||||
|
var_cost += src_location_dict["Variable operating cost (\$)"]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
var_cost = round.(var_cost, digits=2)
|
||||||
|
for year in 1:T
|
||||||
|
opening_cost = round(location_dict["Opening cost (\$)"][year], digits=2)
|
||||||
|
expansion_cost = round(location_dict["Expansion cost (\$)"][year], digits=2)
|
||||||
|
fixed_cost = round(location_dict["Fixed operating cost (\$)"][year], digits=2)
|
||||||
|
total_cost = round(var_cost[year] + opening_cost + expansion_cost + fixed_cost, digits=2)
|
||||||
|
capacity = round(location_dict["Capacity (tonne)"][year], digits=2)
|
||||||
|
processed = round(location_dict["Total input (tonne)"][year], digits=2)
|
||||||
|
utilization_factor = round(processed / capacity * 100.0, digits=2)
|
||||||
|
energy = round(location_dict["Energy (GJ)"][year], digits=2)
|
||||||
|
latitude = round(location_dict["Latitude (deg)"], digits=6)
|
||||||
|
longitude = round(location_dict["Longitude (deg)"], digits=6)
|
||||||
|
push!(df, [
|
||||||
|
plant_name,
|
||||||
|
location_name,
|
||||||
|
year,
|
||||||
|
latitude,
|
||||||
|
longitude,
|
||||||
|
capacity,
|
||||||
|
processed,
|
||||||
|
utilization_factor,
|
||||||
|
energy,
|
||||||
|
opening_cost,
|
||||||
|
expansion_cost,
|
||||||
|
fixed_cost,
|
||||||
|
var_cost[year],
|
||||||
|
total_cost,
|
||||||
|
])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return df
|
||||||
|
end
|
||||||
|
|
||||||
|
function plant_outputs_report(solution::Dict)::DataFrame
|
||||||
|
df = DataFrame()
|
||||||
|
df."plant type" = String[]
|
||||||
|
df."location name" = String[]
|
||||||
|
df."year" = Int[]
|
||||||
|
df."product name" = String[]
|
||||||
|
df."amount produced (tonne)" = Float64[]
|
||||||
|
df."amount sent (tonne)" = Float64[]
|
||||||
|
df."amount disposed (tonne)" = Float64[]
|
||||||
|
df."disposal cost (\$)" = Float64[]
|
||||||
|
T = length(solution["Energy"]["Plants (GJ)"])
|
||||||
|
for (plant_name, plant_dict) in solution["Plants"]
|
||||||
|
for (location_name, location_dict) in plant_dict
|
||||||
|
for (product_name, amount_produced) in location_dict["Total output"]
|
||||||
|
send_dict = location_dict["Output"]["Send"]
|
||||||
|
disposal_dict = location_dict["Output"]["Dispose"]
|
||||||
|
|
||||||
|
sent = zeros(T)
|
||||||
|
if product_name in keys(send_dict)
|
||||||
|
for (dst_plant_name, dst_plant_dict) in send_dict[product_name]
|
||||||
|
for (dst_location_name, dst_location_dict) in dst_plant_dict
|
||||||
|
sent += dst_location_dict["Amount (tonne)"]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
sent = round.(sent, digits=2)
|
||||||
|
|
||||||
|
disposal_amount = zeros(T)
|
||||||
|
disposal_cost = zeros(T)
|
||||||
|
if product_name in keys(disposal_dict)
|
||||||
|
disposal_amount += disposal_dict[product_name]["Amount (tonne)"]
|
||||||
|
disposal_cost += disposal_dict[product_name]["Cost (\$)"]
|
||||||
|
end
|
||||||
|
disposal_amount = round.(disposal_amount, digits=2)
|
||||||
|
disposal_cost = round.(disposal_cost, digits=2)
|
||||||
|
|
||||||
|
for year in 1:T
|
||||||
|
push!(df, [
|
||||||
|
plant_name,
|
||||||
|
location_name,
|
||||||
|
year,
|
||||||
|
product_name,
|
||||||
|
round(amount_produced[year], digits=2),
|
||||||
|
sent[year],
|
||||||
|
disposal_amount[year],
|
||||||
|
disposal_cost[year],
|
||||||
|
])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return df
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function plant_emissions_report(solution::Dict)::DataFrame
|
||||||
|
df = DataFrame()
|
||||||
|
df."plant type" = String[]
|
||||||
|
df."location name" = String[]
|
||||||
|
df."year" = Int[]
|
||||||
|
df."emission type" = String[]
|
||||||
|
df."emission amount (tonne)" = Float64[]
|
||||||
|
T = length(solution["Energy"]["Plants (GJ)"])
|
||||||
|
for (plant_name, plant_dict) in solution["Plants"]
|
||||||
|
for (location_name, location_dict) in plant_dict
|
||||||
|
for (emission_name, emission_amount) in location_dict["Emissions (tonne)"]
|
||||||
|
for year in 1:T
|
||||||
|
push!(df, [
|
||||||
|
plant_name,
|
||||||
|
location_name,
|
||||||
|
year,
|
||||||
|
emission_name,
|
||||||
|
round(emission_amount[year], digits=2),
|
||||||
|
])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return df
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function transportation_report(solution::Dict)::DataFrame
|
||||||
|
df = DataFrame()
|
||||||
|
df."source type" = String[]
|
||||||
|
df."source location name" = String[]
|
||||||
|
df."source latitude (deg)" = Float64[]
|
||||||
|
df."source longitude (deg)" = Float64[]
|
||||||
|
df."destination type" = String[]
|
||||||
|
df."destination location name" = String[]
|
||||||
|
df."destination latitude (deg)" = Float64[]
|
||||||
|
df."destination longitude (deg)" = Float64[]
|
||||||
|
df."product" = String[]
|
||||||
|
df."year" = Int[]
|
||||||
|
df."distance (km)" = Float64[]
|
||||||
|
df."amount (tonne)" = Float64[]
|
||||||
|
df."amount-distance (tonne-km)" = Float64[]
|
||||||
|
df."transportation cost (\$)" = Float64[]
|
||||||
|
df."transportation energy (GJ)" = Float64[]
|
||||||
|
|
||||||
|
T = length(solution["Energy"]["Plants (GJ)"])
|
||||||
|
for (dst_plant_name, dst_plant_dict) in solution["Plants"]
|
||||||
|
for (dst_location_name, dst_location_dict) in dst_plant_dict
|
||||||
|
for (src_plant_name, src_plant_dict) in dst_location_dict["Input"]
|
||||||
|
for (src_location_name, src_location_dict) in src_plant_dict
|
||||||
|
for year in 1:T
|
||||||
|
push!(df, [
|
||||||
|
src_plant_name,
|
||||||
|
src_location_name,
|
||||||
|
round(src_location_dict["Latitude (deg)"], digits=6),
|
||||||
|
round(src_location_dict["Longitude (deg)"], digits=6),
|
||||||
|
dst_plant_name,
|
||||||
|
dst_location_name,
|
||||||
|
round(dst_location_dict["Latitude (deg)"], digits=6),
|
||||||
|
round(dst_location_dict["Longitude (deg)"], digits=6),
|
||||||
|
dst_location_dict["Input product"],
|
||||||
|
year,
|
||||||
|
round(src_location_dict["Distance (km)"][year], digits=2),
|
||||||
|
round(src_location_dict["Amount (tonne)"][year], digits=2),
|
||||||
|
round(src_location_dict["Amount (tonne)"][year] *
|
||||||
|
src_location_dict["Distance (km)"][year],
|
||||||
|
digits=2),
|
||||||
|
round(src_location_dict["Transportation cost (\$)"][year], digits=2),
|
||||||
|
round(src_location_dict["Transportation energy (J)"][year] / 1e9, digits=2),
|
||||||
|
])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return df
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function transportation_emissions_report(solution::Dict)::DataFrame
|
||||||
|
df = DataFrame()
|
||||||
|
df."source type" = String[]
|
||||||
|
df."source location name" = String[]
|
||||||
|
df."source latitude (deg)" = Float64[]
|
||||||
|
df."source longitude (deg)" = Float64[]
|
||||||
|
df."destination type" = String[]
|
||||||
|
df."destination location name" = String[]
|
||||||
|
df."destination latitude (deg)" = Float64[]
|
||||||
|
df."destination longitude (deg)" = Float64[]
|
||||||
|
df."product" = String[]
|
||||||
|
df."year" = Int[]
|
||||||
|
df."distance (km)" = Float64[]
|
||||||
|
df."shipped amount (tonne)" = Float64[]
|
||||||
|
df."shipped amount-distance (tonne-km)" = Float64[]
|
||||||
|
df."emission type" = String[]
|
||||||
|
df."emission amount (tonne)" = Float64[]
|
||||||
|
|
||||||
|
T = length(solution["Energy"]["Plants (GJ)"])
|
||||||
|
for (dst_plant_name, dst_plant_dict) in solution["Plants"]
|
||||||
|
for (dst_location_name, dst_location_dict) in dst_plant_dict
|
||||||
|
for (src_plant_name, src_plant_dict) in dst_location_dict["Input"]
|
||||||
|
for (src_location_name, src_location_dict) in src_plant_dict
|
||||||
|
for (emission_name, emission_amount) in src_location_dict["Emissions (tonne)"]
|
||||||
|
for year in 1:T
|
||||||
|
push!(df, [
|
||||||
|
src_plant_name,
|
||||||
|
src_location_name,
|
||||||
|
round(src_location_dict["Latitude (deg)"], digits=6),
|
||||||
|
round(src_location_dict["Longitude (deg)"], digits=6),
|
||||||
|
dst_plant_name,
|
||||||
|
dst_location_name,
|
||||||
|
round(dst_location_dict["Latitude (deg)"], digits=6),
|
||||||
|
round(dst_location_dict["Longitude (deg)"], digits=6),
|
||||||
|
dst_location_dict["Input product"],
|
||||||
|
year,
|
||||||
|
round(src_location_dict["Distance (km)"][year], digits=2),
|
||||||
|
round(src_location_dict["Amount (tonne)"][year], digits=2),
|
||||||
|
round(src_location_dict["Amount (tonne)"][year] *
|
||||||
|
src_location_dict["Distance (km)"][year],
|
||||||
|
digits=2),
|
||||||
|
emission_name,
|
||||||
|
round(emission_amount[year], digits=2),
|
||||||
|
])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return df
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
write_plants_report(solution, filename) =
|
||||||
|
CSV.write(filename, plants_report(solution))
|
||||||
|
|
||||||
|
write_plant_outputs_report(solution, filename) =
|
||||||
|
CSV.write(filename, plant_outputs_report(solution))
|
||||||
|
|
||||||
|
write_plant_emissions_report(solution, filename) =
|
||||||
|
CSV.write(filename, plant_emissions_report(solution))
|
||||||
|
|
||||||
|
write_transportation_report(solution, filename) =
|
||||||
|
CSV.write(filename, transportation_report(solution))
|
||||||
|
|
||||||
|
write_transportation_emissions_report(solution, filename) =
|
||||||
|
CSV.write(filename, transportation_emissions_report(solution))
|
|
|
|
@ -0,0 +1,28 @@
|
|||||||
|
# RELOG: Reverse Logistics Optimization
|
||||||
|
# Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved.
|
||||||
|
# Released under the modified BSD license. See COPYING.md for more details.
|
||||||
|
|
||||||
|
using RELOG, JSON, GZip
|
||||||
|
|
||||||
|
load_json_gz(filename) = JSON.parse(GZip.gzopen(filename))
|
||||||
|
|
||||||
|
function check(func, expected_csv_filename::String)
|
||||||
|
solution = load_json_gz("fixtures/nimh_solution.json.gz")
|
||||||
|
actual_csv_filename = tempname()
|
||||||
|
func(solution, actual_csv_filename)
|
||||||
|
@test isfile(actual_csv_filename)
|
||||||
|
if readlines(actual_csv_filename) != readlines(expected_csv_filename)
|
||||||
|
out_filename = replace(expected_csv_filename, ".csv" => "_actual.csv")
|
||||||
|
@error "$func: Unexpected CSV contents: $out_filename"
|
||||||
|
write(out_filename, read(actual_csv_filename))
|
||||||
|
@test false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@testset "Reports" begin
|
||||||
|
check(RELOG.write_plants_report, "fixtures/nimh_plants.csv")
|
||||||
|
check(RELOG.write_plant_outputs_report, "fixtures/nimh_plant_outputs.csv")
|
||||||
|
check(RELOG.write_plant_emissions_report, "fixtures/nimh_plant_emissions.csv")
|
||||||
|
check(RELOG.write_transportation_report, "fixtures/nimh_transportation.csv")
|
||||||
|
check(RELOG.write_transportation_emissions_report, "fixtures/nimh_transportation_emissions.csv")
|
||||||
|
end
|