Refactor jupyter integratin

This commit is contained in:
Alexander Nozik 2023-07-19 22:25:32 +03:00
parent 04b4a12946
commit 8b25761dc6
28 changed files with 264 additions and 190 deletions

View File

@ -13,7 +13,7 @@ val fxVersion by extra("11")
allprojects {
group = "space.kscience"
version = "0.3.0-dev-10"
version = "0.3.0-dev-11"
}
subprojects {

View File

@ -47,12 +47,11 @@ kotlin {
val commonMain by getting {
dependencies {
implementation(projects.visionforgeSolid)
implementation(projects.visionforgeGdml)
implementation(projects.visionforgePlotly)
implementation(projects.visionforgeMarkdown)
implementation(projects.visionforgeTables)
implementation(projects.cernRootLoader)
implementation(projects.jupyter)
implementation(projects.visionforgeJupyter.visionforgeJupyterCommon)
}
}
@ -66,6 +65,8 @@ kotlin {
val jvmMain by getting {
dependencies {
implementation("io.ktor:ktor-server-cio:${spclibs.versions.ktor.get()}")
implementation(projects.visionforgeGdml)
implementation(projects.visionforgeServer)
implementation(spclibs.logback.classic)
implementation("com.github.Ricky12Awesome:json-schema-serialization:0.6.6")

View File

@ -0,0 +1,104 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"@file:Repository(\"*mavenLocal\")\n",
"@file:Repository(\"https://repo.kotlin.link\")\n",
"@file:Repository(\"https://maven.pkg.jetbrains.space/spc/p/sci/dev\")\n",
"@file:DependsOn(\"space.kscience:visionforge-jupyter-common-jvm:0.3.0-dev-11\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"outputs": [],
"source": [
":classpath"
],
"metadata": {
"collapsed": false
}
},
{
"cell_type": "code",
"execution_count": null,
"outputs": [],
"source": [
"vf.startServer()"
],
"metadata": {
"collapsed": false
}
},
{
"cell_type": "code",
"execution_count": null,
"outputs": [],
"source": [
"import space.kscience.visionforge.plotly.plotly\n",
"\n",
"vf.page {\n",
" h1 { +\"AAA\" }\n",
" vision {\n",
" solid {\n",
" ambientLight()\n",
" box(100, 100, 200)\n",
"\n",
" sphere(100) {\n",
" x = 300\n",
" }\n",
" }\n",
" }\n",
"\n",
" vision {\n",
" plotly {\n",
" scatter {\n",
" x(1, 2, 3, 1)\n",
" y(1, 2, 3, 4)\n",
" }\n",
" }\n",
" }\n",
"}"
],
"metadata": {
"collapsed": false
}
},
{
"cell_type": "code",
"execution_count": null,
"outputs": [],
"source": [],
"metadata": {
"collapsed": false
}
}
],
"metadata": {
"kernelspec": {
"display_name": "Kotlin",
"language": "kotlin",
"name": "kotlin"
},
"language_info": {
"name": "kotlin",
"version": "1.8.20",
"mimetype": "text/x-kotlin",
"file_extension": ".kt",
"pygments_lexer": "kotlin",
"codemirror_mode": "text/x-kotlin",
"nbconvert_exporter": ""
},
"ktnbPluginMetadata": {
"isAddProjectLibrariesToClasspath": false
}
},
"nbformat": 4,
"nbformat_minor": 0
}

View File

@ -2,15 +2,11 @@
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"execution_count": null,
"metadata": {
"tags": [],
"pycharm": {
"is_executing": true
},
"ExecuteTime": {
"end_time": "2023-05-29T15:22:37.933397300Z",
"start_time": "2023-05-29T15:22:37.913872100Z"
}
},
"outputs": [],
@ -18,57 +14,23 @@
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"ExecuteTime": {
"end_time": "2023-05-29T15:22:50.486483300Z",
"start_time": "2023-05-29T15:22:50.457485500Z"
}
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Line_2.jupyter.kts (1:1 - 3) Unresolved reference: vf"
]
}
],
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"vf.startServer()"
]
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
},
"ExecuteTime": {
"end_time": "2023-05-29T15:22:51.410680600Z",
"start_time": "2023-05-29T15:22:51.250779400Z"
}
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Line_3.jupyter.kts (1:16 - 26) Unresolved reference: coroutines\n",
"Line_3.jupyter.kts (4:1 - 7) Unresolved reference: Plotly\n",
"Line_3.jupyter.kts (5:5 - 12) Unresolved reference: scatter\n",
"Line_3.jupyter.kts (6:9 - 10) Unresolved reference: x\n",
"Line_3.jupyter.kts (7:9 - 10) Unresolved reference: y\n",
"Line_3.jupyter.kts (8:12 - 14) Unresolved reference: vf\n",
"Line_3.jupyter.kts (9:13 - 15) Unresolved reference: vf\n",
"Line_3.jupyter.kts (10:23 - 31) Unresolved reference: isActive\n",
"Line_3.jupyter.kts (11:21 - 26) Unresolved reference: delay\n",
"Line_3.jupyter.kts (12:21 - 22) Unresolved reference: y"
]
}
],
"outputs": [],
"source": [
"import kotlinx.coroutines.*\n",
"import kotlin.random.Random\n",

View File

@ -1,5 +1,5 @@
import space.kscience.dataforge.misc.DFExperimental
import space.kscience.visionforge.jupyter.VFNotebookPlugin
import space.kscience.visionforge.jupyter.VFNotebookClient
import space.kscience.visionforge.markup.MarkupPlugin
import space.kscience.visionforge.plotly.PlotlyPlugin
import space.kscience.visionforge.ring.ThreeWithControlsPlugin
@ -12,5 +12,5 @@ fun main() = runVisionClient {
plugin(PlotlyPlugin)
plugin(MarkupPlugin)
plugin(TableVisionJsPlugin)
plugin(VFNotebookPlugin)
plugin(VFNotebookClient)
}

View File

@ -8,13 +8,15 @@ kscience {
// useSerialization {
// json()
// }
useKtor()
dependencies{
implementation("io.ktor:ktor-server-cio")
implementation(projects.visionforgeThreejs.visionforgeThreejsServer)
implementation("ch.qos.logback:logback-classic:1.4.5")
implementation(spclibs.logback.classic)
}
}
group = "ru.mipt.npm"
group = "center.sciprog"
application {
mainClass.set("ru.mipt.npm.sat.SatServerKt")

View File

@ -1,32 +0,0 @@
# Module visionforge-jupyter-gdml
Jupyter api artifact for GDML rendering
## Usage
## Artifact:
The Maven coordinates of this project are `space.kscience:visionforge-jupyter-gdml:0.2.0`.
**Gradle Groovy:**
```groovy
repositories {
maven { url 'https://repo.kotlin.link' }
mavenCentral()
}
dependencies {
implementation 'space.kscience:visionforge-jupyter-gdml:0.2.0'
}
```
**Gradle Kotlin DSL:**
```kotlin
repositories {
maven("https://repo.kotlin.link")
mavenCentral()
}
dependencies {
implementation("space.kscience:visionforge-jupyter-gdml:0.2.0")
}
```

View File

@ -1,12 +0,0 @@
package space.kscience.visionforge.gdml.jupyter
import space.kscience.dataforge.misc.DFExperimental
import space.kscience.visionforge.ring.ThreeWithControlsPlugin
import space.kscience.visionforge.runVisionClient
@DFExperimental
@JsExport
public fun main(): Unit = runVisionClient {
plugin(ThreeWithControlsPlugin)
}

View File

@ -1,38 +0,0 @@
package space.kscience.visionforge.gdml.jupyter
import org.jetbrains.kotlinx.jupyter.api.libraries.resources
import space.kscience.dataforge.context.Context
import space.kscience.dataforge.misc.DFExperimental
import space.kscience.gdml.Gdml
import space.kscience.visionforge.gdml.toVision
import space.kscience.visionforge.jupyter.VFIntegrationBase
import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.visionManager
@DFExperimental
internal class GdmlForJupyter : VFIntegrationBase(
Context("GDML") {
plugin(Solids)
}.visionManager
) {
override fun Builder.afterLoaded() {
resources {
js("three") {
classPath("js/gdml-jupyter.js")
}
}
import(
"space.kscience.gdml.*",
"space.kscience.visionforge.gdml.jupyter.*"
)
render<Gdml> { gdmlModel ->
handler.produceHtml {
vision { gdmlModel.toVision() }
}
}
}
}

View File

@ -1,3 +0,0 @@
const ringConfig = require('@jetbrains/ring-ui/webpack.config').config;
config.module.rules.push(...ringConfig.module.rules)

View File

@ -64,6 +64,6 @@ include(
":demo:playground",
// ":demo:plotly-fx",
":demo:js-playground",
":jupyter",
":jupyter:visionforge-jupyter-gdml"
":visionforge-jupyter",
":visionforge-jupyter:visionforge-jupyter-common"
)

View File

@ -26,7 +26,7 @@ public data class VisionPage(
}
/**
* Use css with given stylesheet link as a global header for all pages.
* Use css with the given stylesheet link as a global header for all pages.
*/
public fun styleSheetHeader(href: String, block: LINK.() -> Unit = {}): HtmlFragment = {
link {

View File

@ -5,6 +5,7 @@ plugins {
description = "Common visionforge jupyter module"
kscience {
useKtor()
jvm()
js()
jupyterLibrary()
@ -12,6 +13,7 @@ kscience {
api(projects.visionforgeCore)
}
dependencies(jvmMain){
api("io.ktor:ktor-server-cio")
api(projects.visionforgeServer)
}
}

View File

@ -13,7 +13,7 @@ import space.kscience.visionforge.renderAllVisionsById
import space.kscience.visionforge.renderAllVisionsIn
@JsExport
public class VFNotebookPlugin : AbstractPlugin() {
public class VFNotebookClient : AbstractPlugin() {
private val client by require(VisionClient)
public fun renderAllVisionsIn(element: Element) {
@ -39,8 +39,8 @@ public class VFNotebookPlugin : AbstractPlugin() {
override val tag: PluginTag get() = Companion.tag
@Suppress("NON_EXPORTABLE_TYPE")
public companion object : PluginFactory<VFNotebookPlugin> {
override fun build(context: Context, meta: Meta): VFNotebookPlugin = VFNotebookPlugin()
public companion object : PluginFactory<VFNotebookClient> {
override fun build(context: Context, meta: Meta): VFNotebookClient = VFNotebookClient()
override val tag: PluginTag = PluginTag(name = "vision.notebook", group = PluginTag.DATAFORGE_GROUP)
}

View File

@ -16,9 +16,7 @@ import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.ContextAware
import space.kscience.dataforge.context.info
import space.kscience.dataforge.context.logger
import space.kscience.dataforge.meta.get
import space.kscience.dataforge.meta.int
import space.kscience.dataforge.meta.string
import space.kscience.dataforge.meta.*
import space.kscience.dataforge.names.Name
import space.kscience.visionforge.Vision
import space.kscience.visionforge.VisionManager
@ -26,7 +24,6 @@ import space.kscience.visionforge.html.HtmlVisionFragment
import space.kscience.visionforge.html.visionFragment
import space.kscience.visionforge.server.VisionRoute
import space.kscience.visionforge.server.serveVisionData
import space.kscience.visionforge.visionManager
import kotlin.coroutines.CoroutineContext
import kotlin.random.Random
import kotlin.random.nextUInt
@ -41,9 +38,14 @@ internal fun TagConsumer<*>.renderScriptForId(id: String) {
/**
* A handler class that includes a server and common utilities
*/
public class VFForNotebook(override val context: Context) : ContextAware, CoroutineScope {
public class VisionForge(
public val visionManager: VisionManager,
meta: Meta = Meta.EMPTY,
) : ContextAware, CoroutineScope {
public val visionManager: VisionManager = context.visionManager
override val context: Context get() = visionManager.context
public val configuration: ObservableMutableMeta = meta.toMutableMeta()
private var counter = 0
@ -61,9 +63,11 @@ public class VFForNotebook(override val context: Context) : ContextAware, Corout
public fun html(block: TagConsumer<*>.() -> Unit): MimeTypedResult = HTML(createHTML().apply(block).finalize())
public fun getProperty(name: String): TypedMeta<*>? = configuration[name] ?: context.properties[name]
public fun startServer(
host: String = context.properties["visionforge.host"].string ?: "localhost",
port: Int = context.properties["visionforge.port"].int ?: VisionRoute.DEFAULT_PORT,
host: String = getProperty("visionforge.host").string ?: "localhost",
port: Int = getProperty("visionforge.port").int ?: VisionRoute.DEFAULT_PORT,
): MimeTypedResult = html {
if (engine != null) {
p {

View File

@ -18,12 +18,12 @@ import kotlin.random.nextUInt
* A base class for different Jupyter VF integrations
*/
@DFExperimental
public abstract class VFIntegrationBase(
public abstract class VisionForgeIntegration(
public val visionManager: VisionManager,
) : JupyterIntegration(), ContextAware {
override val context: Context get() = visionManager.context
protected val handler: VFForNotebook = VFForNotebook(visionManager.context)
protected val handler: VisionForge = VisionForge(visionManager)
protected abstract fun Builder.afterLoaded()
@ -33,13 +33,15 @@ public abstract class VFIntegrationBase(
declare("VisionForge" to handler, "vf" to handler)
}
onShutdown {
handler.stopServer()
}
import(
"kotlinx.html.*",
"space.kscience.visionforge.html.*"
"space.kscience.visionforge.html.*",
"space.kscience.visionforge.jupyter.*"
)
render<HtmlFragment> { fragment ->
@ -54,7 +56,6 @@ public abstract class VFIntegrationBase(
handler.produceHtml {
vision(vision)
}
}
render<VisionPage> { page ->
@ -94,3 +95,11 @@ public abstract class VFIntegrationBase(
afterLoaded()
}
}
/**
* Create a standalone page in the notebook
*/
public fun VisionForge.page(
pageHeaders: Map<String, HtmlFragment> = emptyMap(),
content: HtmlVisionFragment
): VisionPage = VisionPage(visionManager, pageHeaders, content)

View File

@ -11,11 +11,14 @@ import space.kscience.visionforge.html.VisionOfHtmlForm
public class HtmlFormFragment internal constructor(
public val vision: VisionOfHtmlForm,
public val formBody: HtmlFragment,
){
) {
public val values: Meta? get() = vision.values
public operator fun get(valueName: String): Meta? = values?.get(valueName)
}
/**
* Top level function to create a form
*/
public fun HtmlFormFragment(id: String? = null, builder: FORM.() -> Unit): HtmlFormFragment {
val realId = id ?: "form[${builder.hashCode().toUInt()}]"
return HtmlFormFragment(VisionOfHtmlForm(realId)) {
@ -25,3 +28,7 @@ public fun HtmlFormFragment(id: String? = null, builder: FORM.() -> Unit): HtmlF
}
}
}
public fun VisionForge.form(id: String? = null, builder: FORM.() -> Unit): HtmlFormFragment =
HtmlFormFragment(id, builder)

View File

@ -2,10 +2,11 @@ plugins {
id("space.kscience.gradle.mpp")
}
description = "Jupyter api artifact for GDML rendering"
description = "Jupyter api artifact including all common modules"
kscience {
fullStack("js/gdml-jupyter.js",
fullStack(
"js/visionforge-jupyter-common.js",
jsConfig = { useCommonJs() }
) {
commonWebpackConfig {
@ -16,21 +17,24 @@ kscience {
}
}
dependencies{
dependencies {
implementation(projects.visionforgeSolid)
implementation(projects.jupyter)
implementation(projects.visionforgePlotly)
implementation(projects.visionforgeTables)
implementation(projects.visionforgeMarkdown)
implementation(projects.visionforgeJupyter)
}
dependencies(jvmMain){
jvmMain {
implementation(projects.visionforgeGdml)
}
dependencies(jsMain){
implementation(projects.visionforgeThreejs)
jsMain {
implementation(projects.ui.ring)
implementation(projects.visionforgeThreejs)
}
jupyterLibrary("space.kscience.visionforge.gdml.jupyter.GdmlForJupyter")
jupyterLibrary("space.kscience.visionforge.jupyter.JupyterCommonIntegration")
}
readme {

View File

@ -0,0 +1,17 @@
package space.kscience.visionforge.gdml.jupyter
import space.kscience.visionforge.jupyter.VFNotebookClient
import space.kscience.visionforge.markup.MarkupPlugin
import space.kscience.visionforge.plotly.PlotlyPlugin
import space.kscience.visionforge.ring.ThreeWithControlsPlugin
import space.kscience.visionforge.runVisionClient
import space.kscience.visionforge.tables.TableVisionJsPlugin
public fun main(): Unit = runVisionClient {
plugin(ThreeWithControlsPlugin)
plugin(PlotlyPlugin)
plugin(MarkupPlugin)
plugin(TableVisionJsPlugin)
plugin(VFNotebookClient)
}

View File

@ -1,46 +1,52 @@
package space.kscience.visionforge.examples
package space.kscience.visionforge.jupyter
import kotlinx.html.*
import org.jetbrains.kotlinx.jupyter.api.libraries.resources
import space.kscience.dataforge.context.Context
import space.kscience.dataforge.misc.DFExperimental
import space.kscience.gdml.Gdml
import space.kscience.plotly.Plot
import space.kscience.tables.*
import space.kscience.visionforge.gdml.toVision
import space.kscience.visionforge.jupyter.VFIntegrationBase
import space.kscience.visionforge.markup.MarkupPlugin
import space.kscience.visionforge.plotly.PlotlyPlugin
import space.kscience.visionforge.plotly.asVision
import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.tables.TableVisionPlugin
import space.kscience.visionforge.tables.toVision
import space.kscience.visionforge.visionManager
@DFExperimental
internal class VisionForgePlayGroundForJupyter : VFIntegrationBase(
Context("VisionForge") {
plugin(Solids)
plugin(PlotlyPlugin)
}.visionManager
) {
public class JupyterCommonIntegration : VisionForgeIntegration(CONTEXT.visionManager) {
override fun Builder.afterLoaded() {
resources {
js("VisionForge") {
classPath("js/visionforge-playground.js")
js("three") {
classPath("js/visionforge-jupyter-common.js")
}
}
import(
"space.kscience.gdml.*",
"space.kscience.plotly.*",
"space.kscience.plotly.models.*",
"space.kscience.visionforge.solid.*",
"space.kscience.tables.*",
"space.kscience.dataforge.meta.*",
)
render<Gdml> { gdmlModel ->
handler.produceHtml {
vision { gdmlModel.toVision() }
}
}
render<Table<*>> { table ->
handler.produceHtml {
vision { table.toVision() }
}
}
render<Plot> { plot ->
handler.produceHtml {
vision { plot.asVision() }
@ -48,4 +54,12 @@ internal class VisionForgePlayGroundForJupyter : VFIntegrationBase(
}
}
public companion object {
private val CONTEXT: Context = Context("Jupyter-common") {
plugin(Solids)
plugin(PlotlyPlugin)
plugin(TableVisionPlugin)
plugin(MarkupPlugin)
}
}
}

View File

@ -0,0 +1,24 @@
const ringConfig = require('@jetbrains/ring-ui/webpack.config').config;
const path = require('path');
config.module.rules.push(...ringConfig.module.rules)
config.module.rules.push(
{
test: /\.css$/,
exclude: [
path.resolve(__dirname, "../../node_modules/@jetbrains/ring-ui")
],
use: [
{
loader: 'style-loader',
options: {}
},
{
loader: 'css-loader',
options: {}
}
]
}
)

View File

@ -6,7 +6,7 @@ kscience{
useKtor()
dependencies {
api(projects.visionforgeCore)
api("io.ktor:ktor-server-cio")
api("io.ktor:ktor-server-host-common")
api("io.ktor:ktor-server-html-builder")
api("io.ktor:ktor-server-websockets")
implementation("io.ktor:ktor-server-cors")

View File

@ -2,7 +2,6 @@ package space.kscience.visionforge.server
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.cio.*
import io.ktor.server.engine.*
import io.ktor.server.html.*
import io.ktor.server.http.content.*

View File

@ -246,6 +246,6 @@ public var Solid.scaleZ: Number by float(Z_SCALE_KEY, 1f)
/**
* Add rotation with given [angle] relative to given [axis]
*/
public fun Solid.rotate(angle: Angle, axis: DoubleVector3D) = with(QuaternionField) {
public fun Solid.rotate(angle: Angle, axis: DoubleVector3D): Unit = with(QuaternionField) {
quaternion = Quaternion.fromRotation(angle, axis)*quaternion
}

View File

@ -99,3 +99,8 @@ public inline fun MutableVisionContainer<Solid>.solidGroup(
name: String,
action: SolidGroup.() -> Unit = {},
): SolidGroup = solidGroup(name.parseAsName(), action)
/**
* Create a [SolidGroup] using given configuration [block]
*/
public inline fun SolidGroup(block: SolidGroup.() -> Unit): SolidGroup = SolidGroup().apply(block)

View File

@ -9,9 +9,9 @@ kscience {
js {
useCommonJs()
binaries.library()
browser{
commonWebpackConfig{
cssSupport{
browser {
commonWebpackConfig {
cssSupport {
enabled.set(true)
}
}
@ -21,13 +21,13 @@ kscience {
api(projects.visionforgeCore)
api("space.kscience:tables-kt:${tablesVersion}")
}
dependencies(jsMain){
implementation(npm("tabulator-tables", "5.0.1"))
implementation(npm("@types/tabulator-tables", "5.0.1"))
dependencies(jsMain) {
implementation(npm("tabulator-tables", "5.4.4"))
implementation(npm("@types/tabulator-tables", "5.4.8"))
}
useSerialization()
}
readme{
readme {
maturity = space.kscience.gradle.Maturity.PROTOTYPE
}

View File

@ -86,6 +86,11 @@ public fun Table<String>.toVision(): VisionOfTable = toVision { (it ?: "").asVal
@JvmName("numberTableToVision")
public fun Table<Number>.toVision(): VisionOfTable = toVision { (it ?: Double.NaN).asValue() }
@JvmName("anyTableToVision")
public fun Table<Any?>.toVision(): VisionOfTable = toVision {
(it as? Number)?.asValue() ?: it?.toString()?.asValue() ?: Null
}
@DFExperimental
public inline fun VisionOutput.table(
vararg headers: ColumnHeader<Value>,