I have recently been working on a simple SIR Epidemic Simulation, and wanted to use pbPlots to visualize the data. Unfortunately, I can't get it to work correctly. Every time I run my code and go to open the png file, it just says that the file is unreadable or corrupted. I also noticed that the file size is only 65 bytes, which is smaller than the usual 180KB.
Here's my code:
/*
Brandon Pyle
SIR Epidemic Simulation
This program is a simple customizable epidemic simulation that uses the SIR model
*/
//Include statements
#include <string>
#include <iostream>
#include <iomanip>
#include <vector>
#include "pbPlots.hpp"
#include "supportLib.hpp"
using namespace std;
//Function prototypes
int main()
{
//The following block of code creates the title box in the command line
for (int i = 0; i < 50; i++)
cout << "*";
cout << endl << setw(49) << left << "*" << right << "*" << endl;
cout << "* Brandon Pyle *" << endl;
cout << "* SIR Epidemic Simulation *";
cout << endl << setw(49) << left << "*" << right << "*" << endl;
for (int i = 0; i < 50; i++)
cout << "*";
cout << endl << endl;
//Variable Declarations
int numDays;
int population;
double infectionRate = 0.0002; //Percent of other people a person can infect
double recoveryRate = 10; //In days
cout << "Enter the length of the simulation in days: ";
cin >> numDays;
cout << endl << "Enter the population number for the simulation: ";
cin >> population;
if (population > 5000)
cout << "WARNING: Numbers greater than 5000 may result in incorrect or inaccurate results." << endl;
else
cout << endl;
vector<double> S(population, 0.0); //Number of Susceptible People
vector<double> I(population, 0.0); //Number of Infected People
vector<double> R(population, 0.0); //Number of Removed People
//Creates variables for the X-Axis that are used for pbPlots
vector<double> xPos;
for (double i = 0.0; i < numDays; i++)
xPos.push_back(i);
I[0] = 1; //Starts the simulation with 6 infected people
S[0] = population - I[0]; //Initial number of susceptible people
R[0] = 0; //Initial number of removed people
RGBABitmapImageReference* imageReference = CreateRGBABitmapImageReference();
cout << setw(5) << right << "Day";
cout << setw(13) << right << "Susceptible";
cout << setw(10) << right << "Infected";
cout << setw(9) << right << "Removed" << endl;
for (int i = 0; i < numDays; i++)
{
cout << setw(5) << right << i + 1;
cout << setw(13) << right << fixed << setprecision(0) << S[i];
cout << setw(10) << right << fixed << setprecision(0) << I[i];
cout << setw(9) << right << fixed << setprecision(0) << R[i] << endl << endl;
S[i + 1] = S[i] - infectionRate * S[i] * I[i];
I[i + 1] = I[i] + infectionRate * S[i] * I[i] - I[i] / recoveryRate;
R[i + 1] = R[i] + I[i] / recoveryRate;
}
ScatterPlotSeries* series = GetDefaultScatterPlotSeriesSettings();
series->xs = &xPos;
series->ys = &S;
series->linearInterpolation = false;
series->lineType = toVector(L"solid");
series->color = CreateRGBColor(0, 0, 1);
ScatterPlotSeries* series2 = GetDefaultScatterPlotSeriesSettings();
series->xs = &xPos;
series->ys = &I;
series->linearInterpolation = false;
series->lineType = toVector(L"solid");
series->color = CreateRGBColor(0, 1, 0);
ScatterPlotSeries* series3 = GetDefaultScatterPlotSeriesSettings();
series->xs = &xPos;
series->ys = &R;
series->linearInterpolation = false;
series->lineType = toVector(L"solid");
series->color = CreateRGBColor(0, 0, 0);
ScatterPlotSettings *settings = GetDefaultScatterPlotSettings();
settings->width = 800;
settings->height = 480;
settings->autoBoundaries = true;
settings->autoPadding = true;
settings->title = toVector(L"SIR Epidemic Simulation");
settings->xLabel = toVector(L"Days");
settings->yLabel = toVector(L"Population");
settings->scatterPlotSeries->push_back(series);
settings->scatterPlotSeries->push_back(series2);
settings->scatterPlotSeries->push_back(series3);
DrawScatterPlotFromSettings(imageReference, settings);
//DrawScatterPlot(imageReference, 800, 480, &I, &S);
vector<double>* pngData = ConvertToPNG(imageReference->image);
WriteToFile(pngData, "SIR_Graph_Test.png");
DeleteImage(imageReference->image);
return 0;
}
I have narrowed down the issue to be something with the xPos vector, but I can't figure out why it isn't working. Also, the program does work if you comment out all of the ScatterPlotSeries stuff and uncomment the DrawScatterPlot(...); line. This method works because it uses the I vector for the X axis instead of my xPos vector.
Any suggestions?
Here is the Minimum Reproducible Example:
//Include statements
#include <vector>
#include "pbPlots.hpp"
#include "supportLib.hpp"
using namespace std;
int main()
{
vector<double> xPos;
for (double i = 0.0; i < 200; i++)
xPos.push_back(i);
vector<double> yPos;
for (double i = 0.0; i < 200; i++)
yPos.push_back(pow(i, 2));
vector<double> yPos2;
for (double i = 0.0; i < 200; i++)
yPos2.push_back(i + 2);
RGBABitmapImageReference* imageReference = CreateRGBABitmapImageReference();
ScatterPlotSeries* series = GetDefaultScatterPlotSeriesSettings();
series->xs = &xPos;
series->ys = &yPos;
series->linearInterpolation = false;
series->lineType = toVector(L"solid");
series->color = CreateRGBColor(0, 0, 1);
ScatterPlotSeries* series2 = GetDefaultScatterPlotSeriesSettings();
series->xs = &xPos;
series->ys = &yPos2;
series->linearInterpolation = false;
series->lineType = toVector(L"solid");
series->color = CreateRGBColor(0, 1, 0);
ScatterPlotSettings* settings = GetDefaultScatterPlotSettings();
settings->width = 800;
settings->height = 480;
settings->autoBoundaries = true;
settings->autoPadding = true;
settings->title = toVector(L"SIR Epidemic Simulation");
settings->xLabel = toVector(L"Days");
settings->yLabel = toVector(L"Population");
settings->scatterPlotSeries->push_back(series);
settings->scatterPlotSeries->push_back(series2);
//Comment out the line below when using the working method
DrawScatterPlotFromSettings(imageReference, settings);
//Ucomment the line below to get a working graph
//DrawScatterPlot(imageReference, 800, 480, &xPos, &yPos);
vector<double>* pngData = ConvertToPNG(imageReference->image);
WriteToFile(pngData, "SIR_Graph_Test_2.png");
DeleteImage(imageReference->image);
return 0;
}
Here is an image too compare the working PNG (right) to the corrupted PNG (left)
The problem is simply that you forgot to set the properties of series2. Look at your original code above, it sets the properties of "series" two times. If you change series-> to series2-> the second time, it works.