Compare commits
8 Commits
f238b03833
...
6fd719b9ee
Author | SHA1 | Date | |
---|---|---|---|
6fd719b9ee | |||
42e98f0bcc | |||
fd5ff5e30c | |||
51bb46a45c | |||
d0220c98a4 | |||
c499c3fc47 | |||
6ce1e68b86 | |||
5f4972a05e |
3
.gitignore
vendored
3
.gitignore
vendored
@ -6,6 +6,9 @@ out/
|
||||
.kotlin
|
||||
build/
|
||||
data/
|
||||
.kotlin/
|
||||
|
||||
jcef-bundle/
|
||||
|
||||
!gradle-wrapper.jar
|
||||
|
||||
|
@ -3,8 +3,11 @@
|
||||
## Unreleased
|
||||
|
||||
### Added
|
||||
- Moved plotly-kt repo inside this one
|
||||
|
||||
### Changed
|
||||
- Kotlin 2.0
|
||||
- DataForge 0.9
|
||||
|
||||
### Deprecated
|
||||
|
||||
|
@ -3,14 +3,15 @@ import space.kscience.gradle.useSPCTeam
|
||||
|
||||
plugins {
|
||||
id("space.kscience.gradle.project")
|
||||
id("org.jetbrains.kotlinx.kover") version "0.5.0"
|
||||
alias(spclibs.plugins.kotlinx.kover)
|
||||
}
|
||||
|
||||
val dataforgeVersion by extra("0.8.0")
|
||||
val dataforgeVersion by extra("0.9.0")
|
||||
val plotlyVersion by extra("2.29.0")
|
||||
|
||||
allprojects {
|
||||
group = "space.kscience"
|
||||
version = "0.4.2-dev-1"
|
||||
version = "0.5.0-dev-1"
|
||||
}
|
||||
|
||||
subprojects {
|
||||
@ -25,8 +26,8 @@ subprojects {
|
||||
}
|
||||
|
||||
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
|
||||
kotlinOptions {
|
||||
freeCompilerArgs = freeCompilerArgs + "-Xcontext-receivers"
|
||||
compilerOptions {
|
||||
freeCompilerArgs.add("-Xcontext-receivers")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
plugins {
|
||||
id("space.kscience.gradle.mpp")
|
||||
alias(spclibs.plugins.compose)
|
||||
alias(spclibs.plugins.compose.compiler)
|
||||
alias(spclibs.plugins.compose.jb)
|
||||
}
|
||||
|
||||
kscience {
|
||||
|
@ -1,6 +1,7 @@
|
||||
plugins {
|
||||
id("space.kscience.gradle.mpp")
|
||||
alias(spclibs.plugins.compose)
|
||||
alias(spclibs.plugins.compose.compiler)
|
||||
alias(spclibs.plugins.compose.jb)
|
||||
}
|
||||
|
||||
group = "demo"
|
||||
|
@ -3,8 +3,8 @@
|
||||
package space.kscience.visionforge.gdml.demo
|
||||
|
||||
import androidx.compose.runtime.*
|
||||
import app.softwork.bootstrapcompose.Container
|
||||
import app.softwork.bootstrapcompose.Icon
|
||||
import bootstrap.Container
|
||||
import bootstrap.Icon
|
||||
import org.jetbrains.compose.web.ExperimentalComposeWebApi
|
||||
import org.jetbrains.compose.web.attributes.InputType
|
||||
import org.jetbrains.compose.web.attributes.name
|
||||
|
@ -1,6 +1,7 @@
|
||||
plugins {
|
||||
id("space.kscience.gradle.mpp")
|
||||
alias(spclibs.plugins.compose)
|
||||
alias(spclibs.plugins.compose.compiler)
|
||||
alias(spclibs.plugins.compose.jb)
|
||||
}
|
||||
|
||||
kscience {
|
||||
|
@ -1,8 +1,8 @@
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.remember
|
||||
import app.softwork.bootstrapcompose.Column
|
||||
import app.softwork.bootstrapcompose.Row
|
||||
import bootstrap.Column
|
||||
import bootstrap.Row
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.isActive
|
||||
import org.jetbrains.compose.web.css.*
|
||||
|
@ -1,65 +1,55 @@
|
||||
plugins {
|
||||
id("space.kscience.gradle.mpp")
|
||||
alias(spclibs.plugins.compose)
|
||||
alias(spclibs.plugins.compose.compiler)
|
||||
alias(spclibs.plugins.compose.jb)
|
||||
// alias(spclibs.plugins.ktor)
|
||||
application
|
||||
}
|
||||
|
||||
group = "ru.mipt.npm"
|
||||
|
||||
val ktorVersion: String = spclibs.versions.ktor.get()
|
||||
|
||||
kscience {
|
||||
useCoroutines()
|
||||
useSerialization()
|
||||
useKtor()
|
||||
fullStack(
|
||||
"muon-monitor.js",
|
||||
jvmConfig = { withJava() },
|
||||
// jsConfig = { useCommonJs() },
|
||||
jvmConfig = {withJava()},
|
||||
browserConfig = {
|
||||
webpackTask{
|
||||
cssSupport{
|
||||
commonWebpackConfig {
|
||||
cssSupport {
|
||||
enabled = true
|
||||
}
|
||||
scssSupport{
|
||||
scssSupport {
|
||||
enabled = true
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
useCoroutines()
|
||||
useSerialization()
|
||||
useKtor()
|
||||
|
||||
commonMain {
|
||||
implementation(projects.visionforgeSolid)
|
||||
implementation(projects.visionforgeComposeHtml)
|
||||
}
|
||||
jvmMain {
|
||||
implementation("org.apache.commons:commons-math3:3.6.1")
|
||||
implementation("io.ktor:ktor-server-cio:${ktorVersion}")
|
||||
implementation("io.ktor:ktor-server-content-negotiation:${ktorVersion}")
|
||||
implementation("io.ktor:ktor-serialization-kotlinx-json:${ktorVersion}")
|
||||
implementation("ch.qos.logback:logback-classic:1.2.11")
|
||||
implementation("io.ktor:ktor-server-cio")
|
||||
implementation("io.ktor:ktor-server-content-negotiation")
|
||||
implementation("io.ktor:ktor-serialization-kotlinx-json")
|
||||
implementation(spclibs.logback.classic)
|
||||
}
|
||||
jsMain {
|
||||
implementation(projects.visionforgeThreejs)
|
||||
//implementation(devNpm("webpack-bundle-analyzer", "4.4.0"))
|
||||
}
|
||||
}
|
||||
kotlin{
|
||||
kotlin {
|
||||
explicitApi = null
|
||||
}
|
||||
|
||||
|
||||
application {
|
||||
mainClass.set("ru.mipt.npm.muon.monitor.server.MMServerKt")
|
||||
}
|
||||
|
||||
//distributions {
|
||||
// main {
|
||||
// contents {
|
||||
// from("$buildDir/libs") {
|
||||
// rename("${rootProject.name}-jvm", rootProject.name)
|
||||
// into("lib")
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
mainClass.set("ru.mipt.npm.muon.monitor.MMServerKt")
|
||||
}
|
@ -3,16 +3,15 @@ package ru.mipt.npm.muon.monitor
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
import androidx.compose.runtime.remember
|
||||
import app.softwork.bootstrapcompose.Button
|
||||
import app.softwork.bootstrapcompose.ButtonGroup
|
||||
import app.softwork.bootstrapcompose.Color.Secondary
|
||||
import app.softwork.bootstrapcompose.Container
|
||||
import app.softwork.bootstrapcompose.Layout.Width
|
||||
import bootstrap.Button
|
||||
import bootstrap.ButtonGroup
|
||||
import bootstrap.Layout.Width.Full
|
||||
import kotlinx.browser.window
|
||||
import kotlinx.coroutines.await
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.serialization.json.Json
|
||||
import org.jetbrains.compose.web.css.*
|
||||
import org.jetbrains.compose.web.dom.Div
|
||||
import org.jetbrains.compose.web.dom.P
|
||||
import org.jetbrains.compose.web.dom.Span
|
||||
import org.jetbrains.compose.web.dom.Text
|
||||
@ -52,8 +51,9 @@ fun MMApp(context: Context, model: Model, selected: Name? = null) {
|
||||
|
||||
val events = remember { mutableStateListOf<Event>() }
|
||||
|
||||
Container(fluid = true,
|
||||
Div(
|
||||
attrs = {
|
||||
classes("container-fluid")
|
||||
style {
|
||||
height(100.vh - 12.pt)
|
||||
}
|
||||
@ -66,7 +66,7 @@ fun MMApp(context: Context, model: Model, selected: Name? = null) {
|
||||
options = mmOptions,
|
||||
sidebarTabs = {
|
||||
Tab("Events") {
|
||||
ButtonGroup({ Layout.width = Width.Full }) {
|
||||
ButtonGroup({ Layout.width = Full }) {
|
||||
Button("Next") {
|
||||
context.launch {
|
||||
val event = window.fetch(
|
||||
@ -85,7 +85,7 @@ fun MMApp(context: Context, model: Model, selected: Name? = null) {
|
||||
model.displayEvent(event)
|
||||
}
|
||||
}
|
||||
Button("Clear", color = Secondary) {
|
||||
Button("Clear", color = bootstrap.Color.Secondary) {
|
||||
events.clear()
|
||||
model.reset()
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package ru.mipt.npm.muon.monitor.server
|
||||
package ru.mipt.npm.muon.monitor
|
||||
|
||||
|
||||
import io.ktor.http.ContentType
|
||||
@ -17,7 +17,6 @@ import io.ktor.server.response.respondText
|
||||
import io.ktor.server.routing.Routing
|
||||
import io.ktor.server.routing.get
|
||||
import org.apache.commons.math3.random.JDKRandomGenerator
|
||||
import ru.mipt.npm.muon.monitor.Model
|
||||
import ru.mipt.npm.muon.monitor.sim.Cos2TrackGenerator
|
||||
import ru.mipt.npm.muon.monitor.sim.simulateOne
|
||||
import space.kscience.dataforge.context.Context
|
||||
|
@ -12,7 +12,7 @@ repositories {
|
||||
}
|
||||
|
||||
kotlin {
|
||||
|
||||
jvmToolchain(11)
|
||||
js(IR) {
|
||||
browser {
|
||||
webpackTask {
|
||||
@ -30,12 +30,9 @@ kotlin {
|
||||
|
||||
jvm {
|
||||
// withJava()
|
||||
compilations.all {
|
||||
kotlinOptions {
|
||||
jvmTarget = "11"
|
||||
freeCompilerArgs =
|
||||
freeCompilerArgs + "-Xjvm-default=all" + "-Xopt-in=kotlin.RequiresOptIn" + "-Xlambdas=indy" + "-Xcontext-receivers"
|
||||
}
|
||||
compilerOptions {
|
||||
freeCompilerArgs.addAll("-Xjvm-default=all", "-Xopt-in=kotlin.RequiresOptIn", "-Xlambdas=indy", "-Xcontext-receivers")
|
||||
|
||||
}
|
||||
testRuns["test"].executionTask.configure {
|
||||
useJUnitPlatform()
|
||||
@ -46,9 +43,9 @@ kotlin {
|
||||
val commonMain by getting {
|
||||
dependencies {
|
||||
implementation(projects.visionforgeSolid)
|
||||
implementation(projects.visionforgePlotly)
|
||||
// implementation(projects.visionforgePlotly)
|
||||
implementation(projects.visionforgeMarkdown)
|
||||
implementation(projects.visionforgeTables)
|
||||
// implementation(projects.visionforgeTables)
|
||||
implementation(projects.cernRootLoader)
|
||||
api(projects.visionforgeJupyter.visionforgeJupyterCommon)
|
||||
}
|
||||
|
@ -18,7 +18,6 @@ Before we start, we have to load necessary dependencies:
|
||||
```kotlin
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven("https://maven.pkg.jetbrains.space/public/p/kotlinx-html/maven")
|
||||
|
||||
// Add either the line below:
|
||||
maven("https://repo.kotlin.link")
|
||||
|
@ -1,12 +1,7 @@
|
||||
kotlin.code.style=official
|
||||
kotlin.mpp.stability.nowarn=true
|
||||
kotlin.js.compiler=ir
|
||||
|
||||
org.gradle.parallel=true
|
||||
org.gradle.jvmargs=-Xmx4G
|
||||
|
||||
org.jetbrains.compose.experimental.jscanvas.enabled=true
|
||||
|
||||
toolsVersion=0.15.2-kotlin-1.9.22
|
||||
#kotlin.experimental.tryK2=true
|
||||
#kscience.wasm.disabled=true
|
||||
toolsVersion=0.15.4-kotlin-2.0.0
|
||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
221
plotly/CHANGELOG.md
Normal file
221
plotly/CHANGELOG.md
Normal file
@ -0,0 +1,221 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Added
|
||||
|
||||
### Changed
|
||||
|
||||
### Deprecated
|
||||
|
||||
### Removed
|
||||
|
||||
### Fixed
|
||||
|
||||
### Security
|
||||
|
||||
## 0.7.1 - 2024-02-22
|
||||
|
||||
### Added
|
||||
|
||||
- Compose demo
|
||||
|
||||
### Changed
|
||||
|
||||
- Migrated to DF 0.8
|
||||
|
||||
### Removed
|
||||
|
||||
- Grid view
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed rendering for Jupyter lab
|
||||
|
||||
## 0.6.0 - 2023-07-29
|
||||
|
||||
### Added
|
||||
|
||||
- Add experimental support for events on JS
|
||||
|
||||
### Changed
|
||||
|
||||
- DataForge 0.6.2
|
||||
- Use a self-made Plotly-js bundle instead of one from CDN
|
||||
|
||||
## 0.5.3 - 2023-04-01
|
||||
|
||||
### Added
|
||||
|
||||
- API for background images (https://github.com/SciProgCentre/plotly.kt/issues/49)
|
||||
- API for multiple Y axis (https://github.com/SciProgCentre/plotly.kt/issues/92)
|
||||
- Native support
|
||||
- `plotlykt module` with basic Geo API
|
||||
- DataSourceHost/DataSourcePost to configure custom networks
|
||||
|
||||
### Changed
|
||||
|
||||
- Kotlin 1.8.20
|
||||
- Moved renderers to JVM to avoid confusion with JS direct element rendering.
|
||||
- DataForge 0.6
|
||||
- Replaced krangl by Kotlin-DataFrame in examples
|
||||
- Plotly server uses push strategy by default
|
||||
- Renderers moved to common
|
||||
- Moved to Ktor 2.0
|
||||
|
||||
### Deprecated
|
||||
|
||||
- Page layout. Use VisionForge for that.
|
||||
|
||||
### Removed
|
||||
|
||||
- Moved CORS to `Plotly.serve`
|
||||
|
||||
### Fixed
|
||||
|
||||
- Added a protective copy on reading doubleArray from TraceValues
|
||||
- #85
|
||||
- Rendering in JS that used backend HTML generation
|
||||
|
||||
## 0.5.0
|
||||
|
||||
### Changed
|
||||
|
||||
- Switch to DataForge 0.5
|
||||
-
|
||||
|
||||
## 0.4.4
|
||||
|
||||
### Added
|
||||
|
||||
- Candlestick support
|
||||
- Range builders for axis
|
||||
|
||||
### Changed
|
||||
|
||||
- build tools 0.10.0
|
||||
- demo projects moved to examples
|
||||
|
||||
### Deprecated
|
||||
|
||||
- Direct usage of `range` in axis
|
||||
|
||||
### Fixed
|
||||
|
||||
- #80
|
||||
- Plotly coordinate array wrap is moved to the server side
|
||||
|
||||
## 0.4.3
|
||||
|
||||
### Fixed
|
||||
|
||||
- Proper deserialization of single plot.
|
||||
- A bug in jupyter lab visualization
|
||||
|
||||
## 0.4.2
|
||||
|
||||
### Added
|
||||
|
||||
- `automargin` property to `Axis` according to https://plotly.com/python/reference/layout/xaxis/#layout-xaxis-automargin
|
||||
|
||||
### Fixed
|
||||
|
||||
- Remove unnecessary `kotlinx-css` dependency.
|
||||
- Added compatibility mode for legacy notebooks. Use `Plotly.jupyter.notebook()` call to enable legacy mode.
|
||||
|
||||
## 0.4.0
|
||||
|
||||
### Added
|
||||
|
||||
- Jupyter integration plugin for server
|
||||
- Separate static plot integration module in `plotlykt-jupyter`
|
||||
- Expanded JS demo
|
||||
- Jupyter support goes beta
|
||||
|
||||
### Changed
|
||||
|
||||
- Package change (again) to `space.kscience`
|
||||
- Build tools `0.9.5`
|
||||
- Kotlin `1.5.0`
|
||||
- HtmlFragment renamed to PlotlyHtmlFragment
|
||||
|
||||
### Removed
|
||||
|
||||
- Local bootstrap
|
||||
|
||||
### Fixed
|
||||
|
||||
- Incomplete coverage in JS (#70)
|
||||
|
||||
## 0.3.1
|
||||
|
||||
### Added
|
||||
|
||||
- Table widget implementation by @ArtificialPB
|
||||
- Mathjax header promoted to stable
|
||||
- Tabbed plots layout (experimental)
|
||||
- Trace value builders for functions and ranges (experimental)
|
||||
|
||||
### Changed
|
||||
|
||||
- **Breaking API change!** Trace `text` replaced by `TraceValues`
|
||||
- Moved to DataForge 0.3 API
|
||||
- Kotlin 1.4.30
|
||||
- **JVM-IR**
|
||||
- Plot `Config` moved to constructor
|
||||
- Replaced direct color accessor by a delegate
|
||||
|
||||
### Fixed
|
||||
|
||||
- https://github.com/mipt-npm/plotly.kt/issues/53
|
||||
- Add JQuery to Bootstrap headers
|
||||
|
||||
## 0.3.0
|
||||
|
||||
### Changed
|
||||
|
||||
- Serialization API is encapsulated (not longer exposed) in order to provide compatibility with new serialization.
|
||||
- Migration to Kotlin 1.4
|
||||
- Minor breaking change in Plot to encapsulate serialization usage
|
||||
- JS supports IR. LEGACY is not supported anymore.
|
||||
|
||||
### Fixed
|
||||
|
||||
- https://github.com/mipt-npm/plotly.kt/issues/51
|
||||
|
||||
## 0.2.0
|
||||
|
||||
### Added
|
||||
|
||||
- Experimental scripting support
|
||||
- Static export via Orca
|
||||
- Experimental Jupyter support
|
||||
- Color palettes (T10 and XKCD)
|
||||
- New parameters and classes in Trace, Legend, Layout
|
||||
- Parameters description
|
||||
- naming.md with decisions about parameters and methods names
|
||||
- Error bars
|
||||
- New scatter, contour, error plots examples
|
||||
- Interfaces with common parameters for some plots (Histogram, Contour, Heatmap)
|
||||
- New parameters for different plots
|
||||
- Add Z axis
|
||||
- Tutorial about drawing sinus
|
||||
- Loading resources using krangl
|
||||
- TraceValues extension for krangl columns
|
||||
|
||||
### Changed
|
||||
|
||||
- Migrated from `scientifik` to `kscience`
|
||||
- Refactored packages to better suit star import style
|
||||
- Removed bootstrap dependency
|
||||
- Examples colors changed and more cases for each example added
|
||||
- Different types of plots were inherited from Trace
|
||||
- Unnecessary constructors removed
|
||||
- Change Title methods
|
||||
- Project structure updated
|
||||
- Removed other Plot functions
|
||||
- Plot2D renamed to Plot
|
126
plotly/README.md
Normal file
126
plotly/README.md
Normal file
@ -0,0 +1,126 @@
|
||||
[![JetBrains Research](https://jb.gg/badges/research.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub)
|
||||
[![DOI](https://zenodo.org/badge/186020000.svg)](https://zenodo.org/badge/latestdoi/186020000)
|
||||
![Gradle build](https://github.com/mipt-npm/plotly.kt/workflows/Gradle%20build/badge.svg)
|
||||
[![Kotlin JS IR supported](https://img.shields.io/badge/Kotlin%2FJS-IR%20supported-yellow)](https://kotl.in/jsirsupported)
|
||||
|
||||
![Plotlykt logo](./docs/logo_text.svg)
|
||||
|
||||
## Artifact details
|
||||
|
||||
[![Maven Central](https://img.shields.io/maven-central/v/space.kscience/plotlykt-core.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22space.kscience%22%20AND%20a:%22plotlykt-core%22)
|
||||
|
||||
Dev builds and intermediate artifacts are available via `https://repo.kotlin.link` maven repository.
|
||||
|
||||
## Compatibility note
|
||||
The current `$version` version of the library is compatible with kotlin 1.4 with JS-IR and kotlinx-serialization 1.1.0. The JVM part requires JVM 11 to run.
|
||||
|
||||
# TL;DR
|
||||
See [examples](./examples/src/main/kotlin).
|
||||
See [original library samples](https://plotly.com/javascript/) to understand capabilities.
|
||||
|
||||
# Description
|
||||
|
||||
This project is developed to allow simple access to plotly functionality from kotlin-multiplatform. The API allows to create plotly configuration and render it as a plotly chart.
|
||||
|
||||
The library supports three drawable plot objects:
|
||||
* `Plot` itself stands for a stand-alone plot frame. It requires external infrastructure to load appropriate JavaScript libraries.
|
||||
* `PlotFragment` is an HTML fragment possibly including several plots. The API for html is provided by [kotlinx-html](https://github.com/Kotlin/kotlinx.html) library.
|
||||
* `PlotlyPage` is a complete page, including body fragment and page headers (needed to load JavaScript part of Plotly).
|
||||
|
||||
The work with plotly graphs could be rendered in following modes:
|
||||
|
||||
## HTML page export
|
||||
(JVM and native) Export plot or page in a standalone html file, using CDN distribution or local JS file (JVM only). This mode does not support updates.
|
||||
|
||||
See [staticPlot](./examples/src/main/kotlin/staticPlot.kt) and
|
||||
[customPage](./examples/src/main/kotlin/customPage.kt) for examples.
|
||||
|
||||
## Ktor-based server with dynamic updates
|
||||
(JVM only) A Ktor CIO server with full multi-page and update capabilities.
|
||||
|
||||
See [simpleServer](./examples/src/main/kotlin/simpleServer.kt) and
|
||||
[dynamicServer](./examples/src/main/kotlin/dynamicServer.kt) for examples.
|
||||
|
||||
## Kotlin-JS
|
||||
Plotly is a JavaScript library, yet it is convenient to have a type-safe API when using in with Kotlin-JS. The sample application is available in [js-demo](./js-demo) module. One should node that Plotly.kt for JS is not a zero-cost wrapper like TypeScript definitions, it maintains its own object structure, could generate stand-alone models and some internal optimizations.
|
||||
|
||||
## JavaFX browser
|
||||
Plotly.kt could be run in a JavaFX browser. An example project is presented in [fx-demo](./fx-demo).
|
||||
|
||||
## Kotlin jupyter kernel
|
||||
Plotly.kt comes with (beta-version) support for integration with [Kotlin Jupyter kernel](https://github.com/Kotlin/kotlin-jupyter). See details [here](./docs/tutorials/jupyter.md).
|
||||
|
||||
The examples of the notebooks are shown in [notebooks](./examples/notebooks) directory. Plotly.kt uses Kotlin jupyter notebook API for integration (available in kernel version `0.8.3.236` and later). In order to load the library together with automatic imports one need to simply load a library in a following way:
|
||||
|
||||
```kotlin
|
||||
@file:Repository("https://repo.kotlin.link")
|
||||
@file:DependsOn("space.kscience:plotlykt-jupyter:$version")
|
||||
//@file:DependsOn("space.kscience:plotlykt-server:$version") // Use this one for sever integration.
|
||||
```
|
||||
|
||||
The module `plotly` allows rendering static plots in Jupyter. Jupyter lab is currently supported. Jupyter notebook (classic) is able to render only `PlotlyPage` objects, so one must convert plots to pages to be able to use notebook (see [demo notebook](./notebooks/plotlykt-demo-classic.ipynb)).
|
||||
|
||||
The module `plotly-server` adds server capabilities and allows to render dynamic plots in notebooks (see [demo notebook](./notebooks/plotlykt-server-demo.ipynb)). One must note that for dynamic pages, one must pass `renderer` parameter explicitly to plot like it is done in examples.
|
||||
|
||||
**IMPORTANT:** By default, Plotly-kt jupyter integration is configured to work with Jupyter Lab frontend, which renders all cells in the same page. Jupyter classic notebook and DataLore use cell isolation with iframes, so you will see blanks instead of plots. It could be fixed by switching into a notebook mode by running `Plotly.jupyter.notebook()` in a cell after plotly library is loaded.
|
||||
|
||||
## Direct image render via Orca (experimental)
|
||||
[Plotly Orca](https://github.com/plotly/orca) application allows direct rendering of plots (not fragments or pages) to raster of vector images.
|
||||
`Plot.export` extension could be used to call it. It requires for orca to be installed in the system and available on the system path.
|
||||
|
||||
## Kotlin-scripting (experimental)
|
||||
It is possible to separate script logic into stand-alone `plotly.kts` script file and generate an html from the command line. See [plotlykt-script](./plotlykt-script) module for details.
|
||||
|
||||
## Kotlin/Native (experimental)
|
||||
Plotly model now fully supports Kotlin/Native. It means that you can use it to create a proper Plotly-based HTML file. You will still need browser to view it. You can use [native-demo](./examples/native-demo) example.
|
||||
|
||||
# The feature I need is not implemented!
|
||||
|
||||
There are three ways to solve it:
|
||||
1. Contribute! It is easy! Just add a model you need.
|
||||
2. Create a model you need in your project or add an extension. Since the inner model is dynamic, you can add features on flight.
|
||||
3. You can dynamically add missing features directly into configuration
|
||||
like it done in [unsupportedFeature](./examples/src/main/kotlin/unsupportedFeature.kt) example.
|
||||
|
||||
# Build and usage
|
||||
|
||||
In order to use the library, one needs to use following `gradle.kts` configuration:
|
||||
|
||||
```kotlin
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven("https://repo.kotlin.link")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("space.kscience:plotlykt-server:$version")
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
If you do not need the server, then use plotlykt-core instead.
|
||||
|
||||
# Naming
|
||||
The library keeps original Plotly API naming wherever it is possible. There are some usability shortcuts, usually provided via kotlin extensions, included in order to simplify user interaction. For example, `text` and `shape` extensions in the top level API.
|
||||
|
||||
Keeping the original naming sometimes causes clashes with Kotlin code style. For example enum names are unorthodox.
|
||||
|
||||
# Planned features
|
||||
|
||||
* Table widgets
|
||||
* Serverside plot events
|
||||
* Online plot editor
|
||||
* Dynamic data
|
||||
* Mathjax and latex support
|
||||
|
||||
# Contributions and thanks
|
||||
* [Vasily Chernov](https://research.jetbrains.org/researchers/vchernov) - initial project foundation
|
||||
* [Alexander Nozik](https://research.jetbrains.org/researchers/altavir) - dynamic core and server
|
||||
* [Mikhail Zeleniy](https://research.jetbrains.org/researchers/gama_sennin) - basic models
|
||||
* [Ekaterina Samorodova](https://github.com/ebsamorodova) (JBR-2020 summer internship) - Model refactoring, tutorials and `0.2` release.
|
||||
|
||||
The project was partially founded by JetBrains Research grant.
|
||||
|
8
plotly/build.gradle.kts
Normal file
8
plotly/build.gradle.kts
Normal file
@ -0,0 +1,8 @@
|
||||
allprojects {
|
||||
group = "space.kscience"
|
||||
version = "0.7.2"
|
||||
}
|
||||
|
||||
readme {
|
||||
readmeTemplate = file("docs/templates/README-TEMPLATE.md")
|
||||
}
|
BIN
plotly/docs/Dependency structure.vsdx
Normal file
BIN
plotly/docs/Dependency structure.vsdx
Normal file
Binary file not shown.
BIN
plotly/docs/logo.png
Normal file
BIN
plotly/docs/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.8 KiB |
250
plotly/docs/logo.svg
Normal file
250
plotly/docs/logo.svg
Normal file
@ -0,0 +1,250 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
sodipodi:docname="logo_2.svg"
|
||||
inkscape:version="1.0 (6e3e5246a0, 2020-05-07)"
|
||||
id="svg8"
|
||||
version="1.1"
|
||||
viewBox="0 0 29.104165 29.104156"
|
||||
height="29.104156mm"
|
||||
width="29.104164mm">
|
||||
<defs
|
||||
id="defs2">
|
||||
<linearGradient
|
||||
id="linearGradient1618"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop1614"
|
||||
offset="0"
|
||||
style="stop-color:#806ee3;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop1616"
|
||||
offset="1"
|
||||
style="stop-color:#00c3d5;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<rect
|
||||
id="rect1524"
|
||||
height="15.875"
|
||||
width="48.947916"
|
||||
y="7.9604866"
|
||||
x="37.06465" />
|
||||
<marker
|
||||
inkscape:isstock="true"
|
||||
style="overflow:visible"
|
||||
id="Arrow1Lstart"
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow1Lstart">
|
||||
<path
|
||||
transform="matrix(0.8,0,0,0.8,10,0)"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||
id="path1122" />
|
||||
</marker>
|
||||
<linearGradient
|
||||
gradientTransform="rotate(90,10.606316,10.60632)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="21.189653"
|
||||
x2="21.18965"
|
||||
y1="0.022986634"
|
||||
x1="21.18965"
|
||||
id="linearGradient1620"
|
||||
xlink:href="#linearGradient1618"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
gradientTransform="rotate(90,10.606316,10.60632)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="21.189653"
|
||||
x2="0.022983"
|
||||
y1="0.022986634"
|
||||
x1="0.022983"
|
||||
id="linearGradient1638"
|
||||
xlink:href="#linearGradient1618"
|
||||
inkscape:collect="always" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:window-y="34"
|
||||
inkscape:window-x="67"
|
||||
inkscape:window-height="1018"
|
||||
inkscape:window-width="1853"
|
||||
showgrid="true"
|
||||
inkscape:document-rotation="0"
|
||||
inkscape:current-layer="layer2"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:cy="50.040837"
|
||||
inkscape:cx="61.969517"
|
||||
inkscape:zoom="5.9388735"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
borderopacity="1.0"
|
||||
bordercolor="#666666"
|
||||
pagecolor="#ffffff"
|
||||
id="base">
|
||||
<inkscape:grid
|
||||
originy="-125.67708"
|
||||
originx="-59.531251"
|
||||
id="grid843"
|
||||
type="xygrid" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
transform="translate(3.945766,3.9457667)"
|
||||
inkscape:label="Слой 2"
|
||||
id="layer2"
|
||||
inkscape:groupmode="layer">
|
||||
<rect
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:export-xdpi="96"
|
||||
ry="1.0272725e-05"
|
||||
rx="1.0272725e-05"
|
||||
y="-3.9457667"
|
||||
x="-3.945766"
|
||||
height="29.104156"
|
||||
width="29.104164"
|
||||
id="rect1494"
|
||||
style="fill:#ffffff;fill-rule:evenodd;stroke-width:0.264583" />
|
||||
<path
|
||||
id="path1612"
|
||||
d="M 21.189649,21.189653 H 0.02298279 V 0.02298679 Z"
|
||||
style="fill:url(#linearGradient1620);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
id="path1630"
|
||||
d="M 21.189649,0.02298679 0.02298279,21.189653 V 0.02298679 Z"
|
||||
style="fill:url(#linearGradient1638);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
</g>
|
||||
<g
|
||||
transform="translate(-59.531252,-125.67708)"
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Слой 1">
|
||||
<rect
|
||||
transform="rotate(-89.858546)"
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:export-xdpi="96"
|
||||
y="63.831543"
|
||||
x="-150.6329"
|
||||
height="21.166674"
|
||||
width="21.166664"
|
||||
id="rect845"
|
||||
style="fill:none;fill-rule:evenodd;stroke:none;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<ellipse
|
||||
transform="matrix(0.00254488,-0.99999676,0.99999713,0.00239507,0,0)"
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:export-xdpi="96"
|
||||
ry="1.3434278"
|
||||
rx="1.2960323"
|
||||
cy="83.69519"
|
||||
cx="-134.73538"
|
||||
id="path853"
|
||||
style="fill:#00c3d5;fill-opacity:1;stroke:#00c3d5;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<ellipse
|
||||
transform="matrix(0.00251442,-0.99999684,0.99999706,0.00242408,0,0)"
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:export-xdpi="96"
|
||||
style="fill:#00c3d5;fill-opacity:1;stroke:none;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path853-3"
|
||||
cx="-145.31732"
|
||||
cy="83.716812"
|
||||
rx="1.323424"
|
||||
ry="1.3351575" />
|
||||
<ellipse
|
||||
transform="matrix(0.0024009,-0.99999712,0.99999678,0.00253869,0,0)"
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:export-xdpi="96"
|
||||
style="fill:#00c3d5;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path853-6"
|
||||
cx="-140.06395"
|
||||
cy="83.702271"
|
||||
rx="1.3443971"
|
||||
ry="1.2951746" />
|
||||
<ellipse
|
||||
transform="matrix(-0.00258022,0.99999667,-0.99999721,-0.00236228,0,0)"
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:export-xdpi="96"
|
||||
style="fill:#00c3d5;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path853-7"
|
||||
cx="140.02629"
|
||||
cy="-79.456383"
|
||||
rx="1.3054924"
|
||||
ry="1.3265911" />
|
||||
<rect
|
||||
transform="rotate(0.141454)"
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:export-xdpi="96"
|
||||
rx="1.3229166"
|
||||
ry="1.3228887"
|
||||
y="146.68326"
|
||||
x="65.185257"
|
||||
height="2.6457775"
|
||||
width="14.552083"
|
||||
id="rect1120-6-2"
|
||||
style="mix-blend-mode:normal;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke-width:0.264999;stroke-miterlimit:4;stroke-dasharray:none;paint-order:fill markers stroke" />
|
||||
<rect
|
||||
transform="rotate(0.141454)"
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:export-xdpi="96"
|
||||
rx="1.3229166"
|
||||
ry="1.3228887"
|
||||
y="130.77238"
|
||||
x="65.146019"
|
||||
height="2.6457775"
|
||||
width="14.552083"
|
||||
id="rect1120-6-9"
|
||||
style="mix-blend-mode:normal;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke-width:0.264999;stroke-miterlimit:4;stroke-dasharray:none;paint-order:fill markers stroke" />
|
||||
<rect
|
||||
transform="rotate(0.141454)"
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:export-xdpi="96"
|
||||
style="mix-blend-mode:normal;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke-width:0.264999;stroke-miterlimit:4;stroke-dasharray:none;paint-order:fill markers stroke"
|
||||
id="rect1120-6-9-9"
|
||||
width="10.583334"
|
||||
height="2.6457775"
|
||||
x="65.155861"
|
||||
y="134.77705"
|
||||
ry="1.3228887"
|
||||
rx="1.3229166" />
|
||||
<rect
|
||||
transform="rotate(0.141454)"
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:export-xdpi="96"
|
||||
style="mix-blend-mode:normal;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke-width:0.264999;stroke-miterlimit:4;stroke-dasharray:none;paint-order:fill markers stroke"
|
||||
id="rect1120-6-9-3"
|
||||
width="10.583334"
|
||||
height="2.6457775"
|
||||
x="65.175453"
|
||||
y="142.71452"
|
||||
ry="1.3228887"
|
||||
rx="1.3229166" />
|
||||
<rect
|
||||
transform="rotate(0.141454)"
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:export-xdpi="96"
|
||||
style="mix-blend-mode:normal;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke-width:0.264998;stroke-miterlimit:4;stroke-dasharray:none;paint-order:fill markers stroke"
|
||||
id="rect1120-6-9-6"
|
||||
width="6.6145844"
|
||||
height="2.6458383"
|
||||
x="65.165657"
|
||||
y="138.74579"
|
||||
ry="1.3228886"
|
||||
rx="1.3229166" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 8.3 KiB |
263
plotly/docs/logo_text.svg
Normal file
263
plotly/docs/logo_text.svg
Normal file
@ -0,0 +1,263 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-filename="/home/katsam/plotly_pictures/logo_text.png"
|
||||
sodipodi:docname="logo_text.svg"
|
||||
inkscape:version="1.0 (6e3e5246a0, 2020-05-07)"
|
||||
id="svg8"
|
||||
version="1.1"
|
||||
viewBox="0 0 144.19792 41.010418"
|
||||
height="41.010418mm"
|
||||
width="144.19791mm">
|
||||
<defs
|
||||
id="defs2">
|
||||
<rect
|
||||
x="27.804234"
|
||||
y="-1.29993"
|
||||
width="110.37238"
|
||||
height="34.123283"
|
||||
id="rect40" />
|
||||
<linearGradient
|
||||
id="linearGradient1618"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop1614"
|
||||
offset="0"
|
||||
style="stop-color:#806ee3;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop1616"
|
||||
offset="1"
|
||||
style="stop-color:#00c3d5;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
gradientTransform="rotate(90,10.606316,10.60632)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="21.189653"
|
||||
x2="21.18965"
|
||||
y1="0.022986634"
|
||||
x1="21.18965"
|
||||
id="linearGradient1620"
|
||||
xlink:href="#linearGradient1618"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
gradientTransform="rotate(90,10.606316,10.60632)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="21.189653"
|
||||
x2="0.022983"
|
||||
y1="0.022986634"
|
||||
x1="0.022983"
|
||||
id="linearGradient1638"
|
||||
xlink:href="#linearGradient1618"
|
||||
inkscape:collect="always" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:window-y="34"
|
||||
inkscape:window-x="67"
|
||||
inkscape:window-height="1018"
|
||||
inkscape:window-width="1853"
|
||||
showgrid="true"
|
||||
inkscape:document-rotation="0"
|
||||
inkscape:current-layer="layer3"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:cy="-28.867052"
|
||||
inkscape:cx="373.38531"
|
||||
inkscape:zoom="1.7069031"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
borderopacity="1.0"
|
||||
bordercolor="#666666"
|
||||
pagecolor="#ffffff"
|
||||
id="base"
|
||||
inkscape:snap-text-baseline="false">
|
||||
<inkscape:grid
|
||||
originy="-121.70833"
|
||||
originx="-55.562519"
|
||||
id="grid843"
|
||||
type="xygrid" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer3"
|
||||
inkscape:label="Слой 3"
|
||||
transform="translate(3.9687517,3.9687471)">
|
||||
<rect
|
||||
style="fill:#ffffff;fill-rule:evenodd;stroke-width:0.264584"
|
||||
id="rect873"
|
||||
width="144.19791"
|
||||
height="41.010418"
|
||||
x="-3.9687517"
|
||||
y="-3.9687471" />
|
||||
</g>
|
||||
<g
|
||||
transform="translate(7.9145176,7.9145034)"
|
||||
inkscape:label="Слой 2"
|
||||
id="layer2"
|
||||
inkscape:groupmode="layer">
|
||||
<rect
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:export-xdpi="96"
|
||||
ry="1.0272725e-05"
|
||||
rx="1.0272725e-05"
|
||||
y="-3.9457667"
|
||||
x="-3.945766"
|
||||
height="29.104156"
|
||||
width="29.104164"
|
||||
id="rect1494"
|
||||
style="fill:#ffffff;fill-rule:evenodd;stroke-width:0.264583" />
|
||||
<path
|
||||
id="path1612"
|
||||
d="M 21.189649,21.189653 H 0.02298279 V 0.02298679 Z"
|
||||
style="fill:url(#linearGradient1620);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
id="path1630"
|
||||
d="M 21.189649,0.02298679 0.02298279,21.189653 V 0.02298679 Z"
|
||||
style="fill:url(#linearGradient1638);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<text
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:export-xdpi="96"
|
||||
xml:space="preserve"
|
||||
id="text38"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:25.4px;line-height:1.25;font-family:Norasi;-inkscape-font-specification:'Norasi, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;white-space:pre;shape-inside:url(#rect40);fill:#5e4cbf;fill-opacity:1;stroke:#5e3a93;stroke-width:0.402811;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers stroke fill;"
|
||||
transform="matrix(1.2597546,0,0,1.223073,-10.154695,-6.4045632)"><tspan
|
||||
x="27.804688"
|
||||
y="22.194218"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:25.4px;font-family:Norasi;-inkscape-font-specification:'Norasi, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#5e4cbf;fill-opacity:1;stroke:#5e4cbf;stroke-width:0.402811;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers stroke fill">Plotly.kt</tspan></tspan></text>
|
||||
</g>
|
||||
<g
|
||||
transform="translate(-55.5625,-121.70834)"
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Слой 1">
|
||||
<rect
|
||||
transform="rotate(-89.858546)"
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:export-xdpi="96"
|
||||
y="63.831543"
|
||||
x="-150.6329"
|
||||
height="21.166674"
|
||||
width="21.166664"
|
||||
id="rect845"
|
||||
style="fill:none;fill-rule:evenodd;stroke:none;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<ellipse
|
||||
transform="matrix(0.00254488,-0.99999676,0.99999713,0.00239507,-4.0844967e-8,0)"
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:export-xdpi="96"
|
||||
ry="1.3434278"
|
||||
rx="1.2960323"
|
||||
cy="83.69519"
|
||||
cx="-134.73538"
|
||||
id="path853"
|
||||
style="fill:#00c3d5;fill-opacity:1;stroke:#00c3d5;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<ellipse
|
||||
transform="matrix(0.00251442,-0.99999684,0.99999706,0.00242408,-4.0844967e-8,0)"
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:export-xdpi="96"
|
||||
style="fill:#00c3d5;fill-opacity:1;stroke:none;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path853-3"
|
||||
cx="-145.31732"
|
||||
cy="83.716812"
|
||||
rx="1.323424"
|
||||
ry="1.3351575" />
|
||||
<ellipse
|
||||
transform="matrix(0.0024009,-0.99999712,0.99999678,0.00253869,-4.0844967e-8,0)"
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:export-xdpi="96"
|
||||
style="fill:#00c3d5;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path853-6"
|
||||
cx="-140.06395"
|
||||
cy="83.702271"
|
||||
rx="1.3443971"
|
||||
ry="1.2951746" />
|
||||
<ellipse
|
||||
transform="matrix(-0.00258022,0.99999667,-0.99999721,-0.00236228,-4.0844967e-8,0)"
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:export-xdpi="96"
|
||||
style="fill:#00c3d5;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path853-7"
|
||||
cx="140.02629"
|
||||
cy="-79.456383"
|
||||
rx="1.3054924"
|
||||
ry="1.3265911" />
|
||||
<rect
|
||||
transform="rotate(0.141454)"
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:export-xdpi="96"
|
||||
rx="1.3229166"
|
||||
ry="1.3228887"
|
||||
y="146.68326"
|
||||
x="65.185257"
|
||||
height="2.6457775"
|
||||
width="14.552083"
|
||||
id="rect1120-6-2"
|
||||
style="mix-blend-mode:normal;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke-width:0.264999;stroke-miterlimit:4;stroke-dasharray:none;paint-order:fill markers stroke" />
|
||||
<rect
|
||||
transform="rotate(0.141454)"
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:export-xdpi="96"
|
||||
rx="1.3229166"
|
||||
ry="1.3228887"
|
||||
y="130.77238"
|
||||
x="65.146019"
|
||||
height="2.6457775"
|
||||
width="14.552083"
|
||||
id="rect1120-6-9"
|
||||
style="mix-blend-mode:normal;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke-width:0.264999;stroke-miterlimit:4;stroke-dasharray:none;paint-order:fill markers stroke" />
|
||||
<rect
|
||||
transform="rotate(0.141454)"
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:export-xdpi="96"
|
||||
style="mix-blend-mode:normal;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke-width:0.264999;stroke-miterlimit:4;stroke-dasharray:none;paint-order:fill markers stroke"
|
||||
id="rect1120-6-9-9"
|
||||
width="10.583334"
|
||||
height="2.6457775"
|
||||
x="65.155861"
|
||||
y="134.77705"
|
||||
ry="1.3228887"
|
||||
rx="1.3229166" />
|
||||
<rect
|
||||
transform="rotate(0.141454)"
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:export-xdpi="96"
|
||||
style="mix-blend-mode:normal;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke-width:0.264999;stroke-miterlimit:4;stroke-dasharray:none;paint-order:fill markers stroke"
|
||||
id="rect1120-6-9-3"
|
||||
width="10.583334"
|
||||
height="2.6457775"
|
||||
x="65.175453"
|
||||
y="142.71452"
|
||||
ry="1.3228887"
|
||||
rx="1.3229166" />
|
||||
<rect
|
||||
transform="rotate(0.141454)"
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:export-xdpi="96"
|
||||
style="mix-blend-mode:normal;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke-width:0.264998;stroke-miterlimit:4;stroke-dasharray:none;paint-order:fill markers stroke"
|
||||
id="rect1120-6-9-6"
|
||||
width="6.6145844"
|
||||
height="2.6458383"
|
||||
x="65.165657"
|
||||
y="138.74579"
|
||||
ry="1.3228886"
|
||||
rx="1.3229166" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 9.8 KiB |
259
plotly/docs/models.uml
Normal file
259
plotly/docs/models.uml
Normal file
@ -0,0 +1,259 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Diagram>
|
||||
<ID>JAVA</ID>
|
||||
<OriginalElement>kscience.plotly.models</OriginalElement>
|
||||
<nodes>
|
||||
<node x="1679.0" y="1764.0">kscience.plotly.models.Contours</node>
|
||||
<node x="294.0" y="2467.0">kscience.plotly.models.ShapeType</node>
|
||||
<node x="840.0" y="2393.0">kscience.plotly.models.TextPosition</node>
|
||||
<node x="1645.0" y="2393.0">kscience.plotly.models.MeasureMode</node>
|
||||
<node x="0.0" y="2541.0">kscience.plotly.models.BoxMode</node>
|
||||
<node x="1127.0" y="2541.0">kscience.plotly.models.Ticks</node>
|
||||
<node x="868.0" y="2251.0">kscience.plotly.models.Cumulative</node>
|
||||
<node x="1591.0" y="2251.0">kscience.plotly.models.LegendOrientation</node>
|
||||
<node x="1001.0" y="2393.0">kscience.plotly.models.ViolinPoints</node>
|
||||
<node x="1896.0" y="1764.0">kscience.plotly.models.Margin</node>
|
||||
<node x="242.0" y="2251.0">kscience.plotly.models.SelectMarker</node>
|
||||
<node x="0.0" y="2393.0">kscience.plotly.models.VerticalAlign</node>
|
||||
<node x="168.0" y="2393.0">kscience.plotly.models.ShapeSizeMode</node>
|
||||
<node x="126.0" y="2541.0">kscience.plotly.models.BoxMean</node>
|
||||
<node x="1510.0" y="1764.0">kscience.plotly.models.Title</node>
|
||||
<node x="117.0" y="1764.0">kscience.plotly.models.Line</node>
|
||||
<node x="1578.75" y="1211.0">kscience.plotly.models.Heatmap</node>
|
||||
<node x="1060.0" y="2251.0">kscience.plotly.models.SelectPoints</node>
|
||||
<node x="1414.0" y="2467.0">kscience.plotly.models.AxisType</node>
|
||||
<node x="1341.1291666666666" y="440.0">kscience.plotly.models.HeatmapContour</node>
|
||||
<node x="434.0" y="2467.0">kscience.plotly.models.GroupNorm</node>
|
||||
<node x="712.1125" y="0.0">kscience.plotly.models.Trace</node>
|
||||
<node x="1547.0" y="2467.0">kscience.plotly.models.FillType</node>
|
||||
<node x="574.0" y="2467.0">kscience.plotly.models.StackGaps</node>
|
||||
<node x="2261.0" y="2393.0">kscience.plotly.models.ShapeLayer</node>
|
||||
<node x="1273.0" y="1764.0">kscience.plotly.models.Legend</node>
|
||||
<node x="2408.0" y="2393.0">kscience.plotly.models.BoxHoveron</node>
|
||||
<node x="2621.25" y="0.0">kscience.plotly.models.Shape</node>
|
||||
<node x="336.0" y="2393.0">kscience.plotly.models.ShapeFillRule</node>
|
||||
<node x="1680.0" y="2467.0">kscience.plotly.models.TickMode</node>
|
||||
<node x="252.0" y="2541.0">kscience.plotly.models.YAnchor</node>
|
||||
<node x="520.0" y="1167.0">kscience.plotly.models.Bar</node>
|
||||
<node x="1207.3625" y="1233.0">kscience.plotly.models.ContourSpec</node>
|
||||
<node x="1162.0" y="2393.0">kscience.plotly.models.GradientType</node>
|
||||
<node x="332.5" y="1634.0">kscience.plotly.models.ScatterGL</node>
|
||||
<node x="1388.0" y="2251.0">kscience.plotly.models.HistogramDirection</node>
|
||||
<node x="1084.4208333333333" y="1578.0">kscience.plotly.models.Contour</node>
|
||||
<node x="1323.0" y="2393.0">kscience.plotly.models.PieDirection</node>
|
||||
<node x="1246.0" y="2251.0">kscience.plotly.models.Color</node>
|
||||
<node x="1484.0" y="2393.0">kscience.plotly.models.ContoursType</node>
|
||||
<node x="2555.0" y="2393.0">kscience.plotly.models.CurrentBin</node>
|
||||
<node x="2225.25" y="0.0">kscience.plotly.models.Layout</node>
|
||||
<node x="2083.0" y="1764.0">kscience.plotly.models.TraceValues</node>
|
||||
<node x="260.0" y="1167.0">kscience.plotly.models.Scatter</node>
|
||||
<node x="234.0" y="1977.0">kscience.plotly.models.LayoutLine</node>
|
||||
<node x="2340.0" y="2251.0">kscience.plotly.models.ScatterHoveron</node>
|
||||
<node x="202.36249999999995" y="429.0">kscience.plotly.models.SelectedPoints</node>
|
||||
<node x="714.0" y="2467.0">kscience.plotly.models.ErrorType</node>
|
||||
<node x="854.0" y="2467.0">kscience.plotly.models.HoverMode</node>
|
||||
<node x="2702.0" y="2393.0">kscience.plotly.models.ViolinSide</node>
|
||||
<node x="493.0" y="1764.0">kscience.plotly.models.ColorBar</node>
|
||||
<node x="378.0" y="2541.0">kscience.plotly.models.BarNorm</node>
|
||||
<node x="2614.0" y="1764.0">kscience.plotly.models.Domain</node>
|
||||
<node x="0.0" y="1035.0">kscience.plotly.models.Box</node>
|
||||
<node x="0.0" y="1911.0">kscience.plotly.models.MarkerLine</node>
|
||||
<node x="504.0" y="2393.0">kscience.plotly.models.ConstrainText</node>
|
||||
<node x="1285.7375" y="1600.0">kscience.plotly.models.Histogram2DContour</node>
|
||||
<node x="405.0" y="2251.0">kscience.plotly.models.ViolinBox</node>
|
||||
<node x="0.0" y="2467.0">kscience.plotly.models.TraceOrder</node>
|
||||
<node x="1677.0875" y="1600.0">kscience.plotly.models.Histogram2D</node>
|
||||
<node x="1799.0" y="2393.0">kscience.plotly.models.Orientation</node>
|
||||
<node x="1919.25" y="0.0">kscience.plotly.models.Axis</node>
|
||||
<node x="504.0" y="2541.0">kscience.plotly.models.TraceKt</node>
|
||||
<node x="1002.0" y="1764.0">kscience.plotly.models.Error</node>
|
||||
<node x="1953.0" y="2393.0">kscience.plotly.models.ZsmoothType</node>
|
||||
<node x="630.0" y="2541.0">kscience.plotly.models.XAnchor</node>
|
||||
<node x="727.0" y="1764.0">kscience.plotly.models.Marker</node>
|
||||
<node x="1239.0" y="2541.0">kscience.plotly.models.Dash</node>
|
||||
<node x="756.0" y="2541.0">kscience.plotly.models.BarMode</node>
|
||||
<node x="1005.0" y="1156.0">kscience.plotly.models.Violin</node>
|
||||
<node x="1976.0" y="2251.0">kscience.plotly.models.ViolinScaleMode</node>
|
||||
<node x="994.0" y="2467.0">kscience.plotly.models.TraceType</node>
|
||||
<node x="1787.0" y="2251.0">kscience.plotly.models.ContoursColoring</node>
|
||||
<node x="1008.0" y="2541.0">kscience.plotly.models.Symbol</node>
|
||||
<node x="1813.0" y="2467.0">kscience.plotly.models.Calendar</node>
|
||||
<node x="781.0" y="1167.0">kscience.plotly.models.Pie</node>
|
||||
<node x="1134.0" y="2467.0">kscience.plotly.models.BoxPoints</node>
|
||||
<node x="1344.0" y="2541.0">kscience.plotly.models.Ref</node>
|
||||
<node x="147.0" y="2467.0">kscience.plotly.models.ViolinMode</node>
|
||||
<node x="882.0" y="2541.0">kscience.plotly.models.Visible</node>
|
||||
<node x="0.0" y="2251.0">kscience.plotly.models.Gradient</node>
|
||||
<node x="562.0" y="2251.0">kscience.plotly.models.MeanLine</node>
|
||||
<node x="2430.25" y="0.0">kscience.plotly.models.Text</node>
|
||||
<node x="1562.0875" y="1634.0">kscience.plotly.models.HeatmapGL</node>
|
||||
<node x="1722.25" y="429.0">kscience.plotly.models.Table2D</node>
|
||||
<node x="1373.75" y="1145.0">kscience.plotly.models.Histogram</node>
|
||||
<node x="1946.0" y="2467.0">kscience.plotly.models.SizeMode</node>
|
||||
<node x="2515.0" y="2251.0">kscience.plotly.models.QuartileMethod</node>
|
||||
<node x="1274.0" y="2467.0">kscience.plotly.models.LineShape</node>
|
||||
<node x="2158.0" y="2251.0">kscience.plotly.models.HorizontalAlign</node>
|
||||
<node x="2361.0" y="1764.0">kscience.plotly.models.Font</node>
|
||||
<node x="2079.0" y="2467.0">kscience.plotly.models.HistFunc</node>
|
||||
<node x="2107.0" y="2393.0">kscience.plotly.models.ScatterMode</node>
|
||||
<node x="719.0" y="2251.0">kscience.plotly.models.Bins</node>
|
||||
<node x="672.0" y="2393.0">kscience.plotly.models.ViolinHoveron</node>
|
||||
<node x="2212.0" y="2467.0">kscience.plotly.models.HistNorm</node>
|
||||
<node x="2345.0" y="2467.0">kscience.plotly.models.TextInfo</node>
|
||||
<node x="2478.0" y="2467.0">kscience.plotly.models.DataType</node>
|
||||
<node x="2611.0" y="2467.0">kscience.plotly.models.SpanMode</node>
|
||||
</nodes>
|
||||
<notes />
|
||||
<edges>
|
||||
<edge source="kscience.plotly.models.LayoutLine" target="kscience.plotly.models.Line">
|
||||
<point x="0.0" y="-81.5" />
|
||||
<point x="341.0" y="1886.0" />
|
||||
<point x="277.5" y="1886.0" />
|
||||
<point x="53.5" y="48.5" />
|
||||
</edge>
|
||||
<edge source="kscience.plotly.models.Contour" target="kscience.plotly.models.Trace">
|
||||
<point x="-47.33333333333337" y="-70.5" />
|
||||
<point x="1108.0875" y="1558.0" />
|
||||
<point x="770.5" y="1558.0" />
|
||||
<point x="770.5" y="1015.0" />
|
||||
<point x="814.4875" y="1015.0" />
|
||||
<point x="-14.625" y="477.5" />
|
||||
</edge>
|
||||
<edge source="kscience.plotly.models.Histogram" target="kscience.plotly.models.Trace">
|
||||
<point x="0.0" y="-136.5" />
|
||||
<point x="1466.25" y="995.0" />
|
||||
<point x="902.2375000000002" y="995.0" />
|
||||
<point x="73.12500000000011" y="477.5" />
|
||||
</edge>
|
||||
<edge source="kscience.plotly.models.Scatter" target="kscience.plotly.models.Trace">
|
||||
<point x="60.0" y="-114.5" />
|
||||
<point x="440.0" y="995.0" />
|
||||
<point x="755.9875" y="995.0" />
|
||||
<point x="-73.125" y="477.5" />
|
||||
</edge>
|
||||
<edge source="kscience.plotly.models.Contour" target="kscience.plotly.models.HeatmapContour">
|
||||
<point x="0.0" y="-70.5" />
|
||||
<point x="1155.4208333333333" y="1558.0" />
|
||||
<point x="1194.5" y="1558.0" />
|
||||
<point x="1194.5" y="1015.0" />
|
||||
<point x="1373.6291666666666" y="1015.0" />
|
||||
<point x="-32.5" y="37.5" />
|
||||
</edge>
|
||||
<edge source="kscience.plotly.models.Histogram2D" target="kscience.plotly.models.Histogram">
|
||||
<point x="-38.0" y="-48.5" />
|
||||
<point x="1715.0875" y="1548.0" />
|
||||
<point x="1512.5" y="1548.0" />
|
||||
<point x="46.25" y="136.5" />
|
||||
</edge>
|
||||
<edge source="kscience.plotly.models.Pie" target="kscience.plotly.models.Trace">
|
||||
<point x="0.0" y="-114.5" />
|
||||
<point x="883.0" y="1015.0" />
|
||||
<point x="843.7375" y="1015.0" />
|
||||
<point x="14.625" y="477.5" />
|
||||
</edge>
|
||||
<edge source="kscience.plotly.models.Bar" target="kscience.plotly.models.Trace">
|
||||
<point x="60.0" y="-114.5" />
|
||||
<point x="700.0" y="1005.0" />
|
||||
<point x="785.2375" y="1005.0" />
|
||||
<point x="-43.875" y="477.5" />
|
||||
</edge>
|
||||
<edge source="kscience.plotly.models.Histogram2DContour" target="kscience.plotly.models.ContourSpec">
|
||||
<point x="-39.5" y="-48.5" />
|
||||
<point x="1325.2375" y="1558.0" />
|
||||
<point x="1313.8625" y="1558.0" />
|
||||
<point x="35.5" y="48.5" />
|
||||
</edge>
|
||||
<edge source="kscience.plotly.models.Histogram2DContour" target="kscience.plotly.models.Histogram">
|
||||
<point x="39.5" y="-48.5" />
|
||||
<point x="1404.2375" y="1558.0" />
|
||||
<point x="1420.0" y="1558.0" />
|
||||
<point x="-46.25" y="136.5" />
|
||||
</edge>
|
||||
<edge source="kscience.plotly.models.Box" target="kscience.plotly.models.SelectedPoints">
|
||||
<point x="-60.0" y="-246.5" />
|
||||
<point x="60.0" y="975.0" />
|
||||
<point x="242.36249999999995" y="975.0" />
|
||||
<point x="-80.0" y="48.5" />
|
||||
</edge>
|
||||
<edge source="kscience.plotly.models.Heatmap" target="kscience.plotly.models.HeatmapContour">
|
||||
<point x="0.0" y="-70.5" />
|
||||
<point x="1654.75" y="975.0" />
|
||||
<point x="1438.6291666666666" y="975.0" />
|
||||
<point x="32.5" y="37.5" />
|
||||
</edge>
|
||||
<edge source="kscience.plotly.models.Histogram2D" target="kscience.plotly.models.Table2D">
|
||||
<point x="38.0" y="-48.5" />
|
||||
<point x="1791.0875" y="1558.0" />
|
||||
<point x="1832.9875" y="1558.0" />
|
||||
<point x="1832.9875" y="1015.0" />
|
||||
<point x="1836.25" y="1015.0" />
|
||||
<point x="38.0" y="48.5" />
|
||||
</edge>
|
||||
<edge source="kscience.plotly.models.Scatter" target="kscience.plotly.models.SelectedPoints">
|
||||
<point x="-60.0" y="-114.5" />
|
||||
<point x="320.0" y="975.0" />
|
||||
<point x="322.36249999999995" y="975.0" />
|
||||
<point x="0.0" y="48.5" />
|
||||
</edge>
|
||||
<edge source="kscience.plotly.models.Box" target="kscience.plotly.models.Trace">
|
||||
<point x="60.0" y="-246.5" />
|
||||
<point x="180.0" y="985.0" />
|
||||
<point x="726.7375" y="985.0" />
|
||||
<point x="-102.375" y="477.5" />
|
||||
</edge>
|
||||
<edge source="kscience.plotly.models.Contour" target="kscience.plotly.models.ContourSpec">
|
||||
<point x="47.33333333333337" y="-70.5" />
|
||||
<point x="1202.7541666666666" y="1558.0" />
|
||||
<point x="1242.8625" y="1558.0" />
|
||||
<point x="-35.5" y="48.5" />
|
||||
</edge>
|
||||
<edge source="kscience.plotly.models.MarkerLine" target="kscience.plotly.models.Line">
|
||||
<point x="0.0" y="-147.5" />
|
||||
<point x="107.0" y="1886.0" />
|
||||
<point x="170.5" y="1886.0" />
|
||||
<point x="-53.5" y="48.5" />
|
||||
</edge>
|
||||
<edge source="kscience.plotly.models.Bar" target="kscience.plotly.models.SelectedPoints">
|
||||
<point x="-60.0" y="-114.5" />
|
||||
<point x="580.0" y="975.0" />
|
||||
<point x="402.36249999999995" y="975.0" />
|
||||
<point x="80.0" y="48.5" />
|
||||
</edge>
|
||||
<edge source="kscience.plotly.models.ScatterGL" target="kscience.plotly.models.Scatter">
|
||||
<point x="0.0" y="-14.5" />
|
||||
<point x="0.0" y="114.5" />
|
||||
</edge>
|
||||
<edge source="kscience.plotly.models.Heatmap" target="kscience.plotly.models.Table2D">
|
||||
<point x="50.666666666666686" y="-70.5" />
|
||||
<point x="1705.4166666666667" y="1015.0" />
|
||||
<point x="1760.25" y="1015.0" />
|
||||
<point x="-38.0" y="48.5" />
|
||||
</edge>
|
||||
<edge source="kscience.plotly.models.Violin" target="kscience.plotly.models.Trace">
|
||||
<point x="1.1368683772161603E-13" y="-125.5" />
|
||||
<point x="1094.5" y="1005.0" />
|
||||
<point x="872.9875" y="1005.0" />
|
||||
<point x="43.875" y="477.5" />
|
||||
</edge>
|
||||
<edge source="kscience.plotly.models.Heatmap" target="kscience.plotly.models.Trace">
|
||||
<point x="-50.66666666666666" y="-70.5" />
|
||||
<point x="1604.0833333333335" y="985.0" />
|
||||
<point x="931.4875000000002" y="985.0" />
|
||||
<point x="102.37500000000011" y="477.5" />
|
||||
</edge>
|
||||
<edge source="kscience.plotly.models.HeatmapGL" target="kscience.plotly.models.Heatmap">
|
||||
<point x="0.0" y="-14.5" />
|
||||
<point x="1609.5875" y="1558.0" />
|
||||
<point x="1654.75" y="1558.0" />
|
||||
<point x="0.0" y="70.5" />
|
||||
</edge>
|
||||
</edges>
|
||||
<settings layout="Hierarchic Group" zoom="0.8575289575289575" x="848.7753264295362" y="519.9234579018461" />
|
||||
<SelectedNodes />
|
||||
<Categories>
|
||||
<Category>Properties</Category>
|
||||
</Categories>
|
||||
<SCOPE>All</SCOPE>
|
||||
<VISIBILITY>private</VISIBILITY>
|
||||
</Diagram>
|
||||
|
467
plotly/docs/overview.html
Normal file
467
plotly/docs/overview.html
Normal file
File diff suppressed because one or more lines are too long
29
plotly/docs/templates/ARTIFACT-TEMPLATE.md
vendored
Normal file
29
plotly/docs/templates/ARTIFACT-TEMPLATE.md
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
> #### Artifact:
|
||||
>
|
||||
> This module artifact: `${group}:${name}:${version}`.
|
||||
>
|
||||
>
|
||||
> [![Maven Central](https://img.shields.io/maven-central/v/space.kscience/${name}.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22space.kscience%22%20AND%20a:%22${name}%22)
|
||||
>
|
||||
> **Gradle:**
|
||||
>
|
||||
> ```gradle
|
||||
> repositories {
|
||||
> maven { url 'https://repo.kotlin.link' }
|
||||
> }
|
||||
>
|
||||
> dependencies {
|
||||
> implementation '${group}:${name}:${version}'
|
||||
> }
|
||||
> ```
|
||||
> **Gradle Kotlin DSL:**
|
||||
>
|
||||
> ```kotlin
|
||||
> repositories {
|
||||
> maven("https://https://repo.kotlin.link")
|
||||
> }
|
||||
>
|
||||
> dependencies {
|
||||
> implementation("${group}:${name}:${version}")
|
||||
> }
|
||||
> ```
|
126
plotly/docs/templates/README-TEMPLATE.md
vendored
Normal file
126
plotly/docs/templates/README-TEMPLATE.md
vendored
Normal file
@ -0,0 +1,126 @@
|
||||
[![JetBrains Research](https://jb.gg/badges/research.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub)
|
||||
[![DOI](https://zenodo.org/badge/186020000.svg)](https://zenodo.org/badge/latestdoi/186020000)
|
||||
![Gradle build](https://github.com/mipt-npm/plotly.kt/workflows/Gradle%20build/badge.svg)
|
||||
[![Kotlin JS IR supported](https://img.shields.io/badge/Kotlin%2FJS-IR%20supported-yellow)](https://kotl.in/jsirsupported)
|
||||
|
||||
![Plotlykt logo](./docs/logo_text.svg)
|
||||
|
||||
## Artifact details
|
||||
|
||||
[![Maven Central](https://img.shields.io/maven-central/v/space.kscience/plotlykt-core.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22space.kscience%22%20AND%20a:%22plotlykt-core%22)
|
||||
|
||||
Dev builds and intermediate artifacts are available via `https://repo.kotlin.link` maven repository.
|
||||
|
||||
## Compatibility note
|
||||
The current `$version` version of the library is compatible with kotlin 1.4 with JS-IR and kotlinx-serialization 1.1.0. The JVM part requires JVM 11 to run.
|
||||
|
||||
# TL;DR
|
||||
See [examples](./examples/src/main/kotlin).
|
||||
See [original library samples](https://plotly.com/javascript/) to understand capabilities.
|
||||
|
||||
# Description
|
||||
|
||||
This project is developed to allow simple access to plotly functionality from kotlin-multiplatform. The API allows to create plotly configuration and render it as a plotly chart.
|
||||
|
||||
The library supports three drawable plot objects:
|
||||
* `Plot` itself stands for a stand-alone plot frame. It requires external infrastructure to load appropriate JavaScript libraries.
|
||||
* `PlotFragment` is an HTML fragment possibly including several plots. The API for html is provided by [kotlinx-html](https://github.com/Kotlin/kotlinx.html) library.
|
||||
* `PlotlyPage` is a complete page, including body fragment and page headers (needed to load JavaScript part of Plotly).
|
||||
|
||||
The work with plotly graphs could be rendered in following modes:
|
||||
|
||||
## HTML page export
|
||||
(JVM and native) Export plot or page in a standalone html file, using CDN distribution or local JS file (JVM only). This mode does not support updates.
|
||||
|
||||
See [staticPlot](./examples/src/main/kotlin/staticPlot.kt) and
|
||||
[customPage](./examples/src/main/kotlin/customPage.kt) for examples.
|
||||
|
||||
## Ktor-based server with dynamic updates
|
||||
(JVM only) A Ktor CIO server with full multi-page and update capabilities.
|
||||
|
||||
See [simpleServer](./examples/src/main/kotlin/simpleServer.kt) and
|
||||
[dynamicServer](./examples/src/main/kotlin/dynamicServer.kt) for examples.
|
||||
|
||||
## Kotlin-JS
|
||||
Plotly is a JavaScript library, yet it is convenient to have a type-safe API when using in with Kotlin-JS. The sample application is available in [js-demo](./js-demo) module. One should node that Plotly.kt for JS is not a zero-cost wrapper like TypeScript definitions, it maintains its own object structure, could generate stand-alone models and some internal optimizations.
|
||||
|
||||
## JavaFX browser
|
||||
Plotly.kt could be run in a JavaFX browser. An example project is presented in [fx-demo](./fx-demo).
|
||||
|
||||
## Kotlin jupyter kernel
|
||||
Plotly.kt comes with (beta-version) support for integration with [Kotlin Jupyter kernel](https://github.com/Kotlin/kotlin-jupyter). See details [here](./docs/tutorials/jupyter.md).
|
||||
|
||||
The examples of the notebooks are shown in [notebooks](./examples/notebooks) directory. Plotly.kt uses Kotlin jupyter notebook API for integration (available in kernel version `0.8.3.236` and later). In order to load the library together with automatic imports one need to simply load a library in a following way:
|
||||
|
||||
```kotlin
|
||||
@file:Repository("https://repo.kotlin.link")
|
||||
@file:DependsOn("space.kscience:plotlykt-jupyter:$version")
|
||||
//@file:DependsOn("space.kscience:plotlykt-server:$version") // Use this one for sever integration.
|
||||
```
|
||||
|
||||
The module `plotly` allows rendering static plots in Jupyter. Jupyter lab is currently supported. Jupyter notebook (classic) is able to render only `PlotlyPage` objects, so one must convert plots to pages to be able to use notebook (see [demo notebook](./notebooks/plotlykt-demo-classic.ipynb)).
|
||||
|
||||
The module `plotly-server` adds server capabilities and allows to render dynamic plots in notebooks (see [demo notebook](./notebooks/plotlykt-server-demo.ipynb)). One must note that for dynamic pages, one must pass `renderer` parameter explicitly to plot like it is done in examples.
|
||||
|
||||
**IMPORTANT:** By default, Plotly-kt jupyter integration is configured to work with Jupyter Lab frontend, which renders all cells in the same page. Jupyter classic notebook and DataLore use cell isolation with iframes, so you will see blanks instead of plots. It could be fixed by switching into a notebook mode by running `Plotly.jupyter.notebook()` in a cell after plotly library is loaded.
|
||||
|
||||
## Direct image render via Orca (experimental)
|
||||
[Plotly Orca](https://github.com/plotly/orca) application allows direct rendering of plots (not fragments or pages) to raster of vector images.
|
||||
`Plot.export` extension could be used to call it. It requires for orca to be installed in the system and available on the system path.
|
||||
|
||||
## Kotlin-scripting (experimental)
|
||||
It is possible to separate script logic into stand-alone `plotly.kts` script file and generate an html from the command line. See [plotlykt-script](./plotlykt-script) module for details.
|
||||
|
||||
## Kotlin/Native (experimental)
|
||||
Plotly model now fully supports Kotlin/Native. It means that you can use it to create a proper Plotly-based HTML file. You will still need browser to view it. You can use [native-demo](./examples/native-demo) example.
|
||||
|
||||
# The feature I need is not implemented!
|
||||
|
||||
There are three ways to solve it:
|
||||
1. Contribute! It is easy! Just add a model you need.
|
||||
2. Create a model you need in your project or add an extension. Since the inner model is dynamic, you can add features on flight.
|
||||
3. You can dynamically add missing features directly into configuration
|
||||
like it done in [unsupportedFeature](./examples/src/main/kotlin/unsupportedFeature.kt) example.
|
||||
|
||||
# Build and usage
|
||||
|
||||
In order to use the library, one needs to use following `gradle.kts` configuration:
|
||||
|
||||
```kotlin
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven("https://repo.kotlin.link")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("space.kscience:plotlykt-server:$version")
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
If you do not need the server, then use plotlykt-core instead.
|
||||
|
||||
# Naming
|
||||
The library keeps original Plotly API naming wherever it is possible. There are some usability shortcuts, usually provided via kotlin extensions, included in order to simplify user interaction. For example, `text` and `shape` extensions in the top level API.
|
||||
|
||||
Keeping the original naming sometimes causes clashes with Kotlin code style. For example enum names are unorthodox.
|
||||
|
||||
# Planned features
|
||||
|
||||
* Table widgets
|
||||
* Serverside plot events
|
||||
* Online plot editor
|
||||
* Dynamic data
|
||||
* Mathjax and latex support
|
||||
|
||||
# Contributions and thanks
|
||||
* [Vasily Chernov](https://research.jetbrains.org/researchers/vchernov) - initial project foundation
|
||||
* [Alexander Nozik](https://research.jetbrains.org/researchers/altavir) - dynamic core and server
|
||||
* [Mikhail Zeleniy](https://research.jetbrains.org/researchers/gama_sennin) - basic models
|
||||
* [Ekaterina Samorodova](https://github.com/ebsamorodova) (JBR-2020 summer internship) - Model refactoring, tutorials and `0.2` release.
|
||||
|
||||
The project was partially founded by JetBrains Research grant.
|
||||
|
220
plotly/docs/tutorials/HowToDrawASinus.md
Normal file
220
plotly/docs/tutorials/HowToDrawASinus.md
Normal file
@ -0,0 +1,220 @@
|
||||
### How To Draw A Sinus?
|
||||
In data visualization tasks, quite often there is a need to depict mathematical
|
||||
functions - for example, to compare the convergence rate of a model
|
||||
with ideal one or to find an approximation for a given time series. Such charts
|
||||
have a number of features that are not inherent in most other charts: for example,
|
||||
visualizing the perpendicular axes (OX, OY) from (0, 0) and a large number of
|
||||
additional information. This can be the expected value of the function, its extremum
|
||||
points, deviation at various points, etc.
|
||||
|
||||
This article will tell you how to depict an ordinary sinus using the library `Plotly.kt`
|
||||
so that in the end you will get a visual and informative plot.
|
||||
|
||||
1. Let's start with drawing perpendicular OX and OY axes. This requires to do a few things:
|
||||
hide default axes lines, hide zero lines (it's impossible to draw an arrow on the end of it),
|
||||
add perpendicular arrows using annotations (`Text`) with visible arrows on the end, but without
|
||||
text. After that, let's sign the axes themselves. It is also important to specify the required
|
||||
chart sizes (`width`,` height`) so that after saving the graph will look the same as in the browser.
|
||||
|
||||
```kotlin
|
||||
Plotly.page { // making new html page with plot
|
||||
layout {
|
||||
width = 900 // width of the plot (in px.)
|
||||
height = 500 // height of the plot (in px.)
|
||||
|
||||
text { // vertical axis
|
||||
x = Value.of(0) // position of the top end of the arrow = (0, 1+eps)
|
||||
y = Value.of(1 + eps)
|
||||
ax = Value.of(0) // ax, ay means the offset of the bottom edge relative to the top
|
||||
ay = Value.of(430) // positive (negative) value is the arrow length
|
||||
// upwards (top down) and from right to left (from left to right)
|
||||
}
|
||||
|
||||
text { // horizontal axis
|
||||
y = Value.of(0) // arrow left position = (2PI + eps, 0)
|
||||
x = Value.of(2 * PI + eps)
|
||||
ax = Value.of(-800) // position of the left end of the arrow
|
||||
ay = Value.of(0)
|
||||
}
|
||||
|
||||
xaxis { // OX parameters
|
||||
showline = false // hide OX line
|
||||
zeroline = false // hide zero line
|
||||
}
|
||||
yaxis { // OY parameters
|
||||
showline = false // hide OY line
|
||||
zeroline = false // hide zero line
|
||||
}
|
||||
}
|
||||
}.makeFile() // making temporary file and visualing plot in the browser
|
||||
```
|
||||
|
||||
2. Now we will draw the sinus function itself - for its visualization let's choose a bright blue color,
|
||||
contrasting with both the white background and the black ticks on the axes. After that using
|
||||
the variation of the `mode` parameter (` ScatterMode: lines, markers`) the intersection points with the OY axis
|
||||
will be marked with a slightly darker shade of the same color.
|
||||
|
||||
```kotlin
|
||||
x1 = (-410..410).map{ it / 200 * PI } // function domain (-2PI - eps, 2PI + eps)
|
||||
y1 = sin(x1) // function values
|
||||
|
||||
Plotly.page {
|
||||
scatter { // making Scatter plot (sinus)
|
||||
x.set(x1) // assigning OX values
|
||||
y.set(y1) // assigning OY values
|
||||
line { color(XKCD.CERULEAN) } // color of the line is cerulean
|
||||
}
|
||||
|
||||
scatter { // making Scatter plot (OX axis dots)
|
||||
mode = ScatterMode.markers // visualizing only dots
|
||||
x(-2* PI, -PI, PI, 2* PI) // points of intersection of sinus with OX (values along the X axis)
|
||||
y(0, 0, 0, 0) // points of intersection of sinus with OX (values along the Y axis)
|
||||
line { color(XKCD.CERULEAN_BLUE) } // color of the dots is darker cerulean
|
||||
marker { size = 8 } // dot's diameter is 8 px.
|
||||
}
|
||||
|
||||
layout { ... }
|
||||
}.makeFile()
|
||||
```
|
||||
3. Let's draw horizontal dashed lines on the chart, corresponding to values equal to -1, 1 (extremum lines) and 1/2.
|
||||
This requires changing `line.dash` parameter to `Dash.dash` value. The specified values will be plotted after that
|
||||
on the OY axis using the `tickvals` and` ticklabels` parameters.
|
||||
|
||||
```kotlin
|
||||
...
|
||||
Plotly.page {
|
||||
...
|
||||
layout {
|
||||
shape { // adding new figure (line y = 1)
|
||||
x0 = Value.of(-2*PI) // (-2PI, 1) and (2PI, 1) coordinates
|
||||
x1 = Value.of(2*PI) // will be connected by a line
|
||||
y0 = Value.of(1)
|
||||
y1 = Value.of(1)
|
||||
line { dash = Dash.dash } // dashed type of the line
|
||||
}
|
||||
|
||||
shape { // adding new figure (line y = 1/2)
|
||||
x0 = Value.of(-2*PI) // coordinates (-2PI, 1/2) and (2PI, 1/2)
|
||||
x1 = Value.of(2*PI) // will be connected by a line
|
||||
y0 = Value.of(0.5)
|
||||
y1 = Value.of(0.5)
|
||||
line {
|
||||
color("red") // red color of the line
|
||||
dash = Dash.dash // dashed type of the line
|
||||
}
|
||||
}
|
||||
|
||||
shape { // adding new figure (line y = -1)
|
||||
x0 = Value.of(-2*PI) // coordinates (-2PI, -1) and (2PI, -1)
|
||||
x1 = Value.of(2*PI) // will be connected by a line
|
||||
y0 = Value.of(-1)
|
||||
y1 = Value.of(-1)
|
||||
line { dash = Dash.dash } // dashed type of the line
|
||||
}
|
||||
...
|
||||
}
|
||||
}.makeFile()
|
||||
```
|
||||
|
||||
4. After that, it is worth adding vertical lines connecting points on OX, the values in
|
||||
which equals 1/2, and the value itself in LaTeX format. Shapes are used again for this - an array
|
||||
values of type `Shape.line`. To use LaTeX format you need to include the `MathJax` header.
|
||||
|
||||
```kotlin
|
||||
...
|
||||
val sub = PI / 6
|
||||
val xElems = listOf(-2PI + sub, -PI - sub, 0 + sub, PI - sub)
|
||||
// points, where sinus equals 1/2
|
||||
|
||||
val shapesList = mutableListOf<Shape>() // making list of lines
|
||||
for (x: xElems) {
|
||||
val shape = Shape {
|
||||
x0 = Value.of(x) // (x, 0) and (x, 0.5) will be connected
|
||||
y0 = Value.of(0)
|
||||
x1 = Value.of(x)
|
||||
y0 = Value.of(1/2)
|
||||
line { color("red") } // red color of the line
|
||||
}
|
||||
shapesList.add(shape) // adding new figure to the list
|
||||
}
|
||||
|
||||
Plotly.page(mathJaxHeader, cdnPlotlyHeader) {
|
||||
scatter { // add string "1/2"
|
||||
mode = ScatterMode.text // visualing only text
|
||||
x(-0.35) // text position on the OX axis
|
||||
y(0.56) // text position on the OX axis
|
||||
text = listOf("$\Large{1/2}$") // increasing font size with ТеХ
|
||||
textfont { color("red") } // red color of the font
|
||||
showlegend = false // do not show this trace in the legend
|
||||
hoverinfo = "none" // do not show anything on hover
|
||||
}
|
||||
...
|
||||
layout { // adding figure list to the plot
|
||||
shapes = shapesList
|
||||
...
|
||||
}
|
||||
}.makeFile()
|
||||
```
|
||||
|
||||
5. It remains to add labels on OX corresponding to the intersections of the sinus with the axis. It
|
||||
is done in a similar way, using axis labels (`tickvals`,` ticktext`) and writing text in LaTeX format.
|
||||
|
||||
```kotlin
|
||||
...
|
||||
Plolty.page(mathJaxHeader, cdnPlotlyHeader) {
|
||||
...
|
||||
layout {
|
||||
xaxis { // OX axis parameters
|
||||
...
|
||||
anchor = "free" // axis position is set manually
|
||||
position = 0.43 // assigning axis position
|
||||
tickvals(listOf(-2 * PI-0.05, -PI - 0.15, PI - 0.05, 2 * PI + 0.1))
|
||||
ticktext(listOf("\$\\huge{-2\\pi}\$", "\$\\huge{-\\pi}\$", "\$\\huge{\\pi}\$", "\$\\huge{2\\pi}\$"))
|
||||
// ticks positions and text
|
||||
}
|
||||
yaxis { // OY axis parameters
|
||||
...
|
||||
anchor = "free" // axis position is set manually
|
||||
position = 0.485 // assigning axis position
|
||||
tickvals(listOf(-0.91, 0.09, 1.09))
|
||||
ticktext(listOf("\$\\Large{-1}\$", "\$\\Large{0}\$", "\$\\Large{1}\$"))
|
||||
// ticks positions and text
|
||||
}
|
||||
...
|
||||
}
|
||||
}.makeFile()
|
||||
```
|
||||
|
||||
6. As a final improvement, let's add a legend to the plot, which will be placed in upper right corner of the graph.
|
||||
First you need to set the name of the corresponding line, after which with using the parameters `xanchor = right`
|
||||
and` yanchor = top` set the position of the legend so that the coordinates specified by the parameters
|
||||
`x = 1`,` y = 1` correspond to the position in the upper right corner of the image.
|
||||
|
||||
```kotlin
|
||||
...
|
||||
Plotly.page(mathJaxHeader, cdnPlotlyHeader) {
|
||||
scatter { // sinus Scatter trace
|
||||
...
|
||||
name = "\$\\Large{y = \\mathrm{sin}\\,x}\$"
|
||||
// the name of the plot displayed in the legend
|
||||
}
|
||||
|
||||
layout {
|
||||
legend { // legend parameters
|
||||
x = 0.97 // horizontal position of the legend
|
||||
y = 1 // vertical position of the legend
|
||||
borderwidth = 1 // width of the legend border
|
||||
font { size = 32 } // size of the legend font
|
||||
xanchor = XAnchor.right // "anchoring" the position of the legend to the right corner
|
||||
yanchor = YAnchor.top // "anchoring" the position of the legend to the bottom of the graph
|
||||
}
|
||||
...
|
||||
}
|
||||
}.makeFile()
|
||||
```
|
||||
|
||||
7. Final picture:
|
||||
|
||||
![Картинка](https://i.ibb.co/wKTCp4H/newplot-17.png)
|
||||
|
||||
Source code is available at: https://github.com/mipt-npm/plotly.kt/tree/dev/examples/src/main/kotlin/tutorials/SinusPicture.kt
|
50
plotly/docs/tutorials/jupyter.md
Normal file
50
plotly/docs/tutorials/jupyter.md
Normal file
@ -0,0 +1,50 @@
|
||||
# Plotly.kt Jupyter kernel integration
|
||||
Being a JavaScript library with a Kotlin-JVM backend, Plotly.kt is ideally suited for [Jupyter kotlin kernel](https://github.com/Kotlin/kotlin-jupyter) integration. The integration is supported in two modes:
|
||||
|
||||
* Static rendering in [plotlykt-jupyter](../../plotlykt-jupyter) module.
|
||||
* Dynamic updates processing via [plotlykt-server](../../plotlykt-server) module.
|
||||
|
||||
## Loading the library
|
||||
|
||||
* Install or update [Jupyter kotlin kernel](https://github.com/Kotlin/kotlin-jupyter) to version `0.9` or later.
|
||||
* Launch kotlin kernel in `jupyter lab` (classic jupyter notebook is not supported).
|
||||
* Use `@file:DependsOn("space.kscience:plotlykt-jupyter:$plotlyVersion")` annotation directive to load library, where `$plotlyVersion` is the required version of the library. This approach uses [Kotlin jupyter notebook API](https://github.com/Kotlin/kotlin-jupyter/blob/master/docs/libraries.md#Integration-using-Kotlin-API). For dynamic version one should replace `plotlykt-server` instead of `plotlykr-jupyter`.
|
||||
* Alternatively one could use `%use plotly` [directive](https://github.com/Kotlin/kotlin-jupyter#supported-libraries). For dynamic version one should replace `plotly-server` instead of `plotly`.
|
||||
|
||||
## Automatic rendering
|
||||
|
||||
The integration automatically imports `space.kscience.plotlykt.*` and `space.kscience.plotlykt.models.*` and provides automatic rendering for three basic plotly objects: `Plot`, `PlotlyFragment` and `PlotlyPage`. One needs to return those object as result of last expressions in a cell in order to automatically render them.
|
||||
|
||||
## Dynamic update server
|
||||
|
||||
The dynamic server uses three-way communication to provide updates for the jupyter cell content:
|
||||
|
||||
* Jupyter kernel server
|
||||
* Browser Plotly API (websockets)
|
||||
* Ktor server which provides both static data and updates via web-sockets.
|
||||
|
||||
When the plot is placed into the page, its initial data is embedded into the page as plotly-compatible JSON alongside the path to data server and updates server.
|
||||
|
||||
The resulting HTML looks like this:
|
||||
```html
|
||||
<div id="space.kscience.plotly.Plot@502ed4cc">
|
||||
<script>
|
||||
makePlot(
|
||||
'space.kscience.plotly.Plot@502ed4cc',
|
||||
[/*plot data*/],
|
||||
{/*layout*/},
|
||||
{}
|
||||
);
|
||||
startPush('space.kscience.plotly.Plot@502ed4cc', 'ws://127.0.0.1:3872//ws/space.kscience.plotly.Plot@502ed4cc');
|
||||
</script>
|
||||
</div>
|
||||
```
|
||||
|
||||
The changes in the back-end model are automatically collected and sent to the notebook with fixed intervals (if present).
|
||||
The interval is `100 ms` by default and could be changed via `plotly.updateInterval = 200` line. The server is restarted on interval change.
|
||||
|
||||
The local port used for the server (default is `8882`) also could be changed via configuration object (`plotly.port = 8884`). After port change, all plots that use dynamic updates must be re-created to ensure they use correct update location.
|
||||
|
||||
## What about classic notebook?
|
||||
|
||||
At this moment only Jupyter lab is supported. Classic notebook does not work well because it does not allow loading JS resources globally after the notebook is started. We will research the possibility to support classic notebook as well as other IPython kernels in the future.
|
4
plotly/examples/README.md
Normal file
4
plotly/examples/README.md
Normal file
@ -0,0 +1,4 @@
|
||||
# Module examples
|
||||
|
||||
|
||||
|
44
plotly/examples/build.gradle.kts
Normal file
44
plotly/examples/build.gradle.kts
Normal file
@ -0,0 +1,44 @@
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven("https://repo.kotlin.link")
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(projects.plotly.plotlyktServer)
|
||||
implementation(projects.plotly.plotlyktJupyter)
|
||||
implementation(projects.plotly.plotlyktGeo)
|
||||
implementation(projects.plotly.plotlyktScript)
|
||||
implementation(kotlin("script-runtime"))
|
||||
implementation("org.jetbrains.kotlinx:dataframe:0.13.1")
|
||||
}
|
||||
|
||||
kotlin{
|
||||
jvmToolchain(11)
|
||||
}
|
||||
|
||||
// A workaround for https://youtrack.jetbrains.com/issue/KT-44101
|
||||
|
||||
val copyPlotlyResources by tasks.creating(Copy::class){
|
||||
dependsOn(":plotly:plotlykt-core:jvmProcessResources")
|
||||
mustRunAfter(":plotly:plotlykt-core:jvmTestProcessResources")
|
||||
from(project(":plotly:plotlykt-core").layout.buildDirectory.file("processedResources/jvm"))
|
||||
into(layout.buildDirectory.file("resources"))
|
||||
}
|
||||
|
||||
tasks.getByName("classes").dependsOn(copyPlotlyResources)
|
||||
|
||||
//val runDynamicServer by tasks.creating(JavaExec::class){
|
||||
// group = "run"
|
||||
// classpath = sourceSets["main"].runtimeClasspath
|
||||
// main = "DynamicServerKt"
|
||||
//}
|
||||
//
|
||||
//val runCustomPage by tasks.creating(JavaExec::class){
|
||||
// group = "run"
|
||||
// classpath = sourceSets["main"].runtimeClasspath
|
||||
// main = "CustomPageKt"
|
||||
//}
|
4
plotly/examples/compose-demo/README.md
Normal file
4
plotly/examples/compose-demo/README.md
Normal file
@ -0,0 +1,4 @@
|
||||
# Module compose-demo
|
||||
|
||||
|
||||
|
26
plotly/examples/compose-demo/api/compose-demo.api
Normal file
26
plotly/examples/compose-demo/api/compose-demo.api
Normal file
@ -0,0 +1,26 @@
|
||||
public final class space/kscience/plotly/compose/AppKt {
|
||||
public static final fun App (Landroidx/compose/runtime/Composer;I)V
|
||||
public static final fun main ()V
|
||||
public static synthetic fun main ([Ljava/lang/String;)V
|
||||
}
|
||||
|
||||
public final class space/kscience/plotly/compose/ComposableSingletons$AppKt {
|
||||
public static final field INSTANCE Lspace/kscience/plotly/compose/ComposableSingletons$AppKt;
|
||||
public static field lambda-1 Lkotlin/jvm/functions/Function3;
|
||||
public static field lambda-2 Lkotlin/jvm/functions/Function3;
|
||||
public static field lambda-3 Lkotlin/jvm/functions/Function2;
|
||||
public static field lambda-4 Lkotlin/jvm/functions/Function3;
|
||||
public static field lambda-5 Lkotlin/jvm/functions/Function3;
|
||||
public fun <init> ()V
|
||||
public final fun getLambda-1$compose_demo ()Lkotlin/jvm/functions/Function3;
|
||||
public final fun getLambda-2$compose_demo ()Lkotlin/jvm/functions/Function3;
|
||||
public final fun getLambda-3$compose_demo ()Lkotlin/jvm/functions/Function2;
|
||||
public final fun getLambda-4$compose_demo ()Lkotlin/jvm/functions/Function3;
|
||||
public final fun getLambda-5$compose_demo ()Lkotlin/jvm/functions/Function3;
|
||||
}
|
||||
|
||||
public final class space/kscience/plotly/compose/ServerKt {
|
||||
public static final fun servePlots (Lkotlinx/coroutines/CoroutineScope;Lkotlinx/coroutines/flow/StateFlow;)Lio/ktor/server/engine/ApplicationEngine;
|
||||
public static final fun staticPlot ()Ljava/lang/String;
|
||||
}
|
||||
|
43
plotly/examples/compose-demo/build.gradle.kts
Normal file
43
plotly/examples/compose-demo/build.gradle.kts
Normal file
@ -0,0 +1,43 @@
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
plugins {
|
||||
kotlin("multiplatform")
|
||||
alias(spclibs.plugins.compose.compiler)
|
||||
alias(spclibs.plugins.compose.jb)
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven("https://repo.kotlin.link")
|
||||
maven("https://jogamp.org/deployment/maven")
|
||||
}
|
||||
|
||||
kotlin {
|
||||
jvm()
|
||||
jvmToolchain(17)
|
||||
sourceSets {
|
||||
jvmMain {
|
||||
dependencies {
|
||||
implementation(compose.runtime)
|
||||
implementation(compose.foundation)
|
||||
implementation(compose.material)
|
||||
implementation(compose.desktop.currentOs)
|
||||
implementation("io.github.kevinnzou:compose-webview-multiplatform:1.9.8")
|
||||
implementation(projects.plotly.plotlyktServer)
|
||||
implementation(spclibs.logback.classic)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType<KotlinCompile> {
|
||||
kotlinOptions.freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn"
|
||||
}
|
||||
|
||||
compose {
|
||||
desktop {
|
||||
application {
|
||||
mainClass = "space.kscience.plotly.compose.AppKt"
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
package space.kscience.plotly.compose
|
||||
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Window
|
||||
import androidx.compose.ui.window.application
|
||||
import com.multiplatform.webview.web.LoadingState
|
||||
import com.multiplatform.webview.web.WebView
|
||||
import com.multiplatform.webview.web.rememberWebViewNavigator
|
||||
import com.multiplatform.webview.web.rememberWebViewStateWithHTMLData
|
||||
import dev.datlag.kcef.KCEF
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
||||
private val allowedPages = listOf(
|
||||
"Static",
|
||||
"Dynamic"
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun App() {
|
||||
val scaleFlow = remember { MutableStateFlow(1f) }
|
||||
val scale by scaleFlow.collectAsState()
|
||||
val scope = rememberCoroutineScope()
|
||||
val server = remember {
|
||||
scope.servePlots(scaleFlow)
|
||||
}
|
||||
|
||||
val state = rememberWebViewStateWithHTMLData(staticPlot())
|
||||
|
||||
val navigator = rememberWebViewNavigator()
|
||||
|
||||
val loadingState = state.loadingState
|
||||
if (loadingState is LoadingState.Loading) {
|
||||
LinearProgressIndicator(
|
||||
progress = loadingState.progress,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
}
|
||||
|
||||
Row(Modifier.fillMaxSize()) {
|
||||
Column(Modifier.width(300.dp)) {
|
||||
Button({ navigator.loadHtml(staticPlot()) }, modifier = Modifier.fillMaxWidth()) {
|
||||
Text("Static")
|
||||
}
|
||||
Button({ navigator.loadUrl("http://localhost:7778/Dynamic") }, modifier = Modifier.fillMaxWidth()) {
|
||||
Text("Dynamic")
|
||||
}
|
||||
|
||||
Slider(
|
||||
scale,
|
||||
{ scaleFlow.value = it },
|
||||
valueRange = 0.1f..10f,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
}
|
||||
Column(Modifier.fillMaxSize()) {
|
||||
|
||||
WebView(
|
||||
state = state,
|
||||
navigator = navigator,
|
||||
modifier = Modifier.fillMaxSize()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun main() = application {
|
||||
KCEF.initBlocking(
|
||||
builder = {
|
||||
progress {
|
||||
onDownloading {
|
||||
println("Download progress: $it%")
|
||||
}
|
||||
}
|
||||
release(true)
|
||||
}
|
||||
)
|
||||
Window(onCloseRequest = ::exitApplication) {
|
||||
MaterialTheme {
|
||||
App()
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
package space.kscience.plotly.compose
|
||||
|
||||
import io.ktor.server.engine.ApplicationEngine
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.launch
|
||||
import space.kscience.plotly.*
|
||||
import space.kscience.plotly.models.Scatter
|
||||
import space.kscience.plotly.models.invoke
|
||||
import space.kscience.plotly.server.pushUpdates
|
||||
import space.kscience.plotly.server.serve
|
||||
import kotlin.math.PI
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
|
||||
fun staticPlot(): String = Plotly.page {
|
||||
val x = (0..100).map { it.toDouble() / 100.0 }.toDoubleArray()
|
||||
val y1 = x.map { sin(2.0 * PI * it) }.toDoubleArray()
|
||||
val y2 = x.map { cos(2.0 * PI * it) }.toDoubleArray()
|
||||
val trace1 = Scatter(x, y1) {
|
||||
name = "sin"
|
||||
}
|
||||
val trace2 = Scatter(x, y2) {
|
||||
name = "cos"
|
||||
}
|
||||
plot(config = PlotlyConfig { responsive = true }) {//static plot
|
||||
traces(trace1, trace2)
|
||||
layout {
|
||||
title = "First graph, row: 1, size: 8/12"
|
||||
xaxis.title = "x axis name"
|
||||
yaxis { title = "y axis name" }
|
||||
}
|
||||
}
|
||||
}.render()
|
||||
|
||||
fun CoroutineScope.servePlots(scale: StateFlow<Number>): ApplicationEngine = Plotly.serve(this, port = 7778) {
|
||||
page("Static") { container ->
|
||||
val x = (0..100).map { it.toDouble() / 100.0 }.toDoubleArray()
|
||||
val y1 = x.map { sin(2.0 * PI * it) }.toDoubleArray()
|
||||
val y2 = x.map { cos(2.0 * PI * it) }.toDoubleArray()
|
||||
val trace1 = Scatter(x, y1) {
|
||||
name = "sin"
|
||||
}
|
||||
val trace2 = Scatter(x, y2) {
|
||||
name = "cos"
|
||||
}
|
||||
plot(renderer = container) {//static plot
|
||||
traces(trace1, trace2)
|
||||
layout {
|
||||
title = "First graph, row: 1, size: 8/12"
|
||||
xaxis.title = "x axis name"
|
||||
yaxis { title = "y axis name" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
page("Dynamic") { container ->
|
||||
val x = (0..100).map { it.toDouble() / 100.0 }
|
||||
val y = x.map { sin(2.0 * PI * it) }
|
||||
|
||||
val trace = Scatter(x, y) { name = "sin" }
|
||||
|
||||
val plot = plot("dynamic", config = PlotlyConfig { responsive = true }, renderer = container) {
|
||||
traces(trace)
|
||||
layout {
|
||||
title = "Dynamic plot"
|
||||
xaxis.title = "x axis name"
|
||||
yaxis.title = "y axis name"
|
||||
}
|
||||
}
|
||||
|
||||
launch {
|
||||
var time: Long = 0
|
||||
while (isActive) {
|
||||
delay(10)
|
||||
time += 10
|
||||
val frequency = scale.value.toDouble()
|
||||
val dynamicY = x.map { sin(2.0 * PI * frequency * (it + time.toDouble() / 1000.0)) }
|
||||
//trace.y.numbers = dynamicY
|
||||
plot.data[0].y.numbers = dynamicY
|
||||
plot.layout {
|
||||
xaxis.title = "x axis name (t = $time)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pushUpdates(100)
|
||||
}
|
||||
|
||||
|
4
plotly/examples/fx-demo/README.md
Normal file
4
plotly/examples/fx-demo/README.md
Normal file
@ -0,0 +1,4 @@
|
||||
# Module fx-demo
|
||||
|
||||
|
||||
|
35
plotly/examples/fx-demo/build.gradle.kts
Normal file
35
plotly/examples/fx-demo/build.gradle.kts
Normal file
@ -0,0 +1,35 @@
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
application
|
||||
id("org.openjfx.javafxplugin") version "0.0.10"
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven("https://repo.kotlin.link")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":plotly:plotlykt-server"))
|
||||
implementation("no.tornado:tornadofx:1.7.20")
|
||||
implementation(spclibs.logback.classic)
|
||||
}
|
||||
|
||||
javafx{
|
||||
modules("javafx.web")
|
||||
version = "11"
|
||||
}
|
||||
|
||||
application {
|
||||
mainClass.set("space.kscience.plotly.fx.PlotlyFXAppKt")
|
||||
}
|
||||
|
||||
kotlin{
|
||||
jvmToolchain(11)
|
||||
}
|
||||
|
||||
tasks.withType<KotlinCompile> {
|
||||
kotlinOptions.freeCompilerArgs = kotlinOptions.freeCompilerArgs +"-Xopt-in=kotlin.RequiresOptIn"
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
package space.kscience.plotly.fx
|
||||
|
||||
import javafx.beans.property.SimpleBooleanProperty
|
||||
import javafx.scene.control.SelectionMode
|
||||
import tornadofx.*
|
||||
|
||||
class PlotlyApp : App(PlotlyView::class)
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
launch<PlotlyApp>(args)
|
||||
}
|
||||
|
||||
class PlotlyView : View("Hello PlotlyFX") {
|
||||
private val controller: PlotlyFXController by inject()
|
||||
private val hide = SimpleBooleanProperty(false)
|
||||
override val root = hbox {
|
||||
listview(controller.pages) {
|
||||
selectionModel.selectionMode = SelectionMode.SINGLE
|
||||
selectionModel.selectedItemProperty().addListener(
|
||||
ChangeListener { _, _, value ->
|
||||
hide.value = value != "Dynamic"
|
||||
controller.displayPage(value)
|
||||
}
|
||||
)
|
||||
}
|
||||
vbox {
|
||||
stackpane {
|
||||
webview {
|
||||
engine.isJavaScriptEnabled = true
|
||||
engine.loadWorker.stateProperty().onChange {
|
||||
log.info("WebEngine worker state: $it")
|
||||
}
|
||||
|
||||
engine.loadWorker.exceptionProperty().onChange {
|
||||
log.severe(it?.stackTraceToString())
|
||||
}
|
||||
engine.loadWorker.workDoneProperty().onChange {
|
||||
log.info("Work done: $it")
|
||||
}
|
||||
|
||||
engine.setOnError {
|
||||
log.warning(it.message)
|
||||
}
|
||||
engine.setOnAlert {
|
||||
log.info(it.data)
|
||||
}
|
||||
|
||||
controller.address.onChange {
|
||||
if (it != null) {
|
||||
log.info("Displaying $it")
|
||||
engine.load(it.replace("localhost", "127.0.0.1"))
|
||||
}
|
||||
}
|
||||
}
|
||||
progressindicator {
|
||||
hiddenWhen(controller.address.isNotEmpty)
|
||||
}
|
||||
}
|
||||
slider(1.0, 100.0, 1.0) {
|
||||
hiddenWhen(hide)
|
||||
isShowTickLabels = true
|
||||
isShowTickMarks = true
|
||||
controller.scale.bind(valueProperty())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
controller.startServer()
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package space.kscience.plotly.fx
|
||||
|
||||
import io.ktor.server.engine.ApplicationEngine
|
||||
import javafx.beans.property.SimpleIntegerProperty
|
||||
import javafx.beans.property.SimpleStringProperty
|
||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import tornadofx.*
|
||||
import java.net.URI
|
||||
|
||||
class PlotlyFXController : Controller() {
|
||||
|
||||
val scale = SimpleIntegerProperty(1)
|
||||
|
||||
private var server: ApplicationEngine? = null
|
||||
|
||||
@OptIn(DelicateCoroutinesApi::class)
|
||||
fun startServer() {
|
||||
GlobalScope.launch(Dispatchers.Default) {
|
||||
log.info("Starting server")
|
||||
server = serve(scale)
|
||||
log.info("Server started")
|
||||
runLater {
|
||||
displayPage(pages.first())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val pages = observableListOf(
|
||||
"Dynamic",
|
||||
"Static"
|
||||
)
|
||||
|
||||
val address = SimpleStringProperty()
|
||||
|
||||
fun displayPage(page: String) {
|
||||
server?.let {
|
||||
val connector = it.environment.connectors.first()
|
||||
val uri = URI("http", null, connector.host, connector.port, null, null, null)
|
||||
address.set("$uri/$page")
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
package space.kscience.plotly.fx
|
||||
|
||||
import javafx.beans.value.ObservableIntegerValue
|
||||
import kotlinx.coroutines.*
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.layout
|
||||
import space.kscience.plotly.models.Trace
|
||||
import space.kscience.plotly.models.invoke
|
||||
import space.kscience.plotly.plot
|
||||
import space.kscience.plotly.server.pushUpdates
|
||||
import space.kscience.plotly.server.serve
|
||||
import kotlin.math.PI
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
|
||||
@OptIn(DelicateCoroutinesApi::class)
|
||||
fun serve(scale: ObservableIntegerValue) = Plotly.serve(port = 7778) {
|
||||
embedData = true //Should be set this way to avoid FX browser bug
|
||||
|
||||
page("Static") {
|
||||
val x = (0..100).map { it.toDouble() / 100.0 }.toDoubleArray()
|
||||
val y1 = x.map { sin(2.0 * PI * it) }.toDoubleArray()
|
||||
val y2 = x.map { cos(2.0 * PI * it) }.toDoubleArray()
|
||||
val trace1 = Trace(x, y1) {
|
||||
name = "sin"
|
||||
}
|
||||
val trace2 = Trace(x, y2) {
|
||||
name = "cos"
|
||||
}
|
||||
plot {//static plot
|
||||
traces(trace1, trace2)
|
||||
layout {
|
||||
title = "First graph, row: 1, size: 8/12"
|
||||
xaxis.title = "x axis name"
|
||||
yaxis { title = "y axis name" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
page("Dynamic") { container ->
|
||||
val x = (0..100).map { it.toDouble() / 100.0 }
|
||||
val y = x.map { sin(2.0 * PI * it) }
|
||||
|
||||
val trace = Trace(x, y) { name = "sin" }
|
||||
|
||||
val plot = plot("dynamic", renderer = container) {
|
||||
traces(trace)
|
||||
layout {
|
||||
title = "Dynamic plot"
|
||||
xaxis.title = "x axis name"
|
||||
yaxis.title = "y axis name"
|
||||
}
|
||||
}
|
||||
|
||||
GlobalScope.launch {
|
||||
var time: Long = 0
|
||||
while (isActive) {
|
||||
delay(10)
|
||||
time += 10
|
||||
val frequency = scale.get().toDouble()
|
||||
val dynamicY = x.map { sin(2.0 * PI * frequency * (it + time.toDouble() / 1000.0)) }
|
||||
//trace.y.numbers = dynamicY
|
||||
plot.data[0].y.numbers = dynamicY
|
||||
plot.layout{
|
||||
xaxis.title = "x axis name (t = $time)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pushUpdates(100)
|
||||
}
|
||||
|
||||
|
4
plotly/examples/js-demo/README.md
Normal file
4
plotly/examples/js-demo/README.md
Normal file
@ -0,0 +1,4 @@
|
||||
# Module js-demo
|
||||
|
||||
|
||||
|
27
plotly/examples/js-demo/build.gradle.kts
Normal file
27
plotly/examples/js-demo/build.gradle.kts
Normal file
@ -0,0 +1,27 @@
|
||||
plugins {
|
||||
kotlin("multiplatform")
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven("https://repo.kotlin.link")
|
||||
}
|
||||
|
||||
kotlin {
|
||||
js(IR) {
|
||||
browser()
|
||||
binaries.executable()
|
||||
}
|
||||
sourceSets{
|
||||
jsMain{
|
||||
dependencies{
|
||||
implementation(projects.plotly.plotlyktCore)
|
||||
implementation(spclibs.kotlinx.coroutines.core)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
|
||||
kotlinOptions.freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn"
|
||||
}
|
@ -0,0 +1,142 @@
|
||||
package space.kscience.plotly.jsdemo
|
||||
|
||||
|
||||
import kotlinx.browser.document
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.html.TagConsumer
|
||||
import kotlinx.html.dom.append
|
||||
import kotlinx.html.h1
|
||||
import kotlinx.html.js.div
|
||||
import kotlinx.html.style
|
||||
import kotlinx.serialization.json.Json
|
||||
import org.w3c.dom.HTMLElement
|
||||
import org.w3c.dom.events.Event
|
||||
import space.kscience.dataforge.meta.MetaSerializer
|
||||
import space.kscience.plotly.*
|
||||
import space.kscience.plotly.events.PlotlyEventListenerType
|
||||
import space.kscience.plotly.models.ScatterMode
|
||||
import space.kscience.plotly.models.TraceType
|
||||
import kotlin.random.Random
|
||||
|
||||
private fun onDomLoaded(block: (Event) -> Unit) {
|
||||
document.addEventListener("DOMContentLoaded", block)
|
||||
}
|
||||
|
||||
private fun withCanvas(block: TagConsumer<HTMLElement>.() -> Unit) = onDomLoaded {
|
||||
val element = document.getElementById("canvas") as? HTMLElement
|
||||
?: error("Element with id 'app' not found on page")
|
||||
console.log("element loaded")
|
||||
element.append { block() }
|
||||
}
|
||||
|
||||
|
||||
@OptIn(DelicateCoroutinesApi::class)
|
||||
fun main(): Unit = withCanvas {
|
||||
div {
|
||||
style = "height:50%; width=100%;"
|
||||
h1 { +"Histogram demo" }
|
||||
plotDiv {
|
||||
val rnd = Random(222)
|
||||
histogram {
|
||||
name = "Random data"
|
||||
GlobalScope.launch {
|
||||
while (isActive) {
|
||||
x.numbers = List(500) { rnd.nextDouble() }
|
||||
delay(300)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
layout {
|
||||
bargap = 0.1
|
||||
title {
|
||||
text = "Basic Histogram"
|
||||
font {
|
||||
size = 20
|
||||
color("black")
|
||||
}
|
||||
}
|
||||
xaxis {
|
||||
title {
|
||||
text = "Value"
|
||||
font {
|
||||
size = 16
|
||||
}
|
||||
}
|
||||
}
|
||||
yaxis {
|
||||
title {
|
||||
text = "Count"
|
||||
font {
|
||||
size = 16
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
div {
|
||||
style = "height:50%; width=100%;"
|
||||
h1 { +"Dynamic trace demo" }
|
||||
plotDiv {
|
||||
scatter {
|
||||
x(1, 2, 3, 4)
|
||||
y(10, 15, 13, 17)
|
||||
mode = ScatterMode.markers
|
||||
type = TraceType.scatter
|
||||
}
|
||||
scatter {
|
||||
x(2, 3, 4, 5)
|
||||
y(10, 15, 13, 17)
|
||||
mode = ScatterMode.lines
|
||||
type = TraceType.scatter
|
||||
|
||||
GlobalScope.launch {
|
||||
while (isActive) {
|
||||
delay(500)
|
||||
marker {
|
||||
if (Random.nextBoolean()) {
|
||||
color("magenta")
|
||||
} else {
|
||||
color("blue")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
scatter {
|
||||
x(1, 2, 3, 4)
|
||||
y(12, 5, 2, 12)
|
||||
mode = ScatterMode.`lines+markers`
|
||||
type = TraceType.scatter
|
||||
marker {
|
||||
color("red")
|
||||
}
|
||||
}
|
||||
layout {
|
||||
title = "Line and Scatter Plot"
|
||||
}
|
||||
}
|
||||
}
|
||||
div {
|
||||
style = "height:50%; width=100%;"
|
||||
h1 { +"Deserialization" }
|
||||
val plot = Plotly.plot {
|
||||
scatter {
|
||||
x(1, 2, 3, 4)
|
||||
y(10, 15, 13, 17)
|
||||
mode = ScatterMode.markers
|
||||
type = TraceType.scatter
|
||||
}
|
||||
}
|
||||
val serialized = plot.toJsonString()
|
||||
console.log(serialized)
|
||||
val deserialized = Plot(Json.decodeFromString(MetaSerializer, serialized))
|
||||
plotDiv(plot = deserialized).on(PlotlyEventListenerType.CLICK){
|
||||
console.info(it.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
11
plotly/examples/js-demo/src/main/resources/index.html
Normal file
11
plotly/examples/js-demo/src/main/resources/index.html
Normal file
@ -0,0 +1,11 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Plotly.kt js demo</title>
|
||||
<script type="text/javascript" src="js-demo.js"></script>
|
||||
</head>
|
||||
<body id="application">
|
||||
<div id="canvas"></div>
|
||||
</body>
|
||||
</html>
|
4
plotly/examples/native-demo/README.md
Normal file
4
plotly/examples/native-demo/README.md
Normal file
@ -0,0 +1,4 @@
|
||||
# Module native-demo
|
||||
|
||||
|
||||
|
30
plotly/examples/native-demo/build.gradle.kts
Normal file
30
plotly/examples/native-demo/build.gradle.kts
Normal file
@ -0,0 +1,30 @@
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
plugins {
|
||||
kotlin("multiplatform")
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven("https://repo.kotlin.link")
|
||||
}
|
||||
|
||||
kotlin {
|
||||
linuxX64{
|
||||
binaries{
|
||||
executable()
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets{
|
||||
commonMain {
|
||||
dependencies {
|
||||
implementation(project(":plotly:plotlykt-core"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType<KotlinCompile> {
|
||||
kotlinOptions.freeCompilerArgs = kotlinOptions.freeCompilerArgs +"-Xopt-in=kotlin.RequiresOptIn"
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
import kotlinx.html.div
|
||||
import kotlinx.html.h1
|
||||
import kotlinx.html.hr
|
||||
import space.kscience.plotly.*
|
||||
import space.kscience.plotly.models.Trace
|
||||
import space.kscience.plotly.models.invoke
|
||||
import kotlin.math.PI
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
|
||||
/**
|
||||
* Creates a renderable plotly html
|
||||
*/
|
||||
@OptIn(UnstablePlotlyAPI::class)
|
||||
fun main() {
|
||||
val x1 = (0..100).map { it.toDouble() / 100.0 }
|
||||
val y1 = x1.map { sin(2.0 * PI * it) }
|
||||
val y2 = x1.map { cos(2.0 * PI * it) }
|
||||
|
||||
val trace1 = Trace(x1, y1) { name = "sin" }
|
||||
val trace2 = Trace(x1, y2) { name = "cos" }
|
||||
|
||||
Plotly.page { container ->
|
||||
h1 { +"This is a plotly page" }
|
||||
plot(renderer = container) {
|
||||
traces(trace1, trace2)
|
||||
layout {
|
||||
title = "The plot above"
|
||||
xaxis.title = "x axis name"
|
||||
yaxis.title = "y axis name"
|
||||
}
|
||||
}
|
||||
hr()
|
||||
h1 { +"A custom separator" }
|
||||
hr()
|
||||
div {
|
||||
plot {
|
||||
traces(trace1, trace2)
|
||||
layout {
|
||||
title = "The plot below"
|
||||
xaxis.title = "x axis name"
|
||||
yaxis.title = "y axis name"
|
||||
}
|
||||
}
|
||||
}
|
||||
}.makeFile("plotly.html")
|
||||
}
|
@ -0,0 +1,298 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%use plotly"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# API"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"enum class Severity(val penalty: Double){\n",
|
||||
" MINOR(1.0),\n",
|
||||
" MAJOR(2.0),\n",
|
||||
" CRITICAL(3.0)\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"enum class State{\n",
|
||||
" OPEN,\n",
|
||||
" ASSIGNED,\n",
|
||||
" RESOLVED\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"data class Issue(val id: String, val dayCreated: Int, val severity: Severity, val complexity: Int, \n",
|
||||
" var state: State = State.OPEN, var dayAssigned: Int? = null, var dayResolved: Int? = null){\n",
|
||||
" fun activate(day: Int){ \n",
|
||||
" state = State.ASSIGNED\n",
|
||||
" dayAssigned = day\n",
|
||||
" }\n",
|
||||
" \n",
|
||||
" fun resolve(day: Int){\n",
|
||||
" state = State.RESOLVED\n",
|
||||
" dayResolved = day\n",
|
||||
" }\n",
|
||||
" \n",
|
||||
" internal fun tryResolve(day: Int){\n",
|
||||
" if(state == State.ASSIGNED && day >= (dayAssigned ?: 0) + complexity ){\n",
|
||||
" resolve(day)\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"class Worker(val name: String){\n",
|
||||
" var currentIssue: Issue? = null\n",
|
||||
" private set\n",
|
||||
" \n",
|
||||
" fun isBusy(): Boolean = currentIssue != null\n",
|
||||
" \n",
|
||||
" fun update(day: Int){\n",
|
||||
" currentIssue?.tryResolve(day)\n",
|
||||
" if(currentIssue?.state == State.RESOLVED){\n",
|
||||
" currentIssue = null\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
" \n",
|
||||
" fun assign(day: Int, issue: Issue){\n",
|
||||
" if(currentIssue != null) error(\"Can't assign work to a worker which is busy\")\n",
|
||||
" issue.activate(day)\n",
|
||||
" currentIssue = issue\n",
|
||||
" }\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"interface IssueGenerator{\n",
|
||||
" fun generate(day: Int): List<Issue>\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"interface Strategy{\n",
|
||||
" fun selectIssue(day: Int, issues: List<Issue>): Issue?\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"class WorkResult(val issues: List<Issue>, val workers: Int, val days: Int)\n",
|
||||
"\n",
|
||||
"@OptIn(kotlin.ExperimentalStdlibApi::class)\n",
|
||||
"fun simulate(generator: IssueGenerator, strategy: Strategy, numWorkers: Int = 10, days: Int = 100): WorkResult{\n",
|
||||
" val workers = (0 until numWorkers).map{Worker(\"worker $it\")}\n",
|
||||
" val issues = buildList<Issue>{\n",
|
||||
" for(day in 0 until days){\n",
|
||||
" //update all workers\n",
|
||||
" workers.forEach { it.update(day) }\n",
|
||||
" //generate new issues\n",
|
||||
" val newIssues = generator.generate(day)\n",
|
||||
" addAll(newIssues)\n",
|
||||
" //Select all free workers\n",
|
||||
" workers.filter { !it.isBusy() }.forEach { worker->\n",
|
||||
" val unasigned = filter { it.state == State.OPEN }\n",
|
||||
" val anIssue = strategy.selectIssue(day, unasigned) //select an issue to assign from all unassigned issues\n",
|
||||
" if(anIssue != null){\n",
|
||||
" worker.assign(day, anIssue)\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
" return WorkResult(issues, numWorkers, days)\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"fun WorkResult.computeLoss(): Double = issues.sumByDouble { ((it.dayResolved ?: days) - it.dayCreated)*it.severity.penalty } / days / workers / issues.size"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Implementations"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import kotlin.random.Random\n",
|
||||
"import kotlin.math.pow\n",
|
||||
"\n",
|
||||
"/**\n",
|
||||
"* Generate one random issue per day\n",
|
||||
"*/\n",
|
||||
"class RandomIssueGenerator(seed: Long, val issuesPerDay: Int = 4 ) : IssueGenerator{\n",
|
||||
" private val random = Random(seed)\n",
|
||||
" override fun generate(day: Int): List<Issue>{\n",
|
||||
" return List(issuesPerDay){\n",
|
||||
" val severity = Severity.values()[random.nextInt(3)]\n",
|
||||
" val complexity = random.nextInt(15)\n",
|
||||
" Issue(\"${day}_${it}\", day, severity, complexity)\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"object TakeOldest: Strategy{\n",
|
||||
" override fun selectIssue(day: Int, issues: List<Issue>): Issue?{\n",
|
||||
" return issues.minByOrNull { it.dayCreated }\n",
|
||||
" }\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"class TakeRandom(seed: Long): Strategy{\n",
|
||||
" private val random = Random(seed)\n",
|
||||
" override fun selectIssue(day: Int, issues: List<Issue>): Issue?{\n",
|
||||
" if(issues.isEmpty()) return null\n",
|
||||
" return issues.random(random)\n",
|
||||
" }\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"object TakeCritical: Strategy{\n",
|
||||
" override fun selectIssue(day: Int, issues: List<Issue>): Issue?{\n",
|
||||
" return issues.maxByOrNull { it.severity.penalty*(day - it.dayCreated) }\n",
|
||||
" }\n",
|
||||
"}\n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Simulate lossseverity"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"val seed = 89L\n",
|
||||
"val days = 100\n",
|
||||
"val workers = 10"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Take oldest"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"val result = simulate(RandomIssueGenerator(seed, workers),TakeOldest, days = days)\n",
|
||||
"//result.issues.forEach { println(it)}\n",
|
||||
"result.computeLoss()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Take random"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"simulate(RandomIssueGenerator(seed, workers),TakeRandom(seed), days = days).computeLoss()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Take critical"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"simulate(RandomIssueGenerator(seed, workers), TakeCritical, days = days).computeLoss()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"val seeds = List(1000){Random.nextLong()}\n",
|
||||
"\n",
|
||||
"Plotly.plot{\n",
|
||||
" trace{\n",
|
||||
" x.numbers = seeds.map{ seed -> simulate(RandomIssueGenerator(seed, workers), TakeOldest, days = days).computeLoss()}\n",
|
||||
" name = \"oldest\"\n",
|
||||
" type = TraceType.histogram\n",
|
||||
" }\n",
|
||||
" trace{\n",
|
||||
" x.numbers = seeds.map{ seed -> simulate(RandomIssueGenerator(seed, workers), TakeRandom(seed), days = days).computeLoss()}\n",
|
||||
" name = \"random\"\n",
|
||||
" type = TraceType.histogram\n",
|
||||
" }\n",
|
||||
" trace{\n",
|
||||
" x.numbers = seeds.map{ seed -> simulate(RandomIssueGenerator(seed, workers), TakeCritical, days = days).computeLoss()}\n",
|
||||
" name = \"critical\"\n",
|
||||
" type = TraceType.histogram\n",
|
||||
" }\n",
|
||||
" layout{\n",
|
||||
" title = \"Loss distribtution\"\n",
|
||||
" xaxis {\n",
|
||||
" title = \"Loss\"\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Kotlin",
|
||||
"language": "kotlin",
|
||||
"name": "kotlin"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": "text/x-kotlin",
|
||||
"file_extension": ".kt",
|
||||
"mimetype": "text/x-kotlin",
|
||||
"name": "kotlin",
|
||||
"nbconvert_exporter": "",
|
||||
"pygments_lexer": "kotlin",
|
||||
"version": "1.5.30-dev-598"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
@ -0,0 +1,334 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"21:08:36.601 [DefaultDispatcher-worker-1] INFO ktor.application - No ktor.deployment.watch patterns specified, automatic reload is not active\n",
|
||||
"21:08:36.645 [DefaultDispatcher-worker-1] INFO ktor.application - Responding at http://0.0.0.0:8882\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<div id=\"plotly-load-scripts\"></div>\n",
|
||||
"<script type=\"text/javascript\">(function() {\n",
|
||||
" console.log(\"Starting up plotly script loader\");\n",
|
||||
" //initialize LaTeX for Jupyter\n",
|
||||
" window.PlotlyConfig = {MathJaxConfig: 'local'};\n",
|
||||
"\n",
|
||||
" window.startupPlotly = function (){\n",
|
||||
" if (window.MathJax){ \n",
|
||||
" MathJax.Hub.Config({\n",
|
||||
" SVG: {\n",
|
||||
" font: \"STIX-Web\"\n",
|
||||
" }\n",
|
||||
" });\n",
|
||||
" } \n",
|
||||
" console.info(\"Calling deferred operations in Plotly queue.\")\n",
|
||||
" window.plotlyCallQueue.forEach(function(theCall) {theCall();});\n",
|
||||
" window.plotlyCallQueue = []; \n",
|
||||
" }\n",
|
||||
"})();</script>\n",
|
||||
"<script type=\"text/javascript\" src=\"//localhost:8882/js/plotly.min.js\"></script>\n",
|
||||
"<script type=\"text/javascript\">/**\r\n",
|
||||
" * Use existing plotly or load it from the CDN if it is not available\r\n",
|
||||
" * @param action\r\n",
|
||||
" */\r\n",
|
||||
"function withPlotly(action) {\r\n",
|
||||
" if (typeof Plotly !== \"undefined\") {\r\n",
|
||||
" action(Plotly);\r\n",
|
||||
" } else if (typeof window.promiseOfPlotly !== \"undefined\") {\r\n",
|
||||
" window.promiseOfPlotly.then(plotly => action(plotly));\r\n",
|
||||
" } else {\r\n",
|
||||
" console.warn(\"Plotly not defined. Loading the script from CDN\")\r\n",
|
||||
" window.promiseOfPlotly = new Promise((accept, reject) => {\r\n",
|
||||
" let plotlyLoaderScript = document.createElement(\"script\");\r\n",
|
||||
" plotlyLoaderScript.src = \"https://cdnjs.cloudflare.com/ajax/libs/plotly.js/1.54.6/plotly.min.js\";\r\n",
|
||||
" plotlyLoaderScript.type = 'text/javascript';\r\n",
|
||||
" plotlyLoaderScript.onload = () => {\r\n",
|
||||
" accept(Plotly);\r\n",
|
||||
" }\r\n",
|
||||
" plotlyLoaderScript.onerror = (error) => {\r\n",
|
||||
" console.error(error);\r\n",
|
||||
" reject(error)\r\n",
|
||||
" }\r\n",
|
||||
" document.head.appendChild(plotlyLoaderScript);\r\n",
|
||||
" });\r\n",
|
||||
" }\r\n",
|
||||
"}\r\n",
|
||||
"\r\n",
|
||||
"/**\r\n",
|
||||
" * Request and parse json from given address\r\n",
|
||||
" * @param url {URL}\r\n",
|
||||
" * @param callback\r\n",
|
||||
" * @return Promise<Json>\r\n",
|
||||
" */\r\n",
|
||||
"function getJSON(url, callback) {\r\n",
|
||||
"\r\n",
|
||||
" function handleErrors(response) {\r\n",
|
||||
" if (!response.ok) {\r\n",
|
||||
" throw Error(response.statusText);\r\n",
|
||||
" }\r\n",
|
||||
" return response;\r\n",
|
||||
" }\r\n",
|
||||
"\r\n",
|
||||
" try {\r\n",
|
||||
" fetch(url, {\r\n",
|
||||
" method: 'GET',\r\n",
|
||||
" headers: {\r\n",
|
||||
" Accept: 'application/json',\r\n",
|
||||
" }\r\n",
|
||||
" })\r\n",
|
||||
" .then(handleErrors)\r\n",
|
||||
" .then(response => response.json())\r\n",
|
||||
" .then(json => callback(json))\r\n",
|
||||
" .catch(error => console.log(error));\r\n",
|
||||
" } catch (e) {\r\n",
|
||||
" alert(\"Fetch of plot data failed with error: \" + e)\r\n",
|
||||
" }\r\n",
|
||||
"}\r\n",
|
||||
"\r\n",
|
||||
"/**\r\n",
|
||||
" * Safe call for Plotly.newPlot\r\n",
|
||||
" * @param id\r\n",
|
||||
" * @param data\r\n",
|
||||
" * @param layout\r\n",
|
||||
" * @param config\r\n",
|
||||
" */\r\n",
|
||||
"function makePlot(id, data, layout, config) {\r\n",
|
||||
" withPlotly(plotly => plotly.newPlot(id, data, layout, config))\r\n",
|
||||
"}\r\n",
|
||||
"\r\n",
|
||||
"/**\r\n",
|
||||
" * Create a plot taking data from given url\r\n",
|
||||
" * @param id {string} element id for plot\r\n",
|
||||
" * @param from {URL} json server url\r\n",
|
||||
" * @param config {object} plotly configuration\r\n",
|
||||
" * @return {JSON}\r\n",
|
||||
" */\r\n",
|
||||
"function createPlotFrom(id, from, config = {}) {\r\n",
|
||||
" getJSON(from, json => withPlotly(plotly => {\r\n",
|
||||
" plotly.newPlot(id, json.data, json.layout, config)\r\n",
|
||||
" }));\r\n",
|
||||
"}\r\n",
|
||||
"\r\n",
|
||||
"/**\r\n",
|
||||
" * Update a plot taking data from given url\r\n",
|
||||
" * @param id {string} element id for plot\r\n",
|
||||
" * @param from {URL} json server url\r\n",
|
||||
" * @return {JSON}\r\n",
|
||||
" */\r\n",
|
||||
"function updatePlotFrom(id, from) {\r\n",
|
||||
" getJSON(from, json => withPlotly(plotly => plotly.react(id, json.data, json.layout)));\r\n",
|
||||
"}\r\n",
|
||||
"\r\n",
|
||||
"/**\r\n",
|
||||
" * Start pull updates with regular requests from client side\r\n",
|
||||
" * @param id {string}\r\n",
|
||||
" * @param from\r\n",
|
||||
" * @param millis\r\n",
|
||||
" */\r\n",
|
||||
"function startPull(id, from, millis) {\r\n",
|
||||
" let action = function () {\r\n",
|
||||
" updatePlotFrom(id, from)\r\n",
|
||||
" };\r\n",
|
||||
" window.setInterval(action, millis)\r\n",
|
||||
"}\r\n",
|
||||
"\r\n",
|
||||
"/**\r\n",
|
||||
" * Start push updates via websocket\r\n",
|
||||
" * @param id {string} element id for plot\r\n",
|
||||
" * @param ws {URL} a websocket address\r\n",
|
||||
" */\r\n",
|
||||
"function startPush(id, ws) {\r\n",
|
||||
" let socket = new WebSocket(ws);\r\n",
|
||||
"\r\n",
|
||||
" socket.onopen = function () {\r\n",
|
||||
" console.log(\"[Plotly.kt] A connection for plot with id = \" + id + \" with server established on \" + ws);\r\n",
|
||||
" };\r\n",
|
||||
"\r\n",
|
||||
" socket.onclose = function (event) {\r\n",
|
||||
" if (event.wasClean) {\r\n",
|
||||
" console.log(\"The connection with server is closed\");\r\n",
|
||||
" } else {\r\n",
|
||||
" console.log(\"The connection with server is broken\"); // Server process is dead\r\n",
|
||||
" }\r\n",
|
||||
" console.log('Code: ' + event.code + ' case: ' + event.reason);\r\n",
|
||||
" };\r\n",
|
||||
"\r\n",
|
||||
" socket.onerror = function (error) {\r\n",
|
||||
" console.error(\"Ploty push update error: \" + error.message);\r\n",
|
||||
" socket.close()\r\n",
|
||||
" };\r\n",
|
||||
"\r\n",
|
||||
" socket.onmessage = function (event) {\r\n",
|
||||
" //console.log('got message: ' + event.data);\r\n",
|
||||
" let json = JSON.parse(event.data);\r\n",
|
||||
" //TODO check if plotly is initialized in a cell\r\n",
|
||||
" if (json.plotId === id) {\r\n",
|
||||
" if (json.contentType === \"layout\") {\r\n",
|
||||
" withPlotly(plotly => plotly.relayout(id, json.content));\r\n",
|
||||
" } else if (json.contentType === \"trace\") {\r\n",
|
||||
" let content = json.content;\r\n",
|
||||
" //This is done to satisfy plotly requirements of arrays-in-arrays for data\r\n",
|
||||
" if (content.hasOwnProperty('x')) {\r\n",
|
||||
" content.x = [content.x];\r\n",
|
||||
" }\r\n",
|
||||
" if (content.hasOwnProperty('y')) {\r\n",
|
||||
" content.y = [content.y];\r\n",
|
||||
" }\r\n",
|
||||
" if (content.hasOwnProperty('z')) {\r\n",
|
||||
" content.z = [content.z];\r\n",
|
||||
" }\r\n",
|
||||
" withPlotly(plotly => plotly.restyle(id, content, json['trace']));\r\n",
|
||||
" }\r\n",
|
||||
" }\r\n",
|
||||
" };\r\n",
|
||||
"\r\n",
|
||||
" //gracefully close socket just in case\r\n",
|
||||
" window.onbeforeunload = function () {\r\n",
|
||||
" console.log(\"Gracefully closing socket\");\r\n",
|
||||
" socket.onclose = function () {\r\n",
|
||||
" }; // disable onclose handler first\r\n",
|
||||
" socket.close();\r\n",
|
||||
" };\r\n",
|
||||
"}\r\n",
|
||||
"\r\n",
|
||||
"\r\n",
|
||||
"window.startupPlotly()</script>\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"%use plotly"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2020-08-07T11:08+0300",
|
||||
"start_time": "2020-08-07T11:08+0300"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<div>\n",
|
||||
" <div id=\"scientifik.plotly.Plot@122c8b64\">\n",
|
||||
" <script>\n",
|
||||
"let theCall = function(){\n",
|
||||
" makePlot(\n",
|
||||
" 'scientifik.plotly.Plot@122c8b64',\n",
|
||||
" [{\"x\":[2,3,4,5],\"y\":[10,15,13,17],\"type\":\"scatter\"}],\n",
|
||||
" {\"annotations\":[{\"@index\":\"0\",\"x\":2,\"y\":10,\"text\":\"$\\\\alpha$\",\"font\":{\"size\":18}},{\"@index\":\"1\",\"x\":5,\"y\":17,\"text\":\"$\\\\Omega$\",\"font\":{\"size\":18}}],\"title\":{\"text\":\"$\\\\text{Plot with annotations } \\\\alpha~and~\\\\Omega$\"}},\n",
|
||||
" {\"responsive\":true}\n",
|
||||
" ); \n",
|
||||
"};\n",
|
||||
"\n",
|
||||
"if(typeof Plotly === 'undefined'){\n",
|
||||
" if(!window.plotlyCallQueue) {\n",
|
||||
" window.plotlyCallQueue = [];\n",
|
||||
" } \n",
|
||||
" window.plotlyCallQueue.push(theCall)\n",
|
||||
" window.plotlyCall(theCall);\n",
|
||||
"} else {\n",
|
||||
" theCall();\n",
|
||||
"}\n",
|
||||
"</script>\n",
|
||||
" <script id=\"scientifik.plotly.Plot@122c8b64-push\">\n",
|
||||
" \n",
|
||||
" startPush('scientifik.plotly.Plot@122c8b64', 'ws://localhost:8882/ws/scientifik.plotly.Plot@122c8b64');\n",
|
||||
" \n",
|
||||
" </script>\n",
|
||||
" </div>\n",
|
||||
"</div>\n"
|
||||
]
|
||||
},
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"Plotly.plot {\n",
|
||||
" scatter {\n",
|
||||
" x(2, 3, 4, 5)\n",
|
||||
" y(10, 15, 13, 17)\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" text {\n",
|
||||
" position(2, 10)\n",
|
||||
" font {\n",
|
||||
" size = 18\n",
|
||||
" }\n",
|
||||
" text = \"\\$\\\\alpha\\$\"\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" text {\n",
|
||||
" position(5, 17)\n",
|
||||
" font {\n",
|
||||
" size = 18\n",
|
||||
" }\n",
|
||||
" text = \"\\$\\\\Omega\\$\"\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" layout {\n",
|
||||
" title {\n",
|
||||
" text = \"\\$\\\\text{Plot with annotations } \\\\alpha~and~\\\\Omega\\$\"\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"hide_input": false,
|
||||
"kernelspec": {
|
||||
"display_name": "Kotlin",
|
||||
"language": "kotlin",
|
||||
"name": "kotlin"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": "text/x-kotlin",
|
||||
"file_extension": ".kt",
|
||||
"mimetype": "text/x-kotlin",
|
||||
"name": "kotlin",
|
||||
"pygments_lexer": "kotlin",
|
||||
"version": "1.4.20-dev-2342"
|
||||
},
|
||||
"toc": {
|
||||
"base_numbering": 1,
|
||||
"nav_menu": {},
|
||||
"number_sections": false,
|
||||
"sideBar": false,
|
||||
"skip_h1_title": false,
|
||||
"title_cell": "Table of Contents",
|
||||
"title_sidebar": "Contents",
|
||||
"toc_cell": false,
|
||||
"toc_position": {},
|
||||
"toc_section_display": false,
|
||||
"toc_window_display": false
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
{
|
||||
"imports": [
|
||||
"kscience.plotly.*",
|
||||
"kscience.plotly.models.*",
|
||||
"kscience.plotly.JupyterPlotly",
|
||||
"space.kscience.dataforge.meta.*",
|
||||
"kotlinx.html.*"
|
||||
],
|
||||
"repositories": [
|
||||
"*mavenLocal",
|
||||
"https://dl.bintray.com/mipt-npm/dataforge",
|
||||
"https://dl.bintray.com/mipt-npm/kscience",
|
||||
"https://dl.bintray.com/mipt-npm/dev"
|
||||
],
|
||||
"properties": {
|
||||
"v": "0.2.0"
|
||||
},
|
||||
"link": "https://github.com/mipt-npm/plotly.kt",
|
||||
"dependencies": [
|
||||
"kscience.plotlykt:plotlykt-core-jvm:$v"
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"type": "JS",
|
||||
"name": "Plotly",
|
||||
"locations": [
|
||||
{
|
||||
"path": "https://cdn.plot.ly/plotly-latest.min.js",
|
||||
"type": "URL"
|
||||
},
|
||||
{
|
||||
"path": "js/plotly.min.js",
|
||||
"type": "CLASSPATH_PATH"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"renderers": {
|
||||
"kscience.plotly.HtmlFragment": "HTML($it.toString())",
|
||||
"kscience.plotly.Plot": "HTML(JupyterPlotly.renderPlot($it))",
|
||||
"kscience.plotly.PlotlyFragment": "HTML(JupyterPlotly.renderFragment($it))",
|
||||
"kscience.plotly.PlotlyPage": "HTML(JupyterPlotly.renderPage($it), true)"
|
||||
}
|
||||
}
|
@ -0,0 +1,99 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"start_time": "2021-04-29T19:06:33.505Z"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%use plotly"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"start_time": "2021-04-29T19:05:34.298Z"
|
||||
},
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import kotlin.math.*\n",
|
||||
"\n",
|
||||
"val x1 = (0..100).map { it.toDouble() / 100.0 }\n",
|
||||
"val y1 = x1.map { sin(2.0 * PI * it) }\n",
|
||||
"val y2 = x1.map { cos(2.0 * PI * it) }\n",
|
||||
"\n",
|
||||
"val trace1 = Trace(x1, y1) { name = \"sin\" }\n",
|
||||
"val trace2 = Trace(x1, y2) { name = \"cos\" }\n",
|
||||
"\n",
|
||||
"Plotly.page { renderer ->\n",
|
||||
" val plotConfig = PlotlyConfig{\n",
|
||||
" responsive = true\n",
|
||||
" imageFormat = \"svg\"\n",
|
||||
" } \n",
|
||||
" h1 { +\"A custom separator\" }\n",
|
||||
" hr()\n",
|
||||
" plot(\"below\", renderer = renderer) {\n",
|
||||
" traces(trace1, trace2)\n",
|
||||
" layout {\n",
|
||||
" title = \"The plot below\"\n",
|
||||
" xaxis.title = \"x axis name\"\n",
|
||||
" yaxis.title = \"y axis name\"\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"@webio": {
|
||||
"lastCommId": null,
|
||||
"lastKernelId": null
|
||||
},
|
||||
"hide_input": false,
|
||||
"kernelspec": {
|
||||
"display_name": "Kotlin",
|
||||
"language": "kotlin",
|
||||
"name": "kotlin"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": "text/x-kotlin",
|
||||
"file_extension": ".kt",
|
||||
"mimetype": "text/x-kotlin",
|
||||
"name": "kotlin",
|
||||
"nbconvert_exporter": "",
|
||||
"pygments_lexer": "kotlin",
|
||||
"version": "1.5.30-dev-598"
|
||||
},
|
||||
"toc": {
|
||||
"base_numbering": 1,
|
||||
"nav_menu": {},
|
||||
"number_sections": false,
|
||||
"sideBar": false,
|
||||
"skip_h1_title": false,
|
||||
"title_cell": "Table of Contents",
|
||||
"title_sidebar": "Contents",
|
||||
"toc_cell": false,
|
||||
"toc_position": {},
|
||||
"toc_section_display": false,
|
||||
"toc_window_display": false
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
@ -0,0 +1,225 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2020-08-13T17:37+0300",
|
||||
"start_time": "2020-08-13T17:37+0300"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%use plotly"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Line_4.jupyter-kts (1:8 - 15) Unresolved reference: jupyter"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"Plotly.jupyter.notebook()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2020-08-13T17:37+0300",
|
||||
"start_time": "2020-08-13T17:37+0300"
|
||||
},
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<html>\n",
|
||||
" <head>\n",
|
||||
" <meta charset=\"utf-8\">\n",
|
||||
" <title>Plotly.kt</title>\n",
|
||||
" <script type=\"text/javascript\" src=\"https://cdn.plot.ly/plotly-1.54.6.min.js\"></script>\n",
|
||||
" </head>\n",
|
||||
" <body>\n",
|
||||
" <div id=\"space.kscience.plotly.Plot@246f69fb\">\n",
|
||||
" <script>Plotly.react(\n",
|
||||
" 'space.kscience.plotly.Plot@246f69fb',\n",
|
||||
" [{\"x\":[0.0,0.01,0.02,0.03,0.04,0.05,0.06,0.07,0.08,0.09,0.1,0.11,0.12,0.13,0.14,0.15,0.16,0.17,0.18,0.19,0.2,0.21,0.22,0.23,0.24,0.25,0.26,0.27,0.28,0.29,0.3,0.31,0.32,0.33,0.34,0.35,0.36,0.37,0.38,0.39,0.4,0.41,0.42,0.43,0.44,0.45,0.46,0.47,0.48,0.49,0.5,0.51,0.52,0.53,0.54,0.55,0.56,0.57,0.58,0.59,0.6,0.61,0.62,0.63,0.64,0.65,0.66,0.67,0.68,0.69,0.7,0.71,0.72,0.73,0.74,0.75,0.76,0.77,0.78,0.79,0.8,0.81,0.82,0.83,0.84,0.85,0.86,0.87,0.88,0.89,0.9,0.91,0.92,0.93,0.94,0.95,0.96,0.97,0.98,0.99,1.0],\"name\":\"sin\",\"y\":[0.0,0.06279051952931337,0.12533323356430426,0.1873813145857246,0.2486898871648548,0.3090169943749474,0.3681245526846779,0.4257792915650727,0.4817536741017153,0.5358267949789967,0.5877852522924731,0.6374239897486896,0.6845471059286886,0.7289686274214116,0.7705132427757893,0.8090169943749475,0.8443279255020151,0.8763066800438637,0.9048270524660196,0.9297764858882513,0.9510565162951535,0.9685831611286311,0.9822872507286886,0.9921147013144779,0.9980267284282716,1.0,0.9980267284282716,0.9921147013144778,0.9822872507286886,0.9685831611286312,0.9510565162951536,0.9297764858882513,0.9048270524660195,0.8763066800438635,0.844327925502015,0.8090169943749475,0.7705132427757893,0.7289686274214114,0.6845471059286888,0.6374239897486899,0.5877852522924732,0.535826794978997,0.4817536741017156,0.4257792915650729,0.36812455268467814,0.3090169943749475,0.24868988716485482,0.18738131458572502,0.12533323356430454,0.06279051952931358,1.2246467991473532E-16,-0.06279051952931335,-0.12533323356430429,-0.18738131458572477,-0.24868988716485502,-0.30901699437494773,-0.3681245526846783,-0.42577929156507227,-0.481753674101715,-0.5358267949789964,-0.587785252292473,-0.6374239897486896,-0.6845471059286887,-0.7289686274214113,-0.7705132427757894,-0.8090169943749473,-0.8443279255020153,-0.8763066800438636,-0.9048270524660198,-0.9297764858882511,-0.9510565162951535,-0.968583161128631,-0.9822872507286887,-0.9921147013144778,-0.9980267284282716,-1.0,-0.9980267284282716,-0.9921147013144779,-0.9822872507286887,-0.9685831611286311,-0.9510565162951536,-0.9297764858882512,-0.9048270524660199,-0.8763066800438638,-0.8443279255020155,-0.8090169943749476,-0.7705132427757896,-0.7289686274214116,-0.684547105928689,-0.6374239897486896,-0.5877852522924734,-0.5358267949789963,-0.4817536741017153,-0.4257792915650722,-0.3681245526846787,-0.3090169943749476,-0.24868988716485535,-0.18738131458572468,-0.12533323356430465,-0.06279051952931326,-2.4492935982947064E-16]},{\"x\":[0.0,0.01,0.02,0.03,0.04,0.05,0.06,0.07,0.08,0.09,0.1,0.11,0.12,0.13,0.14,0.15,0.16,0.17,0.18,0.19,0.2,0.21,0.22,0.23,0.24,0.25,0.26,0.27,0.28,0.29,0.3,0.31,0.32,0.33,0.34,0.35,0.36,0.37,0.38,0.39,0.4,0.41,0.42,0.43,0.44,0.45,0.46,0.47,0.48,0.49,0.5,0.51,0.52,0.53,0.54,0.55,0.56,0.57,0.58,0.59,0.6,0.61,0.62,0.63,0.64,0.65,0.66,0.67,0.68,0.69,0.7,0.71,0.72,0.73,0.74,0.75,0.76,0.77,0.78,0.79,0.8,0.81,0.82,0.83,0.84,0.85,0.86,0.87,0.88,0.89,0.9,0.91,0.92,0.93,0.94,0.95,0.96,0.97,0.98,0.99,1.0],\"name\":\"cos\",\"y\":[1.0,0.9980267284282716,0.9921147013144779,0.9822872507286887,0.9685831611286311,0.9510565162951535,0.9297764858882515,0.9048270524660195,0.8763066800438636,0.8443279255020151,0.8090169943749475,0.7705132427757893,0.7289686274214116,0.6845471059286886,0.6374239897486896,0.5877852522924731,0.5358267949789965,0.48175367410171516,0.42577929156507266,0.3681245526846781,0.30901699437494745,0.24868988716485496,0.18738131458572474,0.12533323356430426,0.06279051952931353,6.123233995736766E-17,-0.0627905195293134,-0.12533323356430437,-0.18738131458572482,-0.24868988716485463,-0.30901699437494734,-0.368124552684678,-0.4257792915650727,-0.48175367410171543,-0.5358267949789969,-0.587785252292473,-0.6374239897486897,-0.6845471059286887,-0.7289686274214113,-0.7705132427757891,-0.8090169943749473,-0.8443279255020149,-0.8763066800438634,-0.9048270524660194,-0.9297764858882513,-0.9510565162951535,-0.9685831611286311,-0.9822872507286886,-0.9921147013144778,-0.9980267284282716,-1.0,-0.9980267284282716,-0.9921147013144779,-0.9822872507286886,-0.9685831611286311,-0.9510565162951535,-0.9297764858882512,-0.9048270524660197,-0.8763066800438637,-0.8443279255020152,-0.8090169943749476,-0.7705132427757893,-0.7289686274214116,-0.684547105928689,-0.6374239897486895,-0.5877852522924732,-0.5358267949789963,-0.48175367410171527,-0.42577929156507216,-0.3681245526846786,-0.30901699437494756,-0.2486898871648553,-0.18738131458572463,-0.1253332335643046,-0.06279051952931321,-1.8369701987210297E-16,0.06279051952931283,0.12533323356430423,0.18738131458572427,0.24868988716485493,0.30901699437494723,0.36812455268467825,0.4257792915650718,0.48175367410171493,0.535826794978996,0.5877852522924729,0.6374239897486893,0.6845471059286886,0.7289686274214112,0.7705132427757894,0.8090169943749473,0.8443279255020153,0.8763066800438636,0.9048270524660197,0.9297764858882511,0.9510565162951535,0.968583161128631,0.9822872507286887,0.9921147013144778,0.9980267284282716,1.0]}],\n",
|
||||
" {\"xaxis\":{\"title\":\"x axis name\"},\"title\":{\"text\":\"The plot above\"},\"yaxis\":{\"title\":\"y axis name\"}},\n",
|
||||
" {\"toImageButtonOptions\":{\"format\":\"svg\"},\"responsive\":true}\n",
|
||||
");</script>\n",
|
||||
" </div>\n",
|
||||
" <hr>\n",
|
||||
" <h1>A custom separator</h1>\n",
|
||||
" <hr>\n",
|
||||
" <div>\n",
|
||||
" <div id=\"space.kscience.plotly.Plot@386c48c3\">\n",
|
||||
" <script>Plotly.react(\n",
|
||||
" 'space.kscience.plotly.Plot@386c48c3',\n",
|
||||
" [{\"x\":[0.0,0.01,0.02,0.03,0.04,0.05,0.06,0.07,0.08,0.09,0.1,0.11,0.12,0.13,0.14,0.15,0.16,0.17,0.18,0.19,0.2,0.21,0.22,0.23,0.24,0.25,0.26,0.27,0.28,0.29,0.3,0.31,0.32,0.33,0.34,0.35,0.36,0.37,0.38,0.39,0.4,0.41,0.42,0.43,0.44,0.45,0.46,0.47,0.48,0.49,0.5,0.51,0.52,0.53,0.54,0.55,0.56,0.57,0.58,0.59,0.6,0.61,0.62,0.63,0.64,0.65,0.66,0.67,0.68,0.69,0.7,0.71,0.72,0.73,0.74,0.75,0.76,0.77,0.78,0.79,0.8,0.81,0.82,0.83,0.84,0.85,0.86,0.87,0.88,0.89,0.9,0.91,0.92,0.93,0.94,0.95,0.96,0.97,0.98,0.99,1.0],\"name\":\"sin\",\"y\":[0.0,0.06279051952931337,0.12533323356430426,0.1873813145857246,0.2486898871648548,0.3090169943749474,0.3681245526846779,0.4257792915650727,0.4817536741017153,0.5358267949789967,0.5877852522924731,0.6374239897486896,0.6845471059286886,0.7289686274214116,0.7705132427757893,0.8090169943749475,0.8443279255020151,0.8763066800438637,0.9048270524660196,0.9297764858882513,0.9510565162951535,0.9685831611286311,0.9822872507286886,0.9921147013144779,0.9980267284282716,1.0,0.9980267284282716,0.9921147013144778,0.9822872507286886,0.9685831611286312,0.9510565162951536,0.9297764858882513,0.9048270524660195,0.8763066800438635,0.844327925502015,0.8090169943749475,0.7705132427757893,0.7289686274214114,0.6845471059286888,0.6374239897486899,0.5877852522924732,0.535826794978997,0.4817536741017156,0.4257792915650729,0.36812455268467814,0.3090169943749475,0.24868988716485482,0.18738131458572502,0.12533323356430454,0.06279051952931358,1.2246467991473532E-16,-0.06279051952931335,-0.12533323356430429,-0.18738131458572477,-0.24868988716485502,-0.30901699437494773,-0.3681245526846783,-0.42577929156507227,-0.481753674101715,-0.5358267949789964,-0.587785252292473,-0.6374239897486896,-0.6845471059286887,-0.7289686274214113,-0.7705132427757894,-0.8090169943749473,-0.8443279255020153,-0.8763066800438636,-0.9048270524660198,-0.9297764858882511,-0.9510565162951535,-0.968583161128631,-0.9822872507286887,-0.9921147013144778,-0.9980267284282716,-1.0,-0.9980267284282716,-0.9921147013144779,-0.9822872507286887,-0.9685831611286311,-0.9510565162951536,-0.9297764858882512,-0.9048270524660199,-0.8763066800438638,-0.8443279255020155,-0.8090169943749476,-0.7705132427757896,-0.7289686274214116,-0.684547105928689,-0.6374239897486896,-0.5877852522924734,-0.5358267949789963,-0.4817536741017153,-0.4257792915650722,-0.3681245526846787,-0.3090169943749476,-0.24868988716485535,-0.18738131458572468,-0.12533323356430465,-0.06279051952931326,-2.4492935982947064E-16]},{\"x\":[0.0,0.01,0.02,0.03,0.04,0.05,0.06,0.07,0.08,0.09,0.1,0.11,0.12,0.13,0.14,0.15,0.16,0.17,0.18,0.19,0.2,0.21,0.22,0.23,0.24,0.25,0.26,0.27,0.28,0.29,0.3,0.31,0.32,0.33,0.34,0.35,0.36,0.37,0.38,0.39,0.4,0.41,0.42,0.43,0.44,0.45,0.46,0.47,0.48,0.49,0.5,0.51,0.52,0.53,0.54,0.55,0.56,0.57,0.58,0.59,0.6,0.61,0.62,0.63,0.64,0.65,0.66,0.67,0.68,0.69,0.7,0.71,0.72,0.73,0.74,0.75,0.76,0.77,0.78,0.79,0.8,0.81,0.82,0.83,0.84,0.85,0.86,0.87,0.88,0.89,0.9,0.91,0.92,0.93,0.94,0.95,0.96,0.97,0.98,0.99,1.0],\"name\":\"cos\",\"y\":[1.0,0.9980267284282716,0.9921147013144779,0.9822872507286887,0.9685831611286311,0.9510565162951535,0.9297764858882515,0.9048270524660195,0.8763066800438636,0.8443279255020151,0.8090169943749475,0.7705132427757893,0.7289686274214116,0.6845471059286886,0.6374239897486896,0.5877852522924731,0.5358267949789965,0.48175367410171516,0.42577929156507266,0.3681245526846781,0.30901699437494745,0.24868988716485496,0.18738131458572474,0.12533323356430426,0.06279051952931353,6.123233995736766E-17,-0.0627905195293134,-0.12533323356430437,-0.18738131458572482,-0.24868988716485463,-0.30901699437494734,-0.368124552684678,-0.4257792915650727,-0.48175367410171543,-0.5358267949789969,-0.587785252292473,-0.6374239897486897,-0.6845471059286887,-0.7289686274214113,-0.7705132427757891,-0.8090169943749473,-0.8443279255020149,-0.8763066800438634,-0.9048270524660194,-0.9297764858882513,-0.9510565162951535,-0.9685831611286311,-0.9822872507286886,-0.9921147013144778,-0.9980267284282716,-1.0,-0.9980267284282716,-0.9921147013144779,-0.9822872507286886,-0.9685831611286311,-0.9510565162951535,-0.9297764858882512,-0.9048270524660197,-0.8763066800438637,-0.8443279255020152,-0.8090169943749476,-0.7705132427757893,-0.7289686274214116,-0.684547105928689,-0.6374239897486895,-0.5877852522924732,-0.5358267949789963,-0.48175367410171527,-0.42577929156507216,-0.3681245526846786,-0.30901699437494756,-0.2486898871648553,-0.18738131458572463,-0.1253332335643046,-0.06279051952931321,-1.8369701987210297E-16,0.06279051952931283,0.12533323356430423,0.18738131458572427,0.24868988716485493,0.30901699437494723,0.36812455268467825,0.4257792915650718,0.48175367410171493,0.535826794978996,0.5877852522924729,0.6374239897486893,0.6845471059286886,0.7289686274214112,0.7705132427757894,0.8090169943749473,0.8443279255020153,0.8763066800438636,0.9048270524660197,0.9297764858882511,0.9510565162951535,0.968583161128631,0.9822872507286887,0.9921147013144778,0.9980267284282716,1.0]}],\n",
|
||||
" {\"xaxis\":{\"title\":\"x axis name\"},\"width\":450,\"title\":{\"text\":\"The plot below\"},\"yaxis\":{\"title\":\"y axis name\"}},\n",
|
||||
" {}\n",
|
||||
");</script>\n",
|
||||
" </div>\n",
|
||||
" </div>\n",
|
||||
" </body>\n",
|
||||
"</html>\n"
|
||||
]
|
||||
},
|
||||
"execution_count": 7,
|
||||
"metadata": {
|
||||
"text/html": {
|
||||
"isolated": true
|
||||
}
|
||||
},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"val x1 = (0..100).map { it.toDouble() / 100.0 }\n",
|
||||
"val y1 = x1.map { sin(2.0 * PI * it) }\n",
|
||||
"val y2 = x1.map { cos(2.0 * PI * it) }\n",
|
||||
"\n",
|
||||
"val trace1 = Trace(x1, y1) { name = \"sin\" }\n",
|
||||
"val trace2 = Trace(x1, y2) { name = \"cos\" }\n",
|
||||
"\n",
|
||||
"val fragment = Plotly.fragment {\n",
|
||||
" val plotConfig = PlotlyConfig{\n",
|
||||
" responsive = true\n",
|
||||
" set(\"toImageButtonOptions.format\", \"svg\")\n",
|
||||
" }\n",
|
||||
" \n",
|
||||
" plot(config = plotConfig) {\n",
|
||||
" traces(trace1, trace2)\n",
|
||||
" layout {\n",
|
||||
" title = \"The plot above\"\n",
|
||||
" xaxis.title = \"x axis name\"\n",
|
||||
" yaxis.title = \"y axis name\"\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
" hr()\n",
|
||||
" h1 { +\"A custom separator\" }\n",
|
||||
" hr()\n",
|
||||
" div {\n",
|
||||
" plot{\n",
|
||||
" traces(trace1, trace2)\n",
|
||||
" layout {\n",
|
||||
" width = 450\n",
|
||||
" title = \"The plot below\"\n",
|
||||
" xaxis.title = \"x axis name\"\n",
|
||||
" yaxis.title = \"y axis name\"\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
"}\n",
|
||||
"fragment.toPage()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2020-08-12T22:35+0300",
|
||||
"start_time": "2020-08-12T22:35+0300"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<html>\n",
|
||||
" <head>\n",
|
||||
" <meta charset=\"utf-8\">\n",
|
||||
" <title>Plotly.kt</title>\n",
|
||||
" <script type=\"text/javascript\" src=\"https://cdn.plot.ly/plotly-1.54.6.min.js\"></script>\n",
|
||||
" </head>\n",
|
||||
" <body>\n",
|
||||
" <div id=\"space.kscience.plotly.Plot@6713105b\">\n",
|
||||
" <script>Plotly.react(\n",
|
||||
" 'space.kscience.plotly.Plot@6713105b',\n",
|
||||
" [{\"x\":[0.0,0.01,0.02,0.03,0.04,0.05,0.06,0.07,0.08,0.09,0.1,0.11,0.12,0.13,0.14,0.15,0.16,0.17,0.18,0.19,0.2,0.21,0.22,0.23,0.24,0.25,0.26,0.27,0.28,0.29,0.3,0.31,0.32,0.33,0.34,0.35,0.36,0.37,0.38,0.39,0.4,0.41,0.42,0.43,0.44,0.45,0.46,0.47,0.48,0.49,0.5,0.51,0.52,0.53,0.54,0.55,0.56,0.57,0.58,0.59,0.6,0.61,0.62,0.63,0.64,0.65,0.66,0.67,0.68,0.69,0.7,0.71,0.72,0.73,0.74,0.75,0.76,0.77,0.78,0.79,0.8,0.81,0.82,0.83,0.84,0.85,0.86,0.87,0.88,0.89,0.9,0.91,0.92,0.93,0.94,0.95,0.96,0.97,0.98,0.99,1.0],\"name\":\"sin\",\"y\":[0.0,0.06279051952931337,0.12533323356430426,0.1873813145857246,0.2486898871648548,0.3090169943749474,0.3681245526846779,0.4257792915650727,0.4817536741017153,0.5358267949789967,0.5877852522924731,0.6374239897486896,0.6845471059286886,0.7289686274214116,0.7705132427757893,0.8090169943749475,0.8443279255020151,0.8763066800438637,0.9048270524660196,0.9297764858882513,0.9510565162951535,0.9685831611286311,0.9822872507286886,0.9921147013144779,0.9980267284282716,1.0,0.9980267284282716,0.9921147013144778,0.9822872507286886,0.9685831611286312,0.9510565162951536,0.9297764858882513,0.9048270524660195,0.8763066800438635,0.844327925502015,0.8090169943749475,0.7705132427757893,0.7289686274214114,0.6845471059286888,0.6374239897486899,0.5877852522924732,0.535826794978997,0.4817536741017156,0.4257792915650729,0.36812455268467814,0.3090169943749475,0.24868988716485482,0.18738131458572502,0.12533323356430454,0.06279051952931358,1.2246467991473532E-16,-0.06279051952931335,-0.12533323356430429,-0.18738131458572477,-0.24868988716485502,-0.30901699437494773,-0.3681245526846783,-0.42577929156507227,-0.481753674101715,-0.5358267949789964,-0.587785252292473,-0.6374239897486896,-0.6845471059286887,-0.7289686274214113,-0.7705132427757894,-0.8090169943749473,-0.8443279255020153,-0.8763066800438636,-0.9048270524660198,-0.9297764858882511,-0.9510565162951535,-0.968583161128631,-0.9822872507286887,-0.9921147013144778,-0.9980267284282716,-1.0,-0.9980267284282716,-0.9921147013144779,-0.9822872507286887,-0.9685831611286311,-0.9510565162951536,-0.9297764858882512,-0.9048270524660199,-0.8763066800438638,-0.8443279255020155,-0.8090169943749476,-0.7705132427757896,-0.7289686274214116,-0.684547105928689,-0.6374239897486896,-0.5877852522924734,-0.5358267949789963,-0.4817536741017153,-0.4257792915650722,-0.3681245526846787,-0.3090169943749476,-0.24868988716485535,-0.18738131458572468,-0.12533323356430465,-0.06279051952931326,-2.4492935982947064E-16]},{\"x\":[0.0,0.01,0.02,0.03,0.04,0.05,0.06,0.07,0.08,0.09,0.1,0.11,0.12,0.13,0.14,0.15,0.16,0.17,0.18,0.19,0.2,0.21,0.22,0.23,0.24,0.25,0.26,0.27,0.28,0.29,0.3,0.31,0.32,0.33,0.34,0.35,0.36,0.37,0.38,0.39,0.4,0.41,0.42,0.43,0.44,0.45,0.46,0.47,0.48,0.49,0.5,0.51,0.52,0.53,0.54,0.55,0.56,0.57,0.58,0.59,0.6,0.61,0.62,0.63,0.64,0.65,0.66,0.67,0.68,0.69,0.7,0.71,0.72,0.73,0.74,0.75,0.76,0.77,0.78,0.79,0.8,0.81,0.82,0.83,0.84,0.85,0.86,0.87,0.88,0.89,0.9,0.91,0.92,0.93,0.94,0.95,0.96,0.97,0.98,0.99,1.0],\"name\":\"cos\",\"y\":[1.0,0.9980267284282716,0.9921147013144779,0.9822872507286887,0.9685831611286311,0.9510565162951535,0.9297764858882515,0.9048270524660195,0.8763066800438636,0.8443279255020151,0.8090169943749475,0.7705132427757893,0.7289686274214116,0.6845471059286886,0.6374239897486896,0.5877852522924731,0.5358267949789965,0.48175367410171516,0.42577929156507266,0.3681245526846781,0.30901699437494745,0.24868988716485496,0.18738131458572474,0.12533323356430426,0.06279051952931353,6.123233995736766E-17,-0.0627905195293134,-0.12533323356430437,-0.18738131458572482,-0.24868988716485463,-0.30901699437494734,-0.368124552684678,-0.4257792915650727,-0.48175367410171543,-0.5358267949789969,-0.587785252292473,-0.6374239897486897,-0.6845471059286887,-0.7289686274214113,-0.7705132427757891,-0.8090169943749473,-0.8443279255020149,-0.8763066800438634,-0.9048270524660194,-0.9297764858882513,-0.9510565162951535,-0.9685831611286311,-0.9822872507286886,-0.9921147013144778,-0.9980267284282716,-1.0,-0.9980267284282716,-0.9921147013144779,-0.9822872507286886,-0.9685831611286311,-0.9510565162951535,-0.9297764858882512,-0.9048270524660197,-0.8763066800438637,-0.8443279255020152,-0.8090169943749476,-0.7705132427757893,-0.7289686274214116,-0.684547105928689,-0.6374239897486895,-0.5877852522924732,-0.5358267949789963,-0.48175367410171527,-0.42577929156507216,-0.3681245526846786,-0.30901699437494756,-0.2486898871648553,-0.18738131458572463,-0.1253332335643046,-0.06279051952931321,-1.8369701987210297E-16,0.06279051952931283,0.12533323356430423,0.18738131458572427,0.24868988716485493,0.30901699437494723,0.36812455268467825,0.4257792915650718,0.48175367410171493,0.535826794978996,0.5877852522924729,0.6374239897486893,0.6845471059286886,0.7289686274214112,0.7705132427757894,0.8090169943749473,0.8443279255020153,0.8763066800438636,0.9048270524660197,0.9297764858882511,0.9510565162951535,0.968583161128631,0.9822872507286887,0.9921147013144778,0.9980267284282716,1.0]}],\n",
|
||||
" {\"xaxis\":{\"title\":\"x axis name\"},\"title\":{\"text\":\"The plot below\"},\"yaxis\":{\"title\":\"y axis name\"}},\n",
|
||||
" {}\n",
|
||||
");</script>\n",
|
||||
" </div>\n",
|
||||
" </body>\n",
|
||||
"</html>\n"
|
||||
]
|
||||
},
|
||||
"execution_count": 8,
|
||||
"metadata": {
|
||||
"text/html": {
|
||||
"isolated": true
|
||||
}
|
||||
},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"Plotly.plot {\n",
|
||||
" traces(trace1, trace2)\n",
|
||||
" layout {\n",
|
||||
" title = \"The plot below\"\n",
|
||||
" xaxis.title = \"x axis name\"\n",
|
||||
" yaxis.title = \"y axis name\"\n",
|
||||
" }\n",
|
||||
"}.toPage()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"@webio": {
|
||||
"lastCommId": null,
|
||||
"lastKernelId": null
|
||||
},
|
||||
"hide_input": false,
|
||||
"kernelspec": {
|
||||
"display_name": "Kotlin",
|
||||
"language": "kotlin",
|
||||
"name": "kotlin"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": "text/x-kotlin",
|
||||
"file_extension": ".kt",
|
||||
"mimetype": "text/x-kotlin",
|
||||
"name": "kotlin",
|
||||
"nbconvert_exporter": "",
|
||||
"pygments_lexer": "kotlin",
|
||||
"version": "1.5.30-dev-598"
|
||||
},
|
||||
"toc": {
|
||||
"base_numbering": 1,
|
||||
"nav_menu": {},
|
||||
"number_sections": false,
|
||||
"sideBar": false,
|
||||
"skip_h1_title": false,
|
||||
"title_cell": "Table of Contents",
|
||||
"title_sidebar": "Contents",
|
||||
"toc_cell": false,
|
||||
"toc_position": {},
|
||||
"toc_section_display": false,
|
||||
"toc_window_display": false
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,402 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 24,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2020-07-31T11:42+0300",
|
||||
"start_time": "2020-07-31T11:42+0300"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<div style=\"color: blue;\">The server is already running on 8882. It must be shut down first to be restarted.</div>\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"%use plotly\n",
|
||||
"import kotlin.math.*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 25,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2020-07-31T11:42+0300",
|
||||
"start_time": "2020-07-31T11:42+0300"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<div>\n",
|
||||
" <div id=\"kscience.plotly.Plot@11b65246\">\n",
|
||||
" <script>\n",
|
||||
"require([\"plotly\"], plotly =>{\n",
|
||||
" plotly.react(\n",
|
||||
" 'kscience.plotly.Plot@11b65246',\n",
|
||||
" [{\"x\":[0.0,0.01,0.02,0.03,0.04,0.05,0.06,0.07,0.08,0.09,0.1,0.11,0.12,0.13,0.14,0.15,0.16,0.17,0.18,0.19,0.2,0.21,0.22,0.23,0.24,0.25,0.26,0.27,0.28,0.29,0.3,0.31,0.32,0.33,0.34,0.35,0.36,0.37,0.38,0.39,0.4,0.41,0.42,0.43,0.44,0.45,0.46,0.47,0.48,0.49,0.5,0.51,0.52,0.53,0.54,0.55,0.56,0.57,0.58,0.59,0.6,0.61,0.62,0.63,0.64,0.65,0.66,0.67,0.68,0.69,0.7,0.71,0.72,0.73,0.74,0.75,0.76,0.77,0.78,0.79,0.8,0.81,0.82,0.83,0.84,0.85,0.86,0.87,0.88,0.89,0.9,0.91,0.92,0.93,0.94,0.95,0.96,0.97,0.98,0.99,1.0],\"name\":\"sin\",\"y\":[0.0,0.06279051952931337,0.12533323356430426,0.1873813145857246,0.2486898871648548,0.3090169943749474,0.3681245526846779,0.4257792915650727,0.4817536741017153,0.5358267949789967,0.5877852522924731,0.6374239897486896,0.6845471059286886,0.7289686274214116,0.7705132427757893,0.8090169943749475,0.8443279255020151,0.8763066800438637,0.9048270524660196,0.9297764858882513,0.9510565162951535,0.9685831611286311,0.9822872507286886,0.9921147013144779,0.9980267284282716,1.0,0.9980267284282716,0.9921147013144778,0.9822872507286886,0.9685831611286312,0.9510565162951536,0.9297764858882513,0.9048270524660195,0.8763066800438635,0.844327925502015,0.8090169943749475,0.7705132427757893,0.7289686274214114,0.6845471059286888,0.6374239897486899,0.5877852522924732,0.535826794978997,0.4817536741017156,0.4257792915650729,0.36812455268467814,0.3090169943749475,0.24868988716485482,0.18738131458572502,0.12533323356430454,0.06279051952931358,1.2246467991473532E-16,-0.06279051952931335,-0.12533323356430429,-0.18738131458572477,-0.24868988716485502,-0.30901699437494773,-0.3681245526846783,-0.42577929156507227,-0.481753674101715,-0.5358267949789964,-0.587785252292473,-0.6374239897486896,-0.6845471059286887,-0.7289686274214113,-0.7705132427757894,-0.8090169943749473,-0.8443279255020153,-0.8763066800438636,-0.9048270524660198,-0.9297764858882511,-0.9510565162951535,-0.968583161128631,-0.9822872507286887,-0.9921147013144778,-0.9980267284282716,-1.0,-0.9980267284282716,-0.9921147013144779,-0.9822872507286887,-0.9685831611286311,-0.9510565162951536,-0.9297764858882512,-0.9048270524660199,-0.8763066800438638,-0.8443279255020155,-0.8090169943749476,-0.7705132427757896,-0.7289686274214116,-0.684547105928689,-0.6374239897486896,-0.5877852522924734,-0.5358267949789963,-0.4817536741017153,-0.4257792915650722,-0.3681245526846787,-0.3090169943749476,-0.24868988716485535,-0.18738131458572468,-0.12533323356430465,-0.06279051952931326,-2.4492935982947064E-16]},{\"x\":[0.0,0.01,0.02,0.03,0.04,0.05,0.06,0.07,0.08,0.09,0.1,0.11,0.12,0.13,0.14,0.15,0.16,0.17,0.18,0.19,0.2,0.21,0.22,0.23,0.24,0.25,0.26,0.27,0.28,0.29,0.3,0.31,0.32,0.33,0.34,0.35,0.36,0.37,0.38,0.39,0.4,0.41,0.42,0.43,0.44,0.45,0.46,0.47,0.48,0.49,0.5,0.51,0.52,0.53,0.54,0.55,0.56,0.57,0.58,0.59,0.6,0.61,0.62,0.63,0.64,0.65,0.66,0.67,0.68,0.69,0.7,0.71,0.72,0.73,0.74,0.75,0.76,0.77,0.78,0.79,0.8,0.81,0.82,0.83,0.84,0.85,0.86,0.87,0.88,0.89,0.9,0.91,0.92,0.93,0.94,0.95,0.96,0.97,0.98,0.99,1.0],\"name\":\"cos\",\"y\":[1.0,0.9980267284282716,0.9921147013144779,0.9822872507286887,0.9685831611286311,0.9510565162951535,0.9297764858882515,0.9048270524660195,0.8763066800438636,0.8443279255020151,0.8090169943749475,0.7705132427757893,0.7289686274214116,0.6845471059286886,0.6374239897486896,0.5877852522924731,0.5358267949789965,0.48175367410171516,0.42577929156507266,0.3681245526846781,0.30901699437494745,0.24868988716485496,0.18738131458572474,0.12533323356430426,0.06279051952931353,6.123233995736766E-17,-0.0627905195293134,-0.12533323356430437,-0.18738131458572482,-0.24868988716485463,-0.30901699437494734,-0.368124552684678,-0.4257792915650727,-0.48175367410171543,-0.5358267949789969,-0.587785252292473,-0.6374239897486897,-0.6845471059286887,-0.7289686274214113,-0.7705132427757891,-0.8090169943749473,-0.8443279255020149,-0.8763066800438634,-0.9048270524660194,-0.9297764858882513,-0.9510565162951535,-0.9685831611286311,-0.9822872507286886,-0.9921147013144778,-0.9980267284282716,-1.0,-0.9980267284282716,-0.9921147013144779,-0.9822872507286886,-0.9685831611286311,-0.9510565162951535,-0.9297764858882512,-0.9048270524660197,-0.8763066800438637,-0.8443279255020152,-0.8090169943749476,-0.7705132427757893,-0.7289686274214116,-0.684547105928689,-0.6374239897486895,-0.5877852522924732,-0.5358267949789963,-0.48175367410171527,-0.42577929156507216,-0.3681245526846786,-0.30901699437494756,-0.2486898871648553,-0.18738131458572463,-0.1253332335643046,-0.06279051952931321,-1.8369701987210297E-16,0.06279051952931283,0.12533323356430423,0.18738131458572427,0.24868988716485493,0.30901699437494723,0.36812455268467825,0.4257792915650718,0.48175367410171493,0.535826794978996,0.5877852522924729,0.6374239897486893,0.6845471059286886,0.7289686274214112,0.7705132427757894,0.8090169943749473,0.8443279255020153,0.8763066800438636,0.9048270524660197,0.9297764858882511,0.9510565162951535,0.968583161128631,0.9822872507286887,0.9921147013144778,0.9980267284282716,1.0]}],\n",
|
||||
" {\"xaxis\":{\"title\":\"x axis name\"},\"title\":{\"text\":\"The plot above\"},\"yaxis\":{\"title\":\"y axis name\"}},\n",
|
||||
" {\"responsive\":true}\n",
|
||||
" );\n",
|
||||
"});\n",
|
||||
"</script>\n",
|
||||
" <script id=\"kscience.plotly.Plot@11b65246-push\">\n",
|
||||
" require([\"plotly-server\"], plotlyServer =>{\n",
|
||||
" startPush('kscience.plotly.Plot@11b65246', 'ws://localhost:8882/ws/kscience.plotly.Plot@11b65246');\n",
|
||||
" });\n",
|
||||
" </script>\n",
|
||||
" </div>\n",
|
||||
" <hr>\n",
|
||||
" <h1>A custom separator</h1>\n",
|
||||
" <hr>\n",
|
||||
" <div>\n",
|
||||
" <div id=\"kscience.plotly.Plot@4803d1c0\">\n",
|
||||
" <script>\n",
|
||||
"require([\"plotly\"], plotly =>{\n",
|
||||
" plotly.react(\n",
|
||||
" 'kscience.plotly.Plot@4803d1c0',\n",
|
||||
" [{\"x\":[0.0,0.01,0.02,0.03,0.04,0.05,0.06,0.07,0.08,0.09,0.1,0.11,0.12,0.13,0.14,0.15,0.16,0.17,0.18,0.19,0.2,0.21,0.22,0.23,0.24,0.25,0.26,0.27,0.28,0.29,0.3,0.31,0.32,0.33,0.34,0.35,0.36,0.37,0.38,0.39,0.4,0.41,0.42,0.43,0.44,0.45,0.46,0.47,0.48,0.49,0.5,0.51,0.52,0.53,0.54,0.55,0.56,0.57,0.58,0.59,0.6,0.61,0.62,0.63,0.64,0.65,0.66,0.67,0.68,0.69,0.7,0.71,0.72,0.73,0.74,0.75,0.76,0.77,0.78,0.79,0.8,0.81,0.82,0.83,0.84,0.85,0.86,0.87,0.88,0.89,0.9,0.91,0.92,0.93,0.94,0.95,0.96,0.97,0.98,0.99,1.0],\"name\":\"sin\",\"y\":[0.0,0.06279051952931337,0.12533323356430426,0.1873813145857246,0.2486898871648548,0.3090169943749474,0.3681245526846779,0.4257792915650727,0.4817536741017153,0.5358267949789967,0.5877852522924731,0.6374239897486896,0.6845471059286886,0.7289686274214116,0.7705132427757893,0.8090169943749475,0.8443279255020151,0.8763066800438637,0.9048270524660196,0.9297764858882513,0.9510565162951535,0.9685831611286311,0.9822872507286886,0.9921147013144779,0.9980267284282716,1.0,0.9980267284282716,0.9921147013144778,0.9822872507286886,0.9685831611286312,0.9510565162951536,0.9297764858882513,0.9048270524660195,0.8763066800438635,0.844327925502015,0.8090169943749475,0.7705132427757893,0.7289686274214114,0.6845471059286888,0.6374239897486899,0.5877852522924732,0.535826794978997,0.4817536741017156,0.4257792915650729,0.36812455268467814,0.3090169943749475,0.24868988716485482,0.18738131458572502,0.12533323356430454,0.06279051952931358,1.2246467991473532E-16,-0.06279051952931335,-0.12533323356430429,-0.18738131458572477,-0.24868988716485502,-0.30901699437494773,-0.3681245526846783,-0.42577929156507227,-0.481753674101715,-0.5358267949789964,-0.587785252292473,-0.6374239897486896,-0.6845471059286887,-0.7289686274214113,-0.7705132427757894,-0.8090169943749473,-0.8443279255020153,-0.8763066800438636,-0.9048270524660198,-0.9297764858882511,-0.9510565162951535,-0.968583161128631,-0.9822872507286887,-0.9921147013144778,-0.9980267284282716,-1.0,-0.9980267284282716,-0.9921147013144779,-0.9822872507286887,-0.9685831611286311,-0.9510565162951536,-0.9297764858882512,-0.9048270524660199,-0.8763066800438638,-0.8443279255020155,-0.8090169943749476,-0.7705132427757896,-0.7289686274214116,-0.684547105928689,-0.6374239897486896,-0.5877852522924734,-0.5358267949789963,-0.4817536741017153,-0.4257792915650722,-0.3681245526846787,-0.3090169943749476,-0.24868988716485535,-0.18738131458572468,-0.12533323356430465,-0.06279051952931326,-2.4492935982947064E-16]},{\"x\":[0.0,0.01,0.02,0.03,0.04,0.05,0.06,0.07,0.08,0.09,0.1,0.11,0.12,0.13,0.14,0.15,0.16,0.17,0.18,0.19,0.2,0.21,0.22,0.23,0.24,0.25,0.26,0.27,0.28,0.29,0.3,0.31,0.32,0.33,0.34,0.35,0.36,0.37,0.38,0.39,0.4,0.41,0.42,0.43,0.44,0.45,0.46,0.47,0.48,0.49,0.5,0.51,0.52,0.53,0.54,0.55,0.56,0.57,0.58,0.59,0.6,0.61,0.62,0.63,0.64,0.65,0.66,0.67,0.68,0.69,0.7,0.71,0.72,0.73,0.74,0.75,0.76,0.77,0.78,0.79,0.8,0.81,0.82,0.83,0.84,0.85,0.86,0.87,0.88,0.89,0.9,0.91,0.92,0.93,0.94,0.95,0.96,0.97,0.98,0.99,1.0],\"name\":\"cos\",\"y\":[1.0,0.9980267284282716,0.9921147013144779,0.9822872507286887,0.9685831611286311,0.9510565162951535,0.9297764858882515,0.9048270524660195,0.8763066800438636,0.8443279255020151,0.8090169943749475,0.7705132427757893,0.7289686274214116,0.6845471059286886,0.6374239897486896,0.5877852522924731,0.5358267949789965,0.48175367410171516,0.42577929156507266,0.3681245526846781,0.30901699437494745,0.24868988716485496,0.18738131458572474,0.12533323356430426,0.06279051952931353,6.123233995736766E-17,-0.0627905195293134,-0.12533323356430437,-0.18738131458572482,-0.24868988716485463,-0.30901699437494734,-0.368124552684678,-0.4257792915650727,-0.48175367410171543,-0.5358267949789969,-0.587785252292473,-0.6374239897486897,-0.6845471059286887,-0.7289686274214113,-0.7705132427757891,-0.8090169943749473,-0.8443279255020149,-0.8763066800438634,-0.9048270524660194,-0.9297764858882513,-0.9510565162951535,-0.9685831611286311,-0.9822872507286886,-0.9921147013144778,-0.9980267284282716,-1.0,-0.9980267284282716,-0.9921147013144779,-0.9822872507286886,-0.9685831611286311,-0.9510565162951535,-0.9297764858882512,-0.9048270524660197,-0.8763066800438637,-0.8443279255020152,-0.8090169943749476,-0.7705132427757893,-0.7289686274214116,-0.684547105928689,-0.6374239897486895,-0.5877852522924732,-0.5358267949789963,-0.48175367410171527,-0.42577929156507216,-0.3681245526846786,-0.30901699437494756,-0.2486898871648553,-0.18738131458572463,-0.1253332335643046,-0.06279051952931321,-1.8369701987210297E-16,0.06279051952931283,0.12533323356430423,0.18738131458572427,0.24868988716485493,0.30901699437494723,0.36812455268467825,0.4257792915650718,0.48175367410171493,0.535826794978996,0.5877852522924729,0.6374239897486893,0.6845471059286886,0.7289686274214112,0.7705132427757894,0.8090169943749473,0.8443279255020153,0.8763066800438636,0.9048270524660197,0.9297764858882511,0.9510565162951535,0.968583161128631,0.9822872507286887,0.9921147013144778,0.9980267284282716,1.0]}],\n",
|
||||
" {\"xaxis\":{\"title\":\"x axis name\"},\"title\":{\"text\":\"The plot below\"},\"yaxis\":{\"title\":\"y axis name\"}},\n",
|
||||
" {}\n",
|
||||
" );\n",
|
||||
"});\n",
|
||||
"</script>\n",
|
||||
" <script id=\"kscience.plotly.Plot@4803d1c0-push\">\n",
|
||||
" require([\"plotly-server\"], plotlyServer =>{\n",
|
||||
" startPush('kscience.plotly.Plot@4803d1c0', 'ws://localhost:8882/ws/kscience.plotly.Plot@4803d1c0');\n",
|
||||
" });\n",
|
||||
" </script>\n",
|
||||
" </div>\n",
|
||||
" </div>\n",
|
||||
"</div>\n"
|
||||
]
|
||||
},
|
||||
"execution_count": 25,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"val x1 = (0..100).map { it.toDouble() / 100.0 }\n",
|
||||
"val y1 = x1.map { sin(2.0 * PI * it) }\n",
|
||||
"val y2 = x1.map { cos(2.0 * PI * it) }\n",
|
||||
"\n",
|
||||
"val trace1 = Trace(x1, y1) { name = \"sin\" }\n",
|
||||
"val trace2 = Trace(x1, y2) { name = \"cos\" }\n",
|
||||
"\n",
|
||||
"val fragment = Plotly.fragment { container ->\n",
|
||||
" plot(container = container, config = PlotlyConfig{responsive = true}) {\n",
|
||||
" traces(trace1, trace2)\n",
|
||||
" layout {\n",
|
||||
" title = \"The plot above\"\n",
|
||||
" xaxis.title = \"x axis name\"\n",
|
||||
" yaxis.title = \"y axis name\"\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
" hr()\n",
|
||||
" h1 { +\"A custom separator\" }\n",
|
||||
" hr()\n",
|
||||
" div {\n",
|
||||
" plot(container = container) {\n",
|
||||
" traces(trace1, trace2)\n",
|
||||
" layout {\n",
|
||||
" title = \"The plot below\"\n",
|
||||
" xaxis.title = \"x axis name\"\n",
|
||||
" yaxis.title = \"y axis name\"\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
"}\n",
|
||||
"fragment"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 26,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2020-07-31T11:42+0300",
|
||||
"start_time": "2020-07-31T11:42+0300"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<div>\n",
|
||||
" <div id=\"kscience.plotly.Plot@192c70fb\">\n",
|
||||
" <script>\n",
|
||||
"require([\"plotly\"], plotly =>{\n",
|
||||
" plotly.react(\n",
|
||||
" 'kscience.plotly.Plot@192c70fb',\n",
|
||||
" [{\"x\":[0.0,0.01,0.02,0.03,0.04,0.05,0.06,0.07,0.08,0.09,0.1,0.11,0.12,0.13,0.14,0.15,0.16,0.17,0.18,0.19,0.2,0.21,0.22,0.23,0.24,0.25,0.26,0.27,0.28,0.29,0.3,0.31,0.32,0.33,0.34,0.35,0.36,0.37,0.38,0.39,0.4,0.41,0.42,0.43,0.44,0.45,0.46,0.47,0.48,0.49,0.5,0.51,0.52,0.53,0.54,0.55,0.56,0.57,0.58,0.59,0.6,0.61,0.62,0.63,0.64,0.65,0.66,0.67,0.68,0.69,0.7,0.71,0.72,0.73,0.74,0.75,0.76,0.77,0.78,0.79,0.8,0.81,0.82,0.83,0.84,0.85,0.86,0.87,0.88,0.89,0.9,0.91,0.92,0.93,0.94,0.95,0.96,0.97,0.98,0.99,1.0],\"name\":\"sin\",\"y\":[0.0,0.06279051952931337,0.12533323356430426,0.1873813145857246,0.2486898871648548,0.3090169943749474,0.3681245526846779,0.4257792915650727,0.4817536741017153,0.5358267949789967,0.5877852522924731,0.6374239897486896,0.6845471059286886,0.7289686274214116,0.7705132427757893,0.8090169943749475,0.8443279255020151,0.8763066800438637,0.9048270524660196,0.9297764858882513,0.9510565162951535,0.9685831611286311,0.9822872507286886,0.9921147013144779,0.9980267284282716,1.0,0.9980267284282716,0.9921147013144778,0.9822872507286886,0.9685831611286312,0.9510565162951536,0.9297764858882513,0.9048270524660195,0.8763066800438635,0.844327925502015,0.8090169943749475,0.7705132427757893,0.7289686274214114,0.6845471059286888,0.6374239897486899,0.5877852522924732,0.535826794978997,0.4817536741017156,0.4257792915650729,0.36812455268467814,0.3090169943749475,0.24868988716485482,0.18738131458572502,0.12533323356430454,0.06279051952931358,1.2246467991473532E-16,-0.06279051952931335,-0.12533323356430429,-0.18738131458572477,-0.24868988716485502,-0.30901699437494773,-0.3681245526846783,-0.42577929156507227,-0.481753674101715,-0.5358267949789964,-0.587785252292473,-0.6374239897486896,-0.6845471059286887,-0.7289686274214113,-0.7705132427757894,-0.8090169943749473,-0.8443279255020153,-0.8763066800438636,-0.9048270524660198,-0.9297764858882511,-0.9510565162951535,-0.968583161128631,-0.9822872507286887,-0.9921147013144778,-0.9980267284282716,-1.0,-0.9980267284282716,-0.9921147013144779,-0.9822872507286887,-0.9685831611286311,-0.9510565162951536,-0.9297764858882512,-0.9048270524660199,-0.8763066800438638,-0.8443279255020155,-0.8090169943749476,-0.7705132427757896,-0.7289686274214116,-0.684547105928689,-0.6374239897486896,-0.5877852522924734,-0.5358267949789963,-0.4817536741017153,-0.4257792915650722,-0.3681245526846787,-0.3090169943749476,-0.24868988716485535,-0.18738131458572468,-0.12533323356430465,-0.06279051952931326,-2.4492935982947064E-16]},{\"x\":[0.0,0.01,0.02,0.03,0.04,0.05,0.06,0.07,0.08,0.09,0.1,0.11,0.12,0.13,0.14,0.15,0.16,0.17,0.18,0.19,0.2,0.21,0.22,0.23,0.24,0.25,0.26,0.27,0.28,0.29,0.3,0.31,0.32,0.33,0.34,0.35,0.36,0.37,0.38,0.39,0.4,0.41,0.42,0.43,0.44,0.45,0.46,0.47,0.48,0.49,0.5,0.51,0.52,0.53,0.54,0.55,0.56,0.57,0.58,0.59,0.6,0.61,0.62,0.63,0.64,0.65,0.66,0.67,0.68,0.69,0.7,0.71,0.72,0.73,0.74,0.75,0.76,0.77,0.78,0.79,0.8,0.81,0.82,0.83,0.84,0.85,0.86,0.87,0.88,0.89,0.9,0.91,0.92,0.93,0.94,0.95,0.96,0.97,0.98,0.99,1.0],\"name\":\"cos\",\"y\":[1.0,0.9980267284282716,0.9921147013144779,0.9822872507286887,0.9685831611286311,0.9510565162951535,0.9297764858882515,0.9048270524660195,0.8763066800438636,0.8443279255020151,0.8090169943749475,0.7705132427757893,0.7289686274214116,0.6845471059286886,0.6374239897486896,0.5877852522924731,0.5358267949789965,0.48175367410171516,0.42577929156507266,0.3681245526846781,0.30901699437494745,0.24868988716485496,0.18738131458572474,0.12533323356430426,0.06279051952931353,6.123233995736766E-17,-0.0627905195293134,-0.12533323356430437,-0.18738131458572482,-0.24868988716485463,-0.30901699437494734,-0.368124552684678,-0.4257792915650727,-0.48175367410171543,-0.5358267949789969,-0.587785252292473,-0.6374239897486897,-0.6845471059286887,-0.7289686274214113,-0.7705132427757891,-0.8090169943749473,-0.8443279255020149,-0.8763066800438634,-0.9048270524660194,-0.9297764858882513,-0.9510565162951535,-0.9685831611286311,-0.9822872507286886,-0.9921147013144778,-0.9980267284282716,-1.0,-0.9980267284282716,-0.9921147013144779,-0.9822872507286886,-0.9685831611286311,-0.9510565162951535,-0.9297764858882512,-0.9048270524660197,-0.8763066800438637,-0.8443279255020152,-0.8090169943749476,-0.7705132427757893,-0.7289686274214116,-0.684547105928689,-0.6374239897486895,-0.5877852522924732,-0.5358267949789963,-0.48175367410171527,-0.42577929156507216,-0.3681245526846786,-0.30901699437494756,-0.2486898871648553,-0.18738131458572463,-0.1253332335643046,-0.06279051952931321,-1.8369701987210297E-16,0.06279051952931283,0.12533323356430423,0.18738131458572427,0.24868988716485493,0.30901699437494723,0.36812455268467825,0.4257792915650718,0.48175367410171493,0.535826794978996,0.5877852522924729,0.6374239897486893,0.6845471059286886,0.7289686274214112,0.7705132427757894,0.8090169943749473,0.8443279255020153,0.8763066800438636,0.9048270524660197,0.9297764858882511,0.9510565162951535,0.968583161128631,0.9822872507286887,0.9921147013144778,0.9980267284282716,1.0]}],\n",
|
||||
" {\"xaxis\":{\"title\":\"x axis name\"},\"title\":{\"text\":\"The plot below\"},\"yaxis\":{\"title\":\"y axis name\"}},\n",
|
||||
" {\"responsive\":true}\n",
|
||||
" );\n",
|
||||
"});\n",
|
||||
"</script>\n",
|
||||
" <script id=\"kscience.plotly.Plot@192c70fb-push\">\n",
|
||||
" require([\"plotly-server\"], plotlyServer =>{\n",
|
||||
" startPush('kscience.plotly.Plot@192c70fb', 'ws://localhost:8882/ws/kscience.plotly.Plot@192c70fb');\n",
|
||||
" });\n",
|
||||
" </script>\n",
|
||||
" </div>\n",
|
||||
"</div>\n"
|
||||
]
|
||||
},
|
||||
"execution_count": 26,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"Plotly.plot {\n",
|
||||
" traces(trace1, trace2)\n",
|
||||
" layout {\n",
|
||||
" title = \"The plot below\"\n",
|
||||
" xaxis.title = \"x axis name\"\n",
|
||||
" yaxis.title = \"y axis name\"\n",
|
||||
" }\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 27,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2020-07-31T11:42+0300",
|
||||
"start_time": "2020-07-31T11:42+0300"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<div>\n",
|
||||
" <div id=\"kscience.plotly.Plot@e8a413\">\n",
|
||||
" <script>\n",
|
||||
"require([\"plotly\"], plotly =>{\n",
|
||||
" plotly.react(\n",
|
||||
" 'kscience.plotly.Plot@e8a413',\n",
|
||||
" [{\"x\":[0.0,0.01,0.02,0.03,0.04,0.05,0.06,0.07,0.08,0.09,0.1,0.11,0.12,0.13,0.14,0.15,0.16,0.17,0.18,0.19,0.2,0.21,0.22,0.23,0.24,0.25,0.26,0.27,0.28,0.29,0.3,0.31,0.32,0.33,0.34,0.35,0.36,0.37,0.38,0.39,0.4,0.41,0.42,0.43,0.44,0.45,0.46,0.47,0.48,0.49,0.5,0.51,0.52,0.53,0.54,0.55,0.56,0.57,0.58,0.59,0.6,0.61,0.62,0.63,0.64,0.65,0.66,0.67,0.68,0.69,0.7,0.71,0.72,0.73,0.74,0.75,0.76,0.77,0.78,0.79,0.8,0.81,0.82,0.83,0.84,0.85,0.86,0.87,0.88,0.89,0.9,0.91,0.92,0.93,0.94,0.95,0.96,0.97,0.98,0.99,1.0],\"name\":\"sin\",\"y\":[0.0,0.06279051952931337,0.12533323356430426,0.1873813145857246,0.2486898871648548,0.3090169943749474,0.3681245526846779,0.4257792915650727,0.4817536741017153,0.5358267949789967,0.5877852522924731,0.6374239897486896,0.6845471059286886,0.7289686274214116,0.7705132427757893,0.8090169943749475,0.8443279255020151,0.8763066800438637,0.9048270524660196,0.9297764858882513,0.9510565162951535,0.9685831611286311,0.9822872507286886,0.9921147013144779,0.9980267284282716,1.0,0.9980267284282716,0.9921147013144778,0.9822872507286886,0.9685831611286312,0.9510565162951536,0.9297764858882513,0.9048270524660195,0.8763066800438635,0.844327925502015,0.8090169943749475,0.7705132427757893,0.7289686274214114,0.6845471059286888,0.6374239897486899,0.5877852522924732,0.535826794978997,0.4817536741017156,0.4257792915650729,0.36812455268467814,0.3090169943749475,0.24868988716485482,0.18738131458572502,0.12533323356430454,0.06279051952931358,1.2246467991473532E-16,-0.06279051952931335,-0.12533323356430429,-0.18738131458572477,-0.24868988716485502,-0.30901699437494773,-0.3681245526846783,-0.42577929156507227,-0.481753674101715,-0.5358267949789964,-0.587785252292473,-0.6374239897486896,-0.6845471059286887,-0.7289686274214113,-0.7705132427757894,-0.8090169943749473,-0.8443279255020153,-0.8763066800438636,-0.9048270524660198,-0.9297764858882511,-0.9510565162951535,-0.968583161128631,-0.9822872507286887,-0.9921147013144778,-0.9980267284282716,-1.0,-0.9980267284282716,-0.9921147013144779,-0.9822872507286887,-0.9685831611286311,-0.9510565162951536,-0.9297764858882512,-0.9048270524660199,-0.8763066800438638,-0.8443279255020155,-0.8090169943749476,-0.7705132427757896,-0.7289686274214116,-0.684547105928689,-0.6374239897486896,-0.5877852522924734,-0.5358267949789963,-0.4817536741017153,-0.4257792915650722,-0.3681245526846787,-0.3090169943749476,-0.24868988716485535,-0.18738131458572468,-0.12533323356430465,-0.06279051952931326,-2.4492935982947064E-16]}],\n",
|
||||
" {\"xaxis\":{\"title\":\"x axis name\"},\"title\":{\"text\":\"Dynamic plot\"},\"yaxis\":{\"title\":\"y axis name\"}},\n",
|
||||
" {\"responsive\":true}\n",
|
||||
" );\n",
|
||||
"});\n",
|
||||
"</script>\n",
|
||||
" <script id=\"kscience.plotly.Plot@e8a413-push\">\n",
|
||||
" require([\"plotly-server\"], plotlyServer =>{\n",
|
||||
" startPush('kscience.plotly.Plot@e8a413', 'ws://localhost:8882/ws/kscience.plotly.Plot@e8a413');\n",
|
||||
" });\n",
|
||||
" </script>\n",
|
||||
" </div>\n",
|
||||
"</div>\n"
|
||||
]
|
||||
},
|
||||
"execution_count": 27,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"val x = (0..100).map { it.toDouble() / 100.0 }\n",
|
||||
"val y = x.map { sin(2.0 * PI * it) }\n",
|
||||
"\n",
|
||||
"val trace = Trace(x, y) { name = \"sin\" }\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"val dynamicPlot = Plotly.plot {\n",
|
||||
" traces(trace)\n",
|
||||
" layout {\n",
|
||||
" title = \"Dynamic plot\"\n",
|
||||
" xaxis.title = \"x axis name\"\n",
|
||||
" yaxis.title = \"y axis name\"\n",
|
||||
" }\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"dynamicPlot"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 28,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2020-07-31T11:42+0300",
|
||||
"start_time": "2020-07-31T11:42+0300"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import kotlinx.coroutines.*\n",
|
||||
"\n",
|
||||
"val job = GlobalScope.launch {\n",
|
||||
" var time: Long = 0\n",
|
||||
" while (isActive) {\n",
|
||||
" delay(10)\n",
|
||||
" time += 10\n",
|
||||
" val dynamicY = x.map { sin(2.0 * PI * (it + time.toDouble() / 1000.0)) }\n",
|
||||
" trace.y.set(dynamicY)\n",
|
||||
" }\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 29,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2020-07-31T11:42+0300",
|
||||
"start_time": "2020-07-31T11:42+0300"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"job.cancel()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 30,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2020-07-31T11:42+0300",
|
||||
"start_time": "2020-07-31T11:42+0300"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"dynamicPlot.layout.xaxis.title = \"крокозябра\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 31,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2020-07-31T11:43+0300",
|
||||
"start_time": "2020-07-31T11:42+0300"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"11:43:00.894 [DefaultDispatcher-worker-2] DEBUG ktor.application - Closed server socket for kscience.plotly.Plot@1822ae52\n",
|
||||
"11:43:00.895 [DefaultDispatcher-worker-6] DEBUG ktor.application - Closed server socket for kscience.plotly.Plot@5ec8af0d\n",
|
||||
"11:43:00.896 [pool-2-thread-1] INFO ktor.application - 101 Switching Protocols: GET - /ws/kscience.plotly.Plot@1822ae52, cancelled\n",
|
||||
"11:43:00.897 [DefaultDispatcher-worker-14] DEBUG ktor.application - Closed server socket for kscience.plotly.Plot@4eefd342\n",
|
||||
"11:43:00.897 [pool-2-thread-2] INFO ktor.application - 101 Switching Protocols: GET - /ws/kscience.plotly.Plot@5ec8af0d, cancelled\n",
|
||||
"11:43:00.898 [pool-2-thread-3] INFO ktor.application - 101 Switching Protocols: GET - /ws/kscience.plotly.Plot@4eefd342, cancelled\n",
|
||||
"11:43:00.905 [DefaultDispatcher-worker-9] ERROR io.ktor.server.cio.HttpServer - Unhandled exception caught for CoroutineName(http-pipeline-writer)\n",
|
||||
"kotlinx.coroutines.CoroutinesInternalError: Fatal exception in coroutines machinery for DispatchedContinuation[ExperimentalCoroutineDispatcher@1a6cc06[scheduler = DefaultDispatcher@1aa286ac[Pool Size {core = 14, max = 1536}, Worker States {CPU = 7, blocking = 0, parked = 7, dormant = 0, terminated = 0}, running workers queues = [0c, 0c, 0c, 0c, 1c, 0c, 0c], global CPU queue size = 0, global blocking queue size = 0, Control State {created workers= 14, blocking tasks = 0, CPUs acquired = 7}]], Continuation at io.ktor.server.cio.backend.ServerPipelineKt$startServerConnectionPipeline$1$outputsActor$1.invokeSuspend(ServerPipeline.kt:49)@3401b226]. Please read KDoc to 'handleFatalException' method and report this incident to maintainers\n",
|
||||
"\tat kotlinx.coroutines.DispatchedTask.handleFatalException$kotlinx_coroutines_core(DispatchedTask.kt:93)\n",
|
||||
"\tat kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:64)\n",
|
||||
"\tat kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)\n",
|
||||
"\tat kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:738)\n",
|
||||
"\tat kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)\n",
|
||||
"\tat kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)\n",
|
||||
"Caused by: java.lang.ClassCastException: class kotlin.coroutines.jvm.internal.CompletedContinuation cannot be cast to class kotlinx.coroutines.DispatchedContinuation (kotlin.coroutines.jvm.internal.CompletedContinuation is in unnamed module of loader 'app'; kotlinx.coroutines.DispatchedContinuation is in unnamed module of loader java.net.URLClassLoader @7323f4f)\n",
|
||||
"\tat kotlinx.coroutines.CoroutineDispatcher.releaseInterceptedContinuation(CoroutineDispatcher.kt:103)\n",
|
||||
"\tat kotlin.coroutines.jvm.internal.ContinuationImpl.releaseIntercepted(ContinuationImpl.kt:118)\n",
|
||||
"\tat kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:39)\n",
|
||||
"\tat kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:55)\n",
|
||||
"\t... 4 common frames omitted\n",
|
||||
"11:43:00.905 [DefaultDispatcher-worker-4] ERROR io.ktor.server.cio.HttpServer - Unhandled exception caught for CoroutineName(http-pipeline-writer)\n",
|
||||
"kotlinx.coroutines.CoroutinesInternalError: Fatal exception in coroutines machinery for DispatchedContinuation[ExperimentalCoroutineDispatcher@1a6cc06[scheduler = DefaultDispatcher@1aa286ac[Pool Size {core = 14, max = 1536}, Worker States {CPU = 9, blocking = 0, parked = 5, dormant = 0, terminated = 0}, running workers queues = [0c, 1c, 0c, 0c, 0c, 0c, 1c, 0c, 0c], global CPU queue size = 0, global blocking queue size = 0, Control State {created workers= 14, blocking tasks = 0, CPUs acquired = 7}]], Continuation at io.ktor.server.cio.backend.ServerPipelineKt$startServerConnectionPipeline$1$outputsActor$1.invokeSuspend(ServerPipeline.kt:49)@34cb0946]. Please read KDoc to 'handleFatalException' method and report this incident to maintainers\n",
|
||||
"\tat kotlinx.coroutines.DispatchedTask.handleFatalException$kotlinx_coroutines_core(DispatchedTask.kt:93)\n",
|
||||
"\tat kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:64)\n",
|
||||
"\tat kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)\n",
|
||||
"\tat kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:738)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<div>Update server is stopped</div>\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"\tat kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)\n",
|
||||
"\tat kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)\n",
|
||||
"Caused by: java.lang.ClassCastException: class kotlin.coroutines.jvm.internal.CompletedContinuation cannot be cast to class kotlinx.coroutines.DispatchedContinuation (kotlin.coroutines.jvm.internal.CompletedContinuation is in unnamed module of loader 'app'; kotlinx.coroutines.DispatchedContinuation is in unnamed module of loader java.net.URLClassLoader @7323f4f)\n",
|
||||
"\tat kotlinx.coroutines.CoroutineDispatcher.releaseInterceptedContinuation(CoroutineDispatcher.kt:103)\n",
|
||||
"\tat kotlin.coroutines.jvm.internal.ContinuationImpl.releaseIntercepted(ContinuationImpl.kt:118)\n",
|
||||
"\tat kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:39)\n",
|
||||
"\tat kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:55)\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"JupyterPlotly.stopUpdates()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"@webio": {
|
||||
"lastCommId": null,
|
||||
"lastKernelId": null
|
||||
},
|
||||
"hide_input": false,
|
||||
"kernelspec": {
|
||||
"display_name": "Kotlin",
|
||||
"language": "kotlin",
|
||||
"name": "kotlin"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": "text/x-kotlin",
|
||||
"file_extension": ".kt",
|
||||
"mimetype": "text/x-kotlin",
|
||||
"name": "kotlin",
|
||||
"pygments_lexer": "kotlin",
|
||||
"version": "1.4.20-dev-2342"
|
||||
},
|
||||
"toc": {
|
||||
"base_numbering": 1,
|
||||
"nav_menu": {},
|
||||
"number_sections": false,
|
||||
"sideBar": false,
|
||||
"skip_h1_title": false,
|
||||
"title_cell": "Table of Contents",
|
||||
"title_sidebar": "Contents",
|
||||
"toc_cell": false,
|
||||
"toc_position": {},
|
||||
"toc_section_display": false,
|
||||
"toc_window_display": false
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
@ -0,0 +1,226 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2020-08-08T21:37+0300",
|
||||
"start_time": "2020-08-08T21:37+0300"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%use plotly-server\n",
|
||||
"import kotlin.math.*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2020-08-08T21:37+0300",
|
||||
"start_time": "2020-08-08T21:37+0300"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"val x1 = (0..100).map { it.toDouble() / 100.0 }\n",
|
||||
"val y1 = x1.map { sin(2.0 * PI * it) }\n",
|
||||
"val y2 = x1.map { cos(2.0 * PI * it) }\n",
|
||||
"\n",
|
||||
"val trace1 = Trace(x1, y1) { name = \"sin\" }\n",
|
||||
"val trace2 = Trace(x1, y2) { name = \"cos\" }\n",
|
||||
"\n",
|
||||
"val fragment = Plotly.fragment { renderer ->\n",
|
||||
" val plotConfig = PlotlyConfig{\n",
|
||||
" responsive = true\n",
|
||||
" } \n",
|
||||
" \n",
|
||||
" plot(\"above\", config = plotConfig, renderer = renderer) {\n",
|
||||
" traces(trace1, trace2)\n",
|
||||
" layout {\n",
|
||||
" title = \"The plot above\"\n",
|
||||
" xaxis.title = \"x axis name\"\n",
|
||||
" yaxis.title = \"y axis name\"\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
" hr()\n",
|
||||
" h1 { +\"A custom separator\" }\n",
|
||||
" hr()\n",
|
||||
" div {\n",
|
||||
" plot(renderer = renderer) {\n",
|
||||
" traces(trace1, trace2)\n",
|
||||
" layout {\n",
|
||||
" title = \"The plot below\"\n",
|
||||
" xaxis.title = \"x axis name\"\n",
|
||||
" yaxis.title = \"y axis name\"\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
"}\n",
|
||||
"fragment"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2020-08-08T21:37+0300",
|
||||
"start_time": "2020-08-08T21:37+0300"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"Plotly.plot {\n",
|
||||
" traces(trace1, trace2)\n",
|
||||
" layout {\n",
|
||||
" title = \"The plot below\"\n",
|
||||
" xaxis.title = \"x axis name\"\n",
|
||||
" yaxis.title = \"y axis name\"\n",
|
||||
" }\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2020-08-08T21:37+0300",
|
||||
"start_time": "2020-08-08T21:37+0300"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"val x = (0..100).map { it.toDouble() / 100.0 }\n",
|
||||
"val y = x.map { sin(2.0 * PI * it) }\n",
|
||||
"\n",
|
||||
"val trace = Trace(x, y) { name = \"sin\" }\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"val dynamicPlot = Plotly.plot {\n",
|
||||
" traces(trace)\n",
|
||||
" layout {\n",
|
||||
" title = \"Dynamic plot\"\n",
|
||||
" xaxis.title = \"x axis name\"\n",
|
||||
" yaxis.title = \"y axis name\"\n",
|
||||
" }\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"dynamicPlot"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2020-08-08T21:37+0300",
|
||||
"start_time": "2020-08-08T21:37+0300"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import kotlinx.coroutines.*\n",
|
||||
"\n",
|
||||
"val job = GlobalScope.launch {\n",
|
||||
" var time: Long = 0\n",
|
||||
" while (isActive) {\n",
|
||||
" delay(10)\n",
|
||||
" time += 10\n",
|
||||
" val dynamicY = x.map { sin(2.0 * PI * (it + time.toDouble() / 1000.0)) }\n",
|
||||
" trace.y.set(dynamicY)\n",
|
||||
" }\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2020-08-08T21:37+0300",
|
||||
"start_time": "2020-08-08T21:37+0300"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"job.cancel()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2020-08-08T21:37+0300",
|
||||
"start_time": "2020-08-08T21:37+0300"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"dynamicPlot.layout.xaxis.title = \"крокозябра\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2020-08-08T21:37+0300",
|
||||
"start_time": "2020-08-08T21:37+0300"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"plotly.port = 8884"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"@webio": {
|
||||
"lastCommId": null,
|
||||
"lastKernelId": null
|
||||
},
|
||||
"hide_input": false,
|
||||
"kernelspec": {
|
||||
"display_name": "Kotlin",
|
||||
"language": "kotlin",
|
||||
"name": "kotlin"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": "text/x-kotlin",
|
||||
"file_extension": ".kt",
|
||||
"mimetype": "text/x-kotlin",
|
||||
"name": "kotlin",
|
||||
"nbconvert_exporter": "",
|
||||
"pygments_lexer": "kotlin",
|
||||
"version": "1.5.30-dev-598"
|
||||
},
|
||||
"toc": {
|
||||
"base_numbering": 1,
|
||||
"nav_menu": {},
|
||||
"number_sections": false,
|
||||
"sideBar": false,
|
||||
"skip_h1_title": false,
|
||||
"title_cell": "Table of Contents",
|
||||
"title_sidebar": "Contents",
|
||||
"toc_cell": false,
|
||||
"toc_position": {},
|
||||
"toc_section_display": false,
|
||||
"toc_window_display": false
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
298
plotly/examples/notebooks/Issue-sim.ipynb
Normal file
298
plotly/examples/notebooks/Issue-sim.ipynb
Normal file
@ -0,0 +1,298 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%use plotly"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# API"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"enum class Severity(val penalty: Double){\n",
|
||||
" MINOR(1.0),\n",
|
||||
" MAJOR(2.0),\n",
|
||||
" CRITICAL(3.0)\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"enum class State{\n",
|
||||
" OPEN,\n",
|
||||
" ASSIGNED,\n",
|
||||
" RESOLVED\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"data class Issue(val id: String, val dayCreated: Int, val severity: Severity, val complexity: Int, \n",
|
||||
" var state: State = State.OPEN, var dayAssigned: Int? = null, var dayResolved: Int? = null){\n",
|
||||
" fun activate(day: Int){ \n",
|
||||
" state = State.ASSIGNED\n",
|
||||
" dayAssigned = day\n",
|
||||
" }\n",
|
||||
" \n",
|
||||
" fun resolve(day: Int){\n",
|
||||
" state = State.RESOLVED\n",
|
||||
" dayResolved = day\n",
|
||||
" }\n",
|
||||
" \n",
|
||||
" internal fun tryResolve(day: Int){\n",
|
||||
" if(state == State.ASSIGNED && day >= (dayAssigned ?: 0) + complexity ){\n",
|
||||
" resolve(day)\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"class Worker(val name: String){\n",
|
||||
" var currentIssue: Issue? = null\n",
|
||||
" private set\n",
|
||||
" \n",
|
||||
" fun isBusy(): Boolean = currentIssue != null\n",
|
||||
" \n",
|
||||
" fun update(day: Int){\n",
|
||||
" currentIssue?.tryResolve(day)\n",
|
||||
" if(currentIssue?.state == State.RESOLVED){\n",
|
||||
" currentIssue = null\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
" \n",
|
||||
" fun assign(day: Int, issue: Issue){\n",
|
||||
" if(currentIssue != null) error(\"Can't assign work to a worker which is busy\")\n",
|
||||
" issue.activate(day)\n",
|
||||
" currentIssue = issue\n",
|
||||
" }\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"interface IssueGenerator{\n",
|
||||
" fun generate(day: Int): List<Issue>\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"interface Strategy{\n",
|
||||
" fun selectIssue(day: Int, issues: List<Issue>): Issue?\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"class WorkResult(val issues: List<Issue>, val workers: Int, val days: Int)\n",
|
||||
"\n",
|
||||
"@OptIn(kotlin.ExperimentalStdlibApi::class)\n",
|
||||
"fun simulate(generator: IssueGenerator, strategy: Strategy, numWorkers: Int = 10, days: Int = 100): WorkResult{\n",
|
||||
" val workers = (0 until numWorkers).map{Worker(\"worker $it\")}\n",
|
||||
" val issues = buildList<Issue>{\n",
|
||||
" for(day in 0 until days){\n",
|
||||
" //update all workers\n",
|
||||
" workers.forEach { it.update(day) }\n",
|
||||
" //generate new issues\n",
|
||||
" val newIssues = generator.generate(day)\n",
|
||||
" addAll(newIssues)\n",
|
||||
" //Select all free workers\n",
|
||||
" workers.filter { !it.isBusy() }.forEach { worker->\n",
|
||||
" val unasigned = filter { it.state == State.OPEN }\n",
|
||||
" val anIssue = strategy.selectIssue(day, unasigned) //select an issue to assign from all unassigned issues\n",
|
||||
" if(anIssue != null){\n",
|
||||
" worker.assign(day, anIssue)\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
" return WorkResult(issues, numWorkers, days)\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"fun WorkResult.computeLoss(): Double = issues.sumByDouble { ((it.dayResolved ?: days) - it.dayCreated)*it.severity.penalty } / days / workers / issues.size"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Implementations"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import kotlin.random.Random\n",
|
||||
"import kotlin.math.pow\n",
|
||||
"\n",
|
||||
"/**\n",
|
||||
"* Generate one random issue per day\n",
|
||||
"*/\n",
|
||||
"class RandomIssueGenerator(seed: Long, val issuesPerDay: Int = 4 ) : IssueGenerator{\n",
|
||||
" private val random = Random(seed)\n",
|
||||
" override fun generate(day: Int): List<Issue>{\n",
|
||||
" return List(issuesPerDay){\n",
|
||||
" val severity = Severity.values()[random.nextInt(3)]\n",
|
||||
" val complexity = random.nextInt(15)\n",
|
||||
" Issue(\"${day}_${it}\", day, severity, complexity)\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"object TakeOldest: Strategy{\n",
|
||||
" override fun selectIssue(day: Int, issues: List<Issue>): Issue?{\n",
|
||||
" return issues.minByOrNull { it.dayCreated }\n",
|
||||
" }\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"class TakeRandom(seed: Long): Strategy{\n",
|
||||
" private val random = Random(seed)\n",
|
||||
" override fun selectIssue(day: Int, issues: List<Issue>): Issue?{\n",
|
||||
" if(issues.isEmpty()) return null\n",
|
||||
" return issues.random(random)\n",
|
||||
" }\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"object TakeCritical: Strategy{\n",
|
||||
" override fun selectIssue(day: Int, issues: List<Issue>): Issue?{\n",
|
||||
" return issues.maxByOrNull { it.severity.penalty*(day - it.dayCreated) }\n",
|
||||
" }\n",
|
||||
"}\n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Simulate lossseverity"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"val seed = 89L\n",
|
||||
"val days = 100\n",
|
||||
"val workers = 10"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Take oldest"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"val result = simulate(RandomIssueGenerator(seed, workers),TakeOldest, days = days)\n",
|
||||
"//result.issues.forEach { println(it)}\n",
|
||||
"result.computeLoss()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Take random"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"simulate(RandomIssueGenerator(seed, workers),TakeRandom(seed), days = days).computeLoss()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Take critical"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"simulate(RandomIssueGenerator(seed, workers), TakeCritical, days = days).computeLoss()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"val seeds = List(1000){Random.nextLong()}\n",
|
||||
"\n",
|
||||
"Plotly.plot{\n",
|
||||
" trace{\n",
|
||||
" x.numbers = seeds.map{ seed -> simulate(RandomIssueGenerator(seed, workers), TakeOldest, days = days).computeLoss()}\n",
|
||||
" name = \"oldest\"\n",
|
||||
" type = TraceType.histogram\n",
|
||||
" }\n",
|
||||
" trace{\n",
|
||||
" x.numbers = seeds.map{ seed -> simulate(RandomIssueGenerator(seed, workers), TakeRandom(seed), days = days).computeLoss()}\n",
|
||||
" name = \"random\"\n",
|
||||
" type = TraceType.histogram\n",
|
||||
" }\n",
|
||||
" trace{\n",
|
||||
" x.numbers = seeds.map{ seed -> simulate(RandomIssueGenerator(seed, workers), TakeCritical, days = days).computeLoss()}\n",
|
||||
" name = \"critical\"\n",
|
||||
" type = TraceType.histogram\n",
|
||||
" }\n",
|
||||
" layout{\n",
|
||||
" title = \"Loss distribtution\"\n",
|
||||
" xaxis {\n",
|
||||
" title = \"Loss\"\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Kotlin",
|
||||
"language": "kotlin",
|
||||
"name": "kotlin"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": "text/x-kotlin",
|
||||
"file_extension": ".kt",
|
||||
"mimetype": "text/x-kotlin",
|
||||
"name": "kotlin",
|
||||
"nbconvert_exporter": "",
|
||||
"pygments_lexer": "kotlin",
|
||||
"version": "1.5.30-dev-598"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
334
plotly/examples/notebooks/latex-demo.ipynb
Normal file
334
plotly/examples/notebooks/latex-demo.ipynb
Normal file
@ -0,0 +1,334 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"21:08:36.601 [DefaultDispatcher-worker-1] INFO ktor.application - No ktor.deployment.watch patterns specified, automatic reload is not active\n",
|
||||
"21:08:36.645 [DefaultDispatcher-worker-1] INFO ktor.application - Responding at http://0.0.0.0:8882\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<div id=\"plotly-load-scripts\"></div>\n",
|
||||
"<script type=\"text/javascript\">(function() {\n",
|
||||
" console.log(\"Starting up plotly script loader\");\n",
|
||||
" //initialize LaTeX for Jupyter\n",
|
||||
" window.PlotlyConfig = {MathJaxConfig: 'local'};\n",
|
||||
"\n",
|
||||
" window.startupPlotly = function (){\n",
|
||||
" if (window.MathJax){ \n",
|
||||
" MathJax.Hub.Config({\n",
|
||||
" SVG: {\n",
|
||||
" font: \"STIX-Web\"\n",
|
||||
" }\n",
|
||||
" });\n",
|
||||
" } \n",
|
||||
" console.info(\"Calling deferred operations in Plotly queue.\")\n",
|
||||
" window.plotlyCallQueue.forEach(function(theCall) {theCall();});\n",
|
||||
" window.plotlyCallQueue = []; \n",
|
||||
" }\n",
|
||||
"})();</script>\n",
|
||||
"<script type=\"text/javascript\" src=\"//localhost:8882/js/plotly.min.js\"></script>\n",
|
||||
"<script type=\"text/javascript\">/**\r\n",
|
||||
" * Use existing plotly or load it from the CDN if it is not available\r\n",
|
||||
" * @param action\r\n",
|
||||
" */\r\n",
|
||||
"function withPlotly(action) {\r\n",
|
||||
" if (typeof Plotly !== \"undefined\") {\r\n",
|
||||
" action(Plotly);\r\n",
|
||||
" } else if (typeof window.promiseOfPlotly !== \"undefined\") {\r\n",
|
||||
" window.promiseOfPlotly.then(plotly => action(plotly));\r\n",
|
||||
" } else {\r\n",
|
||||
" console.warn(\"Plotly not defined. Loading the script from CDN\")\r\n",
|
||||
" window.promiseOfPlotly = new Promise((accept, reject) => {\r\n",
|
||||
" let plotlyLoaderScript = document.createElement(\"script\");\r\n",
|
||||
" plotlyLoaderScript.src = \"https://cdnjs.cloudflare.com/ajax/libs/plotly.js/1.54.6/plotly.min.js\";\r\n",
|
||||
" plotlyLoaderScript.type = 'text/javascript';\r\n",
|
||||
" plotlyLoaderScript.onload = () => {\r\n",
|
||||
" accept(Plotly);\r\n",
|
||||
" }\r\n",
|
||||
" plotlyLoaderScript.onerror = (error) => {\r\n",
|
||||
" console.error(error);\r\n",
|
||||
" reject(error)\r\n",
|
||||
" }\r\n",
|
||||
" document.head.appendChild(plotlyLoaderScript);\r\n",
|
||||
" });\r\n",
|
||||
" }\r\n",
|
||||
"}\r\n",
|
||||
"\r\n",
|
||||
"/**\r\n",
|
||||
" * Request and parse json from given address\r\n",
|
||||
" * @param url {URL}\r\n",
|
||||
" * @param callback\r\n",
|
||||
" * @return Promise<Json>\r\n",
|
||||
" */\r\n",
|
||||
"function getJSON(url, callback) {\r\n",
|
||||
"\r\n",
|
||||
" function handleErrors(response) {\r\n",
|
||||
" if (!response.ok) {\r\n",
|
||||
" throw Error(response.statusText);\r\n",
|
||||
" }\r\n",
|
||||
" return response;\r\n",
|
||||
" }\r\n",
|
||||
"\r\n",
|
||||
" try {\r\n",
|
||||
" fetch(url, {\r\n",
|
||||
" method: 'GET',\r\n",
|
||||
" headers: {\r\n",
|
||||
" Accept: 'application/json',\r\n",
|
||||
" }\r\n",
|
||||
" })\r\n",
|
||||
" .then(handleErrors)\r\n",
|
||||
" .then(response => response.json())\r\n",
|
||||
" .then(json => callback(json))\r\n",
|
||||
" .catch(error => console.log(error));\r\n",
|
||||
" } catch (e) {\r\n",
|
||||
" alert(\"Fetch of plot data failed with error: \" + e)\r\n",
|
||||
" }\r\n",
|
||||
"}\r\n",
|
||||
"\r\n",
|
||||
"/**\r\n",
|
||||
" * Safe call for Plotly.newPlot\r\n",
|
||||
" * @param id\r\n",
|
||||
" * @param data\r\n",
|
||||
" * @param layout\r\n",
|
||||
" * @param config\r\n",
|
||||
" */\r\n",
|
||||
"function makePlot(id, data, layout, config) {\r\n",
|
||||
" withPlotly(plotly => plotly.newPlot(id, data, layout, config))\r\n",
|
||||
"}\r\n",
|
||||
"\r\n",
|
||||
"/**\r\n",
|
||||
" * Create a plot taking data from given url\r\n",
|
||||
" * @param id {string} element id for plot\r\n",
|
||||
" * @param from {URL} json server url\r\n",
|
||||
" * @param config {object} plotly configuration\r\n",
|
||||
" * @return {JSON}\r\n",
|
||||
" */\r\n",
|
||||
"function createPlotFrom(id, from, config = {}) {\r\n",
|
||||
" getJSON(from, json => withPlotly(plotly => {\r\n",
|
||||
" plotly.newPlot(id, json.data, json.layout, config)\r\n",
|
||||
" }));\r\n",
|
||||
"}\r\n",
|
||||
"\r\n",
|
||||
"/**\r\n",
|
||||
" * Update a plot taking data from given url\r\n",
|
||||
" * @param id {string} element id for plot\r\n",
|
||||
" * @param from {URL} json server url\r\n",
|
||||
" * @return {JSON}\r\n",
|
||||
" */\r\n",
|
||||
"function updatePlotFrom(id, from) {\r\n",
|
||||
" getJSON(from, json => withPlotly(plotly => plotly.react(id, json.data, json.layout)));\r\n",
|
||||
"}\r\n",
|
||||
"\r\n",
|
||||
"/**\r\n",
|
||||
" * Start pull updates with regular requests from client side\r\n",
|
||||
" * @param id {string}\r\n",
|
||||
" * @param from\r\n",
|
||||
" * @param millis\r\n",
|
||||
" */\r\n",
|
||||
"function startPull(id, from, millis) {\r\n",
|
||||
" let action = function () {\r\n",
|
||||
" updatePlotFrom(id, from)\r\n",
|
||||
" };\r\n",
|
||||
" window.setInterval(action, millis)\r\n",
|
||||
"}\r\n",
|
||||
"\r\n",
|
||||
"/**\r\n",
|
||||
" * Start push updates via websocket\r\n",
|
||||
" * @param id {string} element id for plot\r\n",
|
||||
" * @param ws {URL} a websocket address\r\n",
|
||||
" */\r\n",
|
||||
"function startPush(id, ws) {\r\n",
|
||||
" let socket = new WebSocket(ws);\r\n",
|
||||
"\r\n",
|
||||
" socket.onopen = function () {\r\n",
|
||||
" console.log(\"[Plotly.kt] A connection for plot with id = \" + id + \" with server established on \" + ws);\r\n",
|
||||
" };\r\n",
|
||||
"\r\n",
|
||||
" socket.onclose = function (event) {\r\n",
|
||||
" if (event.wasClean) {\r\n",
|
||||
" console.log(\"The connection with server is closed\");\r\n",
|
||||
" } else {\r\n",
|
||||
" console.log(\"The connection with server is broken\"); // Server process is dead\r\n",
|
||||
" }\r\n",
|
||||
" console.log('Code: ' + event.code + ' case: ' + event.reason);\r\n",
|
||||
" };\r\n",
|
||||
"\r\n",
|
||||
" socket.onerror = function (error) {\r\n",
|
||||
" console.error(\"Ploty push update error: \" + error.message);\r\n",
|
||||
" socket.close()\r\n",
|
||||
" };\r\n",
|
||||
"\r\n",
|
||||
" socket.onmessage = function (event) {\r\n",
|
||||
" //console.log('got message: ' + event.data);\r\n",
|
||||
" let json = JSON.parse(event.data);\r\n",
|
||||
" //TODO check if plotly is initialized in a cell\r\n",
|
||||
" if (json.plotId === id) {\r\n",
|
||||
" if (json.contentType === \"layout\") {\r\n",
|
||||
" withPlotly(plotly => plotly.relayout(id, json.content));\r\n",
|
||||
" } else if (json.contentType === \"trace\") {\r\n",
|
||||
" let content = json.content;\r\n",
|
||||
" //This is done to satisfy plotly requirements of arrays-in-arrays for data\r\n",
|
||||
" if (content.hasOwnProperty('x')) {\r\n",
|
||||
" content.x = [content.x];\r\n",
|
||||
" }\r\n",
|
||||
" if (content.hasOwnProperty('y')) {\r\n",
|
||||
" content.y = [content.y];\r\n",
|
||||
" }\r\n",
|
||||
" if (content.hasOwnProperty('z')) {\r\n",
|
||||
" content.z = [content.z];\r\n",
|
||||
" }\r\n",
|
||||
" withPlotly(plotly => plotly.restyle(id, content, json['trace']));\r\n",
|
||||
" }\r\n",
|
||||
" }\r\n",
|
||||
" };\r\n",
|
||||
"\r\n",
|
||||
" //gracefully close socket just in case\r\n",
|
||||
" window.onbeforeunload = function () {\r\n",
|
||||
" console.log(\"Gracefully closing socket\");\r\n",
|
||||
" socket.onclose = function () {\r\n",
|
||||
" }; // disable onclose handler first\r\n",
|
||||
" socket.close();\r\n",
|
||||
" };\r\n",
|
||||
"}\r\n",
|
||||
"\r\n",
|
||||
"\r\n",
|
||||
"window.startupPlotly()</script>\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"%use plotly"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2020-08-07T11:08+0300",
|
||||
"start_time": "2020-08-07T11:08+0300"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<div>\n",
|
||||
" <div id=\"scientifik.plotly.Plot@122c8b64\">\n",
|
||||
" <script>\n",
|
||||
"let theCall = function(){\n",
|
||||
" makePlot(\n",
|
||||
" 'scientifik.plotly.Plot@122c8b64',\n",
|
||||
" [{\"x\":[2,3,4,5],\"y\":[10,15,13,17],\"type\":\"scatter\"}],\n",
|
||||
" {\"annotations\":[{\"@index\":\"0\",\"x\":2,\"y\":10,\"text\":\"$\\\\alpha$\",\"font\":{\"size\":18}},{\"@index\":\"1\",\"x\":5,\"y\":17,\"text\":\"$\\\\Omega$\",\"font\":{\"size\":18}}],\"title\":{\"text\":\"$\\\\text{Plot with annotations } \\\\alpha~and~\\\\Omega$\"}},\n",
|
||||
" {\"responsive\":true}\n",
|
||||
" ); \n",
|
||||
"};\n",
|
||||
"\n",
|
||||
"if(typeof Plotly === 'undefined'){\n",
|
||||
" if(!window.plotlyCallQueue) {\n",
|
||||
" window.plotlyCallQueue = [];\n",
|
||||
" } \n",
|
||||
" window.plotlyCallQueue.push(theCall)\n",
|
||||
" window.plotlyCall(theCall);\n",
|
||||
"} else {\n",
|
||||
" theCall();\n",
|
||||
"}\n",
|
||||
"</script>\n",
|
||||
" <script id=\"scientifik.plotly.Plot@122c8b64-push\">\n",
|
||||
" \n",
|
||||
" startPush('scientifik.plotly.Plot@122c8b64', 'ws://localhost:8882/ws/scientifik.plotly.Plot@122c8b64');\n",
|
||||
" \n",
|
||||
" </script>\n",
|
||||
" </div>\n",
|
||||
"</div>\n"
|
||||
]
|
||||
},
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"Plotly.plot {\n",
|
||||
" scatter {\n",
|
||||
" x(2, 3, 4, 5)\n",
|
||||
" y(10, 15, 13, 17)\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" text {\n",
|
||||
" position(2, 10)\n",
|
||||
" font {\n",
|
||||
" size = 18\n",
|
||||
" }\n",
|
||||
" text = \"\\$\\\\alpha\\$\"\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" text {\n",
|
||||
" position(5, 17)\n",
|
||||
" font {\n",
|
||||
" size = 18\n",
|
||||
" }\n",
|
||||
" text = \"\\$\\\\Omega\\$\"\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" layout {\n",
|
||||
" title {\n",
|
||||
" text = \"\\$\\\\text{Plot with annotations } \\\\alpha~and~\\\\Omega\\$\"\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"hide_input": false,
|
||||
"kernelspec": {
|
||||
"display_name": "Kotlin",
|
||||
"language": "kotlin",
|
||||
"name": "kotlin"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": "text/x-kotlin",
|
||||
"file_extension": ".kt",
|
||||
"mimetype": "text/x-kotlin",
|
||||
"name": "kotlin",
|
||||
"pygments_lexer": "kotlin",
|
||||
"version": "1.4.20-dev-2342"
|
||||
},
|
||||
"toc": {
|
||||
"base_numbering": 1,
|
||||
"nav_menu": {},
|
||||
"number_sections": false,
|
||||
"sideBar": false,
|
||||
"skip_h1_title": false,
|
||||
"title_cell": "Table of Contents",
|
||||
"title_sidebar": "Contents",
|
||||
"toc_cell": false,
|
||||
"toc_position": {},
|
||||
"toc_section_display": false,
|
||||
"toc_window_display": false
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
156
plotly/examples/notebooks/plotlykt-demo.ipynb
Normal file
156
plotly/examples/notebooks/plotlykt-demo.ipynb
Normal file
@ -0,0 +1,156 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import space.kscience.plotly.PlotlyIntegration\n",
|
||||
"USE(PlotlyIntegration())\n",
|
||||
"//@file:CompilerArgs(\"-jvm-target=11\")\n",
|
||||
"//@file:Repository(\"https://repo.kotlin.link\")\n",
|
||||
"//@file:DependsOn(\"space.kscience:plotlykt-jupyter-jvm:0.7.1\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import kotlin.math.*\n",
|
||||
"\n",
|
||||
"val x1 = (0..100).map { it.toDouble() / 100.0 }\n",
|
||||
"val y1 = x1.map { sin(2.0 * PI * it) }\n",
|
||||
"val y2 = x1.map { cos(2.0 * PI * it) }\n",
|
||||
"\n",
|
||||
"val trace1 = Trace(x1, y1) { name = \"sin\" }\n",
|
||||
"val trace2 = Trace(x1, y2) { name = \"cos\" }\n",
|
||||
"\n",
|
||||
"Plotly.page { renderer ->\n",
|
||||
" val plotConfig = PlotlyConfig{\n",
|
||||
" responsive = true\n",
|
||||
" imageFormat = \"svg\"\n",
|
||||
" } \n",
|
||||
" h1 { +\"A custom header\" }\n",
|
||||
" hr()\n",
|
||||
" plot(\"below\", config = plotConfig, renderer = renderer) {\n",
|
||||
" traces(trace1, trace2)\n",
|
||||
" layout {\n",
|
||||
" title = \"The plot below\"\n",
|
||||
" xaxis.title = \"x axis name\"\n",
|
||||
" yaxis.title = \"y axis name\"\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"HTML(\n",
|
||||
" \"\"\"\n",
|
||||
" <div id=\"debug\">\n",
|
||||
" debug\n",
|
||||
" </div>\n",
|
||||
" \"\"\".trimIndent()\n",
|
||||
")"
|
||||
],
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"HTML(\"\"\"\n",
|
||||
"<script type = \"text/javascript\">\n",
|
||||
" element = document.getElementById(\"debug\")\n",
|
||||
" element.append(window.Plotly)\n",
|
||||
" element.append(window.plotlyConnect)\n",
|
||||
"</script>\n",
|
||||
" \"\"\".trimIndent())"
|
||||
],
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"outputs": [],
|
||||
"source": [],
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"HTML(\"\"\"\n",
|
||||
"<script src=\"https://cdn.plot.ly/plotly-2.29.1.min.js\" charset=\"utf-8\"></script>\n",
|
||||
"\"\"\")"
|
||||
],
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"execution_count": null
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"outputs": [],
|
||||
"source": [],
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"@webio": {
|
||||
"lastCommId": null,
|
||||
"lastKernelId": null
|
||||
},
|
||||
"hide_input": false,
|
||||
"kernelspec": {
|
||||
"display_name": "Kotlin",
|
||||
"language": "kotlin",
|
||||
"name": "kotlin"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": "text/x-kotlin",
|
||||
"file_extension": ".kt",
|
||||
"mimetype": "text/x-kotlin",
|
||||
"name": "kotlin",
|
||||
"nbconvert_exporter": "",
|
||||
"pygments_lexer": "kotlin",
|
||||
"version": "1.5.30-dev-598"
|
||||
},
|
||||
"toc": {
|
||||
"base_numbering": 1,
|
||||
"nav_menu": {},
|
||||
"number_sections": false,
|
||||
"sideBar": false,
|
||||
"skip_h1_title": false,
|
||||
"title_cell": "Table of Contents",
|
||||
"title_sidebar": "Contents",
|
||||
"toc_cell": false,
|
||||
"toc_position": {},
|
||||
"toc_section_display": false,
|
||||
"toc_window_display": false
|
||||
},
|
||||
"ktnbPluginMetadata": {
|
||||
"projectDependencies": true
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
213
plotly/examples/notebooks/plotlykt-server-demo.ipynb
Normal file
213
plotly/examples/notebooks/plotlykt-server-demo.ipynb
Normal file
@ -0,0 +1,213 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import space.kscience.plotly.server.PlotlyServerIntegration\n",
|
||||
"import space.kscience.plotly.server.jupyter\n",
|
||||
"\n",
|
||||
"USE(PlotlyServerIntegration())"
|
||||
],
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import kotlin.math.*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"val x1 = (0..100).map { it.toDouble() / 100.0 }\n",
|
||||
"val y1 = x1.map { sin(2.0 * PI * it) }\n",
|
||||
"val y2 = x1.map { cos(2.0 * PI * it) }\n",
|
||||
"\n",
|
||||
"val trace1 = Trace(x1, y1) { name = \"sin\" }\n",
|
||||
"val trace2 = Trace(x1, y2) { name = \"cos\" }\n",
|
||||
"\n",
|
||||
"val fragment = Plotly.fragment { renderer ->\n",
|
||||
" val plotConfig = PlotlyConfig {\n",
|
||||
" responsive = true\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" plot(\"above\", config = plotConfig, renderer = renderer) {\n",
|
||||
" traces(trace1, trace2)\n",
|
||||
" layout {\n",
|
||||
" title = \"The plot above\"\n",
|
||||
" xaxis.title = \"x axis name\"\n",
|
||||
" yaxis.title = \"y axis name\"\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
" hr()\n",
|
||||
" h1 { +\"A custom separator\" }\n",
|
||||
" hr()\n",
|
||||
" div {\n",
|
||||
" plot(\"below\", renderer = renderer) {\n",
|
||||
" traces(trace1, trace2)\n",
|
||||
" layout {\n",
|
||||
" title = \"The plot below\"\n",
|
||||
" xaxis.title = \"x axis name\"\n",
|
||||
" yaxis.title = \"y axis name\"\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
"}\n",
|
||||
"fragment"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"Plotly.plot {\n",
|
||||
" traces(trace1, trace2)\n",
|
||||
" layout {\n",
|
||||
" title = \"The plot below\"\n",
|
||||
" xaxis.title = \"x axis name\"\n",
|
||||
" yaxis.title = \"y axis name\"\n",
|
||||
" }\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"val x = (0..100).map { it.toDouble() / 100.0 }\n",
|
||||
"val y = x.map { sin(2.0 * PI * it) }\n",
|
||||
"\n",
|
||||
"val trace = Trace(x, y) { name = \"sin\" }\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"val dynamicPlot = Plotly.plot {\n",
|
||||
" traces(trace)\n",
|
||||
" layout {\n",
|
||||
" title = \"Dynamic plot\"\n",
|
||||
" xaxis.title = \"x axis name\"\n",
|
||||
" yaxis.title = \"y axis name\"\n",
|
||||
" }\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"dynamicPlot"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import kotlinx.coroutines.*\n",
|
||||
"\n",
|
||||
"val job = GlobalScope.launch {\n",
|
||||
" var time: Long = 0\n",
|
||||
" while (isActive) {\n",
|
||||
" delay(10)\n",
|
||||
" time += 10\n",
|
||||
" val dynamicY = x.map { sin(2.0 * PI * (it + time.toDouble() / 1000.0)) }\n",
|
||||
" trace.y.set(dynamicY)\n",
|
||||
" }\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"job.cancel()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"dynamicPlot.layout.xaxis.title = \"крокозябра\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"Plotly.jupyter.port = 8884"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"Plotly.jupyter.port"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"outputs": [],
|
||||
"source": [],
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"@webio": {
|
||||
"lastCommId": null,
|
||||
"lastKernelId": null
|
||||
},
|
||||
"hide_input": false,
|
||||
"kernelspec": {
|
||||
"display_name": "Kotlin",
|
||||
"language": "kotlin",
|
||||
"name": "kotlin"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": "text/x-kotlin",
|
||||
"file_extension": ".kt",
|
||||
"mimetype": "text/x-kotlin",
|
||||
"name": "kotlin",
|
||||
"nbconvert_exporter": "",
|
||||
"pygments_lexer": "kotlin",
|
||||
"version": "1.5.30-dev-598"
|
||||
},
|
||||
"toc": {
|
||||
"base_numbering": 1,
|
||||
"nav_menu": {},
|
||||
"number_sections": false,
|
||||
"sideBar": false,
|
||||
"skip_h1_title": false,
|
||||
"title_cell": "Table of Contents",
|
||||
"title_sidebar": "Contents",
|
||||
"toc_cell": false,
|
||||
"toc_position": {},
|
||||
"toc_section_display": false,
|
||||
"toc_window_display": false
|
||||
},
|
||||
"ktnbPluginMetadata": {
|
||||
"projectDependencies": true
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package annotation
|
||||
|
||||
import space.kscience.plotly.*
|
||||
import space.kscience.plotly.models.ScatterMode
|
||||
|
||||
fun main() {
|
||||
val plot = Plotly.plot {
|
||||
scatter {
|
||||
x(2, 3, 4, 5)
|
||||
y(10, 15, 13, 17)
|
||||
mode = ScatterMode.lines
|
||||
}
|
||||
|
||||
text {
|
||||
position(2, 10)
|
||||
text = "start"
|
||||
}
|
||||
|
||||
text {
|
||||
position(5, 17)
|
||||
text = "finish"
|
||||
}
|
||||
|
||||
layout {
|
||||
title = "Plot with annotation"
|
||||
}
|
||||
}
|
||||
|
||||
plot.makeFile()
|
||||
}
|
45
plotly/examples/src/main/kotlin/bar/BarChartWithHoverText.kt
Normal file
45
plotly/examples/src/main/kotlin/bar/BarChartWithHoverText.kt
Normal file
@ -0,0 +1,45 @@
|
||||
package bar
|
||||
|
||||
import space.kscience.dataforge.meta.invoke
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.bar
|
||||
import space.kscience.plotly.makeFile
|
||||
|
||||
|
||||
/**
|
||||
* - Bar chart with hover text
|
||||
* - Use rgb color palette
|
||||
* - Rotate axis ticks
|
||||
*/
|
||||
fun main() {
|
||||
val plot = Plotly.plot {
|
||||
bar {
|
||||
x("Liam", "Sophie", "Jacob", "Mia", "William", "Olivia")
|
||||
y(8.0, 8.0, 12.0, 12.0, 13.0, 20.0)
|
||||
text("4.17 below the mean", "4.17 below the mean", "0.17 below the mean",
|
||||
"0.17 below the mean", "0.83 above the mean", "7.83 above the mean")
|
||||
marker {
|
||||
color("rgb(142, 124, 195)")
|
||||
}
|
||||
showlegend = false
|
||||
}
|
||||
|
||||
layout {
|
||||
title {
|
||||
text = "Number of Graphs Made this Week"
|
||||
font {
|
||||
family = "Raleway, sans-serif"
|
||||
}
|
||||
}
|
||||
xaxis {
|
||||
tickangle = -45
|
||||
}
|
||||
yaxis {
|
||||
zeroline = false
|
||||
gridwidth = 2
|
||||
}
|
||||
bargap = 0.05
|
||||
}
|
||||
}
|
||||
plot.makeFile()
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
package bar
|
||||
|
||||
import space.kscience.dataforge.meta.invoke
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.makeFile
|
||||
import space.kscience.plotly.models.Bar
|
||||
import space.kscience.plotly.models.BarMode
|
||||
|
||||
|
||||
/**
|
||||
* - Colored and styled bar chart
|
||||
* - Change font size and color of axis title & labels
|
||||
* - Use grouped barmode
|
||||
*/
|
||||
fun main() {
|
||||
val years = listOf(1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012)
|
||||
val trace1 = Bar {
|
||||
x.set(years)
|
||||
y(219, 146, 112, 127, 124, 180, 236, 207, 236, 263, 350, 430, 474, 526, 488, 537, 500, 439)
|
||||
name = "Rest of world"
|
||||
marker {
|
||||
color("rgb(55, 83, 109)")
|
||||
}
|
||||
}
|
||||
|
||||
val trace2 = Bar {
|
||||
x.set(years)
|
||||
y(16, 13, 10, 11, 28, 37, 43, 55, 56, 88, 105, 156, 270, 299, 340, 403, 549, 499)
|
||||
name = "China"
|
||||
marker {
|
||||
color("rgb(26, 118, 255)")
|
||||
}
|
||||
}
|
||||
|
||||
val plot = Plotly.plot {
|
||||
traces(trace1, trace2)
|
||||
|
||||
layout {
|
||||
title = "US Export of Plastic Scrap"
|
||||
xaxis {
|
||||
tickfont {
|
||||
size = 14
|
||||
color("rgb(107, 107, 107)")
|
||||
}
|
||||
}
|
||||
yaxis {
|
||||
title {
|
||||
text = "USD (millions)"
|
||||
font {
|
||||
size = 16
|
||||
color("rgb(107, 107, 107)")
|
||||
}
|
||||
}
|
||||
tickfont {
|
||||
size = 14
|
||||
color("rgb(107, 107, 107)")
|
||||
}
|
||||
}
|
||||
legend {
|
||||
x = 0
|
||||
y = 1.0
|
||||
bgcolor("rgba(255, 255, 255, 0)")
|
||||
bordercolor("rgba(255, 255, 255, 0)")
|
||||
}
|
||||
|
||||
barmode = BarMode.group
|
||||
bargap = 0.15
|
||||
bargroupgap = 0.1
|
||||
}
|
||||
}
|
||||
plot.makeFile()
|
||||
}
|
43
plotly/examples/src/main/kotlin/bar/GroupedBarChart.kt
Normal file
43
plotly/examples/src/main/kotlin/bar/GroupedBarChart.kt
Normal file
@ -0,0 +1,43 @@
|
||||
package bar
|
||||
|
||||
import space.kscience.dataforge.meta.invoke
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.makeFile
|
||||
import space.kscience.plotly.models.Bar
|
||||
import space.kscience.plotly.models.BarMode
|
||||
import space.kscience.plotly.palettes.Xkcd
|
||||
|
||||
|
||||
/**
|
||||
* - Grouped bar chart
|
||||
* - Use XKCD color palette
|
||||
*/
|
||||
fun main() {
|
||||
val trace1 = Bar {
|
||||
x("giraffes", "orangutans", "monkeys")
|
||||
y(20, 14, 23)
|
||||
name = "SF Zoo"
|
||||
marker {
|
||||
color(Xkcd.GREEN)
|
||||
}
|
||||
}
|
||||
|
||||
val trace2 = Bar {
|
||||
x("giraffes", "orangutans", "monkeys")
|
||||
y(12, 18, 29)
|
||||
name = "LA Zoo"
|
||||
marker {
|
||||
color(Xkcd.BLUE)
|
||||
}
|
||||
}
|
||||
|
||||
val plot = Plotly.plot {
|
||||
traces(trace1, trace2)
|
||||
|
||||
layout {
|
||||
title = "Grouped Bar Chart"
|
||||
barmode = BarMode.group
|
||||
}
|
||||
}
|
||||
plot.makeFile()
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
package bar
|
||||
|
||||
import space.kscience.dataforge.meta.invoke
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.makeFile
|
||||
import space.kscience.plotly.models.Bar
|
||||
import space.kscience.plotly.models.TextPosition
|
||||
|
||||
|
||||
/**
|
||||
* - Grouped bar chart
|
||||
* - Use rgb(a) color palette
|
||||
* - Hide hoverinfo & legend
|
||||
* - Show text on the bars
|
||||
*/
|
||||
fun main() {
|
||||
val xValues = listOf("Product A", "Product B", "Product C")
|
||||
val yValues = listOf(20, 14, 23)
|
||||
val yValues2 = listOf(24, 16, 20)
|
||||
|
||||
val trace1 = Bar {
|
||||
x.strings = xValues
|
||||
y.numbers = yValues
|
||||
text.strings = yValues.map { it.toString() }
|
||||
textposition = TextPosition.auto
|
||||
hoverinfo = "none"
|
||||
opacity = 0.5
|
||||
showlegend = false
|
||||
marker {
|
||||
color("rgb(158, 202, 225)")
|
||||
line {
|
||||
color("rgb(8, 48, 107)")
|
||||
width = 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val trace2 = Bar {
|
||||
x.strings = xValues
|
||||
y.numbers = yValues2
|
||||
text.strings = yValues2.map { it.toString() }
|
||||
textposition = TextPosition.auto
|
||||
hoverinfo = "none"
|
||||
showlegend = false
|
||||
marker {
|
||||
color("rgba(58, 200, 225, 0.5)")
|
||||
line {
|
||||
color("rgb(8, 48, 107)")
|
||||
width = 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val plot = Plotly.plot {
|
||||
traces(trace1, trace2)
|
||||
|
||||
layout {
|
||||
title = "January 2013 Sales Report"
|
||||
}
|
||||
}
|
||||
plot.makeFile()
|
||||
}
|
61
plotly/examples/src/main/kotlin/bar/HorizontalBarPlot.kt
Normal file
61
plotly/examples/src/main/kotlin/bar/HorizontalBarPlot.kt
Normal file
@ -0,0 +1,61 @@
|
||||
package bar
|
||||
|
||||
import space.kscience.dataforge.meta.invoke
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.makeFile
|
||||
import space.kscience.plotly.models.Bar
|
||||
import space.kscience.plotly.models.Orientation
|
||||
import kotlin.random.Random
|
||||
|
||||
|
||||
/**
|
||||
* - Horizontal bar chart
|
||||
* - Use css named color palette
|
||||
* - Change fontsize of the ticks
|
||||
* - Add space between axis and ticklabels (set tickcolor to white)
|
||||
*/
|
||||
fun main() {
|
||||
val colors = listOf("DarkOliveGreen", "OliveDrab", "YellowGreen", "GreenYellow", "Yellow", "PeachPuff",
|
||||
"Pink", "HotPink", "DeepPink", "MediumVioletRed", "Purple", "RebeccaPurple", "MediumBlue", "Blue",
|
||||
"DodgerBlue", "SteelBlue", "LightSlateGrey", "SlateGrey", "DarkSlateGrey", "Black")
|
||||
val length = mutableListOf<Double>()
|
||||
for (i in colors.indices) {
|
||||
length.add(Random.nextDouble())
|
||||
}
|
||||
|
||||
val bar = Bar {
|
||||
y.strings = colors
|
||||
x.numbers = length
|
||||
orientation = Orientation.h
|
||||
marker {
|
||||
colors(colors)
|
||||
}
|
||||
}
|
||||
|
||||
val plot = Plotly.plot {
|
||||
traces(bar)
|
||||
|
||||
layout {
|
||||
title = "What an Awesome Plot!"
|
||||
height = 700
|
||||
width = 1200
|
||||
margin {
|
||||
l = 160
|
||||
}
|
||||
|
||||
xaxis {
|
||||
tickfont {
|
||||
size = 14
|
||||
}
|
||||
}
|
||||
yaxis {
|
||||
tickfont {
|
||||
size = 16
|
||||
}
|
||||
ticklen = 4
|
||||
tickcolor("white")
|
||||
}
|
||||
}
|
||||
}
|
||||
plot.makeFile()
|
||||
}
|
41
plotly/examples/src/main/kotlin/bar/IndividualBarBase.kt
Normal file
41
plotly/examples/src/main/kotlin/bar/IndividualBarBase.kt
Normal file
@ -0,0 +1,41 @@
|
||||
package bar
|
||||
|
||||
import space.kscience.dataforge.meta.invoke
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.makeFile
|
||||
import space.kscience.plotly.models.Bar
|
||||
|
||||
|
||||
/**
|
||||
* - Bar chart with customized base
|
||||
* -
|
||||
*/
|
||||
fun main() {
|
||||
val trace1 = Bar {
|
||||
x("2016", "2017", "2018")
|
||||
y(500, 600, 700)
|
||||
base = listOf(-500, -600, -700)
|
||||
marker {
|
||||
color("red")
|
||||
}
|
||||
name = "expenses"
|
||||
}
|
||||
|
||||
val trace2 = Bar {
|
||||
x("2016", "2017", "2018")
|
||||
y(300, 400, 700)
|
||||
marker {
|
||||
color("blue")
|
||||
}
|
||||
name = "revenue"
|
||||
}
|
||||
|
||||
val plot = Plotly.plot {
|
||||
traces(trace1, trace2)
|
||||
|
||||
layout {
|
||||
title = "Customizing individual bar base"
|
||||
}
|
||||
}
|
||||
plot.makeFile()
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package bar
|
||||
|
||||
import space.kscience.dataforge.meta.invoke
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.bar
|
||||
import space.kscience.plotly.makeFile
|
||||
|
||||
|
||||
/**
|
||||
* - Colored bar chart
|
||||
* - Use array of colors
|
||||
* - Make bar chart without making Bar piece
|
||||
* - Customizing individual bar colors and width
|
||||
*/
|
||||
fun main() {
|
||||
val plot = Plotly.plot {
|
||||
bar {
|
||||
x("Feature A", "Feature B", "Feature C", "Feature D", "Feature E")
|
||||
y(20, 14, 23, 25, 22)
|
||||
widthList = listOf<Number>(0.8, 0.8, 0.9, 0.6, 0.8)
|
||||
marker {
|
||||
colors(listOf("rgba(204, 204, 204, 1)", "rgba(222, 45, 38, 0.8)", "rgba(204, 204, 204, 1)",
|
||||
"rgba(204, 204, 204, 1)", "rgba(204, 204, 204, 1)"))
|
||||
}
|
||||
}
|
||||
|
||||
layout {
|
||||
title = "Least Used Feature"
|
||||
}
|
||||
}
|
||||
plot.makeFile()
|
||||
}
|
62
plotly/examples/src/main/kotlin/bar/StackedBarChart.kt
Normal file
62
plotly/examples/src/main/kotlin/bar/StackedBarChart.kt
Normal file
@ -0,0 +1,62 @@
|
||||
package bar
|
||||
|
||||
import space.kscience.dataforge.meta.invoke
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.bar
|
||||
import space.kscience.plotly.makeFile
|
||||
import space.kscience.plotly.models.BarMode
|
||||
import space.kscience.plotly.models.XAnchor
|
||||
import space.kscience.plotly.models.YAnchor
|
||||
|
||||
|
||||
/**
|
||||
* - Stacked bar chart
|
||||
* - Use css named colors
|
||||
* - Show legend inside the plot
|
||||
* - Change margins
|
||||
*/
|
||||
fun main() {
|
||||
val values = listOf<Number>(1, 2, 3.5, 4.1, 4.7, 4, 3.2, 1.95, 1)
|
||||
|
||||
val plot = Plotly.plot {
|
||||
bar {
|
||||
y.numbers = values
|
||||
marker { color("red") }
|
||||
}
|
||||
|
||||
bar {
|
||||
y.numbers = values
|
||||
marker { color("orange") }
|
||||
}
|
||||
|
||||
bar {
|
||||
y.numbers = values
|
||||
marker { color("yellow") }
|
||||
}
|
||||
|
||||
bar {
|
||||
y.numbers = values
|
||||
marker { color("greenyellow") }
|
||||
}
|
||||
|
||||
bar {
|
||||
y.numbers = values
|
||||
marker { color("limegreen") }
|
||||
}
|
||||
|
||||
layout {
|
||||
barmode = BarMode.stack
|
||||
title = "Stacked Bar Chart"
|
||||
margin { l = 20; r = 20; b = 20; t = 40 }
|
||||
|
||||
legend {
|
||||
xanchor = XAnchor.right
|
||||
yanchor = YAnchor.top
|
||||
x = 1
|
||||
y = 1
|
||||
borderwidth = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
plot.makeFile()
|
||||
}
|
46
plotly/examples/src/main/kotlin/box/BasicBoxPlot.kt
Normal file
46
plotly/examples/src/main/kotlin/box/BasicBoxPlot.kt
Normal file
@ -0,0 +1,46 @@
|
||||
package box
|
||||
|
||||
import space.kscience.dataforge.meta.invoke
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.makeFile
|
||||
import space.kscience.plotly.models.Box
|
||||
import space.kscience.plotly.models.BoxPoints
|
||||
import kotlin.random.Random
|
||||
|
||||
|
||||
/**
|
||||
* - Basic Box plot with all points
|
||||
*/
|
||||
fun main() {
|
||||
val size = 50
|
||||
val y0 = mutableListOf<Double>()
|
||||
val y1 = mutableListOf<Double>()
|
||||
|
||||
for (i in 0 until size) {
|
||||
y0.add(Random.nextDouble())
|
||||
y1.add(Random.nextDouble())
|
||||
}
|
||||
|
||||
val trace1 = Box {
|
||||
y.set(y0)
|
||||
boxpoints = BoxPoints.all
|
||||
jitter = 0.3
|
||||
pointpos = -1.8
|
||||
}
|
||||
|
||||
val trace2 = Box {
|
||||
y.set(y1)
|
||||
boxpoints = BoxPoints.all
|
||||
jitter = 0.3
|
||||
pointpos = -1.8
|
||||
}
|
||||
|
||||
val plot = Plotly.plot {
|
||||
traces(trace1, trace2)
|
||||
|
||||
layout {
|
||||
title = "Basic Box Plot"
|
||||
}
|
||||
}
|
||||
plot.makeFile()
|
||||
}
|
88
plotly/examples/src/main/kotlin/box/FullyStyledBoxPlot.kt
Normal file
88
plotly/examples/src/main/kotlin/box/FullyStyledBoxPlot.kt
Normal file
@ -0,0 +1,88 @@
|
||||
package box
|
||||
|
||||
import space.kscience.dataforge.meta.invoke
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.makeFile
|
||||
import space.kscience.plotly.models.Box
|
||||
import space.kscience.plotly.models.BoxPoints
|
||||
import space.kscience.plotly.models.Trace
|
||||
import kotlin.random.Random
|
||||
|
||||
|
||||
fun getRandom(size: Int, mul: Double): List<Double> {
|
||||
val value = mutableListOf<Double>()
|
||||
for (i in 0..size) {
|
||||
value.add(Random.nextDouble() * mul)
|
||||
}
|
||||
return value.toList()
|
||||
}
|
||||
|
||||
/**
|
||||
* - Styled box plot
|
||||
* - Style zeroline & grid
|
||||
* - Change background color of the plot
|
||||
* - Use array of traces
|
||||
*/
|
||||
fun main() {
|
||||
val xData = listOf("Carmelo<br>Anthony", "Dwyane<br>Wade", "Deron<br>Williams",
|
||||
"Brook<br>Lopez", "Damian<br>Lillard", "David<br>West",
|
||||
"Blake<br>Griffin", "David<br>Lee", "Demar<br>Derozan")
|
||||
val yData = listOf(
|
||||
getRandom(30, 10.0),
|
||||
getRandom(30, 20.0),
|
||||
getRandom(30, 25.0),
|
||||
getRandom(30, 40.0),
|
||||
getRandom(30, 45.0),
|
||||
getRandom(30, 30.0),
|
||||
getRandom(30, 20.0),
|
||||
getRandom(30, 15.0),
|
||||
getRandom(30, 43.0),
|
||||
getRandom(30, 10.0)
|
||||
)
|
||||
|
||||
val data = mutableListOf<Trace>()
|
||||
for (i in xData.indices) {
|
||||
val result = Box {
|
||||
y.set(yData[i])
|
||||
name = xData[i]
|
||||
boxpoints = BoxPoints.all
|
||||
jitter = 0.5
|
||||
whiskerwidth = 0.2
|
||||
fillcolor("cls")
|
||||
marker {
|
||||
size = 2
|
||||
}
|
||||
line {
|
||||
width = 1
|
||||
}
|
||||
showlegend = false
|
||||
}
|
||||
data.add(result)
|
||||
}
|
||||
|
||||
val plot = Plotly.plot {
|
||||
traces(data)
|
||||
|
||||
layout {
|
||||
title = "Points Scored by the Top 9 Scoring NBA Players in 2012"
|
||||
yaxis {
|
||||
autorange = true
|
||||
showgrid = true
|
||||
zeroline = true
|
||||
gridcolor("rgb(255, 255, 255)")
|
||||
gridwidth = 1
|
||||
zerolinecolor("rgb(255, 255, 255)")
|
||||
zerolinewidth = 2
|
||||
}
|
||||
margin {
|
||||
l = 40
|
||||
r = 30
|
||||
b = 80
|
||||
t = 100
|
||||
}
|
||||
paper_bgcolor("rgb(243, 243, 243)")
|
||||
plot_bgcolor("rgb(243, 243, 243)")
|
||||
}
|
||||
}
|
||||
plot.makeFile()
|
||||
}
|
67
plotly/examples/src/main/kotlin/box/HorizontalBoxPlot.kt
Normal file
67
plotly/examples/src/main/kotlin/box/HorizontalBoxPlot.kt
Normal file
@ -0,0 +1,67 @@
|
||||
package box
|
||||
|
||||
import space.kscience.dataforge.meta.invoke
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.makeFile
|
||||
import space.kscience.plotly.models.Box
|
||||
import space.kscience.plotly.models.BoxMean
|
||||
import space.kscience.plotly.models.BoxMode
|
||||
import space.kscience.plotly.models.Orientation
|
||||
|
||||
|
||||
/**
|
||||
* - Horizontal box plot
|
||||
* - Grouped boxes
|
||||
* - Change box colors
|
||||
*/
|
||||
fun main() {
|
||||
val y0 = listOf("day 1", "day 1", "day 1", "day 1", "day 1", "day 1",
|
||||
"day 2", "day 2", "day 2", "day 2", "day 2", "day 2")
|
||||
|
||||
val trace1 = Box {
|
||||
x(0.2, 0.2, 0.6, 1.0, 0.5, 0.4, 0.2, 0.7, 0.9, 0.1, 0.5, 0.3)
|
||||
y.strings = y0
|
||||
name = "kale"
|
||||
marker {
|
||||
color("#3D9970")
|
||||
}
|
||||
boxmean = BoxMean.`false`
|
||||
orientation = Orientation.h
|
||||
}
|
||||
|
||||
val trace2 = Box {
|
||||
x(0.6, 0.7, 0.3, 0.6, 0.0, 0.5, 0.7, 0.9, 0.5, 0.8, 0.7, 0.2)
|
||||
y.strings = y0
|
||||
name = "radishes"
|
||||
marker {
|
||||
color("#FF4136")
|
||||
}
|
||||
boxmean = BoxMean.`false`
|
||||
orientation = Orientation.h
|
||||
}
|
||||
|
||||
val trace3 = Box {
|
||||
x(0.1, 0.3, 0.1, 0.9, 0.6, 0.6, 0.9, 1.0, 0.3, 0.6, 0.8, 0.5)
|
||||
y.strings = y0
|
||||
name = "carrots"
|
||||
marker {
|
||||
color("#FF851B")
|
||||
}
|
||||
boxmean = BoxMean.`false`
|
||||
orientation = Orientation.h
|
||||
}
|
||||
|
||||
val plot = Plotly.plot {
|
||||
traces(trace1, trace2, trace3)
|
||||
|
||||
layout {
|
||||
title = "Grouped Horizontal Box Plot"
|
||||
xaxis {
|
||||
title = "normalized moisture"
|
||||
zeroline = false
|
||||
}
|
||||
boxmode = BoxMode.group
|
||||
}
|
||||
}
|
||||
plot.makeFile()
|
||||
}
|
40
plotly/examples/src/main/kotlin/box/StylingMeanAndSd.kt
Normal file
40
plotly/examples/src/main/kotlin/box/StylingMeanAndSd.kt
Normal file
@ -0,0 +1,40 @@
|
||||
package box
|
||||
|
||||
import space.kscience.dataforge.meta.invoke
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.makeFile
|
||||
import space.kscience.plotly.models.Box
|
||||
import space.kscience.plotly.models.BoxMean
|
||||
import space.kscience.plotly.palettes.Xkcd
|
||||
|
||||
fun main() {
|
||||
val y1 = listOf(2.37, 2.16, 4.82, 1.73, 1.04, 0.23, 1.32, 2.91, 0.11, 4.51, 0.51,
|
||||
3.75, 1.35, 2.98, 4.50, 0.18, 4.66, 1.30, 2.06, 1.19)
|
||||
|
||||
val trace1 = Box {
|
||||
y.numbers = y1
|
||||
name = "Only Mean"
|
||||
marker {
|
||||
color(Xkcd.CERULEAN)
|
||||
}
|
||||
boxmean = BoxMean.`true`
|
||||
}
|
||||
|
||||
val trace2 = Box {
|
||||
y.numbers = y1
|
||||
name = "Mean and Standard Deviation"
|
||||
marker {
|
||||
color(Xkcd.BLUE_VIOLET)
|
||||
}
|
||||
boxmean = BoxMean.sd
|
||||
}
|
||||
|
||||
val plot = Plotly.plot {
|
||||
traces(trace1, trace2)
|
||||
|
||||
layout {
|
||||
title = "Box Plot Styling Mean and Standard Deviation"
|
||||
}
|
||||
}
|
||||
plot.makeFile()
|
||||
}
|
66
plotly/examples/src/main/kotlin/box/StylingOutliers.kt
Normal file
66
plotly/examples/src/main/kotlin/box/StylingOutliers.kt
Normal file
@ -0,0 +1,66 @@
|
||||
package box
|
||||
|
||||
import space.kscience.dataforge.meta.invoke
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.makeFile
|
||||
import space.kscience.plotly.models.Box
|
||||
import space.kscience.plotly.models.BoxPoints
|
||||
|
||||
fun main() {
|
||||
val y1 = listOf<Number>(0.75, 5.25, 5.5, 6, 6.2, 6.6, 6.80, 7.0, 7.2, 7.5, 7.5, 7.75, 8.15, 8.15,
|
||||
8.65, 8.93, 9.2, 9.5, 10, 10.25, 11.5, 12, 16, 20.90, 22.3, 23.25)
|
||||
|
||||
val trace1 = Box {
|
||||
y.set(y1)
|
||||
name = "All Points"
|
||||
jitter = 0.3
|
||||
pointpos = -1.8
|
||||
marker {
|
||||
color("rgb(7, 40, 89)")
|
||||
}
|
||||
boxpoints = BoxPoints.all
|
||||
}
|
||||
|
||||
val trace2 = Box {
|
||||
y.set(y1)
|
||||
name = "Only Wiskers"
|
||||
marker {
|
||||
color("rgb(9, 56, 125)")
|
||||
}
|
||||
boxpoints = BoxPoints.`false`
|
||||
}
|
||||
|
||||
val trace3 = Box {
|
||||
y.set(y1)
|
||||
name = "Suspected Outlier"
|
||||
marker {
|
||||
color("rgb(8, 81, 156)")
|
||||
outliercolor("rgba(219, 64, 82, 0.6)")
|
||||
line {
|
||||
outliercolor("rgba(219, 64, 82, 1.0)")
|
||||
outlierwidth = 2
|
||||
}
|
||||
}
|
||||
boxpoints = BoxPoints.suspectedoutliers
|
||||
}
|
||||
|
||||
val trace4 = Box {
|
||||
y.set(y1)
|
||||
name = "Wiskers and Outliers"
|
||||
marker {
|
||||
color("rgb(107, 174, 214)")
|
||||
}
|
||||
boxpoints = BoxPoints.outliers
|
||||
}
|
||||
|
||||
val plot = Plotly.plot {
|
||||
traces(trace1, trace2, trace3, trace4)
|
||||
|
||||
layout {
|
||||
width = 700
|
||||
height = 450
|
||||
title = "Box Plot Styling Outliers"
|
||||
}
|
||||
}
|
||||
plot.makeFile()
|
||||
}
|
215
plotly/examples/src/main/kotlin/candlestick/basicCandleStick.kt
Normal file
215
plotly/examples/src/main/kotlin/candlestick/basicCandleStick.kt
Normal file
@ -0,0 +1,215 @@
|
||||
package candlestick
|
||||
|
||||
import space.kscience.dataforge.meta.invoke
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.layout
|
||||
import space.kscience.plotly.makeFile
|
||||
import space.kscience.plotly.models.AxisType
|
||||
import space.kscience.plotly.models.CandleStick
|
||||
import space.kscience.plotly.models.DragMode
|
||||
|
||||
internal val candleStickTrace = CandleStick {
|
||||
x.strings = listOf(
|
||||
"2017-01-04",
|
||||
"2017-01-05",
|
||||
"2017-01-06",
|
||||
"2017-01-09",
|
||||
"2017-01-10",
|
||||
"2017-01-11",
|
||||
"2017-01-12",
|
||||
"2017-01-13",
|
||||
"2017-01-17",
|
||||
"2017-01-18",
|
||||
"2017-01-19",
|
||||
"2017-01-20",
|
||||
"2017-01-23",
|
||||
"2017-01-24",
|
||||
"2017-01-25",
|
||||
"2017-01-26",
|
||||
"2017-01-27",
|
||||
"2017-01-30",
|
||||
"2017-01-31",
|
||||
"2017-02-01",
|
||||
"2017-02-02",
|
||||
"2017-02-03",
|
||||
"2017-02-06",
|
||||
"2017-02-07",
|
||||
"2017-02-08",
|
||||
"2017-02-09",
|
||||
"2017-02-10",
|
||||
"2017-02-13",
|
||||
"2017-02-14",
|
||||
"2017-02-15"
|
||||
)
|
||||
|
||||
close.numbers = listOf(
|
||||
116.019997,
|
||||
116.610001,
|
||||
117.910004,
|
||||
118.989998,
|
||||
119.110001,
|
||||
119.75,
|
||||
119.25,
|
||||
119.040001,
|
||||
120,
|
||||
119.989998,
|
||||
119.779999,
|
||||
120,
|
||||
120.080002,
|
||||
119.970001,
|
||||
121.879997,
|
||||
121.940002,
|
||||
121.949997,
|
||||
121.629997,
|
||||
121.349998,
|
||||
128.75,
|
||||
128.529999,
|
||||
129.080002,
|
||||
130.289993,
|
||||
131.529999,
|
||||
132.039993,
|
||||
132.419998,
|
||||
132.119995,
|
||||
133.289993,
|
||||
135.020004,
|
||||
135.509995
|
||||
)
|
||||
|
||||
high.numbers = listOf(
|
||||
116.510002,
|
||||
116.860001,
|
||||
118.160004,
|
||||
119.43,
|
||||
119.379997,
|
||||
119.93,
|
||||
119.300003,
|
||||
119.620003,
|
||||
120.239998,
|
||||
120.5,
|
||||
120.089996,
|
||||
120.449997,
|
||||
120.809998,
|
||||
120.099998,
|
||||
122.099998,
|
||||
122.440002,
|
||||
122.349998,
|
||||
121.629997,
|
||||
121.389999,
|
||||
130.490005,
|
||||
129.389999,
|
||||
129.190002,
|
||||
130.5,
|
||||
132.089996,
|
||||
132.220001,
|
||||
132.449997,
|
||||
132.940002,
|
||||
133.820007,
|
||||
135.089996,
|
||||
136.270004
|
||||
)
|
||||
|
||||
increasing {
|
||||
lineColor("#17BECF")
|
||||
}
|
||||
|
||||
decreasing {
|
||||
lineColor("#7F7F7F")
|
||||
}
|
||||
|
||||
line { color("rgba(31,119,180,1)") }
|
||||
|
||||
low.numbers = listOf(
|
||||
115.75,
|
||||
115.809998,
|
||||
116.470001,
|
||||
117.940002,
|
||||
118.300003,
|
||||
118.599998,
|
||||
118.209999,
|
||||
118.809998,
|
||||
118.220001,
|
||||
119.709999,
|
||||
119.370003,
|
||||
119.730003,
|
||||
119.769997,
|
||||
119.5,
|
||||
120.279999,
|
||||
121.599998,
|
||||
121.599998,
|
||||
120.660004,
|
||||
120.620003,
|
||||
127.010002,
|
||||
127.779999,
|
||||
128.160004,
|
||||
128.899994,
|
||||
130.449997,
|
||||
131.220001,
|
||||
131.119995,
|
||||
132.050003,
|
||||
132.75,
|
||||
133.25,
|
||||
134.619995
|
||||
)
|
||||
|
||||
open.numbers = listOf(
|
||||
115.849998,
|
||||
115.919998,
|
||||
116.779999,
|
||||
117.949997,
|
||||
118.769997,
|
||||
118.739998,
|
||||
118.900002,
|
||||
119.110001,
|
||||
118.339996,
|
||||
120,
|
||||
119.400002,
|
||||
120.449997,
|
||||
120,
|
||||
119.550003,
|
||||
120.419998,
|
||||
121.669998,
|
||||
122.139999,
|
||||
120.93,
|
||||
121.150002,
|
||||
127.029999,
|
||||
127.980003,
|
||||
128.309998,
|
||||
129.130005,
|
||||
130.539993,
|
||||
131.350006,
|
||||
131.649994,
|
||||
132.460007,
|
||||
133.080002,
|
||||
133.470001,
|
||||
135.520004
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
fun main() {
|
||||
Plotly.plot {
|
||||
traces(candleStickTrace)
|
||||
layout {
|
||||
dragmode = DragMode.zoom
|
||||
margin {
|
||||
r = 10
|
||||
t = 25
|
||||
b = 40
|
||||
l = 60
|
||||
}
|
||||
showlegend = false
|
||||
xaxis {
|
||||
autorange = true
|
||||
range("2017-01-03 12:00".."2017-02-15 12:00")
|
||||
//rangeslider: { range: ["2017-01-03 12:00", "2017-02-15 12:00"] },
|
||||
title = "Date"
|
||||
type = AxisType.date
|
||||
}
|
||||
yaxis {
|
||||
autorange = true
|
||||
range(114.609999778..137.410004222)
|
||||
type = AxisType.linear
|
||||
}
|
||||
}
|
||||
}.makeFile()
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package candlestick
|
||||
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.launch
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.layout
|
||||
import space.kscience.plotly.models.AxisType
|
||||
import space.kscience.plotly.models.DragMode
|
||||
import space.kscience.plotly.plot
|
||||
import space.kscience.plotly.server.close
|
||||
import space.kscience.plotly.server.pushUpdates
|
||||
import space.kscience.plotly.server.serve
|
||||
import space.kscience.plotly.server.show
|
||||
import kotlin.random.Random
|
||||
|
||||
fun main() {
|
||||
val server = Plotly.serve {
|
||||
pushUpdates(50)
|
||||
page { plotly ->
|
||||
plot(renderer = plotly) {
|
||||
traces(candleStickTrace)
|
||||
layout {
|
||||
dragmode = DragMode.zoom
|
||||
margin {
|
||||
r = 10
|
||||
t = 25
|
||||
b = 40
|
||||
l = 60
|
||||
}
|
||||
showlegend = false
|
||||
xaxis {
|
||||
type = AxisType.date
|
||||
range("2017-01-03 12:00".."2017-02-15 12:00")
|
||||
//rangeslider: { range: ["2017-01-03 12:00", "2017-02-15 12:00"] },
|
||||
title = "Date"
|
||||
}
|
||||
yaxis {
|
||||
range(114.609999778..137.410004222)
|
||||
}
|
||||
}
|
||||
|
||||
launch {
|
||||
while (isActive) {
|
||||
delay(400)
|
||||
candleStickTrace.open.numbers = candleStickTrace.open.doubles.map { it + Random.nextDouble() - 0.5 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
server.show()
|
||||
println("Enter 'exit' to close server")
|
||||
while (readLine()?.trim() != "exit") {
|
||||
//wait
|
||||
}
|
||||
|
||||
server.close()
|
||||
}
|
138
plotly/examples/src/main/kotlin/complexDynamicServer.kt
Normal file
138
plotly/examples/src/main/kotlin/complexDynamicServer.kt
Normal file
@ -0,0 +1,138 @@
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.zip
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.html.div
|
||||
import kotlinx.html.link
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.layout
|
||||
import space.kscience.plotly.models.Trace
|
||||
import space.kscience.plotly.plot
|
||||
import space.kscience.plotly.server.pushUpdates
|
||||
import space.kscience.plotly.server.serve
|
||||
import space.kscience.plotly.server.show
|
||||
import space.kscience.plotly.trace
|
||||
import java.time.Instant
|
||||
import java.util.concurrent.ConcurrentLinkedQueue
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
|
||||
|
||||
/**
|
||||
* In-place replacement for absent method from stdlib
|
||||
*/
|
||||
fun <T> Flow<T>.windowed(size: Int): Flow<Iterable<T>> {
|
||||
val queue = ConcurrentLinkedQueue<T>()
|
||||
return flow {
|
||||
this@windowed.collect {
|
||||
queue.add(it)
|
||||
if (queue.size >= size) {
|
||||
queue.poll()
|
||||
}
|
||||
emit(queue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun Trace.updateFrom(axisName: String, flow: Flow<Iterable<Double>>) {
|
||||
flow.collect {
|
||||
axis(axisName).numbers = it
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun Trace.updateXYFrom(flow: Flow<Iterable<Pair<Double, Double>>>) {
|
||||
flow.collect { pairs ->
|
||||
x.numbers = pairs.map { it.first }
|
||||
y.numbers = pairs.map { it.second }
|
||||
}
|
||||
}
|
||||
|
||||
fun main() {
|
||||
val server = Plotly.serve {
|
||||
val sinFlow = flow {
|
||||
while (true) {
|
||||
delay(40)
|
||||
val time = Instant.now()
|
||||
emit(sin(time.toEpochMilli().toDouble() / 2500))
|
||||
}
|
||||
}
|
||||
val cosFlow = flow {
|
||||
while (true) {
|
||||
delay(50)
|
||||
val time = Instant.now()
|
||||
emit(cos(time.toEpochMilli().toDouble() / 2500))
|
||||
}
|
||||
}
|
||||
val sinCosFlow = sinFlow.zip(cosFlow) { sin, cos ->
|
||||
sin to cos
|
||||
}
|
||||
page { renderer ->
|
||||
link {
|
||||
rel = "stylesheet"
|
||||
href = "https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css"
|
||||
attributes["integrity"] = "sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk"
|
||||
attributes["crossorigin"] = "anonymous"
|
||||
}
|
||||
div("row") {
|
||||
div("col-6") {
|
||||
plot(renderer = renderer) {
|
||||
layout {
|
||||
title = "sin property"
|
||||
xaxis.title = "point index"
|
||||
yaxis.title = "sin"
|
||||
}
|
||||
trace {
|
||||
val flow: Flow<Iterable<Double>> = sinFlow.windowed(100)
|
||||
launch {
|
||||
updateFrom(Trace.Y_AXIS, flow)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
div("col-6") {
|
||||
plot(renderer = renderer) {
|
||||
layout {
|
||||
title = "cos property"
|
||||
xaxis.title = "point index"
|
||||
yaxis.title = "cos"
|
||||
}
|
||||
trace {
|
||||
val flow: Flow<Iterable<Double>> = cosFlow.windowed(100)
|
||||
launch {
|
||||
updateFrom(Trace.Y_AXIS, flow)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
div("row") {
|
||||
div("col-12") {
|
||||
plot(renderer = renderer) {
|
||||
layout {
|
||||
title = "cos vs sin"
|
||||
xaxis.title = "sin"
|
||||
yaxis.title = "cos"
|
||||
}
|
||||
trace {
|
||||
name = "non-synchronized"
|
||||
val flow: Flow<Iterable<Pair<Double, Double>>> = sinCosFlow.windowed(30)
|
||||
launch {
|
||||
updateXYFrom(flow)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
pushUpdates(100) // start sending updates via websocket to the front-end
|
||||
}
|
||||
|
||||
server.show()
|
||||
|
||||
println("Press Enter to close server")
|
||||
readLine()
|
||||
|
||||
server.stop(1000, 5000)
|
||||
}
|
60
plotly/examples/src/main/kotlin/contour/BasicContour.kt
Normal file
60
plotly/examples/src/main/kotlin/contour/BasicContour.kt
Normal file
@ -0,0 +1,60 @@
|
||||
package contour
|
||||
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.layout
|
||||
import space.kscience.plotly.makeFile
|
||||
import space.kscience.plotly.models.Contour
|
||||
import space.kscience.plotly.models.MeasureMode
|
||||
|
||||
|
||||
/**
|
||||
* - basic contour plot
|
||||
* - change font size of labels ticks
|
||||
* - setting x and y coordinates
|
||||
* - change color bar size
|
||||
*/
|
||||
fun main() {
|
||||
val values: List<List<Number>> = listOf(
|
||||
listOf<Number>(10, 10.625, 12.5, 15.625, 20.0),
|
||||
listOf<Number>(5.625, 6.25, 8.125, 11.25, 15.625),
|
||||
listOf<Number>(2.5, 3.125, 5.0, 8.125, 12.5),
|
||||
listOf<Number>(0.625, 1.25, 3.125, 6.25, 10.625),
|
||||
listOf<Number>(0.0, 0.625, 2.5, 5.625, 10)
|
||||
)
|
||||
val x1 = listOf(-9, -6, -5, -3, -1)
|
||||
val y1 = listOf(0, 1, 4, 5, 7)
|
||||
|
||||
val contour = Contour{
|
||||
x.numbers = x1
|
||||
y.numbers = y1
|
||||
z(values)
|
||||
|
||||
colorbar {
|
||||
thickness = 75.0
|
||||
thicknessmode = MeasureMode.pixels
|
||||
len = 0.9
|
||||
lenmode = MeasureMode.fraction
|
||||
outlinewidth = 0
|
||||
}
|
||||
}
|
||||
|
||||
val plot = Plotly.plot {
|
||||
traces(contour)
|
||||
|
||||
layout {
|
||||
title = "Basic Contour Plot"
|
||||
xaxis {
|
||||
tickfont {
|
||||
size = 16
|
||||
}
|
||||
}
|
||||
yaxis {
|
||||
tickfont {
|
||||
size = 16
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
plot.makeFile()
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package contour
|
||||
|
||||
import space.kscience.dataforge.meta.Value
|
||||
import space.kscience.dataforge.meta.invoke
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.makeFile
|
||||
import space.kscience.plotly.models.Contour
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.sin
|
||||
|
||||
/**
|
||||
* - simple contour plot without level lines
|
||||
* - transpose axis
|
||||
* - change size of the plot
|
||||
* - change color scale
|
||||
*/
|
||||
fun main() {
|
||||
val size = 25
|
||||
val x1 = (0..size).map { it.toDouble() / 5 }
|
||||
val y1 = (0..size).map { it.toDouble() / 5 }
|
||||
val z = mutableListOf<MutableList<Double>>()
|
||||
|
||||
for (i in y1.indices) {
|
||||
z.add(MutableList(size + 1) { 0.0 })
|
||||
}
|
||||
|
||||
for (i in x1.indices) {
|
||||
for (j in y1.indices) {
|
||||
z[i][j] = sin(x1[i]).pow(10) + cos(10 + y1[j] * x1[i]) * cos(x1[i])
|
||||
}
|
||||
}
|
||||
|
||||
val contour = Contour {
|
||||
x.numbers = x1
|
||||
y.numbers = y1
|
||||
z(z)
|
||||
|
||||
transpose = true
|
||||
colorscale = Value.of("Portland")
|
||||
reversescale = true
|
||||
|
||||
contours {
|
||||
showlines = false
|
||||
}
|
||||
}
|
||||
|
||||
val plot = Plotly.plot {
|
||||
traces(contour)
|
||||
|
||||
layout {
|
||||
width = 1000
|
||||
height = 500
|
||||
title = "Colored Contour Plot"
|
||||
}
|
||||
}
|
||||
|
||||
plot.makeFile()
|
||||
}
|
59
plotly/examples/src/main/kotlin/contour/ConnectNullGaps.kt
Normal file
59
plotly/examples/src/main/kotlin/contour/ConnectNullGaps.kt
Normal file
@ -0,0 +1,59 @@
|
||||
package contour
|
||||
|
||||
import space.kscience.plotly.*
|
||||
import space.kscience.plotly.models.Contour
|
||||
|
||||
|
||||
/**
|
||||
* - contour plots with and without gaps between not-null values
|
||||
* - change plot size
|
||||
* - stack two plots
|
||||
*/
|
||||
fun main() {
|
||||
val x1 = (0..7)
|
||||
val y2 = (0..6)
|
||||
|
||||
val z1 = listOf(
|
||||
listOf<Number?>(null, null, null, 12, 13, 14, 15, 16),
|
||||
listOf<Number?>(null, 1, null, 11, null, null, null, 17),
|
||||
listOf<Number?>(null, 2, 6, 7, null, null, null, 18),
|
||||
listOf<Number?>(null, 3, null, 8, null, null, null, 19),
|
||||
listOf<Number?>(5, 4, 10, 9, null, null, null, 20),
|
||||
listOf<Number?>(null, null, null, 27, null, null, null, 21),
|
||||
listOf<Number?>(null, null, null, 26, 25, 24, 23, 22))
|
||||
|
||||
val contour1 = Contour{
|
||||
x.set(x1)
|
||||
y.set(y2)
|
||||
z.set(z1)
|
||||
showscale = false
|
||||
}
|
||||
|
||||
val contour2 = Contour {
|
||||
x.set(x1)
|
||||
y.set(y2)
|
||||
z.set(z1)
|
||||
showscale = false
|
||||
connectgaps = true
|
||||
}
|
||||
|
||||
Plotly.fragment {
|
||||
plot {
|
||||
traces(contour1)
|
||||
layout {
|
||||
width = 800
|
||||
height = 450
|
||||
title = "Gaps Between Nulls"
|
||||
}
|
||||
}
|
||||
|
||||
plot {
|
||||
traces(contour2)
|
||||
layout {
|
||||
width = 800
|
||||
height = 450
|
||||
title = "Connected Gaps"
|
||||
}
|
||||
}
|
||||
}.makeFile()
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
package contour
|
||||
|
||||
import space.kscience.dataforge.meta.Value
|
||||
import space.kscience.dataforge.meta.invoke
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.contour
|
||||
import space.kscience.plotly.makeFile
|
||||
import space.kscience.plotly.models.ContoursColoring
|
||||
import kotlin.math.exp
|
||||
import kotlin.math.pow
|
||||
|
||||
/**
|
||||
* - colored contour plot lines
|
||||
* - labels on contour lines
|
||||
* - change size of the plot and contour lines width
|
||||
*/
|
||||
fun main() {
|
||||
val range = -300..300
|
||||
val rangeSize = range.last - range.first + 1
|
||||
val x1 = range.map { it.toDouble() / 100 }
|
||||
val y1 = range.map { it.toDouble() / 100 }
|
||||
val values = mutableListOf<MutableList<Double>>()
|
||||
|
||||
for (i in y1.indices) {
|
||||
values.add(MutableList(rangeSize) { 0.0 })
|
||||
}
|
||||
|
||||
for (i in x1.indices) {
|
||||
for (j in y1.indices) {
|
||||
val z1 = exp(-x1[i].pow(2) - y1[j].pow(2))
|
||||
val z2 = exp(-(x1[i] - 1).pow(2) - (y1[j] - 1).pow(2))
|
||||
values[i][j] = (z1 - z2) * 2
|
||||
}
|
||||
}
|
||||
|
||||
val plot = Plotly.plot {
|
||||
contour {
|
||||
x.set(x1)
|
||||
y.set(y1)
|
||||
z.set(values)
|
||||
|
||||
line {
|
||||
width = 4
|
||||
}
|
||||
|
||||
colorscale = Value.of("Jet")
|
||||
contours {
|
||||
coloring = ContoursColoring.lines
|
||||
showlabels = true
|
||||
|
||||
labelfont {
|
||||
size = 16
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
layout {
|
||||
width = 700
|
||||
height = 600
|
||||
title = "Contour Lines with Labels"
|
||||
}
|
||||
}
|
||||
|
||||
plot.makeFile()
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package contour
|
||||
|
||||
import space.kscience.dataforge.meta.Value
|
||||
import space.kscience.dataforge.meta.invoke
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.makeFile
|
||||
import space.kscience.plotly.models.Contour
|
||||
|
||||
fun main() {
|
||||
val z1 = listOf(
|
||||
listOf<Number>(10, 10.625, 12.5, 15.625, 20),
|
||||
listOf<Number>(5.625, 6.25, 8.125, 11.25, 15.625),
|
||||
listOf<Number>(2.5, 3.125, 5.0, 8.125, 12.5),
|
||||
listOf<Number>(0.625, 1.25, 3.125, 6.25, 10.625),
|
||||
listOf<Number>(0, 0.625, 2.5, 5.625, 10))
|
||||
|
||||
val contour = Contour {
|
||||
z.set(z1)
|
||||
colorscale = Value.of("Jet")
|
||||
dx = 10
|
||||
x0 = Value.of(5)
|
||||
dy = 10
|
||||
y0 = Value.of(10)
|
||||
}
|
||||
|
||||
val plot = Plotly.plot {
|
||||
traces(contour)
|
||||
|
||||
layout {
|
||||
title = "Customizing Spacing Between X and Y Axis Ticks"
|
||||
}
|
||||
}
|
||||
|
||||
plot.makeFile()
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
package contour
|
||||
|
||||
import space.kscience.dataforge.meta.Value
|
||||
import space.kscience.dataforge.meta.invoke
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.contour
|
||||
import space.kscience.plotly.makeFile
|
||||
import space.kscience.plotly.models.ContoursColoring
|
||||
import space.kscience.plotly.models.Dash
|
||||
import kotlin.math.exp
|
||||
import kotlin.math.pow
|
||||
|
||||
/**
|
||||
* - colored contour plot lines
|
||||
* - labels on contour lines
|
||||
* - hide colorbar
|
||||
* - change size of the plot and contour lines width
|
||||
* - change style of contour lines
|
||||
*/
|
||||
fun main() {
|
||||
val range = -160..260 step 4
|
||||
val rangeSize = (range.last - range.first) / 4 + 1
|
||||
val x1 = range.map { it.toDouble() / 100 }
|
||||
val y1 = range.map { it.toDouble() / 100 }
|
||||
val z1 = mutableListOf<MutableList<Double?>>()
|
||||
val z2 = mutableListOf<MutableList<Double?>>()
|
||||
|
||||
for (i in x1.indices) {
|
||||
z1.add(MutableList(rangeSize) { 0.0 })
|
||||
z2.add(MutableList(rangeSize) { 0.0 })
|
||||
}
|
||||
|
||||
for (i in x1.indices) {
|
||||
for (j in y1.indices) {
|
||||
val elem1 = exp(-x1[i].pow(2) - y1[j].pow(2))
|
||||
val elem2 = exp(-(x1[i] - 1).pow(2) - (y1[j] - 1).pow(2))
|
||||
val elem = (elem1 - elem2) * 2
|
||||
if (elem >= -0.01) {
|
||||
z1[i][j] = elem
|
||||
z2[i][j] = null
|
||||
} else {
|
||||
z2[i][j] = elem
|
||||
z1[i][j] = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val plot = Plotly.plot {
|
||||
contour {
|
||||
x.set(x1)
|
||||
y.set(y1)
|
||||
z.set(z1)
|
||||
|
||||
line {
|
||||
width = 4
|
||||
}
|
||||
connectgaps = true
|
||||
colorscale = Value.of("Jet")
|
||||
showscale = false
|
||||
contours {
|
||||
coloring = ContoursColoring.lines
|
||||
showlabels = true
|
||||
}
|
||||
}
|
||||
|
||||
contour {
|
||||
x.set(x1)
|
||||
y.set(y1)
|
||||
z.set(z2)
|
||||
|
||||
line {
|
||||
width = 4
|
||||
dash = Dash.dash
|
||||
}
|
||||
connectgaps = true
|
||||
colorscale = Value.of("Jet")
|
||||
reversescale = true
|
||||
showscale = false
|
||||
contours {
|
||||
coloring = ContoursColoring.lines
|
||||
showlabels = true
|
||||
}
|
||||
}
|
||||
|
||||
layout {
|
||||
width = 900
|
||||
height = 750
|
||||
title = "Negative Contours Dashed"
|
||||
}
|
||||
}
|
||||
|
||||
plot.makeFile()
|
||||
}
|
52
plotly/examples/src/main/kotlin/contour/SimpleContourPlot.kt
Normal file
52
plotly/examples/src/main/kotlin/contour/SimpleContourPlot.kt
Normal file
@ -0,0 +1,52 @@
|
||||
package contour
|
||||
|
||||
import space.kscience.dataforge.meta.asValue
|
||||
import space.kscience.dataforge.meta.invoke
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.contour
|
||||
import space.kscience.plotly.makeFile
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.ln
|
||||
import kotlin.math.sin
|
||||
|
||||
|
||||
/**
|
||||
* - simple contour plot
|
||||
* - change colorscale
|
||||
* - set x and y coordinates of the plot
|
||||
*/
|
||||
fun main() {
|
||||
val size = 100
|
||||
val x1 = mutableListOf<Double>()
|
||||
val y1 = mutableListOf<Double>()
|
||||
val z1 = mutableListOf<MutableList<Double>>()
|
||||
|
||||
for (i in 0 until size) {
|
||||
val elem = -2 * Math.PI + 4 * Math.PI * i / size
|
||||
x1.add(elem)
|
||||
y1.add(elem)
|
||||
z1.add(MutableList(size) { 0.0 })
|
||||
}
|
||||
|
||||
for (i in x1.indices) {
|
||||
for (j in y1.indices) {
|
||||
val r2 = x1[i] * x1[i] + y1[j] * y1[j]
|
||||
z1[i][j] = sin(x1[i]) * cos(y1[j]) * sin(r2) / ln(r2 + 1)
|
||||
}
|
||||
}
|
||||
|
||||
val plot = Plotly.plot {
|
||||
contour {
|
||||
x.set(x1)
|
||||
y.set(x1)
|
||||
z.set(z1)
|
||||
colorscale = "YlGnBu".asValue()
|
||||
}
|
||||
|
||||
layout {
|
||||
title = "Simple Contour Plot"
|
||||
}
|
||||
}
|
||||
|
||||
plot.makeFile()
|
||||
}
|
43
plotly/examples/src/main/kotlin/customPage.kt
Normal file
43
plotly/examples/src/main/kotlin/customPage.kt
Normal file
@ -0,0 +1,43 @@
|
||||
import kotlinx.html.div
|
||||
import kotlinx.html.h1
|
||||
import kotlinx.html.hr
|
||||
import space.kscience.plotly.*
|
||||
import space.kscience.plotly.models.Trace
|
||||
import space.kscience.plotly.models.invoke
|
||||
import kotlin.math.PI
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
|
||||
fun main() {
|
||||
|
||||
val x1 = (0..100).map { it.toDouble() / 100.0 }
|
||||
val y1 = x1.map { sin(2.0 * PI * it) }
|
||||
val y2 = x1.map { cos(2.0 * PI * it) }
|
||||
|
||||
val trace1 = Trace(x1, y1) { name = "sin" }
|
||||
val trace2 = Trace(x1, y2) { name = "cos" }
|
||||
|
||||
Plotly.page { container ->
|
||||
plot(renderer = container) {
|
||||
traces(trace1, trace2)
|
||||
layout {
|
||||
title = "The plot above"
|
||||
xaxis.title = "x axis name"
|
||||
yaxis.title = "y axis name"
|
||||
}
|
||||
}
|
||||
hr()
|
||||
h1 { +"A custom separator" }
|
||||
hr()
|
||||
div {
|
||||
plot {
|
||||
traces(trace1, trace2)
|
||||
layout {
|
||||
title = "The plot below"
|
||||
xaxis.title = "x axis name"
|
||||
yaxis.title = "y axis name"
|
||||
}
|
||||
}
|
||||
}
|
||||
}.makeFile()
|
||||
}
|
36
plotly/examples/src/main/kotlin/downloadChartAsSVG.kt
Normal file
36
plotly/examples/src/main/kotlin/downloadChartAsSVG.kt
Normal file
@ -0,0 +1,36 @@
|
||||
import space.kscience.plotly.*
|
||||
import space.kscience.plotly.models.ScatterMode
|
||||
|
||||
|
||||
/**
|
||||
* - Bubble chart with different marker sizes
|
||||
* - Download plot as SVG using configuration button
|
||||
*/
|
||||
fun main() {
|
||||
val fragment = Plotly.fragment {
|
||||
val plotConfig = PlotlyConfig{
|
||||
saveAsSvg()
|
||||
}
|
||||
|
||||
plot(config = plotConfig) {
|
||||
scatter {
|
||||
x(1, 2, 3, 4)
|
||||
y(10, 11, 12, 13)
|
||||
text("A<br>size: 40", "B<br>size: 60", "C<br>size: 80", "D<br>size: 100")
|
||||
mode = ScatterMode.markers
|
||||
marker {
|
||||
colors(listOf("rgb(93, 164, 214)", "rgb(255, 144, 14)", "rgb(44, 160, 101)", "rgb(255, 65, 54)"))
|
||||
sizesList = listOf(40, 60, 80, 100)
|
||||
}
|
||||
}
|
||||
|
||||
layout {
|
||||
title = "Download Chart as SVG instead of PNG"
|
||||
showlegend = false
|
||||
height = 600
|
||||
width = 600
|
||||
}
|
||||
}
|
||||
}
|
||||
fragment.makeFile()
|
||||
}
|
84
plotly/examples/src/main/kotlin/dynamicServer.kt
Normal file
84
plotly/examples/src/main/kotlin/dynamicServer.kt
Normal file
@ -0,0 +1,84 @@
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.html.a
|
||||
import kotlinx.html.h1
|
||||
import space.kscience.dataforge.meta.invoke
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.models.Trace
|
||||
import space.kscience.plotly.models.invoke
|
||||
import space.kscience.plotly.plot
|
||||
import space.kscience.plotly.server.close
|
||||
import space.kscience.plotly.server.pushUpdates
|
||||
import space.kscience.plotly.server.serve
|
||||
import space.kscience.plotly.server.show
|
||||
import kotlin.math.PI
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
|
||||
|
||||
@OptIn(DelicateCoroutinesApi::class)
|
||||
fun main() {
|
||||
|
||||
val freq = 1.0 / 1000
|
||||
val oscillationFreq = 1.0 / 10000
|
||||
|
||||
val x = (0..100).map { it.toDouble() / 100.0 }
|
||||
val sinY = x.map { sin(2.0 * PI * it) }
|
||||
val cosY = x.map { cos(2.0 * PI * it) }
|
||||
|
||||
val sinTrace = Trace(x, sinY) { name = "sin" }
|
||||
val cosTrace = Trace(x, cosY) { name = "cos" }
|
||||
|
||||
val server = Plotly.serve(port = 7878) {
|
||||
embedData = true
|
||||
|
||||
//root level plots go to default page
|
||||
page { plotly ->
|
||||
h1 { +"This is the plot page" }
|
||||
a("/other") { +"The other page" }
|
||||
plot(renderer = plotly) {
|
||||
traces(sinTrace, cosTrace)
|
||||
layout {
|
||||
title = "Other dynamic plot"
|
||||
xaxis.title = "x axis name"
|
||||
yaxis.title = "y axis name"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
page("other") { plotly ->
|
||||
h1 { +"This is the other plot page" }
|
||||
a("/") { +"Back to the main page" }
|
||||
plot(renderer = plotly) {
|
||||
traces(sinTrace)
|
||||
layout {
|
||||
title = "Dynamic plot"
|
||||
xaxis.title = "x axis name"
|
||||
yaxis.title = "y axis name"
|
||||
}
|
||||
}
|
||||
}
|
||||
pushUpdates(50) // start sending updates via websocket to the front-end
|
||||
}
|
||||
|
||||
server.show()
|
||||
|
||||
//Start pushing updates
|
||||
GlobalScope.launch {
|
||||
var time: Long = 0
|
||||
|
||||
while (isActive) {
|
||||
delay(10)
|
||||
time += 10
|
||||
sinTrace.y.numbers = x.map { sin(2.0 * PI * (it + time.toDouble() * freq)) }
|
||||
val cosAmp = cos(2.0 * PI * oscillationFreq * time)
|
||||
cosTrace.y.numbers = x.map { cos(2.0 * PI * (it + time.toDouble() * freq)) * cosAmp }
|
||||
}
|
||||
}
|
||||
|
||||
println("Press Enter to close server")
|
||||
while (readLine()?.trim() != "exit"){
|
||||
//wait
|
||||
}
|
||||
|
||||
server.close()
|
||||
}
|
32
plotly/examples/src/main/kotlin/embededFileExport.kt
Normal file
32
plotly/examples/src/main/kotlin/embededFileExport.kt
Normal file
@ -0,0 +1,32 @@
|
||||
import space.kscience.dataforge.meta.invoke
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.ResourceLocation
|
||||
import space.kscience.plotly.makeFile
|
||||
import space.kscience.plotly.trace
|
||||
import kotlin.math.PI
|
||||
import kotlin.math.sin
|
||||
|
||||
|
||||
fun main() {
|
||||
val x1 = (0..100).map { it.toDouble() / 100.0 }
|
||||
val y1 = x1.map { sin(2.0 * PI * it) }
|
||||
|
||||
val plot = Plotly.plot {
|
||||
trace {
|
||||
x.set(x1)
|
||||
y.set(y1)
|
||||
name = "for a single trace in graph its name would be hidden"
|
||||
}
|
||||
layout {
|
||||
title = "Graph name"
|
||||
xaxis {
|
||||
title = "x axis"
|
||||
}
|
||||
yaxis {
|
||||
title = "y axis"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
plot.makeFile(resourceLocation = ResourceLocation.EMBED)
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
package errorPlots
|
||||
|
||||
import space.kscience.dataforge.meta.invoke
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.makeFile
|
||||
import space.kscience.plotly.models.ErrorType
|
||||
import space.kscience.plotly.models.TraceOrder
|
||||
import space.kscience.plotly.models.XAnchor
|
||||
import space.kscience.plotly.models.YAnchor
|
||||
import space.kscience.plotly.scatter
|
||||
|
||||
/**
|
||||
* - asymmetric error bars
|
||||
* - use numeric array as error length
|
||||
* - use only negative or positive errors
|
||||
* - change legend position
|
||||
* - change width of the legend border
|
||||
* - change order of legend items
|
||||
*/
|
||||
fun main() {
|
||||
val x1 = listOf(1, 2, 3, 4)
|
||||
val y1 = listOf(2, 3, 5, 8)
|
||||
val err = listOf(0.5, 0.75, 1.0, 1.25)
|
||||
|
||||
val plot = Plotly.plot {
|
||||
scatter {
|
||||
x.set(x1)
|
||||
y.set(y1)
|
||||
name = "both errors"
|
||||
error_y {
|
||||
type = ErrorType.data
|
||||
array = err
|
||||
visible = true
|
||||
}
|
||||
}
|
||||
|
||||
scatter {
|
||||
x.set(x1)
|
||||
y.set(y1.map { it + 4 }.toList())
|
||||
name = "positive err"
|
||||
error_y {
|
||||
type = ErrorType.data
|
||||
array = err
|
||||
symmetric = false
|
||||
visible = true
|
||||
}
|
||||
}
|
||||
|
||||
scatter {
|
||||
x.set(x1)
|
||||
y.set(y1.map { it + 8 }.toList())
|
||||
name = "negative err"
|
||||
error_y {
|
||||
type = ErrorType.data
|
||||
arrayminus = err
|
||||
symmetric = false
|
||||
visible = true
|
||||
}
|
||||
}
|
||||
|
||||
layout {
|
||||
title = "Asymmetric Error Bars"
|
||||
legend {
|
||||
x = 0.05
|
||||
borderwidth = 1
|
||||
xanchor = XAnchor.left
|
||||
yanchor = YAnchor.top
|
||||
traceorder = TraceOrder.reversed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
plot.makeFile()
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
package errorPlots
|
||||
|
||||
import space.kscience.dataforge.meta.invoke
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.bar
|
||||
import space.kscience.plotly.makeFile
|
||||
import space.kscience.plotly.models.BarMode
|
||||
import space.kscience.plotly.models.ErrorType
|
||||
import space.kscience.plotly.models.XAnchor
|
||||
|
||||
|
||||
/**
|
||||
* - bar chart with symmetrical error bars
|
||||
* - use numeric array as error bars length
|
||||
* - change color and width of legend border
|
||||
*/
|
||||
fun main() {
|
||||
val x1 = listOf("Trial 1", "Trial 2", "Trial 3")
|
||||
val y1 = listOf(3, 6, 4)
|
||||
val y2 = listOf(4, 7, 3)
|
||||
|
||||
|
||||
val plot = Plotly.plot {
|
||||
bar {
|
||||
x.set(x1)
|
||||
y.set(y1)
|
||||
name = "Experimental"
|
||||
error_y {
|
||||
type = ErrorType.data
|
||||
array = listOf(1, 0.5, 1.5)
|
||||
visible = true
|
||||
}
|
||||
}
|
||||
|
||||
bar {
|
||||
x.set(x1)
|
||||
y.set(y2)
|
||||
name = "Control"
|
||||
error_y {
|
||||
type = ErrorType.data
|
||||
array = listOf(1, 0.5, 1.5)
|
||||
visible = true
|
||||
}
|
||||
}
|
||||
|
||||
layout {
|
||||
barmode = BarMode.group
|
||||
title = "Bar Chart with Error Bars"
|
||||
legend {
|
||||
x = 1
|
||||
y = 1
|
||||
bordercolor("black")
|
||||
borderwidth = 1
|
||||
xanchor = XAnchor.auto
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
plot.makeFile()
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package errorPlots
|
||||
|
||||
import space.kscience.dataforge.meta.invoke
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.makeFile
|
||||
import space.kscience.plotly.models.ErrorType
|
||||
import space.kscience.plotly.trace
|
||||
|
||||
/**
|
||||
* - basic symmetric error bars
|
||||
* - use numeric array as error length
|
||||
* - change color of error bars
|
||||
*/
|
||||
fun main() {
|
||||
val xValues = listOf(0, 1, 2)
|
||||
val yValues = listOf(6, 10, 2)
|
||||
val err = listOf(1, 2, 3)
|
||||
|
||||
val plot = Plotly.plot {
|
||||
trace {
|
||||
x.numbers = xValues
|
||||
y.numbers = yValues
|
||||
error_y {
|
||||
type = ErrorType.data
|
||||
array = err
|
||||
visible = true
|
||||
color("orange")
|
||||
}
|
||||
}
|
||||
|
||||
layout {
|
||||
title = "Basic Symmetric Error Bars"
|
||||
}
|
||||
}
|
||||
|
||||
plot.makeFile()
|
||||
}
|
44
plotly/examples/src/main/kotlin/errorPlots/ColoredBoxPlot.kt
Normal file
44
plotly/examples/src/main/kotlin/errorPlots/ColoredBoxPlot.kt
Normal file
@ -0,0 +1,44 @@
|
||||
package errorPlots
|
||||
|
||||
import space.kscience.dataforge.meta.invoke
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.box
|
||||
import space.kscience.plotly.makeFile
|
||||
import space.kscience.plotly.palettes.T10
|
||||
import java.util.*
|
||||
|
||||
|
||||
/**
|
||||
* - basic box plot
|
||||
* - change color of the boxes
|
||||
* - use T10 as color palette
|
||||
*/
|
||||
fun main() {
|
||||
val rnd = Random()
|
||||
val y1 = List(50) { rnd.nextDouble() }
|
||||
val y2 = List(50) { rnd.nextDouble() + 1 }
|
||||
|
||||
val plot = Plotly.plot {
|
||||
box {
|
||||
y.set(y1)
|
||||
name = "Sample A"
|
||||
marker {
|
||||
color(T10.PINK)
|
||||
}
|
||||
}
|
||||
|
||||
box {
|
||||
y.set(y2)
|
||||
name = "Sample B"
|
||||
marker {
|
||||
color(T10.OLIVE)
|
||||
}
|
||||
}
|
||||
|
||||
layout {
|
||||
title = "Colored Box Plot"
|
||||
}
|
||||
}
|
||||
|
||||
plot.makeFile()
|
||||
}
|
112
plotly/examples/src/main/kotlin/errorPlots/FillLines.kt
Normal file
112
plotly/examples/src/main/kotlin/errorPlots/FillLines.kt
Normal file
@ -0,0 +1,112 @@
|
||||
package errorPlots
|
||||
|
||||
import space.kscience.dataforge.meta.invoke
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.makeFile
|
||||
import space.kscience.plotly.models.FillType
|
||||
import space.kscience.plotly.models.Scatter
|
||||
import space.kscience.plotly.models.ScatterMode
|
||||
import space.kscience.plotly.models.Ticks
|
||||
|
||||
|
||||
/**
|
||||
* - Scatter plot with filled error lines
|
||||
* - Use rgb(a) color palette
|
||||
* - Change colors of grid, paper background and line fills
|
||||
*/
|
||||
fun main() {
|
||||
val trace1 = Scatter {
|
||||
x(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
|
||||
y(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
fill = FillType.tozerox
|
||||
fillcolor("rgba(0, 100, 80, 0.2)")
|
||||
line {
|
||||
color("transparent")
|
||||
}
|
||||
name = "Fair"
|
||||
showlegend = false
|
||||
}
|
||||
|
||||
val trace2 = Scatter {
|
||||
x(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
|
||||
y(5.5, 3, 5.5, 8, 6, 3, 8, 5, 6, 5.5, 4.75, 5, 4, 7, 2, 4, 7, 4.4, 2, 4.5)
|
||||
fill = FillType.tozerox
|
||||
fillcolor("rgba(0, 176, 246, 0.2)")
|
||||
line {
|
||||
color("transparent")
|
||||
}
|
||||
name = "Premium"
|
||||
showlegend = false
|
||||
}
|
||||
|
||||
val trace3 = Scatter {
|
||||
x(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
|
||||
y(11, 9, 7, 5, 3, 1, 3, 5, 3, 1, -1, 1, 3, 1, -0.5, 1, 3, 5, 7, 9)
|
||||
fill = FillType.tozerox
|
||||
fillcolor("rgba(231, 107, 243, 0.2)")
|
||||
line {
|
||||
color("transparent")
|
||||
}
|
||||
name = "Fair"
|
||||
showlegend = false
|
||||
}
|
||||
|
||||
val trace4 = Scatter {
|
||||
x(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
|
||||
y(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
|
||||
line {
|
||||
color("rgb(0, 100, 80)")
|
||||
}
|
||||
mode = ScatterMode.lines
|
||||
name = "Fair"
|
||||
}
|
||||
|
||||
val trace5 = Scatter {
|
||||
x(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
|
||||
y(5, 2.5, 5, 7.5, 5, 2.5, 7.5, 4.5, 5.5, 5)
|
||||
line {
|
||||
color("rgb(0, 176, 246)")
|
||||
}
|
||||
mode = ScatterMode.lines
|
||||
name = "Premium"
|
||||
}
|
||||
|
||||
val trace6 = Scatter {
|
||||
x(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
|
||||
y(10, 8, 6, 4, 2, 0, 2, 4, 2, 0)
|
||||
line {
|
||||
color("rgb(231, 107, 243)")
|
||||
}
|
||||
mode = ScatterMode.lines
|
||||
name = "Ideal"
|
||||
}
|
||||
|
||||
val plot = Plotly.plot {
|
||||
traces(trace1, trace2, trace3, trace4, trace5, trace6)
|
||||
|
||||
layout {
|
||||
paper_bgcolor("rgb(255, 255, 255)")
|
||||
plot_bgcolor("rgb(229, 229, 229)")
|
||||
xaxis {
|
||||
gridcolor("rgb(255, 255, 255)")
|
||||
range(1.0..10.0)
|
||||
showgrid = true
|
||||
showline = false
|
||||
showticklabels = true
|
||||
tickcolor("rgb(127, 127, 127)")
|
||||
ticks = Ticks.outside
|
||||
zeroline = false
|
||||
}
|
||||
yaxis {
|
||||
gridcolor("rgb(255, 255, 255)")
|
||||
showgrid = true
|
||||
showline = false
|
||||
showticklabels = true
|
||||
tickcolor("rgb(127, 127, 127)")
|
||||
ticks = Ticks.outside
|
||||
zeroline = false
|
||||
}
|
||||
}
|
||||
}
|
||||
plot.makeFile()
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package errorPlots
|
||||
|
||||
import space.kscience.dataforge.meta.invoke
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.makeFile
|
||||
import space.kscience.plotly.palettes.Xkcd
|
||||
import space.kscience.plotly.trace
|
||||
import java.util.*
|
||||
|
||||
|
||||
/**
|
||||
* - simple scatter with random length of horizontal error bars
|
||||
* - change error bars color
|
||||
* - use XKCD as color palette
|
||||
*/
|
||||
fun main() {
|
||||
val rnd = Random()
|
||||
val xValues = (0..100 step 4).toList().map { it / 20.0 }
|
||||
val err = List(26) { rnd.nextDouble() / 2 }
|
||||
|
||||
val plot = Plotly.plot {
|
||||
trace {
|
||||
x.numbers = xValues
|
||||
marker {
|
||||
color(Xkcd.PURPLE)
|
||||
}
|
||||
error_x {
|
||||
array = err
|
||||
color(Xkcd.PALE_PURPLE)
|
||||
}
|
||||
}
|
||||
layout {
|
||||
title = "Random Data Error"
|
||||
}
|
||||
}
|
||||
|
||||
plot.makeFile()
|
||||
}
|
35
plotly/examples/src/main/kotlin/functionTraces.kt
Normal file
35
plotly/examples/src/main/kotlin/functionTraces.kt
Normal file
@ -0,0 +1,35 @@
|
||||
import space.kscience.dataforge.meta.invoke
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.UnstablePlotlyAPI
|
||||
import space.kscience.plotly.makeFile
|
||||
import space.kscience.plotly.models.functionXY
|
||||
import space.kscience.plotly.trace
|
||||
import kotlin.math.PI
|
||||
import kotlin.math.sin
|
||||
|
||||
@OptIn(UnstablePlotlyAPI::class)
|
||||
fun main() {
|
||||
val plot = Plotly.plot {
|
||||
repeat(50) { phase ->
|
||||
trace {
|
||||
functionXY(0.0..2 * PI, step = 0.05) {
|
||||
sin(it + phase * 2 * PI / 60)
|
||||
}
|
||||
name = "Sin with phase offset ${phase * 2 * PI / 60}"
|
||||
}
|
||||
}
|
||||
|
||||
layout {
|
||||
title = "Graph name"
|
||||
xaxis {
|
||||
title = "x axis"
|
||||
}
|
||||
yaxis {
|
||||
title = "y axis"
|
||||
}
|
||||
height = 700
|
||||
}
|
||||
}
|
||||
|
||||
plot.makeFile()
|
||||
}
|
42
plotly/examples/src/main/kotlin/geo/choropleth.kt
Normal file
42
plotly/examples/src/main/kotlin/geo/choropleth.kt
Normal file
@ -0,0 +1,42 @@
|
||||
package geo
|
||||
|
||||
import io.invoke
|
||||
import org.jetbrains.kotlinx.dataframe.DataFrame
|
||||
import org.jetbrains.kotlinx.dataframe.io.readCSV
|
||||
|
||||
import space.kscience.dataforge.meta.invoke
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.layout
|
||||
import space.kscience.plotly.makeFile
|
||||
import space.kscience.plotly.models.geo.GeoScope
|
||||
import space.kscience.plotly.models.geo.LocationMode
|
||||
import space.kscience.plotly.models.geo.choropleth
|
||||
import space.kscience.plotly.models.geo.geo
|
||||
|
||||
private val df = DataFrame.readCSV("https://raw.githubusercontent.com/plotly/datasets/master/2014_usa_states.csv")
|
||||
|
||||
//https://plotly.com/javascript/choropleth-maps/#choropleth-map-of-2014-us-population-by-state
|
||||
fun main() {
|
||||
val plot = Plotly.plot {
|
||||
choropleth {
|
||||
locationmode = LocationMode.`USA-states`
|
||||
text(df["State"])
|
||||
locations(df["Postal"])
|
||||
z(df["Population"])
|
||||
}
|
||||
|
||||
layout {
|
||||
title = "2014 US Popultaion by State"
|
||||
geo{
|
||||
scope = GeoScope.usa
|
||||
countrycolor(255,255,255)
|
||||
landcolor(217, 217, 217)
|
||||
showland = true
|
||||
lakecolor(255, 255, 255)
|
||||
showlakes = true
|
||||
subunitcolor(255,255,255)
|
||||
}
|
||||
}
|
||||
}
|
||||
plot.makeFile()
|
||||
}
|
76
plotly/examples/src/main/kotlin/geo/dynamicMap.kt
Normal file
76
plotly/examples/src/main/kotlin/geo/dynamicMap.kt
Normal file
@ -0,0 +1,76 @@
|
||||
package geo
|
||||
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.serialization.json.int
|
||||
import space.kscience.dataforge.meta.invoke
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.layout
|
||||
import space.kscience.plotly.models.geo.LocationMode
|
||||
import space.kscience.plotly.models.geo.choroplethMapBox
|
||||
import space.kscience.plotly.models.geo.json.GeoJsonFeatureCollection
|
||||
import space.kscience.plotly.models.geo.json.combine
|
||||
import space.kscience.plotly.models.geo.openStreetMap
|
||||
import space.kscience.plotly.server.close
|
||||
import space.kscience.plotly.server.plot
|
||||
import space.kscience.plotly.server.serve
|
||||
import java.net.URL
|
||||
import kotlin.random.Random
|
||||
|
||||
fun main() {
|
||||
|
||||
//downloading GeoJson
|
||||
val geoJsonString =
|
||||
URL("https://raw.githubusercontent.com/isellsoap/deutschlandGeoJSON/main/4_kreise/4_niedrig.geo.json").readText()
|
||||
|
||||
|
||||
// Filtering GeoJson features and creating new feature set
|
||||
val features = GeoJsonFeatureCollection.parse(geoJsonString).filter {
|
||||
it.getString("NAME_1") == "Sachsen"
|
||||
}.combine()
|
||||
|
||||
val server = Plotly.serve {
|
||||
plot {
|
||||
choroplethMapBox {
|
||||
geoJsonFeatures(features)
|
||||
//Switch to geojson-id mode
|
||||
locationmode = LocationMode.`geojson-id`
|
||||
|
||||
//Setup the background map
|
||||
openStreetMap {
|
||||
center {
|
||||
lat = 51.05
|
||||
lon = 13.73
|
||||
}
|
||||
zoom = 7.0
|
||||
} // Set hover text to region names
|
||||
text.strings = features.map { it.getString("NAME_3")!! }
|
||||
// Set displayed locations
|
||||
locations.numbers = features.map { it.id!!.int }
|
||||
// Set random values to locations
|
||||
z.numbers = features.map { Random.nextDouble(1.0, 10.0) }
|
||||
launch {
|
||||
while (isActive) {
|
||||
delay(300)
|
||||
z.numbers = features.map { Random.nextDouble(1.0, 10.0) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
layout {
|
||||
title = "Geojson demo"
|
||||
height = 800
|
||||
}
|
||||
embedData = true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
println("Press Enter to close server")
|
||||
while (readLine()?.trim() != "exit") {
|
||||
//wait
|
||||
}
|
||||
|
||||
server.close()
|
||||
}
|
61
plotly/examples/src/main/kotlin/geo/saxony.kt
Normal file
61
plotly/examples/src/main/kotlin/geo/saxony.kt
Normal file
@ -0,0 +1,61 @@
|
||||
package geo
|
||||
|
||||
import kotlinx.serialization.json.int
|
||||
import space.kscience.dataforge.meta.invoke
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.layout
|
||||
import space.kscience.plotly.makeFile
|
||||
import space.kscience.plotly.models.geo.LocationMode
|
||||
import space.kscience.plotly.models.geo.choroplethMapBox
|
||||
import space.kscience.plotly.models.geo.json.GeoJsonFeatureCollection
|
||||
import space.kscience.plotly.models.geo.json.combine
|
||||
import space.kscience.plotly.models.geo.openStreetMap
|
||||
import java.net.URL
|
||||
import kotlin.random.Random
|
||||
|
||||
|
||||
fun main() {
|
||||
|
||||
//downloading GeoJson
|
||||
val geoJsonString =
|
||||
URL("https://raw.githubusercontent.com/isellsoap/deutschlandGeoJSON/main/4_kreise/4_niedrig.geo.json").readText()
|
||||
|
||||
|
||||
// Filtering GeoJson features and creating new feature set
|
||||
val features = GeoJsonFeatureCollection.parse(geoJsonString).filter {
|
||||
it.getString("NAME_1") == "Sachsen"
|
||||
}.combine()
|
||||
|
||||
val plot = Plotly.plot {
|
||||
choroplethMapBox {
|
||||
// Use this for remote-loaded feature set
|
||||
// geojsonUrl =
|
||||
// "https://raw.githubusercontent.com/isellsoap/deutschlandGeoJSON/main/4_kreise/4_niedrig.geo.json"
|
||||
//load local in-memory feature set and switch to
|
||||
geoJsonFeatures(features)
|
||||
//Switch to geojson-id mode
|
||||
locationmode = LocationMode.`geojson-id`
|
||||
// Set hover text to region names
|
||||
text.strings = features.map { it.getString("NAME_3")!! }
|
||||
// Set displayed locations
|
||||
locations.numbers = features.map { it.id!!.int }
|
||||
// Set random values to locations
|
||||
z.numbers = features.map { Random.nextDouble(1.0, 10.0) }
|
||||
}
|
||||
|
||||
layout {
|
||||
title = "Geojson demo"
|
||||
height = 800
|
||||
}
|
||||
|
||||
// Setup the background map
|
||||
openStreetMap {
|
||||
center {
|
||||
lat = 51.05
|
||||
lon = 13.73
|
||||
}
|
||||
zoom = 7.0
|
||||
}
|
||||
}
|
||||
plot.makeFile()
|
||||
}
|
47
plotly/examples/src/main/kotlin/geo/scattermapbox.kt
Normal file
47
plotly/examples/src/main/kotlin/geo/scattermapbox.kt
Normal file
@ -0,0 +1,47 @@
|
||||
package geo
|
||||
|
||||
import io.invoke
|
||||
import org.jetbrains.kotlinx.dataframe.DataFrame
|
||||
import org.jetbrains.kotlinx.dataframe.io.readCSV
|
||||
import space.kscience.dataforge.meta.invoke
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.layout
|
||||
import space.kscience.plotly.makeFile
|
||||
import space.kscience.plotly.models.DragMode
|
||||
import space.kscience.plotly.models.geo.mapbox
|
||||
import space.kscience.plotly.models.geo.scattermapbox
|
||||
import space.kscience.plotly.models.geo.useOpenStreetMap
|
||||
|
||||
private val df = DataFrame.readCSV(
|
||||
"https://raw.githubusercontent.com/plotly/datasets/master/2015_06_30_precipitation.csv"
|
||||
)
|
||||
|
||||
//https://plotly.com/javascript/mapbox-layers/#openstreetmap-tiles-no-token-needed
|
||||
fun main() {
|
||||
val plot = Plotly.plot {
|
||||
scattermapbox {
|
||||
text(df["Globvalue"])
|
||||
lon(df["Lon"])
|
||||
lat(df["Lat"])
|
||||
marker {
|
||||
color("fuchsia")
|
||||
size = 4
|
||||
}
|
||||
}
|
||||
|
||||
layout {
|
||||
title = "OpenStreetMap with markers"
|
||||
dragmode = DragMode.zoom
|
||||
//margin { r = 0; t= 0; b= 0; l= 0 }
|
||||
mapbox {
|
||||
useOpenStreetMap()
|
||||
center {
|
||||
lat = 38
|
||||
lon = -90
|
||||
}
|
||||
zoom = 3.0
|
||||
}
|
||||
}
|
||||
}
|
||||
plot.makeFile()
|
||||
}
|
129
plotly/examples/src/main/kotlin/gridPageLayout.kt
Normal file
129
plotly/examples/src/main/kotlin/gridPageLayout.kt
Normal file
@ -0,0 +1,129 @@
|
||||
import kotlinx.html.div
|
||||
import space.kscience.plotly.*
|
||||
import space.kscience.plotly.models.Trace
|
||||
import space.kscience.plotly.models.invoke
|
||||
import space.kscience.plotly.palettes.T10
|
||||
import kotlin.math.PI
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
|
||||
|
||||
private class PlotGrid {
|
||||
public data class PlotCell(val id: String, val plot: Plot, val row: Int, val col: Int, val width: Int = 1)
|
||||
|
||||
private val cells = HashMap<String, PlotCell>()
|
||||
|
||||
/**
|
||||
* @return Columns in ascending order, grouped by rows in ascending order.
|
||||
* */
|
||||
public val grid: List<List<PlotCell>>
|
||||
get() = cells.values.groupBy { it.row }.toSortedMap().values.map {
|
||||
it.sortedBy { cell -> cell.col }
|
||||
}.toList()
|
||||
|
||||
public operator fun get(id: String): PlotCell? = cells[id]
|
||||
|
||||
private var currentRow = 0
|
||||
private var currentCol = 0
|
||||
|
||||
public fun plot(
|
||||
plot: Plot,
|
||||
id: String = plot.toString(),
|
||||
width: Int = 6,
|
||||
row: Int? = null,
|
||||
col: Int? = null,
|
||||
): Plot {
|
||||
val actualRow = if (row != null) {
|
||||
row
|
||||
} else {
|
||||
currentCol = 0
|
||||
currentRow++
|
||||
}
|
||||
|
||||
val actualColumn = col ?: currentCol++
|
||||
|
||||
cells[id] = PlotCell(id, plot, actualRow, actualColumn, width)
|
||||
|
||||
return plot
|
||||
}
|
||||
|
||||
public fun plot(
|
||||
row: Int? = null,
|
||||
col: Int? = null,
|
||||
id: String? = null,
|
||||
width: Int = 6,
|
||||
block: Plot.() -> Unit,
|
||||
): Plot {
|
||||
val plot = Plotly.plot(block)
|
||||
return plot(plot, id ?: plot.toString(), width, row, col)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun Plotly.grid(block: PlotGrid.() -> Unit): PlotlyPage {
|
||||
val grid = PlotGrid().apply(block)
|
||||
return page(cdnBootstrap, cdnPlotlyHeader) { container ->
|
||||
div("col") {
|
||||
grid.grid.forEach { row ->
|
||||
div("row") {
|
||||
row.forEach { cell ->
|
||||
div("col-${cell.width}") {
|
||||
plot(cell.plot, cell.id, renderer = container)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun main() {
|
||||
|
||||
val x = (0..100).map { it.toDouble() / 100.0 }
|
||||
val y1 = x.map { sin(2.0 * PI * it) }
|
||||
val y2 = x.map { cos(2.0 * PI * it) }
|
||||
|
||||
val trace1 = Trace(x, y1) {
|
||||
name = "sin"
|
||||
marker.color(T10.BLUE)
|
||||
|
||||
}
|
||||
|
||||
val trace2 = Trace(x, y2) {
|
||||
name = "cos"
|
||||
marker.color(T10.ORANGE)
|
||||
|
||||
}
|
||||
|
||||
val plot = Plotly.grid {
|
||||
// title = "Page sample"
|
||||
plot(row = 1, width = 8) {
|
||||
traces(trace1, trace2)
|
||||
layout {
|
||||
title = "First graph, row: 1, size: 8/12"
|
||||
xaxis.title = "x axis name"
|
||||
xaxis.title = "y axis name"
|
||||
}
|
||||
}
|
||||
|
||||
plot(row = 1, width = 4) {
|
||||
traces(trace1, trace2)
|
||||
layout {
|
||||
title = "Second graph, row: 1, size: 4/12"
|
||||
xaxis.title = "x axis name"
|
||||
xaxis.title = "y axis name"
|
||||
}
|
||||
}
|
||||
|
||||
plot(row = 2, width = 12) {
|
||||
traces(trace1, trace2)
|
||||
layout {
|
||||
title = "Third graph, row: 2, size: 12/12"
|
||||
xaxis.title = "x axis name"
|
||||
xaxis.title = "y axis name"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
plot.makeFile()
|
||||
}
|
75
plotly/examples/src/main/kotlin/heatmap/AnnotatedHeatmap.kt
Normal file
75
plotly/examples/src/main/kotlin/heatmap/AnnotatedHeatmap.kt
Normal file
@ -0,0 +1,75 @@
|
||||
package heatmap
|
||||
|
||||
import space.kscience.dataforge.meta.Value
|
||||
import space.kscience.dataforge.meta.invoke
|
||||
import space.kscience.plotly.Plotly
|
||||
import space.kscience.plotly.heatmap
|
||||
import space.kscience.plotly.makeFile
|
||||
import space.kscience.plotly.models.Font
|
||||
import space.kscience.plotly.models.Text
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.sin
|
||||
|
||||
/**
|
||||
* - Heatmap with annotations
|
||||
* - Change font color and size of annotations text
|
||||
* - Remove annotations arrows
|
||||
* - Change colorscale and size of plot
|
||||
*/
|
||||
fun main() {
|
||||
val x1 = (5..25).map { it.toDouble() / 5 }
|
||||
val y1 = (5..25).map { it.toDouble() / 5 }
|
||||
val z1 = mutableListOf<MutableList<Double>>()
|
||||
|
||||
for (i in y1.indices) {
|
||||
z1.add(MutableList(x1.size) { 0.0 })
|
||||
}
|
||||
|
||||
val annotationsList = mutableListOf<Text>()
|
||||
|
||||
for (i in y1.indices) {
|
||||
for (j in x1.indices) {
|
||||
z1[i][j] = sin(x1[i]).pow(10) + cos(10 + y1[j] * x1[i]) * cos(x1[i])
|
||||
val annotation = Text()
|
||||
annotation.x = Value.of(x1[j])
|
||||
annotation.y = Value.of(y1[i])
|
||||
annotation.text = z1[i][j].toString().substring(0..4)
|
||||
|
||||
val annotationsFont = Font()
|
||||
annotationsFont.size = 16
|
||||
if (z1[i][j] > 0) {
|
||||
annotationsFont.color("black")
|
||||
} else {
|
||||
annotationsFont.color("white")
|
||||
}
|
||||
annotation.font = annotationsFont
|
||||
annotation.showarrow = false
|
||||
annotationsList.add(annotation)
|
||||
}
|
||||
}
|
||||
|
||||
val plot = Plotly.plot {
|
||||
heatmap {
|
||||
x.set(x1)
|
||||
y.set(y1)
|
||||
z.set(z1)
|
||||
colorscale = Value.of("Viridis")
|
||||
}
|
||||
|
||||
layout {
|
||||
height = 800
|
||||
width = 1400
|
||||
xaxis {
|
||||
tickcolor("white")
|
||||
}
|
||||
yaxis {
|
||||
tickcolor("white")
|
||||
}
|
||||
annotations = annotationsList
|
||||
title = "Heatmap with Annotations"
|
||||
}
|
||||
}
|
||||
|
||||
plot.makeFile()
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user