diff -r 5d448b8564e5 examples/stats/.project
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/stats/.project Wed Jul 01 16:12:09 2009 +0200
@@ -0,0 +1,11 @@
+
+
+ stats
+
+
+
+
+
+
+
+
diff -r 5d448b8564e5 examples/stats/README
--- a/examples/stats/README Mon Jun 29 13:24:10 2009 +0200
+++ b/examples/stats/README Wed Jul 01 16:12:09 2009 +0200
@@ -14,3 +14,23 @@
available online on the ns-3 wiki at:
http://www.nsnam.org/wiki/index.php/Statistical_Framework_for_Network_Simulation
+
+*** Using ns-3 with the OMNeT++ analysis tool ***
+
+The stat framework can write out the result in a format that is compatible with the
+output format of OMNeT++ 4 Discrete Event Simulator Framework.
+Use the wifi-example-omnet.sh script to generate the results in OMNeT++ format.
+
+If you want to analyse the results with OMNeT++'s result analyser tool:
+a) Download OMNeT++ 4 and install it. Start the IDE. (www.omnetpp.org)
+b) If you do not want to install the whole simulator framework, there is a seperate
+ package which contains only the analysis tool from the OMNeT++ package.
+ You can download it from http://omnetpp.org/download/release/omnetpp-scave.tgz
+
+Once you are running the OMNeT++ IDE or the separate analysis tool (SCAVE)
+- Choose File|Import...|Existing Projects into Workspace, then click [Next]
+- Select root directory. (choose the examples/stats directory) and click [Finish]
+
+Double click the wifi-example-omnet.anf in the opened project and select
+the Chart page to see the created chart. Experiment with the analysis tool and read its
+documentation: http://omnetpp.org/doc/omnetpp40/userguide/ch09.html
diff -r 5d448b8564e5 examples/stats/wifi-example-db.sh
--- a/examples/stats/wifi-example-db.sh Mon Jun 29 13:24:10 2009 +0200
+++ b/examples/stats/wifi-example-db.sh Wed Jul 01 16:12:09 2009 +0200
@@ -64,8 +64,8 @@
from Singletons rx, Singletons tx, Experiments exp \
where rx.run = tx.run AND \
rx.run = exp.run AND \
- rx.name='receiver-rx-packets' AND \
- tx.name='sender-tx-packets' \
+ rx.variable='receiver-rx-packets' AND \
+ tx.variable='sender-tx-packets' \
group by exp.input \
order by abs(exp.input) ASC;"
diff -r 5d448b8564e5 examples/stats/wifi-example-omnet.anf
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/stats/wifi-example-omnet.anf Wed Jul 01 16:12:09 2009 +0200
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff -r 5d448b8564e5 examples/stats/wifi-example-omnet.sh
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/stats/wifi-example-omnet.sh Wed Jul 01 16:12:09 2009 +0200
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+DISTANCES="25 50 75 100 125 145 147 150 152 155 157 160 162 165 167 170 172 175 177 180"
+TRIALS="1 2 3 4 5"
+
+echo WiFi Experiment Example - OMNeT++ output
+
+export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:bin/
+
+for trial in $TRIALS
+do
+ for distance in $DISTANCES
+ do
+ echo Trial $trial, distance $distance
+ ../../waf --run "wifi-example-sim --format=omnet --distance=$distance --run=run-$distance-$trial"
+ done
+done
+
+rm *.sca
+mv ../../*.sca .
+
+echo "Done; data in data-run-*.sca files. Open SCAVE, create a new workspace and import this directory."
diff -r 5d448b8564e5 examples/stats/wifi-example-sim.cc
--- a/examples/stats/wifi-example-sim.cc Mon Jun 29 13:24:10 2009 +0200
+++ b/examples/stats/wifi-example-sim.cc Wed Jul 01 16:12:09 2009 +0200
@@ -200,6 +200,7 @@
Ptr > totalTx =
CreateObject >();
totalTx->SetKey("wifi-tx-frames");
+ totalTx->SetContext("node[0]");
Config::Connect("/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/Mac/MacTx",
MakeBoundCallback(&TxCallback, totalTx));
data.AddDataCalculator(totalTx);
@@ -211,6 +212,7 @@
Ptr totalRx =
CreateObject();
totalRx->SetKey("wifi-rx-frames");
+ totalRx->SetContext("node[1]");
Config::Connect("/NodeList/1/DeviceList/*/$ns3::WifiNetDevice/Mac/MacRx",
MakeCallback(&PacketCounterCalculator::PacketUpdate,
totalRx));
@@ -225,6 +227,7 @@
Ptr appTx =
CreateObject();
appTx->SetKey("sender-tx-packets");
+ appTx->SetContext("node[0]");
Config::Connect("/NodeList/0/ApplicationList/*/$Sender/Tx",
MakeCallback(&PacketCounterCalculator::PacketUpdate,
appTx));
@@ -237,6 +240,7 @@
Ptr > appRx =
CreateObject >();
appRx->SetKey("receiver-rx-packets");
+ appRx->SetContext("node[1]");
receiver->SetCounter(appRx);
data.AddDataCalculator(appRx);
@@ -263,6 +267,7 @@
Ptr appTxPkts =
CreateObject();
appTxPkts->SetKey("tx-pkt-size");
+ appTxPkts->SetContext("node[0]");
Config::Connect("/NodeList/0/ApplicationList/*/$Sender/Tx",
MakeCallback
(&PacketSizeMinMaxAvgTotalCalculator::PacketUpdate,
@@ -277,6 +282,7 @@
Ptr delayStat =
CreateObject();
delayStat->SetKey("delay");
+ delayStat->SetContext(".");
receiver->SetDelayTracker(delayStat);
data.AddDataCalculator(delayStat);
diff -r 5d448b8564e5 src/contrib/stats/basic-data-calculators.h
--- a/src/contrib/stats/basic-data-calculators.h Mon Jun 29 13:24:10 2009 +0200
+++ b/src/contrib/stats/basic-data-calculators.h Wed Jul 01 16:12:09 2009 +0200
@@ -29,7 +29,8 @@
//------------------------------------------------------------
//--------------------------------------------
template
- class MinMaxAvgTotalCalculator : public DataCalculator {
+ class MinMaxAvgTotalCalculator : public DataCalculator,
+ public StatisticalSummary {
public:
MinMaxAvgTotalCalculator();
virtual ~MinMaxAvgTotalCalculator();
@@ -38,6 +39,15 @@
virtual void Output(DataOutputCallback &callback) const;
+ long getCount() const { return m_count; }
+ double getSum() const { return m_total; }
+ double getMin() const { return m_min; }
+ double getMax() const { return m_max; }
+ double getMean() const { return m_total / (double)m_count; }
+ double getStddev() const { return NaN; } // unsupported
+ double getVariance() const { return NaN; } // unsupported
+ double getSqrSum() const { return NaN; } // unsupported
+
protected:
virtual void DoDispose(void);
@@ -86,23 +96,15 @@
}
// end MinMaxAvgTotalCalculator::Update
}
+
template
void
MinMaxAvgTotalCalculator::Output(DataOutputCallback &callback) const
{
- callback.OutputSingleton(m_key, "count", m_count);
- if (m_count > 0) {
- callback.OutputSingleton(m_key, "total", m_total);
- callback.OutputSingleton(m_key, "average", m_total/m_count);
- callback.OutputSingleton(m_key, "max", m_max);
- callback.OutputSingleton(m_key, "min", m_min);
- }
- // end MinMaxAvgTotalCalculator::Output
+ callback.OutputStatistic(m_context, m_key, this);
}
-
-
//------------------------------------------------------------
//--------------------------------------------
template
@@ -178,7 +180,7 @@
void
CounterCalculator::Output(DataOutputCallback &callback) const
{
- callback.OutputSingleton(m_key, "count", m_count);
+ callback.OutputSingleton(m_context, m_key, m_count);
// end CounterCalculator::Output
}
diff -r 5d448b8564e5 src/contrib/stats/data-calculator.cc
--- a/src/contrib/stats/data-calculator.cc Mon Jun 29 13:24:10 2009 +0200
+++ b/src/contrib/stats/data-calculator.cc Wed Jul 01 16:12:09 2009 +0200
@@ -27,6 +27,8 @@
NS_LOG_COMPONENT_DEFINE("DataCalculator");
+static double zero = 0;
+const double ns3::NaN = zero / zero;
//--------------------------------------------------------------
//----------------------------------------------
@@ -70,6 +72,20 @@
//----------------------------------------------
void
+DataCalculator::SetContext(const std::string context)
+{
+ m_context = context;
+ // end DataCalculator::SetContext
+}
+
+std::string
+DataCalculator::GetContext() const
+{
+ return m_context;
+ // end DataCalculator::GetContext
+}
+//----------------------------------------------
+void
DataCalculator::Enable()
{
m_enabled = true;
diff -r 5d448b8564e5 src/contrib/stats/data-calculator.h
--- a/src/contrib/stats/data-calculator.h Mon Jun 29 13:24:10 2009 +0200
+++ b/src/contrib/stats/data-calculator.h Wed Jul 01 16:12:09 2009 +0200
@@ -26,9 +26,56 @@
#include "ns3/simulator.h"
namespace ns3 {
+ extern const double NaN;
+ inline bool isNaN(double x) { return x != x; }
class DataOutputCallback;
+ class StatisticalSummary {
+ public:
+ /**
+ * Returns the number of the observations.
+ */
+ virtual long getCount() const = 0;
+
+ /**
+ * Returns the sum of the values.
+ * @see getWeightedSum()
+ */
+ virtual double getSum() const = 0;
+
+ /**
+ * Returns the sum of the squared values.
+ * @see getWeightedSqrSum()
+ */
+ virtual double getSqrSum() const = 0;
+
+ /**
+ * Returns the minimum of the values.
+ */
+ virtual double getMin() const = 0;
+
+ /**
+ * Returns the maximum of the values.
+ */
+ virtual double getMax() const = 0;
+
+ /**
+ * Returns the mean of the (weighted) observations.
+ */
+ virtual double getMean() const = 0;
+
+ /**
+ * Returns the standard deviation of the (weighted) observations.
+ */
+ virtual double getStddev() const = 0;
+
+ /**
+ * Returns the variance of the (weighted) observations.
+ */
+ virtual double getVariance() const = 0;
+ };
+
//------------------------------------------------------------
//--------------------------------------------
class DataCalculator : public Object {
@@ -43,6 +90,9 @@
void SetKey(const std::string key);
std::string GetKey() const;
+ void SetContext(const std::string context);
+ std::string GetContext() const;
+
virtual void Start(const Time& startTime);
virtual void Stop(const Time& stopTime);
@@ -52,6 +102,7 @@
bool m_enabled; // Descendant classes *must* check & respect m_enabled!
std::string m_key;
+ std::string m_context;
virtual void DoDispose(void);
diff -r 5d448b8564e5 src/contrib/stats/data-output-interface.h
--- a/src/contrib/stats/data-output-interface.h Mon Jun 29 13:24:10 2009 +0200
+++ b/src/contrib/stats/data-output-interface.h Wed Jul 01 16:12:09 2009 +0200
@@ -23,6 +23,7 @@
#include "ns3/object.h"
#include "ns3/nstime.h"
+#include "ns3/data-calculator.h"
namespace ns3 {
@@ -52,6 +53,10 @@
public:
virtual ~DataOutputCallback() {}
+ virtual void OutputStatistic(std::string key,
+ std::string variable,
+ const StatisticalSummary *statSum) = 0;
+
virtual void OutputSingleton(std::string key,
std::string variable,
int val) = 0;
diff -r 5d448b8564e5 src/contrib/stats/omnet-data-output.cc
--- a/src/contrib/stats/omnet-data-output.cc Mon Jun 29 13:24:10 2009 +0200
+++ b/src/contrib/stats/omnet-data-output.cc Wed Jul 01 16:12:09 2009 +0200
@@ -19,6 +19,7 @@
*/
#include
+#include
#include "ns3/log.h"
#include "ns3/nstime.h"
@@ -54,26 +55,31 @@
}
//----------------------------------------------
+
+inline bool isNumeric(const std::string& s) {
+ char *endp;
+ strtod(s.c_str(), &endp);
+ return endp == s.c_str() + s.size();
+}
+
void
OmnetDataOutput::Output(DataCollector &dc)
{
std::ofstream scalarFile;
- std::string fn = m_filePrefix + ".sca";
- scalarFile.open(fn.c_str(), std::ios_base::app);
+ std::string fn = m_filePrefix +"-"+dc.GetRunLabel()+ ".sca";
+ scalarFile.open(fn.c_str(), std::ios_base::out);
- scalarFile << std::endl;
+ // TODO add timestamp to the runlevel
scalarFile << "run " << dc.GetRunLabel() << std::endl;
- scalarFile << std::endl;
scalarFile << "attr experiment \"" << dc.GetExperimentLabel()
<< "\"" << std::endl;
scalarFile << "attr strategy \"" << dc.GetStrategyLabel()
<< "\"" << std::endl;
- scalarFile << "attr input \"" << dc.GetInputLabel()
+ scalarFile << "attr measurement \"" << dc.GetInputLabel()
<< "\"" << std::endl;
scalarFile << "attr description \"" << dc.GetDescription()
<< "\"" << std::endl;
- scalarFile << std::endl;
for (MetadataList::iterator i = dc.MetadataBegin();
i != dc.MetadataEnd(); i++) {
@@ -83,7 +89,18 @@
}
scalarFile << std::endl;
-
+ if (isNumeric(dc.GetInputLabel())) {
+ scalarFile << "scalar . measurement \"" << dc.GetInputLabel()
+ << "\"" << std::endl;
+ }
+ for (MetadataList::iterator i = dc.MetadataBegin();
+ i != dc.MetadataEnd(); i++) {
+ std::pair blob = (*i);
+ if (isNumeric(blob.second)) {
+ scalarFile << "scalar . \"" << blob.first << "\" \"" << blob.second << "\""
+ << std::endl;
+ }
+ }
OmnetOutputCallback callback(&scalarFile);
for (DataCalculatorList::iterator i = dc.DataCalculatorBegin();
@@ -97,6 +114,7 @@
// end OmnetDataOutput::Output
}
+
OmnetDataOutput::OmnetOutputCallback::OmnetOutputCallback
(std::ostream *scalar) :
m_scalar(scalar)
@@ -104,42 +122,92 @@
}
void
-OmnetDataOutput::OmnetOutputCallback::OutputSingleton(std::string key,
- std::string variable,
+OmnetDataOutput::OmnetOutputCallback::OutputStatistic(std::string context,
+ std::string name,
+ const StatisticalSummary *statSum)
+{
+ if (context == "")
+ context = ".";
+ if (name == "")
+ name = "\"\"";
+ (*m_scalar) << "statistic " << context << " " << name << std::endl;
+ if (!isNaN(statSum->getCount()))
+ (*m_scalar) << "field count " << statSum->getCount() << std::endl;
+ if (!isNaN(statSum->getSum()))
+ (*m_scalar) << "field sum " << statSum->getSum() << std::endl;
+ if (!isNaN(statSum->getMean()))
+ (*m_scalar) << "field mean " << statSum->getMean() << std::endl;
+ if (!isNaN(statSum->getMin()))
+ (*m_scalar) << "field min " << statSum->getMin() << std::endl;
+ if (!isNaN(statSum->getMax()))
+ (*m_scalar) << "field max " << statSum->getMax() << std::endl;
+ if (!isNaN(statSum->getSqrSum()))
+ (*m_scalar) << "field sqrsum " << statSum->getSqrSum() << std::endl;
+ if (!isNaN(statSum->getStddev()))
+ (*m_scalar) << "field stddev " << statSum->getStddev() << std::endl;
+}
+
+void
+OmnetDataOutput::OmnetOutputCallback::OutputSingleton(std::string context,
+ std::string name,
int val)
{
- (*m_scalar) << "scalar " << key << " " << variable << " " << val << std::endl;
+ if (context == "")
+ context = ".";
+ if (name == "")
+ name = "\"\"";
+ (*m_scalar) << "scalar " << context << " " << name << " " << val << std::endl;
// end OmnetDataOutput::OmnetOutputCallback::OutputSingleton
}
+
void
-OmnetDataOutput::OmnetOutputCallback::OutputSingleton(std::string key,
- std::string variable,
+OmnetDataOutput::OmnetOutputCallback::OutputSingleton(std::string context,
+ std::string name,
uint32_t val)
{
- (*m_scalar) << "scalar " << key << " " << variable << " " << val << std::endl;
+ if (context == "")
+ context = ".";
+ if (name == "")
+ name = "\"\"";
+ (*m_scalar) << "scalar " << context << " " << name << " " << val << std::endl;
// end OmnetDataOutput::OmnetOutputCallback::OutputSingleton
}
+
void
-OmnetDataOutput::OmnetOutputCallback::OutputSingleton(std::string key,
- std::string variable,
+OmnetDataOutput::OmnetOutputCallback::OutputSingleton(std::string context,
+ std::string name,
double val)
{
- (*m_scalar) << "scalar " << key << " " << variable << " " << val << std::endl;
+ if (context == "")
+ context = ".";
+ if (name == "")
+ name = "\"\"";
+ (*m_scalar) << "scalar " << context << " " << name << " " << val << std::endl;
// end OmnetDataOutput::OmnetOutputCallback::OutputSingleton
}
+
void
-OmnetDataOutput::OmnetOutputCallback::OutputSingleton(std::string key,
- std::string variable,
+OmnetDataOutput::OmnetOutputCallback::OutputSingleton(std::string context,
+ std::string name,
std::string val)
{
- (*m_scalar) << "scalar " << key << " " << variable << " " << val << std::endl;
+ if (context == "")
+ context = ".";
+ if (name == "")
+ name = "\"\"";
+ (*m_scalar) << "scalar " << context << " " << name << " " << val << std::endl;
// end OmnetDataOutput::OmnetOutputCallback::OutputSingleton
}
+
void
-OmnetDataOutput::OmnetOutputCallback::OutputSingleton(std::string key,
- std::string variable,
+OmnetDataOutput::OmnetOutputCallback::OutputSingleton(std::string context,
+ std::string name,
Time val)
{
- (*m_scalar) << "scalar " << key << " " << variable << " " << val << std::endl;
+ if (context == "")
+ context = ".";
+ if (name == "")
+ name = "\"\"";
+ (*m_scalar) << "scalar " << context << " " << name << " " << val.GetTimeStep() << std::endl;
// end OmnetDataOutput::OmnetOutputCallback::OutputSingleton
}
diff -r 5d448b8564e5 src/contrib/stats/omnet-data-output.h
--- a/src/contrib/stats/omnet-data-output.h Mon Jun 29 13:24:10 2009 +0200
+++ b/src/contrib/stats/omnet-data-output.h Wed Jul 01 16:12:09 2009 +0200
@@ -45,24 +45,28 @@
public:
OmnetOutputCallback(std::ostream *scalar);
- void OutputSingleton(std::string key,
- std::string variable,
+ void OutputStatistic(std::string context,
+ std::string name,
+ const StatisticalSummary *statSum);
+
+ void OutputSingleton(std::string context,
+ std::string name,
int val);
- void OutputSingleton(std::string key,
- std::string variable,
+ void OutputSingleton(std::string context,
+ std::string name,
uint32_t val);
- void OutputSingleton(std::string key,
- std::string variable,
+ void OutputSingleton(std::string context,
+ std::string name,
double val);
- void OutputSingleton(std::string key,
- std::string variable,
+ void OutputSingleton(std::string context,
+ std::string name,
std::string val);
- void OutputSingleton(std::string key,
- std::string variable,
+ void OutputSingleton(std::string context,
+ std::string name,
Time val);
private:
diff -r 5d448b8564e5 src/contrib/stats/sqlite-data-output.cc
--- a/src/contrib/stats/sqlite-data-output.cc Mon Jun 29 13:24:10 2009 +0200
+++ b/src/contrib/stats/sqlite-data-output.cc Wed Jul 01 16:12:09 2009 +0200
@@ -154,6 +154,25 @@
}
void
+SqliteDataOutput::SqliteOutputCallback::OutputStatistic(std::string key,
+ std::string variable,
+ const StatisticalSummary *statSum)
+{
+ OutputSingleton(key,variable+"-count", (double)statSum->getCount());
+ if (!isNaN(statSum->getSum()))
+ OutputSingleton(key,variable+"-total", statSum->getSum());
+ if (!isNaN(statSum->getMax()))
+ OutputSingleton(key,variable+"-max", statSum->getMax());
+ if (!isNaN(statSum->getMin()))
+ OutputSingleton(key,variable+"-min", statSum->getMin());
+ if (!isNaN(statSum->getSqrSum()))
+ OutputSingleton(key,variable+"-sqrsum", statSum->getSqrSum());
+ if (!isNaN(statSum->getStddev()))
+ OutputSingleton(key,variable+"-stddev", statSum->getStddev());
+}
+
+
+void
SqliteDataOutput::SqliteOutputCallback::OutputSingleton(std::string key,
std::string variable,
int val)
diff -r 5d448b8564e5 src/contrib/stats/sqlite-data-output.h
--- a/src/contrib/stats/sqlite-data-output.h Mon Jun 29 13:24:10 2009 +0200
+++ b/src/contrib/stats/sqlite-data-output.h Wed Jul 01 16:12:09 2009 +0200
@@ -48,6 +48,10 @@
public:
SqliteOutputCallback(Ptr owner, std::string run);
+ void OutputStatistic(std::string key,
+ std::string variable,
+ const StatisticalSummary *statSum);
+
void OutputSingleton(std::string key,
std::string variable,
int val);
diff -r 5d448b8564e5 src/contrib/stats/time-data-calculators.cc
--- a/src/contrib/stats/time-data-calculators.cc Mon Jun 29 13:24:10 2009 +0200
+++ b/src/contrib/stats/time-data-calculators.cc Wed Jul 01 16:12:09 2009 +0200
@@ -70,12 +70,12 @@
void
TimeMinMaxAvgTotalCalculator::Output(DataOutputCallback &callback) const
{
- callback.OutputSingleton(m_key, "count", m_count);
+ callback.OutputSingleton(m_context, m_key + "-count", m_count);
if (m_count > 0) {
- callback.OutputSingleton(m_key, "total", m_total);
- callback.OutputSingleton(m_key, "average", m_total/Scalar(m_count));
- callback.OutputSingleton(m_key, "max", m_max);
- callback.OutputSingleton(m_key, "min", m_min);
+ callback.OutputSingleton(m_context, m_key + "-total", m_total);
+ callback.OutputSingleton(m_context, m_key + "-average", m_total/Scalar(m_count));
+ callback.OutputSingleton(m_context, m_key + "-max", m_max);
+ callback.OutputSingleton(m_context, m_key + "-min", m_min);
}
// end TimeMinMaxAvgTotalCalculator::Output
}