Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F386265
sa-ews1.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Size
11 KB
Referenced Files
None
Subscribers
None
sa-ews1.cpp
View Options
//===-- apps/sa-ews1/sa-ews1.cpp --------------------------------*- C++ -*-===//
//
// The RoSA Framework -- Application SA-EWS1
//
//===----------------------------------------------------------------------===//
///
/// \file apps/sa-ews1/sa-ews1.cpp
///
/// \author David Juhasz (david.juhasz@tuwien.ac.at)
///
/// \date 2017-2019
///
/// \brief The application SA-EWS1 implements the case study from the paper:
/// M. Götzinger, N. Taherinejad, A. M. Rahmani, P. Liljeberg, A. Jantsch, and
/// H. Tenhunen: Enhancing the Early Warning Score System Using Data Confidence
/// DOI: 10.1007/978-3-319-58877-3_12
//===----------------------------------------------------------------------===//
#include
"rosa/agent/Abstraction.hpp"
#include
"rosa/agent/Confidence.hpp"
#include
"rosa/config/version.h"
#include
"rosa/deluxe/DeluxeContext.hpp"
#include
"rosa/support/csv/CSVReader.hpp"
#include
"rosa/support/csv/CSVWriter.hpp"
#include
<fstream>
using
namespace
rosa
;
using
namespace
rosa
::
agent
;
using
namespace
rosa
::
deluxe
;
using
namespace
rosa
::
terminal
;
const
std
::
string
AppName
=
"SA-EWS1"
;
/// Paths for the CSV files for simulation.
///
///@{
const
std
::
string
HRCSVPath
=
"HR.csv"
;
const
std
::
string
BRCSVPath
=
"BR.csv"
;
const
std
::
string
SpO2CSVPath
=
"SpO2.csv"
;
const
std
::
string
BPSysCSVPath
=
"BPSys.csv"
;
const
std
::
string
BodyTempCSVPath
=
"BodyTemp.csv"
;
const
std
::
string
ScoreCSVPath
=
"Score.csv"
;
///@}
/// How many cycles of simulation to perform.
const
size_t
NumberOfSimulationCycles
=
16
;
/// Warning levels for abstraction.
enum
WarningScore
{
No
=
0
,
Low
=
1
,
High
=
2
,
Emergency
=
3
};
/// Helper function creating a deluxe agent for pre-processing sensory values.
///
/// Received values are first validated for confidence. Values which the
/// validator does not mark confident are ignored. Confident values are
/// abstracted into a \c WarningScore value, which is the result of the
/// processing function.
///
/// \note The result, \c WarningScore, is returned as \c uint32_t because
/// enumeration types are not integrated into built-in types. Hence, a master
/// to these agents receives its input as \c uint32_t values, and may cast them
/// to \c WarningScore explicitly.
///
/// \tparam T type of values to receive from the sensor
///
/// \param C the deluxe context to create the agent in
/// \param Name name of the new agent
/// \param CC confidence validator to use
/// \param A abstraction to use
///
/// \return handle for the new agent
template
<
typename
T
>
AgentHandle
createLowLevelAgent
(
std
::
unique_ptr
<
DeluxeContext
>
&
C
,
const
std
::
string
&
Name
,
const
Confidence
<
T
>
&
CC
,
const
Abstraction
<
T
,
WarningScore
>
&
A
)
{
using
handler
=
std
::
function
<
Optional
<
uint32_t
>
(
std
::
pair
<
T
,
bool
>
)
>
;
using
result
=
Optional
<
uint32_t
>
;
return
C
->
createAgent
(
Name
,
handler
([
&
,
Name
](
std
::
pair
<
T
,
bool
>
I
)
->
result
{
LOG_INFO_STREAM
<<
"
\n
******
\n
"
<<
Name
<<
" "
<<
(
I
.
second
?
"<New>"
:
"<Old>"
)
<<
" value: "
<<
I
.
first
<<
"
\n
******
\n
"
;
return
(
I
.
second
&&
CC
(
I
.
first
))
?
result
(
A
(
I
.
first
))
:
result
();
}));
}
int
main
(
void
)
{
LOG_INFO_STREAM
<<
'\n'
<<
library_string
()
<<
" -- "
<<
Color
::
Red
<<
AppName
<<
"app"
<<
Color
::
Default
<<
'\n'
<<
Color
::
Yellow
<<
"CSV files are read from and written to the current working directory."
<<
Color
::
Default
<<
'\n'
;
std
::
unique_ptr
<
DeluxeContext
>
C
=
DeluxeContext
::
create
(
AppName
);
//
// Create deluxe sensors.
//
LOG_INFO
(
"Creating sensors."
);
// All sensors are created without defining a normal generator function, but
// with the default value of the second argument. That, however, requires the
// data type to be explicitly defined. This is good for simulation only.
AgentHandle
HRSensor
=
C
->
createSensor
<
int32_t
>
(
"HR Sensor"
);
AgentHandle
BRSensor
=
C
->
createSensor
<
int32_t
>
(
"BR Sensor"
);
AgentHandle
SpO2Sensor
=
C
->
createSensor
<
int32_t
>
(
"SpO2 Sensor"
);
AgentHandle
BPSysSensor
=
C
->
createSensor
<
int32_t
>
(
"BPSys Sensor"
);
AgentHandle
BodyTempSensor
=
C
->
createSensor
<
float
>
(
"BodyTemp Sensor"
);
//
// Create functionalities.
//
LOG_INFO
(
"Creating Functionalities for Agents."
);
//
// Define confidence validators.
//
// Lower bounds are inclusive and upper bounds are exclusive.
Confidence
<
int32_t
>
HRConfidence
(
0
,
501
);
Confidence
<
int32_t
>
BRConfidence
(
0
,
301
);
Confidence
<
int32_t
>
SpO2Confidence
(
0
,
101
);
Confidence
<
int32_t
>
BPSysConfidence
(
0
,
501
);
Confidence
<
float
>
BodyTempConfidence
(
-60
,
nextRepresentableFloatingPoint
(
50.0f
));
//
// Define abstractions.
//
RangeAbstraction
<
int32_t
,
WarningScore
>
HRAbstraction
(
{{{
0
,
40
},
Emergency
},
{{
40
,
51
},
High
},
{{
51
,
60
},
Low
},
{{
60
,
100
},
No
},
{{
100
,
110
},
Low
},
{{
110
,
129
},
High
},
{{
129
,
200
},
Emergency
}},
Emergency
);
RangeAbstraction
<
int32_t
,
WarningScore
>
BRAbstraction
({{{
0
,
9
},
High
},
{{
9
,
14
},
No
},
{{
14
,
20
},
Low
},
{{
20
,
29
},
High
},
{{
29
,
50
},
Emergency
}},
Emergency
);
RangeAbstraction
<
int32_t
,
WarningScore
>
SpO2Abstraction
({{{
1
,
85
},
Emergency
},
{{
85
,
90
},
High
},
{{
90
,
95
},
Low
},
{{
95
,
100
},
No
}},
Emergency
);
RangeAbstraction
<
int32_t
,
WarningScore
>
BPSysAbstraction
(
{{{
0
,
70
},
Emergency
},
{{
70
,
81
},
High
},
{{
81
,
101
},
Low
},
{{
101
,
149
},
No
},
{{
149
,
169
},
Low
},
{{
169
,
179
},
High
},
{{
179
,
200
},
Emergency
}},
Emergency
);
RangeAbstraction
<
float
,
WarningScore
>
BodyTempAbstraction
(
{{{
0.f
,
28.f
},
Emergency
},
{{
28.f
,
32.f
},
High
},
{{
32.f
,
35.f
},
Low
},
{{
35.f
,
38.f
},
No
},
{{
38.f
,
39.5f
},
High
},
{{
39.5f
,
100.f
},
Emergency
}},
Emergency
);
//
// Create low-level deluxe agents with \c createLowLevelAgent.
//
LOG_INFO
(
"Creating low-level agents."
);
AgentHandle
HRAgent
=
createLowLevelAgent
(
C
,
"HR Agent"
,
HRConfidence
,
HRAbstraction
);
AgentHandle
BRAgent
=
createLowLevelAgent
(
C
,
"BR Agent"
,
BRConfidence
,
BRAbstraction
);
AgentHandle
SpO2Agent
=
createLowLevelAgent
(
C
,
"SpO2 Agent"
,
SpO2Confidence
,
SpO2Abstraction
);
AgentHandle
BPSysAgent
=
createLowLevelAgent
(
C
,
"BPSys Agent"
,
BPSysConfidence
,
BPSysAbstraction
);
AgentHandle
BodyTempAgent
=
createLowLevelAgent
(
C
,
"BodyTemp Agent"
,
BodyTempConfidence
,
BodyTempAbstraction
);
//
// Connect sensors to low-level agents.
//
LOG_INFO
(
"Connect sensors to their corresponding low-level agents."
);
C
->
connectSensor
(
HRAgent
,
0
,
HRSensor
,
"HR Sensor Channel"
);
C
->
connectSensor
(
BRAgent
,
0
,
BRSensor
,
"BR Sensor Channel"
);
C
->
connectSensor
(
SpO2Agent
,
0
,
SpO2Sensor
,
"SpO2 Sensor Channel"
);
C
->
connectSensor
(
BPSysAgent
,
0
,
BPSysSensor
,
"BPSys Sensor Channel"
);
C
->
connectSensor
(
BodyTempAgent
,
0
,
BodyTempSensor
,
"BodyTemp Sensor Channel"
);
//
// Create a high-level deluxe agent.
//
LOG_INFO
(
"Create high-level agent."
);
// The new agent logs its input values and results in the the sum of them.
AgentHandle
BodyAgent
=
C
->
createAgent
(
"Body Agent"
,
std
::
function
<
Optional
<
uint32_t
>
(
std
::
pair
<
uint32_t
,
bool
>
,
std
::
pair
<
uint32_t
,
bool
>
,
std
::
pair
<
uint32_t
,
bool
>
,
std
::
pair
<
uint32_t
,
bool
>
,
std
::
pair
<
uint32_t
,
bool
>
)
>
(
[](
std
::
pair
<
uint32_t
,
bool
>
HR
,
std
::
pair
<
uint32_t
,
bool
>
BR
,
std
::
pair
<
uint32_t
,
bool
>
SpO2
,
std
::
pair
<
uint32_t
,
bool
>
BPSys
,
std
::
pair
<
uint32_t
,
bool
>
BodyTemp
)
->
Optional
<
uint32_t
>
{
LOG_INFO_STREAM
<<
"
\n
*******
\n
Body Agent trigged with values:
\n
"
<<
(
HR
.
second
?
"<New>"
:
"<Old>"
)
<<
" HR warning score: "
<<
HR
.
first
<<
"
\n
"
<<
(
BR
.
second
?
"<New>"
:
"<Old>"
)
<<
" BR warning score: "
<<
BR
.
first
<<
"
\n
"
<<
(
SpO2
.
second
?
"<New>"
:
"<Old>"
)
<<
" SpO2 warning score: "
<<
SpO2
.
first
<<
"
\n
"
<<
(
BPSys
.
second
?
"<New>"
:
"<Old>"
)
<<
" BPSys warning score: "
<<
BPSys
.
first
<<
"
\n
"
<<
(
BodyTemp
.
second
?
"<New>"
:
"<Old>"
)
<<
" BodyTemp warning score: "
<<
BodyTemp
.
first
<<
"
\n
******
\n
"
;
return
{
HR
.
first
+
BR
.
first
+
SpO2
.
first
+
BPSys
.
first
+
BodyTemp
.
first
};
}));
//
// Connect low-level agents to the high-level agent.
//
LOG_INFO
(
"Connect low-level agents to the high-level agent."
);
C
->
connectAgents
(
BodyAgent
,
0
,
HRAgent
,
"HR Agent Channel"
);
C
->
connectAgents
(
BodyAgent
,
1
,
BRAgent
,
"BR Agent Channel"
);
C
->
connectAgents
(
BodyAgent
,
2
,
SpO2Agent
,
"SpO2 Agent Channel"
);
C
->
connectAgents
(
BodyAgent
,
3
,
BPSysAgent
,
"BPSys Agent Channel"
);
C
->
connectAgents
(
BodyAgent
,
4
,
BodyTempAgent
,
"BodyTemp Agent Channel"
);
//
// For simulation output, create a logger agent writing the output of the
// high-level agent into a CSV file.
//
LOG_INFO
(
"Create a logger agent."
);
// Create CSV writer.
std
::
ofstream
ScoreCSV
(
ScoreCSVPath
);
csv
::
CSVWriter
<
uint32_t
>
ScoreWriter
(
ScoreCSV
);
// The agent writes each new input value into a CSV file and produces nothing.
AgentHandle
LoggerAgent
=
C
->
createAgent
(
"Logger Agent"
,
std
::
function
<
Optional
<
unit_t
>
(
std
::
pair
<
uint32_t
,
bool
>
)
>
(
[
&
ScoreWriter
](
std
::
pair
<
uint32_t
,
bool
>
Score
)
->
Optional
<
unit_t
>
{
if
(
Score
.
second
)
{
// The state of \p ScoreWriter is not checked, expecting good.
ScoreWriter
<<
Score
.
first
;
}
return
{};
}));
//
// Connect the high-level agent to the logger agent.
//
LOG_INFO
(
"Connect the high-level agent to the logger agent."
);
C
->
connectAgents
(
LoggerAgent
,
0
,
BodyAgent
,
"Body Agent Channel"
);
//
// Do simulation.
//
LOG_INFO
(
"Setting up and performing simulation."
);
//
// Initialize deluxe context for simulation.
//
C
->
initializeSimulation
();
//
// Open CSV files and register them for their corresponding sensors.
//
// Type aliases for iterators.
using
CSVInt
=
csv
::
CSVFlatIterator
<
int32_t
>
;
using
CSVFloat
=
csv
::
CSVFlatIterator
<
float
>
;
std
::
ifstream
HRCSV
(
HRCSVPath
);
C
->
registerSensorValues
(
HRSensor
,
CSVInt
(
HRCSV
),
CSVInt
());
std
::
ifstream
BRCSV
(
BRCSVPath
);
C
->
registerSensorValues
(
BRSensor
,
CSVInt
(
BRCSV
),
CSVInt
());
std
::
ifstream
SpO2CSV
(
SpO2CSVPath
);
C
->
registerSensorValues
(
SpO2Sensor
,
CSVInt
(
SpO2CSV
),
CSVInt
());
std
::
ifstream
BPSysCSV
(
BPSysCSVPath
);
C
->
registerSensorValues
(
BPSysSensor
,
CSVInt
(
BPSysCSV
),
CSVInt
());
std
::
ifstream
BodyTempCSV
(
BodyTempCSVPath
);
C
->
registerSensorValues
(
BodyTempSensor
,
CSVFloat
(
BodyTempCSV
),
CSVFloat
());
//
// Simulate.
//
C
->
simulate
(
NumberOfSimulationCycles
);
return
0
;
}
File Metadata
Details
Attached
Mime Type
text/x-c++
Expires
Wed, Jul 2, 6:23 AM (11 h, 11 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
157119
Default Alt Text
sa-ews1.cpp (11 KB)
Attached To
Mode
R20 SoC_Rosa_repo
Attached
Detach File
Event Timeline
Log In to Comment