in core/src/main/scala/com/spotify/featran/transformers/Transformer.scala [50:99]
protected def checkRange(name: String, value: Double, lower: Double, upper: Double): Unit =
require(value >= lower && value <= upper, s"$name $value not in the range[$lower, $upper]")
/** Aggregator for computing input values into a summary. */
def aggregator: Aggregator[A, B, C]
/** Number of generated features given an aggregator summary. */
def featureDimension(c: C): Int
/** Names of the generated features given an aggregator summary. */
def featureNames(c: C): Seq[String]
/**
* Build features from a single input value and an aggregator summary.
* @param a
* input value
* @param c
* aggregator summary
* @param fb
* feature builder
*/
def buildFeatures(a: Option[A], c: C, fb: FeatureBuilder[_]): Unit
protected def nameAt(n: Int): String = name + '_' + n
@nowarn("cat=deprecation")
protected def names(n: Int): Stream[String] = (0 until n).toStream.map(nameAt)
/**
* Builds a new transformer with an extra input preprocessing step
* @param f
* input preprocessing function
*/
def contramap[AA](f: AA => A): Transformer[AA, B, C] = new Transformer[AA, B, C](name) {
override val aggregator: Aggregator[AA, B, C] = new Aggregator[AA, B, C] {
override def prepare(a: AA): B = self.aggregator.prepare(f(a))
override def semigroup = self.aggregator.semigroup
override def present(b: B): C = self.aggregator.present(b)
}
override def buildFeatures(a: Option[AA], c: C, fb: FeatureBuilder[_]): Unit =
self.buildFeatures(a.map(f), c, fb)
override def decodeAggregator(s: String): C = self.decodeAggregator(s)
override def encodeAggregator(c: C): String = self.encodeAggregator(c)
override def featureDimension(c: C): Int = self.featureDimension(c)
override def featureNames(c: C): Seq[String] = self.featureNames(c)
override def flatRead[T: FlatReader]: T => Option[Any] =
self.flatRead[T]
override def flatWriter[T](implicit fw: FlatWriter[T]): Option[AA] => fw.IF =
self.flatWriter[T].compose(x => x.map(f))
}