diff --git a/dataforge-vis-common/src/jvmTest/kotlin/hep/dataforge/vis/fx/demo/MetaEditorDemo.kt b/dataforge-vis-common/src/jvmTest/kotlin/hep/dataforge/vis/fx/demo/MetaEditorDemo.kt index b24fa441..09ec35fc 100644 --- a/dataforge-vis-common/src/jvmTest/kotlin/hep/dataforge/vis/fx/demo/MetaEditorDemo.kt +++ b/dataforge-vis-common/src/jvmTest/kotlin/hep/dataforge/vis/fx/demo/MetaEditorDemo.kt @@ -25,7 +25,7 @@ class MetaEditorDemo : View("Meta editor demo") { } }.toConfig() - val descriptor = NodeDescriptor.build { + val descriptor = NodeDescriptor { node("aNode") { info = "A root demo node" value("b") { diff --git a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeLabelFactory.kt b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeLabelFactory.kt index b7d292c7..3076e9bb 100644 --- a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeLabelFactory.kt +++ b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeLabelFactory.kt @@ -8,9 +8,11 @@ import info.laht.threekt.geometries.PlaneBufferGeometry import info.laht.threekt.materials.MeshBasicMaterial import info.laht.threekt.objects.Mesh import info.laht.threekt.textures.Texture -import org.w3c.dom.* +import org.w3c.dom.CanvasRenderingContext2D +import org.w3c.dom.CanvasTextBaseline +import org.w3c.dom.HTMLCanvasElement +import org.w3c.dom.MIDDLE import kotlin.browser.document -import kotlin.math.PI import kotlin.reflect.KClass /** @@ -24,11 +26,13 @@ object ThreeLabelFactory : ThreeFactory { val context = canvas.getContext("2d") as CanvasRenderingContext2D context.font = "Bold ${obj.fontSize}pt ${obj.fontFamily}" context.fillStyle = obj.color ?: "black" - context.textAlign = CanvasTextAlign.CENTER - //context.textBaseline = CanvasTextBaseline.MIDDLE + //context.textAlign = CanvasTextAlign.CENTER + context.textBaseline = CanvasTextBaseline.MIDDLE val metrics = context.measureText(obj.text) + //canvas.width = metrics.width.toInt() - context.fillText(obj.text, 0.5*metrics.width, 0.5*metrics.width) + + context.fillText(obj.text, (canvas.width - metrics.width)/2, 0.5*canvas.height) // canvas contents will be used for a texture @@ -46,8 +50,6 @@ object ThreeLabelFactory : ThreeFactory { material ) - //mesh.rotateX(PI) - mesh.updatePosition(obj) return mesh diff --git a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeMaterials.kt b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeMaterials.kt index a1e9495e..b712e9be 100644 --- a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeMaterials.kt +++ b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeMaterials.kt @@ -92,12 +92,23 @@ fun MetaItem<*>.color(): Color { //fun Material3D?.jsLineMaterial(): Material = this?.config.jsLineMaterial() fun Mesh.updateMaterial(obj: VisualObject) { - val meta = obj.getProperty(Material3D.MATERIAL_KEY).node?:EmptyMeta - material = MeshBasicMaterial().apply { - color = meta[Material3D.COLOR_KEY]?.color() ?: ThreeMaterials.DEFAULT_COLOR - opacity = meta[Material3D.OPACITY_KEY]?.double ?: 1.0 - transparent = opacity < 1.0 - wireframe = meta[Material3D.WIREFRAME_KEY].boolean?:false - needsUpdate = true + val meta = obj.getProperty(Material3D.MATERIAL_KEY).node ?: EmptyMeta + material = if(meta[Material3D.SPECULAR_COLOR]!= null){ + MeshPhongMaterial().apply { + color = meta[Material3D.COLOR_KEY]?.color() ?: ThreeMaterials.DEFAULT_COLOR + specular = meta[Material3D.SPECULAR_COLOR]!!.color() + opacity = meta[Material3D.OPACITY_KEY]?.double ?: 1.0 + transparent = opacity <= 0.0 + wireframe = meta[Material3D.WIREFRAME_KEY].boolean ?: false + needsUpdate = true + } + }else { + MeshBasicMaterial().apply { + color = meta[Material3D.COLOR_KEY]?.color() ?: ThreeMaterials.DEFAULT_COLOR + opacity = meta[Material3D.OPACITY_KEY]?.double ?: 1.0 + transparent = opacity <= 0.0 + wireframe = meta[Material3D.WIREFRAME_KEY].boolean ?: false + needsUpdate = true + } } } diff --git a/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FXCanvas3D.kt b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FXCanvas3D.kt index 3c990648..1704eeb2 100644 --- a/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FXCanvas3D.kt +++ b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FXCanvas3D.kt @@ -14,7 +14,7 @@ import javafx.scene.paint.Color import org.fxyz3d.scene.Axes import tornadofx.* -class FXCanvas3D(val plugin: FX3DPlugin, val spec: CanvasSpec) : +class FXCanvas3D(val plugin: FX3DPlugin, val spec: CanvasSpec = CanvasSpec.empty()) : Fragment(), Renderer, ContextAware { override val context: Context get() = plugin.context diff --git a/demo/muon-monitor/build.gradle.kts b/demo/muon-monitor/build.gradle.kts index a6338794..1b649501 100644 --- a/demo/muon-monitor/build.gradle.kts +++ b/demo/muon-monitor/build.gradle.kts @@ -11,6 +11,8 @@ group = "ru.mipt.npm" useSerialization() +val ktor_version = "1.3.0-rc" + kotlin { jvm { @@ -28,15 +30,20 @@ kotlin { sourceSets { commonMain { dependencies { - api(project(":dataforge-vis-spatial")) - api(project(":dataforge-vis-spatial-gdml")) + implementation(project(":dataforge-vis-spatial")) + } + } + jvmMain{ + dependencies { + implementation("org.apache.commons:commons-math3:3.6.1") + implementation("io.ktor:ktor-server-cio:$ktor_version") } } } } application { - mainClassName = "hep.dataforge.vis.spatial.demo.FXDemoAppKt" + mainClassName = "ru.mipt.npm.muon.monitor.MMDemoAppKt" } configure { diff --git a/demo/muon-monitor/src/commonMain/kotlin/ru/mipt/npm/muon/monitor/Event.kt b/demo/muon-monitor/src/commonMain/kotlin/ru/mipt/npm/muon/monitor/Event.kt index 3c22885e..1992442d 100644 --- a/demo/muon-monitor/src/commonMain/kotlin/ru/mipt/npm/muon/monitor/Event.kt +++ b/demo/muon-monitor/src/commonMain/kotlin/ru/mipt/npm/muon/monitor/Event.kt @@ -1,14 +1,18 @@ -package ru.mipt.npm.muon.sim +@file:UseSerializers(Point3DSerializer::class) +package ru.mipt.npm.muon.monitor +import hep.dataforge.vis.spatial.Point3D +import hep.dataforge.vis.spatial.Point3DSerializer import kotlinx.serialization.Serializable -import ru.mipt.npm.muon.monitor.Line +import kotlinx.serialization.UseSerializers +typealias Track = List /** - * Created by darksnake on 11-May-16. + * */ @Serializable -data class Event(val track: Line, val hits: Set) { +data class Event(val track: Track?, val hits: Collection) { /** * The unique identity for given set of hits. One identity could correspond to different tracks */ diff --git a/demo/muon-monitor/src/commonMain/kotlin/ru/mipt/npm/muon/monitor/Model.kt b/demo/muon-monitor/src/commonMain/kotlin/ru/mipt/npm/muon/monitor/Model.kt index ecb29248..6a33cb1c 100644 --- a/demo/muon-monitor/src/commonMain/kotlin/ru/mipt/npm/muon/monitor/Model.kt +++ b/demo/muon-monitor/src/commonMain/kotlin/ru/mipt/npm/muon/monitor/Model.kt @@ -2,13 +2,10 @@ package ru.mipt.npm.muon.monitor import hep.dataforge.vis.common.removeAll import hep.dataforge.vis.spatial.* -import ru.mipt.npm.muon.sim.Event -import ru.mipt.npm.muon.sim.Monitor -import ru.mipt.npm.muon.sim.Monitor.CENTRAL_LAYER_Z -import ru.mipt.npm.muon.sim.Monitor.LOWER_LAYER_Z -import ru.mipt.npm.muon.sim.Monitor.UPPER_LAYER_Z -import ru.mipt.npm.muon.sim.SC1 -import ru.mipt.npm.muon.sim.SC16 +import ru.mipt.npm.muon.monitor.Monitor.CENTRAL_LAYER_Z +import ru.mipt.npm.muon.monitor.Monitor.LOWER_LAYER_Z +import ru.mipt.npm.muon.monitor.Monitor.UPPER_LAYER_Z +import kotlin.math.PI class Model { private val map = HashMap() @@ -16,17 +13,17 @@ class Model { private fun VisualGroup3D.pixel(pixel: SC1) { val group = group(pixel.name) { - box(Monitor.PIXEL_XY_SIZE, Monitor.PIXEL_Z_SIZE, Monitor.PIXEL_XY_SIZE){ - position = Point3D(pixel.center.x, pixel.center.z,pixel.center.y) - } + position = Point3D(pixel.center.x, pixel.center.y, pixel.center.z) + box(pixel.xSize, pixel.ySize, pixel.zSize) label(pixel.name) { - y = Monitor.PIXEL_Z_SIZE / 2 + z = - Monitor.PIXEL_Z_SIZE / 2 - 5 + rotationY = PI } } map[pixel.name] = group } - private fun VisualGroup3D.detector(detector: SC16){ + private fun VisualGroup3D.detector(detector: SC16) { group(detector.name) { detector.pixels.forEach { pixel(it) @@ -37,6 +34,7 @@ class Model { var tracks: VisualGroup3D val root: VisualGroup3D = VisualGroup3D().apply { + rotationX = PI / 2 group("bottom") { Monitor.detectors.filter { it.center.z == LOWER_LAYER_Z }.forEach { detector(it) @@ -71,6 +69,11 @@ class Model { fun showEvent(event: Event) { events.add(event) - highlight(event.id) + event.hits.forEach { + highlight(it) + } + event.track?.let { + tracks.polyline(*it.toTypedArray()) + } } } \ No newline at end of file diff --git a/demo/muon-monitor/src/commonMain/kotlin/ru/mipt/npm/muon/monitor/Monitor.kt b/demo/muon-monitor/src/commonMain/kotlin/ru/mipt/npm/muon/monitor/Monitor.kt index 42e267b4..b80fa328 100644 --- a/demo/muon-monitor/src/commonMain/kotlin/ru/mipt/npm/muon/monitor/Monitor.kt +++ b/demo/muon-monitor/src/commonMain/kotlin/ru/mipt/npm/muon/monitor/Monitor.kt @@ -1,14 +1,17 @@ -package ru.mipt.npm.muon.sim +package ru.mipt.npm.muon.monitor import hep.dataforge.vis.spatial.Point3D import hep.dataforge.vis.spatial.plus +import ru.mipt.npm.muon.monitor.Monitor.PIXEL_XY_SIZE +import ru.mipt.npm.muon.monitor.Monitor.PIXEL_Z_SIZE /** * A single pixel */ -class SC1( +open class SC1( val name: String, - val center: Point3D + val center: Point3D, + val xSize: Double = PIXEL_XY_SIZE, val ySize: Double = PIXEL_XY_SIZE, val zSize: Double = PIXEL_Z_SIZE ) class SC16( @@ -109,55 +112,27 @@ class SC16( expect fun readResource(path: String): String +internal expect fun readMonitorConfig(): String + /** * General geometry definitions * Created by darksnake on 09-May-16. */ object Monitor { - const val GEOMETRY_TOLERANCE = 0.01; - const val PIXEL_XY_SIZE = 122.0; - const val PIXEL_XY_SPACING = 123.2; - const val PIXEL_Z_SIZE = 30.0; - const val CENTRAL_LAYER_Z = 0.0; - const val UPPER_LAYER_Z = 166.0; - const val LOWER_LAYER_Z = -180.0; - - private val monitorConfig = """ - --Place-|-SC16-|-TB-CHN-|-HB-CHN-|-X-coord-|-Y-coord-|-Z-coord-|-Theta-|-Phi - ---------------------------------------------------------------------------- - RT100 SC86 3 0 0 1000 0 0 270 - RT100 SC87 6 1 0 500 0 0 270 - RT100 SC88 8 2 0 0 0 0 270 - RT100 SC91 9 3 500 1000 0 0 270 - RT100 SC92 10 4 500 500 0 0 270 - RT100 SC93 11 5 500 0 0 0 270 - RT100 SC94 12 6 1000 1000 0 0 270 - RT100 SC85 13 7 1000 500 0 0 270 - RT100 SC96 15 8 1000 0 0 0 270 - ### - RT100 SC81 26 12 250 750 180 0 270 - RT100 SC82 27 11 250 250 180 0 270 - RT100 SC83 28 23 750 750 180 0 270 - RT100 SC84 29 9 750 250 180 0 270 - ### - RT100 SC72 80 21 1000 0 346 0 270 - RT100 SC73 79 20 1000 500 346 0 270 - RT100 SC74 78 19 1000 1000 346 0 270 - RT100 SC75 77 18 500 0 346 0 270 - RT100 SC76 84 17 500 500 346 0 270 - RT100 SC77 75 16 500 1000 346 0 270 - RT100 SC78 74 15 0 0 346 0 270 - RT100 SC79 73 14 0 500 346 0 270 - RT100 SC80 72 13 0 1000 346 0 270 - STOP - """.trimIndent() + const val GEOMETRY_TOLERANCE = 0.01 + const val PIXEL_XY_SIZE = 122.0 + const val PIXEL_XY_SPACING = 123.2 + const val PIXEL_Z_SIZE = 30.0 + const val CENTRAL_LAYER_Z = 0.0 + const val UPPER_LAYER_Z = 166.0 + const val LOWER_LAYER_Z = -180.0 /** * Build map for the whole monitor */ val detectors: Collection by lazy { - monitorConfig.lineSequence().mapNotNull { line -> + readMonitorConfig().lineSequence().mapNotNull { line -> if (line.startsWith(" ")) { val split = line.trim().split("\\s+".toRegex()); val detectorName = split[1]; @@ -171,4 +146,6 @@ object Monitor { }.toList() } + val pixels: Collection get() = detectors.flatMap { it.pixels } + } \ No newline at end of file diff --git a/demo/muon-monitor/src/commonMain/kotlin/ru/mipt/npm/muon/monitor/geometry.kt b/demo/muon-monitor/src/commonMain/kotlin/ru/mipt/npm/muon/monitor/geometry.kt deleted file mode 100644 index 8e2f533d..00000000 --- a/demo/muon-monitor/src/commonMain/kotlin/ru/mipt/npm/muon/monitor/geometry.kt +++ /dev/null @@ -1,18 +0,0 @@ -@file:UseSerializers(Point3DSerializer::class) -package ru.mipt.npm.muon.monitor - -import hep.dataforge.vis.spatial.Point3D -import hep.dataforge.vis.spatial.Point3DSerializer -import kotlinx.serialization.Serializable -import kotlinx.serialization.UseSerializers - -@Serializable -data class Line( - val start: Point3D, - val direction: Point3D -) - -data class Plane( - val normal: Point3D, - val offset: Number -) diff --git a/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/readResource.kt b/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/readResource.kt index 9d36767c..46242a20 100644 --- a/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/readResource.kt +++ b/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/readResource.kt @@ -1,7 +1,40 @@ -package ru.mipt.npm.muon.sim +package ru.mipt.npm.muon.monitor import hep.dataforge.js.requireJS actual fun readResource(path: String): String { return requireJS(path) as String +} + +// TODO replace by resource +internal actual fun readMonitorConfig(): String{ + return """ + --Place-|-SC16-|-TB-CHN-|-HB-CHN-|-X-coord-|-Y-coord-|-Z-coord-|-Theta-|-Phi + ---------------------------------------------------------------------------- + RT100 SC86 3 0 0 1000 0 0 270 + RT100 SC87 6 1 0 500 0 0 270 + RT100 SC88 8 2 0 0 0 0 270 + RT100 SC91 9 3 500 1000 0 0 270 + RT100 SC92 10 4 500 500 0 0 270 + RT100 SC93 11 5 500 0 0 0 270 + RT100 SC94 12 6 1000 1000 0 0 270 + RT100 SC85 13 7 1000 500 0 0 270 + RT100 SC96 15 8 1000 0 0 0 270 + ### + RT100 SC81 26 12 250 750 180 0 270 + RT100 SC82 27 11 250 250 180 0 270 + RT100 SC83 28 23 750 750 180 0 270 + RT100 SC84 29 9 750 250 180 0 270 + ### + RT100 SC72 80 21 1000 0 346 0 270 + RT100 SC73 79 20 1000 500 346 0 270 + RT100 SC74 78 19 1000 1000 346 0 270 + RT100 SC75 77 18 500 0 346 0 270 + RT100 SC76 84 17 500 500 346 0 270 + RT100 SC77 75 16 500 1000 346 0 270 + RT100 SC78 74 15 0 0 346 0 270 + RT100 SC79 73 14 0 500 346 0 270 + RT100 SC80 72 13 0 1000 346 0 270 + STOP + """.trimIndent() } \ No newline at end of file diff --git a/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/readResource.kt b/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/readResource.kt index ee6b3520..37a11680 100644 --- a/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/readResource.kt +++ b/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/readResource.kt @@ -1,5 +1,10 @@ -package ru.mipt.npm.muon.sim +package ru.mipt.npm.muon.monitor actual fun readResource(path: String): String { - return ClassLoader.getSystemClassLoader().getResourceAsStream("map-RMM110.sc16").readAllBytes().contentToString() + return ClassLoader.getSystemClassLoader().getResourceAsStream(path)?.readAllBytes()?.contentToString() + ?: error("Resource '$path' not found") +} + +internal actual fun readMonitorConfig(): String { + return readResource("map-RMM110.sc16") } \ No newline at end of file diff --git a/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/sim/Pixel.kt b/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/sim/Pixel.kt new file mode 100644 index 00000000..c3873e50 --- /dev/null +++ b/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/sim/Pixel.kt @@ -0,0 +1,121 @@ +package ru.mipt.npm.muon.monitor.sim + +import org.apache.commons.math3.geometry.euclidean.threed.Line +import org.apache.commons.math3.geometry.euclidean.threed.Plane +import org.apache.commons.math3.geometry.euclidean.threed.Vector3D +import ru.mipt.npm.muon.monitor.Monitor.CENTRAL_LAYER_Z +import ru.mipt.npm.muon.monitor.Monitor.GEOMETRY_TOLERANCE +import ru.mipt.npm.muon.monitor.Monitor.LOWER_LAYER_Z +import ru.mipt.npm.muon.monitor.Monitor.PIXEL_XY_SIZE +import ru.mipt.npm.muon.monitor.Monitor.UPPER_LAYER_Z +import ru.mipt.npm.muon.monitor.SC1 + +/** + * Auxiliary cache for [SC1] planes + */ +internal class SC1Aux(val sc: SC1, var efficiency: Double = 1.0) { + // val layer: Layer = findLayer(center.z); + private val upLayer = + findLayer(sc.center.z + sc.zSize / 2.0)//Layer("${name}_up", center.z + zSize / 2.0); + private val bottomLayer = + findLayer(sc.center.z - sc.zSize / 2.0)//Layer("${name}_bottom", center.z - zSize / 2.0); + private val centralLayer = findLayer(sc.center.z) + + private val center = Vector3D(sc.center.x, sc.center.y, sc.center.z) + + private val sideLayers: Array = arrayOf( + Plane(center.add(Vector3D(PIXEL_XY_SIZE / 2, 0.0, 0.0)), Vector3D(1.0, 0.0, 0.0), GEOMETRY_TOLERANCE), + Plane(center.add(Vector3D(-PIXEL_XY_SIZE / 2, 0.0, 0.0)), Vector3D(-1.0, 0.0, 0.0), GEOMETRY_TOLERANCE), + Plane(center.add(Vector3D(0.0, PIXEL_XY_SIZE / 2, 0.0)), Vector3D(0.0, 1.0, 0.0), GEOMETRY_TOLERANCE), + Plane(center.add(Vector3D(0.0, -PIXEL_XY_SIZE / 2, 0.0)), Vector3D(0.0, -1.0, 0.0), GEOMETRY_TOLERANCE) + ); + + //TODO add efficiency + private fun containsPoint(x: Double, y: Double, z: Double, tolerance: Double = GEOMETRY_TOLERANCE): Boolean { + return x <= sc.center.x + sc.xSize / 2.0 + tolerance && x >= sc.center.x - sc.xSize / 2.0 - tolerance && + y <= sc.center.y + sc.ySize / 2.0 + tolerance && y >= sc.center.y - sc.ySize / 2.0 - tolerance && + z <= sc.center.z + sc.zSize / 2.0 + tolerance && z >= sc.center.z - sc.zSize / 2.0 - tolerance; + } + + /** + * Check if pixel contains point + */ + private fun containsPoint(point: Vector3D, tolerance: Double = GEOMETRY_TOLERANCE): Boolean { + return containsPoint(point.x, point.y, point.z, tolerance); + } + + /** + * Return number of detector pixel like SCxx-12 + */ + fun getDetectorNumber(): Int { + return sc.name.substring(2, 4).toInt(); + } + + /** + * Return number of pixel in detector like SC79-xx + */ + fun getPixelNumber(): Int { + return sc.name.substring(5).toInt(); + } + + /** + * The layer number from up to bottom + */ + fun getLayerNumber(): Int { + return when (this.center.z) { + UPPER_LAYER_Z -> 1; + CENTRAL_LAYER_Z -> 2; + LOWER_LAYER_Z -> 3; + else -> throw RuntimeException("Unknown layer"); + } + } + + /** + * Check if track crosses the pixel + */ + fun isHit(track: Line): Boolean { + //check central plane as well as upper and bottom planes of the layer + val upperIntersection = upLayer.intersection(track); + val bottomIntersection = bottomLayer.intersection(track); + val upperHit = containsPoint(upperIntersection); + val bottomHit = containsPoint(bottomIntersection); + + if (!bottomHit && !upperHit) { + return false; + } else if (upperHit && bottomHit) { + return eff(); + } else { + val verticalHitPoint = if (upperHit) { + upperIntersection + } else { + bottomIntersection + } + val horizontalHitPoint = getHorizontalHitPoint(track); + return if (horizontalHitPoint == null) { + //If horizontal intersection could not be found, it is near the rib and therefore length is always sufficient + true; + } else { + val length = verticalHitPoint.distance(horizontalHitPoint); + (length >= MINIMAL_TRACK_LENGTH) && eff(); + } + } + } + + private fun getHorizontalHitPoint(track: Line): Vector3D? { + return sideLayers + .map { it.intersection(track) }//FIXME there is a problem with geometric tolerances here + .firstOrNull { it != null && containsPoint(it, 100 * GEOMETRY_TOLERANCE) }; + } + + private fun eff(): Boolean { + return efficiency == 1.0 || rnd.nextDouble() < efficiency; + } +} + +private val auxCache = HashMap() + +fun SC1.isHit(track: Line): Boolean{ + return auxCache.getOrPut(this){ + SC1Aux(this) + }.isHit(track) +} \ No newline at end of file diff --git a/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/sim/line.kt b/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/sim/line.kt new file mode 100644 index 00000000..db673b97 --- /dev/null +++ b/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/sim/line.kt @@ -0,0 +1,61 @@ +package ru.mipt.npm.muon.monitor.sim + +import hep.dataforge.vis.spatial.Point3D +import org.apache.commons.math3.geometry.euclidean.threed.Line +import org.apache.commons.math3.geometry.euclidean.threed.Plane +import org.apache.commons.math3.geometry.euclidean.threed.Vector3D +import ru.mipt.npm.muon.monitor.Monitor.CENTRAL_LAYER_Z +import ru.mipt.npm.muon.monitor.Monitor.GEOMETRY_TOLERANCE + +/** + * Created by darksnake on 11-May-16. + */ + +private val basePlane = Plane(Vector3D(0.0, 0.0, 0.0), Vector3D(0.0, 0.0, 1.0), GEOMETRY_TOLERANCE); + +/** + * elevation angle + */ +fun Line.getTheta(): Double { + return direction.delta; +} + +/** + * Azimuthal angle + */ +fun Line.getPhi(): Double { + return direction.alpha; +} + +/** + * x of intersection with base (central) plane + */ +fun Line.getX(): Double { + return basePlane.intersection(this).x; +} + +fun Line.getY(): Double { + return basePlane.intersection(this).y; +} + +fun makeTrack(start: Vector3D, direction: Vector3D): Line { + return Line(start, start.add(direction), GEOMETRY_TOLERANCE) +} + +fun makeTrack(x: Double, y: Double, theta: Double, phi: Double): Line { + //TODO check angle definitions + return makeTrack( + Vector3D(x, y, CENTRAL_LAYER_Z), + Vector3D(phi, theta) + ) +} + +fun Vector3D.toPoint() = Point3D(x, y, z) + +fun Line.toPoints(): List { + val basePoint = basePlane.intersection(this) + val bottom = basePoint.subtract(300.0, direction) + val top = basePoint.add(300.0, direction) + return listOf(bottom.toPoint(), top.toPoint()) +} + diff --git a/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/sim/monitor.kt b/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/sim/monitor.kt new file mode 100644 index 00000000..b7039ac6 --- /dev/null +++ b/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/sim/monitor.kt @@ -0,0 +1,55 @@ +package ru.mipt.npm.muon.monitor.sim + +import org.apache.commons.math3.geometry.euclidean.threed.Line +import org.apache.commons.math3.geometry.euclidean.threed.Plane +import org.apache.commons.math3.geometry.euclidean.threed.Vector3D +import org.apache.commons.math3.random.JDKRandomGenerator +import org.apache.commons.math3.random.RandomGenerator +import ru.mipt.npm.muon.monitor.Event +import ru.mipt.npm.muon.monitor.Monitor +import ru.mipt.npm.muon.monitor.SC1 +import ru.mipt.npm.muon.monitor.readResource +import java.util.* + + +// minimal track length in detector +val MINIMAL_TRACK_LENGTH = 10.0 + +var rnd: RandomGenerator = JDKRandomGenerator(223) + + +private val layerCache = HashMap() + +fun findLayer(z: Double): Plane = layerCache.getOrPut(z){ + Plane(Vector3D(0.0, 0.0, z), Vector3D(0.0, 0.0, 1.0), + Monitor.GEOMETRY_TOLERANCE + ) +} + +fun readEffs(): Map { + val effMap = HashMap() + var detectorName: String = "" + var index: Int = 0 + readResource("Effs-MM-minhits-4.dat").lineSequence().forEach { line -> + val trimmed = line.trim() + if (trimmed.startsWith("SC")) { + detectorName = trimmed.split(Regex("\\s+"))[2] + } else if (trimmed.startsWith("pixel")) { + index = 0 + } else if (!trimmed.isEmpty()) { + val eff = trimmed.split(Regex("\\s+"))[1].toDouble() + effMap.put("SC${detectorName}_${index}", eff) + index++ + } + } + return effMap +} + + +fun buildEventByTrack(track: Line, hitResolver: (Line) -> Collection = defaultHitResolver): Event { + return Event(track.toPoints(), hitResolver(track).map { it.name }) +} + +val defaultHitResolver: (Line) -> Collection = { track: Line -> + Monitor.pixels.filter { it.isHit(track) }.toSet() +} \ No newline at end of file diff --git a/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/sim/simulation.kt b/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/sim/simulation.kt new file mode 100644 index 00000000..c7ba89fe --- /dev/null +++ b/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/sim/simulation.kt @@ -0,0 +1,71 @@ +package ru.mipt.npm.muon.monitor.sim + +import org.apache.commons.math3.geometry.euclidean.threed.Line +import ru.mipt.npm.muon.monitor.Event +import ru.mipt.npm.muon.monitor.Monitor.PIXEL_XY_SIZE + + +/** + * Simulate single track and returns corresponding event + */ +fun simulateOne(trackGenerator: TrackGenerator = UniformTrackGenerator()): Event { + val track = trackGenerator.generate() + return buildEventByTrack(track) +} + +interface TrackGenerator { + fun generate(): Line +} + +/** + * A uniform generator with track bases distributed in square in central plane, uniform phi and cos theta + */ +class UniformTrackGenerator(val maxX: Double = 4 * PIXEL_XY_SIZE, val maxY: Double = 4 * PIXEL_XY_SIZE) : + TrackGenerator { + override fun generate(): Line { + val x = (1 - rnd.nextDouble() * 2.0) * maxX + val y = (1 - rnd.nextDouble() * 2.0) * maxY + val phi = (1 - rnd.nextDouble() * 2.0) * Math.PI + val theta = Math.PI / 2 - Math.acos(rnd.nextDouble()) + return makeTrack(x, y, theta, phi) + } +} + +class FixedAngleGenerator( + val phi: Double, val theta: Double, + val maxX: Double = 4 * PIXEL_XY_SIZE, + val maxY: Double = 4 * PIXEL_XY_SIZE +) : TrackGenerator { + override fun generate(): Line { + val x = (1 - rnd.nextDouble() * 2.0) * maxX + val y = (1 - rnd.nextDouble() * 2.0) * maxY + return makeTrack(x, y, theta, phi) + } +} + +/** + * Generating surface distribution using accept-reject method + */ +class Cos2TrackGenerator( + val power: Double = 2.0, + val maxX: Double = 4 * PIXEL_XY_SIZE, + val maxY: Double = 4 * PIXEL_XY_SIZE +) : + TrackGenerator { + override fun generate(): Line { + val x = (1 - rnd.nextDouble() * 2.0) * maxX + val y = (1 - rnd.nextDouble() * 2.0) * maxY + val phi = (1 - rnd.nextDouble() * 2.0) * Math.PI + + + for (i in 0..500) { + val thetaCandidate = Math.acos(rnd.nextDouble()) + val u = rnd.nextDouble() + val sin = Math.sin(thetaCandidate) + if (u < Math.pow(sin, power) / sin) { + return makeTrack(x, y, thetaCandidate, phi) + } + } + throw RuntimeException("Failed to generate theta from distribution") + } +} \ No newline at end of file diff --git a/demo/muon-monitor/src/jvmMain/resources/Effs-MM-minhits-4.dat b/demo/muon-monitor/src/jvmMain/resources/Effs-MM-minhits-4.dat new file mode 100644 index 00000000..6c700195 --- /dev/null +++ b/demo/muon-monitor/src/jvmMain/resources/Effs-MM-minhits-4.dat @@ -0,0 +1,397 @@ + SC16 = 72 the min number of hits = 4 + pixel eff d_eff n_hit n_tot + 1a 0.9815 0.0070 39065 39801 + 2a 0.9790 0.0070 38199 39019 + 3a 0.9811 0.0070 38791 39538 + 4a 0.9833 0.0069 39987 40668 + 1b 0.9810 0.0070 38941 39697 + 2b 0.9800 0.0071 37449 38213 + 3b 0.9804 0.0070 39025 39806 + 4b 0.9804 0.0069 40432 41241 + 1c 0.9787 0.0069 39365 40221 + 2c 0.9793 0.0071 38092 38898 + 3c 0.9812 0.0070 38548 39288 + 4c 0.9806 0.0068 40894 41702 + 1d 0.9793 0.0069 39640 40479 + 2d 0.9775 0.0071 37605 38470 + 3d 0.9778 0.0069 39541 40439 + 4d 0.9786 0.0067 41719 42631 + SC16 = 73 the min number of hits = 4 + pixel eff d_eff n_hit n_tot + 1a 0.9794 0.0069 39439 40270 + 2a 0.9791 0.0071 37754 38561 + 3a 0.9789 0.0069 39348 40198 + 4a 0.9794 0.0068 41517 42391 + 1b 0.9795 0.0070 39205 40027 + 2b 0.9796 0.0071 37647 38432 + 3b 0.9809 0.0070 38528 39280 + 4b 0.9818 0.0069 40075 40817 + 1c 0.9800 0.0071 38046 38822 + 2c 0.9805 0.0071 37651 38399 + 3c 0.9776 0.0069 39304 40205 + 4c 0.9817 0.0068 41296 42065 + 1d 0.9797 0.0070 38920 39728 + 2d 0.9802 0.0071 38191 38964 + 3d 0.9802 0.0070 38525 39302 + 4d 0.9825 0.0069 40020 40733 + SC16 = 74 the min number of hits = 4 + pixel eff d_eff n_hit n_tot + 1a 0.9820 0.0070 39544 40270 + 2a 0.9816 0.0071 37850 38561 + 3a 0.9826 0.0070 39500 40198 + 4a 0.9835 0.0068 41693 42391 + 1b 0.9826 0.0070 39332 40027 + 2b 0.9811 0.0071 37707 38432 + 3b 0.9839 0.0070 38646 39280 + 4b 0.9855 0.0069 40224 40817 + 1c 0.9817 0.0071 38111 38822 + 2c 0.9825 0.0071 37726 38399 + 3c 0.9827 0.0070 39511 40205 + 4c 0.9842 0.0068 41399 42065 + 1d 0.9847 0.0070 39119 39728 + 2d 0.9825 0.0071 38282 38964 + 3d 0.9832 0.0070 38642 39302 + 4d 0.9856 0.0069 40148 40733 + SC16 = 75 the min number of hits = 4 + pixel eff d_eff n_hit n_tot + 1a 0.9850 0.0069 40488 41106 + 2a 0.9824 0.0070 39586 40294 + 3a 0.9842 0.0069 40539 41189 + 4a 0.9877 0.0068 41864 42385 + 1b 0.9837 0.0069 40803 41478 + 2b 0.9835 0.0070 38953 39605 + 3b 0.9839 0.0069 40864 41533 + 4b 0.9856 0.0068 41895 42505 + 1c 0.9843 0.0068 41478 42139 + 2c 0.9825 0.0069 39926 40637 + 3c 0.9854 0.0069 40817 41422 + 4c 0.9866 0.0067 42925 43509 + 1d 0.9839 0.0068 41165 41839 + 2d 0.9837 0.0070 39517 40172 + 3d 0.9830 0.0068 40869 41576 + 4d 0.9840 0.0066 43928 44642 + SC16 = 76 the min number of hits = 4 + pixel eff d_eff n_hit n_tot + 1a 0.9862 0.0068 41502 42083 + 2a 0.9871 0.0070 39451 39965 + 3a 0.9886 0.0069 40287 40752 + 4a 0.9897 0.0068 42213 42652 + 1b 0.9871 0.0068 41396 41939 + 2b 0.9864 0.0070 39284 39824 + 3b 0.9870 0.0069 41226 41768 + 4b 0.9863 0.0067 43486 44088 + 1c 0.9889 0.0070 40084 40533 + 2c 0.9868 0.0070 39824 40357 + 3c 0.9889 0.0069 40552 41008 + 4c 0.9908 0.0069 41425 41809 + 1d 0.9887 0.0070 40039 40498 + 2d 0.9873 0.0070 39214 39717 + 3d 0.9865 0.0069 40925 41486 + 4d 0.9883 0.0068 42085 42583 + SC16 = 77 the min number of hits = 4 + pixel eff d_eff n_hit n_tot + 1a 0.9895 0.0082 29031 29339 + 2a 0.9887 0.0083 28275 28599 + 3a 0.9893 0.0081 29510 29830 + 4a 0.9902 0.0080 30308 30607 + 1b 0.9889 0.0082 28597 28918 + 2b 0.9888 0.0084 27365 27675 + 3b 0.9892 0.0083 28387 28696 + 4b 0.9913 0.0082 29412 29669 + 1c 0.9897 0.0082 28659 28957 + 2c 0.9885 0.0083 27926 28250 + 3c 0.9902 0.0082 29138 29426 + 4c 0.9909 0.0080 30831 31113 + 1d 0.9895 0.0081 29622 29937 + 2d 0.9879 0.0084 27787 28126 + 3d 0.9900 0.0082 28675 28964 + 4d 0.9913 0.0080 30536 30804 + SC16 = 78 the min number of hits = 4 + pixel eff d_eff n_hit n_tot + 1a 0.9807 0.0068 41199 42008 + 2a 0.9786 0.0069 39864 40735 + 3a 0.9783 0.0068 41363 42279 + 4a 0.9815 0.0067 42769 43577 + 1b 0.9813 0.0068 40825 41605 + 2b 0.9796 0.0069 39542 40366 + 3b 0.9815 0.0069 40446 41209 + 4b 0.9841 0.0068 41689 42362 + 1c 0.9788 0.0068 41347 42244 + 2c 0.9795 0.0069 40231 41075 + 3c 0.9788 0.0068 41565 42465 + 4c 0.9810 0.0066 44415 45276 + 1d 0.9796 0.0067 41707 42576 + 2d 0.9801 0.0069 39722 40528 + 3d 0.9816 0.0068 40700 41462 + 4d 0.9816 0.0067 43022 43830 + SC16 = 79 the min number of hits = 4 + pixel eff d_eff n_hit n_tot + 1a 0.9796 0.0081 29157 29765 + 2a 0.9781 0.0081 28678 29321 + 3a 0.9811 0.0081 28751 29304 + 4a 0.9783 0.0080 29750 30410 + 1b 0.9782 0.0081 29080 29728 + 2b 0.9762 0.0082 27948 28628 + 3b 0.9796 0.0080 29739 30358 + 4b 0.9796 0.0079 30395 31029 + 1c 0.9787 0.0080 29856 30505 + 2c 0.9787 0.0081 28613 29235 + 3c 0.9800 0.0081 29214 29811 + 4c 0.9804 0.0079 30742 31356 + 1d 0.9781 0.0080 29903 30572 + 2d 0.9780 0.0082 28276 28912 + 3d 0.9772 0.0080 29570 30259 + 4d 0.9788 0.0078 31546 32229 + SC16 = 80 the min number of hits = 4 + pixel eff d_eff n_hit n_tot + 1a 0.9850 0.0082 28399 28832 + 2a 0.9834 0.0083 27891 28363 + 3a 0.9859 0.0082 28386 28791 + 4a 0.9878 0.0081 29272 29634 + 1b 0.9858 0.0083 28122 28528 + 2b 0.9833 0.0084 26978 27437 + 3b 0.9846 0.0082 28345 28789 + 4b 0.9872 0.0081 29293 29674 + 1c 0.9841 0.0082 28684 29148 + 2c 0.9828 0.0083 27674 28159 + 3c 0.9851 0.0083 27958 28381 + 4c 0.9869 0.0081 29810 30206 + 1d 0.9848 0.0081 29321 29774 + 2d 0.9844 0.0083 27631 28069 + 3d 0.9836 0.0082 28503 28979 + 4d 0.9851 0.0079 30577 31038 + SC16 = 81 the min number of hits = 4 + pixel eff d_eff n_hit n_tot + 1a 0.9856 0.0086 25820 26198 + 2a 0.9868 0.0089 24696 25027 + 3a 0.9892 0.0088 25195 25469 + 4a 0.9892 0.0087 25786 26068 + 1b 0.9858 0.0087 25638 26007 + 2b 0.9863 0.0089 24125 24459 + 3b 0.9873 0.0086 25929 26262 + 4b 0.9852 0.0085 26940 27344 + 1c 0.9885 0.0089 24530 24816 + 2c 0.9873 0.0089 24570 24886 + 3c 0.9888 0.0088 25000 25282 + 4c 0.9907 0.0087 26103 26347 + 1d 0.9887 0.0088 25076 25362 + 2d 0.9857 0.0089 24340 24694 + 3d 0.9864 0.0087 25796 26152 + 4d 0.9871 0.0086 26010 26350 + SC16 = 82 the min number of hits = 4 + pixel eff d_eff n_hit n_tot + 1a 0.9841 0.0069 40146 40794 + 2a 0.9830 0.0070 39206 39884 + 3a 0.9854 0.0070 39525 40112 + 4a 0.9874 0.0069 40762 41284 + 1b 0.9857 0.0069 40187 40771 + 2b 0.9851 0.0071 38243 38823 + 3b 0.9835 0.0069 40009 40679 + 4b 0.9850 0.0068 41450 42082 + 1c 0.9835 0.0069 40251 40927 + 2c 0.9843 0.0070 39042 39663 + 3c 0.9845 0.0069 39990 40621 + 4c 0.9869 0.0068 41955 42512 + 1d 0.9819 0.0069 40635 41386 + 2d 0.9843 0.0070 38912 39532 + 3d 0.9831 0.0069 40428 41121 + 4d 0.9825 0.0067 42663 43422 + SC16 = 83 the min number of hits = 4 + pixel eff d_eff n_hit n_tot + 1a 0.9845 0.0068 41429 42083 + 2a 0.9830 0.0070 39286 39965 + 3a 0.9838 0.0069 40092 40752 + 4a 0.9850 0.0068 42013 42652 + 1b 0.9840 0.0068 41266 41939 + 2b 0.9837 0.0070 39174 39824 + 3b 0.9842 0.0068 41108 41768 + 4b 0.9841 0.0067 43388 44088 + 1c 0.9851 0.0069 39928 40533 + 2c 0.9817 0.0069 39617 40357 + 3c 0.9849 0.0069 40390 41008 + 4c 0.9863 0.0068 41238 41809 + 1d 0.9849 0.0069 39885 40498 + 2d 0.9843 0.0070 39092 39717 + 3d 0.9828 0.0069 40774 41486 + 4d 0.9859 0.0068 41981 42583 + SC16 = 84 the min number of hits = 4 + pixel eff d_eff n_hit n_tot + 1a 0.9808 0.0086 25720 26224 + 2a 0.9780 0.0088 24341 24889 + 3a 0.9834 0.0086 26105 26547 + 4a 0.9796 0.0085 26333 26881 + 1b 0.9835 0.0087 25276 25699 + 2b 0.9816 0.0088 24571 25032 + 3b 0.9790 0.0087 25134 25674 + 4b 0.9866 0.0086 25969 26323 + 1c 0.9851 0.0086 25755 26145 + 2c 0.9831 0.0088 24727 25152 + 3c 0.9821 0.0086 25863 26335 + 4c 0.9813 0.0083 27641 28169 + 1d 0.9845 0.0086 26120 26532 + 2d 0.9835 0.0088 24676 25090 + 3d 0.9805 0.0086 25495 26003 + 4d 0.9847 0.0084 27010 27430 + SC16 = 85 the min number of hits = 4 + pixel eff d_eff n_hit n_tot + 1a 0.9888 0.0069 41438 41908 + 2a 0.9879 0.0070 40115 40608 + 3a 0.9885 0.0068 41522 42007 + 4a 0.9890 0.0066 44029 44518 + 1b 0.9876 0.0068 41537 42059 + 2b 0.9883 0.0070 39491 39958 + 3b 0.9908 0.0069 40708 41086 + 4b 0.9895 0.0068 42674 43128 + 1c 0.9893 0.0070 40236 40672 + 2c 0.9883 0.0070 39383 39849 + 3c 0.9887 0.0068 41897 42374 + 4c 0.9901 0.0067 43244 43677 + 1d 0.9891 0.0069 40750 41197 + 2d 0.9878 0.0070 39719 40209 + 3d 0.9901 0.0069 40752 41159 + 4d 0.9902 0.0068 42110 42525 + SC16 = 86 the min number of hits = 4 + pixel eff d_eff n_hit n_tot + 1a 0.9870 0.0081 29757 30148 + 2a 0.9883 0.0082 28618 28958 + 3a 0.9879 0.0082 29167 29524 + 4a 0.9886 0.0079 30975 31331 + 1b 0.9887 0.0081 29794 30133 + 2b 0.9876 0.0083 28184 28538 + 3b 0.9895 0.0082 29207 29518 + 4b 0.9907 0.0080 30271 30555 + 1c 0.9883 0.0082 28908 29251 + 2c 0.9887 0.0083 28282 28606 + 3c 0.9883 0.0081 29827 30181 + 4c 0.9916 0.0079 31116 31380 + 1d 0.9900 0.0082 29326 29622 + 2d 0.9884 0.0082 28561 28897 + 3d 0.9898 0.0082 29081 29380 + 4d 0.9911 0.0081 29889 30158 + SC16 = 87 the min number of hits = 4 + pixel eff d_eff n_hit n_tot + 1a 0.9876 0.0070 39769 40270 + 2a 0.9875 0.0071 38079 38561 + 3a 0.9886 0.0070 39740 40198 + 4a 0.9869 0.0068 41835 42391 + 1b 0.9878 0.0070 39538 40027 + 2b 0.9871 0.0071 37936 38432 + 3b 0.9885 0.0071 38827 39280 + 4b 0.9896 0.0069 40393 40817 + 1c 0.9887 0.0071 38383 38822 + 2c 0.9864 0.0071 37878 38399 + 3c 0.9892 0.0070 39772 40205 + 4c 0.9899 0.0068 41641 42065 + 1d 0.9890 0.0070 39290 39728 + 2d 0.9880 0.0071 38495 38964 + 3d 0.9888 0.0071 38862 39302 + 4d 0.9912 0.0070 40375 40733 + SC16 = 88 the min number of hits = 4 + pixel eff d_eff n_hit n_tot + 1a 0.9804 0.0068 41090 41910 + 2a 0.9788 0.0068 40437 41311 + 3a 0.9787 0.0067 41989 42905 + 4a 0.9814 0.0067 42708 43517 + 1b 0.9806 0.0068 41179 41993 + 2b 0.9786 0.0069 39836 40706 + 3b 0.9822 0.0068 40809 41550 + 4b 0.9830 0.0068 41869 42592 + 1c 0.9790 0.0067 41953 42853 + 2c 0.9778 0.0068 40547 41467 + 3c 0.9776 0.0067 42426 43398 + 4c 0.9781 0.0065 45386 46401 + 1d 0.9781 0.0067 42368 43318 + 2d 0.9798 0.0069 40395 41227 + 3d 0.9794 0.0068 41421 42293 + 4d 0.9810 0.0066 43810 44658 + SC16 = 91 the min number of hits = 4 + pixel eff d_eff n_hit n_tot + 1a 0.9804 0.0068 41402 42230 + 2a 0.9765 0.0068 40606 41582 + 3a 0.9816 0.0068 41040 41811 + 4a 0.9818 0.0067 42427 43215 + 1b 0.9812 0.0068 41383 42176 + 2b 0.9785 0.0069 39515 40383 + 3b 0.9787 0.0068 41492 42394 + 4b 0.9812 0.0067 43091 43918 + 1c 0.9774 0.0067 41827 42794 + 2c 0.9782 0.0069 40267 41164 + 3c 0.9801 0.0068 41027 41862 + 4c 0.9801 0.0066 43673 44562 + 1d 0.9801 0.0067 42176 43031 + 2d 0.9789 0.0068 40435 41308 + 3d 0.9774 0.0067 42377 43359 + 4d 0.9771 0.0065 44859 45908 + SC16 = 92 the min number of hits = 4 + pixel eff d_eff n_hit n_tot + 1a 0.9879 0.0082 28816 29168 + 2a 0.9876 0.0084 27450 27795 + 3a 0.9881 0.0082 28799 29147 + 4a 0.9877 0.0080 30498 30878 + 1b 0.9885 0.0082 28573 28904 + 2b 0.9881 0.0084 27702 28037 + 3b 0.9899 0.0083 28461 28752 + 4b 0.9905 0.0081 29726 30012 + 1c 0.9891 0.0084 27799 28104 + 2c 0.9892 0.0084 27657 27958 + 3c 0.9880 0.0082 28644 28991 + 4c 0.9903 0.0080 30138 30432 + 1d 0.9896 0.0082 28735 29037 + 2d 0.9891 0.0084 27680 27984 + 3d 0.9903 0.0083 28303 28580 + 4d 0.9912 0.0082 29272 29532 + SC16 = 93 the min number of hits = 4 + pixel eff d_eff n_hit n_tot + 1a 0.9847 0.0069 40699 41330 + 2a 0.9845 0.0070 39280 39898 + 3a 0.9220 0.0066 37984 41198 + 4a 0.9864 0.0067 43034 43629 + 1b 0.9851 0.0069 40603 41216 + 2b 0.9841 0.0071 38495 39117 + 3b 0.9873 0.0070 39577 40088 + 4b 0.9866 0.0068 41684 42250 + 1c 0.9859 0.0070 39523 40090 + 2c 0.9863 0.0070 39423 39972 + 3c 0.9865 0.0069 40785 41343 + 4c 0.9865 0.0068 42213 42790 + 1d 0.9857 0.0069 40010 40589 + 2d 0.9854 0.0070 38880 39456 + 3d 0.9859 0.0070 39559 40124 + 4d 0.9875 0.0069 40866 41385 + SC16 = 94 the min number of hits = 4 + pixel eff d_eff n_hit n_tot + 1a 0.9784 0.0086 25543 26106 + 2a 0.9800 0.0087 25262 25777 + 3a 0.9850 0.0087 25523 25912 + 4a 0.9835 0.0086 26036 26473 + 1b 0.9817 0.0087 25195 25664 + 2b 0.9768 0.0089 24039 24610 + 3b 0.9788 0.0086 25589 26143 + 4b 0.9821 0.0085 26527 27010 + 1c 0.9822 0.0086 25724 26191 + 2c 0.9802 0.0087 24951 25455 + 3c 0.9778 0.0087 25174 25746 + 4c 0.9810 0.0084 26777 27297 + 1d 0.9808 0.0086 25943 26452 + 2d 0.9775 0.0088 24528 25093 + 3d 0.9799 0.0086 25872 26404 + 4d 0.9783 0.0083 27161 27764 + SC16 = 96 the min number of hits = 4 + pixel eff d_eff n_hit n_tot + 1a 0.9865 0.0068 42151 42727 + 2a 0.9874 0.0070 40062 40574 + 3a 0.9890 0.0069 41115 41571 + 4a 0.9895 0.0068 42296 42743 + 1b 0.9874 0.0068 41364 41890 + 2b 0.9864 0.0070 39479 40022 + 3b 0.9872 0.0068 41528 42067 + 4b 0.9870 0.0067 43749 44326 + 1c 0.9898 0.0069 40533 40952 + 2c 0.9873 0.0069 40513 41034 + 3c 0.9898 0.0069 40908 41329 + 4c 0.9903 0.0068 42150 42562 + 1d 0.9882 0.0069 40903 41392 + 2d 0.9879 0.0070 39634 40121 + 3d 0.9862 0.0068 41810 42396 + 4d 0.9893 0.0067 43167 43635 +