Values + Binary values to kotlin

This commit is contained in:
Alexander Nozik 2018-04-28 10:05:52 +03:00
parent 42594e119e
commit dae12c1b9c
25 changed files with 54 additions and 49 deletions

View File

@ -29,7 +29,7 @@ class PKT8VirtualPort(private val portName: String, meta: Meta) : VirtualPort(me
"s" -> { "s" -> {
val letters = arrayOf("a", "b", "c", "d", "e", "f", "g", "h") val letters = arrayOf("a", "b", "c", "d", "e", "f", "g", "h")
for (letter in letters) { for (letter in letters) {
val channelMeta = MetaUtils.findNodeByValue(meta, "channel", "letter", Value.of(letter)).orElse(Meta.empty()) val channelMeta = MetaUtils.findNodeByValue(meta, "channel", "letter", Value.parseValue(letter)).orElse(Meta.empty())
val average: Double val average: Double
val sigma: Double val sigma: Double

View File

@ -24,8 +24,8 @@ import hep.dataforge.storage.api.TableLoader
import hep.dataforge.storage.commons.LoaderFactory import hep.dataforge.storage.commons.LoaderFactory
import hep.dataforge.storage.commons.StorageConnection import hep.dataforge.storage.commons.StorageConnection
import hep.dataforge.tables.TableFormatBuilder import hep.dataforge.tables.TableFormatBuilder
import hep.dataforge.tables.ValueMap
import hep.dataforge.utils.DateTimeUtils import hep.dataforge.utils.DateTimeUtils
import hep.dataforge.values.ValueMap
import hep.dataforge.values.ValueType import hep.dataforge.values.ValueType
import hep.dataforge.values.Values import hep.dataforge.values.Values
import inr.numass.control.DeviceView import inr.numass.control.DeviceView

View File

@ -2,6 +2,7 @@ package inr.numass
import hep.dataforge.io.envelopes.* import hep.dataforge.io.envelopes.*
import hep.dataforge.values.Value import hep.dataforge.values.Value
import hep.dataforge.values.parseValue
import inr.numass.data.legacy.NumassFileEnvelope.Companion.LEGACY_END_SEQUENCE import inr.numass.data.legacy.NumassFileEnvelope.Companion.LEGACY_END_SEQUENCE
import inr.numass.data.legacy.NumassFileEnvelope.Companion.LEGACY_START_SEQUENCE import inr.numass.data.legacy.NumassFileEnvelope.Companion.LEGACY_START_SEQUENCE
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
@ -60,7 +61,7 @@ class NumassEnvelopeType : EnvelopeType {
val metaType = MetaType.resolve(metaTypeCode) val metaType = MetaType.resolve(metaTypeCode)
if (metaType != null) { if (metaType != null) {
res[Envelope.META_TYPE_PROPERTY] = Value.of(metaType.name) res[Envelope.META_TYPE_PROPERTY] = metaType.name.parseValue()
} else { } else {
LoggerFactory.getLogger(EnvelopeTag::class.java).warn("Could not resolve meta type. Using default") LoggerFactory.getLogger(EnvelopeTag::class.java).warn("Could not resolve meta type. Using default")
} }

View File

@ -19,10 +19,11 @@ import hep.dataforge.meta.Meta
import hep.dataforge.meta.MetaBuilder import hep.dataforge.meta.MetaBuilder
import hep.dataforge.tables.Adapters.* import hep.dataforge.tables.Adapters.*
import hep.dataforge.tables.BasicAdapter import hep.dataforge.tables.BasicAdapter
import hep.dataforge.tables.ValueMap
import hep.dataforge.tables.ValuesAdapter import hep.dataforge.tables.ValuesAdapter
import hep.dataforge.values.Value import hep.dataforge.values.Value
import hep.dataforge.values.ValueMap
import hep.dataforge.values.Values import hep.dataforge.values.Values
import hep.dataforge.values.asValue
import java.util.* import java.util.*
import java.util.stream.Stream import java.util.stream.Stream
@ -51,7 +52,7 @@ class SpectrumAdapter : BasicAdapter {
} }
fun getTime(point: Values): Double { fun getTime(point: Values): Double {
return this.optComponent(point, POINT_LENGTH_NAME).map<Double> { it.getDouble() }.orElse(1.0) return this.optComponent(point, POINT_LENGTH_NAME).map<Double> { it.double }.orElse(1.0)
} }
fun buildSpectrumDataPoint(x: Double, count: Long, t: Double): Values { fun buildSpectrumDataPoint(x: Double, count: Long, t: Double): Values {
@ -69,21 +70,19 @@ class SpectrumAdapter : BasicAdapter {
when (component) { when (component) {
"count" -> return super.optComponent(values, Y_VALUE_KEY) "count" -> return super.optComponent(values, Y_VALUE_KEY)
Y_VALUE_KEY -> return super.optComponent(values, Y_VALUE_KEY) Y_VALUE_KEY -> return super.optComponent(values, Y_VALUE_KEY)
.map { it -> it.getDouble() / getTime(values) } .map { it -> it.double / getTime(values) }
.map { Value.of(it) } .map { it.asValue() }
Y_ERROR_KEY -> { Y_ERROR_KEY -> {
val err = super.optComponent(values, Y_ERROR_KEY) val err = super.optComponent(values, Y_ERROR_KEY)
return if (err.isPresent) { return if (err.isPresent) {
Optional.of(Value.of(err.get().getDouble() / getTime(values))) Optional.of(Value.of(err.get().double / getTime(values)))
} else { } else {
val y = getComponent(values, Y_VALUE_KEY).getDouble() val y = getComponent(values, Y_VALUE_KEY).double
if (y < 0) { when {
Optional.empty() y < 0 -> Optional.empty()
} else if (y == 0.0) { y == 0.0 -> //avoid infinite weights
//avoid infinite weights
Optional.of(Value.of(1.0 / getTime(values))) Optional.of(Value.of(1.0 / getTime(values)))
} else { else -> Optional.of(Value.of(Math.sqrt(y) / getTime(values)))
Optional.of(Value.of(Math.sqrt(y) / getTime(values)))
} }
} }
} }

View File

@ -20,6 +20,7 @@ import hep.dataforge.meta.Meta
import hep.dataforge.tables.* import hep.dataforge.tables.*
import hep.dataforge.tables.Adapters.* import hep.dataforge.tables.Adapters.*
import hep.dataforge.values.Value import hep.dataforge.values.Value
import hep.dataforge.values.ValueMap
import hep.dataforge.values.Values import hep.dataforge.values.Values
import inr.numass.data.api.NumassBlock import inr.numass.data.api.NumassBlock
import inr.numass.data.api.NumassEvent import inr.numass.data.api.NumassEvent

View File

@ -17,7 +17,7 @@
package inr.numass.data.analyzers package inr.numass.data.analyzers
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.tables.ValueMap import hep.dataforge.values.ValueMap
import hep.dataforge.values.Values import hep.dataforge.values.Values
import inr.numass.data.api.NumassBlock import inr.numass.data.api.NumassBlock
import inr.numass.data.api.SignalProcessor import inr.numass.data.api.SignalProcessor

View File

@ -18,8 +18,8 @@ package inr.numass.data.analyzers
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.tables.TableFormat import hep.dataforge.tables.TableFormat
import hep.dataforge.tables.ValueMap
import hep.dataforge.values.Value import hep.dataforge.values.Value
import hep.dataforge.values.ValueMap
import hep.dataforge.values.Values import hep.dataforge.values.Values
import inr.numass.data.api.NumassBlock import inr.numass.data.api.NumassBlock
import inr.numass.data.api.NumassEvent import inr.numass.data.api.NumassEvent
@ -54,7 +54,7 @@ class SmartAnalyzer(processor: SignalProcessor? = null) : AbstractAnalyzer(proce
override fun analyze(block: NumassBlock, config: Meta): Values { override fun analyze(block: NumassBlock, config: Meta): Values {
val analyzer = getAnalyzer(config) val analyzer = getAnalyzer(config)
val map = analyzer.analyze(block, config).asMap() val map = analyzer.analyze(block, config).asMap().toMutableMap()
map.putIfAbsent(TimeAnalyzer.T0_KEY, Value.of(0.0)) map.putIfAbsent(TimeAnalyzer.T0_KEY, Value.of(0.0))
return ValueMap(map) return ValueMap(map)
} }

View File

@ -22,8 +22,8 @@ import hep.dataforge.meta.Meta
import hep.dataforge.tables.Adapters.* import hep.dataforge.tables.Adapters.*
import hep.dataforge.tables.TableFormat import hep.dataforge.tables.TableFormat
import hep.dataforge.tables.TableFormatBuilder import hep.dataforge.tables.TableFormatBuilder
import hep.dataforge.tables.ValueMap
import hep.dataforge.values.Value import hep.dataforge.values.Value
import hep.dataforge.values.ValueMap
import hep.dataforge.values.ValueType import hep.dataforge.values.ValueType
import hep.dataforge.values.Values import hep.dataforge.values.Values
import inr.numass.data.api.NumassBlock import inr.numass.data.api.NumassBlock

View File

@ -39,7 +39,7 @@ class ClassicNumassPoint(private val envelope: Envelope) : NumassPoint {
override val startTime: Instant override val startTime: Instant
get() = if (meta.hasValue("start_time")) { get() = if (meta.hasValue("start_time")) {
meta.getValue("start_time").getTime() meta.getValue("start_time").time
} else { } else {
super.startTime super.startTime
} }

View File

@ -118,7 +118,7 @@ class NumassDataLoader(
} }
override val startTime: Instant override val startTime: Instant
get() = meta.optValue("start_time").map<Instant> { it.getTime() }.orElseGet { super.startTime } get() = meta.optValue("start_time").map<Instant> { it.time }.orElseGet { super.startTime }
override val isOpen: Boolean override val isOpen: Boolean
@ -188,7 +188,7 @@ class NumassDataLoader(
*/ */
private fun readTime(meta: Meta): Instant { private fun readTime(meta: Meta): Instant {
return if (meta.hasValue("start_time")) { return if (meta.hasValue("start_time")) {
meta.getValue("start_time").getTime() meta.getValue("start_time").time
} else { } else {
Instant.EPOCH Instant.EPOCH
} }

View File

@ -4,7 +4,7 @@ import hep.dataforge.context.Context
import hep.dataforge.context.Global import hep.dataforge.context.Global
import hep.dataforge.grind.GrindShell import hep.dataforge.grind.GrindShell
import hep.dataforge.grind.helpers.PlotHelper import hep.dataforge.grind.helpers.PlotHelper
import hep.dataforge.tables.ValueMap import hep.dataforge.values.ValueMap
import inr.numass.NumassPlugin import inr.numass.NumassPlugin
import inr.numass.data.PointAnalyzer import inr.numass.data.PointAnalyzer
import inr.numass.data.analyzers.NumassAnalyzer import inr.numass.data.analyzers.NumassAnalyzer

View File

@ -12,7 +12,7 @@ import hep.dataforge.meta.Laminate;
import hep.dataforge.meta.Meta; import hep.dataforge.meta.Meta;
import hep.dataforge.tables.ListTable; import hep.dataforge.tables.ListTable;
import hep.dataforge.tables.Table; import hep.dataforge.tables.Table;
import hep.dataforge.tables.ValueMap; import hep.dataforge.values.ValueMap;
import hep.dataforge.values.Values; import hep.dataforge.values.Values;
import java.util.ArrayList; import java.util.ArrayList;

View File

@ -23,8 +23,8 @@ import hep.dataforge.meta.Laminate;
import hep.dataforge.meta.Meta; import hep.dataforge.meta.Meta;
import hep.dataforge.tables.ListTable; import hep.dataforge.tables.ListTable;
import hep.dataforge.tables.Table; import hep.dataforge.tables.Table;
import hep.dataforge.tables.ValueMap;
import hep.dataforge.values.Value; import hep.dataforge.values.Value;
import hep.dataforge.values.ValueMap;
import hep.dataforge.values.Values; import hep.dataforge.values.Values;
import inr.numass.NumassUtils; import inr.numass.NumassUtils;
import inr.numass.data.analyzers.NumassAnalyzer; import inr.numass.data.analyzers.NumassAnalyzer;

View File

@ -13,7 +13,7 @@ import hep.dataforge.meta.Laminate;
import hep.dataforge.meta.Meta; import hep.dataforge.meta.Meta;
import hep.dataforge.tables.ListTable; import hep.dataforge.tables.ListTable;
import hep.dataforge.tables.Table; import hep.dataforge.tables.Table;
import hep.dataforge.tables.ValueMap; import hep.dataforge.values.ValueMap;
import hep.dataforge.values.Values; import hep.dataforge.values.Values;
import inr.numass.NumassUtils; import inr.numass.NumassUtils;

View File

@ -17,7 +17,7 @@ package inr.numass.utils;
import hep.dataforge.tables.ListTable; import hep.dataforge.tables.ListTable;
import hep.dataforge.tables.Table; import hep.dataforge.tables.Table;
import hep.dataforge.tables.ValueMap; import hep.dataforge.values.ValueMap;
import hep.dataforge.values.Values; import hep.dataforge.values.Values;
import java.util.Scanner; import java.util.Scanner;
@ -38,7 +38,7 @@ public class DataModelUtils {
for (int i = 0; i < numpoints; i++) { for (int i = 0; i < numpoints; i++) {
// формула работает даже в том случае когда порядок точек обратный // формула работает даже в том случае когда порядок точек обратный
double x = from + (to - from) / (numpoints - 1) * i; double x = from + (to - from) / (numpoints - 1) * i;
Values point = ValueMap.of(list, x, time); Values point = ValueMap.Companion.of(list, x, time);
res.row(point); res.row(point);
} }
@ -52,7 +52,7 @@ public class DataModelUtils {
while (scan.hasNextLine()) { while (scan.hasNextLine()) {
double x = scan.nextDouble(); double x = scan.nextDouble();
int time = scan.nextInt(); int time = scan.nextInt();
res.row(ValueMap.of(list, x, time)); res.row(ValueMap.Companion.of(list, x, time));
} }
return res.build(); return res.build();
} }

View File

@ -20,7 +20,7 @@ import hep.dataforge.meta.Meta;
import hep.dataforge.tables.Adapters; import hep.dataforge.tables.Adapters;
import hep.dataforge.tables.ListTable; import hep.dataforge.tables.ListTable;
import hep.dataforge.tables.Table; import hep.dataforge.tables.Table;
import hep.dataforge.tables.ValueMap; import hep.dataforge.values.ValueMap;
import hep.dataforge.values.Values; import hep.dataforge.values.Values;
import inr.numass.data.SpectrumAdapter; import inr.numass.data.SpectrumAdapter;
@ -53,7 +53,7 @@ public class OldDataReader {
if (lineScan.hasNextDouble()) { if (lineScan.hasNextDouble()) {
ushift = lineScan.nextDouble(); ushift = lineScan.nextDouble();
} }
Values point = ValueMap.of(list, u, time, ushift); Values point = ValueMap.Companion.of(list, u, time, ushift);
res.row(point); res.row(point);
} }
return res.build(); return res.build();

View File

@ -9,7 +9,7 @@ import hep.dataforge.meta.Meta;
import hep.dataforge.tables.ListTable; import hep.dataforge.tables.ListTable;
import hep.dataforge.tables.Table; import hep.dataforge.tables.Table;
import hep.dataforge.tables.TableTransform; import hep.dataforge.tables.TableTransform;
import hep.dataforge.tables.ValueMap; import hep.dataforge.values.ValueMap;
import hep.dataforge.values.Values; import hep.dataforge.values.Values;
import inr.numass.data.analyzers.NumassAnalyzer; import inr.numass.data.analyzers.NumassAnalyzer;
import inr.numass.data.analyzers.NumassAnalyzerKt; import inr.numass.data.analyzers.NumassAnalyzerKt;
@ -85,7 +85,7 @@ public class UnderflowCorrection {
double a = fitRes[0]; double a = fitRes[0];
double sigma = fitRes[1]; double sigma = fitRes[1];
return ValueMap.of(pointNames, point.getVoltage(), a, sigma, a * sigma * Math.exp(xLow / sigma) / norm + 1d); return ValueMap.Companion.of(pointNames, point.getVoltage(), a, sigma, a * sigma * Math.exp(xLow / sigma) / norm + 1d);
} }
public Table fitAllPoints(Iterable<NumassPoint> data, int xLow, int xHigh, int upper, int binning) { public Table fitAllPoints(Iterable<NumassPoint> data, int xLow, int xHigh, int upper, int binning) {

View File

@ -31,7 +31,7 @@ import hep.dataforge.meta.MetaBuilder
import hep.dataforge.plots.jfreechart.JFreeChartFrame import hep.dataforge.plots.jfreechart.JFreeChartFrame
import hep.dataforge.tables.ListTable import hep.dataforge.tables.ListTable
import hep.dataforge.tables.Table import hep.dataforge.tables.Table
import hep.dataforge.tables.ValueMap import hep.dataforge.values.ValueMap
import hep.dataforge.values.ValueType import hep.dataforge.values.ValueType
import hep.dataforge.values.Values import hep.dataforge.values.Values
import inr.numass.data.analyzers.NumassAnalyzer import inr.numass.data.analyzers.NumassAnalyzer

View File

@ -23,7 +23,11 @@ import hep.dataforge.description.NodeDef
import hep.dataforge.description.TypedActionDef import hep.dataforge.description.TypedActionDef
import hep.dataforge.meta.Laminate import hep.dataforge.meta.Laminate
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.tables.* import hep.dataforge.tables.ListTable
import hep.dataforge.tables.MetaTableFormat
import hep.dataforge.tables.Table
import hep.dataforge.tables.TableTransform
import hep.dataforge.values.ValueMap
import hep.dataforge.values.Values import hep.dataforge.values.Values
import inr.numass.NumassUtils import inr.numass.NumassUtils
import inr.numass.data.analyzers.NumassAnalyzer import inr.numass.data.analyzers.NumassAnalyzer

View File

@ -27,8 +27,8 @@ import hep.dataforge.stat.fit.FitState
import hep.dataforge.tables.ListTable import hep.dataforge.tables.ListTable
import hep.dataforge.tables.MetaTableFormat import hep.dataforge.tables.MetaTableFormat
import hep.dataforge.tables.Table import hep.dataforge.tables.Table
import hep.dataforge.tables.ValueMap
import hep.dataforge.values.Value import hep.dataforge.values.Value
import hep.dataforge.values.ValueMap
import inr.numass.NumassUtils import inr.numass.NumassUtils
import java.util.* import java.util.*
@ -76,7 +76,7 @@ object SummaryAction : ManyToOneAction<FitState, Table>() {
input.forEach { key: String, value: FitState -> input.forEach { key: String, value: FitState ->
val values = arrayOfNulls<Value>(names.size) val values = arrayOfNulls<Value>(names.size)
values[0] = Value.of(key) values[0] = Value.parseValue(key)
for (i in parNames.indices) { for (i in parNames.indices) {
val `val` = Value.of(value.parameters.getDouble(parNames[i])) val `val` = Value.of(value.parameters.getDouble(parNames[i]))
values[2 * i + 1] = `val` values[2 * i + 1] = `val`
@ -92,7 +92,7 @@ object SummaryAction : ManyToOneAction<FitState, Table>() {
} }
val averageValues = arrayOfNulls<Value>(names.size) val averageValues = arrayOfNulls<Value>(names.size)
averageValues[0] = Value.of("average") averageValues[0] = Value.parseValue("average")
averageValues[averageValues.size - 1] = Value.of(0) averageValues[averageValues.size - 1] = Value.of(0)
for (i in parNames.indices) { for (i in parNames.indices) {

View File

@ -5,12 +5,11 @@ import hep.dataforge.data.DataNode
import hep.dataforge.data.DataSet import hep.dataforge.data.DataSet
import hep.dataforge.kodex.buildMeta import hep.dataforge.kodex.buildMeta
import hep.dataforge.kodex.pipe import hep.dataforge.kodex.pipe
import hep.dataforge.kodex.toList
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.storage.commons.StorageUtils import hep.dataforge.storage.commons.StorageUtils
import hep.dataforge.tables.ListTable import hep.dataforge.tables.ListTable
import hep.dataforge.tables.Table import hep.dataforge.tables.Table
import hep.dataforge.tables.ValueMap import hep.dataforge.values.ValueMap
import hep.dataforge.values.Values import hep.dataforge.values.Values
import inr.numass.data.analyzers.NumassAnalyzer.Companion.CHANNEL_KEY import inr.numass.data.analyzers.NumassAnalyzer.Companion.CHANNEL_KEY
import inr.numass.data.analyzers.NumassAnalyzer.Companion.COUNT_RATE_KEY import inr.numass.data.analyzers.NumassAnalyzer.Companion.COUNT_RATE_KEY

View File

@ -35,7 +35,7 @@ object NumassFitScanTask : AbstractTask<FitResult>() {
.collect(Collectors.toList<Any>()) .collect(Collectors.toList<Any>())
) )
} else { } else {
config.getValue("hep/dataforge/values", Value.of("[2.5e5, 1e6, 2.25e6, 4e6, 6.25e6, 9e6]")) config.getValue("hep/dataforge/values", Value.parseValue("[2.5e5, 1e6, 2.25e6, 4e6, 6.25e6, 9e6]"))
} }
val action = FitAction() val action = FitAction()

View File

@ -12,7 +12,7 @@ import hep.dataforge.meta.Meta
import hep.dataforge.meta.MetaBuilder import hep.dataforge.meta.MetaBuilder
import hep.dataforge.storage.commons.LoaderFactory import hep.dataforge.storage.commons.LoaderFactory
import hep.dataforge.storage.commons.StorageManager import hep.dataforge.storage.commons.StorageManager
import hep.dataforge.tables.ValueMap import hep.dataforge.values.ValueMap
import inr.numass.client.NumassClient import inr.numass.client.NumassClient
new StorageManager().startGlobal(); new StorageManager().startGlobal();

View File

@ -58,7 +58,7 @@ class HVView : View(title = "High voltage time plot", icon = ImageView(dfIcon))
hvData?.let { hvData?.let {
for (dp in it) { for (dp in it) {
val plot: TimePlot = frame[change.key] as TimePlot? ?: TimePlot(change.key).apply { frame.add(this) } val plot: TimePlot = frame[change.key] as TimePlot? ?: TimePlot(change.key).apply { frame.add(this) }
plot.put(dp.getValue("timestamp").getTime(), dp.getValue("value")) plot.put(dp.getValue("timestamp").time, dp.getValue("value"))
} }
} }
container.progress = 1.0; container.progress = 1.0;

View File

@ -2,17 +2,18 @@ package inr.numass.server
import hep.dataforge.control.DeviceManager import hep.dataforge.control.DeviceManager
import hep.dataforge.providers.Path import hep.dataforge.providers.Path
import hep.dataforge.server.* import hep.dataforge.server.InterceptorFactory
import hep.dataforge.server.ServerInterceptor
import hep.dataforge.server.asJson
import hep.dataforge.server.jsonObject
import hep.dataforge.storage.api.TableLoader import hep.dataforge.storage.api.TableLoader
import hep.dataforge.storage.commons.StorageManager import hep.dataforge.storage.commons.StorageManager
import hep.dataforge.storage.commons.StorageUtils
import hep.dataforge.values.Value import hep.dataforge.values.Value
import io.ktor.application.ApplicationCall import io.ktor.application.ApplicationCall
import io.ktor.application.call import io.ktor.application.call
import io.ktor.http.ContentType import io.ktor.http.ContentType
import io.ktor.response.respondText import io.ktor.response.respondText
import io.ktor.routing.get import io.ktor.routing.get
import javax.json.JsonObjectBuilder
private suspend fun ApplicationCall.error(type: String, message: String) { private suspend fun ApplicationCall.error(type: String, message: String) {
@ -64,8 +65,8 @@ val storageInterceptor = InterceptorFactory { context, meta ->
if (loaderObject.isPresent) { if (loaderObject.isPresent) {
val loader = loaderObject.get(); val loader = loaderObject.get();
if (loader is TableLoader) { if (loader is TableLoader) {
val from = Value.of(call.request.queryParameters["from"] ?: "") val from = Value.parseValue(call.request.queryParameters["from"] ?: "")
val to = Value.of(call.request.queryParameters["to"] ?: "") val to = Value.parseValue(call.request.queryParameters["to"] ?: "")
val maxItems = (call.request.queryParameters["maxItems"] ?: "1000").toInt() val maxItems = (call.request.queryParameters["maxItems"] ?: "1000").toInt()
call.json { call.json {
add("path", loader.path.toString()) add("path", loader.path.toString())