Commit b9a359c2 authored by Peter van 't Hof's avatar Peter van 't Hof
Browse files

Removed contigs storage in Stats class

parent 0d184280
...@@ -23,7 +23,7 @@ import scala.collection.mutable ...@@ -23,7 +23,7 @@ import scala.collection.mutable
* @param sampleToSample Stores sample to sample compare stats * @param sampleToSample Stores sample to sample compare stats
*/ */
case class SampleStats( case class SampleStats(
genotypeStats: mutable.Map[String, mutable.Map[String, mutable.Map[Any, Int]]] = mutable.Map(), genotypeStats: mutable.Map[String, mutable.Map[Any, Int]] = mutable.Map(),
sampleToSample: mutable.Map[String, SampleToSampleStats] = mutable.Map()) { sampleToSample: mutable.Map[String, SampleToSampleStats] = mutable.Map()) {
/** Add an other class */ /** Add an other class */
...@@ -32,12 +32,10 @@ case class SampleStats( ...@@ -32,12 +32,10 @@ case class SampleStats(
if (this.sampleToSample.contains(key)) this.sampleToSample(key) += value if (this.sampleToSample.contains(key)) this.sampleToSample(key) += value
else this.sampleToSample(key) = value else this.sampleToSample(key) = value
} }
for ((chr, chrMap) <- other.genotypeStats; (field, fieldMap) <- chrMap) { for ((field, fieldMap) <- other.genotypeStats) {
if (!this.genotypeStats.contains(chr)) val thisField = this.genotypeStats.get(field)
genotypeStats += (chr -> mutable.Map[String, mutable.Map[Any, Int]]())
val thisField = this.genotypeStats(chr).get(field)
if (thisField.isDefined) Stats.mergeStatsMap(thisField.get, fieldMap) if (thisField.isDefined) Stats.mergeStatsMap(thisField.get, fieldMap)
else this.genotypeStats(chr) += field -> fieldMap else this.genotypeStats += field -> fieldMap
} }
} }
} }
...@@ -16,9 +16,10 @@ package nl.lumc.sasc.biopet.tools.vcfstats ...@@ -16,9 +16,10 @@ package nl.lumc.sasc.biopet.tools.vcfstats
import java.io.{File, PrintWriter} import java.io.{File, PrintWriter}
import scala.collection.mutable import nl.lumc.sasc.biopet.tools.vcfstats.VcfStats.sampleDistributions
import nl.lumc.sasc.biopet.utils.sortAnyAny import scala.collection.mutable
import nl.lumc.sasc.biopet.utils.{ConfigUtils, sortAnyAny}
/** /**
* General stats class to store vcf stats * General stats class to store vcf stats
...@@ -26,7 +27,7 @@ import nl.lumc.sasc.biopet.utils.sortAnyAny ...@@ -26,7 +27,7 @@ import nl.lumc.sasc.biopet.utils.sortAnyAny
* @param generalStats Stores are general stats * @param generalStats Stores are general stats
* @param samplesStats Stores all sample/genotype specific stats * @param samplesStats Stores all sample/genotype specific stats
*/ */
case class Stats(generalStats: mutable.Map[String, mutable.Map[String, mutable.Map[Any, Int]]] = case class Stats(generalStats: mutable.Map[String, mutable.Map[Any, Int]] =
mutable.Map(), mutable.Map(),
samplesStats: mutable.Map[String, SampleStats] = mutable.Map()) { samplesStats: mutable.Map[String, SampleStats] = mutable.Map()) {
...@@ -36,12 +37,10 @@ case class Stats(generalStats: mutable.Map[String, mutable.Map[String, mutable.M ...@@ -36,12 +37,10 @@ case class Stats(generalStats: mutable.Map[String, mutable.Map[String, mutable.M
if (this.samplesStats.contains(key)) this.samplesStats(key) += value if (this.samplesStats.contains(key)) this.samplesStats(key) += value
else this.samplesStats(key) = value else this.samplesStats(key) = value
} }
for ((chr, chrMap) <- other.generalStats; (field, fieldMap) <- chrMap) { for ((field, fieldMap) <- other.generalStats) {
if (!this.generalStats.contains(chr)) val thisField = this.generalStats.get(field)
generalStats += (chr -> mutable.Map[String, mutable.Map[Any, Int]]())
val thisField = this.generalStats(chr).get(field)
if (thisField.isDefined) Stats.mergeStatsMap(thisField.get, fieldMap) if (thisField.isDefined) Stats.mergeStatsMap(thisField.get, fieldMap)
else this.generalStats(chr) += field -> fieldMap else this.generalStats += field -> fieldMap
} }
this this
} }
...@@ -49,17 +48,13 @@ case class Stats(generalStats: mutable.Map[String, mutable.Map[String, mutable.M ...@@ -49,17 +48,13 @@ case class Stats(generalStats: mutable.Map[String, mutable.Map[String, mutable.M
/** Function to write 1 specific general field */ /** Function to write 1 specific general field */
def writeField(field: String, def writeField(field: String,
outputDir: File, outputDir: File,
prefix: String = "", prefix: String = ""): File = {
chr: String = "total"): File = { val file = prefix match {
val file = (prefix, chr) match { case "" => new File(outputDir, field + ".tsv")
case ("", "total") => new File(outputDir, field + ".tsv") case _ => new File(outputDir, prefix + "-" + field + ".tsv")
case (_, "total") => new File(outputDir, prefix + "-" + field + ".tsv")
case ("", _) => new File(outputDir, chr + "-" + field + ".tsv")
case _ => new File(outputDir, prefix + "-" + chr + "-" + field + ".tsv")
} }
val data = this.generalStats val data = this.generalStats
.getOrElse(chr, mutable.Map[String, mutable.Map[Any, Int]]())
.getOrElse(field, mutable.Map[Any, Int]()) .getOrElse(field, mutable.Map[Any, Int]())
file.getParentFile.mkdirs() file.getParentFile.mkdirs()
...@@ -73,10 +68,9 @@ case class Stats(generalStats: mutable.Map[String, mutable.Map[String, mutable.M ...@@ -73,10 +68,9 @@ case class Stats(generalStats: mutable.Map[String, mutable.Map[String, mutable.M
} }
/** Function to write 1 specific general field */ /** Function to write 1 specific general field */
def getField(field: String, chr: String = "total"): Map[String, Array[Any]] = { def getField(field: String): Map[String, Array[Any]] = {
val data = this.generalStats val data = this.generalStats
.getOrElse(chr, mutable.Map[String, mutable.Map[Any, Int]]())
.getOrElse(field, mutable.Map[Any, Int]()) .getOrElse(field, mutable.Map[Any, Int]())
val rows = for (key <- data.keySet.toArray.sortWith(sortAnyAny)) yield { val rows = for (key <- data.keySet.toArray.sortWith(sortAnyAny)) yield {
(key, data(key)) (key, data(key))
...@@ -88,13 +82,10 @@ case class Stats(generalStats: mutable.Map[String, mutable.Map[String, mutable.M ...@@ -88,13 +82,10 @@ case class Stats(generalStats: mutable.Map[String, mutable.Map[String, mutable.M
def writeGenotypeField(samples: List[String], def writeGenotypeField(samples: List[String],
field: String, field: String,
outputDir: File, outputDir: File,
prefix: String = "", prefix: String = ""): Unit = {
chr: String = "total"): Unit = { val file = prefix match {
val file = (prefix, chr) match { case "" => new File(outputDir, field + ".tsv")
case ("", "total") => new File(outputDir, field + ".tsv") case _ => new File(outputDir, prefix + "-" + field + ".tsv")
case (_, "total") => new File(outputDir, prefix + "-" + field + ".tsv")
case ("", _) => new File(outputDir, chr + "-" + field + ".tsv")
case _ => new File(outputDir, prefix + "-" + chr + "-" + field + ".tsv")
} }
file.getParentFile.mkdirs() file.getParentFile.mkdirs()
...@@ -105,7 +96,6 @@ case class Stats(generalStats: mutable.Map[String, mutable.Map[String, mutable.M ...@@ -105,7 +96,6 @@ case class Stats(generalStats: mutable.Map[String, mutable.Map[String, mutable.M
this this
.samplesStats(sample) .samplesStats(sample)
.genotypeStats .genotypeStats
.getOrElse(chr, Map[String, Map[Any, Int]]())
.getOrElse(field, Map[Any, Int]()) .getOrElse(field, Map[Any, Int]())
.keySet).fold(Set[Any]())(_ ++ _) .keySet).fold(Set[Any]())(_ ++ _)
for (key <- keySet.toList.sortWith(sortAnyAny)) { for (key <- keySet.toList.sortWith(sortAnyAny)) {
...@@ -114,7 +104,6 @@ case class Stats(generalStats: mutable.Map[String, mutable.Map[String, mutable.M ...@@ -114,7 +104,6 @@ case class Stats(generalStats: mutable.Map[String, mutable.Map[String, mutable.M
this this
.samplesStats(sample) .samplesStats(sample)
.genotypeStats .genotypeStats
.getOrElse(chr, Map[String, Map[Any, Int]]())
.getOrElse(field, Map[Any, Int]()) .getOrElse(field, Map[Any, Int]())
.getOrElse(key, 0) .getOrElse(key, 0)
writer.println(values.mkString(key + "\t", "\t", "")) writer.println(values.mkString(key + "\t", "\t", ""))
...@@ -124,14 +113,12 @@ case class Stats(generalStats: mutable.Map[String, mutable.Map[String, mutable.M ...@@ -124,14 +113,12 @@ case class Stats(generalStats: mutable.Map[String, mutable.Map[String, mutable.M
/** Function to write 1 specific genotype field */ /** Function to write 1 specific genotype field */
def getGenotypeField(samples: List[String], def getGenotypeField(samples: List[String],
field: String, field: String): Map[String, Map[String, Any]] = {
chr: String = "total"): Map[String, Map[String, Any]] = {
val keySet = (for (sample <- samples) val keySet = (for (sample <- samples)
yield yield
this this
.samplesStats(sample) .samplesStats(sample)
.genotypeStats .genotypeStats
.getOrElse(chr, Map[String, Map[Any, Int]]())
.getOrElse(field, Map[Any, Int]()) .getOrElse(field, Map[Any, Int]())
.keySet).fold(Set[Any]())(_ ++ _) .keySet).fold(Set[Any]())(_ ++ _)
...@@ -144,7 +131,6 @@ case class Stats(generalStats: mutable.Map[String, mutable.Map[String, mutable.M ...@@ -144,7 +131,6 @@ case class Stats(generalStats: mutable.Map[String, mutable.Map[String, mutable.M
key.toString -> this key.toString -> this
.samplesStats(sample) .samplesStats(sample)
.genotypeStats .genotypeStats
.getOrElse(chr, Map[String, Map[Any, Int]]())
.getOrElse(field, Map[Any, Int]()) .getOrElse(field, Map[Any, Int]())
.get(key)) .get(key))
.filter(_._2.isDefined) .filter(_._2.isDefined)
...@@ -153,19 +139,17 @@ case class Stats(generalStats: mutable.Map[String, mutable.Map[String, mutable.M ...@@ -153,19 +139,17 @@ case class Stats(generalStats: mutable.Map[String, mutable.Map[String, mutable.M
} }
/** This will generate stats for one contig */ /** This will generate stats for one contig */
def getContigStats(contig: String, def getStatsAsMap(samples: List[String],
samples: List[String],
genotypeFields: List[String] = Nil, genotypeFields: List[String] = Nil,
infoFields: List[String] = Nil, infoFields: List[String] = Nil,
sampleDistributions: List[String] = Nil): Map[String, Any] = { sampleDistributions: List[String] = Nil): Map[String, Any] = {
Map( Map(
"genotype" -> genotypeFields.map(f => f -> getGenotypeField(samples, f, contig)).toMap, "genotype" -> genotypeFields.map(f => f -> getGenotypeField(samples, f)).toMap,
"info" -> infoFields.map(f => f -> getField(f, contig)).toMap, "info" -> infoFields.map(f => f -> getField(f)).toMap,
"sample_distributions" -> sampleDistributions "sample_distributions" -> sampleDistributions
.map(f => f -> getField("SampleDistribution-" + f, contig)) .map(f => f -> getField("SampleDistribution-" + f))
.toMap .toMap
) ++ (if (contig == "total") ) ++ Map(
Map(
"sample_compare" -> Map( "sample_compare" -> Map(
"samples" -> samples, "samples" -> samples,
"genotype_overlap" -> samples.map(sample1 => "genotype_overlap" -> samples.map(sample1 =>
...@@ -176,29 +160,21 @@ case class Stats(generalStats: mutable.Map[String, mutable.Map[String, mutable.M ...@@ -176,29 +160,21 @@ case class Stats(generalStats: mutable.Map[String, mutable.Map[String, mutable.M
samplesStats(sample1).sampleToSample(sample2).alleleOverlap)) samplesStats(sample1).sampleToSample(sample2).alleleOverlap))
) )
) )
else Map())
} }
/** This will generate stats for total */ def writeToFile(outputFile: File,
def getTotalStats(samples: List[String],
genotypeFields: List[String] = Nil,
infoFields: List[String] = Nil,
sampleDistributions: List[String] = Nil): Map[String, Any] =
getContigStats("total", samples, genotypeFields, infoFields, sampleDistributions)
/** This will generate stats for total and contigs separated */
def getAllStats(contigs: List[String],
samples: List[String], samples: List[String],
genotypeFields: List[String] = Nil, genotypeFields: List[String] = Nil,
infoFields: List[String] = Nil, infoFields: List[String] = Nil,
sampleDistributions: List[String] = Nil): Map[String, Any] = { sampleDistributions: List[String] = Nil): Unit = {
Map( val allWriter = new PrintWriter(outputFile)
"contigs" -> contigs val json = ConfigUtils.mapToJson(
.map(c => c -> getContigStats(c, samples, genotypeFields, infoFields, sampleDistributions)) this.getStatsAsMap(samples, genotypeFields, infoFields, sampleDistributions))
.toMap, allWriter.println(json.nospaces)
"total" -> getTotalStats(samples, genotypeFields, infoFields, sampleDistributions) allWriter.close()
)
} }
} }
object Stats { object Stats {
...@@ -222,17 +198,15 @@ object Stats { ...@@ -222,17 +198,15 @@ object Stats {
} }
/** Merge m2 into m1 */ /** Merge m2 into m1 */
def mergeNestedStatsMap(m1: mutable.Map[String, mutable.Map[String, mutable.Map[Any, Int]]], def mergeNestedStatsMap(m1: mutable.Map[String, mutable.Map[Any, Int]],
m2: Map[String, Map[String, Map[Any, Int]]]): Unit = { m2: Map[String, Map[Any, Int]]): Unit = {
for ((chr, chrMap) <- m2; (field, fieldMap) <- chrMap) { for ((field, fieldMap) <- m2) {
if (m1.contains(chr)) { if (m1.contains(field)) {
if (m1(chr).contains(field)) { for ((key, value) <- fieldMap) {
for ((key, value) <- fieldMap) { if (m1(field).contains(key)) m1(field)(key) += value
if (m1(chr)(field).contains(key)) m1(chr)(field)(key) += value else m1(field)(key) = value
else m1(chr)(field)(key) = value }
} } else m1(field) = mutable.Map(fieldMap.toList: _*)
} else m1(chr)(field) = mutable.Map(fieldMap.toList: _*)
} else m1(chr) = mutable.Map(field -> mutable.Map(fieldMap.toList: _*))
} }
} }
} }
...@@ -6,7 +6,7 @@ import java.net.URLClassLoader ...@@ -6,7 +6,7 @@ import java.net.URLClassLoader
import htsjdk.variant.variantcontext.{Genotype, VariantContext} import htsjdk.variant.variantcontext.{Genotype, VariantContext}
import htsjdk.variant.vcf.VCFFileReader import htsjdk.variant.vcf.VCFFileReader
import nl.lumc.sasc.biopet.utils.intervals.{BedRecord, BedRecordList} import nl.lumc.sasc.biopet.utils.intervals.{BedRecord, BedRecordList}
import nl.lumc.sasc.biopet.utils.{ConfigUtils, ToolCommand, VcfUtils} import nl.lumc.sasc.biopet.utils.{ToolCommand, VcfUtils}
import org.apache.spark.{SparkConf, SparkContext} import org.apache.spark.{SparkConf, SparkContext}
import scala.collection.JavaConversions._ import scala.collection.JavaConversions._
...@@ -83,13 +83,7 @@ object VcfStats extends ToolCommand { ...@@ -83,13 +83,7 @@ object VcfStats extends ToolCommand {
val totalStats = regionStats.reduce(_ += _) val totalStats = regionStats.reduce(_ += _)
val allWriter = new PrintWriter(new File(cmdArgs.outputDir, "stats.json")) totalStats.writeToFile(new File(cmdArgs.outputDir, "stats.json"), samples, adGenotypeTags, adInfoTags, sampleDistributions)
val json = ConfigUtils.mapToJson(
totalStats.getAllStats(contigs, samples, adGenotypeTags, adInfoTags, sampleDistributions))
allWriter.println(json.nospaces)
allWriter.close()
//TODO: write wig files
writeOverlap(totalStats, writeOverlap(totalStats,
_.genotypeOverlap, _.genotypeOverlap,
...@@ -240,7 +234,7 @@ object VcfStats extends ToolCommand { ...@@ -240,7 +234,7 @@ object VcfStats extends ToolCommand {
protected[tools] def checkGenotype( protected[tools] def checkGenotype(
record: VariantContext, record: VariantContext,
genotype: Genotype, genotype: Genotype,
additionalTags: List[String]): Map[String, Map[String, Map[Any, Int]]] = { additionalTags: List[String]): Map[String, Map[Any, Int]] = {
val buffer = mutable.Map[String, Map[Any, Int]]() val buffer = mutable.Map[String, Map[Any, Int]]()
def addToBuffer(key: String, value: Any, found: Boolean): Unit = { def addToBuffer(key: String, value: Any, found: Boolean): Unit = {
...@@ -288,13 +282,13 @@ object VcfStats extends ToolCommand { ...@@ -288,13 +282,13 @@ object VcfStats extends ToolCommand {
else addToBuffer(tag, value, found = true) else addToBuffer(tag, value, found = true)
} }
Map(record.getContig -> buffer.toMap, "total" -> buffer.toMap) buffer.toMap
} }
/** Function to check all general stats, all info expect sample/genotype specific stats */ /** Function to check all general stats, all info expect sample/genotype specific stats */
protected[tools] def checkGeneral( protected[tools] def checkGeneral(
record: VariantContext, record: VariantContext,
additionalTags: List[String]): Map[String, Map[String, Map[Any, Int]]] = { additionalTags: List[String]): Map[String, Map[Any, Int]] = {
val buffer = mutable.Map[String, Map[Any, Int]]() val buffer = mutable.Map[String, Map[Any, Int]]()
def addToBuffer(key: String, value: Any, found: Boolean): Unit = { def addToBuffer(key: String, value: Any, found: Boolean): Unit = {
...@@ -371,11 +365,11 @@ object VcfStats extends ToolCommand { ...@@ -371,11 +365,11 @@ object VcfStats extends ToolCommand {
else addToBuffer(tag, value, found = true) else addToBuffer(tag, value, found = true)
} }
Map(record.getContig -> buffer.toMap, "total" -> buffer.toMap) buffer.toMap
} }
protected[tools] def fillGeneral( protected[tools] def fillGeneral(
additionalTags: List[String]): Map[String, Map[String, Map[Any, Int]]] = { additionalTags: List[String]): Map[String, Map[Any, Int]] = {
val buffer = mutable.Map[String, Map[Any, Int]]() val buffer = mutable.Map[String, Map[Any, Int]]()
def addToBuffer(key: String, value: Any, found: Boolean): Unit = { def addToBuffer(key: String, value: Any, found: Boolean): Unit = {
...@@ -425,11 +419,11 @@ object VcfStats extends ToolCommand { ...@@ -425,11 +419,11 @@ object VcfStats extends ToolCommand {
addToBuffer(tag, "not set", found = false) addToBuffer(tag, "not set", found = false)
} }
Map("total" -> buffer.toMap) buffer.toMap
} }
protected[tools] def fillGenotype( protected[tools] def fillGenotype(
additionalTags: List[String]): Map[String, Map[String, Map[Any, Int]]] = { additionalTags: List[String]): Map[String, Map[Any, Int]] = {
val buffer = mutable.Map[String, Map[Any, Int]]() val buffer = mutable.Map[String, Map[Any, Int]]()
def addToBuffer(key: String, value: Any, found: Boolean): Unit = { def addToBuffer(key: String, value: Any, found: Boolean): Unit = {
...@@ -461,6 +455,6 @@ object VcfStats extends ToolCommand { ...@@ -461,6 +455,6 @@ object VcfStats extends ToolCommand {
addToBuffer(tag, 0, found = false) addToBuffer(tag, 0, found = false)
} }
Map("total" -> buffer.toMap) buffer.toMap
} }
} }
...@@ -82,19 +82,14 @@ class VcfStatsTest extends TestNGSuite with Matchers { ...@@ -82,19 +82,14 @@ class VcfStatsTest extends TestNGSuite with Matchers {
s1.sampleToSample("s1").alleleOverlap = 1 s1.sampleToSample("s1").alleleOverlap = 1
s2.sampleToSample("s2").alleleOverlap = 2 s2.sampleToSample("s2").alleleOverlap = 2
val bla1 = s1.genotypeStats s1.genotypeStats += "1" -> mutable.Map(1 -> 1)
.getOrElse("chr", mutable.Map[String, mutable.Map[Any, Int]]()) += "1" -> mutable.Map(1 -> 1) s2.genotypeStats += "2" -> mutable.Map(2 -> 2)
s1.genotypeStats += "chr" -> bla1
val bla2 = s2.genotypeStats
.getOrElse("chr", mutable.Map[String, mutable.Map[Any, Int]]()) += "2" -> mutable.Map(2 -> 2)
s2.genotypeStats += "chr" -> bla2
val ss1 = SampleToSampleStats() val ss1 = SampleToSampleStats()
val ss2 = SampleToSampleStats() val ss2 = SampleToSampleStats()
s1 += s2 s1 += s2
s1.genotypeStats s1.genotypeStats shouldBe mutable.Map(
.getOrElse("chr", mutable.Map[String, mutable.Map[Any, Int]]()) shouldBe mutable.Map(
"1" -> mutable.Map(1 -> 1), "1" -> mutable.Map(1 -> 1),
"2" -> mutable.Map(2 -> 2)) "2" -> mutable.Map(2 -> 2))
ss1.alleleOverlap = 1 ss1.alleleOverlap = 1
...@@ -102,14 +97,12 @@ class VcfStatsTest extends TestNGSuite with Matchers { ...@@ -102,14 +97,12 @@ class VcfStatsTest extends TestNGSuite with Matchers {
s1.sampleToSample shouldBe mutable.Map("s1" -> ss1, "s2" -> ss2) s1.sampleToSample shouldBe mutable.Map("s1" -> ss1, "s2" -> ss2)
s1 += s2 s1 += s2
s1.genotypeStats s1.genotypeStats shouldBe mutable.Map(
.getOrElse("chr", mutable.Map[String, mutable.Map[Any, Int]]()) shouldBe mutable.Map(
"1" -> mutable.Map(1 -> 1), "1" -> mutable.Map(1 -> 1),
"2" -> mutable.Map(2 -> 4)) "2" -> mutable.Map(2 -> 4))
s1 += s1 s1 += s1
s1.genotypeStats s1.genotypeStats shouldBe mutable.Map(
.getOrElse("chr", mutable.Map[String, mutable.Map[Any, Int]]()) shouldBe mutable.Map(
"1" -> mutable.Map(1 -> 2), "1" -> mutable.Map(1 -> 2),
"2" -> mutable.Map(2 -> 8)) "2" -> mutable.Map(2 -> 8))
} }
...@@ -137,50 +130,22 @@ class VcfStatsTest extends TestNGSuite with Matchers { ...@@ -137,50 +130,22 @@ class VcfStatsTest extends TestNGSuite with Matchers {
@Test @Test
def testMergeNestedStatsMap(): Unit = { def testMergeNestedStatsMap(): Unit = {
val m1: mutable.Map[String, mutable.Map[String, mutable.Map[Any, Int]]] = mutable.Map( val m1: mutable.Map[String, mutable.Map[Any, Int]] = mutable.Map("nested" -> mutable.Map("a" -> 1))
"test" -> val m2: Map[String, Map[Any, Int]] = Map("nested" -> Map("b" -> 2))
mutable.Map("nested" -> mutable.Map("a" -> 1)))
val m2: Map[String, Map[String, Map[Any, Int]]] = Map(
"test" ->
Map("nested" -> Map("b" -> 2)))
Stats.mergeNestedStatsMap(m1, m2) Stats.mergeNestedStatsMap(m1, m2)
m1 should equal( m1 should equal(
mutable.Map("test" -> mutable.Map("nested" -> mutable.Map("a" -> 1, "b" -> 2)))) mutable.Map("nested" -> mutable.Map("a" -> 1, "b" -> 2)))
val m3: mutable.Map[String, mutable.Map[String, mutable.Map[Any, Int]]] = mutable.Map( val m3: mutable.Map[String, mutable.Map[Any, Int]] = mutable.Map("nestedd" -> mutable.Map(1 -> 500))
"test" -> val m4: Map[String, Map[Any, Int]] = Map("nestedd" -> Map(6 -> 125))
mutable.Map("nestedd" -> mutable.Map(1 -> 500)))
val m4: Map[String, Map[String, Map[Any, Int]]] = Map(
"test" ->
Map("nestedd" -> Map(6 -> 125)))
Stats.mergeNestedStatsMap(m3, m4) Stats.mergeNestedStatsMap(m3, m4)
m3 should equal( m3 should equal(mutable.Map("nestedd" -> mutable.Map(1 -> 500, 6 -> 125)))
mutable.Map("test" -> mutable.Map("nestedd" -> mutable.Map(1 -> 500, 6 -> 125))))
val m5 = m3.toMap.map(x => x._1 -> x._2.toMap.map(y => y._1 -> y._2.toMap))
Stats.mergeNestedStatsMap(m1, m5)
m1 should equal(
mutable.Map("test" -> mutable.Map("nested" -> mutable.Map("a" -> 1, "b" -> 2),
"nestedd" -> mutable.Map(1 -> 500, 6 -> 125))))