diff --git a/sessl-james/src/main/scala/sessl/james/Report.scala b/sessl-james/src/main/scala/sessl/james/Report.scala index ac5e79f..08ee7e0 100644 --- a/sessl-james/src/main/scala/sessl/james/Report.scala +++ b/sessl-james/src/main/scala/sessl/james/Report.scala @@ -107,10 +107,10 @@ trait Report extends AbstractReport { case v: ScatterPlotView => new ScatterPlotDataView(to2DJavaDoubleArray(v.xData, v.yData), v.caption, v.title, Array[String](v.xLabel, v.yLabel)) case v: HistogramView => new HistogramDataView(toDoubleArray(v.data), v.caption, v.title, v.xLabel, v.yLabel) - case v: BoxPlotView => new BoxPlotDataView(to2DJavaDoubleArray(v.data.map(_._2): _*), - v.caption, v.title, Array(v.xLabel, v.yLabel), Array(v.data.map(x => x._1): _*)) - case v: LinePlotView => new LineChartDataView(to2DJavaDoubleArray(v.data.map(_._2): _*), - v.caption, v.title, Array(v.xLabel, v.yLabel), Array(v.data.map(x => x._1).tail: _*)) + case v: BoxPlotView => new BoxPlotDataView(to2DJavaDoubleArray(v.data.toSeq.map(_._2): _*), + v.caption, v.title, Array(v.xLabel, v.yLabel), Array(v.data.toSeq.map(x => x._1): _*)) + case v: LinePlotView => new LineChartDataView(to2DJavaDoubleArray(v.data.toSeq.map(_._2): _*), + v.caption, v.title, Array(v.xLabel, v.yLabel), Array(v.data.toSeq.map(x => x._1).tail: _*)) case v: StatisticalTestView => val dataPair = new org.jamesii.core.util.misc.Pair[Array[java.lang.Double], Array[java.lang.Double]](toDoubleArray(v.firstData._2), toDoubleArray(v.secondData._2)) new StatisticalTestDataView(dataPair, v.caption, v.firstData._1, v.secondData._1, true, true, StatisticalTestDefinition.KOLMOGOROV_SMIRNOV) diff --git a/sessl-james/src/test/scala/tests/sessl/james/TestReport.scala b/sessl-james/src/test/scala/tests/sessl/james/TestReport.scala index 0d298a3..0721e5b 100644 --- a/sessl-james/src/test/scala/tests/sessl/james/TestReport.scala +++ b/sessl-james/src/test/scala/tests/sessl/james/TestReport.scala @@ -78,7 +78,7 @@ import org.junit.Assert._ val files = new File(exp.reportName).list.toSet assertTrue("The directory for raw data, the auxiliary plotting methods, and the report itself should be there", files("raw") && files("plotting.R") && files("report.Rtex")) val dataFiles = rawDataDir.listFiles - assertTrue("There should be 28 files containing the raw data, and none of them should be empty.", dataFiles.length == 28 && dataFiles.forall(_.length > 0)) + assertEquals("There should be non-empty raw data files", 28, dataFiles.filter(_.length > 0).length) } } diff --git a/sessl/src/main/scala/sessl/AbstractReport.scala b/sessl/src/main/scala/sessl/AbstractReport.scala index d5c0e92..719fcdf 100644 --- a/sessl/src/main/scala/sessl/AbstractReport.scala +++ b/sessl/src/main/scala/sessl/AbstractReport.scala @@ -147,9 +147,9 @@ trait AbstractReport extends ExperimentConfiguration { } /** Converts data items to a common format that can be used for line plots. */ - private[this] def convertToLinePlotData(data: Iterable[Any]): List[(String, List[_])] = data.head match { + private[this] def convertToLinePlotData(data: Iterable[Any]): Seq[(String, Iterable[_])] = data.head match { case tuple: (_, _) => ("Time", tuple._2.asInstanceOf[Trajectory].map(_._1)) :: data.toList.flatMap(toNamedList) - case trajectory: List[_] => ("Time", trajectory.asInstanceOf[Trajectory].map(_._1)) :: data.toList.flatMap(toNamedList) + case trajectory: Iterable[_] => ("Time", trajectory.asInstanceOf[Trajectory].map(_._1)) :: data.toList.flatMap(toNamedList) case _ => data.toList.flatMap(toNamedList) } @@ -175,22 +175,22 @@ trait AbstractReport extends ExperimentConfiguration { */ def reportTable(data: Any*)(caption: String = "") = { val namedData = data.flatMap(toNamedList) - val tableData = namedData.map(x => x._1 :: x._2.map(_.toString)) - currentSection.childs += TableView(tableData.toList, caption, currentSection) + val tableData = namedData.map(x => x._1 :: x._2.map(_.toString).toList) + currentSection.childs += TableView(tableData, caption, currentSection) } /** Converts an object of a suitable type into a tuple (name, list of values)*/ - private[this] def toNamedList(data: Any): Seq[(String, List[_])] = { + private[this] def toNamedList(data: Any): Seq[(String, Iterable[_])] = { data match { //Because of type erasure, we have to match the types of the list content separately - case tuple: (_, _) => tuple._2.asInstanceOf[List[_]].head match { + case tuple: (_, _) => tuple._2.asInstanceOf[Iterable[_]].head match { case t: (_, _) => Seq((tuple._1.toString, tuple._2.asInstanceOf[Trajectory].map(_._2))) - case _ => Seq((tuple._1.toString, tuple._2.asInstanceOf[List[_]])) + case _ => Seq((tuple._1.toString, tuple._2.asInstanceOf[Iterable[_]])) } case seq: Seq[_] => seq.head match { - case t: (_, _) => seq.asInstanceOf[Seq[(_, List[Double])]].map(tuple => (tuple._1.toString, tuple._2)) - case nestedSeq: Seq[_] => seq.asInstanceOf[Seq[Seq[Double]]].map(rawData => ("", rawData.toList)) - case n: Number => Seq(("", seq.asInstanceOf[Seq[Number]].map(_.doubleValue()).toList)) + case t: (_, _) => seq.asInstanceOf[Seq[(_, Iterable[Double])]].map(tuple => (tuple._1.toString, tuple._2)) + case nestedSeq: Seq[_] => seq.asInstanceOf[Seq[Iterable[_]]].map(rawData => ("", rawData)) + case n: Number => Seq(("", seq.asInstanceOf[Iterable[Number]].map(_.doubleValue()).toList)) } case _ => throw new IllegalArgumentException("Entity '" + data + "' cannot be converted to a tuple (name, list of values).") } @@ -205,7 +205,7 @@ trait AbstractReport extends ExperimentConfiguration { protected def topmostElements = rootSection.children /** Checks whether the elements in the list are numeric. */ - private def dataIsNumeric(values: List[_]): Boolean = { + private def dataIsNumeric(values: Iterable[_]): Boolean = { val typesOK = typesConform(classOf[Number], values) if (!typesOK) logger.warn("Some elements to be plotted are not numbers, hence this plot view is skipped: " + values) @@ -213,10 +213,10 @@ trait AbstractReport extends ExperimentConfiguration { } /** Checks whether the elements in all given lists are numeric. */ - private def dataAreNumeric(data: List[_]*): Boolean = data.forall(dataIsNumeric) + private def dataAreNumeric(data: Iterable[_]*): Boolean = data.forall(dataIsNumeric) /** Converts a list of Any into a list of Double.*/ - private def toDoubleList(values: List[_]) = values.asInstanceOf[List[Number]].map(_.doubleValue()) + private def toDoubleList(values: Iterable[_]) = values.asInstanceOf[Iterable[Number]].map(_.doubleValue()).toSeq /** Needs to be realized by concrete implementations*/ def generateReport(results: ExperimentResults): Unit @@ -251,19 +251,19 @@ protected case class ReportSectionNode(name: String, description: String, parent trait DataView extends ReportNode /** Display a scatter plot. */ -case class ScatterPlotView(xData: List[Double], yData: List[Double], title: String, caption: String, xLabel: String, yLabel: String, parent: ReportSection) extends DataView +case class ScatterPlotView(xData: Iterable[Double], yData: Iterable[Double], title: String, caption: String, xLabel: String, yLabel: String, parent: ReportSection) extends DataView /** Display a histogram. */ -case class HistogramView(data: List[Double], title: String, caption: String, xLabel: String, yLabel: String, parent: ReportSection) extends DataView +case class HistogramView(data: Iterable[Double], title: String, caption: String, xLabel: String, yLabel: String, parent: ReportSection) extends DataView /** Display a box plot. */ -case class BoxPlotView(data: List[(String, List[Double])], title: String, caption: String, xLabel: String, yLabel: String, parent: ReportSection) extends DataView +case class BoxPlotView(data: Iterable[(String, Iterable[Double])], title: String, caption: String, xLabel: String, yLabel: String, parent: ReportSection) extends DataView /** Display a line plot. */ -case class LinePlotView(data: List[(String, List[Double])], title: String, caption: String, xLabel: String, yLabel: String, parent: ReportSection) extends DataView +case class LinePlotView(data: Iterable[(String, Iterable[Double])], title: String, caption: String, xLabel: String, yLabel: String, parent: ReportSection) extends DataView /** Display the results of a statistical test. */ -case class StatisticalTestView(firstData: (String, List[Double]), secondData: (String, List[Double]), caption: String, testMethod: Option[TwoPairedStatisticalTest], parent: ReportSection) extends DataView +case class StatisticalTestView(firstData: (String, Iterable[Double]), secondData: (String, Iterable[Double]), caption: String, testMethod: Option[TwoPairedStatisticalTest], parent: ReportSection) extends DataView /** Display the results in a table. */ -case class TableView(data: List[List[String]], caption: String, parent: ReportSection) extends DataView +case class TableView(data: Seq[Seq[String]], caption: String, parent: ReportSection) extends DataView diff --git a/sessl/src/main/scala/sessl/util/MiscUtils.scala b/sessl/src/main/scala/sessl/util/MiscUtils.scala index 27a779b..2e44263 100644 --- a/sessl/src/main/scala/sessl/util/MiscUtils.scala +++ b/sessl/src/main/scala/sessl/util/MiscUtils.scala @@ -66,7 +66,7 @@ object MiscUtils extends Logging { * the values * @return true, if all elements in the sequence are of this kind */ - def typesConform(clazz: java.lang.Class[_], values: Seq[Any]): Boolean = + def typesConform(clazz: java.lang.Class[_], values: Iterable[Any]): Boolean = filterByConformantType(clazz, values).isEmpty /** Filters a list by the type of its elements. @@ -87,7 +87,7 @@ object MiscUtils extends Logging { * the values * @return the sequence of elements with non-conforming types */ - def filterByConformantType(clazz: java.lang.Class[_], values: Seq[Any]) = values.filter(x => !clazz.isAssignableFrom(x.getClass)) + def filterByConformantType(clazz: java.lang.Class[_], values: Iterable[Any]) = values.filter(x => !clazz.isAssignableFrom(x.getClass)) /** Gets the value or, if it is empty, gets default instead. * diff --git a/sessl/src/main/scala/sessl/util/ScalaToJava.scala b/sessl/src/main/scala/sessl/util/ScalaToJava.scala index 4261ed8..45fb15a 100644 --- a/sessl/src/main/scala/sessl/util/ScalaToJava.scala +++ b/sessl/src/main/scala/sessl/util/ScalaToJava.scala @@ -53,10 +53,9 @@ object ScalaToJava { def toDoubleArray(values: Iterable[Double]): Array[java.lang.Double] = values.map(_.asInstanceOf[java.lang.Double]).toArray /** Convert list to (transposed) nested array. */ - def to2DTransposedJavaStringArray(valueLists: List[String]*): Array[Array[java.lang.String]] = { + def to2DTransposedJavaStringArray(valueLists: Seq[String]*): Array[Array[java.lang.String]] = { if (valueLists.length == 0) return Array.ofDim(0) - val rv: Array[Array[java.lang.String]] = Array.ofDim(valueLists.head.length) for (i <- valueLists.head.indices) rv(i) = Array.ofDim(valueLists.length) @@ -66,7 +65,7 @@ object ScalaToJava { } /** Convert list to nested array. */ - def to2DJavaDoubleArray(valueLists: List[Double]*) = { + def to2DJavaDoubleArray(valueLists: Iterable[Double]*) = { val rv: Array[Array[java.lang.Double]] = Array.ofDim(valueLists.length) for (i <- valueLists.indices) rv(i) = toDoubleArray(valueLists(i))