[add][mod] added output files and modified config
- added OutputFile class to library - [mod] use file from arg as config if exists - [mod] added readme text
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
# untitled
|
||||
# Sensor Simulation
|
||||
|
||||
Sensor simulation that focuses on generating high volumes of sensor output. The output can be used to simulate faulty and correct behaviour, based on a ground truth. To remove the requirement of collecting and compose ground truth values for specific scenarios, the simulation also allows for a ground truth to be automatically generated during the simulation. The simulation is fully controllable and creates reproducible outputs with a given configuration.
|
||||
|
||||
## Wiki
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
simulation:
|
||||
duration: 24
|
||||
tickfactor: 10
|
||||
tickfactor: 1
|
||||
runs: 1
|
||||
parCell: 0
|
||||
parCellThreads: 5
|
||||
@@ -19,10 +19,7 @@ sensors:
|
||||
- [1, 1, 5]
|
||||
- [2, 2, 5]
|
||||
- [3, 3, 5]
|
||||
blocks:
|
||||
- start: [0, 4]
|
||||
end: [6, 6]
|
||||
count: 210
|
||||
- [4, 4, 5]
|
||||
|
||||
- group: faultyTemp
|
||||
parent: temperature
|
||||
@@ -36,39 +33,47 @@ sensors:
|
||||
cells:
|
||||
- [3, 3, 5]
|
||||
|
||||
# all cells are declared to output the gt
|
||||
# of baseline for each into the console
|
||||
# all cells are declared to output the gt
|
||||
# of baseline for each into the console
|
||||
- group: baseline
|
||||
blocks:
|
||||
- start: [0, 0]
|
||||
end: [6, 6]
|
||||
count: 0
|
||||
- [0, 0, 0]
|
||||
- [1, 1, 0]
|
||||
- [2, 2, 0]
|
||||
- [3, 3, 0]
|
||||
- [4, 4, 0]
|
||||
|
||||
groundtruths:
|
||||
- group: baseline
|
||||
truth:
|
||||
- value: 10.0
|
||||
- value: 7.0
|
||||
timeline:
|
||||
- start: 0
|
||||
end: 7
|
||||
- [18, 24]
|
||||
- [7, 10]
|
||||
- [12, 16.0]
|
||||
end: 2
|
||||
- [19, 22]
|
||||
- [2, 7.0]
|
||||
- [22, 7.0]
|
||||
delta:
|
||||
- name: fluctuate
|
||||
args: {range: 0.0, center: [3, 3], distOffset: -0.5, time:[0, 12, 18]}
|
||||
args: {range: 0.0, center: [3, 3], distOffset: -0.5, time:[0, 19, 22]}
|
||||
timeline:
|
||||
- [0, 7]
|
||||
- [12, 16]
|
||||
- [18, 24]
|
||||
- [7, change, {range: 0.0, target: 16.0, targetTime: 12, center: [3, 3], distOffset: -0.5, time:[7]}]
|
||||
- [16, change, {range: 0.0, target: 10.0, targetTime: 18, center: [3, 3], distOffset: -0.5, time:[]}]
|
||||
- [0, 2]
|
||||
- [3, 5]
|
||||
- [8, 9]
|
||||
- [19, 22]
|
||||
- [23, 24]
|
||||
- [2, change, {range: 0.0, target: 6.0, targetTime: 3, center: [3, 3], distOffset: -0.5, time:[2]}]
|
||||
- [5, change, {range: 0.0, target: 4.0, targetTime: 7, center: [3, 3], distOffset: -0.5, time:[]}]
|
||||
- [7, change, {range: 0.0, target: 5.0, targetTime: 8, center: [3, 3], distOffset: -0.5, time:[]}]
|
||||
- [9, change, {range: 0.0, target: 9.0, targetTime: 17, center: [3, 3], distOffset: -0.5, time:[]}]
|
||||
- [17, change, {range: 0.0, target: 7.0, targetTime: 19, center: [3, 3], distOffset: -0.5, time:[]}]
|
||||
- [22, change, {range: 0.0, target: 6.0, targetTime: 23, center: [3, 3], distOffset: -0.5, time:[22]}]
|
||||
|
||||
- group: temperature
|
||||
parent: baseline
|
||||
delta:
|
||||
- name: fluctuate
|
||||
args: {range: 1.0}
|
||||
args: {range: 0.3}
|
||||
timeline:
|
||||
- [0, 7]
|
||||
- [12, 16]
|
||||
|
||||
@@ -8,11 +8,12 @@ import scim.lib.simInterfaces.SimulationBehaviour
|
||||
object Main {
|
||||
// o7
|
||||
def main(args: Array[String]): Unit = {
|
||||
startSimulation()
|
||||
val file = if(args.length > 0) args(0) else "docs/wiki/config/config_due.yml"
|
||||
startSimulation(file)
|
||||
}
|
||||
|
||||
def startSimulation(): Unit = {
|
||||
val config = new Parser().parse("docs/wiki/config/config_preview.yml", scim.components.behaviour.behaviours)
|
||||
def startSimulation(file: String): Unit = {
|
||||
val config = new Parser().parse(file, scim.components.behaviour.behaviours)
|
||||
val sharedMemory = config.sharedMemory
|
||||
val output = new Output(sharedMemory)
|
||||
val simulator = new Simulation(config)
|
||||
|
||||
@@ -159,7 +159,7 @@ package object behaviour {
|
||||
|
||||
def fluctuate (cell: Cell, time: Time, inTruth: Option[Double], args: Option[FunctionArgs]): Option[Double] = {
|
||||
if(inTruth.isEmpty) return None
|
||||
val range: Double = args.getParam("range", 1.0)
|
||||
val range: Double = args.getParam("range", 0.0)
|
||||
val center: Vector[Int] = args.getParam("center", Vector(0, 0))
|
||||
val distOffset: Option[Double] = args.getParam[Double]("distOffset")
|
||||
val offsetTimes: Option[Vector[Int]] = args.getParam[Vector[Int]]("time")
|
||||
@@ -177,7 +177,7 @@ package object behaviour {
|
||||
|
||||
def change (cell: Cell, time: Time, inTruth: Option[Double], args: Option[FunctionArgs]): Option[Double] = {
|
||||
if(inTruth.isEmpty) return None
|
||||
val range: Double = args.getParam("range", 1.0)
|
||||
val range: Double = args.getParam("range", 0.0)
|
||||
val target: Double = args.getParam("target", inTruth.get + 5)
|
||||
val targetTime: Int = args.getParam("targetTime", time.getNormalized + 1) * time.tickfactor.getOrElse(1) + 1
|
||||
val center: Vector[Int] = args.getParam("center", Vector(0, 0))
|
||||
|
||||
@@ -2,16 +2,27 @@ package scim.components
|
||||
|
||||
import scim.datastruct.{Cell, Group, SensorResult, SharedMemory, Time, Truth}
|
||||
import scim.lib.consoleUtil.Color._
|
||||
import scim.lib.io._
|
||||
|
||||
class Output(sharedMemory: SharedMemory, printOutput: Boolean = true) extends Runnable {
|
||||
val outputFileBaseline = OutputFile("baseline.txt")
|
||||
val outputFileTemperature = OutputFile("temperature.txt")
|
||||
val outputFileFaultyTemp = OutputFile("faultyTemp.txt")
|
||||
val outputFileSensor = OutputFile("sensor_temp.txt")
|
||||
val outputFileFaultySensor = OutputFile("sensor_fault.txt")
|
||||
def run(): Unit = {
|
||||
val duration = sharedMemory.config.getDuration
|
||||
def outputHelper(time: Time): Unit = {
|
||||
val simOutput = sharedMemory.subscribe(time)
|
||||
outputData(time, simOutput._1, simOutput._2)
|
||||
}
|
||||
|
||||
//outputFile.buffer("group,time,x,y,gt\n")
|
||||
Vector.tabulate(duration)(t => Time(t, duration)).foreach(outputHelper)
|
||||
outputFileBaseline.write()
|
||||
outputFileTemperature.write()
|
||||
outputFileFaultyTemp.write()
|
||||
outputFileSensor.write()
|
||||
outputFileFaultySensor.write()
|
||||
}
|
||||
|
||||
def outputData(time: Time, sensors: Map[Cell, Map[Group, Vector[SensorResult]]], groundTruths: Map[Cell, Map[Group, Truth]]): Unit = {
|
||||
@@ -28,6 +39,22 @@ class Output(sharedMemory: SharedMemory, printOutput: Boolean = true) extends Ru
|
||||
groups._2.foreach(res => print(res.get._3.getOrElse("None") + (if(res.eq(lastElement.get)) "" else " | ")))
|
||||
if(groundTruths.contains(cell) && groundTruths(cell).contains(group)) print(GREEN("\n Ground Truth: ") + groundTruths(cell)(group).peak().getOrElse("None"))
|
||||
print("\n")
|
||||
|
||||
val x = cell.x; val y = cell.y
|
||||
val groupName = group.name
|
||||
val groupParent = group.parent.getOrElse("");
|
||||
val value = groundTruths(cell)(group).peak().getOrElse(None).getOrElse(None)
|
||||
val sResult = if(groups._2.size > 0) groups._2(0).get._3.getOrElse(None) else None
|
||||
if(groupName == "baseline") {
|
||||
outputFileBaseline.buffer(time.time + "," + x + "," + y + "," + value.toString + "\n")
|
||||
} else if(groupName == "temperature") {
|
||||
outputFileTemperature.buffer(time.time + "," + x + "," + y + "," + value.toString + "\n")
|
||||
outputFileSensor.buffer(time.time + "," + x + "," + y + "," + sResult.toString + "\n")
|
||||
} else if(groupName == "faultyTemp") {
|
||||
outputFileFaultyTemp.buffer(time.time + "," + x + "," + y + "," + value.toString + "\n")
|
||||
outputFileFaultySensor.buffer(time.time + "," + x + "," + y + "," + sResult.toString + "\n")
|
||||
}
|
||||
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ class SimulationConfigParser(input: Map[String, Any], simulationBehaviours: Simu
|
||||
val blockCells = Cell(start(0), start(1)).block(Cell(end(0), end(1)))
|
||||
val countPerCell: Int = count / blockCells.length
|
||||
var countRest: Int = count % blockCells.length
|
||||
|
||||
// TODO: filter out empty cells and return early if countPerCell == 0
|
||||
val result: Vector[(Cell, SensorCount)] = blockCells.map(cell => {
|
||||
val sensorCount = SensorCount(countPerCell + (if(countRest > 0) 1 else 0))
|
||||
if(countRest > 0) countRest -= 1
|
||||
@@ -150,7 +150,7 @@ class SimulationConfigParser(input: Map[String, Any], simulationBehaviours: Simu
|
||||
mergeMaps[Cell, SensorCount](blocks.map(parseBlock), (a: SensorCount, b: SensorCount) => a.add(b), SensorCount(0))
|
||||
}
|
||||
|
||||
// don't add tickfacor here, this is done in parseTruth with config.time()
|
||||
// don't add tickfacor here, this is done in parseTruth with config.time() and parseFunction with config.tickfactor
|
||||
private def parseTimeLineElement(timeLineElement: Any): (Int, Option[Int]) = {
|
||||
timeLineElement match {
|
||||
case timeLineElement: Vector[_] => val elementVector = timeLineElement.asInstanceOf[Vector[Int]]
|
||||
|
||||
@@ -163,7 +163,7 @@ case class FunctionArgs(args: Map[String, Any]) {
|
||||
}
|
||||
|
||||
case class BehaviourVector(function: Vector[Option[(SimulationBehaviour, Option[FunctionArgs])]],
|
||||
defaultFunc: SimulationBehaviour = (_: Cell, _: Time, v: Option[Double], _: Option[FunctionArgs]) => v,
|
||||
defaultFunc: SimulationBehaviour = (_: Cell, _: Time, _: Option[Double], _: Option[FunctionArgs]) => None,
|
||||
defaultArgs: Option[FunctionArgs] = None) {
|
||||
def get(t: Time): (SimulationBehaviour, Option[FunctionArgs]) = {
|
||||
function(t.time).getOrElse((defaultFunc, defaultArgs))
|
||||
|
||||
@@ -439,3 +439,29 @@ package object parserUtil {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
package object io {
|
||||
import java.io._
|
||||
case class OutputFile(fileName: String = "output.txt", newFile: Boolean = true) {
|
||||
val file = new File(fileName)
|
||||
val buffer: mutable.StringBuilder = new mutable.StringBuilder()
|
||||
|
||||
if(newFile) {
|
||||
val fw = new FileWriter(file)
|
||||
fw.write("")
|
||||
fw.close()
|
||||
}
|
||||
|
||||
def buffer(text: String): Unit = {
|
||||
buffer.append(text)
|
||||
}
|
||||
|
||||
def write(): Unit = {
|
||||
val fwAppend = new FileWriter(file, true)
|
||||
fwAppend.write(buffer.toString())
|
||||
fwAppend.close()
|
||||
buffer.clear()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user