Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package graphics.scenery
- import cleargl.GLVector
- import edu.mines.jtk.sgl.Tuple4
- import graphics.scenery.backends.Renderer
- import graphics.scenery.controls.TrackedDeviceType
- import java.awt.geom.Ellipse2D
- //import org.jruby.RubyBoolean
- //import org.junit.Test
- import java.io.File
- import java.lang.IllegalStateException
- import java.util.*
- import kotlin.collections.ArrayList
- import kotlin.collections.HashMap
- import kotlin.concurrent.thread
- import kotlin.math.cos
- import kotlin.math.sin
- import kotlin.random.Random
- class TSNEPlot(val fileName: String = "Pancreas_metadata_FACS_TSNE.csv"): Node() {
- val laser = Cylinder(0.005f, 0.2f, 20)
- var mesh = Mesh()
- var textBoardMesh = Mesh()
- var positionScaling = 0.2f
- init {
- fun simpleCsvReader(pathname: String = "Pancreas_metadata_FACS_TSNE.csv"): Pair<HashMap<String, ArrayList<String>>, ArrayList<ArrayList<Float>>> {
- //logger.info("my file name is: $pathname")
- val result = ArrayList<ArrayList<Float>>()
- val names = ArrayList<String>()
- val plate = ArrayList<String>()
- val csv = File(pathname)
- var nline = 0
- csv.forEachLine(Charsets.UTF_8) { line ->
- if (nline != 0) {
- val fields = ArrayList<Float>()
- // TODO: triple check this line is correct
- var colN = 0
- line.split(",").drop(8).forEach {
- if (colN == 0) {
- plate.add(it.replace("\"", ""))
- } else if (colN == 1) {
- names.add(it.replace("\"", ""))
- } else {
- val field = it.toFloat()
- fields.add(field)
- }
- colN += 1
- }
- result.add(fields)
- }
- nline += 1
- }
- //print("$plate")
- val metaresult = hashMapOf(
- "pancreaticCellMap" to names,
- "plateMap" to plate
- )
- return Pair(metaresult, result)
- }//basic .csv reader
- fun csvReader(pathName: String = "TabulaMuris3Ddata.csv"): Triple<ArrayList<String>, ArrayList<ArrayList<Float>>, ArrayList<ArrayList<Float>>> {
- val cellNames = ArrayList<String>()
- val geneExpressions = ArrayList<ArrayList<Float>>()
- val tsneCoordinates = ArrayList<ArrayList<Float>>()
- val csv = File(pathName)
- var nline = 0
- csv.forEachLine(Charsets.UTF_8) {line ->
- if(nline != 0) {
- val tsneFields = ArrayList<Float>()
- val geneFields = ArrayList<Float>()
- var colN = 0
- line.split(";").drop(1).forEach {
- //logger.info("this is my line $line")
- if(colN == 0) {
- cellNames.add(it.replace("\"", ""))
- //logger.info("this should be a cell name: $it")
- }
- else if(colN in 1..3) {
- val itFloatGene = it.toFloat()
- geneFields.add(itFloatGene)
- }
- else if(colN in 4..6) {
- val itFloatTsne = it.toFloat()
- tsneFields.add(itFloatTsne)
- }
- colN += 1
- }
- geneExpressions.add(geneFields)
- tsneCoordinates.add(tsneFields)
- }
- nline += 1
- }
- return Triple(cellNames, geneExpressions, tsneCoordinates)
- }//read in tabula muris data
- //csv parameters
- val (metadataTable, positionTable) = simpleCsvReader("Pancreas_metadata_FACS_TSNE.csv")
- val (cellNames, geneExpressions, tsneCoordinates) = csvReader("TabulaMuris3Ddata.csv")
- val uniqueCellNames = cellNames.toSet()
- fun getColorMaps(): HashMap<String, HashMap<String, GLVector>> {
- val tabulaCells = HashMap<String, GLVector>()
- for(i in uniqueCellNames){
- tabulaCells[i] = graphics.scenery.numerics.Random.randomVectorFromRange(3, 0f, 255f)
- logger.info("entry $i in tabulaCells: ${tabulaCells[i]}")
- }
- val pancreaticCellMap = hashMapOf(
- "udf" to GLVector(255 / 255f, 98 / 255f, 188 / 255f),
- "type B pancreatic cell" to GLVector(232 / 255f, 107 / 255f, 244 / 255f),
- "pancreatic stellate cell" to GLVector(149 / 255f, 145 / 255f, 255 / 255f),
- "pancreatic PP cell" to GLVector(0 / 255f, 176 / 255f, 246 / 255f),
- "pancreatic ductal cell" to GLVector(0 / 255f, 191 / 255f, 196 / 255f),
- "pancreatic D cell" to GLVector(0 / 255f, 190 / 255f, 125 / 255f),
- "pancreatic acinar cell" to GLVector(57 / 255f, 182 / 255f, 0 / 255f),
- "pancreatic A cell" to GLVector(162 / 255f, 165 / 255f, 0 / 255f),
- "leukocyte" to GLVector(216 / 255f, 144 / 255f, 0 / 255f),
- "endothelial cell" to GLVector(248 / 255f, 118 / 255f, 108 / 255f)
- )
- val plateMap = hashMapOf(
- "MAA000574" to GLVector(102 / 255f, 194 / 255f, 165 / 255f),
- "MAA000577" to GLVector(252 / 255f, 141 / 255f, 98 / 255f),
- "MAA000884" to GLVector(141 / 255f, 160 / 255f, 203 / 255f),
- "MAA000910" to GLVector(231 / 255f, 138 / 255f, 195 / 255f),
- "MAA001857" to GLVector(166 / 255f, 216 / 255f, 84 / 255f),
- "MAA001861" to GLVector(255 / 255f, 217 / 255f, 47 / 255f),
- "MAA001862" to GLVector(229 / 255f, 196 / 255f, 148 / 255f),
- "MAA001868" to GLVector(179 / 255f, 179 / 255f, 179 / 255f)
- )
- val hashDatabase = hashMapOf(
- "pancreaticCellMap" to pancreaticCellMap,
- "plateMap" to plateMap,
- "tabulaCells" to tabulaCells
- )
- return hashDatabase
- }//get color maps
- fun getShapeMaps(): HashMap<String, Node>{
- return hashMapOf(
- "deltahedra" to Icosphere(0.20f * positionScaling, 0),
- "ellipses" to Icosphere(0.20f * positionScaling, 3),
- "cubes" to Box(GLVector(0.01f * positionScaling, 0.01f * positionScaling, 0.01f * positionScaling))
- )
- }//get shape maps
- // Parameters
- val colorMaps = getColorMaps()
- val defaultColor = "pancreaticCellMap"
- val defaultShape = "ellipses"
- val names = metadataTable[defaultColor]
- val colorMap = colorMaps[defaultColor]
- val tabulaColorMap = colorMaps["tabulaCells"]
- if (names == null || colorMap == null || tabulaColorMap == null) {
- throw IllegalStateException("names or colorMap not found")
- }
- val v = getShapeMaps()[defaultShape]
- v!!.name = "master sphere"
- v.material = ShaderMaterial.fromFiles("DefaultDeferredInstanced.vert", "DefaultDeferred.frag")
- v.material.ambient = GLVector(0.1f, 0.0f, 0.0f)
- v.material.diffuse = GLVector(0.8f, 0.7f, 0.7f)
- v.material.specular = GLVector(0.05f, 0f, 0f)
- v.material.metallic = 0.01f
- v.material.roughness = 0.5f
- v.instancedProperties["ModelMatrix"] = { v.model }
- addChild(v)
- var zipCounter = 0
- cellNames.zip(tsneCoordinates) {cell, tsne ->
- val s = Mesh()
- val parsedGeneExpression = geneExpressions[zipCounter]
- val getShapeMap = getShapeMaps()[defaultShape]
- //val s = getShapeMap ?: throw IllegalStateException("s not found")
- s.name = cell
- s.scale = GLVector(parsedGeneExpression[0]*0.5f, parsedGeneExpression[1]*0.5f, parsedGeneExpression[2]*0.5f)
- s.position = GLVector(tsne[0], tsne[1], tsne[2])
- s.material.diffuse = tabulaColorMap.getOrDefault(cell, GLVector(1.0f, 0f, 0f))
- logger.info("this is the assigned color: ${tabulaColorMap[cell]}")
- // s.material.ambient = GLVector(0.1f, 0.0f, 0.0f)
- // s.material.specular = GLVector(0.05f, 0f, 0f)
- // s.material.metallic = 0.01f
- // s.material.roughness = 0.5f
- v.instances.add(s)
- zipCounter += 1
- }
- val x = Cylinder.betweenPoints(GLVector(-5.00f, 0f, 0f), GLVector(5.00f, 0f, 0f))
- x.material.diffuse = GLVector(1.0f, 1.0f, 1.0f)
- val y = Cylinder.betweenPoints(GLVector(0f, -5.00f, 0f), GLVector(0f, 5.00f, 0f))
- y.material.diffuse = GLVector(1.0f, 1.0f, 1.0f)
- val z = Cylinder.betweenPoints(GLVector(0f, 0f, -20.00f), GLVector(0f, 0f, 5.00f))
- z.material.diffuse = GLVector(1.0f, 1.0f, 1.0f)
- // Add objects to the scene
- addChild(x)
- addChild(y)
- addChild(z)// Cylinders
- addChild(mesh)
- // Create scene lighting
- Light.createLightTetrahedron<PointLight>(spread = 10.0f, radius = 95.0f).forEach {
- addChild(it)
- }
- //Add box to scene for sense of bound
- val hullbox = Box(GLVector(100.0f, 100.0f, 100.0f), insideNormals = true)
- with(hullbox) {
- position = GLVector(0.0f, 0.0f, 0.0f)
- material.ambient = GLVector(0.6f, 0.6f, 0.6f)
- material.diffuse = GLVector(0.4f, 0.4f, 0.4f)
- material.specular = GLVector(0.0f, 0.0f, 0.0f)
- material.cullingMode = Material.CullingMode.Front
- }
- addChild(hullbox)//hullbox
- laser.material.diffuse = GLVector(5.0f, 0.0f, 0.02f)
- laser.material.metallic = 0.0f
- laser.material.roughness = 1.0f
- laser.rotation.rotateByAngleX(-Math.PI.toFloat()/2.0f)
- laser.visible = false//laser
- //fetch center of mass for each cell type and attach TextBoard with cell type at that location
- val listOfCells = arrayListOf(
- "udf",
- "type B pancreatic cell",
- "pancreatic stellate cell",
- "pancreatic PP cell",
- "pancreatic ductal cell",
- "pancreatic D cell",
- "pancreatic acinar cell",
- "pancreatic A cell",
- "leukocyte",
- "endothelial cell")
- fun fetchCenterOfMass(type: String): GLVector {
- var additiveMass = FloatArray(3)
- var filteredLength = 0f
- for(i in mesh.children.filter{ it.name == type }) {
- additiveMass[0] += i.position.toFloatArray()[0]
- additiveMass[1] += i.position.toFloatArray()[1]
- additiveMass[2] += i.position.toFloatArray()[2]
- filteredLength += 1
- //logger.info("added mass: $additiveMass")
- }
- return GLVector(
- additiveMass[0] / filteredLength,
- additiveMass[1] / filteredLength,
- additiveMass[2] / filteredLength
- )
- }
- fun textBoardPositions(): HashMap<String, GLVector> {
- val massMap = HashMap<String, GLVector>()
- for(i in listOfCells){
- massMap[i] = fetchCenterOfMass(i)
- //logger.info("center of mass for $i is: ${fetchCenterOfMass(i)}")
- }
- return massMap
- }
- val massMap = textBoardPositions()
- //logger.info("massMap: $massMap")
- for(i in listOfCells){
- val t = TextBoard(isBillboard = false)
- t.text = i
- t.name = i
- t.transparent = 0
- t.fontColor = GLVector(0.0f, 0.0f, 0.0f)
- t.backgroundColor = colorMap[i]!!
- t.position = massMap[i]!!//*positionScaling
- //logger.info("scaled size: ${t.position}")
- t.scale = GLVector(2.0f, 2.0f, 2.0f)*positionScaling
- t.opacity = 0.5f
- textBoardMesh.addChild(t)
- }
- addChild(textBoardMesh)
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement