Fix for number started xml name

This commit is contained in:
Alexander Nozik 2018-04-18 14:22:03 +03:00
parent 32b9a44a7f
commit a425d6cb6c
3 changed files with 122 additions and 55 deletions

View File

@ -139,7 +139,7 @@ object Communications {
data class DanteMessage(val command: CommandType, val board: Int, val packet: Int, val payload: ByteArray) { data class DanteMessage(val command: CommandType, val board: Int, val packet: Int, val payload: ByteArray) {
override fun toString(): String { override fun toString(): String {
return "${command.name}[$board, $packet]: ${payload.size}" return "${command.name}[$board, $packet] of size ${payload.size}"
} }
} }

View File

@ -32,6 +32,7 @@ import java.lang.Math.pow
import java.net.Socket import java.net.Socket
import java.nio.ByteBuffer import java.nio.ByteBuffer
import java.nio.ByteOrder import java.nio.ByteOrder
import java.time.Duration
import java.time.Instant import java.time.Instant
import java.util.* import java.util.*
import java.util.concurrent.atomic.AtomicLong import java.util.concurrent.atomic.AtomicLong
@ -69,7 +70,7 @@ class DanteClient(val ip: String, chainLength: Int) : AutoCloseable {
*/ */
private data class BoardState(val num: Int, var meta: Meta? = null) private data class BoardState(val num: Int, var meta: Meta? = null)
private val boards = (0 until chainLength).map { BoardState(it) } private val boards = (0..chainLength).map { BoardState(it) }
fun open() { fun open() {
@ -118,16 +119,18 @@ class DanteClient(val ip: String, chainLength: Int) : AutoCloseable {
val socket = Socket(ip, 8000 + port) val socket = Socket(ip, 8000 + port)
logger.info("Opened socket {}", socket.inetAddress) logger.info("Opened socket {}", "${socket.inetAddress}:${socket.port}")
//Create command queue on port 0 //Create command queue on port 0
if (port == 0) { if (port == 0) {
outputJob.cancel() //outputJob.cancel()
output = socket.getOutputStream() output = socket.getOutputStream()
outputJob = launch(context = pool, parent = parentJob) { outputJob = launch(context = pool, parent = parentJob) {
val command = sendChannel.receive() while (true) {
output.write(command) val command = sendChannel.receive()
logger.debug("Sent {}", command.hex) output.write(command)
logger.trace("Sent {}", command.hex)
}
} }
} }
@ -139,10 +142,11 @@ class DanteClient(val ip: String, chainLength: Int) : AutoCloseable {
// second check is not executed unless first one is true // second check is not executed unless first one is true
val header = ByteArray(6) val header = ByteArray(6)
stream.read(header) stream.read(header)
val command = Communications.CommandType.values().find { it.byte == header[0] }!! val command = Communications.CommandType.values().find { it.byte == header[0] }
?: throw RuntimeException("Unknown command code: ${header[0]}")
val board = header[1] val board = header[1]
val packet = header[2] val packet = header[2]
val length = header[3].positive * 0x100 + header[4].positive * 0x010 + header[5].positive val length = (header[3].positive * 0x100 + header[4].positive * 0x010 + header[5].positive) * 4
val payload = ByteArray(length) val payload = ByteArray(length)
stream.read(payload) stream.read(payload)
handle(Communications.DanteMessage(command, board.positive, packet.positive, payload)) handle(Communications.DanteMessage(command, board.positive, packet.positive, payload))
@ -171,7 +175,7 @@ class DanteClient(val ip: String, chainLength: Int) : AutoCloseable {
* Generate next packet number * Generate next packet number
*/ */
private fun nextPacket(): Int { private fun nextPacket(): Int {
return (packetNumber.incrementAndGet() % 256 - 128).toInt() return (packetNumber.incrementAndGet() % 256).toInt()
} }
private fun List<Long>.asBuffer(): ByteBuffer { private fun List<Long>.asBuffer(): ByteBuffer {
@ -191,9 +195,9 @@ class DanteClient(val ip: String, chainLength: Int) : AutoCloseable {
private suspend fun writeRegister(board: Int, register: Int, data: List<Long>, mask: Long? = null) { private suspend fun writeRegister(board: Int, register: Int, data: List<Long>, mask: Long? = null) {
//representing data as byte buffer //representing data as byte buffer
val buffer = if (mask != null) { val buffer = if (mask != null) {
val oldData = readRegister(board, register, data.size) val oldData = withTimeout(1000) { readRegister(board, register, data.size) }
//(oldData & not_mask) | (newData & mask); //(oldData & not_mask) | (newData & mask);
(0..data.size).map { (oldData[it] and mask.inv()).or(data[it] and mask) }.asBuffer(); (0 until data.size).map { (oldData[it] and mask.inv()).or(data[it] and mask) }.asBuffer();
} else { } else {
data.asBuffer() data.asBuffer()
} }
@ -206,6 +210,7 @@ class DanteClient(val ip: String, chainLength: Int) : AutoCloseable {
} }
private suspend fun readRegister(board: Int, register: Int, length: Int = 1): List<Long> { private suspend fun readRegister(board: Int, register: Int, length: Int = 1): List<Long> {
val packet = nextPacket() val packet = nextPacket()
send(READ, board, packet, register, length = length) send(READ, board, packet, register, length = length)
var message: Communications.DanteMessage? = null var message: Communications.DanteMessage? = null
@ -222,6 +227,10 @@ class DanteClient(val ip: String, chainLength: Int) : AutoCloseable {
}.map { it.positive }.toList() }.map { it.positive }.toList()
} }
suspend fun getFirmwareVersion(): Long {
return readRegister(0, Communications.Register.FIRMWARE_VERSION.code)[0]
}
/** /**
* Write a single DPP parameter * Write a single DPP parameter
* @param register number of parameter register * @param register number of parameter register
@ -242,15 +251,15 @@ class DanteClient(val ip: String, chainLength: Int) : AutoCloseable {
*/ */
suspend fun configureBoard(board: Int, meta: Meta) { suspend fun configureBoard(board: Int, meta: Meta) {
val gain = meta.getDouble("gain") val gain = meta.getDouble("gain")
val det_thresh = meta.getInt("detection_thresold") val det_thresh = meta.getInt("detection_threshold")
val pileup_thr = meta.getInt("pileup_thresold") val pileup_thr = meta.getInt("pileup_threshold")
val en_fil_peak_time = meta.getInt("energy_filter.peaking_time") val en_fil_peak_time = meta.getInt("energy_filter.peaking_time")
val en_fil_flattop = meta.getInt("energy_filter.flat_top") val en_fil_flattop = meta.getInt("energy_filter.flat_top")
val fast_peak_time = meta.getInt("fast_filter.peaking_time") val fast_peak_time = meta.getInt("fast_filter.peaking_time")
val fast_flattop = meta.getInt("fast_filter.flat_top") val fast_flattop = meta.getInt("fast_filter.flat_top")
val recovery_time = meta.getValue("recovery_time").longValue() val recovery_time = meta.getValue("recovery_time").longValue()
val zero_peak_rate = meta.getInt("zero_peak_rate") val zero_peak_rate = meta.getInt("zero_peak_rate")
val inverted_input = meta.getInt("inverted_input") val inverted_input = meta.getInt("inverted_input", 0)
assert(en_fil_peak_time in 1..511) assert(en_fil_peak_time in 1..511)
assert(gain in 0.01..(en_fil_peak_time * 2 - 0.01)) assert(gain in 0.01..(en_fil_peak_time * 2 - 0.01))
@ -306,7 +315,9 @@ class DanteClient(val ip: String, chainLength: Int) : AutoCloseable {
writeDPP(board, 128, 0b100 + inverted_input * (1L shl 24)) writeDPP(board, 128, 0b100 + inverted_input * (1L shl 24))
writeDPP(board, 128, 1 + inverted_input * (1L shl 24)) writeDPP(board, 128, 1 + inverted_input * (1L shl 24))
logger.info("Finished {} board configuration", board) logger.info("Finished {} board configuration", board)
boards.find { it.num == board }?.meta = meta
} }
/** /**
@ -323,14 +334,14 @@ class DanteClient(val ip: String, chainLength: Int) : AutoCloseable {
* Clear unused data * Clear unused data
*/ */
private suspend fun clearData() { private suspend fun clearData() {
for (element in dataChannel) { while (!dataChannel.isEmpty) {
logger.warn("Dumping residual data packet {}", element.toString()) logger.warn("Dumping residual data packet {}", dataChannel.receive().toString())
} }
} }
private suspend fun clearCommunications() { private suspend fun clearCommunications() {
for (element in comChannel) { while (!dataChannel.isEmpty) {
logger.debug("Dumping residual communication packet {}", element.toString()) logger.debug("Dumping residual communication packet {}", dataChannel.receive().toString())
} }
} }
@ -356,7 +367,13 @@ class DanteClient(val ip: String, chainLength: Int) : AutoCloseable {
writeRegister(it.num, ACQUISITION_TIME.code, length.toLong()) writeRegister(it.num, ACQUISITION_TIME.code, length.toLong())
writeRegister(it.num, TIME_PER_MAP_POINT.code, statisticsInterval.toLong(), 0x00FFFFFF) writeRegister(it.num, TIME_PER_MAP_POINT.code, statisticsInterval.toLong(), 0x00FFFFFF)
writeRegister(it.num, MAP_POINTS.code, (length.toDouble() / statisticsInterval).toLong(), 0x00FFFFFF) writeRegister(it.num, MAP_POINTS.code, (length.toDouble() / statisticsInterval).toLong(), 0x00FFFFFF)
if (readRegister(it.num, ACQUISITION_SETTINGS.code)[0] != Communications.AcquisitionMode.LIST_MODE.long) {
throw RuntimeException("Set list mode failed")
}
} }
// logger.info("Waiting for configuration to settle")
// delay(500)
writeRegister(0, ACQUISITION_STATUS.code, 0x00000001, 0x00000001) writeRegister(0, ACQUISITION_STATUS.code, 0x00000001, 0x00000001)
val start = Instant.now() val start = Instant.now()
@ -364,8 +381,12 @@ class DanteClient(val ip: String, chainLength: Int) : AutoCloseable {
val dataCollectorJob = launch(context = pool, parent = parentJob) { val dataCollectorJob = launch(context = pool, parent = parentJob) {
while (true) { while (Duration.between(start, Instant.now()) < Duration.ofMillis(length + 4000L)) {
val packet = dataChannel.receive() val packet = withTimeout(1000) { dataChannel.receive() }
if (packet.command != LIST_MODE) {
logger.warn("Unexpected packet type: {}", packet.command.name)
continue
}
val channel = packet.board val channel = packet.board
// get or create new channel block // get or create new channel block
val channelBuilder = builder.channelsBuilderList.find { it.id.toInt() == channel } val channelBuilder = builder.channelsBuilderList.find { it.id.toInt() == channel }
@ -376,7 +397,7 @@ class DanteClient(val ip: String, chainLength: Int) : AutoCloseable {
it.addBlocksBuilder().also { it.addBlocksBuilder().also {
it.time = (start.epochSecond * 1e9 + start.nano).toLong() it.time = (start.epochSecond * 1e9 + start.nano).toLong()
it.binSize = 8 // tick in nanos it.binSize = 8 // tick in nanos
it.length = length.toLong() * 1000 //block length in nanos it.length = (length * 1e6).toLong() //block length in nanos
} }
} }
} }
@ -402,20 +423,16 @@ class DanteClient(val ip: String, chainLength: Int) : AutoCloseable {
} }
} }
} }
} writeRegister(0, ACQUISITION_STATUS.code, 0x00000001, 0x00000000)
/**
* Cancel data collection after specific time passed
*/
val schedulerJob = launch(context = pool, parent = parentJob) {
delay(length + 2000L)
dataCollectorJob.cancel(CancellationException("Expired"))
} }
val meta = buildMeta { val meta = buildMeta {
setNode("dpp", boards.first().meta) boards.first().meta?.let {
putNode("dpp", it)
}
} }
dataCollectorJob.join() dataCollectorJob.join()
return ProtoNumassPoint(builder.build(), meta) return ProtoNumassPoint(builder.build(), meta)
} }

View File

@ -16,39 +16,89 @@
package inr.numass.control.dante package inr.numass.control.dante
import hep.dataforge.context.Context
import hep.dataforge.context.Global
import hep.dataforge.fx.plots.FXPlotManager
import hep.dataforge.kodex.KMetaBuilder
import hep.dataforge.kodex.buildMeta import hep.dataforge.kodex.buildMeta
import hep.dataforge.kodex.configure
import hep.dataforge.kodex.nullable
import hep.dataforge.plots.data.DataPlot
import hep.dataforge.tables.Adapters
import inr.numass.data.analyzers.NumassAnalyzer
import inr.numass.data.analyzers.SimpleAnalyzer
import inr.numass.data.analyzers.withBinning
import inr.numass.data.api.NumassBlock
import inr.numass.data.channel import inr.numass.data.channel
import kotlinx.coroutines.experimental.runBlocking import kotlinx.coroutines.experimental.runBlocking
fun main(args: Array<String>) { fun main(args: Array<String>) {
val client = DanteClient("192.168.111.123", 7) val client = DanteClient("192.168.111.120", 7)
client.open()
val meta = buildMeta { val meta = buildMeta {
"gain" to 1.0
/* "detection_threshold" to 150
val gain = meta.getDouble("gain") "pileup_threshold" to 1
val det_thresh = meta.getInt("detection_thresold") "energy_filter" to {
val pileup_thr = meta.getInt("pileup_thresold") "peaking_time" to 63
val en_fil_peak_time = meta.getInt("energy_filter.peaking_time") "flat_top" to 2
val en_fil_flattop = meta.getInt("energy_filter.flat_top") }
val fast_peak_time = meta.getInt("fast_filter.peaking_time") "fast_filter" to {
val fast_flattop = meta.getInt("fast_filter.flat_top") "peaking_time" to 4
val recovery_time = meta.getValue("recovery_time").longValue() "flat_top" to 1
val zero_peak_rate = meta.getInt("zero_peak_rate") }
val inverted_input = meta.getInt("inverted_input") "recovery_time" to 100
*/ "zero_peak_rate" to 0
} }
runBlocking { runBlocking {
println("Firmware version: ${client.getFirmwareVersion()}")
// client.reset()
// delay(500)
client.configureAll(meta) client.configureAll(meta)
}
val point = runBlocking { val point = client.readPoint(10 * 1000)
client.readPoint(10*1000)
} println("***META***")
println("***META***") println(point.meta)
println(point.meta) println("***BLOCKS***")
println("***BLOCKS***") point.blocks.forEach {
point.blocks.forEach { println("channel: ${it.channel}")
println("channel: ${it.channel}") println("\tlength: ${it.length}")
println("\tlength: ${it.length}") println("\tevents: ${it.events.count()}")
println("\tevents: ${it.events.count()}") it.plotAmplitudeSpectrum(plotName = it.channel.toString())
}
}
}
fun NumassBlock.plotAmplitudeSpectrum(plotName: String = "spectrum", frameName: String = "", context: Context = Global, metaAction: KMetaBuilder.() -> Unit = {}) {
val meta = buildMeta("meta", metaAction)
val plotManager = context.load(FXPlotManager::class)
val binning = meta.getInt("binning", 20)
val lo = meta.optNumber("window.lo").nullable?.toInt()
val up = meta.optNumber("window.up").nullable?.toInt()
val data = SimpleAnalyzer().getAmplitudeSpectrum(this, meta.getMetaOrEmpty("spectrum")).withBinning(binning, lo, up)
plotManager.display(name = frameName) {
val valueAxis = if (meta.getBoolean("normalize", false)) {
NumassAnalyzer.COUNT_RATE_KEY
} else {
NumassAnalyzer.COUNT_KEY
}
plots.configure {
"connectionType" to "step"
"thickness" to 2
"showLine" to true
"showSymbol" to false
"showErrors" to false
}.setType(DataPlot::class)
val plot = DataPlot.plot(
plotName,
Adapters.buildXYAdapter(NumassAnalyzer.CHANNEL_KEY, valueAxis),
data
)
plot.configure(meta)
add(plot)
} }
} }