Add Jupyter integration

This commit is contained in:
Iaroslav Postovalov 2021-03-31 19:39:34 +07:00
parent 72d91b04da
commit 77d72c7bf6
No known key found for this signature in database
GPG Key ID: 46E15E4A31B3BCD7
8 changed files with 154 additions and 3 deletions

View File

@ -11,6 +11,7 @@
- Multiplatform integration
- Integration for any Field element
- Extended operations for ND4J fields
- Jupyter Notebook integration module (kmath-jupyter)
### Changed
- Exponential operations merged with hyperbolic functions

View File

@ -1,5 +1,6 @@
plugins {
id("ru.mipt.npm.gradle.project")
kotlin("jupyter.api") apply false
}
allprojects {

View File

@ -18,11 +18,14 @@ import space.kscience.kmath.misc.UnstableKMathAPI
public object MathMLSyntaxRenderer : SyntaxRenderer {
public override fun render(node: MathSyntax, output: Appendable) {
output.append("<math xmlns=\"https://www.w3.org/1998/Math/MathML\"><mrow>")
render0(node, output)
renderPart(node, output)
output.append("</mrow></math>")
}
private fun render0(node: MathSyntax, output: Appendable): Unit = output.run {
/**
* Renders a part of syntax returning a correct MathML tag not the whole MathML instance.
*/
public fun renderPart(node: MathSyntax, output: Appendable): Unit = output.run {
fun tag(tagName: String, vararg attr: Pair<String, String>, block: () -> Unit = {}) {
append('<')
append(tagName)
@ -47,7 +50,7 @@ public object MathMLSyntaxRenderer : SyntaxRenderer {
append('>')
}
fun render(syntax: MathSyntax) = render0(syntax, output)
fun render(syntax: MathSyntax) = renderPart(syntax, output)
when (node) {
is NumberSyntax -> tag("mn") { append(node.string) }

View File

@ -272,6 +272,8 @@ public final class space/kscience/kmath/expressions/MstExtendedField : space/ksc
public fun sin (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary;
public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object;
public fun sinh (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary;
public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object;
public fun sqrt (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST;
public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object;
public fun tan (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary;
public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object;

View File

@ -135,6 +135,7 @@ public object MstExtendedField : ExtendedField<MST>, NumericAlgebra<MST> {
public override fun acosh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.ACOSH_OPERATION)(arg)
public override fun atanh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.ATANH_OPERATION)(arg)
public override fun add(a: MST, b: MST): MST.Binary = MstField.add(a, b)
public override fun sqrt(arg: MST): MST = unaryOperationFunction(PowerOperations.SQRT_OPERATION)(arg)
public override fun scale(a: MST, value: Double): MST =
binaryOperation(GroupOperations.PLUS_OPERATION, a, number(value))

View File

@ -0,0 +1,19 @@
plugins {
id("ru.mipt.npm.gradle.jvm")
kotlin("jupyter.api")
}
dependencies {
api(project(":kmath-ast"))
api(project(":kmath-complex"))
api(project(":kmath-for-real"))
implementation("org.jetbrains.kotlinx:kotlinx-html-jvm:0.7.3")
}
readme {
maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE
}
kotlin.sourceSets.all {
languageSettings.useExperimentalAnnotation("space.kscience.kmath.misc.UnstableKMathAPI")
}

View File

@ -0,0 +1,120 @@
package space.kscience.kmath.jupyter
import kotlinx.html.Unsafe
import kotlinx.html.div
import kotlinx.html.stream.createHTML
import kotlinx.html.unsafe
import org.jetbrains.kotlinx.jupyter.api.DisplayResult
import org.jetbrains.kotlinx.jupyter.api.HTML
import org.jetbrains.kotlinx.jupyter.api.annotations.JupyterLibrary
import org.jetbrains.kotlinx.jupyter.api.libraries.JupyterIntegration
import space.kscience.kmath.expressions.MST
import space.kscience.kmath.ast.rendering.FeaturedMathRendererWithPostProcess
import space.kscience.kmath.ast.rendering.MathMLSyntaxRenderer
import space.kscience.kmath.ast.rendering.renderWithStringBuilder
import space.kscience.kmath.complex.Complex
import space.kscience.kmath.nd.Structure2D
import space.kscience.kmath.operations.GroupOperations
import space.kscience.kmath.operations.RingOperations
import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.asSequence
@JupyterLibrary
internal class KMathJupyter : JupyterIntegration() {
private val mathRender = FeaturedMathRendererWithPostProcess.Default
private val syntaxRender = MathMLSyntaxRenderer
override fun Builder.onLoaded() {
import(
"space.kscience.kmath.ast.*",
"space.kscience.kmath.ast.rendering.*",
"space.kscience.kmath.operations.*",
"space.kscience.kmath.expressions.*",
"space.kscience.kmath.misc.*",
"space.kscience.kmath.real.*",
)
fun MST.toDisplayResult(): DisplayResult = HTML(createHTML().div {
unsafe {
+syntaxRender.renderWithStringBuilder(mathRender.render(this@toDisplayResult))
}
})
render<MST> { it.toDisplayResult() }
render<Number> { MST.Numeric(it).toDisplayResult() }
fun Unsafe.appendCellValue(it: Any?) {
when (it) {
is Number -> {
val s = StringBuilder()
syntaxRender.renderPart(mathRender.render(MST.Numeric(it)), s)
+s.toString()
}
is MST -> {
val s = StringBuilder()
syntaxRender.renderPart(mathRender.render(it), s)
+s.toString()
}
else -> {
+"<ms>"
+it.toString()
+"</ms>"
}
}
}
render<Structure2D<*>> { structure ->
HTML(createHTML().div {
unsafe {
+"<math xmlns=\"https://www.w3.org/1998/Math/MathML\">"
+"<mrow>"
+"<mfenced open=\"[\" close=\"]\" separators=\"\">"
+"<mtable>"
structure.rows.forEach { row ->
+"<mtr>"
row.asSequence().forEach {
+"<mtd>"
appendCellValue(it)
+"</mtd>"
}
+"</mtr>"
}
+"</mtable>"
+"</mfenced>"
+"</mrow>"
+"</math>"
}
})
}
render<Buffer<*>> { buffer ->
HTML(createHTML().div {
unsafe {
+"<math xmlns=\"https://www.w3.org/1998/Math/MathML\">"
+"<mrow>"
+"<mfenced open=\"[\" close=\"]\" separators=\"\">"
+"<mtable>"
buffer.asSequence().forEach {
+"<mtr>"
+"<mtd>"
appendCellValue(it)
+"</mtd>"
+"</mtr>"
}
+"</mtable>"
+"</mfenced>"
+"</mrow>"
+"</math>"
}
})
}
render<Complex> {
MST.Binary(
operation = GroupOperations.PLUS_OPERATION,
left = MST.Numeric(it.re),
right = MST.Binary(RingOperations.TIMES_OPERATION, MST.Numeric(it.im), MST.Symbolic("i")),
).toDisplayResult()
}
}
}

View File

@ -17,6 +17,9 @@ pluginManagement {
id("ru.mipt.npm.gradle.project") version toolsVersion
id("ru.mipt.npm.gradle.mpp") version toolsVersion
id("ru.mipt.npm.gradle.jvm") version toolsVersion
kotlin("jupyter.api") version "0.9.0.12"
kotlin("jvm") version kotlinVersion
kotlin("plugin.allopen") version kotlinVersion
}
}
@ -39,6 +42,7 @@ include(
":kmath-ast",
":kmath-ejml",
":kmath-kotlingrad",
":kmath-jupyter",
":examples",
":benchmarks"
)