Skip to content

Commit

Permalink
Scala 2.12 compatibility complete:
Browse files Browse the repository at this point in the history
  -- Added charts code to code base
  -- Removed scalaxy-streams
  -- Removed several un used dependencies

Signed-off-by: mandar2812 <mandar2812@gmail.com>
  • Loading branch information
mandar2812 committed Dec 18, 2018
1 parent 2decd0e commit ff3660e
Show file tree
Hide file tree
Showing 72 changed files with 3,825 additions and 188 deletions.
2 changes: 1 addition & 1 deletion build.sbt
Expand Up @@ -21,7 +21,7 @@ val baseSettings = Seq(
Resolver.sonatypeRepo("public"),
Resolver.sonatypeRepo("snapshots"),
Resolver.typesafeIvyRepo("releases")),
scalacOptions ++= Seq("-optimise", "-Yclosure-elim", "-Yinline", "-target:jvm-1.8"),
//scalacOptions ++= Seq("-optimise", "-Yclosure-elim", "-Yinline", "-target:jvm-1.8"),
publishTo := sonatypePublishTo.value,
useGpg := true
)
Expand Down
2 changes: 1 addition & 1 deletion conf/DynaMLInit.scala
Expand Up @@ -11,7 +11,7 @@ import org.apache.spark.SparkContext
import org.apache.spark.SparkConf
import org.apache.spark.rdd.RDD
//Load Wisp-Highcharts for plotting
import com.quantifind.charts.Highcharts._
import io.github.mandar2812.dynaml.graphics.charts.Highcharts._
//Import spire implicits for definition of
//fields, algebraic structures on primitive types
import spire.implicits._
Expand Down
@@ -0,0 +1,13 @@
package io.github.mandar2812.dynaml.utils.sumac;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Arg {
String name() default "";
String description() default "";
}
@@ -0,0 +1,10 @@
package io.github.mandar2812.dynaml.utils.sumac;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Ignore {}
@@ -0,0 +1,14 @@
package io.github.mandar2812.dynaml.utils.sumac.validation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Use this annotation on any string field that is both required and presents a valid file that exists
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface FileExists {}
@@ -0,0 +1,15 @@
package io.github.mandar2812.dynaml.utils.sumac.validation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Use this annotation on any arg-field which must have a positive (> 0) value to add an automatic validation function.
*
* It is meaningless if applied to a non-numeric field.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Positive {}
@@ -0,0 +1,16 @@
package io.github.mandar2812.dynaml.utils.sumac.validation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Range {
double min();
double max();
}
@@ -0,0 +1,18 @@
package io.github.mandar2812.dynaml.utils.sumac.validation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Use this annotation on any arg-field which must be given a value distinct from its "default" value. It will
* automatically add a validation function.
*
* Usually, the "default" value of a field is whatever the value is with a no-arg constructor. Note that this
* annotation does *not* just check that some argument was given. The argument must be distinct from the default
* value. This means that you should make the default value of the field something that is *invalid*.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Required {}
Expand Up @@ -36,7 +36,7 @@ import org.apache.spark.rdd.RDD
import org.renjin.script.RenjinScriptEngine
import org.renjin.sexp._

import scalaxy.streams.optimize
//import scalaxy.streams.optimize
import scala.reflect.ClassTag
import scala.util.Random

Expand Down Expand Up @@ -709,15 +709,9 @@ object DynaMLPipe {
* [[DenseVector]] instances into uniform splits and
* put them back together.
* */
val breezeDVSplitEncoder = (n: Int) => Encoder((v: DenseVector[Double]) => {
optimize {
Array.tabulate(v.length/n)(i => v(i*n until math.min((i+1)*n, v.length)))
}
}, (vs: Array[DenseVector[Double]]) => {
optimize {
DenseVector(vs.map(_.toArray).reduceLeft((a,b) => a++b))
}
})
val breezeDVSplitEncoder = (n: Int) => Encoder(
(v: DenseVector[Double]) => Array.tabulate(v.length/n)(i => v(i*n until math.min((i+1)*n, v.length))),
(vs: Array[DenseVector[Double]]) => DenseVector(vs.map(_.toArray).reduceLeft((a,b) => a++b)))

/**
* Creates an [[Encoder]] which replicates a
Expand Down
Expand Up @@ -21,7 +21,7 @@ package io.github.mandar2812.dynaml.evaluation
import breeze.linalg.DenseVector
import org.apache.log4j.{Priority, Logger}

import com.quantifind.charts.Highcharts._
import io.github.mandar2812.dynaml.graphics.charts.Highcharts._

/**
* Class implementing the calculation
Expand Down
Expand Up @@ -19,7 +19,7 @@ under the License.
package io.github.mandar2812.dynaml.evaluation

import breeze.linalg.DenseVector
import com.quantifind.charts.Highcharts._
import io.github.mandar2812.dynaml.graphics.charts.Highcharts._
import org.apache.log4j.{Priority, Logger}
import org.apache.spark.rdd.RDD

Expand Down
Expand Up @@ -22,7 +22,7 @@ import breeze.linalg.DenseVector
import breeze.numerics.{abs, log, sqrt}
import io.github.mandar2812.dynaml.utils
import org.apache.log4j.{Logger, Priority}
import com.quantifind.charts.Highcharts._
import io.github.mandar2812.dynaml.graphics.charts.Highcharts._
import io.github.mandar2812.dynaml.algebra.square

/**
Expand Down
Expand Up @@ -19,7 +19,7 @@ under the License.
package io.github.mandar2812.dynaml.evaluation

import breeze.linalg.DenseVector
import com.quantifind.charts.Highcharts._
import io.github.mandar2812.dynaml.graphics.charts.Highcharts._
import org.apache.log4j.{Priority, Logger}
import org.apache.spark.Accumulator
import org.apache.spark.broadcast.Broadcast
Expand Down
Expand Up @@ -18,7 +18,7 @@ under the License.
* */
package io.github.mandar2812.dynaml.evaluation

import com.quantifind.charts.Highcharts.{regression, title, xAxis, yAxis}
import io.github.mandar2812.dynaml.graphics.charts.Highcharts.{regression, title, xAxis, yAxis}
import io.github.mandar2812.dynaml.tensorflow.{dtf, dtfutils}
import org.platanios.tensorflow.api.{::, Tensor}

Expand Down
@@ -0,0 +1,208 @@
package io.github.mandar2812.dynaml.graphics.charts

import highcharts._
import repl._
import scala.collection.immutable.ListMap
import scala.language.implicitConversions

/**
* User: austin
* Date: 12/2/14
*
* Highcharts implementation of plotting functionality. Includes several highcharts specific plots
*
* I rely on the fact that an implicit method defined in an object takes precedence over one
* defined in a trait to have Iterable[T] with PartialFunction[Int, T] resolve to this method
*/

object Highcharts extends IterablePairLowerPriorityImplicits with BinnedDataLowerPriorityImplicits with HighchartsStyles {

implicit def mkStringIterableIterable[B: Numeric](ab: (Iterable[String], Iterable[B])) = new StringIterableIterable(ab._1, ab._2)
implicit def mkStringIterableIterable[B: Numeric](ab: (Iterable[(String, B)])) = new StringIterableIterable(ab.map(_._1), ab.map(_._2))

implicit def mkStringArrayArray[B: Numeric](ab: (Array[String], Array[B])) = new StringIterableIterable(ab._1.toSeq, ab._2.toSeq)
implicit def mkStringArrayArray[B: Numeric](ab: (Array[(String, B)])) = new StringIterableIterable(ab.map(_._1).toSeq, ab.map(_._2).toSeq)

implicit def mkIterableIterable[A: Numeric, B: Numeric](ab: (Iterable[A], Iterable[B])) = new IterableIterable(ab._1, ab._2)
implicit def mkIterableIterable[A: Numeric, B: Numeric](ab: (Iterable[(A, B)])) = new IterableIterable(ab.map(_._1), ab.map(_._2))
implicit def mkIterableIterable[B: Numeric](b: (Iterable[B])) = new IterableIterable((0 until b.size), b)

implicit def mkArrayArray[A: Numeric, B: Numeric](ab: (Array[A], Array[B])) = new IterableIterable(ab._1.toSeq, ab._2.toSeq)
implicit def mkArrayArray[A: Numeric, B: Numeric](ab: (Array[(A, B)])) = new IterableIterable(ab.map(_._1).toSeq, ab.map(_._2).toSeq)
implicit def mkArrayArray[B: Numeric](b: (Array[B])) = new IterableIterable((0 until b.size), b.toSeq)

implicit def mkArrayIterable[A: Numeric, B: Numeric](ab: (Array[A], Iterable[B])) = new IterableIterable(ab._1.toSeq, ab._2)
implicit def mkIterableArray[A: Numeric, B: Numeric](ab: (Iterable[A], Array[B])) = new IterableIterable(ab._1, ab._2.toSeq)

implicit def binIterableNumBins[A: Numeric](data: Iterable[A], numBins: Int): BinnedData = new IterableBinned[A](data, numBins)
implicit def mkPair[A, B: Numeric](data: Iterable[(A, B)]) = new PairBinned(data)
implicit def mkTrueTriplet[A, B, C: Numeric](data: Iterable[(A, B, C)]) = new TrueTripletBinned(data)
implicit def mkCoupledTriplet[A, B, C: Numeric](data: Iterable[((A, B), C)]) = new CoupledTripletBinned(data)

implicit def binIterableNumBins[A: Numeric](data: Array[A], numBins: Int): BinnedData = new IterableBinned[A](data.toSeq, numBins)
implicit def mkPair[A, B: Numeric](data: Array[(A, B)]) = new PairBinned(data.toSeq)
implicit def mkTrueTriplet[A, B, C: Numeric](data: Array[(A, B, C)]) = new TrueTripletBinned(data.toSeq)
implicit def mkCoupledTriplet[A, B, C: Numeric](data: Array[((A, B), C)]) = new CoupledTripletBinned(data.toSeq)

// for boxplot
def invalidSizeBoxPlot() = {
System.err.println("Warning: tried to create a boxplot from a list that wasn't size 5 - removing invalid elements")
}

implicit def mkBoxedDataBoxes[T: Numeric](data: Iterable[(T, T, T, T, T)]): Iterable[BoxplotData[T]] = {
data.map{case(low, q1, median, q3, high) => Data(low, q1, median, q3, high)}
}
implicit def mkBoxedDataXBoxes[T: Numeric](data: Iterable[(Any, T, T, T, T, T)]): Iterable[BoxplotData[T]] = {
data.map{case(x, low, q1, median, q3, high) => Data(x, low, q1, median, q3, high)}
}
implicit def mkBoxedDataIterable[T: Numeric](data: Iterable[Iterable[T]]): Iterable[BoxplotData[T]] = {
if(data.exists(_.size != 5)) invalidSizeBoxPlot()
data.filter(_.size == 5).map(_.toList).map{itr => Data(itr(0), itr(1), itr(2), itr(3), itr(4))}
}
implicit def mkBoxedDataArray[T: Numeric](data: Iterable[Array[T]]): Iterable[BoxplotData[T]] = {
if(data.exists(_.size != 5)) invalidSizeBoxPlot()
data.filter(_.size == 5).map{itr => Data(itr(0), itr(1), itr(2), itr(3), itr(4))}
}
implicit def mkBoxedDataXIterable[T: Numeric](data: Iterable[(Any, Iterable[T])]): Iterable[BoxplotData[T]] = {
if(data.exists(_._2.size != 5)) invalidSizeBoxPlot()
data.filter(_._2.size == 5).map{case(x, itr) => x -> itr.toList}.map{case(x, itr) => Data(x, itr(0), itr(1), itr(2), itr(3), itr(4))}
}
implicit def mkBoxedDataXArray[T: Numeric](data: Iterable[(Any, Array[T])]): Iterable[BoxplotData[T]] = {
if(data.exists(_._2.size != 5)) invalidSizeBoxPlot()
data.filter(_._2.size == 5).map{case(x, itr) => Data(x, itr(0), itr(1), itr(2), itr(3), itr(4))}
}

def stopServer = stopWispServer
def startServer() = startWispServer()
def setPort(port: Int) = setWispPort(port)

private def addStyle[A, B, C, D](hc: Highchart, xy: IterablePair[A, B, C, D]) = {
xy match {
case s: StringIterableIterable[_] => xAxisCategories(hc, s.getCategories)
case _ => hc
}
}

def area[A, B, C: Numeric, D: Numeric](xy: IterablePair[A, B, C, D]) = {
val (xr, yr) = xy.toIterables
val hc = xyToSeries(xr, yr, SeriesType.area)
plot(addStyle(hc, xy))
}

def areaspline[A, B, C: Numeric, D: Numeric](xy: IterablePair[A, B, C, D]) = {
val (xr, yr) = xy.toIterables
val hc = xyToSeries(xr, yr, SeriesType.areaspline)
plot(addStyle(hc, xy))
}

def bar[A, B, C: Numeric, D: Numeric](xy: IterablePair[A, B, C, D]) = {
val (xr, yr) = xy.toIterables
val hc = xyToSeries(xr, yr, SeriesType.bar)
plot(addStyle(hc, xy))
}

def boxplot[T: Numeric](data: Iterable[BoxplotData[T]]) = {
plot(Highchart(series = Seq(Series(data = data, chart = Some(SeriesType.boxplot)))))
}

def column[A, B, C: Numeric, D: Numeric](xy: IterablePair[A, B, C, D]) = {
val (xr, yr) = xy.toIterables
val hc = xyToSeries(xr, yr, SeriesType.column)
plot(addStyle(hc, xy))
}

def histogram[A: Numeric](data: Iterable[A], numBins: Int) = {
val binCounts = binIterableNumBins(data, numBins).toBinned().toSeq
plot(Histogram.histogram(binCounts))
}

def histogram(data: BinnedData) = {
val binCounts = data.toBinned().toSeq
plot(Histogram.histogram(binCounts))
}

def line[A, B, C: Numeric, D: Numeric](xy: IterablePair[A, B, C, D]) = {
val (xr, yr) = xy.toIterables
val hc = xyToSeries(xr, yr, SeriesType.line)
plot(addStyle(hc, xy))
}

def pie[A, B, C: Numeric, D: Numeric](xy: IterablePair[A, B, C, D]) = {
val (xr, yr) = xy.toIterables
val hc = xyToSeries(xr, yr, SeriesType.pie)
plot(addStyle(hc, xy))
}

def regression[A, B, C: Numeric, D: Numeric](xy: IterablePair[A, B, C, D]) = {
def numericToDouble[X](x: X)(implicit ev: Numeric[X]): Double = ev.toDouble(x)
val (xr, yr) = xy.toIterables
LeastSquareRegression.leastSquareRegression(xr.toSeq.map(numericToDouble(_)), yr.toSeq.map(numericToDouble(_)))
}

def scatter[A, B, C: Numeric, D: Numeric](xy: IterablePair[A, B, C, D]) = {
val (xr, yr) = xy.toIterables
val hc = xyToSeries(xr, yr, SeriesType.scatter)
plot(addStyle(hc, xy))
}

def spline[A, B, C: Numeric, D: Numeric](xy: IterablePair[A, B, C, D]) = {
val (xr, yr) = xy.toIterables
val hc = xyToSeries(xr, yr, SeriesType.spline)
plot(addStyle(hc, xy))
}

// Todo: can we disclose this information through reflection, instead of hardcoding it?
/**
* Output the basic usage of Highcharts
*/
def help(): Unit = {
println("\nAvailable Plot Types: Takes an Iterable, an Iterable of pairs, a pair of Iterables, or an Iterable and a Function\n")
Seq("area", "areaspline", "bar", "column", "line", "pie", "scatter", "spline", "regression")
.map(s => "\t" + s)
.foreach(println)
println("\nOther plotting options:\n")
Map(
"histogram" -> "Iterable of Numerics or Pairs",
"boxplot" -> "Collections of five Numerics : low, q1, median, q3, high"
)
.map{case(plot, description) =>"\t%-35s%s".format(plot, description)}
.foreach(println)
println("\nStylistic changes:\n")
ListMap(
List("hold") -> "plots the next plot on top of the existing plot",
List("unhold") -> "plots the next plot in a new chart",
List("title(String)") -> "add a title to the most recent plot",
List("xAxis(String)") -> "adds a label to the x-axis",
List(
"xAxisType([",
""""linear", "logarithmic",""",
""""datetime", "category"""",
"])"
) -> "updates the x-axis type",
List("xAxisCategories(Iterable[String])") -> "create named labels for x-axis",
List("yAxis(String)") -> "adds a label to y-axis",
List(
"yAxisType([",
""""linear", "logarithmic",""",
""""datetime", "category"""",
"])"
) -> "updates the y-axis type",
List("yAxisCategories(Iterable[String])") -> "create named labels for y-axis",
List("legend(Iterable[String])") -> "adds a legend to the most recent plot",
List("""stack(["normal", "percent"])""") -> "stacks bars, columns, and lines relative to each other",
List("unstack") -> "remove stacking"
).foreach { case (methodLines, description) =>
println("\t%-35s%s".format(methodLines(0), description))
methodLines.slice(1, methodLines.length - 1).foreach(line => println("\t %s".format(line)))
methodLines.slice(1, methodLines.length).reverse.headOption.foreach(line => println("\t%s".format(line)))
}

println("\nServer Controls:\n")
ListMap(
"undo" -> "undoes the most recent action",
"redo" -> "the opposite of undo",
"delete" -> "wipes the most recent chart from the page",
"deleteAll" -> "wipes all plots from the page"
).foreach{case(method, description) => println("\t%-35s%s".format(method, description))}
}
}

0 comments on commit ff3660e

Please sign in to comment.